Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions locales/ja-JP.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3552,3 +3552,12 @@ _qr:
scanFile: "端末の画像をスキャン"
raw: "テキスト"
mfm: "MFM"

_tlOnboarding:
titleWelcome: "{name} へようこそ!"
titleNormal: "ホームタイムラインにノートはありません"
description: "ホームタイムラインには、あなたがフォローしているアカウントのノートが表示されます。まずは気になるユーザーをフォローしてみましょう!"
descriptionZeroFollowing: "ホームタイムラインには、あなたがフォローしているアカウントのノートが表示されます。あなたはまだ誰もフォローしていないので、ここにノートは表示されません。まずは気になるユーザーをフォローしてみましょう!"
ltlTitle: "ローカルタイムライン"
ltlDescription: "このサーバーにいるユーザー全員の投稿が見られる公開タイムラインを見てみましょう。"
exploreDescription: "人気のノートやユーザーを見つけて交流をはじめましょう。"
16 changes: 15 additions & 1 deletion packages/frontend/src/components/form/link.vue
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ SPDX-License-Identifier: AGPL-3.0-only
>
<component
:is="to ? (external ? 'a' : 'MkA') : 'div'"
:class="[$style.main, { [$style.active]: active }]"
:class="[$style.main, { [$style.large]: large, [$style.active]: active }]"
class="_button"
v-bind="to ? (external ? { href: to, target: '_blank' } : { to, behavior }) : {}"
>
Expand All @@ -25,6 +25,9 @@ SPDX-License-Identifier: AGPL-3.0-only
<div>
<MkCondensedLine :minScale="2 / 3"><slot></slot></MkCondensedLine>
</div>
<div v-if="$slots.caption" :class="$style.headerTextSub">
<MkCondensedLine :minScale="2 / 3"><slot name="caption"></slot></MkCondensedLine>
</div>
</div>
<span :class="$style.suffix">
<span :class="$style.suffixText"><slot name="suffix"></slot></span>
Expand All @@ -41,6 +44,7 @@ defineProps<{
external?: boolean;
behavior?: null | 'window' | 'browser';
inline?: boolean;
large?: boolean;
}>();
</script>

Expand All @@ -65,6 +69,11 @@ defineProps<{
border-radius: 6px;
font-size: 0.9em;

&.large {
font-size: 1em;
padding: 9px 12px;
}

&:hover {
text-decoration: none;
background: var(--MI_THEME-folderHeaderHoverBg);
Expand Down Expand Up @@ -99,6 +108,11 @@ defineProps<{
padding-right: 12px;
}

.headerTextSub {
color: color(from var(--MI_THEME-fg) srgb r g b / 0.75);
font-size: .85em;
}

.suffix {
margin-left: auto;
opacity: 0.7;
Expand Down
56 changes: 54 additions & 2 deletions packages/frontend/src/pages/timeline.vue
Original file line number Diff line number Diff line change
Expand Up @@ -21,19 +21,42 @@ SPDX-License-Identifier: AGPL-3.0-only
:withSensitive="withSensitive"
:onlyFiles="onlyFiles"
:sound="true"
/>
>
<template #empty>
<div v-if="$i != null && src === 'home'" class="_panel _gaps" :class="$style.tlOnboardingRoot">
<div :class="$style.tlOnboardingTitle">
<i class="ti ti-info-circle"></i> {{ isNewlyCreatedAccount ? i18n.tsx._tlOnboarding.titleWelcome({ name: instanceName }) : i18n.ts._tlOnboarding.titleNormal}}
</div>
<div :class="$style.tlOnboardingDescription">{{ $i.followingCount === 0 ? i18n.ts._tlOnboarding.descriptionZeroFollowing : i18n.ts._tlOnboarding.description }}</div>
<div class="_gaps_s">
<FormLink to="/explore" large>
<template #icon><i class="ti ti-hash"></i></template>
{{ i18n.ts.explore }}
<template #caption>{{ i18n.ts._tlOnboarding.exploreDescription }}</template>
</FormLink>
<FormLink v-if="isAvailableBasicTimeline('local')" large @click="switchToLocal">
<template #icon><i :class="basicTimelineIconClass('local')"></i></template>
{{ i18n.ts._tlOnboarding.ltlTitle }}
<template #caption>{{ i18n.ts._tlOnboarding.ltlDescription }}</template>
</FormLink>
</div>
</div>
</template>
</MkStreamingNotesTimeline>
</div>
</PageWithHeader>
</template>

<script lang="ts" setup>
import { computed, watch, provide, useTemplateRef, ref, onMounted, onActivated } from 'vue';
import { computed, watch, useTemplateRef, ref, onMounted, onActivated } from 'vue';
import { instanceName } from '@@/js/config.js';
import type { Tab } from '@/components/global/MkPageHeader.tabs.vue';
import type { MenuItem } from '@/types/menu.js';
import type { BasicTimelineType } from '@/timelines.js';
import type { PageHeaderItem } from '@/types/page-header.js';
import MkStreamingNotesTimeline from '@/components/MkStreamingNotesTimeline.vue';
import MkPostForm from '@/components/MkPostForm.vue';
import FormLink from '@/components/form/link.vue';
import * as os from '@/os.js';
import { store } from '@/store.js';
import { i18n } from '@/i18n.js';
Expand Down Expand Up @@ -106,6 +129,20 @@ const withSensitive = computed<boolean>({

const showFixedPostForm = prefer.model('showFixedPostForm');

//#region TLチュートリアル
const isNewlyCreatedAccount = computed(() => {
if (!$i) return false;
const createdAt = Date.parse($i.createdAt);
const now = Date.now();
return (now - createdAt) < (7 * 24 * 60 * 60 * 1000); // 7日以内
});

function switchToLocal() {
if (!isAvailableBasicTimeline('local')) return;
src.value = 'local';
}
//#endregion

async function chooseList(ev: PointerEvent): Promise<void> {
const lists = await userListsCache.fetch();
const items: (MenuItem | undefined)[] = [
Expand Down Expand Up @@ -333,4 +370,19 @@ definePage(() => ({
border-radius: var(--MI-radius);
overflow: clip;
}

.tlOnboardingRoot {
border-radius: var(--MI-radius);
overflow: clip;
padding: var(--MI-margin);
border: 2px solid var(--MI_THEME-accent);
}

.tlOnboardingTitle {
font-weight: bold;
}

.tlOnboardingDescription {
font-size: 90%;
}
</style>
30 changes: 30 additions & 0 deletions packages/i18n/src/autogen/locale.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13258,4 +13258,34 @@ export interface Locale extends ILocale {
*/
"mfm": string;
};
"_tlOnboarding": {
/**
* {name} へようこそ!
*/
"titleWelcome": ParameterizedString<"name">;
/**
* ホームタイムラインにノートはありません
*/
"titleNormal": string;
/**
* ホームタイムラインには、あなたがフォローしているアカウントのノートが表示されます。まずは気になるユーザーをフォローしてみましょう!
*/
"description": string;
/**
* ホームタイムラインには、あなたがフォローしているアカウントのノートが表示されます。あなたはまだ誰もフォローしていないので、ここにノートは表示されません。まずは気になるユーザーをフォローしてみましょう!
*/
"descriptionZeroFollowing": string;
/**
* ローカルタイムライン
*/
"ltlTitle": string;
/**
* このサーバーにいるユーザー全員の投稿が見られる公開タイムラインを見てみましょう。
*/
"ltlDescription": string;
/**
* 人気のノートやユーザーを見つけて交流をはじめましょう。
*/
"exploreDescription": string;
};
}
Loading