Compare commits

...

42 Commits

Author SHA1 Message Date
255222bfb4 5.15.0 2018-08-05 13:47:51 +09:00
9e5e3c2f2e ✌️ 2018-08-05 13:44:44 +09:00
5bd80f115f Merge pull request #2089 from syuilo/greenkeeper/@types/node-10.5.6
Update @types/node to the latest version 🚀
2018-08-05 13:41:05 +09:00
c86e1a3e9b Merge pull request #2088 from syuilo/greenkeeper/commander-2.17.0
Update commander to the latest version 🚀
2018-08-05 13:40:57 +09:00
128a201b9d #2080 など 2018-08-05 13:40:26 +09:00
b68f74f39c typo 2018-08-05 12:33:55 +09:00
cd28504dd8 Add new MFM syntax 2018-08-05 12:33:51 +09:00
f762cf2770 Merge branch 'master' of https://github.com/syuilo/misskey 2018-08-04 23:04:56 +09:00
d84cae9358 5.14.0 2018-08-04 23:04:45 +09:00
9c54721010 Merge pull request #2090 from syuilo/l10n_master
New Crowdin translations
2018-08-04 23:03:59 +09:00
16f35c81a1 New translations ja.yml (Korean) 2018-08-04 23:00:59 +09:00
d0dbb62a54 New translations ja.yml (English) 2018-08-04 23:00:57 +09:00
9fa68f4478 New translations ja.yml (Catalan) 2018-08-04 22:51:25 +09:00
0d76625868 New translations ja.yml (Portuguese) 2018-08-04 22:51:23 +09:00
5a8a701188 New translations ja.yml (Korean) 2018-08-04 22:51:21 +09:00
121344afbb New translations ja.yml (Polish) 2018-08-04 22:51:19 +09:00
d647cf3446 New translations ja.yml (Chinese Simplified) 2018-08-04 22:51:16 +09:00
04a23b3f2f New translations ja.yml (Italian) 2018-08-04 22:51:14 +09:00
08826e1c41 New translations ja.yml (Russian) 2018-08-04 22:51:12 +09:00
2e31e3c7cb New translations ja.yml (English) 2018-08-04 22:51:10 +09:00
7aed50f9fa New translations ja.yml (Spanish) 2018-08-04 22:51:08 +09:00
2de782dbe4 New translations ja.yml (German) 2018-08-04 22:51:06 +09:00
50693fbe25 New translations ja.yml (French) 2018-08-04 22:51:03 +09:00
9a2ff56a79 動きのあるMFMを無効にするオプションを実装 2018-08-04 22:48:35 +09:00
daed63d66c Update doc 2018-08-04 22:33:37 +09:00
f2241a47b7 New translations ja.yml (Catalan) 2018-08-04 22:31:23 +09:00
de95aac59b New translations ja.yml (Portuguese) 2018-08-04 22:31:20 +09:00
8612ac0c6a New translations ja.yml (Korean) 2018-08-04 22:31:18 +09:00
2118e500a8 New translations ja.yml (Polish) 2018-08-04 22:31:16 +09:00
a7063eab85 New translations ja.yml (Chinese Simplified) 2018-08-04 22:31:14 +09:00
5b5ae0e47f New translations ja.yml (Italian) 2018-08-04 22:31:12 +09:00
b19ecc1a0d New translations ja.yml (Russian) 2018-08-04 22:31:10 +09:00
ac9223957f New translations ja.yml (English) 2018-08-04 22:31:07 +09:00
e580adc41e New translations ja.yml (Spanish) 2018-08-04 22:31:05 +09:00
607a105b78 New translations ja.yml (German) 2018-08-04 22:31:03 +09:00
cc601cf600 New translations ja.yml (French) 2018-08-04 22:31:01 +09:00
be9f6ad294 Implement surrender of reversi 2018-08-04 22:28:01 +09:00
a2952c02cf New translations ja.yml (French) 2018-08-04 21:31:21 +09:00
244d567b3a 5.13.2 2018-08-04 12:38:14 +09:00
61a9ad23f1 Fix bug 2018-08-04 12:35:57 +09:00
864d1a39cd fix(package): update @types/node to version 10.5.6 2018-08-04 01:48:39 +00:00
e14f244e83 fix(package): update commander to version 2.17.0 2018-08-04 00:14:18 +00:00
31 changed files with 313 additions and 41 deletions

View File

