diff --git a/controller/app/src/main/java/org/appdevforall/k2go/dependency/domain/DashNodeRequirement.java b/controller/app/src/main/java/org/appdevforall/k2go/dependency/domain/DashNodeRequirement.java
new file mode 100644
index 000000000..7db6f0a8c
--- /dev/null
+++ b/controller/app/src/main/java/org/appdevforall/k2go/dependency/domain/DashNodeRequirement.java
@@ -0,0 +1,36 @@
+/*
+ * ============================================================================
+ * Name : DashNodeRequirement.java
+ * Author : AppDevForAll
+ * Copyright : Copyright (c) 2026 AppDevForAll
+ * Description : K2GO-430. Per-module minimum dash-node version. Pure data + lookup; the version compare
+ * and the box read live elsewhere (redesign.DashboardVersion), so this stays a plain,
+ * unit-testable registry with no Android or network dependency.
+ *
+ * Forgejo needs the dashboard build that ships its repo status/refresh endpoints (1.3.7):
+ * an older dash-node makes "Install repos"/"Update repos" and the seed break silently, so
+ * installing Forgejo is HARD-blocked below that version. Other modules have no hard minimum
+ * (a soft "update the dashboard" suggestion applies to all installs, handled in the gate).
+ * ============================================================================
+ */
+package org.appdevforall.k2go.dependency.domain;
+
+import androidx.annotation.Nullable;
+
+public final class DashNodeRequirement {
+ private DashNodeRequirement() {}
+
+ /** {major, minor, patch} minimum dash-node for {@code moduleKey}, or null when it has no hard minimum. */
+ @Nullable
+ public static int[] minFor(@Nullable String moduleKey) {
+ if ("forgejo".equals(moduleKey)) return new int[]{1, 3, 7};
+ return null;
+ }
+
+ /** Human "x.y.z" label for the minimum, or null when there is none. */
+ @Nullable
+ public static String minLabel(@Nullable String moduleKey) {
+ int[] m = minFor(moduleKey);
+ return m == null ? null : m[0] + "." + m[1] + "." + m[2];
+ }
+}
diff --git a/controller/app/src/main/java/org/appdevforall/k2go/dependency/presentation/DashNodeGate.java b/controller/app/src/main/java/org/appdevforall/k2go/dependency/presentation/DashNodeGate.java
new file mode 100644
index 000000000..27e24e162
--- /dev/null
+++ b/controller/app/src/main/java/org/appdevforall/k2go/dependency/presentation/DashNodeGate.java
@@ -0,0 +1,101 @@
+/*
+ * ============================================================================
+ * Name : DashNodeGate.java
+ * Author : AppDevForAll
+ * Copyright : Copyright (c) 2026 AppDevForAll
+ * Description : K2GO-430. Gate a module install on the box dash-node version. Two mechanisms:
+ * HARD block : a module that declares a minimum (DashNodeRequirement, e.g. Forgejo -> 1.3.7)
+ * cannot install on a box below it; show a dialog and route to the dashboard update.
+ * SOFT suggest : for a batch, when a dashboard update is available, recommend updating first
+ * (Update / Install anyway). Reuses the existing version read (DashboardVersion, from the
+ * rootfs, no network/proot) and the cached update-check (UpdateStatusCache), so the gate is
+ * synchronous.
+ * ============================================================================
+ */
+package org.appdevforall.k2go.dependency.presentation;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import org.appdevforall.k2go.R;
+import org.appdevforall.k2go.dependency.domain.DashNodeRequirement;
+import org.appdevforall.k2go.redesign.DashboardVersion;
+import org.appdevforall.k2go.redesign.OpReturnNavigator;
+import org.appdevforall.k2go.redesign.UpdateStatusCache;
+import org.appdevforall.k2go.ui.dialog.BrandDialog;
+
+public final class DashNodeGate {
+ private DashNodeGate() {}
+
+ /** True when the box dash-node is below {@code moduleKey}'s hard minimum (null key / no minimum = false).
+ * A null (unreadable) installed version blocks a module that HAS a minimum: do not install it against
+ * a dashboard we cannot verify. */
+ public static boolean installBlocked(@NonNull Context ctx, @Nullable String moduleKey) {
+ int[] min = DashNodeRequirement.minFor(moduleKey);
+ return min != null && !DashboardVersion.atLeast(DashboardVersion.installed(ctx), min[0], min[1], min[2]);
+ }
+
+ /** The first key below its dash-node minimum, or null. */
+ @Nullable
+ private static String firstBlocked(@NonNull Context ctx, @Nullable String[] keys) {
+ if (keys == null) return null;
+ for (String k : keys) if (installBlocked(ctx, k)) return k;
+ return null;
+ }
+
+ /**
+ * Gate a module install batch before it runs. If any banked module needs a newer dash-node than the
+ * box has, block and route to the dashboard update. Otherwise, if a dashboard update is available,
+ * suggest it first (Update / Install anyway). Otherwise run {@code onProceed} straight away.
+ */
+ public static void guardModuleBatch(@NonNull Activity act, @Nullable String[] bankedKeys, @NonNull Runnable onProceed) {
+ String blocked = firstBlocked(act, bankedKeys);
+ if (blocked != null) { showBlocked(act, blocked); return; }
+ if (UpdateStatusCache.updateAvailable(act)) { showSuggest(act, onProceed); return; }
+ onProceed.run();
+ }
+
+ /**
+ * Gate a single-module (re)install, e.g. a retry: returns false (and shows the block dialog) when the
+ * module is below its dash-node minimum, true when it may proceed. Hard block only (a retry does not
+ * carry the soft update suggestion). Covers the install paths that start the index directly, not via
+ * the batch gate.
+ */
+ public static boolean allowInstall(@NonNull Context ctx, @Nullable String moduleKey) {
+ if (installBlocked(ctx, moduleKey)) { showBlocked(ctx, moduleKey); return false; }
+ return true;
+ }
+
+ private static void showBlocked(@NonNull Context ctx, @NonNull String moduleKey) {
+ new BrandDialog(ctx)
+ .setTitle(R.string.k2go_dep_required_title)
+ .setMessage(ctx.getString(R.string.k2go_dep_required_msg_fmt, DashNodeRequirement.minLabel(moduleKey)))
+ .setPositive(R.string.k2go_dep_update_dashboard, BrandDialog.Role.PRIMARY, () -> openDashboard(ctx))
+ .setNegative(android.R.string.cancel, null)
+ .show();
+ }
+
+ private static void showSuggest(@NonNull Context ctx, @NonNull Runnable onProceed) {
+ new BrandDialog(ctx)
+ .setTitle(R.string.k2go_dep_suggest_title)
+ .setMessage(R.string.k2go_dep_suggest_msg)
+ .setPositive(R.string.k2go_dep_update_dashboard, BrandDialog.Role.PRIMARY, () -> openDashboard(ctx))
+ .setNegative(R.string.k2go_dep_install_anyway, onProceed::run)
+ // The suggestion is optional: dismissing it (back / tap-outside) proceeds with the install
+ // the user already asked for, rather than silently swallowing it.
+ .setOnCancel(onProceed::run)
+ .show();
+ }
+
+ /** Open the dashboard detail (the Rebuild/Update card) so the user can update the dash-node. Reuses the
+ * canonical navigation intent instead of rebuilding it here. */
+ private static void openDashboard(@NonNull Context ctx) {
+ Intent i = OpReturnNavigator.dashboardRebuild(ctx);
+ if (!(ctx instanceof Activity)) i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ ctx.startActivity(i);
+ }
+}
diff --git a/controller/app/src/main/java/org/appdevforall/k2go/redesign/ModuleRetry.java b/controller/app/src/main/java/org/appdevforall/k2go/redesign/ModuleRetry.java
index 1a3eba0c7..f44d3e9cc 100644
--- a/controller/app/src/main/java/org/appdevforall/k2go/redesign/ModuleRetry.java
+++ b/controller/app/src/main/java/org/appdevforall/k2go/redesign/ModuleRetry.java
@@ -54,6 +54,12 @@ public static boolean fire(View anchor, String moduleKey) {
Snackbars.make(anchor, BusyMessage.resFor(ctx)).show();
return false;
}
+ // K2GO-430: a retry starts the install directly (not via openModuleIndex), so gate the dash-node
+ // dependency here too. If the box dash-node is below the module's minimum, the gate shows the
+ // "update the dashboard first" dialog and the retry does not fire.
+ if (!org.appdevforall.k2go.dependency.presentation.DashNodeGate.allowInstall(ctx, moduleKey)) {
+ return false;
+ }
InstallService.retryModules(ctx, Collections.singletonList(moduleKey));
return true;
}
diff --git a/controller/app/src/main/java/org/appdevforall/k2go/redesign/SetupLibraryActivity.java b/controller/app/src/main/java/org/appdevforall/k2go/redesign/SetupLibraryActivity.java
index 856a0f2e5..e0997ce6e 100644
--- a/controller/app/src/main/java/org/appdevforall/k2go/redesign/SetupLibraryActivity.java
+++ b/controller/app/src/main/java/org/appdevforall/k2go/redesign/SetupLibraryActivity.java
@@ -659,17 +659,23 @@ public void openDashboardDetail() {
* banked in ModuleWishlist; the index drains them through the proot queue (ModuleProvisioner),
* same mechanism as maps. */
public void openModuleIndex() {
- // ADFA-5228: module app installs are proot (STOPPED) runroles — confirm before entering the
- // index that drains them. Class is read from the operation (the first banked module); a LIVE
- // op would pass straight through the gate.
- String[] banked = ModuleWishlist.keys(this);
- org.appdevforall.k2go.system.domain.Operation op =
- org.appdevforall.k2go.system.domain.Operation.appInstall(banked.length > 0 ? banked[0] : "");
- // K2GO-404: the runrole fetches over the network inside the proot, so gate on metered cost at
- // the START (like the rootfs/maps installs); a decline leaves the modules banked.
- InstallConfirm.gate(this, op, () ->
- org.appdevforall.k2go.networkpolicy.presentation.NetworkPolicyGate.guardHeavyStart(this,
- () -> startActivity(new Intent(this, SetupProgressActivity.class))));
+ final String[] banked = ModuleWishlist.keys(this);
+ // K2GO-430: a banked module may need a newer dash-node than the box has (Forgejo -> 1.3.7). Block
+ // the batch and route to the dashboard update when any module is below its minimum; else, when a
+ // dashboard update is available, suggest it first. This gates every install path (they all run
+ // through here) before the proot queue starts.
+ org.appdevforall.k2go.dependency.presentation.DashNodeGate.guardModuleBatch(this, banked, () -> {
+ // ADFA-5228: module app installs are proot (STOPPED) runroles — confirm before entering the
+ // index that drains them. Class is read from the operation (the first banked module); a LIVE
+ // op would pass straight through the gate.
+ org.appdevforall.k2go.system.domain.Operation op =
+ org.appdevforall.k2go.system.domain.Operation.appInstall(banked.length > 0 ? banked[0] : "");
+ // K2GO-404: the runrole fetches over the network inside the proot, so gate on metered cost at
+ // the START (like the rootfs/maps installs); a decline leaves the modules banked.
+ InstallConfirm.gate(this, op, () ->
+ org.appdevforall.k2go.networkpolicy.presentation.NetworkPolicyGate.guardHeavyStart(this,
+ () -> startActivity(new Intent(this, SetupProgressActivity.class))));
+ });
}
/** ADFA-4952: open the dedicated backup/restore job screen (mode = MODE_BACKUP / MODE_RESTORE). */
diff --git a/controller/app/src/main/res/values-ar/strings.xml b/controller/app/src/main/res/values-ar/strings.xml
index 97eb7c351..fdbd39ea1 100644
--- a/controller/app/src/main/res/values-ar/strings.xml
+++ b/controller/app/src/main/res/values-ar/strings.xml
@@ -1370,4 +1370,10 @@
تعذّر تحديث المستودعات
جارٍ الإلغاء...
تم إلغاء التحديث
+ حدّث dashboard أولاً
+ تحتاج هذه الوحدة إلى dashboard بالإصدار %1$s أو أحدث قبل تثبيتها.
+ تحديث dashboard
+ يتوفر تحديث لـ dashboard
+ يُوصى بتحديث dashboard أولاً حتى تعمل ميزات الوحدة الجديدة بشكل صحيح.
+ التثبيت على أي حال
diff --git a/controller/app/src/main/res/values-az/strings.xml b/controller/app/src/main/res/values-az/strings.xml
index 6e2c3085f..34609063e 100644
--- a/controller/app/src/main/res/values-az/strings.xml
+++ b/controller/app/src/main/res/values-az/strings.xml
@@ -1390,4 +1390,10 @@
Anbarlar yenilene bilmedi
Legv edilir...
Yenileme legv edildi
+ Evvelce dashboard-u yenileyin
+ Bu modul qurasdirila bilmesi ucun %1$s ve ya daha yeni dashboard versiyasina ehtiyac duyur.
+ Dashboard-u yenile
+ Dashboard yenilemesi movcuddur
+ Yeni modul funksiyalarinin duzgun islemesi ucun evvelce dashboard-u yenilemek tovsiye olunur.
+ Yene de qurasdir
diff --git a/controller/app/src/main/res/values-bg/strings.xml b/controller/app/src/main/res/values-bg/strings.xml
index 7ad9f8bcd..b77ee0dda 100644
--- a/controller/app/src/main/res/values-bg/strings.xml
+++ b/controller/app/src/main/res/values-bg/strings.xml
@@ -1377,4 +1377,10 @@
Хранилищата не можаха да бъдат обновени
Отказване...
Обновяването е отказано
+ Първо обновете dashboard
+ Този модул се нуждае от dashboard версия %1$s или по-нова, преди да може да се инсталира.
+ Обнови dashboard
+ Налична е актуализация на dashboard
+ Препоръчва се първо да обновите dashboard, за да работят правилно новите функции на модула.
+ Инсталирай въпреки това
diff --git a/controller/app/src/main/res/values-bn/strings.xml b/controller/app/src/main/res/values-bn/strings.xml
index a9bae6a19..e472c0e26 100644
--- a/controller/app/src/main/res/values-bn/strings.xml
+++ b/controller/app/src/main/res/values-bn/strings.xml
@@ -1383,4 +1383,10 @@
রিপোজিটরি আপডেট করা যায়নি
বাতিল করা হচ্ছে...
আপডেট বাতিল করা হয়েছে
+ প্রথমে dashboard আপডেট করুন
+ ইনস্টল করার আগে এই মডিউলের dashboard %1$s বা নতুন সংস্করণ প্রয়োজন।
+ dashboard আপডেট করুন
+ dashboard আপডেট উপলব্ধ
+ মডিউলের নতুন বৈশিষ্ট্য ঠিকমতো কাজ করার জন্য প্রথমে dashboard আপডেট করার পরামর্শ দেওয়া হয়।
+ তবুও ইনস্টল করুন
diff --git a/controller/app/src/main/res/values-cs/strings.xml b/controller/app/src/main/res/values-cs/strings.xml
index 84b4e8e02..b9caf9283 100644
--- a/controller/app/src/main/res/values-cs/strings.xml
+++ b/controller/app/src/main/res/values-cs/strings.xml
@@ -1377,4 +1377,10 @@
Repozitare se nepodarilo aktualizovat
Ruseni...
Aktualizace zrusena
+ Nejprve aktualizujte dashboard
+ Tento modul potrebuje dashboard ve verzi %1$s nebo novejsi, nez jej bude mozne nainstalovat.
+ Aktualizovat dashboard
+ Je dostupna aktualizace dashboardu
+ Doporucujeme nejprve aktualizovat dashboard, aby nove funkce modulu fungovaly spravne.
+ Presto nainstalovat
diff --git a/controller/app/src/main/res/values-de/strings.xml b/controller/app/src/main/res/values-de/strings.xml
index 91be962cf..6983be2b8 100644
--- a/controller/app/src/main/res/values-de/strings.xml
+++ b/controller/app/src/main/res/values-de/strings.xml
@@ -1370,4 +1370,10 @@
Repositorys konnten nicht aktualisiert werden
Wird abgebrochen...
Aktualisierung abgebrochen
+ Zuerst das Dashboard aktualisieren
+ Dieses Modul benoetigt das Dashboard in Version %1$s oder neuer, bevor es installiert werden kann.
+ Dashboard aktualisieren
+ Ein Dashboard-Update ist verfuegbar
+ Es wird empfohlen, zuerst das Dashboard zu aktualisieren, damit neue Modulfunktionen richtig laufen.
+ Trotzdem installieren
diff --git a/controller/app/src/main/res/values-el/strings.xml b/controller/app/src/main/res/values-el/strings.xml
index 8a39f79a1..e950af472 100644
--- a/controller/app/src/main/res/values-el/strings.xml
+++ b/controller/app/src/main/res/values-el/strings.xml
@@ -1377,4 +1377,10 @@
Δεν ήταν δυνατή η ενημέρωση των αποθετηρίων
Ακύρωση...
Η ενημέρωση ακυρώθηκε
+ Ενημερώστε πρώτα το dashboard
+ Αυτή η μονάδα χρειάζεται το dashboard στην έκδοση %1$s ή νεότερη πριν εγκατασταθεί.
+ Ενημέρωση dashboard
+ Διαθέσιμη ενημέρωση dashboard
+ Συνιστάται να ενημερώσετε πρώτα το dashboard ώστε οι νέες λειτουργίες της μονάδας να λειτουργούν σωστά.
+ Εγκατάσταση ούτως ή άλλως
diff --git a/controller/app/src/main/res/values-es/strings.xml b/controller/app/src/main/res/values-es/strings.xml
index ecf2e9456..bf14176c8 100644
--- a/controller/app/src/main/res/values-es/strings.xml
+++ b/controller/app/src/main/res/values-es/strings.xml
@@ -1446,4 +1446,10 @@
No se pudieron actualizar los repositorios
Cancelando...
Actualizacion cancelada
+ Actualiza primero el dashboard
+ Este modulo necesita el dashboard actualizado a la version %1$s o mas reciente antes de poder instalarse.
+ Actualizar dashboard
+ Hay una actualizacion del dashboard disponible
+ Se recomienda actualizar primero el dashboard para que las nuevas funciones del modulo funcionen bien.
+ Instalar de todos modos
diff --git a/controller/app/src/main/res/values-fa/strings.xml b/controller/app/src/main/res/values-fa/strings.xml
index c32b195d0..d412e0f42 100644
--- a/controller/app/src/main/res/values-fa/strings.xml
+++ b/controller/app/src/main/res/values-fa/strings.xml
@@ -1370,4 +1370,10 @@
بهروزرسانی مخازن ممکن نشد
در حال لغو...
بهروزرسانی لغو شد
+ ابتدا dashboard را بهروزرسانی کنید
+ این ماژول پیش از نصب به dashboard نسخه %1$s یا جدیدتر نیاز دارد.
+ بهروزرسانی dashboard
+ بهروزرسانی dashboard در دسترس است
+ توصیه میشود ابتدا dashboard را بهروزرسانی کنید تا قابلیتهای جدید ماژول درست کار کنند.
+ به هر حال نصب شود
diff --git a/controller/app/src/main/res/values-fr/strings.xml b/controller/app/src/main/res/values-fr/strings.xml
index 4fc4b9b90..f4fbb4d31 100644
--- a/controller/app/src/main/res/values-fr/strings.xml
+++ b/controller/app/src/main/res/values-fr/strings.xml
@@ -1457,4 +1457,10 @@
Impossible de mettre a jour les depots
Annulation...
Mise a jour annulee
+ Mettez d\'abord a jour le dashboard
+ Ce module a besoin du dashboard en version %1$s ou plus recente avant de pouvoir etre installe.
+ Mettre a jour le dashboard
+ Une mise a jour du dashboard est disponible
+ Il est recommande de mettre a jour le dashboard d\'abord pour que les nouvelles fonctions du module marchent bien.
+ Installer quand meme
diff --git a/controller/app/src/main/res/values-gu/strings.xml b/controller/app/src/main/res/values-gu/strings.xml
index 6b88e8f9e..2efdeb86b 100644
--- a/controller/app/src/main/res/values-gu/strings.xml
+++ b/controller/app/src/main/res/values-gu/strings.xml
@@ -1383,4 +1383,10 @@
રિપોઝિટરી અપડેટ થઈ શકી નથી
રદ કરી રહ્યાં છીએ...
અપડેટ રદ કરાયું
+ પહેલાં dashboard અપડેટ કરો
+ ઇન્સ્ટૉલ થાય તે પહેલાં આ મૉડ્યૂલને dashboard ના %1$s અથવા નવા સંસ્કરણની જરૂર છે.
+ dashboard અપડેટ કરો
+ dashboard અપડેટ ઉપલબ્ધ છે
+ મૉડ્યૂલની નવી સુવિધાઓ યોગ્ય રીતે કામ કરે તે માટે પહેલાં dashboard અપડેટ કરવાની ભલામણ છે.
+ તોપણ ઇન્સ્ટૉલ કરો
diff --git a/controller/app/src/main/res/values-hi/strings.xml b/controller/app/src/main/res/values-hi/strings.xml
index fc34978d5..6f189ad71 100644
--- a/controller/app/src/main/res/values-hi/strings.xml
+++ b/controller/app/src/main/res/values-hi/strings.xml
@@ -1447,4 +1447,10 @@
रिपॉज़िटरी अपडेट नहीं हो सकीं
रद्द किया जा रहा है...
अपडेट रद्द किया गया
+ पहले dashboard अपडेट करें
+ इंस्टॉल होने से पहले इस मॉड्यूल को dashboard के %1$s या नए संस्करण की ज़रूरत है।
+ dashboard अपडेट करें
+ dashboard अपडेट उपलब्ध है
+ अनुशंसित है कि पहले dashboard अपडेट करें ताकि मॉड्यूल की नई सुविधाएँ सही से काम करें।
+ फिर भी इंस्टॉल करें
diff --git a/controller/app/src/main/res/values-hu/strings.xml b/controller/app/src/main/res/values-hu/strings.xml
index 21f5c57a5..482ac6ede 100644
--- a/controller/app/src/main/res/values-hu/strings.xml
+++ b/controller/app/src/main/res/values-hu/strings.xml
@@ -1370,4 +1370,10 @@
Nem sikerult frissiteni az adattarakat
Megszakitas...
Frissites megszakitva
+ Eloszor frissitse a dashboardot
+ Ehhez a modulhoz a dashboard %1$s vagy ujabb verzioja szukseges a telepites elott.
+ Dashboard frissitese
+ Elerheto a dashboard frissitese
+ Ajanlott eloszor frissiteni a dashboardot, hogy az uj modulfunkciok megfeleloen mukodjenek.
+ Telepites mindenkepp
diff --git a/controller/app/src/main/res/values-in/strings.xml b/controller/app/src/main/res/values-in/strings.xml
index 6cd5d9fb3..fdf692ed6 100644
--- a/controller/app/src/main/res/values-in/strings.xml
+++ b/controller/app/src/main/res/values-in/strings.xml
@@ -1377,4 +1377,10 @@
Tidak dapat memperbarui repositori
Membatalkan...
Pembaruan dibatalkan
+ Perbarui dashboard dulu
+ Modul ini memerlukan dashboard versi %1$s atau lebih baru sebelum dapat dipasang.
+ Perbarui dashboard
+ Pembaruan dashboard tersedia
+ Disarankan memperbarui dashboard dulu agar fitur baru modul berfungsi dengan benar.
+ Tetap pasang
diff --git a/controller/app/src/main/res/values-it/strings.xml b/controller/app/src/main/res/values-it/strings.xml
index 576ecf3d4..d370f067e 100644
--- a/controller/app/src/main/res/values-it/strings.xml
+++ b/controller/app/src/main/res/values-it/strings.xml
@@ -1370,4 +1370,10 @@
Impossibile aggiornare i repository
Annullamento...
Aggiornamento annullato
+ Aggiorna prima il dashboard
+ Questo modulo richiede il dashboard aggiornato alla versione %1$s o successiva prima di poter essere installato.
+ Aggiorna dashboard
+ E disponibile un aggiornamento del dashboard
+ Si consiglia di aggiornare prima il dashboard affinche le nuove funzioni del modulo funzionino bene.
+ Installa comunque
diff --git a/controller/app/src/main/res/values-ja/strings.xml b/controller/app/src/main/res/values-ja/strings.xml
index a30291b2f..06a0f3448 100644
--- a/controller/app/src/main/res/values-ja/strings.xml
+++ b/controller/app/src/main/res/values-ja/strings.xml
@@ -1371,4 +1371,10 @@
リポジトリを更新できませんでした
キャンセルしています...
更新をキャンセルしました
+ 先に dashboard を更新してください
+ このモジュールをインストールするには dashboard のバージョン %1$s 以降が必要です。
+ dashboard を更新
+ dashboard の更新があります
+ モジュールの新機能が正しく動作するよう、先に dashboard を更新することをおすすめします。
+ それでもインストール
diff --git a/controller/app/src/main/res/values-ko/strings.xml b/controller/app/src/main/res/values-ko/strings.xml
index dd23ffab6..445767e50 100644
--- a/controller/app/src/main/res/values-ko/strings.xml
+++ b/controller/app/src/main/res/values-ko/strings.xml
@@ -1371,4 +1371,10 @@
저장소를 업데이트할 수 없습니다
취소 중...
업데이트 취소됨
+ 먼저 dashboard를 업데이트하세요
+ 이 모듈을 설치하려면 dashboard %1$s 이상 버전이 필요합니다.
+ dashboard 업데이트
+ dashboard 업데이트가 있습니다
+ 모듈의 새 기능이 제대로 작동하도록 먼저 dashboard를 업데이트하는 것이 좋습니다.
+ 무시하고 설치
diff --git a/controller/app/src/main/res/values-lt/strings.xml b/controller/app/src/main/res/values-lt/strings.xml
index 75d716273..4af76665e 100644
--- a/controller/app/src/main/res/values-lt/strings.xml
+++ b/controller/app/src/main/res/values-lt/strings.xml
@@ -1387,4 +1387,10 @@
Nepavyko atnaujinti saugyklu
Atsaukiama...
Atnaujinimas atsauktas
+ Pirma atnaujinkite dashboard
+ Siam moduliui reikia dashboard %1$s ar naujesnes versijos, kad ji butu galima idiegti.
+ Atnaujinti dashboard
+ Yra dashboard atnaujinimas
+ Rekomenduojama pirma atnaujinti dashboard, kad naujos modulio funkcijos veiktu tinkamai.
+ Vis tiek idiegti
diff --git a/controller/app/src/main/res/values-nl/strings.xml b/controller/app/src/main/res/values-nl/strings.xml
index 277ce699e..492453d33 100644
--- a/controller/app/src/main/res/values-nl/strings.xml
+++ b/controller/app/src/main/res/values-nl/strings.xml
@@ -1370,4 +1370,10 @@
Kan de repository\'s niet bijwerken
Annuleren...
Bijwerken geannuleerd
+ Werk eerst het dashboard bij
+ Deze module heeft het dashboard in versie %1$s of nieuwer nodig voordat het geinstalleerd kan worden.
+ Dashboard bijwerken
+ Er is een dashboard-update beschikbaar
+ Het wordt aanbevolen eerst het dashboard bij te werken zodat nieuwe modulefuncties goed werken.
+ Toch installeren
diff --git a/controller/app/src/main/res/values-no/strings.xml b/controller/app/src/main/res/values-no/strings.xml
index ff481e03b..27b2e8a93 100644
--- a/controller/app/src/main/res/values-no/strings.xml
+++ b/controller/app/src/main/res/values-no/strings.xml
@@ -1380,4 +1380,10 @@
Kunne ikke oppdatere repositoriene
Avbryter...
Oppdatering avbrutt
+ Oppdater dashboard forst
+ Denne modulen trenger dashboard i versjon %1$s eller nyere for den kan installeres.
+ Oppdater dashboard
+ En dashboard-oppdatering er tilgjengelig
+ Det anbefales a oppdatere dashboard forst slik at nye modulfunksjoner fungerer riktig.
+ Installer likevel
diff --git a/controller/app/src/main/res/values-pl/strings.xml b/controller/app/src/main/res/values-pl/strings.xml
index 50f41afca..4834f2a2f 100644
--- a/controller/app/src/main/res/values-pl/strings.xml
+++ b/controller/app/src/main/res/values-pl/strings.xml
@@ -1380,4 +1380,10 @@
Nie udalo sie zaktualizowac repozytoriow
Anulowanie...
Aktualizacja anulowana
+ Najpierw zaktualizuj dashboard
+ Ten modul wymaga dashboardu w wersji %1$s lub nowszej, zanim bedzie mozna go zainstalowac.
+ Zaktualizuj dashboard
+ Dostepna jest aktualizacja dashboardu
+ Zalecane jest najpierw zaktualizowanie dashboardu, aby nowe funkcje modulu dzialaly poprawnie.
+ Zainstaluj mimo to
diff --git a/controller/app/src/main/res/values-pt/strings.xml b/controller/app/src/main/res/values-pt/strings.xml
index 9dea3c8e4..e25e8bbad 100644
--- a/controller/app/src/main/res/values-pt/strings.xml
+++ b/controller/app/src/main/res/values-pt/strings.xml
@@ -1449,4 +1449,10 @@
Nao foi possivel atualizar os repositorios
Cancelando...
Atualizacao cancelada
+ Atualize primeiro o dashboard
+ Este modulo precisa do dashboard atualizado para a versao %1$s ou mais recente antes de poder ser instalado.
+ Atualizar dashboard
+ Ha uma atualizacao do dashboard disponivel
+ Recomenda-se atualizar o dashboard primeiro para que os novos recursos do modulo funcionem corretamente.
+ Instalar mesmo assim
diff --git a/controller/app/src/main/res/values-ro/strings.xml b/controller/app/src/main/res/values-ro/strings.xml
index 1ca176c50..2212c0416 100644
--- a/controller/app/src/main/res/values-ro/strings.xml
+++ b/controller/app/src/main/res/values-ro/strings.xml
@@ -1370,4 +1370,10 @@
Depozitele nu au putut fi actualizate
Se anuleaza...
Actualizare anulata
+ Actualizeaza mai intai dashboardul
+ Acest modul are nevoie de dashboard in versiunea %1$s sau mai noua inainte de a putea fi instalat.
+ Actualizeaza dashboardul
+ Este disponibila o actualizare a dashboardului
+ Se recomanda actualizarea dashboardului mai intai, pentru ca noile functii ale modulului sa functioneze corect.
+ Instaleaza oricum
diff --git a/controller/app/src/main/res/values-ru-rRU/strings.xml b/controller/app/src/main/res/values-ru-rRU/strings.xml
index 0c0e7b3da..8821dadc0 100644
--- a/controller/app/src/main/res/values-ru-rRU/strings.xml
+++ b/controller/app/src/main/res/values-ru-rRU/strings.xml
@@ -1446,4 +1446,10 @@
Не удалось обновить репозитории
Отмена...
Обновление отменено
+ Сначала обновите dashboard
+ Этому модулю нужен dashboard версии %1$s или новее перед установкой.
+ Обновить dashboard
+ Доступно обновление dashboard
+ Рекомендуется сначала обновить dashboard, чтобы новые функции модуля работали правильно.
+ Всё равно установить
diff --git a/controller/app/src/main/res/values-sk/strings.xml b/controller/app/src/main/res/values-sk/strings.xml
index 93ee06269..acd30a2d7 100644
--- a/controller/app/src/main/res/values-sk/strings.xml
+++ b/controller/app/src/main/res/values-sk/strings.xml
@@ -1377,4 +1377,10 @@
Repozitare sa nepodarilo aktualizovat
Rusi sa...
Aktualizacia zrusena
+ Najprv aktualizujte dashboard
+ Tento modul potrebuje dashboard vo verzii %1$s alebo novsej, nez ho bude mozne nainstalovat.
+ Aktualizovat dashboard
+ Je dostupna aktualizacia dashboardu
+ Odporucame najprv aktualizovat dashboard, aby nove funkcie modulu fungovali spravne.
+ Aj tak nainstalovat
diff --git a/controller/app/src/main/res/values-sr/strings.xml b/controller/app/src/main/res/values-sr/strings.xml
index 08bea847c..81ef37814 100644
--- a/controller/app/src/main/res/values-sr/strings.xml
+++ b/controller/app/src/main/res/values-sr/strings.xml
@@ -1383,4 +1383,10 @@
Није могуће ажурирати репозиторијуме
Отказивање...
Ажурирање отказано
+ Прво ажурирајте dashboard
+ Овом модулу је потребан dashboard верзије %1$s или новије пре инсталације.
+ Ажурирај dashboard
+ Доступно је ажурирање dashboard-а
+ Препоручује се да прво ажурирате dashboard како би нове функције модула радиле исправно.
+ Ипак инсталирај
diff --git a/controller/app/src/main/res/values-sw/strings.xml b/controller/app/src/main/res/values-sw/strings.xml
index d790c4dde..3c60425d7 100644
--- a/controller/app/src/main/res/values-sw/strings.xml
+++ b/controller/app/src/main/res/values-sw/strings.xml
@@ -1390,4 +1390,10 @@
Imeshindwa kusasisha hazina
Inaghairi...
Usasishaji umeghairiwa
+ Sasisha dashboard kwanza
+ Moduli hii inahitaji dashboard toleo la %1$s au jipya zaidi kabla ya kusakinishwa.
+ Sasisha dashboard
+ Sasisho la dashboard linapatikana
+ Inashauriwa kusasisha dashboard kwanza ili vipengele vipya vya moduli vifanye kazi vizuri.
+ Sakinisha hata hivyo
diff --git a/controller/app/src/main/res/values-ta/strings.xml b/controller/app/src/main/res/values-ta/strings.xml
index 6ad9b7de3..58136b32f 100644
--- a/controller/app/src/main/res/values-ta/strings.xml
+++ b/controller/app/src/main/res/values-ta/strings.xml
@@ -1390,4 +1390,10 @@
களஞ்சியங்களைப் புதுப்பிக்க முடியவில்லை
ரத்து செய்யப்படுகிறது...
புதுப்பிப்பு ரத்து செய்யப்பட்டது
+ முதலில் dashboard ஐப் புதுப்பிக்கவும்
+ நிறுவப்படுவதற்கு முன் இந்த தொகுதிக்கு dashboard பதிப்பு %1$s அல்லது புதியது தேவை.
+ dashboard ஐப் புதுப்பி
+ dashboard புதுப்பிப்பு உள்ளது
+ தொகுதியின் புதிய அம்சங்கள் சரியாக இயங்க முதலில் dashboard ஐப் புதுப்பிக்க பரிந்துரைக்கப்படுகிறது.
+ இருப்பினும் நிறுவு
diff --git a/controller/app/src/main/res/values-tr/strings.xml b/controller/app/src/main/res/values-tr/strings.xml
index 6617d5778..26e5c3ed2 100644
--- a/controller/app/src/main/res/values-tr/strings.xml
+++ b/controller/app/src/main/res/values-tr/strings.xml
@@ -1370,4 +1370,10 @@
Depolar guncellenemedi
Iptal ediliyor...
Guncelleme iptal edildi
+ Once dashboard\'u guncelleyin
+ Bu modul, kurulabilmesi icin dashboard\'un %1$s veya daha yeni surumune ihtiyac duyar.
+ Dashboard\'u guncelle
+ Bir dashboard guncellemesi mevcut
+ Yeni modul ozelliklerinin duzgun calismasi icin once dashboard\'u guncellemeniz onerilir.
+ Yine de yukle
diff --git a/controller/app/src/main/res/values-uk/strings.xml b/controller/app/src/main/res/values-uk/strings.xml
index 65361e3e0..33bcf9835 100644
--- a/controller/app/src/main/res/values-uk/strings.xml
+++ b/controller/app/src/main/res/values-uk/strings.xml
@@ -1370,4 +1370,10 @@
Не вдалося оновити репозиторії
Скасування...
Оновлення скасовано
+ Спочатку оновіть dashboard
+ Цьому модулю потрібен dashboard версії %1$s або новішої перед встановленням.
+ Оновити dashboard
+ Доступне оновлення dashboard
+ Рекомендовано спочатку оновити dashboard, щоб нові функції модуля працювали правильно.
+ Усе одно встановити
diff --git a/controller/app/src/main/res/values-vi/strings.xml b/controller/app/src/main/res/values-vi/strings.xml
index 87efacda8..921240390 100644
--- a/controller/app/src/main/res/values-vi/strings.xml
+++ b/controller/app/src/main/res/values-vi/strings.xml
@@ -1370,4 +1370,10 @@
Khong the cap nhat kho
Dang huy...
Da huy cap nhat
+ Cap nhat dashboard truoc
+ Mo-dun nay can dashboard phien ban %1$s tro len truoc khi co the cai dat.
+ Cap nhat dashboard
+ Da co ban cap nhat dashboard
+ Nen cap nhat dashboard truoc de cac tinh nang moi cua mo-dun hoat dong dung.
+ Van cai dat
diff --git a/controller/app/src/main/res/values-yo/strings.xml b/controller/app/src/main/res/values-yo/strings.xml
index 776646189..1dc8f85e9 100644
--- a/controller/app/src/main/res/values-yo/strings.xml
+++ b/controller/app/src/main/res/values-yo/strings.xml
@@ -1390,4 +1390,10 @@
Ko seese lati se imudojuiwon awon ibi itoju
Nfagile...
A ti fagile imudojuiwon
+ Kokoo se imudojuiwon dashboard
+ Modulu yii nilo dashboard eda %1$s tabi tuntun ki o to le fi sori ero.
+ Se imudojuiwon dashboard
+ Imudojuiwon dashboard wa
+ A gba o nimoran lati kokoo se imudojuiwon dashboard ki awon eya tuntun ti modulu le sise daradara.
+ Fi sori ero lonakona
diff --git a/controller/app/src/main/res/values-zh-rCN/strings.xml b/controller/app/src/main/res/values-zh-rCN/strings.xml
index 32962d0cb..cf9972dcb 100644
--- a/controller/app/src/main/res/values-zh-rCN/strings.xml
+++ b/controller/app/src/main/res/values-zh-rCN/strings.xml
@@ -1371,4 +1371,10 @@
无法更新仓库
正在取消...
更新已取消
+ 请先更新 dashboard
+ 此模块需要 dashboard 更新到 %1$s 或更高版本才能安装。
+ 更新 dashboard
+ 有可用的 dashboard 更新
+ 建议先更新 dashboard,以便模块的新功能正常运行。
+ 仍然安装
diff --git a/controller/app/src/main/res/values/strings.xml b/controller/app/src/main/res/values/strings.xml
index df6c87c3f..abf6d470a 100644
--- a/controller/app/src/main/res/values/strings.xml
+++ b/controller/app/src/main/res/values/strings.xml
@@ -1556,4 +1556,10 @@
Could not update the repositories
Cancelling...
Update cancelled
+ Update the dashboard first
+ This module needs the dashboard updated to %1$s or newer before it can be installed.
+ Update dashboard
+ A dashboard update is available
+ Updating the dashboard first is recommended so new module features work correctly.
+ Install anyway
diff --git a/controller/app/src/test/java/org/appdevforall/k2go/dependency/domain/DashNodeRequirementTest.java b/controller/app/src/test/java/org/appdevforall/k2go/dependency/domain/DashNodeRequirementTest.java
new file mode 100644
index 000000000..66ff5b76e
--- /dev/null
+++ b/controller/app/src/test/java/org/appdevforall/k2go/dependency/domain/DashNodeRequirementTest.java
@@ -0,0 +1,31 @@
+package org.appdevforall.k2go.dependency.domain;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+import org.junit.Test;
+
+/** K2GO-430: the per-module dash-node minimum registry. Pure data, so a plain JVM test. */
+public class DashNodeRequirementTest {
+
+ @Test
+ public void forgejoRequiresOneThreeSeven() {
+ assertArrayEquals(new int[]{1, 3, 7}, DashNodeRequirement.minFor("forgejo"));
+ assertEquals("1.3.7", DashNodeRequirement.minLabel("forgejo"));
+ }
+
+ @Test
+ public void otherModulesHaveNoHardMinimum() {
+ assertNull(DashNodeRequirement.minFor("kiwix"));
+ assertNull(DashNodeRequirement.minFor("maps"));
+ assertNull(DashNodeRequirement.minLabel("kolibri"));
+ }
+
+ @Test
+ public void nullOrUnknownKeyIsSafe() {
+ assertNull(DashNodeRequirement.minFor(null));
+ assertNull(DashNodeRequirement.minLabel(null));
+ assertNull(DashNodeRequirement.minFor(""));
+ }
+}
diff --git a/controller/app/src/test/java/org/appdevforall/k2go/redesign/DashboardVersionTest.java b/controller/app/src/test/java/org/appdevforall/k2go/redesign/DashboardVersionTest.java
new file mode 100644
index 000000000..ed4c6bc46
--- /dev/null
+++ b/controller/app/src/test/java/org/appdevforall/k2go/redesign/DashboardVersionTest.java
@@ -0,0 +1,45 @@
+package org.appdevforall.k2go.redesign;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Test;
+
+/** K2GO-430: the version compare behind the dash-node dependency gate (installBlocked uses it). Pure,
+ * so a plain JVM test; installed(Context) reads a file and is not covered here. */
+public class DashboardVersionTest {
+
+ @Test
+ public void nullOrJunkIsBelowAnyMinimum() {
+ assertFalse(DashboardVersion.atLeast(null, 1, 3, 7));
+ assertFalse(DashboardVersion.atLeast("", 1, 3, 7));
+ assertFalse(DashboardVersion.atLeast("not-a-version", 1, 3, 7));
+ }
+
+ @Test
+ public void exactMinimumMeetsIt() {
+ assertTrue(DashboardVersion.atLeast("1.3.7", 1, 3, 7));
+ }
+
+ @Test
+ public void belowMinimumFails() {
+ assertFalse(DashboardVersion.atLeast("1.3.6", 1, 3, 7));
+ assertFalse(DashboardVersion.atLeast("1.2.9", 1, 3, 7));
+ assertFalse(DashboardVersion.atLeast("0.9.9", 1, 3, 7));
+ assertFalse(DashboardVersion.atLeast("1.3", 1, 3, 7)); // missing patch = .0, so 1.3.0 < 1.3.7
+ }
+
+ @Test
+ public void aboveMinimumPasses() {
+ assertTrue(DashboardVersion.atLeast("1.3.8", 1, 3, 7));
+ assertTrue(DashboardVersion.atLeast("1.3.10", 1, 3, 7)); // numeric compare, not lexical
+ assertTrue(DashboardVersion.atLeast("1.4.0", 1, 3, 7));
+ assertTrue(DashboardVersion.atLeast("2.0.0", 1, 3, 7));
+ }
+
+ @Test
+ public void suffixesAreIgnored() {
+ assertTrue(DashboardVersion.atLeast("1.3.7-beta", 1, 3, 7));
+ assertTrue(DashboardVersion.atLeast("1.4.0+build5", 1, 3, 7));
+ }
+}