Compare commits
12 Commits
b53da62196
...
81873d8561
Author | SHA1 | Date |
---|---|---|
taichan | 81873d8561 | |
かっこかり | 3bf63dd9c5 | |
かっこかり | ce95323e49 | |
taichanne30 | 48232ca57b | |
taichanne30 | 3564bf5c66 | |
taichanne30 | 685fc2bd9d | |
taichanne30 | 6cc0138d1e | |
taichan | d3228d5570 | |
taichanne30 | 4a8ffe20a7 | |
taichanne30 | 5615675991 | |
taichan | 0c65b8058a | |
taichanne30 | 82bec76cd4 |
|
@ -14,6 +14,7 @@
|
|||
- Fix: 月の違う同じ日はセパレータが表示されないのを修正
|
||||
- Fix: 縦横比が極端なカスタム絵文字を表示する際にレイアウトが崩れる箇所があるのを修正
|
||||
(Cherry-picked from https://github.com/MisskeyIO/misskey/pull/725)
|
||||
- Fix: 設定変更時のリロード確認ダイアログが複数個表示されることがある問題を修正
|
||||
|
||||
### Server
|
||||
- Fix: アンテナの書き込み時にキーワードが与えられなかった場合のエラーをApiErrorとして投げるように
|
||||
|
@ -302,7 +303,7 @@
|
|||
- Fix: カスタム絵文字の画像読み込みに失敗した際はテキストではなくダミー画像を表示 #13487
|
||||
|
||||
### Server
|
||||
-
|
||||
- Fix: FTT有効かつDBフォールバック有効時、STLのようにタイムラインのソースが複数だとFTTとDBのフォールバック間で取得されないノートがある問題
|
||||
|
||||
## 2024.3.0
|
||||
|
||||
|
|
|
@ -3121,7 +3121,7 @@ export interface Locale extends ILocale {
|
|||
*/
|
||||
"narrow": string;
|
||||
/**
|
||||
* 設定はページリロード後に反映されます。今すぐリロードしますか?
|
||||
* 設定はページリロード後に反映されます。
|
||||
*/
|
||||
"reloadToApplySetting": string;
|
||||
/**
|
||||
|
|
|
@ -778,7 +778,7 @@ left: "左"
|
|||
center: "中央"
|
||||
wide: "広い"
|
||||
narrow: "狭い"
|
||||
reloadToApplySetting: "設定はページリロード後に反映されます。今すぐリロードしますか?"
|
||||
reloadToApplySetting: "設定はページリロード後に反映されます。"
|
||||
needReloadToApply: "反映には再起動が必要です。"
|
||||
showTitlebar: "タイトルバーを表示する"
|
||||
clearCache: "キャッシュをクリア"
|
||||
|
|
|
@ -123,11 +123,14 @@ export class AntennaService implements OnApplicationShutdown {
|
|||
if (antenna.src === 'home') {
|
||||
// TODO
|
||||
} else if (antenna.src === 'list') {
|
||||
const listUsers = (await this.userListMembershipsRepository.findBy({
|
||||
userListId: antenna.userListId!,
|
||||
})).map(x => x.userId);
|
||||
|
||||
if (!listUsers.includes(note.userId)) return false;
|
||||
if (antenna.userListId == null) return false;
|
||||
const exists = await this.userListMembershipsRepository.exists({
|
||||
where: {
|
||||
userListId: antenna.userListId,
|
||||
userId: note.userId,
|
||||
},
|
||||
});
|
||||
if (!exists) return false;
|
||||
} else if (antenna.src === 'users') {
|
||||
const accts = antenna.users.map(x => {
|
||||
const { username, host } = Acct.parse(x);
|
||||
|
|
|
@ -34,6 +34,7 @@ type TimelineOptions = {
|
|||
excludeReplies?: boolean;
|
||||
excludePureRenotes: boolean;
|
||||
dbFallback: (untilId: string | null, sinceId: string | null, limit: number) => Promise<MiNote[]>,
|
||||
preventEmptyTimelineDbFallback?: boolean;
|
||||
};
|
||||
|
||||
@Injectable()
|
||||
|
@ -63,12 +64,20 @@ export class FanoutTimelineEndpointService {
|
|||
|
||||
const redisResult = await this.fanoutTimelineService.getMulti(ps.redisTimelines, ps.untilId, ps.sinceId);
|
||||
|
||||
// TODO: いい感じにgetMulti内でソート済だからuniqするときにredisResultが全てソート済なのを利用して再ソートを避けたい
|
||||
const redisResultIds = Array.from(new Set(redisResult.flat(1))).sort(idCompare);
|
||||
// オプション無効時、取得したredisResultのうち、2つ以上ソースがあり、1つでも空であればDBにフォールバックする
|
||||
let shouldFallbackToDb = ps.useDbFallback &&
|
||||
(ps.preventEmptyTimelineDbFallback !== true && redisResult.length > 1 && redisResult.some(ids => ids.length === 0));
|
||||
|
||||
// 取得したresultの中で最古のIDのうち、最も新しいものを取得
|
||||
const fttThresholdId = redisResult.map(ids => ids[0]).sort()[0];
|
||||
|
||||
// TODO: いい感じにgetMulti内でソート済だからuniqするときにredisResultが全てソート済なのを利用して再ソートを避けたい
|
||||
const redisResultIds = shouldFallbackToDb ? [] : Array.from(new Set(redisResult.flat(1))).sort(idCompare);
|
||||
|
||||
let noteIds = redisResultIds.filter(id => id >= fttThresholdId).slice(0, ps.limit);
|
||||
|
||||
let noteIds = redisResultIds.slice(0, ps.limit);
|
||||
const oldestNoteId = ascending ? redisResultIds[0] : redisResultIds[redisResultIds.length - 1];
|
||||
const shouldFallbackToDb = noteIds.length === 0 || ps.sinceId != null && ps.sinceId < oldestNoteId;
|
||||
shouldFallbackToDb ||= ps.useDbFallback && (noteIds.length === 0 || ps.sinceId != null && ps.sinceId < oldestNoteId);
|
||||
|
||||
if (!shouldFallbackToDb) {
|
||||
let filter = ps.noteFilter ?? (_note => true);
|
||||
|
|
|
@ -143,6 +143,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
|
|||
withFiles: ps.withFiles,
|
||||
withRenotes: ps.withRenotes,
|
||||
}, me),
|
||||
preventEmptyTimelineDbFallback: true,
|
||||
});
|
||||
|
||||
return timeline;
|
||||
|
|
|
@ -258,7 +258,7 @@ import { langs } from '@@/js/config.js';
|
|||
import { defaultStore } from '@/store.js';
|
||||
import * as os from '@/os.js';
|
||||
import { misskeyApi } from '@/scripts/misskey-api.js';
|
||||
import { unisonReload } from '@/scripts/unison-reload.js';
|
||||
import { reloadAsk } from '@/scripts/reload-ask.js';
|
||||
import { i18n } from '@/i18n.js';
|
||||
import { definePageMetadata } from '@/scripts/page-metadata.js';
|
||||
import { miLocalStorage } from '@/local-storage.js';
|
||||
|
@ -270,16 +270,6 @@ const fontSize = ref(miLocalStorage.getItem('fontSize'));
|
|||
const useSystemFont = ref(miLocalStorage.getItem('useSystemFont') != null);
|
||||
const dataSaver = ref(defaultStore.state.dataSaver);
|
||||
|
||||
async function reloadAsk() {
|
||||
const { canceled } = await os.confirm({
|
||||
type: 'info',
|
||||
text: i18n.ts.reloadToApplySetting,
|
||||
});
|
||||
if (canceled) return;
|
||||
|
||||
unisonReload();
|
||||
}
|
||||
|
||||
const hemisphere = computed(defaultStore.makeGetterSetter('hemisphere'));
|
||||
const overridedDeviceKind = computed(defaultStore.makeGetterSetter('overridedDeviceKind'));
|
||||
const serverDisconnectedBehavior = computed(defaultStore.makeGetterSetter('serverDisconnectedBehavior'));
|
||||
|
@ -369,7 +359,7 @@ watch([
|
|||
confirmWhenRevealingSensitiveMedia,
|
||||
contextMenu,
|
||||
], async () => {
|
||||
await reloadAsk();
|
||||
await reloadAsk({ reason: i18n.ts.reloadToApplySetting, unison: true });
|
||||
});
|
||||
|
||||
const emojiIndexLangs = ['en-US', 'ja-JP', 'ja-JP_hira'] as const;
|
||||
|
|
|
@ -54,7 +54,7 @@ import MkContainer from '@/components/MkContainer.vue';
|
|||
import * as os from '@/os.js';
|
||||
import { navbarItemDef } from '@/navbar.js';
|
||||
import { defaultStore } from '@/store.js';
|
||||
import { unisonReload } from '@/scripts/unison-reload.js';
|
||||
import { reloadAsk } from '@/scripts/reload-ask.js';
|
||||
import { i18n } from '@/i18n.js';
|
||||
import { definePageMetadata } from '@/scripts/page-metadata.js';
|
||||
|
||||
|
@ -67,16 +67,6 @@ const items = ref(defaultStore.state.menu.map(x => ({
|
|||
|
||||
const menuDisplay = computed(defaultStore.makeGetterSetter('menuDisplay'));
|
||||
|
||||
async function reloadAsk() {
|
||||
const { canceled } = await os.confirm({
|
||||
type: 'info',
|
||||
text: i18n.ts.reloadToApplySetting,
|
||||
});
|
||||
if (canceled) return;
|
||||
|
||||
unisonReload();
|
||||
}
|
||||
|
||||
async function addItem() {
|
||||
const menu = Object.keys(navbarItemDef).filter(k => !defaultStore.state.menu.includes(k));
|
||||
const { canceled, result: item } = await os.select({
|
||||
|
@ -100,7 +90,7 @@ function removeItem(index: number) {
|
|||
|
||||
async function save() {
|
||||
defaultStore.set('menu', items.value.map(x => x.type));
|
||||
await reloadAsk();
|
||||
await reloadAsk({ reason: i18n.ts.reloadToApplySetting, unison: true });
|
||||
}
|
||||
|
||||
function reset() {
|
||||
|
@ -111,7 +101,7 @@ function reset() {
|
|||
}
|
||||
|
||||
watch(menuDisplay, async () => {
|
||||
await reloadAsk();
|
||||
await reloadAsk({ reason: i18n.ts.reloadToApplySetting, unison: true });
|
||||
});
|
||||
|
||||
const headerActions = computed(() => []);
|
||||
|
|
|
@ -98,7 +98,7 @@ import { defaultStore } from '@/store.js';
|
|||
import { signout, signinRequired } from '@/account.js';
|
||||
import { i18n } from '@/i18n.js';
|
||||
import { definePageMetadata } from '@/scripts/page-metadata.js';
|
||||
import { unisonReload } from '@/scripts/unison-reload.js';
|
||||
import { reloadAsk } from '@/scripts/reload-ask.js';
|
||||
import FormSection from '@/components/form/section.vue';
|
||||
|
||||
const $i = signinRequired();
|
||||
|
@ -132,16 +132,6 @@ async function deleteAccount() {
|
|||
await signout();
|
||||
}
|
||||
|
||||
async function reloadAsk() {
|
||||
const { canceled } = await os.confirm({
|
||||
type: 'info',
|
||||
text: i18n.ts.reloadToApplySetting,
|
||||
});
|
||||
if (canceled) return;
|
||||
|
||||
unisonReload();
|
||||
}
|
||||
|
||||
async function updateRepliesAll(withReplies: boolean) {
|
||||
const { canceled } = await os.confirm({
|
||||
type: 'warning',
|
||||
|
@ -155,7 +145,7 @@ async function updateRepliesAll(withReplies: boolean) {
|
|||
watch([
|
||||
enableCondensedLineForAcct,
|
||||
], async () => {
|
||||
await reloadAsk();
|
||||
await reloadAsk({ reason: i18n.ts.reloadToApplySetting, unison: true });
|
||||
});
|
||||
|
||||
const headerActions = computed(() => []);
|
||||
|
|
|
@ -88,19 +88,9 @@ import { uniqueBy } from '@/scripts/array.js';
|
|||
import { fetchThemes, getThemes } from '@/theme-store.js';
|
||||
import { definePageMetadata } from '@/scripts/page-metadata.js';
|
||||
import { miLocalStorage } from '@/local-storage.js';
|
||||
import { unisonReload } from '@/scripts/unison-reload.js';
|
||||
import { reloadAsk } from '@/scripts/reload-ask.js';
|
||||
import * as os from '@/os.js';
|
||||
|
||||
async function reloadAsk() {
|
||||
const { canceled } = await os.confirm({
|
||||
type: 'info',
|
||||
text: i18n.ts.reloadToApplySetting,
|
||||
});
|
||||
if (canceled) return;
|
||||
|
||||
unisonReload();
|
||||
}
|
||||
|
||||
const installedThemes = ref(getThemes());
|
||||
const builtinThemes = getBuiltinThemesRef();
|
||||
|
||||
|
@ -148,13 +138,13 @@ watch(syncDeviceDarkMode, () => {
|
|||
}
|
||||
});
|
||||
|
||||
watch(wallpaper, () => {
|
||||
watch(wallpaper, async () => {
|
||||
if (wallpaper.value == null) {
|
||||
miLocalStorage.removeItem('wallpaper');
|
||||
} else {
|
||||
miLocalStorage.setItem('wallpaper', wallpaper.value);
|
||||
}
|
||||
reloadAsk();
|
||||
await reloadAsk({ reason: i18n.ts.reloadToApplySetting, unison: true });
|
||||
});
|
||||
|
||||
onActivated(() => {
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: syuilo and misskey-project
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import { i18n } from '@/i18n.js';
|
||||
import * as os from '@/os.js';
|
||||
import { unisonReload } from '@/scripts/unison-reload.js';
|
||||
|
||||
let isReloadConfirming = false;
|
||||
|
||||
export async function reloadAsk(opts: {
|
||||
unison?: boolean;
|
||||
reason?: string;
|
||||
}) {
|
||||
if (isReloadConfirming) {
|
||||
return;
|
||||
}
|
||||
|
||||
isReloadConfirming = true;
|
||||
|
||||
const { canceled } = await os.confirm(opts.reason == null ? {
|
||||
type: 'info',
|
||||
text: i18n.ts.reloadConfirm,
|
||||
} : {
|
||||
type: 'info',
|
||||
title: i18n.ts.reloadConfirm,
|
||||
text: opts.reason,
|
||||
}).finally(() => {
|
||||
isReloadConfirming = false;
|
||||
});
|
||||
|
||||
if (canceled) return;
|
||||
|
||||
if (opts.unison) {
|
||||
unisonReload();
|
||||
} else {
|
||||
location.reload();
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue