summaryrefslogtreecommitdiff
path: root/packages/frontend/src/components/MkTutorialDialog.vue
diff options
context:
space:
mode:
authorかっこかり <67428053+kakkokari-gtyih@users.noreply.github.com>2023-11-03 15:35:07 +0900
committerGitHub <noreply@github.com>2023-11-03 15:35:07 +0900
commit24e629ca5c50789ff0aba31532ae66b51148d70f (patch)
tree513155452fd0644c6b69bf7e53e26ab6575977db /packages/frontend/src/components/MkTutorialDialog.vue
parentenhance: アカウント登録時のメールアドレス認証に30分の有... (diff)
downloadsharkey-24e629ca5c50789ff0aba31532ae66b51148d70f.tar.gz
sharkey-24e629ca5c50789ff0aba31532ae66b51148d70f.tar.bz2
sharkey-24e629ca5c50789ff0aba31532ae66b51148d70f.zip
enhance: 初期設定とチュートリアルを統合 (#12141)
* better onboarding experience * enhance: iroiro * (add) title * (enhance) 戻る・次へボタンを全ページでstickyに * fix merging * (add) iroiro * remove unnecessary file * Update CHANGELOG.md * tweak texts * (fix) reactionViewer mock * change strings * Update MkTutorialDialog.Note.vue * Update ja-JP.yml * (fix) reactionViewer error * (fix) path * refactor * fix * Update MkPostForm.vue * Update ja-JP.yml * Update ja-JP.yml * tweak text * Update ja-JP.yml * Update ja-JP.yml * Update ja-JP.yml * (add) achivement * (add) もう一度見れますよメッセージを追加 * Revert "feat: レジストリAPIをサードパーティから利用可能に (#12229)" This reverts commit 79346272f8792d35955efd3aaaa1e42e0cd2a6e3. * Revert "(add) もう一度見れますよメッセージを追加" This reverts commit 6123b35215133f0d5e5db356bb43f4acbafab8fa. * Revert "Revert "feat: レジストリAPIをサードパーティから利用可能に (#12229)"" This reverts commit bae684e484ef99308d7ac816a822047117efe1c6. * tweak --------- Co-authored-by: syuilo <Syuilotan@yahoo.co.jp>
Diffstat (limited to 'packages/frontend/src/components/MkTutorialDialog.vue')
-rw-r--r--packages/frontend/src/components/MkTutorialDialog.vue260
1 files changed, 260 insertions, 0 deletions
diff --git a/packages/frontend/src/components/MkTutorialDialog.vue b/packages/frontend/src/components/MkTutorialDialog.vue
new file mode 100644
index 0000000000..e28838425f
--- /dev/null
+++ b/packages/frontend/src/components/MkTutorialDialog.vue
@@ -0,0 +1,260 @@
+<!--
+SPDX-FileCopyrightText: syuilo and other misskey contributors
+SPDX-License-Identifier: AGPL-3.0-only
+-->
+
+<template>
+<MkModalWindow
+ ref="dialog"
+ :width="600"
+ :height="650"
+ @close="close(true)"
+ @closed="emit('closed')"
+>
+ <template v-if="page === 1" #header><i class="ti ti-pencil"></i> {{ i18n.ts._initialTutorial._note.title }}</template>
+ <template v-else-if="page === 2" #header><i class="ti ti-mood-smile"></i> {{ i18n.ts._initialTutorial._reaction.title }}</template>
+ <template v-else-if="page === 3" #header><i class="ti ti-home"></i> {{ i18n.ts._initialTutorial._timeline.title }}</template>
+ <template v-else-if="page === 4" #header><i class="ti ti-pencil-plus"></i> {{ i18n.ts._initialTutorial._postNote.title }}</template>
+ <template v-else-if="page === 5" #header><i class="ti ti-eye-exclamation"></i> {{ i18n.ts._initialTutorial._howToMakeAttachmentsSensitive.title }}</template>
+ <template v-else #header>{{ i18n.ts._initialTutorial.title }}</template>
+
+ <div style="overflow-x: clip;">
+ <Transition
+ mode="out-in"
+ :enterActiveClass="$style.transition_x_enterActive"
+ :leaveActiveClass="$style.transition_x_leaveActive"
+ :enterFromClass="$style.transition_x_enterFrom"
+ :leaveToClass="$style.transition_x_leaveTo"
+ >
+ <template v-if="page === 0">
+ <div :class="$style.centerPage">
+ <MkAnimBg style="position: absolute; top: 0;" :scale="1.5"/>
+ <MkSpacer :marginMin="20" :marginMax="28">
+ <div class="_gaps" style="text-align: center;">
+ <i class="ti ti-confetti" style="display: block; margin: auto; font-size: 3em; color: var(--accent);"></i>
+ <div style="font-size: 120%;">{{ i18n.ts._initialTutorial._landing.title }}</div>
+ <div>{{ i18n.ts._initialTutorial._landing.description }}</div>
+ <MkButton primary rounded gradate style="margin: 16px auto 0 auto;" @click="page++">{{ i18n.ts._initialTutorial.launchTutorial }} <i class="ti ti-arrow-right"></i></MkButton>
+ <MkButton style="margin: 0 auto;" transparent rounded @click="close(true)">{{ i18n.ts.close }}</MkButton>
+ </div>
+ </MkSpacer>
+ </div>
+ </template>
+ <template v-else-if="page === 1">
+ <div style="height: 100cqh; overflow: auto;">
+ <div :class="$style.pageRoot">
+ <MkSpacer :marginMin="20" :marginMax="28" :class="$style.pageMain">
+ <XNote phase="aboutNote"/>
+ </MkSpacer>
+ <div :class="$style.pageFooter">
+ <div class="_buttonsCenter">
+ <MkButton v-if="initialPage !== 1" rounded @click="page--"><i class="ti ti-arrow-left"></i> {{ i18n.ts.goBack }}</MkButton>
+ <MkButton primary rounded gradate @click="page++">{{ i18n.ts.continue }} <i class="ti ti-arrow-right"></i></MkButton>
+ </div>
+ </div>
+ </div>
+ </div>
+ </template>
+ <template v-else-if="page === 2">
+ <div style="height: 100cqh; overflow: auto;">
+ <div :class="$style.pageRoot">
+ <MkSpacer :marginMin="20" :marginMax="28" :class="$style.pageMain">
+ <div class="_gaps">
+ <XNote phase="howToReact" @reacted="isReactionTutorialPushed = true"/>
+ <div v-if="!isReactionTutorialPushed">{{ i18n.ts._initialTutorial._reaction.reactToContinue }}</div>
+ </div>
+ </MkSpacer>
+ <div :class="$style.pageFooter">
+ <div class="_buttonsCenter">
+ <MkButton v-if="initialPage !== 2" rounded @click="page--"><i class="ti ti-arrow-left"></i> {{ i18n.ts.goBack }}</MkButton>
+ <MkButton primary rounded gradate :disabled="!isReactionTutorialPushed" @click="page++">{{ i18n.ts.continue }} <i class="ti ti-arrow-right"></i></MkButton>
+ </div>
+ </div>
+ </div>
+ </div>
+ </template>
+ <template v-else-if="page === 3">
+ <div style="height: 100cqh; overflow: auto;">
+ <div :class="$style.pageRoot">
+ <MkSpacer :marginMin="20" :marginMax="28" :class="$style.pageMain">
+ <XTimeline/>
+ </MkSpacer>
+ <div :class="$style.pageFooter">
+ <div class="_buttonsCenter">
+ <MkButton v-if="initialPage !== 3" rounded @click="page--"><i class="ti ti-arrow-left"></i> {{ i18n.ts.goBack }}</MkButton>
+ <MkButton primary rounded gradate @click="page++">{{ i18n.ts.continue }} <i class="ti ti-arrow-right"></i></MkButton>
+ </div>
+ </div>
+ </div>
+ </div>
+ </template>
+ <template v-else-if="page === 4">
+ <div style="height: 100cqh; overflow: auto;">
+ <div :class="$style.pageRoot">
+ <MkSpacer :marginMin="20" :marginMax="28" :class="$style.pageMain">
+ <XPostNote/>
+ </MkSpacer>
+ <div :class="$style.pageFooter">
+ <div class="_buttonsCenter">
+ <MkButton v-if="initialPage !== 3" rounded @click="page--"><i class="ti ti-arrow-left"></i> {{ i18n.ts.goBack }}</MkButton>
+ <MkButton primary rounded gradate @click="page++">{{ i18n.ts.continue }} <i class="ti ti-arrow-right"></i></MkButton>
+ </div>
+ </div>
+ </div>
+ </div>
+ </template>
+ <template v-else-if="page === 5">
+ <div style="height: 100cqh; overflow: auto;">
+ <div :class="$style.pageRoot">
+ <MkSpacer :marginMin="20" :marginMax="28" :class="$style.pageMain">
+ <div class="_gaps">
+ <XSensitive @succeeded="isSensitiveTutorialSucceeded = true"/>
+ <div v-if="!isSensitiveTutorialSucceeded">{{ i18n.ts._initialTutorial._howToMakeAttachmentsSensitive.doItToContinue }}</div>
+ </div>
+ </MkSpacer>
+ <div :class="$style.pageFooter">
+ <div class="_buttonsCenter">
+ <MkButton v-if="initialPage !== 2" rounded @click="page--"><i class="ti ti-arrow-left"></i> {{ i18n.ts.goBack }}</MkButton>
+ <MkButton primary rounded gradate :disabled="!isSensitiveTutorialSucceeded" @click="page++">{{ i18n.ts.continue }} <i class="ti ti-arrow-right"></i></MkButton>
+ </div>
+ </div>
+ </div>
+ </div>
+ </template>
+ <template v-else-if="page === 6">
+ <div :class="$style.centerPage">
+ <MkAnimBg style="position: absolute; top: 0;" :scale="1.5"/>
+ <MkSpacer :marginMin="20" :marginMax="28">
+ <div class="_gaps" style="text-align: center;">
+ <i class="ti ti-check" style="display: block; margin: auto; font-size: 3em; color: var(--accent);"></i>
+ <div style="font-size: 120%;">{{ i18n.ts._initialTutorial._done.title }}</div>
+ <I18n :src="i18n.ts._initialTutorial._done.description" tag="div" style="padding: 0 16px;">
+ <template #link>
+ <a href="https://misskey-hub.net/help.html" target="_blank" class="_link">{{ i18n.ts.help }}</a>
+ </template>
+ </I18n>
+ <div>{{ i18n.t('_initialAccountSetting.haveFun', { name: instance.name ?? host }) }}</div>
+ <div class="_buttonsCenter" style="margin-top: 16px;">
+ <MkButton v-if="initialPage !== 4" rounded @click="page--"><i class="ti ti-arrow-left"></i> {{ i18n.ts.goBack }}</MkButton>
+ <MkButton rounded primary gradate @click="close(false)">{{ i18n.ts.close }}</MkButton>
+ </div>
+ </div>
+ </MkSpacer>
+ </div>
+ </template>
+ </Transition>
+ </div>
+</MkModalWindow>
+</template>
+
+<script lang="ts" setup>
+import { ref, shallowRef, watch } from 'vue';
+import MkModalWindow from '@/components/MkModalWindow.vue';
+import MkButton from '@/components/MkButton.vue';
+import XNote from '@/components/MkTutorialDialog.Note.vue';
+import XTimeline from '@/components/MkTutorialDialog.Timeline.vue';
+import XPostNote from '@/components/MkTutorialDialog.PostNote.vue';
+import XSensitive from '@/components/MkTutorialDialog.Sensitive.vue';
+import MkAnimBg from '@/components/MkAnimBg.vue';
+import { i18n } from '@/i18n.js';
+import { instance } from '@/instance.js';
+import { host } from '@/config.js';
+import { claimAchievement } from '@/scripts/achievements.js';
+import * as os from '@/os.js';
+
+const props = defineProps<{
+ initialPage?: number;
+}>();
+
+const emit = defineEmits<{
+ (ev: 'closed'): void;
+}>();
+
+const dialog = shallowRef<InstanceType<typeof MkModalWindow>>();
+
+// eslint-disable-next-line vue/no-setup-props-destructure
+const page = ref(props.initialPage ?? 0);
+
+watch(page, (to) => {
+ // チュートリアルの枚数を増やしたら必ず変更すること!!
+ if (to === 6) {
+ claimAchievement('tutorialCompleted');
+ }
+});
+
+const isReactionTutorialPushed = ref<boolean>(false);
+const isSensitiveTutorialSucceeded = ref<boolean>(false);
+
+async function close(skip: boolean) {
+ if (skip) {
+ const { canceled } = await os.confirm({
+ type: 'warning',
+ text: i18n.ts._initialTutorial.skipAreYouSure,
+ });
+ if (canceled) return;
+ }
+
+ dialog.value?.close();
+}
+</script>
+
+<style lang="scss" module>
+.transition_x_enterActive,
+.transition_x_leaveActive {
+ transition: opacity 0.3s cubic-bezier(0,0,.35,1), transform 0.3s cubic-bezier(0,0,.35,1);
+}
+.transition_x_enterFrom {
+ opacity: 0;
+ transform: translateX(50px);
+}
+.transition_x_leaveTo {
+ opacity: 0;
+ transform: translateX(-50px);
+}
+
+.progressBar {
+ position: absolute;
+ top: 0;
+ left: 0;
+ z-index: 10;
+ width: 100%;
+ height: 4px;
+}
+
+.progressBarValue {
+ height: 100%;
+ background: linear-gradient(90deg, var(--buttonGradateA), var(--buttonGradateB));
+ transition: all 0.5s cubic-bezier(0,.5,.5,1);
+}
+
+.centerPage {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ height: 100cqh;
+ padding-bottom: 30px;
+ box-sizing: border-box;
+}
+
+.pageRoot {
+ display: flex;
+ flex-direction: column;
+ min-height: 100%;
+}
+
+.pageMain {
+ flex-grow: 1;
+ line-height: 1.5;
+}
+
+.pageFooter {
+ position: sticky;
+ bottom: 0;
+ left: 0;
+ flex-shrink: 0;
+ padding: 12px;
+ border-top: solid 0.5px var(--divider);
+ -webkit-backdrop-filter: blur(15px);
+ backdrop-filter: blur(15px);
+}
+</style>