diff options
| author | Hazelnoot <acomputerdog@gmail.com> | 2025-04-02 22:29:14 -0400 |
|---|---|---|
| committer | Hazelnoot <acomputerdog@gmail.com> | 2025-04-02 22:29:14 -0400 |
| commit | dab9b518e48f04833708a1704e331fd262f575bd (patch) | |
| tree | ca4dfba2efbe5d550c7d19474d4d91850cb6ccd2 /packages/frontend/src | |
| parent | fix vue warning about render functions (diff) | |
| parent | 🎨 (diff) | |
| download | sharkey-dab9b518e48f04833708a1704e331fd262f575bd.tar.gz sharkey-dab9b518e48f04833708a1704e331fd262f575bd.tar.bz2 sharkey-dab9b518e48f04833708a1704e331fd262f575bd.zip | |
merge from misskey-develop
Diffstat (limited to 'packages/frontend/src')
| -rw-r--r-- | packages/frontend/src/boot/common.ts | 37 | ||||
| -rw-r--r-- | packages/frontend/src/components/MkAntennaEditor.vue | 4 | ||||
| -rw-r--r-- | packages/frontend/src/components/MkTutorialDialog.vue | 1 | ||||
| -rw-r--r-- | packages/frontend/src/pages/clip.vue | 2 | ||||
| -rw-r--r-- | packages/frontend/src/pages/settings/deck.vue | 2 | ||||
| -rw-r--r-- | packages/frontend/src/pages/settings/emoji-palette.vue | 2 | ||||
| -rw-r--r-- | packages/frontend/src/pages/settings/theme.vue | 20 | ||||
| -rw-r--r-- | packages/frontend/src/pages/tag.vue | 2 | ||||
| -rw-r--r-- | packages/frontend/src/ui/deck.vue | 18 | ||||
| -rw-r--r-- | packages/frontend/src/ui/deck/column.vue | 2 | ||||
| -rw-r--r-- | packages/frontend/src/utility/autogen/settings-search-index.ts | 5 | ||||
| -rw-r--r-- | packages/frontend/src/utility/get-note-menu.ts | 4 | ||||
| -rw-r--r-- | packages/frontend/src/utility/get-user-menu.ts | 2 |
13 files changed, 88 insertions, 13 deletions
diff --git a/packages/frontend/src/boot/common.ts b/packages/frontend/src/boot/common.ts index defdb00568..918a3703c3 100644 --- a/packages/frontend/src/boot/common.ts +++ b/packages/frontend/src/boot/common.ts @@ -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のやつを解除 diff --git a/packages/frontend/src/components/MkAntennaEditor.vue b/packages/frontend/src/components/MkAntennaEditor.vue index ac71618ee2..e1c8200b73 100644 --- a/packages/frontend/src/components/MkAntennaEditor.vue +++ b/packages/frontend/src/components/MkAntennaEditor.vue @@ -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()), diff --git a/packages/frontend/src/components/MkTutorialDialog.vue b/packages/frontend/src/components/MkTutorialDialog.vue index 3e91baada4..92f71b01af 100644 --- a/packages/frontend/src/components/MkTutorialDialog.vue +++ b/packages/frontend/src/components/MkTutorialDialog.vue @@ -249,6 +249,7 @@ async function close(skip: boolean) { .pageFooter { position: sticky; + z-index: 1; bottom: 0; left: 0; flex-shrink: 0; diff --git a/packages/frontend/src/pages/clip.vue b/packages/frontend/src/pages/clip.vue index 041364d4fc..22c8a6b49d 100644 --- a/packages/frontend/src/pages/clip.vue +++ b/packages/frontend/src/pages/clip.vue @@ -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); }, diff --git a/packages/frontend/src/pages/settings/deck.vue b/packages/frontend/src/pages/settings/deck.vue index f4bce8a5dd..39055268d4 100644 --- a/packages/frontend/src/pages/settings/deck.vue +++ b/packages/frontend/src/pages/settings/deck.vue @@ -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> diff --git a/packages/frontend/src/pages/settings/emoji-palette.vue b/packages/frontend/src/pages/settings/emoji-palette.vue index f11261c05b..6de266689c 100644 --- a/packages/frontend/src/pages/settings/emoji-palette.vue +++ b/packages/frontend/src/pages/settings/emoji-palette.vue @@ -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> diff --git a/packages/frontend/src/pages/settings/theme.vue b/packages/frontend/src/pages/settings/theme.vue index 5a96fdf0fb..88ddbb7660 100644 --- a/packages/frontend/src/pages/settings/theme.vue +++ b/packages/frontend/src/pages/settings/theme.vue @@ -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(() => []); diff --git a/packages/frontend/src/pages/tag.vue b/packages/frontend/src/pages/tag.vue index 9b789e0d5b..77e102f239 100644 --- a/packages/frontend/src/pages/tag.vue +++ b/packages/frontend/src/pages/tag.vue @@ -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); diff --git a/packages/frontend/src/ui/deck.vue b/packages/frontend/src/ui/deck.vue index 79d8b1f1d2..09d362fa42 100644 --- a/packages/frontend/src/ui/deck.vue +++ b/packages/frontend/src/ui/deck.vue @@ -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; } diff --git a/packages/frontend/src/ui/deck/column.vue b/packages/frontend/src/ui/deck/column.vue index 09f748fcc6..0cffc628f0 100644 --- a/packages/frontend/src/ui/deck/column.vue +++ b/packages/frontend/src/ui/deck/column.vue @@ -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)"> diff --git a/packages/frontend/src/utility/autogen/settings-search-index.ts b/packages/frontend/src/utility/autogen/settings-search-index.ts index bf3f0b1428..ecf8001c1f 100644 --- a/packages/frontend/src/utility/autogen/settings-search-index.ts +++ b/packages/frontend/src/utility/autogen/settings-search-index.ts @@ -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'], diff --git a/packages/frontend/src/utility/get-note-menu.ts b/packages/frontend/src/utility/get-note-menu.ts index 723b109547..d796eb4fba 100644 --- a/packages/frontend/src/utility/get-note-menu.ts +++ b/packages/frontend/src/utility/get-note-menu.ts @@ -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)); } } diff --git a/packages/frontend/src/utility/get-user-menu.ts b/packages/frontend/src/utility/get-user-menu.ts index 8eb2ef3ec9..eecd87147b 100644 --- a/packages/frontend/src/utility/get-user-menu.ts +++ b/packages/frontend/src/utility/get-user-menu.ts @@ -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, |