From 18f1debdd6b900fea7036920ddec2b74990745ad Mon Sep 17 00:00:00 2001 From: Luis Guzman Date: Sun, 8 Nov 2026 04:06:51 -0600 Subject: [PATCH 1/2] K2GO-557 feat(dashboard): in-app update alerts (low-memory gate, failure dialog) Replace the system-notification advisory and failure with in-app UX: a pre-start low-memory gate, a failure dialog, and an app-wide foreground observer that re-shows a pending failure. One flag in UpdateStatusCache is the single source of truth. Low-memory trigger raised to 450 MB from on-device measurement. --- .../appdevforall/k2go/IIABApplication.java | 3 + .../org/appdevforall/k2go/SplashActivity.java | 3 +- .../dashboard/data/DeviceMemoryReader.java | 33 +++++++ .../k2go/dashboard/domain/DeviceMemory.java | 30 ++++++ .../dashboard/domain/LowMemoryAdvice.java | 34 +++++++ .../presentation/DashUpdateFailureDialog.java | 97 +++++++++++++++++++ .../dashboard/presentation/LowMemoryGate.java | 45 +++++++++ .../redesign/DashboardDetailFragment.java | 26 ++++- .../k2go/redesign/DashboardRebuild.java | 6 +- .../redesign/DashboardRebuildService.java | 35 +++++-- .../k2go/redesign/UpdateStatusCache.java | 15 +++ .../k2go/ui/ForegroundActivityHolder.java | 64 ++++++++++++ .../app/src/main/res/values/strings.xml | 9 ++ .../dashboard/domain/LowMemoryAdviceTest.java | 34 +++++++ 14 files changed, 421 insertions(+), 13 deletions(-) create mode 100644 controller/app/src/main/java/org/appdevforall/k2go/dashboard/data/DeviceMemoryReader.java create mode 100644 controller/app/src/main/java/org/appdevforall/k2go/dashboard/domain/DeviceMemory.java create mode 100644 controller/app/src/main/java/org/appdevforall/k2go/dashboard/domain/LowMemoryAdvice.java create mode 100644 controller/app/src/main/java/org/appdevforall/k2go/dashboard/presentation/DashUpdateFailureDialog.java create mode 100644 controller/app/src/main/java/org/appdevforall/k2go/dashboard/presentation/LowMemoryGate.java create mode 100644 controller/app/src/main/java/org/appdevforall/k2go/ui/ForegroundActivityHolder.java create mode 100644 controller/app/src/test/java/org/appdevforall/k2go/dashboard/domain/LowMemoryAdviceTest.java diff --git a/controller/app/src/main/java/org/appdevforall/k2go/IIABApplication.java b/controller/app/src/main/java/org/appdevforall/k2go/IIABApplication.java index fb3c07899..26d64bc00 100644 --- a/controller/app/src/main/java/org/appdevforall/k2go/IIABApplication.java +++ b/controller/app/src/main/java/org/appdevforall/k2go/IIABApplication.java @@ -76,6 +76,9 @@ public void onCreate() { // K2GO-439: one owner pads every activity's content by the system-bar insets (targetSdk 35 // edge-to-edge); screens that manage their own insets opt out via EdgeToEdge.SelfManaged. registerActivityLifecycleCallbacks(new org.appdevforall.k2go.ui.EdgeToEdgeCallbacks()); + // K2GO-557: one app-scoped holder of the foreground Activity. Exposes current() (a reusable + // handle for app-wide work) and re-shows a pending dash-node update failure on the next resume. + registerActivityLifecycleCallbacks(new org.appdevforall.k2go.ui.ForegroundActivityHolder()); } /** diff --git a/controller/app/src/main/java/org/appdevforall/k2go/SplashActivity.java b/controller/app/src/main/java/org/appdevforall/k2go/SplashActivity.java index 02d56c5f3..6e3840602 100644 --- a/controller/app/src/main/java/org/appdevforall/k2go/SplashActivity.java +++ b/controller/app/src/main/java/org/appdevforall/k2go/SplashActivity.java @@ -20,7 +20,8 @@ public class SplashActivity extends AppCompatActivity - implements org.appdevforall.k2go.ui.EdgeToEdge.SelfManaged { + implements org.appdevforall.k2go.ui.EdgeToEdge.SelfManaged, + org.appdevforall.k2go.ui.ForegroundActivityHolder.DialogExempt { private static final long EXIT_AT_MS = 3100L; private static final long EXIT_FADE_MS = 400L; diff --git a/controller/app/src/main/java/org/appdevforall/k2go/dashboard/data/DeviceMemoryReader.java b/controller/app/src/main/java/org/appdevforall/k2go/dashboard/data/DeviceMemoryReader.java new file mode 100644 index 000000000..8900e4955 --- /dev/null +++ b/controller/app/src/main/java/org/appdevforall/k2go/dashboard/data/DeviceMemoryReader.java @@ -0,0 +1,33 @@ +/* + * ============================================================================ + * Name : DeviceMemoryReader.java + * Author : AppDevForAll + * Copyright : Copyright (c) 2026 AppDevForAll + * Description : K2GO-557. Reads live device memory into a domain DeviceMemory, from + * ActivityManager.MemoryInfo (device-wide figures, not this process heap). Data layer: + * the only place in this slice that touches android.*. + * ============================================================================ + */ +package org.appdevforall.k2go.dashboard.data; + +import android.app.ActivityManager; +import android.content.Context; + +import androidx.annotation.NonNull; + +import org.appdevforall.k2go.dashboard.domain.DeviceMemory; + +public final class DeviceMemoryReader { + private DeviceMemoryReader() {} + + /** Snapshot device memory now. If ActivityManager is unavailable, return a snapshot that reads as + * "not low", so the advisory never fires on a bad read (fail open: the update is non-blocking). */ + @NonNull + public static DeviceMemory read(@NonNull Context ctx) { + ActivityManager am = (ActivityManager) ctx.getSystemService(Context.ACTIVITY_SERVICE); + if (am == null) return new DeviceMemory(Long.MAX_VALUE, 0L, false); + ActivityManager.MemoryInfo info = new ActivityManager.MemoryInfo(); + am.getMemoryInfo(info); + return new DeviceMemory(info.availMem, info.totalMem, info.lowMemory); + } +} diff --git a/controller/app/src/main/java/org/appdevforall/k2go/dashboard/domain/DeviceMemory.java b/controller/app/src/main/java/org/appdevforall/k2go/dashboard/domain/DeviceMemory.java new file mode 100644 index 000000000..31588c2f7 --- /dev/null +++ b/controller/app/src/main/java/org/appdevforall/k2go/dashboard/domain/DeviceMemory.java @@ -0,0 +1,30 @@ +/* + * ============================================================================ + * Name : DeviceMemory.java + * Author : AppDevForAll + * Copyright : Copyright (c) 2026 AppDevForAll + * Description : K2GO-557. A snapshot of device memory at one moment, as plain numbers. Pure domain: + * no android.* import, so the low-memory rule that reads it stays unit-testable on a + * plain JVM. The data source (DeviceMemoryReader) fills this from ActivityManager. + * ============================================================================ + */ +package org.appdevforall.k2go.dashboard.domain; + +public final class DeviceMemory { + private final long availableBytes; + private final long totalBytes; + private final boolean systemLowMemory; + + public DeviceMemory(long availableBytes, long totalBytes, boolean systemLowMemory) { + this.availableBytes = availableBytes; + this.totalBytes = totalBytes; + this.systemLowMemory = systemLowMemory; + } + + public long availableBytes() { return availableBytes; } + + public long totalBytes() { return totalBytes; } + + /** True when Android already reports the system is under memory pressure (MemoryInfo.lowMemory). */ + public boolean systemLowMemory() { return systemLowMemory; } +} diff --git a/controller/app/src/main/java/org/appdevforall/k2go/dashboard/domain/LowMemoryAdvice.java b/controller/app/src/main/java/org/appdevforall/k2go/dashboard/domain/LowMemoryAdvice.java new file mode 100644 index 000000000..ba41b6981 --- /dev/null +++ b/controller/app/src/main/java/org/appdevforall/k2go/dashboard/domain/LowMemoryAdvice.java @@ -0,0 +1,34 @@ +/* + * ============================================================================ + * Name : LowMemoryAdvice.java + * Author : AppDevForAll + * Copyright : Copyright (c) 2026 AppDevForAll + * Description : K2GO-557. The single rule for "should we advise the user to close apps before this + * dash-node update". The update stages a second node and a tsc build next to the live + * server, so it needs working memory. We advise ONLY when free memory is at or below + * what the update needs: with clear headroom we stay silent (no nagging). The advice is + * advisory, never a gate: the update still runs. Pure domain, unit-tested. + * ============================================================================ + */ +package org.appdevforall.k2go.dashboard.domain; + +public final class LowMemoryAdvice { + private LowMemoryAdvice() {} + + /** + * Working memory the live update needs (the staging node plus the tsc build, beside the live + * server). Measured on a 64-bit device for K2GO-557: a cold build (the box was idle, which is the + * real user case) consumes about 386 MB and also uses swap. This value is that peak plus a small + * margin. We advise only at or below it, so a device with clear headroom is left alone. Tune it + * again from field results. A 32-bit device runs lighter per process but has far less headroom. + */ + public static final long UPDATE_WORKING_SET_BYTES = 450L * 1024L * 1024L; // about 450 MB + + /** Advise (advisory only) when the system already reports memory pressure, or when free memory is + * at or below what the update needs. */ + public static boolean shouldAdviseCloseApps(DeviceMemory memory) { + if (memory == null) return false; + if (memory.systemLowMemory()) return true; + return memory.availableBytes() <= UPDATE_WORKING_SET_BYTES; + } +} diff --git a/controller/app/src/main/java/org/appdevforall/k2go/dashboard/presentation/DashUpdateFailureDialog.java b/controller/app/src/main/java/org/appdevforall/k2go/dashboard/presentation/DashUpdateFailureDialog.java new file mode 100644 index 000000000..4e018a6d6 --- /dev/null +++ b/controller/app/src/main/java/org/appdevforall/k2go/dashboard/presentation/DashUpdateFailureDialog.java @@ -0,0 +1,97 @@ +/* + * ============================================================================ + * Name : DashUpdateFailureDialog.java + * Author : AppDevForAll + * Copyright : Copyright (c) 2026 AppDevForAll + * Description : K2GO-557. The IN-APP "dashboard update failed" notice, replacing the old system + * notification. Shown two ways from one guarded helper: the instant pop while the user + * watches the card (STATE_ERROR broadcast), and a re-show on the next foreground when the + * failure happened with no screen watching (maybeShow, driven by the persisted flag in + * UpdateStatusCache). Any dismissal acknowledges the failure (clears the flag), so it shows + * once per failure and never nags. Mirrors LibraryActivity.showDamagedDialog. + * ============================================================================ + */ +package org.appdevforall.k2go.dashboard.presentation; + +import android.app.Activity; +import android.view.ContextThemeWrapper; + +import androidx.annotation.NonNull; +import androidx.annotation.StringRes; + +import org.appdevforall.k2go.LogRepository; +import org.appdevforall.k2go.R; +import org.appdevforall.k2go.feedback.domain.FeedbackType; +import org.appdevforall.k2go.feedback.presentation.FeedbackFab; +import org.appdevforall.k2go.redesign.OpReturnNavigator; +import org.appdevforall.k2go.redesign.UpdateStatusCache; +import org.appdevforall.k2go.ui.dialog.BrandDialog; + +import java.lang.ref.WeakReference; +import java.util.List; + +public final class DashUpdateFailureDialog { + private DashUpdateFailureDialog() {} + + // One dialog at a time across the app: the instant pop (dashboard) and the app-wide re-show + // (ForegroundActivityHolder) both route here, so guard against a second copy stacking on top. + private static WeakReference showing; + + private static boolean isShowing() { + BrandDialog.Handle h = showing == null ? null : showing.get(); + return h != null && h.getDialog() != null && h.getDialog().isShowing(); + } + + /** + * Re-show a pending failure on any foreground screen (the app-wide path). No-op when nothing is + * pending or a copy is already up. The primary action opens the dashboard, where Rebuild retries. + */ + public static void maybeShow(@NonNull Activity act) { + if (!UpdateStatusCache.pendingFailure(act)) return; + show(act, R.string.k2go_dash_update_open_dashboard, () -> openDashboard(act)); + } + + /** + * Show the failure dialog now. {@code primaryText}/{@code onPrimary} are the primary action: "Try + * again" in place on the dashboard card, or "Open dashboard" from any other screen. The reason line is + * the same for every failure ("the previous version was kept", which holds whether the build failed or + * never started), so it is not threaded through: one accurate message, one source. + */ + public static void show(@NonNull Activity act, @StringRes int primaryText, @NonNull Runnable onPrimary) { + if (act.isFinishing() || act.isDestroyed() || isShowing()) return; + CharSequence message = act.getString(R.string.k2go_dash_live_error) + "\n\n" + + act.getString(R.string.k2go_dash_update_failed_text); + // Theme-wrap so the Material dialog inflates even if the host Activity's own theme is not Material. + BrandDialog.Handle h = new BrandDialog(new ContextThemeWrapper(act, R.style.Theme_K2Go)) + .setIcon(R.drawable.ic_error_outline_24, R.color.k2go_clay) + .setTitle(R.string.k2go_dash_update_failed_title) + .setMessage(message) + .setPositive(primaryText, BrandDialog.Role.PRIMARY, () -> { ack(act); onPrimary.run(); }) + .setNegative(R.string.k2go_damaged_close, () -> ack(act)) + // Report sends the APK log tail and keeps the dialog up (box-side log is deferred, K2GO-557). + .setNeutral(R.string.k2go_damaged_report, () -> FeedbackFab.sendFeedback( + act, "dash-update-failed", FeedbackType.BUG, report())) + .setDismissOnNeutral(false) + .setOnCancel(() -> ack(act)) + .show(); + showing = new WeakReference<>(h); + } + + /** Acknowledge: a failure the user has now seen is no longer pending. */ + private static void ack(@NonNull Activity act) { + UpdateStatusCache.setPendingFailure(act, false); + } + + private static void openDashboard(@NonNull Activity act) { + act.startActivity(OpReturnNavigator.dashboardRebuild(act)); + } + + /** K2GO-557: the APK-side log tail, as the body of a report. Box-side log is a later ticket. */ + private static String report() { + List all = LogRepository.get().snapshot(); + int from = Math.max(0, all.size() - 80); + StringBuilder sb = new StringBuilder("Dashboard update did not finish. Last lines:\n"); + for (int i = from; i < all.size(); i++) sb.append(all.get(i)).append('\n'); + return sb.toString(); + } +} diff --git a/controller/app/src/main/java/org/appdevforall/k2go/dashboard/presentation/LowMemoryGate.java b/controller/app/src/main/java/org/appdevforall/k2go/dashboard/presentation/LowMemoryGate.java new file mode 100644 index 000000000..2a92e0418 --- /dev/null +++ b/controller/app/src/main/java/org/appdevforall/k2go/dashboard/presentation/LowMemoryGate.java @@ -0,0 +1,45 @@ +/* + * ============================================================================ + * Name : LowMemoryGate.java + * Author : AppDevForAll + * Copyright : Copyright (c) 2026 AppDevForAll + * Description : K2GO-557. Pre-start in-app gate for the dash-node live update. When the device is low on + * memory the update may fail, so warn BEFORE it starts and let the user close other apps + * first ("Not now") or proceed ("Start anyway"). Presentation only: the "is memory tight" + * rule stays pure in LowMemoryAdvice, the read in DeviceMemoryReader; this just turns that + * boolean into a dialog. Mirrors dependency.presentation.DashNodeGate. + * ============================================================================ + */ +package org.appdevforall.k2go.dashboard.presentation; + +import android.app.Activity; +import android.view.ContextThemeWrapper; + +import androidx.annotation.NonNull; + +import org.appdevforall.k2go.R; +import org.appdevforall.k2go.dashboard.data.DeviceMemoryReader; +import org.appdevforall.k2go.dashboard.domain.LowMemoryAdvice; +import org.appdevforall.k2go.ui.dialog.BrandDialog; + +public final class LowMemoryGate { + private LowMemoryGate() {} + + /** + * Run {@code onProceed} straight away when memory is fine. When it is tight, show the advisory and run + * {@code onProceed} only if the user picks "Start anyway"; "Not now" (or dismissing) does nothing, so + * the user can close apps and retry. Advisory, not a block: the choice is always the user's. + */ + public static void guard(@NonNull Activity act, @NonNull Runnable onProceed) { + if (!LowMemoryAdvice.shouldAdviseCloseApps(DeviceMemoryReader.read(act))) { + onProceed.run(); + return; + } + new BrandDialog(new ContextThemeWrapper(act, R.style.Theme_K2Go)) + .setTitle(R.string.k2go_dash_lowmem_title) + .setMessage(R.string.k2go_dash_lowmem_text) + .setPositive(R.string.k2go_dash_lowmem_start_anyway, BrandDialog.Role.PRIMARY, onProceed::run) + .setNegative(R.string.k2go_dash_lowmem_not_now, null) + .show(); + } +} diff --git a/controller/app/src/main/java/org/appdevforall/k2go/redesign/DashboardDetailFragment.java b/controller/app/src/main/java/org/appdevforall/k2go/redesign/DashboardDetailFragment.java index 3a6339a77..2d47aef6f 100644 --- a/controller/app/src/main/java/org/appdevforall/k2go/redesign/DashboardDetailFragment.java +++ b/controller/app/src/main/java/org/appdevforall/k2go/redesign/DashboardDetailFragment.java @@ -87,8 +87,13 @@ public class DashboardDetailFragment extends Fragment { } else if (DashboardRebuildService.STATE_DONE.equals(state)) { setUpdating(false); refreshAfterLiveUpdate(); - } else if (DashboardRebuildService.STATE_ERROR.equals(state) - || DashboardRebuildService.STATE_CANCELLED.equals(state)) { + } else if (DashboardRebuildService.STATE_ERROR.equals(state)) { + setUpdating(false); + fetchUpdateStatus(); // version unchanged; re-resolve the pill/emphasis + // K2GO-557: pop the in-app failure dialog now (the user is watching). The service already + // set the pending-failure flag, so if this card is gone it re-shows app-wide instead. + showFailureHere(); + } else if (DashboardRebuildService.STATE_CANCELLED.equals(state)) { setUpdating(false); fetchUpdateStatus(); // version unchanged; re-resolve the pill/emphasis } @@ -154,6 +159,23 @@ public void onStart() { ContextCompat.registerReceiver(requireContext(), rebuildState, f, ContextCompat.RECEIVER_NOT_EXPORTED); resolveInitialUpdatingState(); + // K2GO-557: if a past update failed while this card was away, re-show it HERE (Try again retries + // in place). onStart runs before the app-wide holder's resume, so the card's "Try again" wins over + // the holder's generic "Open dashboard" (the shared dialog guard prevents a double). + if (!DashboardRebuildService.isRunning() && UpdateStatusCache.pendingFailure(requireContext())) { + showFailureHere(); + } + } + + /** K2GO-557: the in-app update-failure dialog for THIS card, where "Try again" re-runs the gated start + * in place (gates, confirm, low-memory advisory, then start). */ + private void showFailureHere() { + if (!isAdded()) return; + final View root = getView(); + if (root == null) return; + org.appdevforall.k2go.dashboard.presentation.DashUpdateFailureDialog.show( + requireActivity(), R.string.k2go_dash_update_retry, + () -> { if (isAdded()) DashboardRebuild.confirmAndStart(this, root, updateAvailable); }); } @Override diff --git a/controller/app/src/main/java/org/appdevforall/k2go/redesign/DashboardRebuild.java b/controller/app/src/main/java/org/appdevforall/k2go/redesign/DashboardRebuild.java index e0c469db4..f584fc27a 100644 --- a/controller/app/src/main/java/org/appdevforall/k2go/redesign/DashboardRebuild.java +++ b/controller/app/src/main/java/org/appdevforall/k2go/redesign/DashboardRebuild.java @@ -66,8 +66,12 @@ public static void confirmAndStart(@NonNull Fragment host, @NonNull View anchor, : R.string.k2go_dash_rebuild_confirm_title) .setMessage(R.string.k2go_dash_rebuild_confirm_msg) .setCheckbox(R.string.k2go_dash_update_site, true) + // K2GO-557: after the user confirms, a low-memory device gets one more in-app advisory + // ("Not now / Start anyway") before the update actually starts. Fine memory proceeds at once. .setPositive(updateAvailable ? R.string.k2go_dash_update : R.string.k2go_dash_rebuild, - BrandDialog.Role.PRIMARY, checked -> start(host, anchor, checked)) + BrandDialog.Role.PRIMARY, + checked -> org.appdevforall.k2go.dashboard.presentation.LowMemoryGate.guard( + host.requireActivity(), () -> start(host, anchor, checked))) .setNegative(android.R.string.cancel, null) .show(); } diff --git a/controller/app/src/main/java/org/appdevforall/k2go/redesign/DashboardRebuildService.java b/controller/app/src/main/java/org/appdevforall/k2go/redesign/DashboardRebuildService.java index 3bc72936d..f1dd82f73 100644 --- a/controller/app/src/main/java/org/appdevforall/k2go/redesign/DashboardRebuildService.java +++ b/controller/app/src/main/java/org/appdevforall/k2go/redesign/DashboardRebuildService.java @@ -143,6 +143,8 @@ public int onStartCommand(Intent intent, int flags, int startId) { if (started) return START_NOT_STICKY; started = true; RUNNING = true; + // K2GO-557: a fresh run (start or re-own) clears any stale unacked failure from a previous attempt. + UpdateStatusCache.setPendingFailure(this, false); startedAtMs = android.os.SystemClock.elapsedRealtime(); // ADFA-5343 (Phase 3B): arm the stall backstop broadcastState(STATE_RUNNING); if (ACTION_ATTACH.equals(action)) { @@ -266,15 +268,28 @@ private void schedule() { private void finish(String state, @StringRes int msgRes) { poller.removeCallbacksAndMessages(null); RUNNING = false; - // Keep the final notification on screen after we drop the foreground state. - stopForeground(Service.STOP_FOREGROUND_DETACH); - NotificationManager m = getSystemService(NotificationManager.class); - if (m != null) m.notify(NOTIFICATION_ID, buildFinal(msgRes)); + if (STATE_ERROR.equals(state)) { + // K2GO-557: the failure is surfaced IN-APP (DashUpdateFailureDialog), not as a system + // notification. Set the single pending-failure flag BEFORE broadcasting, so a visible card + // reads it fresh and a failure with no screen watching re-shows on the next foreground. Drop + // the ongoing progress notification: no silent "success-looking" final for an error. + UpdateStatusCache.setPendingFailure(this, true); + stopForeground(Service.STOP_FOREGROUND_REMOVE); + } else { + if (STATE_DONE.equals(state)) UpdateStatusCache.setPendingFailure(this, false); // success clears it + // Success: keep the notification on screen and replace it with the quiet final one. + stopForeground(Service.STOP_FOREGROUND_DETACH); + NotificationManager m = getSystemService(NotificationManager.class); + if (m != null) m.notify(NOTIFICATION_ID, buildFinal(msgRes)); + } broadcastState(state); stopSelf(); } - @Override public void onDestroy() { RUNNING = false; super.onDestroy(); } // safety if torn down early + @Override public void onDestroy() { + RUNNING = false; // safety if torn down early + super.onDestroy(); + } private void broadcastState(String state) { sendBroadcast(new Intent(ACTION_STATE).setPackage(getPackageName()).putExtra(EXTRA_STATE, state)); @@ -282,10 +297,10 @@ private void broadcastState(String state) { private void createNotificationChannel() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - NotificationChannel ch = new NotificationChannel( - CHANNEL_ID, getString(R.string.k2go_dash_update_channel_name), NotificationManager.IMPORTANCE_LOW); NotificationManager m = getSystemService(NotificationManager.class); - if (m != null) m.createNotificationChannel(ch); + if (m == null) return; + m.createNotificationChannel(new NotificationChannel( + CHANNEL_ID, getString(R.string.k2go_dash_update_channel_name), NotificationManager.IMPORTANCE_LOW)); } } @@ -330,7 +345,8 @@ private String progressText() { return EtaText.percentAndEta(this, lastPercent, lastEtaSeconds); } - /** Final result notification (done/error) — dismissible, auto-cancels on tap. */ + /** Final SUCCESS notification: dismissible, auto-cancels on tap, quiet (LOW channel). A failure is + * surfaced in-app (K2GO-557, DashUpdateFailureDialog), so this final is only ever a success. */ private Notification buildFinal(@StringRes int msgRes) { return new NotificationCompat.Builder(this, CHANNEL_ID) .setContentTitle(getString(R.string.k2go_dash_live_title)) @@ -342,4 +358,5 @@ private Notification buildFinal(@StringRes int msgRes) { .setPriority(NotificationCompat.PRIORITY_LOW) .build(); } + } diff --git a/controller/app/src/main/java/org/appdevforall/k2go/redesign/UpdateStatusCache.java b/controller/app/src/main/java/org/appdevforall/k2go/redesign/UpdateStatusCache.java index 8ef1ee1c3..ca7bdcfcb 100644 --- a/controller/app/src/main/java/org/appdevforall/k2go/redesign/UpdateStatusCache.java +++ b/controller/app/src/main/java/org/appdevforall/k2go/redesign/UpdateStatusCache.java @@ -24,6 +24,11 @@ private UpdateStatusCache() {} // installed dash-node version changes (a rebuild), its served JS/HTML changed under the WebView, // so we clear the cache once and record the new version here. private static final String KEY_CACHE_VER = "cache_cleared_version"; + // K2GO-557: a live update failed and the user has not acknowledged it yet. The single source of + // truth for "there is an unacked update failure", written by DashboardRebuildService (the one owner + // that always runs to completion) and cleared on success, on a new start, or when the in-app failure + // dialog is dismissed. The failure is surfaced IN-APP, not as a system notification. + private static final String KEY_PENDING_FAILURE = "pending_failure"; private static SharedPreferences prefs(Context ctx) { return ctx.getApplicationContext().getSharedPreferences(PREFS, Context.MODE_PRIVATE); @@ -56,4 +61,14 @@ public static String cacheClearedVersion(Context ctx) { public static void setCacheClearedVersion(Context ctx, String version) { prefs(ctx).edit().putString(KEY_CACHE_VER, version == null ? "" : version).apply(); } + + /** K2GO-557: mark (or clear) an unacknowledged live-update failure. */ + public static void setPendingFailure(Context ctx, boolean pending) { + prefs(ctx).edit().putBoolean(KEY_PENDING_FAILURE, pending).apply(); + } + + /** K2GO-557: true when a live update failed and the user has not seen the in-app notice yet. */ + public static boolean pendingFailure(Context ctx) { + return prefs(ctx).getBoolean(KEY_PENDING_FAILURE, false); + } } diff --git a/controller/app/src/main/java/org/appdevforall/k2go/ui/ForegroundActivityHolder.java b/controller/app/src/main/java/org/appdevforall/k2go/ui/ForegroundActivityHolder.java new file mode 100644 index 000000000..d8935dc84 --- /dev/null +++ b/controller/app/src/main/java/org/appdevforall/k2go/ui/ForegroundActivityHolder.java @@ -0,0 +1,64 @@ +/* + * ============================================================================ + * Name : ForegroundActivityHolder.java + * Author : AppDevForAll + * Copyright : Copyright (c) 2026 AppDevForAll + * Description : K2GO-557. One app-scoped holder of the current (resumed) Activity, registered once from + * IIABApplication. It lets app-wide work reach the foreground screen without a per-screen + * base class. {@link #current()} is a reusable foundation (future: password prompts). On + * each resume it also re-shows a pending dash-node update failure + * (DashUpdateFailureDialog.maybeShow), so a failure that happened while no screen was + * watching is not lost. The reference is weak and cleared on pause, so it never pins an + * Activity. + * ============================================================================ + */ +package org.appdevforall.k2go.ui; + +import android.app.Activity; +import android.app.Application; +import android.os.Bundle; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import org.appdevforall.k2go.dashboard.presentation.DashUpdateFailureDialog; + +import java.lang.ref.WeakReference; + +public final class ForegroundActivityHolder implements Application.ActivityLifecycleCallbacks { + + /** + * Marker for an Activity that must NOT host app-wide dialogs: transient or non-Material-themed + * screens (the splash, translucent confirms). The holder skips them, so a re-show never inflates a + * Material dialog on a theme that lacks it (it crashes) or on a window about to finish. Same opt-out + * shape as {@code EdgeToEdge.SelfManaged}. + */ + public interface DialogExempt {} + + private static WeakReference current; + + /** The current resumed Activity (never a {@link DialogExempt} one), or null when backgrounded. */ + @Nullable + public static Activity current() { + return current == null ? null : current.get(); + } + + @Override + public void onActivityResumed(@NonNull Activity a) { + if (a instanceof DialogExempt) return; // splash / translucent: not a dialog host + current = new WeakReference<>(a); + // K2GO-557: re-surface a pending update failure on the screen the user just returned to. + DashUpdateFailureDialog.maybeShow(a); + } + + @Override + public void onActivityPaused(@NonNull Activity a) { + if (current() == a) current = null; + } + + @Override public void onActivityCreated(@NonNull Activity a, @Nullable Bundle savedInstanceState) {} + @Override public void onActivityStarted(@NonNull Activity a) {} + @Override public void onActivityStopped(@NonNull Activity a) {} + @Override public void onActivitySaveInstanceState(@NonNull Activity a, @NonNull Bundle outState) {} + @Override public void onActivityDestroyed(@NonNull Activity a) {} +} diff --git a/controller/app/src/main/res/values/strings.xml b/controller/app/src/main/res/values/strings.xml index f085a8414..c5b1a797d 100644 --- a/controller/app/src/main/res/values/strings.xml +++ b/controller/app/src/main/res/values/strings.xml @@ -1740,4 +1740,13 @@ Setting things up... Making it yours... Almost there... + + Device is low on memory + Your device is low on memory. The update may fail. Close other apps first, or start anyway. + Not now + Start anyway + Dashboard update failed + Close other apps and try again. If it keeps failing, contact us. + Try again + Open dashboard diff --git a/controller/app/src/test/java/org/appdevforall/k2go/dashboard/domain/LowMemoryAdviceTest.java b/controller/app/src/test/java/org/appdevforall/k2go/dashboard/domain/LowMemoryAdviceTest.java new file mode 100644 index 000000000..743527b3f --- /dev/null +++ b/controller/app/src/test/java/org/appdevforall/k2go/dashboard/domain/LowMemoryAdviceTest.java @@ -0,0 +1,34 @@ +package org.appdevforall.k2go.dashboard.domain; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import org.junit.Test; + +/** Pure-JVM tests for the low-memory advisory rule (K2GO-557). */ +public class LowMemoryAdviceTest { + + private static final long MB = 1024L * 1024L; + + @Test public void comfortableHeadroom_noAdvice() { + // About 700 MB free and not low: clear headroom, so leave the user alone. + assertFalse(LowMemoryAdvice.shouldAdviseCloseApps(new DeviceMemory(700 * MB, 1400 * MB, false))); + } + + @Test public void exactlyAtNeed_advises() { + assertTrue(LowMemoryAdvice.shouldAdviseCloseApps( + new DeviceMemory(LowMemoryAdvice.UPDATE_WORKING_SET_BYTES, 1400 * MB, false))); + } + + @Test public void belowNeed_advises() { + assertTrue(LowMemoryAdvice.shouldAdviseCloseApps(new DeviceMemory(200 * MB, 1400 * MB, false))); + } + + @Test public void systemLowMemory_advisesEvenWithHeadroom() { + assertTrue(LowMemoryAdvice.shouldAdviseCloseApps(new DeviceMemory(800 * MB, 1400 * MB, true))); + } + + @Test public void nullSnapshot_noAdvice() { + assertFalse(LowMemoryAdvice.shouldAdviseCloseApps(null)); + } +} From 61f37c6db37feb4b499a22dceb7f35662093d482 Mon Sep 17 00:00:00 2001 From: Luis Guzman Date: Sun, 8 Nov 2026 04:07:03 -0600 Subject: [PATCH 2/2] K2GO-557 chore(l10n): translate in-app update alert strings (33 locales) Migrate the 8 K2GO-557 UI strings from the untranslated tracker into the 33 locale strings.xml files. Machine-translated, marked for human review. --- controller/app/src/main/res/values-ar/strings.xml | 9 +++++++++ controller/app/src/main/res/values-az/strings.xml | 9 +++++++++ controller/app/src/main/res/values-bg/strings.xml | 9 +++++++++ controller/app/src/main/res/values-bn/strings.xml | 9 +++++++++ controller/app/src/main/res/values-cs/strings.xml | 9 +++++++++ controller/app/src/main/res/values-de/strings.xml | 9 +++++++++ controller/app/src/main/res/values-el/strings.xml | 9 +++++++++ controller/app/src/main/res/values-es/strings.xml | 9 +++++++++ controller/app/src/main/res/values-fa/strings.xml | 9 +++++++++ controller/app/src/main/res/values-fr/strings.xml | 9 +++++++++ controller/app/src/main/res/values-gu/strings.xml | 9 +++++++++ controller/app/src/main/res/values-hi/strings.xml | 9 +++++++++ controller/app/src/main/res/values-hu/strings.xml | 9 +++++++++ controller/app/src/main/res/values-in/strings.xml | 9 +++++++++ controller/app/src/main/res/values-it/strings.xml | 9 +++++++++ controller/app/src/main/res/values-ja/strings.xml | 9 +++++++++ controller/app/src/main/res/values-ko/strings.xml | 9 +++++++++ controller/app/src/main/res/values-lt/strings.xml | 9 +++++++++ controller/app/src/main/res/values-nl/strings.xml | 9 +++++++++ controller/app/src/main/res/values-no/strings.xml | 9 +++++++++ controller/app/src/main/res/values-pl/strings.xml | 9 +++++++++ controller/app/src/main/res/values-pt/strings.xml | 9 +++++++++ controller/app/src/main/res/values-ro/strings.xml | 9 +++++++++ controller/app/src/main/res/values-ru-rRU/strings.xml | 9 +++++++++ controller/app/src/main/res/values-sk/strings.xml | 9 +++++++++ controller/app/src/main/res/values-sr/strings.xml | 9 +++++++++ controller/app/src/main/res/values-sw/strings.xml | 9 +++++++++ controller/app/src/main/res/values-ta/strings.xml | 9 +++++++++ controller/app/src/main/res/values-tr/strings.xml | 9 +++++++++ controller/app/src/main/res/values-uk/strings.xml | 9 +++++++++ controller/app/src/main/res/values-vi/strings.xml | 9 +++++++++ controller/app/src/main/res/values-yo/strings.xml | 9 +++++++++ controller/app/src/main/res/values-zh-rCN/strings.xml | 9 +++++++++ 33 files changed, 297 insertions(+) diff --git a/controller/app/src/main/res/values-ar/strings.xml b/controller/app/src/main/res/values-ar/strings.xml index 31e61a5ff..a84f3d782 100644 --- a/controller/app/src/main/res/values-ar/strings.xml +++ b/controller/app/src/main/res/values-ar/strings.xml @@ -1544,4 +1544,13 @@ جارٍ إعداد كل شيء... نجعله خاصًا بك... أوشكنا على الانتهاء... + + الذاكرة منخفضة في الجهاز + ذاكرة جهازك منخفضة. قد يفشل التحديث. أغلق التطبيقات الأخرى أولاً، أو ابدأ على أي حال. + ليس الآن + ابدأ على أي حال + فشل تحديث لوحة التحكم + أغلق التطبيقات الأخرى وحاول مرة أخرى. إذا استمر الفشل، فتواصل معنا. + إعادة المحاولة + فتح لوحة التحكم diff --git a/controller/app/src/main/res/values-az/strings.xml b/controller/app/src/main/res/values-az/strings.xml index dd4a9d81d..a2bc87da6 100644 --- a/controller/app/src/main/res/values-az/strings.xml +++ b/controller/app/src/main/res/values-az/strings.xml @@ -1564,4 +1564,13 @@ Hər şey qurulur... Sizə uyğunlaşdırılır... Az qaldı... + + Cihazın yaddaşı azdır + Cihazınızın yaddaşı azdır. Yeniləmə uğursuz ola bilər. Əvvəlcə digər tətbiqləri bağlayın və ya yenə də başladın. + İndi yox + Yenə də başlat + Panelin yenilənməsi uğursuz oldu + Digər tətbiqləri bağlayıb yenidən cəhd edin. Davamlı uğursuz olarsa, bizimlə əlaqə saxlayın. + Yenidən cəhd et + Paneli aç diff --git a/controller/app/src/main/res/values-bg/strings.xml b/controller/app/src/main/res/values-bg/strings.xml index b60f016e8..55fe33e64 100644 --- a/controller/app/src/main/res/values-bg/strings.xml +++ b/controller/app/src/main/res/values-bg/strings.xml @@ -1551,4 +1551,13 @@ Подготвяме всичко... Правим я ваша... Почти готово... + + Устройството е с малко памет + Устройството ви е с малко памет. Актуализацията може да е неуспешна. Първо затворете други приложения или стартирайте въпреки това. + Не сега + Стартиране въпреки това + Актуализацията на таблото е неуспешна + Затворете други приложения и опитайте отново. Ако продължава да е неуспешна, свържете се с нас. + Опитайте отново + Отваряне на таблото diff --git a/controller/app/src/main/res/values-bn/strings.xml b/controller/app/src/main/res/values-bn/strings.xml index 5c288ba21..5cad70641 100644 --- a/controller/app/src/main/res/values-bn/strings.xml +++ b/controller/app/src/main/res/values-bn/strings.xml @@ -1557,4 +1557,13 @@ সবকিছু প্রস্তুত হচ্ছে... আপনার মতো করে তোলা হচ্ছে... প্রায় শেষ... + + ডিভাইসে মেমরি কম + আপনার ডিভাইসে মেমরি কম। আপডেট ব্যর্থ হতে পারে। প্রথমে অন্য অ্যাপ বন্ধ করুন, বা তবুও শুরু করুন। + এখন নয় + তবুও শুরু করুন + ড্যাশবোর্ড আপডেট ব্যর্থ হয়েছে + অন্য অ্যাপ বন্ধ করে আবার চেষ্টা করুন। যদি বারবার ব্যর্থ হয়, আমাদের সাথে যোগাযোগ করুন। + আবার চেষ্টা করুন + ড্যাশবোর্ড খুলুন diff --git a/controller/app/src/main/res/values-cs/strings.xml b/controller/app/src/main/res/values-cs/strings.xml index 5246692be..7757c2b5a 100644 --- a/controller/app/src/main/res/values-cs/strings.xml +++ b/controller/app/src/main/res/values-cs/strings.xml @@ -1551,4 +1551,13 @@ Vše se nastavuje... Aby byl jen váš... Skoro hotovo... + + Zařízení má málo paměti + Vaše zařízení má málo paměti. Aktualizace může selhat. Nejprve zavřete ostatní aplikace, nebo ji přesto spusťte. + Teď ne + Přesto spustit + Aktualizace nástěnky selhala + Zavřete ostatní aplikace a zkuste to znovu. Pokud selhává dál, kontaktujte nás. + Zkusit znovu + Otevřít nástěnku diff --git a/controller/app/src/main/res/values-de/strings.xml b/controller/app/src/main/res/values-de/strings.xml index 9e107756d..8f06b4fee 100644 --- a/controller/app/src/main/res/values-de/strings.xml +++ b/controller/app/src/main/res/values-de/strings.xml @@ -1544,4 +1544,13 @@ Alles wird eingerichtet... Ganz nach deinem Geschmack... Fast fertig... + + Gerät hat wenig Arbeitsspeicher + Ihr Gerät hat wenig Arbeitsspeicher. Die Aktualisierung kann fehlschlagen. Schließen Sie zuerst andere Apps oder fahren Sie trotzdem fort. + Jetzt nicht + Trotzdem starten + Dashboard-Aktualisierung fehlgeschlagen + Schließen Sie andere Apps und versuchen Sie es erneut. Wenn es weiterhin fehlschlägt, kontaktieren Sie uns. + Erneut versuchen + Dashboard öffnen diff --git a/controller/app/src/main/res/values-el/strings.xml b/controller/app/src/main/res/values-el/strings.xml index 00620d63d..2954f3383 100644 --- a/controller/app/src/main/res/values-el/strings.xml +++ b/controller/app/src/main/res/values-el/strings.xml @@ -1551,4 +1551,13 @@ Όλα ρυθμίζονται... Το κάνουμε δικό σας... Σχεδόν έτοιμο... + + Η συσκευή έχει λίγη μνήμη + Η συσκευή σας έχει λίγη μνήμη. Η ενημέρωση μπορεί να αποτύχει. Κλείστε πρώτα άλλες εφαρμογές ή ξεκινήστε έτσι κι αλλιώς. + Όχι τώρα + Έναρξη ούτως ή άλλως + Η ενημέρωση του πίνακα απέτυχε + Κλείστε άλλες εφαρμογές και δοκιμάστε ξανά. Αν συνεχίζει να αποτυγχάνει, επικοινωνήστε μαζί μας. + Δοκιμάστε ξανά + Άνοιγμα πίνακα diff --git a/controller/app/src/main/res/values-es/strings.xml b/controller/app/src/main/res/values-es/strings.xml index 27bfe90ae..84859cbdd 100644 --- a/controller/app/src/main/res/values-es/strings.xml +++ b/controller/app/src/main/res/values-es/strings.xml @@ -1620,4 +1620,13 @@ Configurando todo... Haciéndolo tuyo... Ya casi... + + El dispositivo tiene poca memoria + Tu dispositivo tiene poca memoria. La actualización podría fallar. Cierra otras apps primero, o inicia de todos modos. + Ahora no + Iniciar de todos modos + La actualización del panel falló + Cierra otras apps e inténtalo de nuevo. Si sigue fallando, contáctanos. + Intentar de nuevo + Abrir panel diff --git a/controller/app/src/main/res/values-fa/strings.xml b/controller/app/src/main/res/values-fa/strings.xml index 913947b41..59f4daded 100644 --- a/controller/app/src/main/res/values-fa/strings.xml +++ b/controller/app/src/main/res/values-fa/strings.xml @@ -1544,4 +1544,13 @@ در حال آماده‌سازی همه‌چیز... مخصوص شما می‌شود... تقریباً تمام است... + + حافظهٔ دستگاه کم است + حافظهٔ دستگاه شما کم است. ممکن است به‌روزرسانی ناموفق باشد. ابتدا برنامه‌های دیگر را ببندید یا به‌هرحال شروع کنید. + اکنون نه + به‌هرحال شروع کن + به‌روزرسانی داشبورد ناموفق بود + برنامه‌های دیگر را ببندید و دوباره تلاش کنید. اگر همچنان ناموفق بود، با ما تماس بگیرید. + تلاش دوباره + باز کردن داشبورد diff --git a/controller/app/src/main/res/values-fr/strings.xml b/controller/app/src/main/res/values-fr/strings.xml index 307b838dd..811b3a737 100644 --- a/controller/app/src/main/res/values-fr/strings.xml +++ b/controller/app/src/main/res/values-fr/strings.xml @@ -1631,4 +1631,13 @@ Mise en place... À votre image... Presque fini... + + L\'appareil manque de mémoire + Votre appareil manque de mémoire. La mise à jour peut échouer. Fermez d\'abord les autres applis, ou lancez quand même. + Pas maintenant + Lancer quand même + Échec de la mise à jour du tableau de bord + Fermez les autres applis et réessayez. Si cela échoue encore, contactez-nous. + Réessayer + Ouvrir le tableau de bord diff --git a/controller/app/src/main/res/values-gu/strings.xml b/controller/app/src/main/res/values-gu/strings.xml index 6f5478f4b..86cd8f204 100644 --- a/controller/app/src/main/res/values-gu/strings.xml +++ b/controller/app/src/main/res/values-gu/strings.xml @@ -1557,4 +1557,13 @@ બધું તૈયાર કરી રહ્યા છીએ... તેને તમારું બનાવી રહ્યા છીએ... લગભગ થઈ ગયું... + + ઉપકરણમાં મેમરી ઓછી છે + તમારા ઉપકરણમાં મેમરી ઓછી છે. અપડેટ નિષ્ફળ થઈ શકે છે. પહેલાં બીજી ઍપ બંધ કરો, અથવા તો પણ શરૂ કરો. + હમણાં નહીં + તો પણ શરૂ કરો + ડૅશબોર્ડ અપડેટ નિષ્ફળ થયું + બીજી ઍપ બંધ કરો અને ફરી પ્રયાસ કરો. જો વારંવાર નિષ્ફળ થાય, તો અમારો સંપર્ક કરો. + ફરી પ્રયાસ કરો + ડૅશબોર્ડ ખોલો diff --git a/controller/app/src/main/res/values-hi/strings.xml b/controller/app/src/main/res/values-hi/strings.xml index 65a4cc00a..6530f6053 100644 --- a/controller/app/src/main/res/values-hi/strings.xml +++ b/controller/app/src/main/res/values-hi/strings.xml @@ -1621,4 +1621,13 @@ सब कुछ सेट हो रहा है... इसे आपका बनाया जा रहा है... बस थोड़ा और... + + डिवाइस में मेमोरी कम है + आपके डिवाइस में मेमोरी कम है. अपडेट विफल हो सकता है. पहले दूसरे ऐप बंद करें, या फिर भी शुरू करें. + अभी नहीं + फिर भी शुरू करें + डैशबोर्ड अपडेट विफल रहा + दूसरे ऐप बंद करें और फिर से कोशिश करें. अगर यह बार-बार विफल हो, तो हमसे संपर्क करें. + फिर से कोशिश करें + डैशबोर्ड खोलें diff --git a/controller/app/src/main/res/values-hu/strings.xml b/controller/app/src/main/res/values-hu/strings.xml index 14252f4ca..ee9deb060 100644 --- a/controller/app/src/main/res/values-hu/strings.xml +++ b/controller/app/src/main/res/values-hu/strings.xml @@ -1544,4 +1544,13 @@ Minden beállítása... A tiéd lesz... Mindjárt kész... + + Az eszköz memóriája kevés + Az eszközödön kevés a memória. A frissítés meghiúsulhat. Előbb zárj be más alkalmazásokat, vagy indítsd el mégis. + Most nem + Indítás mégis + Az irányítópult frissítése sikertelen + Zárj be más alkalmazásokat, és próbáld újra. Ha továbbra is sikertelen, lépj kapcsolatba velünk. + Újra + Irányítópult megnyitása diff --git a/controller/app/src/main/res/values-in/strings.xml b/controller/app/src/main/res/values-in/strings.xml index 466d3582f..5743e31c3 100644 --- a/controller/app/src/main/res/values-in/strings.xml +++ b/controller/app/src/main/res/values-in/strings.xml @@ -1551,4 +1551,13 @@ Menyiapkan semuanya... Menjadikannya milik Anda... Hampir selesai... + + Memori perangkat rendah + Memori perangkat Anda rendah. Pembaruan mungkin gagal. Tutup aplikasi lain dulu, atau tetap mulai. + Nanti saja + Tetap mulai + Pembaruan dasbor gagal + Tutup aplikasi lain dan coba lagi. Jika terus gagal, hubungi kami. + Coba lagi + Buka dasbor diff --git a/controller/app/src/main/res/values-it/strings.xml b/controller/app/src/main/res/values-it/strings.xml index bcc1d9854..961ce1847 100644 --- a/controller/app/src/main/res/values-it/strings.xml +++ b/controller/app/src/main/res/values-it/strings.xml @@ -1544,4 +1544,13 @@ Configurazione in corso... Lo rendiamo tuo... Quasi pronto... + + Il dispositivo ha poca memoria + Il tuo dispositivo ha poca memoria. L\'aggiornamento potrebbe non riuscire. Chiudi prima le altre app, oppure avvia comunque. + Non ora + Avvia comunque + Aggiornamento della dashboard non riuscito + Chiudi le altre app e riprova. Se continua a non funzionare, contattaci. + Riprova + Apri la dashboard diff --git a/controller/app/src/main/res/values-ja/strings.xml b/controller/app/src/main/res/values-ja/strings.xml index b57327c1e..e2b626164 100644 --- a/controller/app/src/main/res/values-ja/strings.xml +++ b/controller/app/src/main/res/values-ja/strings.xml @@ -1545,4 +1545,13 @@ すべてを設定中... あなた仕様に... もうすぐです... + + デバイスのメモリが不足しています + デバイスのメモリが不足しています。更新に失敗する可能性があります。先に他のアプリを閉じるか、このまま開始してください。 + 後で + このまま開始 + ダッシュボードの更新に失敗しました + 他のアプリを閉じてもう一度お試しください。繰り返し失敗する場合はお問い合わせください。 + 再試行 + ダッシュボードを開く diff --git a/controller/app/src/main/res/values-ko/strings.xml b/controller/app/src/main/res/values-ko/strings.xml index e09917530..f730dfc1d 100644 --- a/controller/app/src/main/res/values-ko/strings.xml +++ b/controller/app/src/main/res/values-ko/strings.xml @@ -1545,4 +1545,13 @@ 모든 것을 설정하는 중... 나만의 것으로... 거의 다 됐어요... + + 기기 메모리가 부족합니다 + 기기 메모리가 부족합니다. 업데이트가 실패할 수 있습니다. 먼저 다른 앱을 닫거나 그래도 시작하세요. + 나중에 + 그래도 시작 + 대시보드 업데이트 실패 + 다른 앱을 닫고 다시 시도하세요. 계속 실패하면 문의해 주세요. + 다시 시도 + 대시보드 열기 diff --git a/controller/app/src/main/res/values-lt/strings.xml b/controller/app/src/main/res/values-lt/strings.xml index 0ab8e60d9..d3eba0d19 100644 --- a/controller/app/src/main/res/values-lt/strings.xml +++ b/controller/app/src/main/res/values-lt/strings.xml @@ -1561,4 +1561,13 @@ Viskas nustatoma... Pritaikoma jums... Beveik baigta... + + Įrenginyje mažai atminties + Jūsų įrenginyje mažai atminties. Naujinimas gali nepavykti. Pirmiausia uždarykite kitas programas arba vis tiek paleiskite. + Ne dabar + Vis tiek paleisti + Nepavyko atnaujinti skydelio + Uždarykite kitas programas ir bandykite dar kartą. Jei vis tiek nepavyksta, susisiekite su mumis. + Bandyti dar kartą + Atidaryti skydelį diff --git a/controller/app/src/main/res/values-nl/strings.xml b/controller/app/src/main/res/values-nl/strings.xml index 6bf88a180..1f4f93487 100644 --- a/controller/app/src/main/res/values-nl/strings.xml +++ b/controller/app/src/main/res/values-nl/strings.xml @@ -1544,4 +1544,13 @@ Alles instellen... Helemaal van jou maken... Bijna klaar... + + Apparaat heeft weinig geheugen + Je apparaat heeft weinig geheugen. De update kan mislukken. Sluit eerst andere apps, of start toch. + Niet nu + Toch starten + Dashboard-update mislukt + Sluit andere apps en probeer het opnieuw. Als het blijft mislukken, neem contact met ons op. + Opnieuw proberen + Dashboard openen diff --git a/controller/app/src/main/res/values-no/strings.xml b/controller/app/src/main/res/values-no/strings.xml index 76b19a9d4..dae79a9a4 100644 --- a/controller/app/src/main/res/values-no/strings.xml +++ b/controller/app/src/main/res/values-no/strings.xml @@ -1554,4 +1554,13 @@ Setter opp alt... Gjør det til ditt... Nesten ferdig... + + Enheten har lite minne + Enheten din har lite minne. Oppdateringen kan mislykkes. Lukk andre apper først, eller start likevel. + Ikke nå + Start likevel + Oppdatering av dashbordet mislyktes + Lukk andre apper og prøv igjen. Hvis det fortsatt mislykkes, kontakt oss. + Prøv igjen + Åpne dashbord diff --git a/controller/app/src/main/res/values-pl/strings.xml b/controller/app/src/main/res/values-pl/strings.xml index 7581bd594..fb44268aa 100644 --- a/controller/app/src/main/res/values-pl/strings.xml +++ b/controller/app/src/main/res/values-pl/strings.xml @@ -1554,4 +1554,13 @@ Konfigurowanie wszystkiego... Dopasowywanie do Ciebie... Prawie gotowe... + + Urządzenie ma mało pamięci + Twoje urządzenie ma mało pamięci. Aktualizacja może się nie powieść. Najpierw zamknij inne aplikacje lub uruchom mimo to. + Nie teraz + Uruchom mimo to + Aktualizacja pulpitu nie powiodła się + Zamknij inne aplikacje i spróbuj ponownie. Jeśli problem będzie się powtarzać, skontaktuj się z nami. + Spróbuj ponownie + Otwórz pulpit diff --git a/controller/app/src/main/res/values-pt/strings.xml b/controller/app/src/main/res/values-pt/strings.xml index 4cd9cd62b..9e1994daa 100644 --- a/controller/app/src/main/res/values-pt/strings.xml +++ b/controller/app/src/main/res/values-pt/strings.xml @@ -1623,4 +1623,13 @@ A configurar tudo... A torná-lo seu... Quase pronto... + + O dispositivo está com pouca memória + Seu dispositivo está com pouca memória. A atualização pode falhar. Feche outros apps primeiro ou inicie mesmo assim. + Agora não + Iniciar mesmo assim + Falha na atualização do painel + Feche outros apps e tente novamente. Se continuar falhando, fale conosco. + Tentar novamente + Abrir painel diff --git a/controller/app/src/main/res/values-ro/strings.xml b/controller/app/src/main/res/values-ro/strings.xml index 727c86620..b7ba0f4ca 100644 --- a/controller/app/src/main/res/values-ro/strings.xml +++ b/controller/app/src/main/res/values-ro/strings.xml @@ -1544,4 +1544,13 @@ Configurăm totul... Îl facem al tău... Aproape gata... + + Dispozitivul are memorie insuficientă + Dispozitivul tău are memorie insuficientă. Actualizarea poate eșua. Închide mai întâi alte aplicații sau pornește oricum. + Nu acum + Pornește oricum + Actualizarea panoului a eșuat + Închide alte aplicații și încearcă din nou. Dacă tot eșuează, contactează-ne. + Încearcă din nou + Deschide panoul 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 4ef60fc81..b9f896632 100644 --- a/controller/app/src/main/res/values-ru-rRU/strings.xml +++ b/controller/app/src/main/res/values-ru-rRU/strings.xml @@ -1620,4 +1620,13 @@ Всё настраиваем... Делаем её вашей... Почти готово... + + На устройстве мало памяти + На вашем устройстве мало памяти. Обновление может не выполниться. Сначала закройте другие приложения или всё равно запустите. + Не сейчас + Всё равно запустить + Не удалось обновить панель + Закройте другие приложения и повторите попытку. Если ошибка повторяется, свяжитесь с нами. + Повторить + Открыть панель diff --git a/controller/app/src/main/res/values-sk/strings.xml b/controller/app/src/main/res/values-sk/strings.xml index 400e69e7a..5f779b385 100644 --- a/controller/app/src/main/res/values-sk/strings.xml +++ b/controller/app/src/main/res/values-sk/strings.xml @@ -1551,4 +1551,13 @@ Všetko sa nastavuje... Aby bol len váš... Takmer hotovo... + + Zariadenie má málo pamäte + Vaše zariadenie má málo pamäte. Aktualizácia môže zlyhať. Najprv zatvorte ostatné aplikácie, alebo ju napriek tomu spustite. + Teraz nie + Napriek tomu spustiť + Aktualizácia panela zlyhala + Zatvorte ostatné aplikácie a skúste to znova. Ak zlyháva naďalej, kontaktujte nás. + Skúsiť znova + Otvoriť panel diff --git a/controller/app/src/main/res/values-sr/strings.xml b/controller/app/src/main/res/values-sr/strings.xml index 9bc10cdb1..6e19355fe 100644 --- a/controller/app/src/main/res/values-sr/strings.xml +++ b/controller/app/src/main/res/values-sr/strings.xml @@ -1557,4 +1557,13 @@ Све се подешава... Прилагођавамо га вама... Скоро готово... + + Уређај има мало меморије + Ваш уређај има мало меморије. Ажурирање можда неће успети. Прво затворите друге апликације или свеједно покрените. + Не сада + Свеједно покрени + Ажурирање контролне табле није успело + Затворите друге апликације и покушајте поново. Ако и даље не успева, контактирајте нас. + Покушај поново + Отвори контролну таблу diff --git a/controller/app/src/main/res/values-sw/strings.xml b/controller/app/src/main/res/values-sw/strings.xml index 7a392a0c2..37995b31a 100644 --- a/controller/app/src/main/res/values-sw/strings.xml +++ b/controller/app/src/main/res/values-sw/strings.xml @@ -1564,4 +1564,13 @@ Tunaandaa kila kitu... Tunaufanya kuwa wako... Karibu tumemaliza... + + Kifaa kina kumbukumbu ndogo + Kifaa chako kina kumbukumbu ndogo. Sasisho linaweza kushindwa. Funga programu zingine kwanza, au anza hata hivyo. + Si sasa + Anza hata hivyo + Kusasisha dashibodi kumeshindwa + Funga programu zingine na ujaribu tena. Ikiendelea kushindwa, wasiliana nasi. + Jaribu tena + Fungua dashibodi diff --git a/controller/app/src/main/res/values-ta/strings.xml b/controller/app/src/main/res/values-ta/strings.xml index 2582c684a..6faf82e4e 100644 --- a/controller/app/src/main/res/values-ta/strings.xml +++ b/controller/app/src/main/res/values-ta/strings.xml @@ -1564,4 +1564,13 @@ அனைத்தையும் அமைக்கிறது... உங்களுடையதாக்குகிறது... கிட்டத்தட்ட முடிந்தது... + + சாதனத்தில் நினைவகம் குறைவு + உங்கள் சாதனத்தில் நினைவகம் குறைவாக உள்ளது. புதுப்பிப்பு தோல்வியடையலாம். முதலில் மற்ற ஆப்ஸை மூடுங்கள் அல்லது எப்படியும் தொடங்குங்கள். + இப்போது வேண்டாம் + எப்படியும் தொடங்கு + டாஷ்போர்டு புதுப்பிப்பு தோல்வியடைந்தது + மற்ற ஆப்ஸை மூடிவிட்டு மீண்டும் முயலுங்கள். தொடர்ந்து தோல்வியடைந்தால், எங்களைத் தொடர்பு கொள்ளுங்கள். + மீண்டும் முயல் + டாஷ்போர்டைத் திற diff --git a/controller/app/src/main/res/values-tr/strings.xml b/controller/app/src/main/res/values-tr/strings.xml index b127dee02..7ccf69ed6 100644 --- a/controller/app/src/main/res/values-tr/strings.xml +++ b/controller/app/src/main/res/values-tr/strings.xml @@ -1544,4 +1544,13 @@ Her şey hazırlanıyor... Size özel hale getiriliyor... Neredeyse bitti... + + Cihazın belleği az + Cihazınızın belleği az. Güncelleme başarısız olabilir. Önce diğer uygulamaları kapatın veya yine de başlatın. + Şimdi değil + Yine de başlat + Pano güncellemesi başarısız oldu + Diğer uygulamaları kapatıp tekrar deneyin. Sorun sürerse bizimle iletişime geçin. + Tekrar dene + Panoyu aç diff --git a/controller/app/src/main/res/values-uk/strings.xml b/controller/app/src/main/res/values-uk/strings.xml index 9f467d6b6..4b93f3cb8 100644 --- a/controller/app/src/main/res/values-uk/strings.xml +++ b/controller/app/src/main/res/values-uk/strings.xml @@ -1544,4 +1544,13 @@ Усе налаштовуємо... Робимо її вашою... Майже готово... + + На пристрої мало пам\'яті + На вашому пристрої мало пам\'яті. Оновлення може не вдатися. Спершу закрийте інші застосунки або все одно запустіть. + Не зараз + Усе одно запустити + Не вдалося оновити панель + Закрийте інші застосунки та повторіть спробу. Якщо помилка повторюється, зв\'яжіться з нами. + Повторити + Відкрити панель diff --git a/controller/app/src/main/res/values-vi/strings.xml b/controller/app/src/main/res/values-vi/strings.xml index 19a5b0b19..b18938e89 100644 --- a/controller/app/src/main/res/values-vi/strings.xml +++ b/controller/app/src/main/res/values-vi/strings.xml @@ -1544,4 +1544,13 @@ Đang thiết lập mọi thứ... Đang biến nó thành của bạn... Sắp xong rồi... + + Thiết bị sắp hết bộ nhớ + Thiết bị của bạn sắp hết bộ nhớ. Bản cập nhật có thể thất bại. Hãy đóng các ứng dụng khác trước, hoặc vẫn bắt đầu. + Để sau + Vẫn bắt đầu + Cập nhật bảng điều khiển thất bại + Đóng các ứng dụng khác và thử lại. Nếu vẫn thất bại, hãy liên hệ với chúng tôi. + Thử lại + Mở bảng điều khiển diff --git a/controller/app/src/main/res/values-yo/strings.xml b/controller/app/src/main/res/values-yo/strings.xml index 933dffa0c..233fdb528 100644 --- a/controller/app/src/main/res/values-yo/strings.xml +++ b/controller/app/src/main/res/values-yo/strings.xml @@ -1564,4 +1564,13 @@ Ń ṣètò ohun gbogbo... Ń sọ ọ́ di tìrẹ... Ó ti fẹ́ parí... + + Ẹrọ ní ìrántí kékeré + Ẹrọ rẹ ní ìrántí kékeré. Ìmúdójúìwọ̀n lè kùnà. Ti àwọn áàpù mìíràn pa lákọ̀ọ́kọ́, tàbí bẹ̀rẹ̀ lọ́nàkọnà. + Kì í ṣe nísinsìnyí + Bẹ̀rẹ̀ lọ́nàkọnà + Ìmúdójúìwọ̀n dasibodu kùnà + Ti àwọn áàpù mìíràn pa kí o sì tún gbìyànjú. Tí ó bá ń kùnà nígbàgbogbo, kàn sí wa. + Tún gbìyànjú + Ṣí dasibodu 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 6b9a12825..9b8f933f2 100644 --- a/controller/app/src/main/res/values-zh-rCN/strings.xml +++ b/controller/app/src/main/res/values-zh-rCN/strings.xml @@ -1545,4 +1545,13 @@ 正在完成设置... 正在打造专属于你的系统... 马上就好... + + 设备内存不足 + 您的设备内存不足。更新可能会失败。请先关闭其他应用,或仍然开始。 + 以后再说 + 仍然开始 + 仪表板更新失败 + 关闭其他应用后重试。如果持续失败,请联系我们。 + 重试 + 打开仪表板