From f193661e68ff91492144a54efab3097b52e2b790 Mon Sep 17 00:00:00 2001 From: Denozordec Date: Mon, 12 Oct 2026 10:25:38 +0700 Subject: [PATCH] android: quick settings tile states and widget sizes as in the Final 2026 mockup Co-Authored-By: Claude Opus 5.5 --- .../strongswan/android/ui/MainActivity.java | 6 ++ .../strongswan/android/ui/VpnTileService.java | 56 +++++++++++++------ .../strongswan/android/ui/widget/ShxWidget.kt | 4 +- .../app/src/main/res/values-ru/strings.xml | 5 ++ .../app/src/main/res/values/strings.xml | 6 ++ 5 files changed, 58 insertions(+), 19 deletions(-) diff --git a/src/frontends/android/app/src/main/java/org/strongswan/android/ui/MainActivity.java b/src/frontends/android/app/src/main/java/org/strongswan/android/ui/MainActivity.java index 9a352004f..6a61e219c 100644 --- a/src/frontends/android/app/src/main/java/org/strongswan/android/ui/MainActivity.java +++ b/src/frontends/android/app/src/main/java/org/strongswan/android/ui/MainActivity.java @@ -23,6 +23,7 @@ import org.strongswan.android.logic.updates.UpdateManager; import org.strongswan.android.ui.compose.ShxAppKt; import org.strongswan.android.ui.compose.ShxNavigation; import org.strongswan.android.ui.compose.ShxTab; +import android.service.quicksettings.TileService; import androidx.appcompat.app.AppCompatActivity; import androidx.core.splashscreen.SplashScreen; @@ -121,6 +122,11 @@ public class MainActivity extends AppCompatActivity intent.removeExtra(EXTRA_ADD_SERVER); ShxNavigation.INSTANCE.requestAddServer(); } + if (intent != null && TileService.ACTION_QS_TILE_PREFERENCES.equals(intent.getAction())) + { + intent.setAction(null); + ShxNavigation.INSTANCE.request(ShxTab.PROFILES); + } if (intent != null && intent.getBooleanExtra(EXTRA_OPEN_SERVERS, false)) { intent.removeExtra(EXTRA_OPEN_SERVERS); diff --git a/src/frontends/android/app/src/main/java/org/strongswan/android/ui/VpnTileService.java b/src/frontends/android/app/src/main/java/org/strongswan/android/ui/VpnTileService.java index b45e21424..45139f0ee 100644 --- a/src/frontends/android/app/src/main/java/org/strongswan/android/ui/VpnTileService.java +++ b/src/frontends/android/app/src/main/java/org/strongswan/android/ui/VpnTileService.java @@ -152,7 +152,12 @@ public class VpnTileService extends TileService implements VpnStateService.VpnSt { /* always get the plain profile without cached password */ profile = mDataSource.getVpnProfile(profile.getUUID()); } - /* reconnect the profile in case of an error */ + /* a problem: the tap opens the app, which explains it (F_QsTile) */ + if (mService.getErrorState() != VpnStateService.ErrorState.NO_ERROR) + { + openApp(new Intent(this, MainActivity.class)); + return; + } if (mService.getErrorState() == VpnStateService.ErrorState.NO_ERROR) { switch (mService.getState()) @@ -212,11 +217,16 @@ public class VpnTileService extends TileService implements VpnStateService.VpnSt return; } } - Intent intent = new Intent(this, MainActivity.class); - intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + /* no servers yet: straight to «Add server» */ + openApp(new Intent(this, MainActivity.class).putExtra(MainActivity.EXTRA_ADD_SERVER, getProfile() == null)); + } + + private void openApp(Intent intent) + { + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) { - startActivityAndCollapse(PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_IMMUTABLE)); + startActivityAndCollapse(PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_UPDATE_CURRENT)); } else { @@ -255,11 +265,28 @@ public class VpnTileService extends TileService implements VpnStateService.VpnSt return; } + /* F_QsTile: always «SHX VPN», the state in the subtitle */ + tile.setLabel(getString(R.string.tile_label)); + String subtitle; if (error != VpnStateService.ErrorState.NO_ERROR) { tile.setState(Tile.STATE_INACTIVE); tile.setIcon(Icon.createWithResource(this, R.drawable.ic_notification_warning)); - tile.setLabel(getString(R.string.tile_connect)); + switch (error) + { + case UNREACHABLE: + case LOOKUP_FAILED: + subtitle = getString(R.string.tile_no_answer); + break; + case AUTH_FAILED: + case PEER_AUTH_FAILED: + case PASSWORD_MISSING: + subtitle = getString(R.string.tile_auth_error); + break; + default: + subtitle = getString(R.string.tile_problem); + break; + } } else { @@ -269,30 +296,25 @@ public class VpnTileService extends TileService implements VpnStateService.VpnSt case DISABLED: tile.setState(Tile.STATE_INACTIVE); tile.setIcon(Icon.createWithResource(this, R.drawable.ic_notification_disconnected)); - tile.setLabel(getString(R.string.tile_connect)); + subtitle = getString(R.string.tile_off); break; case CONNECTING: tile.setState(Tile.STATE_ACTIVE); tile.setIcon(Icon.createWithResource(this, R.drawable.ic_notification_connecting)); - tile.setLabel(getString(R.string.tile_disconnect)); + subtitle = getString(R.string.tile_connecting); break; case CONNECTED: + default: tile.setState(Tile.STATE_ACTIVE); tile.setIcon(Icon.createWithResource(this, R.drawable.ic_notification)); - tile.setLabel(getString(R.string.tile_disconnect)); + /* the server name, unless the screen is locked */ + subtitle = profile != null && !isSecure() ? profile.getName() : getString(R.string.status_protected); break; } } - if (profile != null && !isSecure()) + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) - { /* keep the action label, show the profile as the tile subtitle */ - tile.setSubtitle(profile.getName()); - } - else - { - tile.setLabel(profile.getName()); - } + tile.setSubtitle(subtitle); } tile.updateTile(); } diff --git a/src/frontends/android/app/src/main/java/org/strongswan/android/ui/widget/ShxWidget.kt b/src/frontends/android/app/src/main/java/org/strongswan/android/ui/widget/ShxWidget.kt index f40b1d25c..0ce46b0e5 100644 --- a/src/frontends/android/app/src/main/java/org/strongswan/android/ui/widget/ShxWidget.kt +++ b/src/frontends/android/app/src/main/java/org/strongswan/android/ui/widget/ShxWidget.kt @@ -160,8 +160,8 @@ object ShxWidgetState /* the sizes of F_Widgets: 1×1 status icon, 2×1 status and button, 4×2 detailed */ private val ICON = DpSize(56.dp, 56.dp) -private val SMALL = DpSize(150.dp, 64.dp) -private val LARGE = DpSize(250.dp, 150.dp) +private val SMALL = DpSize(110.dp, 48.dp) +private val LARGE = DpSize(220.dp, 110.dp) /** Home screen widget as on F_Widgets, in three sizes. */ class ShxWidget : GlanceAppWidget() diff --git a/src/frontends/android/app/src/main/res/values-ru/strings.xml b/src/frontends/android/app/src/main/res/values-ru/strings.xml index 0c00d330d..4b09ffd05 100644 --- a/src/frontends/android/app/src/main/res/values-ru/strings.xml +++ b/src/frontends/android/app/src/main/res/values-ru/strings.xml @@ -1021,4 +1021,9 @@ Проблема тап — %1$s Пауза + Выключен + Подключаемся… + Сервер не отвечает + Ошибка входа + Проблема с подключением diff --git a/src/frontends/android/app/src/main/res/values/strings.xml b/src/frontends/android/app/src/main/res/values/strings.xml index ee4d72774..63b3cfa71 100644 --- a/src/frontends/android/app/src/main/res/values/strings.xml +++ b/src/frontends/android/app/src/main/res/values/strings.xml @@ -1006,4 +1006,10 @@ Problem tap — %1$s Pause + Off + Connecting… + Server not responding + Sign-in failed + Connection problem + SHX VPN