This commit is contained in:
mattyatea 2024-02-05 01:28:12 +09:00
parent fd54c299a5
commit 2ab6bb52c2
6 changed files with 122 additions and 67 deletions

16
locales/index.d.ts vendored
View File

@ -108,6 +108,22 @@ export interface Locale extends ILocale {
* *
*/ */
"showGlobalTimeline": string; "showGlobalTimeline": string;
/**
*
*/
"showHomeTimeline": string;
/**
*
*/
"showLocalTimeline": string;
/**
*
*/
"showSocialTimeline": string;
/**
* TLの名前を表示する
*/
"topBarNameShown": string;
/** /**
* {user} * {user}
*/ */

View File

@ -23,6 +23,10 @@ myLists: "自分の作成したリスト"
noThankYou: "やめておく" noThankYou: "やめておく"
enterUsername: "ユーザー名を入力" enterUsername: "ユーザー名を入力"
showGlobalTimeline: "グローバルタイムラインを表示する" showGlobalTimeline: "グローバルタイムラインを表示する"
showHomeTimeline: "ホームタイムラインを表示する"
showLocalTimeline: "ローカルタイムラインを表示する"
showSocialTimeline: "ソーシャルタイムラインを表示する"
topBarNameShown: "上のバーのTLの名前を表示する"
renotedBy: "{user}がリノート" renotedBy: "{user}がリノート"
noNotes: "ノートはありません" noNotes: "ノートはありません"
noNotifications: "通知はありません" noNotifications: "通知はありません"

View File

@ -5,7 +5,7 @@
import ms from 'ms'; import ms from 'ms';
import { Inject, Injectable } from '@nestjs/common'; import { Inject, Injectable } from '@nestjs/common';
import type { UsersRepository, NotesRepository , DriveFilesRepository, MiDriveFile} from '@/models/_.js'; import type { UsersRepository, NotesRepository, DriveFilesRepository, MiDriveFile } from '@/models/_.js';
import { Endpoint } from '@/server/api/endpoint-base.js'; import { Endpoint } from '@/server/api/endpoint-base.js';
import { NoteDeleteService } from '@/core/NoteDeleteService.js'; import { NoteDeleteService } from '@/core/NoteDeleteService.js';
import { DI } from '@/di-symbols.js'; import { DI } from '@/di-symbols.js';
@ -14,7 +14,6 @@ import { GlobalEventService } from '@/core/GlobalEventService.js';
import { MAX_NOTE_TEXT_LENGTH } from '@/const.js'; import { MAX_NOTE_TEXT_LENGTH } from '@/const.js';
import { ApiError } from '../../error.js'; import { ApiError } from '../../error.js';
export const meta = { export const meta = {
tags: ['notes'], tags: ['notes'],
@ -35,11 +34,11 @@ export const meta = {
code: 'NO_SUCH_NOTE', code: 'NO_SUCH_NOTE',
id: 'a6584e14-6e01-4ad3-b566-851e7bf0d474', id: 'a6584e14-6e01-4ad3-b566-851e7bf0d474',
}, },
noSuchFile: { noSuchFile: {
message: 'Some files are not found.', message: 'Some files are not found.',
code: 'NO_SUCH_FILE', code: 'NO_SUCH_FILE',
id: 'b6992544-63e7-67f0-fa7f-32444b1b5306', id: 'b6992544-63e7-67f0-fa7f-32444b1b5306',
}, },
}, },
} as const; } as const;
@ -49,8 +48,8 @@ export const paramDef = {
noteId: { type: 'string', format: 'misskey:id' }, noteId: { type: 'string', format: 'misskey:id' },
visibility: { type: 'string', enum: ['public', 'home', 'followers', 'specified'], default: 'public' }, visibility: { type: 'string', enum: ['public', 'home', 'followers', 'specified'], default: 'public' },
visibleUserIds: { type: 'array', uniqueItems: true, items: { visibleUserIds: { type: 'array', uniqueItems: true, items: {
type: 'string', format: 'misskey:id', type: 'string', format: 'misskey:id',
} }, } },
cw: { type: 'string', nullable: true, maxLength: 100 }, cw: { type: 'string', nullable: true, maxLength: 100 },
localOnly: { type: 'boolean', default: false }, localOnly: { type: 'boolean', default: false },
reactionAcceptance: { type: 'string', nullable: true, enum: [null, 'likeOnly', 'likeOnlyForRemote', 'nonSensitiveOnly', 'nonSensitiveOnlyForLocalLikeOnlyForRemote'], default: null }, reactionAcceptance: { type: 'string', nullable: true, enum: [null, 'likeOnly', 'likeOnlyForRemote', 'nonSensitiveOnly', 'nonSensitiveOnlyForLocalLikeOnlyForRemote'], default: null },
@ -132,34 +131,43 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
throw err; throw err;
}); });
let files: MiDriveFile[] = []; let files: MiDriveFile[] = [];
const fileIds = ps.fileIds ?? null; const fileIds = ps.fileIds ?? null;
if (fileIds != null) { if (fileIds != null) {
files = await this.driveFilesRepository.createQueryBuilder('file') files = await this.driveFilesRepository.createQueryBuilder('file')
.where('file.userId = :userId AND file.id IN (:...fileIds)', { .where('file.userId = :userId AND file.id IN (:...fileIds)', {
userId: me.id, userId: me.id,
fileIds, fileIds,
}) })
.orderBy('array_position(ARRAY[:...fileIds], "id"::text)') .orderBy('array_position(ARRAY[:...fileIds], "id"::text)')
.setParameters({ fileIds }) .setParameters({ fileIds })
.getMany(); .getMany();
if (files.length !== fileIds.length) { if (files.length !== fileIds.length) {
throw new ApiError(meta.errors.noSuchFile); throw new ApiError(meta.errors.noSuchFile);
} }
} }
if (note.userId !== me.id) { if (note.userId !== me.id) {
throw new ApiError(meta.errors.noSuchNote); throw new ApiError(meta.errors.noSuchNote);
} }
await this.notesRepository.update({ id: note.id }, { await this.notesRepository.update({ id: note.id }, {
updatedAt: new Date(), updatedAt: new Date(),
cw: ps.cw, cw: ps.cw,
text: ps.text, text: ps.text,
fileIds: files.length > 0 ? files.map(f => f.id) : undefined, fileIds: files.length > 0 ? files.map(f => f.id) : undefined,
poll: ps.poll ? {
choices: ps.poll.choices,
multiple: ps.poll.multiple ?? false,
expiresAt: ps.poll.expiresAt ? new Date(ps.poll.expiresAt) : null,
} : undefined,
localOnly: ps.localOnly,
reactionAcceptance: ps.reactionAcceptance,
apMentions: ps.noExtractMentions ? [] : undefined,
apHashtags: ps.noExtractHashtags ? [] : undefined,
apEmojis: ps.noExtractEmojis ? [] : undefined,
}); });
this.globalEventService.publishNoteStream(note.id, 'updated', { this.globalEventService.publishNoteStream(note.id, 'updated', {

View File

@ -38,16 +38,19 @@ SPDX-License-Identifier: AGPL-3.0-only
<MkSwitch v-model="showFixedPostFormInChannel">{{ i18n.ts.showFixedPostFormInChannel }}</MkSwitch> <MkSwitch v-model="showFixedPostFormInChannel">{{ i18n.ts.showFixedPostFormInChannel }}</MkSwitch>
<MkFolder> <MkFolder>
<template #label>{{ i18n.ts.pinnedList }}</template> <template #label>{{ i18n.ts.pinnedList }}</template>
<div class="_margin" v-for="pinnedLists in defaultStore.reactiveState.pinnedUserLists.value"> <div v-for="pinnedLists in defaultStore.reactiveState.pinnedUserLists.value" class="_margin">
{{ pinnedLists.name }} {{ pinnedLists.name }}
<MkButton danger @click="removePinnedList(pinnedLists.id,pinnedLists.name)"><i class="ti ti-trash"></i> {{ i18n.ts.remove }}</MkButton> <MkButton danger @click="removePinnedList(pinnedLists.id,pinnedLists.name)"><i class="ti ti-trash"></i> {{ i18n.ts.remove }}</MkButton>
</div> </div>
<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>
<MkSwitch v-model="showMediaTimeline">{{ i18n.ts.showMediaTimeline }}<template #caption>{{ i18n.ts.showMediaTimelineInfo }} </template></MkSwitch> <MkSwitch v-model="showMediaTimeline">{{ i18n.ts.showMediaTimeline }}<template #caption>{{ i18n.ts.showMediaTimelineInfo }} </template></MkSwitch>
<MkSwitch v-model="showGlobalTimeline">{{ i18n.ts.showGlobalTimeline }}</MkSwitch> <MkSwitch v-model="showGlobalTimeline">{{ i18n.ts.showGlobalTimeline }}</MkSwitch>
<MkSwitch v-model="showHomeTimeline">{{ i18n.ts.showHomeTimeline }}</MkSwitch>
<MkSwitch v-model="showSocialTimeline">{{ i18n.ts.showSocialTimeline }}</MkSwitch>
<MkSwitch v-model="showLocalTimeline">{{ i18n.ts.showLocalTimeline }}</MkSwitch>
<MkSwitch v-model="topBarNameShown">{{ i18n.ts.topBarNameShown }}</MkSwitch>
</div> </div>
</FormSection> </FormSection>
<MkFoldableSection :expanded="false" class="item"> <MkFoldableSection :expanded="false" class="item">
@ -350,7 +353,7 @@ import MkInfo from '@/components/MkInfo.vue';
import { langs } from '@/config.js'; import { langs } from '@/config.js';
import { defaultStore } from '@/store.js'; import { defaultStore } from '@/store.js';
import * as os from '@/os.js'; import * as os from '@/os.js';
import {signinRequired} from '@/account.js'; import { signinRequired } from '@/account.js';
import { unisonReload } from '@/scripts/unison-reload.js'; import { unisonReload } from '@/scripts/unison-reload.js';
import { i18n } from '@/i18n.js'; import { i18n } from '@/i18n.js';
import { definePageMetadata } from '@/scripts/page-metadata.js'; import { definePageMetadata } from '@/scripts/page-metadata.js';
@ -422,6 +425,10 @@ const enableonlyAndWithSave = computed(defaultStore.makeGetterSetter('onlyAndWit
const enablehanntenn = computed(defaultStore.makeGetterSetter('enablehanntenn')); const enablehanntenn = computed(defaultStore.makeGetterSetter('enablehanntenn'));
const showMediaTimeline = computed(defaultStore.makeGetterSetter('showMediaTimeline')); const showMediaTimeline = computed(defaultStore.makeGetterSetter('showMediaTimeline'));
const showGlobalTimeline = computed(defaultStore.makeGetterSetter('showGlobalTimeline')); const showGlobalTimeline = computed(defaultStore.makeGetterSetter('showGlobalTimeline'));
const showLocalTimeline = computed(defaultStore.makeGetterSetter('showLocalTimeline'));
const showHomeTimeline = computed(defaultStore.makeGetterSetter('showHomeTimeline'));
const showSocialTimeline = computed(defaultStore.makeGetterSetter('showSocialTimeline'));
const topBarNameShown = computed(defaultStore.makeGetterSetter('topBarNameShown'));
const showVisibilityColor = computed(defaultStore.makeGetterSetter('showVisibilityColor')); const showVisibilityColor = computed(defaultStore.makeGetterSetter('showVisibilityColor'));
const disableStreamingTimeline = computed(defaultStore.makeGetterSetter('disableStreamingTimeline')); const disableStreamingTimeline = computed(defaultStore.makeGetterSetter('disableStreamingTimeline'));
const useGroupedNotifications = computed(defaultStore.makeGetterSetter('useGroupedNotifications')); const useGroupedNotifications = computed(defaultStore.makeGetterSetter('useGroupedNotifications'));
@ -449,8 +456,8 @@ const remoteLocalTimelineEnable3 = computed(defaultStore.makeGetterSetter('remot
const remoteLocalTimelineEnable4 = computed(defaultStore.makeGetterSetter('remoteLocalTimelineEnable4')); const remoteLocalTimelineEnable4 = computed(defaultStore.makeGetterSetter('remoteLocalTimelineEnable4'));
const remoteLocalTimelineEnable5 = computed(defaultStore.makeGetterSetter('remoteLocalTimelineEnable5')); const remoteLocalTimelineEnable5 = computed(defaultStore.makeGetterSetter('remoteLocalTimelineEnable5'));
const $i = signinRequired(); const $i = signinRequired();
const pinnedMax = $i.policies?.listPinnedLimit; const pinnedMax = $i.policies.listPinnedLimit;
const maxLocalTimeline = $i.policies?.localTimelineAnyLimit; const maxLocalTimeline = $i.policies.localTimelineAnyLimit;
watch(lang, () => { watch(lang, () => {
miLocalStorage.setItem('lang', lang.value as string); miLocalStorage.setItem('lang', lang.value as string);
miLocalStorage.removeItem('locale'); miLocalStorage.removeItem('locale');
@ -518,6 +525,10 @@ watch([
showVisibilityColor, showVisibilityColor,
enableonlyAndWithSave, enableonlyAndWithSave,
showGlobalTimeline, showGlobalTimeline,
showSocialTimeline,
showLocalTimeline,
showHomeTimeline,
topBarNameShown,
disableStreamingTimeline, disableStreamingTimeline,
enableSeasonalScreenEffect, enableSeasonalScreenEffect,
], async () => { ], async () => {
@ -611,26 +622,24 @@ async function setPinnedList() {
} }
} }
async function removePinnedList(id,name) { async function removePinnedList(id, name) {
if (!id) return;
const { canceled } = await os.confirm({
type: 'warning',
text: i18n.tsx.removeAreYouSure({ x: name ?? id }),
});
if (canceled) return;
if (!id) return; if (id === 'all') {
const {canceled} = await os.confirm({ if (canceled) return;
type: 'warning',
text: i18n.tsx.removeAreYouSure({x: name ?? id }),
});
if (canceled) return;
if (id === 'all') { defaultStore.set('pinnedUserLists', []);
return;
}
if (canceled) return; const pinnedLists = defaultStore.state.pinnedUserLists;
const newPinnedLists = pinnedLists.filter(pinnedList => pinnedList.id !== id);
defaultStore.set('pinnedUserLists', []); defaultStore.set('pinnedUserLists', newPinnedLists);
return;
}
const pinnedLists = defaultStore.state.pinnedUserLists;
const newPinnedLists = pinnedLists.filter(pinnedList => pinnedList.id !== id);
defaultStore.set('pinnedUserLists', newPinnedLists);
} }
let smashCount = 0; let smashCount = 0;

View File

@ -55,7 +55,7 @@ import { miLocalStorage } from '@/local-storage.js';
provide('shouldOmitHeaderTitle', true); provide('shouldOmitHeaderTitle', true);
const isLocalTimelineAvailable = ($i == null && instance.policies.ltlAvailable) || ($i != null && $i.policies.ltlAvailable); const isLocalTimelineAvailable = ($i == null && instance.policies.ltlAvailable && defaultStore.state.showLocalTimeline) || ($i != null && $i.policies.ltlAvailable && defaultStore.state.showLocalTimeline);
const isGlobalTimelineAvailable = ($i == null && instance.policies.gtlAvailable && defaultStore.state.showGlobalTimeline) || ($i != null && $i.policies.gtlAvailable && defaultStore.state.showGlobalTimeline); const isGlobalTimelineAvailable = ($i == null && instance.policies.gtlAvailable && defaultStore.state.showGlobalTimeline) || ($i != null && $i.policies.gtlAvailable && defaultStore.state.showGlobalTimeline);
const keymap = { const keymap = {
't': focus, 't': focus,
@ -110,6 +110,8 @@ const remoteLocalTimelineEnable2 = ref(defaultStore.state.remoteLocalTimelineEna
const remoteLocalTimelineEnable3 = ref(defaultStore.state.remoteLocalTimelineEnable3); const remoteLocalTimelineEnable3 = ref(defaultStore.state.remoteLocalTimelineEnable3);
const remoteLocalTimelineEnable4 = ref(defaultStore.state.remoteLocalTimelineEnable4); const remoteLocalTimelineEnable4 = ref(defaultStore.state.remoteLocalTimelineEnable4);
const remoteLocalTimelineEnable5 = ref(defaultStore.state.remoteLocalTimelineEnable5); const remoteLocalTimelineEnable5 = ref(defaultStore.state.remoteLocalTimelineEnable5);
const showHomeTimeline = ref(defaultStore.state.showHomeTimeline);
const showSocialTimeline = ref(defaultStore.state.showSocialTimeline);
watch(src, () => { watch(src, () => {
queue.value = 0; queue.value = 0;
}); });
@ -282,57 +284,57 @@ const headerTabs = computed(() => [...(defaultStore.reactiveState.pinnedUserList
key: 'list:' + l.id, key: 'list:' + l.id,
title: l.name, title: l.name,
icon: 'ti ti-star', icon: 'ti ti-star',
iconOnly: false, iconOnly: defaultStore.state.topBarNameShown ?? false,
}))), { }))), ...(showHomeTimeline.value ? [{
key: 'home', key: 'home',
title: i18n.ts._timelines.home, title: i18n.ts._timelines.home,
icon: 'ti ti-home', icon: 'ti ti-home',
iconOnly: false, iconOnly: defaultStore.state.topBarNameShown ?? false,
}, ...(isLocalTimelineAvailable ? [{ }] : []), ...(isLocalTimelineAvailable ? [{
key: 'local', key: 'local',
title: i18n.ts._timelines.local, title: i18n.ts._timelines.local,
icon: 'ti ti-planet', icon: 'ti ti-planet',
iconOnly: false, iconOnly: defaultStore.state.topBarNameShown ?? false,
}, ...(isShowMediaTimeline.value ? [{ }] : []), ...(isShowMediaTimeline.value ? [{
key: 'media', key: 'media',
title: i18n.ts._timelines.media, title: i18n.ts._timelines.media,
icon: 'ti ti-photo', icon: 'ti ti-photo',
iconOnly: false, iconOnly: defaultStore.state.topBarNameShown ?? false,
}] : []), { }] : []), ...(showSocialTimeline.value ? [{
key: 'social', key: 'social',
title: i18n.ts._timelines.social, title: i18n.ts._timelines.social,
icon: 'ti ti-universe', icon: 'ti ti-universe',
iconOnly: false, iconOnly: defaultStore.state.topBarNameShown ?? false,
}] : []), ...(remoteLocalTimelineEnable1.value ? [{ }] : []), ...(remoteLocalTimelineEnable1.value ? [{
key: 'custom-timeline-1', key: 'custom-timeline-1',
title: defaultStore.state.remoteLocalTimelineName1, title: defaultStore.state.remoteLocalTimelineName1,
icon: 'ti ti-plus', icon: 'ti ti-plus',
iconOnly: false, iconOnly: defaultStore.state.topBarNameShown ?? false,
}] : []), ...(remoteLocalTimelineEnable2.value ? [{ }] : []), ...(remoteLocalTimelineEnable2.value ? [{
key: 'custom-timeline-2', key: 'custom-timeline-2',
title: defaultStore.state.remoteLocalTimelineName2, title: defaultStore.state.remoteLocalTimelineName2,
icon: 'ti ti-plus', icon: 'ti ti-plus',
iconOnly: false, iconOnly: defaultStore.state.topBarNameShown ?? false,
}] : []), ...(remoteLocalTimelineEnable3.value ? [{ }] : []), ...(remoteLocalTimelineEnable3.value ? [{
key: 'custom-timeline-3', key: 'custom-timeline-3',
title: defaultStore.state.remoteLocalTimelineName3, title: defaultStore.state.remoteLocalTimelineName3,
icon: 'ti ti-plus', icon: 'ti ti-plus',
iconOnly: false, iconOnly: defaultStore.state.topBarNameShown ?? false,
}] : []), ...(remoteLocalTimelineEnable4.value ? [{ }] : []), ...(remoteLocalTimelineEnable4.value ? [{
key: 'custom-timeline-4', key: 'custom-timeline-4',
title: defaultStore.state.remoteLocalTimelineName4, title: defaultStore.state.remoteLocalTimelineName4,
icon: 'ti ti-plus', icon: 'ti ti-plus',
iconOnly: false, iconOnly: defaultStore.state.topBarNameShown ?? false,
}] : []), ...(remoteLocalTimelineEnable5.value ? [{ }] : []), ...(remoteLocalTimelineEnable5.value ? [{
key: 'custom-timeline-5', key: 'custom-timeline-5',
title: defaultStore.state.remoteLocalTimelineName5, title: defaultStore.state.remoteLocalTimelineName5,
icon: 'ti ti-plus', icon: 'ti ti-plus',
iconOnly: false, iconOnly: defaultStore.state.topBarNameShown ?? false,
}] : []), ...(isGlobalTimelineAvailable ? [{ }] : []), ...(isGlobalTimelineAvailable ? [{
key: 'global', key: 'global',
title: i18n.ts._timelines.global, title: i18n.ts._timelines.global,
icon: 'ti ti-whirl', icon: 'ti ti-whirl',
iconOnly: false, iconOnly: defaultStore.state.topBarNameShown ?? false,
}] : []), { }] : []), {
icon: 'ti ti-list', icon: 'ti ti-list',
title: i18n.ts.lists, title: i18n.ts.lists,

View File

@ -364,6 +364,22 @@ export const defaultStore = markRaw(new Storage('base', {
where: 'device', where: 'device',
default: false, default: false,
}, },
topBarNameShown: {
where: 'device',
default: false,
},
showHomeTimeline: {
where: 'device',
default: true,
},
showLocalTimeline: {
where: 'device',
default: true,
},
showSocialTimeline: {
where: 'device',
default: true,
},
showGapBetweenNotesInTimeline: { showGapBetweenNotesInTimeline: {
where: 'device', where: 'device',
default: false, default: false,
@ -676,10 +692,10 @@ export const defaultStore = markRaw(new Storage('base', {
sfxVolume: 1, sfxVolume: 1,
}, },
}, },
hemisphere: { hemisphere: {
where: 'device', where: 'device',
default: hemisphere as 'N' | 'S', default: hemisphere as 'N' | 'S',
}, },
enableHorizontalSwipe: { enableHorizontalSwipe: {
where: 'device', where: 'device',
default: true, default: true,