This commit is contained in:
2026-05-23 16:45:23 +08:00
parent 1336695068
commit 9d6ed4b0a5
8 changed files with 70 additions and 23 deletions

View File

@@ -2,7 +2,7 @@
"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.3",
"version": "0.1.4",
"publisher": "hesukastro",
"license": "UNLICENSED",
"repository": {

View File

@@ -20,6 +20,7 @@ export function openApplovinUpload(_context: vscode.ExtensionContext) {
canSelectMany: true,
filters: { HTML: ['html', 'htm'] },
openLabel: 'Select',
defaultUri: getPickerDefaultUri(),
});
if (picked && picked.length) {
panel.webview.postMessage({
@@ -163,6 +164,17 @@ async function handleUpload(panel: vscode.WebviewPanel, filePaths: string[]) {
panel.webview.postMessage({ type: 'done' });
}
function getPickerDefaultUri(): vscode.Uri | undefined {
const folders = vscode.workspace.workspaceFolders;
if (!folders || folders.length === 0) return undefined;
const root = folders[0].uri.fsPath;
const dist = path.join(root, 'dist');
if (fs.existsSync(dist) && fs.statSync(dist).isDirectory()) {
return vscode.Uri.file(dist);
}
return vscode.Uri.file(root);
}
function qrBaseName(name: string): string {
return (name || 'qr').replace(/\.html?$/i, '').replace(/[\\/:*?"<>|]/g, '_') || 'qr';
}

View File

@@ -17,18 +17,16 @@ export function openPlecUpload(_context: vscode.ExtensionContext) {
if (msg.type === 'pickFile') {
const picked = await vscode.window.showOpenDialog({
canSelectMany: false,
canSelectMany: true,
filters: { HTML: ['html', 'htm'] },
openLabel: 'Select',
defaultUri: getPickerDefaultUri(),
});
if (picked && picked[0]) {
const fp = picked[0].fsPath;
if (picked && picked.length) {
panel.webview.postMessage({
type: 'fileSelected',
type: 'filesSelected',
rowId: msg.rowId,
path: fp,
name: path.basename(fp),
files: picked.map(u => ({ path: u.fsPath, name: path.basename(u.fsPath) })),
});
}
return;
@@ -233,6 +231,12 @@ function getHtml(): string {
const vscode = acquireVsCodeApi();
let nextId = 1;
const tbody = document.querySelector('#rows tbody');
function parseIterationName(filename) {
const base = filename.replace(/\\.html?$/i, '');
const match = base.match(/\\b(full|\\d+clk|\\d+s(?:ec)?)\\b/i);
return match ? match[1].toLowerCase() : base;
}
const statusEl = document.getElementById('status');
const resultsEl = document.getElementById('results');
@@ -286,13 +290,22 @@ function getHtml(): string {
window.addEventListener('message', (e) => {
const m = e.data;
if (m.type === 'fileSelected') {
const tr = tbody.querySelector('tr[data-id="' + m.rowId + '"]');
if (m.type === 'filesSelected') {
const firstTr = tbody.querySelector('tr[data-id="' + m.rowId + '"]');
m.files.forEach(function(f, i) {
let tr;
if (i === 0) {
tr = firstTr;
} else {
addRow();
tr = tbody.lastElementChild;
}
if (!tr) return;
tr.querySelector('[data-path]').value = m.path;
tr.querySelector('[data-name]').textContent = m.name;
tr.querySelector('[data-path]').value = f.path;
tr.querySelector('[data-name]').textContent = f.name;
const iter = tr.querySelector('[data-iter]');
if (!iter.value) iter.value = m.name.replace(/\\.html?$/i, '');
if (!iter.value) iter.value = parseIterationName(f.name);
});
} else if (m.type === 'status') {
statusEl.textContent = m.message;
statusEl.className = '';

View File

@@ -236,11 +236,16 @@ function handle(m) {
}
func ApplovinPick(w http.ResponseWriter, r *http.Request) {
cfg := LoadConfig()
picked := PickFiles(
"Select HTML files",
[]FileFilter{{Name: "HTML", Extensions: []string{"html", "htm"}}},
true, "",
true, cfg.LastPickDir,
)
if len(picked) > 0 {
cfg.LastPickDir = filepath.Dir(picked[0])
_ = SaveConfig(cfg)
}
files := make([]map[string]string, 0, len(picked))
for _, p := range picked {
files = append(files, map[string]string{"path": p, "name": filepath.Base(p)})

View File

@@ -36,6 +36,7 @@ type AppConfig struct {
Applovin ApplovinConfig `json:"applovin"`
SendToMobile SendToMobileConfig `json:"sendToMobile"`
DailyUpdate DailyUpdateConfig `json:"dailyUpdate"`
LastPickDir string `json:"lastPickDir,omitempty"`
}
var configMu sync.Mutex

View File

@@ -54,6 +54,12 @@ const tbody = document.querySelector('#rows tbody');
const statusEl = document.getElementById('status');
const resultsEl = document.getElementById('results');
function parseIterationName(filename) {
const base = filename.replace(/\.html?$/i, '');
const match = base.match(/\b(full|\d+clk|\d+s(?:ec)?)\b/i);
return match ? match[1].toLowerCase() : base;
}
function addRow() {
const id = 'r' + (nextId++);
const tr = document.createElement('tr');
@@ -73,11 +79,14 @@ function addRow() {
tr.querySelector('.pick').addEventListener('click', async () => {
const res = await fetch('/api/plec/pick', { method: 'POST' });
const j = await res.json();
if (j.path) {
tr.querySelector('[data-path]').value = j.path;
tr.querySelector('[data-name]').textContent = j.name;
const iter = tr.querySelector('[data-iter]');
if (!iter.value) iter.value = j.name.replace(/\.html?$/i, '');
if (j.files && j.files.length) {
j.files.forEach(function(f, i) {
const target = i === 0 ? tr : (addRow(), tbody.lastElementChild);
target.querySelector('[data-path]').value = f.path;
target.querySelector('[data-name]').textContent = f.name;
const iter = target.querySelector('[data-iter]');
if (!iter.value) iter.value = parseIterationName(f.name);
});
}
});
tr.querySelector('.remove-btn').addEventListener('click', () => {
@@ -163,16 +172,23 @@ addRow();
}
func PlecPick(w http.ResponseWriter, r *http.Request) {
cfg := LoadConfig()
picked := PickFiles(
"Select HTML",
[]FileFilter{{Name: "HTML", Extensions: []string{"html", "htm"}}},
false, "",
true, cfg.LastPickDir,
)
if len(picked) == 0 {
writeJSON(w, map[string]any{"path": nil})
writeJSON(w, map[string]any{"files": []any{}})
return
}
writeJSON(w, map[string]any{"path": picked[0], "name": filepath.Base(picked[0])})
cfg.LastPickDir = filepath.Dir(picked[0])
_ = SaveConfig(cfg)
files := make([]map[string]string, 0, len(picked))
for _, p := range picked {
files = append(files, map[string]string{"path": p, "name": filepath.Base(p)})
}
writeJSON(w, map[string]any{"files": files})
}
type plecRow struct {