diff options
Diffstat (limited to 'packages/frontend/src/pages')
108 files changed, 553 insertions, 511 deletions
diff --git a/packages/frontend/src/pages/about.federation.vue b/packages/frontend/src/pages/about.federation.vue index 71353c7dfa..2190be8bec 100644 --- a/packages/frontend/src/pages/about.federation.vue +++ b/packages/frontend/src/pages/about.federation.vue @@ -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> diff --git a/packages/frontend/src/pages/about.overview.vue b/packages/frontend/src/pages/about.overview.vue index ca070c65a4..42898b3447 100644 --- a/packages/frontend/src/pages/about.overview.vue +++ b/packages/frontend/src/pages/about.overview.vue @@ -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; diff --git a/packages/frontend/src/pages/admin-user.vue b/packages/frontend/src/pages/admin-user.vue index 22e16effe0..f63b81c393 100644 --- a/packages/frontend/src/pages/admin-user.vue +++ b/packages/frontend/src/pages/admin-user.vue @@ -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 { diff --git a/packages/frontend/src/pages/admin/RolesEditorFormula.vue b/packages/frontend/src/pages/admin/RolesEditorFormula.vue index f001a4ac20..4762ef3f97 100644 --- a/packages/frontend/src/pages/admin/RolesEditorFormula.vue +++ b/packages/frontend/src/pages/admin/RolesEditorFormula.vue @@ -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> diff --git a/packages/frontend/src/pages/admin/_header_.vue b/packages/frontend/src/pages/admin/_header_.vue index 2a71e3efab..b061b2fa0c 100644 --- a/packages/frontend/src/pages/admin/_header_.vue +++ b/packages/frontend/src/pages/admin/_header_.vue @@ -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; diff --git a/packages/frontend/src/pages/admin/abuse-report/notification-recipient.editor.vue b/packages/frontend/src/pages/admin/abuse-report/notification-recipient.editor.vue index 827e22e8ae..eef24afd32 100644 --- a/packages/frontend/src/pages/admin/abuse-report/notification-recipient.editor.vue +++ b/packages/frontend/src/pages/admin/abuse-report/notification-recipient.editor.vue @@ -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 { diff --git a/packages/frontend/src/pages/admin/abuse-report/notification-recipient.item.vue b/packages/frontend/src/pages/admin/abuse-report/notification-recipient.item.vue index 0b86808faf..36d586bd23 100644 --- a/packages/frontend/src/pages/admin/abuse-report/notification-recipient.item.vue +++ b/packages/frontend/src/pages/admin/abuse-report/notification-recipient.item.vue @@ -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> diff --git a/packages/frontend/src/pages/admin/abuses.vue b/packages/frontend/src/pages/admin/abuses.vue index c8a9ca7112..a164ecb1fe 100644 --- a/packages/frontend/src/pages/admin/abuses.vue +++ b/packages/frontend/src/pages/admin/abuses.vue @@ -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(() => []); diff --git a/packages/frontend/src/pages/admin/ads.vue b/packages/frontend/src/pages/admin/ads.vue index 6c8901b10b..0d67359e47 100644 --- a/packages/frontend/src/pages/admin/ads.vue +++ b/packages/frontend/src/pages/admin/ads.vue @@ -266,7 +266,7 @@ definePageMetadata(() => ({ padding: 32px; &:not(:last-child) { - margin-bottom: var(--margin); + margin-bottom: var(--MI-margin); } } .input { diff --git a/packages/frontend/src/pages/admin/announcements.vue b/packages/frontend/src/pages/admin/announcements.vue index fd37311b21..e420586017 100644 --- a/packages/frontend/src/pages/admin/announcements.vue +++ b/packages/frontend/src/pages/admin/announcements.vue @@ -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> diff --git a/packages/frontend/src/pages/admin/bot-protection.vue b/packages/frontend/src/pages/admin/bot-protection.vue index 644436cde6..2f6dac8097 100644 --- a/packages/frontend/src/pages/admin/bot-protection.vue +++ b/packages/frontend/src/pages/admin/bot-protection.vue @@ -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); }); diff --git a/packages/frontend/src/pages/admin/branding.vue b/packages/frontend/src/pages/admin/branding.vue index d3d52002fe..cc05466832 100644 --- a/packages/frontend/src/pages/admin/branding.vue +++ b/packages/frontend/src/pages/admin/branding.vue @@ -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> diff --git a/packages/frontend/src/pages/admin/email-settings.vue b/packages/frontend/src/pages/admin/email-settings.vue index ddfe5ae81f..2f1d12ebb5 100644 --- a/packages/frontend/src/pages/admin/email-settings.vue +++ b/packages/frontend/src/pages/admin/email-settings.vue @@ -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> diff --git a/packages/frontend/src/pages/admin/federation.vue b/packages/frontend/src/pages/admin/federation.vue index 1902c97724..ef6bbb865b 100644 --- a/packages/frontend/src/pages/admin/federation.vue +++ b/packages/frontend/src/pages/admin/federation.vue @@ -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> diff --git a/packages/frontend/src/pages/admin/files.vue b/packages/frontend/src/pages/admin/files.vue index 5132b85c64..4cc859227f 100644 --- a/packages/frontend/src/pages/admin/files.vue +++ b/packages/frontend/src/pages/admin/files.vue @@ -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> diff --git a/packages/frontend/src/pages/admin/index.vue b/packages/frontend/src/pages/admin/index.vue index e8d123060a..1fb49d51d9 100644 --- a/packages/frontend/src/pages/admin/index.vue +++ b/packages/frontend/src/pages/admin/index.vue @@ -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%; } diff --git a/packages/frontend/src/pages/admin/moderation.vue b/packages/frontend/src/pages/admin/moderation.vue index bbcf2a6f77..03d1731a74 100644 --- a/packages/frontend/src/pages/admin/moderation.vue +++ b/packages/frontend/src/pages/admin/moderation.vue @@ -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"> @@ -85,6 +86,18 @@ SPDX-License-Identifier: AGPL-3.0-only </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'), diff --git a/packages/frontend/src/pages/admin/modlog.ModLog.vue b/packages/frontend/src/pages/admin/modlog.ModLog.vue index 6c81155c51..8af8d29e1a 100644 --- a/packages/frontend/src/pages/admin/modlog.ModLog.vue +++ b/packages/frontend/src/pages/admin/modlog.ModLog.vue @@ -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> diff --git a/packages/frontend/src/pages/admin/modlog.vue b/packages/frontend/src/pages/admin/modlog.vue index 4e0d0f941e..35f939f1be 100644 --- a/packages/frontend/src/pages/admin/modlog.vue +++ b/packages/frontend/src/pages/admin/modlog.vue @@ -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>>(); diff --git a/packages/frontend/src/pages/admin/object-storage.vue b/packages/frontend/src/pages/admin/object-storage.vue index 5fddb715cd..d5a664934c 100644 --- a/packages/frontend/src/pages/admin/object-storage.vue +++ b/packages/frontend/src/pages/admin/object-storage.vue @@ -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> diff --git a/packages/frontend/src/pages/admin/overview.ap-requests.vue b/packages/frontend/src/pages/admin/overview.ap-requests.vue index 4bbb9210af..570fcddc07 100644 --- a/packages/frontend/src/pages/admin/overview.ap-requests.vue +++ b/packages/frontend/src/pages/admin/overview.ap-requests.vue @@ -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); } } } diff --git a/packages/frontend/src/pages/admin/overview.federation.vue b/packages/frontend/src/pages/admin/overview.federation.vue index ea01d073ea..1ada4a5251 100644 --- a/packages/frontend/src/pages/admin/overview.federation.vue +++ b/packages/frontend/src/pages/admin/overview.federation.vue @@ -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); } diff --git a/packages/frontend/src/pages/admin/overview.pie.vue b/packages/frontend/src/pages/admin/overview.pie.vue index c7a9f2a702..a21ec6c464 100644 --- a/packages/frontend/src/pages/admin/overview.pie.vue +++ b/packages/frontend/src/pages/admin/overview.pie.vue @@ -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), diff --git a/packages/frontend/src/pages/admin/overview.queue.vue b/packages/frontend/src/pages/admin/overview.queue.vue index fb190f5325..de6b254412 100644 --- a/packages/frontend/src/pages/admin/overview.queue.vue +++ b/packages/frontend/src/pages/admin/overview.queue.vue @@ -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; diff --git a/packages/frontend/src/pages/admin/overview.stats.vue b/packages/frontend/src/pages/admin/overview.stats.vue index 37399a5724..12f2c82ff7 100644 --- a/packages/frontend/src/pages/admin/overview.stats.vue +++ b/packages/frontend/src/pages/admin/overview.stats.vue @@ -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); } diff --git a/packages/frontend/src/pages/admin/performance.vue b/packages/frontend/src/pages/admin/performance.vue index 7e0a932f82..12338f0bf9 100644 --- a/packages/frontend/src/pages/admin/performance.vue +++ b/packages/frontend/src/pages/admin/performance.vue @@ -30,6 +30,13 @@ SPDX-License-Identifier: AGPL-3.0-only </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> <template #caption>{{ i18n.ts.turnOffToImprovePerformance }}</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, diff --git a/packages/frontend/src/pages/admin/queue.chart.vue b/packages/frontend/src/pages/admin/queue.chart.vue index 960a263a86..7c171ba0e1 100644 --- a/packages/frontend/src/pages/admin/queue.chart.vue +++ b/packages/frontend/src/pages/admin/queue.chart.vue @@ -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 { diff --git a/packages/frontend/src/pages/admin/relays.vue b/packages/frontend/src/pages/admin/relays.vue index 04982eea1f..17e99e6593 100644 --- a/packages/frontend/src/pages/admin/relays.vue +++ b/packages/frontend/src/pages/admin/relays.vue @@ -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> diff --git a/packages/frontend/src/pages/admin/roles.edit.vue b/packages/frontend/src/pages/admin/roles.edit.vue index 60f06d50ba..2b4006c3f7 100644 --- a/packages/frontend/src/pages/admin/roles.edit.vue +++ b/packages/frontend/src/pages/admin/roles.edit.vue @@ -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> diff --git a/packages/frontend/src/pages/admin/roles.role.vue b/packages/frontend/src/pages/admin/roles.role.vue index 6bce60cfb9..d1c7be39d6 100644 --- a/packages/frontend/src/pages/admin/roles.role.vue +++ b/packages/frontend/src/pages/admin/roles.role.vue @@ -184,7 +184,7 @@ definePageMetadata(() => ({ .userItemSub { padding: 6px 12px; font-size: 85%; - color: var(--fgTransparentWeak); + color: var(--MI_THEME-fgTransparentWeak); } .userItemMainBody { diff --git a/packages/frontend/src/pages/admin/server-rules.vue b/packages/frontend/src/pages/admin/server-rules.vue index 4788c16830..1ce7190d9c 100644 --- a/packages/frontend/src/pages/admin/server-rules.vue +++ b/packages/frontend/src/pages/admin/server-rules.vue @@ -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); } } diff --git a/packages/frontend/src/pages/admin/settings.vue b/packages/frontend/src/pages/admin/settings.vue index 04975dcbf3..68f211de5c 100644 --- a/packages/frontend/src/pages/admin/settings.vue +++ b/packages/frontend/src/pages/admin/settings.vue @@ -438,6 +438,6 @@ definePageMetadata(() => ({ <style lang="scss" module> .subCaption { font-size: 0.85em; - color: var(--fgTransparentWeak); + color: var(--MI_THEME-fgTransparentWeak); } </style> diff --git a/packages/frontend/src/pages/admin/system-webhook.item.vue b/packages/frontend/src/pages/admin/system-webhook.item.vue index 4e767fba16..45f0fff107 100644 --- a/packages/frontend/src/pages/admin/system-webhook.item.vue +++ b/packages/frontend/src/pages/admin/system-webhook.item.vue @@ -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> diff --git a/packages/frontend/src/pages/announcement.vue b/packages/frontend/src/pages/announcement.vue index 802a6bf399..3840e6a494 100644 --- a/packages/frontend/src/pages/announcement.vue +++ b/packages/frontend/src/pages/announcement.vue @@ -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> diff --git a/packages/frontend/src/pages/announcements.vue b/packages/frontend/src/pages/announcements.vue index a9bcfee803..4eee275f07 100644 --- a/packages/frontend/src/pages/announcements.vue +++ b/packages/frontend/src/pages/announcements.vue @@ -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> diff --git a/packages/frontend/src/pages/antenna-timeline.vue b/packages/frontend/src/pages/antenna-timeline.vue index e57e212b60..fbfbb6edf7 100644 --- a/packages/frontend/src/pages/antenna-timeline.vue +++ b/packages/frontend/src/pages/antenna-timeline.vue @@ -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> diff --git a/packages/frontend/src/pages/avatar-decorations.vue b/packages/frontend/src/pages/avatar-decorations.vue index b377314856..b97e7c0eea 100644 --- a/packages/frontend/src/pages/avatar-decorations.vue +++ b/packages/frontend/src/pages/avatar-decorations.vue @@ -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 { diff --git a/packages/frontend/src/pages/channel-editor.vue b/packages/frontend/src/pages/channel-editor.vue index d3f4a65b89..6d8274a55c 100644 --- a/packages/frontend/src/pages/channel-editor.vue +++ b/packages/frontend/src/pages/channel-editor.vue @@ -216,7 +216,7 @@ definePageMetadata(() => ({ text-overflow: ellipsis; overflow: hidden; white-space: nowrap; - color: var(--navFg); + color: var(--MI_THEME-navFg); } .pinnedNoteRemove { diff --git a/packages/frontend/src/pages/channel.vue b/packages/frontend/src/pages/channel.vue index 790e16e471..6193e8857e 100644 --- a/packages/frontend/src/pages/channel.vue +++ b/packages/frontend/src/pages/channel.vue @@ -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; diff --git a/packages/frontend/src/pages/clip.vue b/packages/frontend/src/pages/clip.vue index 52b852ad17..9d8ba71a2d 100644 --- a/packages/frontend/src/pages/clip.vue +++ b/packages/frontend/src/pages/clip.vue @@ -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); } diff --git a/packages/frontend/src/pages/custom-emojis-manager.vue b/packages/frontend/src/pages/custom-emojis-manager.vue index 8904096875..48a64e5a02 100644 --- a/packages/frontend/src/pages/custom-emojis-manager.vue +++ b/packages/frontend/src/pages/custom-emojis-manager.vue @@ -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 { diff --git a/packages/frontend/src/pages/drive.file.info.vue b/packages/frontend/src/pages/drive.file.info.vue index 36e95cec2d..604abba562 100644 --- a/packages/frontend/src/pages/drive.file.info.vue +++ b/packages/frontend/src/pages/drive.file.info.vue @@ -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; } } diff --git a/packages/frontend/src/pages/drop-and-fusion.game.vue b/packages/frontend/src/pages/drop-and-fusion.game.vue index 4db952eac2..fb4d599c28 100644 --- a/packages/frontend/src/pages/drop-and-fusion.game.vue +++ b/packages/frontend/src/pages/drop-and-fusion.game.vue @@ -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"> diff --git a/packages/frontend/src/pages/emoji-edit-dialog.vue b/packages/frontend/src/pages/emoji-edit-dialog.vue index c5f0dde878..7bcd5addef 100644 --- a/packages/frontend/src/pages/emoji-edit-dialog.vue +++ b/packages/frontend/src/pages/emoji-edit-dialog.vue @@ -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> diff --git a/packages/frontend/src/pages/emojis.emoji.vue b/packages/frontend/src/pages/emojis.emoji.vue index 03a3b8f1c0..458642699e 100644 --- a/packages/frontend/src/pages/emojis.emoji.vue +++ b/packages/frontend/src/pages/emojis.emoji.vue @@ -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); } } diff --git a/packages/frontend/src/pages/explore.featured.vue b/packages/frontend/src/pages/explore.featured.vue index cfdb235d3a..8b16a88ff3 100644 --- a/packages/frontend/src/pages/explore.featured.vue +++ b/packages/frontend/src/pages/explore.featured.vue @@ -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> diff --git a/packages/frontend/src/pages/explore.users.vue b/packages/frontend/src/pages/explore.users.vue index 805d826946..2550100a42 100644 --- a/packages/frontend/src/pages/explore.users.vue +++ b/packages/frontend/src/pages/explore.users.vue @@ -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> diff --git a/packages/frontend/src/pages/favorites.vue b/packages/frontend/src/pages/favorites.vue index cb1feef016..ab26573b19 100644 --- a/packages/frontend/src/pages/favorites.vue +++ b/packages/frontend/src/pages/favorites.vue @@ -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> diff --git a/packages/frontend/src/pages/flash/flash-edit.vue b/packages/frontend/src/pages/flash/flash-edit.vue index fd6fadd0b3..d84ec4873b 100644 --- a/packages/frontend/src/pages/flash/flash-edit.vue +++ b/packages/frontend/src/pages/flash/flash-edit.vue @@ -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> diff --git a/packages/frontend/src/pages/flash/flash-index.vue b/packages/frontend/src/pages/flash/flash-index.vue index f63a799365..2b85489706 100644 --- a/packages/frontend/src/pages/flash/flash-index.vue +++ b/packages/frontend/src/pages/flash/flash-index.vue @@ -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, diff --git a/packages/frontend/src/pages/flash/flash.vue b/packages/frontend/src/pages/flash/flash.vue index 1229fcfd4e..7a7d52691c 100644 --- a/packages/frontend/src/pages/flash/flash.vue +++ b/packages/frontend/src/pages/flash/flash.vue @@ -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; diff --git a/packages/frontend/src/pages/gallery/edit.vue b/packages/frontend/src/pages/gallery/edit.vue index a68a7e5c41..70f8b2c31d 100644 --- a/packages/frontend/src/pages/gallery/edit.vue +++ b/packages/frontend/src/pages/gallery/edit.vue @@ -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> diff --git a/packages/frontend/src/pages/gallery/index.vue b/packages/frontend/src/pages/gallery/index.vue index e0b137ed28..2162e269bf 100644 --- a/packages/frontend/src/pages/gallery/index.vue +++ b/packages/frontend/src/pages/gallery/index.vue @@ -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> diff --git a/packages/frontend/src/pages/gallery/post.vue b/packages/frontend/src/pages/gallery/post.vue index 6ed119c0c4..539a6a9a7b 100644 --- a/packages/frontend/src/pages/gallery/post.vue +++ b/packages/frontend/src/pages/gallery/post.vue @@ -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 { diff --git a/packages/frontend/src/pages/games.vue b/packages/frontend/src/pages/games.vue index b52f4decaa..998b8be0f3 100644 --- a/packages/frontend/src/pages/games.vue +++ b/packages/frontend/src/pages/games.vue @@ -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> diff --git a/packages/frontend/src/pages/install-extensions.vue b/packages/frontend/src/pages/install-extensions.vue index 4bee437f65..6d68ed83b4 100644 --- a/packages/frontend/src/pages/install-extensions.vue +++ b/packages/frontend/src/pages/install-extensions.vue @@ -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> diff --git a/packages/frontend/src/pages/instance-info.vue b/packages/frontend/src/pages/instance-info.vue index a5e6e5ac33..78d765df80 100644 --- a/packages/frontend/src/pages/instance-info.vue +++ b/packages/frontend/src/pages/instance-info.vue @@ -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> diff --git a/packages/frontend/src/pages/list.vue b/packages/frontend/src/pages/list.vue index 03ab804d05..cab807d610 100644 --- a/packages/frontend/src/pages/list.vue +++ b/packages/frontend/src/pages/list.vue @@ -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 { diff --git a/packages/frontend/src/pages/my-antennas/index.vue b/packages/frontend/src/pages/my-antennas/index.vue index 9233695900..607843892e 100644 --- a/packages/frontend/src/pages/my-antennas/index.vue +++ b/packages/frontend/src/pages/my-antennas/index.vue @@ -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; } } diff --git a/packages/frontend/src/pages/my-lists/index.vue b/packages/frontend/src/pages/my-lists/index.vue index cd68be4ac3..a6e1f12d8a 100644 --- a/packages/frontend/src/pages/my-lists/index.vue +++ b/packages/frontend/src/pages/my-lists/index.vue @@ -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; } } diff --git a/packages/frontend/src/pages/my-lists/list.vue b/packages/frontend/src/pages/my-lists/list.vue index 5f195693cc..804a5ae8f8 100644 --- a/packages/frontend/src/pages/my-lists/list.vue +++ b/packages/frontend/src/pages/my-lists/list.vue @@ -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> diff --git a/packages/frontend/src/pages/note.vue b/packages/frontend/src/pages/note.vue index d0bbaeddd9..f6eef52153 100644 --- a/packages/frontend/src/pages/note.vue +++ b/packages/frontend/src/pages/note.vue @@ -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> diff --git a/packages/frontend/src/pages/notifications.vue b/packages/frontend/src/pages/notifications.vue index bd93fc8369..46ee501c76 100644 --- a/packages/frontend/src/pages/notifications.vue +++ b/packages/frontend/src/pages/notifications.vue @@ -102,7 +102,7 @@ definePageMetadata(() => ({ <style module lang="scss"> .notifications { - border-radius: var(--radius); + border-radius: var(--MI-radius); overflow: clip; } </style> diff --git a/packages/frontend/src/pages/page-editor/els/page-editor.el.text.vue b/packages/frontend/src/pages/page-editor/els/page-editor.el.text.vue index 14c3e6845e..f09f7e1acd 100644 --- a/packages/frontend/src/pages/page-editor/els/page-editor.el.text.vue +++ b/packages/frontend/src/pages/page-editor/els/page-editor.el.text.vue @@ -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; } diff --git a/packages/frontend/src/pages/page-editor/page-editor.container.vue b/packages/frontend/src/pages/page-editor/page-editor.container.vue index 2531de0e62..28b224f752 100644 --- a/packages/frontend/src/pages/page-editor/page-editor.container.vue +++ b/packages/frontend/src/pages/page-editor/page-editor.container.vue @@ -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 { diff --git a/packages/frontend/src/pages/page.vue b/packages/frontend/src/pages/page.vue index 12b70fa64f..544e112111 100644 --- a/packages/frontend/src/pages/page.vue +++ b/packages/frontend/src/pages/page.vue @@ -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> diff --git a/packages/frontend/src/pages/reversi/game.board.vue b/packages/frontend/src/pages/reversi/game.board.vue index 54e66f6e16..429f502133 100644 --- a/packages/frontend/src/pages/reversi/game.board.vue +++ b/packages/frontend/src/pages/reversi/game.board.vue @@ -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 { diff --git a/packages/frontend/src/pages/reversi/game.setting.vue b/packages/frontend/src/pages/reversi/game.setting.vue index 08bb3cb76c..dfb6e3f53e 100644 --- a/packages/frontend/src/pages/reversi/game.setting.vue +++ b/packages/frontend/src/pages/reversi/game.setting.vue @@ -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> diff --git a/packages/frontend/src/pages/reversi/index.vue b/packages/frontend/src/pages/reversi/index.vue index d823861b4a..d608a2411c 100644 --- a/packages/frontend/src/pages/reversi/index.vue +++ b/packages/frontend/src/pages/reversi/index.vue @@ -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; } diff --git a/packages/frontend/src/pages/scratchpad.vue b/packages/frontend/src/pages/scratchpad.vue index 155d8b82d7..2250e1ce60 100644 --- a/packages/frontend/src/pages/scratchpad.vue +++ b/packages/frontend/src/pages/scratchpad.vue @@ -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; } diff --git a/packages/frontend/src/pages/search.note.vue b/packages/frontend/src/pages/search.note.vue index 66c5c92480..d64537d289 100644 --- a/packages/frontend/src/pages/search.note.vue +++ b/packages/frontend/src/pages/search.note.vue @@ -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; } diff --git a/packages/frontend/src/pages/settings/2fa.vue b/packages/frontend/src/pages/settings/2fa.vue index 6a9a1e16e2..a76b748ac1 100644 --- a/packages/frontend/src/pages/settings/2fa.vue +++ b/packages/frontend/src/pages/settings/2fa.vue @@ -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"/> diff --git a/packages/frontend/src/pages/settings/accounts.vue b/packages/frontend/src/pages/settings/accounts.vue index 08c9261dcf..1bbedb817e 100644 --- a/packages/frontend/src/pages/settings/accounts.vue +++ b/packages/frontend/src/pages/settings/accounts.vue @@ -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); } diff --git a/packages/frontend/src/pages/settings/apps.vue b/packages/frontend/src/pages/settings/apps.vue index c58ea5d378..68e36ef1bb 100644 --- a/packages/frontend/src/pages/settings/apps.vue +++ b/packages/frontend/src/pages/settings/apps.vue @@ -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> diff --git a/packages/frontend/src/pages/settings/avatar-decoration.decoration.vue b/packages/frontend/src/pages/settings/avatar-decoration.decoration.vue index 9f7852a71d..5c59f4cbe4 100644 --- a/packages/frontend/src/pages/settings/avatar-decoration.decoration.vue +++ b/packages/frontend/src/pages/settings/avatar-decoration.decoration.vue @@ -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 { diff --git a/packages/frontend/src/pages/settings/avatar-decoration.dialog.vue b/packages/frontend/src/pages/settings/avatar-decoration.dialog.vue index 4ec4610279..b84665b111 100644 --- a/packages/frontend/src/pages/settings/avatar-decoration.dialog.vue +++ b/packages/frontend/src/pages/settings/avatar-decoration.dialog.vue @@ -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> diff --git a/packages/frontend/src/pages/settings/avatar-decoration.vue b/packages/frontend/src/pages/settings/avatar-decoration.vue index 5324a6b7f7..efcd2a5f3f 100644 --- a/packages/frontend/src/pages/settings/avatar-decoration.vue +++ b/packages/frontend/src/pages/settings/avatar-decoration.vue @@ -148,7 +148,7 @@ definePageMetadata(() => ({ .current { padding: 16px; - border-radius: var(--radius); + border-radius: var(--MI-radius); } .decorations { diff --git a/packages/frontend/src/pages/settings/drive-cleaner.vue b/packages/frontend/src/pages/settings/drive-cleaner.vue index 432295aa7f..4054cd810a 100644 --- a/packages/frontend/src/pages/settings/drive-cleaner.vue +++ b/packages/frontend/src/pages/settings/drive-cleaner.vue @@ -177,7 +177,7 @@ definePageMetadata(() => ({ align-items: center; &:hover { - color: var(--accent); + color: var(--MI_THEME-accent); } } diff --git a/packages/frontend/src/pages/settings/email.vue b/packages/frontend/src/pages/settings/email.vue index f226647569..d452f249b6 100644 --- a/packages/frontend/src/pages/settings/email.vue +++ b/packages/frontend/src/pages/settings/email.vue @@ -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> diff --git a/packages/frontend/src/pages/settings/emoji-picker.vue b/packages/frontend/src/pages/settings/emoji-picker.vue index bb919c6c53..eb5424ea6c 100644 --- a/packages/frontend/src/pages/settings/emoji-picker.vue +++ b/packages/frontend/src/pages/settings/emoji-picker.vue @@ -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> diff --git a/packages/frontend/src/pages/settings/index.vue b/packages/frontend/src/pages/settings/index.vue index f6f2ffc553..552b4ee028 100644 --- a/packages/frontend/src/pages/settings/index.vue +++ b/packages/frontend/src/pages/settings/index.vue @@ -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> diff --git a/packages/frontend/src/pages/settings/mute-block.vue b/packages/frontend/src/pages/settings/mute-block.vue index a5c381200f..82aeb6063f 100644 --- a/packages/frontend/src/pages/settings/mute-block.vue +++ b/packages/frontend/src/pages/settings/mute-block.vue @@ -243,7 +243,7 @@ definePageMetadata(() => ({ .userItemSub { padding: 6px 12px; font-size: 85%; - color: var(--fgTransparentWeak); + color: var(--MI_THEME-fgTransparentWeak); } .userItemMainBody { diff --git a/packages/frontend/src/pages/settings/navbar.vue b/packages/frontend/src/pages/settings/navbar.vue index a0e6cad9c8..b189db0f8f 100644 --- a/packages/frontend/src/pages/settings/navbar.vue +++ b/packages/frontend/src/pages/settings/navbar.vue @@ -122,7 +122,7 @@ definePageMetadata(() => ({ text-overflow: ellipsis; overflow: hidden; white-space: nowrap; - color: var(--navFg); + color: var(--MI_THEME-navFg); } .itemIcon { diff --git a/packages/frontend/src/pages/settings/other.vue b/packages/frontend/src/pages/settings/other.vue index eb9d158c1e..abe4524126 100644 --- a/packages/frontend/src/pages/settings/other.vue +++ b/packages/frontend/src/pages/settings/other.vue @@ -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({ diff --git a/packages/frontend/src/pages/settings/preferences-backups.vue b/packages/frontend/src/pages/settings/preferences-backups.vue index 8036ef5555..f7dcc7b139 100644 --- a/packages/frontend/src/pages/settings/preferences-backups.vue +++ b/packages/frontend/src/pages/settings/preferences-backups.vue @@ -469,7 +469,7 @@ definePageMetadata(() => ({ <style lang="scss" module> .buttons { display: flex; - gap: var(--margin); + gap: var(--MI-margin); flex-wrap: wrap; } diff --git a/packages/frontend/src/pages/settings/profile.vue b/packages/frontend/src/pages/settings/profile.vue index c94cd512f3..9ff4a63e09 100644 --- a/packages/frontend/src/pages/settings/profile.vue +++ b/packages/frontend/src/pages/settings/profile.vue @@ -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) { diff --git a/packages/frontend/src/pages/settings/security.vue b/packages/frontend/src/pages/settings/security.vue index de0f63630e..8f9d4f858b 100644 --- a/packages/frontend/src/pages/settings/security.vue +++ b/packages/frontend/src/pages/settings/security.vue @@ -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); } } diff --git a/packages/frontend/src/pages/settings/sounds.sound.vue b/packages/frontend/src/pages/settings/sounds.sound.vue index 81478fede5..56f65e2309 100644 --- a/packages/frontend/src/pages/settings/sounds.sound.vue +++ b/packages/frontend/src/pages/settings/sounds.sound.vue @@ -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> diff --git a/packages/frontend/src/pages/settings/theme.vue b/packages/frontend/src/pages/settings/theme.vue index e7aef55a53..34a0245406 100644 --- a/packages/frontend/src/pages/settings/theme.vue +++ b/packages/frontend/src/pages/settings/theme.vue @@ -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 { diff --git a/packages/frontend/src/pages/settings/webhook.edit.vue b/packages/frontend/src/pages/settings/webhook.edit.vue index adeaf8550c..40d23e36c5 100644 --- a/packages/frontend/src/pages/settings/webhook.edit.vue +++ b/packages/frontend/src/pages/settings/webhook.edit.vue @@ -184,6 +184,6 @@ definePageMetadata(() => ({ .description { font-size: 0.85em; padding: 8px 0 0 0; - color: var(--fgTransparentWeak); + color: var(--MI_THEME-fgTransparentWeak); } </style> diff --git a/packages/frontend/src/pages/settings/webhook.vue b/packages/frontend/src/pages/settings/webhook.vue index 0d11b00c97..af8b7ca945 100644 --- a/packages/frontend/src/pages/settings/webhook.vue +++ b/packages/frontend/src/pages/settings/webhook.vue @@ -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> diff --git a/packages/frontend/src/pages/signup-complete.vue b/packages/frontend/src/pages/signup-complete.vue index 226f08bf8e..503e6e0f73 100644 --- a/packages/frontend/src/pages/signup-complete.vue +++ b/packages/frontend/src/pages/signup-complete.vue @@ -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> diff --git a/packages/frontend/src/pages/tag.vue b/packages/frontend/src/pages/tag.vue index 0d261b1af3..a45b61fb10 100644 --- a/packages/frontend/src/pages/tag.vue +++ b/packages/frontend/src/pages/tag.vue @@ -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; } diff --git a/packages/frontend/src/pages/theme-editor.vue b/packages/frontend/src/pages/theme-editor.vue index 2fa6eb81ba..21f4548d2e 100644 --- a/packages/frontend/src/pages/theme-editor.vue +++ b/packages/frontend/src/pages/theme-editor.vue @@ -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 { diff --git a/packages/frontend/src/pages/timeline.vue b/packages/frontend/src/pages/timeline.vue index 60974da971..92bfd9cdf1 100644 --- a/packages/frontend/src/pages/timeline.vue +++ b/packages/frontend/src/pages/timeline.vue @@ -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> diff --git a/packages/frontend/src/pages/user-list-timeline.vue b/packages/frontend/src/pages/user-list-timeline.vue index 396e6eb14a..d7326f0195 100644 --- a/packages/frontend/src/pages/user-list-timeline.vue +++ b/packages/frontend/src/pages/user-list-timeline.vue @@ -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> diff --git a/packages/frontend/src/pages/user/clips.vue b/packages/frontend/src/pages/user/clips.vue index ac01cff8cd..38ce78e8d5 100644 --- a/packages/frontend/src/pages/user/clips.vue +++ b/packages/frontend/src/pages/user/clips.vue @@ -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> diff --git a/packages/frontend/src/pages/user/follow-list.vue b/packages/frontend/src/pages/user/follow-list.vue index e60dccec17..868767e8f4 100644 --- a/packages/frontend/src/pages/user/follow-list.vue +++ b/packages/frontend/src/pages/user/follow-list.vue @@ -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> diff --git a/packages/frontend/src/pages/user/gallery.vue b/packages/frontend/src/pages/user/gallery.vue index 9ba81322ba..0bc5628528 100644 --- a/packages/frontend/src/pages/user/gallery.vue +++ b/packages/frontend/src/pages/user/gallery.vue @@ -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> diff --git a/packages/frontend/src/pages/user/home.vue b/packages/frontend/src/pages/user/home.vue index 279f301d78..30ecbd5100 100644 --- a/packages/frontend/src/pages/user/home.vue +++ b/packages/frontend/src/pages/user/home.vue @@ -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) { diff --git a/packages/frontend/src/pages/user/index.timeline.vue b/packages/frontend/src/pages/user/index.timeline.vue index 8dbf90f344..49d015a530 100644 --- a/packages/frontend/src/pages/user/index.timeline.vue +++ b/packages/frontend/src/pages/user/index.timeline.vue @@ -51,13 +51,13 @@ const pagination = computed(() => tab.value === 'featured' ? { <style lang="scss" module> .tab { - padding: calc(var(--margin) / 2) 0; - background: var(--bg); + padding: calc(var(--MI-margin) / 2) 0; + background: var(--MI_THEME-bg); } .tl { - background: var(--bg); - border-radius: var(--radius); + background: var(--MI_THEME-bg); + border-radius: var(--MI-radius); overflow: clip; } </style> diff --git a/packages/frontend/src/pages/user/lists.vue b/packages/frontend/src/pages/user/lists.vue index 8f95ce2dc9..46af3f7f37 100644 --- a/packages/frontend/src/pages/user/lists.vue +++ b/packages/frontend/src/pages/user/lists.vue @@ -44,12 +44,12 @@ const pagination = { .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; } } diff --git a/packages/frontend/src/pages/user/raw.vue b/packages/frontend/src/pages/user/raw.vue index ac18ad9392..4499eec10a 100644 --- a/packages/frontend/src/pages/user/raw.vue +++ b/packages/frontend/src/pages/user/raw.vue @@ -113,18 +113,18 @@ const suspended = computed(() => props.user.isSuspended ?? false); } > .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); } } </style> diff --git a/packages/frontend/src/pages/user/reactions.vue b/packages/frontend/src/pages/user/reactions.vue index 3671decc18..7168778e12 100644 --- a/packages/frontend/src/pages/user/reactions.vue +++ b/packages/frontend/src/pages/user/reactions.vue @@ -44,7 +44,7 @@ const pagination = { align-items: center; padding: 8px 16px; margin-bottom: 8px; - border-bottom: solid 2px var(--divider); + border-bottom: solid 2px var(--MI_THEME-divider); } .avatar { diff --git a/packages/frontend/src/pages/welcome.entrance.a.vue b/packages/frontend/src/pages/welcome.entrance.a.vue index 0d132e6a86..f6b7557e6d 100644 --- a/packages/frontend/src/pages/welcome.entrance.a.vue +++ b/packages/frontend/src/pages/welcome.entrance.a.vue @@ -98,7 +98,7 @@ misskeyApiGet('federation/instances', { left: 0; width: 100vw; height: 100vh; - background: var(--accent); + background: var(--MI_THEME-accent); clip-path: polygon(0% 0%, 45% 0%, 20% 100%, 0% 100%); } > .shape2 { @@ -107,7 +107,7 @@ misskeyApiGet('federation/instances', { left: 0; width: 100vw; height: 100vh; - background: var(--accent); + background: var(--MI_THEME-accent); clip-path: polygon(0% 0%, 25% 0%, 35% 100%, 0% 100%); opacity: 0.5; } @@ -164,9 +164,9 @@ misskeyApiGet('federation/instances', { left: 0; right: 0; margin: auto; - background: var(--acrylicPanel); - -webkit-backdrop-filter: var(--blur, blur(15px)); - backdrop-filter: var(--blur, blur(15px)); + background: var(--MI_THEME-acrylicPanel); + -webkit-backdrop-filter: var(--MI-blur, blur(15px)); + backdrop-filter: var(--MI-blur, blur(15px)); border-radius: var(--radius-ellipse); overflow: clip; width: 800px; @@ -186,7 +186,7 @@ misskeyApiGet('federation/instances', { vertical-align: bottom; padding: 6px 12px 6px 6px; margin: 0 10px 0 0; - background: var(--panel); + background: var(--MI_THEME-panel); border-radius: var(--radius-ellipse); > :global(.icon) { diff --git a/packages/frontend/src/pages/welcome.setup.vue b/packages/frontend/src/pages/welcome.setup.vue index 5a41100bf1..58e815d89c 100644 --- a/packages/frontend/src/pages/welcome.setup.vue +++ b/packages/frontend/src/pages/welcome.setup.vue @@ -14,6 +14,10 @@ SPDX-License-Identifier: AGPL-3.0-only </div> <div class="_gaps_m" style="padding: 32px;"> <div>{{ i18n.ts.intro }}</div> + <MkInput v-model="setupPassword" type="password" data-cy-admin-initial-password> + <template #label>{{ i18n.ts.initialPasswordForSetup }} <div v-tooltip:dialog="i18n.ts.initialPasswordForSetupDescription" class="_button _help"><i class="ti ti-help-circle"></i></div></template> + <template #prefix><i class="ti ti-lock"></i></template> + </MkInput> <MkInput v-model="username" pattern="^[a-zA-Z0-9_]{1,20}$" :spellcheck="false" required data-cy-admin-username> <template #label>{{ i18n.ts.username }}</template> <template #prefix>@</template> @@ -36,9 +40,9 @@ SPDX-License-Identifier: AGPL-3.0-only <script lang="ts" setup> import { ref } from 'vue'; +import { host, version } from '@@/js/config.js'; import MkButton from '@/components/MkButton.vue'; import MkInput from '@/components/MkInput.vue'; -import { host, version } from '@@/js/config.js'; import * as os from '@/os.js'; import { misskeyApi } from '@/scripts/misskey-api.js'; import { login } from '@/account.js'; @@ -47,6 +51,7 @@ import MkAnimBg from '@/components/MkAnimBg.vue'; const username = ref(''); const password = ref(''); +const setupPassword = ref(''); const submitting = ref(false); function submit() { @@ -56,14 +61,27 @@ function submit() { misskeyApi('admin/accounts/create', { username: username.value, password: password.value, + setupPassword: setupPassword.value === '' ? null : setupPassword.value, }).then(res => { return login(res.token); - }).catch(() => { + }).catch((err) => { submitting.value = false; + let title = i18n.ts.somethingHappened; + let text = err.message + '\n' + err.id; + + if (err.code === 'ACCESS_DENIED') { + title = i18n.ts.permissionDeniedError; + text = i18n.ts.operationForbidden; + } else if (err.code === 'INCORRECT_INITIAL_PASSWORD') { + title = i18n.ts.permissionDeniedError; + text = i18n.ts.incorrectPassword; + } + os.alert({ type: 'error', - text: i18n.ts.somethingHappened, + title, + text, }); }); } @@ -74,14 +92,14 @@ function submit() { min-height: 100svh; padding: 32px 32px 64px 32px; box-sizing: border-box; -display: grid; -place-content: center; + display: grid; + 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; @@ -92,8 +110,8 @@ place-content: center; font-size: 1.5em; text-align: center; padding: 32px; - background: var(--accentedBg); - color: var(--accent); + background: var(--MI_THEME-accentedBg); + color: var(--MI_THEME-accent); font-weight: bold; } diff --git a/packages/frontend/src/pages/welcome.timeline.note.vue b/packages/frontend/src/pages/welcome.timeline.note.vue index ee8d4e1d62..5a03483d0c 100644 --- a/packages/frontend/src/pages/welcome.timeline.note.vue +++ b/packages/frontend/src/pages/welcome.timeline.note.vue @@ -84,7 +84,7 @@ onUpdated(() => { 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)); } } @@ -100,7 +100,7 @@ onUpdated(() => { margin: 8px -16px -8px; padding: 8px 16px 0; width: calc(100% + 32px); - border-top: 1px solid var(--divider); + border-top: 1px solid var(--MI_THEME-divider); } .richcontent { diff --git a/packages/frontend/src/pages/welcome.timeline.vue b/packages/frontend/src/pages/welcome.timeline.vue index 16d558cc91..2964b15164 100644 --- a/packages/frontend/src/pages/welcome.timeline.vue +++ b/packages/frontend/src/pages/welcome.timeline.vue @@ -60,7 +60,7 @@ onUpdated(() => { transform: translate3d(0, 0, 0); } 100% { - transform: translate3d(0, calc(calc(-100% - 128px) - var(--margin)), 0); + transform: translate3d(0, calc(calc(-100% - 128px) - var(--MI-margin)), 0); } } @@ -69,7 +69,7 @@ onUpdated(() => { transform: translate3d(0, -128px, 0); } 100% { - transform: translate3d(0, calc(calc(-100% - 128px) - var(--margin)), 0); + transform: translate3d(0, calc(calc(-100% - 128px) - var(--MI-margin)), 0); } } |