Merge tag '2024.10.1' into feature/2024.10

This commit is contained in:
dakkar 2024-11-08 15:52:37 +00:00
commit f079edaf3c
454 changed files with 9728 additions and 3363 deletions

View file

@ -10,7 +10,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<template #prefix><i class="ti ti-search"></i></template>
<template #label>{{ i18n.ts.host }}</template>
</MkInput>
<FormSplit style="margin-top: var(--margin);">
<FormSplit style="margin-top: var(--MI-margin);">
<MkSelect v-model="state">
<template #label>{{ i18n.ts.state }}</template>
<option value="all">{{ i18n.ts.all }}</option>

View file

@ -172,7 +172,7 @@ await misskeyApi('sponsors', { instance: true }).then((res) => sponsors.value.pu
text-align: center;
border-radius: var(--radius);
overflow: clip;
background-color: var(--panel);
background-color: var(--MI_THEME-panel);
background-size: cover;
background-position: center center;
}
@ -208,14 +208,14 @@ await misskeyApi('sponsors', { instance: true }).then((res) => sponsors.value.pu
flex-shrink: 0;
display: flex;
position: sticky;
top: calc(var(--stickyTop, 0px) + 8px);
top: calc(var(--MI-stickyTop, 0px) + 8px);
counter-increment: item;
content: counter(item);
width: 32px;
height: 32px;
line-height: 32px;
background-color: var(--accentedBg);
color: var(--accent);
background-color: var(--MI_THEME-accentedBg);
color: var(--MI_THEME-accent);
font-size: 13px;
font-weight: bold;
align-items: center;

View file

@ -55,6 +55,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<MkTextarea v-model="moderationNote" manualSave>
<template #label>{{ i18n.ts.moderationNote }}</template>
<template #caption>{{ i18n.ts.moderationNoteDescription }}</template>
</MkTextarea>
<FormSection v-if="user.host">
@ -140,15 +141,21 @@ SPDX-License-Identifier: AGPL-3.0-only
<div v-else-if="tab === 'announcements'" class="_gaps">
<MkButton primary rounded @click="createAnnouncement"><i class="ti ti-plus"></i> {{ i18n.ts._announcement.new }}</MkButton>
<MkSelect v-model="announcementsStatus">
<template #label>{{ i18n.ts.filter }}</template>
<option value="active">{{ i18n.ts.active }}</option>
<option value="archived">{{ i18n.ts.archived }}</option>
</MkSelect>
<MkPagination :pagination="announcementsPagination">
<template #default="{ items }">
<div class="_gaps_s">
<div v-for="announcement in items" :key="announcement.id" v-panel :class="$style.announcementItem" @click="editAnnouncement(announcement)">
<span style="margin-right: 0.5em;">
<i v-if="announcement.icon === 'info'" class="ti ti-info-circle"></i>
<i v-else-if="announcement.icon === 'warning'" class="ti ti-alert-triangle" style="color: var(--warn);"></i>
<i v-else-if="announcement.icon === 'error'" class="ti ti-circle-x" style="color: var(--error);"></i>
<i v-else-if="announcement.icon === 'success'" class="ti ti-check" style="color: var(--success);"></i>
<i v-else-if="announcement.icon === 'warning'" class="ti ti-alert-triangle" style="color: var(--MI_THEME-warn);"></i>
<i v-else-if="announcement.icon === 'error'" class="ti ti-circle-x" style="color: var(--MI_THEME-error);"></i>
<i v-else-if="announcement.icon === 'success'" class="ti ti-check" style="color: var(--MI_THEME-success);"></i>
</span>
<span>{{ announcement.title }}</span>
<span v-if="announcement.reads > 0" style="margin-left: auto; opacity: 0.7;">{{ i18n.ts.messageRead }}</span>
@ -193,6 +200,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<script lang="ts" setup>
import { computed, defineAsyncComponent, watch, ref } from 'vue';
import * as Misskey from 'misskey-js';
import { url } from '@@/js/config.js';
import MkChart from '@/components/MkChart.vue';
import MkObjectView from '@/components/MkObjectView.vue';
import MkTextarea from '@/components/MkTextarea.vue';
@ -208,7 +216,6 @@ import MkFileListForAdmin from '@/components/MkFileListForAdmin.vue';
import MkInfo from '@/components/MkInfo.vue';
import * as os from '@/os.js';
import { misskeyApi } from '@/scripts/misskey-api.js';
import { url } from '@@/js/config.js';
import { acct } from '@/filters/user.js';
import { definePageMetadata } from '@/scripts/page-metadata.js';
import { i18n } from '@/i18n.js';
@ -244,11 +251,15 @@ const filesPagination = {
userId: props.userId,
})),
};
const announcementsStatus = ref<'active' | 'archived'>('active');
const announcementsPagination = {
endpoint: 'admin/announcements/list' as const,
limit: 10,
params: computed(() => ({
userId: props.userId,
status: announcementsStatus.value,
})),
};
const expandedRoles = ref([]);
@ -600,18 +611,18 @@ definePageMetadata(() => ({
}
> .suspended {
color: var(--error);
border-color: var(--error);
color: var(--MI_THEME-error);
border-color: var(--MI_THEME-error);
}
> .silenced {
color: var(--warn);
border-color: var(--warn);
color: var(--MI_THEME-warn);
border-color: var(--MI_THEME-warn);
}
> .moderator {
color: var(--success);
border-color: var(--success);
color: var(--MI_THEME-success);
border-color: var(--MI_THEME-success);
}
}
}
@ -670,7 +681,7 @@ definePageMetadata(() => ({
.roleItemSub {
padding: 6px 12px;
font-size: 85%;
color: var(--fgTransparentWeak);
color: var(--MI_THEME-fgTransparentWeak);
}
.roleUnassign {

View file

@ -155,12 +155,12 @@ function removeSelf() {
}
.item {
border: solid 2px var(--divider);
border-radius: var(--radius);
border: solid 2px var(--MI_THEME-divider);
border-radius: var(--MI-radius);
padding: 12px;
&:hover {
border-color: var(--accent);
border-color: var(--MI_THEME-accent);
}
}
</style>

View file

@ -119,7 +119,7 @@ function onTabClick(tab: Tab, ev: MouseEvent): void {
}
const calcBg = () => {
const rawBg = pageMetadata.value?.bg ?? 'var(--bg)';
const rawBg = pageMetadata.value?.bg ?? 'var(--MI_THEME-bg)';
const tinyBg = tinycolor(rawBg.startsWith('var(') ? getComputedStyle(document.documentElement).getPropertyValue(rawBg.slice(4, -1)) : rawBg);
tinyBg.setAlpha(0.85);
bg.value = tinyBg.toRgbString();
@ -156,8 +156,8 @@ onUnmounted(() => {
--height: 60px;
display: flex;
width: 100%;
-webkit-backdrop-filter: var(--blur, blur(15px));
backdrop-filter: var(--blur, blur(15px));
-webkit-backdrop-filter: var(--MI-blur, blur(15px));
backdrop-filter: var(--MI-blur, blur(15px));
> .buttons {
--margin: 8px;
@ -189,7 +189,7 @@ onUnmounted(() => {
}
&.highlighted {
color: var(--accent);
color: var(--MI_THEME-accent);
}
}
@ -286,7 +286,7 @@ onUnmounted(() => {
position: absolute;
bottom: 0;
height: 3px;
background: var(--accent);
background: var(--MI_THEME-accent);
border-radius: var(--radius-ellipse);
transition: all 0.2s ease;
pointer-events: none;

View file

@ -294,10 +294,10 @@ onMounted(async () => {
bottom: 0;
left: 0;
padding: 12px;
border-top: solid 0.5px var(--divider);
background: var(--acrylicBg);
-webkit-backdrop-filter: var(--blur, blur(15px));
backdrop-filter: var(--blur, blur(15px));
border-top: solid 0.5px var(--MI_THEME-divider);
background: var(--MI_THEME-acrylicBg);
-webkit-backdrop-filter: var(--MI-blur, blur(15px));
backdrop-filter: var(--MI-blur, blur(15px));
}
.systemWebhook {

View file

@ -87,7 +87,7 @@ function onDeleteButtonClicked() {
}
.rightDivider {
border-right: 0.5px solid var(--divider);
border-right: 0.5px solid var(--MI_THEME-divider);
}
.recipientButtons {
@ -108,7 +108,7 @@ function onDeleteButtonClicked() {
padding: 8px;
&:hover {
background-color: var(--buttonBg);
background-color: var(--MI_THEME-buttonBg);
}
}
</style>

View file

@ -12,6 +12,10 @@ SPDX-License-Identifier: AGPL-3.0-only
<MkButton link to="/admin/abuse-report-notification-recipient" primary>{{ i18n.ts.notificationSetting }}</MkButton>
</div>
<MkInfo v-if="!defaultStore.reactiveState.abusesTutorial.value" closable @close="closeTutorial()">
{{ i18n.ts._abuseUserReport.resolveTutorial }}
</MkInfo>
<div :class="$style.inputs" class="_gaps">
<MkSelect v-model="state" style="margin: 0; flex: 1;">
<template #label>{{ i18n.ts.state }}</template>
@ -44,8 +48,10 @@ SPDX-License-Identifier: AGPL-3.0-only
</div>
-->
<MkPagination v-slot="{items}" ref="reports" :pagination="pagination" :displayLimit="50" style="margin-top: var(--margin);">
<XAbuseReport v-for="report in items" :key="report.id" :report="report" @resolved="resolved"/>
<MkPagination v-slot="{items}" ref="reports" :pagination="pagination" :displayLimit="50">
<div class="_gaps">
<XAbuseReport v-for="report in items" :key="report.id" :report="report" @resolved="resolved"/>
</div>
</MkPagination>
</div>
</MkSpacer>
@ -54,7 +60,6 @@ SPDX-License-Identifier: AGPL-3.0-only
<script lang="ts" setup>
import { computed, shallowRef, ref } from 'vue';
import XHeader from './_header_.vue';
import MkSelect from '@/components/MkSelect.vue';
import MkPagination from '@/components/MkPagination.vue';
@ -62,6 +67,8 @@ import XAbuseReport from '@/components/MkAbuseReport.vue';
import { i18n } from '@/i18n.js';
import { definePageMetadata } from '@/scripts/page-metadata.js';
import MkButton from '@/components/MkButton.vue';
import MkInfo from '@/components/MkInfo.vue';
import { defaultStore } from '@/store.js';
const reports = shallowRef<InstanceType<typeof MkPagination>>();
@ -85,6 +92,10 @@ function resolved(reportId) {
reports.value?.removeItem(reportId);
}
function closeTutorial() {
defaultStore.set('abusesTutorial', false);
}
const headerActions = computed(() => []);
const headerTabs = computed(() => []);

View file

@ -266,7 +266,7 @@ definePageMetadata(() => ({
padding: 32px;
&:not(:last-child) {
margin-bottom: var(--margin);
margin-bottom: var(--MI-margin);
}
}
.input {

View file

@ -24,9 +24,9 @@ SPDX-License-Identifier: AGPL-3.0-only
<template #label>{{ announcement.title }}</template>
<template #icon>
<i v-if="announcement.icon === 'info'" class="ti ti-info-circle"></i>
<i v-else-if="announcement.icon === 'warning'" class="ti ti-alert-triangle" style="color: var(--warn);"></i>
<i v-else-if="announcement.icon === 'error'" class="ti ti-circle-x" style="color: var(--error);"></i>
<i v-else-if="announcement.icon === 'success'" class="ti ti-check" style="color: var(--success);"></i>
<i v-else-if="announcement.icon === 'warning'" class="ti ti-alert-triangle" style="color: var(--MI_THEME-warn);"></i>
<i v-else-if="announcement.icon === 'error'" class="ti ti-circle-x" style="color: var(--MI_THEME-error);"></i>
<i v-else-if="announcement.icon === 'success'" class="ti ti-check" style="color: var(--MI_THEME-success);"></i>
</template>
<template #caption>{{ announcement.text }}</template>
<template #footer>
@ -51,9 +51,9 @@ SPDX-License-Identifier: AGPL-3.0-only
<MkRadios v-model="announcement.icon">
<template #label>{{ i18n.ts.icon }}</template>
<option value="info"><i class="ti ti-info-circle"></i></option>
<option value="warning"><i class="ti ti-alert-triangle" style="color: var(--warn);"></i></option>
<option value="error"><i class="ti ti-circle-x" style="color: var(--error);"></i></option>
<option value="success"><i class="ti ti-check" style="color: var(--success);"></i></option>
<option value="warning"><i class="ti ti-alert-triangle" style="color: var(--MI_THEME-warn);"></i></option>
<option value="error"><i class="ti ti-circle-x" style="color: var(--MI_THEME-error);"></i></option>
<option value="success"><i class="ti ti-check" style="color: var(--MI_THEME-success);"></i></option>
</MkRadios>
<MkRadios v-model="announcement.display">
<template #label>{{ i18n.ts.display }}</template>

View file

@ -12,6 +12,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<template v-else-if="botProtectionForm.savedState.provider === 'recaptcha'" #suffix>reCAPTCHA</template>
<template v-else-if="botProtectionForm.savedState.provider === 'turnstile'" #suffix>Turnstile</template>
<template v-else-if="botProtectionForm.savedState.provider === 'fc'" #suffix>FriendlyCaptcha</template>
<template v-else-if="botProtectionForm.savedState.provider === 'testcaptcha'" #suffix>testCaptcha</template>
<template v-else #suffix>{{ i18n.ts.none }} ({{ i18n.ts.notRecommended }})</template>
<template v-if="botProtectionForm.modified.value" #footer>
<MkFormFooter :form="botProtectionForm"/>
@ -25,6 +26,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<option value="recaptcha">reCAPTCHA</option>
<option value="turnstile">Turnstile</option>
<option value="fc">FriendlyCaptcha</option>
<option value="testcaptcha">testCaptcha</option>
</MkRadios>
<template v-if="botProtectionForm.state.provider === 'hcaptcha'">
@ -101,6 +103,13 @@ SPDX-License-Identifier: AGPL-3.0-only
<MkCaptcha provider="fc" :sitekey="botProtectionForm.state.fcSiteKey"/>
</FormSlot>
</template>
<template v-else-if="botProtectionForm.state.provider === 'testcaptcha'">
<MkInfo warn><span v-html="i18n.ts.testCaptchaWarning"></span></MkInfo>
<FormSlot>
<template #label>{{ i18n.ts.preview }}</template>
<MkCaptcha provider="testcaptcha"/>
</FormSlot>
</template>
</div>
</MkFolder>
</template>
@ -117,6 +126,7 @@ import { i18n } from '@/i18n.js';
import { useForm } from '@/scripts/use-form.js';
import MkFormFooter from '@/components/MkFormFooter.vue';
import MkFolder from '@/components/MkFolder.vue';
import MkInfo from '@/components/MkInfo.vue';
const MkCaptcha = defineAsyncComponent(() => import('@/components/MkCaptcha.vue'));
@ -133,6 +143,8 @@ const botProtectionForm = useForm({
? 'mcaptcha'
: meta.enableFC
? 'fc'
: meta.enableTestcaptcha
? 'testcaptcha'
: null,
hcaptchaSiteKey: meta.hcaptchaSiteKey,
hcaptchaSecretKey: meta.hcaptchaSecretKey,
@ -163,6 +175,7 @@ const botProtectionForm = useForm({
enableFC: state.provider === 'fc',
fcSiteKey: state.fcSiteKey,
fcSecretKey: state.fcSecretKey,
enableTestcaptcha: state.provider === 'testcaptcha',
});
fetchInstance(true);
});

View file

@ -218,7 +218,7 @@ definePageMetadata(() => ({
<style lang="scss" module>
.footer {
-webkit-backdrop-filter: var(--blur, blur(15px));
backdrop-filter: var(--blur, blur(15px));
-webkit-backdrop-filter: var(--MI-blur, blur(15px));
backdrop-filter: var(--MI-blur, blur(15px));
}
</style>

View file

@ -138,7 +138,7 @@ definePageMetadata(() => ({
<style lang="scss" module>
.footer {
-webkit-backdrop-filter: var(--blur, blur(15px));
backdrop-filter: var(--blur, blur(15px));
-webkit-backdrop-filter: var(--MI-blur, blur(15px));
backdrop-filter: var(--MI-blur, blur(15px));
}
</style>

View file

@ -14,7 +14,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<template #prefix><i class="ti ti-search"></i></template>
<template #label>{{ i18n.ts.host }}</template>
</MkInput>
<FormSplit style="margin-top: var(--margin);">
<FormSplit style="margin-top: var(--MI-margin);">
<MkSelect v-model="state">
<template #label>{{ i18n.ts.state }}</template>
<option value="all">{{ i18n.ts.all }}</option>

View file

@ -9,7 +9,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<template #header><XHeader :actions="headerActions"/></template>
<MkSpacer :contentMax="900">
<div class="_gaps">
<div class="inputs" style="display: flex; gap: var(--margin); flex-wrap: wrap;">
<div class="inputs" style="display: flex; gap: var(--MI-margin); flex-wrap: wrap;">
<MkSelect v-model="origin" style="margin: 0; flex: 1;">
<template #label>{{ i18n.ts.instance }}</template>
<option value="combined">{{ i18n.ts.all }}</option>
@ -20,7 +20,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<template #label>{{ i18n.ts.host }}</template>
</MkInput>
</div>
<div class="inputs" style="display: flex; gap: var(--margin); flex-wrap: wrap;">
<div class="inputs" style="display: flex; gap: var(--MI-margin); flex-wrap: wrap;">
<MkInput v-model="userId" :debounce="true" type="search" style="margin: 0; flex: 1;">
<template #label>User ID</template>
</MkInput>

View file

@ -26,7 +26,7 @@ SPDX-License-Identifier: AGPL-3.0-only
</MkSpacer>
</div>
<div v-if="!(narrow && currentPage?.route.name == null)" class="main">
<RouterView/>
<RouterView nested/>
</div>
</div>
</template>
@ -346,7 +346,7 @@ defineExpose({
width: 32%;
max-width: 280px;
box-sizing: border-box;
border-right: solid 0.5px var(--divider);
border-right: solid 0.5px var(--MI_THEME-divider);
overflow: auto;
height: 100%;
}

View file

@ -12,6 +12,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<div class="_gaps_m">
<MkSwitch v-model="enableRegistration" @change="onChange_enableRegistration">
<template #label>{{ i18n.ts.enableRegistration }}</template>
<template #caption>{{ i18n.ts._serverSettings.thisSettingWillAutomaticallyOffWhenModeratorsInactive }}</template>
</MkSwitch>
<MkSwitch v-model="emailRequiredForSignup" @change="onChange_emailRequiredForSignup">
@ -84,6 +85,18 @@ SPDX-License-Identifier: AGPL-3.0-only
</div>
</MkFolder>
<MkFolder>
<template #icon><i class="ti ti-user-x"></i></template>
<template #label>{{ i18n.ts.prohibitedWordsForNameOfUser }}</template>
<div class="_gaps">
<MkTextarea v-model="prohibitedWordsForNameOfUser">
<template #caption>{{ i18n.ts.prohibitedWordsForNameOfUserDescription }}<br>{{ i18n.ts.prohibitedWordsDescription2 }}</template>
</MkTextarea>
<MkButton primary @click="save_prohibitedWordsForNameOfUser">{{ i18n.ts.save }}</MkButton>
</div>
</MkFolder>
<MkFolder>
<template #icon><i class="ti ti-eye-off"></i></template>
<template #label>{{ i18n.ts.hiddenTags }}</template>
@ -160,6 +173,7 @@ const approvalRequiredForSignup = ref<boolean>(false);
const bubbleTimelineEnabled = ref<boolean>(false);
const sensitiveWords = ref<string>('');
const prohibitedWords = ref<string>('');
const prohibitedWordsForNameOfUser = ref<string>('');
const hiddenTags = ref<string>('');
const preservedUsernames = ref<string>('');
const bubbleTimeline = ref<string>('');
@ -175,13 +189,14 @@ async function init() {
approvalRequiredForSignup.value = meta.approvalRequiredForSignup;
sensitiveWords.value = meta.sensitiveWords.join('\n');
prohibitedWords.value = meta.prohibitedWords.join('\n');
prohibitedWordsForNameOfUser.value = meta.prohibitedWordsForNameOfUser.join('\n');
hiddenTags.value = meta.hiddenTags.join('\n');
preservedUsernames.value = meta.preservedUsernames.join('\n');
bubbleTimeline.value = meta.bubbleInstances.join('\n');
bubbleTimelineEnabled.value = meta.policies.btlAvailable;
trustedLinkUrlPatterns.value = meta.trustedLinkUrlPatterns.join('\n');
blockedHosts.value = meta.blockedHosts.join('\n');
silencedHosts.value = meta.silencedHosts.join('\n');
silencedHosts.value = meta.silencedHosts?.join('\n') ?? '';
mediaSilencedHosts.value = meta.mediaSilencedHosts.join('\n');
}
@ -249,6 +264,14 @@ function save_prohibitedWords() {
});
}
function save_prohibitedWordsForNameOfUser() {
os.apiWithDialog('admin/update-meta', {
prohibitedWordsForNameOfUser: prohibitedWordsForNameOfUser.value.split('\n'),
}).then(() => {
fetchInstance(true);
});
}
function save_hiddenTags() {
os.apiWithDialog('admin/update-meta', {
hiddenTags: hiddenTags.value.split('\n'),

View file

@ -101,7 +101,7 @@ SPDX-License-Identifier: AGPL-3.0-only
</template>
<div>
<div style="display: flex; gap: var(--margin); flex-wrap: wrap;">
<div style="display: flex; gap: var(--MI-margin); flex-wrap: wrap;">
<div style="flex: 1;">{{ i18n.ts.moderator }}: <MkA :to="`/admin/user/${log.userId}`" class="_link">@{{ log.user?.username }}</MkA></div>
<div style="flex: 1;">{{ i18n.ts.dateAndTime }}: <MkTime :time="log.createdAt" mode="detail"/></div>
</div>
@ -180,6 +180,11 @@ SPDX-License-Identifier: AGPL-3.0-only
<CodeDiff :context="5" :hideHeader="true" :oldString="JSON5.stringify(log.info.before, null, '\t')" :newString="JSON5.stringify(log.info.after, null, '\t')" language="javascript" maxHeight="300px"/>
</div>
</template>
<template v-else-if="log.type === 'updateAbuseReportNote'">
<div :class="$style.diff">
<CodeDiff :context="5" :hideHeader="true" :oldString="log.info.before ?? ''" :newString="log.info.after ?? ''" maxHeight="300px"/>
</div>
</template>
<details>
<summary>raw</summary>
@ -215,14 +220,14 @@ const props = defineProps<{
}
.logYellow {
color: var(--warn);
color: var(--MI_THEME-warn);
}
.logRed {
color: var(--error);
color: var(--MI_THEME-error);
}
.logGreen {
color: var(--success);
color: var(--MI_THEME-success);
}
</style>

View file

@ -8,7 +8,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<template #header><XHeader :actions="headerActions" :tabs="headerTabs"/></template>
<MkSpacer :contentMax="900">
<div>
<div style="display: flex; gap: var(--margin); flex-wrap: wrap;">
<div style="display: flex; gap: var(--MI-margin); flex-wrap: wrap;">
<MkSelect v-model="type" style="margin: 0; flex: 1;">
<template #label>{{ i18n.ts.type }}</template>
<option :value="null">{{ i18n.ts.all }}</option>
@ -19,10 +19,10 @@ SPDX-License-Identifier: AGPL-3.0-only
</MkInput>
</div>
<MkPagination v-slot="{items}" ref="logs" :pagination="pagination" :displayLimit="50" style="margin-top: var(--margin);">
<div class="_gaps_s">
<XModLog v-for="item in items" :key="item.id" :log="item"/>
</div>
<MkPagination v-slot="{items}" ref="logs" :pagination="pagination" :displayLimit="50" style="margin-top: var(--MI-margin);">
<MkDateSeparatedList v-slot="{ item }" :items="items" :noGap="false" style="--MI-margin: 8px;">
<XModLog :key="item.id" :log="item"/>
</MkDateSeparatedList>
</MkPagination>
</div>
</MkSpacer>
@ -39,6 +39,7 @@ import MkInput from '@/components/MkInput.vue';
import MkPagination from '@/components/MkPagination.vue';
import { i18n } from '@/i18n.js';
import { definePageMetadata } from '@/scripts/page-metadata.js';
import MkDateSeparatedList from '@/components/MkDateSeparatedList.vue';
const logs = shallowRef<InstanceType<typeof MkPagination>>();

View file

@ -157,7 +157,7 @@ definePageMetadata(() => ({
<style lang="scss" module>
.footer {
-webkit-backdrop-filter: var(--blur, blur(15px));
backdrop-filter: var(--blur, blur(15px));
-webkit-backdrop-filter: var(--MI-blur, blur(15px));
backdrop-filter: var(--MI-blur, blur(15px));
}
</style>

View file

@ -278,7 +278,7 @@ onMounted(async () => {
padding: 16px;
&:first-child {
border-bottom: solid 0.5px var(--divider);
border-bottom: solid 0.5px var(--MI_THEME-divider);
}
}
}

View file

@ -151,8 +151,8 @@ onMounted(async () => {
height: 100%;
aspect-ratio: 1;
margin-right: 12px;
background: var(--accentedBg);
color: var(--accent);
background: var(--MI_THEME-accentedBg);
color: var(--MI_THEME-accent);
border-radius: var(--radius);
}

View file

@ -41,7 +41,7 @@ onMounted(() => {
labels: props.data.map(x => x.name),
datasets: [{
backgroundColor: props.data.map(x => x.color),
borderColor: getComputedStyle(document.documentElement).getPropertyValue('--panel'),
borderColor: getComputedStyle(document.documentElement).getPropertyValue('--MI_THEME-panel'),
borderWidth: 2,
hoverOffset: 0,
data: props.data.map(x => x.value),

View file

@ -119,8 +119,8 @@ onUnmounted(() => {
> .chart {
min-width: 0;
padding: 16px;
background: var(--panel);
border-radius: var(--radius);
background: var(--MI_THEME-panel);
border-radius: var(--MI-radius);
> .title {
font-size: 0.85em;

View file

@ -114,8 +114,8 @@ onMounted(async () => {
height: 100%;
aspect-ratio: 1;
margin-right: 12px;
background: var(--accentedBg);
color: var(--accent);
background: var(--MI_THEME-accentedBg);
color: var(--MI_THEME-accent);
border-radius: var(--radius);
}

View file

@ -29,6 +29,13 @@ SPDX-License-Identifier: AGPL-3.0-only
</MkSwitch>
</div>
<div class="_panel" style="padding: 16px;">
<MkSwitch v-model="enableStatsForFederatedInstances" @change="onChange_enableStatsForFederatedInstances">
<template #label>{{ i18n.ts.enableStatsForFederatedInstances }}</template>
<template #caption>{{ i18n.ts.turnOffToImprovePerformance }}</template>
</MkSwitch>
</div>
<div class="_panel" style="padding: 16px;">
<MkSwitch v-model="enableChartsForFederatedInstances" @change="onChange_enableChartsForFederatedInstances">
<template #label>{{ i18n.ts.enableChartsForFederatedInstances }}</template>
@ -120,6 +127,7 @@ const meta = await misskeyApi('admin/meta');
const enableServerMachineStats = ref(meta.enableServerMachineStats);
const enableIdenticonGeneration = ref(meta.enableIdenticonGeneration);
const enableChartsForRemoteUser = ref(meta.enableChartsForRemoteUser);
const enableStatsForFederatedInstances = ref(meta.enableStatsForFederatedInstances);
const enableChartsForFederatedInstances = ref(meta.enableChartsForFederatedInstances);
function onChange_enableServerMachineStats(value: boolean) {
@ -146,6 +154,14 @@ function onChange_enableChartsForRemoteUser(value: boolean) {
});
}
function onChange_enableStatsForFederatedInstances(value: boolean) {
os.apiWithDialog('admin/update-meta', {
enableStatsForFederatedInstances: value,
}).then(() => {
fetchInstance(true);
});
}
function onChange_enableChartsForFederatedInstances(value: boolean) {
os.apiWithDialog('admin/update-meta', {
enableChartsForFederatedInstances: value,

View file

@ -135,8 +135,8 @@ onUnmounted(() => {
.chart {
min-width: 0;
padding: 16px;
background: var(--panel);
border-radius: var(--radius);
background: var(--MI_THEME-panel);
border-radius: var(--MI-radius);
}
.chartTitle {

View file

@ -11,8 +11,8 @@ SPDX-License-Identifier: AGPL-3.0-only
<div v-for="relay in relays" :key="relay.inbox" class="relaycxt _panel" style="padding: 16px;">
<div>{{ relay.inbox }}</div>
<div style="margin: 8px 0;">
<i v-if="relay.status === 'accepted'" class="ti ti-check" :class="$style.icon" style="color: var(--success);"></i>
<i v-else-if="relay.status === 'rejected'" class="ti ti-ban" :class="$style.icon" style="color: var(--error);"></i>
<i v-if="relay.status === 'accepted'" class="ti ti-check" :class="$style.icon" style="color: var(--MI_THEME-success);"></i>
<i v-else-if="relay.status === 'rejected'" class="ti ti-ban" :class="$style.icon" style="color: var(--MI_THEME-error);"></i>
<i v-else class="ti ti-clock" :class="$style.icon"></i>
<span>{{ i18n.ts._relayStatus[relay.status] }}</span>
</div>

View file

@ -95,7 +95,7 @@ definePageMetadata(() => ({
<style lang="scss" module>
.footer {
-webkit-backdrop-filter: var(--blur, blur(15px));
backdrop-filter: var(--blur, blur(15px));
-webkit-backdrop-filter: var(--MI-blur, blur(15px));
backdrop-filter: var(--MI-blur, blur(15px));
}
</style>

View file

@ -184,7 +184,7 @@ definePageMetadata(() => ({
.userItemSub {
padding: 6px 12px;
font-size: 85%;
color: var(--fgTransparentWeak);
color: var(--MI_THEME-fgTransparentWeak);
}
.userItemMainBody {

View file

@ -76,7 +76,7 @@ definePageMetadata(() => ({
<style lang="scss" module>
.item {
display: block;
color: var(--navFg);
color: var(--MI_THEME-navFg);
}
.itemHeader {
@ -96,8 +96,8 @@ definePageMetadata(() => ({
.itemNumber {
display: flex;
background-color: var(--accentedBg);
color: var(--accent);
background-color: var(--MI_THEME-accentedBg);
color: var(--MI_THEME-accent);
font-size: 14px;
font-weight: bold;
width: 28px;
@ -117,12 +117,12 @@ definePageMetadata(() => ({
.itemRemove {
width: 40px;
height: 40px;
color: var(--error);
color: var(--MI_THEME-error);
margin-left: auto;
border-radius: var(--radius-sm);
&:hover {
background: var(--X5);
background: var(--MI_THEME-X5);
}
}

View file

@ -438,6 +438,6 @@ definePageMetadata(() => ({
<style lang="scss" module>
.subCaption {
font-size: 0.85em;
color: var(--fgTransparentWeak);
color: var(--MI_THEME-fgTransparentWeak);
}
</style>

View file

@ -6,15 +6,16 @@ SPDX-License-Identifier: AGPL-3.0-only
<template>
<MkFolder>
<template #label>{{ entity.name || entity.url }}</template>
<template v-if="entity.name != null && entity.name != ''" #caption>{{ entity.url }}</template>
<template #icon>
<i v-if="!entity.isActive" class="ti ti-player-pause"/>
<i v-else-if="entity.latestStatus === null" class="ti ti-circle"/>
<i
v-else-if="[200, 201, 204].includes(entity.latestStatus)"
class="ti ti-check"
:style="{ color: 'var(--success)' }"
:style="{ color: 'var(--MI_THEME-success)' }"
/>
<i v-else class="ti ti-alert-triangle" :style="{ color: 'var(--error)' }"/>
<i v-else class="ti ti-alert-triangle" :style="{ color: 'var(--MI_THEME-error)' }"/>
</template>
<template #suffix>
<MkTime v-if="entity.latestSentAt" :time="entity.latestSentAt" style="margin-right: 8px"/>
@ -74,6 +75,6 @@ function onDeleteClick() {
margin-right: 0.75em;
flex-shrink: 0;
text-align: center;
color: var(--fgTransparentWeak);
color: var(--MI_THEME-fgTransparentWeak);
}
</style>

View file

@ -20,9 +20,9 @@ SPDX-License-Identifier: AGPL-3.0-only
<span v-if="$i && !announcement.silence && !announcement.isRead" style="margin-right: 0.5em;">🆕</span>
<span style="margin-right: 0.5em;">
<i v-if="announcement.icon === 'info'" class="ti ti-info-circle"></i>
<i v-else-if="announcement.icon === 'warning'" class="ti ti-alert-triangle" style="color: var(--warn);"></i>
<i v-else-if="announcement.icon === 'error'" class="ti ti-circle-x" style="color: var(--error);"></i>
<i v-else-if="announcement.icon === 'success'" class="ti ti-check" style="color: var(--success);"></i>
<i v-else-if="announcement.icon === 'warning'" class="ti ti-alert-triangle" style="color: var(--MI_THEME-warn);"></i>
<i v-else-if="announcement.icon === 'error'" class="ti ti-circle-x" style="color: var(--MI_THEME-error);"></i>
<i v-else-if="announcement.icon === 'success'" class="ti ti-check" style="color: var(--MI_THEME-success);"></i>
</span>
<Mfm :text="announcement.title"/>
</div>

View file

@ -17,9 +17,9 @@ SPDX-License-Identifier: AGPL-3.0-only
<span v-if="$i && !announcement.silence && !announcement.isRead" style="margin-right: 0.5em;">🆕</span>
<span style="margin-right: 0.5em;">
<i v-if="announcement.icon === 'info'" class="ti ti-info-circle"></i>
<i v-else-if="announcement.icon === 'warning'" class="ti ti-alert-triangle" style="color: var(--warn);"></i>
<i v-else-if="announcement.icon === 'error'" class="ti ti-circle-x" style="color: var(--error);"></i>
<i v-else-if="announcement.icon === 'success'" class="ti ti-check" style="color: var(--success);"></i>
<i v-else-if="announcement.icon === 'warning'" class="ti ti-alert-triangle" style="color: var(--MI_THEME-warn);"></i>
<i v-else-if="announcement.icon === 'error'" class="ti ti-circle-x" style="color: var(--MI_THEME-error);"></i>
<i v-else-if="announcement.icon === 'success'" class="ti ti-check" style="color: var(--MI_THEME-success);"></i>
</span>
<MkA :to="`/announcements/${announcement.id}`"><span>{{ announcement.title }}</span></MkA>
</div>

View file

@ -97,26 +97,26 @@ definePageMetadata(() => ({
<style lang="scss" module>
.new {
position: sticky;
top: calc(var(--stickyTop, 0px) + 16px);
top: calc(var(--MI-stickyTop, 0px) + 16px);
z-index: 1000;
width: 100%;
margin: calc(-0.675em - 8px) 0;
&:first-child {
margin-top: calc(-0.675em - 8px - var(--margin));
margin-top: calc(-0.675em - 8px - var(--MI-margin));
}
}
.newButton {
display: block;
margin: var(--margin) auto 0 auto;
margin: var(--MI-margin) auto 0 auto;
padding: 8px 16px;
border-radius: var(--radius-xl);
}
.tl {
background: var(--bg);
border-radius: var(--radius);
background: var(--MI_THEME-bg);
border-radius: var(--MI-radius);
overflow: clip;
}
</style>

View file

@ -124,7 +124,7 @@ definePageMetadata(() => ({
display: grid;
grid-template-columns: 1fr;
grid-template-rows: auto auto;
gap: var(--margin);
gap: var(--MI-margin);
}
.preview {
@ -132,7 +132,7 @@ definePageMetadata(() => ({
place-items: center;
grid-template-columns: 1fr 1fr;
grid-template-rows: 1fr;
gap: var(--margin);
gap: var(--MI-margin);
}
.previewItem {
@ -142,7 +142,7 @@ definePageMetadata(() => ({
display: flex;
align-items: center;
justify-content: center;
border-radius: var(--radius);
border-radius: var(--MI-radius);
&.light {
background: #eee;
@ -157,7 +157,7 @@ definePageMetadata(() => ({
.editorWrapper {
grid-template-columns: 200px 1fr;
grid-template-rows: 1fr;
gap: calc(var(--margin) * 2);
gap: calc(var(--MI-margin) * 2);
}
.preview {

View file

@ -216,7 +216,7 @@ definePageMetadata(() => ({
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
color: var(--navFg);
color: var(--MI_THEME-navFg);
}
.pinnedNoteRemove {

View file

@ -300,14 +300,14 @@ definePageMetadata(() => ({
<style lang="scss" module>
.main {
min-height: calc(100cqh - (var(--stickyTop, 0px) + var(--stickyBottom, 0px)));
min-height: calc(100cqh - (var(--MI-stickyTop, 0px) + var(--MI-stickyBottom, 0px)));
}
.footer {
-webkit-backdrop-filter: var(--blur, blur(15px));
backdrop-filter: var(--blur, blur(15px));
background: var(--acrylicBg);
border-top: solid 0.5px var(--divider);
-webkit-backdrop-filter: var(--MI-blur, blur(15px));
backdrop-filter: var(--MI-blur, blur(15px));
background: var(--MI_THEME-acrylicBg);
border-top: solid 0.5px var(--MI_THEME-divider);
}
.bannerContainer {
@ -341,7 +341,7 @@ definePageMetadata(() => ({
left: 0;
width: 100%;
height: 64px;
background: linear-gradient(0deg, var(--panel), color(from var(--panel) srgb r g b / 0));
background: linear-gradient(0deg, var(--MI_THEME-panel), color(from var(--MI_THEME-panel) srgb r g b / 0));
}
.bannerStatus {
@ -366,7 +366,7 @@ definePageMetadata(() => ({
bottom: 16px;
left: 16px;
background: rgba(0, 0, 0, 0.7);
color: var(--warn);
color: var(--MI_THEME-warn);
border-radius: var(--radius-sm);
font-weight: bold;
font-size: 1em;

View file

@ -198,7 +198,7 @@ definePageMetadata(() => ({
.user {
--height: 32px;
padding: 16px;
border-top: solid 0.5px var(--divider);
border-top: solid 0.5px var(--MI_THEME-divider);
line-height: var(--height);
}

View file

@ -330,28 +330,28 @@ definePageMetadata(() => ({
.ogwlenmc {
> .local {
.empty {
margin: var(--margin);
margin: var(--MI-margin);
}
.ldhfsamy {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(190px, 1fr));
grid-gap: 12px;
margin: var(--margin) 0;
margin: var(--MI-margin) 0;
> .emoji {
display: flex;
align-items: center;
padding: 11px;
text-align: left;
border: solid 1px var(--panel);
border: solid 1px var(--MI_THEME-panel);
&:hover {
border-color: var(--inputBorderHover);
border-color: var(--MI_THEME-inputBorderHover);
}
&.selected {
border-color: var(--accent);
border-color: var(--MI_THEME-accent);
}
> .img {
@ -382,14 +382,14 @@ definePageMetadata(() => ({
> .remote {
.empty {
margin: var(--margin);
margin: var(--MI-margin);
}
.ldhfsamy {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(190px, 1fr));
grid-gap: 12px;
margin: var(--margin) 0;
margin: var(--MI-margin) 0;
> .emoji {
display: flex;
@ -398,7 +398,7 @@ definePageMetadata(() => ({
text-align: left;
&:hover {
color: var(--accent);
color: var(--MI_THEME-accent);
}
> .img {

View file

@ -231,8 +231,8 @@ onMounted(async () => {
<style lang="scss" module>
.filePreviewRoot {
background: var(--panel);
border-radius: var(--radius);
background: var(--MI_THEME-panel);
border-radius: var(--MI-radius);
// MkMediaList 4px
padding: calc(1rem - 4px) 1rem 1rem;
}
@ -262,8 +262,8 @@ onMounted(async () => {
&:hover,
&:focus-visible {
background-color: var(--accentedBg);
color: var(--accent);
background-color: var(--MI_THEME-accentedBg);
color: var(--MI_THEME-accent);
text-decoration: none;
outline: none;
}
@ -285,7 +285,7 @@ onMounted(async () => {
align-items: center;
min-width: 0;
font-weight: 700;
border-radius: var(--radius);
border-radius: var(--MI-radius);
font-size: .8rem;
>.fileNameEditIcon {
@ -299,12 +299,12 @@ onMounted(async () => {
}
&:hover {
background-color: var(--accentedBg);
background-color: var(--MI_THEME-accentedBg);
>.fileName,
>.fileNameEditIcon {
visibility: visible;
color: var(--accent);
color: var(--MI_THEME-accent);
}
}
}
@ -322,7 +322,7 @@ onMounted(async () => {
display: block;
width: 100%;
padding: .5rem 1rem;
border-radius: var(--radius);
border-radius: var(--MI-radius);
.kvEditIcon {
display: inline-block;
@ -332,11 +332,11 @@ onMounted(async () => {
}
&:hover {
color: var(--accent);
background-color: var(--accentedBg);
color: var(--MI_THEME-accent);
background-color: var(--MI_THEME-accentedBg);
.kvEditIcon {
color: var(--accent);
color: var(--MI_THEME-accent);
visibility: visible;
}
}

View file

@ -111,7 +111,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<div v-if="replaying" class="_woodenFrame">
<div class="_woodenFrameInner">
<div style="background: #0004;">
<div style="height: 10px; background: var(--accent); will-change: width;" :style="{ width: `${(currentFrame / endedAtFrame) * 100}%` }"></div>
<div style="height: 10px; background: var(--MI_THEME-accent); will-change: width;" :style="{ width: `${(currentFrame / endedAtFrame) * 100}%` }"></div>
</div>
</div>
<div class="_woodenFrameInner">

View file

@ -243,9 +243,9 @@ async function del() {
bottom: 0;
left: 0;
padding: 12px;
border-top: solid 0.5px var(--divider);
background: var(--acrylicBg);
-webkit-backdrop-filter: var(--blur, blur(15px));
backdrop-filter: var(--blur, blur(15px));
border-top: solid 0.5px var(--MI_THEME-divider);
background: var(--MI_THEME-acrylicBg);
-webkit-backdrop-filter: var(--MI-blur, blur(15px));
backdrop-filter: var(--MI-blur, blur(15px));
}
</style>

View file

@ -58,11 +58,11 @@ function menu(ev) {
align-items: center;
padding: 12px;
text-align: left;
background: var(--panel);
background: var(--MI_THEME-panel);
border-radius: var(--radius-sm);
&:hover {
border-color: var(--accent);
border-color: var(--MI_THEME-accent);
}
}

View file

@ -5,7 +5,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<template>
<MkSpacer :contentMax="800">
<MkTab v-model="tab" style="margin-bottom: var(--margin);">
<MkTab v-model="tab" style="margin-bottom: var(--MI-margin);">
<option value="notes">{{ i18n.ts.notes }}</option>
<option value="polls">{{ i18n.ts.poll }}</option>
</MkTab>

View file

@ -5,7 +5,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<template>
<MkSpacer :contentMax="1200">
<MkTab v-model="origin" style="margin-bottom: var(--margin);">
<MkTab v-model="origin" style="margin-bottom: var(--MI-margin);">
<option value="local">{{ i18n.ts.local }}</option>
<option value="remote">{{ i18n.ts.remote }}</option>
</MkTab>

View file

@ -53,7 +53,7 @@ definePageMetadata(() => ({
<style lang="scss" module>
.note {
background: var(--panel);
border-radius: var(--radius);
background: var(--MI_THEME-panel);
border-radius: var(--MI-radius);
}
</style>

View file

@ -467,8 +467,8 @@ definePageMetadata(() => ({
</script>
<style lang="scss" module>
.footer {
backdrop-filter: var(--blur, blur(15px));
background: var(--acrylicBg);
border-top: solid .5px var(--divider);
backdrop-filter: var(--MI-blur, blur(15px));
background: var(--MI_THEME-acrylicBg);
border-top: solid .5px var(--MI_THEME-divider);
}
</style>

View file

@ -55,7 +55,8 @@ const tab = ref('featured');
const featuredFlashsPagination = {
endpoint: 'flash/featured' as const,
noPaging: true,
limit: 5,
offsetMode: true,
};
const myFlashsPagination = {
endpoint: 'flash/my' as const,

View file

@ -51,7 +51,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<div><i class="ti ti-clock"></i> {{ i18n.ts.createdAt }}: <MkTime :time="flash.createdAt" mode="detail"/></div>
</div>
</div>
<MkA v-if="$i && $i.id === flash.userId" :to="`/play/${flash.id}/edit`" style="color: var(--accent);">{{ i18n.ts._play.editThisPage }}</MkA>
<MkA v-if="$i && $i.id === flash.userId" :to="`/play/${flash.id}/edit`" style="color: var(--MI_THEME-accent);">{{ i18n.ts._play.editThisPage }}</MkA>
<MkAd :prefer="['horizontal', 'horizontal-big']"/>
</div>
<MkError v-else-if="error" @retry="fetchFlash()"/>
@ -367,7 +367,7 @@ definePageMetadata(() => ({
justify-content: center;
gap: 12px;
padding: 16px;
border-bottom: 1px solid var(--divider);
border-bottom: 1px solid var(--MI_THEME-divider);
&:last-child {
border-bottom: none;

View file

@ -141,7 +141,7 @@ definePageMetadata(() => ({
top: 8px;
left: 9px;
padding: 8px;
background: var(--panel);
background: var(--MI_THEME-panel);
}
> .remove {
@ -149,7 +149,7 @@ definePageMetadata(() => ({
top: 8px;
right: 9px;
padding: 8px;
background: var(--panel);
background: var(--MI_THEME-panel);
}
}
</style>

View file

@ -130,6 +130,6 @@ definePageMetadata(() => ({
display: grid;
grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
grid-gap: 12px;
margin: 0 var(--margin);
margin: 0 var(--MI-margin);
}
</style>

View file

@ -262,14 +262,14 @@ definePageMetadata(() => ({
align-items: center;
margin-top: 16px;
padding: 16px 0 0 0;
border-top: solid 0.5px var(--divider);
border-top: solid 0.5px var(--MI_THEME-divider);
> .like {
> .button {
--accent: rgb(241 97 132);
--X8: rgb(241 92 128);
--buttonBg: rgb(216 71 106 / 5%);
--buttonHoverBg: rgb(216 71 106 / 10%);
--MI_THEME-accent: rgb(241 97 132);
--MI_THEME-X8: rgb(241 92 128);
--MI_THEME-buttonBg: rgb(216 71 106 / 5%);
--MI_THEME-buttonHoverBg: rgb(216 71 106 / 10%);
color: #ff002f;
::v-deep(.count) {
@ -286,7 +286,7 @@ definePageMetadata(() => ({
margin: 0 8px;
&:hover {
color: var(--fgHighlighted);
color: var(--MI_THEME-fgHighlighted);
}
}
}
@ -295,7 +295,7 @@ definePageMetadata(() => ({
> .user {
margin-top: 16px;
padding: 16px 0 0 0;
border-top: solid 0.5px var(--divider);
border-top: solid 0.5px var(--MI_THEME-divider);
display: flex;
align-items: center;
flex-wrap: wrap;
@ -321,7 +321,7 @@ definePageMetadata(() => ({
display: grid;
grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
grid-gap: 12px;
margin: var(--margin);
margin: var(--MI-margin);
> .post {

View file

@ -35,7 +35,7 @@ definePageMetadata(() => ({
<style module>
.link:focus-within {
outline: 2px solid var(--focus);
outline: 2px solid var(--MI_THEME-focus);
outline-offset: -2px;
}
</style>

View file

@ -8,76 +8,26 @@ SPDX-License-Identifier: AGPL-3.0-only
<template #header><MkPageHeader :actions="headerActions" :tabs="headerTabs"/></template>
<MkSpacer :contentMax="500">
<MkLoading v-if="uiPhase === 'fetching'"/>
<div v-else-if="uiPhase === 'confirm' && data" class="_gaps_m" :class="$style.extInstallerRoot">
<div :class="$style.extInstallerIconWrapper">
<i v-if="data.type === 'plugin'" class="ti ti-plug"></i>
<i v-else-if="data.type === 'theme'" class="ti ti-palette"></i>
<i v-else class="ti ti-download"></i>
</div>
<h2 :class="$style.extInstallerTitle">{{ i18n.ts._externalResourceInstaller[`_${data.type}`].title }}</h2>
<div :class="$style.extInstallerNormDesc">{{ i18n.ts._externalResourceInstaller.checkVendorBeforeInstall }}</div>
<MkInfo v-if="data.type === 'plugin'" :warn="true">{{ i18n.ts._plugin.installWarn }}</MkInfo>
<FormSection>
<template #label>{{ i18n.ts._externalResourceInstaller[`_${data.type}`].metaTitle }}</template>
<div class="_gaps_s">
<FormSplit>
<MkExtensionInstaller v-else-if="uiPhase === 'confirm' && data" :extension="data" @confirm="install()">
<template #additionalInfo>
<FormSection>
<template #label>{{ i18n.ts._externalResourceInstaller._vendorInfo.title }}</template>
<div class="_gaps_s">
<MkKeyValue>
<template #key>{{ i18n.ts.name }}</template>
<template #value>{{ data.meta?.name }}</template>
<template #key>{{ i18n.ts._externalResourceInstaller._vendorInfo.endpoint }}</template>
<template #value><MkUrl :url="url" :showUrlPreview="false"></MkUrl></template>
</MkKeyValue>
<MkKeyValue>
<template #key>{{ i18n.ts.author }}</template>
<template #value>{{ data.meta?.author }}</template>
<template #key>{{ i18n.ts._externalResourceInstaller._vendorInfo.hashVerify }}</template>
<template #value>
<!-- この画面が出ている時点でハッシュの検証には成功している -->
<i class="ti ti-check" style="color: var(--MI_THEME-accent)"></i>
</template>
</MkKeyValue>
</FormSplit>
<MkKeyValue v-if="data.type === 'plugin'">
<template #key>{{ i18n.ts.description }}</template>
<template #value>{{ data.meta?.description }}</template>
</MkKeyValue>
<MkKeyValue v-if="data.type === 'plugin'">
<template #key>{{ i18n.ts.version }}</template>
<template #value>{{ data.meta?.version }}</template>
</MkKeyValue>
<MkKeyValue v-if="data.type === 'plugin'">
<template #key>{{ i18n.ts.permission }}</template>
<template #value>
<ul :class="$style.extInstallerKVList">
<li v-for="permission in data.meta?.permissions" :key="permission">{{ i18n.ts._permissions[permission] }}</li>
</ul>
</template>
</MkKeyValue>
<MkKeyValue v-if="data.type === 'theme' && data.meta?.base">
<template #key>{{ i18n.ts._externalResourceInstaller._meta.base }}</template>
<template #value>{{ i18n.ts[data.meta.base] }}</template>
</MkKeyValue>
<MkFolder>
<template #icon><i class="ti ti-code"></i></template>
<template #label>{{ i18n.ts._plugin.viewSource }}</template>
<MkCode :code="data.raw ?? ''"/>
</MkFolder>
</div>
</FormSection>
<FormSection>
<template #label>{{ i18n.ts._externalResourceInstaller._vendorInfo.title }}</template>
<div class="_gaps_s">
<MkKeyValue>
<template #key>{{ i18n.ts._externalResourceInstaller._vendorInfo.endpoint }}</template>
<template #value><MkUrl :url="url ?? ''" :showUrlPreview="false"></MkUrl></template>
</MkKeyValue>
<MkKeyValue>
<template #key>{{ i18n.ts._externalResourceInstaller._vendorInfo.hashVerify }}</template>
<template #value>
<!--この画面が出ている時点でハッシュの検証には成功している-->
<i class="ti ti-check" style="color: var(--accent)"></i>
</template>
</MkKeyValue>
</div>
</FormSection>
<div class="_buttonsCenter">
<MkButton primary @click="install()"><i class="ti ti-check"></i> {{ i18n.ts.install }}</MkButton>
</div>
</div>
</div>
</FormSection>
</template>
</MkExtensionInstaller>
<div v-else-if="uiPhase === 'error'" class="_gaps_m" :class="[$style.extInstallerRoot, $style.error]">
<div :class="$style.extInstallerIconWrapper">
<i class="ti ti-circle-x"></i>
@ -96,14 +46,11 @@ SPDX-License-Identifier: AGPL-3.0-only
<script lang="ts" setup>
import { ref, computed, onActivated, onDeactivated, nextTick } from 'vue';
import MkLoading from '@/components/global/MkLoading.vue';
import MkExtensionInstaller, { type Extension } from '@/components/MkExtensionInstaller.vue';
import MkButton from '@/components/MkButton.vue';
import FormSection from '@/components/form/section.vue';
import FormSplit from '@/components/form/split.vue';
import MkCode from '@/components/MkCode.vue';
import MkUrl from '@/components/global/MkUrl.vue';
import MkInfo from '@/components/MkInfo.vue';
import MkFolder from '@/components/MkFolder.vue';
import MkKeyValue from '@/components/MkKeyValue.vue';
import MkUrl from '@/components/global/MkUrl.vue';
import FormSection from '@/components/form/section.vue';
import * as os from '@/os.js';
import { misskeyApi } from '@/scripts/misskey-api.js';
import { AiScriptPluginMeta, parsePluginMeta, installPlugin } from '@/scripts/install-plugin.js';
@ -124,24 +71,7 @@ const errorKV = ref<{
const url = ref<string | null>(null);
const hash = ref<string | null>(null);
const data = ref<{
type: 'plugin' | 'theme';
raw: string;
meta?: {
// Plugin & Theme Common
name: string;
author: string;
// Plugin
description?: string;
version?: string;
permissions?: string[];
config?: Record<string, any>;
// Theme
base?: 'light' | 'dark';
};
} | null>(null);
const data = ref<Extension | null>(null);
function goBack(): void {
history.back();
@ -227,7 +157,7 @@ async function fetch() {
data.value = {
type: 'theme',
meta: {
description,
// description, // 使
...meta,
},
raw: res.data,
@ -320,8 +250,8 @@ definePageMetadata(() => ({
<style lang="scss" module>
.extInstallerRoot {
border-radius: var(--radius);
background: var(--panel);
border-radius: var(--MI-radius);
background: var(--MI_THEME-panel);
padding: 1.5rem;
}
@ -335,8 +265,8 @@ definePageMetadata(() => ({
margin-left: auto;
margin-right: auto;
background-color: var(--accentedBg);
color: var(--accent);
background-color: var(--MI_THEME-accentedBg);
color: var(--MI_THEME-accent);
}
.error .extInstallerIconWrapper {
@ -353,9 +283,4 @@ definePageMetadata(() => ({
.extInstallerNormDesc {
text-align: center;
}
.extInstallerKVList {
margin-top: 0;
margin-bottom: 0;
}
</style>

View file

@ -59,6 +59,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<MkButton @click="refreshMetadata"><i class="ti ti-refresh"></i> Refresh metadata</MkButton>
<MkTextarea v-model="moderationNote" manualSave>
<template #label>{{ i18n.ts.moderationNote }}</template>
<template #caption>{{ i18n.ts.moderationNoteDescription }}</template>
</MkTextarea>
</div>
</FormSection>

View file

@ -108,7 +108,7 @@ definePageMetadata(() => ({
</script>
<style lang="scss" module>
.main {
min-height: calc(100cqh - (var(--stickyTop, 0px) + var(--stickyBottom, 0px)));
min-height: calc(100cqh - (var(--MI-stickyTop, 0px) + var(--MI-stickyBottom, 0px)));
}
.userItem {

View file

@ -73,11 +73,11 @@ onActivated(() => {
.antenna {
display: block;
padding: 16px;
border: solid 1px var(--divider);
border: solid 1px var(--MI_THEME-divider);
border-radius: var(--radius-sm);
&:hover {
border: solid 1px var(--accent);
border: solid 1px var(--MI_THEME-accent);
text-decoration: none;
}
}

View file

@ -85,12 +85,12 @@ onActivated(() => {
.list {
display: block;
padding: 16px;
border: solid 1px var(--divider);
border: solid 1px var(--MI_THEME-divider);
border-radius: var(--radius-sm);
margin-bottom: 8px;
&:hover {
border: solid 1px var(--accent);
border: solid 1px var(--MI_THEME-accent);
text-decoration: none;
}
}

View file

@ -134,7 +134,7 @@ async function removeUser(item, ev) {
async function showMembershipMenu(item, ev) {
const withRepliesRef = ref(item.withReplies);
os.popupMenu([{
type: 'switch',
text: i18n.ts.showRepliesToOthersInTimeline,
@ -199,7 +199,7 @@ definePageMetadata(() => ({
<style lang="scss" module>
.main {
min-height: calc(100cqh - (var(--stickyTop, 0px) + var(--stickyBottom, 0px)));
min-height: calc(100cqh - (var(--MI-stickyTop, 0px) + var(--MI-stickyBottom, 0px)));
}
.userItem {
@ -234,8 +234,8 @@ definePageMetadata(() => ({
}
.footer {
-webkit-backdrop-filter: var(--blur, blur(15px));
backdrop-filter: var(--blur, blur(15px));
border-top: solid 0.5px var(--divider);
-webkit-backdrop-filter: var(--MI-blur, blur(15px));
backdrop-filter: var(--MI-blur, blur(15px));
border-top: solid 0.5px var(--MI_THEME-divider);
}
</style>

View file

@ -182,11 +182,11 @@ definePageMetadata(() => ({
}
.loadNext {
margin-bottom: var(--margin);
margin-bottom: var(--MI-margin);
}
.loadPrev {
margin-top: var(--margin);
margin-top: var(--MI-margin);
}
.loadButton {
@ -194,7 +194,7 @@ definePageMetadata(() => ({
}
.note {
border-radius: var(--radius);
background: var(--panel);
border-radius: var(--MI-radius);
background: var(--MI_THEME-panel);
}
</style>

View file

@ -102,7 +102,7 @@ definePageMetadata(() => ({
<style module lang="scss">
.notifications {
border-radius: var(--radius);
border-radius: var(--MI-radius);
overflow: clip;
}
</style>

View file

@ -63,7 +63,7 @@ onUnmounted(() => {
box-shadow: none;
padding: 16px;
background: transparent;
color: var(--fg);
color: var(--MI_THEME-fg);
font-size: 14px;
box-sizing: border-box;
}

View file

@ -60,12 +60,12 @@ function remove() {
.cpjygsrt {
position: relative;
overflow: hidden;
background: var(--panel);
border: solid 2px var(--X12);
background: var(--MI_THEME-panel);
border: solid 2px var(--MI_THEME-X12);
border-radius: var(--radius-sm);
&:hover {
border: solid 2px var(--X13);
border: solid 2px var(--MI_THEME-X13);
}
&.warn {

View file

@ -357,24 +357,24 @@ definePageMetadata(() => ({
&:hover,
&:focus-visible {
background-color: var(--accentedBg);
color: var(--accent);
background-color: var(--MI_THEME-accentedBg);
color: var(--MI_THEME-accent);
text-decoration: none;
outline: none;
}
}
.pageMain {
border-radius: var(--radius);
border-radius: var(--MI-radius);
padding: 2rem;
background: var(--panel);
background: var(--MI_THEME-panel);
box-sizing: border-box;
}
.pageBanner {
width: calc(100% + 4rem);
margin: -2rem -2rem 1.5rem;
border-radius: var(--radius) var(--radius) 0 0;
border-radius: var(--MI-radius) var(--MI-radius) 0 0;
overflow: hidden;
position: relative;
@ -399,7 +399,7 @@ definePageMetadata(() => ({
}
.pageBannerBgFallback2 {
background-color: var(--accentedBg);
background-color: var(--MI_THEME-accentedBg);
}
&::after {
@ -409,7 +409,7 @@ definePageMetadata(() => ({
bottom: 0;
width: 100%;
height: 100px;
background: linear-gradient(0deg, var(--panel), transparent);
background: linear-gradient(0deg, var(--MI_THEME-panel), transparent);
}
}
@ -433,7 +433,7 @@ definePageMetadata(() => ({
h1 {
font-size: 2rem;
font-weight: 700;
color: var(--fg);
color: var(--MI_THEME-fg);
margin: 0;
}
@ -458,7 +458,7 @@ definePageMetadata(() => ({
flex-shrink: 0;
display: flex;
align-items: center;
gap: var(--marginHalf);
gap: var(--MI-marginHalf);
margin-left: auto;
}
}
@ -472,14 +472,14 @@ definePageMetadata(() => ({
display: flex;
align-items: center;
border-top: 1px solid var(--divider);
border-top: 1px solid var(--MI_THEME-divider);
padding-top: 1.5rem;
margin-bottom: 1.5rem;
> .other {
margin-left: auto;
display: flex;
gap: var(--marginHalf);
gap: var(--MI-marginHalf);
}
}
@ -487,7 +487,7 @@ definePageMetadata(() => ({
display: flex;
align-items: center;
border-top: 1px solid var(--divider);
border-top: 1px solid var(--MI_THEME-divider);
padding-top: 1.5rem;
margin-bottom: 1.5rem;
@ -526,14 +526,14 @@ definePageMetadata(() => ({
display: flex;
align-items: center;
flex-wrap: wrap;
gap: var(--marginHalf);
gap: var(--MI-marginHalf);
}
.relatedPagesRoot {
padding: var(--margin);
padding: var(--MI-margin);
}
.relatedPagesItem > article {
background-color: var(--panelHighlight) !important;
background-color: var(--MI_THEME-panelHighlight) !important;
}
</style>

View file

@ -504,7 +504,7 @@ $gap: 4px;
.boardInner {
padding: 32px;
background: var(--panel);
background: var(--MI_THEME-panel);
box-shadow: 0 0 2px 1px #ce8a5c, inset 0 0 1px 1px #693410;
border-radius: 8px;
}
@ -574,34 +574,34 @@ $gap: 4px;
transition: border 0.25s ease, opacity 0.25s ease;
&.boardCell_empty {
border: solid 2px var(--divider);
border: solid 2px var(--MI_THEME-divider);
}
&.boardCell_empty.boardCell_can {
border-color: var(--accent);
border-color: var(--MI_THEME-accent);
opacity: 0.5;
}
&.boardCell_empty.boardCell_myTurn {
border-color: var(--divider);
border-color: var(--MI_THEME-divider);
opacity: 1;
&.boardCell_can {
border-color: var(--accent);
border-color: var(--MI_THEME-accent);
cursor: pointer;
&:hover {
background: var(--accent);
background: var(--MI_THEME-accent);
}
}
}
&.boardCell_prev {
box-shadow: 0 0 0 4px var(--accent);
box-shadow: 0 0 0 4px var(--MI_THEME-accent);
}
&.boardCell_isEnded {
border-color: var(--divider);
border-color: var(--MI_THEME-divider);
}
&.boardCell_none {

View file

@ -17,7 +17,7 @@ SPDX-License-Identifier: AGPL-3.0-only
</template>
<template v-else>
<div class="_panel">
<div style="display: flex; align-items: center; padding: 16px; border-bottom: solid 1px var(--divider);">
<div style="display: flex; align-items: center; padding: 16px; border-bottom: solid 1px var(--MI_THEME-divider);">
<div>{{ mapName }}</div>
<MkButton style="margin-left: auto;" @click="chooseMap">{{ i18n.ts._reversi.chooseBoard }}</MkButton>
</div>
@ -87,7 +87,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<div :class="$style.footer">
<MkSpacer :contentMax="700" :marginMin="16" :marginMax="16">
<div style="text-align: center;" class="_gaps_s">
<div v-if="opponentHasSettingsChanged" style="color: var(--warn);">{{ i18n.ts._reversi.opponentHasSettingsChanged }}</div>
<div v-if="opponentHasSettingsChanged" style="color: var(--MI_THEME-warn);">{{ i18n.ts._reversi.opponentHasSettingsChanged }}</div>
<div>
<template v-if="isReady && isOpReady">{{ i18n.ts._reversi.thisGameIsStartedSoon }}<MkEllipsis/></template>
<template v-if="isReady && !isOpReady">{{ i18n.ts._reversi.waitingForOther }}<MkEllipsis/></template>
@ -273,14 +273,14 @@ onUnmounted(() => {
width: 300px;
height: 300px;
margin: 0 auto;
color: var(--fg);
color: var(--MI_THEME-fg);
}
.boardCell {
display: grid;
place-items: center;
background: transparent;
border: solid 2px var(--divider);
border: solid 2px var(--MI_THEME-divider);
border-radius: 6px;
overflow: clip;
cursor: pointer;
@ -290,9 +290,9 @@ onUnmounted(() => {
}
.footer {
-webkit-backdrop-filter: var(--blur, blur(15px));
backdrop-filter: var(--blur, blur(15px));
background: var(--acrylicBg);
border-top: solid 0.5px var(--divider);
-webkit-backdrop-filter: var(--MI-blur, blur(15px));
backdrop-filter: var(--MI-blur, blur(15px));
background: var(--MI_THEME-acrylicBg);
border-top: solid 0.5px var(--MI_THEME-divider);
}
</style>

View file

@ -36,13 +36,13 @@ SPDX-License-Identifier: AGPL-3.0-only
<div :class="$style.gamePreviews">
<MkA v-for="g in items" :key="g.id" v-panel :class="[$style.gamePreview, !g.isStarted && !g.isEnded && $style.gamePreviewWaiting, g.isStarted && !g.isEnded && $style.gamePreviewActive]" tabindex="-1" :to="`/reversi/g/${g.id}`">
<div :class="$style.gamePreviewPlayers">
<span v-if="g.winnerId === g.user1Id" style="margin-right: 0.75em; color: var(--accent); font-weight: bold;"><i class="ti ti-trophy"></i></span>
<span v-if="g.winnerId === g.user1Id" style="margin-right: 0.75em; color: var(--MI_THEME-accent); font-weight: bold;"><i class="ti ti-trophy"></i></span>
<span v-if="g.winnerId === g.user2Id" style="margin-right: 0.75em; visibility: hidden;"><i class="ti ti-x"></i></span>
<MkAvatar :class="$style.gamePreviewPlayersAvatar" :user="g.user1"/>
<span style="margin: 0 1em;">vs</span>
<MkAvatar :class="$style.gamePreviewPlayersAvatar" :user="g.user2"/>
<span v-if="g.winnerId === g.user1Id" style="margin-left: 0.75em; visibility: hidden;"><i class="ti ti-x"></i></span>
<span v-if="g.winnerId === g.user2Id" style="margin-left: 0.75em; color: var(--accent); font-weight: bold;"><i class="ti ti-trophy"></i></span>
<span v-if="g.winnerId === g.user2Id" style="margin-left: 0.75em; color: var(--MI_THEME-accent); font-weight: bold;"><i class="ti ti-trophy"></i></span>
</div>
<div :class="$style.gamePreviewFooter">
<span v-if="g.isStarted && !g.isEnded" :class="$style.gamePreviewStatusActive">{{ i18n.ts._reversi.playing }}</span>
@ -63,13 +63,13 @@ SPDX-License-Identifier: AGPL-3.0-only
<div :class="$style.gamePreviews">
<MkA v-for="g in items" :key="g.id" v-panel :class="[$style.gamePreview, !g.isStarted && !g.isEnded && $style.gamePreviewWaiting, g.isStarted && !g.isEnded && $style.gamePreviewActive]" tabindex="-1" :to="`/reversi/g/${g.id}`">
<div :class="$style.gamePreviewPlayers">
<span v-if="g.winnerId === g.user1Id" style="margin-right: 0.75em; color: var(--accent); font-weight: bold;"><i class="ti ti-trophy"></i></span>
<span v-if="g.winnerId === g.user1Id" style="margin-right: 0.75em; color: var(--MI_THEME-accent); font-weight: bold;"><i class="ti ti-trophy"></i></span>
<span v-if="g.winnerId === g.user2Id" style="margin-right: 0.75em; visibility: hidden;"><i class="ti ti-x"></i></span>
<MkAvatar :class="$style.gamePreviewPlayersAvatar" :user="g.user1"/>
<span style="margin: 0 1em;">vs</span>
<MkAvatar :class="$style.gamePreviewPlayersAvatar" :user="g.user2"/>
<span v-if="g.winnerId === g.user1Id" style="margin-left: 0.75em; visibility: hidden;"><i class="ti ti-x"></i></span>
<span v-if="g.winnerId === g.user2Id" style="margin-left: 0.75em; color: var(--accent); font-weight: bold;"><i class="ti ti-trophy"></i></span>
<span v-if="g.winnerId === g.user2Id" style="margin-left: 0.75em; color: var(--MI_THEME-accent); font-weight: bold;"><i class="ti ti-trophy"></i></span>
</div>
<div :class="$style.gamePreviewFooter">
<span v-if="g.isStarted && !g.isEnded" :class="$style.gamePreviewStatusActive">{{ i18n.ts._reversi.playing }}</span>
@ -285,7 +285,7 @@ definePageMetadata(() => ({
.gamePreviews {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
grid-gap: var(--margin);
grid-gap: var(--MI-margin);
}
.gamePreview {
@ -295,11 +295,11 @@ definePageMetadata(() => ({
}
.gamePreviewActive {
box-shadow: inset 0 0 8px 0px var(--accent);
box-shadow: inset 0 0 8px 0px var(--MI_THEME-accent);
}
.gamePreviewWaiting {
box-shadow: inset 0 0 8px 0px var(--warn);
box-shadow: inset 0 0 8px 0px var(--MI_THEME-warn);
}
.gamePreviewPlayers {
@ -324,19 +324,19 @@ definePageMetadata(() => ({
.gamePreviewFooter {
display: flex;
align-items: baseline;
border-top: solid 0.5px var(--divider);
border-top: solid 0.5px var(--MI_THEME-divider);
padding: 6px 10px;
font-size: 0.9em;
}
.gamePreviewStatusActive {
color: var(--accent);
color: var(--MI_THEME-accent);
font-weight: bold;
animation: blink 2s infinite;
}
.gamePreviewStatusWaiting {
color: var(--warn);
color: var(--MI_THEME-warn);
font-weight: bold;
animation: blink 2s infinite;
}

View file

@ -204,7 +204,7 @@ definePageMetadata(() => ({
.root {
display: flex;
flex-direction: column;
gap: var(--margin);
gap: var(--MI-margin);
}
.editor {
@ -242,14 +242,14 @@ definePageMetadata(() => ({
}
.uiInspectorUnShown {
color: var(--fgTransparent);
color: var(--MI_THEME-fgTransparent);
}
.uiInspectorType {
display: inline-block;
border: hidden;
border-radius: 10px;
background-color: var(--panelHighlight);
background-color: var(--MI_THEME-panelHighlight);
padding: 2px 8px;
font-size: 12px;
}

View file

@ -225,12 +225,12 @@ async function search() {
justify-content: center;
}
.addMeButton {
border: 2px dashed var(--fgTransparent);
border: 2px dashed var(--MI_THEME-fgTransparent);
padding: 12px;
margin-right: 16px;
}
.addUserButton {
border: 2px dashed var(--fgTransparent);
border: 2px dashed var(--MI_THEME-fgTransparent);
padding: 12px;
flex-grow: 1;
}

View file

@ -19,7 +19,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<template #icon><i class="ti ti-shield-lock"></i></template>
<template #label>{{ i18n.ts.totp }}</template>
<template #caption>{{ i18n.ts.totpDescription }}</template>
<template #suffix><i v-if="$i.twoFactorEnabled" class="ti ti-check" style="color: var(--success)"></i></template>
<template #suffix><i v-if="$i.twoFactorEnabled" class="ti ti-check" style="color: var(--MI_THEME-success)"></i></template>
<div v-if="$i.twoFactorEnabled" class="_gaps_s">
<div v-text="i18n.ts._2fa.alreadyRegistered"/>

View file

@ -45,7 +45,7 @@ const init = async () => {
});
};
function menu(account, ev) {
function menu(account: Misskey.entities.UserDetailed, ev: MouseEvent) {
os.popupMenu([{
text: i18n.ts.switch,
icon: 'ti ti-switch-horizontal',
@ -58,7 +58,7 @@ function menu(account, ev) {
}], ev.currentTarget ?? ev.target);
}
function addAccount(ev) {
function addAccount(ev: MouseEvent) {
os.popupMenu([{
text: i18n.ts.existingAccount,
action: () => { addExistingAccount(); },
@ -68,14 +68,14 @@ function addAccount(ev) {
}], ev.currentTarget ?? ev.target);
}
async function removeAccount(account) {
async function removeAccount(account: Misskey.entities.UserDetailed) {
await _removeAccount(account.id);
accounts.value = accounts.value.filter(x => x.id !== account.id);
}
function addExistingAccount() {
const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkSigninDialog.vue')), {}, {
done: async res => {
done: async (res: Misskey.entities.SigninFlowResponse & { finished: true }) => {
await addAccounts(res.id, res.i);
os.success();
init();
@ -86,17 +86,17 @@ function addExistingAccount() {
function createAccount() {
const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkSignupDialog.vue')), {}, {
done: async res => {
await addAccounts(res.id, res.i);
switchAccountWithToken(res.i);
done: async (res: Misskey.entities.SignupResponse) => {
await addAccounts(res.id, res.token);
switchAccountWithToken(res.token);
},
closed: () => dispose(),
});
}
async function switchAccount(account: any) {
const fetchedAccounts: any[] = await getAccounts();
const token = fetchedAccounts.find(x => x.id === account.id).token;
const fetchedAccounts = await getAccounts();
const token = fetchedAccounts.find(x => x.id === account.id)!.token;
switchAccountWithToken(token);
}

View file

@ -14,30 +14,39 @@ SPDX-License-Identifier: AGPL-3.0-only
</template>
<template #default="{items}">
<div class="_gaps">
<div v-for="token in items" :key="token.id" class="_panel" :class="$style.app">
<img v-if="token.iconUrl" :class="$style.appIcon" :src="token.iconUrl" alt=""/>
<div :class="$style.appBody">
<div :class="$style.appName">{{ token.name }}</div>
<div>{{ token.description }}</div>
<MkKeyValue oneline>
<template #key>{{ i18n.ts.installedDate }}</template>
<template #value><MkTime :time="token.createdAt"/></template>
</MkKeyValue>
<MkKeyValue oneline>
<template #key>{{ i18n.ts.lastUsedDate }}</template>
<template #value><MkTime :time="token.lastUsedAt"/></template>
</MkKeyValue>
<details>
<summary>{{ i18n.ts.details }}</summary>
<MkFolder v-for="token in items" :key="token.id" :defaultOpen="true">
<template #icon>
<img v-if="token.iconUrl" :class="$style.appIcon" :src="token.iconUrl" alt=""/>
<i v-else class="ti ti-plug"/>
</template>
<template #label>{{ token.name }}</template>
<template #caption>{{ token.description }}</template>
<template #suffix><MkTime :time="token.lastUsedAt"/></template>
<template #footer>
<MkButton danger @click="revoke(token)"><i class="ti ti-trash"></i> {{ i18n.ts.delete }}</MkButton>
</template>
<div class="_gaps_s">
<div v-if="token.description">{{ token.description }}</div>
<div>
<MkKeyValue oneline>
<template #key>{{ i18n.ts.installedDate }}</template>
<template #value><MkTime :time="token.createdAt" :mode="'detail'"/></template>
</MkKeyValue>
<MkKeyValue oneline>
<template #key>{{ i18n.ts.lastUsedDate }}</template>
<template #value><MkTime :time="token.lastUsedAt" :mode="'detail'"/></template>
</MkKeyValue>
</div>
<MkFolder>
<template #label>{{ i18n.ts.permission }}</template>
<template #suffix>{{ Object.keys(token.permission).length === 0 ? i18n.ts.none : Object.keys(token.permission).length }}</template>
<ul>
<li v-for="p in token.permission" :key="p">{{ i18n.ts._permissions[p] }}</li>
</ul>
</details>
<div>
<MkButton inline danger @click="revoke(token)"><i class="ti ti-trash"></i></MkButton>
</div>
</MkFolder>
</div>
</div>
</MkFolder>
</div>
</template>
</FormPagination>
@ -52,6 +61,7 @@ import { i18n } from '@/i18n.js';
import { definePageMetadata } from '@/scripts/page-metadata.js';
import MkKeyValue from '@/components/MkKeyValue.vue';
import MkButton from '@/components/MkButton.vue';
import MkFolder from '@/components/MkFolder.vue';
import { infoImageUrl } from '@/instance.js';
const list = ref<InstanceType<typeof FormPagination>>();
@ -82,26 +92,9 @@ definePageMetadata(() => ({
</script>
<style lang="scss" module>
.app {
display: flex;
padding: 16px;
}
.appIcon {
display: block;
flex-shrink: 0;
margin: 0 12px 0 0;
width: 50px;
height: 50px;
border-radius: var(--radius-sm);
}
.appBody {
width: calc(100% - 62px);
position: relative;
}
.appName {
font-weight: bold;
width: 20px;
height: 20px;
border-radius: 4px;
}
</style>

View file

@ -44,7 +44,7 @@ const emit = defineEmits<{
.root {
cursor: pointer;
padding: 16px 16px 28px 16px;
border: solid 2px var(--divider);
border: solid 2px var(--MI_THEME-divider);
border-radius: var(--radius-sm);
text-align: center;
font-size: 90%;
@ -53,8 +53,8 @@ const emit = defineEmits<{
}
.active {
background-color: var(--accentedBg);
border-color: var(--accent);
background-color: var(--MI_THEME-accentedBg);
border-color: var(--MI_THEME-accent);
}
.name {

View file

@ -159,8 +159,8 @@ async function detach() {
bottom: 0;
left: 0;
padding: 12px;
border-top: solid 0.5px var(--divider);
-webkit-backdrop-filter: var(--blur, blur(15px));
backdrop-filter: var(--blur, blur(15px));
border-top: solid 0.5px var(--MI_THEME-divider);
-webkit-backdrop-filter: var(--MI-blur, blur(15px));
backdrop-filter: var(--MI-blur, blur(15px));
}
</style>

View file

@ -148,7 +148,7 @@ definePageMetadata(() => ({
.current {
padding: 16px;
border-radius: var(--radius);
border-radius: var(--MI-radius);
}
.decorations {

View file

@ -177,7 +177,7 @@ definePageMetadata(() => ({
align-items: center;
&:hover {
color: var(--accent);
color: var(--MI_THEME-accent);
}
}

View file

@ -10,7 +10,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<MkInput v-model="emailAddress" type="email" manualSave>
<template #prefix><i class="ti ti-mail"></i></template>
<template v-if="$i.email && !$i.emailVerified" #caption>{{ i18n.ts.verificationEmailSent }}</template>
<template v-else-if="emailAddress === $i.email && $i.emailVerified" #caption><i class="ti ti-check" style="color: var(--success);"></i> {{ i18n.ts.emailVerified }}</template>
<template v-else-if="emailAddress === $i.email && $i.emailVerified" #caption><i class="ti ti-check" style="color: var(--MI_THEME-success);"></i> {{ i18n.ts.emailVerified }}</template>
</MkInput>
</FormSection>

View file

@ -287,9 +287,9 @@ definePageMetadata(() => ({
<style lang="scss" module>
.tab {
margin: calc(var(--margin) / 2) 0;
padding: calc(var(--margin) / 2) 0;
background: var(--bg);
margin: calc(var(--MI-margin) / 2) 0;
padding: calc(var(--MI-margin) / 2) 0;
background: var(--MI_THEME-bg);
}
.emojis {
@ -311,6 +311,6 @@ definePageMetadata(() => ({
.editorCaption {
font-size: 0.85em;
padding: 8px 0 0 0;
color: var(--fgTransparentWeak);
color: var(--MI_THEME-fgTransparentWeak);
}
</style>

View file

@ -17,7 +17,7 @@ SPDX-License-Identifier: AGPL-3.0-only
</div>
<div v-if="!(narrow && currentPage?.route.name == null)" class="main">
<div class="bkzroven" style="container-type: inline-size;">
<RouterView/>
<RouterView nested/>
</div>
</div>
</div>

View file

@ -243,7 +243,7 @@ definePageMetadata(() => ({
.userItemSub {
padding: 6px 12px;
font-size: 85%;
color: var(--fgTransparentWeak);
color: var(--MI_THEME-fgTransparentWeak);
}
.userItemMainBody {

View file

@ -122,7 +122,7 @@ definePageMetadata(() => ({
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
color: var(--navFg);
color: var(--MI_THEME-navFg);
}
.itemIcon {

View file

@ -65,6 +65,9 @@ SPDX-License-Identifier: AGPL-3.0-only
<MkSwitch v-model="enableCondensedLine">
<template #label>Enable condensed line</template>
</MkSwitch>
<MkSwitch v-model="skipNoteRender">
<template #label>Enable note render skipping</template>
</MkSwitch>
</div>
</MkFolder>
@ -116,9 +119,14 @@ const $i = signinRequired();
const reportError = computed(defaultStore.makeGetterSetter('reportError'));
const enableCondensedLine = computed(defaultStore.makeGetterSetter('enableCondensedLine'));
const skipNoteRender = computed(defaultStore.makeGetterSetter('skipNoteRender'));
const devMode = computed(defaultStore.makeGetterSetter('devMode'));
const defaultWithReplies = computed(defaultStore.makeGetterSetter('defaultWithReplies'));
watch(skipNoteRender, async () => {
await reloadAsk({ reason: i18n.ts.reloadToApplySetting, unison: true });
});
async function deleteAccount() {
{
const { canceled } = await os.confirm({

View file

@ -469,7 +469,7 @@ definePageMetadata(() => ({
<style lang="scss" module>
.buttons {
display: flex;
gap: var(--margin);
gap: var(--MI-margin);
flex-wrap: wrap;
}

View file

@ -52,14 +52,17 @@ SPDX-License-Identifier: AGPL-3.0-only
<MkFolder>
<template #icon><i class="ti ti-list"></i></template>
<template #label>{{ i18n.ts._profile.metadataEdit }}</template>
<div :class="$style.metadataRoot">
<div :class="$style.metadataMargin">
<MkButton :disabled="fields.length >= 16" inline style="margin-right: 8px;" @click="addField"><i class="ti ti-plus"></i> {{ i18n.ts.add }}</MkButton>
<MkButton v-if="!fieldEditMode" :disabled="fields.length <= 1" inline danger style="margin-right: 8px;" @click="fieldEditMode = !fieldEditMode"><i class="ti ti-trash"></i> {{ i18n.ts.delete }}</MkButton>
<MkButton v-else inline style="margin-right: 8px;" @click="fieldEditMode = !fieldEditMode"><i class="ti ti-arrows-sort"></i> {{ i18n.ts.rearrange }}</MkButton>
<MkButton inline primary @click="saveFields"><i class="ti ti-check"></i> {{ i18n.ts.save }}</MkButton>
<template #footer>
<div class="_buttons">
<MkButton primary @click="saveFields"><i class="ti ti-check"></i> {{ i18n.ts.save }}</MkButton>
<MkButton :disabled="fields.length >= 16" @click="addField"><i class="ti ti-plus"></i> {{ i18n.ts.add }}</MkButton>
<MkButton v-if="!fieldEditMode" :disabled="fields.length <= 1" danger @click="fieldEditMode = !fieldEditMode"><i class="ti ti-trash"></i> {{ i18n.ts.delete }}</MkButton>
<MkButton v-else @click="fieldEditMode = !fieldEditMode"><i class="ti ti-arrows-sort"></i> {{ i18n.ts.rearrange }}</MkButton>
</div>
</template>
<div :class="$style.metadataRoot" class="_gaps_s">
<MkInfo>{{ i18n.ts._profile.verifiedLinkDescription }}</MkInfo>
<Sortable
v-model="fields"
@ -71,24 +74,20 @@ SPDX-License-Identifier: AGPL-3.0-only
@end="e => e.item.classList.remove('active')"
>
<template #item="{element, index}">
<div :class="$style.fieldDragItem">
<div v-panel :class="$style.fieldDragItem">
<button v-if="!fieldEditMode" class="_button" :class="$style.dragItemHandle" tabindex="-1"><i class="ti ti-menu"></i></button>
<button v-if="fieldEditMode" :disabled="fields.length <= 1" class="_button" :class="$style.dragItemRemove" @click="deleteField(index)"><i class="ti ti-x"></i></button>
<div :class="$style.dragItemForm">
<FormSplit :minWidth="200">
<MkInput v-model="element.name" small>
<template #label>{{ i18n.ts._profile.metadataLabel }}</template>
<MkInput v-model="element.name" small :placeholder="i18n.ts._profile.metadataLabel">
</MkInput>
<MkInput v-model="element.value" small>
<template #label>{{ i18n.ts._profile.metadataContent }}</template>
<MkInput v-model="element.value" small :placeholder="i18n.ts._profile.metadataContent">
</MkInput>
</FormSplit>
</div>
</div>
</template>
</Sortable>
<MkInfo>{{ i18n.ts._profile.verifiedLinkDescription }}</MkInfo>
</div>
</MkFolder>
<template #caption>{{ i18n.ts._profile.metadataDescription }}</template>
@ -158,6 +157,10 @@ const setMaxBirthDate = () => {
return `${y}-12-31`;
};
function assertVaildLang(lang: string | null): lang is keyof typeof langmap {
return lang != null && lang in langmap;
}
const profile = reactive({
name: $i.name,
description: $i.description,
@ -165,7 +168,7 @@ const profile = reactive({
location: $i.location,
birthday: $i.birthday,
listenbrainz: $i.listenbrainz,
lang: $i.lang,
lang: assertVaildLang($i.lang) ? $i.lang : null,
isBot: $i.isBot ?? false,
isCat: $i.isCat ?? false,
speakAsCat: $i.speakAsCat ?? false,
@ -229,6 +232,11 @@ function save() {
isBot: !!profile.isBot,
isCat: !!profile.isCat,
speakAsCat: !!profile.speakAsCat,
}, undefined, {
'0b3f9f6a-2f4d-4b1f-9fb4-49d3a2fd7191': {
title: i18n.ts.yourNameContainsProhibitedWords,
text: i18n.ts.yourNameContainsProhibitedWordsDescription,
},
});
globalEvents.emit('requestClearPageCache');
claimAchievement('profileFilled');
@ -417,7 +425,7 @@ definePageMetadata(() => ({
height: 130px;
background-size: cover;
background-position: center;
border-bottom: solid 1px var(--divider);
border-bottom: solid 1px var(--MI_THEME-divider);
overflow: clip;
}
@ -449,19 +457,11 @@ definePageMetadata(() => ({
container-type: inline-size;
}
.metadataMargin {
margin-bottom: 1.5em;
}
.fieldDragItem {
display: flex;
padding-bottom: .75em;
padding: 10px;
align-items: flex-end;
border-bottom: solid 0.5px var(--divider);
&:last-child {
border-bottom: 0;
}
border-radius: 6px;
/* (drag button) 32px + (drag button margin) 8px + (input width) 200px * 2 + (input gap) 12px = 452px */
@container (max-width: 452px) {

View file

@ -124,7 +124,7 @@ definePageMetadata(() => ({
}
&:not(:last-child) {
border-bottom: solid 0.5px var(--divider);
border-bottom: solid 0.5px var(--MI_THEME-divider);
}
> header {
@ -136,11 +136,11 @@ definePageMetadata(() => ({
margin-right: 0.75em;
&.succ {
color: var(--success);
color: var(--MI_THEME-success);
}
&.fail {
color: var(--error);
color: var(--MI_THEME-error);
}
}

View file

@ -194,7 +194,7 @@ function save() {
flex-grow: 1;
min-width: 0;
font-weight: 700;
color: var(--error);
color: var(--MI_THEME-error);
}
.fileSelectorButton {
@ -203,6 +203,6 @@ function save() {
.fileNotSelected {
font-weight: 700;
color: var(--infoWarnFg);
color: var(--MI_THEME-infoWarnFg);
}
</style>

View file

@ -204,7 +204,7 @@ definePageMetadata(() => ({
}
.dn:focus-visible ~ .toggle {
outline: 2px solid var(--focus);
outline: 2px solid var(--MI_THEME-focus);
outline-offset: 2px;
}
@ -227,12 +227,12 @@ definePageMetadata(() => ({
> .before {
left: -70px;
color: var(--accent);
color: var(--MI_THEME-accent);
}
> .after {
right: -68px;
color: var(--fg);
color: var(--MI_THEME-fg);
}
}
@ -350,11 +350,11 @@ definePageMetadata(() => ({
background-color: #749DD6;
> .before {
color: var(--fg);
color: var(--MI_THEME-fg);
}
> .after {
color: var(--accent);
color: var(--MI_THEME-accent);
}
.toggle__handler {
@ -405,14 +405,14 @@ definePageMetadata(() => ({
> .sync {
padding: 14px 16px;
border-top: solid 0.5px var(--divider);
border-top: solid 0.5px var(--MI_THEME-divider);
}
}
.rsljpzjq {
> .selects {
display: flex;
gap: 1.5em var(--margin);
gap: 1.5em var(--MI-margin);
flex-wrap: wrap;
> .select {

View file

@ -184,6 +184,6 @@ definePageMetadata(() => ({
.description {
font-size: 0.85em;
padding: 8px 0 0 0;
color: var(--fgTransparentWeak);
color: var(--MI_THEME-fgTransparentWeak);
}
</style>

View file

@ -17,8 +17,8 @@ SPDX-License-Identifier: AGPL-3.0-only
<template #icon>
<i v-if="webhook.active === false" class="ti ti-player-pause"></i>
<i v-else-if="webhook.latestStatus === null" class="ti ti-circle"></i>
<i v-else-if="[200, 201, 204].includes(webhook.latestStatus)" class="ti ti-check" :style="{ color: 'var(--success)' }"></i>
<i v-else class="ti ti-alert-triangle" :style="{ color: 'var(--error)' }"></i>
<i v-else-if="[200, 201, 204].includes(webhook.latestStatus)" class="ti ti-check" :style="{ color: 'var(--MI_THEME-success)' }"></i>
<i v-else class="ti ti-alert-triangle" :style="{ color: 'var(--MI_THEME-error)' }"></i>
</template>
{{ webhook.name || webhook.url }}
<template #suffix>

View file

@ -78,7 +78,7 @@ place-content: center;
.form {
position: relative;
z-index: 10;
border-radius: var(--radius);
border-radius: var(--MI-radius);
box-shadow: 0 8px 16px rgba(0, 0, 0, 0.1);
overflow: clip;
max-width: 500px;
@ -88,7 +88,7 @@ place-content: center;
padding: 16px;
text-align: center;
font-size: 26px;
background-color: var(--accentedBg);
color: var(--accent);
background-color: var(--MI_THEME-accentedBg);
color: var(--MI_THEME-accent);
}
</style>

View file

@ -76,10 +76,10 @@ definePageMetadata(() => ({
<style lang="scss" module>
.footer {
-webkit-backdrop-filter: var(--blur, blur(15px));
backdrop-filter: var(--blur, blur(15px));
background: var(--acrylicBg);
border-top: solid 0.5px var(--divider);
-webkit-backdrop-filter: var(--MI-blur, blur(15px));
backdrop-filter: var(--MI-blur, blur(15px));
background: var(--MI_THEME-acrylicBg);
border-top: solid 0.5px var(--MI_THEME-divider);
display: flex;
}

View file

@ -259,7 +259,7 @@ definePageMetadata(() => ({
}
&.active {
box-shadow: 0 0 0 2px var(--divider) inset;
box-shadow: 0 0 0 2px var(--MI_THEME-divider) inset;
}
&.rounded {

View file

@ -9,10 +9,10 @@ SPDX-License-Identifier: AGPL-3.0-only
<MkSpacer :contentMax="800">
<MkHorizontalSwipe v-model:tab="src" :tabs="$i ? headerTabs : headerTabsWhenNotLogin">
<div :key="src" ref="rootEl">
<MkInfo v-if="isBasicTimeline(src) && !defaultStore.reactiveState.timelineTutorials.value[src]" style="margin-bottom: var(--margin);" closable @close="closeTutorial()">
<MkInfo v-if="isBasicTimeline(src) && !defaultStore.reactiveState.timelineTutorials.value[src]" style="margin-bottom: var(--MI-margin);" closable @close="closeTutorial()">
{{ i18n.ts._timelineDescription[src] }}
</MkInfo>
<MkPostForm v-if="defaultStore.reactiveState.showFixedPostForm.value" :class="$style.postForm" class="post-form _panel" fixed style="margin-bottom: var(--margin);"/>
<MkPostForm v-if="defaultStore.reactiveState.showFixedPostForm.value" :class="$style.postForm" class="post-form _panel" fixed style="margin-bottom: var(--MI-margin);"/>
<div v-if="queue > 0" :class="$style.new"><button class="_buttonPrimary" :class="$style.newButton" @click="top()">{{ i18n.ts.newNoteRecived }}</button></div>
<div :class="$style.tl">
<MkTimeline
@ -363,30 +363,30 @@ definePageMetadata(() => ({
<style lang="scss" module>
.new {
position: sticky;
top: calc(var(--stickyTop, 0px) + 16px);
top: calc(var(--MI-stickyTop, 0px) + 16px);
z-index: 1000;
width: 100%;
margin: calc(-0.675em - 8px) 0;
&:first-child {
margin-top: calc(-0.675em - 8px - var(--margin));
margin-top: calc(-0.675em - 8px - var(--MI-margin));
}
}
.newButton {
display: block;
margin: var(--margin) auto 0 auto;
margin: var(--MI-margin) auto 0 auto;
padding: 8px 16px;
border-radius: var(--radius-xl);
}
.postForm {
border-radius: var(--radius);
border-radius: var(--MI-radius);
}
.tl {
background: var(--bg);
border-radius: var(--radius);
background: var(--MI_THEME-bg);
border-radius: var(--MI-radius);
overflow: clip;
}
</style>

View file

@ -114,26 +114,26 @@ definePageMetadata(() => ({
<style lang="scss" module>
.new {
position: sticky;
top: calc(var(--stickyTop, 0px) + 16px);
top: calc(var(--MI-stickyTop, 0px) + 16px);
z-index: 1000;
width: 100%;
margin: calc(-0.675em - 8px) 0;
&:first-child {
margin-top: calc(-0.675em - 8px - var(--margin));
margin-top: calc(-0.675em - 8px - var(--MI-margin));
}
}
.newButton {
display: block;
margin: var(--margin) auto 0 auto;
margin: var(--MI-margin) auto 0 auto;
padding: 8px 16px;
border-radius: var(--radius-xl);
}
.tl {
background: var(--bg);
border-radius: var(--radius);
background: var(--MI_THEME-bg);
border-radius: var(--MI-radius);
overflow: clip;
}
</style>

View file

@ -43,6 +43,6 @@ const pagination = {
.description {
margin-top: 8px;
padding-top: 8px;
border-top: solid 0.5px var(--divider);
border-top: solid 0.5px var(--MI_THEME-divider);
}
</style>

View file

@ -45,6 +45,6 @@ const followersPagination = {
.users {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
grid-gap: var(--margin);
grid-gap: var(--MI-margin);
}
</style>

View file

@ -38,6 +38,6 @@ const pagination = {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
grid-gap: 12px;
margin: var(--margin);
margin: var(--MI-margin);
}
</style>

View file

@ -22,7 +22,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<MkUserName class="name" :user="user" :nowrap="true"/>
<div class="bottom">
<span class="username"><MkAcct :user="user" :detail="true"/></span>
<span v-if="user.isAdmin" :title="i18n.ts.isAdmin" style="color: var(--badge);"><i class="ti ti-shield"></i></span>
<span v-if="user.isAdmin" :title="i18n.ts.isAdmin" style="color: var(--MI_THEME-badge);"><i class="ti ti-shield"></i></span>
<span v-if="user.isLocked" :title="i18n.ts.isLocked"><i class="ti ti-lock"></i></span>
<span v-if="user.isBot" :title="i18n.ts.isBot"><i class="ti ti-robot"></i></span>
<button v-if="$i && !isEditingMemo && !memoDraft" class="_button add-note-button" @click="showMemoTextarea">
@ -49,15 +49,16 @@ SPDX-License-Identifier: AGPL-3.0-only
<MkUserName :user="user" :nowrap="false" class="name"/>
<div class="bottom">
<span class="username"><MkAcct :user="user" :detail="true"/></span>
<span v-if="user.isAdmin" :title="i18n.ts.isAdmin" style="color: var(--badge);"><i class="ti ti-shield"></i></span>
<span v-if="user.isAdmin" :title="i18n.ts.isAdmin" style="color: var(--MI_THEME-badge);"><i class="ti ti-shield"></i></span>
<span v-if="user.isLocked" :title="i18n.ts.isLocked"><i class="ti ti-lock"></i></span>
<span v-if="user.isBot" :title="i18n.ts.isBot"><i class="ti ti-robot"></i></span>
</div>
</div>
<div v-if="user.followedMessage != null" class="followedMessage">
<div style="border: solid 1px var(--love); border-radius: 6px; background: color-mix(in srgb, var(--love), transparent 90%); padding: 6px 8px;">
<Mfm :text="user.followedMessage" :author="user"/>
</div>
<MkFukidashi class="fukidashi" :tail="narrow ? 'none' : 'left'" negativeMargin shadow>
<div class="messageHeader">{{ i18n.ts.messageToFollower }}</div>
<div><MkSparkle><Mfm :plain="true" :text="user.followedMessage" :author="user"/></MkSparkle></div>
</MkFukidashi>
</div>
<div v-if="user.roles.length > 0" class="roles">
<span v-for="role in user.roles" :key="role.id" v-tooltip="role.description" class="role" :style="{ '--color': role.color }">
@ -70,6 +71,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<div v-if="iAmModerator" class="moderationNote">
<MkTextarea v-if="editModerationNote || (moderationNote != null && moderationNote !== '')" v-model="moderationNote" manualSave>
<template #label>{{ i18n.ts.moderationNote }}</template>
<template #caption>{{ i18n.ts.moderationNoteDescription }}</template>
</MkTextarea>
<div v-else>
<MkButton small @click="editModerationNote = true">{{ i18n.ts.addModerationNote }}</MkButton>
@ -190,15 +192,16 @@ SPDX-License-Identifier: AGPL-3.0-only
<script lang="ts" setup>
import { defineAsyncComponent, computed, onMounted, onUnmounted, nextTick, watch, ref } from 'vue';
import * as Misskey from 'misskey-js';
import { getScrollPosition } from '@@/js/scroll.js';
import MkTab from '@/components/MkTab.vue';
import MkNotes from '@/components/MkNotes.vue';
import MkFollowButton from '@/components/MkFollowButton.vue';
import MkAccountMoved from '@/components/MkAccountMoved.vue';
import MkFukidashi from '@/components/MkFukidashi.vue';
import MkRemoteCaution from '@/components/MkRemoteCaution.vue';
import MkTextarea from '@/components/MkTextarea.vue';
import MkInfo from '@/components/MkInfo.vue';
import MkButton from '@/components/MkButton.vue';
import { getScrollPosition } from '@@/js/scroll.js';
import { getUserMenu } from '@/scripts/get-user-menu.js';
import number from '@/filters/number.js';
import { userPage } from '@/filters/user.js';
@ -213,11 +216,12 @@ import { isFollowingVisibleForMe, isFollowersVisibleForMe } from '@/scripts/isFf
import { useRouter } from '@/router/supplier.js';
import { getStaticImageUrl } from '@/scripts/media-proxy.js';
import { infoImageUrl } from '@/instance.js';
import MkSparkle from '@/components/MkSparkle.vue';
const MkNote = defineAsyncComponent(() =>
defaultStore.state.noteDesign === 'sharkey'
? import('@/components/SkNote.vue')
: import('@/components/MkNote.vue'),
? import('@/components/SkNote.vue')
: import('@/components/MkNote.vue'),
);
function calcAge(birthdate: string): number {
@ -473,8 +477,8 @@ onUnmounted(() => {
position: absolute;
top: 12px;
right: 12px;
-webkit-backdrop-filter: var(--blur, blur(8px));
backdrop-filter: var(--blur, blur(8px));
-webkit-backdrop-filter: var(--MI-blur, blur(8px));
backdrop-filter: var(--MI-blur, blur(8px));
background: rgba(0, 0, 0, 0.2);
padding: 8px;
border-radius: var(--radius-lg);
@ -528,8 +532,8 @@ onUnmounted(() => {
> .add-note-button {
background: rgba(0, 0, 0, 0.2);
color: #fff;
-webkit-backdrop-filter: var(--blur, blur(8px));
backdrop-filter: var(--blur, blur(8px));
-webkit-backdrop-filter: var(--MI-blur, blur(8px));
backdrop-filter: var(--MI-blur, blur(8px));
border-radius: var(--radius-lg);
padding: 4px 8px;
font-size: 80%;
@ -543,7 +547,7 @@ onUnmounted(() => {
text-align: center;
padding: 50px 8px 16px 8px;
font-weight: bold;
border-bottom: solid 0.5px var(--divider);
border-bottom: solid 0.5px var(--MI_THEME-divider);
> .bottom {
> * {
@ -567,7 +571,18 @@ onUnmounted(() => {
> .followedMessage {
padding: 24px 24px 0 154px;
font-size: 0.9em;
> .fukidashi {
display: block;
--fukidashi-bg: color-mix(in srgb, var(--MI_THEME-accent), var(--MI_THEME-panel) 85%);
--fukidashi-radius: 16px;
font-size: 0.9em;
.messageHeader {
opacity: 0.7;
font-size: 0.85em;
}
}
}
> .roles {
@ -578,7 +593,7 @@ onUnmounted(() => {
gap: 8px;
> .role {
border: solid 1px var(--color, var(--divider));
border: solid 1px var(--color, var(--MI_THEME-divider));
border-radius: var(--radius-ellipse);
margin-right: 4px;
padding: 3px 8px;
@ -592,15 +607,15 @@ onUnmounted(() => {
> .memo {
margin: 12px 24px 0 154px;
background: transparent;
color: var(--fg);
border: 1px solid var(--divider);
color: var(--MI_THEME-fg);
border: 1px solid var(--MI_THEME-divider);
border-radius: var(--radius-sm);
padding: 8px;
line-height: 0;
> .heading {
text-align: left;
color: var(--fgTransparent);
color: var(--MI_THEME-fgTransparent);
line-height: 1.5;
font-size: 85%;
}
@ -615,7 +630,7 @@ onUnmounted(() => {
height: auto;
min-height: 0;
line-height: 1.5;
color: var(--fg);
color: var(--MI_THEME-fg);
overflow: hidden;
background: transparent;
font-family: inherit;
@ -635,7 +650,7 @@ onUnmounted(() => {
> .fields {
padding: 24px;
font-size: 0.9em;
border-top: solid 0.5px var(--divider);
border-top: solid 0.5px var(--MI_THEME-divider);
> .field {
display: flex;
@ -672,14 +687,14 @@ onUnmounted(() => {
> .status {
display: flex;
padding: 24px;
border-top: solid 0.5px var(--divider);
border-top: solid 0.5px var(--MI_THEME-divider);
> a {
flex: 1;
text-align: center;
&.active {
color: var(--accent);
color: var(--MI_THEME-accent);
}
&:hover {
@ -701,7 +716,7 @@ onUnmounted(() => {
> .contents {
> .content {
margin-bottom: var(--margin);
margin-bottom: var(--MI-margin);
}
}
}
@ -718,7 +733,7 @@ onUnmounted(() => {
> .sub {
max-width: 350px;
min-width: 350px;
margin-left: var(--margin);
margin-left: var(--MI-margin);
}
}
}
@ -796,7 +811,7 @@ onUnmounted(() => {
<style lang="scss" module>
.tl {
background-color: rgba(0, 0, 0, 0);
border-radius: var(--radius);
border-radius: var(--MI-radius);
overflow: clip;
z-index: 0;
}
@ -817,7 +832,7 @@ onUnmounted(() => {
.verifiedLink {
margin-left: 4px;
color: var(--success);
color: var(--MI_THEME-success);
}
.pinnedNote:not(:last-child) {

Some files were not shown because too many files have changed in this diff Show more