-
-
-
+
-import { defineAsyncComponent, inject } from 'vue';
+import { inject } from 'vue';
import * as Misskey from 'misskey-js';
import type { MenuItem } from '@/types/menu';
import { copyToClipboard } from '@/utility/copy-to-clipboard';
import MkDriveFileThumbnail from '@/components/MkDriveFileThumbnail.vue';
+import MkDraggable from '@/components/MkDraggable.vue';
import * as os from '@/os.js';
import { misskeyApi } from '@/utility/misskey-api.js';
import { i18n } from '@/i18n.js';
@@ -45,8 +53,6 @@ import { prefer } from '@/preferences.js';
import { DI } from '@/di.js';
import { globalEvents } from '@/events.js';
-const Sortable = defineAsyncComponent(() => import('vuedraggable').then(x => x.default));
-
const props = defineProps<{
modelValue: Misskey.entities.DriveFile[];
detachMediaFn?: (id: string) => void;
@@ -221,7 +227,6 @@ function showFileMenu(file: Misskey.entities.DriveFile, ev: MouseEvent | Keyboar
position: relative;
width: 64px;
height: 64px;
- margin-right: 4px;
border-radius: 4px;
overflow: hidden;
cursor: move;
diff --git a/packages/frontend/src/components/MkWidgets.vue b/packages/frontend/src/components/MkWidgets.vue
index cf7c2cda80..e7712e8aae 100644
--- a/packages/frontend/src/components/MkWidgets.vue
+++ b/packages/frontend/src/components/MkWidgets.vue
@@ -4,7 +4,7 @@ SPDX-License-Identifier: AGPL-3.0-only
-->
-
+
@@ -13,25 +13,21 @@ SPDX-License-Identifier: AGPL-3.0-only
{{ i18n.ts.add }}
{{ i18n.ts.close }}
- emit('updateWidgets', v)"
>
-
+
-
+
@@ -49,19 +45,18 @@ export type DefaultStoredWidget = {
diff --git a/packages/frontend/src/pages/settings/emoji-palette.palette.vue b/packages/frontend/src/pages/settings/emoji-palette.palette.vue
index b624d424f3..0282f62fb8 100644
--- a/packages/frontend/src/pages/settings/emoji-palette.palette.vue
+++ b/packages/frontend/src/pages/settings/emoji-palette.palette.vue
@@ -18,19 +18,18 @@ SPDX-License-Identifier: AGPL-3.0-only
- emojis = v.map(x => x.emoji)"
>
-
-
-
+
{{ i18n.ts.reactionSettingDescription2 }}
@@ -47,7 +46,6 @@ SPDX-License-Identifier: AGPL-3.0-only
+
diff --git a/packages/frontend/src/components/MkChart.vue b/packages/frontend/src/components/MkChart.vue
index c54081ad42..e418e729ca 100644
--- a/packages/frontend/src/components/MkChart.vue
+++ b/packages/frontend/src/components/MkChart.vue
@@ -94,8 +94,8 @@ const props = withDefaults(defineProps<{
const legendEl = useTemplateRef('legendEl');
-const sum = (...arr) => arr.reduce((r, a) => r.map((b, i) => a[i] + b));
-const negate = arr => arr.map(x => -x);
+const sum = (...arr: number[][]) => arr.reduce((r, a) => r.map((b, i) => a[i] + b));
+const negate = (arr: number[]) => arr.map((x) => -x);
const colors = {
blue: '#008FFB',
@@ -108,7 +108,7 @@ const colors = {
cyan: '#00e0e0',
};
const colorSets = [colors.blue, colors.green, colors.yellow, colors.red, colors.purple];
-const getColor = (i) => {
+const getColor = (i: number) => {
return colorSets[i % colorSets.length];
};
@@ -142,7 +142,7 @@ const getDate = (ago: number) => {
return props.span === 'day' ? new Date(y, m, d - ago) : new Date(y, m, d, h - ago);
};
-const format = (arr) => {
+const format = (arr: number[]) => {
return arr.map((v, i) => ({
x: getDate(i).getTime(),
y: v,
@@ -371,7 +371,7 @@ const fetchApRequestChart = async (): Promise
=> {
};
};
-const fetchNotesChart = async (type: string): Promise => {
+const fetchNotesChart = async (type: 'local' | 'remote' | 'combined'): Promise => {
const raw = await misskeyApiGet('charts/notes', { limit: props.limit, span: props.span });
return {
series: [{
diff --git a/packages/frontend/src/components/MkClickerGame.vue b/packages/frontend/src/components/MkClickerGame.vue
index 775964af50..0c856c57eb 100644
--- a/packages/frontend/src/components/MkClickerGame.vue
+++ b/packages/frontend/src/components/MkClickerGame.vue
@@ -20,9 +20,9 @@ SPDX-License-Identifier: AGPL-3.0-only
diff --git a/packages/frontend/src/components/MkDrive.file.vue b/packages/frontend/src/components/MkDrive.file.vue
index 0eca85b3a6..e2858084c0 100644
--- a/packages/frontend/src/components/MkDrive.file.vue
+++ b/packages/frontend/src/components/MkDrive.file.vue
@@ -64,7 +64,7 @@ const isDragging = ref(false);
const title = computed(() => `${props.file.name}\n${props.file.type} ${bytes(props.file.size)}`);
-function onContextmenu(ev: MouseEvent) {
+function onContextmenu(ev: PointerEvent) {
os.contextMenu(getDriveFileMenu(props.file, props.folder), ev);
}
diff --git a/packages/frontend/src/components/MkDrive.folder.vue b/packages/frontend/src/components/MkDrive.folder.vue
index 8b2609852c..6d93dfc0d4 100644
--- a/packages/frontend/src/components/MkDrive.folder.vue
+++ b/packages/frontend/src/components/MkDrive.folder.vue
@@ -57,7 +57,7 @@ const props = withDefaults(defineProps<{
const emit = defineEmits<{
(ev: 'chosen', v: Misskey.entities.DriveFolder): void;
(ev: 'unchose', v: Misskey.entities.DriveFolder): void;
- (ev: 'upload', files: File[], folder: Misskey.entities.DriveFolder);
+ (ev: 'upload', files: File[], folder: Misskey.entities.DriveFolder): void;
(ev: 'dragstart'): void;
(ev: 'dragend'): void;
}>();
@@ -277,7 +277,7 @@ function setAsUploadFolder() {
prefer.commit('uploadFolder', props.folder.id);
}
-function onContextmenu(ev: MouseEvent) {
+function onContextmenu(ev: PointerEvent) {
let menu: MenuItem[];
menu = [{
text: i18n.ts.openInWindow,
diff --git a/packages/frontend/src/components/MkDrive.vue b/packages/frontend/src/components/MkDrive.vue
index 6e286f4882..2961bc5032 100644
--- a/packages/frontend/src/components/MkDrive.vue
+++ b/packages/frontend/src/components/MkDrive.vue
@@ -139,7 +139,9 @@ SPDX-License-Identifier: AGPL-3.0-only
primary
rounded
@click="fetchMoreFiles"
- >{{ i18n.ts.loadMore }}
+ >
+ {{ i18n.ts.loadMore }}
+
{{ i18n.ts.dropHereToUpload }}
@@ -491,7 +493,7 @@ function deleteFolder(folderToDelete: Misskey.entities.DriveFolder) {
});
}
-function onFileClick(ev: MouseEvent, file: Misskey.entities.DriveFile) {
+function onFileClick(ev: PointerEvent, file: Misskey.entities.DriveFile) {
if (ev.shiftKey) {
isEditMode.value = true;
}
@@ -563,7 +565,7 @@ function cd(target?: Misskey.entities.DriveFolder | Misskey.entities.DriveFolder
folder.value = folderToMove;
hierarchyFolders.value = [];
- const dive = folderToDive => {
+ const dive = (folderToDive: Misskey.entities.DriveFolder) => {
hierarchyFolders.value.unshift(folderToDive);
if (folderToDive.parent) dive(folderToDive.parent);
};
@@ -689,11 +691,11 @@ function getMenu() {
return menu;
}
-function showMenu(ev: MouseEvent) {
+function showMenu(ev: PointerEvent) {
os.popupMenu(getMenu(), (ev.currentTarget ?? ev.target ?? undefined) as HTMLElement | undefined);
}
-function onContextmenu(ev: MouseEvent) {
+function onContextmenu(ev: PointerEvent) {
os.contextMenu(getMenu(), ev);
}
diff --git a/packages/frontend/src/components/MkEmojiPicker.section.vue b/packages/frontend/src/components/MkEmojiPicker.section.vue
index ef515e471f..3ee32710e5 100644
--- a/packages/frontend/src/components/MkEmojiPicker.section.vue
+++ b/packages/frontend/src/components/MkEmojiPicker.section.vue
@@ -62,8 +62,8 @@ SPDX-License-Identifier: AGPL-3.0-only
diff --git a/packages/frontend/src/components/MkEmojiPicker.vue b/packages/frontend/src/components/MkEmojiPicker.vue
index 33e9137c2f..bf0f9d0130 100644
--- a/packages/frontend/src/components/MkEmojiPicker.vue
+++ b/packages/frontend/src/components/MkEmojiPicker.vue
@@ -412,13 +412,13 @@ function getDef(emoji: string): string | Misskey.entities.EmojiSimple | UnicodeE
}
/** @see MkEmojiPicker.section.vue */
-function computeButtonTitle(ev: MouseEvent): void {
+function computeButtonTitle(ev: PointerEvent): void {
const elm = ev.target as HTMLElement;
const emoji = elm.dataset.emoji as string;
elm.title = getEmojiName(emoji);
}
-function chosen(emoji: string | Misskey.entities.EmojiSimple | UnicodeEmojiDef, ev?: MouseEvent) {
+function chosen(emoji: string | Misskey.entities.EmojiSimple | UnicodeEmojiDef, ev?: PointerEvent) {
const el = ev && (ev.currentTarget ?? ev.target) as HTMLElement | null | undefined;
if (el && prefer.s.animation) {
const rect = el.getBoundingClientRect();
diff --git a/packages/frontend/src/components/MkExtensionInstaller.vue b/packages/frontend/src/components/MkExtensionInstaller.vue
index c9d18ee731..9c0cce7689 100644
--- a/packages/frontend/src/components/MkExtensionInstaller.vue
+++ b/packages/frontend/src/components/MkExtensionInstaller.vue
@@ -45,7 +45,7 @@ SPDX-License-Identifier: AGPL-3.0-only
{{ i18n.ts.permission }}
- - {{ i18n.ts._permissions[permission] }}
+ - {{ (i18n.ts._permissions as any)[permission] ?? permission }}
{{ i18n.ts.none }}
diff --git a/packages/frontend/src/components/MkFolder.vue b/packages/frontend/src/components/MkFolder.vue
index 94fdf6da36..864f53d09c 100644
--- a/packages/frontend/src/components/MkFolder.vue
+++ b/packages/frontend/src/components/MkFolder.vue
@@ -169,7 +169,7 @@ function afterLeave(el: Element) {
let pageId = pageFolderTeleportCount.value;
pageFolderTeleportCount.value += 1000;
-async function toggle(ev: MouseEvent) {
+async function toggle(ev: PointerEvent) {
if (asPage && !opened.value) {
pageId++;
const { dispose } = await popup(MkFolderPage, {
diff --git a/packages/frontend/src/components/MkForm.file.vue b/packages/frontend/src/components/MkForm.file.vue
index 182ff3ccf5..d233467e8b 100644
--- a/packages/frontend/src/components/MkForm.file.vue
+++ b/packages/frontend/src/components/MkForm.file.vue
@@ -50,7 +50,7 @@ if (props.fileId) {
});
}
-function selectButton(ev: MouseEvent) {
+function selectButton(ev: PointerEvent) {
selectFile({
anchorElement: ev.currentTarget ?? ev.target,
multiple: false,
diff --git a/packages/frontend/src/components/MkHeatmap.vue b/packages/frontend/src/components/MkHeatmap.vue
index abbf86004b..03780bf3ba 100644
--- a/packages/frontend/src/components/MkHeatmap.vue
+++ b/packages/frontend/src/components/MkHeatmap.vue
@@ -125,8 +125,7 @@ async function renderChart() {
data: format(values) as any,
borderWidth: 0,
borderRadius: 3,
- backgroundColor(c) {
- // @ts-expect-error TS(2339)
+ backgroundColor(c: any) {
const value = c.dataset.data[c.dataIndex].v as number;
let a = (value - min) / max;
if (value !== 0) { // 0でない限りは完全に不可視にはしない
@@ -195,7 +194,7 @@ async function renderChart() {
font: {
size: 9,
},
- callback: (value, index, values) => ['', 'Mon', '', 'Wed', '', 'Fri', ''][value],
+ callback: (value, index, values) => ['', 'Mon', '', 'Wed', '', 'Fri', ''][value as any],
},
},
},
diff --git a/packages/frontend/src/components/MkImageEffectorDialog.vue b/packages/frontend/src/components/MkImageEffectorDialog.vue
index 01df7d7496..f740002088 100644
--- a/packages/frontend/src/components/MkImageEffectorDialog.vue
+++ b/packages/frontend/src/components/MkImageEffectorDialog.vue
@@ -95,7 +95,7 @@ watch(layers, async () => {
}
}, { deep: true });
-function addEffect(ev: MouseEvent) {
+function addEffect(ev: PointerEvent) {
os.popupMenu(Object.entries(FXS).map(([id, fx]) => ({
text: fx.uiDefinition.name,
action: () => {
@@ -219,7 +219,7 @@ watch(enabled, () => {
const penMode = ref<'fill' | 'blur' | 'pixelate' | null>(null);
-function showPenMenu(ev: MouseEvent) {
+function showPenMenu(ev: PointerEvent) {
os.popupMenu([{
text: i18n.ts._imageEffector._fxs.fill,
action: () => {
diff --git a/packages/frontend/src/components/MkInput.vue b/packages/frontend/src/components/MkInput.vue
index 7f052dff94..4f6ca083a3 100644
--- a/packages/frontend/src/components/MkInput.vue
+++ b/packages/frontend/src/components/MkInput.vue
@@ -88,7 +88,7 @@ const props = defineProps<{
}>();
const emit = defineEmits<{
- (ev: 'change', _ev: KeyboardEvent): void;
+ (ev: 'change', _ev: InputEvent): void;
(ev: 'keydown', _ev: KeyboardEvent): void;
(ev: 'enter', _ev: KeyboardEvent): void;
(ev: 'update:modelValue', value: ModelValueType
): void;
@@ -111,10 +111,9 @@ const height =
let autocompleteWorker: Autocomplete | null = null;
const focus = () => inputEl.value?.focus();
-const onInput = (event: Event) => {
- const ev = event as KeyboardEvent;
+const onInput = (event: InputEvent) => {
changed.value = true;
- emit('change', ev);
+ emit('change', event);
};
const onKeydown = (ev: KeyboardEvent) => {
if (ev.isComposing || ev.key === 'Process' || ev.keyCode === 229) return;
diff --git a/packages/frontend/src/components/MkInstanceCardMini.vue b/packages/frontend/src/components/MkInstanceCardMini.vue
index 7902151921..130a0e9986 100644
--- a/packages/frontend/src/components/MkInstanceCardMini.vue
+++ b/packages/frontend/src/components/MkInstanceCardMini.vue
@@ -33,7 +33,7 @@ misskeyApiGet('charts/instance', { host: props.instance.host, limit: 16 + 1, spa
chartValues.value = res.requests.received;
});
-function getInstanceIcon(instance): string {
+function getInstanceIcon(instance: Misskey.entities.FederationInstance): string {
return getProxiedImageUrlNullable(instance.iconUrl, 'preview') ?? getProxiedImageUrlNullable(instance.faviconUrl, 'preview') ?? '/client-assets/dummy.png';
}
diff --git a/packages/frontend/src/components/MkInstanceStats.vue b/packages/frontend/src/components/MkInstanceStats.vue
index 13048a2e1b..368fa5be27 100644
--- a/packages/frontend/src/components/MkInstanceStats.vue
+++ b/packages/frontend/src/components/MkInstanceStats.vue
@@ -57,10 +57,10 @@ SPDX-License-Identifier: AGPL-3.0-only
diff --git a/packages/frontend/src/components/MkLaunchPad.vue b/packages/frontend/src/components/MkLaunchPad.vue
index d8725ade0b..0c73df4e2d 100644
--- a/packages/frontend/src/components/MkLaunchPad.vue
+++ b/packages/frontend/src/components/MkLaunchPad.vue
@@ -8,13 +8,13 @@ SPDX-License-Identifier: AGPL-3.0-only
- { item.action($event); close(); }">
+ { item.action!($event); close(); }">
{{ item.text }}
{{ item.indicateValue }}
-
+
{{ item.text }}
{{ item.indicateValue }}
diff --git a/packages/frontend/src/components/MkMediaImage.vue b/packages/frontend/src/components/MkMediaImage.vue
index 345c261776..c7d8c95b7b 100644
--- a/packages/frontend/src/components/MkMediaImage.vue
+++ b/packages/frontend/src/components/MkMediaImage.vue
@@ -100,7 +100,7 @@ const url = computed(() => (props.raw || prefer.s.loadRawImages)
: props.image.thumbnailUrl!,
);
-async function reveal(ev: MouseEvent) {
+async function reveal(ev: PointerEvent) {
if (!props.controls) {
return;
}
@@ -123,7 +123,7 @@ watch(() => props.image, (newImage) => {
immediate: true,
});
-function showMenu(ev: MouseEvent) {
+function showMenu(ev: PointerEvent) {
const menuItems: MenuItem[] = [];
menuItems.push({
diff --git a/packages/frontend/src/components/MkMediaVideo.vue b/packages/frontend/src/components/MkMediaVideo.vue
index 63db3c3ab5..aac52bfa26 100644
--- a/packages/frontend/src/components/MkMediaVideo.vue
+++ b/packages/frontend/src/components/MkMediaVideo.vue
@@ -190,7 +190,7 @@ async function reveal() {
// Menu
const menuShowing = ref(false);
-function showMenu(ev: MouseEvent) {
+function showMenu(ev: PointerEvent) {
const menu: MenuItem[] = [
// TODO: 再生キューに追加
{
diff --git a/packages/frontend/src/components/MkMenu.vue b/packages/frontend/src/components/MkMenu.vue
index 6efaa655bc..22d5802596 100644
--- a/packages/frontend/src/components/MkMenu.vue
+++ b/packages/frontend/src/components/MkMenu.vue
@@ -316,7 +316,7 @@ function onItemMouseLeave() {
if (childCloseTimer) window.clearTimeout(childCloseTimer);
}
-async function showRadioOptions(item: MenuRadio, ev: Event) {
+async function showRadioOptions(item: MenuRadio, ev: MouseEvent | PointerEvent | KeyboardEvent) {
const children: MenuItem[] = Object.keys(item.options).map(key => {
const value = item.options[key];
return {
@@ -341,7 +341,7 @@ async function showRadioOptions(item: MenuRadio, ev: Event) {
}
}
-async function showChildren(item: MenuParent, ev: Event) {
+async function showChildren(item: MenuParent, ev: MouseEvent | PointerEvent | KeyboardEvent) {
ev.stopPropagation();
const children: MenuItem[] = await (async () => {
@@ -371,7 +371,7 @@ async function showChildren(item: MenuParent, ev: Event) {
}
}
-function clicked(fn: MenuAction, ev: MouseEvent, doClose = true) {
+function clicked(fn: MenuAction, ev: PointerEvent, doClose = true) {
fn(ev);
if (!doClose) return;
diff --git a/packages/frontend/src/components/MkModal.vue b/packages/frontend/src/components/MkModal.vue
index 660d5a26be..92174d8ef7 100644
--- a/packages/frontend/src/components/MkModal.vue
+++ b/packages/frontend/src/components/MkModal.vue
@@ -184,8 +184,8 @@ const align = () => {
const width = content.value!.offsetWidth;
const height = content.value!.offsetHeight;
- let left;
- let top;
+ let left = 0;
+ let top = 0;
const x = anchorRect.left + (fixed.value ? 0 : window.scrollX);
const y = anchorRect.top + (fixed.value ? 0 : window.scrollY);
diff --git a/packages/frontend/src/components/MkNote.vue b/packages/frontend/src/components/MkNote.vue
index 56def64d3d..c78cc44425 100644
--- a/packages/frontend/src/components/MkNote.vue
+++ b/packages/frontend/src/components/MkNote.vue
@@ -594,7 +594,7 @@ function toggleReact() {
}
}
-function onContextmenu(ev: MouseEvent): void {
+function onContextmenu(ev: PointerEvent): void {
if (props.mock) {
return;
}
diff --git a/packages/frontend/src/components/MkNoteDetailed.vue b/packages/frontend/src/components/MkNoteDetailed.vue
index febf909f42..cfb65cd9b7 100644
--- a/packages/frontend/src/components/MkNoteDetailed.vue
+++ b/packages/frontend/src/components/MkNoteDetailed.vue
@@ -17,7 +17,7 @@ SPDX-License-Identifier: AGPL-3.0-only
-
+
@@ -111,7 +111,7 @@ SPDX-License-Identifier: AGPL-3.0-only
-
+
@@ -233,7 +232,7 @@ SPDX-License-Identifier: AGPL-3.0-only
diff --git a/packages/frontend/src/components/MkStreamingNotesTimeline.vue b/packages/frontend/src/components/MkStreamingNotesTimeline.vue
index bc6ebf0918..9784d8e017 100644
--- a/packages/frontend/src/components/MkStreamingNotesTimeline.vue
+++ b/packages/frontend/src/components/MkStreamingNotesTimeline.vue
@@ -350,13 +350,12 @@ function connectChannel() {
connections.main = stream.useChannel('main');
connections.main.on('mention', prepend);
} else if (props.src === 'directs') {
- const onNote = note => {
+ connections.main = stream.useChannel('main');
+ connections.main.on('mention', note => {
if (note.visibility === 'specified') {
prepend(note);
}
- };
- connections.main = stream.useChannel('main');
- connections.main.on('mention', onNote);
+ });
} else if (props.src === 'list') {
if (props.list == null) return;
connections.userList = stream.useChannel('userList', {
diff --git a/packages/frontend/src/components/MkStreamingNotificationsTimeline.vue b/packages/frontend/src/components/MkStreamingNotificationsTimeline.vue
index 6ee2e347a5..91f071fe63 100644
--- a/packages/frontend/src/components/MkStreamingNotificationsTimeline.vue
+++ b/packages/frontend/src/components/MkStreamingNotificationsTimeline.vue
@@ -137,8 +137,8 @@ watch(visibility, () => {
}
});
-function onNotification(notification) {
- const isMuted = props.excludeTypes ? props.excludeTypes.includes(notification.type) : false;
+function onNotification(notification: Misskey.entities.Notification) {
+ const isMuted = props.excludeTypes ? props.excludeTypes.includes(notification.type as typeof notificationTypes[number]) : false;
if (isMuted || window.document.visibilityState === 'visible') {
if (store.s.realtimeMode) {
useStream().send('readNotification');
diff --git a/packages/frontend/src/components/MkSuperMenu.vue b/packages/frontend/src/components/MkSuperMenu.vue
index 236afa127c..585a628a96 100644
--- a/packages/frontend/src/components/MkSuperMenu.vue
+++ b/packages/frontend/src/components/MkSuperMenu.vue
@@ -82,7 +82,7 @@ export type SuperMenuDef = {
text: string;
danger?: boolean;
active?: boolean;
- action: (ev: MouseEvent) => Awaitable;
+ action: (ev: PointerEvent) => Awaitable;
} | {
type?: 'link';
to: string;
diff --git a/packages/frontend/src/components/MkSystemWebhookEditor.vue b/packages/frontend/src/components/MkSystemWebhookEditor.vue
index cd72204fce..1536b14455 100644
--- a/packages/frontend/src/components/MkSystemWebhookEditor.vue
+++ b/packages/frontend/src/components/MkSystemWebhookEditor.vue
@@ -245,7 +245,7 @@ onMounted(async () => {
secret.value = res.secret;
isActive.value = res.isActive;
for (const ev of Object.keys(events.value)) {
- events.value[ev] = res.on.includes(ev as SystemWebhookEventType);
+ events.value[ev as SystemWebhookEventType] = res.on.includes(ev as SystemWebhookEventType);
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
} catch (ex: any) {
diff --git a/packages/frontend/src/components/MkTabs.vue b/packages/frontend/src/components/MkTabs.vue
index 9798e2c3b3..a6342ec2e1 100644
--- a/packages/frontend/src/components/MkTabs.vue
+++ b/packages/frontend/src/components/MkTabs.vue
@@ -50,7 +50,7 @@ SPDX-License-Identifier: AGPL-3.0-only
diff --git a/packages/frontend/src/components/MkTutorialDialog.Note.vue b/packages/frontend/src/components/MkTutorialDialog.Note.vue
index b77e67e9c6..3ab2c5f0d4 100644
--- a/packages/frontend/src/components/MkTutorialDialog.Note.vue
+++ b/packages/frontend/src/components/MkTutorialDialog.Note.vue
@@ -74,7 +74,7 @@ const exampleNote = reactive({
});
const onceReacted = ref(false);
-function addReaction(emoji) {
+function addReaction(emoji: string) {
onceReacted.value = true;
emit('reacted');
doNotification(emoji);
@@ -96,7 +96,7 @@ function doNotification(emoji: string): void {
globalEvents.emit('clientNotification', notification);
}
-function removeReaction(emoji) {
+function removeReaction(emoji: string) {
delete exampleNote.reactions[emoji];
exampleNote.myReaction = undefined;
}
diff --git a/packages/frontend/src/components/MkUploaderDialog.vue b/packages/frontend/src/components/MkUploaderDialog.vue
index 8849fa447d..69de56d45c 100644
--- a/packages/frontend/src/components/MkUploaderDialog.vue
+++ b/packages/frontend/src/components/MkUploaderDialog.vue
@@ -166,17 +166,17 @@ async function done() {
dialog.value?.close();
}
-async function chooseFile(ev: MouseEvent) {
+async function chooseFile(ev: PointerEvent) {
const newFiles = await os.chooseFileFromPc({ multiple: true });
uploader.addFiles(newFiles);
}
-function showPerItemMenu(item: UploaderItem, ev: MouseEvent) {
+function showPerItemMenu(item: UploaderItem, ev: PointerEvent) {
const menu = uploader.getMenu(item);
os.popupMenu(menu, ev.currentTarget ?? ev.target);
}
-function showPerItemMenuViaContextmenu(item: UploaderItem, ev: MouseEvent) {
+function showPerItemMenuViaContextmenu(item: UploaderItem, ev: PointerEvent) {
const menu = uploader.getMenu(item);
os.contextMenu(menu, ev);
}
diff --git a/packages/frontend/src/components/MkUploaderItems.vue b/packages/frontend/src/components/MkUploaderItems.vue
index f31c717ad5..51f7ac2d09 100644
--- a/packages/frontend/src/components/MkUploaderItems.vue
+++ b/packages/frontend/src/components/MkUploaderItems.vue
@@ -57,18 +57,18 @@ const props = defineProps<{
}>();
const emit = defineEmits<{
- (ev: 'showMenu', item: UploaderItem, event: MouseEvent): void;
- (ev: 'showMenuViaContextmenu', item: UploaderItem, event: MouseEvent): void;
+ (ev: 'showMenu', item: UploaderItem, event: PointerEvent): void;
+ (ev: 'showMenuViaContextmenu', item: UploaderItem, event: PointerEvent): void;
}>();
-function onContextmenu(item: UploaderItem, ev: MouseEvent) {
+function onContextmenu(item: UploaderItem, ev: PointerEvent) {
if (ev.target && isLink(ev.target as HTMLElement)) return;
if (window.getSelection()?.toString() !== '') return;
emit('showMenuViaContextmenu', item, ev);
}
-function onThumbnailClick(item: UploaderItem, ev: MouseEvent) {
+function onThumbnailClick(item: UploaderItem, ev: PointerEvent) {
// TODO: preview when item is image
}
diff --git a/packages/frontend/src/components/MkUserList.vue b/packages/frontend/src/components/MkUserList.vue
index f47d9b56dc..8ce929fff3 100644
--- a/packages/frontend/src/components/MkUserList.vue
+++ b/packages/frontend/src/components/MkUserList.vue
@@ -27,7 +27,7 @@ const props = withDefaults(defineProps<{
noGap?: boolean;
extractor?: ExtractorFunction;
}>(), {
- extractor: (item) => item,
+ extractor: (item: any) => item as Misskey.entities.UserDetailed,
});
diff --git a/packages/frontend/src/components/MkUserPopup.vue b/packages/frontend/src/components/MkUserPopup.vue
index f794899281..9f196ac2c1 100644
--- a/packages/frontend/src/components/MkUserPopup.vue
+++ b/packages/frontend/src/components/MkUserPopup.vue
@@ -90,7 +90,7 @@ const top = ref(0);
const left = ref(0);
const error = ref(false);
-function showMenu(ev: MouseEvent) {
+function showMenu(ev: PointerEvent) {
if (user.value == null) return;
const { menu, cleanup } = getUserMenu(user.value);
os.popupMenu(menu, ev.currentTarget ?? ev.target).finally(cleanup);
diff --git a/packages/frontend/src/components/MkUserSetupDialog.Profile.vue b/packages/frontend/src/components/MkUserSetupDialog.Profile.vue
index 4e96eff82e..95449dd0eb 100644
--- a/packages/frontend/src/components/MkUserSetupDialog.Profile.vue
+++ b/packages/frontend/src/components/MkUserSetupDialog.Profile.vue
@@ -66,7 +66,7 @@ watch(description, () => {
});
});
-async function setAvatar(ev) {
+async function setAvatar(ev: PointerEvent) {
const files = await os.chooseFileFromPc({ multiple: false });
const file = files[0];
diff --git a/packages/frontend/src/components/MkVisitorDashboard.ActiveUsersChart.vue b/packages/frontend/src/components/MkVisitorDashboard.ActiveUsersChart.vue
index 6aaee76565..6513ca385d 100644
--- a/packages/frontend/src/components/MkVisitorDashboard.ActiveUsersChart.vue
+++ b/packages/frontend/src/components/MkVisitorDashboard.ActiveUsersChart.vue
@@ -46,7 +46,7 @@ async function renderChart() {
return new Date(y, m, d - ago);
};
- const format = (arr) => {
+ const format = (arr: number[]) => {
return arr.map((v, i) => ({
x: getDate(i).getTime(),
y: v,
diff --git a/packages/frontend/src/components/MkVisitorDashboard.vue b/packages/frontend/src/components/MkVisitorDashboard.vue
index 8bef225de5..2ce1912b86 100644
--- a/packages/frontend/src/components/MkVisitorDashboard.vue
+++ b/packages/frontend/src/components/MkVisitorDashboard.vue
@@ -94,7 +94,7 @@ function signup() {
});
}
-function showMenu(ev: MouseEvent) {
+function showMenu(ev: PointerEvent) {
openInstanceMenu(ev);
}
diff --git a/packages/frontend/src/components/MkWaitingDialog.vue b/packages/frontend/src/components/MkWaitingDialog.vue
index 820cf05e1f..18f2b3e189 100644
--- a/packages/frontend/src/components/MkWaitingDialog.vue
+++ b/packages/frontend/src/components/MkWaitingDialog.vue
@@ -26,8 +26,8 @@ const props = defineProps<{
}>();
const emit = defineEmits<{
- (ev: 'done');
- (ev: 'closed');
+ (ev: 'done'): void;
+ (ev: 'closed'): void;
}>();
function done() {
diff --git a/packages/frontend/src/components/MkWatermarkEditorDialog.Layer.vue b/packages/frontend/src/components/MkWatermarkEditorDialog.Layer.vue
index 154b3ffc27..8e5bb6221d 100644
--- a/packages/frontend/src/components/MkWatermarkEditorDialog.Layer.vue
+++ b/packages/frontend/src/components/MkWatermarkEditorDialog.Layer.vue
@@ -387,7 +387,7 @@ onMounted(async () => {
}
});
-function chooseFile(ev: MouseEvent) {
+function chooseFile(ev: PointerEvent) {
selectFile({
anchorElement: ev.currentTarget ?? ev.target,
multiple: false,
diff --git a/packages/frontend/src/components/MkWatermarkEditorDialog.vue b/packages/frontend/src/components/MkWatermarkEditorDialog.vue
index 7fe497e455..cadf9ba522 100644
--- a/packages/frontend/src/components/MkWatermarkEditorDialog.vue
+++ b/packages/frontend/src/components/MkWatermarkEditorDialog.vue
@@ -350,7 +350,7 @@ async function save() {
}
}
-function addLayer(ev: MouseEvent) {
+function addLayer(ev: PointerEvent) {
os.popupMenu([{
text: i18n.ts._watermarkEditor.text,
action: () => {
diff --git a/packages/frontend/src/components/MkWidgetSettingsDialog.vue b/packages/frontend/src/components/MkWidgetSettingsDialog.vue
index 951ac88465..63f294770c 100644
--- a/packages/frontend/src/components/MkWidgetSettingsDialog.vue
+++ b/packages/frontend/src/components/MkWidgetSettingsDialog.vue
@@ -14,7 +14,7 @@ SPDX-License-Identifier: AGPL-3.0-only
@ok="save()"
@closed="emit('closed')"
>
- {{ i18n.ts._widgets[widgetName] ?? widgetName }}
+ {{ (i18n.ts._widgets as any)[widgetName] ?? widgetName }}
diff --git a/packages/frontend/src/components/MkWidgets.vue b/packages/frontend/src/components/MkWidgets.vue
index e7712e8aae..a27613c24c 100644
--- a/packages/frontend/src/components/MkWidgets.vue
+++ b/packages/frontend/src/components/MkWidgets.vue
@@ -24,12 +24,12 @@ SPDX-License-Identifier: AGPL-3.0-only
-
+
-
+
@@ -47,6 +47,7 @@ export type DefaultStoredWidget = {
diff --git a/packages/frontend/src/components/global/MkA.vue b/packages/frontend/src/components/global/MkA.vue
index 99693a4c00..7d2908d4be 100644
--- a/packages/frontend/src/components/global/MkA.vue
+++ b/packages/frontend/src/components/global/MkA.vue
@@ -48,7 +48,7 @@ const active = computed(() => {
return resolved.route.name === router.currentRoute.value.name;
});
-function onContextmenu(ev) {
+function onContextmenu(ev: PointerEvent) {
const selection = window.getSelection();
if (selection && selection.toString() !== '') return;
os.contextMenu([{
@@ -85,7 +85,7 @@ function openWindow() {
os.pageWindow(props.to);
}
-function nav(ev: MouseEvent) {
+function nav(ev: PointerEvent) {
// 制御キーとの組み合わせは無視(shiftを除く)
if (ev.metaKey || ev.altKey || ev.ctrlKey) return;
diff --git a/packages/frontend/src/components/global/MkAvatar.vue b/packages/frontend/src/components/global/MkAvatar.vue
index e7208ed574..fd1d0c2b63 100644
--- a/packages/frontend/src/components/global/MkAvatar.vue
+++ b/packages/frontend/src/components/global/MkAvatar.vue
@@ -77,7 +77,7 @@ const props = withDefaults(defineProps<{
});
const emit = defineEmits<{
- (ev: 'click', v: MouseEvent): void;
+ (ev: 'click', v: PointerEvent): void;
}>();
const showDecoration = props.forceShowDecoration || prefer.s.showAvatarDecorations;
@@ -91,7 +91,7 @@ const url = computed(() => {
return props.user.avatarUrl;
});
-function onClick(ev: MouseEvent): void {
+function onClick(ev: PointerEvent): void {
if (props.link) return;
emit('click', ev);
}
diff --git a/packages/frontend/src/components/global/MkCondensedLine.vue b/packages/frontend/src/components/global/MkCondensedLine.vue
index 473d444c16..e1fbec4b6f 100644
--- a/packages/frontend/src/components/global/MkCondensedLine.vue
+++ b/packages/frontend/src/components/global/MkCondensedLine.vue
@@ -23,8 +23,8 @@ const observer = new ResizeObserver((entries) => {
transform: string;
}[] = [];
for (const entry of entries) {
- const content = (entry.target[contentSymbol] ? entry.target : entry.target.firstElementChild) as HTMLSpanElement;
- const props: Required = content[contentSymbol];
+ const content = ((entry.target as any)[contentSymbol] ? entry.target : entry.target.firstElementChild) as HTMLSpanElement;
+ const props: Required = (content as any)[contentSymbol];
const container = content.parentElement as HTMLSpanElement;
const contentWidth = content.getBoundingClientRect().width;
const containerWidth = container.getBoundingClientRect().width;
@@ -46,15 +46,15 @@ const props = withDefaults(defineProps(), {
const content = ref();
watch(content, (value, oldValue) => {
- if (oldValue) {
- delete oldValue[contentSymbol];
+ if (oldValue != null) {
+ delete (oldValue as any)[contentSymbol];
observer.unobserve(oldValue);
if (oldValue.parentElement) {
observer.unobserve(oldValue.parentElement);
}
}
- if (value) {
- value[contentSymbol] = props;
+ if (value != null) {
+ (value as any)[contentSymbol] = props;
observer.observe(value);
if (value.parentElement) {
observer.observe(value.parentElement);
diff --git a/packages/frontend/src/components/global/MkCustomEmoji.vue b/packages/frontend/src/components/global/MkCustomEmoji.vue
index 31c358eee7..9a171876a0 100644
--- a/packages/frontend/src/components/global/MkCustomEmoji.vue
+++ b/packages/frontend/src/components/global/MkCustomEmoji.vue
@@ -102,7 +102,7 @@ const url = computed(() => {
const alt = computed(() => `:${customEmojiName.value}:`);
const errored = ref(url.value == null);
-function onClick(ev: MouseEvent) {
+function onClick(ev: PointerEvent) {
if (props.menu) {
const menuItems: MenuItem[] = [];
diff --git a/packages/frontend/src/components/global/MkEmoji.vue b/packages/frontend/src/components/global/MkEmoji.vue
index 792f9c7d6f..686720cec2 100644
--- a/packages/frontend/src/components/global/MkEmoji.vue
+++ b/packages/frontend/src/components/global/MkEmoji.vue
@@ -67,7 +67,7 @@ function unmute() {
});
}
-function onClick(ev: MouseEvent) {
+function onClick(ev: PointerEvent) {
if (props.menu) {
const menuItems: MenuItem[] = [];
diff --git a/packages/frontend/src/components/global/MkMfm.ts b/packages/frontend/src/components/global/MkMfm.ts
index 3ad2fda0ee..d270571d4a 100644
--- a/packages/frontend/src/components/global/MkMfm.ts
+++ b/packages/frontend/src/components/global/MkMfm.ts
@@ -319,7 +319,7 @@ export default function (props: MfmProps, { emit }: { emit: SetupContext
export type Tab = {
key: string;
- onClick?: (ev: MouseEvent) => void;
+ onClick?: (ev: PointerEvent) => void;
iconOnly?: boolean;
title: string;
icon?: string;
@@ -70,8 +70,8 @@ const props = withDefaults(defineProps<{
});
const emit = defineEmits<{
- (ev: 'update:tab', key: string);
- (ev: 'tabClick', key: string);
+ (ev: 'update:tab', key: string): void;
+ (ev: 'tabClick', key: string): void;
}>();
const el = useTemplateRef('el');
@@ -96,7 +96,7 @@ function onTabMousedown(tab: Tab, ev: MouseEvent): void {
}
}
-function onTabClick(t: Tab, ev: MouseEvent): void {
+function onTabClick(t: Tab, ev: PointerEvent): void {
emit('tabClick', t.key);
if (t.onClick) {
diff --git a/packages/frontend/src/components/global/MkPageHeader.vue b/packages/frontend/src/components/global/MkPageHeader.vue
index 2445f8e0ef..e8c93b7092 100644
--- a/packages/frontend/src/components/global/MkPageHeader.vue
+++ b/packages/frontend/src/components/global/MkPageHeader.vue
@@ -61,7 +61,6 @@ export type PageHeaderProps = {
import { onMounted, onUnmounted, ref, inject, useTemplateRef, computed } from 'vue';
import { scrollToTop } from '@@/js/scroll.js';
import XTabs from './MkPageHeader.tabs.vue';
-import { globalEvents } from '@/events.js';
import { getAccountMenu } from '@/accounts.js';
import { $i } from '@/i.js';
import { DI } from '@/di.js';
@@ -72,7 +71,7 @@ const props = withDefaults(defineProps(), {
});
const emit = defineEmits<{
- (ev: 'update:tab', key: string);
+ (ev: 'update:tab', key: string): void;
}>();
//const viewId = inject(DI.viewId);
@@ -100,7 +99,7 @@ const top = () => {
}
};
-async function openAccountMenu(ev: MouseEvent) {
+async function openAccountMenu(ev: PointerEvent) {
const menuItems = await getAccountMenu({
withExtraOperation: true,
});
diff --git a/packages/frontend/src/components/global/MkTip.vue b/packages/frontend/src/components/global/MkTip.vue
index 231957a232..1827c16c89 100644
--- a/packages/frontend/src/components/global/MkTip.vue
+++ b/packages/frontend/src/components/global/MkTip.vue
@@ -32,7 +32,7 @@ function _closeTip() {
closeTip(props.k);
}
-function showMenu(ev: MouseEvent) {
+function showMenu(ev: PointerEvent) {
os.popupMenu([{
icon: 'ti ti-bulb-off',
text: i18n.ts.hideAllTips,
diff --git a/packages/frontend/src/components/grid/MkDataCell.vue b/packages/frontend/src/components/grid/MkDataCell.vue
index 6f1dae8398..8745146ccf 100644
--- a/packages/frontend/src/components/grid/MkDataCell.vue
+++ b/packages/frontend/src/components/grid/MkDataCell.vue
@@ -188,7 +188,7 @@ function onCellKeyDown(ev: KeyboardEvent) {
}
}
-function onInputText(ev: Event) {
+function onInputText(ev: InputEvent) {
editingValue.value = (ev.target as HTMLInputElement).value;
}
diff --git a/packages/frontend/src/components/grid/MkGrid.vue b/packages/frontend/src/components/grid/MkGrid.vue
index 96d9e35773..097a91bad5 100644
--- a/packages/frontend/src/components/grid/MkGrid.vue
+++ b/packages/frontend/src/components/grid/MkGrid.vue
@@ -715,7 +715,7 @@ function onMouseUp(ev: MouseEvent) {
}
}
-function onContextMenu(ev: MouseEvent) {
+function onContextMenu(ev: PointerEvent) {
const cellAddress = getCellAddress(ev.target as HTMLElement);
if (_DEV_) {
console.log(`[grid][context-menu] button: ${ev.button}, cell: ${cellAddress.row}x${cellAddress.col}`);
diff --git a/packages/frontend/src/composables/use-chart-tooltip.ts b/packages/frontend/src/composables/use-chart-tooltip.ts
index a42f70ba02..9816de7c14 100644
--- a/packages/frontend/src/composables/use-chart-tooltip.ts
+++ b/packages/frontend/src/composables/use-chart-tooltip.ts
@@ -4,6 +4,7 @@
*/
import { onUnmounted, onDeactivated, ref } from 'vue';
+import type { Chart, ChartType, TooltipModel } from 'chart.js';
import * as os from '@/os.js';
import MkChartTooltip from '@/components/MkChartTooltip.vue';
@@ -40,7 +41,7 @@ export function useChartTooltip(opts: { position: 'top' | 'middle' } = { positio
tooltipShowing.value = false;
});
- function handler(context) {
+ function handler(context: { chart: Chart; tooltip: TooltipModel }) {
if (context.tooltip.opacity === 0) {
tooltipShowing.value = false;
return;
@@ -48,8 +49,8 @@ export function useChartTooltip(opts: { position: 'top' | 'middle' } = { positio
tooltipTitle.value = context.tooltip.title[0];
tooltipSeries.value = context.tooltip.body.map((b, i) => ({
- backgroundColor: context.tooltip.labelColors[i].backgroundColor,
- borderColor: context.tooltip.labelColors[i].borderColor,
+ backgroundColor: context.tooltip.labelColors[i].backgroundColor as string,
+ borderColor: context.tooltip.labelColors[i].borderColor as string,
text: b.lines[0],
}));
diff --git a/packages/frontend/src/composables/use-form.ts b/packages/frontend/src/composables/use-form.ts
index 38e9b40e20..812b66d1f0 100644
--- a/packages/frontend/src/composables/use-form.ts
+++ b/packages/frontend/src/composables/use-form.ts
@@ -31,7 +31,7 @@ export function useForm>(initialState: T, save: (n
watch([currentState, previousState], () => {
for (const key in modifiedStates) {
- modifiedStates[key] = !deepEqual(currentState[key], previousState[key]);
+ (modifiedStates as any)[key] = !deepEqual(currentState[key], previousState[key]);
}
}, { deep: true });
diff --git a/packages/frontend/src/composables/use-note-capture.ts b/packages/frontend/src/composables/use-note-capture.ts
index 2aeb9074e5..25a9383cd5 100644
--- a/packages/frontend/src/composables/use-note-capture.ts
+++ b/packages/frontend/src/composables/use-note-capture.ts
@@ -7,6 +7,7 @@ import { onUnmounted, reactive } from 'vue';
import * as Misskey from 'misskey-js';
import { EventEmitter } from 'eventemitter3';
import type { Reactive } from 'vue';
+import type { NoteUpdatedEvent } from 'misskey-js/streaming.types.js';
import { useStream } from '@/stream.js';
import { $i } from '@/i.js';
import { store } from '@/store.js';
@@ -15,9 +16,9 @@ import { prefer } from '@/preferences.js';
import { globalEvents } from '@/events.js';
export const noteEvents = new EventEmitter<{
- [ev: `reacted:${string}`]: (ctx: { userId: Misskey.entities.User['id']; reaction: string; emoji?: { name: string; url: string; }; }) => void;
- [ev: `unreacted:${string}`]: (ctx: { userId: Misskey.entities.User['id']; reaction: string; emoji?: { name: string; url: string; }; }) => void;
- [ev: `pollVoted:${string}`]: (ctx: { userId: Misskey.entities.User['id']; choice: string; }) => void;
+ [ev: `reacted:${string}`]: (ctx: { userId: Misskey.entities.User['id']; reaction: string; emoji?: { name: string; url: string; } | null; }) => void;
+ [ev: `unreacted:${string}`]: (ctx: { userId: Misskey.entities.User['id']; reaction: string; emoji?: { name: string; url: string; } | null; }) => void;
+ [ev: `pollVoted:${string}`]: (ctx: { userId: Misskey.entities.User['id']; choice: number; }) => void;
}>();
const fetchEvent = new EventEmitter<{
@@ -117,7 +118,7 @@ function realtimeSubscribe(props: {
const note = props.note;
const connection = useStream();
- function onStreamNoteUpdated(noteData): void {
+ function onStreamNoteUpdated(noteData: NoteUpdatedEvent): void {
const { type, id, body } = noteData;
if (id !== note.id) return;
@@ -136,7 +137,6 @@ function realtimeSubscribe(props: {
noteEvents.emit(`unreacted:${id}`, {
userId: body.userId,
reaction: body.reaction,
- emoji: body.emoji,
});
break;
}
@@ -194,9 +194,9 @@ export function useNoteCapture(props: {
parentNote: Misskey.entities.Note | null;
mock?: boolean;
}): {
- $note: Reactive;
- subscribe: () => void;
- } {
+ $note: Reactive;
+ subscribe: () => void;
+} {
const { note, parentNote, mock } = props;
const $note = reactive({
@@ -224,7 +224,7 @@ export function useNoteCapture(props: {
const reactionUserMap = new Map();
let latestPollVotedKey: string | null = null;
- function onReacted(ctx: { userId: Misskey.entities.User['id']; reaction: string; emoji?: { name: string; url: string; }; }): void {
+ function onReacted(ctx: { userId: Misskey.entities.User['id']; reaction: string; emoji?: { name: string; url: string; } | null; }): void {
let normalizedName = ctx.reaction.replace(/^:(\w+):$/, ':$1@.:');
normalizedName = normalizedName.match('\u200d') ? normalizedName : normalizedName.replace(/\ufe0f/g, '');
if (reactionUserMap.has(ctx.userId) && reactionUserMap.get(ctx.userId) === normalizedName) return;
@@ -244,7 +244,7 @@ export function useNoteCapture(props: {
}
}
- function onUnreacted(ctx: { userId: Misskey.entities.User['id']; reaction: string; emoji?: { name: string; url: string; }; }): void {
+ function onUnreacted(ctx: { userId: Misskey.entities.User['id']; reaction: string; emoji?: { name: string; url: string; } | null; }): void {
let normalizedName = ctx.reaction.replace(/^:(\w+):$/, ':$1@.:');
normalizedName = normalizedName.match('\u200d') ? normalizedName : normalizedName.replace(/\ufe0f/g, '');
@@ -263,7 +263,7 @@ export function useNoteCapture(props: {
}
}
- function onPollVoted(ctx: { userId: Misskey.entities.User['id']; choice: string; }): void {
+ function onPollVoted(ctx: { userId: Misskey.entities.User['id']; choice: number; }): void {
const newPollVotedKey = `${ctx.userId}:${ctx.choice}`;
if (newPollVotedKey === latestPollVotedKey) return;
latestPollVotedKey = newPollVotedKey;
diff --git a/packages/frontend/src/composables/use-tooltip.ts b/packages/frontend/src/composables/use-tooltip.ts
index af76a3a1e8..e369928208 100644
--- a/packages/frontend/src/composables/use-tooltip.ts
+++ b/packages/frontend/src/composables/use-tooltip.ts
@@ -22,7 +22,7 @@ export function useTooltip(
let changeShowingState: (() => void) | null;
- let autoHidingTimer;
+ let autoHidingTimer: number | null = null;
const open = () => {
close();
@@ -43,7 +43,7 @@ export function useTooltip(
isHovering = false;
window.clearTimeout(timeoutId);
close();
- window.clearInterval(autoHidingTimer);
+ if (autoHidingTimer != null) window.clearInterval(autoHidingTimer);
}
}, 1000);
};
@@ -66,7 +66,7 @@ export function useTooltip(
if (!isHovering) return;
isHovering = false;
window.clearTimeout(timeoutId);
- window.clearInterval(autoHidingTimer);
+ if (autoHidingTimer != null) window.clearInterval(autoHidingTimer);
close();
};
@@ -81,7 +81,7 @@ export function useTooltip(
if (!isHovering) return;
isHovering = false;
window.clearTimeout(timeoutId);
- window.clearInterval(autoHidingTimer);
+ if (autoHidingTimer != null) window.clearInterval(autoHidingTimer);
close();
};
diff --git a/packages/frontend/src/composables/use-uploader.ts b/packages/frontend/src/composables/use-uploader.ts
index 8ffb1e656b..fabc04895e 100644
--- a/packages/frontend/src/composables/use-uploader.ts
+++ b/packages/frontend/src/composables/use-uploader.ts
@@ -664,7 +664,7 @@ export function useUploader(options: {
if (needsCompress) {
const config = {
- mimeType: isWebpSupported() ? 'image/webp' : 'image/jpeg',
+ mimeType: (isWebpSupported() ? 'image/webp' : 'image/jpeg') as 'image/webp' | 'image/jpeg',
maxWidth: compressionSettings.maxWidth,
maxHeight: compressionSettings.maxHeight,
quality: isWebpSupported() ? 0.85 : 0.8,
diff --git a/packages/frontend/src/custom-emojis.ts b/packages/frontend/src/custom-emojis.ts
index 45d4b40fd7..e04d540c38 100644
--- a/packages/frontend/src/custom-emojis.ts
+++ b/packages/frontend/src/custom-emojis.ts
@@ -60,11 +60,11 @@ export async function fetchCustomEmojis(force = false) {
set('lastEmojisFetchedAt', now);
}
-let cachedTags;
+let cachedTags: string[] | null = null;
export function getCustomEmojiTags() {
if (cachedTags) return cachedTags;
- const tags = new Set();
+ const tags = new Set();
for (const emoji of customEmojis.value) {
for (const tag of emoji.aliases) {
tags.add(tag);
diff --git a/packages/frontend/src/deck.ts b/packages/frontend/src/deck.ts
index 208adae8fe..e85ca76ca1 100644
--- a/packages/frontend/src/deck.ts
+++ b/packages/frontend/src/deck.ts
@@ -316,14 +316,14 @@ export function updateColumn(id: Column['id'], column: Partial) {
const currentColumn = deepClone(columns.value[columnIndex]);
if (currentColumn == null) return;
for (const [k, v] of Object.entries(column)) {
- currentColumn[k] = v;
+ (currentColumn[k as keyof typeof column] as any) = v;
}
newColumns[columnIndex] = currentColumn;
columns.value = newColumns;
saveCurrentDeckProfile();
}
-export function switchProfileMenu(ev: MouseEvent) {
+export function switchProfileMenu(ev: PointerEvent) {
const items: MenuItem[] = prefer.s['deck.profile'] ? [{
text: prefer.s['deck.profile'],
active: true,
diff --git a/packages/frontend/src/filters/bytes.ts b/packages/frontend/src/filters/bytes.ts
index 49b44167d4..a5b6fad3b1 100644
--- a/packages/frontend/src/filters/bytes.ts
+++ b/packages/frontend/src/filters/bytes.ts
@@ -3,7 +3,7 @@
* SPDX-License-Identifier: AGPL-3.0-only
*/
-export default (v, digits = 0) => {
+export default (v: number | null, digits = 0) => {
if (v == null) return '?';
const sizes = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB', 'RB', 'QB'];
if (v === 0) return '0';
diff --git a/packages/frontend/src/filters/kmg.ts b/packages/frontend/src/filters/kmg.ts
index 9608e420f6..0aaa70d50d 100644
--- a/packages/frontend/src/filters/kmg.ts
+++ b/packages/frontend/src/filters/kmg.ts
@@ -3,7 +3,7 @@
* SPDX-License-Identifier: AGPL-3.0-only
*/
-export default (v, fractionDigits = 0) => {
+export default (v: number | null, fractionDigits = 0) => {
if (v == null) return 'N/A';
if (v === 0) return '0';
const sizes = ['', 'K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y', 'R', 'Q'];
diff --git a/packages/frontend/src/filters/note.ts b/packages/frontend/src/filters/note.ts
index ce31021469..3fcd50c5e3 100644
--- a/packages/frontend/src/filters/note.ts
+++ b/packages/frontend/src/filters/note.ts
@@ -3,6 +3,6 @@
* SPDX-License-Identifier: AGPL-3.0-only
*/
-export const notePage = note => {
+export const notePage = (note: { id: string }) => {
return `/notes/${note.id}`;
};
diff --git a/packages/frontend/src/instance.ts b/packages/frontend/src/instance.ts
index c9d83a4dbe..547db12e34 100644
--- a/packages/frontend/src/instance.ts
+++ b/packages/frontend/src/instance.ts
@@ -43,7 +43,7 @@ export async function fetchInstance(force = false): Promise
? GetPathQuery
: Record
- : never
+ : never
: never
: never
: Def['path'] extends Path
@@ -133,9 +133,9 @@ type GetSinglePathQuery
? UnwrapReadOnly<{ [Key in keyof Query]?: string; }>
: Record
+ : Record
: Record
- : Record
- >;
+>;
type GetPathQuery> = GetSinglePathQuery;
@@ -320,11 +320,11 @@ export class Nirax extends EventEmitter {
if (route.query != null && queryString != null) {
const queryObject = [...new URLSearchParams(queryString).entries()]
- .reduce((obj, entry) => ({ ...obj, [entry[0]]: entry[1] }), {});
+ .reduce((obj, entry) => ({ ...obj, [entry[0]]: entry[1] }), {}) as Record;
for (const q in route.query) {
const as = route.query[q];
- if (queryObject[q]) {
+ if (queryObject[q] != null) {
props.set(as, safeURIDecode(queryObject[q]));
}
}
diff --git a/packages/frontend/src/navbar.ts b/packages/frontend/src/navbar.ts
index a162b3aa9e..c5b77c498a 100644
--- a/packages/frontend/src/navbar.ts
+++ b/packages/frontend/src/navbar.ts
@@ -6,6 +6,7 @@
import { computed, reactive } from 'vue';
import { ui } from '@@/js/config.js';
import { clearCache } from './utility/clear-cache.js';
+import type { ComputedRef } from 'vue';
import { $i } from '@/i.js';
import { miLocalStorage } from '@/local-storage.js';
import { openInstanceMenu, openToolsMenu } from '@/ui/_common_/common.js';
@@ -14,7 +15,17 @@ import * as os from '@/os.js';
import { i18n } from '@/i18n.js';
import { unisonReload } from '@/utility/unison-reload.js';
-export const navbarItemDef = reactive({
+export const navbarItemDef = reactive<{
+ [key: string]: {
+ title: string;
+ icon: string;
+ show?: ComputedRef;
+ indicated?: ComputedRef;
+ indicateValue?: ComputedRef;
+ to?: string;
+ action?: (ev: PointerEvent) => void;
+ };
+}>({
notifications: {
title: i18n.ts.notifications,
icon: 'ti ti-bell',
@@ -137,7 +148,7 @@ export const navbarItemDef = reactive({
ui: {
title: i18n.ts.switchUi,
icon: 'ti ti-devices',
- action: (ev: MouseEvent) => {
+ action: (ev) => {
os.popupMenu([{
text: i18n.ts.default,
active: ui === 'default' || ui === null,
diff --git a/packages/frontend/src/os.ts b/packages/frontend/src/os.ts
index 73f18bc6b5..2e2d0a814e 100644
--- a/packages/frontend/src/os.ts
+++ b/packages/frontend/src/os.ts
@@ -666,7 +666,7 @@ export function popupMenu(items: (MenuItem | null)[], anchorElement?: HTMLElemen
}));
}
-export function contextMenu(items: MenuItem[], ev: MouseEvent): Promise {
+export function contextMenu(items: MenuItem[], ev: PointerEvent): Promise {
if (
prefer.s.contextMenu === 'native' ||
(prefer.s.contextMenu === 'appWithShift' && !ev.shiftKey)
diff --git a/packages/frontend/src/pages/about.federation.vue b/packages/frontend/src/pages/about.federation.vue
index bbfb9a3b7c..c109000108 100644
--- a/packages/frontend/src/pages/about.federation.vue
+++ b/packages/frontend/src/pages/about.federation.vue
@@ -97,7 +97,7 @@ const paginator = markRaw(new Paginator('federation/instances', {
})),
}));
-function getStatus(instance) {
+function getStatus(instance: Misskey.entities.FederationInstance) {
if (instance.isSuspended) return 'Suspended';
if (instance.isBlocked) return 'Blocked';
if (instance.isSilenced) return 'Silenced';
diff --git a/packages/frontend/src/pages/admin-user.vue b/packages/frontend/src/pages/admin-user.vue
index 22e377c75d..b084eb5ab2 100644
--- a/packages/frontend/src/pages/admin-user.vue
+++ b/packages/frontend/src/pages/admin-user.vue
@@ -105,7 +105,7 @@ SPDX-License-Identifier: AGPL-3.0-only
{{ i18n.ts._role.policies }}
- {{ policy }} ... {{ info.policies[policy] }}
+ {{ policy }} ... {{ info.policies[policy as keyof typeof info.policies] }}
@@ -209,6 +209,7 @@ SPDX-License-Identifier: AGPL-3.0-only
import { computed, defineAsyncComponent, watch, ref, markRaw } from 'vue';
import * as Misskey from 'misskey-js';
import { url } from '@@/js/config.js';
+import type { ChartSrc } from '@/components/MkChart.vue';
import MkChart from '@/components/MkChart.vue';
import MkObjectView from '@/components/MkObjectView.vue';
import MkTextarea from '@/components/MkTextarea.vue';
@@ -231,7 +232,6 @@ import { ensureSignin, iAmAdmin, iAmModerator } from '@/i.js';
import MkRolePreview from '@/components/MkRolePreview.vue';
import MkPagination from '@/components/MkPagination.vue';
import { Paginator } from '@/utility/paginator.js';
-import type { ChartSrc } from '@/components/MkChart.vue';
const $i = ensureSignin();
@@ -251,7 +251,7 @@ const {
} = useMkSelect({
items: [
{ label: i18n.ts.notes, value: 'per-user-notes' },
-],
+ ],
initialValue: 'per-user-notes',
});
const user = ref(result.user);
@@ -344,7 +344,7 @@ async function resetPassword() {
}
}
-async function toggleSuspend(v) {
+async function toggleSuspend(v: boolean) {
const confirm = await os.confirm({
type: 'warning',
text: v ? i18n.ts.suspendConfirm : i18n.ts.unsuspendConfirm,
@@ -475,7 +475,7 @@ async function assignRole() {
refreshUser();
}
-async function unassignRole(role: typeof info.value.roles[number], ev: MouseEvent) {
+async function unassignRole(role: typeof info.value.roles[number], ev: PointerEvent) {
os.popupMenu([{
text: i18n.ts.unassign,
icon: 'ti ti-x',
@@ -503,7 +503,7 @@ async function createAnnouncement() {
});
}
-async function editAnnouncement(announcement) {
+async function editAnnouncement(announcement: Misskey.entities.AdminAnnouncementsListResponse[number]) {
const { dispose } = await os.popupAsyncWithDialog(import('@/components/MkUserAnnouncementEditDialog.vue').then(x => x.default), {
user: user.value,
announcement,
diff --git a/packages/frontend/src/pages/admin/RolesEditorFormula.vue b/packages/frontend/src/pages/admin/RolesEditorFormula.vue
index 9eeedd5c1d..13f66662d0 100644
--- a/packages/frontend/src/pages/admin/RolesEditorFormula.vue
+++ b/packages/frontend/src/pages/admin/RolesEditorFormula.vue
@@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only
-
+
@@ -16,7 +16,7 @@ SPDX-License-Identifier: AGPL-3.0-only
-
+
valuesItemUpdated(updated)"
- @remove="removeItem(item.id)"
+ @update:modelValue="updated => childValuesItemUpdated(updated)"
+ @remove="removeChildItem(item.id)"
/>
-
{{ i18n.ts.add }}
+
{{ i18n.ts.add }}
-
diff --git a/packages/frontend/src/pages/settings/preferences.vue b/packages/frontend/src/pages/settings/preferences.vue
index 76b84795f6..13f76fac98 100644
--- a/packages/frontend/src/pages/settings/preferences.vue
+++ b/packages/frontend/src/pages/settings/preferences.vue
@@ -269,6 +269,14 @@ SPDX-License-Identifier: AGPL-3.0-only
+
+
+
+ {{ i18n.ts.showMediaListByGridInWideArea }}
+
+
+
+
;
+ /**
+ * 画面幅が広いときはメディアリストを横並びで表示する
+ */
+ "showMediaListByGridInWideArea": string;
/**
* フォロー申請はありません
*/
--
cgit v1.2.3-freya
From b941c896aa5512240de9121a1850d55aa5f8b68b Mon Sep 17 00:00:00 2001
From: かっこかり <67428053+kakkokari-gtyih@users.noreply.github.com>
Date: Wed, 14 Jan 2026 14:02:50 +0900
Subject: refactor(frontend): MkRadiosの指定をpropsから行うように (#16597)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
* refactor(frontend): MkRadiosの指定をpropsから行うように
* spdx
* fix lint
* fix: mkradiosを動的slotsに対応させる
* fix: remove comment [ci skip]
* fix lint
* fix lint
* migrate
* rename
* fix
* fix
* fix types
* remove unused imports
* fix
* wip
---------
Co-authored-by: syuilo <4439005+syuilo@users.noreply.github.com>
---
.../src/core/entities/ReversiGameEntityService.ts | 8 +-
.../backend/src/models/json-schema/reversi-game.ts | 2 +
packages/frontend/src/components/MkDialog.vue | 3 +-
packages/frontend/src/components/MkForm.vue | 14 +-
.../src/components/MkImageEffectorFxForm.vue | 6 +-
packages/frontend/src/components/MkMenu.vue | 15 +-
packages/frontend/src/components/MkRadio.vue | 6 +-
packages/frontend/src/components/MkRadios.vue | 193 ++++++++++++---------
packages/frontend/src/components/MkSelect.vue | 2 +-
.../src/components/MkServerSetupWizard.vue | 52 +++---
.../components/MkUserAnnouncementEditDialog.vue | 26 ++-
packages/frontend/src/composables/use-mkselect.ts | 3 +-
packages/frontend/src/os.ts | 3 +-
packages/frontend/src/pages/admin/ads.vue | 24 ++-
.../frontend/src/pages/admin/announcements.vue | 26 ++-
.../frontend/src/pages/admin/bot-protection.vue | 18 +-
packages/frontend/src/pages/admin/branding.vue | 10 +-
packages/frontend/src/pages/admin/security.vue | 14 +-
packages/frontend/src/pages/admin/settings.vue | 12 +-
packages/frontend/src/pages/channels.vue | 17 +-
.../frontend/src/pages/reversi/game.setting.vue | 45 +++--
packages/frontend/src/pages/search.note.vue | 28 ++-
packages/frontend/src/pages/search.user.vue | 14 +-
packages/frontend/src/pages/settings/deck.vue | 32 ++--
.../frontend/src/pages/settings/emoji-palette.vue | 53 ++++--
packages/frontend/src/pages/settings/navbar.vue | 10 +-
.../frontend/src/pages/settings/preferences.vue | 102 +++++++----
.../src/pages/settings/statusbar.statusbar.vue | 16 +-
packages/frontend/src/preferences/def.ts | 4 +-
packages/frontend/src/store.ts | 4 +-
packages/frontend/src/types/menu.ts | 3 +-
packages/frontend/src/types/option-value.ts | 6 +
packages/frontend/src/utility/form.ts | 8 +-
packages/misskey-js/src/autogen/types.ts | 6 +-
34 files changed, 503 insertions(+), 282 deletions(-)
create mode 100644 packages/frontend/src/types/option-value.ts
(limited to 'packages/frontend/src')
diff --git a/packages/backend/src/core/entities/ReversiGameEntityService.ts b/packages/backend/src/core/entities/ReversiGameEntityService.ts
index df042e75c1..21099bad3e 100644
--- a/packages/backend/src/core/entities/ReversiGameEntityService.ts
+++ b/packages/backend/src/core/entities/ReversiGameEntityService.ts
@@ -14,6 +14,10 @@ import { bindThis } from '@/decorators.js';
import { IdService } from '@/core/IdService.js';
import { UserEntityService } from './UserEntityService.js';
+function assertBw(bw: string): bw is Packed<'ReversiGameDetailed'>['bw'] {
+ return ['random', '1', '2'].includes(bw);
+}
+
@Injectable()
export class ReversiGameEntityService {
constructor(
@@ -58,7 +62,7 @@ export class ReversiGameEntityService {
surrenderedUserId: game.surrenderedUserId,
timeoutUserId: game.timeoutUserId,
black: game.black,
- bw: game.bw,
+ bw: assertBw(game.bw) ? game.bw : 'random',
isLlotheo: game.isLlotheo,
canPutEverywhere: game.canPutEverywhere,
loopedBoard: game.loopedBoard,
@@ -116,7 +120,7 @@ export class ReversiGameEntityService {
surrenderedUserId: game.surrenderedUserId,
timeoutUserId: game.timeoutUserId,
black: game.black,
- bw: game.bw,
+ bw: assertBw(game.bw) ? game.bw : 'random',
isLlotheo: game.isLlotheo,
canPutEverywhere: game.canPutEverywhere,
loopedBoard: game.loopedBoard,
diff --git a/packages/backend/src/models/json-schema/reversi-game.ts b/packages/backend/src/models/json-schema/reversi-game.ts
index cb37200384..378ae41cb5 100644
--- a/packages/backend/src/models/json-schema/reversi-game.ts
+++ b/packages/backend/src/models/json-schema/reversi-game.ts
@@ -81,6 +81,7 @@ export const packedReversiGameLiteSchema = {
bw: {
type: 'string',
optional: false, nullable: false,
+ enum: ['random', '1', '2'],
},
noIrregularRules: {
type: 'boolean',
@@ -199,6 +200,7 @@ export const packedReversiGameDetailedSchema = {
bw: {
type: 'string',
optional: false, nullable: false,
+ enum: ['random', '1', '2'],
},
noIrregularRules: {
type: 'boolean',
diff --git a/packages/frontend/src/components/MkDialog.vue b/packages/frontend/src/components/MkDialog.vue
index bea0392d2d..4801b412f8 100644
--- a/packages/frontend/src/components/MkDialog.vue
+++ b/packages/frontend/src/components/MkDialog.vue
@@ -52,7 +52,8 @@ import MkModal from '@/components/MkModal.vue';
import MkButton from '@/components/MkButton.vue';
import MkInput from '@/components/MkInput.vue';
import MkSelect from '@/components/MkSelect.vue';
-import type { MkSelectItem, OptionValue } from '@/components/MkSelect.vue';
+import type { MkSelectItem } from '@/components/MkSelect.vue';
+import type { OptionValue } from '@/types/option-value.js';
import { useMkSelect } from '@/composables/use-mkselect.js';
import { i18n } from '@/i18n.js';
diff --git a/packages/frontend/src/components/MkForm.vue b/packages/frontend/src/components/MkForm.vue
index 3d4724e6b7..1ece0ad4c3 100644
--- a/packages/frontend/src/components/MkForm.vue
+++ b/packages/frontend/src/components/MkForm.vue
@@ -26,9 +26,8 @@ SPDX-License-Identifier: AGPL-3.0-only
({{ i18n.ts.optional }})
-
+
({{ i18n.ts.optional }})
-
({{ i18n.ts.optional }})
@@ -60,6 +59,7 @@ import MkButton from '@/components/MkButton.vue';
import MkRadios from '@/components/MkRadios.vue';
import { i18n } from '@/i18n.js';
import type { MkSelectItem } from '@/components/MkSelect.vue';
+import type { MkRadiosOption } from '@/components/MkRadios.vue';
import type { Form, EnumFormItem, RadioFormItem } from '@/utility/form.js';
const props = defineProps<{
@@ -113,7 +113,13 @@ function getMkSelectDef(def: EnumFormItem): MkSelectItem[] {
});
}
-function getRadioKey(e: RadioFormItem['options'][number]) {
- return typeof e.value === 'string' ? e.value : JSON.stringify(e.value);
+function getRadioOptionsDef(def: RadioFormItem): MkRadiosOption[] {
+ return def.options.map((v) => {
+ if (typeof v === 'string') {
+ return { value: v, label: v };
+ } else {
+ return { value: v.value, label: v.label };
+ }
+ });
}
diff --git a/packages/frontend/src/components/MkImageEffectorFxForm.vue b/packages/frontend/src/components/MkImageEffectorFxForm.vue
index 51485977a9..723b5f093e 100644
--- a/packages/frontend/src/components/MkImageEffectorFxForm.vue
+++ b/packages/frontend/src/components/MkImageEffectorFxForm.vue
@@ -28,13 +28,9 @@ SPDX-License-Identifier: AGPL-3.0-only
{{ v.label ?? k }}
{{ v.caption }}
-
+
{{ v.label ?? k }}
{{ v.caption }}
-
diff --git a/packages/frontend/src/components/MkMenu.vue b/packages/frontend/src/components/MkMenu.vue
index 22d5802596..b618dab6b2 100644
--- a/packages/frontend/src/components/MkMenu.vue
+++ b/packages/frontend/src/components/MkMenu.vue
@@ -323,9 +323,20 @@ async function showRadioOptions(item: MenuRadio, ev: MouseEvent | PointerEvent |
type: 'radioOption',
text: key,
action: () => {
- item.ref = value;
+ if ('value' in item.ref) {
+ item.ref.value = value;
+ } else {
+ // @ts-expect-error リアクティビティは保たれる
+ item.ref = value;
+ }
},
- active: computed(() => item.ref === value),
+ active: computed(() => {
+ if ('value' in item.ref) {
+ return item.ref.value === value;
+ } else {
+ return item.ref === value;
+ }
+ }),
};
});
diff --git a/packages/frontend/src/components/MkRadio.vue b/packages/frontend/src/components/MkRadio.vue
index a7d77dd118..19ba90052c 100644
--- a/packages/frontend/src/components/MkRadio.vue
+++ b/packages/frontend/src/components/MkRadio.vue
@@ -24,8 +24,9 @@ SPDX-License-Identifier: AGPL-3.0-only
-
+
+
-
diff --git a/packages/frontend/src/components/MkSelect.vue b/packages/frontend/src/components/MkSelect.vue
index f130145e36..6f6957d504 100644
--- a/packages/frontend/src/components/MkSelect.vue
+++ b/packages/frontend/src/components/MkSelect.vue
@@ -40,7 +40,7 @@ SPDX-License-Identifier: AGPL-3.0-only
-
-
diff --git a/packages/frontend/src/components/MkRadios.vue b/packages/frontend/src/components/MkRadios.vue
index 43957a0673..e2210e858e 100644
--- a/packages/frontend/src/components/MkRadios.vue
+++ b/packages/frontend/src/components/MkRadios.vue
@@ -8,15 +8,27 @@ SPDX-License-Identifier: AGPL-3.0-only
+
-
-
+
+
+
+
+
@@ -26,8 +38,9 @@ SPDX-License-Identifier: AGPL-3.0-only
-
+
+
@@ -51,8 +64,6 @@ export type MkRadiosOption = {
diff --git a/packages/frontend/src/pages/admin/ads.vue b/packages/frontend/src/pages/admin/ads.vue
index e06ea50453..0efd1a2e28 100644
--- a/packages/frontend/src/pages/admin/ads.vue
+++ b/packages/frontend/src/pages/admin/ads.vue
@@ -33,15 +33,6 @@ SPDX-License-Identifier: AGPL-3.0-only
Form
-
-
{{ i18n.ts.ratio }}
--
cgit v1.2.3-freya
From bd81a6c8adb45067bee9582f84855a60a962e92b Mon Sep 17 00:00:00 2001
From: かっこかり <67428053+kakkokari-gtyih@users.noreply.github.com>
Date: Wed, 14 Jan 2026 14:45:45 +0900
Subject: refactor(frontend): anyを除去2 (#17092)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
* wip
* fix types
* fix
---
packages/backend/src/misc/json-schema.ts | 2 +
packages/backend/src/models/Meta.ts | 6 ++-
packages/backend/src/models/json-schema/meta.ts | 23 ++++++++++-
.../backend/src/server/api/endpoints/admin/meta.ts | 3 +-
.../src/server/api/endpoints/admin/update-meta.ts | 20 ++++++++--
.../frontend/src/components/MkAchievements.vue | 6 +--
.../frontend/src/components/MkAutocomplete.vue | 17 ++++----
.../src/components/MkExtensionInstaller.vue | 9 +++--
.../frontend/src/components/MkNotification.vue | 2 +-
.../components/MkPushNotificationAllowButton.vue | 2 +-
.../src/components/MkRetentionLineChart.vue | 17 +++++---
.../src/components/MkServerSetupWizard.vue | 2 +-
.../src/components/MkWidgetSettingsDialog.vue | 5 ++-
.../src/components/global/MkCondensedLine.vue | 2 +-
packages/frontend/src/instance.ts | 6 ---
packages/frontend/src/pages/admin/branding.vue | 12 +++---
packages/frontend/src/pages/auth.form.vue | 8 +++-
packages/frontend/src/pages/flash/flash.vue | 2 +-
packages/frontend/src/pages/settings/plugin.vue | 2 +-
.../frontend/src/pages/settings/preferences.vue | 4 +-
packages/frontend/src/plugin.ts | 6 +--
packages/frontend/src/pref-migrate.ts | 9 +++--
packages/frontend/src/store.ts | 6 +--
packages/frontend/src/utility/autocomplete.ts | 45 +++++++++++++---------
packages/frontend/src/widgets/WidgetAichan.vue | 2 +-
packages/frontend/src/widgets/WidgetTimeline.vue | 10 ++---
packages/frontend/src/widgets/WidgetTrends.vue | 2 +-
packages/frontend/src/widgets/index.ts | 2 +
packages/frontend/src/widgets/widget.ts | 3 +-
packages/misskey-js/etc/misskey-js.api.md | 4 ++
packages/misskey-js/src/autogen/models.ts | 1 +
packages/misskey-js/src/autogen/types.ts | 17 ++++++--
32 files changed, 164 insertions(+), 93 deletions(-)
(limited to 'packages/frontend/src')
diff --git a/packages/backend/src/misc/json-schema.ts b/packages/backend/src/misc/json-schema.ts
index 3fa49e3cd1..cf233defd9 100644
--- a/packages/backend/src/misc/json-schema.ts
+++ b/packages/backend/src/misc/json-schema.ts
@@ -64,6 +64,7 @@ import {
packedMetaDetailedOnlySchema,
packedMetaDetailedSchema,
packedMetaLiteSchema,
+ packedMetaClientOptionsSchema,
} from '@/models/json-schema/meta.js';
import { packedUserWebhookSchema } from '@/models/json-schema/user-webhook.js';
import { packedSystemWebhookSchema } from '@/models/json-schema/system-webhook.js';
@@ -135,6 +136,7 @@ export const refs = {
MetaLite: packedMetaLiteSchema,
MetaDetailedOnly: packedMetaDetailedOnlySchema,
MetaDetailed: packedMetaDetailedSchema,
+ MetaClientOptions: packedMetaClientOptionsSchema,
UserWebhook: packedUserWebhookSchema,
SystemWebhook: packedSystemWebhookSchema,
AbuseReportNotificationRecipient: packedAbuseReportNotificationRecipientSchema,
diff --git a/packages/backend/src/models/Meta.ts b/packages/backend/src/models/Meta.ts
index a6f68194c5..620853450c 100644
--- a/packages/backend/src/models/Meta.ts
+++ b/packages/backend/src/models/Meta.ts
@@ -725,7 +725,11 @@ export class MiMeta {
@Column('jsonb', {
default: { },
})
- public clientOptions: Record;
+ public clientOptions: {
+ entrancePageStyle: 'classic' | 'simple';
+ showTimelineForVisitor: boolean;
+ showActivitiesForVisitor: boolean;
+ };
}
export type SoftwareSuspension = {
diff --git a/packages/backend/src/models/json-schema/meta.ts b/packages/backend/src/models/json-schema/meta.ts
index a0e7d490b3..0c3ec141bc 100644
--- a/packages/backend/src/models/json-schema/meta.ts
+++ b/packages/backend/src/models/json-schema/meta.ts
@@ -72,8 +72,7 @@ export const packedMetaLiteSchema = {
optional: false, nullable: true,
},
clientOptions: {
- type: 'object',
- optional: false, nullable: false,
+ ref: 'MetaClientOptions',
},
disableRegistration: {
type: 'boolean',
@@ -397,3 +396,23 @@ export const packedMetaDetailedSchema = {
},
],
} as const;
+
+export const packedMetaClientOptionsSchema = {
+ type: 'object',
+ optional: false, nullable: false,
+ properties: {
+ entrancePageStyle: {
+ type: 'string',
+ enum: ['classic', 'simple'],
+ optional: false, nullable: false,
+ },
+ showTimelineForVisitor: {
+ type: 'boolean',
+ optional: false, nullable: false,
+ },
+ showActivitiesForVisitor: {
+ type: 'boolean',
+ optional: false, nullable: false,
+ },
+ },
+} as const;
diff --git a/packages/backend/src/server/api/endpoints/admin/meta.ts b/packages/backend/src/server/api/endpoints/admin/meta.ts
index 2c7f793584..5beed3a7e8 100644
--- a/packages/backend/src/server/api/endpoints/admin/meta.ts
+++ b/packages/backend/src/server/api/endpoints/admin/meta.ts
@@ -428,8 +428,7 @@ export const meta = {
optional: false, nullable: true,
},
clientOptions: {
- type: 'object',
- optional: false, nullable: false,
+ ref: 'MetaClientOptions',
},
description: {
type: 'string',
diff --git a/packages/backend/src/server/api/endpoints/admin/update-meta.ts b/packages/backend/src/server/api/endpoints/admin/update-meta.ts
index b3c2cecc67..7a8dfc4555 100644
--- a/packages/backend/src/server/api/endpoints/admin/update-meta.ts
+++ b/packages/backend/src/server/api/endpoints/admin/update-meta.ts
@@ -3,7 +3,8 @@
* SPDX-License-Identifier: AGPL-3.0-only
*/
-import { Injectable } from '@nestjs/common';
+import { Injectable, Inject } from '@nestjs/common';
+import { DI } from '@/di-symbols.js';
import type { MiMeta } from '@/models/Meta.js';
import { ModerationLogService } from '@/core/ModerationLogService.js';
import { Endpoint } from '@/server/api/endpoint-base.js';
@@ -67,7 +68,14 @@ export const paramDef = {
description: { type: 'string', nullable: true },
defaultLightTheme: { type: 'string', nullable: true },
defaultDarkTheme: { type: 'string', nullable: true },
- clientOptions: { type: 'object', nullable: false },
+ clientOptions: {
+ type: 'object', nullable: false,
+ properties: {
+ entrancePageStyle: { type: 'string', nullable: false, enum: ['classic', 'simple'] },
+ showTimelineForVisitor: { type: 'boolean', nullable: false },
+ showActivitiesForVisitor: { type: 'boolean', nullable: false },
+ },
+ },
cacheRemoteFiles: { type: 'boolean' },
cacheRemoteSensitiveFiles: { type: 'boolean' },
emailRequiredForSignup: { type: 'boolean' },
@@ -217,6 +225,9 @@ export const paramDef = {
@Injectable()
export default class extends Endpoint { // eslint-disable-line import/no-default-export
constructor(
+ @Inject(DI.meta)
+ private serverSettings: MiMeta,
+
private metaService: MetaService,
private moderationLogService: ModerationLogService,
) {
@@ -329,7 +340,10 @@ export default class extends Endpoint { // eslint-
}
if (ps.clientOptions !== undefined) {
- set.clientOptions = ps.clientOptions;
+ set.clientOptions = {
+ ...serverSettings.clientOptions,
+ ...ps.clientOptions,
+ };
}
if (ps.cacheRemoteFiles !== undefined) {
diff --git a/packages/frontend/src/components/MkAchievements.vue b/packages/frontend/src/components/MkAchievements.vue
index d0e138c229..fe6415eabb 100644
--- a/packages/frontend/src/components/MkAchievements.vue
+++ b/packages/frontend/src/components/MkAchievements.vue
@@ -23,13 +23,13 @@ SPDX-License-Identifier: AGPL-3.0-only
- {{ (i18n.ts._achievements._types as any)['_' + achievement.name].title }}
+ {{ i18n.ts._achievements._types[`_${achievement.name}`].title }}
-
{{ withDescription ? (i18n.ts._achievements._types as any)['_' + achievement.name].description : '???' }}
-
{{ (i18n.ts._achievements._types as any)['_' + achievement.name].flavor }}
+
{{ withDescription ? i18n.ts._achievements._types[`_${achievement.name}`].description : '???' }}
+
{{ (i18n.ts._achievements._types[`_${achievement.name}`] as { flavor: string; }).flavor }}