add SREBOT, SHARED, TSSBOT contents (fixup for #1223)

PR #1223 only staged the deletions of the old paths because the new
top-level directories were still untracked when the commit was authored.
This commit adds the actual restructured tree: SREBOT/ (existing bot),
SHARED/ (vromfs, data_parser, ICONS/MAPS/FONTS, DAGOR_FILES,
update_game_files), and TSSBOT/ (skeleton).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
FURRO404
2026-05-13 23:17:02 -07:00
commit 2b399fdb81
186 changed files with 96596 additions and 0 deletions
+93
View File
@@ -0,0 +1,93 @@
(function () {
'use strict';
const modal = document.getElementById('season-recap-modal');
const btn = document.getElementById('season-recap-btn');
const selectEl = document.getElementById('season-recap-select');
const genBtn = document.getElementById('season-recap-generate');
const img = document.getElementById('season-recap-image');
const statusEl = document.getElementById('season-recap-status');
if (!modal || !btn || !selectEl || !genBtn || !img) {
console.warn('[recap] modal elements not found; skipping init');
return;
}
const scriptTag = document.currentScript;
const clanId = scriptTag && scriptTag.dataset.clanId;
if (!clanId) {
console.warn('[recap] no clan_id on script tag; disabling button');
btn.disabled = true;
return;
}
function openModal() {
modal.classList.remove('hidden');
modal.setAttribute('aria-hidden', 'false');
}
function closeModal() {
modal.classList.add('hidden');
modal.setAttribute('aria-hidden', 'true');
}
modal.querySelectorAll('[data-close]').forEach(el => el.addEventListener('click', closeModal));
btn.addEventListener('click', async () => {
openModal();
if (!selectEl.options.length) await loadSeasons();
});
function t(key) {
return (window.__t && window.__t('seasonCard.' + key)) || key;
}
async function loadSeasons() {
statusEl.textContent = t('loadingSeasons');
try {
if (!window.apiClient) {
throw new Error('apiClient not available');
}
const seasons = await window.apiClient.request('/api/seasons');
const entries = Object.entries(seasons).sort((a, b) => b[1].start - a[1].start);
selectEl.innerHTML = '';
for (const [name, range] of entries) {
const opt = document.createElement('option');
opt.value = name;
opt.textContent = range.status === 'in_progress'
? `${name} ${t('inProgressSuffix')}`
: name;
selectEl.appendChild(opt);
}
statusEl.textContent = '';
} catch (err) {
console.error('[recap] seasons fetch failed:', err);
statusEl.textContent = t('failedSeasons');
}
}
function selectedTheme() {
const checked = document.querySelector('input[name="season-recap-theme"]:checked');
return (checked && checked.value) || 'dark';
}
genBtn.addEventListener('click', () => {
const season = selectEl.value;
if (!season) return;
const theme = selectedTheme();
const lang = document.documentElement.lang || 'en';
const base = `/squadron/${encodeURIComponent(clanId)}/recap/${encodeURIComponent(season)}.png`;
const params = new URLSearchParams({ theme, lang });
statusEl.textContent = t('generating');
img.style.display = 'none';
img.onload = () => {
statusEl.textContent = '';
img.style.display = 'block';
};
img.onerror = () => {
statusEl.textContent = t('failedGenerate');
};
const currentOpt = selectEl.options[selectEl.selectedIndex];
const inProgressLabel = t('inProgressSuffix');
const isInProgress = !!(currentOpt && inProgressLabel && currentOpt.textContent.indexOf(inProgressLabel) !== -1);
if (isInProgress) params.set('t', String(Date.now()));
img.src = `${base}?${params.toString()}`;
});
})();