feat: 単元を URL ?unit= で同期しリロード後も同じ単元を表示

Made-with: Cursor
This commit is contained in:
posimai 2026-04-19 00:09:51 +09:00
parent 199509f72e
commit 93056d6b7b
2 changed files with 29 additions and 2 deletions

View File

@ -422,7 +422,7 @@ header{display:flex;align-items:center;justify-content:space-between;padding:0 1
<!-- UNIT VIEW --> <!-- UNIT VIEW -->
<div x-show="currentUnit"> <div x-show="currentUnit">
<div class="unit-header"> <div class="unit-header">
<button class="unit-back" @click="currentUnit=null;quizState={}"> <button class="unit-back" @click="goHome()">
<i data-lucide="arrow-left" style="width:12px;height:12px"></i> <i data-lucide="arrow-left" style="width:12px;height:12px"></i>
一覧 一覧
</button> </button>
@ -790,12 +790,38 @@ function bokiApp(){
catch{ this.scores = {}; } catch{ this.scores = {}; }
const t = localStorage.getItem('posimai-boki-theme')||'system'; const t = localStorage.getItem('posimai-boki-theme')||'system';
this.isDark = t==='dark'||(t==='system'&&matchMedia('(prefers-color-scheme:dark)').matches); this.isDark = t==='dark'||(t==='system'&&matchMedia('(prefers-color-scheme:dark)').matches);
const uid=(new URLSearchParams(location.search).get('unit')||'').trim().toLowerCase();
if(uid){
const u=this.allUnits().find(x=>x.id===uid);
if(u){ this.currentUnit=u; this.quizState={}; }
else{ try{ const url=new URL(window.location.href); url.searchParams.delete('unit'); const q=url.searchParams.toString(); history.replaceState(null,'',url.pathname+(q?'?'+q:'')+url.hash); }catch(e){} }
}
this.syncUnitToUrl();
this.$nextTick(()=>{ if(window.lucide) lucide.createIcons(); }); this.$nextTick(()=>{ if(window.lucide) lucide.createIcons(); });
if('serviceWorker' in navigator){ if('serviceWorker' in navigator){
navigator.serviceWorker.register('/sw.js').catch(()=>{}); navigator.serviceWorker.register('/sw.js').catch(()=>{});
} }
}, },
syncUnitToUrl(){
try{
const url=new URL(window.location.href);
if(this.currentUnit&&this.currentUnit.id) url.searchParams.set('unit',this.currentUnit.id);
else url.searchParams.delete('unit');
const q=url.searchParams.toString();
const path=url.pathname+(q?'?'+q:'')+url.hash;
if(path!==window.location.pathname+window.location.search+window.location.hash)
history.replaceState(null,'',path);
}catch(e){}
},
goHome(){
this.currentUnit=null;
this.quizState={};
this.syncUnitToUrl();
this.$nextTick(()=>{ if(window.lucide) lucide.createIcons(); });
},
get filteredCats(){ get filteredCats(){
if(!this.search) return this.categories; if(!this.search) return this.categories;
const q=this.search.toLowerCase(); const q=this.search.toLowerCase();
@ -872,6 +898,7 @@ function bokiApp(){
openUnit(unit){ openUnit(unit){
this.currentUnit=unit; this.currentUnit=unit;
this.quizState={}; this.quizState={};
this.syncUnitToUrl();
this.$nextTick(()=>{ this.$nextTick(()=>{
if(window.lucide) lucide.createIcons(); if(window.lucide) lucide.createIcons();
const m=document.getElementById('main'); const m=document.getElementById('main');

2
sw.js
View File

@ -1,5 +1,5 @@
// posimai-boki SW — stale-while-revalidate + skipWaiting // posimai-boki SW — stale-while-revalidate + skipWaiting
const CACHE = 'posimai-boki-v9'; const CACHE = 'posimai-boki-v10';
const STATIC = ['/', '/index.html', '/manifest.json', '/logo.png']; const STATIC = ['/', '/index.html', '/manifest.json', '/logo.png'];
self.addEventListener('install', e => { self.addEventListener('install', e => {