diff --git a/.claude/settings.local.json b/.claude/settings.local.json new file mode 100644 index 0000000..540eac8 --- /dev/null +++ b/.claude/settings.local.json @@ -0,0 +1,7 @@ +{ + "permissions": { + "allow": [ + "Bash(go build *)" + ] + } +} diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..d297027 --- /dev/null +++ b/LICENSE @@ -0,0 +1,4 @@ +Copyright (c) 2026 HPL + +All rights reserved. This software is proprietary and confidential. +Unauthorized copying, distribution, or use is prohibited. diff --git a/dist/hpl-toolbox-0.1.2.exe b/dist/hpl-toolbox-0.1.2.exe new file mode 100644 index 0000000..dfb28a6 Binary files /dev/null and b/dist/hpl-toolbox-0.1.2.exe differ diff --git a/dist/hpl-toolbox-0.1.3.vsix b/dist/hpl-toolbox-0.1.3.vsix new file mode 100644 index 0000000..e34dadc Binary files /dev/null and b/dist/hpl-toolbox-0.1.3.vsix differ diff --git a/dist/hpl-toolbox.exe b/dist/hpl-toolbox.exe index dfb28a6..c2736ec 100644 Binary files a/dist/hpl-toolbox.exe and b/dist/hpl-toolbox.exe differ diff --git a/package.json b/package.json index f89f6d8..cd68cac 100644 --- a/package.json +++ b/package.json @@ -2,8 +2,13 @@ "name": "hpl-toolbox", "displayName": "HPL Toolbox", "description": "Bundled tools: PLEC Upload, AppLovin Demo Upload, Base64 Asset Scanner, Daily Update. Local HTML Host.", - "version": "0.1.2", + "version": "0.1.3", "publisher": "hesukastro", + "license": "UNLICENSED", + "repository": { + "type": "git", + "url": "https://gitea.hesukastro.com/hesukastro/vsix-hpl-toolbox.git" + }, "engines": { "vscode": "^1.85.0" }, diff --git a/src/tools/applovinUpload.ts b/src/tools/applovinUpload.ts index d6045b2..9f0e447 100644 --- a/src/tools/applovinUpload.ts +++ b/src/tools/applovinUpload.ts @@ -34,6 +34,16 @@ export function openApplovinUpload(_context: vscode.ExtensionContext) { await handleUpload(panel, msg.paths); return; } + + if (msg.type === 'saveQr') { + await handleSaveQr(panel, msg.url, msg.name); + return; + } + + if (msg.type === 'saveAllQrs') { + await handleSaveAllQrs(panel, msg.items || []); + return; + } } catch (err: any) { panel.webview.postMessage({ type: 'error', message: err?.message || String(err) }); } @@ -124,6 +134,68 @@ async function handleUpload(panel: vscode.WebviewPanel, filePaths: string[]) { panel.webview.postMessage({ type: 'done' }); } +function qrBaseName(name: string): string { + return (name || 'qr').replace(/\.html?$/i, '').replace(/[\\/:*?"<>|]/g, '_') || 'qr'; +} + +async function downloadQr(url: string, destPath: string): Promise { + const res = await fetch(url); + if (!res.ok) throw new Error(`HTTP ${res.status}`); + const buf = Buffer.from(await res.arrayBuffer()); + await fs.promises.writeFile(destPath, buf); +} + +async function handleSaveQr(panel: vscode.WebviewPanel, url: string, name: string) { + if (!url) return; + const base = qrBaseName(name); + const defaultUri = vscode.Uri.file(path.join(require('os').homedir(), 'Downloads', `${base}.png`)); + const target = await vscode.window.showSaveDialog({ + defaultUri, + filters: { 'PNG Image': ['png'] }, + saveLabel: 'Save QR', + }); + if (!target) return; + try { + await downloadQr(url, target.fsPath); + panel.webview.postMessage({ type: 'status', message: `Saved QR: ${target.fsPath}` }); + } catch (err: any) { + panel.webview.postMessage({ type: 'error', message: 'Save QR failed: ' + (err?.message || err) }); + } +} + +async function handleSaveAllQrs(panel: vscode.WebviewPanel, items: Array<{ name: string; url: string }>) { + if (!items.length) return; + const picked = await vscode.window.showOpenDialog({ + canSelectFiles: false, + canSelectFolders: true, + canSelectMany: false, + openLabel: 'Save QRs Here', + }); + if (!picked || !picked.length) return; + const dir = picked[0].fsPath; + let saved = 0; + const errors: string[] = []; + for (const it of items) { + const base = qrBaseName(it.name); + let dest = path.join(dir, `${base}.png`); + let n = 1; + while (fs.existsSync(dest)) { + dest = path.join(dir, `${base} (${n++}).png`); + } + try { + await downloadQr(it.url, dest); + saved++; + } catch (err: any) { + errors.push(`${it.name}: ${err?.message || err}`); + } + } + if (errors.length) { + panel.webview.postMessage({ type: 'error', message: `Saved ${saved}/${items.length}. Errors:\n` + errors.join('\n') }); + } else { + panel.webview.postMessage({ type: 'status', message: `Saved ${saved} QR${saved === 1 ? '' : 's'} to ${dir}` }); + } +} + function getHtml(): string { return ` @@ -163,11 +235,15 @@ function getHtml(): string {

Upload HTML files to p.applov.in and get QR codes to scan with the AppLovin Playable Preview app (iOS/Android).

- + + (no files)
+
+ +
@@ -175,13 +251,51 @@ function getHtml(): string {