This commit is contained in:
2026-05-23 16:57:24 +08:00
parent 9d6ed4b0a5
commit 6be55255b2
10 changed files with 44 additions and 12 deletions

View File

@@ -112,7 +112,7 @@ if ($Standalone) {
$exeName = "hpl-toolbox-$version.exe" $exeName = "hpl-toolbox-$version.exe"
$exeOut = Join-Path $distDir $exeName $exeOut = Join-Path $distDir $exeName
go build -ldflags="-s -w -H windowsgui" -trimpath -o $exeOut . go build -ldflags="-s -w -H windowsgui -X main.AppVersion=$version" -trimpath -o $exeOut .
if ($LASTEXITCODE -ne 0) { Write-Error "go build failed"; exit 1 } if ($LASTEXITCODE -ne 0) { Write-Error "go build failed"; exit 1 }
$summary += [pscustomobject]@{ $summary += [pscustomobject]@{

View File

@@ -2,7 +2,7 @@
"name": "hpl-toolbox", "name": "hpl-toolbox",
"displayName": "HPL Toolbox", "displayName": "HPL Toolbox",
"description": "Bundled tools: PLEC Upload, AppLovin Demo Upload, Base64 Asset Scanner, Daily Update. Local HTML Host.", "description": "Bundled tools: PLEC Upload, AppLovin Demo Upload, Base64 Asset Scanner, Daily Update. Local HTML Host.",
"version": "0.1.4", "version": "0.1.5",
"publisher": "hesukastro", "publisher": "hesukastro",
"license": "UNLICENSED", "license": "UNLICENSED",
"repository": { "repository": {

View File

@@ -13,7 +13,7 @@ export function activate(context: vscode.ExtensionContext) {
vscode.commands.registerCommand('hplToolbox.openBase64Scanner', () => openBase64Scanner(context)), vscode.commands.registerCommand('hplToolbox.openBase64Scanner', () => openBase64Scanner(context)),
vscode.commands.registerCommand('hplToolbox.openDailyUpdate', () => openDailyUpdate(context)), vscode.commands.registerCommand('hplToolbox.openDailyUpdate', () => openDailyUpdate(context)),
vscode.commands.registerCommand('hplToolbox.openSendToMobile', () => openSendToMobile(context)), vscode.commands.registerCommand('hplToolbox.openSendToMobile', () => openSendToMobile(context)),
vscode.window.registerWebviewViewProvider('hplToolbox.launcher', new LauncherViewProvider()) vscode.window.registerWebviewViewProvider('hplToolbox.launcher', new LauncherViewProvider(context))
); );
} }

View File

@@ -1,9 +1,12 @@
import * as vscode from 'vscode'; import * as vscode from 'vscode';
export class LauncherViewProvider implements vscode.WebviewViewProvider { export class LauncherViewProvider implements vscode.WebviewViewProvider {
constructor(private readonly context: vscode.ExtensionContext) {}
resolveWebviewView(view: vscode.WebviewView) { resolveWebviewView(view: vscode.WebviewView) {
view.webview.options = { enableScripts: true }; view.webview.options = { enableScripts: true };
view.webview.html = getHtml(); const version = this.context.extension.packageJSON.version as string;
view.webview.html = getHtml(version);
view.webview.onDidReceiveMessage((msg) => { view.webview.onDidReceiveMessage((msg) => {
if (msg?.type === 'open' && typeof msg.command === 'string') { if (msg?.type === 'open' && typeof msg.command === 'string') {
vscode.commands.executeCommand(msg.command); vscode.commands.executeCommand(msg.command);
@@ -12,7 +15,7 @@ export class LauncherViewProvider implements vscode.WebviewViewProvider {
} }
} }
function getHtml(): string { function getHtml(version: string): string {
return `<!DOCTYPE html> return `<!DOCTYPE html>
<html> <html>
<head> <head>
@@ -35,7 +38,7 @@ function getHtml(): string {
</style> </style>
</head> </head>
<body> <body>
<h3>HPL Toolbox</h3> <h3>HPL Toolbox ${version}</h3>
<button class="tool-btn" data-cmd="hplToolbox.openPlecUpload"> <button class="tool-btn" data-cmd="hplToolbox.openPlecUpload">
PLEC Upload PLEC Upload
<span class="tool-desc">Upload HTML to internal PLEC server</span> <span class="tool-desc">Upload HTML to internal PLEC server</span>

View File

@@ -234,8 +234,11 @@ function getHtml(): string {
function parseIterationName(filename) { function parseIterationName(filename) {
const base = filename.replace(/\\.html?$/i, ''); const base = filename.replace(/\\.html?$/i, '');
const match = base.match(/\\b(full|\\d+clk|\\d+s(?:ec)?)\\b/i); const tokens = base.split('_');
return match ? match[1].toLowerCase() : base; for (const t of tokens) {
if (/^(full|\\d+clk|\\d+s(?:ec)?)$/i.test(t)) return t.toLowerCase();
}
return base;
} }
const statusEl = document.getElementById('status'); const statusEl = document.getElementById('status');
const resultsEl = document.getElementById('results'); const resultsEl = document.getElementById('results');
@@ -292,6 +295,7 @@ function getHtml(): string {
const m = e.data; const m = e.data;
if (m.type === 'filesSelected') { if (m.type === 'filesSelected') {
const firstTr = tbody.querySelector('tr[data-id="' + m.rowId + '"]'); const firstTr = tbody.querySelector('tr[data-id="' + m.rowId + '"]');
const affected = [];
m.files.forEach(function(f, i) { m.files.forEach(function(f, i) {
let tr; let tr;
if (i === 0) { if (i === 0) {
@@ -305,7 +309,16 @@ function getHtml(): string {
tr.querySelector('[data-name]').textContent = f.name; tr.querySelector('[data-name]').textContent = f.name;
const iter = tr.querySelector('[data-iter]'); const iter = tr.querySelector('[data-iter]');
if (!iter.value) iter.value = parseIterationName(f.name); if (!iter.value) iter.value = parseIterationName(f.name);
affected.push(tr);
}); });
if (affected.length > 1) {
const iters = affected.map(r => r.querySelector('[data-iter]').value);
if (iters[0] !== '' && iters.every(n => n === iters[0])) {
affected.forEach((r, i) => {
r.querySelector('[data-iter]').value = String(i + 1).padStart(2, '0') + '_' + iters[0];
});
}
}
} else if (m.type === 'status') { } else if (m.type === 'status') {
statusEl.textContent = m.message; statusEl.textContent = m.message;
statusEl.className = ''; statusEl.className = '';

View File

@@ -17,6 +17,7 @@ const SharedCSS = `
.topbar a { color: #9cdcfe; text-decoration: none; padding: 4px 10px; border-radius: 3px; } .topbar a { color: #9cdcfe; text-decoration: none; padding: 4px 10px; border-radius: 3px; }
.topbar a:hover { background: #2a2d2e; } .topbar a:hover { background: #2a2d2e; }
.topbar a.active { background: #094771; color: #fff; } .topbar a.active { background: #094771; color: #fff; }
.topbar-version { margin-left: auto; font-size: 11px; opacity: 0.45; letter-spacing: 0.4px; }
.content { padding: 16px; max-width: 980px; margin: 0 auto; } .content { padding: 16px; max-width: 980px; margin: 0 auto; }
h2 { margin-top: 0; font-weight: 500; } h2 { margin-top: 0; font-weight: 500; }
input[type=text], input[type=date], select, textarea { input[type=text], input[type=date], select, textarea {
@@ -67,7 +68,7 @@ func Page(activePath, title, body string) string {
<title>` + title + ` — HPL Toolbox</title> <title>` + title + ` — HPL Toolbox</title>
<style>` + SharedCSS + `</style> <style>` + SharedCSS + `</style>
</head><body> </head><body>
<div class="topbar">` + tabs.String() + `</div> <div class="topbar">` + tabs.String() + `<span class="topbar-version">v` + AppVersion + `</span></div>
<div class="content">` + body + `</div> <div class="content">` + body + `</div>
</body></html>` </body></html>`
} }

View File

@@ -16,6 +16,8 @@ import (
webview "github.com/jchv/go-webview2" webview "github.com/jchv/go-webview2"
) )
var AppVersion = "dev"
var currentHwnd atomic.Uintptr var currentHwnd atomic.Uintptr
func setupFileLogging() { func setupFileLogging() {
@@ -68,7 +70,7 @@ func main() {
AutoFocus: true, AutoFocus: true,
DataPath: webviewTmp, DataPath: webviewTmp,
WindowOptions: webview.WindowOptions{ WindowOptions: webview.WindowOptions{
Title: "HPL Toolbox", Title: "HPL Toolbox " + AppVersion,
Width: 1100, Width: 1100,
Height: 720, Height: 720,
IconId: 1, IconId: 1,

View File

@@ -56,8 +56,11 @@ const resultsEl = document.getElementById('results');
function parseIterationName(filename) { function parseIterationName(filename) {
const base = filename.replace(/\.html?$/i, ''); const base = filename.replace(/\.html?$/i, '');
const match = base.match(/\b(full|\d+clk|\d+s(?:ec)?)\b/i); const tokens = base.split('_');
return match ? match[1].toLowerCase() : base; for (const t of tokens) {
if (/^(full|\d+clk|\d+s(?:ec)?)$/i.test(t)) return t.toLowerCase();
}
return base;
} }
function addRow() { function addRow() {
@@ -80,13 +83,23 @@ function addRow() {
const res = await fetch('/api/plec/pick', { method: 'POST' }); const res = await fetch('/api/plec/pick', { method: 'POST' });
const j = await res.json(); const j = await res.json();
if (j.files && j.files.length) { if (j.files && j.files.length) {
const affected = [];
j.files.forEach(function(f, i) { j.files.forEach(function(f, i) {
const target = i === 0 ? tr : (addRow(), tbody.lastElementChild); const target = i === 0 ? tr : (addRow(), tbody.lastElementChild);
target.querySelector('[data-path]').value = f.path; target.querySelector('[data-path]').value = f.path;
target.querySelector('[data-name]').textContent = f.name; target.querySelector('[data-name]').textContent = f.name;
const iter = target.querySelector('[data-iter]'); const iter = target.querySelector('[data-iter]');
if (!iter.value) iter.value = parseIterationName(f.name); if (!iter.value) iter.value = parseIterationName(f.name);
affected.push(target);
}); });
if (affected.length > 1) {
const iters = affected.map(r => r.querySelector('[data-iter]').value);
if (iters[0] !== '' && iters.every(n => n === iters[0])) {
affected.forEach((r, i) => {
r.querySelector('[data-iter]').value = String(i + 1).padStart(2, '0') + '_' + iters[0];
});
}
}
} }
}); });
tr.querySelector('.remove-btn').addEventListener('click', () => { tr.querySelector('.remove-btn').addEventListener('click', () => {