diff --git a/locales/index.d.ts b/locales/index.d.ts index d483fea83..44dcfc63f 100644 --- a/locales/index.d.ts +++ b/locales/index.d.ts @@ -4884,6 +4884,14 @@ export interface Locale extends ILocale { * スワイプしてタブを切り替える */ "enableHorizontalSwipe": string; + /** + * チュートリアルをスキップできないようにする + */ + "prohibitSkippingTutorial": string; + /** + * 新規登録したユーザーに表示されるチュートリアルをスキップできないようにします。チュートリアルを完了せずチュートリアルページを回避した場合でも、強制的にリダイレクトされます。 + */ + "prohibitSkippingTutorialDescription": string; "_bubbleGame": { /** * 遊び方 @@ -4954,68 +4962,6 @@ export interface Locale extends ILocale { */ "silenceDescription": string; }; - "_initialAccountSetting": { - /** - * アカウントの作成が完了しました! - */ - "accountCreated": string; - /** - * さっそくアカウントの初期設定を行いましょう。 - */ - "letsStartAccountSetup": string; - /** - * まずはあなたのプロフィールを設定しましょう。 - */ - "letsFillYourProfile": string; - /** - * プロフィール設定 - */ - "profileSetting": string; - /** - * プライバシー設定 - */ - "privacySetting": string; - /** - * これらの設定は後から変更できます。 - */ - "theseSettingsCanEditLater": string; - /** - * この他にも様々な設定を「設定」ページから行えます。ぜひ後で確認してみてください。 - */ - "youCanEditMoreSettingsInSettingsPageLater": string; - /** - * タイムラインを構築するため、気になるユーザーをフォローしてみましょう。 - */ - "followUsers": string; - /** - * プッシュ通知を有効にすると{name}の通知をお使いのデバイスで受け取ることができます。 - */ - "pushNotificationDescription": ParameterizedString<"name">; - /** - * 初期設定が完了しました! - */ - "initialAccountSettingCompleted": string; - /** - * {name}をお楽しみください! - */ - "haveFun": ParameterizedString<"name">; - /** - * このまま{name}(Misskey)の使い方についてのチュートリアルに進むこともできますが、ここで中断してすぐに使い始めることもできます。 - */ - "youCanContinueTutorial": ParameterizedString<"name">; - /** - * チュートリアルを開始 - */ - "startTutorial": string; - /** - * 初期設定をスキップしますか? - */ - "skipAreYouSure": string; - /** - * 初期設定をあとでやり直しますか? - */ - "laterAreYouSure": string; - }; "_initialTutorial": { /** * チュートリアルを見る @@ -5129,6 +5075,16 @@ export interface Locale extends ILocale { */ "description3": ParameterizedString<"link">; }; + "_followUsers": { + /** + * 誰もフォローしていない状態だと、ホームタイムラインには何も表示されません。 + */ + "description1": string; + /** + * タイムラインを構築するため、気になるユーザーをフォローしてみましょう。 + */ + "description2": string; + }; "_postNote": { /** * ノートの投稿設定 @@ -5229,6 +5185,30 @@ export interface Locale extends ILocale { */ "doItToContinue": string; }; + "_pushNotification": { + /** + * プッシュ通知を有効にすると{name}の通知をお使いのデバイスで受け取ることができます。 + */ + "description": ParameterizedString<"name">; + }; + "_privacySettings": { + /** + * プライバシー設定 + */ + "title": string; + /** + * 多くのユーザーが利用しているプライバシー関連の設定項目をリストアップしました。必要に応じて変更してください。 + */ + "description1": string; + /** + * これらの設定は後から変更できます。 + */ + "theseSettingsCanEditLater": string; + /** + * この他にも様々な設定を「設定」ページから行えます。ぜひ後で確認してみてください。 + */ + "youCanEditMoreSettingsInSettingsPageLater": string; + }; "_done": { /** * チュートリアルは終了です🎉 @@ -5238,6 +5218,67 @@ export interface Locale extends ILocale { * ここで紹介した機能はほんの一部にすぎません。Misskeyの使い方をより詳しく知るには、{link}をご覧ください。 */ "description": ParameterizedString<"link">; + /** + * {name}をお楽しみください! + */ + "haveFun": ParameterizedString<"name">; + /** + * このチュートリアルは、「もっと!」→「情報」→「チュートリアルを見る」からいつでも見返すことができます。 + */ + "youCanReferTutorialBy": string; + }; + "_onboardingLanding": { + /** + * アカウントの作成が完了しました! + */ + "accountCreated": string; + /** + * ようこそ、{name}へ! + */ + "welcomeToX": ParameterizedString<"name">; + /** + * 「{name}に登録したは良いものの、どう使えばいいか分からない…💦」といったことを防ぐために、まずはMisskeyの基本的な使い方を学びましょう。 + */ + "description": ParameterizedString<"name">; + /** + * このチュートリアルの所要時間は{min}分程度です。 + * チュートリアルを完了すると実績が解除されます。 + */ + "takesAbout": ParameterizedString<"min">; + }; + "_onboardingDone": { + /** + * お疲れ様でした!次のステップに進んで、{name}をもっと楽しめるようにしましょう。 + */ + "description": ParameterizedString<"name">; + /** + * 元のページに戻る + */ + "backToOriginalPath": string; + /** + * あなたがアクセスしようとしていたページに戻ります。 + */ + "backToOriginalPathDescription": string; + /** + * プロフィール設定 + */ + "profile": string; + /** + * 他のユーザーが親しみやすいように、プロフィールをつくりましょう。 + */ + "profileDescription": string; + /** + * 人気のノートやユーザーを見つけて交流をはじめましょう。 + */ + "exploreDescription": string; + /** + * ホーム画面に進む + */ + "goToTimeline": string; + /** + * 設定等を行わず、通常のホーム画面(タイムライン)に進みます。 + */ + "goToTimelineDescription": string; }; }; "_timelineDescription": { diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml index 7e16619fc..401285ca3 100644 --- a/locales/ja-JP.yml +++ b/locales/ja-JP.yml @@ -1217,6 +1217,8 @@ hemisphere: "お住まいの地域" withSensitive: "センシティブなファイルを含むノートを表示" userSaysSomethingSensitive: "{name}のセンシティブなファイルを含む投稿" enableHorizontalSwipe: "スワイプしてタブを切り替える" +prohibitSkippingTutorial: "チュートリアルをスキップできないようにする" +prohibitSkippingTutorialDescription: "新規登録したユーザーに表示されるチュートリアルをスキップできないようにします。チュートリアルを完了せずチュートリアルページを回避した場合でも、強制的にリダイレクトされます。" _bubbleGame: howToPlay: "遊び方" @@ -1239,23 +1241,6 @@ _announcement: silence: "非通知" silenceDescription: "オンにすると、このお知らせは通知されず、既読にする必要もなくなります。" -_initialAccountSetting: - accountCreated: "アカウントの作成が完了しました!" - letsStartAccountSetup: "さっそくアカウントの初期設定を行いましょう。" - letsFillYourProfile: "まずはあなたのプロフィールを設定しましょう。" - profileSetting: "プロフィール設定" - privacySetting: "プライバシー設定" - theseSettingsCanEditLater: "これらの設定は後から変更できます。" - youCanEditMoreSettingsInSettingsPageLater: "この他にも様々な設定を「設定」ページから行えます。ぜひ後で確認してみてください。" - followUsers: "タイムラインを構築するため、気になるユーザーをフォローしてみましょう。" - pushNotificationDescription: "プッシュ通知を有効にすると{name}の通知をお使いのデバイスで受け取ることができます。" - initialAccountSettingCompleted: "初期設定が完了しました!" - haveFun: "{name}をお楽しみください!" - youCanContinueTutorial: "このまま{name}(Misskey)の使い方についてのチュートリアルに進むこともできますが、ここで中断してすぐに使い始めることもできます。" - startTutorial: "チュートリアルを開始" - skipAreYouSure: "初期設定をスキップしますか?" - laterAreYouSure: "初期設定をあとでやり直しますか?" - _initialTutorial: launchTutorial: "チュートリアルを見る" title: "チュートリアル" @@ -1287,6 +1272,9 @@ _initialTutorial: global: "接続している他のすべてのサーバーからの投稿を見られます。" description2: "それぞれのタイムラインは、画面上部でいつでも切り替えられます。" description3: "その他にも、リストタイムラインやチャンネルタイムラインなどがあります。詳しくは{link}をご覧ください。" + _followUsers: + description1: "誰もフォローしていない状態だと、ホームタイムラインには何も表示されません。" + description2: "タイムラインを構築するため、気になるユーザーをフォローしてみましょう。" _postNote: title: "ノートの投稿設定" description1: "Misskeyにノートを投稿する際には、様々なオプションの設定が可能です。投稿フォームはこのようになっています。" @@ -1315,9 +1303,32 @@ _initialTutorial: method: "添付ファイルをセンシティブにする際は、そのファイルをクリックしてメニューを開き、「センシティブとして設定」をクリックします。" sensitiveSucceeded: "ファイルを添付する際は、サーバーのガイドラインに従ってセンシティブを適切に設定してください。" doItToContinue: "画像をセンシティブに設定すると先に進めるようになります。" + _pushNotification: + description: "プッシュ通知を有効にすると{name}の通知をお使いのデバイスで受け取ることができます。" + _privacySettings: + title: "プライバシー設定" + description1: "多くのユーザーが利用しているプライバシー関連の設定項目をリストアップしました。必要に応じて変更してください。" + theseSettingsCanEditLater: "これらの設定は後から変更できます。" + youCanEditMoreSettingsInSettingsPageLater: "この他にも様々な設定を「設定」ページから行えます。ぜひ後で確認してみてください。" _done: title: "チュートリアルは終了です🎉" description: "ここで紹介した機能はほんの一部にすぎません。Misskeyの使い方をより詳しく知るには、{link}をご覧ください。" + haveFun: "{name}をお楽しみください!" + youCanReferTutorialBy: "このチュートリアルは、「もっと!」→「情報」→「チュートリアルを見る」からいつでも見返すことができます。" + _onboardingLanding: + accountCreated: "アカウントの作成が完了しました!" + welcomeToX: "ようこそ、{name}へ!" + description: "「{name}に登録したは良いものの、どう使えばいいか分からない…💦」といったことを防ぐために、まずはMisskeyの基本的な使い方を学びましょう。" + takesAbout: "このチュートリアルの所要時間は{min}分程度です。\nチュートリアルを完了すると実績が解除されます。" + _onboardingDone: + description: "お疲れ様でした!次のステップに進んで、{name}をもっと楽しめるようにしましょう。" + backToOriginalPath: "元のページに戻る" + backToOriginalPathDescription: "あなたがアクセスしようとしていたページに戻ります。" + profile: "プロフィール設定" + profileDescription: "他のユーザーが親しみやすいように、プロフィールをつくりましょう。" + exploreDescription: "人気のノートやユーザーを見つけて交流をはじめましょう。" + goToTimeline: "ホーム画面に進む" + goToTimelineDescription: "設定等を行わず、通常のホーム画面(タイムライン)に進みます。" _timelineDescription: home: "ホームタイムラインでは、あなたがフォローしているアカウントの投稿を見られます。" diff --git a/packages/frontend/.storybook/generate.tsx b/packages/frontend/.storybook/generate.tsx index 76c5b6be4..0f9c8da62 100644 --- a/packages/frontend/.storybook/generate.tsx +++ b/packages/frontend/.storybook/generate.tsx @@ -406,8 +406,6 @@ function toStories(component: string): Promise { glob('src/components/MkDigitalClock.vue'), glob('src/components/MkGalleryPostPreview.vue'), glob('src/components/MkSignupServerRules.vue'), - glob('src/components/MkUserSetupDialog.vue'), - glob('src/components/MkUserSetupDialog.*.vue'), glob('src/components/MkInviteCode.vue'), glob('src/pages/user/home.vue'), ]); diff --git a/packages/frontend/package.json b/packages/frontend/package.json index 91a391ac0..04d4c6e80 100644 --- a/packages/frontend/package.json +++ b/packages/frontend/package.json @@ -97,6 +97,7 @@ "@storybook/vue3": "8.0.0-beta.2", "@storybook/vue3-vite": "8.0.0-beta.2", "@testing-library/vue": "8.0.2", + "@types/canvas-confetti": "^1.6.4", "@types/escape-regexp": "0.0.3", "@types/estree": "1.0.5", "@types/matter-js": "0.19.6", diff --git a/packages/frontend/src/_boot_.ts b/packages/frontend/src/_boot_.ts index 875353f8a..a532c9b8a 100644 --- a/packages/frontend/src/_boot_.ts +++ b/packages/frontend/src/_boot_.ts @@ -10,7 +10,7 @@ import '@/style.scss'; import { mainBoot } from '@/boot/main-boot.js'; import { subBoot } from '@/boot/sub-boot.js'; -const subBootPaths = ['/share', '/auth', '/miauth', '/signup-complete']; +const subBootPaths = ['/share', '/auth', '/miauth', '/signup-complete', '/onboarding']; if (subBootPaths.some(i => location.pathname === i || location.pathname.startsWith(i + '/'))) { subBoot(); diff --git a/packages/frontend/src/boot/common.ts b/packages/frontend/src/boot/common.ts index 681beaf00..ae4278ea2 100644 --- a/packages/frontend/src/boot/common.ts +++ b/packages/frontend/src/boot/common.ts @@ -21,6 +21,7 @@ import { getUrlWithoutLoginId } from '@/scripts/login-id.js'; import { getAccountFromId } from '@/scripts/get-account-from-id.js'; import { deckStore } from '@/ui/deck/deck-store.js'; import { miLocalStorage } from '@/local-storage.js'; +import { claimedAchievements } from '@/scripts/achievements.js'; import { fetchCustomEmojis } from '@/custom-emojis.js'; import { setupRouter } from '@/router/definition.js'; @@ -118,6 +119,14 @@ export async function common(createVue: () => App) { await defaultStore.ready; await deckStore.ready; + // 2024年3月1日JST以降に作成されたアカウントで、チュートリアル完了していない場合、チュートリアルにリダイレクト + if ($i && new Date($i.createdAt).getTime() >= 1709218800000 && !claimedAchievements.includes('tutorialCompleted') && !location.pathname.startsWith('/onboarding') && !location.pathname.startsWith('/signup-complete')) { + const param = new URLSearchParams(); + param.set('redirected_from', location.pathname + location.search + location.hash); + location.replace('/onboarding?' + param.toString()); + return; + } + const fetchInstanceMetaPromise = fetchInstance(); fetchInstanceMetaPromise.then(() => { diff --git a/packages/frontend/src/boot/main-boot.ts b/packages/frontend/src/boot/main-boot.ts index 61f04678b..d2d415b3a 100644 --- a/packages/frontend/src/boot/main-boot.ts +++ b/packages/frontend/src/boot/main-boot.ts @@ -102,12 +102,6 @@ export async function mainBoot() { // only add post shortcuts if logged in hotkeys['p|n'] = post; - defaultStore.loaded.then(() => { - if (defaultStore.state.accountSetupWizard !== -1) { - popup(defineAsyncComponent(() => import('@/components/MkUserSetupDialog.vue')), {}, {}, 'closed'); - } - }); - for (const announcement of ($i.unreadAnnouncements ?? []).filter(x => x.display === 'dialog')) { popup(defineAsyncComponent(() => import('@/components/MkAnnouncementDialog.vue')), { announcement, diff --git a/packages/frontend/src/components/MkUserSetupDialog.User.vue b/packages/frontend/src/components/MkTutorial.FollowUsers.UserCard.vue similarity index 100% rename from packages/frontend/src/components/MkUserSetupDialog.User.vue rename to packages/frontend/src/components/MkTutorial.FollowUsers.UserCard.vue diff --git a/packages/frontend/src/components/MkUserSetupDialog.Follow.vue b/packages/frontend/src/components/MkTutorial.FollowUsers.vue similarity index 82% rename from packages/frontend/src/components/MkUserSetupDialog.Follow.vue rename to packages/frontend/src/components/MkTutorial.FollowUsers.vue index 1524ea0ec..df2a8150e 100644 --- a/packages/frontend/src/components/MkUserSetupDialog.Follow.vue +++ b/packages/frontend/src/components/MkTutorial.FollowUsers.vue @@ -5,7 +5,8 @@ SPDX-License-Identifier: AGPL-3.0-only