Web app: new entities (Image, RenderedAsset, SharedImage, Token, DeviceImageHistory), enums, repositories, controllers, message handlers, migrations, tests, frontend upload/library/sticker UI, Vue components. Firmware: EPD background screen binaries + gen scripts, setup_bg header. Infra: ddev config, test bundle, gitignore coverage dir. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -8,7 +8,12 @@
|
||||
:aria-label="tab.label"
|
||||
:aria-current="isActive(tab.to) ? 'page' : undefined"
|
||||
>
|
||||
<span class="bottom-nav__icon" aria-hidden="true" v-html="tab.icon" />
|
||||
<span class="bottom-nav__icon-wrap" aria-hidden="true">
|
||||
<span class="bottom-nav__icon" v-html="tab.icon" />
|
||||
<span v-if="tab.name === 'shared' && imagesStore.pendingCount > 0" class="bottom-nav__badge">
|
||||
{{ imagesStore.pendingCount > 9 ? '9+' : imagesStore.pendingCount }}
|
||||
</span>
|
||||
</span>
|
||||
<span class="bottom-nav__label">{{ tab.label }}</span>
|
||||
</RouterLink>
|
||||
</nav>
|
||||
@@ -16,8 +21,10 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useRoute } from 'vue-router'
|
||||
import { useImagesStore } from '@/stores/images'
|
||||
|
||||
const route = useRoute()
|
||||
const route = useRoute()
|
||||
const imagesStore = useImagesStore()
|
||||
|
||||
const tabs = [
|
||||
{
|
||||
@@ -35,7 +42,7 @@ const tabs = [
|
||||
{
|
||||
name: 'shared',
|
||||
label: 'Shared',
|
||||
to: '/shared',
|
||||
to: '/library?tab=shared',
|
||||
icon: '<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="18" cy="5" r="3"/><circle cx="6" cy="12" r="3"/><circle cx="18" cy="19" r="3"/><line x1="8.59" y1="13.51" x2="15.42" y2="17.49"/><line x1="15.41" y1="6.51" x2="8.59" y2="10.49"/></svg>',
|
||||
},
|
||||
{
|
||||
@@ -46,7 +53,8 @@ const tabs = [
|
||||
},
|
||||
]
|
||||
|
||||
function isActive(path: string) {
|
||||
function isActive(to: string) {
|
||||
const path = to.split('?')[0]
|
||||
if (path === '/') return route.path === '/'
|
||||
return route.path.startsWith(path)
|
||||
}
|
||||
@@ -85,6 +93,15 @@ function isActive(path: string) {
|
||||
}
|
||||
}
|
||||
|
||||
&__icon-wrap {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
}
|
||||
|
||||
&__icon {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@@ -93,6 +110,24 @@ function isActive(path: string) {
|
||||
height: 24px;
|
||||
}
|
||||
|
||||
&__badge {
|
||||
position: absolute;
|
||||
top: -4px;
|
||||
right: -6px;
|
||||
min-width: 16px;
|
||||
height: 16px;
|
||||
padding: 0 4px;
|
||||
background: var(--color-primary);
|
||||
color: var(--color-primary-fg);
|
||||
border-radius: 999px;
|
||||
font-size: 10px;
|
||||
font-weight: 700;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
&__label {
|
||||
font-size: var(--text-xs);
|
||||
font-weight: 600;
|
||||
|
||||
Reference in New Issue
Block a user