Skip to content
Open
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 @@ -37,6 +37,7 @@
import org.appdevforall.k2go.R;
import org.appdevforall.k2go.applang.data.ContentLanguage;
import org.appdevforall.k2go.kolibri.domain.Channel;
import org.appdevforall.k2go.redesign.K2GoFilterChip;
import org.appdevforall.k2go.redesign.SetupLibraryActivity;
import org.appdevforall.k2go.redesign.ZimLanguageDialog;
import org.appdevforall.k2go.util.ByteFormatter;
Expand Down Expand Up @@ -80,8 +81,8 @@ public final class KolibriBrowseFragment extends Fragment {
private TextView storageLabel;
private ProgressBar storageBar;
private LinearLayout chips;
private TextView sortSize;
private TextView sortName;
private com.google.android.material.chip.Chip sortSize;
private com.google.android.material.chip.Chip sortName;
private LinearLayout list;
private Button review;

Expand Down Expand Up @@ -281,11 +282,10 @@ private void updateSortControls() {
pill(sortName, s.isName());
}

/** The one pill style in the app: teal filled when on, hairline outline when off. */
private void pill(TextView t, boolean on) {
t.setBackgroundResource(on ? R.drawable.k2go_chip_bg : R.drawable.k2go_pill_bg);
t.setTextColor(ContextCompat.getColor(requireContext(),
on ? android.R.color.white : R.color.k2go_ink));
// K2GO-385 (PR3): the shared filter chip (8dp, 32dp, check when active) -- the sort toggles now match
// the ZIM sort chips and the category/Books filters; the label still carries the sort direction.
private void pill(com.google.android.material.chip.Chip t, boolean on) {
K2GoFilterChip.style(t, on);
}

/**
Expand Down Expand Up @@ -456,25 +456,19 @@ private void buildChips(KolibriCatalogUiState s) {
}

private View chip(String label, final String group) {
TextView t = new TextView(requireContext());
t.setText(label);
t.setTextAppearance(com.google.android.material.R.style.TextAppearance_Material3_BodySmall);
t.setGravity(Gravity.CENTER);
t.setMinHeight(px(48)); // tap target, even though the pill looks smaller
t.setPadding(px(14), px(8), px(14), px(8));
pill(t, group.equals(groupFilter));

// K2GO-385 (PR3): category chips use the shared filter chip too.
com.google.android.material.chip.Chip c = K2GoFilterChip.create(requireContext(), label,
group.equals(groupFilter), x -> {
if (!group.equals(groupFilter)) {
groupFilter = group;
render(vm.state().getValue());
}
});
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
lp.rightMargin = px(8);
t.setLayoutParams(lp);
t.setOnClickListener(x -> {
if (!group.equals(groupFilter)) {
groupFilter = group;
render(vm.state().getValue());
}
});
return t;
c.setLayoutParams(lp);
return c;
}

private void updateStorage() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@
import androidx.fragment.app.Fragment;

import org.appdevforall.k2go.PortalActivity;
import com.google.android.material.chip.Chip;

import org.appdevforall.k2go.R;
import org.appdevforall.k2go.config.BoxEndpoints;
import org.json.JSONArray;
Expand Down Expand Up @@ -200,22 +202,10 @@ private void openLanguagePicker() {
() -> { lang = ""; updateLangPill(); loadBooks(); });
}

private TextView chip(String text, boolean on, Runnable onClick) {
TextView t = new TextView(requireContext());
t.setText(text);
t.setPadding(px(14), px(8), px(14), px(8));
t.setBackgroundResource(on ? R.drawable.k2go_chip_bg : R.drawable.k2go_pill_bg);
// ADFA-5248: apply the text appearance FIRST, then the color. TextAppearance_Material3_*
// carries its own colorOnSurface, so setting the color before it silently overwrote the chip
// color (the real bug the ticket reported: onSurface flips with the theme, giving dark-on-
// dark-teal in light mode and light-on-aqua in dark mode — never legible on the teal fill).
// With the order fixed, k2go_on_teal sticks: it flips against the fill (light text on the
// dark-teal light-mode fill, dark text on the light-aqua dark-mode fill).
t.setTextAppearance(com.google.android.material.R.style.TextAppearance_Material3_BodySmall);
t.setTextColor(ContextCompat.getColor(requireContext(), on ? R.color.k2go_on_teal : R.color.k2go_ink));
t.setClickable(true);
t.setOnClickListener(v -> onClick.run());
return t;
// K2GO-385 (PR3): the shared filter chip (8dp corner, 32dp, check when selected). Replaces the
// per-screen k2go_chip_bg/k2go_pill_bg drawable pair that had drifted from the other filter surfaces.
private Chip chip(String text, boolean on, Runnable onClick) {
return K2GoFilterChip.create(requireContext(), text, on, v -> onClick.run());
}

private void loadLibrary() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -443,13 +443,15 @@ private void showOverlay(String name, long sizeBytes) {
// ADFA-4896: Stop/Retry beside Cancel. The label follows the reported state; the tap fires the
// matching verb and the poll (onPaused/onProgress) is the source of truth.
overlayStopped = false;
overlayStop = new MaterialButton(themed, null,
com.google.android.material.R.attr.materialButtonOutlinedStyle);
// K2GO-385 (PR3): the download controls use the app button system (K2Go outlined stadium) via the
// shared overlay, not a bare Material3 outlined button. FQR's overlay is a themed (day/night)
// surface, so the K2Go outlined style's theme teal is right here -- not the fixed boot tokens.
ContextThemeWrapper btnCtx = new ContextThemeWrapper(themed, R.style.ThemeOverlay_K2Go_Button_Outlined);
overlayStop = new MaterialButton(btnCtx, null);
overlayStop.setText(R.string.k2go_clone_stop_confirm);
overlayStop.setOnClickListener(v -> toggleStop());
row.addView(overlayStop);
MaterialButton cancel = new MaterialButton(themed, null,
com.google.android.material.R.attr.materialButtonOutlinedStyle);
MaterialButton cancel = new MaterialButton(btnCtx, null);
cancel.setText(R.string.k2go_cancel);
cancel.setOnClickListener(v -> { client.cancel(); hideOverlay(); });
row.addView(cancel);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/*
* ============================================================================
* Name : K2GoFilterChip.java
* Author : AppDevForAll
* Copyright : Copyright (c) 2026 AppDevForAll
* Description : K2GO-385 (PR3). The shared FILTER CHIP (pill-roles design decision, board
* k2go-chip-vs-button-v1): a selectable/toggle chip -- Popular / Educational, a ZIM
* category, a sort order. Per the decision it is an 8dp-corner, ~32dp Material 3 chip
* with a leading check when selected -- "8dp corner + check = toggle", distinct on
* purpose from the stadium action button, the dot+text status and the 8dp metadata
* tag. Built ONCE here instead of the three drifted per-screen chip builders it
* replaces (ZimLanding / ZimCategory / BooksLanding). Colour is the app teal (filled +
* on-teal text when selected; transparent + teal outline + teal text when not). Pure
* UI; no domain/data dependencies.
* ============================================================================
*/
package org.appdevforall.k2go.redesign;

import android.content.Context;
import android.content.res.ColorStateList;
import android.graphics.Color;
import android.view.View;

import androidx.core.content.ContextCompat;

import com.google.android.material.chip.Chip;

import org.appdevforall.k2go.R;

public final class K2GoFilterChip {

private K2GoFilterChip() {}

/**
* Build a selectable filter chip. {@code selected} sets the checked look (teal fill + check);
* {@code onClick} fires on tap -- the caller owns the selection model (usually rebuilding the
* row), so the chip is a view of that state, not the source of truth.
*/
public static Chip create(Context ctx, CharSequence label, boolean selected, View.OnClickListener onClick) {
Chip chip = new Chip(ctx);
chip.setText(label);
style(chip, selected);
chip.setOnClickListener(onClick);
return chip;
}

/**
* Apply the filter-chip look + selected state to an EXISTING chip (e.g. one inflated from XML,
* like the ZimCategory sort chips). Idempotent -- safe to call on every render. The caller owns
* the text (so a sort chip can carry its "By size ▲" direction) and the click.
*/
public static void style(Chip chip, boolean selected) {
Context ctx = chip.getContext();
float d = ctx.getResources().getDisplayMetrics().density;
chip.setCheckable(true);
chip.setChecked(selected);
chip.setCheckedIconVisible(true); // the "check" cue the design calls for
// A bare new Chip(ctx) picks up the theme's default (Assist) chipStyle, which has NO checkedIcon,
// so set a plain check explicitly -- otherwise setCheckedIconVisible shows nothing.
chip.setCheckedIcon(ContextCompat.getDrawable(ctx, R.drawable.ic_check_16));
chip.setChipCornerRadius(8 * d); // 8dp corner = chip/toggle (not a stadium pill)
chip.setChipMinHeight(32 * d); // the 32dp step on the 4dp role ladder
chip.setEnsureMinTouchTargetSize(true); // keep a >=48dp touch target on the 32dp chip
chip.setTextAppearance(com.google.android.material.R.style.TextAppearance_Material3_LabelLarge);

int teal = ContextCompat.getColor(ctx, R.color.k2go_teal);
int onTeal = ContextCompat.getColor(ctx, R.color.k2go_on_teal);
int[][] states = { new int[]{ android.R.attr.state_checked }, new int[0] };
chip.setChipBackgroundColor(new ColorStateList(states, new int[]{ teal, Color.TRANSPARENT }));
chip.setChipStrokeColor(new ColorStateList(states, new int[]{ Color.TRANSPARENT, teal }));
chip.setChipStrokeWidth(Math.max(1, Math.round(1.4f * d)));
chip.setTextColor(new ColorStateList(states, new int[]{ onTeal, teal }));
chip.setCheckedIconTint(ColorStateList.valueOf(onTeal));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,8 @@ private static final class Entry {
private long freeMb = 0, totalMb = 0;

private LinearLayout list;
private TextView freeLabel, sortSize, sortName, sortGroup, count, langCurrent, langSub;
private TextView freeLabel, count, langCurrent, langSub;
private com.google.android.material.chip.Chip sortSize, sortName, sortGroup;
private ProgressBar bar;
private Button add;

Expand Down Expand Up @@ -275,10 +276,11 @@ private void addHeader(String title, String desc) {
list.addView(h);
}

private void chip(TextView t, boolean on) {
t.setBackgroundResource(on ? R.drawable.k2go_chip_bg : R.drawable.k2go_pill_bg);
// ADFA-4910: white on the selected (teal) chip (same fix as Books / MapsChoose).
t.setTextColor(ContextCompat.getColor(requireContext(), on ? android.R.color.white : R.color.k2go_ink));
// K2GO-385 (PR3): the sort chips use the one shared filter chip (8dp, 32dp, check when active) so
// they stop looking different from the category/Books filter chips; the label still carries the
// sort direction (e.g. "By size ▲").
private void chip(com.google.android.material.chip.Chip t, boolean on) {
K2GoFilterChip.style(t, on);
}

// ADFA-5033: flat list row (spec §10) — a simple line with a hairline between rows, NOT a card.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@
import androidx.core.content.ContextCompat;
import androidx.fragment.app.Fragment;

import com.google.android.material.chip.Chip;

import org.appdevforall.k2go.R;
import org.appdevforall.k2go.applang.data.ContentLanguage;
import org.json.JSONObject;
Expand Down Expand Up @@ -253,36 +255,19 @@ private void buildChips() {

private View chip(String label, String groupKey) {
boolean selected = (groupKey == null) ? (selectedGroup == null) : groupKey.equals(selectedGroup);
int teal = ContextCompat.getColor(requireContext(), R.color.k2go_teal);
TextView t = new TextView(requireContext());
t.setText(label);
t.setTextAppearance(com.google.android.material.R.style.TextAppearance_Material3_LabelLarge);
t.setGravity(Gravity.CENTER);
t.setMinHeight(px(48)); // ADFA-5033: ≥48dp tap target (spec §9)
t.setPadding(px(14), px(6), px(14), px(6));
android.graphics.drawable.GradientDrawable bg = new android.graphics.drawable.GradientDrawable();
bg.setShape(android.graphics.drawable.GradientDrawable.RECTANGLE);
bg.setCornerRadius(px(24)); // full pill at 48dp
if (selected) {
bg.setColor(teal);
t.setTextColor(android.graphics.Color.WHITE);
} else {
bg.setColor(android.graphics.Color.TRANSPARENT);
bg.setStroke(Math.max(1, Math.round(1.4f * getResources().getDisplayMetrics().density)), teal);
t.setTextColor(teal);
}
t.setBackground(bg);
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
lp.rightMargin = px(8);
t.setLayoutParams(lp);
t.setOnClickListener(v -> {
// K2GO-385 (PR3): one shared filter chip (8dp corner, 32dp, check when selected) -- replaces the
// per-screen 48dp teal pill that had drifted from the other filter surfaces.
Chip c = K2GoFilterChip.create(requireContext(), label, selected, v -> {
selectedGroup = groupKey;
expanded = false;
buildChips();
buildRows();
});
return t;
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
lp.rightMargin = px(8);
c.setLayoutParams(lp);
return c;
}

/** Teal caps section header (MOST CONTENT / group headers). */
Expand Down
10 changes: 10 additions & 0 deletions controller/app/src/main/res/drawable/ic_check_16.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<!-- K2GO-385 (PR3): plain checkmark for the filter chip's checked state. Tinted by the chip. -->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="18dp"
android:height="18dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="#FFFFFFFF"
android:pathData="M9,16.17L4.83,12l-1.42,1.41L9,19 21,7l-1.41,-1.41z" />
</vector>
13 changes: 4 additions & 9 deletions controller/app/src/main/res/layout/activity_library.xml
Original file line number Diff line number Diff line change
Expand Up @@ -201,22 +201,17 @@
android:visibility="gone">
<com.google.android.material.button.MaterialButton
android:id="@+id/k2go_dl_toggle"
style="@style/Widget.Material3.Button.OutlinedButton"
style="@style/Widget.K2Go.Button.Outlined.OnBootPaper"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:minWidth="132dp"
android:textColor="@color/k2go_boot_ink"
app:strokeColor="@color/k2go_boot_ink"
app:rippleColor="@color/k2go_boot_muted" />
android:minWidth="132dp" />
<com.google.android.material.button.MaterialButton
android:id="@+id/k2go_dl_cancel"
style="@style/Widget.Material3.Button.TextButton"
style="@style/Widget.K2Go.Button.Text.OnBootPaper"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:text="@string/k2go_dl_cancel"
android:textColor="@color/k2go_boot_muted"
app:rippleColor="@color/k2go_boot_muted" />
android:text="@string/k2go_dl_cancel" />
</LinearLayout>
</LinearLayout>
</FrameLayout>
Original file line number Diff line number Diff line change
Expand Up @@ -133,26 +133,16 @@
android:layout_marginTop="12dp"
android:orientation="horizontal">

<TextView
<com.google.android.material.chip.Chip
android:id="@+id/k2go_kbrowse_sort_size"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="12dp"
android:paddingRight="12dp"
android:paddingTop="8dp"
android:paddingBottom="8dp"
android:textAppearance="?attr/textAppearanceBodySmall" />
android:layout_height="wrap_content" />

<TextView
<com.google.android.material.chip.Chip
android:id="@+id/k2go_kbrowse_sort_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:paddingLeft="12dp"
android:paddingRight="12dp"
android:paddingTop="8dp"
android:paddingBottom="8dp"
android:textAppearance="?attr/textAppearanceBodySmall" />
android:layout_marginStart="8dp" />
</LinearLayout>

<!-- Count on its own line so it can never share the scrollable chip row. -->
Expand Down
18 changes: 6 additions & 12 deletions controller/app/src/main/res/layout/fragment_k2go_zim_category.xml
Original file line number Diff line number Diff line change
Expand Up @@ -100,23 +100,17 @@
android:layout_marginTop="12dp"
android:orientation="horizontal">

<TextView android:id="@+id/k2go_zc_sort_size"
android:layout_width="wrap_content" android:layout_height="wrap_content"
android:paddingLeft="12dp" android:paddingRight="12dp" android:paddingTop="8dp" android:paddingBottom="8dp"
android:textAppearance="?attr/textAppearanceBodySmall" />
<com.google.android.material.chip.Chip android:id="@+id/k2go_zc_sort_size"
android:layout_width="wrap_content" android:layout_height="wrap_content" />

<TextView android:id="@+id/k2go_zc_sort_name"
<com.google.android.material.chip.Chip android:id="@+id/k2go_zc_sort_name"
android:layout_width="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:paddingLeft="12dp" android:paddingRight="12dp" android:paddingTop="8dp" android:paddingBottom="8dp"
android:textAppearance="?attr/textAppearanceBodySmall" />
android:layout_marginStart="8dp" />

<TextView android:id="@+id/k2go_zc_sort_group"
<com.google.android.material.chip.Chip android:id="@+id/k2go_zc_sort_group"
android:layout_width="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:paddingLeft="12dp" android:paddingRight="12dp" android:paddingTop="8dp" android:paddingBottom="8dp"
android:text="@string/k2go_zc_sort_group"
android:textAppearance="?attr/textAppearanceBodySmall" />
android:text="@string/k2go_zc_sort_group" />
</LinearLayout>

<!-- ADFA-5033: count on its OWN line (design board k2go-count-overflow-v1) so it never shares the
Expand Down
Loading
Loading