ecac6c4bda
Closes the last two findings from the 2026-06-02 audit (G5.1 + G5.4). G5.1 — Centroid version no longer drifts: CentroidService now reads MLSettings.embedder_model_version (the DB row tag_and_embed already writes from) for both the centroid model- version stamp and the drift-detection comparison. Previously the centroid sites imported MODEL_VERSION from env, so the version stamped on centroids could disagree with the version stamped on the embeddings they were built from. By construction those now match, so list_drifted won't silently miss the env-vs-DB drift case. embedder.py keeps MODEL_VERSION as an env-driven constant for the actual model loader — that's a different concern (which weights are loaded) from the version-stamp that gets persisted alongside data. G5.4 — Modal is a Pinia-only overlay: The previous URL↔modal sync in GalleryView and ArtistGalleryTab leaked the modal across route changes (RouterLink to /artist/<slug> left the modal mounted on top of the new route) and re-opened it on history back/forward with stale ?image=N entries. Now: openImage() just calls modal.open(id) — no URL push. GalleryView's dead closeImage helper is deleted. A route.name watcher in App.vue closes the modal whenever the route changes, which auto-fixes RouterLink-in-modal and back/forward. Backward-compat: ?image=N is still honored on initial mount as a one-shot deep-link opener, then router.replace strips the query so the URL doesn't re-trigger and no extra history entry is added. Existing bookmarks / shared URLs keep working; new opens stay Pinia-only.
39 lines
1.2 KiB
Vue
39 lines
1.2 KiB
Vue
<template>
|
|
<v-app>
|
|
<AppShell>
|
|
<RouterView />
|
|
</AppShell>
|
|
<ImageViewer v-if="modal.isOpen" @close="modal.close()" />
|
|
<AppSnackbar ref="snackbar" />
|
|
</v-app>
|
|
</template>
|
|
|
|
<script setup>
|
|
import { onMounted, ref, watch } from 'vue'
|
|
import { useRoute } from 'vue-router'
|
|
|
|
import AppShell from './components/AppShell.vue'
|
|
import AppSnackbar from './components/AppSnackbar.vue'
|
|
import ImageViewer from './components/modal/ImageViewer.vue'
|
|
import { useModalStore } from './stores/modal.js'
|
|
|
|
const modal = useModalStore()
|
|
const snackbar = ref(null)
|
|
const route = useRoute()
|
|
|
|
onMounted(() => {
|
|
// Expose snackbar via a simple global so stores can call it without props.
|
|
window.__fcToast = (opts) => snackbar.value?.open(opts)
|
|
})
|
|
|
|
// Audit 2026-06-02: the modal is an overlay, not a page. When the
|
|
// route changes (RouterLink inside the modal, history back/forward,
|
|
// programmatic push from any view), close the modal so it doesn't
|
|
// hover over a different route. Watching route.name (not the path)
|
|
// keeps within-route nav like /artist/foo → /artist/bar from
|
|
// dismissing the modal mid-browse.
|
|
watch(() => route.name, () => {
|
|
if (modal.isOpen) modal.close()
|
|
})
|
|
</script>
|