This commit is contained in:
syuilo 2025-08-26 08:50:34 +09:00
parent 0c8545ec1c
commit 506c8a259b
8 changed files with 26 additions and 22 deletions

View File

@ -61,7 +61,7 @@ const event_reaction = ref(true);
const event_mention = ref(true); const event_mention = ref(true);
async function create(): Promise<void> { async function create(): Promise<void> {
const events = []; const events: string[] = [];
if (event_follow.value) events.push('follow'); if (event_follow.value) events.push('follow');
if (event_followed.value) events.push('followed'); if (event_followed.value) events.push('followed');
if (event_note.value) events.push('note'); if (event_note.value) events.push('note');

View File

@ -11,12 +11,12 @@ SPDX-License-Identifier: AGPL-3.0-only
<template #label>{{ i18n.ts.backgroundColor }}</template> <template #label>{{ i18n.ts.backgroundColor }}</template>
<div class="cwepdizn-colors"> <div class="cwepdizn-colors">
<div class="row"> <div class="row">
<button v-for="color in bgColors.filter(x => x.kind === 'light')" :key="color.color" class="color _button" :class="{ active: theme.props.bg === color.color }" @click="setBgColor(color)"> <button v-for="color in bgColors.filter(x => x.kind === 'light')" class="color _button" :class="{ active: theme.props.bg === color.color }" @click="setBgColor(color)">
<div class="preview" :style="{ background: color.forPreview }"></div> <div class="preview" :style="{ background: color.forPreview }"></div>
</button> </button>
</div> </div>
<div class="row"> <div class="row">
<button v-for="color in bgColors.filter(x => x.kind === 'dark')" :key="color.color" class="color _button" :class="{ active: theme.props.bg === color.color }" @click="setBgColor(color)"> <button v-for="color in bgColors.filter(x => x.kind === 'dark')" class="color _button" :class="{ active: theme.props.bg === color.color }" @click="setBgColor(color)">
<div class="preview" :style="{ background: color.forPreview }"></div> <div class="preview" :style="{ background: color.forPreview }"></div>
</button> </button>
</div> </div>
@ -27,7 +27,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<template #label>{{ i18n.ts.accentColor }}</template> <template #label>{{ i18n.ts.accentColor }}</template>
<div class="cwepdizn-colors"> <div class="cwepdizn-colors">
<div class="row"> <div class="row">
<button v-for="color in accentColors" :key="color" class="color rounded _button" :class="{ active: theme.props.accent === color }" @click="setAccentColor(color)"> <button v-for="color in accentColors" class="color rounded _button" :class="{ active: theme.props.accent === color }" @click="setAccentColor(color)">
<div class="preview" :style="{ background: color }"></div> <div class="preview" :style="{ background: color }"></div>
</button> </button>
</div> </div>
@ -38,7 +38,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<template #label>{{ i18n.ts.textColor }}</template> <template #label>{{ i18n.ts.textColor }}</template>
<div class="cwepdizn-colors"> <div class="cwepdizn-colors">
<div class="row"> <div class="row">
<button v-for="color in fgColors" :key="color" class="color char _button" :class="{ active: (theme.props.fg === color.forLight) || (theme.props.fg === color.forDark) }" @click="setFgColor(color)"> <button v-for="color in fgColors" class="color char _button" :class="{ active: (theme.props.fg === color.forLight) || (theme.props.fg === color.forDark) }" @click="setFgColor(color)">
<div class="preview" :style="{ color: color.forPreview ? color.forPreview : theme.base === 'light' ? '#5f5f5f' : '#dadada' }">A</div> <div class="preview" :style="{ color: color.forPreview ? color.forPreview : theme.base === 'light' ? '#5f5f5f' : '#dadada' }">A</div>
</button> </button>
</div> </div>
@ -75,17 +75,17 @@ SPDX-License-Identifier: AGPL-3.0-only
import { watch, ref, computed } from 'vue'; import { watch, ref, computed } from 'vue';
import { toUnicode } from 'punycode.js'; import { toUnicode } from 'punycode.js';
import tinycolor from 'tinycolor2'; import tinycolor from 'tinycolor2';
import { genId } from '@/utility/id.js';
import JSON5 from 'json5'; import JSON5 from 'json5';
import lightTheme from '@@/themes/_light.json5'; import lightTheme from '@@/themes/_light.json5';
import darkTheme from '@@/themes/_dark.json5'; import darkTheme from '@@/themes/_dark.json5';
import { host } from '@@/js/config.js'; import { host } from '@@/js/config.js';
import type { Theme } from '@/theme.js'; import type { Theme } from '@/theme.js';
import { genId } from '@/utility/id.js';
import MkButton from '@/components/MkButton.vue'; import MkButton from '@/components/MkButton.vue';
import MkCodeEditor from '@/components/MkCodeEditor.vue'; import MkCodeEditor from '@/components/MkCodeEditor.vue';
import MkTextarea from '@/components/MkTextarea.vue'; import MkTextarea from '@/components/MkTextarea.vue';
import MkFolder from '@/components/MkFolder.vue'; import MkFolder from '@/components/MkFolder.vue';
import { $i } from '@/i.js'; import { ensureSignin } from '@/i.js';
import { addTheme, applyTheme } from '@/theme.js'; import { addTheme, applyTheme } from '@/theme.js';
import * as os from '@/os.js'; import * as os from '@/os.js';
import { store } from '@/store.js'; import { store } from '@/store.js';
@ -94,6 +94,8 @@ import { useLeaveGuard } from '@/composables/use-leave-guard.js';
import { definePage } from '@/page.js'; import { definePage } from '@/page.js';
import { prefer } from '@/preferences.js'; import { prefer } from '@/preferences.js';
const $i = ensureSignin();
const bgColors = [ const bgColors = [
{ color: '#f5f5f5', kind: 'light', forPreview: '#f5f5f5' }, { color: '#f5f5f5', kind: 'light', forPreview: '#f5f5f5' },
{ color: '#f0eee9', kind: 'light', forPreview: '#f3e2b9' }, { color: '#f0eee9', kind: 'light', forPreview: '#f3e2b9' },
@ -123,12 +125,15 @@ const fgColors = [
{ color: 'pink', forLight: '#84667d', forDark: '#e4d1e0', forPreview: '#b12390' }, { color: 'pink', forLight: '#84667d', forDark: '#e4d1e0', forPreview: '#b12390' },
]; ];
const theme = ref<Partial<Theme>>({ const theme = ref<Theme>({
id: genId(),
name: 'untitled',
author: `@${$i.username}@${toUnicode(host)}`,
base: 'light', base: 'light',
props: lightTheme.props, props: lightTheme.props,
}); });
const description = ref<string | null>(null); const description = ref<string | null>(null);
const themeCode = ref<string | null>(null); const themeCode = ref<string>('');
const changed = ref(false); const changed = ref(false);
useLeaveGuard(changed); useLeaveGuard(changed);
@ -194,7 +199,6 @@ async function saveAs() {
theme.value.id = genId(); theme.value.id = genId();
theme.value.name = name; theme.value.name = name;
theme.value.author = `@${$i.username}@${toUnicode(host)}`;
if (description.value) theme.value.desc = description.value; if (description.value) theme.value.desc = description.value;
await addTheme(theme.value); await addTheme(theme.value);
applyTheme(theme.value); applyTheme(theme.value);

View File

@ -36,7 +36,7 @@ const props = defineProps<{
const chartEl = useTemplateRef('chartEl'); const chartEl = useTemplateRef('chartEl');
const legendEl = useTemplateRef('legendEl'); const legendEl = useTemplateRef('legendEl');
const now = new Date(); const now = new Date();
let chartInstance: Chart = null; let chartInstance: Chart | null = null;
const chartLimit = 30; const chartLimit = 30;
const fetching = ref(true); const fetching = ref(true);

View File

@ -7,7 +7,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<div> <div>
<MkPagination v-slot="{items}" :paginator="type === 'following' ? followingPaginator : followersPaginator" withControl> <MkPagination v-slot="{items}" :paginator="type === 'following' ? followingPaginator : followersPaginator" withControl>
<div :class="$style.users"> <div :class="$style.users">
<MkUserInfo v-for="user in items.map(x => type === 'following' ? x.followee : x.follower)" :key="user.id" :user="user"/> <MkUserInfo v-for="user in items.map(x => type === 'following' ? x.followee! : x.follower!)" :key="user.id" :user="user"/>
</div> </div>
</MkPagination> </MkPagination>
</div> </div>

View File

@ -25,8 +25,8 @@ SPDX-License-Identifier: AGPL-3.0-only
<MkUserName class="name" :user="user" :nowrap="true"/> <MkUserName class="name" :user="user" :nowrap="true"/>
<div class="bottom"> <div class="bottom">
<span class="username"><MkAcct :user="user" :detail="true"/></span> <span class="username"><MkAcct :user="user" :detail="true"/></span>
<span v-if="user.isLocked" :title="i18n.ts.isLocked"><i class="ti ti-lock"></i></span> <span v-if="user.isLocked"><i class="ti ti-lock"></i></span>
<span v-if="user.isBot" :title="i18n.ts.isBot"><i class="ti ti-robot"></i></span> <span v-if="user.isBot"><i class="ti ti-robot"></i></span>
<button v-if="$i && !isEditingMemo && !memoDraft" class="_button add-note-button" @click="showMemoTextarea"> <button v-if="$i && !isEditingMemo && !memoDraft" class="_button add-note-button" @click="showMemoTextarea">
<i class="ti ti-edit"/> {{ i18n.ts.addMemo }} <i class="ti ti-edit"/> {{ i18n.ts.addMemo }}
</button> </button>
@ -43,8 +43,8 @@ SPDX-License-Identifier: AGPL-3.0-only
<MkUserName :user="user" :nowrap="false" class="name"/> <MkUserName :user="user" :nowrap="false" class="name"/>
<div class="bottom"> <div class="bottom">
<span class="username"><MkAcct :user="user" :detail="true"/></span> <span class="username"><MkAcct :user="user" :detail="true"/></span>
<span v-if="user.isLocked" :title="i18n.ts.isLocked"><i class="ti ti-lock"></i></span> <span v-if="user.isLocked"><i class="ti ti-lock"></i></span>
<span v-if="user.isBot" :title="i18n.ts.isBot"><i class="ti ti-robot"></i></span> <span v-if="user.isBot"><i class="ti ti-robot"></i></span>
</div> </div>
</div> </div>
<div v-if="user.followedMessage != null" class="followedMessage"> <div v-if="user.followedMessage != null" class="followedMessage">
@ -228,7 +228,7 @@ const bannerEl = ref<null | HTMLElement>(null);
const memoTextareaEl = ref<null | HTMLElement>(null); const memoTextareaEl = ref<null | HTMLElement>(null);
const memoDraft = ref(props.user.memo); const memoDraft = ref(props.user.memo);
const isEditingMemo = ref(false); const isEditingMemo = ref(false);
const moderationNote = ref(props.user.moderationNote); const moderationNote = ref(props.user.moderationNote ?? '');
const editModerationNote = ref(false); const editModerationNote = ref(false);
watch(moderationNote, async () => { watch(moderationNote, async () => {

View File

@ -48,7 +48,7 @@ import FormSection from '@/components/form/section.vue';
import MkObjectView from '@/components/MkObjectView.vue'; import MkObjectView from '@/components/MkObjectView.vue';
const props = defineProps<{ const props = defineProps<{
user: Misskey.entities.User; user: Misskey.entities.UserDetailed & { isModerator?: boolean; };
}>(); }>();
const moderator = computed(() => props.user.isModerator ?? false); const moderator = computed(() => props.user.isModerator ?? false);

View File

@ -12,7 +12,7 @@ export async function lookupUser() {
const { canceled, result } = await os.inputText({ const { canceled, result } = await os.inputText({
title: i18n.ts.usernameOrUserId, title: i18n.ts.usernameOrUserId,
}); });
if (canceled) return; if (canceled || result == null) return;
const show = (user) => { const show = (user) => {
os.pageWindow(`/admin/user/${user.id}`); os.pageWindow(`/admin/user/${user.id}`);
@ -46,7 +46,7 @@ export async function lookupUserByEmail() {
title: i18n.ts.emailAddress, title: i18n.ts.emailAddress,
type: 'email', type: 'email',
}); });
if (canceled) return; if (canceled || result == null) return;
try { try {
const user = await os.apiWithDialog('admin/accounts/find-by-email', { email: result }); const user = await os.apiWithDialog('admin/accounts/find-by-email', { email: result });

View File

@ -179,7 +179,7 @@ export function getNoteMenu(props: {
translating: Ref<boolean>; translating: Ref<boolean>;
currentClip?: Misskey.entities.Clip; currentClip?: Misskey.entities.Clip;
}) { }) {
const appearNote = getAppearNote(props.note); const appearNote = getAppearNote(props.note) ?? props.note;
const link = appearNote.url ?? appearNote.uri; const link = appearNote.url ?? appearNote.uri;
const cleanups = [] as (() => void)[]; const cleanups = [] as (() => void)[];
@ -554,7 +554,7 @@ export function getRenoteMenu(props: {
renoteButton: ShallowRef<HTMLElement | null | undefined>; renoteButton: ShallowRef<HTMLElement | null | undefined>;
mock?: boolean; mock?: boolean;
}) { }) {
const appearNote = getAppearNote(props.note); const appearNote = getAppearNote(props.note) ?? props.note;
const channelRenoteItems: MenuItem[] = []; const channelRenoteItems: MenuItem[] = [];
const normalRenoteItems: MenuItem[] = []; const normalRenoteItems: MenuItem[] = [];