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
This commit is contained in:
parent
2a14025c29
commit
41592eafb3
|
|
@ -618,6 +618,9 @@ export const packedMeDetailedOnlySchema = {
|
||||||
achievementEarned: { optional: true, ...notificationRecieveConfig },
|
achievementEarned: { optional: true, ...notificationRecieveConfig },
|
||||||
app: { optional: true, ...notificationRecieveConfig },
|
app: { optional: true, ...notificationRecieveConfig },
|
||||||
test: { optional: true, ...notificationRecieveConfig },
|
test: { optional: true, ...notificationRecieveConfig },
|
||||||
|
login: { optional: true, ...notificationRecieveConfig },
|
||||||
|
createToken: { optional: true, ...notificationRecieveConfig },
|
||||||
|
exportCompleted: { optional: true, ...notificationRecieveConfig },
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
emailNotificationTypes: {
|
emailNotificationTypes: {
|
||||||
|
|
|
||||||
|
|
@ -51,11 +51,13 @@ export const meta = {
|
||||||
},
|
},
|
||||||
icon: {
|
icon: {
|
||||||
type: 'string',
|
type: 'string',
|
||||||
optional: false, nullable: true,
|
optional: false, nullable: false,
|
||||||
|
enum: ['info', 'warning', 'error', 'success'],
|
||||||
},
|
},
|
||||||
display: {
|
display: {
|
||||||
type: 'string',
|
type: 'string',
|
||||||
optional: false, nullable: false,
|
optional: false, nullable: false,
|
||||||
|
enum: ['normal', 'banner', 'dialog'],
|
||||||
},
|
},
|
||||||
isActive: {
|
isActive: {
|
||||||
type: 'boolean',
|
type: 'boolean',
|
||||||
|
|
|
||||||
|
|
@ -24,39 +24,7 @@ export const meta = {
|
||||||
optional: false, nullable: false,
|
optional: false, nullable: false,
|
||||||
items: {
|
items: {
|
||||||
type: 'object',
|
type: 'object',
|
||||||
optional: false, nullable: false,
|
ref: 'EmojiDetailed',
|
||||||
properties: {
|
|
||||||
id: {
|
|
||||||
type: 'string',
|
|
||||||
optional: false, nullable: false,
|
|
||||||
format: 'id',
|
|
||||||
},
|
|
||||||
aliases: {
|
|
||||||
type: 'array',
|
|
||||||
optional: false, nullable: false,
|
|
||||||
items: {
|
|
||||||
type: 'string',
|
|
||||||
optional: false, nullable: false,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
name: {
|
|
||||||
type: 'string',
|
|
||||||
optional: false, nullable: false,
|
|
||||||
},
|
|
||||||
category: {
|
|
||||||
type: 'string',
|
|
||||||
optional: false, nullable: true,
|
|
||||||
},
|
|
||||||
host: {
|
|
||||||
type: 'string',
|
|
||||||
optional: false, nullable: true,
|
|
||||||
description: 'The local host is represented with `null`.',
|
|
||||||
},
|
|
||||||
url: {
|
|
||||||
type: 'string',
|
|
||||||
optional: false, nullable: false,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
} as const;
|
} as const;
|
||||||
|
|
|
||||||
|
|
@ -64,7 +64,7 @@ const url = computed(() => (props.raw)
|
||||||
: props.image.thumbnailUrl,
|
: props.image.thumbnailUrl,
|
||||||
);
|
);
|
||||||
|
|
||||||
async function onclick(ev: MouseEvent) {
|
async function onclick(ev: PointerEvent) {
|
||||||
if (hide.value) {
|
if (hide.value) {
|
||||||
ev.stopPropagation();
|
ev.stopPropagation();
|
||||||
hide.value = false;
|
hide.value = false;
|
||||||
|
|
|
||||||
|
|
@ -299,7 +299,7 @@ export default function (props: MfmProps, { emit }: { emit: SetupContext<MfmEven
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
case 'clickable': {
|
case 'clickable': {
|
||||||
return h('span', { onClick(ev: MouseEvent): void {
|
return h('span', { onClick(ev: PointerEvent): void {
|
||||||
ev.stopPropagation();
|
ev.stopPropagation();
|
||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
const clickEv = typeof token.props.args.ev === 'string' ? token.props.args.ev : '';
|
const clickEv = typeof token.props.args.ev === 'string' ? token.props.args.ev : '';
|
||||||
|
|
|
||||||
|
|
@ -84,7 +84,7 @@ const pagination = computed(() => ({
|
||||||
|
|
||||||
const notesEl = useTemplateRef('notesEl');
|
const notesEl = useTemplateRef('notesEl');
|
||||||
|
|
||||||
function top(ev: MouseEvent) {
|
function top(ev: PointerEvent) {
|
||||||
const target = ev.target as HTMLElement | null;
|
const target = ev.target as HTMLElement | null;
|
||||||
if (target && isLink(target)) return;
|
if (target && isLink(target)) return;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -40,15 +40,15 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed, inject, useTemplateRef } from 'vue';
|
import { computed, inject, useTemplateRef } from 'vue';
|
||||||
import { scrollToTop } from '@@/js/scroll.js';
|
import { scrollToTop } from '@@/js/scroll.js';
|
||||||
|
import { url, instanceName } from '@@/js/config.js';
|
||||||
|
import { isLink } from '@@/js/is-link.js';
|
||||||
|
import { defaultEmbedParams } from '@@/js/embed-page.js';
|
||||||
import type { Paging } from '@/components/EmPagination.vue';
|
import type { Paging } from '@/components/EmPagination.vue';
|
||||||
import EmNotes from '@/components/EmNotes.vue';
|
import EmNotes from '@/components/EmNotes.vue';
|
||||||
import XNotFound from '@/pages/not-found.vue';
|
import XNotFound from '@/pages/not-found.vue';
|
||||||
import EmTimelineContainer from '@/components/EmTimelineContainer.vue';
|
import EmTimelineContainer from '@/components/EmTimelineContainer.vue';
|
||||||
import { i18n } from '@/i18n.js';
|
import { i18n } from '@/i18n.js';
|
||||||
import { url, instanceName } from '@@/js/config.js';
|
|
||||||
import { isLink } from '@@/js/is-link.js';
|
|
||||||
import { DI } from '@/di.js';
|
import { DI } from '@/di.js';
|
||||||
import { defaultEmbedParams } from '@@/js/embed-page.js';
|
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
tag: string;
|
tag: string;
|
||||||
|
|
@ -67,7 +67,7 @@ const pagination = computed(() => ({
|
||||||
|
|
||||||
const notesEl = useTemplateRef('notesEl');
|
const notesEl = useTemplateRef('notesEl');
|
||||||
|
|
||||||
function top(ev: MouseEvent) {
|
function top(ev: PointerEvent) {
|
||||||
const target = ev.target as HTMLElement | null;
|
const target = ev.target as HTMLElement | null;
|
||||||
if (target && isLink(target)) return;
|
if (target && isLink(target)) return;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -49,6 +49,8 @@ import { ref, computed, inject, useTemplateRef } from 'vue';
|
||||||
import * as Misskey from 'misskey-js';
|
import * as Misskey from 'misskey-js';
|
||||||
import { url, instanceName } from '@@/js/config.js';
|
import { url, instanceName } from '@@/js/config.js';
|
||||||
import { defaultEmbedParams } from '@@/js/embed-page.js';
|
import { defaultEmbedParams } from '@@/js/embed-page.js';
|
||||||
|
import { scrollToTop } from '@@/js/scroll.js';
|
||||||
|
import { isLink } from '@@/js/is-link.js';
|
||||||
import type { Paging } from '@/components/EmPagination.vue';
|
import type { Paging } from '@/components/EmPagination.vue';
|
||||||
import EmNotes from '@/components/EmNotes.vue';
|
import EmNotes from '@/components/EmNotes.vue';
|
||||||
import EmAvatar from '@/components/EmAvatar.vue';
|
import EmAvatar from '@/components/EmAvatar.vue';
|
||||||
|
|
@ -56,8 +58,6 @@ import EmUserName from '@/components/EmUserName.vue';
|
||||||
import I18n from '@/components/I18n.vue';
|
import I18n from '@/components/I18n.vue';
|
||||||
import XNotFound from '@/pages/not-found.vue';
|
import XNotFound from '@/pages/not-found.vue';
|
||||||
import EmTimelineContainer from '@/components/EmTimelineContainer.vue';
|
import EmTimelineContainer from '@/components/EmTimelineContainer.vue';
|
||||||
import { scrollToTop } from '@@/js/scroll.js';
|
|
||||||
import { isLink } from '@@/js/is-link.js';
|
|
||||||
import { misskeyApi } from '@/misskey-api.js';
|
import { misskeyApi } from '@/misskey-api.js';
|
||||||
import { i18n } from '@/i18n.js';
|
import { i18n } from '@/i18n.js';
|
||||||
import { assertServerContext } from '@/server-context.js';
|
import { assertServerContext } from '@/server-context.js';
|
||||||
|
|
@ -101,7 +101,7 @@ const pagination = computed(() => ({
|
||||||
|
|
||||||
const notesEl = useTemplateRef('notesEl');
|
const notesEl = useTemplateRef('notesEl');
|
||||||
|
|
||||||
function top(ev: MouseEvent) {
|
function top(ev: PointerEvent) {
|
||||||
const target = ev.target as HTMLElement | null;
|
const target = ev.target as HTMLElement | null;
|
||||||
if (target && isLink(target)) return;
|
if (target && isLink(target)) return;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"allowJs": true,
|
"allowJs": true,
|
||||||
"noEmitOnError": false,
|
"noEmitOnError": false,
|
||||||
"noImplicitAny": false,
|
"noImplicitAny": true,
|
||||||
"noImplicitReturns": true,
|
"noImplicitReturns": true,
|
||||||
"noUnusedParameters": false,
|
"noUnusedParameters": false,
|
||||||
"noUnusedLocals": false,
|
"noUnusedLocals": false,
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@ export function getChartResolver(fields: string[], option?: { accumulate?: boole
|
||||||
const res = {};
|
const res = {};
|
||||||
for (const field of fields) {
|
for (const field of fields) {
|
||||||
const layers = field.split('.');
|
const layers = field.split('.');
|
||||||
let current = res;
|
let current = res as any;
|
||||||
while (layers.length > 1) {
|
while (layers.length > 1) {
|
||||||
const currentKey = layers.shift()!;
|
const currentKey = layers.shift()!;
|
||||||
if (current[currentKey] == null) current[currentKey] = {};
|
if (current[currentKey] == null) current[currentKey] = {};
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,6 @@
|
||||||
"@discordapp/twemoji": "16.0.1",
|
"@discordapp/twemoji": "16.0.1",
|
||||||
"@github/webauthn-json": "2.1.1",
|
"@github/webauthn-json": "2.1.1",
|
||||||
"@mcaptcha/vanilla-glue": "0.1.0-rc2",
|
"@mcaptcha/vanilla-glue": "0.1.0-rc2",
|
||||||
"i18n": "workspace:*",
|
|
||||||
"@misskey-dev/browser-image-resizer": "2024.1.0",
|
"@misskey-dev/browser-image-resizer": "2024.1.0",
|
||||||
"@rollup/plugin-json": "6.1.0",
|
"@rollup/plugin-json": "6.1.0",
|
||||||
"@rollup/plugin-replace": "6.0.3",
|
"@rollup/plugin-replace": "6.0.3",
|
||||||
|
|
@ -48,6 +47,7 @@
|
||||||
"execa": "9.6.1",
|
"execa": "9.6.1",
|
||||||
"exifreader": "4.33.1",
|
"exifreader": "4.33.1",
|
||||||
"frontend-shared": "workspace:*",
|
"frontend-shared": "workspace:*",
|
||||||
|
"i18n": "workspace:*",
|
||||||
"icons-subsetter": "workspace:*",
|
"icons-subsetter": "workspace:*",
|
||||||
"idb-keyval": "6.2.2",
|
"idb-keyval": "6.2.2",
|
||||||
"insert-text-at-cursor": "0.3.0",
|
"insert-text-at-cursor": "0.3.0",
|
||||||
|
|
@ -100,12 +100,14 @@
|
||||||
"@testing-library/vue": "8.1.0",
|
"@testing-library/vue": "8.1.0",
|
||||||
"@types/canvas-confetti": "1.9.0",
|
"@types/canvas-confetti": "1.9.0",
|
||||||
"@types/estree": "1.0.8",
|
"@types/estree": "1.0.8",
|
||||||
|
"@types/insert-text-at-cursor": "0.3.2",
|
||||||
"@types/matter-js": "0.20.2",
|
"@types/matter-js": "0.20.2",
|
||||||
"@types/micromatch": "4.0.10",
|
"@types/micromatch": "4.0.10",
|
||||||
"@types/node": "24.10.4",
|
"@types/node": "24.10.4",
|
||||||
"@types/punycode.js": "npm:@types/punycode@2.1.4",
|
"@types/punycode.js": "npm:@types/punycode@2.1.4",
|
||||||
"@types/sanitize-html": "2.16.0",
|
"@types/sanitize-html": "2.16.0",
|
||||||
"@types/seedrandom": "3.0.8",
|
"@types/seedrandom": "3.0.8",
|
||||||
|
"@types/textarea-caret": "3.0.4",
|
||||||
"@types/throttle-debounce": "5.0.2",
|
"@types/throttle-debounce": "5.0.2",
|
||||||
"@types/tinycolor2": "1.4.6",
|
"@types/tinycolor2": "1.4.6",
|
||||||
"@typescript-eslint/eslint-plugin": "8.50.1",
|
"@typescript-eslint/eslint-plugin": "8.50.1",
|
||||||
|
|
|
||||||
|
|
@ -126,10 +126,10 @@ export function updateCurrentAccount(accountData: Misskey.entities.MeDetailed) {
|
||||||
if (!$i) return;
|
if (!$i) return;
|
||||||
const token = $i.token;
|
const token = $i.token;
|
||||||
for (const key of Object.keys($i)) {
|
for (const key of Object.keys($i)) {
|
||||||
delete $i[key];
|
delete $i[key as keyof typeof $i];
|
||||||
}
|
}
|
||||||
for (const [key, value] of Object.entries(accountData)) {
|
for (const [key, value] of Object.entries(accountData)) {
|
||||||
$i[key] = value;
|
($i[key as keyof typeof accountData] as any) = value;
|
||||||
}
|
}
|
||||||
store.set('accountInfos', { ...store.s.accountInfos, [host + '/' + $i.id]: $i });
|
store.set('accountInfos', { ...store.s.accountInfos, [host + '/' + $i.id]: $i });
|
||||||
$i.token = token;
|
$i.token = token;
|
||||||
|
|
@ -139,7 +139,7 @@ export function updateCurrentAccount(accountData: Misskey.entities.MeDetailed) {
|
||||||
export function updateCurrentAccountPartial(accountData: Partial<Misskey.entities.MeDetailed>) {
|
export function updateCurrentAccountPartial(accountData: Partial<Misskey.entities.MeDetailed>) {
|
||||||
if (!$i) return;
|
if (!$i) return;
|
||||||
for (const [key, value] of Object.entries(accountData)) {
|
for (const [key, value] of Object.entries(accountData)) {
|
||||||
$i[key] = value;
|
($i[key as keyof typeof accountData] as any) = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
store.set('accountInfos', { ...store.s.accountInfos, [host + '/' + $i.id]: $i });
|
store.set('accountInfos', { ...store.s.accountInfos, [host + '/' + $i.id]: $i });
|
||||||
|
|
|
||||||
|
|
@ -531,7 +531,7 @@ function getPostFormOptions(def: values.Value | undefined, call: (fn: values.VFn
|
||||||
export function registerAsUiLib(components: Ref<AsUiComponent>[], done: (root: Ref<AsUiRoot>) => void) {
|
export function registerAsUiLib(components: Ref<AsUiComponent>[], done: (root: Ref<AsUiRoot>) => void) {
|
||||||
type OptionsConverter<T extends AsUiComponent, C> = (def: values.Value | undefined, call: C) => Options<T>;
|
type OptionsConverter<T extends AsUiComponent, C> = (def: values.Value | undefined, call: C) => Options<T>;
|
||||||
|
|
||||||
const instances = {};
|
const instances = {} as Record<string, values.VObj>;
|
||||||
|
|
||||||
function createComponentInstance<T extends AsUiComponent, C>(
|
function createComponentInstance<T extends AsUiComponent, C>(
|
||||||
type: T['type'],
|
type: T['type'],
|
||||||
|
|
@ -555,7 +555,7 @@ export function registerAsUiLib(components: Ref<AsUiComponent>[], done: (root: R
|
||||||
const updates = getOptions(def, call);
|
const updates = getOptions(def, call);
|
||||||
for (const update of def.value.keys()) {
|
for (const update of def.value.keys()) {
|
||||||
if (!Object.hasOwn(updates, update)) continue;
|
if (!Object.hasOwn(updates, update)) continue;
|
||||||
component.value[update] = updates[update];
|
component.value[update] = updates[update as keyof Options<T>];
|
||||||
}
|
}
|
||||||
})],
|
})],
|
||||||
]));
|
]));
|
||||||
|
|
|
||||||
|
|
@ -90,6 +90,7 @@ export async function initAnalytics(instance: Misskey.entities.MetaDetailed) {
|
||||||
|
|
||||||
// Google Analytics
|
// Google Analytics
|
||||||
if (instance.googleAnalyticsMeasurementId) {
|
if (instance.googleAnalyticsMeasurementId) {
|
||||||
|
//@ts-expect-error Dynamic import
|
||||||
const { default: googleAnalytics } = await import('@analytics/google-analytics');
|
const { default: googleAnalytics } = await import('@analytics/google-analytics');
|
||||||
|
|
||||||
plugins.push(googleAnalytics({
|
plugins.push(googleAnalytics({
|
||||||
|
|
|
||||||
|
|
@ -115,7 +115,7 @@ watch(moderationNote, async () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
function resolve(resolvedAs) {
|
function resolve(resolvedAs: 'accept' | 'reject' | null) {
|
||||||
os.apiWithDialog('admin/resolve-abuse-user-report', {
|
os.apiWithDialog('admin/resolve-abuse-user-report', {
|
||||||
reportId: props.report.id,
|
reportId: props.report.id,
|
||||||
resolvedAs,
|
resolvedAs,
|
||||||
|
|
@ -132,7 +132,7 @@ function forward() {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function showMenu(ev: MouseEvent) {
|
function showMenu(ev: PointerEvent) {
|
||||||
os.popupMenu([{
|
os.popupMenu([{
|
||||||
icon: 'ti ti-hash',
|
icon: 'ti ti-hash',
|
||||||
text: 'Copy ID',
|
text: 'Copy ID',
|
||||||
|
|
|
||||||
|
|
@ -23,13 +23,13 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
</div>
|
</div>
|
||||||
<div :class="$style.body">
|
<div :class="$style.body">
|
||||||
<div :class="$style.header">
|
<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">
|
<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>
|
<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>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div :class="$style.description">{{ withDescription ? i18n.ts._achievements._types['_' + achievement.name].description : '???' }}</div>
|
<div :class="$style.description">{{ withDescription ? (i18n.ts._achievements._types as any)['_' + 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 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>
|
||||||
</div>
|
</div>
|
||||||
<template v-if="withLocked">
|
<template v-if="withLocked">
|
||||||
|
|
@ -54,7 +54,6 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import * as Misskey from 'misskey-js';
|
import * as Misskey from 'misskey-js';
|
||||||
import { onMounted, ref, computed } from 'vue';
|
import { onMounted, ref, computed } from 'vue';
|
||||||
import * as os from '@/os.js';
|
|
||||||
import { misskeyApi } from '@/utility/misskey-api.js';
|
import { misskeyApi } from '@/utility/misskey-api.js';
|
||||||
import { i18n } from '@/i18n.js';
|
import { i18n } from '@/i18n.js';
|
||||||
import { ACHIEVEMENT_TYPES, ACHIEVEMENT_BADGES, claimAchievement } from '@/utility/achievements.js';
|
import { ACHIEVEMENT_TYPES, ACHIEVEMENT_BADGES, claimAchievement } from '@/utility/achievements.js';
|
||||||
|
|
|
||||||
|
|
@ -64,13 +64,13 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { ref, computed } from 'vue';
|
import { ref, computed } from 'vue';
|
||||||
import type { Ref } from 'vue';
|
import type { Ref } from 'vue';
|
||||||
|
import type { AsUiComponent, AsUiRoot, AsUiPostFormButton } from '@/aiscript/ui.js';
|
||||||
import * as os from '@/os.js';
|
import * as os from '@/os.js';
|
||||||
import MkButton from '@/components/MkButton.vue';
|
import MkButton from '@/components/MkButton.vue';
|
||||||
import MkInput from '@/components/MkInput.vue';
|
import MkInput from '@/components/MkInput.vue';
|
||||||
import MkSwitch from '@/components/MkSwitch.vue';
|
import MkSwitch from '@/components/MkSwitch.vue';
|
||||||
import MkTextarea from '@/components/MkTextarea.vue';
|
import MkTextarea from '@/components/MkTextarea.vue';
|
||||||
import MkSelect from '@/components/MkSelect.vue';
|
import MkSelect from '@/components/MkSelect.vue';
|
||||||
import type { AsUiComponent, AsUiRoot, AsUiPostFormButton } from '@/aiscript/ui.js';
|
|
||||||
import MkFolder from '@/components/MkFolder.vue';
|
import MkFolder from '@/components/MkFolder.vue';
|
||||||
import MkPostForm from '@/components/MkPostForm.vue';
|
import MkPostForm from '@/components/MkPostForm.vue';
|
||||||
import { useMkSelect } from '@/composables/use-mkselect.js';
|
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,
|
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;
|
valueForSelect.value = v;
|
||||||
if ('onChange' in c && c.onChange) {
|
if ('onChange' in c && c.onChange) {
|
||||||
c.onChange(v as never);
|
c.onChange(v as never);
|
||||||
|
|
|
||||||
|
|
@ -183,7 +183,7 @@ async function init() {
|
||||||
|
|
||||||
init();
|
init();
|
||||||
|
|
||||||
function clickAddAccount(ev: MouseEvent) {
|
function clickAddAccount(ev: PointerEvent) {
|
||||||
selectedUser.value = null;
|
selectedUser.value = null;
|
||||||
|
|
||||||
os.popupMenu([{
|
os.popupMenu([{
|
||||||
|
|
|
||||||
|
|
@ -3,15 +3,14 @@
|
||||||
* SPDX-License-Identifier: AGPL-3.0-only
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* eslint-disable @typescript-eslint/explicit-function-return-type */
|
|
||||||
import { action } from 'storybook/actions';
|
import { action } from 'storybook/actions';
|
||||||
import { expect, userEvent, waitFor, within } from '@storybook/test';
|
import { expect, userEvent, waitFor, within } from '@storybook/test';
|
||||||
import type { StoryObj } from '@storybook/vue3';
|
|
||||||
import { HttpResponse, http } from 'msw';
|
import { HttpResponse, http } from 'msw';
|
||||||
import { userDetailed } from '../../.storybook/fakes.js';
|
import { userDetailed } from '../../.storybook/fakes.js';
|
||||||
import { commonHandlers } from '../../.storybook/mocks.js';
|
import { commonHandlers } from '../../.storybook/mocks.js';
|
||||||
import MkAutocomplete from './MkAutocomplete.vue';
|
import MkAutocomplete from './MkAutocomplete.vue';
|
||||||
import MkInput from './MkInput.vue';
|
import MkInput from './MkInput.vue';
|
||||||
|
import type { StoryObj } from '@storybook/vue3';
|
||||||
import { tick } from '@/utility/test-utils.js';
|
import { tick } from '@/utility/test-utils.js';
|
||||||
const common = {
|
const common = {
|
||||||
render(args) {
|
render(args) {
|
||||||
|
|
@ -81,7 +80,7 @@ export const User = {
|
||||||
...common.args,
|
...common.args,
|
||||||
type: 'user',
|
type: 'user',
|
||||||
},
|
},
|
||||||
async play({ canvasElement }) {
|
async play({ canvasElement }: { canvasElement: HTMLElement }) {
|
||||||
const canvas = within(canvasElement);
|
const canvas = within(canvasElement);
|
||||||
const input = canvas.getByRole('combobox');
|
const input = canvas.getByRole('combobox');
|
||||||
await waitFor(() => userEvent.hover(input));
|
await waitFor(() => userEvent.hover(input));
|
||||||
|
|
@ -114,7 +113,7 @@ export const Hashtag = {
|
||||||
...common.args,
|
...common.args,
|
||||||
type: 'hashtag',
|
type: 'hashtag',
|
||||||
},
|
},
|
||||||
async play({ canvasElement }) {
|
async play({ canvasElement }: { canvasElement: HTMLElement }) {
|
||||||
const canvas = within(canvasElement);
|
const canvas = within(canvasElement);
|
||||||
const input = canvas.getByRole('combobox');
|
const input = canvas.getByRole('combobox');
|
||||||
await waitFor(() => userEvent.hover(input));
|
await waitFor(() => userEvent.hover(input));
|
||||||
|
|
|
||||||
|
|
@ -50,7 +50,7 @@ import { emojilist, getEmojiName } from '@@/js/emojilist.js';
|
||||||
import { char2twemojiFilePath, char2fluentEmojiFilePath } from '@@/js/emoji-base.js';
|
import { char2twemojiFilePath, char2fluentEmojiFilePath } from '@@/js/emoji-base.js';
|
||||||
import { MFM_TAGS, MFM_PARAMS } from '@@/js/const.js';
|
import { MFM_TAGS, MFM_PARAMS } from '@@/js/const.js';
|
||||||
import type { EmojiDef } from '@/utility/search-emoji.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 { acct } from '@/filters/user.js';
|
||||||
import * as os from '@/os.js';
|
import * as os from '@/os.js';
|
||||||
import { misskeyApi } from '@/utility/misskey-api.js';
|
import { misskeyApi } from '@/utility/misskey-api.js';
|
||||||
|
|
@ -310,8 +310,8 @@ function exec() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function onMousedown(event: Event) {
|
function onMousedown(event: MouseEvent) {
|
||||||
if (!contains(rootEl.value, event.target) && (rootEl.value !== event.target)) props.close();
|
if (!elementContains(rootEl.value, event.target as Element) && (rootEl.value !== event.target)) props.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
function onKeydown(event: KeyboardEvent) {
|
function onKeydown(event: KeyboardEvent) {
|
||||||
|
|
|
||||||
|
|
@ -63,7 +63,7 @@ const props = defineProps<{
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
(ev: 'click', payload: MouseEvent): void;
|
(ev: 'click', payload: PointerEvent): void;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const el = useTemplateRef('el');
|
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);
|
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 origin = { x: circleCenterX, y: circleCenterY };
|
||||||
const dist1 = distance({ x: 0, y: 0 }, origin);
|
const dist1 = distance({ x: 0, y: 0 }, origin);
|
||||||
const dist2 = distance({ x: boxW, y: 0 }, origin);
|
const dist2 = distance({ x: boxW, y: 0 }, origin);
|
||||||
|
|
|
||||||
|
|
@ -84,7 +84,7 @@ const variable = computed(() => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const loaded = !!window[variable.value];
|
const loaded = !!(window as any)[variable.value];
|
||||||
|
|
||||||
const src = computed(() => {
|
const src = computed(() => {
|
||||||
switch (props.provider) {
|
switch (props.provider) {
|
||||||
|
|
@ -98,7 +98,7 @@ const src = computed(() => {
|
||||||
|
|
||||||
const scriptId = computed(() => `script-${props.provider}`);
|
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 () => {
|
watch(() => [props.instanceUrl, props.sitekey, props.secretKey], async () => {
|
||||||
// 変更があったときはリフレッシュと再レンダリングをしておかないと、変更後の値で再検証が出来ない
|
// 変更があったときはリフレッシュと再レンダリングをしておかないと、変更後の値で再検証が出来ない
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,6 @@ const props = withDefaults(defineProps<{
|
||||||
noGap?: boolean;
|
noGap?: boolean;
|
||||||
extractor?: ExtractorFunction<P, Misskey.entities.Channel>;
|
extractor?: ExtractorFunction<P, Misskey.entities.Channel>;
|
||||||
}>(), {
|
}>(), {
|
||||||
extractor: (item) => item,
|
extractor: (item: any) => item as Misskey.entities.Channel,
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
|
||||||
|
|
@ -94,8 +94,8 @@ const props = withDefaults(defineProps<{
|
||||||
|
|
||||||
const legendEl = useTemplateRef('legendEl');
|
const legendEl = useTemplateRef('legendEl');
|
||||||
|
|
||||||
const sum = (...arr) => arr.reduce((r, a) => r.map((b, i) => a[i] + b));
|
const sum = (...arr: number[][]) => arr.reduce((r, a) => r.map((b, i) => a[i] + b));
|
||||||
const negate = arr => arr.map(x => -x);
|
const negate = (arr: number[]) => arr.map((x) => -x);
|
||||||
|
|
||||||
const colors = {
|
const colors = {
|
||||||
blue: '#008FFB',
|
blue: '#008FFB',
|
||||||
|
|
@ -108,7 +108,7 @@ const colors = {
|
||||||
cyan: '#00e0e0',
|
cyan: '#00e0e0',
|
||||||
};
|
};
|
||||||
const colorSets = [colors.blue, colors.green, colors.yellow, colors.red, colors.purple];
|
const colorSets = [colors.blue, colors.green, colors.yellow, colors.red, colors.purple];
|
||||||
const getColor = (i) => {
|
const getColor = (i: number) => {
|
||||||
return colorSets[i % colorSets.length];
|
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);
|
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) => ({
|
return arr.map((v, i) => ({
|
||||||
x: getDate(i).getTime(),
|
x: getDate(i).getTime(),
|
||||||
y: v,
|
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 });
|
const raw = await misskeyApiGet('charts/notes', { limit: props.limit, span: props.span });
|
||||||
return {
|
return {
|
||||||
series: [{
|
series: [{
|
||||||
|
|
|
||||||
|
|
@ -20,9 +20,9 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { computed, onMounted, onUnmounted, ref } from 'vue';
|
import { computed, onMounted, onUnmounted, ref } from 'vue';
|
||||||
|
import { useInterval } from '@@/js/use-interval.js';
|
||||||
import MkPlusOneEffect from '@/components/MkPlusOneEffect.vue';
|
import MkPlusOneEffect from '@/components/MkPlusOneEffect.vue';
|
||||||
import * as os from '@/os.js';
|
import * as os from '@/os.js';
|
||||||
import { useInterval } from '@@/js/use-interval.js';
|
|
||||||
import * as game from '@/utility/clicker-game.js';
|
import * as game from '@/utility/clicker-game.js';
|
||||||
import number from '@/filters/number.js';
|
import number from '@/filters/number.js';
|
||||||
import { claimAchievement } from '@/utility/achievements.js';
|
import { claimAchievement } from '@/utility/achievements.js';
|
||||||
|
|
@ -32,7 +32,7 @@ const cookies = computed(() => saveData.value?.cookies);
|
||||||
const cps = ref(0);
|
const cps = ref(0);
|
||||||
const prevCookies = ref(0);
|
const prevCookies = ref(0);
|
||||||
|
|
||||||
function onClick(ev: MouseEvent) {
|
function onClick(ev: PointerEvent) {
|
||||||
const x = ev.clientX;
|
const x = ev.clientX;
|
||||||
const y = ev.clientY;
|
const y = ev.clientY;
|
||||||
const { dispose } = os.popup(MkPlusOneEffect, { x, y }, {
|
const { dispose } = os.popup(MkPlusOneEffect, { x, y }, {
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,7 @@ import XCode from '@/components/MkCode.core.vue';
|
||||||
|
|
||||||
const props = withDefaults(defineProps<{
|
const props = withDefaults(defineProps<{
|
||||||
modelValue: string | null;
|
modelValue: string | null;
|
||||||
lang: string;
|
lang?: string;
|
||||||
required?: boolean;
|
required?: boolean;
|
||||||
readonly?: boolean;
|
readonly?: boolean;
|
||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
|
|
@ -51,7 +51,7 @@ const props = withDefaults(defineProps<{
|
||||||
});
|
});
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
(ev: 'change', _ev: KeyboardEvent): void;
|
(ev: 'change', _ev: InputEvent): void;
|
||||||
(ev: 'keydown', _ev: KeyboardEvent): void;
|
(ev: 'keydown', _ev: KeyboardEvent): void;
|
||||||
(ev: 'enter'): void;
|
(ev: 'enter'): void;
|
||||||
(ev: 'update:modelValue', value: string): void;
|
(ev: 'update:modelValue', value: string): void;
|
||||||
|
|
@ -63,15 +63,17 @@ const focused = ref(false);
|
||||||
const changed = ref(false);
|
const changed = ref(false);
|
||||||
const inputEl = useTemplateRef('inputEl');
|
const inputEl = useTemplateRef('inputEl');
|
||||||
|
|
||||||
const focus = () => inputEl.value?.focus();
|
function focus() {
|
||||||
|
inputEl.value?.focus();
|
||||||
|
}
|
||||||
|
|
||||||
const onInput = (ev) => {
|
function onInput(ev: InputEvent) {
|
||||||
v.value = ev.target?.value ?? v.value;
|
v.value = (inputEl.value?.value) ?? '';
|
||||||
changed.value = true;
|
changed.value = true;
|
||||||
emit('change', ev);
|
emit('change', ev);
|
||||||
};
|
}
|
||||||
|
|
||||||
const onKeydown = (ev: KeyboardEvent) => {
|
function onKeydown(ev: KeyboardEvent) {
|
||||||
if (ev.isComposing || ev.key === 'Process' || ev.keyCode === 229) return;
|
if (ev.isComposing || ev.key === 'Process' || ev.keyCode === 229) return;
|
||||||
|
|
||||||
emit('keydown', ev);
|
emit('keydown', ev);
|
||||||
|
|
@ -102,12 +104,12 @@ const onKeydown = (ev: KeyboardEvent) => {
|
||||||
});
|
});
|
||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
const updated = () => {
|
function updated() {
|
||||||
changed.value = false;
|
changed.value = false;
|
||||||
emit('update:modelValue', v.value);
|
emit('update:modelValue', v.value);
|
||||||
};
|
}
|
||||||
|
|
||||||
const debouncedUpdated = debounce(1000, updated);
|
const debouncedUpdated = debounce(1000, updated);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,11 +3,9 @@
|
||||||
* SPDX-License-Identifier: AGPL-3.0-only
|
* 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 { userEvent, within } from '@storybook/test';
|
||||||
import MkContextMenu from './MkContextMenu.vue';
|
import MkContextMenu from './MkContextMenu.vue';
|
||||||
|
import type { StoryObj } from '@storybook/vue3';
|
||||||
import * as os from '@/os.js';
|
import * as os from '@/os.js';
|
||||||
export const Empty = {
|
export const Empty = {
|
||||||
render(args) {
|
render(args) {
|
||||||
|
|
@ -25,7 +23,7 @@ export const Empty = {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
onContextmenu(ev: MouseEvent) {
|
onContextmenu(ev: PointerEvent) {
|
||||||
os.contextMenu(args.items, ev);
|
os.contextMenu(args.items, ev);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -21,13 +21,13 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
import { onMounted, onBeforeUnmount, useTemplateRef, ref } from 'vue';
|
import { onMounted, onBeforeUnmount, useTemplateRef, ref } from 'vue';
|
||||||
import MkMenu from './MkMenu.vue';
|
import MkMenu from './MkMenu.vue';
|
||||||
import type { MenuItem } from '@/types/menu.js';
|
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 { prefer } from '@/preferences.js';
|
||||||
import * as os from '@/os.js';
|
import * as os from '@/os.js';
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
items: MenuItem[];
|
items: MenuItem[];
|
||||||
ev: MouseEvent;
|
ev: PointerEvent;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
|
|
@ -75,8 +75,8 @@ onBeforeUnmount(() => {
|
||||||
window.document.body.removeEventListener('mousedown', onMousedown);
|
window.document.body.removeEventListener('mousedown', onMousedown);
|
||||||
});
|
});
|
||||||
|
|
||||||
function onMousedown(evt: Event) {
|
function onMousedown(evt: MouseEvent) {
|
||||||
if (!contains(rootEl.value, evt.target) && (rootEl.value !== evt.target)) emit('closed');
|
if (!elementContains(rootEl.value, evt.target as Element) && (rootEl.value !== evt.target)) emit('closed');
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -64,7 +64,7 @@ const isDragging = ref(false);
|
||||||
|
|
||||||
const title = computed(() => `${props.file.name}\n${props.file.type} ${bytes(props.file.size)}`);
|
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);
|
os.contextMenu(getDriveFileMenu(props.file, props.folder), ev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -57,7 +57,7 @@ const props = withDefaults(defineProps<{
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
(ev: 'chosen', v: Misskey.entities.DriveFolder): void;
|
(ev: 'chosen', v: Misskey.entities.DriveFolder): void;
|
||||||
(ev: 'unchose', 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: 'dragstart'): void;
|
||||||
(ev: 'dragend'): void;
|
(ev: 'dragend'): void;
|
||||||
}>();
|
}>();
|
||||||
|
|
@ -277,7 +277,7 @@ function setAsUploadFolder() {
|
||||||
prefer.commit('uploadFolder', props.folder.id);
|
prefer.commit('uploadFolder', props.folder.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
function onContextmenu(ev: MouseEvent) {
|
function onContextmenu(ev: PointerEvent) {
|
||||||
let menu: MenuItem[];
|
let menu: MenuItem[];
|
||||||
menu = [{
|
menu = [{
|
||||||
text: i18n.ts.openInWindow,
|
text: i18n.ts.openInWindow,
|
||||||
|
|
|
||||||
|
|
@ -139,7 +139,9 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
primary
|
primary
|
||||||
rounded
|
rounded
|
||||||
@click="fetchMoreFiles"
|
@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="filesPaginator.items.value.length == 0 && foldersPaginator.items.value.length == 0 && !fetching" :class="$style.empty">
|
||||||
<div v-if="draghover">{{ i18n.ts.dropHereToUpload }}</div>
|
<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) {
|
if (ev.shiftKey) {
|
||||||
isEditMode.value = true;
|
isEditMode.value = true;
|
||||||
}
|
}
|
||||||
|
|
@ -563,7 +565,7 @@ function cd(target?: Misskey.entities.DriveFolder | Misskey.entities.DriveFolder
|
||||||
folder.value = folderToMove;
|
folder.value = folderToMove;
|
||||||
hierarchyFolders.value = [];
|
hierarchyFolders.value = [];
|
||||||
|
|
||||||
const dive = folderToDive => {
|
const dive = (folderToDive: Misskey.entities.DriveFolder) => {
|
||||||
hierarchyFolders.value.unshift(folderToDive);
|
hierarchyFolders.value.unshift(folderToDive);
|
||||||
if (folderToDive.parent) dive(folderToDive.parent);
|
if (folderToDive.parent) dive(folderToDive.parent);
|
||||||
};
|
};
|
||||||
|
|
@ -689,11 +691,11 @@ function getMenu() {
|
||||||
return menu;
|
return menu;
|
||||||
}
|
}
|
||||||
|
|
||||||
function showMenu(ev: MouseEvent) {
|
function showMenu(ev: PointerEvent) {
|
||||||
os.popupMenu(getMenu(), (ev.currentTarget ?? ev.target ?? undefined) as HTMLElement | undefined);
|
os.popupMenu(getMenu(), (ev.currentTarget ?? ev.target ?? undefined) as HTMLElement | undefined);
|
||||||
}
|
}
|
||||||
|
|
||||||
function onContextmenu(ev: MouseEvent) {
|
function onContextmenu(ev: PointerEvent) {
|
||||||
os.contextMenu(getMenu(), ev);
|
os.contextMenu(getMenu(), ev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -62,8 +62,8 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { ref, computed } from 'vue';
|
import { ref, computed } from 'vue';
|
||||||
import type { Ref } from 'vue';
|
|
||||||
import { getEmojiName } from '@@/js/emojilist.js';
|
import { getEmojiName } from '@@/js/emojilist.js';
|
||||||
|
import type { Ref } from 'vue';
|
||||||
import type { CustomEmojiFolderTree } from '@@/js/emojilist.js';
|
import type { CustomEmojiFolderTree } from '@@/js/emojilist.js';
|
||||||
import { i18n } from '@/i18n.js';
|
import { i18n } from '@/i18n.js';
|
||||||
import { customEmojis } from '@/custom-emojis.js';
|
import { customEmojis } from '@/custom-emojis.js';
|
||||||
|
|
@ -78,7 +78,7 @@ const props = defineProps<{
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const emit = defineEmits<{
|
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);
|
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);
|
const shown = ref(!!props.initialShown);
|
||||||
|
|
||||||
/** @see MkEmojiPicker.vue */
|
/** @see MkEmojiPicker.vue */
|
||||||
function computeButtonTitle(ev: MouseEvent): void {
|
function computeButtonTitle(ev: PointerEvent): void {
|
||||||
const elm = ev.target as HTMLElement;
|
const elm = ev.target as HTMLElement;
|
||||||
const emoji = elm.dataset.emoji as string;
|
const emoji = elm.dataset.emoji as string;
|
||||||
elm.title = getEmojiName(emoji);
|
elm.title = getEmojiName(emoji);
|
||||||
}
|
}
|
||||||
|
|
||||||
function nestedChosen(emoji: string, ev: MouseEvent) {
|
function nestedChosen(emoji: string, ev: PointerEvent) {
|
||||||
emit('chosen', emoji, ev);
|
emit('chosen', emoji, ev);
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
|
||||||
|
|
@ -412,13 +412,13 @@ function getDef(emoji: string): string | Misskey.entities.EmojiSimple | UnicodeE
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @see MkEmojiPicker.section.vue */
|
/** @see MkEmojiPicker.section.vue */
|
||||||
function computeButtonTitle(ev: MouseEvent): void {
|
function computeButtonTitle(ev: PointerEvent): void {
|
||||||
const elm = ev.target as HTMLElement;
|
const elm = ev.target as HTMLElement;
|
||||||
const emoji = elm.dataset.emoji as string;
|
const emoji = elm.dataset.emoji as string;
|
||||||
elm.title = getEmojiName(emoji);
|
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;
|
const el = ev && (ev.currentTarget ?? ev.target) as HTMLElement | null | undefined;
|
||||||
if (el && prefer.s.animation) {
|
if (el && prefer.s.animation) {
|
||||||
const rect = el.getBoundingClientRect();
|
const rect = el.getBoundingClientRect();
|
||||||
|
|
|
||||||
|
|
@ -45,7 +45,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
<template #key>{{ i18n.ts.permission }}</template>
|
<template #key>{{ i18n.ts.permission }}</template>
|
||||||
<template #value>
|
<template #value>
|
||||||
<ul v-if="extension.meta.permissions && extension.meta.permissions.length > 0" :class="$style.extInstallerKVList">
|
<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>
|
</ul>
|
||||||
<template v-else>{{ i18n.ts.none }}</template>
|
<template v-else>{{ i18n.ts.none }}</template>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
||||||
|
|
@ -169,7 +169,7 @@ function afterLeave(el: Element) {
|
||||||
let pageId = pageFolderTeleportCount.value;
|
let pageId = pageFolderTeleportCount.value;
|
||||||
pageFolderTeleportCount.value += 1000;
|
pageFolderTeleportCount.value += 1000;
|
||||||
|
|
||||||
async function toggle(ev: MouseEvent) {
|
async function toggle(ev: PointerEvent) {
|
||||||
if (asPage && !opened.value) {
|
if (asPage && !opened.value) {
|
||||||
pageId++;
|
pageId++;
|
||||||
const { dispose } = await popup(MkFolderPage, {
|
const { dispose } = await popup(MkFolderPage, {
|
||||||
|
|
|
||||||
|
|
@ -50,7 +50,7 @@ if (props.fileId) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function selectButton(ev: MouseEvent) {
|
function selectButton(ev: PointerEvent) {
|
||||||
selectFile({
|
selectFile({
|
||||||
anchorElement: ev.currentTarget ?? ev.target,
|
anchorElement: ev.currentTarget ?? ev.target,
|
||||||
multiple: false,
|
multiple: false,
|
||||||
|
|
|
||||||
|
|
@ -125,8 +125,7 @@ async function renderChart() {
|
||||||
data: format(values) as any,
|
data: format(values) as any,
|
||||||
borderWidth: 0,
|
borderWidth: 0,
|
||||||
borderRadius: 3,
|
borderRadius: 3,
|
||||||
backgroundColor(c) {
|
backgroundColor(c: any) {
|
||||||
// @ts-expect-error TS(2339)
|
|
||||||
const value = c.dataset.data[c.dataIndex].v as number;
|
const value = c.dataset.data[c.dataIndex].v as number;
|
||||||
let a = (value - min) / max;
|
let a = (value - min) / max;
|
||||||
if (value !== 0) { // 0でない限りは完全に不可視にはしない
|
if (value !== 0) { // 0でない限りは完全に不可視にはしない
|
||||||
|
|
@ -195,7 +194,7 @@ async function renderChart() {
|
||||||
font: {
|
font: {
|
||||||
size: 9,
|
size: 9,
|
||||||
},
|
},
|
||||||
callback: (value, index, values) => ['', 'Mon', '', 'Wed', '', 'Fri', ''][value],
|
callback: (value, index, values) => ['', 'Mon', '', 'Wed', '', 'Fri', ''][value as any],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -95,7 +95,7 @@ watch(layers, async () => {
|
||||||
}
|
}
|
||||||
}, { deep: true });
|
}, { deep: true });
|
||||||
|
|
||||||
function addEffect(ev: MouseEvent) {
|
function addEffect(ev: PointerEvent) {
|
||||||
os.popupMenu(Object.entries(FXS).map(([id, fx]) => ({
|
os.popupMenu(Object.entries(FXS).map(([id, fx]) => ({
|
||||||
text: fx.uiDefinition.name,
|
text: fx.uiDefinition.name,
|
||||||
action: () => {
|
action: () => {
|
||||||
|
|
@ -219,7 +219,7 @@ watch(enabled, () => {
|
||||||
|
|
||||||
const penMode = ref<'fill' | 'blur' | 'pixelate' | null>(null);
|
const penMode = ref<'fill' | 'blur' | 'pixelate' | null>(null);
|
||||||
|
|
||||||
function showPenMenu(ev: MouseEvent) {
|
function showPenMenu(ev: PointerEvent) {
|
||||||
os.popupMenu([{
|
os.popupMenu([{
|
||||||
text: i18n.ts._imageEffector._fxs.fill,
|
text: i18n.ts._imageEffector._fxs.fill,
|
||||||
action: () => {
|
action: () => {
|
||||||
|
|
|
||||||
|
|
@ -88,7 +88,7 @@ const props = defineProps<{
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
(ev: 'change', _ev: KeyboardEvent): void;
|
(ev: 'change', _ev: InputEvent): void;
|
||||||
(ev: 'keydown', _ev: KeyboardEvent): void;
|
(ev: 'keydown', _ev: KeyboardEvent): void;
|
||||||
(ev: 'enter', _ev: KeyboardEvent): void;
|
(ev: 'enter', _ev: KeyboardEvent): void;
|
||||||
(ev: 'update:modelValue', value: ModelValueType<T>): void;
|
(ev: 'update:modelValue', value: ModelValueType<T>): void;
|
||||||
|
|
@ -111,10 +111,9 @@ const height =
|
||||||
let autocompleteWorker: Autocomplete | null = null;
|
let autocompleteWorker: Autocomplete | null = null;
|
||||||
|
|
||||||
const focus = () => inputEl.value?.focus();
|
const focus = () => inputEl.value?.focus();
|
||||||
const onInput = (event: Event) => {
|
const onInput = (event: InputEvent) => {
|
||||||
const ev = event as KeyboardEvent;
|
|
||||||
changed.value = true;
|
changed.value = true;
|
||||||
emit('change', ev);
|
emit('change', event);
|
||||||
};
|
};
|
||||||
const onKeydown = (ev: KeyboardEvent) => {
|
const onKeydown = (ev: KeyboardEvent) => {
|
||||||
if (ev.isComposing || ev.key === 'Process' || ev.keyCode === 229) return;
|
if (ev.isComposing || ev.key === 'Process' || ev.keyCode === 229) return;
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@ misskeyApiGet('charts/instance', { host: props.instance.host, limit: 16 + 1, spa
|
||||||
chartValues.value = res.requests.received;
|
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';
|
return getProxiedImageUrlNullable(instance.iconUrl, 'preview') ?? getProxiedImageUrlNullable(instance.faviconUrl, 'preview') ?? '/client-assets/dummy.png';
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
|
||||||
|
|
@ -57,10 +57,10 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { onMounted, computed, useTemplateRef } from 'vue';
|
import { onMounted, computed, useTemplateRef } from 'vue';
|
||||||
import { Chart } from 'chart.js';
|
import { Chart } from 'chart.js';
|
||||||
import MkSelect from '@/components/MkSelect.vue';
|
|
||||||
import type { MkSelectItem, ItemOption } 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 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 { useChartTooltip } from '@/composables/use-chart-tooltip.js';
|
||||||
import { $i } from '@/i.js';
|
import { $i } from '@/i.js';
|
||||||
import * as os from '@/os.js';
|
import * as os from '@/os.js';
|
||||||
|
|
@ -172,7 +172,14 @@ const { handler: externalTooltipHandler2 } = useChartTooltip({
|
||||||
position: 'middle',
|
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, {
|
const chartInstance = new Chart(chartEl, {
|
||||||
type: 'doughnut',
|
type: 'doughnut',
|
||||||
data: {
|
data: {
|
||||||
|
|
@ -198,8 +205,8 @@ function createDoughnut(chartEl, tooltip, data) {
|
||||||
onClick: (ev) => {
|
onClick: (ev) => {
|
||||||
if (ev.native == null) return;
|
if (ev.native == null) return;
|
||||||
const hit = chartInstance.getElementsAtEventForMode(ev.native, 'nearest', { intersect: true }, false)[0];
|
const hit = chartInstance.getElementsAtEventForMode(ev.native, 'nearest', { intersect: true }, false)[0];
|
||||||
if (hit && data[hit.index].onClick) {
|
if (hit != null) {
|
||||||
data[hit.index].onClick();
|
data[hit.index].onClick?.();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
plugins: {
|
plugins: {
|
||||||
|
|
@ -223,16 +230,9 @@ function createDoughnut(chartEl, tooltip, data) {
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
misskeyApiGet('federation/stats', { limit: 30 }).then(fedStats => {
|
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 => ({
|
const subs: ChartData = fedStats.topSubInstances.map(x => ({
|
||||||
name: x.host,
|
name: x.host,
|
||||||
color: x.themeColor,
|
color: x.themeColor ?? '#888888',
|
||||||
value: x.followersCount,
|
value: x.followersCount,
|
||||||
onClick: () => {
|
onClick: () => {
|
||||||
os.pageWindow(`/instance-info/${x.host}`);
|
os.pageWindow(`/instance-info/${x.host}`);
|
||||||
|
|
@ -245,11 +245,11 @@ onMounted(() => {
|
||||||
value: fedStats.otherFollowersCount,
|
value: fedStats.otherFollowersCount,
|
||||||
});
|
});
|
||||||
|
|
||||||
createDoughnut(subDoughnutEl.value, externalTooltipHandler1, subs);
|
if (subDoughnutEl.value != null) createDoughnut(subDoughnutEl.value, externalTooltipHandler1, subs);
|
||||||
|
|
||||||
const pubs: ChartData = fedStats.topPubInstances.map(x => ({
|
const pubs: ChartData = fedStats.topPubInstances.map(x => ({
|
||||||
name: x.host,
|
name: x.host,
|
||||||
color: x.themeColor,
|
color: x.themeColor ?? '#888888',
|
||||||
value: x.followingCount,
|
value: x.followingCount,
|
||||||
onClick: () => {
|
onClick: () => {
|
||||||
os.pageWindow(`/instance-info/${x.host}`);
|
os.pageWindow(`/instance-info/${x.host}`);
|
||||||
|
|
@ -262,7 +262,7 @@ onMounted(() => {
|
||||||
value: fedStats.otherFollowingCount,
|
value: fedStats.otherFollowingCount,
|
||||||
});
|
});
|
||||||
|
|
||||||
createDoughnut(pubDoughnutEl.value, externalTooltipHandler2, pubs);
|
if (pubDoughnutEl.value != null) createDoughnut(pubDoughnutEl.value, externalTooltipHandler2, pubs);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
|
||||||
|
|
@ -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="szkkfdyq _popup _shadow" :class="{ asDrawer: type === 'drawer' }" :style="{ maxHeight: maxHeight ? maxHeight + 'px' : '' }">
|
||||||
<div class="main">
|
<div class="main">
|
||||||
<template v-for="item in items" :key="item.text">
|
<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>
|
<i class="icon" :class="item.icon"></i>
|
||||||
<div class="text">{{ item.text }}</div>
|
<div class="text">{{ item.text }}</div>
|
||||||
<span v-if="item.indicate && item.indicateValue" class="_indicateCounter indicatorWithValue">{{ item.indicateValue }}</span>
|
<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>
|
<span v-else-if="item.indicate" class="indicator _blink"><i class="_indicatorCircle"></i></span>
|
||||||
</button>
|
</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>
|
<i class="icon" :class="item.icon"></i>
|
||||||
<div class="text">{{ item.text }}</div>
|
<div class="text">{{ item.text }}</div>
|
||||||
<span v-if="item.indicate && item.indicateValue" class="_indicateCounter indicatorWithValue">{{ item.indicateValue }}</span>
|
<span v-if="item.indicate && item.indicateValue" class="_indicateCounter indicatorWithValue">{{ item.indicateValue }}</span>
|
||||||
|
|
|
||||||
|
|
@ -100,7 +100,7 @@ const url = computed(() => (props.raw || prefer.s.loadRawImages)
|
||||||
: props.image.thumbnailUrl!,
|
: props.image.thumbnailUrl!,
|
||||||
);
|
);
|
||||||
|
|
||||||
async function reveal(ev: MouseEvent) {
|
async function reveal(ev: PointerEvent) {
|
||||||
if (!props.controls) {
|
if (!props.controls) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -123,7 +123,7 @@ watch(() => props.image, (newImage) => {
|
||||||
immediate: true,
|
immediate: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
function showMenu(ev: MouseEvent) {
|
function showMenu(ev: PointerEvent) {
|
||||||
const menuItems: MenuItem[] = [];
|
const menuItems: MenuItem[] = [];
|
||||||
|
|
||||||
menuItems.push({
|
menuItems.push({
|
||||||
|
|
|
||||||
|
|
@ -190,7 +190,7 @@ async function reveal() {
|
||||||
// Menu
|
// Menu
|
||||||
const menuShowing = ref(false);
|
const menuShowing = ref(false);
|
||||||
|
|
||||||
function showMenu(ev: MouseEvent) {
|
function showMenu(ev: PointerEvent) {
|
||||||
const menu: MenuItem[] = [
|
const menu: MenuItem[] = [
|
||||||
// TODO: 再生キューに追加
|
// TODO: 再生キューに追加
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -316,7 +316,7 @@ function onItemMouseLeave() {
|
||||||
if (childCloseTimer) window.clearTimeout(childCloseTimer);
|
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 children: MenuItem[] = Object.keys(item.options).map<MenuRadioOption>(key => {
|
||||||
const value = item.options[key];
|
const value = item.options[key];
|
||||||
return {
|
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();
|
ev.stopPropagation();
|
||||||
|
|
||||||
const children: MenuItem[] = await (async () => {
|
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);
|
fn(ev);
|
||||||
|
|
||||||
if (!doClose) return;
|
if (!doClose) return;
|
||||||
|
|
|
||||||
|
|
@ -184,8 +184,8 @@ const align = () => {
|
||||||
const width = content.value!.offsetWidth;
|
const width = content.value!.offsetWidth;
|
||||||
const height = content.value!.offsetHeight;
|
const height = content.value!.offsetHeight;
|
||||||
|
|
||||||
let left;
|
let left = 0;
|
||||||
let top;
|
let top = 0;
|
||||||
|
|
||||||
const x = anchorRect.left + (fixed.value ? 0 : window.scrollX);
|
const x = anchorRect.left + (fixed.value ? 0 : window.scrollX);
|
||||||
const y = anchorRect.top + (fixed.value ? 0 : window.scrollY);
|
const y = anchorRect.top + (fixed.value ? 0 : window.scrollY);
|
||||||
|
|
|
||||||
|
|
@ -594,7 +594,7 @@ function toggleReact() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function onContextmenu(ev: MouseEvent): void {
|
function onContextmenu(ev: PointerEvent): void {
|
||||||
if (props.mock) {
|
if (props.mock) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
</div>
|
</div>
|
||||||
<MkNoteSub v-for="note in conversation" :key="note.id" :class="$style.replyToMore" :note="note"/>
|
<MkNoteSub v-for="note in conversation" :key="note.id" :class="$style.replyToMore" :note="note"/>
|
||||||
</div>
|
</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">
|
<div v-if="isRenote" :class="$style.renote">
|
||||||
<MkAvatar :class="$style.renoteAvatar" :user="note.user" link preview/>
|
<MkAvatar :class="$style.renoteAvatar" :user="note.user" link preview/>
|
||||||
<i class="ti ti-repeat" style="margin-right: 4px;"></i>
|
<i class="ti ti-repeat" style="margin-right: 4px;"></i>
|
||||||
|
|
@ -111,7 +111,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="appearNote.files && appearNote.files.length > 0">
|
<div v-if="appearNote.files && appearNote.files.length > 0">
|
||||||
<MkMediaList ref="galleryEl" :mediaList="appearNote.files"/>
|
<MkMediaList :mediaList="appearNote.files"/>
|
||||||
</div>
|
</div>
|
||||||
<MkPoll
|
<MkPoll
|
||||||
v-if="appearNote.poll"
|
v-if="appearNote.poll"
|
||||||
|
|
@ -144,7 +144,6 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
:myReaction="$appearNote.myReaction"
|
:myReaction="$appearNote.myReaction"
|
||||||
:noteId="appearNote.id"
|
:noteId="appearNote.id"
|
||||||
:maxNumber="16"
|
:maxNumber="16"
|
||||||
@mockUpdateMyReaction="emitUpdReaction"
|
|
||||||
/>
|
/>
|
||||||
<button class="_button" :class="$style.noteFooterButton" @click="reply()">
|
<button class="_button" :class="$style.noteFooterButton" @click="reply()">
|
||||||
<i class="ti ti-arrow-back-up"></i>
|
<i class="ti ti-arrow-back-up"></i>
|
||||||
|
|
@ -233,7 +232,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<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 mfm from 'mfm-js';
|
||||||
import * as Misskey from 'misskey-js';
|
import * as Misskey from 'misskey-js';
|
||||||
import { isLink } from '@@/js/is-link.js';
|
import { isLink } from '@@/js/is-link.js';
|
||||||
|
|
@ -324,7 +323,6 @@ const renoteButton = useTemplateRef('renoteButton');
|
||||||
const renoteTime = useTemplateRef('renoteTime');
|
const renoteTime = useTemplateRef('renoteTime');
|
||||||
const reactButton = useTemplateRef('reactButton');
|
const reactButton = useTemplateRef('reactButton');
|
||||||
const clipButton = useTemplateRef('clipButton');
|
const clipButton = useTemplateRef('clipButton');
|
||||||
const galleryEl = useTemplateRef('galleryEl');
|
|
||||||
const isMyRenote = $i && ($i.id === note.userId);
|
const isMyRenote = $i && ($i.id === note.userId);
|
||||||
const showContent = ref(false);
|
const showContent = ref(false);
|
||||||
const isDeleted = ref(false);
|
const isDeleted = ref(false);
|
||||||
|
|
@ -358,7 +356,7 @@ const keymap = {
|
||||||
if (!prefer.s.showClipButtonInNoteFooter) return;
|
if (!prefer.s.showClipButtonInNoteFooter) return;
|
||||||
clip();
|
clip();
|
||||||
},
|
},
|
||||||
'o': () => galleryEl.value?.openGallery(),
|
//'o': () => galleryEl.value?.openGallery(),
|
||||||
'v|enter': () => {
|
'v|enter': () => {
|
||||||
if (appearNote.cw != null) {
|
if (appearNote.cw != null) {
|
||||||
showContent.value = !showContent.value;
|
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 (ev.target && isLink(ev.target as HTMLElement)) return;
|
||||||
if (window.getSelection()?.toString() !== '') return;
|
if (window.getSelection()?.toString() !== '') return;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -121,7 +121,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
{{ notification.invitation.room.name }}
|
{{ notification.invitation.room.name }}
|
||||||
</div>
|
</div>
|
||||||
<MkA v-else-if="notification.type === 'achievementEarned'" :class="$style.text" to="/my/achievements">
|
<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>
|
||||||
<MkA v-else-if="notification.type === 'exportCompleted'" :class="$style.text" :to="`/my/drive/file/${notification.fileId}`">
|
<MkA v-else-if="notification.type === 'exportCompleted'" :class="$style.text" :to="`/my/drive/file/${notification.fileId}`">
|
||||||
{{ i18n.ts.showFile }}
|
{{ i18n.ts.showFile }}
|
||||||
|
|
|
||||||
|
|
@ -42,7 +42,7 @@ const props = defineProps<{
|
||||||
value: unknown;
|
value: unknown;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const collapsed = reactive({});
|
const collapsed = reactive<Record<string, boolean>>({});
|
||||||
|
|
||||||
if (isObject(props.value)) {
|
if (isObject(props.value)) {
|
||||||
for (const key in props.value) {
|
for (const key in props.value) {
|
||||||
|
|
|
||||||
|
|
@ -88,7 +88,7 @@ const shouldEnableInfiniteScroll = computed(() => {
|
||||||
return prefer.r.enableInfiniteScroll.value && !props.forceDisableInfiniteScroll;
|
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 (ev.target && isLink(ev.target as HTMLElement)) return;
|
||||||
if (window.getSelection()?.toString() !== '') return;
|
if (window.getSelection()?.toString() !== '') return;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -110,7 +110,7 @@ if (props.modelValue.expiresAt) {
|
||||||
expiration.value = 'infinite';
|
expiration.value = 'infinite';
|
||||||
}
|
}
|
||||||
|
|
||||||
function onInput(i, value) {
|
function onInput(i: number, value: string) {
|
||||||
choices.value[i] = value;
|
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);
|
choices.value = choices.value.filter((_, _i) => _i !== i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -55,7 +55,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
<div :class="$style.visibleUsers">
|
<div :class="$style.visibleUsers">
|
||||||
<span v-for="u in visibleUsers" :key="u.id" :class="$style.visibleUser">
|
<span v-for="u in visibleUsers" :key="u.id" :class="$style.visibleUser">
|
||||||
<MkAcct :user="u"/>
|
<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>
|
</span>
|
||||||
<button class="_buttonPrimary" style="padding: 4px; border-radius: 8px;" @click="addVisibleUser"><i class="ti ti-plus ti-fw"></i></button>
|
<button class="_buttonPrimary" style="padding: 4px; border-radius: 8px;" @click="addVisibleUser"><i class="ti ti-plus ti-fw"></i></button>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -476,6 +476,7 @@ function togglePoll() {
|
||||||
}
|
}
|
||||||
|
|
||||||
function addTag(tag: string) {
|
function addTag(tag: string) {
|
||||||
|
if (textareaEl.value == null) return;
|
||||||
insertTextAtCursor(textareaEl.value, ` #${tag} `);
|
insertTextAtCursor(textareaEl.value, ` #${tag} `);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -486,7 +487,7 @@ function focus() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function chooseFileFromPc(ev: MouseEvent) {
|
function chooseFileFromPc(ev: PointerEvent) {
|
||||||
if (props.mock) return;
|
if (props.mock) return;
|
||||||
|
|
||||||
os.chooseFileFromPc({ multiple: true }).then(files => {
|
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;
|
if (props.mock) return;
|
||||||
|
|
||||||
chooseDriveFile({ multiple: true }).then(driveFiles => {
|
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);
|
files.value = files.value.filter(x => x.id !== id);
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateFileSensitive(file, sensitive) {
|
function updateFileSensitive(file: Misskey.entities.DriveFile, isSensitive: boolean) {
|
||||||
if (props.mock) {
|
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;
|
files.value[files.value.findIndex(x => x.id === file.id)].name = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -704,8 +705,8 @@ function addVisibleUser() {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function removeVisibleUser(user) {
|
function removeVisibleUser(id: string) {
|
||||||
visibleUsers.value = erase(user, visibleUsers.value);
|
visibleUsers.value = visibleUsers.value.filter(u => u.id !== id);
|
||||||
}
|
}
|
||||||
|
|
||||||
function clear() {
|
function clear() {
|
||||||
|
|
@ -742,7 +743,8 @@ const pastedFileName = 'yyyy-MM-dd HH-mm-ss [{{number}}]';
|
||||||
|
|
||||||
async function onPaste(ev: ClipboardEvent) {
|
async function onPaste(ev: ClipboardEvent) {
|
||||||
if (props.mock) return;
|
if (props.mock) return;
|
||||||
if (!ev.clipboardData) return;
|
if (ev.clipboardData == null) return;
|
||||||
|
if (textareaEl.value == null) return;
|
||||||
|
|
||||||
let pastedFiles: File[] = [];
|
let pastedFiles: File[] = [];
|
||||||
for (const { item, i } of Array.from(ev.clipboardData.items, (data, x) => ({ item: data, i: x }))) {
|
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/')) {
|
if (!renoteTargetNote.value && !quoteId.value && paste.startsWith(url + '/notes/')) {
|
||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
|
|
||||||
os.confirm({
|
const { canceled } = await os.confirm({
|
||||||
type: 'info',
|
type: 'info',
|
||||||
text: i18n.ts.quoteQuestion,
|
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) {
|
if (paste.length > 1000) {
|
||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
os.confirm({
|
|
||||||
|
const { canceled } = await os.confirm({
|
||||||
type: 'info',
|
type: 'info',
|
||||||
text: i18n.ts.attachAsFileQuestion,
|
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) {
|
function onDragover(ev: DragEvent) {
|
||||||
if (!ev.dataTransfer.items[0]) return;
|
if (ev.dataTransfer == null) return;
|
||||||
|
if (ev.dataTransfer.items[0] == null) return;
|
||||||
|
|
||||||
const isFile = ev.dataTransfer.items[0].kind === 'file';
|
const isFile = ev.dataTransfer.items[0].kind === 'file';
|
||||||
if (isFile || checkDragDataType(ev, ['driveFiles'])) {
|
if (isFile || checkDragDataType(ev, ['driveFiles'])) {
|
||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
|
|
@ -852,13 +857,32 @@ function onDrop(ev: DragEvent): void {
|
||||||
//#endregion
|
//#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() {
|
function saveDraft() {
|
||||||
if (props.instant || props.mock) return;
|
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] = {
|
draftsData[draftKey.value] = {
|
||||||
updatedAt: new Date(),
|
updatedAt: new Date().toISOString(),
|
||||||
data: {
|
data: {
|
||||||
text: text.value,
|
text: text.value,
|
||||||
useCw: useCw.value,
|
useCw: useCw.value,
|
||||||
|
|
@ -874,15 +898,15 @@ function saveDraft() {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
miLocalStorage.setItem('drafts', JSON.stringify(draftData));
|
miLocalStorage.setItem('drafts', JSON.stringify(draftsData));
|
||||||
}
|
}
|
||||||
|
|
||||||
function deleteDraft() {
|
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: {
|
async function saveServerDraft(options: {
|
||||||
|
|
@ -924,8 +948,8 @@ async function uploadFiles() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function post(ev?: MouseEvent) {
|
async function post(ev?: PointerEvent) {
|
||||||
if (ev) {
|
if (ev != null) {
|
||||||
const el = (ev.currentTarget ?? ev.target) as HTMLElement | null;
|
const el = (ev.currentTarget ?? ev.target) as HTMLElement | null;
|
||||||
|
|
||||||
if (el && prefer.s.animation) {
|
if (el && prefer.s.animation) {
|
||||||
|
|
@ -1138,11 +1162,12 @@ function cancel() {
|
||||||
|
|
||||||
function insertMention() {
|
function insertMention() {
|
||||||
os.selectUser({ localOnly: localOnly.value, includeSelf: true }).then(user => {
|
os.selectUser({ localOnly: localOnly.value, includeSelf: true }).then(user => {
|
||||||
|
if (textareaEl.value == null) return;
|
||||||
insertTextAtCursor(textareaEl.value, '@' + Misskey.acct.toString(user) + ' ');
|
insertTextAtCursor(textareaEl.value, '@' + Misskey.acct.toString(user) + ' ');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async function insertEmoji(ev: MouseEvent) {
|
async function insertEmoji(ev: PointerEvent) {
|
||||||
textAreaReadOnly.value = true;
|
textAreaReadOnly.value = true;
|
||||||
const target = ev.currentTarget ?? ev.target;
|
const target = ev.currentTarget ?? ev.target;
|
||||||
if (target == null) return;
|
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;
|
if (textareaEl.value == null) return;
|
||||||
let pos = textareaEl.value.selectionStart ?? 0;
|
let pos = textareaEl.value.selectionStart ?? 0;
|
||||||
let posEnd = textareaEl.value.selectionEnd ?? text.value.length;
|
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 => ({
|
os.popupMenu(postFormActions.map(action => ({
|
||||||
text: action.title,
|
text: action.title,
|
||||||
action: () => {
|
action: () => {
|
||||||
|
|
@ -1222,7 +1247,7 @@ function showActions(ev: MouseEvent) {
|
||||||
|
|
||||||
const postAccount = ref<Misskey.entities.UserDetailed | null>(null);
|
const postAccount = ref<Misskey.entities.UserDetailed | null>(null);
|
||||||
|
|
||||||
async function openAccountMenu(ev: MouseEvent) {
|
async function openAccountMenu(ev: PointerEvent) {
|
||||||
if (props.mock) return;
|
if (props.mock) return;
|
||||||
|
|
||||||
function showDraftsDialog(scheduled: boolean) {
|
function showDraftsDialog(scheduled: boolean) {
|
||||||
|
|
@ -1312,12 +1337,12 @@ async function openAccountMenu(ev: MouseEvent) {
|
||||||
}, { type: 'divider' }, ...items], (ev.currentTarget ?? ev.target ?? undefined) as HTMLElement | undefined);
|
}, { 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);
|
const menu = uploader.getMenu(item);
|
||||||
os.popupMenu(menu, ev.currentTarget ?? ev.target);
|
os.popupMenu(menu, ev.currentTarget ?? ev.target);
|
||||||
}
|
}
|
||||||
|
|
||||||
function showPerUploadItemMenuViaContextmenu(item: UploaderItem, ev: MouseEvent) {
|
function showPerUploadItemMenuViaContextmenu(item: UploaderItem, ev: PointerEvent) {
|
||||||
const menu = uploader.getMenu(item);
|
const menu = uploader.getMenu(item);
|
||||||
os.contextMenu(menu, ev);
|
os.contextMenu(menu, ev);
|
||||||
}
|
}
|
||||||
|
|
@ -1392,8 +1417,8 @@ onMounted(() => {
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
// 書きかけの投稿を復元
|
// 書きかけの投稿を復元
|
||||||
if (!props.instant && !props.mention && !props.specified && !props.mock) {
|
if (!props.instant && !props.mention && !props.specified && !props.mock) {
|
||||||
const draft = JSON.parse(miLocalStorage.getItem('drafts') ?? '{}')[draftKey.value];
|
const draft = JSON.parse(miLocalStorage.getItem('drafts') ?? '{}')[draftKey.value] as StoredDrafts[string] | undefined;
|
||||||
if (draft) {
|
if (draft != null) {
|
||||||
text.value = draft.data.text;
|
text.value = draft.data.text;
|
||||||
useCw.value = draft.data.useCw;
|
useCw.value = draft.data.useCw;
|
||||||
cw.value = draft.data.cw;
|
cw.value = draft.data.cw;
|
||||||
|
|
|
||||||
|
|
@ -97,7 +97,7 @@ async function detachAndDeleteMedia(file: Misskey.entities.DriveFile) {
|
||||||
globalEvents.emit('driveFilesDeleted', [file]);
|
globalEvents.emit('driveFilesDeleted', [file]);
|
||||||
}
|
}
|
||||||
|
|
||||||
function toggleSensitive(file) {
|
function toggleSensitive(file: Misskey.entities.DriveFile) {
|
||||||
if (mock) {
|
if (mock) {
|
||||||
emit('changeSensitive', file, !file.isSensitive);
|
emit('changeSensitive', file, !file.isSensitive);
|
||||||
return;
|
return;
|
||||||
|
|
@ -111,7 +111,7 @@ function toggleSensitive(file) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async function rename(file) {
|
async function rename(file: Misskey.entities.DriveFile) {
|
||||||
if (mock) return;
|
if (mock) return;
|
||||||
|
|
||||||
const { canceled, result } = await os.inputText({
|
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;
|
if (menuShowing) return;
|
||||||
|
|
||||||
const isImage = file.type.startsWith('image/');
|
const isImage = file.type.startsWith('image/');
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,7 @@ const props = withDefaults(defineProps<{
|
||||||
const isAccountOverrided = ref(prefer.isAccountOverrided(props.k));
|
const isAccountOverrided = ref(prefer.isAccountOverrided(props.k));
|
||||||
const isSyncEnabled = ref(prefer.isSyncEnabled(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(() => {
|
const i = window.setInterval(() => {
|
||||||
isAccountOverrided.value = prefer.isAccountOverrided(props.k);
|
isAccountOverrided.value = prefer.isAccountOverrided(props.k);
|
||||||
isSyncEnabled.value = prefer.isSyncEnabled(props.k);
|
isSyncEnabled.value = prefer.isSyncEnabled(props.k);
|
||||||
|
|
|
||||||
|
|
@ -89,7 +89,7 @@ const selectUser = async () => {
|
||||||
await os.selectUser();
|
await os.selectUser();
|
||||||
};
|
};
|
||||||
|
|
||||||
const openMenu = async (ev: Event) => {
|
const openMenu = async (ev: PointerEvent) => {
|
||||||
os.popupMenu([{
|
os.popupMenu([{
|
||||||
type: 'label',
|
type: 'label',
|
||||||
text: 'Fruits',
|
text: 'Fruits',
|
||||||
|
|
|
||||||
|
|
@ -153,7 +153,7 @@ async function toggleReaction() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function menu(ev) {
|
async function menu(ev: PointerEvent) {
|
||||||
let menuItems: MenuItem[] = [];
|
let menuItems: MenuItem[] = [];
|
||||||
|
|
||||||
if (canGetInfo.value) {
|
if (canGetInfo.value) {
|
||||||
|
|
|
||||||
|
|
@ -32,11 +32,11 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
import * as Misskey from 'misskey-js';
|
import * as Misskey from 'misskey-js';
|
||||||
import { inject, watch, ref } from 'vue';
|
import { inject, watch, ref } from 'vue';
|
||||||
import { TransitionGroup } from 'vue';
|
import { TransitionGroup } from 'vue';
|
||||||
|
import { isSupportedEmoji } from '@@/js/emojilist.js';
|
||||||
import XReaction from '@/components/MkReactionsViewer.reaction.vue';
|
import XReaction from '@/components/MkReactionsViewer.reaction.vue';
|
||||||
import { $i } from '@/i.js';
|
import { $i } from '@/i.js';
|
||||||
import { prefer } from '@/preferences.js';
|
import { prefer } from '@/preferences.js';
|
||||||
import { customEmojisMap } from '@/custom-emojis.js';
|
import { customEmojisMap } from '@/custom-emojis.js';
|
||||||
import { isSupportedEmoji } from '@@/js/emojilist.js';
|
|
||||||
import { DI } from '@/di.js';
|
import { DI } from '@/di.js';
|
||||||
|
|
||||||
const props = withDefaults(defineProps<{
|
const props = withDefaults(defineProps<{
|
||||||
|
|
@ -60,8 +60,8 @@ const initialReactions = new Set(Object.keys(props.reactions));
|
||||||
const _reactions = ref<[string, number][]>([]);
|
const _reactions = ref<[string, number][]>([]);
|
||||||
const hasMoreReactions = ref(false);
|
const hasMoreReactions = ref(false);
|
||||||
|
|
||||||
if (props.myReaction && !Object.keys(_reactions.value).includes(props.myReaction)) {
|
if (props.myReaction != null && !(props.myReaction in props.reactions)) {
|
||||||
_reactions.value[props.myReaction] = props.reactions[props.myReaction];
|
_reactions.value.push([props.myReaction, props.reactions[props.myReaction]]);
|
||||||
}
|
}
|
||||||
|
|
||||||
function onMockToggleReaction(emoji: string, count: number) {
|
function onMockToggleReaction(emoji: string, count: number) {
|
||||||
|
|
|
||||||
|
|
@ -98,7 +98,7 @@ async function renderChart() {
|
||||||
data: data as any,
|
data: data as any,
|
||||||
borderWidth: 0,
|
borderWidth: 0,
|
||||||
borderRadius: 3,
|
borderRadius: 3,
|
||||||
backgroundColor(c) {
|
backgroundColor(c: any) {
|
||||||
const v = c.dataset.data[c.dataIndex] as unknown as typeof data[0];
|
const v = c.dataset.data[c.dataIndex] as unknown as typeof data[0];
|
||||||
const value = v.v;
|
const value = v.v;
|
||||||
const m = max(v.y);
|
const m = max(v.y);
|
||||||
|
|
@ -179,7 +179,7 @@ async function renderChart() {
|
||||||
enabled: false,
|
enabled: false,
|
||||||
callbacks: {
|
callbacks: {
|
||||||
title(context) {
|
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)));
|
return getYYYYMMDD(new Date(new Date(v.y).getTime() + (v.x * 86400000)));
|
||||||
},
|
},
|
||||||
label(context) {
|
label(context) {
|
||||||
|
|
|
||||||
|
|
@ -55,9 +55,9 @@ import MkModalWindow from '@/components/MkModalWindow.vue';
|
||||||
import MkLoading from '@/components/global/MkLoading.vue';
|
import MkLoading from '@/components/global/MkLoading.vue';
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
(ev: 'done', value: Misskey.entities.Role[]),
|
(ev: 'done', value: Misskey.entities.Role[]): void;
|
||||||
(ev: 'close'),
|
(ev: 'close'): void;
|
||||||
(ev: 'closed'),
|
(ev: 'closed'): void;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const props = withDefaults(defineProps<{
|
const props = withDefaults(defineProps<{
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@ import MkModalWindow from '@/components/MkModalWindow.vue';
|
||||||
import MkServerSetupWizard from '@/components/MkServerSetupWizard.vue';
|
import MkServerSetupWizard from '@/components/MkServerSetupWizard.vue';
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
(ev: 'closed'),
|
(ev: 'closed'): void;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const windowEl = useTemplateRef('windowEl');
|
const windowEl = useTemplateRef('windowEl');
|
||||||
|
|
|
||||||
|
|
@ -78,7 +78,7 @@ const props = withDefaults(defineProps<{
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
(ev: 'usernameSubmitted', v: string): void;
|
(ev: 'usernameSubmitted', v: string): void;
|
||||||
(ev: 'passkeyClick', v: MouseEvent): void;
|
(ev: 'passkeyClick', v: PointerEvent): void;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const host = toUnicode(configHost);
|
const host = toUnicode(configHost);
|
||||||
|
|
|
||||||
|
|
@ -25,11 +25,11 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
<script setup lang="ts" generic="T extends string">
|
<script setup lang="ts" generic="T extends string">
|
||||||
import { toRefs } from 'vue';
|
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 MkTagItem from '@/components/MkTagItem.vue';
|
||||||
import MkButton from '@/components/MkButton.vue';
|
import MkButton from '@/components/MkButton.vue';
|
||||||
import type { MenuItem } from '@/types/menu.js';
|
|
||||||
import * as os from '@/os.js';
|
import * as os from '@/os.js';
|
||||||
import type { SortOrder } from '@/components/MkSortOrderEditor.define.js';
|
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
(ev: 'update', sortOrders: SortOrder<T>[]): void;
|
(ev: 'update', sortOrders: SortOrder<T>[]): void;
|
||||||
|
|
@ -55,7 +55,7 @@ function onToggleSortOrderButtonClicked(order: SortOrder<T>) {
|
||||||
emitOrder(currentOrders.value);
|
emitOrder(currentOrders.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
function onAddSortOrderButtonClicked(ev: MouseEvent) {
|
function onAddSortOrderButtonClicked(ev: PointerEvent) {
|
||||||
const menuItems: MenuItem[] = props.baseOrderKeyNames
|
const menuItems: MenuItem[] = props.baseOrderKeyNames
|
||||||
.filter(baseKey => !currentOrders.value.map(it => it.key).includes(baseKey))
|
.filter(baseKey => !currentOrders.value.map(it => it.key).includes(baseKey))
|
||||||
.map(it => {
|
.map(it => {
|
||||||
|
|
|
||||||
|
|
@ -88,7 +88,7 @@ function setPosition() {
|
||||||
bodyEl.value.style.top = data.top + 'px';
|
bodyEl.value.style.top = data.top + 'px';
|
||||||
}
|
}
|
||||||
|
|
||||||
let loopHandler;
|
let loopHandler: number | null = null;
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
|
|
@ -104,7 +104,7 @@ onMounted(() => {
|
||||||
});
|
});
|
||||||
|
|
||||||
onUnmounted(() => {
|
onUnmounted(() => {
|
||||||
window.cancelAnimationFrame(loopHandler);
|
if (loopHandler != null) window.cancelAnimationFrame(loopHandler);
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -350,13 +350,12 @@ function connectChannel() {
|
||||||
connections.main = stream.useChannel('main');
|
connections.main = stream.useChannel('main');
|
||||||
connections.main.on('mention', prepend);
|
connections.main.on('mention', prepend);
|
||||||
} else if (props.src === 'directs') {
|
} else if (props.src === 'directs') {
|
||||||
const onNote = note => {
|
connections.main = stream.useChannel('main');
|
||||||
|
connections.main.on('mention', note => {
|
||||||
if (note.visibility === 'specified') {
|
if (note.visibility === 'specified') {
|
||||||
prepend(note);
|
prepend(note);
|
||||||
}
|
}
|
||||||
};
|
});
|
||||||
connections.main = stream.useChannel('main');
|
|
||||||
connections.main.on('mention', onNote);
|
|
||||||
} else if (props.src === 'list') {
|
} else if (props.src === 'list') {
|
||||||
if (props.list == null) return;
|
if (props.list == null) return;
|
||||||
connections.userList = stream.useChannel('userList', {
|
connections.userList = stream.useChannel('userList', {
|
||||||
|
|
|
||||||
|
|
@ -137,8 +137,8 @@ watch(visibility, () => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
function onNotification(notification) {
|
function onNotification(notification: Misskey.entities.Notification) {
|
||||||
const isMuted = props.excludeTypes ? props.excludeTypes.includes(notification.type) : false;
|
const isMuted = props.excludeTypes ? props.excludeTypes.includes(notification.type as typeof notificationTypes[number]) : false;
|
||||||
if (isMuted || window.document.visibilityState === 'visible') {
|
if (isMuted || window.document.visibilityState === 'visible') {
|
||||||
if (store.s.realtimeMode) {
|
if (store.s.realtimeMode) {
|
||||||
useStream().send('readNotification');
|
useStream().send('readNotification');
|
||||||
|
|
|
||||||
|
|
@ -82,7 +82,7 @@ export type SuperMenuDef = {
|
||||||
text: string;
|
text: string;
|
||||||
danger?: boolean;
|
danger?: boolean;
|
||||||
active?: boolean;
|
active?: boolean;
|
||||||
action: (ev: MouseEvent) => Awaitable<void>;
|
action: (ev: PointerEvent) => Awaitable<void>;
|
||||||
} | {
|
} | {
|
||||||
type?: 'link';
|
type?: 'link';
|
||||||
to: string;
|
to: string;
|
||||||
|
|
|
||||||
|
|
@ -245,7 +245,7 @@ onMounted(async () => {
|
||||||
secret.value = res.secret;
|
secret.value = res.secret;
|
||||||
isActive.value = res.isActive;
|
isActive.value = res.isActive;
|
||||||
for (const ev of Object.keys(events.value)) {
|
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
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
} catch (ex: any) {
|
} catch (ex: any) {
|
||||||
|
|
|
||||||
|
|
@ -50,7 +50,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
export type Tab<K = string> = {
|
export type Tab<K = string> = {
|
||||||
key: K;
|
key: K;
|
||||||
onClick?: (ev: MouseEvent) => void;
|
onClick?: (ev: PointerEvent) => void;
|
||||||
iconOnly?: boolean;
|
iconOnly?: boolean;
|
||||||
title: string;
|
title: string;
|
||||||
icon?: string;
|
icon?: string;
|
||||||
|
|
@ -74,7 +74,7 @@ const props = withDefaults(defineProps<{
|
||||||
});
|
});
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
(ev: 'tabClick', key: string);
|
(ev: 'tabClick', key: string): void;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const tab = defineModel<T['key']>('tab');
|
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);
|
emit('tabClick', t.key);
|
||||||
|
|
||||||
if (t.onClick) {
|
if (t.onClick) {
|
||||||
|
|
|
||||||
|
|
@ -17,8 +17,8 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
import MkButton from '@/components/MkButton.vue';
|
import MkButton from '@/components/MkButton.vue';
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
(ev: 'click', payload: MouseEvent): void;
|
(ev: 'click', payload: PointerEvent): void;
|
||||||
(ev: 'exButtonClick', payload: MouseEvent): void;
|
(ev: 'exButtonClick', payload: PointerEvent): void;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
defineProps<{
|
defineProps<{
|
||||||
|
|
|
||||||
|
|
@ -63,7 +63,7 @@ const props = defineProps<{
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
(ev: 'change', _ev: KeyboardEvent): void;
|
(ev: 'change', _ev: InputEvent): void;
|
||||||
(ev: 'keydown', _ev: KeyboardEvent): void;
|
(ev: 'keydown', _ev: KeyboardEvent): void;
|
||||||
(ev: 'enter'): void;
|
(ev: 'enter'): void;
|
||||||
(ev: 'update:modelValue', value: string): void;
|
(ev: 'update:modelValue', value: string): void;
|
||||||
|
|
@ -79,12 +79,16 @@ const inputEl = useTemplateRef('inputEl');
|
||||||
const preview = ref(false);
|
const preview = ref(false);
|
||||||
let autocompleteWorker: Autocomplete | null = null;
|
let autocompleteWorker: Autocomplete | null = null;
|
||||||
|
|
||||||
const focus = () => inputEl.value?.focus();
|
function focus() {
|
||||||
const onInput = (ev) => {
|
inputEl.value?.focus();
|
||||||
|
}
|
||||||
|
|
||||||
|
function onInput(ev: InputEvent) {
|
||||||
changed.value = true;
|
changed.value = true;
|
||||||
emit('change', ev);
|
emit('change', ev);
|
||||||
};
|
}
|
||||||
const onKeydown = (ev: KeyboardEvent) => {
|
|
||||||
|
function onKeydown(ev: KeyboardEvent) {
|
||||||
if (ev.isComposing || ev.key === 'Process' || ev.keyCode === 229) return;
|
if (ev.isComposing || ev.key === 'Process' || ev.keyCode === 229) return;
|
||||||
|
|
||||||
emit('keydown', ev);
|
emit('keydown', ev);
|
||||||
|
|
@ -102,12 +106,12 @@ const onKeydown = (ev: KeyboardEvent) => {
|
||||||
});
|
});
|
||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
const updated = () => {
|
function updated() {
|
||||||
changed.value = false;
|
changed.value = false;
|
||||||
emit('update:modelValue', v.value ?? '');
|
emit('update:modelValue', v.value ?? '');
|
||||||
};
|
}
|
||||||
|
|
||||||
const debouncedUpdated = debounce(1000, updated);
|
const debouncedUpdated = debounce(1000, updated);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -33,12 +33,12 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
<MkButton inline @click="enableAll">{{ i18n.ts.enableAll }}</MkButton>
|
<MkButton inline @click="enableAll">{{ i18n.ts.enableAll }}</MkButton>
|
||||||
</div>
|
</div>
|
||||||
<div class="_gaps_s">
|
<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>
|
||||||
<div v-if="iAmAdmin" :class="$style.adminPermissions">
|
<div v-if="iAmAdmin" :class="$style.adminPermissions">
|
||||||
<div :class="$style.adminPermissionsHeader"><b>{{ i18n.ts.adminPermission }}</b></div>
|
<div :class="$style.adminPermissionsHeader"><b>{{ i18n.ts.adminPermission }}</b></div>
|
||||||
<div class="_gaps_s">
|
<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>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -102,8 +102,8 @@ function ok(): void {
|
||||||
emit('done', {
|
emit('done', {
|
||||||
name: name.value,
|
name: name.value,
|
||||||
permissions: [
|
permissions: [
|
||||||
...Object.keys(permissionSwitches.value).filter(p => permissionSwitches.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]) : []),
|
...(iAmAdmin ? Object.keys(permissionSwitchesForAdmin.value).filter(p => permissionSwitchesForAdmin.value[p as (typeof Misskey.permissions)[number]]) : []),
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
dialog.value?.close();
|
dialog.value?.close();
|
||||||
|
|
@ -111,22 +111,22 @@ function ok(): void {
|
||||||
|
|
||||||
function disableAll(): void {
|
function disableAll(): void {
|
||||||
for (const p in permissionSwitches.value) {
|
for (const p in permissionSwitches.value) {
|
||||||
permissionSwitches.value[p] = false;
|
permissionSwitches.value[p as (typeof Misskey.permissions)[number]] = false;
|
||||||
}
|
}
|
||||||
if (iAmAdmin) {
|
if (iAmAdmin) {
|
||||||
for (const p in permissionSwitchesForAdmin.value) {
|
for (const p in permissionSwitchesForAdmin.value) {
|
||||||
permissionSwitchesForAdmin.value[p] = false;
|
permissionSwitchesForAdmin.value[p as (typeof Misskey.permissions)[number]] = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function enableAll(): void {
|
function enableAll(): void {
|
||||||
for (const p in permissionSwitches.value) {
|
for (const p in permissionSwitches.value) {
|
||||||
permissionSwitches.value[p] = true;
|
permissionSwitches.value[p as (typeof Misskey.permissions)[number]] = true;
|
||||||
}
|
}
|
||||||
if (iAmAdmin) {
|
if (iAmAdmin) {
|
||||||
for (const p in permissionSwitchesForAdmin.value) {
|
for (const p in permissionSwitchesForAdmin.value) {
|
||||||
permissionSwitchesForAdmin.value[p] = true;
|
permissionSwitchesForAdmin.value[p as (typeof Misskey.permissions)[number]] = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -71,7 +71,7 @@ function setPosition() {
|
||||||
el.value.style.top = data.top + 'px';
|
el.value.style.top = data.top + 'px';
|
||||||
}
|
}
|
||||||
|
|
||||||
let loopHandler;
|
let loopHandler: number | null = null;
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
|
|
@ -87,7 +87,7 @@ onMounted(() => {
|
||||||
});
|
});
|
||||||
|
|
||||||
onUnmounted(() => {
|
onUnmounted(() => {
|
||||||
window.cancelAnimationFrame(loopHandler);
|
if (loopHandler != null) window.cancelAnimationFrame(loopHandler);
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -74,7 +74,7 @@ const exampleNote = reactive<Misskey.entities.Note>({
|
||||||
});
|
});
|
||||||
const onceReacted = ref<boolean>(false);
|
const onceReacted = ref<boolean>(false);
|
||||||
|
|
||||||
function addReaction(emoji) {
|
function addReaction(emoji: string) {
|
||||||
onceReacted.value = true;
|
onceReacted.value = true;
|
||||||
emit('reacted');
|
emit('reacted');
|
||||||
doNotification(emoji);
|
doNotification(emoji);
|
||||||
|
|
@ -96,7 +96,7 @@ function doNotification(emoji: string): void {
|
||||||
globalEvents.emit('clientNotification', notification);
|
globalEvents.emit('clientNotification', notification);
|
||||||
}
|
}
|
||||||
|
|
||||||
function removeReaction(emoji) {
|
function removeReaction(emoji: string) {
|
||||||
delete exampleNote.reactions[emoji];
|
delete exampleNote.reactions[emoji];
|
||||||
exampleNote.myReaction = undefined;
|
exampleNote.myReaction = undefined;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -166,17 +166,17 @@ async function done() {
|
||||||
dialog.value?.close();
|
dialog.value?.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
async function chooseFile(ev: MouseEvent) {
|
async function chooseFile(ev: PointerEvent) {
|
||||||
const newFiles = await os.chooseFileFromPc({ multiple: true });
|
const newFiles = await os.chooseFileFromPc({ multiple: true });
|
||||||
uploader.addFiles(newFiles);
|
uploader.addFiles(newFiles);
|
||||||
}
|
}
|
||||||
|
|
||||||
function showPerItemMenu(item: UploaderItem, ev: MouseEvent) {
|
function showPerItemMenu(item: UploaderItem, ev: PointerEvent) {
|
||||||
const menu = uploader.getMenu(item);
|
const menu = uploader.getMenu(item);
|
||||||
os.popupMenu(menu, ev.currentTarget ?? ev.target);
|
os.popupMenu(menu, ev.currentTarget ?? ev.target);
|
||||||
}
|
}
|
||||||
|
|
||||||
function showPerItemMenuViaContextmenu(item: UploaderItem, ev: MouseEvent) {
|
function showPerItemMenuViaContextmenu(item: UploaderItem, ev: PointerEvent) {
|
||||||
const menu = uploader.getMenu(item);
|
const menu = uploader.getMenu(item);
|
||||||
os.contextMenu(menu, ev);
|
os.contextMenu(menu, ev);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -57,18 +57,18 @@ const props = defineProps<{
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
(ev: 'showMenu', item: UploaderItem, event: MouseEvent): void;
|
(ev: 'showMenu', item: UploaderItem, event: PointerEvent): void;
|
||||||
(ev: 'showMenuViaContextmenu', item: UploaderItem, event: MouseEvent): 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 (ev.target && isLink(ev.target as HTMLElement)) return;
|
||||||
if (window.getSelection()?.toString() !== '') return;
|
if (window.getSelection()?.toString() !== '') return;
|
||||||
|
|
||||||
emit('showMenuViaContextmenu', item, ev);
|
emit('showMenuViaContextmenu', item, ev);
|
||||||
}
|
}
|
||||||
|
|
||||||
function onThumbnailClick(item: UploaderItem, ev: MouseEvent) {
|
function onThumbnailClick(item: UploaderItem, ev: PointerEvent) {
|
||||||
// TODO: preview when item is image
|
// TODO: preview when item is image
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ const props = withDefaults(defineProps<{
|
||||||
noGap?: boolean;
|
noGap?: boolean;
|
||||||
extractor?: ExtractorFunction<P, Misskey.entities.UserDetailed>;
|
extractor?: ExtractorFunction<P, Misskey.entities.UserDetailed>;
|
||||||
}>(), {
|
}>(), {
|
||||||
extractor: (item) => item,
|
extractor: (item: any) => item as Misskey.entities.UserDetailed,
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -90,7 +90,7 @@ const top = ref(0);
|
||||||
const left = ref(0);
|
const left = ref(0);
|
||||||
const error = ref(false);
|
const error = ref(false);
|
||||||
|
|
||||||
function showMenu(ev: MouseEvent) {
|
function showMenu(ev: PointerEvent) {
|
||||||
if (user.value == null) return;
|
if (user.value == null) return;
|
||||||
const { menu, cleanup } = getUserMenu(user.value);
|
const { menu, cleanup } = getUserMenu(user.value);
|
||||||
os.popupMenu(menu, ev.currentTarget ?? ev.target).finally(cleanup);
|
os.popupMenu(menu, ev.currentTarget ?? ev.target).finally(cleanup);
|
||||||
|
|
|
||||||
|
|
@ -66,7 +66,7 @@ watch(description, () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
async function setAvatar(ev) {
|
async function setAvatar(ev: PointerEvent) {
|
||||||
const files = await os.chooseFileFromPc({ multiple: false });
|
const files = await os.chooseFileFromPc({ multiple: false });
|
||||||
const file = files[0];
|
const file = files[0];
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -46,7 +46,7 @@ async function renderChart() {
|
||||||
return new Date(y, m, d - ago);
|
return new Date(y, m, d - ago);
|
||||||
};
|
};
|
||||||
|
|
||||||
const format = (arr) => {
|
const format = (arr: number[]) => {
|
||||||
return arr.map((v, i) => ({
|
return arr.map((v, i) => ({
|
||||||
x: getDate(i).getTime(),
|
x: getDate(i).getTime(),
|
||||||
y: v,
|
y: v,
|
||||||
|
|
|
||||||
|
|
@ -94,7 +94,7 @@ function signup() {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function showMenu(ev: MouseEvent) {
|
function showMenu(ev: PointerEvent) {
|
||||||
openInstanceMenu(ev);
|
openInstanceMenu(ev);
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
|
||||||
|
|
@ -26,8 +26,8 @@ const props = defineProps<{
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
(ev: 'done');
|
(ev: 'done'): void;
|
||||||
(ev: 'closed');
|
(ev: 'closed'): void;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
function done() {
|
function done() {
|
||||||
|
|
|
||||||
|
|
@ -387,7 +387,7 @@ onMounted(async () => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
function chooseFile(ev: MouseEvent) {
|
function chooseFile(ev: PointerEvent) {
|
||||||
selectFile({
|
selectFile({
|
||||||
anchorElement: ev.currentTarget ?? ev.target,
|
anchorElement: ev.currentTarget ?? ev.target,
|
||||||
multiple: false,
|
multiple: false,
|
||||||
|
|
|
||||||
|
|
@ -350,7 +350,7 @@ async function save() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function addLayer(ev: MouseEvent) {
|
function addLayer(ev: PointerEvent) {
|
||||||
os.popupMenu([{
|
os.popupMenu([{
|
||||||
text: i18n.ts._watermarkEditor.text,
|
text: i18n.ts._watermarkEditor.text,
|
||||||
action: () => {
|
action: () => {
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
@ok="save()"
|
@ok="save()"
|
||||||
@closed="emit('closed')"
|
@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>
|
<MkPreviewWithControls>
|
||||||
<template #preview>
|
<template #preview>
|
||||||
|
|
|
||||||
|
|
@ -24,12 +24,12 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
<div :class="[$style.widget, $style.customizeContainer]" data-cy-customize-container>
|
<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.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>
|
<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>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</MkDraggable>
|
</MkDraggable>
|
||||||
</template>
|
</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>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
@ -47,6 +47,7 @@ export type DefaultStoredWidget = {
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { computed } from 'vue';
|
import { computed } from 'vue';
|
||||||
import { isLink } from '@@/js/is-link.js';
|
import { isLink } from '@@/js/is-link.js';
|
||||||
|
import type { Component } from 'vue';
|
||||||
import { genId } from '@/utility/id.js';
|
import { genId } from '@/utility/id.js';
|
||||||
import MkSelect from '@/components/MkSelect.vue';
|
import MkSelect from '@/components/MkSelect.vue';
|
||||||
import MkButton from '@/components/MkButton.vue';
|
import MkButton from '@/components/MkButton.vue';
|
||||||
|
|
@ -64,13 +65,13 @@ const props = defineProps<{
|
||||||
|
|
||||||
const _widgetDefs = computed(() => {
|
const _widgetDefs = computed(() => {
|
||||||
if (instance.federation === 'none') {
|
if (instance.federation === 'none') {
|
||||||
return widgetDefs.filter(x => !federationWidgets.includes(x));
|
return widgetDefs.filter(x => !federationWidgets.includes(x as any));
|
||||||
} else {
|
} else {
|
||||||
return widgetDefs;
|
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<{
|
const emit = defineEmits<{
|
||||||
(ev: 'updateWidgets', widgets: Widget[]): void;
|
(ev: 'updateWidgets', widgets: Widget[]): void;
|
||||||
|
|
@ -80,10 +81,11 @@ const emit = defineEmits<{
|
||||||
(ev: 'exit'): void;
|
(ev: 'exit'): void;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const widgetRefs = {};
|
const widgetRefs = {} as Record<string, Component & { configure: () => void }>;
|
||||||
const configWidget = (id: string) => {
|
|
||||||
|
function configWidget(id: string) {
|
||||||
widgetRefs[id].configure();
|
widgetRefs[id].configure();
|
||||||
};
|
}
|
||||||
|
|
||||||
const {
|
const {
|
||||||
model: widgetAdderSelected,
|
model: widgetAdderSelected,
|
||||||
|
|
@ -93,7 +95,7 @@ const {
|
||||||
initialValue: null,
|
initialValue: null,
|
||||||
});
|
});
|
||||||
|
|
||||||
const addWidget = () => {
|
function addWidget() {
|
||||||
if (widgetAdderSelected.value == null) return;
|
if (widgetAdderSelected.value == null) return;
|
||||||
|
|
||||||
emit('addWidget', {
|
emit('addWidget', {
|
||||||
|
|
@ -103,23 +105,25 @@ const addWidget = () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
widgetAdderSelected.value = null;
|
widgetAdderSelected.value = null;
|
||||||
};
|
}
|
||||||
const removeWidget = (widget) => {
|
|
||||||
emit('removeWidget', widget);
|
|
||||||
};
|
|
||||||
const updateWidget = (id: Widget['id'], data: Widget['data']) => {
|
|
||||||
emit('updateWidget', { id, data });
|
|
||||||
};
|
|
||||||
|
|
||||||
function onContextmenu(widget: Widget, ev: MouseEvent) {
|
function removeWidget(widget: Widget) {
|
||||||
|
emit('removeWidget', widget);
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateWidget(id: Widget['id'], data: Widget['data']) {
|
||||||
|
emit('updateWidget', { id, data });
|
||||||
|
}
|
||||||
|
|
||||||
|
function onContextmenu(widget: Widget, ev: PointerEvent) {
|
||||||
const element = ev.target as HTMLElement | null;
|
const element = ev.target as HTMLElement | null;
|
||||||
if (element && isLink(element)) return;
|
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;
|
if (window.getSelection()?.toString() !== '') return;
|
||||||
|
|
||||||
os.contextMenu([{
|
os.contextMenu([{
|
||||||
type: 'label',
|
type: 'label',
|
||||||
text: i18n.ts._widgets[widget.name],
|
text: i18n.ts._widgets[widget.name as typeof widgetDefs[number]],
|
||||||
}, {
|
}, {
|
||||||
icon: 'ti ti-settings',
|
icon: 'ti ti-settings',
|
||||||
text: i18n.ts.settings,
|
text: i18n.ts.settings,
|
||||||
|
|
|
||||||
|
|
@ -55,7 +55,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { onBeforeUnmount, onMounted, provide, useTemplateRef, ref } from 'vue';
|
import { onBeforeUnmount, onMounted, provide, useTemplateRef, ref } from 'vue';
|
||||||
import type { MenuItem } from '@/types/menu.js';
|
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 * as os from '@/os.js';
|
||||||
import { i18n } from '@/i18n.js';
|
import { i18n } from '@/i18n.js';
|
||||||
import { prefer } from '@/preferences.js';
|
import { prefer } from '@/preferences.js';
|
||||||
|
|
@ -78,12 +78,12 @@ function dragListen(fn: (ev: MouseEvent | TouchEvent) => void) {
|
||||||
window.addEventListener('touchend', dragClear.bind(null, fn));
|
window.addEventListener('touchend', dragClear.bind(null, fn));
|
||||||
}
|
}
|
||||||
|
|
||||||
function dragClear(fn) {
|
function dragClear(fn: (ev: MouseEvent | TouchEvent) => void) {
|
||||||
window.removeEventListener('mousemove', fn);
|
window.removeEventListener('mousemove', fn);
|
||||||
window.removeEventListener('touchmove', fn);
|
window.removeEventListener('touchmove', fn);
|
||||||
window.removeEventListener('mouseleave', dragClear);
|
window.removeEventListener('mouseleave', dragClear as any);
|
||||||
window.removeEventListener('mouseup', dragClear);
|
window.removeEventListener('mouseup', dragClear as any);
|
||||||
window.removeEventListener('touchend', dragClear);
|
window.removeEventListener('touchend', dragClear as any);
|
||||||
}
|
}
|
||||||
|
|
||||||
const props = withDefaults(defineProps<{
|
const props = withDefaults(defineProps<{
|
||||||
|
|
@ -128,7 +128,7 @@ function close() {
|
||||||
showing.value = false;
|
showing.value = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
function onKeydown(evt) {
|
function onKeydown(evt: KeyboardEvent) {
|
||||||
if (evt.which === 27) { // Esc
|
if (evt.which === 27) { // Esc
|
||||||
evt.preventDefault();
|
evt.preventDefault();
|
||||||
evt.stopPropagation();
|
evt.stopPropagation();
|
||||||
|
|
@ -136,7 +136,7 @@ function onKeydown(evt) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function onContextmenu(ev: MouseEvent) {
|
function onContextmenu(ev: PointerEvent) {
|
||||||
if (props.contextmenu) {
|
if (props.contextmenu) {
|
||||||
os.contextMenu(props.contextmenu, ev);
|
os.contextMenu(props.contextmenu, ev);
|
||||||
}
|
}
|
||||||
|
|
@ -240,7 +240,7 @@ function onHeaderMousedown(evt: MouseEvent | TouchEvent) {
|
||||||
const main = rootEl.value;
|
const main = rootEl.value;
|
||||||
if (main == null) return;
|
if (main == null) return;
|
||||||
|
|
||||||
if (!contains(main, window.document.activeElement)) main.focus();
|
if (!elementContains(main, window.document.activeElement)) main.focus();
|
||||||
|
|
||||||
const position = main.getBoundingClientRect();
|
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 (height > window.innerHeight) height = window.innerHeight;
|
||||||
if (rootEl.value) rootEl.value.style.height = height + 'px';
|
if (rootEl.value) rootEl.value.style.height = height + 'px';
|
||||||
}
|
}
|
||||||
|
|
||||||
// 幅を適用
|
// 幅を適用
|
||||||
function applyTransformWidth(width) {
|
function applyTransformWidth(width: number) {
|
||||||
if (width > window.innerWidth) width = window.innerWidth;
|
if (width > window.innerWidth) width = window.innerWidth;
|
||||||
if (rootEl.value) rootEl.value.style.width = width + 'px';
|
if (rootEl.value) rootEl.value.style.width = width + 'px';
|
||||||
}
|
}
|
||||||
|
|
||||||
// Y座標を適用
|
// Y座標を適用
|
||||||
function applyTransformTop(top) {
|
function applyTransformTop(top: number) {
|
||||||
if (rootEl.value) rootEl.value.style.top = top + 'px';
|
if (rootEl.value) rootEl.value.style.top = top + 'px';
|
||||||
}
|
}
|
||||||
|
|
||||||
// X座標を適用
|
// X座標を適用
|
||||||
function applyTransformLeft(left) {
|
function applyTransformLeft(left: number) {
|
||||||
if (rootEl.value) rootEl.value.style.left = left + 'px';
|
if (rootEl.value) rootEl.value.style.left = left + 'px';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -46,6 +46,6 @@ const parsed = computed(() => {
|
||||||
});
|
});
|
||||||
|
|
||||||
const render = () => {
|
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>
|
</script>
|
||||||
|
|
|
||||||
|
|
@ -48,7 +48,7 @@ const active = computed(() => {
|
||||||
return resolved.route.name === router.currentRoute.value.name;
|
return resolved.route.name === router.currentRoute.value.name;
|
||||||
});
|
});
|
||||||
|
|
||||||
function onContextmenu(ev) {
|
function onContextmenu(ev: PointerEvent) {
|
||||||
const selection = window.getSelection();
|
const selection = window.getSelection();
|
||||||
if (selection && selection.toString() !== '') return;
|
if (selection && selection.toString() !== '') return;
|
||||||
os.contextMenu([{
|
os.contextMenu([{
|
||||||
|
|
@ -85,7 +85,7 @@ function openWindow() {
|
||||||
os.pageWindow(props.to);
|
os.pageWindow(props.to);
|
||||||
}
|
}
|
||||||
|
|
||||||
function nav(ev: MouseEvent) {
|
function nav(ev: PointerEvent) {
|
||||||
// 制御キーとの組み合わせは無視(shiftを除く)
|
// 制御キーとの組み合わせは無視(shiftを除く)
|
||||||
if (ev.metaKey || ev.altKey || ev.ctrlKey) return;
|
if (ev.metaKey || ev.altKey || ev.ctrlKey) return;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -77,7 +77,7 @@ const props = withDefaults(defineProps<{
|
||||||
});
|
});
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
(ev: 'click', v: MouseEvent): void;
|
(ev: 'click', v: PointerEvent): void;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const showDecoration = props.forceShowDecoration || prefer.s.showAvatarDecorations;
|
const showDecoration = props.forceShowDecoration || prefer.s.showAvatarDecorations;
|
||||||
|
|
@ -91,7 +91,7 @@ const url = computed(() => {
|
||||||
return props.user.avatarUrl;
|
return props.user.avatarUrl;
|
||||||
});
|
});
|
||||||
|
|
||||||
function onClick(ev: MouseEvent): void {
|
function onClick(ev: PointerEvent): void {
|
||||||
if (props.link) return;
|
if (props.link) return;
|
||||||
emit('click', ev);
|
emit('click', ev);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -23,8 +23,8 @@ const observer = new ResizeObserver((entries) => {
|
||||||
transform: string;
|
transform: string;
|
||||||
}[] = [];
|
}[] = [];
|
||||||
for (const entry of entries) {
|
for (const entry of entries) {
|
||||||
const content = (entry.target[contentSymbol] ? entry.target : entry.target.firstElementChild) as HTMLSpanElement;
|
const content = ((entry.target as any)[contentSymbol] ? entry.target : entry.target.firstElementChild) as HTMLSpanElement;
|
||||||
const props: Required<Props> = content[contentSymbol];
|
const props: Required<Props> = (content as any)[contentSymbol];
|
||||||
const container = content.parentElement as HTMLSpanElement;
|
const container = content.parentElement as HTMLSpanElement;
|
||||||
const contentWidth = content.getBoundingClientRect().width;
|
const contentWidth = content.getBoundingClientRect().width;
|
||||||
const containerWidth = container.getBoundingClientRect().width;
|
const containerWidth = container.getBoundingClientRect().width;
|
||||||
|
|
@ -46,15 +46,15 @@ const props = withDefaults(defineProps<Props>(), {
|
||||||
const content = ref<HTMLSpanElement>();
|
const content = ref<HTMLSpanElement>();
|
||||||
|
|
||||||
watch(content, (value, oldValue) => {
|
watch(content, (value, oldValue) => {
|
||||||
if (oldValue) {
|
if (oldValue != null) {
|
||||||
delete oldValue[contentSymbol];
|
delete (oldValue as any)[contentSymbol];
|
||||||
observer.unobserve(oldValue);
|
observer.unobserve(oldValue);
|
||||||
if (oldValue.parentElement) {
|
if (oldValue.parentElement) {
|
||||||
observer.unobserve(oldValue.parentElement);
|
observer.unobserve(oldValue.parentElement);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (value) {
|
if (value != null) {
|
||||||
value[contentSymbol] = props;
|
(value as any)[contentSymbol] = props;
|
||||||
observer.observe(value);
|
observer.observe(value);
|
||||||
if (value.parentElement) {
|
if (value.parentElement) {
|
||||||
observer.observe(value.parentElement);
|
observer.observe(value.parentElement);
|
||||||
|
|
|
||||||
|
|
@ -102,7 +102,7 @@ const url = computed(() => {
|
||||||
const alt = computed(() => `:${customEmojiName.value}:`);
|
const alt = computed(() => `:${customEmojiName.value}:`);
|
||||||
const errored = ref(url.value == null);
|
const errored = ref(url.value == null);
|
||||||
|
|
||||||
function onClick(ev: MouseEvent) {
|
function onClick(ev: PointerEvent) {
|
||||||
if (props.menu) {
|
if (props.menu) {
|
||||||
const menuItems: MenuItem[] = [];
|
const menuItems: MenuItem[] = [];
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -67,7 +67,7 @@ function unmute() {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function onClick(ev: MouseEvent) {
|
function onClick(ev: PointerEvent) {
|
||||||
if (props.menu) {
|
if (props.menu) {
|
||||||
const menuItems: MenuItem[] = [];
|
const menuItems: MenuItem[] = [];
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -319,7 +319,7 @@ export default function (props: MfmProps, { emit }: { emit: SetupContext<MfmEven
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
case 'clickable': {
|
case 'clickable': {
|
||||||
return h('span', { onClick(ev: MouseEvent): void {
|
return h('span', { onClick(ev: PointerEvent): void {
|
||||||
ev.stopPropagation();
|
ev.stopPropagation();
|
||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
const clickEv = typeof token.props.args.ev === 'string' ? token.props.args.ev : '';
|
const clickEv = typeof token.props.args.ev === 'string' ? token.props.args.ev : '';
|
||||||
|
|
|
||||||
|
|
@ -46,7 +46,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
export type Tab = {
|
export type Tab = {
|
||||||
key: string;
|
key: string;
|
||||||
onClick?: (ev: MouseEvent) => void;
|
onClick?: (ev: PointerEvent) => void;
|
||||||
iconOnly?: boolean;
|
iconOnly?: boolean;
|
||||||
title: string;
|
title: string;
|
||||||
icon?: string;
|
icon?: string;
|
||||||
|
|
@ -70,8 +70,8 @@ const props = withDefaults(defineProps<{
|
||||||
});
|
});
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
(ev: 'update:tab', key: string);
|
(ev: 'update:tab', key: string): void;
|
||||||
(ev: 'tabClick', key: string);
|
(ev: 'tabClick', key: string): void;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const el = useTemplateRef('el');
|
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);
|
emit('tabClick', t.key);
|
||||||
|
|
||||||
if (t.onClick) {
|
if (t.onClick) {
|
||||||
|
|
|
||||||
|
|
@ -61,7 +61,6 @@ export type PageHeaderProps = {
|
||||||
import { onMounted, onUnmounted, ref, inject, useTemplateRef, computed } from 'vue';
|
import { onMounted, onUnmounted, ref, inject, useTemplateRef, computed } from 'vue';
|
||||||
import { scrollToTop } from '@@/js/scroll.js';
|
import { scrollToTop } from '@@/js/scroll.js';
|
||||||
import XTabs from './MkPageHeader.tabs.vue';
|
import XTabs from './MkPageHeader.tabs.vue';
|
||||||
import { globalEvents } from '@/events.js';
|
|
||||||
import { getAccountMenu } from '@/accounts.js';
|
import { getAccountMenu } from '@/accounts.js';
|
||||||
import { $i } from '@/i.js';
|
import { $i } from '@/i.js';
|
||||||
import { DI } from '@/di.js';
|
import { DI } from '@/di.js';
|
||||||
|
|
@ -72,7 +71,7 @@ const props = withDefaults(defineProps<PageHeaderProps>(), {
|
||||||
});
|
});
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
(ev: 'update:tab', key: string);
|
(ev: 'update:tab', key: string): void;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
//const viewId = inject(DI.viewId);
|
//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({
|
const menuItems = await getAccountMenu({
|
||||||
withExtraOperation: true,
|
withExtraOperation: true,
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,7 @@ function _closeTip() {
|
||||||
closeTip(props.k);
|
closeTip(props.k);
|
||||||
}
|
}
|
||||||
|
|
||||||
function showMenu(ev: MouseEvent) {
|
function showMenu(ev: PointerEvent) {
|
||||||
os.popupMenu([{
|
os.popupMenu([{
|
||||||
icon: 'ti ti-bulb-off',
|
icon: 'ti ti-bulb-off',
|
||||||
text: i18n.ts.hideAllTips,
|
text: i18n.ts.hideAllTips,
|
||||||
|
|
|
||||||
|
|
@ -188,7 +188,7 @@ function onCellKeyDown(ev: KeyboardEvent) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function onInputText(ev: Event) {
|
function onInputText(ev: InputEvent) {
|
||||||
editingValue.value = (ev.target as HTMLInputElement).value;
|
editingValue.value = (ev.target as HTMLInputElement).value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -715,7 +715,7 @@ function onMouseUp(ev: MouseEvent) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function onContextMenu(ev: MouseEvent) {
|
function onContextMenu(ev: PointerEvent) {
|
||||||
const cellAddress = getCellAddress(ev.target as HTMLElement);
|
const cellAddress = getCellAddress(ev.target as HTMLElement);
|
||||||
if (_DEV_) {
|
if (_DEV_) {
|
||||||
console.log(`[grid][context-menu] button: ${ev.button}, cell: ${cellAddress.row}x${cellAddress.col}`);
|
console.log(`[grid][context-menu] button: ${ev.button}, cell: ${cellAddress.row}x${cellAddress.col}`);
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { onUnmounted, onDeactivated, ref } from 'vue';
|
import { onUnmounted, onDeactivated, ref } from 'vue';
|
||||||
|
import type { Chart, ChartType, TooltipModel } from 'chart.js';
|
||||||
import * as os from '@/os.js';
|
import * as os from '@/os.js';
|
||||||
import MkChartTooltip from '@/components/MkChartTooltip.vue';
|
import MkChartTooltip from '@/components/MkChartTooltip.vue';
|
||||||
|
|
||||||
|
|
@ -40,7 +41,7 @@ export function useChartTooltip(opts: { position: 'top' | 'middle' } = { positio
|
||||||
tooltipShowing.value = false;
|
tooltipShowing.value = false;
|
||||||
});
|
});
|
||||||
|
|
||||||
function handler(context) {
|
function handler(context: { chart: Chart; tooltip: TooltipModel<ChartType> }) {
|
||||||
if (context.tooltip.opacity === 0) {
|
if (context.tooltip.opacity === 0) {
|
||||||
tooltipShowing.value = false;
|
tooltipShowing.value = false;
|
||||||
return;
|
return;
|
||||||
|
|
@ -48,8 +49,8 @@ export function useChartTooltip(opts: { position: 'top' | 'middle' } = { positio
|
||||||
|
|
||||||
tooltipTitle.value = context.tooltip.title[0];
|
tooltipTitle.value = context.tooltip.title[0];
|
||||||
tooltipSeries.value = context.tooltip.body.map((b, i) => ({
|
tooltipSeries.value = context.tooltip.body.map((b, i) => ({
|
||||||
backgroundColor: context.tooltip.labelColors[i].backgroundColor,
|
backgroundColor: context.tooltip.labelColors[i].backgroundColor as string,
|
||||||
borderColor: context.tooltip.labelColors[i].borderColor,
|
borderColor: context.tooltip.labelColors[i].borderColor as string,
|
||||||
text: b.lines[0],
|
text: b.lines[0],
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue