From aa6561084c1e15515a75b5e0c238a99dea023a31 Mon Sep 17 00:00:00 2001 From: Luis Guzman Date: Thu, 6 Aug 2026 14:58:00 -0600 Subject: [PATCH 1/4] ADFA-5051: dash-node 1.2.0 live self-update + version-gated update routing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sets 1.2.0 as the self-update cutover baseline. From 1.2.0 the app updates the dash-node core LIVE over REST (POST /system/dashboard/rebuild — the blue-green staged/smoke-tested/atomic-swap/rollback rebuild from ADFA-5011); installs on < 1.2.0 take the proot rebuild once as a bridge to 1.2.0. Server: bump package.json + lock to 1.2.0 + CHANGELOG (no endpoint change). App: - DashboardClient: rebuildStart (POST, maps 409 = already running) + rebuildStatus. - DashboardVersion.atLeast(): semver gate (null -> false, defaults to proot). - DashboardRebuild: version-gated start() -> startRest (trigger + poll status in a progress dialog, tolerating the brief restart window) vs startProot (existing). - New live-update strings + 33-locale l10n. Reviewed via /engineering:code-review; fixes applied: version read moved off the main thread; poll timeout shows a distinct "finishing in background" message instead of the rollback/failure copy; single reused poller Handler; dropped the unnecessary FixedLengthStreamingMode on the bodyless POST. Static-verified only (tsc + javalang + XML). NOT yet run on a device: the live REST rebuild flow (trigger/poll/restart tolerance/rollback) is pending a controlled test. --- .../controller/redesign/DashboardClient.java | 62 +++++++++ .../controller/redesign/DashboardRebuild.java | 130 ++++++++++++++++-- .../controller/redesign/DashboardVersion.java | 15 ++ .../src/main/res/values-ar/strings_k2go.xml | 6 + .../src/main/res/values-az/strings_k2go.xml | 6 + .../src/main/res/values-bg/strings_k2go.xml | 6 + .../src/main/res/values-bn/strings_k2go.xml | 6 + .../src/main/res/values-cs/strings_k2go.xml | 6 + .../src/main/res/values-de/strings_k2go.xml | 6 + .../src/main/res/values-el/strings_k2go.xml | 6 + .../src/main/res/values-es/strings_k2go.xml | 6 + .../src/main/res/values-fa/strings_k2go.xml | 6 + .../src/main/res/values-fr/strings_k2go.xml | 6 + .../src/main/res/values-gu/strings_k2go.xml | 6 + .../src/main/res/values-hi/strings_k2go.xml | 6 + .../src/main/res/values-hu/strings_k2go.xml | 6 + .../src/main/res/values-in/strings_k2go.xml | 6 + .../src/main/res/values-it/strings_k2go.xml | 6 + .../src/main/res/values-ja/strings_k2go.xml | 6 + .../src/main/res/values-ko/strings_k2go.xml | 6 + .../src/main/res/values-lt/strings_k2go.xml | 6 + .../src/main/res/values-nl/strings_k2go.xml | 6 + .../src/main/res/values-no/strings_k2go.xml | 6 + .../src/main/res/values-pl/strings_k2go.xml | 6 + .../src/main/res/values-pt/strings_k2go.xml | 6 + .../src/main/res/values-ro/strings_k2go.xml | 6 + .../main/res/values-ru-rRU/strings_k2go.xml | 6 + .../src/main/res/values-sk/strings_k2go.xml | 6 + .../src/main/res/values-sr/strings_k2go.xml | 6 + .../src/main/res/values-sw/strings_k2go.xml | 6 + .../src/main/res/values-ta/strings_k2go.xml | 6 + .../src/main/res/values-tr/strings_k2go.xml | 6 + .../src/main/res/values-uk/strings_k2go.xml | 6 + .../src/main/res/values-vi/strings_k2go.xml | 6 + .../src/main/res/values-yo/strings_k2go.xml | 6 + .../main/res/values-zh-rCN/strings_k2go.xml | 6 + .../app/src/main/res/values/strings_k2go.xml | 7 + static/dashboard/CHANGELOG.md | 1 + static/dashboard/package-lock.json | 4 +- static/dashboard/package.json | 2 +- 40 files changed, 407 insertions(+), 12 deletions(-) diff --git a/controller/app/src/main/java/org/iiab/controller/redesign/DashboardClient.java b/controller/app/src/main/java/org/iiab/controller/redesign/DashboardClient.java index f2b9f5ee..a9015e35 100644 --- a/controller/app/src/main/java/org/iiab/controller/redesign/DashboardClient.java +++ b/controller/app/src/main/java/org/iiab/controller/redesign/DashboardClient.java @@ -32,6 +32,8 @@ public final class DashboardClient { private DashboardClient() {} private static final String URL_UPDATE_CHECK = BoxEndpoints.API + "/system/dashboard/update-check"; + private static final String URL_REBUILD = BoxEndpoints.API + "/system/dashboard/rebuild"; + private static final String URL_REBUILD_STATUS = BoxEndpoints.API + "/system/dashboard/rebuild/status"; private static final Handler MAIN = new Handler(Looper.getMainLooper()); public interface UpdateCb { @@ -39,6 +41,47 @@ public interface UpdateCb { void onErr(String message); } + /** ADFA-5051: result of triggering the live REST rebuild. {@code alreadyRunning} = the box reported + * a rebuild already in progress (HTTP 409) — the caller can just start polling status. */ + public interface RebuildStartCb { + void onStarted(boolean alreadyRunning); + void onErr(String message); + } + + /** ADFA-5051: current rebuild state from the box: idle | running | done | error. */ + public interface RebuildStatusCb { + void onState(String state); + void onErr(String message); + } + + /** ADFA-5051: trigger the in-server blue-green rebuild (POST). Fire-and-forget: the box returns 202 + * at once (or 409 if one is already running); the caller then polls {@link #rebuildStatus}. */ + public static void rebuildStart(RebuildStartCb cb) { + AppExecutors.get().io().execute(() -> { + int[] status = {0}; + try { + httpPost(URL_REBUILD, status); + MAIN.post(() -> cb.onStarted(false)); + } catch (Exception e) { + if (status[0] == 409) { MAIN.post(() -> cb.onStarted(true)); return; } + MAIN.post(() -> cb.onErr("could not start rebuild")); + } + }); + } + + /** ADFA-5051: read the rebuild state file the script writes (idle/running/done/error). */ + public static void rebuildStatus(RebuildStatusCb cb) { + AppExecutors.get().io().execute(() -> { + try { + JSONObject o = new JSONObject(httpGet(URL_REBUILD_STATUS)); + final String state = o.optString("state", "idle"); + MAIN.post(() -> cb.onState(state)); + } catch (Exception e) { + MAIN.post(() -> cb.onErr("status unavailable")); + } + }); + } + /** Ask the box whether a newer dash-node build is available. Runs off the main thread; the result * (or an error, when the box is stopped/offline) is posted back to the UI. */ public static void updateCheck(UpdateCb cb) { @@ -74,6 +117,25 @@ private static String httpGet(String urlStr) throws Exception { } } + /** POST with no body; {@code statusOut[0]} receives the HTTP status so callers can map 409. The + * trigger returns immediately (202), so a short read timeout is fine. */ + private static void httpPost(String urlStr, int[] statusOut) throws Exception { + HttpURLConnection c = (HttpURLConnection) new URL(urlStr).openConnection(); + try { + c.setUseCaches(false); + c.setConnectTimeout(5000); + c.setReadTimeout(10000); + c.setRequestMethod("POST"); // bodyless trigger; no doOutput/body needed + c.setRequestProperty("Accept", "application/json"); + int code = c.getResponseCode(); + statusOut[0] = code; + readAll(code >= 200 && code < 400 ? c.getInputStream() : c.getErrorStream()); + if (code < 200 || code >= 400) throw new Exception("HTTP " + code); + } finally { + c.disconnect(); + } + } + private static String readAll(InputStream is) throws Exception { if (is == null) return ""; ByteArrayOutputStream buf = new ByteArrayOutputStream(); diff --git a/controller/app/src/main/java/org/iiab/controller/redesign/DashboardRebuild.java b/controller/app/src/main/java/org/iiab/controller/redesign/DashboardRebuild.java index 272d7aeb..b4208a0c 100644 --- a/controller/app/src/main/java/org/iiab/controller/redesign/DashboardRebuild.java +++ b/controller/app/src/main/java/org/iiab/controller/redesign/DashboardRebuild.java @@ -3,11 +3,15 @@ * Name : DashboardRebuild.java * Author : AppDevForAll * Copyright : Copyright (c) 2026 AppDevForAll - * Description : ADFA-5011. Single entry point for starting a dash-node REST-core rebuild, shared by - * the Module-management hub row and the dashboard detail card so both offer the exact - * same gated flow: busy check (EnvironmentLock) -> internet check -> confirm dialog -> - * start the guarded InstallService rebuild + open the progress screen (which now stays - * put until the rebuild reaches SUCCESS/FAILED). + * Description : ADFA-5011 / ADFA-5051. Single entry point for starting a dash-node REST-core rebuild, + * shared by the Module-management hub row and the dashboard detail card. Gated flow: + * busy check (EnvironmentLock) -> internet check -> confirm dialog -> start. + * + * ADFA-5051 — version-gated cutover: from dash-node 1.2.0 the core updates ITSELF LIVE + * over REST (POST /system/dashboard/rebuild: the blue-green rebuild that stages, smoke- + * tests, atomically swaps and rolls back on failure — no rootfs/proot). Installs still + * on < 1.2.0 predate that, so they take the heavier proot rebuild (InstallService) once + * to reach 1.2.0; from there every later update is the live REST path. * ============================================================================ */ package org.iiab.controller.redesign; @@ -15,20 +19,34 @@ import android.content.Context; import android.content.Intent; import android.os.Build; +import android.os.Handler; +import android.os.Looper; +import android.view.Gravity; import android.view.View; +import android.widget.LinearLayout; +import android.widget.TextView; import androidx.annotation.NonNull; +import androidx.appcompat.app.AlertDialog; import androidx.fragment.app.Fragment; import com.google.android.material.dialog.MaterialAlertDialogBuilder; +import com.google.android.material.progressindicator.CircularProgressIndicator; import org.iiab.controller.R; import org.iiab.controller.install.presentation.InstallService; +import org.iiab.controller.util.AppExecutors; import org.iiab.controller.util.Snackbars; public final class DashboardRebuild { private DashboardRebuild() {} + // Live-rebuild poll cadence + overall cap. The blue-green rebuild does yarn install/build + smoke + // test + a dash-node restart, so allow a generous ceiling; the restart briefly makes the status + // endpoint unreachable, which we treat as "keep polling", not a failure. + private static final long POLL_MS = 2500L; + private static final int MAX_POLLS = 160; // ~6.5 min + /** Gate then confirm then start. {@code anchor} is where a "busy"/"no internet" snackbar shows. */ public static void confirmAndStart(@NonNull Fragment host, @NonNull View anchor) { Context ctx = host.requireContext(); @@ -44,13 +62,29 @@ public static void confirmAndStart(@NonNull Fragment host, @NonNull View anchor) .setTitle(R.string.k2go_dash_rebuild_confirm_title) .setMessage(R.string.k2go_dash_rebuild_confirm_msg) .setNegativeButton(android.R.string.cancel, null) - .setPositiveButton(R.string.k2go_dash_rebuild, (d, w) -> start(host)) + .setPositiveButton(R.string.k2go_dash_rebuild, (d, w) -> start(host, anchor)) .show(); } - /** Kick the foreground rebuild service and open the guarded progress screen (flagged as a rebuild - * so it stays on the animation and blocks leaving until the rebuild finishes). */ - private static void start(@NonNull Fragment host) { + /** ADFA-5051: route by the installed dash-node version. >= 1.2.0 updates live over REST; older + * installs take the proot rebuild once as a bridge to 1.2.0. The version read hits disk, so it + * runs off the main thread; the routing itself is posted back to the UI. */ + private static void start(@NonNull Fragment host, @NonNull View anchor) { + final Context app = host.requireContext().getApplicationContext(); + final Handler main = new Handler(Looper.getMainLooper()); + AppExecutors.get().io().execute(() -> { + final boolean rest = DashboardVersion.atLeast(DashboardVersion.installed(app), 1, 2, 0); + main.post(() -> { + if (!host.isAdded()) return; + if (rest) startRest(host, anchor); + else startProot(host); + }); + }); + } + + /** Kick the foreground proot rebuild service and open the guarded progress screen (flagged as a + * rebuild so it stays on the animation and blocks leaving until the rebuild finishes). */ + private static void startProot(@NonNull Fragment host) { Context ctx = host.requireContext(); Intent svc = new Intent(ctx, InstallService.class) .setAction(InstallService.ACTION_REBUILD_DASHBOARD); @@ -60,6 +94,84 @@ private static void start(@NonNull Fragment host) { .putExtra(SetupProgressActivity.EXTRA_REBUILD, true)); } + /** ADFA-5051: live REST update. Trigger the in-server rebuild, then show a non-cancelable progress + * dialog that polls the state until done/error (tolerating the brief restart window). */ + private static void startRest(@NonNull Fragment host, @NonNull View anchor) { + Context ctx = host.requireContext(); + LinearLayout box = new LinearLayout(ctx); + box.setOrientation(LinearLayout.HORIZONTAL); + box.setGravity(Gravity.CENTER_VERTICAL); + int pad = Math.round(24 * ctx.getResources().getDisplayMetrics().density); + box.setPadding(pad, pad, pad, pad); + CircularProgressIndicator spin = new CircularProgressIndicator(ctx); + spin.setIndeterminate(true); + box.addView(spin); + TextView msg = new TextView(ctx); + msg.setText(R.string.k2go_dash_live_running); + LinearLayout.LayoutParams mlp = new LinearLayout.LayoutParams(-2, -2); + mlp.leftMargin = pad; + msg.setLayoutParams(mlp); + box.addView(msg); + + final AlertDialog dialog = new MaterialAlertDialogBuilder(ctx) + .setTitle(R.string.k2go_dash_live_title) + .setView(box) + .setCancelable(false) + .show(); + + final Handler poller = new Handler(Looper.getMainLooper()); + DashboardClient.rebuildStart(new DashboardClient.RebuildStartCb() { + @Override public void onStarted(boolean alreadyRunning) { + if (!host.isAdded()) { safeDismiss(dialog); return; } + pollStatus(host, dialog, poller, new int[]{0}); + } + @Override public void onErr(String message) { + safeDismiss(dialog); + if (host.isAdded()) Snackbars.make(anchor, R.string.k2go_dash_live_start_failed).show(); + } + }); + } + + /** Poll rebuild state until a terminal one, reusing a single {@code poller} Handler. A status error + * is transient (dash-node restarts mid-swap) so we keep polling until MAX_POLLS. Hitting the cap is + * NOT a failure: the rebuild runs detached server-side and may still finish, so we show a distinct + * "still working in the background" message rather than the rollback/failure one. */ + private static void pollStatus(@NonNull Fragment host, @NonNull AlertDialog dialog, + @NonNull Handler poller, int[] tries) { + if (!host.isAdded()) { safeDismiss(dialog); return; } + if (tries[0]++ >= MAX_POLLS) { finishRest(host, dialog, R.string.k2go_dash_live_timeout); return; } + DashboardClient.rebuildStatus(new DashboardClient.RebuildStatusCb() { + @Override public void onState(String state) { + if (!host.isAdded()) { safeDismiss(dialog); return; } + if ("done".equals(state)) { finishRest(host, dialog, R.string.k2go_dash_live_done); return; } + if ("error".equals(state)) { finishRest(host, dialog, R.string.k2go_dash_live_error); return; } + schedule(); + } + @Override public void onErr(String message) { + if (!host.isAdded()) { safeDismiss(dialog); return; } + schedule(); // API likely restarting mid-swap; keep waiting + } + private void schedule() { + poller.postDelayed(() -> pollStatus(host, dialog, poller, tries), POLL_MS); + } + }); + } + + /** Swap the progress dialog for a simple result dialog carrying {@code msgRes} (done/error/timeout). */ + private static void finishRest(@NonNull Fragment host, @NonNull AlertDialog dialog, int msgRes) { + safeDismiss(dialog); + if (!host.isAdded()) return; + new MaterialAlertDialogBuilder(host.requireContext()) + .setTitle(R.string.k2go_dash_live_title) + .setMessage(msgRes) + .setPositiveButton(android.R.string.ok, null) + .show(); + } + + private static void safeDismiss(@NonNull AlertDialog d) { + try { if (d.isShowing()) d.dismiss(); } catch (Exception ignore) { /* activity gone */ } + } + /** True when the device reports an internet-capable active network. Unknown -> true (let the * preflight decide), matching the previous inline check in ModuleHubFragment. */ public static boolean hasInternet(@NonNull Context ctx) { diff --git a/controller/app/src/main/java/org/iiab/controller/redesign/DashboardVersion.java b/controller/app/src/main/java/org/iiab/controller/redesign/DashboardVersion.java index 87947e96..54154f43 100644 --- a/controller/app/src/main/java/org/iiab/controller/redesign/DashboardVersion.java +++ b/controller/app/src/main/java/org/iiab/controller/redesign/DashboardVersion.java @@ -27,6 +27,21 @@ public final class DashboardVersion { private DashboardVersion() {} + /** ADFA-5051: true when {@code version} (x.y.z, any suffix ignored) is >= major.minor.patch. + * A null/unparseable version returns false, so callers default to the safe (proot) path. */ + public static boolean atLeast(@Nullable String version, int major, int minor, int patch) { + if (version == null) return false; + String core = version.split("[-+]", 2)[0]; // drop any "-beta"/"+build" suffix + String[] p = core.split("\\."); + int[] want = {major, minor, patch}; + for (int i = 0; i < 3; i++) { + int have = 0; + if (i < p.length) { try { have = Integer.parseInt(p[i].trim()); } catch (NumberFormatException e) { have = 0; } } + if (have != want[i]) return have > want[i]; + } + return true; // exactly equal + } + /** Installed dash-node version from the rootfs package.json, or null if not found/parseable. */ @Nullable public static String installed(@NonNull Context ctx) { diff --git a/controller/app/src/main/res/values-ar/strings_k2go.xml b/controller/app/src/main/res/values-ar/strings_k2go.xml index a4182617..3213fb20 100644 --- a/controller/app/src/main/res/values-ar/strings_k2go.xml +++ b/controller/app/src/main/res/values-ar/strings_k2go.xml @@ -680,6 +680,12 @@ إعادة بناء نواة REST؟ تُحدِّث dash-node إلى أحدث إصدار. يكون الخادم غير متاح لفترة وجيزة أثناء إعادة البناء؛ لا تغادر هذه الشاشة حتى تنتهي. تتطلب إعادة البناء اتصالاً بالإنترنت. + جارٍ تحديث لوحة التحكم + جارٍ التحديث في مكانه… ستُعاد تشغيل لوحة التحكم لفترة وجيزة. + تم تحديث لوحة التحكم. + فشل التحديث — تم الاحتفاظ بالإصدار السابق. + يستغرق هذا وقتًا أطول من المعتاد. سيكتمل في الخلفية — تحقّق من الإصدار بعد قليل. + تعذّر بدء التحديث. حاول مرة أخرى. Dashboard (REST API) نواة النظام · مثبَّتة دائمًا لوحة التحكم هي نواة واجهة REST API للجهاز (dash-node): خدمة Node صغيرة على 127.0.0.1:4000، يقدّمها nginx ويشرف عليها pdsm. تُشغِّل كل إجراء للمكتبة داخل التطبيق: تصفّح الكتب وتنزيلها، وإضافة محتوى Wikipedia وZIM وحذفه، وجلسات Kolibri، والخرائط، وحالة النظام. على عكس وحدات المحتوى، لا تُثبَّت ولا تُزال — فهي تأتي مع الجهاز وموجودة دائمًا. عند توفّر إصدار أحدث يمكنك إعادة بنائها في مكانها. diff --git a/controller/app/src/main/res/values-az/strings_k2go.xml b/controller/app/src/main/res/values-az/strings_k2go.xml index 9d5e6636..42369a37 100644 --- a/controller/app/src/main/res/values-az/strings_k2go.xml +++ b/controller/app/src/main/res/values-az/strings_k2go.xml @@ -680,6 +680,12 @@ REST nüvəsi yenidən qurulsun? dash-node-u ən son versiyaya yeniləyir. Yenidən qurma zamanı server qısa müddət əlçatmaz olur; bitənə qədər bu ekranı tərk etməyin. Yenidən qurma internet bağlantısı tələb edir. + İdarə paneli yenilənir + Yerində yenilənir… idarə paneli qısa müddət yenidən başladılacaq. + İdarə paneli yeniləndi. + Yeniləmə alınmadı — əvvəlki versiya saxlanıldı. + Bu adətən olduğundan uzun çəkir. Arxa planda tamamlanacaq — bir azdan versiyanı yoxlayın. + Yeniləməni başlatmaq alınmadı. Yenidən cəhd edin. Dashboard (REST API) Sistem nüvəsi · həmişə quraşdırılıb Panel qutunun REST API nüvəsidir (dash-node): 127.0.0.1:4000 ünvanında işləyən, nginx tərəfindən təqdim edilən və pdsm tərəfindən idarə olunan kiçik Node xidmətidir. O, tətbiqdəki bütün kitabxana əməliyyatlarını işə salır: Kitablara baxış və endirmə, Wikipedia və ZIM məzmununun əlavə edilməsi və silinməsi, Kolibri sessiyaları, Xəritələr və sistem vəziyyəti. Məzmun modullarından fərqli olaraq quraşdırılmır və silinmir — qutu ilə birlikdə gəlir və həmişə mövcuddur. Daha yeni versiya olduqda onu yerində yenidən qura bilərsiniz. diff --git a/controller/app/src/main/res/values-bg/strings_k2go.xml b/controller/app/src/main/res/values-bg/strings_k2go.xml index 96e7ec0d..84cde47c 100644 --- a/controller/app/src/main/res/values-bg/strings_k2go.xml +++ b/controller/app/src/main/res/values-bg/strings_k2go.xml @@ -680,6 +680,12 @@ Да се пресъздаде ли REST ядрото? Актуализира dash-node до най-новата версия. Сървърът е за кратко недостъпен по време на пресъздаването; не напускайте този екран, докато не приключи. Пресъздаването изисква интернет връзка. + Обновяване на таблото + Обновяване на място… таблото се рестартира за кратко. + Таблото е обновено. + Обновяването е неуспешно — предишната версия е запазена. + Това отнема повече от обичайното. Ще завърши на заден план — проверете версията след малко. + Обновяването не можа да започне. Опитайте отново. Dashboard (REST API) Системно ядро · винаги инсталирано Таблото е REST API ядрото на устройството (dash-node): малка Node услуга на 127.0.0.1:4000, обслужвана от nginx и наблюдавана от pdsm. То захранва всяко действие на библиотеката в приложението: разглеждане и изтегляне на Книги, добавяне и изтриване на съдържание от Wikipedia и ZIM, сесии на Kolibri, Карти и състояние на системата. За разлика от модулите за съдържание, то не се инсталира и не се премахва — идва с устройството и винаги присъства. Когато има по-нова версия, можете да го пресъздадете на място. diff --git a/controller/app/src/main/res/values-bn/strings_k2go.xml b/controller/app/src/main/res/values-bn/strings_k2go.xml index 51db2a38..c3b714c0 100644 --- a/controller/app/src/main/res/values-bn/strings_k2go.xml +++ b/controller/app/src/main/res/values-bn/strings_k2go.xml @@ -680,6 +680,12 @@ REST কোর পুনর্নির্মাণ করবেন? dash-node কে সর্বশেষ সংস্করণে আপডেট করে। পুনর্নির্মাণের সময় সার্ভার কিছুক্ষণের জন্য অনুপলব্ধ থাকে; শেষ না হওয়া পর্যন্ত এই স্ক্রিন ছেড়ে যাবেন না। পুনর্নির্মাণের জন্য ইন্টারনেট সংযোগ প্রয়োজন। + ড্যাশবোর্ড আপডেট হচ্ছে + স্থানেই আপডেট হচ্ছে… ড্যাশবোর্ড কিছুক্ষণের জন্য রিস্টার্ট হবে। + ড্যাশবোর্ড আপডেট হয়েছে। + আপডেট ব্যর্থ হয়েছে — পূর্ববর্তী সংস্করণটি রাখা হয়েছে। + এটি স্বাভাবিকের চেয়ে বেশি সময় নিচ্ছে। এটি ব্যাকগ্রাউন্ডে সম্পন্ন হবে — একটু পরে সংস্করণটি দেখুন। + আপডেট শুরু করা যায়নি। আবার চেষ্টা করুন। Dashboard (REST API) সিস্টেম কোর · সর্বদা ইনস্টল করা ড্যাশবোর্ড হলো বাক্সের REST API কোর (dash-node): 127.0.0.1:4000-এ একটি ছোট Node পরিষেবা, যা nginx পরিবেশন করে এবং pdsm তত্ত্বাবধান করে। এটি অ্যাপে প্রতিটি লাইব্রেরি ক্রিয়া চালায়: বই ব্রাউজ ও ডাউনলোড, Wikipedia ও ZIM কনটেন্ট যোগ ও মুছে ফেলা, Kolibri সেশন, মানচিত্র এবং সিস্টেম অবস্থা। কনটেন্ট মডিউলের বিপরীতে, এটি ইনস্টল বা সরানো হয় না — এটি বাক্সের সাথে আসে এবং সবসময় উপস্থিত থাকে। নতুন সংস্করণ পাওয়া গেলে আপনি এটি জায়গাতেই পুনর্নির্মাণ করতে পারেন। diff --git a/controller/app/src/main/res/values-cs/strings_k2go.xml b/controller/app/src/main/res/values-cs/strings_k2go.xml index c68e02f8..49a85d51 100644 --- a/controller/app/src/main/res/values-cs/strings_k2go.xml +++ b/controller/app/src/main/res/values-cs/strings_k2go.xml @@ -680,6 +680,12 @@ Přestavět jádro REST? Aktualizuje dash-node na nejnovější verzi. Server je během přestavby krátce nedostupný; neopouštějte tuto obrazovku, dokud neskončí. Přestavba vyžaduje připojení k internetu. + Aktualizace nástěnky + Aktualizace na místě… nástěnka se na chvíli restartuje. + Nástěnka je aktualizována. + Aktualizace selhala — předchozí verze byla zachována. + Trvá to déle než obvykle. Dokončí se na pozadí — za chvíli zkontrolujte verzi. + Aktualizaci se nepodařilo spustit. Zkuste to znovu. Dashboard (REST API) Jádro systému · vždy nainstalováno Nástěnka je jádro REST API zařízení (dash-node) — malá služba Node na 127.0.0.1:4000, obsluhovaná nginx a řízená pdsm. Pohání každou akci knihovny v aplikaci: procházení a stahování Knih, přidávání a mazání obsahu Wikipedie a ZIM, relace Kolibri, Mapy a stav systému. Na rozdíl od modulů obsahu se neinstaluje ani neodstraňuje — je součástí zařízení a je vždy přítomna. Když je k dispozici novější verze, můžete ji přestavět na místě. diff --git a/controller/app/src/main/res/values-de/strings_k2go.xml b/controller/app/src/main/res/values-de/strings_k2go.xml index 7e4ccc4b..1c5a1877 100644 --- a/controller/app/src/main/res/values-de/strings_k2go.xml +++ b/controller/app/src/main/res/values-de/strings_k2go.xml @@ -681,6 +681,12 @@ REST-Kern neu erstellen? Aktualisiert dash-node auf die neueste Version. Der Server ist während der Neuerstellung kurz nicht verfügbar; verlassen Sie diesen Bildschirm nicht, bis es fertig ist. Für die Neuerstellung ist eine Internetverbindung nötig. + Dashboard wird aktualisiert + Aktualisierung an Ort und Stelle… das Dashboard startet kurz neu. + Dashboard aktualisiert. + Aktualisierung fehlgeschlagen — die vorherige Version wurde beibehalten. + Das dauert länger als üblich. Es wird im Hintergrund abgeschlossen — prüfe die Version gleich. + Aktualisierung konnte nicht gestartet werden. Erneut versuchen. Dashboard (REST API) Systemkern · immer installiert Das Dashboard ist der REST-API-Kern der Box (dash-node) — ein kleiner Node-Dienst auf 127.0.0.1:4000, bereitgestellt über nginx und überwacht von pdsm. Er treibt jede Bibliotheksaktion in der App an: Bücher durchsuchen und herunterladen, Wikipedia- und ZIM-Inhalte hinzufügen und löschen, Kolibri-Sitzungen, Karten und Systemstatus. Anders als die Inhaltsmodule wird er nicht installiert oder entfernt — er gehört zur Box und ist immer vorhanden. Wenn eine neuere Version verfügbar ist, können Sie ihn an Ort und Stelle neu erstellen. diff --git a/controller/app/src/main/res/values-el/strings_k2go.xml b/controller/app/src/main/res/values-el/strings_k2go.xml index 1917eb27..e8ad7801 100644 --- a/controller/app/src/main/res/values-el/strings_k2go.xml +++ b/controller/app/src/main/res/values-el/strings_k2go.xml @@ -681,6 +681,12 @@ Ανασυγκρότηση του πυρήνα REST; Ενημερώνει το dash-node στην πιο πρόσφατη έκδοση. Ο διακομιστής είναι για λίγο μη διαθέσιμος κατά την ανασυγκρότηση· μην φύγετε από αυτήν την οθόνη μέχρι να ολοκληρωθεί. Η ανασυγκρότηση χρειάζεται σύνδεση στο διαδίκτυο. + Ενημέρωση πίνακα + Ενημέρωση επιτόπου… ο πίνακας επανεκκινείται για λίγο. + Ο πίνακας ενημερώθηκε. + Η ενημέρωση απέτυχε — διατηρήθηκε η προηγούμενη έκδοση. + Αυτό διαρκεί περισσότερο από το συνηθισμένο. Θα ολοκληρωθεί στο παρασκήνιο — ελέγξτε την έκδοση σε λίγο. + Δεν ήταν δυνατή η έναρξη της ενημέρωσης. Δοκιμάστε ξανά. Dashboard (REST API) Πυρήνας συστήματος · πάντα εγκατεστημένος Ο πίνακας είναι ο πυρήνας REST API της συσκευής (dash-node): μια μικρή υπηρεσία Node στο 127.0.0.1:4000, που εξυπηρετείται από το nginx και επιβλέπεται από το pdsm. Τροφοδοτεί κάθε ενέργεια της βιβλιοθήκης στην εφαρμογή: περιήγηση και λήψη Βιβλίων, προσθήκη και διαγραφή περιεχομένου Wikipedia και ZIM, συνεδρίες Kolibri, Χάρτες και κατάσταση συστήματος. Σε αντίθεση με τις μονάδες περιεχομένου, δεν εγκαθίσταται ούτε αφαιρείται — συνοδεύει τη συσκευή και είναι πάντα παρών. Όταν υπάρχει νεότερη έκδοση, μπορείτε να τον ανασυγκροτήσετε επιτόπου. diff --git a/controller/app/src/main/res/values-es/strings_k2go.xml b/controller/app/src/main/res/values-es/strings_k2go.xml index 3fbdf572..c482fcf2 100644 --- a/controller/app/src/main/res/values-es/strings_k2go.xml +++ b/controller/app/src/main/res/values-es/strings_k2go.xml @@ -680,6 +680,12 @@ ¿Reconstruir el núcleo REST? Actualiza dash-node a la última versión. El servidor queda brevemente no disponible mientras se reconstruye; no salgas de esta pantalla hasta que termine. La reconstrucción necesita conexión a internet. + Actualizando el panel + Actualizando en el sitio… el panel se reinicia brevemente. + Panel actualizado. + La actualización falló — se conservó la versión anterior. + Esto está tardando más de lo normal. Terminará en segundo plano — revisa la versión en un momento. + No se pudo iniciar la actualización. Inténtalo de nuevo. Dashboard (REST API) Núcleo del sistema · siempre instalado El dashboard es el núcleo de la API REST de la caja (dash-node): un pequeño servicio Node en 127.0.0.1:4000, servido por nginx y supervisado por pdsm. Impulsa cada acción de la biblioteca en la app: explorar y descargar Libros, añadir y eliminar contenido de Wikipedia y ZIM, sesiones de Kolibri, Mapas y el estado del sistema. A diferencia de los módulos de contenido, no es algo que instales o quites: viene con la caja y siempre está presente. Cuando hay una versión más reciente, puedes reconstruirlo en el sitio. diff --git a/controller/app/src/main/res/values-fa/strings_k2go.xml b/controller/app/src/main/res/values-fa/strings_k2go.xml index c0f099c6..eed10404 100644 --- a/controller/app/src/main/res/values-fa/strings_k2go.xml +++ b/controller/app/src/main/res/values-fa/strings_k2go.xml @@ -680,6 +680,12 @@ هستهٔ REST بازسازی شود؟ dash-node را به آخرین نسخه به‌روزرسانی می‌کند. سرور در حین بازسازی برای مدت کوتاهی در دسترس نیست؛ تا پایان کار این صفحه را ترک نکنید. بازسازی به اتصال اینترنت نیاز دارد. + در حال به‌روزرسانی داشبورد + به‌روزرسانی در محل… داشبورد برای لحظه‌ای دوباره راه‌اندازی می‌شود. + داشبورد به‌روزرسانی شد. + به‌روزرسانی ناموفق بود — نسخهٔ قبلی حفظ شد. + این کار بیشتر از حد معمول طول می‌کشد. در پس‌زمینه تمام می‌شود — کمی بعد نسخه را بررسی کنید. + شروع به‌روزرسانی ممکن نشد. دوباره تلاش کنید. Dashboard (REST API) هستهٔ سیستم · همیشه نصب‌شده داشبورد هستهٔ REST API دستگاه است (dash-node): یک سرویس کوچک Node روی 127.0.0.1:4000 که nginx آن را ارائه می‌دهد و pdsm بر آن نظارت دارد. هر کنش کتابخانه در برنامه را پیش می‌برد: مرور و دانلود کتاب‌ها، افزودن و حذف محتوای Wikipedia و ZIM، نشست‌های Kolibri، نقشه‌ها و وضعیت سیستم. برخلاف ماژول‌های محتوا، نصب یا حذف نمی‌شود — همراه دستگاه می‌آید و همیشه حاضر است. وقتی نسخهٔ جدیدتری در دسترس باشد می‌توانید آن را در همان‌جا بازسازی کنید. diff --git a/controller/app/src/main/res/values-fr/strings_k2go.xml b/controller/app/src/main/res/values-fr/strings_k2go.xml index 18f9c410..c5b82a6b 100644 --- a/controller/app/src/main/res/values-fr/strings_k2go.xml +++ b/controller/app/src/main/res/values-fr/strings_k2go.xml @@ -690,6 +690,12 @@ Reconstruire le cœur REST ? Met à jour dash-node vers la dernière version. Le serveur est brièvement indisponible pendant la reconstruction ; ne quittez pas cet écran avant la fin. La reconstruction nécessite une connexion internet. + Mise à jour du tableau de bord + Mise à jour sur place… le tableau de bord redémarre brièvement. + Tableau de bord mis à jour. + Échec de la mise à jour — la version précédente a été conservée. + Cela prend plus de temps que d\'habitude. La mise à jour se terminera en arrière-plan — vérifiez la version dans un instant. + Impossible de démarrer la mise à jour. Réessayez. Dashboard (REST API) Cœur du système · toujours installé Le dashboard est le cœur de l\'API REST du boîtier (dash-node) : un petit service Node sur 127.0.0.1:4000, servi par nginx et supervisé par pdsm. Il alimente chaque action de la bibliothèque dans l\'app : parcourir et télécharger des Livres, ajouter et supprimer du contenu Wikipedia et ZIM, les sessions Kolibri, les Cartes et l\'état du système. Contrairement aux modules de contenu, il ne s\'installe ni ne se supprime : il est fourni avec le boîtier et toujours présent. Lorsqu\'une version plus récente est disponible, vous pouvez le reconstruire sur place. diff --git a/controller/app/src/main/res/values-gu/strings_k2go.xml b/controller/app/src/main/res/values-gu/strings_k2go.xml index f2586227..0705d960 100644 --- a/controller/app/src/main/res/values-gu/strings_k2go.xml +++ b/controller/app/src/main/res/values-gu/strings_k2go.xml @@ -680,6 +680,12 @@ REST કોર ફરીથી બનાવવો? dash-node ને નવીનતમ સંસ્કરણમાં અપડેટ કરે છે. ફરીથી બનાવતી વખતે સર્વર થોડા સમય માટે અનુપલબ્ધ રહે છે; પૂર્ણ ન થાય ત્યાં સુધી આ સ્ક્રીન છોડશો નહીં. ફરીથી બનાવવા માટે ઇન્ટરનેટ કનેક્શન જરૂરી છે. + ડેશબોર્ડ અપડેટ થઈ રહ્યું છે + સ્થળ પર જ અપડેટ થઈ રહ્યું છે… ડેશબોર્ડ થોડી વાર માટે રીસ્ટાર્ટ થશે. + ડેશબોર્ડ અપડેટ થયું. + અપડેટ નિષ્ફળ — અગાઉની આવૃત્તિ જાળવી રાખી. + આ સામાન્ય કરતાં વધુ સમય લઈ રહ્યું છે. તે પૃષ્ઠભૂમિમાં પૂર્ણ થશે — થોડી વારમાં આવૃત્તિ તપાસો. + અપડેટ શરૂ કરી શકાયું નહીં. ફરી પ્રયાસ કરો. Dashboard (REST API) સિસ્ટમ કોર · હંમેશા સ્થાપિત ડેશબોર્ડ એ બોક્સનું REST API કોર છે (dash-node): 127.0.0.1:4000 પર એક નાની Node સેવા, જેને nginx પીરસે છે અને pdsm દેખરેખ રાખે છે. તે એપમાં દરેક લાઇબ્રેરી ક્રિયા ચલાવે છે: પુસ્તકો બ્રાઉઝ અને ડાઉનલોડ, Wikipedia અને ZIM સામગ્રી ઉમેરવી અને કાઢી નાખવી, Kolibri સત્રો, નકશા અને સિસ્ટમ સ્થિતિ. સામગ્રી મોડ્યુલોથી વિપરીત, તે સ્થાપિત કે દૂર કરાતું નથી — તે બોક્સ સાથે આવે છે અને હંમેશા હાજર રહે છે. જ્યારે નવું સંસ્કરણ ઉપલબ્ધ હોય, ત્યારે તમે તેને સ્થળ પર જ ફરીથી બનાવી શકો છો. diff --git a/controller/app/src/main/res/values-hi/strings_k2go.xml b/controller/app/src/main/res/values-hi/strings_k2go.xml index 0cafe1f0..c202603f 100644 --- a/controller/app/src/main/res/values-hi/strings_k2go.xml +++ b/controller/app/src/main/res/values-hi/strings_k2go.xml @@ -680,6 +680,12 @@ REST कोर फिर से बनाएँ? dash-node को नवीनतम संस्करण में अपडेट करता है. फिर से बनाने के दौरान सर्वर थोड़ी देर के लिए अनुपलब्ध रहता है; समाप्त होने तक यह स्क्रीन न छोड़ें. फिर से बनाने के लिए इंटरनेट कनेक्शन आवश्यक है. + डैशबोर्ड अपडेट हो रहा है + यहीं अपडेट हो रहा है… डैशबोर्ड थोड़ी देर के लिए पुनः शुरू होगा। + डैशबोर्ड अपडेट हो गया। + अपडेट विफल — पिछला संस्करण रखा गया। + यह सामान्य से अधिक समय ले रहा है। यह पृष्ठभूमि में पूरा होगा — थोड़ी देर में संस्करण जांचें। + अपडेट शुरू नहीं हो सका। फिर से प्रयास करें। Dashboard (REST API) सिस्टम कोर · हमेशा स्थापित डैशबोर्ड बॉक्स का REST API कोर है (dash-node): 127.0.0.1:4000 पर एक छोटी Node सेवा, जिसे nginx परोसता है और pdsm देखरेख करता है. यह ऐप में हर लाइब्रेरी क्रिया को सक्षम करता है: किताबें ब्राउज़ और डाउनलोड करना, Wikipedia और ZIM सामग्री जोड़ना और हटाना, Kolibri सत्र, मानचित्र और सिस्टम स्थिति. सामग्री मॉड्यूल के विपरीत, इसे स्थापित या हटाया नहीं जाता — यह बॉक्स के साथ आता है और हमेशा मौजूद रहता है. जब कोई नया संस्करण उपलब्ध हो, आप इसे यथास्थान फिर से बना सकते हैं. diff --git a/controller/app/src/main/res/values-hu/strings_k2go.xml b/controller/app/src/main/res/values-hu/strings_k2go.xml index a2129dff..0b2ab809 100644 --- a/controller/app/src/main/res/values-hu/strings_k2go.xml +++ b/controller/app/src/main/res/values-hu/strings_k2go.xml @@ -680,6 +680,12 @@ Újraépíti a REST magot? Frissíti a dash-node-ot a legújabb verzióra. A szerver az újraépítés alatt rövid ideig nem elérhető; ne hagyd el ezt a képernyőt, amíg be nem fejeződik. Az újraépítéshez internetkapcsolat szükséges. + Irányítópult frissítése + Frissítés helyben… az irányítópult röviden újraindul. + Az irányítópult frissült. + A frissítés sikertelen — az előző verzió megmaradt. + Ez a szokásosnál tovább tart. A háttérben befejeződik — nézze meg a verziót egy pillanat múlva. + A frissítést nem sikerült elindítani. Próbálja újra. Dashboard (REST API) Rendszermag · mindig telepítve Az irányítópult a doboz REST API magja (dash-node): egy kis Node szolgáltatás a 127.0.0.1:4000 címen, amelyet az nginx szolgál ki és a pdsm felügyel. Ez működteti az alkalmazás minden könyvtári műveletét: Könyvek böngészése és letöltése, Wikipédia- és ZIM-tartalom hozzáadása és törlése, Kolibri munkamenetek, Térképek és rendszerállapot. A tartalommoduloktól eltérően nem telepíted vagy távolítod el — a dobozzal érkezik és mindig jelen van. Ha újabb verzió érhető el, helyben újraépítheted. diff --git a/controller/app/src/main/res/values-in/strings_k2go.xml b/controller/app/src/main/res/values-in/strings_k2go.xml index 03b732c9..f6991c9e 100644 --- a/controller/app/src/main/res/values-in/strings_k2go.xml +++ b/controller/app/src/main/res/values-in/strings_k2go.xml @@ -680,6 +680,12 @@ Bangun ulang inti REST? Memperbarui dash-node ke versi terbaru. Server sebentar tidak tersedia saat dibangun ulang; jangan tinggalkan layar ini sampai selesai. Membangun ulang memerlukan koneksi internet. + Memperbarui dasbor + Memperbarui di tempat… dasbor dimulai ulang sebentar. + Dasbor diperbarui. + Pembaruan gagal — versi sebelumnya dipertahankan. + Ini memakan waktu lebih lama dari biasanya. Akan selesai di latar belakang — periksa versinya sebentar lagi. + Tidak dapat memulai pembaruan. Coba lagi. Dashboard (REST API) Inti sistem · selalu terpasang Dasbor adalah inti REST API dari box (dash-node): layanan Node kecil di 127.0.0.1:4000, disajikan oleh nginx dan diawasi oleh pdsm. Ia menggerakkan setiap tindakan pustaka di dalam aplikasi: menjelajahi dan mengunduh Buku, menambah dan menghapus konten Wikipedia dan ZIM, sesi Kolibri, Peta, dan status sistem. Berbeda dengan modul konten, ia tidak dipasang atau dihapus — ia hadir bersama box dan selalu ada. Saat versi lebih baru tersedia, Anda dapat membangunnya ulang di tempat. diff --git a/controller/app/src/main/res/values-it/strings_k2go.xml b/controller/app/src/main/res/values-it/strings_k2go.xml index 6cd8888f..5fbb7270 100644 --- a/controller/app/src/main/res/values-it/strings_k2go.xml +++ b/controller/app/src/main/res/values-it/strings_k2go.xml @@ -680,6 +680,12 @@ Ricostruire il nucleo REST? Aggiorna dash-node all\'ultima versione. Il server è brevemente non disponibile durante la ricostruzione; non lasciare questa schermata finché non termina. La ricostruzione richiede una connessione a internet. + Aggiornamento della dashboard + Aggiornamento sul posto… la dashboard si riavvia brevemente. + Dashboard aggiornata. + Aggiornamento non riuscito — è stata mantenuta la versione precedente. + Sta impiegando più del solito. Terminerà in background — controlla la versione tra un momento. + Impossibile avviare l\'aggiornamento. Riprova. Dashboard (REST API) Nucleo di sistema · sempre installato Il dashboard è il nucleo dell\'API REST della box (dash-node): un piccolo servizio Node su 127.0.0.1:4000, servito da nginx e supervisionato da pdsm. Alimenta ogni azione della libreria nell\'app: sfogliare e scaricare Libri, aggiungere ed eliminare contenuti Wikipedia e ZIM, sessioni Kolibri, Mappe e stato del sistema. A differenza dei moduli di contenuto, non si installa né si rimuove: è incluso nella box ed è sempre presente. Quando è disponibile una versione più recente, puoi ricostruirlo sul posto. diff --git a/controller/app/src/main/res/values-ja/strings_k2go.xml b/controller/app/src/main/res/values-ja/strings_k2go.xml index d447e8a3..db8da6d9 100644 --- a/controller/app/src/main/res/values-ja/strings_k2go.xml +++ b/controller/app/src/main/res/values-ja/strings_k2go.xml @@ -680,6 +680,12 @@ REST コアを再構築しますか? dash-node を最新バージョンに更新します。再構築中はサーバーが一時的に利用できなくなります。完了するまでこの画面を離れないでください。 再構築にはインターネット接続が必要です。 + ダッシュボードを更新中 + その場で更新中… ダッシュボードが少しの間再起動します。 + ダッシュボードを更新しました。 + 更新に失敗しました — 以前のバージョンを維持しました。 + 通常より時間がかかっています。バックグラウンドで完了します — 少し後にバージョンを確認してください。 + 更新を開始できませんでした。もう一度お試しください。 Dashboard (REST API) システムコア · 常にインストール済み ダッシュボードはボックスの REST API コア(dash-node)です。127.0.0.1:4000 で動作する小さな Node サービスで、nginx が配信し pdsm が監視します。アプリ内のすべてのライブラリ操作を支えます。書籍の閲覧とダウンロード、Wikipedia と ZIM コンテンツの追加と削除、Kolibri セッション、地図、システム状態などです。コンテンツモジュールとは異なり、インストールや削除はできません。ボックスに付属し、常に存在します。新しいビルドが利用可能になると、その場で再構築できます。 diff --git a/controller/app/src/main/res/values-ko/strings_k2go.xml b/controller/app/src/main/res/values-ko/strings_k2go.xml index 1074a625..7dd4b4c7 100644 --- a/controller/app/src/main/res/values-ko/strings_k2go.xml +++ b/controller/app/src/main/res/values-ko/strings_k2go.xml @@ -680,6 +680,12 @@ REST 코어를 재빌드할까요? dash-node를 최신 버전으로 업데이트합니다. 재빌드하는 동안 서버를 잠시 사용할 수 없습니다. 완료될 때까지 이 화면을 떠나지 마세요. 재빌드하려면 인터넷 연결이 필요합니다. + 대시보드 업데이트 중 + 제자리에서 업데이트 중… 대시보드가 잠시 다시 시작됩니다. + 대시보드가 업데이트되었습니다. + 업데이트 실패 — 이전 버전을 유지했습니다. + 평소보다 오래 걸리고 있습니다. 백그라운드에서 완료됩니다 — 잠시 후 버전을 확인하세요. + 업데이트를 시작할 수 없습니다. 다시 시도하세요. Dashboard (REST API) 시스템 코어 · 항상 설치됨 대시보드는 박스의 REST API 코어(dash-node)입니다. 127.0.0.1:4000에서 실행되는 작은 Node 서비스로, nginx가 제공하고 pdsm이 관리합니다. 앱의 모든 라이브러리 작업을 구동합니다: 도서 탐색 및 다운로드, Wikipedia 및 ZIM 콘텐츠 추가 및 삭제, Kolibri 세션, 지도, 시스템 상태. 콘텐츠 모듈과 달리 설치하거나 제거하지 않습니다 — 박스와 함께 제공되며 항상 존재합니다. 새 빌드가 있으면 제자리에서 재빌드할 수 있습니다. diff --git a/controller/app/src/main/res/values-lt/strings_k2go.xml b/controller/app/src/main/res/values-lt/strings_k2go.xml index 778bc3b1..888ba82c 100644 --- a/controller/app/src/main/res/values-lt/strings_k2go.xml +++ b/controller/app/src/main/res/values-lt/strings_k2go.xml @@ -690,6 +690,12 @@ Atkurti REST branduolį? Atnaujina dash-node į naujausią versiją. Atkūrimo metu serveris trumpam nepasiekiamas; nepalikite šio ekrano, kol nebus baigta. Atkūrimui reikia interneto ryšio. + Atnaujinama sąsaja + Atnaujinama vietoje… sąsaja trumpam paleidžiama iš naujo. + Sąsaja atnaujinta. + Atnaujinti nepavyko — palikta ankstesnė versija. + Tai užtrunka ilgiau nei įprastai. Bus baigta fone — netrukus patikrinkite versiją. + Nepavyko pradėti atnaujinimo. Bandykite dar kartą. Dashboard (REST API) Sistemos branduolys · visada įdiegtas Skydelis yra įrenginio REST API branduolys (dash-node): maža Node paslauga adresu 127.0.0.1:4000, aptarnaujama nginx ir prižiūrima pdsm. Jis palaiko kiekvieną bibliotekos veiksmą programoje: Knygų naršymą ir atsisiuntimą, Wikipedia ir ZIM turinio pridėjimą bei šalinimą, Kolibri sesijas, Žemėlapius ir sistemos būseną. Skirtingai nei turinio moduliai, jis nediegiamas ir nešalinamas — pateikiamas su įrenginiu ir visada yra. Kai pasiekiama naujesnė versija, galite jį atkurti vietoje. diff --git a/controller/app/src/main/res/values-nl/strings_k2go.xml b/controller/app/src/main/res/values-nl/strings_k2go.xml index 552445b9..d622d929 100644 --- a/controller/app/src/main/res/values-nl/strings_k2go.xml +++ b/controller/app/src/main/res/values-nl/strings_k2go.xml @@ -680,6 +680,12 @@ REST-kern opnieuw opbouwen? Werkt dash-node bij naar de nieuwste versie. De server is tijdens het opnieuw opbouwen kort niet beschikbaar; verlaat dit scherm niet totdat het klaar is. Opnieuw opbouwen vereist een internetverbinding. + Dashboard bijwerken + Bijwerken ter plekke… het dashboard start kort opnieuw op. + Dashboard bijgewerkt. + Bijwerken mislukt — de vorige versie is behouden. + Dit duurt langer dan normaal. Het wordt op de achtergrond voltooid — controleer de versie zo meteen. + Kan de update niet starten. Probeer het opnieuw. Dashboard (REST API) Systeemkern · altijd geïnstalleerd Het dashboard is de REST-API-kern van de box (dash-node): een kleine Node-service op 127.0.0.1:4000, aangeboden via nginx en beheerd door pdsm. Het drijft elke bibliotheekactie in de app aan: Boeken bladeren en downloaden, Wikipedia- en ZIM-inhoud toevoegen en verwijderen, Kolibri-sessies, Kaarten en systeemstatus. Anders dan de inhoudsmodules installeer of verwijder je het niet: het hoort bij de box en is altijd aanwezig. Als er een nieuwere versie beschikbaar is, kun je het ter plekke opnieuw opbouwen. diff --git a/controller/app/src/main/res/values-no/strings_k2go.xml b/controller/app/src/main/res/values-no/strings_k2go.xml index 7196bd56..3be5ff2a 100644 --- a/controller/app/src/main/res/values-no/strings_k2go.xml +++ b/controller/app/src/main/res/values-no/strings_k2go.xml @@ -690,6 +690,12 @@ Bygge REST-kjernen på nytt? Oppdaterer dash-node til nyeste versjon. Serveren er kort utilgjengelig mens den bygges på nytt; ikke forlat denne skjermen før den er ferdig. Ombygging krever internettforbindelse. + Oppdaterer dashbordet + Oppdaterer på stedet… dashbordet starter kort på nytt. + Dashbordet er oppdatert. + Oppdateringen mislyktes — forrige versjon ble beholdt. + Dette tar lengre tid enn vanlig. Det fullføres i bakgrunnen — sjekk versjonen om et øyeblikk. + Kunne ikke starte oppdateringen. Prøv igjen. Dashboard (REST API) Systemkjerne · alltid installert Kontrollpanelet er boksens REST-API-kjerne (dash-node): en liten Node-tjeneste på 127.0.0.1:4000, levert av nginx og overvåket av pdsm. Den driver alle bibliotekhandlinger i appen: bla i og laste ned Bøker, legge til og slette Wikipedia- og ZIM-innhold, Kolibri-økter, Kart og systemstatus. I motsetning til innholdsmodulene installeres eller fjernes den ikke — den følger med boksen og er alltid til stede. Når en nyere versjon er tilgjengelig, kan du bygge den på nytt på stedet. diff --git a/controller/app/src/main/res/values-pl/strings_k2go.xml b/controller/app/src/main/res/values-pl/strings_k2go.xml index 16303d39..02f781cf 100644 --- a/controller/app/src/main/res/values-pl/strings_k2go.xml +++ b/controller/app/src/main/res/values-pl/strings_k2go.xml @@ -690,6 +690,12 @@ Przebudować rdzeń REST? Aktualizuje dash-node do najnowszej wersji. Serwer jest przez chwilę niedostępny podczas przebudowy; nie opuszczaj tego ekranu, dopóki się nie zakończy. Przebudowa wymaga połączenia z internetem. + Aktualizowanie panelu + Aktualizacja w miejscu… panel na chwilę się zrestartuje. + Panel zaktualizowany. + Aktualizacja nie powiodła się — zachowano poprzednią wersję. + To trwa dłużej niż zwykle. Zakończy się w tle — sprawdź wersję za chwilę. + Nie można rozpocząć aktualizacji. Spróbuj ponownie. Dashboard (REST API) Rdzeń systemu · zawsze zainstalowany Pulpit to rdzeń interfejsu REST API urządzenia (dash-node) — mała usługa Node pod adresem 127.0.0.1:4000, obsługiwana przez nginx i nadzorowana przez pdsm. Napędza każdą akcję biblioteki w aplikacji: przeglądanie i pobieranie Książek, dodawanie i usuwanie treści Wikipedii oraz ZIM, sesje Kolibri, Mapy i stan systemu. W przeciwieństwie do modułów treści nie instaluje się go ani nie usuwa — jest dostarczany z urządzeniem i zawsze obecny. Gdy dostępna jest nowsza wersja, możesz przebudować go w miejscu. diff --git a/controller/app/src/main/res/values-pt/strings_k2go.xml b/controller/app/src/main/res/values-pt/strings_k2go.xml index cf87cba1..be72bf2f 100644 --- a/controller/app/src/main/res/values-pt/strings_k2go.xml +++ b/controller/app/src/main/res/values-pt/strings_k2go.xml @@ -680,6 +680,12 @@ Recompilar o núcleo REST? Atualiza o dash-node para a versão mais recente. O servidor fica brevemente indisponível durante a recompilação; não saia desta tela até terminar. A recompilação precisa de conexão com a internet. + A atualizar o painel + A atualizar no local… o painel reinicia brevemente. + Painel atualizado. + A atualização falhou — a versão anterior foi mantida. + Isto está a demorar mais do que o habitual. Vai terminar em segundo plano — verifique a versão daqui a pouco. + Não foi possível iniciar a atualização. Tente novamente. Dashboard (REST API) Núcleo do sistema · sempre instalado O dashboard é o núcleo da API REST da caixa (dash-node): um pequeno serviço Node em 127.0.0.1:4000, servido pelo nginx e supervisionado pelo pdsm. Ele impulsiona todas as ações da biblioteca no app: navegar e baixar Livros, adicionar e excluir conteúdo da Wikipedia e ZIM, sessões do Kolibri, Mapas e status do sistema. Ao contrário dos módulos de conteúdo, ele não é instalado nem removido: vem com a caixa e está sempre presente. Quando há uma versão mais recente, você pode recompilá-lo no local. diff --git a/controller/app/src/main/res/values-ro/strings_k2go.xml b/controller/app/src/main/res/values-ro/strings_k2go.xml index 557e5dd0..6258b945 100644 --- a/controller/app/src/main/res/values-ro/strings_k2go.xml +++ b/controller/app/src/main/res/values-ro/strings_k2go.xml @@ -680,6 +680,12 @@ Reconstruiești nucleul REST? Actualizează dash-node la cea mai recentă versiune. Serverul este indisponibil pentru scurt timp în timpul reconstruirii; nu părăsi acest ecran până nu se termină. Reconstruirea necesită o conexiune la internet. + Se actualizează panoul + Se actualizează pe loc… panoul repornește pentru scurt timp. + Panoul a fost actualizat. + Actualizarea a eșuat — a fost păstrată versiunea anterioară. + Durează mai mult decât de obicei. Se va finaliza în fundal — verificați versiunea într-un moment. + Actualizarea nu a putut porni. Încercați din nou. Dashboard (REST API) Nucleul sistemului · întotdeauna instalat Panoul este nucleul API REST al cutiei (dash-node): un mic serviciu Node la 127.0.0.1:4000, servit de nginx și supravegheat de pdsm. Alimentează fiecare acțiune a bibliotecii din aplicație: răsfoirea și descărcarea Cărților, adăugarea și ștergerea conținutului Wikipedia și ZIM, sesiunile Kolibri, Hărțile și starea sistemului. Spre deosebire de modulele de conținut, nu se instalează și nu se elimină — vine cu cutia și este întotdeauna prezent. Când este disponibilă o versiune mai nouă, îl poți reconstrui pe loc. diff --git a/controller/app/src/main/res/values-ru-rRU/strings_k2go.xml b/controller/app/src/main/res/values-ru-rRU/strings_k2go.xml index 6f490643..2bf69d59 100644 --- a/controller/app/src/main/res/values-ru-rRU/strings_k2go.xml +++ b/controller/app/src/main/res/values-ru-rRU/strings_k2go.xml @@ -680,6 +680,12 @@ Пересобрать ядро REST? Обновляет dash-node до последней версии. Во время пересборки сервер ненадолго недоступен; не покидайте этот экран, пока она не завершится. Для пересборки нужно подключение к интернету. + Обновление панели + Обновление на месте… панель ненадолго перезапустится. + Панель обновлена. + Не удалось обновить — сохранена предыдущая версия. + Это занимает больше времени, чем обычно. Завершится в фоне — проверьте версию через минуту. + Не удалось запустить обновление. Повторите попытку. Dashboard (REST API) Ядро системы · всегда установлено Панель — это ядро REST API устройства (dash-node): небольшой сервис Node на 127.0.0.1:4000, обслуживаемый nginx и управляемый pdsm. Оно обеспечивает все действия библиотеки в приложении: просмотр и загрузку Книг, добавление и удаление контента Wikipedia и ZIM, сессии Kolibri, Карты и состояние системы. В отличие от модулей контента, его нельзя установить или удалить — оно поставляется с устройством и всегда присутствует. Когда доступна более новая версия, вы можете пересобрать его на месте. diff --git a/controller/app/src/main/res/values-sk/strings_k2go.xml b/controller/app/src/main/res/values-sk/strings_k2go.xml index f3f6ff07..d54beb85 100644 --- a/controller/app/src/main/res/values-sk/strings_k2go.xml +++ b/controller/app/src/main/res/values-sk/strings_k2go.xml @@ -680,6 +680,12 @@ Prestavať jadro REST? Aktualizuje dash-node na najnovšiu verziu. Server je počas prestavby krátko nedostupný; neopúšťajte túto obrazovku, kým sa neskončí. Prestavba vyžaduje pripojenie na internet. + Aktualizácia nástenky + Aktualizácia na mieste… nástenka sa nakrátko reštartuje. + Nástenka je aktualizovaná. + Aktualizácia zlyhala — ponechala sa predchádzajúca verzia. + Trvá to dlhšie ako zvyčajne. Dokončí sa na pozadí — o chvíľu skontrolujte verziu. + Aktualizáciu sa nepodarilo spustiť. Skúste to znova. Dashboard (REST API) Jadro systému · vždy nainštalované Nástenka je jadro REST API zariadenia (dash-node) — malá služba Node na 127.0.0.1:4000, obsluhovaná nginx a riadená pdsm. Poháňa každú akciu knižnice v aplikácii: prehliadanie a sťahovanie Kníh, pridávanie a mazanie obsahu Wikipédie a ZIM, relácie Kolibri, Mapy a stav systému. Na rozdiel od obsahových modulov sa neinštaluje ani neodstraňuje — je súčasťou zariadenia a je vždy prítomná. Keď je dostupná novšia verzia, môžete ju prestavať na mieste. diff --git a/controller/app/src/main/res/values-sr/strings_k2go.xml b/controller/app/src/main/res/values-sr/strings_k2go.xml index 41a07002..e08ab349 100644 --- a/controller/app/src/main/res/values-sr/strings_k2go.xml +++ b/controller/app/src/main/res/values-sr/strings_k2go.xml @@ -680,6 +680,12 @@ Поново изградити REST језгро? Ажурира dash-node на најновију верзију. Сервер је накратко недоступан током поновне изградње; не напуштајте овај екран док се не заврши. Поновна изградња захтева интернет везу. + Ажурирање контролне табле + Ажурирање на лицу места… контролна табла ће се накратко поново покренути. + Контролна табла је ажурирана. + Ажурирање није успело — задржана је претходна верзија. + Ово траје дуже него обично. Завршиће се у позадини — проверите верзију за тренутак. + Ажурирање није могло да почне. Покушајте поново. Dashboard (REST API) Системско језгро · увек инсталирано Контролна табла је REST API језгро уређаја (dash-node): мала Node услуга на 127.0.0.1:4000, коју опслужује nginx а надгледа pdsm. Покреће сваку радњу библиотеке у апликацији: прегледање и преузимање Књига, додавање и брисање садржаја Wikipedia и ZIM, Kolibri сесије, Мапе и стање система. За разлику од модула садржаја, не инсталира се нити уклања — долази уз уређај и увек је присутна. Када је доступна новија верзија, можете је поново изградити на лицу места. diff --git a/controller/app/src/main/res/values-sw/strings_k2go.xml b/controller/app/src/main/res/values-sw/strings_k2go.xml index 94b8ab92..7200289d 100644 --- a/controller/app/src/main/res/values-sw/strings_k2go.xml +++ b/controller/app/src/main/res/values-sw/strings_k2go.xml @@ -680,6 +680,12 @@ Ujenge upya kiini cha REST? Inasasisha dash-node hadi toleo jipya zaidi. Seva haipatikani kwa muda mfupi wakati wa kujengwa upya; usiondoke skrini hii hadi ikamilike. Kujenga upya kunahitaji muunganisho wa intaneti. + Inasasisha dashibodi + Inasasisha papo hapo… dashibodi itaanza upya kwa muda mfupi. + Dashibodi imesasishwa. + Sasisho limeshindwa — toleo la awali limehifadhiwa. + Hii inachukua muda mrefu kuliko kawaida. Itakamilika chinichini — angalia toleo baada ya muda mfupi. + Imeshindwa kuanzisha sasisho. Jaribu tena. Dashboard (REST API) Kiini cha mfumo · kimesakinishwa daima Dashibodi ni kiini cha REST API cha kisanduku (dash-node): huduma ndogo ya Node kwenye 127.0.0.1:4000, inayotolewa na nginx na kusimamiwa na pdsm. Inaendesha kila kitendo cha maktaba ndani ya programu: kuvinjari na kupakua Vitabu, kuongeza na kufuta maudhui ya Wikipedia na ZIM, vipindi vya Kolibri, Ramani na hali ya mfumo. Tofauti na moduli za maudhui, haisakinishwi wala kuondolewa — inakuja na kisanduku na ipo daima. Toleo jipya linapopatikana, unaweza kukijenga upya papo hapo. diff --git a/controller/app/src/main/res/values-ta/strings_k2go.xml b/controller/app/src/main/res/values-ta/strings_k2go.xml index b8828265..f1cff5df 100644 --- a/controller/app/src/main/res/values-ta/strings_k2go.xml +++ b/controller/app/src/main/res/values-ta/strings_k2go.xml @@ -680,6 +680,12 @@ REST கருவை மீண்டும் உருவாக்கவா? dash-node ஐ சமீபத்திய பதிப்பிற்குப் புதுப்பிக்கிறது. மீண்டும் உருவாக்கும்போது சேவையகம் சிறிது நேரம் கிடைக்காது; முடியும் வரை இந்தத் திரையை விட்டு வெளியேறாதீர்கள். மீண்டும் உருவாக்க இணைய இணைப்பு தேவை. + டாஷ்போர்டு புதுப்பிக்கப்படுகிறது + அப்படியே புதுப்பிக்கப்படுகிறது… டாஷ்போர்டு சிறிது நேரம் மறுதொடக்கம் செய்யப்படும். + டாஷ்போர்டு புதுப்பிக்கப்பட்டது. + புதுப்பிப்பு தோல்வி — முந்தைய பதிப்பு வைத்திருக்கப்பட்டது. + இது வழக்கத்தை விட அதிக நேரம் எடுக்கிறது. இது பின்னணியில் முடியும் — சிறிது நேரத்தில் பதிப்பைச் சரிபார்க்கவும். + புதுப்பிப்பைத் தொடங்க முடியவில்லை. மீண்டும் முயற்சிக்கவும். Dashboard (REST API) கணினி கரு · எப்போதும் நிறுவப்பட்டது டாஷ்போர்டு என்பது பெட்டியின் REST API கரு (dash-node): 127.0.0.1:4000 இல் இயங்கும் ஒரு சிறிய Node சேவை, nginx வழங்கி pdsm மேற்பார்வையிடுகிறது. இது பயன்பாட்டில் ஒவ்வொரு நூலக செயலையும் இயக்குகிறது: புத்தகங்களை உலாவுதல் மற்றும் பதிவிறக்குதல், Wikipedia மற்றும் ZIM உள்ளடக்கத்தைச் சேர்த்தல் மற்றும் நீக்குதல், Kolibri அமர்வுகள், வரைபடங்கள் மற்றும் கணினி நிலை. உள்ளடக்க தொகுதிகளைப் போலல்லாமல், இதை நிறுவவோ அகற்றவோ முடியாது — இது பெட்டியுடன் வருகிறது, எப்போதும் இருக்கும். புதிய பதிப்பு கிடைக்கும்போது அதை இடத்திலேயே மீண்டும் உருவாக்கலாம். diff --git a/controller/app/src/main/res/values-tr/strings_k2go.xml b/controller/app/src/main/res/values-tr/strings_k2go.xml index b0b8e592..8534c221 100644 --- a/controller/app/src/main/res/values-tr/strings_k2go.xml +++ b/controller/app/src/main/res/values-tr/strings_k2go.xml @@ -680,6 +680,12 @@ REST çekirdeği yeniden oluşturulsun mu? dash-node\'u en son sürüme günceller. Yeniden oluşturma sırasında sunucu kısa süre kullanılamaz; bitene kadar bu ekrandan ayrılmayın. Yeniden oluşturma için internet bağlantısı gerekir. + Pano güncelleniyor + Yerinde güncelleniyor… pano kısa süre yeniden başlar. + Pano güncellendi. + Güncelleme başarısız — önceki sürüm korundu. + Bu her zamankinden uzun sürüyor. Arka planda tamamlanacak — birazdan sürümü kontrol edin. + Güncelleme başlatılamadı. Tekrar deneyin. Dashboard (REST API) Sistem çekirdeği · her zaman yüklü Pano, kutunun REST API çekirdeğidir (dash-node): 127.0.0.1:4000 üzerinde çalışan, nginx tarafından sunulan ve pdsm tarafından denetlenen küçük bir Node hizmeti. Uygulamadaki her kitaplık eylemini çalıştırır: Kitaplara göz atma ve indirme, Wikipedia ve ZIM içeriği ekleme ve silme, Kolibri oturumları, Haritalar ve sistem durumu. İçerik modüllerinin aksine yüklenmez veya kaldırılmaz — kutuyla birlikte gelir ve her zaman mevcuttur. Daha yeni bir sürüm olduğunda onu yerinde yeniden oluşturabilirsiniz. diff --git a/controller/app/src/main/res/values-uk/strings_k2go.xml b/controller/app/src/main/res/values-uk/strings_k2go.xml index c0823233..a3461dc4 100644 --- a/controller/app/src/main/res/values-uk/strings_k2go.xml +++ b/controller/app/src/main/res/values-uk/strings_k2go.xml @@ -680,6 +680,12 @@ Перезібрати ядро REST? Оновлює dash-node до найновішої версії. Під час перезбирання сервер ненадовго недоступний; не залишайте цей екран, доки воно не завершиться. Для перезбирання потрібне з\'єднання з інтернетом. + Оновлення панелі + Оновлення на місці… панель ненадовго перезапуститься. + Панель оновлено. + Не вдалося оновити — збережено попередню версію. + Це триває довше, ніж зазвичай. Завершиться у фоні — перевірте версію за мить. + Не вдалося розпочати оновлення. Спробуйте ще раз. Dashboard (REST API) Ядро системи · завжди встановлено Панель — це ядро REST API пристрою (dash-node): невеликий сервіс Node на 127.0.0.1:4000, який обслуговує nginx і контролює pdsm. Воно забезпечує всі дії бібліотеки в застосунку: перегляд і завантаження Книг, додавання й видалення вмісту Wikipedia та ZIM, сесії Kolibri, Карти та стан системи. На відміну від модулів вмісту, його не встановлюють і не видаляють — воно постачається з пристроєм і завжди присутнє. Коли доступна новіша версія, ви можете перезібрати його на місці. diff --git a/controller/app/src/main/res/values-vi/strings_k2go.xml b/controller/app/src/main/res/values-vi/strings_k2go.xml index b6f9fb49..b3dcad9f 100644 --- a/controller/app/src/main/res/values-vi/strings_k2go.xml +++ b/controller/app/src/main/res/values-vi/strings_k2go.xml @@ -680,6 +680,12 @@ Xây dựng lại lõi REST? Cập nhật dash-node lên phiên bản mới nhất. Máy chủ tạm thời không khả dụng trong khi xây dựng lại; đừng rời màn hình này cho đến khi hoàn tất. Việc xây dựng lại cần kết nối internet. + Đang cập nhật bảng điều khiển + Đang cập nhật tại chỗ… bảng điều khiển khởi động lại trong giây lát. + Đã cập nhật bảng điều khiển. + Cập nhật thất bại — phiên bản trước đã được giữ lại. + Việc này lâu hơn bình thường. Nó sẽ hoàn tất ở chế độ nền — kiểm tra phiên bản trong giây lát. + Không thể bắt đầu cập nhật. Hãy thử lại. Dashboard (REST API) Lõi hệ thống · luôn được cài đặt Bảng điều khiển là lõi REST API của hộp (dash-node): một dịch vụ Node nhỏ tại 127.0.0.1:4000, do nginx phục vụ và pdsm giám sát. Nó cung cấp mọi thao tác thư viện trong ứng dụng: duyệt và tải Sách, thêm và xóa nội dung Wikipedia và ZIM, phiên Kolibri, Bản đồ và trạng thái hệ thống. Khác với các mô-đun nội dung, nó không được cài đặt hay gỡ bỏ — nó đi kèm với hộp và luôn hiện diện. Khi có bản mới hơn, bạn có thể xây dựng lại nó tại chỗ. diff --git a/controller/app/src/main/res/values-yo/strings_k2go.xml b/controller/app/src/main/res/values-yo/strings_k2go.xml index 913ae2d5..b2d88d5d 100644 --- a/controller/app/src/main/res/values-yo/strings_k2go.xml +++ b/controller/app/src/main/res/values-yo/strings_k2go.xml @@ -680,6 +680,12 @@ Tún kókó REST kọ́? Ó ń ṣe àfikún dash-node sí ẹ̀yà tuntun. Sáfà kì yóò sí fún ìgbà díẹ̀ nígbà tí ó ń tún kọ́; má ṣe kúrò ní ojú-iwé yìí títí yóò fi parí. Àtúnkọ́ nílò ìsopọ̀ íntánẹ́ẹ̀tì. + Ń ṣàtúnṣe dáàṣíbọ́ọ̀dù + Ń ṣàtúnṣe níbí… dáàṣíbọ́ọ̀dù yóò tún bẹ̀rẹ̀ fún ìgbà díẹ̀. + A ti ṣàtúnṣe dáàṣíbọ́ọ̀dù. + Àtúnṣe kùnà — a pa ẹ̀yà tí ó ṣáájú mọ́. + Èyí ń gba àkókò ju ti àtẹ̀yìnwá lọ. Yóò parí ní ẹ̀yìn — ṣàyẹ̀wò ẹ̀yà náà láìpẹ́. + Kò lè bẹ̀rẹ̀ àtúnṣe. Gbìyànjú lẹ́ẹ̀kansi. Dashboard (REST API) Kókó ètò · fi sori ẹrọ nígbà gbogbo Dasibọ́ọ̀dù ni kókó REST API ti àpótí náà (dash-node): iṣẹ́ Node kékeré kan ní 127.0.0.1:4000, tí nginx ń ṣe ìránṣẹ́ tí pdsm sì ń bójútó. Ó ń ṣe àtìlẹ́yìn fún gbogbo iṣẹ́ ilé-ìkàwé nínú áàpù: ríràwo àti gbígba Àwọn Ìwé, fífi kún àti pípa àkóónú Wikipedia àti ZIM rẹ́, àwọn ìpàdé Kolibri, Àwọn Máàpù àti ipò ètò. Yàtọ̀ sí àwọn módù àkóónú, kì í ṣe ohun tí o fi sori ẹrọ tàbí yọ kúrò — ó wá pẹ̀lú àpótí náà ó sì wà nígbà gbogbo. Nígbà tí ẹ̀yà tuntun bá wà, o lè tún un kọ́ níbẹ̀. diff --git a/controller/app/src/main/res/values-zh-rCN/strings_k2go.xml b/controller/app/src/main/res/values-zh-rCN/strings_k2go.xml index 53b3185e..de795352 100644 --- a/controller/app/src/main/res/values-zh-rCN/strings_k2go.xml +++ b/controller/app/src/main/res/values-zh-rCN/strings_k2go.xml @@ -680,6 +680,12 @@ 重建 REST 核心? 将 dash-node 更新到最新版本。重建期间服务器会短暂不可用;完成前请勿离开此界面。 重建需要互联网连接。 + 正在更新仪表板 + 正在原地更新… 仪表板会短暂重启。 + 仪表板已更新。 + 更新失败 — 已保留先前版本。 + 这比平常花的时间更长。它会在后台完成 — 稍后查看版本。 + 无法开始更新。请重试。 Dashboard (REST API) 系统核心 · 始终已安装 仪表板是设备的 REST API 核心(dash-node):运行在 127.0.0.1:4000 上的小型 Node 服务,由 nginx 提供并由 pdsm 监管。它驱动应用内的每一项库操作:浏览和下载图书、添加和删除 Wikipedia 和 ZIM 内容、Kolibri 会话、地图以及系统状态。与内容模块不同,它无法安装或删除——它随设备提供且始终存在。有更新版本时,你可以就地重建它。 diff --git a/controller/app/src/main/res/values/strings_k2go.xml b/controller/app/src/main/res/values/strings_k2go.xml index b197df9f..00eb685d 100644 --- a/controller/app/src/main/res/values/strings_k2go.xml +++ b/controller/app/src/main/res/values/strings_k2go.xml @@ -783,6 +783,13 @@ Rebuild the REST core? Updates dash-node to the latest version. The server is briefly unavailable while it rebuilds; don\'t leave this screen until it finishes. Rebuild needs an internet connection. + + Updating the dashboard + Updating in place… the dashboard restarts briefly. + Dashboard updated. + Update failed — the previous version was kept. + This is taking longer than usual. It will finish in the background — check the version in a moment. + Couldn\'t start the update. Try again. Dashboard (REST API) System core · always installed diff --git a/static/dashboard/CHANGELOG.md b/static/dashboard/CHANGELOG.md index 392d89f0..451462ce 100644 --- a/static/dashboard/CHANGELOG.md +++ b/static/dashboard/CHANGELOG.md @@ -4,6 +4,7 @@ One line per version, newest first. Every REST-facing change bumps the version i (the app surfaces it via `/system/dashboard/update-check` and the "Update available" pill), so this file is the human record of what each bump enables. Keep entries short: `version - change (TICKET)`. +- **1.2.0** - Self-update cutover baseline: no endpoint change, but from this version the app updates the dash-node core **live over REST** (`POST /system/dashboard/rebuild`, the blue-green rebuild from ADFA-5011) instead of a proot rebuild. Installs on < 1.2.0 still use the proot path to reach 1.2.0; 1.2.0+ update to 1.2.1+ via REST. (ADFA-5051) - **1.1.6** - Kolibri modules now in English. REST-facing because the diagnostic text changed: the `blockers[]` strings from `GET /kolibri/ready` and the `error` text on Kolibri jobs. Shapes, status codes and field names are unchanged. - **1.1.5** - Credentials: `POST /credentials/calibre` now validates against live Calibre-Web (401 on reject, save-unverified when the service is down); `GET /credentials/:service` returns the default password only while still at the factory default, for full form prefill. (ADFA-5044) - **1.1.4** - Calibre-Web auto-login: send Flask-Login `remember_me` so the session includes a persistent `remember_token`, which sticks in the WebView despite anonymous/guest browsing. (ADFA-5043) diff --git a/static/dashboard/package-lock.json b/static/dashboard/package-lock.json index 720ddf3d..77005974 100644 --- a/static/dashboard/package-lock.json +++ b/static/dashboard/package-lock.json @@ -1,12 +1,12 @@ { "name": "dashboard-console", - "version": "1.1.6", + "version": "1.2.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "dashboard-console", - "version": "1.1.6", + "version": "1.2.0", "license": "ISC", "dependencies": { "better-sqlite3": "^12.8.0", diff --git a/static/dashboard/package.json b/static/dashboard/package.json index 0ba9c7be..865b5193 100644 --- a/static/dashboard/package.json +++ b/static/dashboard/package.json @@ -1,6 +1,6 @@ { "name": "dashboard-console", - "version": "1.1.6", + "version": "1.2.0", "description": "", "main": "index.js", "scripts": { From aa009c6fa46d496a1f67ef7f58fb7e5d00eedeed Mon Sep 17 00:00:00 2001 From: Luis Guzman Date: Thu, 6 Aug 2026 15:41:23 -0600 Subject: [PATCH 2/4] ADFA-5051: make the update source branch configurable (K2GO_DASH_BRANCH) update-check and the REST rebuild now read the tracked branch from K2GO_DASH_BRANCH (default "main"), and the rebuild spawn is passed the same branch so both always agree on the source. Lets a test box point at a feature branch to exercise the live self-update before merging, without code changes; unset in production it tracks main exactly as before. Rides in the unreleased 1.2.0 (prod-safe, no version bump). --- static/dashboard/routes.ts | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/static/dashboard/routes.ts b/static/dashboard/routes.ts index d407cc7a..22a95e3c 100644 --- a/static/dashboard/routes.ts +++ b/static/dashboard/routes.ts @@ -241,6 +241,11 @@ apiRouter.post('/kiwix/delete', (req: Request, res: Response): void => { // restarting dash-node mid-run never kills it. Declared before the generic /:type/* routes. const REBUILD_SCRIPT = '/opt/iiab-android/tools/rebuild-dashboard.sh'; const REBUILD_STATUS_FILE = '/var/run/dash-rebuild.status'; +// ADFA-5051: the remote branch that update-check compares against AND the rebuild pulls. Defaults to +// mainline; set K2GO_DASH_BRANCH in the dash-node env to point a test box at a feature branch (e.g. +// to exercise the live self-update before merging to main) without touching code. Keep it unset in +// production so both always track main. +const DASH_BRANCH = process.env.K2GO_DASH_BRANCH || 'main'; // Installed dash-node version (from package.json), so the module card can show it + compare. apiRouter.get('/system/version', (_req: Request, res: Response): void => { @@ -268,7 +273,11 @@ apiRouter.post('/system/dashboard/rebuild', (_req: Request, res: Response): void if (!fs.existsSync(REBUILD_SCRIPT)) { res.status(500).json({ error: 'rebuild script not found' }); return; } try { // setsid => own session, so `pdsm restart dash-node` inside the script can't kill this run. - const child = spawn('setsid', ['sh', REBUILD_SCRIPT], { detached: true, stdio: 'ignore' }); + // Pass the tracked branch so the REST rebuild and update-check always agree on the source. + const child = spawn('setsid', ['sh', REBUILD_SCRIPT], { + detached: true, stdio: 'ignore', + env: { ...process.env, K2GO_BRANCH: DASH_BRANCH }, + }); child.unref(); res.status(202).json({ ok: true, state: 'running' }); } catch (e: any) { @@ -282,7 +291,7 @@ apiRouter.post('/system/dashboard/rebuild', (_req: Request, res: Response): void // clone and reuses its existing git auth (like the rebuild). Network-bound, so it runs with a timeout // and returns 503 (not 500) when the remote can't be reached, letting the app keep its last-known state. const UPDATE_CLONE_DIR = '/opt/iiab-android'; -const UPDATE_BRANCH = 'main'; +const UPDATE_BRANCH = DASH_BRANCH; // ADFA-5051: same branch the rebuild pulls (K2GO_DASH_BRANCH override) const UPDATE_PKG_IN_CLONE = 'static/dashboard/package.json'; /** Run git inside the on-device clone with a hard timeout; resolves stdout, rejects on non-zero/timeout. */ From 5592dcf1dbcc7487e3e7ef021e813dd363449313 Mon Sep 17 00:00:00 2001 From: Luis Guzman Date: Thu, 6 Aug 2026 18:52:11 -0600 Subject: [PATCH 3/4] ADFA-5051: harden the live rebuild (proot .l2s. cleanup, rollback completeness, re-verify) Fixes found by on-device testing of the self-update: - proot ".l2s." symlink-loop artifacts (better-sqlite3 build) made cp -a / rm -rf choke and left staging cruft -> copy node_modules with tar --exclude='*.l2s.*' + purge_staging(). - rollback was dist-only: source + package.json synced BEFORE the live verify, so a bad-live update rolled back the binary but reported the failed version. Reorder: swap dist -> verify -> only THEN advance source + package.json + vhost. A failed verify leaves zero drift. - re-verify the rolled-back build actually recovered (log healthy/degraded). - clean the dist backup on every path. Folds into the unreleased 1.2.0 (no API change, no version bump). --- tools/rebuild-dashboard.sh | 92 ++++++++++++++++++++++++++------------ 1 file changed, 64 insertions(+), 28 deletions(-) diff --git a/tools/rebuild-dashboard.sh b/tools/rebuild-dashboard.sh index 560ea497..d53c72b8 100755 --- a/tools/rebuild-dashboard.sh +++ b/tools/rebuild-dashboard.sh @@ -1,15 +1,21 @@ #!/bin/sh -# tools/rebuild-dashboard.sh [CLONE_DIR] — ADFA-5011 +# tools/rebuild-dashboard.sh [CLONE_DIR] — ADFA-5011 / ADFA-5051 # # Rebuild ONLY the dash-node REST API from the on-device clone, without a rootfs rebuild. -# Blue-green + verify-before-swap so the live API is never left in a broken state: +# Blue-green + verify-before-commit so the live API is never left in a broken or misreporting state: # # 1. git fetch + reset --hard origin/ (deterministic; the box clone isn't edited) # 2. build in a STAGING dir (yarn install + build) # 3. smoke-test the STAGED build on a temp port (tools/dashboard-smoketest.sh) -# 4. only if it passes: back up live dist, atomically swap staged dist in, sync source + nginx, -# restart dash-node + nginx, and re-verify LIVE -# 5. if the live check fails: roll back to the backed-up dist and restart +# 4. only if it passes: back up live dist, sync node_modules, atomically swap the dist in, restart +# dash-node, and verify LIVE +# 5a. live OK -> FINALIZE: only now advance source + package.json + nginx vhost to match the running +# dist (so the reported version can never get ahead of the code), reload nginx, done. +# 5b. live FAIL -> roll the dist back, restart, and RE-VERIFY the rollback recovered. Because source + +# package.json were never advanced (5a), a failed update leaves NO version/source drift. +# +# ADFA-5051 also hardens: proot ".l2s." symlink-loop artifacts no longer break the node_modules copy or +# the staging cleanup (see purge_staging), and the backup is cleaned on every path. # # If step 1-3 fail, the LIVE dashboard is never touched. Launched DETACHED (setsid) by # POST /api/system/dashboard/rebuild, so the `pdsm restart dash-node` in step 4 cannot kill @@ -34,7 +40,24 @@ LOCK="/var/run/dash-rebuild.lock" log() { echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*" >> "$LOG" 2>/dev/null; } set_status() { echo "$1" > "$STATUS" 2>/dev/null || true; } -cleanup() { [ -n "${TESTPID:-}" ] && kill "$TESTPID" 2>/dev/null || true; rm -rf "$STAGE"; rmdir "$LOCK" 2>/dev/null || true; } +# ADFA-5051: proot renders some native-build symlinks (e.g. in better-sqlite3/build) as ".l2s." loops +# that `rm -rf` can't recurse into (ELOOP -> "Directory not empty"), but a direct unlink removes them. +# Sweep them first, then remove the tree — so staging is always cleanly removable. +purge_staging() { + [ -d "$STAGE" ] || return 0 + find "$STAGE" -name '*.l2s.*' -exec rm -f {} + 2>/dev/null || true + rm -rf "$STAGE" 2>/dev/null || true +} +# ADFA-5051: poll the LIVE API's smoke test until it passes (~30s) or give up (1 = not healthy). +verify_live() { + _i=1 + while [ "$_i" -le 15 ]; do + if sh "$SMOKE" "http://127.0.0.1:4000/api" >>"$LOG" 2>&1; then return 0; fi + sleep 2; _i=$((_i + 1)) + done + return 1 +} +cleanup() { [ -n "${TESTPID:-}" ] && kill "$TESTPID" 2>/dev/null || true; purge_staging; rmdir "$LOCK" 2>/dev/null || true; } fail() { log "FAIL: $*"; set_status "error"; cleanup; exit 1; } # Single-flight: mkdir is atomic. @@ -55,9 +78,14 @@ git -C "$CLONE_DIR" reset --hard "origin/$BRANCH" >>"$LOG" 2>&1 || fail "git res # 2) build in staging. Reuse live node_modules to speed the install; build fresh dist. log "staging build" -rm -rf "$STAGE"; mkdir -p "$STAGE" || fail "mkdir staging" +purge_staging; mkdir -p "$STAGE" || fail "mkdir staging" ( cd "$SRC" && tar --exclude=node_modules --exclude=dist -cf - . ) | ( cd "$STAGE" && tar -xf - ) || fail "copy source to staging" -[ -d "$LIVE/node_modules" ] && cp -a "$LIVE/node_modules" "$STAGE/node_modules" +# Warm the install from the live node_modules to speed `yarn install`. Use tar (not cp -a) and EXCLUDE +# proot's ".l2s." loop artifacts so the copy never trips on them (cp -a would ELOOP) and staging stays +# cleanly removable; yarn reconciles anything missing. +if [ -d "$LIVE/node_modules" ]; then + ( cd "$LIVE" && tar --exclude='*.l2s.*' -cf - node_modules ) | ( cd "$STAGE" && tar -xf - ) || true +fi ( cd "$STAGE" && yarn install >>"$LOG" 2>&1 && yarn build >>"$LOG" 2>&1 ) || fail "yarn install/build (offline or build error) — live untouched" [ -f "$STAGE/dist/server.js" ] || fail "no dist/server.js after build — live untouched" @@ -71,34 +99,34 @@ RC=$? kill "$TESTPID" 2>/dev/null || true; wait "$TESTPID" 2>/dev/null || true; TESTPID="" [ "$RC" -eq 0 ] || fail "staged smoke test failed (rc=$RC) — NOT promoting; live untouched" -# 4) promote: back up live dist, swap staged in, sync source + nginx, restart. +# 4) promote — swap the dist FIRST and verify it live; only advance source + package.json (and the +# nginx vhost) AFTER the live check passes. That way a failed verify rolls back the dist and the +# version/source were NEVER touched, so the box can't report a version it isn't actually running. log "staged build passed — promoting" rm -rf "$BACKUP" [ -d "$LIVE/dist" ] && cp -a "$LIVE/dist" "$BACKUP" -# Sync source (so the next build matches) — additive tar after dropping pure-source subdirs; -# runtime state (node_modules, *.sqlite3 job storage, books/catalog.db) is left in place. -for d in sockets views public test; do rm -rf "$LIVE/$d"; done -( cd "$STAGE" && tar --exclude=node_modules --exclude=dist -cf - . ) | ( cd "$LIVE" && tar -xf - ) || fail "sync source to live" -cp -a "$STAGE/node_modules/." "$LIVE/node_modules/" 2>/dev/null || true +# node_modules is additive (new deps added, old ones remain), so the old dist tolerates it on rollback; +# safe to sync before the swap so the new dist has its dependencies. tar+exclude avoids the ".l2s." loops. +( cd "$STAGE" && tar --exclude='*.l2s.*' -cf - node_modules ) | ( cd "$LIVE" && tar -xf - ) || true # The dist swap is the near-atomic, restart-critical step (dash-node runs dist/server.js). rm -rf "$LIVE/dist" && cp -a "$STAGE/dist" "$LIVE/dist" || fail "dist swap" -# nginx reads /etc/nginx/conf.d, not /library/dashboard, so mirror the vhost. -[ -f "$LIVE/dash-node-nginx.conf" ] && { cp -f "$LIVE/dash-node-nginx.conf" "$NGINX_CONF_DIR/dash-node-nginx.conf"; chmod 0600 "$NGINX_CONF_DIR/dash-node-nginx.conf"; } -log "restart dash-node + nginx" +log "restart dash-node" /usr/local/bin/pdsm restart dash-node >>"$LOG" 2>&1 || log "warn: pdsm restart dash-node returned non-zero" -/usr/local/bin/pdsm restart nginx >>"$LOG" 2>&1 || log "warn: pdsm restart nginx returned non-zero" -# 5) verify LIVE; roll back the dist if it doesn't come up. +# 5) verify LIVE. On success, finalize (source + package.json + nginx); on failure, roll the dist back. log "verifying live :4000" -ok=0 -i=1 -while [ "$i" -le 15 ]; do - if sh "$SMOKE" "http://127.0.0.1:4000/api" >>"$LOG" 2>&1; then ok=1; break; fi - sleep 2; i=$((i + 1)) -done -if [ "$ok" -eq 1 ]; then - log "live OK — rebuild complete" +if verify_live; then + log "live OK — finalizing (source + package.json + nginx)" + # Now safe to advance the source so the reported version + the next build match the running dist. + # Additive tar after dropping the pure-source subdirs; runtime state (node_modules, *.sqlite3 job + # storage, books/catalog.db) is left in place. + for d in sockets views public test; do rm -rf "$LIVE/$d"; done + ( cd "$STAGE" && tar --exclude=node_modules --exclude=dist -cf - . ) | ( cd "$LIVE" && tar -xf - ) || log "warn: source sync incomplete" + # nginx reads /etc/nginx/conf.d, not /library/dashboard, so mirror the vhost then reload nginx. + [ -f "$LIVE/dash-node-nginx.conf" ] && { cp -f "$LIVE/dash-node-nginx.conf" "$NGINX_CONF_DIR/dash-node-nginx.conf"; chmod 0600 "$NGINX_CONF_DIR/dash-node-nginx.conf"; } + /usr/local/bin/pdsm restart nginx >>"$LOG" 2>&1 || log "warn: pdsm restart nginx returned non-zero" + log "rebuild complete" rm -rf "$BACKUP" set_status "done" else @@ -106,8 +134,16 @@ else if [ -d "$BACKUP" ]; then rm -rf "$LIVE/dist" && cp -a "$BACKUP" "$LIVE/dist" /usr/local/bin/pdsm restart dash-node >>"$LOG" 2>&1 || true - log "rolled back to previous dist" + # Confirm the rolled-back build actually recovered — don't just assume it did. + if verify_live; then + log "rolled back — verified healthy on the previous build (source + version were never advanced)" + else + log "ROLLBACK VERIFY FAILED — dashboard may be degraded; manual check needed" + fi + else + log "no backup available to roll back to — dashboard may be degraded" fi + rm -rf "$BACKUP" set_status "error" fi cleanup From 64f3be33892f0c8040004ce1cdd197a26b71dbb0 Mon Sep 17 00:00:00 2001 From: Luis Guzman Date: Thu, 6 Aug 2026 20:31:14 -0600 Subject: [PATCH 4/4] ADFA-5051: fix live-update UI feedback (stale status + pill refresh) From on-device UI testing: - POST /system/dashboard/rebuild writes status="running" synchronously before returning, so a client polling immediately can't read the PREVIOUS run's "done" and report a false instant success (the detached script set "running" only after it started). - After a successful live REST update, the dashboard card refreshes its version chip + update pill in place (fetchVersionChip reuses one chip, no duplicate) so it flips to "Up to date"/new version without leaving and re-opening. Folds into the unreleased 1.2.0 (no API change). --- .../redesign/DashboardDetailFragment.java | 21 ++++++++--- .../controller/redesign/DashboardRebuild.java | 36 +++++++++++-------- .../redesign/ModuleHubFragment.java | 2 +- static/dashboard/routes.ts | 4 +++ 4 files changed, 44 insertions(+), 19 deletions(-) diff --git a/controller/app/src/main/java/org/iiab/controller/redesign/DashboardDetailFragment.java b/controller/app/src/main/java/org/iiab/controller/redesign/DashboardDetailFragment.java index 9463a78d..1a39b0de 100644 --- a/controller/app/src/main/java/org/iiab/controller/redesign/DashboardDetailFragment.java +++ b/controller/app/src/main/java/org/iiab/controller/redesign/DashboardDetailFragment.java @@ -37,6 +37,7 @@ public class DashboardDetailFragment extends Fragment { private final Handler main = new Handler(Looper.getMainLooper()); private ViewGroup chips; // FlowLayout in XML — typed as ViewGroup so it wraps chips to 2 lines private TextView statusChip; // ADFA-5026: live "Up to date / Update available" pill (restyled in place) + private TextView versionChip; // ADFA-5051: "v" chip, updated in place after a live update private Button rebuild; // de-emphasized when already on the latest private TextView rebuildHint; // "no rebuild needed" note, shown only when on the latest @@ -72,7 +73,7 @@ public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup c // "Rebuild"; hide the secondary "Install now". rebuild = root.findViewById(R.id.k2go_moddet_schedule); rebuild.setText(R.string.k2go_dash_rebuild); - rebuild.setOnClickListener(v -> DashboardRebuild.confirmAndStart(this, root)); + rebuild.setOnClickListener(v -> DashboardRebuild.confirmAndStart(this, root, this::refreshAfterLiveUpdate)); root.findViewById(R.id.k2go_moddet_install_now).setVisibility(View.GONE); rebuildHint = buildRebuildHint(rebuild); // ADFA-5026: "no rebuild needed" note (hidden until on-latest) @@ -138,19 +139,31 @@ private TextView buildRebuildHint(Button rebuildBtn) { } /** Read the installed version from the rootfs package.json on disk (authoritative, always present; - * no network/proot) and, if found, prepend a "v" chip. */ + * no network/proot) and show a "v" chip. ADFA-5051: reuses the same chip on refresh so a + * live update updates it in place instead of prepending a duplicate. */ private void fetchVersionChip() { final Context ctx = requireContext().getApplicationContext(); AppExecutors.get().io().execute(() -> { final String ver = DashboardVersion.installed(ctx); main.post(() -> { - if (isAdded() && chips != null && ver != null) { - chips.addView(chip("v" + ver, R.color.k2go_teal), 0); + if (!isAdded() || chips == null || ver == null) return; + if (versionChip == null) { + versionChip = chip("v" + ver, R.color.k2go_teal); + chips.addView(versionChip, 0); + } else { + styleChip(versionChip, "v" + ver, R.color.k2go_teal); } }); }); } + /** ADFA-5051: after a successful live (REST) update, refresh the version chip + update pill in + * place so the card reflects the new version immediately (no need to leave and re-open). */ + private void refreshAfterLiveUpdate() { + fetchVersionChip(); + fetchUpdateStatus(); + } + /** Small outlined pill for the meta-chip row (matches ModuleDetailFragment). */ private TextView chip(String text, int colorRes) { float d = getResources().getDisplayMetrics().density; diff --git a/controller/app/src/main/java/org/iiab/controller/redesign/DashboardRebuild.java b/controller/app/src/main/java/org/iiab/controller/redesign/DashboardRebuild.java index b4208a0c..d6381d5a 100644 --- a/controller/app/src/main/java/org/iiab/controller/redesign/DashboardRebuild.java +++ b/controller/app/src/main/java/org/iiab/controller/redesign/DashboardRebuild.java @@ -27,6 +27,7 @@ import android.widget.TextView; import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import androidx.appcompat.app.AlertDialog; import androidx.fragment.app.Fragment; @@ -47,8 +48,11 @@ private DashboardRebuild() {} private static final long POLL_MS = 2500L; private static final int MAX_POLLS = 160; // ~6.5 min - /** Gate then confirm then start. {@code anchor} is where a "busy"/"no internet" snackbar shows. */ - public static void confirmAndStart(@NonNull Fragment host, @NonNull View anchor) { + /** Gate then confirm then start. {@code anchor} is where a "busy"/"no internet" snackbar shows. + * {@code onLiveUpdated} (nullable) runs after a successful LIVE (REST) update so the caller can + * refresh its version chip / update pill in place (ADFA-5051). */ + public static void confirmAndStart(@NonNull Fragment host, @NonNull View anchor, + @Nullable Runnable onLiveUpdated) { Context ctx = host.requireContext(); if (org.iiab.controller.env.EnvironmentLock.isHeld(ctx)) { Snackbars.make(anchor, R.string.k2go_install_busy).show(); @@ -62,21 +66,21 @@ public static void confirmAndStart(@NonNull Fragment host, @NonNull View anchor) .setTitle(R.string.k2go_dash_rebuild_confirm_title) .setMessage(R.string.k2go_dash_rebuild_confirm_msg) .setNegativeButton(android.R.string.cancel, null) - .setPositiveButton(R.string.k2go_dash_rebuild, (d, w) -> start(host, anchor)) + .setPositiveButton(R.string.k2go_dash_rebuild, (d, w) -> start(host, anchor, onLiveUpdated)) .show(); } /** ADFA-5051: route by the installed dash-node version. >= 1.2.0 updates live over REST; older * installs take the proot rebuild once as a bridge to 1.2.0. The version read hits disk, so it * runs off the main thread; the routing itself is posted back to the UI. */ - private static void start(@NonNull Fragment host, @NonNull View anchor) { + private static void start(@NonNull Fragment host, @NonNull View anchor, @Nullable Runnable onLiveUpdated) { final Context app = host.requireContext().getApplicationContext(); final Handler main = new Handler(Looper.getMainLooper()); AppExecutors.get().io().execute(() -> { final boolean rest = DashboardVersion.atLeast(DashboardVersion.installed(app), 1, 2, 0); main.post(() -> { if (!host.isAdded()) return; - if (rest) startRest(host, anchor); + if (rest) startRest(host, anchor, onLiveUpdated); else startProot(host); }); }); @@ -96,7 +100,7 @@ private static void startProot(@NonNull Fragment host) { /** ADFA-5051: live REST update. Trigger the in-server rebuild, then show a non-cancelable progress * dialog that polls the state until done/error (tolerating the brief restart window). */ - private static void startRest(@NonNull Fragment host, @NonNull View anchor) { + private static void startRest(@NonNull Fragment host, @NonNull View anchor, @Nullable Runnable onLiveUpdated) { Context ctx = host.requireContext(); LinearLayout box = new LinearLayout(ctx); box.setOrientation(LinearLayout.HORIZONTAL); @@ -123,7 +127,7 @@ private static void startRest(@NonNull Fragment host, @NonNull View anchor) { DashboardClient.rebuildStart(new DashboardClient.RebuildStartCb() { @Override public void onStarted(boolean alreadyRunning) { if (!host.isAdded()) { safeDismiss(dialog); return; } - pollStatus(host, dialog, poller, new int[]{0}); + pollStatus(host, dialog, poller, new int[]{0}, onLiveUpdated); } @Override public void onErr(String message) { safeDismiss(dialog); @@ -137,14 +141,14 @@ private static void startRest(@NonNull Fragment host, @NonNull View anchor) { * NOT a failure: the rebuild runs detached server-side and may still finish, so we show a distinct * "still working in the background" message rather than the rollback/failure one. */ private static void pollStatus(@NonNull Fragment host, @NonNull AlertDialog dialog, - @NonNull Handler poller, int[] tries) { + @NonNull Handler poller, int[] tries, @Nullable Runnable onLiveUpdated) { if (!host.isAdded()) { safeDismiss(dialog); return; } - if (tries[0]++ >= MAX_POLLS) { finishRest(host, dialog, R.string.k2go_dash_live_timeout); return; } + if (tries[0]++ >= MAX_POLLS) { finishRest(host, dialog, R.string.k2go_dash_live_timeout, onLiveUpdated); return; } DashboardClient.rebuildStatus(new DashboardClient.RebuildStatusCb() { @Override public void onState(String state) { if (!host.isAdded()) { safeDismiss(dialog); return; } - if ("done".equals(state)) { finishRest(host, dialog, R.string.k2go_dash_live_done); return; } - if ("error".equals(state)) { finishRest(host, dialog, R.string.k2go_dash_live_error); return; } + if ("done".equals(state)) { finishRest(host, dialog, R.string.k2go_dash_live_done, onLiveUpdated); return; } + if ("error".equals(state)) { finishRest(host, dialog, R.string.k2go_dash_live_error, onLiveUpdated); return; } schedule(); } @Override public void onErr(String message) { @@ -152,15 +156,19 @@ private static void pollStatus(@NonNull Fragment host, @NonNull AlertDialog dial schedule(); // API likely restarting mid-swap; keep waiting } private void schedule() { - poller.postDelayed(() -> pollStatus(host, dialog, poller, tries), POLL_MS); + poller.postDelayed(() -> pollStatus(host, dialog, poller, tries, onLiveUpdated), POLL_MS); } }); } - /** Swap the progress dialog for a simple result dialog carrying {@code msgRes} (done/error/timeout). */ - private static void finishRest(@NonNull Fragment host, @NonNull AlertDialog dialog, int msgRes) { + /** Swap the progress dialog for a simple result dialog carrying {@code msgRes} (done/error/timeout). + * On success, fire {@code onLiveUpdated} (ADFA-5051) so the caller refreshes its version/pill in + * place — otherwise the card keeps showing "update available" and users re-tap Rebuild. */ + private static void finishRest(@NonNull Fragment host, @NonNull AlertDialog dialog, int msgRes, + @Nullable Runnable onLiveUpdated) { safeDismiss(dialog); if (!host.isAdded()) return; + if (msgRes == R.string.k2go_dash_live_done && onLiveUpdated != null) onLiveUpdated.run(); new MaterialAlertDialogBuilder(host.requireContext()) .setTitle(R.string.k2go_dash_live_title) .setMessage(msgRes) diff --git a/controller/app/src/main/java/org/iiab/controller/redesign/ModuleHubFragment.java b/controller/app/src/main/java/org/iiab/controller/redesign/ModuleHubFragment.java index 90cbd64f..9c6b4ab5 100644 --- a/controller/app/src/main/java/org/iiab/controller/redesign/ModuleHubFragment.java +++ b/controller/app/src/main/java/org/iiab/controller/redesign/ModuleHubFragment.java @@ -356,7 +356,7 @@ private void addSystemDashboardCard() { TextView rebuild = statePill(getString(R.string.k2go_dash_rebuild), R.color.k2go_teal); rebuild.setPadding(px(14), px(6), px(14), px(6)); - rebuild.setOnClickListener(v -> DashboardRebuild.confirmAndStart(this, host)); + rebuild.setOnClickListener(v -> DashboardRebuild.confirmAndStart(this, host, null)); LinearLayout.LayoutParams tlp = new LinearLayout.LayoutParams( LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT); tlp.leftMargin = px(10); diff --git a/static/dashboard/routes.ts b/static/dashboard/routes.ts index 22a95e3c..584b82f5 100644 --- a/static/dashboard/routes.ts +++ b/static/dashboard/routes.ts @@ -279,6 +279,10 @@ apiRouter.post('/system/dashboard/rebuild', (_req: Request, res: Response): void env: { ...process.env, K2GO_BRANCH: DASH_BRANCH }, }); child.unref(); + // ADFA-5051: mark "running" synchronously here, before we answer. The detached script also sets + // it, but not until it starts — so a client that polls immediately could otherwise read the + // PREVIOUS run's "done"/"error" and report a false instant success. Writing it now closes that race. + try { fs.writeFileSync(REBUILD_STATUS_FILE, 'running'); } catch { /* best effort */ } res.status(202).json({ ok: true, state: 'running' }); } catch (e: any) { res.status(500).json({ error: e?.message || 'could not start rebuild' });