-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.ts
77 lines (70 loc) · 2.88 KB
/
index.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
import { extractIconFromExe } from './icon_extractor.js';
import { $, addToast, dirname, loadGameIni, registerErrorHandlers } from './utils.js';
import * as zip from './zip.js';
$('#file-picker').addEventListener('change', (evt: Event) => {
const files = (evt.target as HTMLInputElement).files!;
if (files.length === 1 && files[0].name.toLowerCase().endsWith('.zip')) {
handleZip(files[0]);
} else {
addToast('ZIPファイルを選択してください。', 'warning');
gtag('event', 'InstallError', { Reason: 'No ZIP file selected' });
}
}, false);
export async function handleZip(zipFile: File) {
const files = await zip.load(zipFile);
const ini = await loadGameIni(files);
if (!ini) {
addToast('ZIPファイルにゲームデータが見つかりません。', 'error');
gtag('event', 'InstallError', { Reason: 'No game data found in ZIP' });
return;
}
let icon: Uint8Array | null = null;
// Find an .ico file.
const iniDir = dirname(ini.iniPath);
const iconFile = files.find(f => dirname(f.name) === iniDir && f.name.toLowerCase().endsWith('.ico'));
if (iconFile) {
icon = await iconFile.extract();
} else {
// Find an .exe file and extract an icon from it.
const exeFile = files.find(f => dirname(f.name) === iniDir && f.name.toLowerCase().endsWith('.exe'));
if (exeFile) {
icon = extractIconFromExe((await exeFile.extract()).buffer);
}
}
await generateManifest(ini.gameName, icon);
gtag('event', 'ManifestGenerated', { Title: ini.gameName });
($('#add-to-home-screen') as HTMLDialogElement).showModal();
}
async function generateManifest(title: string, icon: Uint8Array | null) {
if (icon) {
await new Promise<void>((res, rej) => {
const blob = new Blob([icon], { type: 'image/x-icon' });
const reader = new FileReader();
reader.onload = () => {
const link = document.createElement('link');
link.rel = 'apple-touch-icon';
link.href = reader.result as string;
document.head.appendChild(link);
res();
};
reader.onerror = rej;
reader.readAsDataURL(blob);
});
}
const baseUrl = new URL(location.href);
const startUrl = new URL('play.html?pwa=1#' + encodeURIComponent(title), baseUrl);
const manifest = {
name: title + ' - XSystem4 for Web',
short_name: title,
start_url: startUrl.href,
display: 'standalone',
background_color: '#000',
theme_color: '#525f7a'
};
console.log(manifest);
const link = document.createElement('link');
link.rel = 'manifest';
link.href = URL.createObjectURL(new Blob([JSON.stringify(manifest)], { type: 'application/json' }));
document.head.appendChild(link);
}
registerErrorHandlers();