diff options
| author | misskey-release-bot[bot] <157398866+misskey-release-bot[bot]@users.noreply.github.com> | 2025-12-22 05:30:45 +0000 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-12-22 05:30:45 +0000 |
| commit | 0d46089f9a18abbb001fee2860dfaabf881831b3 (patch) | |
| tree | 8315f33781b790084279680d05ea521f47fe1219 /packages/frontend/src/ui | |
| parent | Merge pull request #16972 from misskey-dev/develop (diff) | |
| parent | Release: 2025.12.2 (diff) | |
| download | misskey-0d46089f9a18abbb001fee2860dfaabf881831b3.tar.gz misskey-0d46089f9a18abbb001fee2860dfaabf881831b3.tar.bz2 misskey-0d46089f9a18abbb001fee2860dfaabf881831b3.zip | |
Merge pull request #16998 from misskey-dev/develop
Release: 2025.12.2
Diffstat (limited to 'packages/frontend/src/ui')
| -rw-r--r-- | packages/frontend/src/ui/_common_/navbar.vue | 11 | ||||
| -rw-r--r-- | packages/frontend/src/ui/deck.vue | 52 | ||||
| -rw-r--r-- | packages/frontend/src/ui/universal.vue | 15 |
3 files changed, 57 insertions, 21 deletions
diff --git a/packages/frontend/src/ui/_common_/navbar.vue b/packages/frontend/src/ui/_common_/navbar.vue index f37e7ae85e..c679ee7a92 100644 --- a/packages/frontend/src/ui/_common_/navbar.vue +++ b/packages/frontend/src/ui/_common_/navbar.vue @@ -14,6 +14,9 @@ SPDX-License-Identifier: AGPL-3.0-only <i v-if="store.r.realtimeMode.value" class="ti ti-bolt ti-fw"></i> <i v-else class="ti ti-bolt-off ti-fw"></i> </button> + <button v-if="!iconOnly && showWidgetButton" v-tooltip.noDelay.right="i18n.ts.widgets" class="_button" :class="[$style.widget]" @click="() => emit('widgetButtonClick')"> + <i class="ti ti-apps ti-fw"></i> + </button> </div> <div :class="$style.middle"> <MkA v-tooltip.noDelay.right="i18n.ts.timeline" :class="$style.item" :activeClass="$style.active" to="/" exact> @@ -51,7 +54,7 @@ SPDX-License-Identifier: AGPL-3.0-only </MkA> </div> <div :class="$style.bottom"> - <button v-if="showWidgetButton" v-tooltip.noDelay.right="i18n.ts.widgets" class="_button" :class="[$style.widget]" @click="() => emit('widgetButtonClick')"> + <button v-if="iconOnly && showWidgetButton" v-tooltip.noDelay.right="i18n.ts.widgets" class="_button" :class="[$style.widget]" @click="() => emit('widgetButtonClick')"> <i class="ti ti-apps ti-fw"></i> </button> <button v-if="iconOnly" v-tooltip.noDelay.right="i18n.ts.realtimeMode" class="_button" :class="[$style.realtimeMode, store.r.realtimeMode.value ? $style.on : null]" @click="toggleRealtimeMode"> @@ -436,6 +439,12 @@ function menuEdit() { } } + .widget { + display: inline-block; + width: var(--top-height); + margin-left: auto; + } + .bottom { position: sticky; bottom: 0; diff --git a/packages/frontend/src/ui/deck.vue b/packages/frontend/src/ui/deck.vue index 0941c25467..484b7f277a 100644 --- a/packages/frontend/src/ui/deck.vue +++ b/packages/frontend/src/ui/deck.vue @@ -38,36 +38,39 @@ SPDX-License-Identifier: AGPL-3.0-only @headerWheel="onWheel" /> </section> - <div v-if="layout.length === 0" class="_panel" :class="$style.onboarding"> + <div v-if="layout.length === 0" class="_panel _gaps" :class="$style.onboarding"> <div>{{ i18n.ts._deck.introduction }}</div> <div>{{ i18n.ts._deck.introduction2 }}</div> + <MkInfo v-if="!store.r.tips.value.deck" closable @close="closeTip('deck')"> + <button class="_textButton" @click="showTour">{{ i18n.ts._deck.showHowToUse }}</button> + </MkInfo> </div> </div> <div v-if="prefer.r['deck.menuPosition'].value === 'right'" :class="$style.sideMenu"> <div :class="$style.sideMenuTop"> - <button v-tooltip.noDelay.left="`${i18n.ts._deck.profile}: ${prefer.s['deck.profile']}`" :class="$style.sideMenuButton" class="_button" @click="switchProfileMenu"><i class="ti ti-caret-down"></i></button> + <button ref="swicthProfileButtonEl" v-tooltip.noDelay.left="`${i18n.ts._deck.profile}: ${prefer.s['deck.profile']}`" :class="$style.sideMenuButton" class="_button" @click="switchProfileMenu"><i class="ti ti-caret-down"></i></button> <button v-tooltip.noDelay.left="i18n.ts._deck.deleteProfile" :class="$style.sideMenuButton" class="_button" @click="deleteProfile"><i class="ti ti-trash"></i></button> </div> <div :class="$style.sideMenuMiddle"> - <button v-tooltip.noDelay.left="i18n.ts._deck.addColumn" :class="$style.sideMenuButton" class="_button" @click="addColumn"><i class="ti ti-plus"></i></button> + <button ref="addColumnButtonEl" v-tooltip.noDelay.left="i18n.ts._deck.addColumn" :class="$style.sideMenuButton" class="_button" @click="addColumn"><i class="ti ti-plus"></i></button> </div> <div :class="$style.sideMenuBottom"> - <button v-tooltip.noDelay.left="i18n.ts.settings" :class="$style.sideMenuButton" class="_button" @click="showSettings"><i class="ti ti-settings-2"></i></button> + <button ref="settingsButtonEl" v-tooltip.noDelay.left="i18n.ts.settings" :class="$style.sideMenuButton" class="_button" @click="showSettings"><i class="ti ti-settings-2"></i></button> </div> </div> </div> <div v-if="prefer.r['deck.menuPosition'].value === 'bottom'" :class="$style.bottomMenu"> <div :class="$style.bottomMenuLeft"> - <button v-tooltip.noDelay.left="`${i18n.ts._deck.profile}: ${prefer.s['deck.profile']}`" :class="$style.bottomMenuButton" class="_button" @click="switchProfileMenu"><i class="ti ti-caret-down"></i></button> - <button v-tooltip.noDelay.left="i18n.ts._deck.deleteProfile" :class="$style.bottomMenuButton" class="_button" @click="deleteProfile"><i class="ti ti-trash"></i></button> + <button ref="swicthProfileButtonEl" v-tooltip.noDelay.top="`${i18n.ts._deck.profile}: ${prefer.s['deck.profile']}`" :class="$style.bottomMenuButton" class="_button" @click="switchProfileMenu"><i class="ti ti-caret-down"></i></button> + <button v-tooltip.noDelay.top="i18n.ts._deck.deleteProfile" :class="$style.bottomMenuButton" class="_button" @click="deleteProfile"><i class="ti ti-trash"></i></button> </div> <div :class="$style.bottomMenuMiddle"> - <button v-tooltip.noDelay.left="i18n.ts._deck.addColumn" :class="$style.bottomMenuButton" class="_button" @click="addColumn"><i class="ti ti-plus"></i></button> + <button ref="addColumnButtonEl" v-tooltip.noDelay.top="i18n.ts._deck.addColumn" :class="$style.bottomMenuButton" class="_button" @click="addColumn"><i class="ti ti-plus"></i></button> </div> <div :class="$style.bottomMenuRight"> - <button v-tooltip.noDelay.left="i18n.ts.settings" :class="$style.bottomMenuButton" class="_button" @click="showSettings"><i class="ti ti-settings-2"></i></button> + <button ref="settingsButtonEl" v-tooltip.noDelay.top="i18n.ts.settings" :class="$style.bottomMenuButton" class="_button" @click="showSettings"><i class="ti ti-settings-2"></i></button> </div> </div> @@ -96,6 +99,7 @@ import { $i } from '@/i.js'; import { i18n } from '@/i18n.js'; import { deviceKind } from '@/utility/device-kind.js'; import { prefer } from '@/preferences.js'; +import { store } from '@/store.js'; import XMainColumn from '@/ui/deck/main-column.vue'; import XTlColumn from '@/ui/deck/tl-column.vue'; import XAntennaColumn from '@/ui/deck/antenna-column.vue'; @@ -107,10 +111,13 @@ import XMentionsColumn from '@/ui/deck/mentions-column.vue'; import XDirectColumn from '@/ui/deck/direct-column.vue'; import XRoleTimelineColumn from '@/ui/deck/role-timeline-column.vue'; import XChatColumn from '@/ui/deck/chat-column.vue'; +import MkInfo from '@/components/MkInfo.vue'; import { mainRouter } from '@/router.js'; import { columns, layout, columnTypes, switchProfileMenu, addColumn as addColumnToStore, deleteProfile as deleteProfile_ } from '@/deck.js'; import { shouldSuggestRestoreBackup } from '@/preferences/utility.js'; import { shouldSuggestReload } from '@/utility/reload-suggest.js'; +import { startTour } from '@/utility/tour.js'; +import { closeTip } from '@/tips.js'; const XStatusBars = defineAsyncComponent(() => import('@/ui/_common_/statusbars.vue')); const XAnnouncements = defineAsyncComponent(() => import('@/ui/_common_/announcements.vue')); @@ -163,6 +170,9 @@ function showSettings() { } const columnsEl = useTemplateRef('columnsEl'); +const addColumnButtonEl = useTemplateRef('addColumnButtonEl'); +const settingsButtonEl = useTemplateRef('settingsButtonEl'); +const swicthProfileButtonEl = useTemplateRef('swicthProfileButtonEl'); const addColumn = async (ev) => { const { canceled, result: column } = await os.select({ @@ -218,6 +228,30 @@ async function deleteProfile() { os.success(); } +function showTour() { + if (addColumnButtonEl.value == null || + settingsButtonEl.value == null || + swicthProfileButtonEl.value == null) { + return; + } + + startTour([{ + element: addColumnButtonEl.value, + title: i18n.ts._deck._howToUse.addColumn_title, + description: i18n.ts._deck._howToUse.addColumn_description, + }, { + element: settingsButtonEl.value, + title: i18n.ts._deck._howToUse.settings_title, + description: i18n.ts._deck._howToUse.settings_description, + }, { + element: swicthProfileButtonEl.value, + title: i18n.ts._deck._howToUse.switchProfile_title, + description: i18n.ts._deck._howToUse.switchProfile_description, + }]).then(() => { + closeTip('deck'); + }); +} + window.document.documentElement.style.overflowY = 'hidden'; window.document.documentElement.style.scrollBehavior = 'auto'; </script> @@ -345,7 +379,7 @@ window.document.documentElement.style.scrollBehavior = 'auto'; } .bottomMenuButton { - display: block; + display: inline-block; height: 100%; aspect-ratio: 1; } diff --git a/packages/frontend/src/ui/universal.vue b/packages/frontend/src/ui/universal.vue index 727fe08989..497ef72d04 100644 --- a/packages/frontend/src/ui/universal.vue +++ b/packages/frontend/src/ui/universal.vue @@ -8,7 +8,7 @@ SPDX-License-Identifier: AGPL-3.0-only <XTitlebar v-if="prefer.r.showTitlebar.value" style="flex-shrink: 0;"/> <div :class="$style.nonTitlebarArea"> - <XSidebar v-if="!isMobile" :class="$style.sidebar" :showWidgetButton="!isDesktop" @widgetButtonClick="widgetsShowing = true"/> + <XSidebar v-if="!isMobile" :class="$style.sidebar" :showWidgetButton="!showWidgetsSide" @widgetButtonClick="widgetsShowing = true"/> <div :class="[$style.contents, !isMobile && prefer.r.showTitlebar.value ? $style.withSidebarAndTitlebar : null]" @contextmenu.stop="onContextmenu"> <div> @@ -22,7 +22,7 @@ SPDX-License-Identifier: AGPL-3.0-only <XMobileFooterMenu v-if="isMobile" ref="navFooter" v-model:drawerMenuShowing="drawerMenuShowing" v-model:widgetsShowing="widgetsShowing"/> </div> - <div v-if="isDesktop && !pageMetadata?.needWideArea" :class="$style.widgets"> + <div v-if="showWidgetsSide && !pageMetadata?.needWideArea" :class="$style.widgets"> <XWidgets/> </div> </div> @@ -64,7 +64,8 @@ const DESKTOP_THRESHOLD = 1100; const MOBILE_THRESHOLD = 500; // デスクトップでウィンドウを狭くしたときモバイルUIが表示されて欲しいことはあるので deviceKind === 'desktop' の判定は行わない -const isDesktop = ref(window.innerWidth >= DESKTOP_THRESHOLD); +const showWidgetsSide = window.innerWidth >= DESKTOP_THRESHOLD; + const isMobile = ref(deviceKind === 'smartphone' || window.innerWidth <= MOBILE_THRESHOLD); window.addEventListener('resize', () => { isMobile.value = deviceKind === 'smartphone' || window.innerWidth <= MOBILE_THRESHOLD; @@ -102,14 +103,6 @@ if (window.innerWidth > 1024) { } } -onMounted(() => { - if (!isDesktop.value) { - window.addEventListener('resize', () => { - if (window.innerWidth >= DESKTOP_THRESHOLD) isDesktop.value = true; - }, { passive: true }); - } -}); - const onContextmenu = (ev) => { if (isLink(ev.target)) return; if (['INPUT', 'TEXTAREA', 'IMG', 'VIDEO', 'CANVAS'].includes(ev.target.tagName) || ev.target.attributes['contenteditable']) return; |