@ -88,6 +88,7 @@ common:
i-like-sushi: "私は(プリンよりむしろ)寿司が好き"
show-reversi-board-labels: "リバーシのボードの行と列のラベルを表示"
verified-user: "認証済みのユーザー"
disable-animated-mfm: "投稿内の動きのあるテキストを無効にする"
reversi:
drawn: "引き分け"
my-turn: "あなたのターンです"
@ -168,6 +169,9 @@ common/views/components/games/reversi/reversi.vue:
matching:
waiting-for: "{}を待っています"
cancel: "キャンセル"
common/views/components/games/reversi/reversi.game.vue:
surrender: "投了"
surrendered: "投了により"
common/views/components/games/reversi/reversi.index.vue:
title: "Misskey Reversi"
sub-title: "他のMisskeyユーザーとリバーシで対戦しよう"

View File

@ -88,6 +88,7 @@ common:
i-like-sushi: "私は(プリンよりむしろ)寿司が好き"
show-reversi-board-labels: "リバーシのボードの行と列のラベルを表示"
verified-user: "認証済みのユーザー"
disable-animated-mfm: "投稿内の動きのあるテキストを無効にする"
reversi:
drawn: "引き分け"
my-turn: "あなたのターンです"
@ -168,6 +169,9 @@ common/views/components/games/reversi/reversi.vue:
matching:
waiting-for: "{}を待っています"
cancel: "キャンセル"
common/views/components/games/reversi/reversi.game.vue:
surrender: "投了"
surrendered: "投了により"
common/views/components/games/reversi/reversi.index.vue:
title: "Misskey Reversi"
sub-title: "他のMisskeyユーザーとリバーシで対戦しよう"

View File

@ -88,6 +88,7 @@ common:
i-like-sushi: "I prefer sushi rather than pudding"
show-reversi-board-labels: "Show row and column labels in Reversi"
verified-user: "Verified user"
disable-animated-mfm: "Disable animated texts in a post"
reversi:
drawn: "Draw"
my-turn: "Your turn"
@ -168,6 +169,9 @@ common/views/components/games/reversi/reversi.vue:
matching:
waiting-for: "Waiting for {}"
cancel: "Cancel"
common/views/components/games/reversi/reversi.game.vue:
surrender: "Surrender"
surrendered: "By surrender"
common/views/components/games/reversi/reversi.index.vue:
title: "Misskey Reversi"
sub-title: "Play reversi with your friends!"

View File

@ -88,6 +88,7 @@ common:
i-like-sushi: "Prefiero sushi a pudín"
show-reversi-board-labels: "Mostrar etiquetas de filas y columnas en Reversi"
verified-user: "Usuario verificado"
disable-animated-mfm: "投稿内の動きのあるテキストを無効にする"
reversi:
drawn: "Empatado"
my-turn: "Mi turno"
@ -168,6 +169,9 @@ common/views/components/games/reversi/reversi.vue:
matching:
waiting-for: "Esperando por {}"
cancel: "Cancelar"
common/views/components/games/reversi/reversi.game.vue:
surrender: "投了"
surrendered: "投了により"
common/views/components/games/reversi/reversi.index.vue:
title: "Misskey Reversi"
sub-title: "他のMisskeyユーザーとリバーシで対戦しよう"

View File

