fix: fix download page overlay not closing when pro APK is absent, rename Maita to Mai

releases.json に pro キーがないとき apks.pro.url 参照でJSエラーが発生し
hideUserSelect() が実行されず画面が切り替わらないバグを修正。
pro が存在しない場合はカードを非表示にする。
Maita 表記を Mai に変更。

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Ponshu Developer 2026-04-05 09:50:16 +09:00
parent 5dde69788b
commit 4db63eb05a
1 changed files with 225 additions and 35 deletions

View File

@ -3,50 +3,145 @@
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Ponshu Room</title> <title>Ponshu Room - ダウンロード</title>
<meta name="description" content="日本酒コレクションアプリ"> <meta name="description" content="日本酒コレクションアプリ - 撮って、記録して、味わう">
<link rel="preconnect" href="https://fonts.googleapis.com"> <link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans+JP:wght@300;400;500&family=Noto+Serif+JP:wght@400;500&display=swap" rel="stylesheet"> <link href="https://fonts.googleapis.com/css2?family=Noto+Sans+JP:wght@300;400;500&family=Noto+Serif+JP:wght@400;500&display=swap" rel="stylesheet">
<link rel="stylesheet" href="style.css"> <link rel="stylesheet" href="style.css">
<link rel="icon" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><text y='.9em' font-size='90'>🍶</text></svg>"> <link rel="icon" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><text y='.9em' font-size='90'>🍶</text></svg>">
<style>
.user-select-overlay {
position: fixed;
top: 0; left: 0;
width: 100%; height: 100%;
background: rgba(74, 59, 50, 0.95);
backdrop-filter: blur(10px);
display: flex;
align-items: center;
justify-content: center;
z-index: 1000;
opacity: 1;
transition: opacity 0.3s var(--ease-out);
}
.user-select-overlay.hidden {
opacity: 0;
pointer-events: none;
}
.user-select-box {
background: var(--washi-white);
border-radius: 24px;
padding: var(--space-xl);
max-width: 400px;
width: 90%;
text-align: center;
}
.user-select-title {
font-family: var(--font-serif);
font-size: 1.5rem;
margin-bottom: var(--space-lg);
color: var(--sumi-black);
}
.user-buttons {
display: flex;
gap: var(--space-md);
margin-bottom: var(--space-md);
}
.user-button {
flex: 1;
padding: var(--space-lg);
background: white;
border: 2px solid var(--gray-200);
border-radius: 16px;
font-family: var(--font-sans);
font-size: 1.125rem;
font-weight: 500;
color: var(--sumi-black);
cursor: pointer;
transition: all 0.3s var(--ease-out);
}
.user-button:hover {
border-color: var(--kohaku-gold);
transform: translateY(-2px);
box-shadow: 0 12px 24px -8px rgba(74, 59, 50, 0.15);
}
.user-select-note {
font-size: 0.75rem;
color: var(--gray-400);
margin-top: var(--space-md);
}
.version-card.disabled {
opacity: 0.5;
pointer-events: none;
}
.info-banner {
background: rgba(212, 165, 116, 0.1);
border: 1px solid var(--kohaku-gold);
border-radius: 12px;
padding: var(--space-sm) var(--space-md);
text-align: center;
}
.info-banner-user {
font-weight: 500;
color: var(--kohaku-gold);
}
.change-user-btn {
display: inline-block;
margin-top: var(--space-xs);
font-size: 0.75rem;
color: var(--kohaku-gold);
text-decoration: underline;
cursor: pointer;
}
.change-user-btn:hover { color: var(--kohaku-deep); }
.card-version {
font-size: 0.7rem;
color: var(--gray-400);
letter-spacing: 0.04em;
}
@media (prefers-color-scheme: dark) {
.user-select-box { background: #1E1E1E; }
.user-button { background: #2A2A2A; border-color: #3A3A3A; color: var(--sumi-black); }
.info-banner { background: rgba(212, 165, 116, 0.15); }
}
</style>
</head> </head>
<body> <body>
<!-- User Selection Overlay -->
<div id="userSelectOverlay" class="user-select-overlay">
<div class="user-select-box">
<h2 class="user-select-title">ユーザーを選択</h2>
<div class="user-buttons">
<button class="user-button" onclick="selectUser('maita')">Mai</button>
<button class="user-button" onclick="selectUser('eiji')">Eiji</button>
</div>
<p class="user-select-note">あなた専用のAPKをダウンロードします</p>
</div>
</div>
<div class="container"> <div class="container">
<!-- Hero Section --> <!-- Hero -->
<header class="hero"> <header class="hero">
<div class="logo"> <div class="logo">
<svg class="sake-icon" viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg"> <span class="sake-icon" role="img" aria-label="日本酒">🍶</span>
<path d="M24 4L28 12H20L24 4Z" fill="currentColor" opacity="0.6"/>
<path d="M16 12H32V16C32 18 30 20 30 24V40C30 42 28 44 24 44C20 44 18 42 18 40V24C18 20 16 18 16 16V12Z" fill="currentColor"/>
<ellipse cx="24" cy="32" rx="4" ry="2" fill="currentColor" opacity="0.3"/>
</svg>
<h1>Ponshu Room</h1> <h1>Ponshu Room</h1>
</div> </div>
<p class="tagline">日本酒を撮って、記録して、味わう</p> <p class="tagline">日本酒を撮って、記録して、味わう</p>
</header> </header>
<!-- App Preview --> <!-- User Info Banner -->
<section class="preview"> <div id="infoBanner" class="info-banner" style="display: none;">
<div class="phone-frame"> <div class="info-banner-user">
<div class="screen-placeholder"> <span id="currentUserName"></span> 用のAPK &nbsp;·&nbsp; <span id="releaseDate"></span>
<div class="grid-preview">
<div class="grid-item"></div>
<div class="grid-item"></div>
<div class="grid-item"></div>
<div class="grid-item"></div>
<div class="grid-item"></div>
<div class="grid-item"></div>
</div> </div>
<a class="change-user-btn" onclick="changeUser()">ユーザーを変更</a>
</div> </div>
</div>
</section>
<!-- Download Section --> <!-- Download Section -->
<section class="download"> <section class="download">
<div class="version-cards"> <div class="version-cards">
<!-- Lite Version --> <!-- Lite -->
<a href="https://github.com/YOUR_REPO/releases/download/v1.0.12/ponshu-room-lite.apk" class="version-card" download> <a id="liteDownload" href="#" class="version-card" download>
<div class="card-header"> <div class="card-header">
<span class="version-name">Lite</span> <span class="version-name">Lite</span>
<span class="version-badge free">Free</span> <span class="version-badge free">Free</span>
@ -56,11 +151,12 @@
<path d="M12 3v12m0 0l-4-4m4 4l4-4M5 17v2a2 2 0 002 2h10a2 2 0 002-2v-2"/> <path d="M12 3v12m0 0l-4-4m4 4l4-4M5 17v2a2 2 0 002 2h10a2 2 0 002-2v-2"/>
</svg> </svg>
</div> </div>
<span class="file-size">88 MB</span> <span class="card-version" id="liteVersion"></span>
<span class="file-size" id="liteSize">90 MB</span>
</a> </a>
<!-- Pro Version --> <!-- Pro -->
<a href="https://github.com/YOUR_REPO/releases/download/v1.0.12/ponshu-room-pro.apk" class="version-card pro" download> <a id="proDownload" href="#" class="version-card pro" download>
<div class="card-header"> <div class="card-header">
<span class="version-name">Pro</span> <span class="version-name">Pro</span>
<span class="version-badge pro-badge">Pro</span> <span class="version-badge pro-badge">Pro</span>
@ -70,14 +166,15 @@
<path d="M12 3v12m0 0l-4-4m4 4l4-4M5 17v2a2 2 0 002 2h10a2 2 0 002-2v-2"/> <path d="M12 3v12m0 0l-4-4m4 4l4-4M5 17v2a2 2 0 002 2h10a2 2 0 002-2v-2"/>
</svg> </svg>
</div> </div>
<span class="file-size">89 MB</span> <span class="card-version" id="proVersion"></span>
<span class="file-size" id="proSize">90 MB</span>
</a> </a>
</div> </div>
<p class="platform-note">Android 8.0+</p> <p class="platform-note">Android 8.0+ (API Level 24)</p>
</section> </section>
<!-- Features (Icons Only) --> <!-- Features -->
<section class="features"> <section class="features">
<div class="feature"> <div class="feature">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5"> <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
@ -106,11 +203,104 @@
<span>マップ</span> <span>マップ</span>
</div> </div>
</section> </section>
<!-- Footer -->
<footer>
<p>v1.0.12</p>
</footer>
</div> </div>
<script>
let currentUser = null;
let releaseData = null;
// releases.json から動的にデータを取得
async function loadReleases() {
try {
const res = await fetch('releases.json?t=' + Date.now());
releaseData = await res.json();
applyReleaseData();
} catch (e) {
// フォールバック: 固定値
releaseData = {
version: 'v1.0.16',
date: '2026-02-23',
apks: {
maita: {
lite: { url: 'https://posimai-lab.tail72e846.ts.net/mai/ponshu-room-lite/releases/download/v1.0.16/ponshu_room_lite_maita.apk', size_mb: 90 },
pro: { url: 'https://posimai-lab.tail72e846.ts.net/mai/ponshu-room-lite/releases/download/v1.0.16/ponshu_room_pro_maita.apk', size_mb: 90 }
},
eiji: {
lite: { url: 'https://posimai-lab.tail72e846.ts.net/mai/ponshu-room-lite/releases/download/v1.0.16/ponshu_room_lite_eiji.apk', size_mb: 90 },
pro: { url: 'https://posimai-lab.tail72e846.ts.net/mai/ponshu-room-lite/releases/download/v1.0.16/ponshu_room_pro_eiji.apk', size_mb: 90 }
}
}
};
applyReleaseData();
}
}
function applyReleaseData() {
if (!releaseData) return;
document.getElementById('liteVersion').textContent = releaseData.version;
document.getElementById('proVersion').textContent = releaseData.version;
document.getElementById('liteSize').textContent = releaseData.apks.eiji?.lite?.size_mb + ' MB' || '90 MB';
document.getElementById('proSize').textContent = releaseData.apks.eiji?.pro?.size_mb + ' MB' || '90 MB';
document.getElementById('releaseDate').textContent = releaseData.date;
if (currentUser) updateDownloadLinks();
}
function selectUser(user) {
currentUser = user;
localStorage.setItem('ponshu_user', user);
updateDownloadLinks();
hideUserSelect();
}
function changeUser() { showUserSelect(); }
function updateDownloadLinks() {
if (!currentUser || !releaseData) return;
const apks = releaseData.apks[currentUser];
const nameMap = { maita: 'Mai', eiji: 'Eiji' };
// Lite
if (apks?.lite?.url) {
document.getElementById('liteDownload').href = apks.lite.url;
document.getElementById('liteDownload').classList.remove('disabled');
}
// Pro存在しない場合は非表示
const proCard = document.getElementById('proDownload');
if (apks?.pro?.url) {
proCard.href = apks.pro.url;
proCard.style.display = '';
} else {
proCard.style.display = 'none';
}
document.getElementById('currentUserName').textContent = nameMap[currentUser] || currentUser;
document.getElementById('infoBanner').style.display = 'block';
}
function showUserSelect() {
document.getElementById('userSelectOverlay').classList.remove('hidden');
}
function hideUserSelect() {
document.getElementById('userSelectOverlay').classList.add('hidden');
}
window.addEventListener('DOMContentLoaded', async () => {
await loadReleases();
const savedUser = localStorage.getItem('ponshu_user');
if (savedUser === 'maita' || savedUser === 'eiji') {
selectUser(savedUser);
} else {
showUserSelect();
}
});
document.getElementById('liteDownload').addEventListener('click', (e) => {
if (!currentUser) { e.preventDefault(); showUserSelect(); }
});
document.getElementById('proDownload').addEventListener('click', (e) => {
if (!currentUser) { e.preventDefault(); showUserSelect(); }
});
</script>
</body> </body>
</html> </html>