diff options
| author | syuilo <Syuilotan@yahoo.co.jp> | 2018-08-03 23:01:14 +0900 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2018-08-03 23:01:14 +0900 |
| commit | e66ec6823d42fe8cc9267be6ea13422e929d989f (patch) | |
| tree | 8124d05bada0ecb4466796a8ae373b634104b224 /src | |
| parent | New translations ja.yml (English) (diff) | |
| parent | :pizza: (diff) | |
| download | misskey-e66ec6823d42fe8cc9267be6ea13422e929d989f.tar.gz misskey-e66ec6823d42fe8cc9267be6ea13422e929d989f.tar.bz2 misskey-e66ec6823d42fe8cc9267be6ea13422e929d989f.zip | |
Merge branch 'master' into l10n_master
Diffstat (limited to 'src')
46 files changed, 805 insertions, 509 deletions
diff --git a/src/client/app/auth/script.ts b/src/client/app/auth/script.ts index fd985c46ad..bdfdf70be3 100644 --- a/src/client/app/auth/script.ts +++ b/src/client/app/auth/script.ts @@ -15,7 +15,7 @@ import Index from './views/index.vue'; * init */ init(launch => { - document.title = 'Misskey | アプリの連携'; + document.title = '%i18n:common.name% | %i18n:common.application-authorization%'; // Init router const router = new VueRouter({ diff --git a/src/client/app/auth/views/form.vue b/src/client/app/auth/views/form.vue index 80086e3861..2d1e6d3e82 100644 --- a/src/client/app/auth/views/form.vue +++ b/src/client/app/auth/views/form.vue @@ -1,7 +1,7 @@ <template> <div class="form"> <header> - <h1><i>{{ app.name }}</i>があなたのアカウントにアクセスすることを<b>許可</b>しますか?</h1> + <h1>%i18n:@share-access%</h1> <img :src="app.iconUrl"/> </header> <div class="app"> @@ -11,25 +11,25 @@ <p class="description">{{ app.description }}</p> </section> <section> - <h2>このアプリは次の権限を要求しています:</h2> + <h2>%i18n:@permission-ask%</h2> <ul> <template v-for="p in app.permission"> - <li v-if="p == 'account-read'">アカウントの情報を見る。</li> - <li v-if="p == 'account-write'">アカウントの情報を操作する。</li> - <li v-if="p == 'note-write'">投稿する。</li> - <li v-if="p == 'like-write'">いいねしたりいいね解除する。</li> - <li v-if="p == 'following-write'">フォローしたりフォロー解除する。</li> - <li v-if="p == 'drive-read'">ドライブを見る。</li> - <li v-if="p == 'drive-write'">ドライブを操作する。</li> - <li v-if="p == 'notification-read'">通知を見る。</li> - <li v-if="p == 'notification-write'">通知を操作する。</li> + <li v-if="p == 'account-read'">%i18n:@account-read%</li> + <li v-if="p == 'account-write'">%i18n:@account-write%</li> + <li v-if="p == 'note-write'">%i18n:@note-write%</li> + <li v-if="p == 'like-write'">%i18n:@like-write%</li> + <li v-if="p == 'following-write'">%i18n:@following-write%</li> + <li v-if="p == 'drive-read'">%i18n:@drive-read%</li> + <li v-if="p == 'drive-write'">%i18n:@drive-write%</li> + <li v-if="p == 'notification-read'">%i18n:@notification-read%</li> + <li v-if="p == 'notification-write'">%i18n:@notification-write%</li> </template> </ul> </section> </div> <div class="action"> - <button @click="cancel">キャンセル</button> - <button @click="accept">アクセスを許可</button> + <button @click="cancel">%i18n:@cancel%</button> + <button @click="accept">%i18n:@accept%</button> </div> </div> </template> diff --git a/src/client/app/auth/views/index.vue b/src/client/app/auth/views/index.vue index 6d0ba3cda3..609e758994 100644 --- a/src/client/app/auth/views/index.vue +++ b/src/client/app/auth/views/index.vue @@ -1,7 +1,7 @@ <template> <div class="index"> <main v-if="$store.getters.isSignedIn"> - <p class="fetching" v-if="fetching">読み込み中<mk-ellipsis/></p> + <p class="fetching" v-if="fetching">%i18n:@loading%<mk-ellipsis/></p> <x-form class="form" ref="form" @@ -11,20 +11,20 @@ @accepted="accepted" /> <div class="denied" v-if="state == 'denied'"> - <h1>アプリケーションの連携をキャンセルしました。</h1> - <p>このアプリがあなたのアカウントにアクセスすることはありません。</p> + <h1>%i18n:@denied%</h1> + <p>%i18n:@denied-paragraph%</p> </div> <div class="accepted" v-if="state == 'accepted'"> - <h1>{{ session.app.isAuthorized ? 'このアプリは既に連携済みです' : 'アプリケーションの連携を許可しました' }}</h1> - <p v-if="session.app.callbackUrl">アプリケーションに戻っています<mk-ellipsis/></p> - <p v-if="!session.app.callbackUrl">アプリケーションに戻って、やっていってください。</p> + <h1>{{ session.app.isAuthorized ? '%i18n:@already-authorized%' : '%i18n:@allowed%' }}</h1> + <p v-if="session.app.callbackUrl">%i18n:@callback-url%<mk-ellipsis/></p> + <p v-if="!session.app.callbackUrl">%i18n:@please-go-back%</p> </div> <div class="error" v-if="state == 'fetch-session-error'"> - <p>セッションが存在しません。</p> + <p>%i18n:@error%</p> </div> </main> <main class="signin" v-if="!$store.getters.isSignedIn"> - <h1>サインインしてください</h1> + <h1>%i18n:@sign-in%</h1> <mk-signin/> </main> <footer><img src="/assets/auth/icon.svg" alt="Misskey"/></footer> diff --git a/src/client/app/common/scripts/compose-notification.ts b/src/client/app/common/scripts/compose-notification.ts index c93609bc59..4fb0610fd7 100644 --- a/src/client/app/common/scripts/compose-notification.ts +++ b/src/client/app/common/scripts/compose-notification.ts @@ -15,22 +15,22 @@ export default function(type, data): Notification { switch (type) { case 'drive_file_created': return { - title: 'ファイルがアップロードされました', + title: '%i18n:common.notification.file-uploaded%', body: data.name, icon: data.url }; case 'unread_messaging_message': return { - title: `${getUserName(data.user)}さんからメッセージ:`, + title: '%i18n:common.notification.message-from%'.split("{}")[0] + `${getUserName(data.user)}` + '%i18n:common.notification.message-from%'.split("{}")[1] , body: data.text, // TODO: getMessagingMessageSummary(data), icon: data.user.avatarUrl }; case 'reversi_invited': return { - title: '対局への招待があります', - body: `${getUserName(data.parent)}さんから`, + title: '%i18n:common.notification.reversi-invited%', + body: '%i18n:common.notification.reversi-invited-by%'.split("{}")[0] + `${getUserName(data.parent)}` + '%i18n:common.notification.reversi-invited-by%'.split("{}")[1], icon: data.parent.avatarUrl }; @@ -38,21 +38,21 @@ export default function(type, data): Notification { switch (data.type) { case 'mention': return { - title: `${getUserName(data.user)}さんから:`, + title: '%i18n:common.notification.notified-by%'.split("{}")[0] + `${getUserName(data.user)}さんから:` + '%i18n:common.notification.notified-by%'.split("{}")[1], body: getNoteSummary(data), icon: data.user.avatarUrl }; case 'reply': return { - title: `${getUserName(data.user)}さんから返信:`, + title: '%i18n:common.notification.reply-from%'.split("{}")[0] + `${getUserName(data.user)}` + '%i18n:common.notification.reply-from%'.split("{}")[1], body: getNoteSummary(data), icon: data.user.avatarUrl }; case 'quote': return { - title: `${getUserName(data.user)}さんが引用:`, + title: '%i18n:common.notification.quoted-by%'.split("{}")[0] + `${getUserName(data.user)}` + '%i18n:common.notification.quoted-by%'.split("{}")[1], body: getNoteSummary(data), icon: data.user.avatarUrl }; diff --git a/src/client/app/common/scripts/date-stringify.ts b/src/client/app/common/scripts/date-stringify.ts index e51de8833d..2b8e525567 100644 --- a/src/client/app/common/scripts/date-stringify.ts +++ b/src/client/app/common/scripts/date-stringify.ts @@ -1,12 +1,12 @@ export default date => { if (typeof date == 'string') date = new Date(date); return ( - date.getFullYear() + '年' + - (date.getMonth() + 1) + '月' + - date.getDate() + '日' + + date.getFullYear() + '%i18n:common.date.full-year%' + + (date.getMonth() + 1) + '%i18n:common.date.month%' + + date.getDate() + '%i18n:common.date.day%' + ' ' + - date.getHours() + '時' + - date.getMinutes() + '分' + + date.getHours() + '%i18n:common.date.hours%' + + date.getMinutes() + '%i18n:common.date.minutes%' + ' ' + `(${['日', '月', '火', '水', '木', '金', '土'][date.getDay()]})` ); diff --git a/src/client/app/common/scripts/fuck-ad-block.ts b/src/client/app/common/scripts/fuck-ad-block.ts index 9bcf7deeff..ed0904aeb3 100644 --- a/src/client/app/common/scripts/fuck-ad-block.ts +++ b/src/client/app/common/scripts/fuck-ad-block.ts @@ -5,8 +5,8 @@ declare const fuckAdBlock: any; export default (os) => { function adBlockDetected() { os.apis.dialog({ - title: '%fa:exclamation-triangle%広告ブロッカーを無効にしてください', - text: '<strong>Misskeyは広告を掲載していません</strong>が、広告をブロックする機能が有効だと一部の機能が利用できなかったり、不具合が発生する場合があります。', + title: '%fa:exclamation-triangle%%i18n:common.adblock.detected%', + text: '%i18n:common.adblock.warning%', actins: [{ text: 'OK' }] diff --git a/src/client/app/common/views/components/games/reversi/reversi.game.vue b/src/client/app/common/views/components/games/reversi/reversi.game.vue index de9c0395c7..bbfec2c1cc 100644 --- a/src/client/app/common/views/components/games/reversi/reversi.game.vue +++ b/src/client/app/common/views/components/games/reversi/reversi.game.vue @@ -1,14 +1,14 @@ <template> -<div class="root"> +<div class="xqnhankfuuilcwvhgsopeqncafzsquya"> <header><b>{{ blackUser | userName }}</b>(%i18n:common.reversi.black%) vs <b>{{ whiteUser | userName }}</b>(%i18n:common.reversi.white%)</header> <div style="overflow: hidden"> - <p class="turn" v-if="!iAmPlayer && !game.isEnded">{{ '%i18n:common.reversi.turn-of%'.replace('{}', turnUser | userName) }}<mk-ellipsis/></p> - <p class="turn" v-if="logPos != logs.length">{{ '%i18n:common.reversi.past-turn-of%'.replace('{}', turnUser | userName) }}</p> + <p class="turn" v-if="!iAmPlayer && !game.isEnded">{{ '%i18n:common.reversi.turn-of%'.replace('{}', $options.filters.userName(turnUser)) }}<mk-ellipsis/></p> + <p class="turn" v-if="logPos != logs.length">{{ '%i18n:common.reversi.past-turn-of%'.replace('{}', $options.filters.userName(turnUser)) }}</p> <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('{}', game.winner | userName) }}{{ game.settings.isLlotheo ? ' (ロセオ)' : '' }}</template> + <template v-if="game.winner">{{ '%i18n:common.reversi.won%'.replace('{}', $options.filters.userName(game.winner)) }}{{ game.settings.isLlotheo ? ' (ロセオ)' : '' }}</template> <template v-else>%i18n:common.reversi.drawn%</template> </p> </div> @@ -258,12 +258,12 @@ export default Vue.extend({ <style lang="stylus" scoped> @import '~const.styl' -.root +root(isDark) text-align center > header padding 8px - border-bottom dashed 1px #c4cdd4 + border-bottom dashed 1px isDark ? #4c5761 : #c4cdd4 > .board width calc(100% - 16px) @@ -327,16 +327,16 @@ export default Vue.extend({ user-select none &.empty - border solid 2px #eee + border solid 2px isDark ? #51595f : #eee &.empty.can - background #eee + background isDark ? #51595f : #eee &.empty.myTurn - border-color #ddd + border-color isDark ? #6a767f : #ddd &.can - background #eee + background isDark ? #51595f : #eee cursor pointer &:hover @@ -350,7 +350,7 @@ export default Vue.extend({ box-shadow 0 0 0 4px rgba($theme-color, 0.7) &.isEnded - border-color #ddd + border-color isDark ? #6a767f : #ddd &.none border-color transparent !important @@ -388,4 +388,11 @@ export default Vue.extend({ display inline-block margin 0 8px min-width 70px + +.xqnhankfuuilcwvhgsopeqncafzsquya[data-darkmode] + root(true) + +.xqnhankfuuilcwvhgsopeqncafzsquya:not([data-darkmode]) + root(false) + </style> diff --git a/src/client/app/common/views/components/games/reversi/reversi.index.vue b/src/client/app/common/views/components/games/reversi/reversi.index.vue new file mode 100644 index 0000000000..026159a0fd --- /dev/null +++ b/src/client/app/common/views/components/games/reversi/reversi.index.vue @@ -0,0 +1,258 @@ +<template> +<div class="phgnkghfpyvkrvwiajkiuoxyrdaqpzcx"> + <h1>%i18n:@title%</h1> + <p>%i18n:@sub-title%</p> + <div class="play"> + <!--<el-button round>フリーマッチ(準備中)</el-button>--> + <form-button primary round @click="match">%i18n:@invite%</form-button> + <details> + <summary>%i18n:@rule%</summary> + <div> + <p>%i18n:@rule-desc%</p> + <dl> + <dt><b>%i18n:@mode-invite%</b></dt> + <dd>%i18n:@mode-invite-desc%</dd> + </dl> + </div> + </details> + </div> + <section v-if="invitations.length > 0"> + <h2>%i18n:@invitations%</h2> + <div class="invitation" v-for="i in invitations" tabindex="-1" @click="accept(i)"> + <mk-avatar class="avatar" :user="i.parent"/> + <span class="name"><b>{{ i.parent | userName }}</b></span> + <span class="username">@{{ i.parent.username }}</span> + <mk-time :time="i.createdAt"/> + </div> + </section> + <section v-if="myGames.length > 0"> + <h2>%i18n:@my-games%</h2> + <a class="game" v-for="g in myGames" tabindex="-1" @click.prevent="go(g)" :href="`/reversi/${g.id}`"> + <mk-avatar class="avatar" :user="g.user1"/> + <mk-avatar class="avatar" :user="g.user2"/> + <span><b>{{ g.user1 | userName }}</b> vs <b>{{ g.user2 | userName }}</b></span> + <span class="state">{{ g.isEnded ? '%i18n:@game-state.ended%' : '%i18n:@game-state.playing%' }}</span> + </a> + </section> + <section v-if="games.length > 0"> + <h2>%i18n:@all-games%</h2> + <a class="game" v-for="g in games" tabindex="-1" @click.prevent="go(g)" :href="`/reversi/${g.id}`"> + <mk-avatar class="avatar" :user="g.user1"/> + <mk-avatar class="avatar" :user="g.user2"/> + <span><b>{{ g.user1 | userName }}</b> vs <b>{{ g.user2 | userName }}</b></span> + <span class="state">{{ g.isEnded ? '%i18n:@game-state.ended%' : '%i18n:@game-state.playing%' }}</span> + </a> + </section> +</div> +</template> + +<script lang="ts"> +import Vue from 'vue'; + +export default Vue.extend({ + data() { + return { + games: [], + gamesFetching: true, + gamesMoreFetching: false, + myGames: [], + matching: null, + invitations: [], + connection: null, + connectionId: null + }; + }, + + mounted() { + if (this.$store.getters.isSignedIn) { + this.connection = (this as any).os.streams.reversiStream.getConnection(); + this.connectionId = (this as any).os.streams.reversiStream.use(); + + this.connection.on('invited', this.onInvited); + + (this as any).api('games/reversi/games', { + my: true + }).then(games => { + this.myGames = games; + }); + + (this as any).api('games/reversi/invitations').then(invitations => { + this.invitations = this.invitations.concat(invitations); + }); + } + + (this as any).api('games/reversi/games').then(games => { + this.games = games; + this.gamesFetching = false; + }); + }, + + beforeDestroy() { + if (this.connection) { + this.connection.off('invited', this.onInvited); + (this as any).os.streams.reversiStream.dispose(this.connectionId); + } + }, + + methods: { + go(game) { + (this as any).api('games/reversi/games/show', { + gameId: game.id + }).then(game => { + this.$emit('go', game); + }); + }, + + match() { + (this as any).apis.input({ + title: '%i18n:@enter-username%' + }).then(username => { + (this as any).api('users/show', { + username + }).then(user => { + (this as any).api('games/reversi/match', { + userId: user.id + }).then(res => { + if (res == null) { + this.$emit('matching', user); + } else { + this.$emit('go', res); + } + }); + }); + }); + }, + + accept(invitation) { + (this as any).api('games/reversi/match', { + userId: invitation.parent.id + }).then(game => { + if (game) { + this.$emit('go', game); + } + }); + }, + + onInvited(invite) { + this.invitations.unshift(invite); + } + } +}); +</script> + +<style lang="stylus" scoped> +@import '~const.styl' + +root(isDark) + > h1 + margin 0 + padding 24px + font-size 24px + text-align center + font-weight normal + color #fff + background linear-gradient(to bottom, isDark ? #45730e : #8bca3e, isDark ? #464300 : #d6cf31) + + & + p + margin 0 + padding 12px + margin-bottom 12px + text-align center + font-size 14px + border-bottom solid 1px isDark ? #535f65 : #d3d9dc + + > .play + margin 0 auto + padding 0 16px + max-width 500px + text-align center + + > details + margin 8px 0 + + > div + padding 16px + font-size 14px + text-align left + background isDark ? #282c37 : #f5f5f5 + border-radius 8px + + > section + margin 0 auto + padding 0 16px 16px 16px + max-width 500px + border-top solid 1px isDark ? #535f65 : #d3d9dc + + > h2 + margin 0 + padding 16px 0 8px 0 + font-size 16px + font-weight bold + + .invitation + margin 8px 0 + padding 8px + color isDark ? #fff : #677f84 + background isDark ? #282c37 : #fff + box-shadow 0 2px 16px rgba(#000, isDark ? 0.7 : 0.15) + border-radius 6px + cursor pointer + + * + pointer-events none + user-select none + + &:focus + border-color $theme-color + + &:hover + background isDark ? #313543 : #f5f5f5 + + &:active + background isDark ? #1e222b : #eee + + > .avatar + width 32px + height 32px + border-radius 100% + + > span + margin 0 8px + line-height 32px + + .game + display block + margin 8px 0 + padding 8px + color isDark ? #fff : #677f84 + background isDark ? #282c37 : #fff + box-shadow 0 2px 16px rgba(#000, isDark ? 0.7 : 0.15) + border-radius 6px + cursor pointer + + * + pointer-events none + user-select none + + &:hover + background isDark ? #313543 : #f5f5f5 + + &:active + background isDark ? #1e222b : #eee + + > .avatar + width 32px + height 32px + border-radius 100% + + > span + margin 0 8px + line-height 32px + +.phgnkghfpyvkrvwiajkiuoxyrdaqpzcx[data-darkmode] + root(true) + +.phgnkghfpyvkrvwiajkiuoxyrdaqpzcx:not([data-darkmode]) + root(false) + +</style> diff --git a/src/client/app/common/views/components/games/reversi/reversi.room.vue b/src/client/app/common/views/components/games/reversi/reversi.room.vue index 94b36d0870..de5040f630 100644 --- a/src/client/app/common/views/components/games/reversi/reversi.room.vue +++ b/src/client/app/common/views/components/games/reversi/reversi.room.vue @@ -1,78 +1,94 @@ <template> -<div class="root"> +<div class="urbixznjwwuukfsckrwzwsqzsxornqij"> <header><b>{{ game.user1 | userName }}</b> vs <b>{{ game.user2 | userName }}</b></header> <div> <p>%i18n:@settings-of-the-game%</p> - <el-card class="map"> - <div slot="header"> - <el-select :class="$style.mapSelect" v-model="mapName" placeholder="%i18n:@choose-map%" @change="onMapChange"> - <el-option label="%i18n:@random%" :value="null"/> - <el-option-group v-for="c in mapCategories" :key="c" :label="c"> - <el-option v-for="m in maps" v-if="m.category == c" :key="m.name" :label="m.name" :value="m.name"> - <span style="float: left">{{ m.name }}</span> - <span style="float: right; color: #8492a6; font-size: 13px" v-if="m.author">(by <i>{{ m.author }}</i>)</span> - </el-option> - </el-option-group> - </el-select> - </div> - <div :class="$style.board" v-if="game.settings.map != null" :style="{ 'grid-template-rows': `repeat(${ game.settings.map.length }, 1fr)`, 'grid-template-columns': `repeat(${ game.settings.map[0].length }, 1fr)` }"> - <div v-for="(x, i) in game.settings.map.join('')" - :data-none="x == ' '" - @click="onPixelClick(i, x)" - > - <template v-if="x == 'b'">%fa:circle%</template> - <template v-if="x == 'w'">%fa:circle R%</template> + <div class="card map"> + <header> + <select v-model="mapName" placeholder="%i18n:@choose-map%" @change="onMapChange"> + <option label="-Custom-" :value="mapName" v-if="mapName == '-Custom-'"/> + <option label="%i18n:@random%" :value="null"/> + <optgroup v-for="c in mapCategories" :key="c" :label="c"> + <option v-for="m in maps" v-if="m.category == c" :key="m.name" :label="m.name" :value="m.name">{{ m.name }}</option> + </optgroup> + </select> + </header> + + <div> + <div class="random" v-if="game.settings.map == null">%fa:dice%</div> + <div class="board" v-else :style="{ 'grid-template-rows': `repeat(${ game.settings.map.length }, 1fr)`, 'grid-template-columns': `repeat(${ game.settings.map[0].length }, 1fr)` }"> + <div v-for="(x, i) in game.settings.map.join('')" + :data-none="x == ' '" + @click="onPixelClick(i, x)"> + <template v-if="x == 'b'"><template v-if="$store.state.device.darkmode">%fa:circle R%</template><template v-else>%fa:circle%</template></template> + <template v-if="x == 'w'"><template v-if="$store.state.device.darkmode">%fa:circle%</template><template v-else>%fa:circle R%</template></template> + </div> </div> </div> - </el-card> + </div> - <el-card class="bw"> - <div slot="header"> + <div class="card"> + <header> <span>%i18n:@black-or-white%</span> + </header> + + <div> + <form-radio v-model="game.settings.bw" value="random" @change="updateSettings">%i18n:@random%</form-radio> + <form-radio v-model="game.settings.bw" :value="1" @change="updateSettings">{{ '%i18n:@black-is%'.split('{}')[0] }}<b>{{ game.user1 | userName }}</b>{{ '%i18n:@black-is%'.split('{}')[1] }}</form-radio> + <form-radio v-model="game.settings.bw" :value="2" @change="updateSettings">{{ '%i18n:@black-is%'.split('{}')[0] }}<b>{{ game.user2 | userName }}</b>{{ '%i18n:@black-is%'.split('{}')[1] }}</form-radio> </div> - <el-radio v-model="game.settings.bw" label="random" @change="updateSettings">%i18n:@random%</el-radio> - <el-radio v-model="game.settings.bw" :label="1" @change="updateSettings">{{ '%i18n:@black-is%'.split('{}')[0] }}{{ game.user1 | userName }}{{ '%i18n:@black-is%'.split('{}')[1] }}</el-radio> - <el-radio v-model="game.settings.bw" :label="2" @change="updateSettings">{{ '%i18n:@black-is%'.split('{}')[0] }}{{ game.user2 | userName }}{{ '%i18n:@black-is%'.split('{}')[1] }}</el-radio> - </el-card> + </div> - <el-card class="rules"> - <div slot="header"> + <div class="card"> + <header> <span>%i18n:@rules%</span> + </header> + + <div> + <mk-switch v-model="game.settings.isLlotheo" @change="updateSettings" text="%i18n:@is-llotheo%"/> + <mk-switch v-model="game.settings.loopedBoard" @change="updateSettings" text="%i18n:@looped-map%"/> + <mk-switch v-model="game.settings.canPutEverywhere" @change="updateSettings" text="%i18n:@can-put-everywhere%"/> </div> - <mk-switch v-model="game.settings.isLlotheo" @change="updateSettings" text="%i18n:@is-llotheo%"/> - <mk-switch v-model="game.settings.loopedBoard" @change="updateSettings" text="%i18n:@looped-map%"/> - <mk-switch v-model="game.settings.canPutEverywhere" @change="updateSettings" text="%i18n:@can-put-everywhere%"/> - </el-card> + </div> - <el-card class="bot-form" v-if="form"> - <div slot="header"> + <div class="card" v-if="form"> + <header> <span>%i18n:@settings-of-the-bot%</span> - </div> - <el-alert v-for="message in messages" - :title="message.text" - :type="message.type" - :key="message.id" - /> - <template v-for="item in form"> - <mk-switch v-if="item.type == 'button'" v-model="item.value" :key="item.id" :text="item.label" @change="onChangeForm($event, item)">{{ item.desc || '' }}</mk-switch> + </header> - <el-card v-if="item.type == 'radio'" :key="item.id"> - <div slot="header"> - <span>{{ item.label }}</span> + <div> + <el-alert v-for="message in messages" + :title="message.text" + :type="message.type" + :key="message.id"/> + + <template v-for="item in form"> + <mk-switch v-if="item.type == 'button'" v-model="item.value" :key="item.id" :text="item.label" @change="onChangeForm($event, item)">{{ item.desc || '' }}</mk-switch> + + <div class="card" v-if="item.type == 'radio'" :key="item.id"> + <header> + <span>{{ item.label }}</span> + </header> + + <div> + <el-radio v-for="(r, i) in item.items" :key="item.id + ':' + i" v-model="item.value" :label="r.value" @change="onChangeForm($event, item)">{{ r.label }}</el-radio> + </div> </div> - <el-radio v-for="(r, i) in item.items" :key="item.id + ':' + i" v-model="item.value" :label="r.value" @change="onChangeForm($event, item)">{{ r.label }}</el-radio> - </el-card> - <el-card v-if="item.type == 'textbox'" :key="item.id"> - <div slot="header"> - <span>{{ item.label }}</span> + <div class="card" v-if="item.type == 'textbox'" :key="item.id"> + <header> + <span>{{ item.label }}</span> + </header> + + <div> + <el-input v-model="item.value" @change="onChangeForm($event, item)"/> + </div> </div> - <el-input v-model="item.value" @change="onChangeForm($event, item)"/> - </el-card> - </template> - </el-card> + </template> + </div> + </div> </div> <footer> @@ -84,9 +100,9 @@ </p> <div class="actions"> - <el-button @click="exit">%i18n:@cancel%</el-button> - <el-button type="primary" @click="accept" v-if="!isAccepted">%i18n:@ready%</el-button> - <el-button type="primary" @click="cancel" v-if="isAccepted">%i18n:@cancel-ready%</el-button> + <form-button @click="exit">%i18n:@cancel%</form-button> + <form-button primary @click="accept" v-if="!isAccepted">%i18n:@ready%</form-button> + <form-button primary @click="cancel" v-if="isAccepted">%i18n:@cancel-ready%</form-button> </div> </footer> </div> @@ -202,11 +218,11 @@ export default Vue.extend({ }); }, - onMapChange(v) { - if (v == null) { + onMapChange() { + if (this.mapName == null) { this.game.settings.map = null; } else { - this.game.settings.map = Object.values(maps).find(x => x.name == v).data; + this.game.settings.map = Object.values(maps).find(x => x.name == this.mapName).data; } this.$forceUpdate(); this.updateSettings(); @@ -233,9 +249,9 @@ export default Vue.extend({ <style lang="stylus" scoped> @import '~const.styl' -.root +root(isDark) text-align center - background #f9f9f9 + background isDark ? #191b22 : #f9f9f9 > header padding 8px @@ -244,54 +260,87 @@ export default Vue.extend({ > div padding 0 16px - > .map - > .bw - > .rules - > .bot-form - max-width 400px + > .card margin 0 auto 16px auto + &.map + > header + > select + width 100% + padding 12px 14px + background isDark ? #282C37 : #fff + border 1px solid isDark ? #6a707d : #dcdfe6 + border-radius 4px + color isDark ? #fff : #606266 + cursor pointer + transition border-color 0.2s cubic-bezier(0.645, 0.045, 0.355, 1) + + &:hover + border-color isDark ? #a7aebd : #c0c4cc + + &:focus + &:active + border-color $theme-color + + > div + > .random + padding 32px 0 + font-size 64px + color isDark ? #4e5961 : #d8d8d8 + + > .board + display grid + grid-gap 4px + width 300px + height 300px + margin 0 auto + color isDark ? #fff : #444 + + > div + background transparent + border solid 2px isDark ? #6a767f : #ddd + border-radius 6px + overflow hidden + cursor pointer + + * + pointer-events none + user-select none + width 100% + height 100% + + &[data-none] + border-color transparent + + .card + max-width 400px + border-radius 4px + background isDark ? #282C37 : #fff + color isDark ? #fff : #303133 + box-shadow 0 2px 12px 0 rgba(#000, 0.1) + + > header + padding 18px 20px + border-bottom 1px solid isDark ? #1c2023 : #ebeef5 + + > div + padding 20px + color isDark ? #fff : #606266 + > footer position sticky bottom 0 padding 16px - background rgba(255, 255, 255, 0.9) - border-top solid 1px #c4cdd4 + background rgba(isDark ? #191b22 : #fff, 0.9) + border-top solid 1px isDark ? #606266 : #c4cdd4 > .status margin 0 0 16px 0 -</style> - -<style lang="stylus" module> -.mapSelect - width 100% - -.board - display grid - grid-gap 4px - width 300px - height 300px - margin 0 auto - > div - background transparent - border solid 2px #ddd - border-radius 6px - overflow hidden - cursor pointer - - * - pointer-events none - user-select none - width 100% - height 100% +.urbixznjwwuukfsckrwzwsqzsxornqij[data-darkmode] + root(true) - &[data-none] - border-color transparent - -</style> +.urbixznjwwuukfsckrwzwsqzsxornqij:not([data-darkmode]) + root(false) -<style lang="stylus"> -.el-alert__content - position initial !important </style> diff --git a/src/client/app/common/views/components/games/reversi/reversi.vue b/src/client/app/common/views/components/games/reversi/reversi.vue index 43f1c6656a..94431845b0 100644 --- a/src/client/app/common/views/components/games/reversi/reversi.vue +++ b/src/client/app/common/views/components/games/reversi/reversi.vue @@ -1,58 +1,16 @@ <template> -<div class="mk-reversi"> +<div class="vchtoekanapleubgzioubdtmlkribzfd"> <div v-if="game"> <x-gameroom :game="game"/> </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> <div class="cancel"> - <el-button round @click="cancel">%i18n:@matching.cancel%</el-button> + <form-button round @click="cancel">%i18n:@matching.cancel%</form-button> </div> </div> <div class="index" v-else> - <h1>%i18n:@title%</h1> - <p>%i18n:@sub-title%</p> - <div class="play"> - <!--<el-button round>フリーマッチ(準備中)</el-button>--> - <el-button type="primary" round @click="match">%i18n:@invite%</el-button> - <details> - <summary>%i18n:@rule%</summary> - <div> - <p>%i18n:@rule-desc%</p> - <dl> - <dt><b>%i18n:@mode-invite%</b></dt> - <dd>%i18n:@mode-invite-desc%</dd> - </dl> - </div> - </details> - </div> - <section v-if="invitations.length > 0"> - <h2>%i18n:@invitations%</h2> - <div class="invitation" v-for="i in invitations" tabindex="-1" @click="accept(i)"> - <mk-avatar class="avatar" :user="i.parent"/> - <span class="name"><b>{{ i.parent | userName }}</b></span> - <span class="username">@{{ i.parent.username }}</span> - <mk-time :time="i.createdAt"/> - </div> - </section> - <section v-if="myGames.length > 0"> - <h2>%i18n:@my-games%</h2> - <a class="game" v-for="g in myGames" tabindex="-1" @click.prevent="go(g)" :href="`/reversi/${g.id}`"> - <mk-avatar class="avatar" :user="g.user1"/> - <mk-avatar class="avatar" :user="g.user2"/> - <span><b>{{ g.user1 | userName }}</b> vs <b>{{ g.user2 | userName }}</b></span> - <span class="state">{{ g.isEnded ? '%i18n:@game-state.ended%' : '%i18n:@game-state.playing%' }}</span> - </a> - </section> - <section v-if="games.length > 0"> - <h2>%i18n:@all-games%</h2> - <a class="game" v-for="g in games" tabindex="-1" @click.prevent="go(g)" :href="`/reversi/${g.id}`"> - <mk-avatar class="avatar" :user="g.user1"/> - <mk-avatar class="avatar" :user="g.user2"/> - <span><b>{{ g.user1 | userName }}</b> vs <b>{{ g.user2 | userName }}</b></span> - <span class="state">{{ g.isEnded ? '%i18n:@game-state.ended%' : '%i18n:@game-state.playing%' }}</span> - </a> - </section> + <x-index @go="nav" @matching="onMatching"/> </div> </div> </template> @@ -60,23 +18,26 @@ <script lang="ts"> import Vue from 'vue'; import XGameroom from './reversi.gameroom.vue'; +import XIndex from './reversi.index.vue'; +import Progress from '../../../../scripts/loading'; export default Vue.extend({ components: { - XGameroom + XGameroom, + XIndex }, - props: ['initGame'], + props: { + gameId: { + type: String, + required: false + } + }, data() { return { game: null, - games: [], - gamesFetching: true, - gamesMoreFetching: false, - myGames: [], matching: null, - invitations: [], connection: null, connectionId: null, pingClock: null @@ -84,14 +45,18 @@ export default Vue.extend({ }, watch: { - game(g) { - this.$emit('gamed', g); - } - }, - - created() { - if (this.initGame) { - this.game = this.initGame; + gameId(id) { + if (id == null) { + this.game = null; + } else { + Progress.start(); + (this as any).api('games/reversi/games/show', { + gameId: id + }).then(game => { + this.nav(game, true); + Progress.done(); + }); + } } }, @@ -101,17 +66,6 @@ export default Vue.extend({ this.connectionId = (this as any).os.streams.reversiStream.use(); this.connection.on('matched', this.onMatched); - this.connection.on('invited', this.onInvited); - - (this as any).api('games/reversi/games', { - my: true - }).then(games => { - this.myGames = games; - }); - - (this as any).api('games/reversi/invitations').then(invitations => { - this.invitations = this.invitations.concat(invitations); - }); this.pingClock = setInterval(() => { if (this.matching) { @@ -122,17 +76,11 @@ export default Vue.extend({ } }, 3000); } - - (this as any).api('games/reversi/games').then(games => { - this.games = games; - this.gamesFetching = false; - }); }, beforeDestroy() { if (this.connection) { this.connection.off('matched', this.onMatched); - this.connection.off('invited', this.onInvited); (this as any).os.streams.reversiStream.dispose(this.connectionId); clearInterval(this.pingClock); @@ -140,33 +88,17 @@ export default Vue.extend({ }, methods: { - go(game) { - (this as any).api('games/reversi/games/show', { - gameId: game.id - }).then(game => { - this.matching = null; - this.game = game; - }); + nav(game, silent) { + this.matching = null; + this.game = game; + + if (!silent) { + this.$emit('nav', this.game); + } }, - match() { - (this as any).apis.input({ - title: '%i18n:@enter-username%' - }).then(username => { - (this as any).api('users/show', { - username - }).then(user => { - (this as any).api('games/reversi/match', { - userId: user.id - }).then(res => { - if (res == null) { - this.matching = user; - } else { - this.game = res; - } - }); - }); - }); + onMatching(user) { + this.matching = user; }, cancel() { @@ -188,10 +120,6 @@ export default Vue.extend({ onMatched(game) { this.matching = null; this.game = game; - }, - - onInvited(invite) { - this.invitations.unshift(invite); } } }); @@ -200,9 +128,9 @@ export default Vue.extend({ <style lang="stylus" scoped> @import '~const.styl' -.mk-reversi - color #677f84 - background #fff +root(isDark) + color isDark ? #fff : #677f84 + background isDark ? #191b22 : #fff > .matching > h1 @@ -219,109 +147,10 @@ export default Vue.extend({ text-align center border-top dashed 1px #c4cdd4 - > .index - > h1 - margin 0 - padding 24px - font-size 24px - text-align center - font-weight normal - color #fff - background linear-gradient(to bottom, #8bca3e, #d6cf31) - - & + p - margin 0 - padding 12px - margin-bottom 12px - text-align center - font-size 14px - border-bottom solid 1px #d3d9dc - - > .play - margin 0 auto - padding 0 16px - max-width 500px - text-align center - - > details - margin 8px 0 - - > div - padding 16px - font-size 14px - text-align left - background #f5f5f5 - border-radius 8px - - > section - margin 0 auto - padding 0 16px 16px 16px - max-width 500px - border-top solid 1px #d3d9dc - - > h2 - margin 0 - padding 16px 0 8px 0 - font-size 16px - font-weight bold - - .invitation - margin 8px 0 - padding 8px - border solid 1px #e1e5e8 - border-radius 6px - cursor pointer - - * - pointer-events none - user-select none - - &:focus - border-color $theme-color - - &:hover - background #f5f5f5 - - &:active - background #eee - - > .avatar - width 32px - height 32px - border-radius 100% - - > span - margin 0 8px - line-height 32px - - .game - display block - margin 8px 0 - padding 8px - color #677f84 - border solid 1px #e1e5e8 - border-radius 6px - cursor pointer - - * - pointer-events none - user-select none - - &:focus - border-color $theme-color - - &:hover - background #f5f5f5 - - &:active - background #eee +.vchtoekanapleubgzioubdtmlkribzfd[data-darkmode] + root(true) - > .avatar - width 32px - height 32px - border-radius 100% +.vchtoekanapleubgzioubdtmlkribzfd:not([data-darkmode]) + root(false) - > span - margin 0 8px - line-height 32px </style> diff --git a/src/client/app/common/views/components/index.ts b/src/client/app/common/views/components/index.ts index c18a1c3b68..422a3da050 100644 --- a/src/client/app/common/views/components/index.ts +++ b/src/client/app/common/views/components/index.ts @@ -37,6 +37,8 @@ import uiTextarea from './ui/textarea.vue'; import uiSwitch from './ui/switch.vue'; import uiRadio from './ui/radio.vue'; import uiSelect from './ui/select.vue'; +import formButton from './ui/form/button.vue'; +import formRadio from './ui/form/radio.vue'; Vue.component('mk-analog-clock', analogClock); Vue.component('mk-menu', menu); @@ -75,3 +77,5 @@ Vue.component('ui-textarea', uiTextarea); Vue.component('ui-switch', uiSwitch); Vue.component('ui-radio', uiRadio); Vue.component('ui-select', uiSelect); +Vue.component('form-button', formButton); +Vue.component('form-radio', formRadio); diff --git a/src/client/app/common/views/components/ui/form/button.vue b/src/client/app/common/views/components/ui/form/button.vue new file mode 100644 index 0000000000..6e1475bc38 --- /dev/null +++ b/src/client/app/common/views/components/ui/form/button.vue @@ -0,0 +1,86 @@ +<template> +<div class="nvemkhtwcnnpkdrwfcbzuwhfulejhmzg" :class="{ round, primary }"> + <button @click="$emit('click')"> + <slot></slot> + </button> +</div> +</template> + +<script lang="ts"> +import Vue from 'vue'; +export default Vue.extend({ + props: { + round: { + type: Boolean, + required: false, + default: false + }, + primary: { + type: Boolean, + required: false, + default: false + } + } +}); +</script> + +<style lang="stylus" scoped> +@import '~const.styl' + +root(isDark) + display inline-block + + & + .nvemkhtwcnnpkdrwfcbzuwhfulejhmzg + margin-left 12px + + > button + display inline-block + margin 0 + padding 12px 20px + font-size 14px + border 1px solid isDark ? #6d727d : #dcdfe6 + border-radius 4px + outline none + box-shadow none + color isDark ? #fff : #606266 + transition 0.1s + + &:hover + &:focus + color $theme-color + background rgba($theme-color, isDark ? 0.2 : 0.12) + border-color rgba($theme-color, isDark ? 0.5 : 0.3) + + &:active + color darken($theme-color, 20%) + background rgba($theme-color, 0.12) + border-color $theme-color + transition all 0s + + &.primary + > button + border 1px solid $theme-color + background $theme-color + color $theme-color-foreground + + &:hover + &:focus + background lighten($theme-color, 20%) + border-color lighten($theme-color, 20%) + + &:active + background darken($theme-color, 20%) + border-color darken($theme-color, 20%) + transition all 0s + + &.round + > button + border-radius 64px + +.nvemkhtwcnnpkdrwfcbzuwhfulejhmzg[data-darkmode] + root(true) + +.nvemkhtwcnnpkdrwfcbzuwhfulejhmzg:not([data-darkmode]) + root(false) + +</style> diff --git a/src/client/app/common/views/components/ui/form/radio.vue b/src/client/app/common/views/components/ui/form/radio.vue new file mode 100644 index 0000000000..831981bb3e --- /dev/null +++ b/src/client/app/common/views/components/ui/form/radio.vue @@ -0,0 +1,126 @@ +<template> +<div + class="uywduthvrdnlpsvsjkqigicixgyfctto" + :class="{ disabled, checked }" + :aria-checked="checked" + :aria-disabled="disabled" + @click="toggle" +> + <input type="radio" + :disabled="disabled" + > + <span class="button"> + <span></span> + </span> + <span class="label"><slot></slot></span> +</div> +</template> + +<script lang="ts"> +import Vue from 'vue'; +export default Vue.extend({ + model: { + prop: 'model', + event: 'change' + }, + props: { + model: { + required: false + }, + value: { + required: false + }, + disabled: { + type: Boolean, + default: false + } + }, + computed: { + checked(): boolean { + return this.model === this.value; + } + }, + methods: { + toggle() { + this.$emit('change', this.value); + } + } +}); +</script> + +<style lang="stylus" scoped> +@import '~const.styl' + +root(isDark) + display inline-flex + margin 0 16px 0 0 + cursor pointer + transition all 0.3s + + > * + user-select none + + &:hover + > .button + border solid 2px isDark ? rgba(#fff, 0.7) : rgba(#000, 0.54) + + &.disabled + opacity 0.6 + cursor not-allowed + + &.checked + > .button + border-color $theme-color + + &:after + background-color $theme-color + transform scale(1) + opacity 1 + + > .label + color $theme-color + + > input + position absolute + width 0 + height 0 + opacity 0 + margin 0 + + > .button + display inline-block + flex-shrink 0 + width 20px + height 20px + background none + border solid 2px isDark ? rgba(#fff, 0.6) : rgba(#000, 0.4) + border-radius 100% + transition inherit + + &:after + content '' + display block + position absolute + top 3px + right 3px + bottom 3px + left 3px + border-radius 100% + opacity 0 + transform scale(0) + transition 0.4s cubic-bezier(0.25, 0.8, 0.25, 1) + + > .label + margin-left 8px + display block + font-size 14px + line-height 20px + cursor pointer + +.uywduthvrdnlpsvsjkqigicixgyfctto[data-darkmode] + root(true) + +.uywduthvrdnlpsvsjkqigicixgyfctto:not([data-darkmode]) + root(false) + +</style> diff --git a/src/client/app/common/views/pages/follow.vue b/src/client/app/common/views/pages/follow.vue index 4b8c2d3b7c..e1b5b1f120 100644 --- a/src/client/app/common/views/pages/follow.vue +++ b/src/client/app/common/views/pages/follow.vue @@ -71,7 +71,7 @@ export default Vue.extend({ this.user = user; this.fetching = false; Progress.done(); - document.title = getUserName(this.user) + ' | Misskey'; + document.title = getUserName(this.user) + ' | %i18n:common.name%'; }); }, diff --git a/src/client/app/desktop/script.ts b/src/client/app/desktop/script.ts index 297100e0e0..8175ce9b66 100644 --- a/src/client/app/desktop/script.ts +++ b/src/client/app/desktop/script.ts @@ -34,7 +34,7 @@ import MkMessagingRoom from './views/pages/messaging-room.vue'; import MkNote from './views/pages/note.vue'; import MkSearch from './views/pages/search.vue'; import MkTag from './views/pages/tag.vue'; -import MkReversi from './views/pages/reversi.vue'; +import MkReversi from './views/pages/games/reversi.vue'; import MkShare from './views/pages/share.vue'; import MkFollow from '../common/views/pages/follow.vue'; @@ -65,8 +65,7 @@ init(async (launch) => { { path: '/search', component: MkSearch }, { path: '/tags/:tag', component: MkTag }, { path: '/share', component: MkShare }, - { path: '/reversi', component: MkReversi }, - { path: '/reversi/:game', component: MkReversi }, + { path: '/reversi/:game?', component: MkReversi }, { path: '/@:user', component: MkUser }, { path: '/notes/:note', component: MkNote }, { path: '/authorize-follow', component: MkFollow } diff --git a/src/client/app/desktop/views/components/notes.vue b/src/client/app/desktop/views/components/notes.vue index c959508020..0ec2f16dbc 100644 --- a/src/client/app/desktop/views/components/notes.vue +++ b/src/client/app/desktop/views/components/notes.vue @@ -187,7 +187,7 @@ export default Vue.extend({ clearNotification() { this.unreadCount = 0; - document.title = 'Misskey'; + document.title = '%i18n:common.name%'; }, onVisibilitychange() { diff --git a/src/client/app/desktop/views/pages/games/reversi.vue b/src/client/app/desktop/views/pages/games/reversi.vue new file mode 100644 index 0000000000..590bda2d86 --- /dev/null +++ b/src/client/app/desktop/views/pages/games/reversi.vue @@ -0,0 +1,22 @@ +<template> +<component :is="ui ? 'mk-ui' : 'div'"> + <mk-reversi :game-id="$route.params.game" @nav="nav"/> +</component> +</template> + +<script lang="ts"> +import Vue from 'vue'; + +export default Vue.extend({ + props: { + ui: { + default: false + } + }, + methods: { + nav(game) { + history.pushState(null, null, '/reversi/' + game.id); + }, + } +}); +</script> diff --git a/src/client/app/desktop/views/pages/home-customize.vue b/src/client/app/desktop/views/pages/home-customize.vue index da5f15bb69..ffdcf39fe2 100644 --- a/src/client/app/desktop/views/pages/home-customize.vue +++ b/src/client/app/desktop/views/pages/home-customize.vue @@ -6,7 +6,7 @@ import Vue from 'vue'; export default Vue.extend({ mounted() { - document.title = 'Misskey - %i18n:@title%'; + document.title = '%i18n:common.name% - %i18n:@title%'; } }); </script> diff --git a/src/client/app/desktop/views/pages/home.vue b/src/client/app/desktop/views/pages/home.vue index 60b257edb7..0c42e42bd2 100644 --- a/src/client/app/desktop/views/pages/home.vue +++ b/src/client/app/desktop/views/pages/home.vue @@ -16,7 +16,7 @@ export default Vue.extend({ } }, mounted() { - document.title = 'Misskey'; + document.title = '%i18n:common.name%'; Progress.start(); }, diff --git a/src/client/app/desktop/views/pages/reversi.vue b/src/client/app/desktop/views/pages/reversi.vue deleted file mode 100644 index b484b81b5d..0000000000 --- a/src/client/app/desktop/views/pages/reversi.vue +++ /dev/null @@ -1,50 +0,0 @@ -<template> -<component :is="ui ? 'mk-ui' : 'div'"> - <mk-reversi v-if="!fetching" :init-game="game" @gamed="onGamed"/> -</component> -</template> - -<script lang="ts"> -import Vue from 'vue'; -import Progress from '../../../common/scripts/loading'; - -export default Vue.extend({ - props: { - ui: { - default: false - } - }, - data() { - return { - fetching: false, - game: null - }; - }, - watch: { - $route: 'fetch' - }, - created() { - this.fetch(); - }, - methods: { - fetch() { - if (this.$route.params.game == null) return; - - Progress.start(); - this.fetching = true; - - (this as any).api('games/reversi/games/show', { - gameId: this.$route.params.game - }).then(game => { - this.game = game; - this.fetching = false; - - Progress.done(); - }); - }, - onGamed(game) { - history.pushState(null, null, '/reversi/' + game.id); - } - } -}); -</script> diff --git a/src/client/app/desktop/views/pages/share.vue b/src/client/app/desktop/views/pages/share.vue index b1317f93e5..f5f5c4e184 100644 --- a/src/client/app/desktop/views/pages/share.vue +++ b/src/client/app/desktop/views/pages/share.vue @@ -1,12 +1,12 @@ <template> <div class="pptjhabgjtt7kwskbfv4y3uml6fpuhmr"> - <h1>%i18n:@share-with%</h1> + <h1>{{'%i18n:@share-with%'.split("{}")[0] + '%i18n:common.name%' + '%i18n:@share-with%'.split("{}")[1]}}</h1> <div> <mk-signin v-if="!$store.getters.isSignedIn"/> <mk-post-form v-else-if="!posted" :initial-text="text" :instant="true" @posted="posted = true"/> <p v-if="posted" class="posted">%fa:check%</p> </div> - <button v-if="posted" class="ui button" @click="close">%i18n:@close%</button> + <button v-if="posted" class="ui button" @click="close">%i18n:common.close%</button> </div> </template> diff --git a/src/client/app/desktop/views/pages/user/user.vue b/src/client/app/desktop/views/pages/user/user.vue index 64a4eaa872..1a83f81342 100644 --- a/src/client/app/desktop/views/pages/user/user.vue +++ b/src/client/app/desktop/views/pages/user/user.vue @@ -68,7 +68,7 @@ export default Vue.extend({ this.user = user; this.fetching = false; Progress.done(); - document.title = getUserName(this.user) + ' | Misskey'; + document.title = getUserName(this.user) + ' | %i18n:common.name%'; }); }, diff --git a/src/client/app/desktop/views/pages/welcome.vue b/src/client/app/desktop/views/pages/welcome.vue index 7449a3e5a4..9543a55b9a 100644 --- a/src/client/app/desktop/views/pages/welcome.vue +++ b/src/client/app/desktop/views/pages/welcome.vue @@ -17,7 +17,7 @@ <main> <div class="about"> <h1 v-if="name">{{ name }}</h1> - <h1 v-else><img :src="$store.state.device.darkmode ? 'assets/title.dark.svg' : 'assets/title.light.svg'" alt="Misskey"></h1> + <h1 v-else><img :src="$store.state.device.darkmode ? 'assets/title.dark.svg' : 'assets/title.light.svg'" alt="%i18n:common.name%"></h1> <p class="powerd-by" v-if="name">%i18n:@powered-by-misskey%</p> <p class="desc" v-html="description || '%i18n:common.about%'"></p> <a ref="signup" @click="signup">📦 %i18n:@signup%</a> @@ -32,7 +32,7 @@ <mk-nav class="nav"/> </div> <mk-forkit class="forkit"/> - <img src="assets/title.dark.svg" alt="Misskey"> + <img src="assets/title.dark.svg" alt="%i18n:common.name%"> </div> <div class="tl"> <mk-welcome-timeline :max="20"/> diff --git a/src/client/app/dev/views/ui.vue b/src/client/app/dev/views/ui.vue index 4a0fcee635..0a1cdf829b 100644 --- a/src/client/app/dev/views/ui.vue +++ b/src/client/app/dev/views/ui.vue @@ -1,7 +1,7 @@ <template> <div> <b-navbar toggleable="md" type="dark" variant="info"> - <b-navbar-brand>Misskey Developers</b-navbar-brand> + <b-navbar-brand>%i18n:common.name% Developers</b-navbar-brand> <b-navbar-nav> <b-nav-item to="/">Home</b-nav-item> <b-nav-item to="/apps">Apps</b-nav-item> diff --git a/src/client/app/mobile/script.ts b/src/client/app/mobile/script.ts index cb43f9d520..5b9d45462a 100644 --- a/src/client/app/mobile/script.ts +++ b/src/client/app/mobile/script.ts @@ -35,7 +35,7 @@ import MkFavorites from './views/pages/favorites.vue'; import MkUserLists from './views/pages/user-lists.vue'; import MkUserList from './views/pages/user-list.vue'; import MkSettings from './views/pages/settings.vue'; -import MkReversi from './views/pages/reversi.vue'; +import MkReversi from './views/pages/games/reversi.vue'; import MkTag from './views/pages/tag.vue'; import MkShare from './views/pages/share.vue'; import MkFollow from '../common/views/pages/follow.vue'; @@ -76,8 +76,7 @@ init((launch) => { { path: '/search', component: MkSearch }, { path: '/tags/:tag', component: MkTag }, { path: '/share', component: MkShare }, - { path: '/reversi', name: 'reversi', component: MkReversi }, - { path: '/reversi/:game', component: MkReversi }, + { path: '/reversi/:game?', name: 'reversi', component: MkReversi }, { path: '/@:user', component: MkUser }, { path: '/@:user/followers', component: MkFollowers }, { path: '/@:user/following', component: MkFollowing }, diff --git a/src/client/app/mobile/views/components/notes.vue b/src/client/app/mobile/views/components/notes.vue index 01f3d76c74..cba8ef1804 100644 --- a/src/client/app/mobile/views/components/notes.vue +++ b/src/client/app/mobile/views/components/notes.vue @@ -183,7 +183,7 @@ export default Vue.extend({ clearNotification() { this.unreadCount = 0; - document.title = 'Misskey'; + document.title = '%i18n:common.name%'; }, onVisibilitychange() { diff --git a/src/client/app/mobile/views/pages/drive.vue b/src/client/app/mobile/views/pages/drive.vue index 2cf3f510a2..9c635be05b 100644 --- a/src/client/app/mobile/views/pages/drive.vue +++ b/src/client/app/mobile/views/pages/drive.vue @@ -43,7 +43,7 @@ export default Vue.extend({ window.addEventListener('popstate', this.onPopState); }, mounted() { - document.title = 'Misskey Drive'; + document.title = '%i18n:common.name% Drive'; document.documentElement.style.background = '#fff'; }, beforeDestroy() { @@ -63,7 +63,7 @@ export default Vue.extend({ (this.$refs as any).browser.openContextMenu(); }, onMoveRoot(silent) { - const title = 'Misskey Drive'; + const title = '%i18n:common.name% Drive'; if (!silent) { // Rewrite URL @@ -76,7 +76,7 @@ export default Vue.extend({ this.folder = null; }, onOpenFolder(folder, silent) { - const title = folder.name + ' | Misskey Drive'; + const title = folder.name + ' | %i18n:common.name% Drive'; if (!silent) { // Rewrite URL @@ -89,7 +89,7 @@ export default Vue.extend({ this.folder = folder; }, onOpenFile(file, silent) { - const title = file.name + ' | Misskey Drive'; + const title = file.name + ' | %i18n:common.name% Drive'; if (!silent) { // Rewrite URL diff --git a/src/client/app/mobile/views/pages/favorites.vue b/src/client/app/mobile/views/pages/favorites.vue index 1cccf169b0..88a84bd8a2 100644 --- a/src/client/app/mobile/views/pages/favorites.vue +++ b/src/client/app/mobile/views/pages/favorites.vue @@ -28,7 +28,7 @@ export default Vue.extend({ this.fetch(); }, mounted() { - document.title = 'Misskey | %i18n:@notifications%'; + document.title = '%i18n:common.name% | %i18n:@notifications%'; }, methods: { fetch() { diff --git a/src/client/app/mobile/views/pages/followers.vue b/src/client/app/mobile/views/pages/followers.vue index 7dc72a7c30..4956eb1b94 100644 --- a/src/client/app/mobile/views/pages/followers.vue +++ b/src/client/app/mobile/views/pages/followers.vue @@ -49,7 +49,7 @@ export default Vue.extend({ this.user = user; this.fetching = false; - document.title = '%i18n:@followers-of%'.replace('{}', this.name) + ' | Misskey'; + document.title = '%i18n:@followers-of%'.replace('{}', this.name) + ' | %i18n:common.name%'; }); }, onLoaded() { diff --git a/src/client/app/mobile/views/pages/following.vue b/src/client/app/mobile/views/pages/following.vue index 6895a76d53..fa6807a245 100644 --- a/src/client/app/mobile/views/pages/following.vue +++ b/src/client/app/mobile/views/pages/following.vue @@ -48,7 +48,7 @@ export default Vue.extend({ this.user = user; this.fetching = false; - document.title = '%i18n:@followers-of%'.replace('{}', this.name) + ' | Misskey'; + document.title = '%i18n:@followers-of%'.replace('{}', this.name) + ' | %i18n:common.name%'; }); }, onLoaded() { diff --git a/src/client/app/mobile/views/pages/games/reversi.vue b/src/client/app/mobile/views/pages/games/reversi.vue new file mode 100644 index 0000000000..7118644ef3 --- /dev/null +++ b/src/client/app/mobile/views/pages/games/reversi.vue @@ -0,0 +1,22 @@ +<template> +<mk-ui> + <span slot="header">%fa:gamepad%%i18n:@reversi%</span> + <mk-reversi :game-id="$route.params.game" @nav="nav"/> +</mk-ui> +</template> + +<script lang="ts"> +import Vue from 'vue'; + +export default Vue.extend({ + mounted() { + document.title = '%i18n:common.name% %i18n:@reversi%'; + document.documentElement.style.background = '#fff'; + }, + methods: { + nav(game) { + history.pushState(null, null, '/reversi/' + game.id); + } + } +}); +</script> diff --git a/src/client/app/mobile/views/pages/home.vue b/src/client/app/mobile/views/pages/home.vue index 2f57e422a3..7b14c7ee98 100644 --- a/src/client/app/mobile/views/pages/home.vue +++ b/src/client/app/mobile/views/pages/home.vue @@ -96,7 +96,7 @@ export default Vue.extend({ }, mounted() { - document.title = 'Misskey'; + document.title = '%i18n:common.name%'; Progress.start(); diff --git a/src/client/app/mobile/views/pages/messaging-room.vue b/src/client/app/mobile/views/pages/messaging-room.vue index 35ae506761..24ffc658a3 100644 --- a/src/client/app/mobile/views/pages/messaging-room.vue +++ b/src/client/app/mobile/views/pages/messaging-room.vue @@ -47,7 +47,7 @@ export default Vue.extend({ this.user = user; this.fetching = false; - document.title = `%i18n:@messaging%: ${Vue.filter('userName')(this.user)} | Misskey`; + document.title = `%i18n:@messaging%: ${Vue.filter('userName')(this.user)} | %i18n:common.name%`; }); } } diff --git a/src/client/app/mobile/views/pages/messaging.vue b/src/client/app/mobile/views/pages/messaging.vue index 8dcbc5d6c5..b5a4f405fb 100644 --- a/src/client/app/mobile/views/pages/messaging.vue +++ b/src/client/app/mobile/views/pages/messaging.vue @@ -11,7 +11,7 @@ import getAcct from '../../../../../misc/acct/render'; export default Vue.extend({ mounted() { - document.title = 'Misskey %i18n:@messaging%'; + document.title = '%i18n:common.name% %i18n:@messaging%'; }, methods: { navigate(user) { diff --git a/src/client/app/mobile/views/pages/note.vue b/src/client/app/mobile/views/pages/note.vue index 146d89d22b..64d46f051b 100644 --- a/src/client/app/mobile/views/pages/note.vue +++ b/src/client/app/mobile/views/pages/note.vue @@ -31,7 +31,7 @@ export default Vue.extend({ this.fetch(); }, mounted() { - document.title = 'Misskey'; + document.title = '%i18n:common.name%'; }, methods: { fetch() { diff --git a/src/client/app/mobile/views/pages/notifications.vue b/src/client/app/mobile/views/pages/notifications.vue index fcd930997b..3688721613 100644 --- a/src/client/app/mobile/views/pages/notifications.vue +++ b/src/client/app/mobile/views/pages/notifications.vue @@ -15,7 +15,7 @@ import Progress from '../../../common/scripts/loading'; export default Vue.extend({ mounted() { - document.title = 'Misskey | %i18n:@notifications%'; + document.title = '%i18n:common.name% | %i18n:@notifications%'; Progress.start(); }, diff --git a/src/client/app/mobile/views/pages/received-follow-requests.vue b/src/client/app/mobile/views/pages/received-follow-requests.vue index bf26a84ff9..fff2fdea56 100644 --- a/src/client/app/mobile/views/pages/received-follow-requests.vue +++ b/src/client/app/mobile/views/pages/received-follow-requests.vue @@ -25,7 +25,7 @@ export default Vue.extend({ }; }, mounted() { - document.title = 'Misskey | %i18n:@title%'; + document.title = '%i18n:common.name% | %i18n:@title%'; Progress.start(); diff --git a/src/client/app/mobile/views/pages/reversi.vue b/src/client/app/mobile/views/pages/reversi.vue deleted file mode 100644 index a63f84aba2..0000000000 --- a/src/client/app/mobile/views/pages/reversi.vue +++ /dev/null @@ -1,50 +0,0 @@ -<template> -<mk-ui> - <span slot="header">%fa:gamepad%%i18n:@reversi%</span> - <mk-reversi v-if="!fetching" :init-game="game" @gamed="onGamed"/> -</mk-ui> -</template> - -<script lang="ts"> -import Vue from 'vue'; -import Progress from '../../../common/scripts/loading'; - -export default Vue.extend({ - data() { - return { - fetching: false, - game: null - }; - }, - watch: { - $route: 'fetch' - }, - created() { - this.fetch(); - }, - mounted() { - document.title = '%i18n:common.name% %i18n:@reversi%'; - document.documentElement.style.background = '#fff'; - }, - methods: { - fetch() { - if (this.$route.params.game == null) return; - - Progress.start(); - this.fetching = true; - - (this as any).api('games/reversi/games/show', { - gameId: this.$route.params.game - }).then(game => { - this.game = game; - this.fetching = false; - - Progress.done(); - }); - }, - onGamed(game) { - history.pushState(null, null, '/reversi/' + game.id); - } - } -}); -</script> diff --git a/src/client/app/mobile/views/pages/search.vue b/src/client/app/mobile/views/pages/search.vue index 2559922efb..7801068c1a 100644 --- a/src/client/app/mobile/views/pages/search.vue +++ b/src/client/app/mobile/views/pages/search.vue @@ -34,7 +34,7 @@ export default Vue.extend({ } }, mounted() { - document.title = `%i18n:@search%: ${this.q} | Misskey`; + document.title = `%i18n:@search%: ${this.q} | %i18n:common.name%`; this.fetch(); }, diff --git a/src/client/app/mobile/views/pages/settings.vue b/src/client/app/mobile/views/pages/settings.vue index f4645b1837..73bff55e44 100644 --- a/src/client/app/mobile/views/pages/settings.vue +++ b/src/client/app/mobile/views/pages/settings.vue @@ -142,7 +142,7 @@ export default Vue.extend({ }, mounted() { - document.title = 'Misskey | %i18n:@settings%'; + document.title = '%i18n:common.name% | %i18n:@settings%'; }, methods: { diff --git a/src/client/app/mobile/views/pages/share.vue b/src/client/app/mobile/views/pages/share.vue index c69498007d..3e33e32732 100644 --- a/src/client/app/mobile/views/pages/share.vue +++ b/src/client/app/mobile/views/pages/share.vue @@ -1,6 +1,6 @@ <template> <div class="azibmfpleajagva420swmu4c3r7ni7iw"> - <h1>Misskeyで共有</h1> + <h1>{{'%i18n:@share-with%'.split("{}")[0] + '%i18n:common.name%' + '%i18n:@share-with%'.split("{}")[1]}}</h1> <div> <mk-signin v-if="!$store.getters.isSignedIn"/> <mk-post-form v-else-if="!posted" :initial-text="text" :instant="true" @posted="posted = true"/> diff --git a/src/client/app/mobile/views/pages/user-lists.vue b/src/client/app/mobile/views/pages/user-lists.vue index 288295677e..1cce3e9bdd 100644 --- a/src/client/app/mobile/views/pages/user-lists.vue +++ b/src/client/app/mobile/views/pages/user-lists.vue @@ -23,7 +23,7 @@ export default Vue.extend({ }; }, mounted() { - document.title = 'Misskey | %i18n:@title%'; + document.title = '%i18n:common.name% | %i18n:@title%'; Progress.start(); diff --git a/src/client/app/mobile/views/pages/user.vue b/src/client/app/mobile/views/pages/user.vue index 2bc89b81be..d016345717 100644 --- a/src/client/app/mobile/views/pages/user.vue +++ b/src/client/app/mobile/views/pages/user.vue @@ -106,7 +106,7 @@ export default Vue.extend({ this.fetching = false; Progress.done(); - document.title = Vue.filter('userName')(this.user) + ' | Misskey'; + document.title = Vue.filter('userName')(this.user) + ' | %i18n:common.name%'; }); } } diff --git a/src/client/app/mobile/views/pages/welcome.vue b/src/client/app/mobile/views/pages/welcome.vue index d7c874af9a..acc8e2c490 100644 --- a/src/client/app/mobile/views/pages/welcome.vue +++ b/src/client/app/mobile/views/pages/welcome.vue @@ -1,7 +1,7 @@ <template> <div class="welcome"> <div> - <img :src="$store.state.device.darkmode ? 'assets/title.dark.svg' : 'assets/title.light.svg'" alt="Misskey"> + <img :src="$store.state.device.darkmode ? 'assets/title.dark.svg' : 'assets/title.light.svg'" alt="%i18n:common.name%"> <p class="host">{{ host }}</p> <div class="about"> <h2>{{ name || 'unidentified' }}</h2> diff --git a/src/client/app/mobile/views/pages/widgets.vue b/src/client/app/mobile/views/pages/widgets.vue index 0724cd03fa..4400132bf2 100644 --- a/src/client/app/mobile/views/pages/widgets.vue +++ b/src/client/app/mobile/views/pages/widgets.vue @@ -102,12 +102,12 @@ export default Vue.extend({ }, mounted() { - document.title = 'Misskey'; + document.title = '%i18n:common.name%'; }, methods: { hint() { - alert('ウィジェットを追加/削除したり並べ替えたりできます。ウィジェットを移動するには「三」をドラッグします。ウィジェットを削除するには「x」をタップします。いくつかのウィジェットはタップすることで表示を変更できます。'); + alert('%i18n:@widgets-hints%'); }, widgetFunc(id) { diff --git a/src/remote/activitypub/request.ts b/src/remote/activitypub/request.ts index e2b600ae2e..585c1c0ce8 100644 --- a/src/remote/activitypub/request.ts +++ b/src/remote/activitypub/request.ts @@ -20,18 +20,13 @@ export default (user: ILocalUser, url: string, object: any) => new Promise((reso method: 'POST', path: pathname + search, }, res => { - res.on('end', () => { - log(`${url} --> ${res.statusCode}`); + log(`${url} --> ${res.statusCode}`); - if (res.statusCode >= 200 && res.statusCode < 300) { - resolve(); - } else { - reject(res); - } - }); - - res.on('data', () => {}); - res.on('error', reject); + if (res.statusCode >= 400) { + reject(); + } else { + resolve(); + } }); sign(req, { |