html2apk 0.8.0 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +340 -4
- package/package.json +15 -4
- package/src/desktop/main.js +902 -0
- package/src/desktop/preload.js +1 -0
- package/src/desktop/renderer/index.html +12 -6
- package/src/desktop/renderer/renderer.js +1164 -59
- package/src/desktop/renderer/styles.css +199 -30
- package/src/runtime-manager/index.js +79 -17
- package/src/templates/cordova-plugin-html2apk-bridge/plugin.xml +50 -0
- package/src/templates/cordova-plugin-html2apk-bridge/src/android/FloatingIconService.java +33 -0
- package/src/templates/cordova-plugin-html2apk-bridge/src/android/Html2ApkBridge.java +5929 -403
- package/src/templates/cordova-plugin-html2apk-bridge/src/android/xml/html2apk_file_paths.xml +6 -0
- package/src/templates/cordova-plugin-html2apk-bridge/www/html2apk-bridge.js +882 -4
- package/src/templates/html2apk-early-bridge.js +879 -4
- package/src/templates/html2apk-runtime-console.js +321 -29
- package/examples/minimal/dist/MeuApp-1.0.0-debug.apk +0 -0
- package/examples/minimal/dist/MeuApp-1.0.0-release.aab +0 -0
|
@@ -16,6 +16,11 @@
|
|
|
16
16
|
var consoleList = null;
|
|
17
17
|
var networkList = null;
|
|
18
18
|
var badge = null;
|
|
19
|
+
var consoleCount = null;
|
|
20
|
+
var networkCount = null;
|
|
21
|
+
var errorCount = null;
|
|
22
|
+
var copyAllButton = null;
|
|
23
|
+
var copyOnlyErrorsButton = null;
|
|
19
24
|
var activeTab = "console";
|
|
20
25
|
var opened = false;
|
|
21
26
|
var dragMoved = false;
|
|
@@ -29,6 +34,9 @@
|
|
|
29
34
|
"cancelarNotificacao", "cancelNotification",
|
|
30
35
|
"lanterna", "flashlight",
|
|
31
36
|
"alternarLanterna", "toggleFlashlight",
|
|
37
|
+
"tirarFoto", "takePhoto", "capturePhoto",
|
|
38
|
+
"capturarVideo", "captureVideo",
|
|
39
|
+
"escanearQRCode", "scanQRCode", "scanQrCode",
|
|
32
40
|
"ouvirMic", "listenMic", "startMic",
|
|
33
41
|
"pararMic", "stopMic",
|
|
34
42
|
"solicitarPermissaoCamera", "requestCameraPermission",
|
|
@@ -36,9 +44,74 @@
|
|
|
36
44
|
"solicitarPermissaoNotificacoes", "requestNotificationPermission",
|
|
37
45
|
"escolherArquivo", "pickFile",
|
|
38
46
|
"escolherImagem", "pickImage",
|
|
47
|
+
"escolherImagens", "pickImages",
|
|
48
|
+
"escolherPasta", "pickFolder",
|
|
49
|
+
"salvarArquivo", "saveFile",
|
|
50
|
+
"lerArquivo", "readFile", "readStoredFile",
|
|
51
|
+
"excluirArquivo", "deleteFile", "removeFile",
|
|
52
|
+
"listarArquivos", "listFiles",
|
|
53
|
+
"abrirArquivo", "openFile",
|
|
54
|
+
"compartilharArquivo", "shareFile",
|
|
55
|
+
"compartilhar", "share",
|
|
56
|
+
"compartilharApp", "shareApp", "share_me",
|
|
57
|
+
"aguardar", "loading",
|
|
58
|
+
"aoReceberCompartilhamento", "onShareReceived",
|
|
59
|
+
"obterCompartilhamentoInicial", "getInitialShare",
|
|
60
|
+
"procurarBT", "scanBluetooth", "procurarBluetooth", "buscarBT",
|
|
61
|
+
"conectarBT", "connectBluetooth", "conectarBluetooth",
|
|
62
|
+
"enviarBT", "sendBluetooth",
|
|
63
|
+
"aoConectarBT", "onBluetoothConnect",
|
|
64
|
+
"aoReceberDadosBT", "onBluetoothData",
|
|
65
|
+
"aoDarErroBT", "onBluetoothError",
|
|
66
|
+
"procurarWiFi", "scanWiFi", "scanWifi",
|
|
67
|
+
"conectarWiFi", "connectWiFi", "connectWifi",
|
|
68
|
+
"enviarWiFi", "sendWiFi", "sendWifi",
|
|
69
|
+
"aoConectarWiFi", "onWiFiConnect", "onWifiConnect",
|
|
70
|
+
"aoReceberDadosWiFi", "onWiFiData", "onWifiData",
|
|
71
|
+
"aoDarErroWiFi", "onWiFiError", "onWifiError",
|
|
72
|
+
"ocr", "recognizeText", "textFromImage",
|
|
73
|
+
"falar", "speak", "textToSpeech",
|
|
74
|
+
"pararFala", "stopSpeaking",
|
|
75
|
+
"ouvir", "recognizeSpeech", "speechToText",
|
|
76
|
+
"baixarArquivo", "downloadFile",
|
|
77
|
+
"baixarBase64", "downloadBase64", "downloadFromBase64",
|
|
78
|
+
"baixarArquivoLocal", "downloadLocalFile", "downloadFromFile",
|
|
79
|
+
"aoConectarUSB", "onUSBConnect", "onUsbConnect",
|
|
80
|
+
"aoDesconectarUSB", "onUSBDisconnect", "onUsbDisconnect",
|
|
81
|
+
"aoConectarFone", "onHeadphoneConnect",
|
|
82
|
+
"aoDesconectarFone", "onHeadphoneDisconnect",
|
|
83
|
+
"aoMudarVolume", "onVolumeChange",
|
|
84
|
+
"aoAbrirTeclado", "onKeyboardOpen",
|
|
85
|
+
"aoFecharTeclado", "onKeyboardClose",
|
|
86
|
+
"aoSacudirCelular", "onPhoneShake", "onShake",
|
|
87
|
+
"aoVirarCelularParaBaixo", "onPhoneFaceDown",
|
|
88
|
+
"aoAproximarObjeto", "onProximityNear",
|
|
89
|
+
"aoTirarPrint", "onScreenshot",
|
|
90
|
+
"aoMudarOrientacao", "onOrientationChange",
|
|
91
|
+
"aoNFC", "onNFC", "onNfc",
|
|
92
|
+
"aoReceberNotificacao", "onNotificationReceived",
|
|
93
|
+
"definirPapelParede", "setWallpaper", "setPhoneWallpaper",
|
|
94
|
+
"infoPapelParede", "wallpaperInfo",
|
|
95
|
+
"abrirConfiguracaoPapelParede", "openWallpaperSettings",
|
|
96
|
+
"capturarTela", "tirarPrint", "captureScreen", "takeScreenshot", "screenshot",
|
|
97
|
+
"volumeAtual", "currentVolume", "getVolume",
|
|
98
|
+
"definirVolume", "setVolume",
|
|
99
|
+
"aumentarVolume", "increaseVolume",
|
|
100
|
+
"diminuirVolume", "decreaseVolume",
|
|
101
|
+
"configurarIconeFlutuante", "configureFloatingIcon",
|
|
102
|
+
"definirOpacidadeIconeFlutuante", "setFloatingIconOpacity",
|
|
103
|
+
"minimizarApp", "minimizeApp",
|
|
104
|
+
"fecharApp", "closeApp", "exitApp",
|
|
39
105
|
"abrirNoApp", "openInApp",
|
|
40
106
|
"abrirForaDoApp", "openOutsideApp",
|
|
41
107
|
"abrirUrl", "openUrl",
|
|
108
|
+
"obterLocalizacao", "getLocation",
|
|
109
|
+
"acompanharLocalizacao", "watchLocation",
|
|
110
|
+
"pararLocalizacao", "stopLocationWatch",
|
|
111
|
+
"autenticarBiometria", "authenticateBiometric",
|
|
112
|
+
"salvarSeguro", "saveSecure", "secureSet",
|
|
113
|
+
"lerSeguro", "readSecure", "secureGet",
|
|
114
|
+
"removerSeguro", "deleteSecure", "removeSecure",
|
|
42
115
|
"vibrar", "vibrate",
|
|
43
116
|
"toast",
|
|
44
117
|
"statusPermissoes", "permissionStatus",
|
|
@@ -100,6 +173,8 @@
|
|
|
100
173
|
function renderEntry(entry, target) {
|
|
101
174
|
var item;
|
|
102
175
|
var meta;
|
|
176
|
+
var label;
|
|
177
|
+
var time;
|
|
103
178
|
var body;
|
|
104
179
|
|
|
105
180
|
if (!target) {
|
|
@@ -111,11 +186,17 @@
|
|
|
111
186
|
|
|
112
187
|
meta = document.createElement("div");
|
|
113
188
|
meta.className = "html2apk-console-meta";
|
|
114
|
-
|
|
189
|
+
label = document.createElement("span");
|
|
190
|
+
label.className = "html2apk-console-kind";
|
|
191
|
+
label.textContent = entry.kind.toUpperCase();
|
|
192
|
+
time = document.createElement("time");
|
|
193
|
+
time.textContent = entry.time;
|
|
115
194
|
|
|
116
195
|
body = document.createElement("pre");
|
|
117
196
|
body.textContent = entry.message;
|
|
118
197
|
|
|
198
|
+
meta.appendChild(label);
|
|
199
|
+
meta.appendChild(time);
|
|
119
200
|
item.appendChild(meta);
|
|
120
201
|
item.appendChild(body);
|
|
121
202
|
target.appendChild(item);
|
|
@@ -124,7 +205,19 @@
|
|
|
124
205
|
target.removeChild(target.firstChild);
|
|
125
206
|
}
|
|
126
207
|
|
|
208
|
+
scrollListToBottom(target);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
function scrollListToBottom(target) {
|
|
212
|
+
if (!target) {
|
|
213
|
+
return;
|
|
214
|
+
}
|
|
127
215
|
target.scrollTop = target.scrollHeight;
|
|
216
|
+
if (typeof window.requestAnimationFrame === "function") {
|
|
217
|
+
window.requestAnimationFrame(function () {
|
|
218
|
+
target.scrollTop = target.scrollHeight;
|
|
219
|
+
});
|
|
220
|
+
}
|
|
128
221
|
}
|
|
129
222
|
|
|
130
223
|
function renderNetworkEntry(entry) {
|
|
@@ -164,23 +257,32 @@
|
|
|
164
257
|
|
|
165
258
|
function updateBadge() {
|
|
166
259
|
var count;
|
|
167
|
-
if (!badge) {
|
|
168
|
-
return;
|
|
169
|
-
}
|
|
170
260
|
count = entries.filter(function (entry) {
|
|
171
261
|
return entry.kind === "error";
|
|
172
262
|
}).length + networkEntries.filter(function (entry) {
|
|
173
263
|
return !entry.ok;
|
|
174
264
|
}).length;
|
|
175
|
-
|
|
176
|
-
|
|
265
|
+
if (badge) {
|
|
266
|
+
badge.textContent = count ? String(count) : "";
|
|
267
|
+
badge.style.display = count ? "inline-flex" : "none";
|
|
268
|
+
}
|
|
269
|
+
if (consoleCount) {
|
|
270
|
+
consoleCount.textContent = String(entries.length);
|
|
271
|
+
}
|
|
272
|
+
if (networkCount) {
|
|
273
|
+
networkCount.textContent = String(networkEntries.length);
|
|
274
|
+
}
|
|
275
|
+
if (errorCount) {
|
|
276
|
+
errorCount.textContent = String(count);
|
|
277
|
+
}
|
|
177
278
|
}
|
|
178
279
|
|
|
179
280
|
function add(kind, message, detail) {
|
|
281
|
+
var hasDetail = arguments.length > 2 && typeof detail !== "undefined";
|
|
180
282
|
var entry = {
|
|
181
283
|
kind: kind || "info",
|
|
182
284
|
time: now(),
|
|
183
|
-
message:
|
|
285
|
+
message: hasDetail ? String(message || "") + "\n" + short(detail, MAX_DETAIL) : String(message || "")
|
|
184
286
|
};
|
|
185
287
|
|
|
186
288
|
keepEntry(entries, entry);
|
|
@@ -204,6 +306,133 @@
|
|
|
204
306
|
}
|
|
205
307
|
}
|
|
206
308
|
|
|
309
|
+
function consoleEntryText(entry) {
|
|
310
|
+
return "[" + (entry.time || "") + "] " + String(entry.kind || "info").toUpperCase() + "\n" + String(entry.message || "");
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
function networkEntryText(entry) {
|
|
314
|
+
var status = entry.status || "ERR";
|
|
315
|
+
var method = entry.method || "GET";
|
|
316
|
+
var title = method + " " + entry.url + " -> " + status + " (" + (entry.durationMs || 0) + "ms)";
|
|
317
|
+
var detail = {
|
|
318
|
+
type: entry.type,
|
|
319
|
+
ok: entry.ok,
|
|
320
|
+
status: entry.status,
|
|
321
|
+
statusText: entry.statusText,
|
|
322
|
+
durationMs: entry.durationMs,
|
|
323
|
+
requestBody: entry.requestBody,
|
|
324
|
+
responseBody: entry.responseBody,
|
|
325
|
+
error: entry.error
|
|
326
|
+
};
|
|
327
|
+
|
|
328
|
+
return "[" + (entry.time || "") + "] " + (entry.ok ? "NETWORK" : "ERROR") + "\n" + title + "\n" + short(detail, MAX_DETAIL);
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
function runtimeConsoleText(onlyErrors) {
|
|
332
|
+
var output = [];
|
|
333
|
+
entries.forEach(function (entry) {
|
|
334
|
+
if (!onlyErrors || entry.kind === "error") {
|
|
335
|
+
output.push(consoleEntryText(entry));
|
|
336
|
+
}
|
|
337
|
+
});
|
|
338
|
+
networkEntries.forEach(function (entry) {
|
|
339
|
+
if (!onlyErrors || !entry.ok) {
|
|
340
|
+
output.push(networkEntryText(entry));
|
|
341
|
+
}
|
|
342
|
+
});
|
|
343
|
+
if (!output.length) {
|
|
344
|
+
return onlyErrors ? "Nenhum erro registrado." : "Console vazio.";
|
|
345
|
+
}
|
|
346
|
+
return output.join("\n\n");
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
function fallbackCopyText(text) {
|
|
350
|
+
return new Promise(function (resolve, reject) {
|
|
351
|
+
var target = document.body || document.documentElement;
|
|
352
|
+
var textarea;
|
|
353
|
+
var copied = false;
|
|
354
|
+
|
|
355
|
+
if (!target || !document.createElement) {
|
|
356
|
+
reject(new Error("Clipboard indisponivel."));
|
|
357
|
+
return;
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
textarea = document.createElement("textarea");
|
|
361
|
+
textarea.value = text;
|
|
362
|
+
textarea.setAttribute("readonly", "readonly");
|
|
363
|
+
textarea.style.position = "fixed";
|
|
364
|
+
textarea.style.left = "-9999px";
|
|
365
|
+
textarea.style.top = "0";
|
|
366
|
+
textarea.style.opacity = "0";
|
|
367
|
+
target.appendChild(textarea);
|
|
368
|
+
textarea.focus();
|
|
369
|
+
textarea.select();
|
|
370
|
+
|
|
371
|
+
try {
|
|
372
|
+
copied = document.execCommand("copy");
|
|
373
|
+
} catch (error) {
|
|
374
|
+
copied = false;
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
target.removeChild(textarea);
|
|
378
|
+
if (copied) {
|
|
379
|
+
resolve();
|
|
380
|
+
} else {
|
|
381
|
+
reject(new Error("Nao foi possivel copiar."));
|
|
382
|
+
}
|
|
383
|
+
});
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
function copyTextToClipboard(text) {
|
|
387
|
+
if (typeof navigator !== "undefined" && navigator.clipboard && typeof navigator.clipboard.writeText === "function") {
|
|
388
|
+
return navigator.clipboard.writeText(text).catch(function () {
|
|
389
|
+
return fallbackCopyText(text);
|
|
390
|
+
});
|
|
391
|
+
}
|
|
392
|
+
return fallbackCopyText(text);
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
function flashActionButton(target, label) {
|
|
396
|
+
var original;
|
|
397
|
+
if (!target) {
|
|
398
|
+
return;
|
|
399
|
+
}
|
|
400
|
+
original = target.getAttribute("data-original-label") || target.textContent;
|
|
401
|
+
target.setAttribute("data-original-label", original);
|
|
402
|
+
target.textContent = label;
|
|
403
|
+
target.disabled = true;
|
|
404
|
+
setTimeout(function () {
|
|
405
|
+
target.textContent = original;
|
|
406
|
+
target.disabled = false;
|
|
407
|
+
}, 1200);
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
function copyConsole() {
|
|
411
|
+
var text = runtimeConsoleText(false);
|
|
412
|
+
return copyTextToClipboard(text).then(function () {
|
|
413
|
+
add("info", "Console copiado.");
|
|
414
|
+
flashActionButton(copyAllButton, "Copiado");
|
|
415
|
+
return { ok: true, copied: "console" };
|
|
416
|
+
}, function (error) {
|
|
417
|
+
add("error", "Falha ao copiar console", error);
|
|
418
|
+
flashActionButton(copyAllButton, "Falhou");
|
|
419
|
+
return { ok: false, copied: "console", message: error && error.message ? error.message : String(error) };
|
|
420
|
+
});
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
function copyErrors() {
|
|
424
|
+
var text = runtimeConsoleText(true);
|
|
425
|
+
return copyTextToClipboard(text).then(function () {
|
|
426
|
+
add("info", "Erros copiados.");
|
|
427
|
+
flashActionButton(copyOnlyErrorsButton, "Copiado");
|
|
428
|
+
return { ok: true, copied: "errors" };
|
|
429
|
+
}, function (error) {
|
|
430
|
+
add("error", "Falha ao copiar erros", error);
|
|
431
|
+
flashActionButton(copyOnlyErrorsButton, "Falhou");
|
|
432
|
+
return { ok: false, copied: "errors", message: error && error.message ? error.message : String(error) };
|
|
433
|
+
});
|
|
434
|
+
}
|
|
435
|
+
|
|
207
436
|
function setActiveTab(tab) {
|
|
208
437
|
activeTab = tab === "network" ? "network" : "console";
|
|
209
438
|
if (!modal) {
|
|
@@ -218,6 +447,7 @@
|
|
|
218
447
|
if (networkList) {
|
|
219
448
|
networkList.classList.toggle("active", activeTab === "network");
|
|
220
449
|
}
|
|
450
|
+
updateBadge();
|
|
221
451
|
}
|
|
222
452
|
|
|
223
453
|
function clearActiveTab() {
|
|
@@ -358,7 +588,14 @@
|
|
|
358
588
|
var tabs;
|
|
359
589
|
var consoleTab;
|
|
360
590
|
var networkTab;
|
|
591
|
+
var summary;
|
|
592
|
+
var consoleStat;
|
|
593
|
+
var networkStat;
|
|
594
|
+
var errorStat;
|
|
595
|
+
var controls;
|
|
361
596
|
var actions;
|
|
597
|
+
var copyButton;
|
|
598
|
+
var copyErrorsButton;
|
|
362
599
|
var clearButton;
|
|
363
600
|
var closeButton;
|
|
364
601
|
var body;
|
|
@@ -369,20 +606,23 @@
|
|
|
369
606
|
|
|
370
607
|
style = document.createElement("style");
|
|
371
608
|
style.textContent = [
|
|
372
|
-
".html2apk-console-button{position:fixed;right:14px;bottom:14px;z-index:2147483640;width:
|
|
373
|
-
".html2apk-console-button img{width:100%;height:100%;object-fit:cover;border-radius:999px;display:block}.html2apk-console-button.fallback:before{content:'Console';font:800 10px system-ui,Segoe UI,Arial}",
|
|
374
|
-
".html2apk-console-badge{position:absolute;right:-3px;top:-3px;display:none;align-items:center;justify-content:center;min-width:
|
|
375
|
-
".html2apk-console-modal{position:fixed;inset:0;z-index:2147483641;display:none;background:rgba(
|
|
609
|
+
".html2apk-console-button{position:fixed;right:14px;bottom:14px;z-index:2147483640;width:58px;height:58px;border:0;border-radius:999px;background:#126fff;color:#fff;padding:0;box-shadow:0 16px 36px rgba(18,111,255,.34),0 8px 24px rgba(0,0,0,.28);touch-action:none}",
|
|
610
|
+
".html2apk-console-button:active{transform:scale(.98)}.html2apk-console-button img{width:100%;height:100%;object-fit:cover;border-radius:999px;display:block}.html2apk-console-button.fallback:before{content:'Console';font:800 10px system-ui,Segoe UI,Arial}",
|
|
611
|
+
".html2apk-console-badge{position:absolute;right:-3px;top:-3px;display:none;align-items:center;justify-content:center;min-width:21px;height:21px;border-radius:999px;background:#ef4444;color:#fff;font:900 11px system-ui,Segoe UI,Arial;border:2px solid #fff}",
|
|
612
|
+
".html2apk-console-modal{position:fixed;inset:0;z-index:2147483641;display:none;background:rgba(5,10,20,.56);padding:12px;font-family:system-ui,Segoe UI,Arial}",
|
|
376
613
|
".html2apk-console-modal.open{display:flex;align-items:flex-end;justify-content:center}",
|
|
377
|
-
".html2apk-console-panel{width:min(
|
|
378
|
-
".html2apk-console-header{display:grid;grid-template-columns:
|
|
379
|
-
".html2apk-console-
|
|
380
|
-
".html2apk-console-
|
|
381
|
-
".html2apk-console-
|
|
382
|
-
".html2apk-console-
|
|
383
|
-
".html2apk-console-
|
|
384
|
-
".html2apk-console-
|
|
385
|
-
".html2apk-console-
|
|
614
|
+
".html2apk-console-panel{width:min(1040px,calc(100vw - 18px));max-height:min(82vh,760px);background:#0b1020;color:#edf4ff;border:1px solid rgba(148,163,184,.25);border-radius:16px;box-shadow:0 28px 90px rgba(0,0,0,.5);overflow:hidden}",
|
|
615
|
+
".html2apk-console-header{display:grid;grid-template-columns:minmax(0,1fr);gap:10px;padding:12px;border-bottom:1px solid rgba(148,163,184,.22);background:linear-gradient(180deg,#111827,#0f172a);touch-action:none}",
|
|
616
|
+
".html2apk-console-title{display:flex;align-items:center;justify-content:space-between;gap:10px;min-width:0}.html2apk-console-title strong{font-size:15px;line-height:1.2}.html2apk-console-subtitle{display:block;color:#94a3b8;font-size:11px;font-weight:700;margin-top:2px}",
|
|
617
|
+
".html2apk-console-summary{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:8px}.html2apk-console-stat{border:1px solid rgba(148,163,184,.22);background:rgba(15,23,42,.8);border-radius:10px;padding:8px}.html2apk-console-stat span{display:block;color:#94a3b8;font-size:10px;font-weight:900;text-transform:uppercase;letter-spacing:.04em}.html2apk-console-stat strong{display:block;margin-top:2px;font-size:18px;line-height:1;color:#f8fafc}",
|
|
618
|
+
".html2apk-console-controls{display:grid;grid-template-columns:minmax(0,1fr);gap:8px}.html2apk-console-tabs,.html2apk-console-actions{display:flex;gap:8px;flex-wrap:wrap}.html2apk-console-actions{justify-content:flex-start}",
|
|
619
|
+
".html2apk-console-header button{border:1px solid rgba(148,163,184,.28);background:#1e293b;color:#e2e8f0;border-radius:9px;padding:8px 10px;font:800 12px system-ui,Segoe UI,Arial}",
|
|
620
|
+
".html2apk-console-header button.active{background:#126fff;border-color:#60a5fa;color:#fff}.html2apk-console-header button:hover{border-color:#93c5fd}.html2apk-console-header button:disabled{opacity:.72}",
|
|
621
|
+
".html2apk-console-body{height:min(58vh,560px);background:#050816;overflow:hidden}.html2apk-console-list{display:none;height:100%;box-sizing:border-box;overflow:auto;padding:10px 10px 30px;scroll-padding-bottom:30px;overscroll-behavior:contain}.html2apk-console-list:after{content:'';display:block;height:14px}.html2apk-console-list.active{display:block}",
|
|
622
|
+
".html2apk-console-entry{border:1px solid rgba(148,163,184,.16);border-left:4px solid #64748b;border-radius:11px;padding:9px 10px;margin-bottom:8px;background:#0f172a}",
|
|
623
|
+
".html2apk-console-entry.error{border-left-color:#ef4444;background:#1b1117}.html2apk-console-entry.warn{border-left-color:#f59e0b;background:#1a1610}.html2apk-console-entry.call,.html2apk-console-entry.network{border-left-color:#60a5fa}.html2apk-console-entry.ok{border-left-color:#22c55e;background:#0f1a15}.html2apk-console-entry.info{border-left-color:#94a3b8}",
|
|
624
|
+
".html2apk-console-meta{display:flex;align-items:center;justify-content:space-between;gap:10px;color:#94a3b8;font-size:11px;font-weight:900;margin-bottom:6px}.html2apk-console-kind{color:#e2e8f0}.html2apk-console-entry pre{white-space:pre-wrap;word-break:break-word;margin:0;color:#dbeafe;font:12px ui-monospace,SFMono-Regular,Consolas,monospace;line-height:1.48}",
|
|
625
|
+
"@media (min-width:760px){.html2apk-console-header{grid-template-columns:minmax(170px,.8fr) minmax(220px,1fr) minmax(300px,1.2fr);align-items:center}.html2apk-console-controls{grid-template-columns:minmax(0,.9fr) minmax(0,1.1fr)}.html2apk-console-actions{justify-content:flex-end}.html2apk-console-summary{grid-template-columns:repeat(3,minmax(80px,1fr))}}"
|
|
386
626
|
].join("");
|
|
387
627
|
document.head.appendChild(style);
|
|
388
628
|
|
|
@@ -422,11 +662,49 @@
|
|
|
422
662
|
|
|
423
663
|
header = document.createElement("div");
|
|
424
664
|
header.className = "html2apk-console-header";
|
|
425
|
-
title = document.createElement("
|
|
426
|
-
title.
|
|
665
|
+
title = document.createElement("div");
|
|
666
|
+
title.className = "html2apk-console-title";
|
|
667
|
+
title.innerHTML = "<div><strong>Console html2apk</strong><span class=\"html2apk-console-subtitle\">Logs, erros, rede e chamadas nativas</span></div>";
|
|
668
|
+
|
|
669
|
+
summary = document.createElement("div");
|
|
670
|
+
summary.className = "html2apk-console-summary";
|
|
671
|
+
consoleStat = document.createElement("div");
|
|
672
|
+
consoleStat.className = "html2apk-console-stat";
|
|
673
|
+
consoleStat.innerHTML = "<span>Console</span>";
|
|
674
|
+
consoleCount = document.createElement("strong");
|
|
675
|
+
consoleCount.textContent = "0";
|
|
676
|
+
consoleStat.appendChild(consoleCount);
|
|
677
|
+
networkStat = document.createElement("div");
|
|
678
|
+
networkStat.className = "html2apk-console-stat";
|
|
679
|
+
networkStat.innerHTML = "<span>Rede</span>";
|
|
680
|
+
networkCount = document.createElement("strong");
|
|
681
|
+
networkCount.textContent = "0";
|
|
682
|
+
networkStat.appendChild(networkCount);
|
|
683
|
+
errorStat = document.createElement("div");
|
|
684
|
+
errorStat.className = "html2apk-console-stat";
|
|
685
|
+
errorStat.innerHTML = "<span>Erros</span>";
|
|
686
|
+
errorCount = document.createElement("strong");
|
|
687
|
+
errorCount.textContent = "0";
|
|
688
|
+
errorStat.appendChild(errorCount);
|
|
689
|
+
summary.appendChild(consoleStat);
|
|
690
|
+
summary.appendChild(networkStat);
|
|
691
|
+
summary.appendChild(errorStat);
|
|
692
|
+
|
|
693
|
+
controls = document.createElement("div");
|
|
694
|
+
controls.className = "html2apk-console-controls";
|
|
427
695
|
|
|
428
696
|
tabs = document.createElement("div");
|
|
429
697
|
tabs.className = "html2apk-console-tabs";
|
|
698
|
+
controls.appendChild(tabs);
|
|
699
|
+
|
|
700
|
+
closeButton = document.createElement("button");
|
|
701
|
+
closeButton.type = "button";
|
|
702
|
+
closeButton.textContent = "Fechar";
|
|
703
|
+
title.appendChild(closeButton);
|
|
704
|
+
|
|
705
|
+
header.appendChild(title);
|
|
706
|
+
header.appendChild(summary);
|
|
707
|
+
header.appendChild(controls);
|
|
430
708
|
consoleTab = document.createElement("button");
|
|
431
709
|
consoleTab.type = "button";
|
|
432
710
|
consoleTab.textContent = "Console";
|
|
@@ -446,16 +724,25 @@
|
|
|
446
724
|
|
|
447
725
|
actions = document.createElement("div");
|
|
448
726
|
actions.className = "html2apk-console-actions";
|
|
727
|
+
copyButton = document.createElement("button");
|
|
728
|
+
copyButton.type = "button";
|
|
729
|
+
copyButton.textContent = "Copiar console";
|
|
730
|
+
copyButton.addEventListener("click", copyConsole);
|
|
731
|
+
copyAllButton = copyButton;
|
|
732
|
+
copyErrorsButton = document.createElement("button");
|
|
733
|
+
copyErrorsButton.type = "button";
|
|
734
|
+
copyErrorsButton.textContent = "Copiar apenas erros";
|
|
735
|
+
copyErrorsButton.addEventListener("click", copyErrors);
|
|
736
|
+
copyOnlyErrorsButton = copyErrorsButton;
|
|
449
737
|
clearButton = document.createElement("button");
|
|
450
738
|
clearButton.type = "button";
|
|
451
739
|
clearButton.textContent = "Limpar";
|
|
452
740
|
clearButton.addEventListener("click", clearActiveTab);
|
|
453
|
-
closeButton = document.createElement("button");
|
|
454
|
-
closeButton.type = "button";
|
|
455
|
-
closeButton.textContent = "Fechar";
|
|
456
741
|
closeButton.addEventListener("click", closeConsole);
|
|
742
|
+
actions.appendChild(copyButton);
|
|
743
|
+
actions.appendChild(copyErrorsButton);
|
|
457
744
|
actions.appendChild(clearButton);
|
|
458
|
-
|
|
745
|
+
controls.appendChild(actions);
|
|
459
746
|
|
|
460
747
|
body = document.createElement("div");
|
|
461
748
|
body.className = "html2apk-console-body";
|
|
@@ -466,9 +753,6 @@
|
|
|
466
753
|
body.appendChild(consoleList);
|
|
467
754
|
body.appendChild(networkList);
|
|
468
755
|
|
|
469
|
-
header.appendChild(title);
|
|
470
|
-
header.appendChild(tabs);
|
|
471
|
-
header.appendChild(actions);
|
|
472
756
|
panel.appendChild(header);
|
|
473
757
|
panel.appendChild(body);
|
|
474
758
|
modal.appendChild(panel);
|
|
@@ -766,6 +1050,14 @@
|
|
|
766
1050
|
open: openConsole,
|
|
767
1051
|
close: closeConsole,
|
|
768
1052
|
clear: clearActiveTab,
|
|
1053
|
+
copy: copyConsole,
|
|
1054
|
+
copyErrors: copyErrors,
|
|
1055
|
+
text: function (onlyErrors) {
|
|
1056
|
+
return runtimeConsoleText(!!onlyErrors);
|
|
1057
|
+
},
|
|
1058
|
+
errorText: function () {
|
|
1059
|
+
return runtimeConsoleText(true);
|
|
1060
|
+
},
|
|
769
1061
|
log: add,
|
|
770
1062
|
network: addNetwork,
|
|
771
1063
|
entries: function () {
|
|
Binary file
|
|
Binary file
|