mirror of
https://github.com/knutwurst/patchdl.git
synced 2026-10-17 23:00:52 +02:00
Cards show installed, update and newest version side by side, and problems as notes with their action. Other versions became a button. The dialog groups versions into available, needs newer firmware, installed and older (folded), with larger type throughout. Text is at least 13px, buttons 44px tall, and every control has a focus ring. Phones get two status tiles per row and full-width card content.
303 lines
15 KiB
HTML
303 lines
15 KiB
HTML
<!doctype html>
|
||
<html lang="en">
|
||
<head>
|
||
<meta charset="utf-8" />
|
||
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover" />
|
||
<title>PatchDL</title>
|
||
<link rel="stylesheet" href="styles.css" />
|
||
</head>
|
||
<body>
|
||
<svg class="icon-sprite" aria-hidden="true">
|
||
<symbol id="icon-download" viewBox="0 0 24 24">
|
||
<path d="M12 3v11" /><path d="M7 10l5 5 5-5" /><path d="M5 20h14" />
|
||
</symbol>
|
||
<symbol id="icon-refresh" viewBox="0 0 24 24">
|
||
<path d="M20 6v6h-6" /><path d="M4 18v-6h6" />
|
||
<path d="M19 12A7 7 0 0 0 7 7" /><path d="M5 12a7 7 0 0 0 12 5" />
|
||
</symbol>
|
||
<symbol id="icon-settings" viewBox="0 0 24 24">
|
||
<path d="M12 8a4 4 0 1 0 0 8 4 4 0 0 0 0-8z" />
|
||
<path d="M4 12h2M18 12h2M12 4v2M12 18v2M6.5 6.5 8 8M16 16l1.5 1.5M17.5 6.5 16 8M8 16l-1.5 1.5" />
|
||
</symbol>
|
||
<symbol id="icon-search" viewBox="0 0 24 24">
|
||
<path d="M10.5 18a7.5 7.5 0 1 1 0-15 7.5 7.5 0 0 1 0 15z" /><path d="M16 16l5 5" />
|
||
</symbol>
|
||
<symbol id="icon-save" viewBox="0 0 24 24">
|
||
<path d="M5 4h12l2 2v14H5V4z" /><path d="M8 4v6h8V4" /><path d="M8 20v-6h8v6" />
|
||
</symbol>
|
||
<symbol id="icon-log" viewBox="0 0 24 24">
|
||
<path d="M7 4h10l3 3v13H7V4z" /><path d="M17 4v4h4" /><path d="M10 12h7M10 16h5" />
|
||
</symbol>
|
||
<symbol id="icon-grid" viewBox="0 0 24 24">
|
||
<path d="M4 4h7v7H4zM13 4h7v7h-7zM4 13h7v7H4zM13 13h7v7h-7z" />
|
||
</symbol>
|
||
<symbol id="icon-close" viewBox="0 0 24 24">
|
||
<path d="M6 6l12 12M18 6L6 18" />
|
||
</symbol>
|
||
<symbol id="icon-arrow" viewBox="0 0 24 24">
|
||
<path d="M5 12h14" /><path d="M13 6l6 6-6 6" />
|
||
</symbol>
|
||
<symbol id="icon-layers" viewBox="0 0 24 24">
|
||
<path d="M12 3l9 5-9 5-9-5 9-5z" /><path d="M3 13l9 5 9-5" />
|
||
</symbol>
|
||
<symbol id="icon-alert" viewBox="0 0 24 24">
|
||
<path d="M12 3l10 18H2L12 3z" /><path d="M12 10v5" /><path d="M12 18h.01" />
|
||
</symbol>
|
||
<symbol id="icon-check" viewBox="0 0 24 24">
|
||
<path d="M5 12.5l4.5 4.5L19 7" />
|
||
</symbol>
|
||
<symbol id="icon-lock" viewBox="0 0 24 24">
|
||
<path d="M6 11h12v10H6z" /><path d="M8.5 11V8a3.5 3.5 0 0 1 7 0v3" />
|
||
</symbol>
|
||
<symbol id="icon-external" viewBox="0 0 24 24">
|
||
<path d="M14 4h6v6" /><path d="M20 4l-9 9" /><path d="M18 14v6H4V6h6" />
|
||
</symbol>
|
||
<symbol id="icon-chevron" viewBox="0 0 24 24">
|
||
<path d="M9 6l6 6-6 6" />
|
||
</symbol>
|
||
</svg>
|
||
|
||
<div class="app-shell">
|
||
<aside class="rail" aria-label="Navigation" data-i18n-aria-label="nav.label">
|
||
<div class="brand">
|
||
<div class="brand-mark">PD</div>
|
||
<div>
|
||
<strong>PatchDL</strong>
|
||
<span><span class="brand-by" data-i18n="brand.by">by Knutwurst</span> · <span id="brandVersion">--</span></span>
|
||
</div>
|
||
</div>
|
||
|
||
<nav class="nav-list" aria-label="Sections" data-i18n-aria-label="nav.sections">
|
||
<button class="nav-link is-active" data-view="games" aria-label="Games" data-i18n-aria-label="nav.games" aria-current="page">
|
||
<svg><use href="#icon-grid"></use></svg><span data-i18n="nav.games">Games</span>
|
||
</button>
|
||
<button class="nav-link" data-view="settings" aria-label="Settings" data-i18n-aria-label="nav.settings">
|
||
<svg><use href="#icon-settings"></use></svg><span data-i18n="nav.settings">Settings</span>
|
||
</button>
|
||
<button class="nav-link" data-view="logs" aria-label="Logs" data-i18n-aria-label="nav.logs">
|
||
<svg><use href="#icon-log"></use></svg><span data-i18n="nav.logs">Logs</span>
|
||
</button>
|
||
</nav>
|
||
|
||
<div class="rail-foot">
|
||
<span id="railFw">FW --</span>
|
||
<span id="railSpace" data-i18n="rail.freeUnknown">-- free</span>
|
||
<button type="button" class="link-button rail-donate" data-donate data-i18n="donate.button">Buy me a coffee</button>
|
||
</div>
|
||
</aside>
|
||
|
||
<main class="main">
|
||
<!-- ============ GAMES ============ -->
|
||
<section class="view is-active" data-view="games">
|
||
<header class="topbar">
|
||
<div>
|
||
<p class="eyebrow" data-i18n="games.eyebrow">PS5 & PS4 game updates</p>
|
||
<h1 data-i18n="games.title">Games</h1>
|
||
</div>
|
||
<div class="topbar-actions">
|
||
<button class="primary-button" id="updateAllBtn" title="Download (and optionally install) every game that has an available, allowed update" data-i18n-title="games.updateAllTitle">
|
||
<svg><use href="#icon-download"></use></svg>
|
||
<span data-i18n="games.updateAll">Update all</span>
|
||
</button>
|
||
<button class="icon-button" id="refreshBtn" title="Refresh status and games" data-i18n-title="games.refreshTitle" aria-label="Refresh" data-i18n-aria-label="games.refresh">
|
||
<svg><use href="#icon-refresh"></use></svg>
|
||
</button>
|
||
</div>
|
||
</header>
|
||
|
||
<aside id="globalDl" class="global-dl" hidden aria-live="polite">
|
||
<div class="global-dl-row">
|
||
<span class="global-dl-pulse" aria-hidden="true"></span>
|
||
<div class="global-dl-text">
|
||
<div class="global-dl-line1">
|
||
<span class="global-dl-eyebrow" id="globalDlState" data-i18n="dl.downloading">Downloading</span>
|
||
<strong class="global-dl-name" id="globalDlName">—</strong>
|
||
<span class="global-dl-position" id="globalDlPosition" hidden></span>
|
||
</div>
|
||
<div class="global-dl-line2">
|
||
<span id="globalDlPct">0%</span>
|
||
<span class="global-dl-sep" aria-hidden="true">·</span>
|
||
<span id="globalDlSpeed">—</span>
|
||
<span class="global-dl-sep" aria-hidden="true">·</span>
|
||
<span id="globalDlEta">—</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="global-dl-track">
|
||
<i class="global-dl-bar" id="globalDlBar" style="width:0%"></i>
|
||
</div>
|
||
</aside>
|
||
|
||
<section class="status-strip" aria-label="System status" data-i18n-aria-label="status.label">
|
||
<article class="metric">
|
||
<span data-i18n="metric.firmware">Firmware</span>
|
||
<strong id="firmwareValue">--</strong>
|
||
<em id="firmwareBuild" data-i18n="metric.firmwareBuild">System version</em>
|
||
</article>
|
||
<article class="metric">
|
||
<span data-i18n="metric.dns">DNS Guard</span>
|
||
<strong id="dnsValue">--</strong>
|
||
<em data-i18n="metric.dnsNote">System DNS left untouched</em>
|
||
</article>
|
||
<article class="metric">
|
||
<span data-i18n="metric.cdn">CDN Access</span>
|
||
<strong id="resolverValue">--</strong>
|
||
<em data-i18n="metric.cdnNote">PatchDL resolver only</em>
|
||
</article>
|
||
<article class="metric">
|
||
<span data-i18n="metric.storage">Storage</span>
|
||
<strong id="spaceValue">--</strong>
|
||
<em id="downloadDirValue" data-i18n="metric.downloadTarget">Download target</em>
|
||
</article>
|
||
</section>
|
||
|
||
<div class="toolbar">
|
||
<div class="search-box">
|
||
<svg><use href="#icon-search"></use></svg>
|
||
<input id="searchInput" type="search" placeholder="Search title, Title ID, or Content ID" data-i18n-placeholder="search.placeholder" />
|
||
</div>
|
||
<div class="segmented" role="group" aria-label="Filter" data-i18n-aria-label="filter.label">
|
||
<button class="is-selected" data-filter="updates" aria-pressed="true"><span data-i18n="filter.updates">Updates</span> <span class="chip-count"></span></button>
|
||
<button data-filter="uptodate" aria-pressed="false"><span data-i18n="filter.uptodate">Up to date</span> <span class="chip-count"></span></button>
|
||
<button data-filter="blocked" aria-pressed="false"><span data-i18n="filter.blocked">Not supported</span> <span class="chip-count"></span></button>
|
||
<button data-filter="all" aria-pressed="false"><span data-i18n="filter.all">All</span> <span class="chip-count"></span></button>
|
||
</div>
|
||
</div>
|
||
|
||
<section class="game-grid" id="gameGrid"></section>
|
||
</section>
|
||
|
||
<!-- ============ SETTINGS ============ -->
|
||
<section class="view" data-view="settings">
|
||
<header class="topbar">
|
||
<div>
|
||
<p class="eyebrow" data-i18n="settings.eyebrow">Policy</p>
|
||
<h1 data-i18n="settings.title">Settings</h1>
|
||
</div>
|
||
<div class="topbar-actions">
|
||
<button class="primary-button" id="saveBtn">
|
||
<svg><use href="#icon-save"></use></svg>
|
||
<span data-i18n="settings.save">Save</span>
|
||
</button>
|
||
</div>
|
||
</header>
|
||
|
||
<div class="panel">
|
||
<div class="settings-grid">
|
||
<label class="field">
|
||
<span data-i18n="settings.defaultPolicy">Default Policy</span>
|
||
<select id="defaultPolicy">
|
||
<option value="deny" data-i18n="settings.policyDeny">Deny by default</option>
|
||
<option value="allow" data-i18n="settings.policyAllow">Allow by default</option>
|
||
</select>
|
||
</label>
|
||
<label class="field">
|
||
<span data-i18n="settings.downloadFolder">Download Folder</span>
|
||
<input id="downloadDir" type="text" spellcheck="false" readonly
|
||
title="Patches always download to the console's internal storage"
|
||
data-i18n-title="settings.downloadFolderTitle" />
|
||
</label>
|
||
<label class="field">
|
||
<span data-i18n="settings.language">Language</span>
|
||
<select id="language"></select>
|
||
</label>
|
||
|
||
<label class="switch-row">
|
||
<span>
|
||
<strong data-i18n="settings.installAfter">Install after download</strong>
|
||
<em data-i18n="settings.installAfterHint">Global default, overridable per game</em>
|
||
</span>
|
||
<span class="toggle">
|
||
<input id="installAfterDownload" type="checkbox" aria-label="Install after download" data-i18n-aria-label="settings.installAfter" />
|
||
<span class="track"></span>
|
||
</span>
|
||
</label>
|
||
<label class="switch-row">
|
||
<span>
|
||
<strong data-i18n="settings.deleteAfter">Delete PKG after install</strong>
|
||
<em data-i18n="settings.deleteAfterHint">Only after a successful install</em>
|
||
</span>
|
||
<span class="toggle">
|
||
<input id="deleteAfterInstall" type="checkbox" aria-label="Delete package after install" data-i18n-aria-label="settings.deleteAfterAria" />
|
||
<span class="track"></span>
|
||
</span>
|
||
</label>
|
||
<label class="switch-row">
|
||
<span>
|
||
<strong data-i18n="settings.verify">Verify downloaded pieces (SHA-256)</strong>
|
||
<em data-i18n="settings.verifyHint">Checks each manifest piece; off by default, verify on-device first</em>
|
||
</span>
|
||
<span class="toggle">
|
||
<input id="verifyDownloads" type="checkbox" aria-label="Verify downloaded pieces" data-i18n-aria-label="settings.verifyAria" />
|
||
<span class="track"></span>
|
||
</span>
|
||
</label>
|
||
<label class="switch-row">
|
||
<span>
|
||
<strong data-i18n="settings.shortcut">Home-screen shortcut</strong>
|
||
<em id="shortcutHint" data-i18n="settings.shortcutHint">Add a PS5 home-screen icon that opens this UI in the browser</em>
|
||
</span>
|
||
<span class="toggle">
|
||
<input id="homeShortcut" type="checkbox" aria-label="Install home-screen shortcut" data-i18n-aria-label="settings.shortcutAria" />
|
||
<span class="track"></span>
|
||
</span>
|
||
</label>
|
||
<div class="switch-row">
|
||
<span>
|
||
<strong data-i18n="settings.connections">Parallel download connections</strong>
|
||
<em data-i18n="settings.connectionsHint">1–16 · applies live, no payload restart</em>
|
||
</span>
|
||
<div class="stepper" role="group" aria-label="Parallel download connections" data-i18n-aria-label="settings.connections">
|
||
<button type="button" class="stepper-btn" id="connMinus" aria-label="Fewer connections" data-i18n-aria-label="settings.connFewer">−</button>
|
||
<output class="stepper-value" id="connValue" aria-live="polite">4</output>
|
||
<button type="button" class="stepper-btn" id="connPlus" aria-label="More connections" data-i18n-aria-label="settings.connMore">+</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="allowlist">
|
||
<span data-i18n="settings.allowlist">Internal CDN Allowlist</span>
|
||
<div id="allowlistHosts"></div>
|
||
</div>
|
||
|
||
<div class="source-policy">
|
||
<span data-i18n="settings.installProtection">Install Protection</span>
|
||
<div id="sourcePolicyList"></div>
|
||
</div>
|
||
|
||
<div class="storage-list">
|
||
<span><span data-i18n="settings.storage">Downloads on console</span> <em id="storageTotal"></em></span>
|
||
<div id="storageList"></div>
|
||
</div>
|
||
|
||
<div class="donate-row">
|
||
<span data-i18n="settings.donateText">Like PatchDL? You can buy me a coffee.</span>
|
||
<button type="button" class="row-button is-ghost" data-donate data-i18n="donate.button">Buy me a coffee</button>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- ============ LOGS ============ -->
|
||
<section class="view" data-view="logs">
|
||
<header class="topbar">
|
||
<div>
|
||
<p class="eyebrow" data-i18n="logs.eyebrow">Runtime</p>
|
||
<h1 data-i18n="logs.title">Logs</h1>
|
||
</div>
|
||
<div class="topbar-actions">
|
||
<button class="icon-button" id="clearLogBtn" title="Clear log" data-i18n-title="logs.clear" aria-label="Clear log" data-i18n-aria-label="logs.clear">
|
||
<svg><use href="#icon-log"></use></svg>
|
||
</button>
|
||
</div>
|
||
</header>
|
||
<pre id="logOutput" tabindex="0"></pre>
|
||
</section>
|
||
</main>
|
||
</div>
|
||
|
||
<div class="toast" id="toast" role="status" aria-live="polite"></div>
|
||
<script src="i18n.js"></script>
|
||
<script src="app.js"></script>
|
||
</body>
|
||
</html>
|