android: quick settings tile states and widget sizes as in the Final 2026 mockup

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
DenozordecandClaude Opus 5.5 committed 2026-10-12 10:25:38 +07:00
1 parent 53623ebb4a
commit f193661e68
5 files changed
+58 -19

No files matched your search

@@ -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);
@@ -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();
}
@@ -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()
@@ -1021,4 +1021,9 @@
<string name="widget_problem">Проблема</string>
<string name="widget_tap_to">тап — %1$s</string>
<string name="widget_pause">Пауза</string>
<string name="tile_off">Выключен</string>
<string name="tile_connecting">Подключаемся…</string>
<string name="tile_no_answer">Сервер не отвечает</string>
<string name="tile_auth_error">Ошибка входа</string>
<string name="tile_problem">Проблема с подключением</string>
</resources>
@@ -1006,4 +1006,10 @@
<string name="widget_problem">Problem</string>
<string name="widget_tap_to">tap — %1$s</string>
<string name="widget_pause">Pause</string>
<string name="tile_off">Off</string>
<string name="tile_connecting">Connecting…</string>
<string name="tile_no_answer">Server not responding</string>
<string name="tile_auth_error">Sign-in failed</string>
<string name="tile_problem">Connection problem</string>
<string name="tile_label" translatable="false">SHX VPN</string>
</resources>