Merge branch 'misskey-develop' into merge/2025-03-24
# Conflicts: # .github/workflows/api-misskey-js.yml # .github/workflows/changelog-check.yml # .github/workflows/check-misskey-js-autogen.yml # .github/workflows/get-api-diff.yml # .github/workflows/lint.yml # .github/workflows/locale.yml # .github/workflows/on-release-created.yml # .github/workflows/storybook.yml # .github/workflows/test-backend.yml # .github/workflows/test-federation.yml # .github/workflows/test-frontend.yml # .github/workflows/test-misskey-js.yml # .github/workflows/test-production.yml # .github/workflows/validate-api-json.yml # locales/index.d.ts # package.json # packages/misskey-js/generator/package.json # packages/misskey-js/package.json # pnpm-lock.yaml # scripts/changelog-checker/package-lock.json # scripts/changelog-checker/package.json
This commit is contained in:
commit
7ff15816d1
35 changed files with 716 additions and 379 deletions
|
|
@ -12,11 +12,13 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
<path transform="scale(.26458)" d="m439.77 247.19c-43.673 0-78.832 35.157-78.832 78.83v249.98h407.06v-328.81z" :fill="themeVariables.panel"/>
|
||||
</g>
|
||||
<circle cx="32" cy="83" r="21" :fill="themeVariables.accentedBg"/>
|
||||
<circle cx="136" cy="106" r="23" :fill="themeVariables.fg" fill-opacity="0.5"/>
|
||||
<g :fill="themeVariables.fg" fill-rule="evenodd">
|
||||
<rect x="171" y="88" width="48" height="6" ry="3"/>
|
||||
<rect x="171" y="108" width="48" height="6" ry="3"/>
|
||||
<rect x="171" y="128" width="48" height="6" ry="3"/>
|
||||
<g>
|
||||
<rect x="120" y="88" width="40" height="6" ry="3" :fill="themeVariables.fg"/>
|
||||
<rect x="170" y="88" width="20" height="6" ry="3" :fill="themeVariables.mention"/>
|
||||
<rect x="120" y="108" width="20" height="6" ry="3" :fill="themeVariables.hashtag"/>
|
||||
<rect x="150" y="108" width="40" height="6" ry="3" :fill="themeVariables.fg"/>
|
||||
<rect x="120" y="128" width="40" height="6" ry="3" :fill="themeVariables.fg"/>
|
||||
<rect x="170" y="128" width="20" height="6" ry="3" :fill="themeVariables.link"/>
|
||||
</g>
|
||||
<path d="m65.498 40.892h137.7" :stroke="themeVariables.divider" stroke-width="0.75"/>
|
||||
<g transform="matrix(.60823 0 0 .60823 25.45 75.755)" fill="none" :stroke="themeVariables.accent" stroke-linecap="round" stroke-linejoin="round" stroke-width="2">
|
||||
|
|
@ -53,14 +55,23 @@ const themeVariables = ref<{
|
|||
bg: string;
|
||||
panel: string;
|
||||
fg: string;
|
||||
mention: string;
|
||||
hashtag: string;
|
||||
link: string;
|
||||
divider: string;
|
||||
accent: string;
|
||||
accentedBg: string;
|
||||
navBg: string;
|
||||
success: string;
|
||||
warn: string;
|
||||
error: string;
|
||||
}>({
|
||||
bg: 'var(--MI_THEME-bg)',
|
||||
panel: 'var(--MI_THEME-panel)',
|
||||
fg: 'var(--MI_THEME-fg)',
|
||||
mention: 'var(--MI_THEME-mention)',
|
||||
hashtag: 'var(--MI_THEME-hashtag)',
|
||||
link: 'var(--MI_THEME-link)',
|
||||
divider: 'var(--MI_THEME-divider)',
|
||||
accent: 'var(--MI_THEME-accent)',
|
||||
accentedBg: 'var(--MI_THEME-accentedBg)',
|
||||
|
|
@ -86,6 +97,9 @@ watch(() => props.theme, (theme) => {
|
|||
bg: compiled.bg ?? 'var(--MI_THEME-bg)',
|
||||
panel: compiled.panel ?? 'var(--MI_THEME-panel)',
|
||||
fg: compiled.fg ?? 'var(--MI_THEME-fg)',
|
||||
mention: compiled.mention ?? 'var(--MI_THEME-mention)',
|
||||
hashtag: compiled.hashtag ?? 'var(--MI_THEME-hashtag)',
|
||||
link: compiled.link ?? 'var(--MI_THEME-link)',
|
||||
divider: compiled.divider ?? 'var(--MI_THEME-divider)',
|
||||
accent: compiled.accent ?? 'var(--MI_THEME-accent)',
|
||||
accentedBg: compiled.accentedBg ?? 'var(--MI_THEME-accentedBg)',
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
<template>
|
||||
<div>
|
||||
<MkAnimBg style="position: absolute;"/>
|
||||
<div class="_pageScrollable" style="position: absolute; top: 0; width: 100%; height: 100%;">
|
||||
<div class="_pageScrollable" :class="$style.body">
|
||||
<slot></slot>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -17,5 +17,13 @@ import MkAnimBg from '@/components/MkAnimBg.vue';
|
|||
</script>
|
||||
|
||||
<style lang="scss" module>
|
||||
.body {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
// _pageScrollable はパフォーマンス上の理由で背景色が設定されているため
|
||||
background: transparent !important;
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -17,7 +17,6 @@ export type Keys = (
|
|||
'lang' |
|
||||
'drafts' |
|
||||
'hashtags' |
|
||||
'wallpaper' |
|
||||
'colorScheme' |
|
||||
'useSystemFont' |
|
||||
'fontSize' |
|
||||
|
|
|
|||
|
|
@ -12,6 +12,8 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
</MkSwitch>
|
||||
</SearchMarker>
|
||||
|
||||
<hr>
|
||||
|
||||
<SearchMarker :keywords="['ui', 'root', 'page']">
|
||||
<MkPreferenceContainer k="deck.useSimpleUiForNonRootPages">
|
||||
<MkSwitch v-model="useSimpleUiForNonRootPages">
|
||||
|
|
@ -74,19 +76,29 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
</MkRange>
|
||||
</MkPreferenceContainer>
|
||||
</SearchMarker>
|
||||
|
||||
<SearchMarker :keywords="['wallpaper']">
|
||||
<MkPreferenceContainer k="deck.wallpaper">
|
||||
<MkButton v-if="wallpaper == null" @click="setWallpaper"><SearchLabel>{{ i18n.ts.setWallpaper }}</SearchLabel></MkButton>
|
||||
<MkButton v-else @click="wallpaper = null">{{ i18n.ts.removeWallpaper }}</MkButton>
|
||||
</MkPreferenceContainer>
|
||||
</SearchMarker>
|
||||
</div>
|
||||
</SearchMarker>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed, ref } from 'vue';
|
||||
import { computed, ref, watch } from 'vue';
|
||||
import MkSwitch from '@/components/MkSwitch.vue';
|
||||
import MkRadios from '@/components/MkRadios.vue';
|
||||
import MkRange from '@/components/MkRange.vue';
|
||||
import MkButton from '@/components/MkButton.vue';
|
||||
import { i18n } from '@/i18n.js';
|
||||
import { definePage } from '@/page.js';
|
||||
import { prefer } from '@/preferences.js';
|
||||
import MkPreferenceContainer from '@/components/MkPreferenceContainer.vue';
|
||||
import { reloadAsk } from '@/utility/reload-ask.js';
|
||||
import { selectFile } from '@/utility/select-file.js';
|
||||
|
||||
const navWindow = prefer.model('deck.navWindow');
|
||||
const useSimpleUiForNonRootPages = prefer.model('deck.useSimpleUiForNonRootPages');
|
||||
|
|
@ -95,6 +107,17 @@ const columnAlign = prefer.model('deck.columnAlign');
|
|||
const columnGap = prefer.model('deck.columnGap');
|
||||
const menuPosition = prefer.model('deck.menuPosition');
|
||||
const navbarPosition = prefer.model('deck.navbarPosition');
|
||||
const wallpaper = prefer.model('deck.wallpaper');
|
||||
|
||||
watch(wallpaper, async () => {
|
||||
await reloadAsk({ reason: i18n.ts.reloadToApplySetting, unison: true });
|
||||
});
|
||||
|
||||
function setWallpaper(ev: MouseEvent) {
|
||||
selectFile(ev.currentTarget ?? ev.target, null).then(file => {
|
||||
wallpaper.value = file.url;
|
||||
});
|
||||
}
|
||||
|
||||
const profilesSyncEnabled = ref(prefer.isSyncEnabled('deck.profiles'));
|
||||
|
||||
|
|
|
|||
|
|
@ -189,17 +189,12 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
<FormLink to="/theme-editor"><template #icon><i class="ti ti-paint"></i></template>{{ i18n.ts._theme.make }}</FormLink>
|
||||
</div>
|
||||
</FormSection>
|
||||
|
||||
<SearchMarker :keywords="['wallpaper']">
|
||||
<MkButton v-if="wallpaper == null" @click="setWallpaper"><SearchLabel>{{ i18n.ts.setWallpaper }}</SearchLabel></MkButton>
|
||||
<MkButton v-else @click="wallpaper = null">{{ i18n.ts.removeWallpaper }}</MkButton>
|
||||
</SearchMarker>
|
||||
</div>
|
||||
</SearchMarker>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed, onActivated, ref, watch } from 'vue';
|
||||
import { computed, ref, watch } from 'vue';
|
||||
import JSON5 from 'json5';
|
||||
import defaultLightTheme from '@@/themes/l-light.json5';
|
||||
import defaultDarkTheme from '@@/themes/d-green-lime.json5';
|
||||
|
|
@ -207,7 +202,6 @@ import type { Theme } from '@/theme.js';
|
|||
import MkSwitch from '@/components/MkSwitch.vue';
|
||||
import FormSection from '@/components/form/section.vue';
|
||||
import FormLink from '@/components/form/link.vue';
|
||||
import MkButton from '@/components/MkButton.vue';
|
||||
import MkFolder from '@/components/MkFolder.vue';
|
||||
import MkThemePreview from '@/components/MkThemePreview.vue';
|
||||
import { getBuiltinThemesRef, getThemesRef } from '@/theme.js';
|
||||
|
|
@ -262,7 +256,6 @@ const lightThemeId = computed({
|
|||
|
||||
const darkMode = computed(store.makeGetterSetter('darkMode'));
|
||||
const syncDeviceDarkMode = prefer.model('syncDeviceDarkMode');
|
||||
const wallpaper = ref(miLocalStorage.getItem('wallpaper'));
|
||||
const themesCount = installedThemes.value.length;
|
||||
|
||||
watch(syncDeviceDarkMode, () => {
|
||||
|
|
@ -271,21 +264,6 @@ watch(syncDeviceDarkMode, () => {
|
|||
}
|
||||
});
|
||||
|
||||
watch(wallpaper, async () => {
|
||||
if (wallpaper.value == null) {
|
||||
miLocalStorage.removeItem('wallpaper');
|
||||
} else {
|
||||
miLocalStorage.setItem('wallpaper', wallpaper.value);
|
||||
}
|
||||
await reloadAsk({ reason: i18n.ts.reloadToApplySetting, unison: true });
|
||||
});
|
||||
|
||||
function setWallpaper(event) {
|
||||
selectFile(event.currentTarget ?? event.target, null).then(file => {
|
||||
wallpaper.value = file.url;
|
||||
});
|
||||
}
|
||||
|
||||
const headerActions = computed(() => []);
|
||||
|
||||
const headerTabs = computed(() => []);
|
||||
|
|
|
|||
|
|
@ -431,6 +431,9 @@ export const PREF_DEF = {
|
|||
'deck.navbarPosition': {
|
||||
default: 'left' as 'left' | 'top' | 'bottom',
|
||||
},
|
||||
'deck.wallpaper': {
|
||||
default: null as string | null,
|
||||
},
|
||||
|
||||
'chat.showSenderName': {
|
||||
default: false,
|
||||
|
|
|
|||
|
|
@ -228,7 +228,7 @@ function more() {
|
|||
|
||||
&:hover {
|
||||
text-decoration: none;
|
||||
color: var(--MI_THEME-navHoverFg);
|
||||
color: light-dark(hsl(from var(--MI_THEME-navFg) h s calc(l - 17)), hsl(from var(--MI_THEME-navFg) h s calc(l + 17)));
|
||||
}
|
||||
|
||||
&.active {
|
||||
|
|
|
|||
|
|
@ -149,7 +149,7 @@ onMounted(() => {
|
|||
|
||||
&:hover {
|
||||
text-decoration: none;
|
||||
color: var(--MI_THEME-navHoverFg);
|
||||
color: light-dark(hsl(from var(--MI_THEME-navFg) h s calc(l - 17)), hsl(from var(--MI_THEME-navFg) h s calc(l + 17)));
|
||||
}
|
||||
|
||||
&.active {
|
||||
|
|
|
|||
|
|
@ -463,7 +463,7 @@ function menuEdit() {
|
|||
|
||||
&:hover {
|
||||
text-decoration: none;
|
||||
color: var(--MI_THEME-navHoverFg);
|
||||
color: light-dark(hsl(from var(--MI_THEME-navFg) h s calc(l - 17)), hsl(from var(--MI_THEME-navFg) h s calc(l + 17)));
|
||||
}
|
||||
|
||||
&.active {
|
||||
|
|
|
|||
|
|
@ -117,13 +117,12 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed, defineAsyncComponent, ref, useTemplateRef, watch } from 'vue';
|
||||
import { computed, defineAsyncComponent, ref, useTemplateRef } from 'vue';
|
||||
import { v4 as uuid } from 'uuid';
|
||||
import XCommon from './_common_/common.vue';
|
||||
import XSidebar from '@/ui/_common_/navbar.vue';
|
||||
import XNavbarH from '@/ui/_common_/navbar-h.vue';
|
||||
import XDrawerMenu from '@/ui/_common_/navbar-for-mobile.vue';
|
||||
import MkButton from '@/components/MkButton.vue';
|
||||
import * as os from '@/os.js';
|
||||
import { navbarItemDef } from '@/navbar.js';
|
||||
import { $i } from '@/i.js';
|
||||
|
|
@ -143,7 +142,6 @@ import XRoleTimelineColumn from '@/ui/deck/role-timeline-column.vue';
|
|||
import XFollowingColumn from '@/ui/deck/following-column.vue';
|
||||
import { mainRouter } from '@/router.js';
|
||||
import { columns, layout, columnTypes, switchProfileMenu, addColumn as addColumnToStore, deleteProfile as deleteProfile_ } from '@/deck.js';
|
||||
import { miLocalStorage } from '@/local-storage.js';
|
||||
|
||||
const XStatusBars = defineAsyncComponent(() => import('@/ui/_common_/statusbars.vue'));
|
||||
const XAnnouncements = defineAsyncComponent(() => import('@/ui/_common_/announcements.vue'));
|
||||
|
|
@ -178,7 +176,7 @@ window.addEventListener('resize', () => {
|
|||
});
|
||||
|
||||
const snapScroll = deviceKind === 'smartphone' || deviceKind === 'tablet';
|
||||
const withWallpaper = miLocalStorage.getItem('wallpaper') != null;
|
||||
const withWallpaper = prefer.s['deck.wallpaper'] != null;
|
||||
const drawerMenuShowing = ref(false);
|
||||
const gap = prefer.r['deck.columnGap'];
|
||||
|
||||
|
|
@ -234,9 +232,6 @@ function onWheel(ev: WheelEvent) {
|
|||
}
|
||||
}
|
||||
|
||||
window.document.documentElement.style.overflowY = 'hidden';
|
||||
window.document.documentElement.style.scrollBehavior = 'auto';
|
||||
|
||||
async function deleteProfile() {
|
||||
if (prefer.s['deck.profile'] == null) return;
|
||||
|
||||
|
|
@ -251,6 +246,12 @@ async function deleteProfile() {
|
|||
os.success();
|
||||
}
|
||||
|
||||
window.document.documentElement.style.overflowY = 'hidden';
|
||||
window.document.documentElement.style.scrollBehavior = 'auto';
|
||||
|
||||
if (prefer.s['deck.wallpaper'] != null) {
|
||||
window.document.documentElement.style.backgroundImage = `url(${prefer.s['deck.wallpaper']})`;
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" module>
|
||||
|
|
|
|||
|
|
@ -48,13 +48,13 @@ import type { MenuItem } from '@/types/menu.js';
|
|||
import { updateColumn, swapLeftColumn, swapRightColumn, swapUpColumn, swapDownColumn, stackLeftColumn, popRightColumn, removeColumn, swapColumn } from '@/deck.js';
|
||||
import * as os from '@/os.js';
|
||||
import { i18n } from '@/i18n.js';
|
||||
import { miLocalStorage } from '@/local-storage.js';
|
||||
import { prefer } from '@/preferences.js';
|
||||
|
||||
provide('shouldHeaderThin', true);
|
||||
provide('shouldOmitHeaderTitle', true);
|
||||
provide('forceSpacerMin', true);
|
||||
|
||||
const withWallpaper = miLocalStorage.getItem('wallpaper') != null;
|
||||
const withWallpaper = prefer.s['deck.wallpaper'] != null;
|
||||
|
||||
const props = withDefaults(defineProps<{
|
||||
column: Column;
|
||||
|
|
|
|||
|
|
@ -37,11 +37,6 @@ export const searchIndexes: SearchIndexItem[] = [
|
|||
label: i18n.ts.themeForDarkMode,
|
||||
keywords: ['dark', 'theme'],
|
||||
},
|
||||
{
|
||||
id: '8wcoRp76b',
|
||||
label: i18n.ts.setWallpaper,
|
||||
keywords: ['wallpaper'],
|
||||
},
|
||||
],
|
||||
label: i18n.ts.theme,
|
||||
keywords: ['theme'],
|
||||
|
|
@ -861,40 +856,45 @@ export const searchIndexes: SearchIndexItem[] = [
|
|||
keywords: ['sync', 'profiles', 'devices'],
|
||||
},
|
||||
{
|
||||
id: 'iEF0gqNAo',
|
||||
id: 'wWH4pxMQN',
|
||||
label: i18n.ts._deck.useSimpleUiForNonRootPages,
|
||||
keywords: ['ui', 'root', 'page'],
|
||||
},
|
||||
{
|
||||
id: 'BNdSeWxZn',
|
||||
id: '3LR509BvD',
|
||||
label: i18n.ts.defaultNavigationBehaviour,
|
||||
keywords: ['default', 'navigation', 'behaviour', 'window'],
|
||||
},
|
||||
{
|
||||
id: 'zT9pGm8DF',
|
||||
id: 'ybU8RLXgm',
|
||||
label: i18n.ts._deck.alwaysShowMainColumn,
|
||||
keywords: ['always', 'show', 'main', 'column'],
|
||||
},
|
||||
{
|
||||
id: '5dk2xv1vc',
|
||||
id: 'xRasZyAVl',
|
||||
label: i18n.ts._deck.columnAlign,
|
||||
keywords: ['column', 'align'],
|
||||
},
|
||||
{
|
||||
id: 'gtdEA4FTa',
|
||||
id: '6qcyPd0oJ',
|
||||
label: i18n.ts._deck.deckMenuPosition,
|
||||
keywords: ['menu', 'position'],
|
||||
},
|
||||
{
|
||||
id: 'DHVFdPBT6',
|
||||
id: '4zk2Now4S',
|
||||
label: i18n.ts._deck.navbarPosition,
|
||||
keywords: ['navbar', 'position'],
|
||||
},
|
||||
{
|
||||
id: '3UQ8rUssZ',
|
||||
id: 'CGNtJ2I3n',
|
||||
label: i18n.ts._deck.columnGap,
|
||||
keywords: ['column', 'gap', 'margin'],
|
||||
},
|
||||
{
|
||||
id: 'rxPDMo7bE',
|
||||
label: i18n.ts.setWallpaper,
|
||||
keywords: ['wallpaper'],
|
||||
},
|
||||
],
|
||||
label: i18n.ts.deck,
|
||||
keywords: ['deck', 'ui'],
|
||||
|
|
|
|||
|
|
@ -9,9 +9,9 @@ import type { toHiragana as toHiraganaType } from 'wanakana';
|
|||
let toHiragana: typeof toHiraganaType = (str?: string) => str ?? '';
|
||||
let isWanakanaLoaded = false;
|
||||
|
||||
/**
|
||||
/**
|
||||
* ローマ字変換のセットアップ(日本語以外の環境で読み込まないのでlazy-loading)
|
||||
*
|
||||
*
|
||||
* ここの比較系関数を使う際は事前に呼び出す必要がある
|
||||
*/
|
||||
export async function initIntlString(forceWanakana = false) {
|
||||
|
|
@ -82,16 +82,17 @@ export function normalizeStringWithHiragana(str: string) {
|
|||
|
||||
/** aとbが同じかどうか */
|
||||
export function compareStringEquals(a: string, b: string) {
|
||||
return (
|
||||
normalizeString(a) === normalizeString(b) ||
|
||||
normalizeStringWithHiragana(a) === normalizeStringWithHiragana(b)
|
||||
);
|
||||
if (a === b) return true; // まったく同じ場合はtrue。なお、ノーマライズ前後で文字数が変化することがあるため、文字数が違うからといってfalseにはできない
|
||||
if (normalizeString(a) === normalizeString(b)) return true;
|
||||
if (normalizeStringWithHiragana(a) === normalizeStringWithHiragana(b)) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/** baseにqueryが含まれているかどうか */
|
||||
export function compareStringIncludes(base: string, query: string) {
|
||||
return (
|
||||
normalizeString(base).includes(normalizeString(query)) ||
|
||||
normalizeStringWithHiragana(base).includes(normalizeStringWithHiragana(query))
|
||||
);
|
||||
if (base === query) return true; // まったく同じ場合は含まれていると考えてよいのでtrue
|
||||
if (base.includes(query)) return true;
|
||||
if (normalizeString(base).includes(normalizeString(query))) return true;
|
||||
if (normalizeStringWithHiragana(base).includes(normalizeStringWithHiragana(query))) return true;
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue