Repository files navigation

Offline Zip Browser

This project is meant so that I can play interactive fiction games, but it's also good for any similar project. You can even play my LizardUp game if you download the source as a zip and open it.

Use

  1. Use "Open with..." from your file app on a .zip file or standalone .html file, and select "Offline Zip Browser".
  2. Enter a name for it (you cannot change this yet)
    • The app will attempt to guess if .zip or .html but may get it wrong so it's good to specify .zip or .html in the name too.
  3. The file will be saved to app's storage and now any time you open the app you will have access to this file. LocalStorage will persist across sessions. Which means most interactive fiction games with save states will work.

Note: if you use termux + curl to download files, you will have to set the allow-external-apps property must be set to true in ~/.termux/termux.properties in termux.

Manifests

Create a ozb_manifest.json file in your zipped html app next to your index.html with a variety of useful settings that will control how the app is loaded. Generally these properties will help misbehaving applications work better.

Theoretically I'd like to be able to clear cache for a site on startup, but it's not built into web views by default that I can tell.

dateToSpoof

Offset based timestamp, loaded with OffsetDateTime.parse. Values like "2025-01-30T19:00:00-05:00" will work.

useUnsafeURL

Set the base url of the app to a "real" url. The app will still try to prevent access to the wider web.

Deep Links

Deep links to link into the app. Because the app is intentionally not communicating with servers or other apps, deep links do not work inside the app, so you can only link in from another app.

Debug builds of the app use a different deep link hostname (add .debug to the end of the hostname)

  • Delete a file
  • Rename a file
  • Deep link to play a game app://foss.zip.offline.browser.offlinezipbrowser/play/Your_game_here.html

RENAME_FILE

rename a file

DELETE_FILE

delete a file

TODO

  • Clear Cache options
  • Have multiple instances of the app open at once

About

Browse a zip file containing an index.html file as if it was a website. Cache/JS enabled, but it's all offline.

Resources

Stars

4 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Repository files navigation

Offline Zip Browser

This project is meant so that I can play interactive fiction games, but it's also good for any similar project. You can even play my LizardUp game if you download the source as a zip and open it.

Use

  1. Use "Open with..." from your file app on a .zip file or standalone .html file, and select "Offline Zip Browser".
  2. Enter a name for it (you cannot change this yet)
    • The app will attempt to guess if .zip or .html but may get it wrong so it's good to specify .zip or .html in the name too.
  3. The file will be saved to app's storage and now any time you open the app you will have access to this file. LocalStorage will persist across sessions. Which means most interactive fiction games with save states will work.

Note: if you use termux + curl to download files, you will have to set the allow-external-apps property must be set to true in ~/.termux/termux.properties in termux.

Manifests

Create a ozb_manifest.json file in your zipped html app next to your index.html with a variety of useful settings that will control how the app is loaded. Generally these properties will help misbehaving applications work better.

Theoretically I'd like to be able to clear cache for a site on startup, but it's not built into web views by default that I can tell.

dateToSpoof

Offset based timestamp, loaded with OffsetDateTime.parse. Values like "2025-01-30T19:00:00-05:00" will work.

useUnsafeURL

Set the base url of the app to a "real" url. The app will still try to prevent access to the wider web.

Deep Links

Deep links to link into the app. Because the app is intentionally not communicating with servers or other apps, deep links do not work inside the app, so you can only link in from another app.

Debug builds of the app use a different deep link hostname (add .debug to the end of the hostname)

  • Delete a file
  • Rename a file
  • Deep link to play a game app://foss.zip.offline.browser.offlinezipbrowser/play/Your_game_here.html

RENAME_FILE

rename a file

DELETE_FILE

delete a file

TODO

  • Clear Cache options
  • Have multiple instances of the app open at once

About

Browse a zip file containing an index.html file as if it was a website. Cache/JS enabled, but it's all offline.

Resources

Stars

4 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

Offline Zip Browser

This project is meant so that I can play interactive fiction games, but it's also good for any similar project. You can even play my LizardUp game if you download the source as a zip and open it.

Use

  1. Use "Open with..." from your file app on a .zip file or standalone .html file, and select "Offline Zip Browser".
  2. Enter a name for it (you cannot change this yet)
    • The app will attempt to guess if .zip or .html but may get it wrong so it's good to specify .zip or .html in the name too.
  3. The file will be saved to app's storage and now any time you open the app you will have access to this file. LocalStorage will persist across sessions. Which means most interactive fiction games with save states will work.

Note: if you use termux + curl to download files, you will have to set the allow-external-apps property must be set to true in ~/.termux/termux.properties in termux.

Manifests

Create a ozb_manifest.json file in your zipped html app next to your index.html with a variety of useful settings that will control how the app is loaded. Generally these properties will help misbehaving applications work better.

Theoretically I'd like to be able to clear cache for a site on startup, but it's not built into web views by default that I can tell.

dateToSpoof

Offset based timestamp, loaded with OffsetDateTime.parse. Values like "2025-01-30T19:00:00-05:00" will work.

useUnsafeURL

Set the base url of the app to a "real" url. The app will still try to prevent access to the wider web.

Deep Links

Deep links to link into the app. Because the app is intentionally not communicating with servers or other apps, deep links do not work inside the app, so you can only link in from another app.

Debug builds of the app use a different deep link hostname (add .debug to the end of the hostname)

  • Delete a file
  • Rename a file
  • Deep link to play a game app://foss.zip.offline.browser.offlinezipbrowser/play/Your_game_here.html

RENAME_FILE

rename a file

DELETE_FILE

delete a file

TODO

  • Clear Cache options
  • Have multiple instances of the app open at once

About

Browse a zip file containing an index.html file as if it was a website. Cache/JS enabled, but it's all offline.

Resources

Stars

4 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

Offline Zip Browser

This project is meant so that I can play interactive fiction games, but it's also good for any similar project. You can even play my LizardUp game if you download the source as a zip and open it.

Use

  1. Use "Open with..." from your file app on a .zip file or standalone .html file, and select "Offline Zip Browser".
  2. Enter a name for it (you cannot change this yet)
    • The app will attempt to guess if .zip or .html but may get it wrong so it's good to specify .zip or .html in the name too.
  3. The file will be saved to app's storage and now any time you open the app you will have access to this file. LocalStorage will persist across sessions. Which means most interactive fiction games with save states will work.

Note: if you use termux + curl to download files, you will have to set the allow-external-apps property must be set to true in ~/.termux/termux.properties in termux.

Manifests

Create a ozb_manifest.json file in your zipped html app next to your index.html with a variety of useful settings that will control how the app is loaded. Generally these properties will help misbehaving applications work better.

Theoretically I'd like to be able to clear cache for a site on startup, but it's not built into web views by default that I can tell.

dateToSpoof

Offset based timestamp, loaded with OffsetDateTime.parse. Values like "2025-01-30T19:00:00-05:00" will work.

useUnsafeURL

Set the base url of the app to a "real" url. The app will still try to prevent access to the wider web.

Deep Links

Deep links to link into the app. Because the app is intentionally not communicating with servers or other apps, deep links do not work inside the app, so you can only link in from another app.

Debug builds of the app use a different deep link hostname (add .debug to the end of the hostname)

  • Delete a file
  • Rename a file
  • Deep link to play a game app://foss.zip.offline.browser.offlinezipbrowser/play/Your_game_here.html

RENAME_FILE

rename a file

DELETE_FILE

delete a file

TODO

  • Clear Cache options
  • Have multiple instances of the app open at once

About

Browse a zip file containing an index.html file as if it was a website. Cache/JS enabled, but it's all offline.

Resources

Stars

4 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Repository files navigation

Offline Zip Browser

This project is meant so that I can play interactive fiction games, but it's also good for any similar project. You can even play my LizardUp game if you download the source as a zip and open it.

Use

  1. Use "Open with..." from your file app on a .zip file or standalone .html file, and select "Offline Zip Browser".
  2. Enter a name for it (you cannot change this yet)
    • The app will attempt to guess if .zip or .html but may get it wrong so it's good to specify .zip or .html in the name too.
  3. The file will be saved to app's storage and now any time you open the app you will have access to this file. LocalStorage will persist across sessions. Which means most interactive fiction games with save states will work.

Note: if you use termux + curl to download files, you will have to set the allow-external-apps property must be set to true in ~/.termux/termux.properties in termux.

Manifests

Create a ozb_manifest.json file in your zipped html app next to your index.html with a variety of useful settings that will control how the app is loaded. Generally these properties will help misbehaving applications work better.

Theoretically I'd like to be able to clear cache for a site on startup, but it's not built into web views by default that I can tell.

dateToSpoof

Offset based timestamp, loaded with OffsetDateTime.parse. Values like "2025-01-30T19:00:00-05:00" will work.

useUnsafeURL

Set the base url of the app to a "real" url. The app will still try to prevent access to the wider web.

Deep Links

Deep links to link into the app. Because the app is intentionally not communicating with servers or other apps, deep links do not work inside the app, so you can only link in from another app.

Debug builds of the app use a different deep link hostname (add .debug to the end of the hostname)

  • Delete a file
  • Rename a file
  • Deep link to play a game app://foss.zip.offline.browser.offlinezipbrowser/play/Your_game_here.html

RENAME_FILE

rename a file

DELETE_FILE

delete a file

TODO

  • Clear Cache options
  • Have multiple instances of the app open at once

About

Browse a zip file containing an index.html file as if it was a website. Cache/JS enabled, but it's all offline.

Resources

Stars

4 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

Offline Zip Browser

This project is meant so that I can play interactive fiction games, but it's also good for any similar project. You can even play my LizardUp game if you download the source as a zip and open it.

Use

  1. Use "Open with..." from your file app on a .zip file or standalone .html file, and select "Offline Zip Browser".
  2. Enter a name for it (you cannot change this yet)
    • The app will attempt to guess if .zip or .html but may get it wrong so it's good to specify .zip or .html in the name too.
  3. The file will be saved to app's storage and now any time you open the app you will have access to this file. LocalStorage will persist across sessions. Which means most interactive fiction games with save states will work.