@ -88,6 +88,7 @@ common:
i-like-sushi: "Je préfère les sushis (au pudding)"
show-reversi-board-labels: "Afficher les étiquettes des lignes et colonnes dans Reversi"
verified-user: "Utilisateur·trice vérifié·e"
disable-animated-mfm: "投稿内の動きのあるテキストを無効にする"
reversi:
drawn: "Partie nulle"
my-turn: "Cest votre tour"
@ -156,7 +157,7 @@ auth/views/form.vue:
accept: "Autoriser laccès"
auth/views/index.vue:
loading: "Chargement en cours"
denied: "アプリケーションの連携をキャンセルしました。"
denied: "L'autorisation de l'application a été refusée."
denied-paragraph: "Cette application ne va pas accéder à votre compte."
already-authorized: "Cette application est déjà autorisée"
allowed: "アプリケーションの連携を許可しました"
@ -168,6 +169,9 @@ common/views/components/games/reversi/reversi.vue:
matching:
waiting-for: "En attente de {}"
cancel: "Annuler"
common/views/components/games/reversi/reversi.game.vue:
surrender: "投了"
surrendered: "投了により"
common/views/components/games/reversi/reversi.index.vue:
title: "Misskey Reversi"
sub-title: "Jouer à Reversi avec vos amis·es !"
@ -364,15 +368,15 @@ common/views/widgets/slideshow.vue:
common/views/widgets/tips.vue:
tips-line1: "<kbd>t</kbd>でタイムラインにフォーカスできます"
tips-line2: "<kbd>p</kbd>または<kbd>n</kbd>で投稿フォームを開きます"
tips-line3: "投稿フォームにはファイルをドラッグ&ドロップできます"
tips-line4: "投稿フォームにクリップボードにある画像データをペーストできます"
tips-line3: "Vous pouvez glisser et déposer des fichiers sur la fenêtre de la note"
tips-line4: "Vous pouvez coller des images à partir du presse-papier sur la fenêtre de la note"
tips-line5: "ドライブにファイルをドラッグ&ドロップしてアップロードできます"
tips-line6: "ドライブでファイルをドラッグしてフォルダ移動できます"
tips-line7: "ドライブでフォルダをドラッグしてフォルダ移動できます"
tips-line8: "Vous pouvez personnaliser l'Accueil via les paramètres"
tips-line9: "Misskey est sous licence AGPLv3"
tips-line10: "タイムマシンウィジェットを利用すると、簡単に過去のタイムラインに遡れます"
tips-line11: "投稿の ... をクリックして、投稿をユーザーページにピン留めできます"
tips-line11: "Vous pouvez épingler des notes sur votre page en appuyant sur \"…\""
tips-line13: "Tous les fichiers attachés à cette publication sont sauvegardés dans le Drive"
tips-line14: "ホームのカスタマイズ中、ウィジェットを右クリックしてデザインを変更できます"
tips-line17: "「**」でテキストを囲むと**強調表示**されます"

View File

@ -88,6 +88,7 @@ common:
i-like-sushi: "私は(プリンよりむしろ)寿司が好き"
show-reversi-board-labels: "リバーシのボードの行と列のラベルを表示"
verified-user: "認証済みのユーザー"
disable-animated-mfm: "投稿内の動きのあるテキストを無効にする"
reversi:
drawn: "引き分け"
my-turn: "あなたのターンです"
@ -168,6 +169,9 @@ common/views/components/games/reversi/reversi.vue:
matching:
waiting-for: "{}を待っています"
cancel: "キャンセル"
common/views/components/games/reversi/reversi.game.vue:
surrender: "投了"
surrendered: "投了により"
common/views/components/games/reversi/reversi.index.vue:
title: "Misskey Reversi"
sub-title: "他のMisskeyユーザーとリバーシで対戦しよう"

View File

@ -95,6 +95,7 @@ common:
i-like-sushi: "私は(プリンよりむしろ)寿司が好き"
show-reversi-board-labels: "リバーシのボードの行と列のラベルを表示"
verified-user: "認証済みのユーザー"
disable-animated-mfm: "投稿内の動きのあるテキストを無効にする"
reversi:
drawn: "引き分け"
@ -182,6 +183,10 @@ common/views/components/games/reversi/reversi.vue:
waiting-for: "{}を待っています"
cancel: "キャンセル"
common/views/components/games/reversi/reversi.game.vue:
surrender: "投了"
surrendered: "投了により"
common/views/components/games/reversi/reversi.index.vue:
title: "Misskey Reversi"
sub-title: "他のMisskeyユーザーとリバーシで対戦しよう"

View File

@ -1,6 +1,6 @@
---
meta:
lang: "日本語"
lang: "한국어"
divider: ""
common:
misskey: "A ⭐ of fediverse"
@ -88,6 +88,7 @@ common:
i-like-sushi: "私は(プリンよりむしろ)寿司が好き"
show-reversi-board-labels: "リバーシのボードの行と列のラベルを表示"
verified-user: "認証済みのユーザー"
disable-animated-mfm: "投稿内の動きのあるテキストを無効にする"
reversi:
drawn: "引き分け"
my-turn: "あなたのターンです"
@ -168,6 +169,9 @@ common/views/components/games/reversi/reversi.vue:
matching:
waiting-for: "{}を待っています"
cancel: "キャンセル"
common/views/components/games/reversi/reversi.game.vue:
surrender: "投了"
surrendered: "投了により"
common/views/components/games/reversi/reversi.index.vue:
title: "Misskey Reversi"
sub-title: "他のMisskeyユーザーとリバーシで対戦しよう"

View File

