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 @@ -62,25 +62,25 @@ public boolean runsOnThisRuntime() {
private static final Card[] CATALOG = {
new Card("kolibri", R.string.k2go_mod_kolibri_title, R.string.k2go_mod_kolibri_title,
R.string.k2go_mod_kolibri_sub, R.string.k2go_mod_kolibri_desc,
R.drawable.k2go_module_placeholder, false),
R.drawable.ic_card_courses, false),
new Card("calibreweb", R.string.k2go_mod_calibreweb_title, R.string.k2go_mod_calibreweb_title,
R.string.k2go_mod_calibreweb_sub, R.string.k2go_mod_calibreweb_desc,
R.drawable.k2go_module_placeholder, false),
R.drawable.ic_card_book, false),
new Card("kiwix", R.string.k2go_mod_kiwix_title, R.string.k2go_mod_kiwix_detail_title,
R.string.k2go_mod_kiwix_sub, R.string.k2go_mod_kiwix_desc,
R.drawable.k2go_module_placeholder, false),
R.drawable.ic_card_wikipedia, false),
new Card("code", R.string.k2go_mod_code_title, R.string.k2go_mod_code_title,
R.string.k2go_mod_code_sub, R.string.k2go_mod_code_desc,
R.drawable.k2go_module_placeholder, false),
R.drawable.ic_card_code, false),
new Card("forgejo", R.string.k2go_mod_forgejo_title, R.string.k2go_mod_forgejo_title,
R.string.k2go_mod_forgejo_sub, R.string.k2go_mod_forgejo_desc,
R.drawable.k2go_module_placeholder, false),
R.drawable.ic_card_forgejo, false),
new Card("matomo", R.string.k2go_mod_matomo_title, R.string.k2go_mod_matomo_title,
R.string.k2go_mod_matomo_sub, R.string.k2go_mod_matomo_desc,
R.drawable.k2go_module_placeholder, false),
R.drawable.ic_card_matomo, false),
new Card("maps", R.string.k2go_mod_maps_title, R.string.k2go_mod_maps_title,
R.string.k2go_mod_maps_sub, R.string.k2go_mod_maps_desc,
R.drawable.k2go_module_placeholder, true), // ADFA-4958: proot module WITH a content selector
R.drawable.ic_card_maps, true), // ADFA-4958: proot module WITH a content selector
};

/** All presentable module cards (roster-backed), in display order. */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
package org.appdevforall.k2go.redesign;

import android.content.Context;
import android.content.res.ColorStateList;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
Expand All @@ -24,6 +25,8 @@
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;

Expand Down Expand Up @@ -101,6 +104,37 @@ public class ModuleHubFragment extends Fragment {

private int px(int dp) { return Math.round(dp * getResources().getDisplayMetrics().density); }

// K2GO-426: one fixed-width leading slot for every row (checkbox XOR icon) so a selectable row
// and an installed row share the exact same indentation.
private static final int LEAD_SLOT_DP = 40;

private LinearLayout.LayoutParams leadSlotLp() {
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
px(LEAD_SLOT_DP), LinearLayout.LayoutParams.WRAP_CONTENT);
lp.rightMargin = px(4);
return lp;
}

// Wrap a leading element (checkbox or icon) so leadSlotLp() gives every row the same fixed-width
// slot with the child centered. One place builds the slot, so both paths cannot drift.
private FrameLayout leadSlot(View child, int childW, int childH) {
FrameLayout slot = new FrameLayout(requireContext());
FrameLayout.LayoutParams clp = new FrameLayout.LayoutParams(childW, childH);
clp.gravity = Gravity.CENTER;
slot.addView(child, clp);
return slot;
}

// The module icon as a small centered bullet, tinted from the theme primary (parity with the box
// index, whose cards tint their glyph with the primary colour).
private FrameLayout leadIconSlot(int iconRes) {
ImageView iv = new ImageView(requireContext());
iv.setImageResource(iconRes);
iv.setImageTintList(ColorStateList.valueOf(
ContextCompat.getColor(requireContext(), R.color.k2go_teal)));
return leadSlot(iv, px(24), px(24));
}

@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle s) {
Expand Down Expand Up @@ -364,6 +398,11 @@ private void addHiddenSection() {
rlp.bottomMargin = px(12);
row.setLayoutParams(rlp);

// K2GO-426: hidden rows are listed too; the same leading icon slot aligns their titles with
// the rest of the screen. The weight-1 col absorbs the slot, so the Restore button is not
// crowded.
row.addView(leadIconSlot(c.imageRes), leadSlotLp());

LinearLayout col = new LinearLayout(requireContext());
col.setOrientation(LinearLayout.VERTICAL);
TextView name = new TextView(requireContext());
Expand Down Expand Up @@ -422,11 +461,10 @@ private View cardRow(final ModuleCards.Card c, final boolean isInstalled,
}
});

// ADFA-5104: no tick on an installed module. There is nothing to schedule — installing it
// again is not an action the app offers, and a checkbox that does nothing is worse than
// no checkbox. The row still opens its detail, which is where "what is this" lives.
// ADFA-5104: and no tick when the flags could not be read either. Ticking would bank an
// order we have no grounds to take.
// ADFA-5104: no tick on an installed module (nothing to schedule; a checkbox that does
// nothing is worse than none), nor when the flags could not be read. K2GO-426: the leading
// slot is a fixed-width bullet either way: the checkbox when the module is selectable, else
// the module icon, so installed and not-installed rows share one indentation.
if (!isInstalled && !unknown && !failed && !c.hasSelector) { // ADFA-4958: tick to schedule several at once (maps uses its own selector). ADFA-4898: a failed module shows Retry, not the checkbox.
com.google.android.material.checkbox.MaterialCheckBox cb =
new com.google.android.material.checkbox.MaterialCheckBox(requireContext());
Expand All @@ -436,10 +474,10 @@ private View cardRow(final ModuleCards.Card c, final boolean isInstalled,
else ModuleWishlist.remove(requireContext(), c.key());
refreshProceed();
});
LinearLayout.LayoutParams cblp = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
cblp.rightMargin = px(4);
row.addView(cb, cblp);
row.addView(leadSlot(cb, FrameLayout.LayoutParams.WRAP_CONTENT,
FrameLayout.LayoutParams.WRAP_CONTENT), leadSlotLp());
} else {
row.addView(leadIconSlot(c.imageRes), leadSlotLp());
}

LinearLayout col = new LinearLayout(requireContext());
Expand Down Expand Up @@ -511,6 +549,10 @@ private void addSystemDashboardCard() {
lp.bottomMargin = px(12);
row.setLayoutParams(lp);

// K2GO-426: dash-node is the one core entry in this list; give it the same leading icon slot
// as the module rows so its title aligns with theirs.
row.addView(leadIconSlot(R.drawable.ic_card_dashnode), leadSlotLp());

LinearLayout col = new LinearLayout(requireContext());
col.setOrientation(LinearLayout.VERTICAL);
TextView title = new TextView(requireContext());
Expand Down
3 changes: 3 additions & 0 deletions controller/app/src/main/res/drawable/ic_card_dashnode.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<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="M3 13h8V3H3v10zm0 8h8v-6H3v6zm10 0h8V11h-8v10zm0-18v6h8V3h-8z" />
</vector>
3 changes: 3 additions & 0 deletions controller/app/src/main/res/drawable/ic_card_matomo.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<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="M5 9.2h3V19H5zM10.5 5h3v14h-3zM16 13h3v6h-3z" />
</vector>
Loading