Note: if you use termux + curl to download files, you will have to set the allow-external-apps property must be set to true in ~/.termux/termux.properties in termux.

Manifests

Create a ozb_manifest.json file in your zipped html app next to your index.html with a variety of useful settings that will control how the app is loaded. Generally these properties will help misbehaving applications work better.

Theoretically I'd like to be able to clear cache for a site on startup, but it's not built into web views by default that I can tell.

dateToSpoof

Offset based timestamp, loaded with OffsetDateTime.parse. Values like "2025-01-30T19:00:00-05:00" will work.

useUnsafeURL

Set the base url of the app to a "real" url. The app will still try to prevent access to the wider web.

Deep Links

Deep links to link into the app. Because the app is intentionally not communicating with servers or other apps, deep links do not work inside the app, so you can only link in from another app.

Debug builds of the app use a different deep link hostname (add .debug to the end of the hostname)

  • Delete a file
  • Rename a file
  • Deep link to play a game app://foss.zip.offline.browser.offlinezipbrowser/play/Your_game_here.html

RENAME_FILE

rename a file

DELETE_FILE

delete a file

TODO

  • Clear Cache options
  • Have multiple instances of the app open at once

About

Browse a zip file containing an index.html file as if it was a website. Cache/JS enabled, but it's all offline.

Resources

Stars

4 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

Offline Zip Browser

This project is meant so that I can play interactive fiction games, but it's also good for any similar project. You can even play my LizardUp game if you download the source as a zip and open it.

Use

  1. Use "Open with..." from your file app on a .zip file or standalone .html file, and select "Offline Zip Browser".
  2. Enter a name for it (you cannot change this yet)
    • The app will attempt to guess if .zip or .html but may get it wrong so it's good to specify .zip or .html in the name too.
  3. The file will be saved to app's storage and now any time you open the app you will have access to this file. LocalStorage will persist across sessions. Which means most interactive fiction games with save states will work.

Note: if you use termux + curl to download files, you will have to set the allow-external-apps property must be set to true in ~/.termux/termux.properties in termux.

Manifests

Create a ozb_manifest.json file in your zipped html app next to your index.html with a variety of useful settings that will control how the app is loaded. Generally these properties will help misbehaving applications work better.

Theoretically I'd like to be able to clear cache for a site on startup, but it's not built into web views by default that I can tell.

dateToSpoof

Offset based timestamp, loaded with OffsetDateTime.parse. Values like "2025-01-30T19:00:00-05:00" will work.

useUnsafeURL

Set the base url of the app to a "real" url. The app will still try to prevent access to the wider web.

Deep Links

Deep links to link into the app. Because the app is intentionally not communicating with servers or other apps, deep links do not work inside the app, so you can only link in from another app.

Debug builds of the app use a different deep link hostname (add .debug to the end of the hostname)

  • Delete a file
  • Rename a file
  • Deep link to play a game app://foss.zip.offline.browser.offlinezipbrowser/play/Your_game_here.html

RENAME_FILE

rename a file

DELETE_FILE

delete a file

TODO

  • Clear Cache options
  • Have multiple instances of the app open at once

About

Browse a zip file containing an index.html file as if it was a website. Cache/JS enabled, but it's all offline.

Resources

Stars

4 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Repository files navigation

Offline Zip Browser

This project is meant so that I can play interactive fiction games, but it's also good for any similar project. You can even play my LizardUp game if you download the source as a zip and open it.

Use

  1. Use "Open with..." from your file app on a .zip file or standalone .html file, and select "Offline Zip Browser".
  2. Enter a name for it (you cannot change this yet)
    • The app will attempt to guess if .zip or .html but may get it wrong so it's good to specify .zip or .html in the name too.
  3. The file will be saved to app's storage and now any time you open the app you will have access to this file. LocalStorage will persist across sessions. Which means most interactive fiction games with save states will work.

Note: if you use termux + curl to download files, you will have to set the allow-external-apps property must be set to true in ~/.termux/termux.properties in termux.

Manifests

Create a ozb_manifest.json file in your zipped html app next to your index.html with a variety of useful settings that will control how the app is loaded. Generally these properties will help misbehaving applications work better.

Theoretically I'd like to be able to clear cache for a site on startup, but it's not built into web views by default that I can tell.

dateToSpoof

Offset based timestamp, loaded with OffsetDateTime.parse. Values like "2025-01-30T19:00:00-05:00" will work.

useUnsafeURL

Set the base url of the app to a "real" url. The app will still try to prevent access to the wider web.

Deep Links

Deep links to link into the app. Because the app is intentionally not communicating with servers or other apps, deep links do not work inside the app, so you can only link in from another app.

Debug builds of the app use a different deep link hostname (add .debug to the end of the hostname)

  • Delete a file
  • Rename a file
  • Deep link to play a game app://foss.zip.offline.browser.offlinezipbrowser/play/Your_game_here.html

RENAME_FILE

rename a file

DELETE_FILE

delete a file

TODO

  • Clear Cache options
  • Have multiple instances of the app open at once

About

Browse a zip file containing an index.html file as if it was a website. Cache/JS enabled, but it's all offline.

Resources

Stars

4 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages