summaryrefslogtreecommitdiff
path: root/packages/frontend/src/components
diff options
context:
space:
mode:
authorsyuilo <4439005+syuilo@users.noreply.github.com>2026-01-09 22:06:40 +0900
committerGitHub <noreply@github.com>2026-01-09 22:06:40 +0900
commit41592eafb363e3c62ab2d3e5f41b38d7d083d3fb (patch)
tree8f69243a5482ad4161eb28b69769684a221aa05c /packages/frontend/src/components
parentfix(frontend): popupのemit型が正しく利用できるように修正 (#16... (diff)
downloadmisskey-41592eafb363e3c62ab2d3e5f41b38d7d083d3fb.tar.gz
misskey-41592eafb363e3c62ab2d3e5f41b38d7d083d3fb.tar.bz2
misskey-41592eafb363e3c62ab2d3e5f41b38d7d083d3fb.zip
refactor: make noImplicitAny true (#17083)
* wip * Update emojis.emoji.vue * wip * wip * wip * wip * wip * wip * wip * wip * wip * wip * wip * wip * Update manager.ts * wip * wip * wip * wip * wip * wip * wip * wip * wip * wip * wip * wip * wip * wip * wip * wip * wip * wip * wip * wip * wip * wip * wip * wip * wip * wip * wip * wip * Update analytics.ts
Diffstat (limited to 'packages/frontend/src/components')
-rw-r--r--packages/frontend/src/components/MkAbuseReport.vue4
-rw-r--r--packages/frontend/src/components/MkAchievements.vue7
-rw-r--r--packages/frontend/src/components/MkAsUi.vue4
-rw-r--r--packages/frontend/src/components/MkAuthConfirm.vue2
-rw-r--r--packages/frontend/src/components/MkAutocomplete.stories.impl.ts7
-rw-r--r--packages/frontend/src/components/MkAutocomplete.vue6
-rw-r--r--packages/frontend/src/components/MkButton.vue6
-rw-r--r--packages/frontend/src/components/MkCaptcha.vue4
-rw-r--r--packages/frontend/src/components/MkChannelList.vue2
-rw-r--r--packages/frontend/src/components/MkChart.vue10
-rw-r--r--packages/frontend/src/components/MkClickerGame.vue4
-rw-r--r--packages/frontend/src/components/MkCodeEditor.vue22
-rw-r--r--packages/frontend/src/components/MkContextMenu.stories.impl.ts6
-rw-r--r--packages/frontend/src/components/MkContextMenu.vue8
-rw-r--r--packages/frontend/src/components/MkDrive.file.vue2
-rw-r--r--packages/frontend/src/components/MkDrive.folder.vue4
-rw-r--r--packages/frontend/src/components/MkDrive.vue12
-rw-r--r--packages/frontend/src/components/MkEmojiPicker.section.vue8
-rw-r--r--packages/frontend/src/components/MkEmojiPicker.vue4
-rw-r--r--packages/frontend/src/components/MkExtensionInstaller.vue2
-rw-r--r--packages/frontend/src/components/MkFolder.vue2
-rw-r--r--packages/frontend/src/components/MkForm.file.vue2
-rw-r--r--packages/frontend/src/components/MkHeatmap.vue5
-rw-r--r--packages/frontend/src/components/MkImageEffectorDialog.vue4
-rw-r--r--packages/frontend/src/components/MkInput.vue7
-rw-r--r--packages/frontend/src/components/MkInstanceCardMini.vue2
-rw-r--r--packages/frontend/src/components/MkInstanceStats.vue32
-rw-r--r--packages/frontend/src/components/MkLaunchPad.vue4
-rw-r--r--packages/frontend/src/components/MkMediaImage.vue4
-rw-r--r--packages/frontend/src/components/MkMediaVideo.vue2
-rw-r--r--packages/frontend/src/components/MkMenu.vue6
-rw-r--r--packages/frontend/src/components/MkModal.vue4
-rw-r--r--packages/frontend/src/components/MkNote.vue2
-rw-r--r--packages/frontend/src/components/MkNoteDetailed.vue12
-rw-r--r--packages/frontend/src/components/MkNotification.vue2
-rw-r--r--packages/frontend/src/components/MkObjectView.value.vue2
-rw-r--r--packages/frontend/src/components/MkPagination.vue2
-rw-r--r--packages/frontend/src/components/MkPollEditor.vue4
-rw-r--r--packages/frontend/src/components/MkPostForm.vue121
-rw-r--r--packages/frontend/src/components/MkPostFormAttaches.vue6
-rw-r--r--packages/frontend/src/components/MkPreferenceContainer.vue2
-rw-r--r--packages/frontend/src/components/MkPreview.vue2
-rw-r--r--packages/frontend/src/components/MkReactionsViewer.reaction.vue2
-rw-r--r--packages/frontend/src/components/MkReactionsViewer.vue6
-rw-r--r--packages/frontend/src/components/MkRetentionHeatmap.vue4
-rw-r--r--packages/frontend/src/components/MkRoleSelectDialog.vue6
-rw-r--r--packages/frontend/src/components/MkServerSetupWizardDialog.vue2
-rw-r--r--packages/frontend/src/components/MkSignin.input.vue2
-rw-r--r--packages/frontend/src/components/MkSortOrderEditor.vue6
-rw-r--r--packages/frontend/src/components/MkSpot.vue4
-rw-r--r--packages/frontend/src/components/MkStreamingNotesTimeline.vue7
-rw-r--r--packages/frontend/src/components/MkStreamingNotificationsTimeline.vue4
-rw-r--r--packages/frontend/src/components/MkSuperMenu.vue2
-rw-r--r--packages/frontend/src/components/MkSystemWebhookEditor.vue2
-rw-r--r--packages/frontend/src/components/MkTabs.vue6
-rw-r--r--packages/frontend/src/components/MkTagItem.vue4
-rw-r--r--packages/frontend/src/components/MkTextarea.vue20
-rw-r--r--packages/frontend/src/components/MkTokenGenerateWindow.vue16
-rw-r--r--packages/frontend/src/components/MkTooltip.vue4
-rw-r--r--packages/frontend/src/components/MkTutorialDialog.Note.vue4
-rw-r--r--packages/frontend/src/components/MkUploaderDialog.vue6
-rw-r--r--packages/frontend/src/components/MkUploaderItems.vue8
-rw-r--r--packages/frontend/src/components/MkUserList.vue2
-rw-r--r--packages/frontend/src/components/MkUserPopup.vue2
-rw-r--r--packages/frontend/src/components/MkUserSetupDialog.Profile.vue2
-rw-r--r--packages/frontend/src/components/MkVisitorDashboard.ActiveUsersChart.vue2
-rw-r--r--packages/frontend/src/components/MkVisitorDashboard.vue2
-rw-r--r--packages/frontend/src/components/MkWaitingDialog.vue4
-rw-r--r--packages/frontend/src/components/MkWatermarkEditorDialog.Layer.vue2
-rw-r--r--packages/frontend/src/components/MkWatermarkEditorDialog.vue2
-rw-r--r--packages/frontend/src/components/MkWidgetSettingsDialog.vue2
-rw-r--r--packages/frontend/src/components/MkWidgets.vue36
-rw-r--r--packages/frontend/src/components/MkWindow.vue24
-rw-r--r--packages/frontend/src/components/global/I18n.vue2
-rw-r--r--packages/frontend/src/components/global/MkA.vue4
-rw-r--r--packages/frontend/src/components/global/MkAvatar.vue4
-rw-r--r--packages/frontend/src/components/global/MkCondensedLine.vue12
-rw-r--r--packages/frontend/src/components/global/MkCustomEmoji.vue2
-rw-r--r--packages/frontend/src/components/global/MkEmoji.vue2
-rw-r--r--packages/frontend/src/components/global/MkMfm.ts2
-rw-r--r--packages/frontend/src/components/global/MkPageHeader.tabs.vue8
-rw-r--r--packages/frontend/src/components/global/MkPageHeader.vue5
-rw-r--r--packages/frontend/src/components/global/MkTip.vue2
-rw-r--r--packages/frontend/src/components/grid/MkDataCell.vue2
-rw-r--r--packages/frontend/src/components/grid/MkGrid.vue2
85 files changed, 311 insertions, 284 deletions
diff --git a/packages/frontend/src/components/MkAbuseReport.vue b/packages/frontend/src/components/MkAbuseReport.vue
index c7252e7c98..cbc5b27fca 100644
--- a/packages/frontend/src/components/MkAbuseReport.vue
+++ b/packages/frontend/src/components/MkAbuseReport.vue
@@ -115,7 +115,7 @@ watch(moderationNote, async () => {
});
});
-function resolve(resolvedAs) {
+function resolve(resolvedAs: 'accept' | 'reject' | null) {
os.apiWithDialog('admin/resolve-abuse-user-report', {
reportId: props.report.id,
resolvedAs,
@@ -132,7 +132,7 @@ function forward() {
});
}
-function showMenu(ev: MouseEvent) {
+function showMenu(ev: PointerEvent) {
os.popupMenu([{
icon: 'ti ti-hash',
text: 'Copy ID',
diff --git a/packages/frontend/src/components/MkAchievements.vue b/packages/frontend/src/components/MkAchievements.vue
index c786e9fe9f..d0e138c229 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
</div>
<div :class="$style.body">
<div :class="$style.header">
- <span :class="$style.title">{{ i18n.ts._achievements._types['_' + achievement.name].title }}</span>
+ <span :class="$style.title">{{ (i18n.ts._achievements._types as any)['_' + achievement.name].title }}</span>
<span :class="$style.time">
<time v-tooltip="new Date(achievement.unlockedAt).toLocaleString()">{{ new Date(achievement.unlockedAt).getFullYear() }}/{{ new Date(achievement.unlockedAt).getMonth() + 1 }}/{{ new Date(achievement.unlockedAt).getDate() }}</time>
</span>
</div>
- <div :class="$style.description">{{ withDescription ? i18n.ts._achievements._types['_' + achievement.name].description : '???' }}</div>
- <div v-if="i18n.ts._achievements._types['_' + achievement.name].flavor && withDescription" :class="$style.flavor">{{ i18n.ts._achievements._types['_' + achievement.name].flavor }}</div>
+ <div :class="$style.description">{{ withDescription ? (i18n.ts._achievements._types as any)['_' + achievement.name].description : '???' }}</div>
+ <div v-if="(i18n.ts._achievements._types as any)['_' + achievement.name].flavor && withDescription" :class="$style.flavor">{{ (i18n.ts._achievements._types as any)['_' + achievement.name].flavor }}</div>
</div>
</div>
<template v-if="withLocked">
@@ -54,7 +54,6 @@ SPDX-License-Identifier: AGPL-3.0-only
<script lang="ts" setup>
import * as Misskey from 'misskey-js';
import { onMounted, ref, computed } from 'vue';
-import * as os from '@/os.js';
import { misskeyApi } from '@/utility/misskey-api.js';
import { i18n } from '@/i18n.js';
import { ACHIEVEMENT_TYPES, ACHIEVEMENT_BADGES, claimAchievement } from '@/utility/achievements.js';
diff --git a/packages/frontend/src/components/MkAsUi.vue b/packages/frontend/src/components/MkAsUi.vue
index a3b6112629..d44e7724b3 100644
--- a/packages/frontend/src/components/MkAsUi.vue
+++ b/packages/frontend/src/components/MkAsUi.vue
@@ -64,13 +64,13 @@ SPDX-License-Identifier: AGPL-3.0-only
<script lang="ts" setup>
import { ref, computed } from 'vue';
import type { Ref } from 'vue';
+import type { AsUiComponent, AsUiRoot, AsUiPostFormButton } from '@/aiscript/ui.js';
import * as os from '@/os.js';
import MkButton from '@/components/MkButton.vue';
import MkInput from '@/components/MkInput.vue';
import MkSwitch from '@/components/MkSwitch.vue';
import MkTextarea from '@/components/MkTextarea.vue';
import MkSelect from '@/components/MkSelect.vue';
-import type { AsUiComponent, AsUiRoot, AsUiPostFormButton } from '@/aiscript/ui.js';
import MkFolder from '@/components/MkFolder.vue';
import MkPostForm from '@/components/MkPostForm.vue';
import { useMkSelect } from '@/composables/use-mkselect.js';
@@ -144,7 +144,7 @@ const {
initialValue: (c.type === 'select' && 'default' in c && typeof c.default !== 'boolean') ? c.default ?? null : null,
});
-function onSelectUpdate(v) {
+function onSelectUpdate(v: string | null) {
valueForSelect.value = v;
if ('onChange' in c && c.onChange) {
c.onChange(v as never);
diff --git a/packages/frontend/src/components/MkAuthConfirm.vue b/packages/frontend/src/components/MkAuthConfirm.vue
index 8744b50926..b1a29660ad 100644
--- a/packages/frontend/src/components/MkAuthConfirm.vue
+++ b/packages/frontend/src/components/MkAuthConfirm.vue
@@ -183,7 +183,7 @@ async function init() {
init();
-function clickAddAccount(ev: MouseEvent) {
+function clickAddAccount(ev: PointerEvent) {
selectedUser.value = null;
os.popupMenu([{
diff --git a/packages/frontend/src/components/MkAutocomplete.stories.impl.ts b/packages/frontend/src/components/MkAutocomplete.stories.impl.ts
index 15aab8daed..9104650752 100644
--- a/packages/frontend/src/components/MkAutocomplete.stories.impl.ts
+++ b/packages/frontend/src/components/MkAutocomplete.stories.impl.ts
@@ -3,15 +3,14 @@
* SPDX-License-Identifier: AGPL-3.0-only
*/
-/* eslint-disable @typescript-eslint/explicit-function-return-type */
import { action } from 'storybook/actions';
import { expect, userEvent, waitFor, within } from '@storybook/test';
-import type { StoryObj } from '@storybook/vue3';
import { HttpResponse, http } from 'msw';
import { userDetailed } from '../../.storybook/fakes.js';
import { commonHandlers } from '../../.storybook/mocks.js';
import MkAutocomplete from './MkAutocomplete.vue';
import MkInput from './MkInput.vue';
+import type { StoryObj } from '@storybook/vue3';
import { tick } from '@/utility/test-utils.js';
const common = {
render(args) {
@@ -81,7 +80,7 @@ export const User = {
...common.args,
type: 'user',
},
- async play({ canvasElement }) {
+ async play({ canvasElement }: { canvasElement: HTMLElement }) {
const canvas = within(canvasElement);
const input = canvas.getByRole('combobox');
await waitFor(() => userEvent.hover(input));
@@ -114,7 +113,7 @@ export const Hashtag = {
...common.args,
type: 'hashtag',
},
- async play({ canvasElement }) {
+ async play({ canvasElement }: { canvasElement: HTMLElement }) {
const canvas = within(canvasElement);
const input = canvas.getByRole('combobox');
await waitFor(() => userEvent.hover(input));
diff --git a/packages/frontend/src/components/MkAutocomplete.vue b/packages/frontend/src/components/MkAutocomplete.vue
index cf5d95e11b..5e860351af 100644
--- a/packages/frontend/src/components/MkAutocomplete.vue
+++ b/packages/frontend/src/components/MkAutocomplete.vue
@@ -50,7 +50,7 @@ import { emojilist, getEmojiName } from '@@/js/emojilist.js';
import { char2twemojiFilePath, char2fluentEmojiFilePath } from '@@/js/emoji-base.js';
import { MFM_TAGS, MFM_PARAMS } from '@@/js/const.js';
import type { EmojiDef } from '@/utility/search-emoji.js';
-import contains from '@/utility/contains.js';
+import { elementContains } from '@/utility/element-contains.js';
import { acct } from '@/filters/user.js';
import * as os from '@/os.js';
import { misskeyApi } from '@/utility/misskey-api.js';
@@ -310,8 +310,8 @@ function exec() {
}
}
-function onMousedown(event: Event) {
- if (!contains(rootEl.value, event.target) && (rootEl.value !== event.target)) props.close();
+function onMousedown(event: MouseEvent) {
+ if (!elementContains(rootEl.value, event.target as Element) && (rootEl.value !== event.target)) props.close();
}
function onKeydown(event: KeyboardEvent) {
diff --git a/packages/frontend/src/components/MkButton.vue b/packages/frontend/src/components/MkButton.vue
index b729128a21..854ed31ed5 100644
--- a/packages/frontend/src/components/MkButton.vue
+++ b/packages/frontend/src/components/MkButton.vue
@@ -63,7 +63,7 @@ const props = defineProps<{
}>();
const emit = defineEmits<{
- (ev: 'click', payload: MouseEvent): void;
+ (ev: 'click', payload: PointerEvent): void;
}>();
const el = useTemplateRef('el');
@@ -77,11 +77,11 @@ onMounted(() => {
}
});
-function distance(p, q): number {
+function distance(p: { x: number; y: number }, q: { x: number; y: number }): number {
return Math.hypot(p.x - q.x, p.y - q.y);
}
-function calcCircleScale(boxW, boxH, circleCenterX, circleCenterY): number {
+function calcCircleScale(boxW: number, boxH: number, circleCenterX: number, circleCenterY: number): number {
const origin = { x: circleCenterX, y: circleCenterY };
const dist1 = distance({ x: 0, y: 0 }, origin);
const dist2 = distance({ x: boxW, y: 0 }, origin);
diff --git a/packages/frontend/src/components/MkCaptcha.vue b/packages/frontend/src/components/MkCaptcha.vue
index 30940a34a9..6e4a8c13d2 100644
--- a/packages/frontend/src/components/MkCaptcha.vue
+++ b/packages/frontend/src/components/MkCaptcha.vue
@@ -84,7 +84,7 @@ const variable = computed(() => {
}
});
-const loaded = !!window[variable.value];
+const loaded = !!(window as any)[variable.value];
const src = computed(() => {
switch (props.provider) {
@@ -98,7 +98,7 @@ const src = computed(() => {
const scriptId = computed(() => `script-${props.provider}`);
-const captcha = computed<Captcha>(() => window[variable.value] || {} as unknown as Captcha);
+const captcha = computed<Captcha>(() => (window as any)[variable.value] ?? {} as unknown as Captcha);
watch(() => [props.instanceUrl, props.sitekey, props.secretKey], async () => {
// 変更があったときはリフレッシュと再レンダリングをしておかないと、変更後の値で再検証が出来ない
diff --git a/packages/frontend/src/components/MkChannelList.vue b/packages/frontend/src/components/MkChannelList.vue
index 23bb32c6b9..af89ec8252 100644
--- a/packages/frontend/src/components/MkChannelList.vue
+++ b/packages/frontend/src/components/MkChannelList.vue
@@ -24,6 +24,6 @@ const props = withDefaults(defineProps<{
noGap?: boolean;
extractor?: ExtractorFunction<P, Misskey.entities.Channel>;
}>(), {
- extractor: (item) => item,
+ extractor: (item: any) => item as Misskey.entities.Channel,
});
</script>
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<typeof chartData> => {
};
};
-const fetchNotesChart = async (type: string): Promise<typeof chartData> => {
+const fetchNotesChart = async (type: 'local' | 'remote' | 'combined'): Promise<typeof chartData> => {
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
<script lang="ts" setup>
import { computed, onMounted, onUnmounted, ref } from 'vue';
+import { useInterval } from '@@/js/use-interval.js';
import MkPlusOneEffect from '@/components/MkPlusOneEffect.vue';
import * as os from '@/os.js';
-import { useInterval } from '@@/js/use-interval.js';
import * as game from '@/utility/clicker-game.js';
import number from '@/filters/number.js';
import { claimAchievement } from '@/utility/achievements.js';
@@ -32,7 +32,7 @@ const cookies = computed(() => saveData.value?.cookies);
const cps = ref(0);
const prevCookies = ref(0);
-function onClick(ev: MouseEvent) {
+function onClick(ev: PointerEvent) {
const x = ev.clientX;
const y = ev.clientY;
const { dispose } = os.popup(MkPlusOneEffect, { x, y }, {
diff --git a/packages/frontend/src/components/MkCodeEditor.vue b/packages/frontend/src/components/MkCodeEditor.vue
index bdb2ba6a44..dda5a14716 100644
--- a/packages/frontend/src/components/MkCodeEditor.vue
+++ b/packages/frontend/src/components/MkCodeEditor.vue
@@ -40,7 +40,7 @@ import XCode from '@/components/MkCode.core.vue';
const props = withDefaults(defineProps<{
modelValue: string | null;
- lang: string;
+ lang?: string;
required?: boolean;
readonly?: boolean;
disabled?: boolean;
@@ -51,7 +51,7 @@ const props = withDefaults(defineProps<{
});
const emit = defineEmits<{
- (ev: 'change', _ev: KeyboardEvent): void;
+ (ev: 'change', _ev: InputEvent): void;
(ev: 'keydown', _ev: KeyboardEvent): void;
(ev: 'enter'): void;
(ev: 'update:modelValue', value: string): void;
@@ -63,15 +63,17 @@ const focused = ref(false);
const changed = ref(false);
const inputEl = useTemplateRef('inputEl');
-const focus = () => inputEl.value?.focus();
+function focus() {
+ inputEl.value?.focus();
+}
-const onInput = (ev) => {
- v.value = ev.target?.value ?? v.value;
+function onInput(ev: InputEvent) {
+ v.value = (inputEl.value?.value) ?? '';
changed.value = true;
emit('change', ev);
-};
+}
-const onKeydown = (ev: KeyboardEvent) => {
+function onKeydown(ev: KeyboardEvent) {
if (ev.isComposing || ev.key === 'Process' || ev.keyCode === 229) return;
emit('keydown', ev);
@@ -102,12 +104,12 @@ const onKeydown = (ev: KeyboardEvent) => {
});
ev.preventDefault();
}
-};
+}
-const updated = () => {
+function updated() {
changed.value = false;
emit('update:modelValue', v.value);
-};
+}
const debouncedUpdated = debounce(1000, updated);
diff --git a/packages/frontend/src/components/MkContextMenu.stories.impl.ts b/packages/frontend/src/components/MkContextMenu.stories.impl.ts
index 7a5e36131b..fc9fd9bc49 100644
--- a/packages/frontend/src/components/MkContextMenu.stories.impl.ts
+++ b/packages/frontend/src/components/MkContextMenu.stories.impl.ts
@@ -3,11 +3,9 @@
* SPDX-License-Identifier: AGPL-3.0-only
*/
-/* eslint-disable @typescript-eslint/explicit-function-return-type */
-/* eslint-disable import/no-default-export */
-import type { StoryObj } from '@storybook/vue3';
import { userEvent, within } from '@storybook/test';
import MkContextMenu from './MkContextMenu.vue';
+import type { StoryObj } from '@storybook/vue3';
import * as os from '@/os.js';
export const Empty = {
render(args) {
@@ -25,7 +23,7 @@ export const Empty = {
},
},
methods: {
- onContextmenu(ev: MouseEvent) {
+ onContextmenu(ev: PointerEvent) {
os.contextMenu(args.items, ev);
},
},
diff --git a/packages/frontend/src/components/MkContextMenu.vue b/packages/frontend/src/components/MkContextMenu.vue
index 9c6397a72c..6678c8fb91 100644
--- a/packages/frontend/src/components/MkContextMenu.vue
+++ b/packages/frontend/src/components/MkContextMenu.vue
@@ -21,13 +21,13 @@ SPDX-License-Identifier: AGPL-3.0-only
import { onMounted, onBeforeUnmount, useTemplateRef, ref } from 'vue';
import MkMenu from './MkMenu.vue';
import type { MenuItem } from '@/types/menu.js';
-import contains from '@/utility/contains.js';
+import { elementContains } from '@/utility/element-contains.js';
import { prefer } from '@/preferences.js';
import * as os from '@/os.js';
const props = defineProps<{
items: MenuItem[];
- ev: MouseEvent;
+ ev: PointerEvent;
}>();
const emit = defineEmits<{
@@ -75,8 +75,8 @@ onBeforeUnmount(() => {
window.document.body.removeEventListener('mousedown', onMousedown);
});
-function onMousedown(evt: Event) {
- if (!contains(rootEl.value, evt.target) && (rootEl.value !== evt.target)) emit('closed');
+function onMousedown(evt: MouseEvent) {
+ if (!elementContains(rootEl.value, evt.target as Element) && (rootEl.value !== evt.target)) emit('closed');
}
</script>
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 }}</MkButton>
+ >
+ {{ i18n.ts.loadMore }}
+ </MkButton>
<div v-if="filesPaginator.items.value.length == 0 && foldersPaginator.items.value.length == 0 && !fetching" :class="$style.empty">
<div v-if="draghover">{{ i18n.ts.dropHereToUpload }}</div>
@@ -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
<script lang="ts" setup>
import { ref, computed } from 'vue';
-import type { Ref } from 'vue';
import { getEmojiName } from '@@/js/emojilist.js';
+import type { Ref } from 'vue';
import type { CustomEmojiFolderTree } from '@@/js/emojilist.js';
import { i18n } from '@/i18n.js';
import { customEmojis } from '@/custom-emojis.js';
@@ -78,7 +78,7 @@ const props = defineProps<{
}>();
const emit = defineEmits<{
- (ev: 'chosen', v: string, event: MouseEvent): void;
+ (ev: 'chosen', v: string, event: PointerEvent): void;
}>();
const emojis = computed(() => Array.isArray(props.emojis) ? props.emojis : props.emojis.value);
@@ -86,13 +86,13 @@ const emojis = computed(() => Array.isArray(props.emojis) ? props.emojis : props
const shown = ref(!!props.initialShown);
/** @see MkEmojiPicker.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 nestedChosen(emoji: string, ev: MouseEvent) {
+function nestedChosen(emoji: string, ev: PointerEvent) {
emit('chosen', emoji, ev);
}
</script>
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
<template #key>{{ i18n.ts.permission }}</template>
<template #value>
<ul v-if="extension.meta.permissions && extension.meta.permissions.length > 0" :class="$style.extInstallerKVList">
- <li v-for="permission in extension.meta.permissions" :key="permission">{{ i18n.ts._permissions[permission] }}</li>
+ <li v-for="permission in extension.meta.permissions" :key="permission">{{ (i18n.ts._permissions as any)[permission] ?? permission }}</li>
</ul>
<template v-else>{{ i18n.ts.none }}</template>
</template>
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<T>): 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';
}
</script>
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
<script lang="ts" setup>
import { onMounted, computed, useTemplateRef } from 'vue';
import { Chart } from 'chart.js';
-import MkSelect from '@/components/MkSelect.vue';
import type { MkSelectItem, ItemOption } from '@/components/MkSelect.vue';
-import MkChart from '@/components/MkChart.vue';
import type { ChartSrc } from '@/components/MkChart.vue';
+import MkSelect from '@/components/MkSelect.vue';
+import MkChart from '@/components/MkChart.vue';
import { useChartTooltip } from '@/composables/use-chart-tooltip.js';
import { $i } from '@/i.js';
import * as os from '@/os.js';
@@ -172,7 +172,14 @@ const { handler: externalTooltipHandler2 } = useChartTooltip({
position: 'middle',
});
-function createDoughnut(chartEl, tooltip, data) {
+type ChartData = {
+ name: string,
+ color: string,
+ value: number,
+ onClick?: () => void,
+}[];
+
+function createDoughnut(chartEl: HTMLCanvasElement, tooltip: ReturnType<typeof useChartTooltip>['handler'], data: ChartData) {
const chartInstance = new Chart(chartEl, {
type: 'doughnut',
data: {
@@ -198,8 +205,8 @@ function createDoughnut(chartEl, tooltip, data) {
onClick: (ev) => {
if (ev.native == null) return;
const hit = chartInstance.getElementsAtEventForMode(ev.native, 'nearest', { intersect: true }, false)[0];
- if (hit && data[hit.index].onClick) {
- data[hit.index].onClick();
+ if (hit != null) {
+ data[hit.index].onClick?.();
}
},
plugins: {
@@ -223,16 +230,9 @@ function createDoughnut(chartEl, tooltip, data) {
onMounted(() => {
misskeyApiGet('federation/stats', { limit: 30 }).then(fedStats => {
- type ChartData = {
- name: string,
- color: string | null,
- value: number,
- onClick?: () => void,
- }[];
-
const subs: ChartData = fedStats.topSubInstances.map(x => ({
name: x.host,
- color: x.themeColor,
+ color: x.themeColor ?? '#888888',
value: x.followersCount,
onClick: () => {
os.pageWindow(`/instance-info/${x.host}`);
@@ -245,11 +245,11 @@ onMounted(() => {
value: fedStats.otherFollowersCount,
});
- createDoughnut(subDoughnutEl.value, externalTooltipHandler1, subs);
+ if (subDoughnutEl.value != null) createDoughnut(subDoughnutEl.value, externalTooltipHandler1, subs);
const pubs: ChartData = fedStats.topPubInstances.map(x => ({
name: x.host,
- color: x.themeColor,
+ color: x.themeColor ?? '#888888',
value: x.followingCount,
onClick: () => {
os.pageWindow(`/instance-info/${x.host}`);
@@ -262,7 +262,7 @@ onMounted(() => {
value: fedStats.otherFollowingCount,
});
- createDoughnut(pubDoughnutEl.value, externalTooltipHandler2, pubs);
+ if (pubDoughnutEl.value != null) createDoughnut(pubDoughnutEl.value, externalTooltipHandler2, pubs);
});
});
</script>
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
<div class="szkkfdyq _popup _shadow" :class="{ asDrawer: type === 'drawer' }" :style="{ maxHeight: maxHeight ? maxHeight + 'px' : '' }">
<div class="main">
<template v-for="item in items" :key="item.text">
- <button v-if="item.action" v-click-anime class="_button item" @click="$event => { item.action($event); close(); }">
+ <button v-if="item.action != null" v-click-anime class="_button item" @click="$event => { item.action!($event); close(); }">
<i class="icon" :class="item.icon"></i>
<div class="text">{{ item.text }}</div>
<span v-if="item.indicate && item.indicateValue" class="_indicateCounter indicatorWithValue">{{ item.indicateValue }}</span>
<span v-else-if="item.indicate" class="indicator _blink"><i class="_indicatorCircle"></i></span>
</button>
- <MkA v-else v-click-anime :to="item.to" class="item" @click.passive="close()">
+ <MkA v-else-if="item.to != null" v-click-anime :to="item.to" class="item" @click.passive="close()">
<i class="icon" :class="item.icon"></i>
<div class="text">{{ item.text }}</div>
<span v-if="item.indicate && item.indicateValue" class="_indicateCounter indicatorWithValue">{{ item.indicateValue }}</span>
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<MenuRadioOption>(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
</div>
<MkNoteSub v-for="note in conversation" :key="note.id" :class="$style.replyToMore" :note="note"/>
</div>
- <MkNoteSub v-if="appearNote.replyId" :note="appearNote.reply" :class="$style.replyTo"/>
+ <MkNoteSub v-if="appearNote.replyId" :note="appearNote?.reply ?? null" :class="$style.replyTo"/>
<div v-if="isRenote" :class="$style.renote">
<MkAvatar :class="$style.renoteAvatar" :user="note.user" link preview/>
<i class="ti ti-repeat" style="margin-right: 4px;"></i>
@@ -111,7 +111,7 @@ SPDX-License-Identifier: AGPL-3.0-only
</div>
</div>
<div v-if="appearNote.files && appearNote.files.length > 0">
- <MkMediaList ref="galleryEl" :mediaList="appearNote.files"/>
+ <MkMediaList :mediaList="appearNote.files"/>
</div>
<MkPoll
v-if="appearNote.poll"
@@ -144,7 +144,6 @@ SPDX-License-Identifier: AGPL-3.0-only
:myReaction="$appearNote.myReaction"
:noteId="appearNote.id"
:maxNumber="16"
- @mockUpdateMyReaction="emitUpdReaction"
/>
<button class="_button" :class="$style.noteFooterButton" @click="reply()">
<i class="ti ti-arrow-back-up"></i>
@@ -233,7 +232,7 @@ SPDX-License-Identifier: AGPL-3.0-only
</template>
<script lang="ts" setup>
-import { computed, inject, markRaw, onMounted, provide, ref, useTemplateRef } from 'vue';
+import { computed, inject, markRaw, provide, ref, useTemplateRef } from 'vue';
import * as mfm from 'mfm-js';
import * as Misskey from 'misskey-js';
import { isLink } from '@@/js/is-link.js';
@@ -324,7 +323,6 @@ const renoteButton = useTemplateRef('renoteButton');
const renoteTime = useTemplateRef('renoteTime');
const reactButton = useTemplateRef('reactButton');
const clipButton = useTemplateRef('clipButton');
-const galleryEl = useTemplateRef('galleryEl');
const isMyRenote = $i && ($i.id === note.userId);
const showContent = ref(false);
const isDeleted = ref(false);
@@ -358,7 +356,7 @@ const keymap = {
if (!prefer.s.showClipButtonInNoteFooter) return;
clip();
},
- 'o': () => galleryEl.value?.openGallery(),
+ //'o': () => galleryEl.value?.openGallery(),
'v|enter': () => {
if (appearNote.cw != null) {
showContent.value = !showContent.value;
@@ -553,7 +551,7 @@ function toggleReact() {
}
}
-function onContextmenu(ev: MouseEvent): void {
+function onContextmenu(ev: PointerEvent): void {
if (ev.target && isLink(ev.target as HTMLElement)) return;
if (window.getSelection()?.toString() !== '') return;
diff --git a/packages/frontend/src/components/MkNotification.vue b/packages/frontend/src/components/MkNotification.vue
index 45a74e3f02..143ca7fd2f 100644
--- a/packages/frontend/src/components/MkNotification.vue
+++ b/packages/frontend/src/components/MkNotification.vue
@@ -121,7 +121,7 @@ SPDX-License-Identifier: AGPL-3.0-only
{{ notification.invitation.room.name }}
</div>
<MkA v-else-if="notification.type === 'achievementEarned'" :class="$style.text" to="/my/achievements">
- {{ i18n.ts._achievements._types['_' + notification.achievement].title }}
+ {{ (i18n.ts._achievements._types as any)['_' + notification.achievement].title }}
</MkA>
<MkA v-else-if="notification.type === 'exportCompleted'" :class="$style.text" :to="`/my/drive/file/${notification.fileId}`">
{{ i18n.ts.showFile }}
diff --git a/packages/frontend/src/components/MkObjectView.value.vue b/packages/frontend/src/components/MkObjectView.value.vue
index 7fa8c23c6c..abc4407d2a 100644
--- a/packages/frontend/src/components/MkObjectView.value.vue
+++ b/packages/frontend/src/components/MkObjectView.value.vue
@@ -42,7 +42,7 @@ const props = defineProps<{
value: unknown;
}>();
-const collapsed = reactive({});
+const collapsed = reactive<Record<string, boolean>>({});
if (isObject(props.value)) {
for (const key in props.value) {
diff --git a/packages/frontend/src/components/MkPagination.vue b/packages/frontend/src/components/MkPagination.vue
index a4c8ca0095..ad8fcf283c 100644
--- a/packages/frontend/src/components/MkPagination.vue
+++ b/packages/frontend/src/components/MkPagination.vue
@@ -88,7 +88,7 @@ const shouldEnableInfiniteScroll = computed(() => {
return prefer.r.enableInfiniteScroll.value && !props.forceDisableInfiniteScroll;
});
-function onContextmenu(ev: MouseEvent) {
+function onContextmenu(ev: PointerEvent) {
if (ev.target && isLink(ev.target as HTMLElement)) return;
if (window.getSelection()?.toString() !== '') return;
diff --git a/packages/frontend/src/components/MkPollEditor.vue b/packages/frontend/src/components/MkPollEditor.vue
index b7c3d1f42d..bd36a0b97a 100644
--- a/packages/frontend/src/components/MkPollEditor.vue
+++ b/packages/frontend/src/components/MkPollEditor.vue
@@ -110,7 +110,7 @@ if (props.modelValue.expiresAt) {
expiration.value = 'infinite';
}
-function onInput(i, value) {
+function onInput(i: number, value: string) {
choices.value[i] = value;
}
@@ -122,7 +122,7 @@ function add() {
// });
}
-function remove(i) {
+function remove(i: number) {
choices.value = choices.value.filter((_, _i) => _i !== i);
}
diff --git a/packages/frontend/src/components/MkPostForm.vue b/packages/frontend/src/components/MkPostForm.vue
index 9734b51927..c869eeb3fd 100644
--- a/packages/frontend/src/components/MkPostForm.vue
+++ b/packages/frontend/src/components/MkPostForm.vue
@@ -55,7 +55,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<div :class="$style.visibleUsers">
<span v-for="u in visibleUsers" :key="u.id" :class="$style.visibleUser">
<MkAcct :user="u"/>
- <button class="_button" style="padding: 4px 8px;" @click="removeVisibleUser(u)"><i class="ti ti-x"></i></button>
+ <button class="_button" style="padding: 4px 8px;" @click="removeVisibleUser(u.id)"><i class="ti ti-x"></i></button>
</span>
<button class="_buttonPrimary" style="padding: 4px; border-radius: 8px;" @click="addVisibleUser"><i class="ti ti-plus ti-fw"></i></button>
</div>
@@ -476,6 +476,7 @@ function togglePoll() {
}
function addTag(tag: string) {
+ if (textareaEl.value == null) return;
insertTextAtCursor(textareaEl.value, ` #${tag} `);
}
@@ -486,7 +487,7 @@ function focus() {
}
}
-function chooseFileFromPc(ev: MouseEvent) {
+function chooseFileFromPc(ev: PointerEvent) {
if (props.mock) return;
os.chooseFileFromPc({ multiple: true }).then(files => {
@@ -495,7 +496,7 @@ function chooseFileFromPc(ev: MouseEvent) {
});
}
-function chooseFileFromDrive(ev: MouseEvent) {
+function chooseFileFromDrive(ev: PointerEvent) {
if (props.mock) return;
chooseDriveFile({ multiple: true }).then(driveFiles => {
@@ -503,18 +504,18 @@ function chooseFileFromDrive(ev: MouseEvent) {
});
}
-function detachFile(id) {
+function detachFile(id: Misskey.entities.DriveFile['id']) {
files.value = files.value.filter(x => x.id !== id);
}
-function updateFileSensitive(file, sensitive) {
+function updateFileSensitive(file: Misskey.entities.DriveFile, isSensitive: boolean) {
if (props.mock) {
- emit('fileChangeSensitive', file.id, sensitive);
+ emit('fileChangeSensitive', file.id, isSensitive);
}
- files.value[files.value.findIndex(x => x.id === file.id)].isSensitive = sensitive;
+ files.value[files.value.findIndex(x => x.id === file.id)].isSensitive = isSensitive;
}
-function updateFileName(file, name) {
+function updateFileName(file: Misskey.entities.DriveFile, name: Misskey.entities.DriveFile['name']) {
files.value[files.value.findIndex(x => x.id === file.id)].name = name;
}
@@ -704,8 +705,8 @@ function addVisibleUser() {
});
}
-function removeVisibleUser(user) {
- visibleUsers.value = erase(user, visibleUsers.value);
+function removeVisibleUser(id: string) {
+ visibleUsers.value = visibleUsers.value.filter(u => u.id !== id);
}
function clear() {
@@ -742,7 +743,8 @@ const pastedFileName = 'yyyy-MM-dd HH-mm-ss [{{number}}]';
async function onPaste(ev: ClipboardEvent) {
if (props.mock) return;
- if (!ev.clipboardData) return;
+ if (ev.clipboardData == null) return;
+ if (textareaEl.value == null) return;
let pastedFiles: File[] = [];
for (const { item, i } of Array.from(ev.clipboardData.items, (data, x) => ({ item: data, i: x }))) {
@@ -767,39 +769,42 @@ async function onPaste(ev: ClipboardEvent) {
if (!renoteTargetNote.value && !quoteId.value && paste.startsWith(url + '/notes/')) {
ev.preventDefault();
- os.confirm({
+ const { canceled } = await os.confirm({
type: 'info',
text: i18n.ts.quoteQuestion,
- }).then(({ canceled }) => {
- if (canceled) {
- insertTextAtCursor(textareaEl.value, paste);
- return;
- }
-
- quoteId.value = paste.substring(url.length).match(/^\/notes\/(.+?)\/?$/)?.[1] ?? null;
});
+
+ if (canceled) {
+ insertTextAtCursor(textareaEl.value, paste);
+ return;
+ }
+
+ quoteId.value = paste.substring(url.length).match(/^\/notes\/(.+?)\/?$/)?.[1] ?? null;
}
if (paste.length > 1000) {
ev.preventDefault();
- os.confirm({
+
+ const { canceled } = await os.confirm({
type: 'info',
text: i18n.ts.attachAsFileQuestion,
- }).then(({ canceled }) => {
- if (canceled) {
- insertTextAtCursor(textareaEl.value, paste);
- return;
- }
-
- const fileName = formatTimeString(new Date(), pastedFileName).replace(/{{number}}/g, '0');
- const file = new File([paste], `${fileName}.txt`, { type: 'text/plain' });
- uploader.addFiles([file]);
});
+
+ if (canceled) {
+ insertTextAtCursor(textareaEl.value, paste);
+ return;
+ }
+
+ const fileName = formatTimeString(new Date(), pastedFileName).replace(/{{number}}/g, '0');
+ const file = new File([paste], `${fileName}.txt`, { type: 'text/plain' });
+ uploader.addFiles([file]);
}
}
-function onDragover(ev) {
- if (!ev.dataTransfer.items[0]) return;
+function onDragover(ev: DragEvent) {
+ if (ev.dataTransfer == null) return;
+ if (ev.dataTransfer.items[0] == null) return;
+
const isFile = ev.dataTransfer.items[0].kind === 'file';
if (isFile || checkDragDataType(ev, ['driveFiles'])) {
ev.preventDefault();
@@ -852,13 +857,32 @@ function onDrop(ev: DragEvent): void {
//#endregion
}
+type StoredDrafts = {
+ [key: string]: {
+ updatedAt: string;
+ data: {
+ text: string;
+ useCw: boolean;
+ cw: string | null;
+ visibility: 'public' | 'home' | 'followers' | 'specified';
+ localOnly: boolean;
+ files: Misskey.entities.DriveFile[];
+ poll: PollEditorModelValue | null;
+ visibleUserIds?: string[];
+ quoteId: string | null;
+ reactionAcceptance: 'likeOnly' | 'likeOnlyForRemote' | 'nonSensitiveOnly' | 'nonSensitiveOnlyForLocalLikeOnlyForRemote' | null;
+ scheduledAt: number | null;
+ };
+ };
+};
+
function saveDraft() {
if (props.instant || props.mock) return;
- const draftData = JSON.parse(miLocalStorage.getItem('drafts') ?? '{}');
+ const draftsData = JSON.parse(miLocalStorage.getItem('drafts') ?? '{}') as StoredDrafts;
- draftData[draftKey.value] = {
- updatedAt: new Date(),
+ draftsData[draftKey.value] = {
+ updatedAt: new Date().toISOString(),
data: {
text: text.value,
useCw: useCw.value,
@@ -874,15 +898,15 @@ function saveDraft() {
},
};
- miLocalStorage.setItem('drafts', JSON.stringify(draftData));
+ miLocalStorage.setItem('drafts', JSON.stringify(draftsData));
}
function deleteDraft() {
- const draftData = JSON.parse(miLocalStorage.getItem('drafts') ?? '{}');
+ const draftsData = JSON.parse(miLocalStorage.getItem('drafts') ?? '{}') as StoredDrafts;
- delete draftData[draftKey.value];
+ delete draftsData[draftKey.value];
- miLocalStorage.setItem('drafts', JSON.stringify(draftData));
+ miLocalStorage.setItem('drafts', JSON.stringify(draftsData));
}
async function saveServerDraft(options: {
@@ -924,8 +948,8 @@ async function uploadFiles() {
}
}
-async function post(ev?: MouseEvent) {
- if (ev) {
+async function post(ev?: PointerEvent) {
+ if (ev != null) {
const el = (ev.currentTarget ?? ev.target) as HTMLElement | null;
if (el && prefer.s.animation) {
@@ -1138,11 +1162,12 @@ function cancel() {
function insertMention() {
os.selectUser({ localOnly: localOnly.value, includeSelf: true }).then(user => {
+ if (textareaEl.value == null) return;
insertTextAtCursor(textareaEl.value, '@' + Misskey.acct.toString(user) + ' ');
});
}
-async function insertEmoji(ev: MouseEvent) {
+async function insertEmoji(ev: PointerEvent) {
textAreaReadOnly.value = true;
const target = ev.currentTarget ?? ev.target;
if (target == null) return;
@@ -1176,7 +1201,7 @@ async function insertEmoji(ev: MouseEvent) {
);
}
-async function insertMfmFunction(ev: MouseEvent) {
+async function insertMfmFunction(ev: PointerEvent) {
if (textareaEl.value == null) return;
let pos = textareaEl.value.selectionStart ?? 0;
let posEnd = textareaEl.value.selectionEnd ?? text.value.length;
@@ -1204,7 +1229,7 @@ async function insertMfmFunction(ev: MouseEvent) {
);
}
-function showActions(ev: MouseEvent) {
+function showActions(ev: PointerEvent) {
os.popupMenu(postFormActions.map(action => ({
text: action.title,
action: () => {
@@ -1222,7 +1247,7 @@ function showActions(ev: MouseEvent) {
const postAccount = ref<Misskey.entities.UserDetailed | null>(null);
-async function openAccountMenu(ev: MouseEvent) {
+async function openAccountMenu(ev: PointerEvent) {
if (props.mock) return;
function showDraftsDialog(scheduled: boolean) {
@@ -1312,12 +1337,12 @@ async function openAccountMenu(ev: MouseEvent) {
}, { type: 'divider' }, ...items], (ev.currentTarget ?? ev.target ?? undefined) as HTMLElement | undefined);
}
-function showPerUploadItemMenu(item: UploaderItem, ev: MouseEvent) {
+function showPerUploadItemMenu(item: UploaderItem, ev: PointerEvent) {
const menu = uploader.getMenu(item);
os.popupMenu(menu, ev.currentTarget ?? ev.target);
}
-function showPerUploadItemMenuViaContextmenu(item: UploaderItem, ev: MouseEvent) {
+function showPerUploadItemMenuViaContextmenu(item: UploaderItem, ev: PointerEvent) {
const menu = uploader.getMenu(item);
os.contextMenu(menu, ev);
}
@@ -1392,8 +1417,8 @@ onMounted(() => {
nextTick(() => {
// 書きかけの投稿を復元
if (!props.instant && !props.mention && !props.specified && !props.mock) {
- const draft = JSON.parse(miLocalStorage.getItem('drafts') ?? '{}')[draftKey.value];
- if (draft) {
+ const draft = JSON.parse(miLocalStorage.getItem('drafts') ?? '{}')[draftKey.value] as StoredDrafts[string] | undefined;
+ if (draft != null) {
text.value = draft.data.text;
useCw.value = draft.data.useCw;
cw.value = draft.data.cw;
diff --git a/packages/frontend/src/components/MkPostFormAttaches.vue b/packages/frontend/src/components/MkPostFormAttaches.vue
index d198c98404..2d6e7ec6b3 100644
--- a/packages/frontend/src/components/MkPostFormAttaches.vue
+++ b/packages/frontend/src/components/MkPostFormAttaches.vue
@@ -97,7 +97,7 @@ async function detachAndDeleteMedia(file: Misskey.entities.DriveFile) {
globalEvents.emit('driveFilesDeleted', [file]);
}
-function toggleSensitive(file) {
+function toggleSensitive(file: Misskey.entities.DriveFile) {
if (mock) {
emit('changeSensitive', file, !file.isSensitive);
return;
@@ -111,7 +111,7 @@ function toggleSensitive(file) {
});
}
-async function rename(file) {
+async function rename(file: Misskey.entities.DriveFile) {
if (mock) return;
const { canceled, result } = await os.inputText({
@@ -149,7 +149,7 @@ async function describe(file: Misskey.entities.DriveFile) {
});
}
-function showFileMenu(file: Misskey.entities.DriveFile, ev: MouseEvent | KeyboardEvent): void {
+function showFileMenu(file: Misskey.entities.DriveFile, ev: PointerEvent | KeyboardEvent): void {
if (menuShowing) return;
const isImage = file.type.startsWith('image/');
diff --git a/packages/frontend/src/components/MkPreferenceContainer.vue b/packages/frontend/src/components/MkPreferenceContainer.vue
index 70b111513c..1ce608dda9 100644
--- a/packages/frontend/src/components/MkPreferenceContainer.vue
+++ b/packages/frontend/src/components/MkPreferenceContainer.vue
@@ -32,7 +32,7 @@ const props = withDefaults(defineProps<{
const isAccountOverrided = ref(prefer.isAccountOverrided(props.k));
const isSyncEnabled = ref(prefer.isSyncEnabled(props.k));
-function showMenu(ev: MouseEvent, contextmenu?: boolean) {
+function showMenu(ev: PointerEvent, contextmenu?: boolean) {
const i = window.setInterval(() => {
isAccountOverrided.value = prefer.isAccountOverrided(props.k);
isSyncEnabled.value = prefer.isSyncEnabled(props.k);
diff --git a/packages/frontend/src/components/MkPreview.vue b/packages/frontend/src/components/MkPreview.vue
index 6c7bf6be6b..c25f9ab0a9 100644
--- a/packages/frontend/src/components/MkPreview.vue
+++ b/packages/frontend/src/components/MkPreview.vue
@@ -89,7 +89,7 @@ const selectUser = async () => {
await os.selectUser();
};
-const openMenu = async (ev: Event) => {
+const openMenu = async (ev: PointerEvent) => {
os.popupMenu([{
type: 'label',
text: 'Fruits',
diff --git a/packages/frontend/src/components/MkReactionsViewer.reaction.vue b/packages/frontend/src/components/MkReactionsViewer.reaction.vue
index 7c60288883..a89f947fa7 100644
--- a/packages/frontend/src/components/MkReactionsViewer.reaction.vue
+++ b/packages/frontend/src/components/MkReactionsViewer.reaction.vue
@@ -153,7 +153,7 @@ async function toggleReaction() {
}
}
-async function menu(ev) {
+async function menu(ev: PointerEvent) {
let menuItems: MenuItem[] = [];
if (canGetInfo.value) {
diff --git a/packages/frontend/src/components/MkReactionsViewer.vue b/packages/frontend/src/components/MkReactionsViewer.vue
index bd9ef50157..ab7f86842c 100644
--- a/packages/frontend/src/components/MkReactionsViewer.vue
+++ b/packages/frontend/src/components/MkReactionsViewer.vue
@@ -32,11 +32,11 @@ SPDX-License-Identifier: AGPL-3.0-only
import * as Misskey from 'misskey-js';
import { inject, watch, ref } from 'vue';
import { TransitionGroup } from 'vue';
+import { isSupportedEmoji } from '@@/js/emojilist.js';
import XReaction from '@/components/MkReactionsViewer.reaction.vue';
import { $i } from '@/i.js';
import { prefer } from '@/preferences.js';
import { customEmojisMap } from '@/custom-emojis.js';
-import { isSupportedEmoji } from '@@/js/emojilist.js';
import { DI } from '@/di.js';
const props = withDefaults(defineProps<{
@@ -60,8 +60,8 @@ const initialReactions = new Set(Object.keys(props.reactions));
const _reactions = ref<[string, number][]>([]);
const hasMoreReactions = ref(false);
-if (props.myReaction && !Object.keys(_reactions.value).includes(props.myReaction)) {
- _reactions.value[props.myReaction] = props.reactions[props.myReaction];
+if (props.myReaction != null && !(props.myReaction in props.reactions)) {
+ _reactions.value.push([props.myReaction, props.reactions[props.myReaction]]);
}
function onMockToggleReaction(emoji: string, count: number) {
diff --git a/packages/frontend/src/components/MkRetentionHeatmap.vue b/packages/frontend/src/components/MkRetentionHeatmap.vue
index a204bc3bf1..6ab7a01ce7 100644
--- a/packages/frontend/src/components/MkRetentionHeatmap.vue
+++ b/packages/frontend/src/components/MkRetentionHeatmap.vue
@@ -98,7 +98,7 @@ async function renderChart() {
data: data as any,
borderWidth: 0,
borderRadius: 3,
- backgroundColor(c) {
+ backgroundColor(c: any) {
const v = c.dataset.data[c.dataIndex] as unknown as typeof data[0];
const value = v.v;
const m = max(v.y);
@@ -179,7 +179,7 @@ async function renderChart() {
enabled: false,
callbacks: {
title(context) {
- const v = context[0].dataset.data[context[0].dataIndex];
+ const v = context[0].dataset.data[context[0].dataIndex] as unknown as typeof data[0];
return getYYYYMMDD(new Date(new Date(v.y).getTime() + (v.x * 86400000)));
},
label(context) {
diff --git a/packages/frontend/src/components/MkRoleSelectDialog.vue b/packages/frontend/src/components/MkRoleSelectDialog.vue
index 937804703d..651165136a 100644
--- a/packages/frontend/src/components/MkRoleSelectDialog.vue
+++ b/packages/frontend/src/components/MkRoleSelectDialog.vue
@@ -55,9 +55,9 @@ import MkModalWindow from '@/components/MkModalWindow.vue';
import MkLoading from '@/components/global/MkLoading.vue';
const emit = defineEmits<{
- (ev: 'done', value: Misskey.entities.Role[]),
- (ev: 'close'),
- (ev: 'closed'),
+ (ev: 'done', value: Misskey.entities.Role[]): void;
+ (ev: 'close'): void;
+ (ev: 'closed'): void;
}>();
const props = withDefaults(defineProps<{
diff --git a/packages/frontend/src/components/MkServerSetupWizardDialog.vue b/packages/frontend/src/components/MkServerSetupWizardDialog.vue
index ea2c5dd47f..1d03438f83 100644
--- a/packages/frontend/src/components/MkServerSetupWizardDialog.vue
+++ b/packages/frontend/src/components/MkServerSetupWizardDialog.vue
@@ -33,7 +33,7 @@ import MkModalWindow from '@/components/MkModalWindow.vue';
import MkServerSetupWizard from '@/components/MkServerSetupWizard.vue';
const emit = defineEmits<{
- (ev: 'closed'),
+ (ev: 'closed'): void;
}>();
const windowEl = useTemplateRef('windowEl');
diff --git a/packages/frontend/src/components/MkSignin.input.vue b/packages/frontend/src/components/MkSignin.input.vue
index 4c73eab3f5..89ec6373cf 100644
--- a/packages/frontend/src/components/MkSignin.input.vue
+++ b/packages/frontend/src/components/MkSignin.input.vue
@@ -78,7 +78,7 @@ const props = withDefaults(defineProps<{
const emit = defineEmits<{
(ev: 'usernameSubmitted', v: string): void;
- (ev: 'passkeyClick', v: MouseEvent): void;
+ (ev: 'passkeyClick', v: PointerEvent): void;
}>();
const host = toUnicode(configHost);
diff --git a/packages/frontend/src/components/MkSortOrderEditor.vue b/packages/frontend/src/components/MkSortOrderEditor.vue
index 27ffc724ae..3ac809cdbf 100644
--- a/packages/frontend/src/components/MkSortOrderEditor.vue
+++ b/packages/frontend/src/components/MkSortOrderEditor.vue
@@ -25,11 +25,11 @@ SPDX-License-Identifier: AGPL-3.0-only
<script setup lang="ts" generic="T extends string">
import { toRefs } from 'vue';
+import type { MenuItem } from '@/types/menu.js';
+import type { SortOrder } from '@/components/MkSortOrderEditor.define.js';
import MkTagItem from '@/components/MkTagItem.vue';
import MkButton from '@/components/MkButton.vue';
-import type { MenuItem } from '@/types/menu.js';
import * as os from '@/os.js';
-import type { SortOrder } from '@/components/MkSortOrderEditor.define.js';
const emit = defineEmits<{
(ev: 'update', sortOrders: SortOrder<T>[]): void;
@@ -55,7 +55,7 @@ function onToggleSortOrderButtonClicked(order: SortOrder<T>) {
emitOrder(currentOrders.value);
}
-function onAddSortOrderButtonClicked(ev: MouseEvent) {
+function onAddSortOrderButtonClicked(ev: PointerEvent) {
const menuItems: MenuItem[] = props.baseOrderKeyNames
.filter(baseKey => !currentOrders.value.map(it => it.key).includes(baseKey))
.map(it => {
diff --git a/packages/frontend/src/components/MkSpot.vue b/packages/frontend/src/components/MkSpot.vue
index 4a8ebb5f94..4bd11fe938 100644
--- a/packages/frontend/src/components/MkSpot.vue
+++ b/packages/frontend/src/components/MkSpot.vue
@@ -88,7 +88,7 @@ function setPosition() {
bodyEl.value.style.top = data.top + 'px';
}
-let loopHandler;
+let loopHandler: number | null = null;
onMounted(() => {
nextTick(() => {
@@ -104,7 +104,7 @@ onMounted(() => {
});
onUnmounted(() => {
- window.cancelAnimationFrame(loopHandler);
+ if (loopHandler != null) window.cancelAnimationFrame(loopHandler);
});
</script>
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<void>;
+ action: (ev: PointerEvent) => Awaitable<void>;
} | {
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
<script lang="ts">
export type Tab<K = string> = {
key: K;
- onClick?: (ev: MouseEvent) => void;
+ onClick?: (ev: PointerEvent) => void;
iconOnly?: boolean;
title: string;
icon?: string;
@@ -74,7 +74,7 @@ const props = withDefaults(defineProps<{
});
const emit = defineEmits<{
- (ev: 'tabClick', key: string);
+ (ev: 'tabClick', key: string): void;
}>();
const tab = defineModel<T['key']>('tab');
@@ -100,7 +100,7 @@ function onTabMousedown(selectedTab: 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/MkTagItem.vue b/packages/frontend/src/components/MkTagItem.vue
index be735e6407..5cd2113e59 100644
--- a/packages/frontend/src/components/MkTagItem.vue
+++ b/packages/frontend/src/components/MkTagItem.vue
@@ -17,8 +17,8 @@ SPDX-License-Identifier: AGPL-3.0-only
import MkButton from '@/components/MkButton.vue';
const emit = defineEmits<{
- (ev: 'click', payload: MouseEvent): void;
- (ev: 'exButtonClick', payload: MouseEvent): void;
+ (ev: 'click', payload: PointerEvent): void;
+ (ev: 'exButtonClick', payload: PointerEvent): void;
}>();
defineProps<{
diff --git a/packages/frontend/src/components/MkTextarea.vue b/packages/frontend/src/components/MkTextarea.vue
index 407ac33add..d53d4ec018 100644
--- a/packages/frontend/src/components/MkTextarea.vue
+++ b/packages/frontend/src/components/MkTextarea.vue
@@ -63,7 +63,7 @@ const props = defineProps<{
}>();
const emit = defineEmits<{
- (ev: 'change', _ev: KeyboardEvent): void;
+ (ev: 'change', _ev: InputEvent): void;
(ev: 'keydown', _ev: KeyboardEvent): void;
(ev: 'enter'): void;
(ev: 'update:modelValue', value: string): void;
@@ -79,12 +79,16 @@ const inputEl = useTemplateRef('inputEl');
const preview = ref(false);
let autocompleteWorker: Autocomplete | null = null;
-const focus = () => inputEl.value?.focus();
-const onInput = (ev) => {
+function focus() {
+ inputEl.value?.focus();
+}
+
+function onInput(ev: InputEvent) {
changed.value = true;
emit('change', ev);
-};
-const onKeydown = (ev: KeyboardEvent) => {
+}
+
+function onKeydown(ev: KeyboardEvent) {
if (ev.isComposing || ev.key === 'Process' || ev.keyCode === 229) return;
emit('keydown', ev);
@@ -102,12 +106,12 @@ const onKeydown = (ev: KeyboardEvent) => {
});
ev.preventDefault();
}
-};
+}
-const updated = () => {
+function updated() {
changed.value = false;
emit('update:modelValue', v.value ?? '');
-};
+}
const debouncedUpdated = debounce(1000, updated);
diff --git a/packages/frontend/src/components/MkTokenGenerateWindow.vue b/packages/frontend/src/components/MkTokenGenerateWindow.vue
index 42cb6f1e82..8d51e1fa87 100644
--- a/packages/frontend/src/components/MkTokenGenerateWindow.vue
+++ b/packages/frontend/src/components/MkTokenGenerateWindow.vue
@@ -33,12 +33,12 @@ SPDX-License-Identifier: AGPL-3.0-only
<MkButton inline @click="enableAll">{{ i18n.ts.enableAll }}</MkButton>
</div>
<div class="_gaps_s">
- <MkSwitch v-for="kind in Object.keys(permissionSwitches)" :key="kind" v-model="permissionSwitches[kind]">{{ i18n.ts._permissions[kind] }}</MkSwitch>
+ <MkSwitch v-for="kind in Object.keys(permissionSwitches)" :key="kind" v-model="permissionSwitches[kind as keyof typeof permissionSwitches]">{{ i18n.ts._permissions[kind as keyof typeof permissionSwitches] }}</MkSwitch>
</div>
<div v-if="iAmAdmin" :class="$style.adminPermissions">
<div :class="$style.adminPermissionsHeader"><b>{{ i18n.ts.adminPermission }}</b></div>
<div class="_gaps_s">
- <MkSwitch v-for="kind in Object.keys(permissionSwitchesForAdmin)" :key="kind" v-model="permissionSwitchesForAdmin[kind]">{{ i18n.ts._permissions[kind] }}</MkSwitch>
+ <MkSwitch v-for="kind in Object.keys(permissionSwitchesForAdmin)" :key="kind" v-model="permissionSwitchesForAdmin[kind as keyof typeof permissionSwitchesForAdmin]">{{ i18n.ts._permissions[kind as keyof typeof permissionSwitchesForAdmin] }}</MkSwitch>
</div>
</div>
</div>
@@ -102,8 +102,8 @@ function ok(): void {
emit('done', {
name: name.value,
permissions: [
- ...Object.keys(permissionSwitches.value).filter(p => permissionSwitches.value[p]),
- ...(iAmAdmin ? Object.keys(permissionSwitchesForAdmin.value).filter(p => permissionSwitchesForAdmin.value[p]) : []),
+ ...Object.keys(permissionSwitches.value).filter(p => permissionSwitches.value[p as (typeof Misskey.permissions)[number]]),
+ ...(iAmAdmin ? Object.keys(permissionSwitchesForAdmin.value).filter(p => permissionSwitchesForAdmin.value[p as (typeof Misskey.permissions)[number]]) : []),
],
});
dialog.value?.close();
@@ -111,22 +111,22 @@ function ok(): void {
function disableAll(): void {
for (const p in permissionSwitches.value) {
- permissionSwitches.value[p] = false;
+ permissionSwitches.value[p as (typeof Misskey.permissions)[number]] = false;
}
if (iAmAdmin) {
for (const p in permissionSwitchesForAdmin.value) {
- permissionSwitchesForAdmin.value[p] = false;
+ permissionSwitchesForAdmin.value[p as (typeof Misskey.permissions)[number]] = false;
}
}
}
function enableAll(): void {
for (const p in permissionSwitches.value) {
- permissionSwitches.value[p] = true;
+ permissionSwitches.value[p as (typeof Misskey.permissions)[number]] = true;
}
if (iAmAdmin) {
for (const p in permissionSwitchesForAdmin.value) {
- permissionSwitchesForAdmin.value[p] = true;
+ permissionSwitchesForAdmin.value[p as (typeof Misskey.permissions)[number]] = true;
}
}
}
diff --git a/packages/frontend/src/components/MkTooltip.vue b/packages/frontend/src/components/MkTooltip.vue
index aa041c88e5..08a3f02f65 100644
--- a/packages/frontend/src/components/MkTooltip.vue
+++ b/packages/frontend/src/components/MkTooltip.vue
@@ -71,7 +71,7 @@ function setPosition() {
el.value.style.top = data.top + 'px';
}
-let loopHandler;
+let loopHandler: number | null = null;
onMounted(() => {
nextTick(() => {
@@ -87,7 +87,7 @@ onMounted(() => {
});
onUnmounted(() => {
- window.cancelAnimationFrame(loopHandler);
+ if (loopHandler != null) window.cancelAnimationFrame(loopHandler);
});
</script>
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<Misskey.entities.Note>({
});
const onceReacted = ref<boolean>(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
}
</script>
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<P, Misskey.entities.UserDetailed>;
}>(), {
- extractor: (item) => item,
+ extractor: (item: any) => item as Misskey.entities.UserDetailed,
});
</script>
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);
}
</script>
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')"
>
- <template #header><i class="ti ti-icons"></i> {{ i18n.ts._widgets[widgetName] ?? widgetName }}</template>
+ <template #header><i class="ti ti-icons"></i> {{ (i18n.ts._widgets as any)[widgetName] ?? widgetName }}</template>
<MkPreviewWithControls>
<template #preview>
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
<div :class="[$style.widget, $style.customizeContainer]" data-cy-customize-container>
<button :class="$style.customizeContainerConfig" class="_button" @click.prevent.stop="configWidget(item.id)"><i class="ti ti-settings"></i></button>
<button :class="$style.customizeContainerRemove" data-cy-customize-container-remove class="_button" @click.prevent.stop="removeWidget(item)"><i class="ti ti-x"></i></button>
- <component :is="`widget-${item.name}`" :ref="el => widgetRefs[item.id] = el" :class="$style.customizeContainerHandleWidget" :widget="item" @updateProps="updateWidget(item.id, $event)"/>
+ <component :is="`widget-${item.name}`" :ref="(el: any) => widgetRefs[item.id] = el" :class="$style.customizeContainerHandleWidget" :widget="item" @updateProps="updateWidget(item.id, $event)"/>
</div>
</template>
</MkDraggable>
</template>
- <component :is="`widget-${widget.name}`" v-for="widget in _widgets" v-else :key="widget.id" :ref="el => widgetRefs[widget.id] = el" :class="$style.widget" :widget="widget" @updateProps="updateWidget(widget.id, $event)" @contextmenu.stop="onContextmenu(widget, $event)"/>
+ <component :is="`widget-${widget.name}`" v-for="widget in _widgets" v-else :key="widget.id" :ref="(el: any) => widgetRefs[widget.id] = el" :class="$style.widget" :widget="widget" @updateProps="updateWidget(widget.id, $event)" @contextmenu.stop="onContextmenu(widget, $event)"/>
</div>
</template>
@@ -47,6 +47,7 @@ export type DefaultStoredWidget = {
<script lang="ts" setup>
import { computed } from 'vue';
import { isLink } from '@@/js/is-link.js';
+import type { Component } from 'vue';
import { genId } from '@/utility/id.js';
import MkSelect from '@/components/MkSelect.vue';
import MkButton from '@/components/MkButton.vue';
@@ -64,13 +65,13 @@ const props = defineProps<{
const _widgetDefs = computed(() => {
if (instance.federation === 'none') {
- return widgetDefs.filter(x => !federationWidgets.includes(x));
+ return widgetDefs.filter(x => !federationWidgets.includes(x as any));
} else {
return widgetDefs;
}
});
-const _widgets = computed(() => props.widgets.filter(x => _widgetDefs.value.includes(x.name)));
+const _widgets = computed(() => props.widgets.filter(x => _widgetDefs.value.includes(x.name as any)));
const emit = defineEmits<{
(ev: 'updateWidgets', widgets: Widget[]): void;
@@ -80,10 +81,11 @@ const emit = defineEmits<{
(ev: 'exit'): void;
}>();
-const widgetRefs = {};
-const configWidget = (id: string) => {
+const widgetRefs = {} as Record<string, Component & { configure: () => void }>;
+
+function configWidget(id: string) {
widgetRefs[id].configure();
-};
+}
const {
model: widgetAdderSelected,
@@ -93,7 +95,7 @@ const {
initialValue: null,
});
-const addWidget = () => {
+function addWidget() {
if (widgetAdderSelected.value == null) return;
emit('addWidget', {
@@ -103,23 +105,25 @@ const addWidget = () => {
});
widgetAdderSelected.value = null;
-};
-const removeWidget = (widget) => {
+}
+
+function removeWidget(widget: Widget) {
emit('removeWidget', widget);
-};
-const updateWidget = (id: Widget['id'], data: Widget['data']) => {
+}
+
+function updateWidget(id: Widget['id'], data: Widget['data']) {
emit('updateWidget', { id, data });
-};
+}
-function onContextmenu(widget: Widget, ev: MouseEvent) {
+function onContextmenu(widget: Widget, ev: PointerEvent) {
const element = ev.target as HTMLElement | null;
if (element && isLink(element)) return;
- if (element && (['INPUT', 'TEXTAREA', 'IMG', 'VIDEO', 'CANVAS'].includes(element.tagName) || element.attributes['contenteditable'])) return;
+ if (element && (['INPUT', 'TEXTAREA', 'IMG', 'VIDEO', 'CANVAS'].includes(element.tagName) || element.attributes.getNamedItem('contenteditable') != null)) return;
if (window.getSelection()?.toString() !== '') return;
os.contextMenu([{
type: 'label',
- text: i18n.ts._widgets[widget.name],
+ text: i18n.ts._widgets[widget.name as typeof widgetDefs[number]],
}, {
icon: 'ti ti-settings',
text: i18n.ts.settings,
diff --git a/packages/frontend/src/components/MkWindow.vue b/packages/frontend/src/components/MkWindow.vue
index e5ac791d0b..7fb77da476 100644
--- a/packages/frontend/src/components/MkWindow.vue
+++ b/packages/frontend/src/components/MkWindow.vue
@@ -55,7 +55,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<script lang="ts" setup>
import { onBeforeUnmount, onMounted, provide, useTemplateRef, ref } from 'vue';
import type { MenuItem } from '@/types/menu.js';
-import contains from '@/utility/contains.js';
+import { elementContains } from '@/utility/element-contains.js';
import * as os from '@/os.js';
import { i18n } from '@/i18n.js';
import { prefer } from '@/preferences.js';
@@ -78,12 +78,12 @@ function dragListen(fn: (ev: MouseEvent | TouchEvent) => void) {
window.addEventListener('touchend', dragClear.bind(null, fn));
}
-function dragClear(fn) {
+function dragClear(fn: (ev: MouseEvent | TouchEvent) => void) {
window.removeEventListener('mousemove', fn);
window.removeEventListener('touchmove', fn);
- window.removeEventListener('mouseleave', dragClear);
- window.removeEventListener('mouseup', dragClear);
- window.removeEventListener('touchend', dragClear);
+ window.removeEventListener('mouseleave', dragClear as any);
+ window.removeEventListener('mouseup', dragClear as any);
+ window.removeEventListener('touchend', dragClear as any);
}
const props = withDefaults(defineProps<{
@@ -128,7 +128,7 @@ function close() {
showing.value = false;
}
-function onKeydown(evt) {
+function onKeydown(evt: KeyboardEvent) {
if (evt.which === 27) { // Esc
evt.preventDefault();
evt.stopPropagation();
@@ -136,7 +136,7 @@ function onKeydown(evt) {
}
}
-function onContextmenu(ev: MouseEvent) {
+function onContextmenu(ev: PointerEvent) {
if (props.contextmenu) {
os.contextMenu(props.contextmenu, ev);
}
@@ -240,7 +240,7 @@ function onHeaderMousedown(evt: MouseEvent | TouchEvent) {
const main = rootEl.value;
if (main == null) return;
- if (!contains(main, window.document.activeElement)) main.focus();
+ if (!elementContains(main, window.document.activeElement)) main.focus();
const position = main.getBoundingClientRect();
@@ -418,24 +418,24 @@ function onBottomLeftHandleMousedown(evt: MouseEvent | TouchEvent) {
}
// 高さを適用
-function applyTransformHeight(height) {
+function applyTransformHeight(height: number) {
if (height > window.innerHeight) height = window.innerHeight;
if (rootEl.value) rootEl.value.style.height = height + 'px';
}
// 幅を適用
-function applyTransformWidth(width) {
+function applyTransformWidth(width: number) {
if (width > window.innerWidth) width = window.innerWidth;
if (rootEl.value) rootEl.value.style.width = width + 'px';
}
// Y座標を適用
-function applyTransformTop(top) {
+function applyTransformTop(top: number) {
if (rootEl.value) rootEl.value.style.top = top + 'px';
}
// X座標を適用
-function applyTransformLeft(left) {
+function applyTransformLeft(left: number) {
if (rootEl.value) rootEl.value.style.left = left + 'px';
}
diff --git a/packages/frontend/src/components/global/I18n.vue b/packages/frontend/src/components/global/I18n.vue
index 9866e50958..1fad1ee9e6 100644
--- a/packages/frontend/src/components/global/I18n.vue
+++ b/packages/frontend/src/components/global/I18n.vue
@@ -46,6 +46,6 @@ const parsed = computed(() => {
});
const render = () => {
- return h(props.tag, parsed.value.map(x => typeof x === 'string' ? (props.textTag ? h(props.textTag, x) : x) : slots[x.arg]()));
+ return h(props.tag, parsed.value.map(x => typeof x === 'string' ? (props.textTag ? h(props.textTag, x) : x) : (slots as any)[x.arg]()));
};
</script>
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<Props> = content[contentSymbol];
+ const content = ((entry.target as any)[contentSymbol] ? entry.target : entry.target.firstElementChild) as HTMLSpanElement;
+ const props: Required<Props> = (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<Props>(), {
const content = ref<HTMLSpanElement>();
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<MfmEven
]);
}
case 'clickable': {
- return h('span', { onClick(ev: MouseEvent): void {
+ return h('span', { onClick(ev: PointerEvent): void {
ev.stopPropagation();
ev.preventDefault();
const clickEv = typeof token.props.args.ev === 'string' ? token.props.args.ev : '';
diff --git a/packages/frontend/src/components/global/MkPageHeader.tabs.vue b/packages/frontend/src/components/global/MkPageHeader.tabs.vue
index 1ef75281fd..857fd3d8b4 100644
--- a/packages/frontend/src/components/global/MkPageHeader.tabs.vue
+++ b/packages/frontend/src/components/global/MkPageHeader.tabs.vue
@@ -46,7 +46,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<script lang="ts">
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<PageHeaderProps>(), {
});
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}`);