@ -88,6 +88,7 @@ common:
i-like-sushi: "Wolę sushi od puddingu"
show-reversi-board-labels: "Pokazuj podpisy wierszy i kolumn w Reversi"
verified-user: "Zweryfikowany użytkownik"
disable-animated-mfm: "投稿内の動きのあるテキストを無効にする"
reversi:
drawn: "Remis"
my-turn: "Twoja kolej"
@ -168,6 +169,9 @@ common/views/components/games/reversi/reversi.vue:
matching:
waiting-for: "{}を待っています"
cancel: "キャンセル"
common/views/components/games/reversi/reversi.game.vue:
surrender: "投了"
surrendered: "投了により"
common/views/components/games/reversi/reversi.index.vue:
title: "Misskey Reversi"
sub-title: "他のMisskeyユーザーとリバーシで対戦しよう"

View File

@ -88,6 +88,7 @@ common:
i-like-sushi: "私は(プリンよりむしろ)寿司が好き"
show-reversi-board-labels: "リバーシのボードの行と列のラベルを表示"
verified-user: "認証済みのユーザー"
disable-animated-mfm: "投稿内の動きのあるテキストを無効にする"
reversi:
drawn: "引き分け"
my-turn: "あなたのターンです"
@ -168,6 +169,9 @@ common/views/components/games/reversi/reversi.vue:
matching:
waiting-for: "{}を待っています"
cancel: "キャンセル"
common/views/components/games/reversi/reversi.game.vue:
surrender: "投了"
surrendered: "投了により"
common/views/components/games/reversi/reversi.index.vue:
title: "Misskey Reversi"
sub-title: "他のMisskeyユーザーとリバーシで対戦しよう"

View File

@ -88,6 +88,7 @@ common:
i-like-sushi: "私は(プリンよりむしろ)寿司が好き"
show-reversi-board-labels: "リバーシのボードの行と列のラベルを表示"
verified-user: "認証済みのユーザー"
disable-animated-mfm: "投稿内の動きのあるテキストを無効にする"
reversi:
drawn: "引き分け"
my-turn: "あなたのターンです"
@ -168,6 +169,9 @@ common/views/components/games/reversi/reversi.vue:
matching:
waiting-for: "{}を待っています"
cancel: "キャンセル"
common/views/components/games/reversi/reversi.game.vue:
surrender: "投了"
surrendered: "投了により"
common/views/components/games/reversi/reversi.index.vue:
title: "Misskey Reversi"
sub-title: "他のMisskeyユーザーとリバーシで対戦しよう"

View File

@ -88,6 +88,7 @@ common:
i-like-sushi: "私は(プリンよりむしろ)寿司が好き"
show-reversi-board-labels: "リバーシのボードの行と列のラベルを表示"
verified-user: "認証済みのユーザー"
disable-animated-mfm: "投稿内の動きのあるテキストを無効にする"
reversi:
drawn: "引き分け"
my-turn: "あなたのターンです"
@ -168,6 +169,9 @@ common/views/components/games/reversi/reversi.vue:
matching:
waiting-for: "{}を待っています"
cancel: "キャンセル"
common/views/components/games/reversi/reversi.game.vue:
surrender: "投了"
surrendered: "投了により"
common/views/components/games/reversi/reversi.index.vue:
title: "Misskey Reversi"
sub-title: "他のMisskeyユーザーとリバーシで対戦しよう"

View File

