Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -196,9 +196,11 @@ private void populateCards() {

// K2GO-445: the group's members (the IDE, its add-ons, its build assets), same filtering as the
// grid. If all are filtered out, drop the empty group tile too.
// K2GO-443: each member carries its own glyph (they shared the code "</>" before): Code on the Go
// = code, Add-ons = extension (puzzle), Build assets = box. Drives the row AND the action-sheet header.
codeDevMembers.add(new Card("code", getString(R.string.k2go_card_code), false, R.drawable.ic_card_code));
codeDevMembers.add(new Card("code-addons", getString(R.string.k2go_card_code_addons), false, R.drawable.ic_card_code));
codeDevMembers.add(new Card("code-assets", getString(R.string.k2go_card_code_assets), false, R.drawable.ic_card_code));
codeDevMembers.add(new Card("code-addons", getString(R.string.k2go_card_code_addons), false, R.drawable.ic_card_addons));
codeDevMembers.add(new Card("code-assets", getString(R.string.k2go_card_code_assets), false, R.drawable.ic_card_assets));
filterHidden(codeDevMembers);
filterHidden(cards);
if (codeDevMembers.isEmpty()) {
Expand Down Expand Up @@ -500,6 +502,21 @@ private void openCodeDevSheet() {
TextView status = new TextView(ctx);
status.setTextAppearance(com.google.android.material.R.style.TextAppearance_Material3_BodySmall);
rowv.addView(status);
// K2GO-443: per-member overflow menu, between the status and the open arrow (status -> menu ->
// arrow). It opens the member's action sheet (Open / About / Update <x> / Hide) -- the only way
// to reach "Update" for a grouped member, since a row tap routes a ready member straight to its
// content. Material more_vert vector (not a text glyph) in a 48dp touch target, tinted like the
// other sheet icons.
ImageView menu = new ImageView(ctx);
menu.setImageResource(R.drawable.ic_more_vert);
menu.setColorFilter(ContextCompat.getColor(ctx, R.color.k2go_muted));
menu.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
menu.setContentDescription(getString(R.string.k2go_sheet_more));
menu.setClickable(true); menu.setFocusable(true);
menu.setOnClickListener(v -> { dlg.dismiss(); openSheet(m); });
LinearLayout.LayoutParams mlp = new LinearLayout.LayoutParams(dpx(48), dpx(48));
mlp.leftMargin = dpx(4);
rowv.addView(menu, mlp);
TextView chev = new TextView(ctx);
chev.setText("›"); chev.setTextSize(18);
chev.setTextColor(ContextCompat.getColor(ctx, R.color.k2go_muted));
Expand Down
4 changes: 4 additions & 0 deletions controller/app/src/main/res/drawable/ic_card_addons.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<!-- Material Symbols "extension" (a puzzle piece): the Code on the Go add-ons member. Tinted at runtime. -->
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:width="40dp" android:height="40dp" android:viewportWidth="24" android:viewportHeight="24">
<path android:fillColor="#000000" android:pathData="M20.5 11H19V7c0-1.1-0.9-2-2-2h-4V3.5C13 2.12 11.88 1 10.5 1S8 2.12 8 3.5V5H4c-1.1 0-1.99 0.9-1.99 2v3.8H3.5c1.49 0 2.7 1.21 2.7 2.7s-1.21 2.7-2.7 2.7H2V20c0 1.1 0.9 2 2 2h3.8v-1.5c0-1.49 1.21-2.7 2.7-2.7 1.49 0 2.7 1.21 2.7 2.7V22H17c1.1 0 2-0.9 2-2v-4h1.5c1.38 0 2.5-1.12 2.5-2.5S21.88 11 20.5 11z" />
</vector>
4 changes: 4 additions & 0 deletions controller/app/src/main/res/drawable/ic_card_assets.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<!-- Material Symbols "inventory_2" (a closed box): the Code on the Go build-assets member. Tinted at runtime. -->
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:width="40dp" android:height="40dp" android:viewportWidth="24" android:viewportHeight="24">
<path android:fillColor="#000000" android:pathData="M20 2H4c-1 0-2 0.9-2 2v3.01c0 0.72 0.43 1.34 1 1.69V20c0 1.1 1.1 2 2 2h14c0.9 0 2-0.9 2-2V8.7c0.57-0.35 1-0.97 1-1.69V4c0-1.1-1-2-2-2zM15 14H9v-2h6v2zm5-7H4V4l16-0.02V7z" />
</vector>
4 changes: 4 additions & 0 deletions controller/app/src/main/res/drawable/ic_more_vert.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<!-- Material Symbols "more_vert" (overflow menu). Tinted at runtime. -->
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:width="24dp" android:height="24dp" android:viewportWidth="24" android:viewportHeight="24">
<path android:fillColor="#000000" android:pathData="M12 8c1.1 0 2-0.9 2-2s-0.9-2-2-2-2 0.9-2 2 0.9 2 2 2zm0 2c-1.1 0-2 0.9-2 2s0.9 2 2 2 2-0.9 2-2-0.9-2-2-2zm0 6c-1.1 0-2 0.9-2 2s0.9 2 2 2 2-0.9 2-2-0.9-2-2-2z" />
</vector>
Original file line number Diff line number Diff line change
Expand Up @@ -303,16 +303,16 @@ def _stage(source_base, serve_base, out, reuse_from, heavy_sink, limit_large, lo
catalog_bytes = fetch(f"{source_base}/{CATALOG}")
rewritten_catalog = catalog_bytes.decode("utf-8").replace(source_base, serve_base)

# K2GO-441: same-build short-circuit. The catalog carries `generated` (a build timestamp), so a
# byte-identical catalog means the exact same published build: nothing to download, nothing to swap.
# K2GO-441: same published build when the served catalog is byte-identical (the catalog carries a
# `generated` build timestamp). Computed here, but the short-circuit below ALSO requires every planned
# file to be present, so a file lost out-of-band (interrupted swap, disk) still re-downloads.
catalog_same = False
if reuse_from is not None:
try:
if (reuse_from / CATALOG).read_text(encoding="utf-8") == rewritten_catalog:
return {"up_to_date": True, "downloaded": 0, "reused": 0, "failed": 0, "headed": 0}
catalog_same = (reuse_from / CATALOG).read_text(encoding="utf-8") == rewritten_catalog
except OSError:
pass # no served catalog yet: fall through to a full mirror.
catalog_same = False # no served catalog yet: fall through to a full mirror.

out.mkdir(parents=True, exist_ok=True)
catalog = json.loads(catalog_bytes)
served = served_catalog_shas(reuse_from)

Expand All @@ -329,6 +329,16 @@ def _stage(source_base, serve_base, out, reuse_from, heavy_sink, limit_large, lo

paths, sha, size, reuse_ok = build_plan(
source_base, catalog, served, index_unchanged, index_bytes)

# K2GO-443: presence-aware same-build short-circuit. Up to date ONLY when the published build is
# unchanged AND every planned file is still present in the served tree, so a missing/corrupt file
# re-downloads instead of being reported up-to-date (build-assets' short-circuit is likewise
# presence-aware). Reads are cheap here; the expensive staging copy is what this still skips.
if (reuse_from is not None and catalog_same and index_unchanged
and all((reuse_from / rel).is_file() for rel in paths)):
return {"up_to_date": True, "downloaded": 0, "reused": 0, "failed": 0, "headed": 0}

out.mkdir(parents=True, exist_ok=True)
log(f"plan: {len(paths)} files, {len(sha)} verified binaries, "
f"{len(catalog['addons'])} add-ons")

Expand Down
Loading