3 Commits
Author SHA1 Message Date
Momoko-Ayase 512a627066 web: recognize Android targets and point users at the CLI
Dropping an .apk/.apks/.xapk package or a .so library reported
"not recognized — will be skipped", which reads as "not protected"
when the real gap is that the Android pipeline (filesystem
orchestration in senbei-io) has no wasm build. These files now get an
explicit android pseudo-kind at staging time: the row explains that
the CLI handles them, and they neither enable the Unpack button nor
error out mid-run.
2026-09-10 09:32:58 +08:00
Momoko-Ayase a230c37281 web: stack file-row status below the name on narrow screens
On phone-width viewports the right-aligned status column shared a flex
line with a long file name and wrapped one word per line. Below 560px
the row now wraps: name and action icons keep the first line and the
status takes a full-width line underneath.
2026-09-10 09:29:23 +08:00
Momoko-Ayase 4f59e25652 ci: declare rustfmt/clippy components in rust-toolchain.toml
The 1.98.1 pin installs without rustfmt and clippy, so the fmt and
clippy jobs fail at the shim before running. Listing the components in
the toolchain file makes rustup auto-install them on every host,
including the CI runners that invoke cargo with no setup action.
2026-09-10 09:28:50 +08:00
4 changed files with 58 additions and 4 deletions
+4
View File
@@ -1,3 +1,7 @@
[toolchain]
channel = "1.98.1"
# CI invokes rustfmt/clippy through the rustup shim with no setup action, so
# the pinned toolchain must declare its components here — the runner images
# only preinstall them for their default toolchain.
components = ["rustfmt", "clippy"]
targets = ["x86_64-pc-windows-msvc", "wasm32-unknown-unknown"]
+31 -3
View File
@@ -50,6 +50,22 @@ const KIND_LABEL = {
'native-dll': 'protected native DLL',
'managed-dll': 'protected managed DLL',
metadata: 'il2cpp metadata',
'android-package':
'Android app package — the web build cannot unpack these yet; use the senbei CLI',
'android-so':
'Android AArch64 library — the web build cannot unpack these yet; use the senbei CLI',
};
// Android targets are recognized by extension so the row can explain the
// situation instead of reporting a protected file as unrecognized: the
// Android pipeline is filesystem orchestration (senbei-io) with no wasm
// build, so these files need the CLI. The pseudo-kinds are labels only —
// they never reach the worker.
const ANDROID_KIND = {
apk: 'android-package',
apks: 'android-package',
xapk: 'android-package',
so: 'android-so',
};
const COMPANION_SVG =
@@ -91,8 +107,13 @@ async function stageFiles(list) {
// the PE header fields); read a small slice, not the whole file.
const head = new Uint8Array(await file.slice(0, 65536).arrayBuffer());
// Companions are ciphertext fragments; detect() only makes sense on the
// base module, so skip it for `._` files.
const kind = file.name.endsWith('._') ? undefined : detect(head);
// base module, so skip it for `._` files. Android targets short-circuit
// detect() as well: an ELF/zip never classifies as a protected PE, and
// the row must carry the android pseudo-kind for its status line.
const ext = file.name.slice(file.name.lastIndexOf('.') + 1).toLowerCase();
const kind = file.name.endsWith('._')
? undefined
: (ANDROID_KIND[ext] ?? detect(head));
const old = files.get(file.name);
files.set(file.name, {
file,
@@ -284,7 +305,10 @@ function render() {
const unpackable = [...files].some(
([name, e]) =>
!name.endsWith('._') && e.kind !== undefined && e.state === 'staged',
!name.endsWith('._') &&
e.kind !== undefined &&
!e.kind.startsWith('android-') &&
e.state === 'staged',
);
unpackBtn.disabled = !unpackable;
actions.hidden = files.size === 0;
@@ -364,6 +388,10 @@ unpackBtn.addEventListener('click', async () => {
continue;
}
// Android rows are informational only (no wasm pipeline); their staged
// status line already says to use the CLI.
if (entry.kind.startsWith('android-')) continue;
entry.state = 'working';
render();
try {
+3 -1
View File
@@ -56,7 +56,9 @@
<p class="hint">
Protected <code>.exe</code> / <code>.dll</code> modules, optional
<code>._</code> companions, or an il2cpp
<code>global-metadata.dat</code>.
<code>global-metadata.dat</code>. Android packages
(<code>.apk</code> / <code>.apks</code> / <code>.xapk</code>) and
<code>.so</code> libraries are recognized but need the CLI.
</p>
<input type="file" id="picker" multiple hidden>
</div>
+20
View File
@@ -333,6 +333,26 @@ footer {
}
footer a { color: var(--dim); }
/* --- narrow screens --- */
/* On a narrow viewport the status column (flex: 1, right-aligned) is
squeezed by a long file name into a one-word-per-line vertical strip.
Stack the row instead: name + icons on the first line, the status on its
own full-width line below, left-aligned. */
@media (max-width: 560px) {
main { padding: 1.5rem 0.9rem 2.5rem; }
#dropzone { padding: 1.75rem 1rem; }
.file .row { flex-wrap: wrap; }
.file .name { flex: 1; min-width: 0; }
.file .status {
order: 6; /* after the download/remove icons */
flex-basis: 100%;
text-align: left;
}
}
/* --- animations --- */
@keyframes fadeIn {