@ -1,8 +1,8 @@
{
"name": "misskey",
"author": "syuilo <i@syuilo.com>",
"version": "5.13.1",
"clientVersion": "1.0.7963",
"version": "5.15.0",
"clientVersion": "1.0.8007",
"codename": "nighthike",
"main": "./built/index.js",
"private": true,
@ -59,7 +59,7 @@
"@types/mocha": "5.2.3",
"@types/mongodb": "3.1.3",
"@types/ms": "0.7.30",
"@types/node": "10.5.5",
"@types/node": "10.5.6",
"@types/portscanner": "2.1.0",
"@types/pug": "2.0.4",
"@types/qrcode": "1.2.0",
@ -88,7 +88,7 @@
"bootstrap-vue": "2.0.0-rc.11",
"cafy": "11.3.0",
"chalk": "2.4.1",
"commander": "2.16.0",
"commander": "2.17.0",
"crc-32": "1.2.0",
"css-loader": "1.0.0",
"dateformat": "3.0.3",

View File

@ -1,6 +1,7 @@
<template>
<div class="xqnhankfuuilcwvhgsopeqncafzsquya">
<header><b>{{ blackUser | userName }}</b>(%i18n:common.reversi.black%) vs <b>{{ whiteUser | userName }}</b>(%i18n:common.reversi.white%)</header>
<button class="go-index" v-if="selfNav" @click="goIndex">%fa:arrow-left%</button>
<header><b><router-link :to="blackUser | userPage">{{ blackUser | userName }}</router-link></b>(%i18n:common.reversi.black%) vs <b><router-link :to="whiteUser | userPage">{{ whiteUser | userName }}</router-link></b>(%i18n:common.reversi.white%)</header>
<div style="overflow: hidden">
<p class="turn" v-if="!iAmPlayer && !game.isEnded">{{ '%i18n:common.reversi.turn-of%'.replace('{}', $options.filters.userName(turnUser)) }}<mk-ellipsis/></p>
@ -8,7 +9,10 @@
<p class="turn1" v-if="iAmPlayer && !game.isEnded && !isMyTurn">%i18n:common.reversi.opponent-turn%<mk-ellipsis/></p>
<p class="turn2" v-if="iAmPlayer && !game.isEnded && isMyTurn" v-animate-css="{ classes: 'tada', iteration: 'infinite' }">%i18n:common.reversi.my-turn%</p>
<p class="result" v-if="game.isEnded && logPos == logs.length">
<template v-if="game.winner">{{ '%i18n:common.reversi.won%'.replace('{}', $options.filters.userName(game.winner)) }}{{ game.settings.isLlotheo ? ' (ロセオ)' : '' }}</template>
<template v-if="game.winner">
<span>{{ '%i18n:common.reversi.won%'.replace('{}', $options.filters.userName(game.winner)) }}</span>
<span v-if="game.surrendered != null"> (%i18n:@surrendered%)</span>
</template>
<template v-else>%i18n:common.reversi.drawn%</template>
</p>
</div>
@ -41,6 +45,10 @@
<p class="status"><b>{{ '%i18n:common.reversi.this-turn%'.split('{}')[0] }}{{ logPos }}{{ '%i18n:common.reversi.this-turn%'.split('{}')[1] }}</b> %i18n:common.reversi.black%:{{ o.blackCount }} %i18n:common.reversi.white%:{{ o.whiteCount }} %i18n:common.reversi.total%:{{ o.blackCount + o.whiteCount }}</p>
<div class="actions" v-if="!game.isEnded && iAmPlayer">
<form-button @click="surrender">%i18n:@surrender%</form-button>
</div>
<div class="player" v-if="game.isEnded">
<el-button-group>
<el-button type="primary" @click="logPos = 0" :disabled="logPos == 0">%fa:angle-double-left%</el-button>
@ -62,7 +70,20 @@ import Reversi, { Color } from '../../../../../../../games/reversi/core';
import { url } from '../../../../../config';
export default Vue.extend({
props: ['initGame', 'connection'],
props: {
initGame: {
type: Object,
require: true
},
connection: {
type: Object,
require: true
},
selfNav: {
type: Boolean,
require: true
}
},
data() {
return {
@ -79,22 +100,27 @@ export default Vue.extend({
if (!this.$store.getters.isSignedIn) return false;
return this.game.user1Id == this.$store.state.i.id || this.game.user2Id == this.$store.state.i.id;
},
myColor(): Color {
if (!this.iAmPlayer) return null;
if (this.game.user1Id == this.$store.state.i.id && this.game.black == 1) return true;
if (this.game.user2Id == this.$store.state.i.id && this.game.black == 2) return true;
return false;
},
opColor(): Color {
if (!this.iAmPlayer) return null;
return this.myColor === true ? false : true;
},
blackUser(): any {
return this.game.black == 1 ? this.game.user1 : this.game.user2;
},
whiteUser(): any {
return this.game.black == 1 ? this.game.user2 : this.game.user1;
},
turnUser(): any {
if (this.o.turn === true) {
return this.game.black == 1 ? this.game.user1 : this.game.user2;
@ -104,11 +130,13 @@ export default Vue.extend({
return null;
}
},
isMyTurn(): boolean {
if (!this.iAmPlayer) return false;
if (this.turnUser == null) return false;
return this.turnUser.id == this.$store.state.i.id;
},
cellsStyle(): any {
return {
'grid-template-rows': `repeat(${this.game.settings.map.length}, 1fr)`,
@ -165,11 +193,13 @@ export default Vue.extend({
mounted() {
this.connection.on('set', this.onSet);
this.connection.on('rescue', this.onRescue);
this.connection.on('ended', this.onEnded);
},
beforeDestroy() {
this.connection.off('set', this.onSet);
this.connection.off('rescue', this.onRescue);
this.connection.off('ended', this.onEnded);
clearInterval(this.pollingClock);
},
@ -215,6 +245,10 @@ export default Vue.extend({
}
},
onEnded(x) {
this.game = x.game;
},
checkEnd() {
this.game.isEnded = this.o.isEnded;
if (this.game.isEnded) {
@ -250,6 +284,16 @@ export default Vue.extend({
this.checkEnd();
this.$forceUpdate();
},
surrender() {
(this as any).api('games/reversi/games/surrender', {
gameId: this.game.id
});
},
goIndex() {
this.$emit('go-index');
}
}
});
@ -261,10 +305,21 @@ export default Vue.extend({
root(isDark)
text-align center
> .go-index
position absolute
top 0
left 0
z-index 1
width 42px
height 42px
> header
padding 8px
border-bottom dashed 1px isDark ? #4c5761 : #c4cdd4
a
color inherit
> .board
width calc(100% - 16px)
max-width 500px
@ -381,6 +436,9 @@ root(isDark)
margin 0
padding 16px 0
> .actions
padding-bottom 16px
> .player
padding-bottom 32px

View File

@ -1,7 +1,7 @@
<template>
<div>
<x-room v-if="!g.isStarted" :game="g" :connection="connection"/>
<x-game v-else :init-game="g" :connection="connection"/>
<x-game v-else :init-game="g" :connection="connection" :self-nav="selfNav" @go-index="goIndex"/>
</div>
</template>
@ -16,7 +16,16 @@ export default Vue.extend({
XGame,
XRoom
},
props: ['game'],
props: {
game: {
type: Object,
required: true
},
selfNav: {
type: Boolean,
require: true
}
},
data() {
return {
connection: null,
@ -36,6 +45,9 @@ export default Vue.extend({
onStarted(game) {
Object.assign(this.g, game);
this.$forceUpdate();
},
goIndex() {
this.$emit('go-index');
}
}
});

View File

@ -96,11 +96,7 @@ export default Vue.extend({
methods: {
go(game) {
(this as any).api('games/reversi/games/show', {
gameId: game.id
}).then(game => {
this.$emit('go', game);
});
},
match() {

View File

@ -1,7 +1,7 @@
<template>
<div class="vchtoekanapleubgzioubdtmlkribzfd">
<div v-if="game">
<x-gameroom :game="game"/>
<x-gameroom :game="game" :self-nav="selfNav" @go-index="goIndex"/>
</div>
<div class="matching" v-else-if="matching">
<h1>{{ '%i18n:@matching.waiting-for%'.split('{}')[0] }}<b>{{ matching | userName }}</b>{{ '%i18n:@matching.waiting-for%'.split('{}')[1] }}<mk-ellipsis/></h1>
@ -34,6 +34,11 @@ export default Vue.extend({
gameId: {
type: String,
required: false
},
selfNav: {
type: Boolean,
require: false,
default: true
}
},
@ -48,6 +53,10 @@ export default Vue.extend({
},
watch: {
game() {
this.$emit('gamed', this.game);
},
gameId() {
this.fetch();
}
@ -91,18 +100,24 @@ export default Vue.extend({
(this as any).api('games/reversi/games/show', {
gameId: this.gameId
}).then(game => {
this.nav(game, true);
this.game = game;
Progress.done();
});
}
},
nav(game, silent) {
this.matching = null;
this.game = game;
async nav(game, actualNav = true) {
if (this.selfNav) {
// 受け取ったゲーム情報が省略されたものなら完全な情報を取得する
if (game != null && (game.settings == null || game.settings.map == null)) {
game = await (this as any).api('games/reversi/games/show', {
gameId: game.id
});
}
if (!silent) {
this.$emit('nav', this.game);
this.game = game;
} else {
this.$emit('nav', game, actualNav);
}
},
@ -121,7 +136,8 @@ export default Vue.extend({
}).then(game => {
if (game) {
this.matching = null;
this.game = game;
this.nav(game);
}
});
},
@ -129,6 +145,11 @@ export default Vue.extend({
onMatched(game) {
this.matching = null;
this.game = game;
this.nav(game, false);
},
goIndex() {
this.nav(null);
}
}
});

View File

@ -63,12 +63,23 @@ export default Vue.component('misskey-flavored-markdown', {
attrs: {
style: 'display: inline-block; font-size: 200%;'
},
directives: [{
directives: [this.$store.state.settings.disableAnimatedMfm ? {} : {
name: 'animate-css',
value: { classes: 'tada', iteration: 'infinite' }
}]
}, token.big);
case 'motion':
return (createElement as any)('span', {
attrs: {
style: 'display: inline-block;'
},
directives: [this.$store.state.settings.disableAnimatedMfm ? {} : {
name: 'animate-css',
value: { classes: 'rubberBand', iteration: 'infinite' }
}]
}, token.motion);
case 'url':
return createElement(MkUrl, {
props: {

View File

@ -55,6 +55,7 @@
<span>%i18n:@show-maps-desc%</span>
</mk-switch>
<mk-switch v-model="$store.state.settings.reversiBoardLabels" @change="onChangeReversiBoardLabels" text="%i18n:common.show-reversi-board-labels%"/>
<mk-switch v-model="$store.state.settings.disableAnimatedMfm" @change="onChangeDisableAnimatedMfm" text="%i18n:common.disable-animated-mfm%"/>
</section>
<section class="web" v-show="page == 'web'">
@ -376,6 +377,12 @@ export default Vue.extend({
value: v
});
},
onChangeDisableAnimatedMfm(v) {
this.$store.dispatch('settings/set', {
key: 'disableAnimatedMfm',
value: v
});
},
onChangeGradientWindowHeader(v) {
this.$store.dispatch('settings/set', {
key: 'gradientWindowHeader',

View File

@ -1,6 +1,6 @@
<template>
<component :is="ui ? 'mk-ui' : 'div'">
<mk-reversi :game-id="$route.params.game" @nav="nav"/>
<mk-reversi :game-id="$route.params.game" @nav="nav" :self-nav="false"/>
</component>
</template>
@ -14,9 +14,14 @@ export default Vue.extend({
}
},
methods: {
nav(game) {
history.pushState(null, null, '/reversi/' + game.id);
},
nav(game, actualNav) {
if (actualNav) {
this.$router.push('/reversi/' + game.id);
} else {
// TODO: https://github.com/vuejs/vue-router/issues/703
this.$router.push('/reversi/' + game.id);
}
}
}
});
</script>

View File

@ -1,7 +1,7 @@
<template>
<mk-ui>
<span slot="header">%fa:gamepad%%i18n:@reversi%</span>
<mk-reversi :game-id="$route.params.game" @nav="nav"/>
<mk-reversi :game-id="$route.params.game" @nav="nav" :self-nav="false"/>
</mk-ui>
</template>
@ -14,8 +14,13 @@ export default Vue.extend({
document.documentElement.style.background = '#fff';
},
methods: {
nav(game) {
history.pushState(null, null, '/reversi/' + game.id);
nav(game, actualNav) {
if (actualNav) {
this.$router.push('/reversi/' + game.id);
} else {
// TODO: https://github.com/vuejs/vue-router/issues/703
this.$router.push('/reversi/' + game.id);
}
}
}
});

View File

@ -14,6 +14,7 @@
<ui-switch v-model="$store.state.settings.circleIcons" @change="onChangeCircleIcons">%i18n:@circle-icons%</ui-switch>
<ui-switch v-model="$store.state.settings.iLikeSushi" @change="onChangeILikeSushi">%i18n:common.i-like-sushi%</ui-switch>
<ui-switch v-model="$store.state.settings.reversiBoardLabels" @change="onChangeReversiBoardLabels">%i18n:common.show-reversi-board-labels%</ui-switch>
<ui-switch v-model="$store.state.settings.disableAnimatedMfm" @change="onChangeDisableAnimatedMfm">%i18n:common.disable-animated-mfm%</ui-switch>
<div>
<div>%i18n:@timeline%</div>
@ -192,6 +193,13 @@ export default Vue.extend({
});
},
onChangeDisableAnimatedMfm(v) {
this.$store.dispatch('settings/set', {
key: 'disableAnimatedMfm',
value: v
});
},
onChangeShowReplyTarget(v) {
this.$store.dispatch('settings/set', {
key: 'showReplyTarget',

View File

@ -172,3 +172,6 @@ type: `textbox`
}
```
メッセージの種類: `success`, `info`, `warning`, `error`
## 投了する
投了をするには、<a href="./api/endpoints/games/reversi/games/surrender">このエンドポイント</a>にリクエストします。

View File

@ -18,6 +18,12 @@ const handlers: { [key: string]: (window: any, token: any, mentionedRemoteUsers:
document.body.appendChild(b);
},
motion({ document }, { big }) {
const b = document.createElement('strong');
b.textContent = big;
document.body.appendChild(b);
},
code({ document }, { code }) {
const pre = document.createElement('pre');
const inner = document.createElement('code');

View File

@ -1,5 +1,5 @@
/**
* Bold
* Big
*/
export type TextElementBig = {

View File

@ -0,0 +1,20 @@
/**
* Motion
*/
export type TextElementMotion = {
type: 'motion'
content: string
motion: string
};
export default function(text: string) {
const match = text.match(/^\(\(\((.+?)\)\)\)/);
if (!match) return null;
const motion = match[0];
return {
type: 'motion',
content: motion,
motion: match[1]
} as TextElementMotion;
}

View File

@ -14,6 +14,7 @@ import { TextElementQuote } from './elements/quote';
import { TextElementSearch } from './elements/search';
import { TextElementTitle } from './elements/title';
import { TextElementUrl } from './elements/url';
import { TextElementMotion } from './elements/motion';
const elements = [
require('./elements/big'),
@ -27,7 +28,8 @@ const elements = [
require('./elements/inline-code'),
require('./elements/quote'),
require('./elements/emoji'),
require('./elements/search')
require('./elements/search'),
require('./elements/motion')
].map(element => element.default as TextElementProcessor);
export type TextElement = { type: 'text', content: string }
@ -42,7 +44,8 @@ export type TextElement = { type: 'text', content: string }
| TextElementQuote
| TextElementSearch
| TextElementTitle
| TextElementUrl;
| TextElementUrl
| TextElementMotion;
export type TextElementProcessor = (text: string, i: number) => TextElement | TextElement[];
export default (source: string): TextElement[] => {

View File

@ -25,6 +25,7 @@ export interface IReversiGame {
isStarted: boolean;
isEnded: boolean;
winnerId: mongo.ObjectID;
surrendered: mongo.ObjectID;
logs: Array<{
at: Date;
color: boolean;

View File

@ -0,0 +1,59 @@
import $ from 'cafy'; import ID from '../../../../../../misc/cafy-id';
import ReversiGame, { pack } from '../../../../../../models/games/reversi/game';
import { ILocalUser } from '../../../../../../models/user';
import getParams from '../../../../get-params';
import { publishReversiGameStream } from '../../../../../../stream';
export const meta = {
desc: {
ja: '指定したリバーシの対局で投了します。'
},
requireCredential: true,
params: {
gameId: $.type(ID).optional.note({
desc: {
ja: '投了したい対局'
}
})
}
};
export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
const [ps, psErr] = getParams(meta, params);
if (psErr) return rej(psErr);
const game = await ReversiGame.findOne({ _id: ps.gameId });
if (game == null) {
return rej('game not found');
}
if (game.isEnded) {
return rej('this game is already ended');
}
if (!game.user1Id.equals(user._id) && !game.user2Id.equals(user._id)) {
return rej('access denied');
}
const winnerId = game.user1Id.equals(user._id) ? game.user2Id : game.user1Id;
await ReversiGame.update({
_id: game._id
}, {
$set: {
surrendered: user._id,
isEnded: true,
winnerId: winnerId
}
});
publishReversiGameStream(game._id, 'ended', {
winnerId: winnerId,
game: await pack(game._id, user)
});
res();
});

View File

@ -11,7 +11,7 @@ const handler = new EventEmitter();
let bot: IUser;
const post = async (text: string) => {
const post = async (text: string, home = true) => {
if (bot == null) {
const account = await User.findOne({
usernameLower: config.github_bot.username.toLowerCase()
@ -25,7 +25,7 @@ const post = async (text: string) => {
}
}
createNote(bot, { text, visibility: 'home' });
createNote(bot, { text, visibility: home ? 'home' : 'public' });
};
// Init router
@ -130,7 +130,7 @@ handler.on('issue_comment', event => {
handler.on('watch', event => {
const sender = event.sender;
post(`⭐️ Starred by **${sender.login}** ⭐️`);
post(`(((⭐️))) Starred by **${sender.login}** (((⭐️)))`, false);
});
handler.on('fork', event => {

View File

@ -39,6 +39,14 @@ describe('Text', () => {
], tokens);
});
it('motion', () => {
const tokens = analyze('(((Strawberry))) Pasta');
assert.deepEqual([
{ type: 'motion', content: '***Strawberry***', motion: 'Strawberry' },
{ type: 'text', content: ' Pasta' }
], tokens);
});
it('mention', () => {
const tokens = analyze('@himawari お腹ペコい');
assert.deepEqual([