diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml index e8038dfe14..8ce8e1e537 100644 --- a/locales/ja-JP.yml +++ b/locales/ja-JP.yml @@ -374,6 +374,31 @@ transfer: "譲渡" messagingWithUser: "ユーザーとチャット" messagingWithGroup: "グループでチャット" enable: "有効にする" +next: "次" + +_tutorial: + title: "Misskeyの使い方" + step1_1: "ようこそ。" + step1_2: "この画面は「タイムライン」と呼ばれ、あなたや、あなたが「フォロー」する人の「ノート」が時系列で表示されます。" + step1_3: "あなたはまだ何もノートを投稿しておらず、誰もフォローしていないので、タイムラインには何も表示されていないはずです。" + step2_1: "ノートを作成したり誰かをフォローしたりする前に、まずあなたのプロフィールを完成させましょう。" + step2_2: "あなたがどんな人かわかると、多くの人にノートを見てもらえたり、フォローしてもらいやすくなります。" + step3_1: "プロフィール設定はうまくできましたか?" + step3_2: "では試しに、何かノートを投稿してみてください。画面上にある鉛筆マークのボタンを押すとフォームが開きます。" + step3_3: "内容を書いたら、フォーム右上のボタンを押すと投稿できます。" + step3_4: "内容が思いつかない?「Misskey始めました」というのはいかがでしょう。" + step4_1: "投稿できましたか?" + step4_2: "あなたのノートがタイムラインに表示されていれば成功です。" + step5_1: "次は、他の人をフォローしてタイムラインを賑やかにしたいところです。" + step5_2: "{featured}で人気のノートが見れるので、その中から気になった人を選んでフォローしたり、{explore}で人気のユーザーを探すこともできます。" + step5_3: "ユーザーをフォローするには、ユーザーのアイコンをクリックしてユーザーページを表示し、「フォロー」ボタンを押します。" + step5_4: "ユーザーによっては、フォローが承認されるまで時間がかかる場合があります。" + step6_1: "タイムラインに他のユーザーのノートが表示されていれば成功です。" + step6_2: "他の人のノートには、「リアクション」を付けることができ、簡単にあなたの反応を伝えられます。" + step6_3: "リアクションを付けるには、ノートの「+」マークをクリックして、好きなリアクションを選択します。" + step7_1: "これで、Misskeyの基本的な使い方の説明は終わりました。お疲れ様でした。" + step7_2: "もっとMisskeyについて知りたいときは、{help}を見てみてください。" + step7_3: "では、Misskeyをお楽しみください🚀" _2fa: alreadyRegistered: "既に設定は完了しています。" diff --git a/src/client/components/misskey-flavored-markdown.vue b/src/client/components/misskey-flavored-markdown.vue index 960ecf355c..8fe6aba0cf 100644 --- a/src/client/components/misskey-flavored-markdown.vue +++ b/src/client/components/misskey-flavored-markdown.vue @@ -1,5 +1,5 @@ <template> -<mfm-core v-bind="$attrs" class="havbbuyv" :class="{ nowrap: $attrs['nowrap'] }" v-once/> +<mfm-core v-bind="$attrs" class="havbbuyv" :class="{ nowrap: $attrs['nowrap'] }"/> </template> <script lang="ts"> diff --git a/src/client/pages/index.home.vue b/src/client/pages/index.home.vue index 9f1642efa4..75ea81661d 100644 --- a/src/client/pages/index.home.vue +++ b/src/client/pages/index.home.vue @@ -13,16 +13,74 @@ <fa :icon="menuOpened ? faAngleUp : faAngleDown" style="margin-left: 8px;"/> </button> </portal> + + <section class="_card tutorial" v-if="tutorial != -1"> + <div class="_title">{{ $t('_tutorial.title') }}</div> + <div class="_content" v-if="tutorial === 0"> + <div>{{ $t('_tutorial.step1_1') }}</div> + <div>{{ $t('_tutorial.step1_2') }}</div> + <div>{{ $t('_tutorial.step1_3') }}</div> + </div> + <div class="_content" v-else-if="tutorial === 1"> + <div>{{ $t('_tutorial.step2_1') }}</div> + <div>{{ $t('_tutorial.step2_2') }}</div> + <router-link class="_link" to="/my/settings">{{ $t('editProfile') }}</router-link> + </div> + <div class="_content" v-else-if="tutorial === 2"> + <div>{{ $t('_tutorial.step3_1') }}</div> + <div>{{ $t('_tutorial.step3_2') }}</div> + <div>{{ $t('_tutorial.step3_3') }}</div> + <small>{{ $t('_tutorial.step3_4') }}</small> + </div> + <div class="_content" v-else-if="tutorial === 3"> + <div>{{ $t('_tutorial.step4_1') }}</div> + <div>{{ $t('_tutorial.step4_2') }}</div> + </div> + <div class="_content" v-else-if="tutorial === 4"> + <div>{{ $t('_tutorial.step5_1') }}</div> + <i18n path="_tutorial.step5_2" tag="div"> + <router-link class="_link" place="featured" to="/featured">{{ $t('featured') }}</router-link> + <router-link class="_link" place="explore" to="/explore">{{ $t('explore') }}</router-link> + </i18n> + <div>{{ $t('_tutorial.step5_3') }}</div> + <small>{{ $t('_tutorial.step5_4') }}</small> + </div> + <div class="_content" v-else-if="tutorial === 5"> + <div>{{ $t('_tutorial.step6_1') }}</div> + <div>{{ $t('_tutorial.step6_2') }}</div> + <div>{{ $t('_tutorial.step6_3') }}</div> + </div> + <div class="_content" v-else-if="tutorial === 6"> + <div>{{ $t('_tutorial.step7_1') }}</div> + <i18n path="_tutorial.step7_2" tag="div"> + <router-link class="_link" place="help" to="/docs">{{ $t('help') }}</router-link> + </i18n> + <div>{{ $t('_tutorial.step7_3') }}</div> + </div> + <div class="_footer navigation"> + <button class="arrow" @click="tutorial--" :disabled="tutorial === 0"> + <fa :icon="faChevronLeft"/> + </button> + <span>{{ tutorial + 1 }} / 7</span> + <button class="arrow" @click="tutorial++" :disabled="tutorial === 6"> + <fa :icon="faChevronRight"/> + </button> + <mk-button class="ok" @click="tutorial = -1" primary v-if="tutorial === 6"><fa :icon="faCheck"/> {{ $t('gotIt') }}</mk-button> + <mk-button class="ok" @click="tutorial++" primary v-else><fa :icon="faCheck"/> {{ $t('next') }}</mk-button> + </div> + </section> + <x-timeline ref="tl" :key="src === 'list' ? `list:${list.id}` : src === 'antenna' ? `antenna:${antenna.id}` : src" :src="src" :list="list" :antenna="antenna" @before="before()" @after="after()"/> </div> </template> <script lang="ts"> import Vue from 'vue'; -import { faAngleDown, faAngleUp, faHome, faShareAlt, faGlobe, faListUl, faSatellite, faCircle } from '@fortawesome/free-solid-svg-icons'; +import { faAngleDown, faAngleUp, faHome, faShareAlt, faGlobe, faListUl, faSatellite, faCircle, faChevronLeft, faChevronRight, faCheck } from '@fortawesome/free-solid-svg-icons'; import { faComments } from '@fortawesome/free-regular-svg-icons'; import Progress from '../scripts/loading'; import XTimeline from '../components/timeline.vue'; +import MkButton from '../components/ui/button.vue'; export default Vue.extend({ metaInfo() { @@ -32,7 +90,8 @@ export default Vue.extend({ }, components: { - XTimeline + XTimeline, + MkButton, }, props: { @@ -48,7 +107,7 @@ export default Vue.extend({ list: null, antenna: null, menuOpened: false, - faAngleDown, faAngleUp, faHome, faShareAlt, faGlobe, faComments, faListUl, faSatellite, faCircle + faAngleDown, faAngleUp, faHome, faShareAlt, faGlobe, faComments, faListUl, faSatellite, faCircle, faChevronLeft, faChevronRight, faCheck }; }, @@ -57,7 +116,11 @@ export default Vue.extend({ return { 't': this.focus }; - } + }, + tutorial: { + get() { return this.$store.state.settings.tutorial || 0; }, + set(value) { this.$store.dispatch('settings/set', { key: 'tutorial', value }); } + }, }, watch: { @@ -172,7 +235,41 @@ export default Vue.extend({ }); </script> -<style lang="scss"> +<style lang="scss" scoped> +.mk-home { + .tutorial { + margin-bottom: var(--margin); + + > ._content { + > small { + opacity: 0.7; + } + } + + > .navigation { + display: flex; + flex-direction: row; + align-items: baseline; + font-size: 18px; + + > .arrow { + color: var(--fg); + background: none; + border: none; + font-size: inherit; + + &:disabled { + opacity: 0.6; + } + } + + > .ok { + margin-left: auto; + } + } + } +} + ._kjvfvyph_ { position: relative; height: 100%; diff --git a/src/client/store.ts b/src/client/store.ts index 04598525b7..8e75e0acf2 100644 --- a/src/client/store.ts +++ b/src/client/store.ts @@ -5,6 +5,7 @@ import * as nestedProperty from 'nested-property'; import MiOS from './mios'; const defaultSettings = { + tutorial: 0, keepCw: false, showFullAcct: false, rememberNoteVisibility: false, diff --git a/src/server/api/endpoints/announcements.ts b/src/server/api/endpoints/announcements.ts index c6050d6092..2b7f90c31f 100644 --- a/src/server/api/endpoints/announcements.ts +++ b/src/server/api/endpoints/announcements.ts @@ -13,6 +13,11 @@ export const meta = { default: 10 }, + withUnreads: { + validator: $.optional.boolean, + default: false + }, + sinceId: { validator: $.optional.type(ID), }, @@ -38,5 +43,5 @@ export default define(meta, async (ps, user) => { } } - return announcements; + return ps.withUnreads ? announcements.filter((a: any) => !a.isRead) : announcements; });