iOS standalone PWAs don't get Safari's native pull-to-refresh, so add our own. New <PullToRefresh> component handles the gesture: dampened drag past an 80px threshold triggers an async onRefresh; below that it springs back. Swipe direction is locked to the first 6px of movement, so horizontal carousel swipes (landscape Home) don't accidentally fire PTR. The arrow icon rotates from 0° to 180° as the pull approaches the threshold and turns primary-color when ready; during refresh a CSS spinner replaces it. - HomeView refreshes the device list (and sync status with it) - LibraryView refreshes images, pending-share count, devices, and the active shared sub-tab page when it's the one in view Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
<template>
|
||||
<main class="library">
|
||||
<PullToRefresh :is-at-top="isAtTop" :on-refresh="refreshLibrary">
|
||||
<!-- Tabs -->
|
||||
<div class="library__tabs" role="tablist">
|
||||
<button
|
||||
@@ -184,6 +185,7 @@
|
||||
>Next →</button>
|
||||
</div>
|
||||
</template>
|
||||
</PullToRefresh>
|
||||
|
||||
<!-- Share sheet -->
|
||||
<ShareSheet v-if="shareImageId !== null" v-model="shareSheetOpen" :image-id="shareImageId!" />
|
||||
@@ -213,6 +215,7 @@ import BaseBottomSheet from '@/components/BaseBottomSheet.vue'
|
||||
import BaseButton from '@/components/BaseButton.vue'
|
||||
import ApproveCard from '@/components/ApproveCard.vue'
|
||||
import ShareSheet from '@/components/ShareSheet.vue'
|
||||
import PullToRefresh from '@/components/PullToRefresh.vue'
|
||||
import type { Device, Image, SharedImage } from '@/types'
|
||||
|
||||
const router = useRouter()
|
||||
@@ -288,6 +291,21 @@ onMounted(() => {
|
||||
if (activeTab.value === 'shared') loadShared(sharedTab.value)
|
||||
})
|
||||
|
||||
// ── Pull-to-refresh ───────────────────────────────────────────────────────────
|
||||
|
||||
function isAtTop(): boolean {
|
||||
return window.scrollY === 0
|
||||
}
|
||||
|
||||
async function refreshLibrary() {
|
||||
await Promise.all([
|
||||
imagesStore.fetchImages(),
|
||||
imagesStore.fetchPendingCount(),
|
||||
devicesStore.fetchDevices(),
|
||||
activeTab.value === 'shared' ? loadShared(sharedTab.value, sharedPage.value) : Promise.resolve(),
|
||||
])
|
||||
}
|
||||
|
||||
// For now "mine" and "all" show the same list; shared is a placeholder
|
||||
const visibleImages = computed(() => imagesStore.images)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user