1
0

merge from misskey-develop

This commit is contained in:
Hazelnoot
2025-04-02 22:29:14 -04:00
54 changed files with 614 additions and 118 deletions
+36 -1
View File
@@ -5,7 +5,7 @@
import { watch, version as vueVersion } from 'vue';
import { compareVersions } from 'compare-versions';
import { version, lang, langsVersion, updateLocale, locale } from '@@/js/config.js';
import { version, lang, langsVersion, updateLocale, locale, apiUrl } from '@@/js/config.js';
import defaultLightTheme from '@@/themes/l-light.json5';
import defaultDarkTheme from '@@/themes/d-green-lime.json5';
import type { App } from 'vue';
@@ -282,6 +282,41 @@ export async function common(createVue: () => Promise<App<Element>>) {
return root;
})();
if (instance.sentryForFrontend) {
const Sentry = await import('@sentry/vue');
Sentry.init({
app,
integrations: [
...(instance.sentryForFrontend.vueIntegration !== undefined ? [
Sentry.vueIntegration(instance.sentryForFrontend.vueIntegration ?? undefined),
] : []),
...(instance.sentryForFrontend.browserTracingIntegration !== undefined ? [
Sentry.browserTracingIntegration(instance.sentryForFrontend.browserTracingIntegration ?? undefined),
] : []),
...(instance.sentryForFrontend.replayIntegration !== undefined ? [
Sentry.replayIntegration(instance.sentryForFrontend.replayIntegration ?? undefined),
] : []),
],
// Set tracesSampleRate to 1.0 to capture 100%
tracesSampleRate: 1.0,
// Set `tracePropagationTargets` to control for which URLs distributed tracing should be enabled
...(instance.sentryForFrontend.browserTracingIntegration !== undefined ? {
tracePropagationTargets: [apiUrl],
} : {}),
// Capture Replay for 10% of all sessions,
// plus for 100% of sessions with an error
...(instance.sentryForFrontend.replayIntegration !== undefined ? {
replaysSessionSampleRate: 0.1,
replaysOnErrorSampleRate: 1.0,
} : {}),
...instance.sentryForFrontend.options,
});
}
app.mount(rootEl);
// boot.jsのやつを解除
@@ -39,6 +39,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<MkSwitch v-model="localOnly">{{ i18n.ts.localOnly }}</MkSwitch>
<MkSwitch v-model="caseSensitive">{{ i18n.ts.caseSensitive }}</MkSwitch>
<MkSwitch v-model="withFile">{{ i18n.ts.withFileAntenna }}</MkSwitch>
<MkSwitch v-model="hideNotesInSensitiveChannel">{{ i18n.ts.hideNotesInSensitiveChannel }}</MkSwitch>
</div>
<div :class="$style.actions">
<div class="_buttons">
@@ -86,6 +87,7 @@ const initialAntenna = deepMerge<PartialAllowedAntenna>(props.antenna ?? {}, {
caseSensitive: false,
localOnly: false,
withFile: false,
hideNotesInSensitiveChannel: false,
isActive: true,
hasUnreadNote: false,
notify: false,
@@ -108,6 +110,7 @@ const localOnly = ref<boolean>(initialAntenna.localOnly);
const excludeBots = ref<boolean>(initialAntenna.excludeBots);
const withReplies = ref<boolean>(initialAntenna.withReplies);
const withFile = ref<boolean>(initialAntenna.withFile);
const hideNotesInSensitiveChannel = ref<boolean>(initialAntenna.hideNotesInSensitiveChannel);
const userLists = ref<Misskey.entities.UserList[] | null>(null);
watch(() => src.value, async () => {
@@ -124,6 +127,7 @@ async function saveAntenna() {
excludeBots: excludeBots.value,
withReplies: withReplies.value,
withFile: withFile.value,
hideNotesInSensitiveChannel: hideNotesInSensitiveChannel.value,
caseSensitive: caseSensitive.value,
localOnly: localOnly.value,
users: users.value.trim().split('\n').map(x => x.trim()),
@@ -249,6 +249,7 @@ async function close(skip: boolean) {
.pageFooter {
position: sticky;
z-index: 1;
bottom: 0;
left: 0;
flex-shrink: 0;
+1 -1
View File
@@ -150,7 +150,7 @@ const headerActions = computed(() => clip.value && isOwned.value ? [{
},
}, {
icon: 'ti ti-code',
text: i18n.ts.genEmbedCode,
text: i18n.ts.embed,
action: () => {
genEmbedCode('clips', clip.value!.id);
},
@@ -8,7 +8,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<div class="_gaps_m">
<SearchMarker :keywords="['sync', 'profiles', 'devices']">
<MkSwitch :modelValue="profilesSyncEnabled" @update:modelValue="changeProfilesSyncEnabled">
<template #label><SearchLabel>{{ i18n.ts._deck.enableSyncBetweenDevicesForProfiles }}</SearchLabel></template>
<template #label><i class="ti ti-cloud-cog"></i> <SearchLabel>{{ i18n.ts._deck.enableSyncBetweenDevicesForProfiles }}</SearchLabel></template>
</MkSwitch>
</SearchMarker>
@@ -26,7 +26,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<div class="_gaps_m">
<SearchMarker :keywords="['sync', 'palettes', 'devices']">
<MkSwitch :modelValue="palettesSyncEnabled" @update:modelValue="changePalettesSyncEnabled">
<template #label><SearchLabel>{{ i18n.ts._emojiPalette.enableSyncBetweenDevicesForPalettes }}</SearchLabel></template>
<template #label><i class="ti ti-cloud-cog"></i> <SearchLabel>{{ i18n.ts._emojiPalette.enableSyncBetweenDevicesForPalettes }}</SearchLabel></template>
</MkSwitch>
</SearchMarker>
</div>
@@ -181,6 +181,12 @@ SPDX-License-Identifier: AGPL-3.0-only
</template>
</div>
<SearchMarker :keywords="['sync', 'themes', 'devices']">
<MkSwitch :modelValue="themesSyncEnabled" @update:modelValue="changeThemesSyncEnabled">
<template #label><i class="ti ti-cloud-cog"></i> <SearchLabel>{{ i18n.ts._settings.enableSyncThemesBetweenDevices }}</SearchLabel></template>
</MkSwitch>
</SearchMarker>
<FormSection>
<div class="_formLinksGrid">
<FormLink to="/settings/theme/manage"><template #icon><i class="ti ti-tool"></i></template>{{ i18n.ts._theme.manage }}<template #suffix>{{ themesCount }}</template></FormLink>
@@ -264,6 +270,20 @@ watch(syncDeviceDarkMode, () => {
}
});
const themesSyncEnabled = ref(prefer.isSyncEnabled('themes'));
function changeThemesSyncEnabled(value: boolean) {
if (value) {
prefer.enableSync('themes').then((res) => {
if (res == null) return;
if (res.enabled) themesSyncEnabled.value = true;
});
} else {
prefer.disableSync('themes');
themesSyncEnabled.value = false;
}
}
const headerActions = computed(() => []);
const headerTabs = computed(() => []);
+1 -1
View File
@@ -56,7 +56,7 @@ const headerActions = computed(() => [{
label: i18n.ts.more,
handler: (ev: MouseEvent) => {
os.popupMenu([{
text: i18n.ts.genEmbedCode,
text: i18n.ts.embed,
icon: 'ti ti-code',
action: () => {
genEmbedCode('tags', props.tag);
+14 -4
View File
@@ -12,15 +12,15 @@ SPDX-License-Identifier: AGPL-3.0-only
<XAnnouncements v-if="$i"/>
<XStatusBars/>
<div :class="$style.columnsWrapper">
<div ref="columnsEl" :class="[$style.columns, { [$style.center]: prefer.r['deck.columnAlign'].value === 'center', [$style.snapScroll]: snapScroll }]" @contextmenu.self.prevent="onContextmenu" @wheel.self="onWheel">
<!-- passive: https://bugs.webkit.org/show_bug.cgi?id=281300 -->
<div ref="columnsEl" :class="[$style.columns, { [$style.center]: prefer.r['deck.columnAlign'].value === 'center', [$style.snapScroll]: snapScroll }]" @contextmenu.self.prevent="onContextmenu" @wheel.passive.self="onWheel">
<!-- sectionを利用しているのはdeck.vue側でcolumnに対してfirst-of-typeを効かせるため -->
<section
v-for="ids in layout"
:class="$style.section"
:style="columns.filter(c => ids.includes(c.id)).some(c => c.flexible) ? { flex: 1, minWidth: '350px' } : { width: Math.max(...columns.filter(c => ids.includes(c.id)).map(c => c.width)) + 'px' }"
@wheel.self="onWheel"
@wheel.passive.self="onWheel"
>
<Suspense>
<component
@@ -175,7 +175,8 @@ window.addEventListener('resize', () => {
isMobile.value = window.innerWidth <= 500;
});
const snapScroll = deviceKind === 'smartphone' || deviceKind === 'tablet';
// ポインターイベント非対応用に初期値はUAから出す
const snapScroll = ref(deviceKind === 'smartphone' || deviceKind === 'tablet');
const withWallpaper = prefer.s['deck.wallpaper'] != null;
const drawerMenuShowing = ref(false);
const gap = prefer.r['deck.columnGap'];
@@ -226,7 +227,16 @@ const onContextmenu = (ev) => {
}], ev);
};
// タッチでスクロールしてるときはスナップスクロールを有効にする
function pointerEvent(ev: PointerEvent) {
snapScroll.value = ev.pointerType === 'touch';
}
window.document.addEventListener('pointerdown', pointerEvent, { passive: true });
function onWheel(ev: WheelEvent) {
// WheelEvent はマウスからしか発火しないのでスナップスクロールは無効化する
snapScroll.value = false;
if (ev.deltaX === 0 && columnsEl.value != null) {
columnsEl.value.scrollLeft += ev.deltaY;
}
+1 -1
View File
@@ -17,7 +17,7 @@ SPDX-License-Identifier: AGPL-3.0-only
@dragstart="onDragstart"
@dragend="onDragend"
@contextmenu.prevent.stop="onContextmenu"
@wheel="emit('headerWheel', $event)"
@wheel.passive="emit('headerWheel', $event)"
>
<svg viewBox="0 0 256 128" :class="$style.tabShape">
<g transform="matrix(6.2431,0,0,6.2431,-677.417,-29.3839)">
@@ -37,6 +37,11 @@ export const searchIndexes: SearchIndexItem[] = [
label: i18n.ts.themeForDarkMode,
keywords: ['dark', 'theme'],
},
{
id: 'jwW5HULqA',
label: i18n.ts._settings.enableSyncThemesBetweenDevices,
keywords: ['sync', 'themes', 'devices'],
},
],
label: i18n.ts.theme,
keywords: ['theme'],
@@ -342,7 +342,7 @@ export function getNoteMenu(props: {
},
});
} else {
menuItems.push(getNoteEmbedCodeMenu(appearNote, i18n.ts.genEmbedCode));
menuItems.push(getNoteEmbedCodeMenu(appearNote, i18n.ts.embed));
}
if (isSupportShare()) {
@@ -506,7 +506,7 @@ export function getNoteMenu(props: {
},
});
} else {
menuItems.push(getNoteEmbedCodeMenu(appearNote, i18n.ts.genEmbedCode));
menuItems.push(getNoteEmbedCodeMenu(appearNote, i18n.ts.embed));
}
}
@@ -197,7 +197,7 @@ export function getUserMenu(user: Misskey.entities.UserDetailed, router: Router
} else {
menuItems.push({
icon: 'ti ti-code',
text: i18n.ts.genEmbedCode,
text: i18n.ts.embed,
type: 'parent',
children: [{
text: i18n.ts.noteOfThisUser,