This commit is contained in:
parent
0cf3082902
commit
399f7c451b
|
@ -84,6 +84,10 @@ export interface Locale extends ILocale {
|
||||||
* ルビ
|
* ルビ
|
||||||
*/
|
*/
|
||||||
"ruby": string;
|
"ruby": string;
|
||||||
|
/**
|
||||||
|
* ピン留めされたチャンネル
|
||||||
|
*/
|
||||||
|
"pinnedChannel": string;
|
||||||
/**
|
/**
|
||||||
* わかった
|
* わかった
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -17,6 +17,7 @@ notificationIndicator: "通知のインジケーターの数字を表示する"
|
||||||
hanntenn: "アイコンとバナーを反転させる"
|
hanntenn: "アイコンとバナーを反転させる"
|
||||||
hanntennInfo: "ダークだったらライトのアイコンに、ライトだったらダークのアイコンに。"
|
hanntennInfo: "ダークだったらライトのアイコンに、ライトだったらダークのアイコンに。"
|
||||||
ruby: "ルビ"
|
ruby: "ルビ"
|
||||||
|
pinnedChannel: "ピン留めされたチャンネル"
|
||||||
gotIt: "わかった"
|
gotIt: "わかった"
|
||||||
cancel: "キャンセル"
|
cancel: "キャンセル"
|
||||||
myLists: "自分の作成したリスト"
|
myLists: "自分の作成したリスト"
|
||||||
|
|
|
@ -12,3 +12,5 @@ export const rolesCache = new Cache(1000 * 60 * 30, () => misskeyApi('admin/role
|
||||||
export const userListsCache = new Cache<Misskey.entities.UserList[]>(1000 * 60 * 30, () => misskeyApi('users/lists/list'));
|
export const userListsCache = new Cache<Misskey.entities.UserList[]>(1000 * 60 * 30, () => misskeyApi('users/lists/list'));
|
||||||
export const antennasCache = new Cache<Misskey.entities.Antenna[]>(1000 * 60 * 30, () => misskeyApi('antennas/list'));
|
export const antennasCache = new Cache<Misskey.entities.Antenna[]>(1000 * 60 * 30, () => misskeyApi('antennas/list'));
|
||||||
export const userFavoriteListsCache = new Cache(1000 * 60 * 30, () => misskeyApi('users/lists/list-favorite'));
|
export const userFavoriteListsCache = new Cache(1000 * 60 * 30, () => misskeyApi('users/lists/list-favorite'));
|
||||||
|
export const userChannelsCache = new Cache<Misskey.entities.UserChannel[]>(1000 * 60 * 30, () => misskeyApi('channels/owned'));
|
||||||
|
export const userChannelFollowingsCache = new Cache<Misskey.entities.UserChannelFollowing[]>(1000 * 60 * 30, () => misskeyApi('channels/followed'));
|
||||||
|
|
|
@ -125,7 +125,7 @@ import {
|
||||||
iconDark,
|
iconDark,
|
||||||
iconLight,
|
iconLight,
|
||||||
notePostInterruptors,
|
notePostInterruptors,
|
||||||
postFormActions
|
postFormActions,
|
||||||
} from '@/store.js';
|
} from '@/store.js';
|
||||||
import MkInfo from '@/components/MkInfo.vue';
|
import MkInfo from '@/components/MkInfo.vue';
|
||||||
import { i18n } from '@/i18n.js';
|
import { i18n } from '@/i18n.js';
|
||||||
|
@ -146,7 +146,6 @@ const $i = signinRequired();
|
||||||
const modal = inject('modal');
|
const modal = inject('modal');
|
||||||
let gamingType = computed(defaultStore.makeGetterSetter('gamingType'));
|
let gamingType = computed(defaultStore.makeGetterSetter('gamingType'));
|
||||||
|
|
||||||
|
|
||||||
const props = withDefaults(defineProps<{
|
const props = withDefaults(defineProps<{
|
||||||
reply?: Misskey.entities.Note;
|
reply?: Misskey.entities.Note;
|
||||||
renote?: Misskey.entities.Note;
|
renote?: Misskey.entities.Note;
|
||||||
|
@ -286,7 +285,6 @@ watch(text, () => {
|
||||||
}, { immediate: true });
|
}, { immediate: true });
|
||||||
|
|
||||||
watch(visibility, () => {
|
watch(visibility, () => {
|
||||||
|
|
||||||
switch (visibility.value) {
|
switch (visibility.value) {
|
||||||
case 'public':
|
case 'public':
|
||||||
localOnly.value = props.initialLocalOnly ?? defaultStore.state.rememberNoteVisibility ? defaultStore.state.localOnly : defaultStore.state.defaultNoteLocalOnly;
|
localOnly.value = props.initialLocalOnly ?? defaultStore.state.rememberNoteVisibility ? defaultStore.state.localOnly : defaultStore.state.defaultNoteLocalOnly;
|
||||||
|
@ -402,11 +400,11 @@ function checkMissingMention() {
|
||||||
for (const x of extractMentions(ast)) {
|
for (const x of extractMentions(ast)) {
|
||||||
if (!visibleUsers.value.some(u => (u.username === x.username) && (u.host === x.host))) {
|
if (!visibleUsers.value.some(u => (u.username === x.username) && (u.host === x.host))) {
|
||||||
hasNotSpecifiedMentions.value = true;
|
hasNotSpecifiedMentions.value = true;
|
||||||
return;}
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
hasNotSpecifiedMentions.value = false;
|
hasNotSpecifiedMentions.value = false;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function addMissingMention() {
|
function addMissingMention() {
|
||||||
|
@ -420,9 +418,11 @@ function addMissingMention() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function insertRuby() {
|
function insertRuby() {
|
||||||
insertTextAtCursor(textareaEl.value, '$[ruby 本文 上につくやつ]');
|
insertTextAtCursor(textareaEl.value, '$[ruby 本文 上につくやつ]');
|
||||||
}
|
}
|
||||||
|
|
||||||
function togglePoll() {
|
function togglePoll() {
|
||||||
if (poll.value) {
|
if (poll.value) {
|
||||||
poll.value = null;
|
poll.value = null;
|
||||||
|
@ -739,7 +739,8 @@ async function post(ev?: MouseEvent) {
|
||||||
const x = rect.left + (el.offsetWidth / 2);
|
const x = rect.left + (el.offsetWidth / 2);
|
||||||
const y = rect.top + (el.offsetHeight / 2);
|
const y = rect.top + (el.offsetHeight / 2);
|
||||||
os.popup(MkRippleEffect, { x, y }, {}, 'end');
|
os.popup(MkRippleEffect, { x, y }, {}, 'end');
|
||||||
}}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (props.mock) return; const annoying =
|
if (props.mock) return; const annoying =
|
||||||
text.value.includes('$[x2') ||
|
text.value.includes('$[x2') ||
|
||||||
|
@ -819,7 +820,7 @@ async function post(ev?: MouseEvent) {
|
||||||
|
|
||||||
if (postAccount.value) {
|
if (postAccount.value) {
|
||||||
const storedAccounts = await getAccounts();
|
const storedAccounts = await getAccounts();
|
||||||
token = storedAccounts.find(x => x.id === postAccount?.value?.id)?.token;
|
token = storedAccounts.find(x => x.id === postAccount.value?.id)?.token;
|
||||||
}
|
}
|
||||||
|
|
||||||
posting.value = true;
|
posting.value = true;
|
||||||
|
@ -968,7 +969,7 @@ function openAccountMenu(ev: MouseEvent) {
|
||||||
|
|
||||||
function openOtherSettingsMenu(ev: MouseEvent) {
|
function openOtherSettingsMenu(ev: MouseEvent) {
|
||||||
let reactionAcceptanceIcon: string;
|
let reactionAcceptanceIcon: string;
|
||||||
switch (reactionAcceptance) {
|
switch (reactionAcceptance.value) {
|
||||||
case 'likeOnly':
|
case 'likeOnly':
|
||||||
reactionAcceptanceIcon = 'ti ti-heart';
|
reactionAcceptanceIcon = 'ti ti-heart';
|
||||||
break;
|
break;
|
||||||
|
@ -985,13 +986,13 @@ function openOtherSettingsMenu(ev: MouseEvent) {
|
||||||
text: i18n.ts.reactionAcceptance,
|
text: i18n.ts.reactionAcceptance,
|
||||||
icon: reactionAcceptanceIcon,
|
icon: reactionAcceptanceIcon,
|
||||||
action: toggleReactionAcceptance,
|
action: toggleReactionAcceptance,
|
||||||
}, ($i.policies?.canScheduleNote) ? {
|
}, ($i.policies.canScheduleNote) ? {
|
||||||
type: 'button',
|
type: 'button',
|
||||||
text: i18n.ts.schedulePost,
|
text: i18n.ts.schedulePost,
|
||||||
icon: 'ti ti-calendar-time',
|
icon: 'ti ti-calendar-time',
|
||||||
indicate: (schedule != null),
|
indicate: (schedule.value != null),
|
||||||
action: toggleSchedule,
|
action: toggleSchedule,
|
||||||
} : undefined, ...(($i.policies?.canScheduleNote) ? [{ type: 'divider' }, {
|
} : undefined, ...(($i.policies.canScheduleNote) ? [{ type: 'divider' }, {
|
||||||
type: 'button',
|
type: 'button',
|
||||||
text: i18n.ts._schedulePost.list,
|
text: i18n.ts._schedulePost.list,
|
||||||
icon: 'ti ti-calendar-event',
|
icon: 'ti ti-calendar-event',
|
||||||
|
|
|
@ -38,6 +38,7 @@ const props = withDefaults(defineProps<{
|
||||||
withRenotes?: boolean;
|
withRenotes?: boolean;
|
||||||
withReplies?: boolean;
|
withReplies?: boolean;
|
||||||
onlyFiles?: boolean;
|
onlyFiles?: boolean;
|
||||||
|
|
||||||
}>(), {
|
}>(), {
|
||||||
withRenotes: true,
|
withRenotes: true,
|
||||||
withReplies: false,
|
withReplies: false,
|
||||||
|
|
|
@ -177,7 +177,6 @@ onUnmounted(() => {
|
||||||
margin-left: 0;
|
margin-left: 0;
|
||||||
}
|
}
|
||||||
> .titleContainer {
|
> .titleContainer {
|
||||||
margin: 0 auto;
|
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,7 +38,6 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
<!-- スマホ・タブレットの場合、キーボードが表示されると投稿が見づらくなるので、デスクトップ場合のみ自動でフォーカスを当てる -->
|
<!-- スマホ・タブレットの場合、キーボードが表示されると投稿が見づらくなるので、デスクトップ場合のみ自動でフォーカスを当てる -->
|
||||||
<MkPostForm v-if="$i && defaultStore.reactiveState.showFixedPostFormInChannel.value" :channel="channel" class="post-form _panel" fixed :autofocus="deviceKind === 'desktop'"/>
|
<MkPostForm v-if="$i && defaultStore.reactiveState.showFixedPostFormInChannel.value" :channel="channel" class="post-form _panel" fixed :autofocus="deviceKind === 'desktop'"/>
|
||||||
|
|
||||||
<MkTimeline :key="channelId" src="channel" :channel="channelId" @before="before" @after="after" @note="miLocalStorage.setItemAsJson(`channelLastReadedAt:${channel.id}`, Date.now())"/>
|
<MkTimeline :key="channelId" src="channel" :channel="channelId" @before="before" @after="after" @note="miLocalStorage.setItemAsJson(`channelLastReadedAt:${channel.id}`, Date.now())"/>
|
||||||
</div>
|
</div>
|
||||||
<div v-else-if="tab === 'featured'" key="featured">
|
<div v-else-if="tab === 'featured'" key="featured">
|
||||||
|
|
|
@ -23,7 +23,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { computed, ref } from 'vue';
|
import { computed, onMounted, ref } from 'vue';
|
||||||
import XNotifications from '@/components/MkNotifications.vue';
|
import XNotifications from '@/components/MkNotifications.vue';
|
||||||
import MkNotes from '@/components/MkNotes.vue';
|
import MkNotes from '@/components/MkNotes.vue';
|
||||||
import MkHorizontalSwipe from '@/components/MkHorizontalSwipe.vue';
|
import MkHorizontalSwipe from '@/components/MkHorizontalSwipe.vue';
|
||||||
|
@ -74,7 +74,7 @@ const headerActions = computed(() => [{
|
||||||
highlighted: includeTypes.value != null,
|
highlighted: includeTypes.value != null,
|
||||||
handler: setFilter,
|
handler: setFilter,
|
||||||
}].filter(x => x !== undefined));
|
}].filter(x => x !== undefined));
|
||||||
misskeyApi('notifications/mark-all-as-read');
|
|
||||||
const headerTabs = computed(() => [{
|
const headerTabs = computed(() => [{
|
||||||
key: 'all',
|
key: 'all',
|
||||||
title: i18n.ts.all,
|
title: i18n.ts.all,
|
||||||
|
@ -93,6 +93,9 @@ definePageMetadata(computed(() => ({
|
||||||
title: i18n.ts.notifications,
|
title: i18n.ts.notifications,
|
||||||
icon: 'ti ti-bell',
|
icon: 'ti ti-bell',
|
||||||
})));
|
})));
|
||||||
|
onMounted(() => {
|
||||||
|
misskeyApi('notifications/mark-all-as-read');
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style module lang="scss">
|
<style module lang="scss">
|
||||||
|
|
|
@ -45,10 +45,18 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
<MkButton v-if="pinnedMax > defaultStore.reactiveState.pinnedUserLists.value.length " @click="setPinnedList()">{{ i18n.ts.add }}</MkButton>
|
<MkButton v-if="pinnedMax > defaultStore.reactiveState.pinnedUserLists.value.length " @click="setPinnedList()">{{ i18n.ts.add }}</MkButton>
|
||||||
<MkButton v-if="defaultStore.reactiveState.pinnedUserLists.value.length " danger @click="removePinnedList('all')"><i class="ti ti-trash"></i> {{ i18n.ts.all }}{{ i18n.ts.remove }}</MkButton>
|
<MkButton v-if="defaultStore.reactiveState.pinnedUserLists.value.length " danger @click="removePinnedList('all')"><i class="ti ti-trash"></i> {{ i18n.ts.all }}{{ i18n.ts.remove }}</MkButton>
|
||||||
</MkFolder>
|
</MkFolder>
|
||||||
|
<MkFolder>
|
||||||
|
<template #label>{{ i18n.ts.pinnedChannel }}</template>
|
||||||
|
<div v-for="pinnedLists in defaultStore.reactiveState.pinnedChannels.value" class="_margin">
|
||||||
|
{{ pinnedLists.name }}
|
||||||
|
<MkButton danger @click="removePinnedChannel(pinnedLists.id,pinnedLists.name)"><i class="ti ti-trash"></i> {{ i18n.ts.remove }}</MkButton>
|
||||||
|
</div>
|
||||||
|
<MkButton v-if="pinnedMax > defaultStore.reactiveState.pinnedChannels.value.length " @click="setPinnedChannel()">{{ i18n.ts.add }}</MkButton>
|
||||||
|
<MkButton v-if="defaultStore.reactiveState.pinnedChannels.value.length " danger @click="removePinnedChannel('all')"><i class="ti ti-trash"></i> {{ i18n.ts.all }}{{ i18n.ts.remove }}</MkButton>
|
||||||
|
</MkFolder>
|
||||||
<MkFoldableSection :expanded="false" class="item">
|
<MkFoldableSection :expanded="false" class="item">
|
||||||
<template #header>{{ i18n.ts.topbarCustom }}</template>
|
<template #header>{{ i18n.ts.topbarCustom }}</template>
|
||||||
|
|
||||||
|
|
||||||
{{ i18n.ts._timelines.home }}
|
{{ i18n.ts._timelines.home }}
|
||||||
<MkSwitch v-model="showHomeTimeline">{{ i18n.ts.enable }}</MkSwitch>
|
<MkSwitch v-model="showHomeTimeline">{{ i18n.ts.enable }}</MkSwitch>
|
||||||
<br>
|
<br>
|
||||||
|
@ -379,7 +387,7 @@ import { claimAchievement } from '@/scripts/achievements.js';
|
||||||
import MkColorInput from '@/components/MkColorInput.vue';
|
import MkColorInput from '@/components/MkColorInput.vue';
|
||||||
import MkFoldableSection from '@/components/MkFoldableSection.vue';
|
import MkFoldableSection from '@/components/MkFoldableSection.vue';
|
||||||
import MkInput from '@/components/MkInput.vue';
|
import MkInput from '@/components/MkInput.vue';
|
||||||
import { userFavoriteListsCache, userListsCache } from '@/cache.js';
|
import { userChannelFollowingsCache, userChannelsCache, userFavoriteListsCache, userListsCache } from '@/cache.js';
|
||||||
|
|
||||||
const lang = ref(miLocalStorage.getItem('lang'));
|
const lang = ref(miLocalStorage.getItem('lang'));
|
||||||
const fontSize = ref(miLocalStorage.getItem('fontSize'));
|
const fontSize = ref(miLocalStorage.getItem('fontSize'));
|
||||||
|
@ -638,7 +646,7 @@ async function setPinnedList() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function removePinnedList(id, name) {
|
async function removePinnedList(id, name?:string) {
|
||||||
if (!id) return;
|
if (!id) return;
|
||||||
const { canceled } = await os.confirm({
|
const { canceled } = await os.confirm({
|
||||||
type: 'warning',
|
type: 'warning',
|
||||||
|
@ -658,6 +666,46 @@ async function removePinnedList(id, name) {
|
||||||
defaultStore.set('pinnedUserLists', newPinnedLists);
|
defaultStore.set('pinnedUserLists', newPinnedLists);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function setPinnedChannel() {
|
||||||
|
const myChannels = await userChannelsCache.fetch();
|
||||||
|
const favoriteChannels = await userChannelFollowingsCache.fetch();
|
||||||
|
let channels = [...new Set([...myChannels, ...favoriteChannels])];
|
||||||
|
const { canceled, result: channel } = await os.select({
|
||||||
|
title: i18n.ts.selectList,
|
||||||
|
items: channels.map(x => ({
|
||||||
|
value: x, text: x.name,
|
||||||
|
})),
|
||||||
|
});
|
||||||
|
if (canceled) return;
|
||||||
|
let pinnedChannels = defaultStore.state.pinnedChannels;
|
||||||
|
|
||||||
|
// Check if the id is already present in pinnedLists
|
||||||
|
if (!pinnedChannels.some(pinnedChannel => pinnedChannel.id === channel.id)) {
|
||||||
|
pinnedChannels.push(channel);
|
||||||
|
defaultStore.set('pinnedChannels', pinnedChannels);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function removePinnedChannel(id, name?:string) {
|
||||||
|
if (!id) return;
|
||||||
|
const { canceled } = await os.confirm({
|
||||||
|
type: 'warning',
|
||||||
|
text: i18n.tsx.removeAreYouSure({ x: name ?? id }),
|
||||||
|
});
|
||||||
|
if (canceled) return;
|
||||||
|
|
||||||
|
if (id === 'all') {
|
||||||
|
if (canceled) return;
|
||||||
|
|
||||||
|
defaultStore.set('pinnedChannels', []);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const pinnedChannels = defaultStore.state.pinnedChannels;
|
||||||
|
const newPinnedChannels = pinnedChannels.filter(pinnedchannel => pinnedchannel.id !== id);
|
||||||
|
defaultStore.set('pinnedChannels', newPinnedChannels);
|
||||||
|
}
|
||||||
|
|
||||||
let smashCount = 0;
|
let smashCount = 0;
|
||||||
let smashTimer: number | null = null;
|
let smashTimer: number | null = null;
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
<MkInfo v-if="['home', 'local', 'social', 'global'].includes(src) && !defaultStore.reactiveState.timelineTutorials.value[src]" style="margin-bottom: var(--margin);" closable @close="closeTutorial()">
|
<MkInfo v-if="['home', 'local', 'social', 'global'].includes(src) && !defaultStore.reactiveState.timelineTutorials.value[src]" style="margin-bottom: var(--margin);" closable @close="closeTutorial()">
|
||||||
{{ i18n.ts._timelineDescription[src] }}
|
{{ i18n.ts._timelineDescription[src] }}
|
||||||
</MkInfo>
|
</MkInfo>
|
||||||
<MkPostForm v-if="defaultStore.reactiveState.showFixedPostForm.value" :class="$style.postForm" class="post-form _panel" fixed style="margin-bottom: var(--margin);"/>
|
<MkPostForm v-if="$i && defaultStore.reactiveState.showFixedPostForm.value" :channel="channelInfo" :autofocus="deviceKind === 'desktop'" :class="$style.postForm" class="post-form _panel" fixed style="margin-bottom: var(--margin);"/>
|
||||||
<div v-if="queue > 0" :class="$style.new"><button class="_buttonPrimary" :class="$style.newButton" @click="top()">{{ i18n.ts.newNoteRecived }}</button></div>
|
<div v-if="queue > 0" :class="$style.new"><button class="_buttonPrimary" :class="$style.newButton" @click="top()">{{ i18n.ts.newNoteRecived }}</button></div>
|
||||||
<div :class="$style.tl">
|
<div :class="$style.tl">
|
||||||
<MkTimeline
|
<MkTimeline
|
||||||
|
@ -20,6 +20,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
:key="src + withRenotes + withReplies + onlyFiles"
|
:key="src + withRenotes + withReplies + onlyFiles"
|
||||||
:src="src.split(':')[0]"
|
:src="src.split(':')[0]"
|
||||||
:list="src.split(':')[1]"
|
:list="src.split(':')[1]"
|
||||||
|
:channel="src.split(':')[1]"
|
||||||
:withRenotes="withRenotes"
|
:withRenotes="withRenotes"
|
||||||
:withReplies="withReplies"
|
:withReplies="withReplies"
|
||||||
:onlyFiles="onlyFiles"
|
:onlyFiles="onlyFiles"
|
||||||
|
@ -112,8 +113,19 @@ const remoteLocalTimelineEnable4 = ref(defaultStore.state.remoteLocalTimelineEna
|
||||||
const remoteLocalTimelineEnable5 = ref(defaultStore.state.remoteLocalTimelineEnable5);
|
const remoteLocalTimelineEnable5 = ref(defaultStore.state.remoteLocalTimelineEnable5);
|
||||||
const showHomeTimeline = ref(defaultStore.state.showHomeTimeline);
|
const showHomeTimeline = ref(defaultStore.state.showHomeTimeline);
|
||||||
const showSocialTimeline = ref(defaultStore.state.showSocialTimeline);
|
const showSocialTimeline = ref(defaultStore.state.showSocialTimeline);
|
||||||
watch(src, () => {
|
const channelInfo = ref();
|
||||||
|
if (src.value.split(':')[0] === 'channel') {
|
||||||
|
const channelId = src.value.split(':')[1];
|
||||||
|
channelInfo.value = misskeyApi('channels/show', { channelId });
|
||||||
|
}
|
||||||
|
watch(src, async () => {
|
||||||
queue.value = 0;
|
queue.value = 0;
|
||||||
|
if (src.value.split(':')[0] === 'channel') {
|
||||||
|
const channelId = src.value.split(':')[1];
|
||||||
|
channelInfo.value = misskeyApi('channels/show', { channelId });
|
||||||
|
} else {
|
||||||
|
channelInfo.value = null;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
function queueUpdated(q: number): void {
|
function queueUpdated(q: number): void {
|
||||||
|
@ -285,6 +297,11 @@ const headerTabs = computed(() => [...(defaultStore.reactiveState.pinnedUserList
|
||||||
title: l.name,
|
title: l.name,
|
||||||
icon: 'ti ti-star',
|
icon: 'ti ti-star',
|
||||||
iconOnly: defaultStore.state.topBarNameShown ?? false,
|
iconOnly: defaultStore.state.topBarNameShown ?? false,
|
||||||
|
}))), ...(defaultStore.reactiveState.pinnedChannels.value.map(l => ({
|
||||||
|
key: 'channel:' + l.id,
|
||||||
|
title: l.name,
|
||||||
|
icon: 'ti ti-star',
|
||||||
|
iconOnly: defaultStore.state.topBarNameShown ?? false,
|
||||||
}))), ...(showHomeTimeline.value ? [{
|
}))), ...(showHomeTimeline.value ? [{
|
||||||
key: 'home',
|
key: 'home',
|
||||||
title: i18n.ts._timelines.home,
|
title: i18n.ts._timelines.home,
|
||||||
|
|
|
@ -280,7 +280,10 @@ export const defaultStore = markRaw(new Storage('base', {
|
||||||
where: 'deviceAccount',
|
where: 'deviceAccount',
|
||||||
default: [] as Misskey.entities.UserList[],
|
default: [] as Misskey.entities.UserList[],
|
||||||
},
|
},
|
||||||
|
pinnedChannels: {
|
||||||
|
where: 'deviceAccount',
|
||||||
|
default: [] as Misskey.entities.Channel[],
|
||||||
|
},
|
||||||
overridedDeviceKind: {
|
overridedDeviceKind: {
|
||||||
where: 'device',
|
where: 'device',
|
||||||
default: null as null | 'smartphone' | 'tablet' | 'desktop',
|
default: null as null | 'smartphone' | 'tablet' | 'desktop',
|
||||||
|
|
Loading…
Reference in New Issue