1
0

merge: upstream

This commit is contained in:
Marie
2024-01-25 14:21:42 +01:00
41 changed files with 817 additions and 201 deletions
@@ -12,85 +12,96 @@ SPDX-License-Identifier: AGPL-3.0-only
<div class="_gaps" :class="{ [$style.disallowInner]: isReady }">
<div style="font-size: 1.5em; text-align: center;">{{ i18n.ts._reversi.gameSettings }}</div>
<div class="_panel">
<div style="display: flex; align-items: center; padding: 16px; border-bottom: solid 1px var(--divider);">
<div>{{ mapName }}</div>
<MkButton style="margin-left: auto;" @click="chooseMap">{{ i18n.ts._reversi.chooseBoard }}</MkButton>
</div>
<template v-if="game.noIrregularRules">
<div>{{ i18n.ts._reversi.disallowIrregularRules }}</div>
</template>
<template v-else>
<div class="_panel">
<div style="display: flex; align-items: center; padding: 16px; border-bottom: solid 1px var(--divider);">
<div>{{ mapName }}</div>
<MkButton style="margin-left: auto;" @click="chooseMap">{{ i18n.ts._reversi.chooseBoard }}</MkButton>
</div>
<div style="padding: 16px;">
<div v-if="game.map == null"><i class="ph-dice-five ph-bold ph-lg"></i></div>
<div v-else :class="$style.board" :style="{ 'grid-template-rows': `repeat(${ game.map.length }, 1fr)`, 'grid-template-columns': `repeat(${ game.map[0].length }, 1fr)` }">
<div v-for="(x, i) in game.map.join('')" :class="[$style.boardCell, { [$style.boardCellNone]: x == ' ' }]" @click="onMapCellClick(i, x)">
<i v-if="x === 'b' || x === 'w'" style="pointer-events: none; user-select: none;" :class="x === 'b' ? 'ph-circle-half ph-bold ph-lg' : 'ph-circle ph-bold ph-lg'"></i>
<div style="padding: 16px;">
<div v-if="game.map == null"><i class="ph-dice-five ph-bold ph-lg"></i></div>
<div v-else :class="$style.board" :style="{ 'grid-template-rows': `repeat(${ game.map.length }, 1fr)`, 'grid-template-columns': `repeat(${ game.map[0].length }, 1fr)` }">
<div v-for="(x, i) in game.map.join('')" :class="[$style.boardCell, { [$style.boardCellNone]: x == ' ' }]" @click="onMapCellClick(i, x)">
<i v-if="x === 'b' || x === 'w'" style="pointer-events: none; user-select: none;" :class="x === 'b' ? 'ph-circle-half ph-bold ph-lg' : 'ph-circle ph-bold ph-lg'"></i>
</div>
</div>
</div>
</div>
</div>
<MkFolder :defaultOpen="true">
<template #label>{{ i18n.ts._reversi.blackOrWhite }}</template>
<MkFolder :defaultOpen="true">
<template #label>{{ i18n.ts._reversi.blackOrWhite }}</template>
<MkRadios v-model="game.bw">
<option value="random">{{ i18n.ts.random }}</option>
<option :value="'1'">
<I18n :src="i18n.ts._reversi.blackIs" tag="span">
<template #name>
<b><MkUserName :user="game.user1"/></b>
</template>
</I18n>
</option>
<option :value="'2'">
<I18n :src="i18n.ts._reversi.blackIs" tag="span">
<template #name>
<b><MkUserName :user="game.user2"/></b>
</template>
</I18n>
</option>
</MkRadios>
</MkFolder>
<MkRadios v-model="game.bw">
<option value="random">{{ i18n.ts.random }}</option>
<option :value="'1'">
<I18n :src="i18n.ts._reversi.blackIs" tag="span">
<template #name>
<b><MkUserName :user="game.user1"/></b>
</template>
</I18n>
</option>
<option :value="'2'">
<I18n :src="i18n.ts._reversi.blackIs" tag="span">
<template #name>
<b><MkUserName :user="game.user2"/></b>
</template>
</I18n>
</option>
</MkRadios>
</MkFolder>
<MkFolder :defaultOpen="true">
<template #label>{{ i18n.ts._reversi.timeLimitForEachTurn }}</template>
<template #suffix>{{ game.timeLimitForEachTurn }}{{ i18n.ts._time.second }}</template>
<MkFolder :defaultOpen="true">
<template #label>{{ i18n.ts._reversi.timeLimitForEachTurn }}</template>
<template #suffix>{{ game.timeLimitForEachTurn }}{{ i18n.ts._time.second }}</template>
<MkRadios v-model="game.timeLimitForEachTurn">
<option :value="5">5{{ i18n.ts._time.second }}</option>
<option :value="10">10{{ i18n.ts._time.second }}</option>
<option :value="30">30{{ i18n.ts._time.second }}</option>
<option :value="60">60{{ i18n.ts._time.second }}</option>
<option :value="90">90{{ i18n.ts._time.second }}</option>
<option :value="120">120{{ i18n.ts._time.second }}</option>
<option :value="180">180{{ i18n.ts._time.second }}</option>
<option :value="3600">3600{{ i18n.ts._time.second }}</option>
</MkRadios>
</MkFolder>
<MkRadios v-model="game.timeLimitForEachTurn">
<option :value="5">5{{ i18n.ts._time.second }}</option>
<option :value="10">10{{ i18n.ts._time.second }}</option>
<option :value="30">30{{ i18n.ts._time.second }}</option>
<option :value="60">60{{ i18n.ts._time.second }}</option>
<option :value="90">90{{ i18n.ts._time.second }}</option>
<option :value="120">120{{ i18n.ts._time.second }}</option>
<option :value="180">180{{ i18n.ts._time.second }}</option>
<option :value="3600">3600{{ i18n.ts._time.second }}</option>
</MkRadios>
</MkFolder>
<MkFolder :defaultOpen="true">
<template #label>{{ i18n.ts._reversi.rules }}</template>
<MkFolder :defaultOpen="true">
<template #label>{{ i18n.ts._reversi.rules }}</template>
<div class="_gaps_s">
<MkSwitch v-model="game.isLlotheo" @update:modelValue="updateSettings('isLlotheo')">{{ i18n.ts._reversi.isLlotheo }}</MkSwitch>
<MkSwitch v-model="game.loopedBoard" @update:modelValue="updateSettings('loopedBoard')">{{ i18n.ts._reversi.loopedMap }}</MkSwitch>
<MkSwitch v-model="game.canPutEverywhere" @update:modelValue="updateSettings('canPutEverywhere')">{{ i18n.ts._reversi.canPutEverywhere }}</MkSwitch>
</div>
</MkFolder>
<div class="_gaps_s">
<MkSwitch v-model="game.isLlotheo" @update:modelValue="updateSettings('isLlotheo')">{{ i18n.ts._reversi.isLlotheo }}</MkSwitch>
<MkSwitch v-model="game.loopedBoard" @update:modelValue="updateSettings('loopedBoard')">{{ i18n.ts._reversi.loopedMap }}</MkSwitch>
<MkSwitch v-model="game.canPutEverywhere" @update:modelValue="updateSettings('canPutEverywhere')">{{ i18n.ts._reversi.canPutEverywhere }}</MkSwitch>
</div>
</MkFolder>
</template>
</div>
</div>
</MkSpacer>
<template #footer>
<div :class="$style.footer">
<MkSpacer :contentMax="700" :marginMin="16" :marginMax="16">
<div style="text-align: center; margin-bottom: 10px;">
<template v-if="isReady && isOpReady">{{ i18n.ts._reversi.thisGameIsStartedSoon }}<MkEllipsis/></template>
<template v-if="isReady && !isOpReady">{{ i18n.ts._reversi.waitingForOther }}<MkEllipsis/></template>
<template v-if="!isReady && isOpReady">{{ i18n.ts._reversi.waitingForMe }}</template>
<template v-if="!isReady && !isOpReady">{{ i18n.ts._reversi.waitingBoth }}<MkEllipsis/></template>
</div>
<div class="_buttonsCenter">
<MkButton rounded danger @click="cancel">{{ i18n.ts.cancel }}</MkButton>
<MkButton v-if="!isReady" rounded primary @click="ready">{{ i18n.ts._reversi.ready }}</MkButton>
<MkButton v-if="isReady" rounded @click="unready">{{ i18n.ts._reversi.cancelReady }}</MkButton>
<div style="text-align: center;" class="_gaps_s">
<div v-if="opponentHasSettingsChanged" style="color: var(--warn);">{{ i18n.ts._reversi.opponentHasSettingsChanged }}</div>
<div>
<template v-if="isReady && isOpReady">{{ i18n.ts._reversi.thisGameIsStartedSoon }}<MkEllipsis/></template>
<template v-if="isReady && !isOpReady">{{ i18n.ts._reversi.waitingForOther }}<MkEllipsis/></template>
<template v-if="!isReady && isOpReady">{{ i18n.ts._reversi.waitingForMe }}</template>
<template v-if="!isReady && !isOpReady">{{ i18n.ts._reversi.waitingBoth }}<MkEllipsis/></template>
</div>
<div class="_buttonsCenter">
<MkButton rounded danger @click="cancel">{{ i18n.ts.cancel }}</MkButton>
<MkButton v-if="!isReady" rounded primary @click="ready">{{ i18n.ts._reversi.ready }}</MkButton>
<MkButton v-if="isReady" rounded @click="unready">{{ i18n.ts._reversi.cancelReady }}</MkButton>
</div>
<div>
<MkSwitch v-model="shareWhenStart">{{ i18n.ts._reversi.shareToTlTheGameWhenStart }}</MkSwitch>
</div>
</div>
</MkSpacer>
</div>
@@ -124,6 +135,8 @@ const props = defineProps<{
connection: Misskey.ChannelConnection;
}>();
const shareWhenStart = defineModel<boolean>('shareWhenStart', { default: false });
const game = ref<Misskey.entities.ReversiGameDetailed>(deepClone(props.game));
const mapName = computed(() => {
@@ -142,6 +155,8 @@ const isOpReady = computed(() => {
return false;
});
const opponentHasSettingsChanged = ref(false);
watch(() => game.value.bw, () => {
updateSettings('bw');
});
@@ -190,6 +205,7 @@ async function cancel() {
function ready() {
props.connection.send('ready', true);
opponentHasSettingsChanged.value = false;
}
function unready() {
@@ -212,6 +228,10 @@ function onUpdateSettings({ userId, key, value }: { userId: string; key: keyof M
if (userId === $i.id) return;
if (game.value[key] === value) return;
game.value[key] = value;
if (isReady.value) {
opponentHasSettingsChanged.value = true;
unready();
}
}
function onMapCellClick(pos: number, pixel: string) {