-
-
diff --git a/manifest.json b/manifest.json
new file mode 100644
index 0000000..42b266d
--- /dev/null
+++ b/manifest.json
@@ -0,0 +1,18 @@
+{
+ "name": "LINE Ultimate",
+ "short_name": "LINE Ult",
+ "description": "チャットとミニゲームを楽しめるLINE風アプリ",
+ "start_url": "./index.html",
+ "scope": "./",
+ "display": "standalone",
+ "background_color": "#ffffff",
+ "theme_color": "#06c755",
+ "icons": [
+ {
+ "src": "./icons/app-icon.svg",
+ "sizes": "any",
+ "type": "image/svg+xml",
+ "purpose": "any maskable"
+ }
+ ]
+}
diff --git a/sw.js b/sw.js
new file mode 100644
index 0000000..4ac604b
--- /dev/null
+++ b/sw.js
@@ -0,0 +1,30 @@
+const CACHE_NAME = "line-ultimate-pwa-v1";
+const ASSETS = [
+ "./",
+ "./index.html",
+ "./manifest.json",
+ "./icons/app-icon.svg"
+];
+
+self.addEventListener("install", (event) => {
+ event.waitUntil(caches.open(CACHE_NAME).then((cache) => cache.addAll(ASSETS)));
+ self.skipWaiting();
+});
+
+self.addEventListener("activate", (event) => {
+ event.waitUntil(
+ caches.keys().then((keys) => Promise.all(keys.filter((k) => k !== CACHE_NAME).map((k) => caches.delete(k))))
+ );
+ self.clients.claim();
+});
+
+self.addEventListener("fetch", (event) => {
+ if (event.request.method !== "GET") return;
+ event.respondWith(
+ caches.match(event.request).then((cached) => cached || fetch(event.request).then((res) => {
+ const cloned = res.clone();
+ caches.open(CACHE_NAME).then((cache) => cache.put(event.request, cloned));
+ return res;
+ }).catch(() => caches.match("./index.html")))
+ );
+});