1
1
mirror of https://github.com/kokonect-link/cherrypick synced 2024-11-27 06:18:46 +09:00

enhance and fix navbar

fix(frontend/friendly): 0df6c79
This commit is contained in:
NoriDev 2024-11-19 15:57:38 +09:00
parent eae065dde8
commit ba9a50e747
5 changed files with 65 additions and 33 deletions

View File

@ -178,10 +178,6 @@ function learnMoreBottomNavbar() {
}); });
} }
watch([bannerDisplay], async () => {
await reloadAsk({ reason: i18n.ts.reloadToApplySetting, unison: true });
});
const headerActions = computed(() => []); const headerActions = computed(() => []);
const headerTabs = computed(() => []); const headerTabs = computed(() => []);

View File

@ -5,9 +5,9 @@ SPDX-License-Identifier: AGPL-3.0-only
<template> <template>
<div :class="$style.root"> <div :class="$style.root">
<div v-if="['all', 'bg'].includes(<string>defaultStore.state.bannerDisplay)" :class="[$style.banner, $style.topBanner]" :style="{ backgroundImage: `url(${ instance.bannerUrl })` }"></div> <div v-if="['all', 'bg'].includes(<string>bannerDisplay)" :class="[$style.banner, $style.topBanner]" :style="{ backgroundImage: `url(${ instance.bannerUrl })` }"></div>
<div :class="$style.top"> <div :class="$style.top">
<div v-if="['all', 'topBottom', 'top'].includes(<string>defaultStore.state.bannerDisplay)" :class="[$style.banner, $style.topBanner]" :style="{ backgroundImage: `url(${ instance.bannerUrl })` }"></div> <div v-if="['all', 'topBottom', 'top'].includes(<string>bannerDisplay)" :class="[$style.banner, $style.topBanner]" :style="{ backgroundImage: `url(${ instance.bannerUrl })` }"></div>
<button v-vibrate="defaultStore.state.vibrateSystem ? 5 : []" class="_button" :class="$style.instance" @click="openInstanceMenu"> <button v-vibrate="defaultStore.state.vibrateSystem ? 5 : []" class="_button" :class="$style.instance" @click="openInstanceMenu">
<img :src="instance.iconUrl || instance.faviconUrl || '/favicon.ico'" alt="" :class="$style.instanceIcon"/> <img :src="instance.iconUrl || instance.faviconUrl || '/favicon.ico'" alt="" :class="$style.instanceIcon"/>
</button> </button>
@ -40,7 +40,7 @@ SPDX-License-Identifier: AGPL-3.0-only
</MkA> </MkA>
</div> </div>
<div :class="$style.bottom"> <div :class="$style.bottom">
<div v-if="['all', 'topBottom', 'bottom'].includes(<string>defaultStore.state.bannerDisplay)" :class="[$style.banner, $style.bottomBanner]" :style="{ backgroundImage: `url(${ $i.bannerUrl })` }"></div> <div v-if="['all', 'topBottom', 'bottom'].includes(<string>bannerDisplay)" :class="[$style.banner, $style.bottomBanner]" :style="{ backgroundImage: `url(${ $i.bannerUrl })` }"></div>
<button v-vibrate="defaultStore.state.vibrateSystem ? 5 : []" class="_button" :class="$style.post" data-cy-open-post-form @click="os.post"> <button v-vibrate="defaultStore.state.vibrateSystem ? 5 : []" class="_button" :class="$style.post" data-cy-open-post-form @click="os.post">
<i :class="[$style.postIcon, defaultStore.state.renameTheButtonInPostFormToNya ? 'ti-paw-filled' : 'ti-pencil']" class="ti ti-fw"></i><span style="position: relative;">{{ defaultStore.state.renameTheButtonInPostFormToNya ? i18n.ts.nya : i18n.ts.note }}</span> <i :class="[$style.postIcon, defaultStore.state.renameTheButtonInPostFormToNya ? 'ti-paw-filled' : 'ti-pencil']" class="ti ti-fw"></i><span style="position: relative;">{{ defaultStore.state.renameTheButtonInPostFormToNya ? i18n.ts.nya : i18n.ts.note }}</span>
</button> </button>
@ -54,7 +54,7 @@ SPDX-License-Identifier: AGPL-3.0-only
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { computed, defineAsyncComponent, ref, toRef } from 'vue'; import { computed, defineAsyncComponent, ref, toRef, watch } from 'vue';
import { version } from '@@/js/config.js'; import { version } from '@@/js/config.js';
import { openInstanceMenu } from './common.js'; import { openInstanceMenu } from './common.js';
import * as os from '@/os.js'; import * as os from '@/os.js';
@ -75,6 +75,7 @@ const otherMenuItemIndicated = computed(() => {
}); });
const controlPanelIndicated = ref(false); const controlPanelIndicated = ref(false);
const releasesCherryPick = ref(null); const releasesCherryPick = ref(null);
const bannerDisplay = ref('');
if ($i.isAdmin ?? $i.isModerator) { if ($i.isAdmin ?? $i.isModerator) {
misskeyApi('admin/abuse-user-reports', { misskeyApi('admin/abuse-user-reports', {
@ -100,6 +101,14 @@ if ($i.isAdmin ?? $i.isModerator) {
}); });
} }
watch(defaultStore.reactiveState.bannerDisplay, () => {
toggleBannerDisplay();
});
function toggleBannerDisplay() {
bannerDisplay.value = defaultStore.state.bannerDisplay;
}
function compareVersions(v1: string, v2: string): number { function compareVersions(v1: string, v2: string): number {
const v1Parts = v1.split('.').map(Number); const v1Parts = v1.split('.').map(Number);
const v2Parts = v2.split('.').map(Number); const v2Parts = v2.split('.').map(Number);

View File

@ -6,9 +6,9 @@ SPDX-License-Identifier: AGPL-3.0-only
<template> <template>
<div :class="[$style.root, { [$style.iconOnly]: iconOnly }]"> <div :class="[$style.root, { [$style.iconOnly]: iconOnly }]">
<div :class="$style.body"> <div :class="$style.body">
<div v-if="['all', 'bg'].includes(<string>defaultStore.state.bannerDisplay)" :class="[$style.banner, $style.topBanner]" :style="{ backgroundImage: `url(${ instance.bannerUrl })` }"></div> <div v-if="['all', 'bg'].includes(<string>bannerDisplay)" :class="[$style.banner, $style.topBanner]" :style="{ backgroundImage: `url(${ instance.bannerUrl })` }"></div>
<div :class="$style.top"> <div :class="$style.top">
<div v-if="['all', 'topBottom', 'top'].includes(<string>defaultStore.state.bannerDisplay)" :class="[$style.banner, $style.topBanner]" :style="{ backgroundImage: `url(${ instance.bannerUrl })` }"></div> <div v-if="['all', 'topBottom', 'top'].includes(<string>bannerDisplay)" :class="[$style.banner, $style.topBanner]" :style="{ backgroundImage: `url(${ instance.bannerUrl })` }"></div>
<button v-vibrate="defaultStore.state.vibrateSystem ? 5 : []" v-tooltip.noDelay.right="instance.name ?? i18n.ts.instance" class="_button" :class="$style.instance" @click="openInstanceMenu"> <button v-vibrate="defaultStore.state.vibrateSystem ? 5 : []" v-tooltip.noDelay.right="instance.name ?? i18n.ts.instance" class="_button" :class="$style.instance" @click="openInstanceMenu">
<img :src="instance.iconUrl || instance.faviconUrl || '/favicon.ico'" alt="" :class="$style.instanceIcon"/> <img :src="instance.iconUrl || instance.faviconUrl || '/favicon.ico'" alt="" :class="$style.instanceIcon"/>
</button> </button>
@ -51,7 +51,7 @@ SPDX-License-Identifier: AGPL-3.0-only
</MkA> </MkA>
</div> </div>
<div :class="$style.bottom"> <div :class="$style.bottom">
<div v-if="['all', 'topBottom', 'bottom'].includes(<string>defaultStore.state.bannerDisplay)" :class="[$style.banner, $style.bottomBanner]" :style="{ backgroundImage: `url(${ $i.bannerUrl })` }"></div> <div v-if="['all', 'topBottom', 'bottom'].includes(<string>bannerDisplay)" :class="[$style.banner, $style.bottomBanner]" :style="{ backgroundImage: `url(${ $i.bannerUrl })` }"></div>
<button v-vibrate="defaultStore.state.vibrateSystem ? 5 : []" v-tooltip.noDelay.right="defaultStore.state.renameTheButtonInPostFormToNya ? i18n.ts.nya : i18n.ts.note" class="_button" :class="[$style.post]" data-cy-open-post-form @click="os.post"> <button v-vibrate="defaultStore.state.vibrateSystem ? 5 : []" v-tooltip.noDelay.right="defaultStore.state.renameTheButtonInPostFormToNya ? i18n.ts.nya : i18n.ts.note" class="_button" :class="[$style.post]" data-cy-open-post-form @click="os.post">
<i class="ti ti-fw" :class="[$style.postIcon, defaultStore.state.renameTheButtonInPostFormToNya ? 'ti-paw-filled' : 'ti-pencil']"></i><span :class="$style.postText">{{ defaultStore.state.renameTheButtonInPostFormToNya ? i18n.ts.nya : i18n.ts.note }}</span> <i class="ti ti-fw" :class="[$style.postIcon, defaultStore.state.renameTheButtonInPostFormToNya ? 'ti-paw-filled' : 'ti-pencil']"></i><span :class="$style.postText">{{ defaultStore.state.renameTheButtonInPostFormToNya ? i18n.ts.nya : i18n.ts.note }}</span>
</button> </button>
@ -102,6 +102,7 @@ const otherMenuItemIndicated = computed(() => {
}); });
const controlPanelIndicated = ref(false); const controlPanelIndicated = ref(false);
const releasesCherryPick = ref(null); const releasesCherryPick = ref(null);
const bannerDisplay = ref('');
if ($i.isAdmin ?? $i.isModerator) { if ($i.isAdmin ?? $i.isModerator) {
misskeyApi('admin/abuse-user-reports', { misskeyApi('admin/abuse-user-reports', {
@ -141,10 +142,18 @@ watch(defaultStore.reactiveState.menuDisplay, () => {
calcViewState(); calcViewState();
}); });
watch(defaultStore.reactiveState.bannerDisplay, () => {
toggleBannerDisplay();
});
function toggleIconOnly() { function toggleIconOnly() {
defaultStore.set('menuDisplay', iconOnly.value ? 'sideFull' : 'sideIcon'); defaultStore.set('menuDisplay', iconOnly.value ? 'sideFull' : 'sideIcon');
} }
function toggleBannerDisplay() {
bannerDisplay.value = defaultStore.state.bannerDisplay;
}
function compareVersions(v1: string, v2: string): number { function compareVersions(v1: string, v2: string): number {
const v1Parts = v1.split('.').map(Number); const v1Parts = v1.split('.').map(Number);
const v2Parts = v2.split('.').map(Number); const v2Parts = v2.split('.').map(Number);

View File

@ -5,9 +5,9 @@ SPDX-License-Identifier: AGPL-3.0-only
<template> <template>
<div :class="$style.root"> <div :class="$style.root">
<div v-if="['all', 'bg'].includes(<string>defaultStore.state.bannerDisplay)" :class="[$style.banner, $style.topBanner]" :style="{ backgroundImage: `url(${ instance.bannerUrl })` }"></div> <div v-if="['all', 'bg'].includes(<string>bannerDisplay)" :class="[$style.banner, $style.topBanner]" :style="{ backgroundImage: `url(${ instance.bannerUrl })` }"></div>
<div :class="$style.top"> <div :class="$style.top">
<div v-if="['all', 'topBottom', 'top'].includes(<string>defaultStore.state.bannerDisplay)" :class="[$style.banner, $style.topBanner]" :style="{ backgroundImage: `url(${ instance.bannerUrl })` }"></div> <div v-if="['all', 'topBottom', 'top'].includes(<string>bannerDisplay)" :class="[$style.banner, $style.topBanner]" :style="{ backgroundImage: `url(${ instance.bannerUrl })` }"></div>
<button v-vibrate="defaultStore.state.vibrateSystem ? 5 : []" class="_button" :class="$style.instance" @click="openInstanceMenu"> <button v-vibrate="defaultStore.state.vibrateSystem ? 5 : []" class="_button" :class="$style.instance" @click="openInstanceMenu">
<img :src="instance.iconUrl || instance.faviconUrl || '/favicon.ico'" alt="" :class="$style.instanceIcon"/> <img :src="instance.iconUrl || instance.faviconUrl || '/favicon.ico'" alt="" :class="$style.instanceIcon"/>
</button> </button>
@ -40,7 +40,7 @@ SPDX-License-Identifier: AGPL-3.0-only
</MkA> </MkA>
</div> </div>
<div :class="$style.bottom"> <div :class="$style.bottom">
<div v-if="['all', 'topBottom', 'bottom'].includes(<string>defaultStore.state.bannerDisplay)" :class="[$style.banner, $style.bottomBanner]" :style="{ backgroundImage: `url(${ $i.bannerUrl })` }"></div> <div v-if="['all', 'topBottom', 'bottom'].includes(<string>bannerDisplay)" :class="[$style.banner, $style.bottomBanner]" :style="{ backgroundImage: `url(${ $i.bannerUrl })` }"></div>
<button v-vibrate="defaultStore.state.vibrateSystem ? 5 : []" class="_button" :class="$style.post" data-cy-open-post-form @click="os.post"> <button v-vibrate="defaultStore.state.vibrateSystem ? 5 : []" class="_button" :class="$style.post" data-cy-open-post-form @click="os.post">
<i :class="[$style.postIcon, defaultStore.state.renameTheButtonInPostFormToNya ? 'ti-paw-filled' : 'ti-pencil']" class="ti ti-fw"></i><span style="position: relative;">{{ defaultStore.state.renameTheButtonInPostFormToNya ? i18n.ts.nya : i18n.ts.note }}</span> <i :class="[$style.postIcon, defaultStore.state.renameTheButtonInPostFormToNya ? 'ti-paw-filled' : 'ti-pencil']" class="ti ti-fw"></i><span style="position: relative;">{{ defaultStore.state.renameTheButtonInPostFormToNya ? i18n.ts.nya : i18n.ts.note }}</span>
</button> </button>
@ -55,7 +55,7 @@ SPDX-License-Identifier: AGPL-3.0-only
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { computed, defineAsyncComponent, ref, toRef } from 'vue'; import { computed, defineAsyncComponent, ref, toRef, watch } from 'vue';
import { version } from '@@/js/config.js'; import { version } from '@@/js/config.js';
import { openInstanceMenu } from '@/ui/_common_/common.js'; import { openInstanceMenu } from '@/ui/_common_/common.js';
import * as os from '@/os.js'; import * as os from '@/os.js';
@ -77,6 +77,7 @@ const otherMenuItemIndicated = computed(() => {
}); });
const controlPanelIndicated = ref(false); const controlPanelIndicated = ref(false);
const releasesCherryPick = ref(null); const releasesCherryPick = ref(null);
const bannerDisplay = ref('');
if ($i.isAdmin ?? $i.isModerator) { if ($i.isAdmin ?? $i.isModerator) {
misskeyApi('admin/abuse-user-reports', { misskeyApi('admin/abuse-user-reports', {
@ -102,6 +103,14 @@ if ($i.isAdmin ?? $i.isModerator) {
}); });
} }
watch(defaultStore.reactiveState.bannerDisplay, () => {
toggleBannerDisplay();
});
function toggleBannerDisplay() {
bannerDisplay.value = defaultStore.state.bannerDisplay;
}
function compareVersions(v1: string, v2: string): number { function compareVersions(v1: string, v2: string): number {
const v1Parts = v1.split('.').map(Number); const v1Parts = v1.split('.').map(Number);
const v2Parts = v2.split('.').map(Number); const v2Parts = v2.split('.').map(Number);

View File

@ -6,9 +6,9 @@ SPDX-License-Identifier: AGPL-3.0-only
<template> <template>
<div :class="[$style.root, { [$style.iconOnly]: iconOnly }]"> <div :class="[$style.root, { [$style.iconOnly]: iconOnly }]">
<div :class="$style.body"> <div :class="$style.body">
<div v-if="['all', 'bg'].includes(<string>defaultStore.state.bannerDisplay)" :class="[$style.banner, $style.topBanner]" :style="{ backgroundImage: `url(${ instance.bannerUrl })` }"></div> <div v-if="['all', 'bg'].includes(<string>bannerDisplay)" :class="[$style.banner, $style.topBanner]" :style="{ backgroundImage: `url(${ instance.bannerUrl })` }"></div>
<div :class="$style.top"> <div :class="$style.top">
<div v-if="['all', 'topBottom', 'top'].includes(<string>defaultStore.state.bannerDisplay)" :class="[$style.banner, $style.topBanner]" :style="{ backgroundImage: `url(${ instance.bannerUrl })` }"></div> <div v-if="['all', 'topBottom', 'top'].includes(<string>bannerDisplay)" :class="[$style.banner, $style.topBanner]" :style="{ backgroundImage: `url(${ instance.bannerUrl })` }"></div>
<button v-vibrate="defaultStore.state.vibrateSystem ? 5 : []" v-tooltip.noDelay.right="instance.name ?? i18n.ts.instance" class="_button" :class="$style.instance" @click="openInstanceMenu"> <button v-vibrate="defaultStore.state.vibrateSystem ? 5 : []" v-tooltip.noDelay.right="instance.name ?? i18n.ts.instance" class="_button" :class="$style.instance" @click="openInstanceMenu">
<img :src="instance.iconUrl || instance.faviconUrl || '/favicon.ico'" alt="" :class="$style.instanceIcon"/> <img :src="instance.iconUrl || instance.faviconUrl || '/favicon.ico'" alt="" :class="$style.instanceIcon"/>
</button> </button>
@ -51,7 +51,7 @@ SPDX-License-Identifier: AGPL-3.0-only
</MkA> </MkA>
</div> </div>
<div :class="$style.bottom"> <div :class="$style.bottom">
<div v-if="['all', 'topBottom', 'bottom'].includes(<string>defaultStore.state.bannerDisplay)" :class="[$style.banner, $style.bottomBanner]" :style="{ backgroundImage: `url(${ $i.bannerUrl })` }"></div> <div v-if="['all', 'topBottom', 'bottom'].includes(<string>bannerDisplay)" :class="[$style.banner, $style.bottomBanner]" :style="{ backgroundImage: `url(${ $i.bannerUrl })` }"></div>
<button v-vibrate="defaultStore.state.vibrateSystem ? 5 : []" v-tooltip.noDelay.right="defaultStore.state.renameTheButtonInPostFormToNya ? i18n.ts.nya : i18n.ts.note" class="_button" :class="[$style.post]" data-cy-open-post-form @click="os.post"> <button v-vibrate="defaultStore.state.vibrateSystem ? 5 : []" v-tooltip.noDelay.right="defaultStore.state.renameTheButtonInPostFormToNya ? i18n.ts.nya : i18n.ts.note" class="_button" :class="[$style.post]" data-cy-open-post-form @click="os.post">
<i class="ti ti-fw" :class="[$style.postIcon, defaultStore.state.renameTheButtonInPostFormToNya ? 'ti-paw-filled' : 'ti-pencil']"></i><span :class="$style.postText">{{ defaultStore.state.renameTheButtonInPostFormToNya ? i18n.ts.nya : i18n.ts.note }}</span> <i class="ti ti-fw" :class="[$style.postIcon, defaultStore.state.renameTheButtonInPostFormToNya ? 'ti-paw-filled' : 'ti-pencil']"></i><span :class="$style.postText">{{ defaultStore.state.renameTheButtonInPostFormToNya ? i18n.ts.nya : i18n.ts.note }}</span>
</button> </button>
@ -65,22 +65,22 @@ SPDX-License-Identifier: AGPL-3.0-only
<button v-if="!iconOnly" v-vibrate="defaultStore.state.vibrateSystem ? 5 : []" class="_button" :class="[$style.drawer]" @click="openAccountMenu"><i class="ti ti-chevron-up"/></button> <button v-if="!iconOnly" v-vibrate="defaultStore.state.vibrateSystem ? 5 : []" class="_button" :class="[$style.drawer]" @click="openAccountMenu"><i class="ti ti-chevron-up"/></button>
</div> </div>
</div> </div>
<button v-if="!forceIconOnly" class="_button" :class="$style.toggleButton" @click="toggleIconOnly">
<!--
<svg viewBox="0 0 16 48" :class="$style.toggleButtonShape">
<g transform="matrix(0.333333,0,0,0.222222,0.000895785,13.3333)">
<path d="M23.935,-24C37.223,-24 47.995,-7.842 47.995,12.09C47.995,34.077 47.995,62.07 47.995,84.034C47.995,93.573 45.469,102.721 40.972,109.466C36.475,116.211 30.377,120 24.018,120L23.997,120C10.743,120 -0.003,136.118 -0.003,156C-0.003,156 -0.003,156 -0.003,156L-0.003,-60L-0.003,-59.901C-0.003,-50.379 2.519,-41.248 7.007,-34.515C11.496,-27.782 17.584,-24 23.931,-24C23.932,-24 23.934,-24 23.935,-24Z" style="fill:var(--MI_THEME-navBg);"/>
</g>
</svg>
-->
<svg viewBox="0 0 16 64" :class="$style.toggleButtonShape">
<g transform="matrix(0.333333,0,0,0.222222,0.000895785,21.3333)">
<path d="M47.488,7.995C47.79,10.11 47.943,12.266 47.943,14.429C47.997,26.989 47.997,84 47.997,84C47.997,84 44.018,118.246 23.997,133.5C-0.374,152.07 -0.003,192 -0.003,192L-0.003,-96C-0.003,-96 0.151,-56.216 23.997,-37.5C40.861,-24.265 46.043,-1.243 47.488,7.995Z" style="fill:var(--MI_THEME-navBg);"/>
</g>
</svg>
<i :class="'ti ' + `ti-chevron-${ iconOnly ? 'right' : 'left' }`" style="font-size: 12px; margin-left: -8px;"></i>
</button>
</div> </div>
<button v-if="!forceIconOnly" class="_button" :class="$style.toggleButton" @click="toggleIconOnly">
<!--
<svg viewBox="0 0 16 48" :class="$style.toggleButtonShape">
<g transform="matrix(0.333333,0,0,0.222222,0.000895785,13.3333)">
<path d="M23.935,-24C37.223,-24 47.995,-7.842 47.995,12.09C47.995,34.077 47.995,62.07 47.995,84.034C47.995,93.573 45.469,102.721 40.972,109.466C36.475,116.211 30.377,120 24.018,120L23.997,120C10.743,120 -0.003,136.118 -0.003,156C-0.003,156 -0.003,156 -0.003,156L-0.003,-60L-0.003,-59.901C-0.003,-50.379 2.519,-41.248 7.007,-34.515C11.496,-27.782 17.584,-24 23.931,-24C23.932,-24 23.934,-24 23.935,-24Z" style="fill:var(--MI_THEME-navBg);"/>
</g>
</svg>
-->
<svg viewBox="0 0 16 64" :class="$style.toggleButtonShape">
<g transform="matrix(0.333333,0,0,0.222222,0.000895785,21.3333)">
<path d="M47.488,7.995C47.79,10.11 47.943,12.266 47.943,14.429C47.997,26.989 47.997,84 47.997,84C47.997,84 44.018,118.246 23.997,133.5C-0.374,152.07 -0.003,192 -0.003,192L-0.003,-96C-0.003,-96 0.151,-56.216 23.997,-37.5C40.861,-24.265 46.043,-1.243 47.488,7.995Z" style="fill:var(--MI_THEME-navBg);"/>
</g>
</svg>
<i :class="'ti ' + `ti-chevron-${ iconOnly ? 'right' : 'left' }`" style="font-size: 12px; margin-left: -8px;"></i>
</button>
</div> </div>
</template> </template>
@ -109,6 +109,7 @@ const otherMenuItemIndicated = computed(() => {
}); });
const controlPanelIndicated = ref(false); const controlPanelIndicated = ref(false);
const releasesCherryPick = ref(null); const releasesCherryPick = ref(null);
const bannerDisplay = ref('');
if ($i.isAdmin ?? $i.isModerator) { if ($i.isAdmin ?? $i.isModerator) {
misskeyApi('admin/abuse-user-reports', { misskeyApi('admin/abuse-user-reports', {
@ -148,10 +149,18 @@ watch(defaultStore.reactiveState.menuDisplay, () => {
calcViewState(); calcViewState();
}); });
watch(defaultStore.reactiveState.bannerDisplay, () => {
toggleBannerDisplay();
});
function toggleIconOnly() { function toggleIconOnly() {
defaultStore.set('menuDisplay', iconOnly.value ? 'sideFull' : 'sideIcon'); defaultStore.set('menuDisplay', iconOnly.value ? 'sideFull' : 'sideIcon');
} }
function toggleBannerDisplay() {
bannerDisplay.value = defaultStore.state.bannerDisplay;
}
function compareVersions(v1: string, v2: string): number { function compareVersions(v1: string, v2: string): number {
const v1Parts = v1.split('.').map(Number); const v1Parts = v1.split('.').map(Number);
const v2Parts = v2.split('.').map(Number); const v2Parts = v2.split('.').map(Number);