Merge pull request #1789 from JackDanger/fix/plex-home-account-chip

fix(profiles): label a Plex Home parent connection as an account

Conflict resolution: regenerated the Slang outputs against main's
translation set, added the empty locale placeholders the translation
gate requires, and gave the new widget test the StorageService provider
the picker now reads for profile recency.
This commit is contained in:
edde746
2026-08-05 12:31:29 +02:00
26 changed files with 105 additions and 4 deletions
+1
View File
@@ -763,6 +763,7 @@
"deleteThisProfileTitle": "Bu profil silinsin?", "deleteThisProfileTitle": "Bu profil silinsin?",
"deleteThisProfileMessage": "${displayName} silinəcək. Qoşulmalar təsirlənmir.", "deleteThisProfileMessage": "${displayName} silinəcək. Qoşulmalar təsirlənmir.",
"active": "Aktiv", "active": "Aktiv",
"viaPlexAccount": "",
"manage": "İdarə et", "manage": "İdarə et",
"delete": "Sil", "delete": "Sil",
"signOut": "Çıxış et", "signOut": "Çıxış et",
+1
View File
@@ -763,6 +763,7 @@
"deleteThisProfileTitle": "Да се изтрие ли този профил?", "deleteThisProfileTitle": "Да се изтрие ли този профил?",
"deleteThisProfileMessage": "Премахване на ${displayName}. Връзките не се засягат.", "deleteThisProfileMessage": "Премахване на ${displayName}. Връзките не се засягат.",
"active": "Активен", "active": "Активен",
"viaPlexAccount": "",
"manage": "Управление", "manage": "Управление",
"delete": "Изтрий", "delete": "Изтрий",
"signOut": "Изход", "signOut": "Изход",
+1
View File
@@ -763,6 +763,7 @@
"deleteThisProfileTitle": "Slet denne profil?", "deleteThisProfileTitle": "Slet denne profil?",
"deleteThisProfileMessage": "Fjern ${displayName}. Forbindelser påvirkes ikke.", "deleteThisProfileMessage": "Fjern ${displayName}. Forbindelser påvirkes ikke.",
"active": "Aktiv", "active": "Aktiv",
"viaPlexAccount": "",
"manage": "Administrer", "manage": "Administrer",
"delete": "Slet", "delete": "Slet",
"signOut": "Log ud", "signOut": "Log ud",
+1
View File
@@ -763,6 +763,7 @@
"deleteThisProfileTitle": "Dieses Profil löschen?", "deleteThisProfileTitle": "Dieses Profil löschen?",
"deleteThisProfileMessage": "${displayName} entfernen. Verbindungen bleiben unberührt.", "deleteThisProfileMessage": "${displayName} entfernen. Verbindungen bleiben unberührt.",
"active": "Aktiv", "active": "Aktiv",
"viaPlexAccount": "",
"manage": "Verwalten", "manage": "Verwalten",
"delete": "Löschen", "delete": "Löschen",
"signOut": "Abmelden", "signOut": "Abmelden",
+1
View File
@@ -763,6 +763,7 @@
"deleteThisProfileTitle": "Delete this profile?", "deleteThisProfileTitle": "Delete this profile?",
"deleteThisProfileMessage": "Remove ${displayName}. Connections aren't affected.", "deleteThisProfileMessage": "Remove ${displayName}. Connections aren't affected.",
"active": "Active", "active": "Active",
"viaPlexAccount": "via ${name}",
"manage": "Manage", "manage": "Manage",
"delete": "Delete", "delete": "Delete",
"signOut": "Sign out", "signOut": "Sign out",
+1
View File
@@ -763,6 +763,7 @@
"deleteThisProfileTitle": "¿Eliminar este perfil?", "deleteThisProfileTitle": "¿Eliminar este perfil?",
"deleteThisProfileMessage": "Eliminar ${displayName}. Las conexiones no se verán afectadas.", "deleteThisProfileMessage": "Eliminar ${displayName}. Las conexiones no se verán afectadas.",
"active": "Activo", "active": "Activo",
"viaPlexAccount": "",
"manage": "Administrar", "manage": "Administrar",
"delete": "Eliminar", "delete": "Eliminar",
"signOut": "Cerrar sesión", "signOut": "Cerrar sesión",
+1
View File
@@ -763,6 +763,7 @@
"deleteThisProfileTitle": "Supprimer ce profil ?", "deleteThisProfileTitle": "Supprimer ce profil ?",
"deleteThisProfileMessage": "Supprimer ${displayName}. Les connexions ne sont pas affectées.", "deleteThisProfileMessage": "Supprimer ${displayName}. Les connexions ne sont pas affectées.",
"active": "Actif", "active": "Actif",
"viaPlexAccount": "",
"manage": "Gérer", "manage": "Gérer",
"delete": "Supprimer", "delete": "Supprimer",
"signOut": "Se déconnecter", "signOut": "Se déconnecter",
+1
View File
@@ -763,6 +763,7 @@
"deleteThisProfileTitle": "Törlöd ezt a profilt?", "deleteThisProfileTitle": "Törlöd ezt a profilt?",
"deleteThisProfileMessage": "${displayName} eltávolítása. A kapcsolatokat nem érinti.", "deleteThisProfileMessage": "${displayName} eltávolítása. A kapcsolatokat nem érinti.",
"active": "Aktív", "active": "Aktív",
"viaPlexAccount": "",
"manage": "Kezelés", "manage": "Kezelés",
"delete": "Törlés", "delete": "Törlés",
"signOut": "Kijelentkezés", "signOut": "Kijelentkezés",
+1
View File
@@ -763,6 +763,7 @@
"deleteThisProfileTitle": "Eliminare questo profilo?", "deleteThisProfileTitle": "Eliminare questo profilo?",
"deleteThisProfileMessage": "Rimuovi ${displayName}. Le connessioni resteranno invariate.", "deleteThisProfileMessage": "Rimuovi ${displayName}. Le connessioni resteranno invariate.",
"active": "Attivo", "active": "Attivo",
"viaPlexAccount": "",
"manage": "Gestisci", "manage": "Gestisci",
"delete": "Elimina", "delete": "Elimina",
"signOut": "Esci", "signOut": "Esci",
+1
View File
@@ -762,6 +762,7 @@
"deleteThisProfileTitle": "このプロフィールを削除しますか?", "deleteThisProfileTitle": "このプロフィールを削除しますか?",
"deleteThisProfileMessage": "${displayName}を削除します。接続には影響しません。", "deleteThisProfileMessage": "${displayName}を削除します。接続には影響しません。",
"active": "アクティブ", "active": "アクティブ",
"viaPlexAccount": "",
"manage": "管理", "manage": "管理",
"delete": "削除", "delete": "削除",
"signOut": "サインアウト", "signOut": "サインアウト",
+1
View File
@@ -763,6 +763,7 @@
"deleteThisProfileTitle": "Осы профиль өшірілсін бе?", "deleteThisProfileTitle": "Осы профиль өшірілсін бе?",
"deleteThisProfileMessage": "${displayName} өшіріледі. Қосылымдарға әсер етпейді.", "deleteThisProfileMessage": "${displayName} өшіріледі. Қосылымдарға әсер етпейді.",
"active": "Белсенді", "active": "Белсенді",
"viaPlexAccount": "",
"manage": "Басқару", "manage": "Басқару",
"delete": "Өшіру", "delete": "Өшіру",
"signOut": "Шығу", "signOut": "Шығу",
+1
View File
@@ -762,6 +762,7 @@
"deleteThisProfileTitle": "이 프로필을 삭제하시겠습니까?", "deleteThisProfileTitle": "이 프로필을 삭제하시겠습니까?",
"deleteThisProfileMessage": "${displayName}을(를) 제거합니다. 연결에는 영향이 없습니다.", "deleteThisProfileMessage": "${displayName}을(를) 제거합니다. 연결에는 영향이 없습니다.",
"active": "활성", "active": "활성",
"viaPlexAccount": "",
"manage": "관리", "manage": "관리",
"delete": "삭제", "delete": "삭제",
"signOut": "로그아웃", "signOut": "로그아웃",
+1
View File
@@ -763,6 +763,7 @@
"deleteThisProfileTitle": "Slett denne profilen?", "deleteThisProfileTitle": "Slett denne profilen?",
"deleteThisProfileMessage": "Fjern ${displayName}. Tilkoblinger påvirkes ikke.", "deleteThisProfileMessage": "Fjern ${displayName}. Tilkoblinger påvirkes ikke.",
"active": "Aktiv", "active": "Aktiv",
"viaPlexAccount": "",
"manage": "Administrer", "manage": "Administrer",
"delete": "Slett", "delete": "Slett",
"signOut": "Logg ut", "signOut": "Logg ut",
+1
View File
@@ -763,6 +763,7 @@
"deleteThisProfileTitle": "Dit profiel verwijderen?", "deleteThisProfileTitle": "Dit profiel verwijderen?",
"deleteThisProfileMessage": "Verwijder ${displayName}. Verbindingen blijven ongewijzigd.", "deleteThisProfileMessage": "Verwijder ${displayName}. Verbindingen blijven ongewijzigd.",
"active": "Actief", "active": "Actief",
"viaPlexAccount": "",
"manage": "Beheren", "manage": "Beheren",
"delete": "Verwijderen", "delete": "Verwijderen",
"signOut": "Afmelden", "signOut": "Afmelden",
+1
View File
@@ -765,6 +765,7 @@
"deleteThisProfileTitle": "Usunąć ten profil?", "deleteThisProfileTitle": "Usunąć ten profil?",
"deleteThisProfileMessage": "Usuń ${displayName}. Połączenia nie zostaną zmienione.", "deleteThisProfileMessage": "Usuń ${displayName}. Połączenia nie zostaną zmienione.",
"active": "Aktywny", "active": "Aktywny",
"viaPlexAccount": "",
"manage": "Zarządzaj", "manage": "Zarządzaj",
"delete": "Usuń", "delete": "Usuń",
"signOut": "Wyloguj się", "signOut": "Wyloguj się",
+1
View File
@@ -763,6 +763,7 @@
"deleteThisProfileTitle": "Excluir este perfil?", "deleteThisProfileTitle": "Excluir este perfil?",
"deleteThisProfileMessage": "Remover ${displayName}. As conexões não serão afetadas.", "deleteThisProfileMessage": "Remover ${displayName}. As conexões não serão afetadas.",
"active": "Ativo", "active": "Ativo",
"viaPlexAccount": "",
"manage": "Gerenciar", "manage": "Gerenciar",
"delete": "Excluir", "delete": "Excluir",
"signOut": "Sair", "signOut": "Sair",
+1
View File
@@ -765,6 +765,7 @@
"deleteThisProfileTitle": "Удалить этот профиль?", "deleteThisProfileTitle": "Удалить этот профиль?",
"deleteThisProfileMessage": "Удалить ${displayName}. Подключения не изменятся.", "deleteThisProfileMessage": "Удалить ${displayName}. Подключения не изменятся.",
"active": "Активный", "active": "Активный",
"viaPlexAccount": "",
"manage": "Управление", "manage": "Управление",
"delete": "Удалить", "delete": "Удалить",
"signOut": "Выйти", "signOut": "Выйти",
+1 -1
View File
@@ -4,7 +4,7 @@
/// To regenerate, run: `dart run slang` /// To regenerate, run: `dart run slang`
/// ///
/// Locales: 22 /// Locales: 22
/// Strings: 32737 (1488 per locale) /// Strings: 32738 (1488 per locale)
// coverage:ignore-file // coverage:ignore-file
// ignore_for_file: type=lint, unused_import // ignore_for_file: type=lint, unused_import
+6 -2
View File
@@ -2296,6 +2296,9 @@ class Translations$profiles$en {
/// en: 'Active' /// en: 'Active'
String get active => 'Active'; String get active => 'Active';
/// en: 'via ${name}'
String viaPlexAccount({required Object name}) => 'via ${name}';
/// en: 'Manage' /// en: 'Manage'
String get manage => 'Manage'; String get manage => 'Manage';
@@ -6754,6 +6757,7 @@ extension on Translations {
'profiles.deleteThisProfileTitle' => 'Delete this profile?', 'profiles.deleteThisProfileTitle' => 'Delete this profile?',
'profiles.deleteThisProfileMessage' => ({required Object displayName}) => 'Remove ${displayName}. Connections aren\'t affected.', 'profiles.deleteThisProfileMessage' => ({required Object displayName}) => 'Remove ${displayName}. Connections aren\'t affected.',
'profiles.active' => 'Active', 'profiles.active' => 'Active',
'profiles.viaPlexAccount' => ({required Object name}) => 'via ${name}',
'profiles.manage' => 'Manage', 'profiles.manage' => 'Manage',
'profiles.delete' => 'Delete', 'profiles.delete' => 'Delete',
'profiles.signOut' => 'Sign out', 'profiles.signOut' => 'Sign out',
@@ -7062,9 +7066,9 @@ extension on Translations {
'explore.stats.onHold' => ({required Object n}) => '${n} on hold', 'explore.stats.onHold' => ({required Object n}) => '${n} on hold',
'explore.stats.dropped' => ({required Object n}) => '${n} dropped', 'explore.stats.dropped' => ({required Object n}) => '${n} dropped',
'explore.season.winter' => 'Winter', 'explore.season.winter' => 'Winter',
'explore.season.spring' => 'Spring',
_ => null, _ => null,
} ?? switch (path) { } ?? switch (path) {
'explore.season.spring' => 'Spring',
'explore.season.summer' => 'Summer', 'explore.season.summer' => 'Summer',
'explore.season.fall' => 'Fall', 'explore.season.fall' => 'Fall',
'explore.season.withYear' => ({required Object season, required Object year}) => '${season} ${year}', 'explore.season.withYear' => ({required Object season, required Object year}) => '${season} ${year}',
@@ -7576,9 +7580,9 @@ extension on Translations {
'externalPlayer.playerPackage' => 'Package Name', 'externalPlayer.playerPackage' => 'Package Name',
'externalPlayer.playerUrlScheme' => 'URL Scheme', 'externalPlayer.playerUrlScheme' => 'URL Scheme',
'externalPlayer.off' => 'Off', 'externalPlayer.off' => 'Off',
'externalPlayer.launchFailed' => 'Failed to open external player',
_ => null, _ => null,
} ?? switch (path) { } ?? switch (path) {
'externalPlayer.launchFailed' => 'Failed to open external player',
'externalPlayer.appNotInstalled' => ({required Object name}) => '${name} is not installed', 'externalPlayer.appNotInstalled' => ({required Object name}) => '${name} is not installed',
'externalPlayer.playInExternalPlayer' => 'Play in External Player', 'externalPlayer.playInExternalPlayer' => 'Play in External Player',
'metadataEdit.editMetadata' => 'Edit...', 'metadataEdit.editMetadata' => 'Edit...',
+1
View File
@@ -763,6 +763,7 @@
"deleteThisProfileTitle": "Ta bort denna profil?", "deleteThisProfileTitle": "Ta bort denna profil?",
"deleteThisProfileMessage": "Ta bort ${displayName}. Anslutningar påverkas inte.", "deleteThisProfileMessage": "Ta bort ${displayName}. Anslutningar påverkas inte.",
"active": "Aktiv", "active": "Aktiv",
"viaPlexAccount": "",
"manage": "Hantera", "manage": "Hantera",
"delete": "Ta bort", "delete": "Ta bort",
"signOut": "Logga ut", "signOut": "Logga ut",
+1
View File
@@ -763,6 +763,7 @@
"deleteThisProfileTitle": "Bu profil silinsin mi?", "deleteThisProfileTitle": "Bu profil silinsin mi?",
"deleteThisProfileMessage": "${displayName} kişisi kaldırılacak. Bağlantılar etkilenmez.", "deleteThisProfileMessage": "${displayName} kişisi kaldırılacak. Bağlantılar etkilenmez.",
"active": "Aktif", "active": "Aktif",
"viaPlexAccount": "",
"manage": "Yönet", "manage": "Yönet",
"delete": "Sil", "delete": "Sil",
"signOut": "Çıkış Yap", "signOut": "Çıkış Yap",
+1
View File
@@ -763,6 +763,7 @@
"deleteThisProfileTitle": "Ushbu profil oʻchirilsinmi?", "deleteThisProfileTitle": "Ushbu profil oʻchirilsinmi?",
"deleteThisProfileMessage": "${displayName} oʻchiriladi. Ulanishlarga taʼsir qilmaydi.", "deleteThisProfileMessage": "${displayName} oʻchiriladi. Ulanishlarga taʼsir qilmaydi.",
"active": "Faol", "active": "Faol",
"viaPlexAccount": "",
"manage": "Boshqarish", "manage": "Boshqarish",
"delete": "Oʻchirish", "delete": "Oʻchirish",
"signOut": "Chiqish", "signOut": "Chiqish",
+1
View File
@@ -762,6 +762,7 @@
"deleteThisProfileTitle": "刪除此使用者設定檔?", "deleteThisProfileTitle": "刪除此使用者設定檔?",
"deleteThisProfileMessage": "將移除 ${displayName}。連線資訊將不受影響。", "deleteThisProfileMessage": "將移除 ${displayName}。連線資訊將不受影響。",
"active": "使用中", "active": "使用中",
"viaPlexAccount": "",
"manage": "管理", "manage": "管理",
"delete": "刪除", "delete": "刪除",
"signOut": "登出", "signOut": "登出",
+1
View File
@@ -762,6 +762,7 @@
"deleteThisProfileTitle": "删除此用户资料?", "deleteThisProfileTitle": "删除此用户资料?",
"deleteThisProfileMessage": "移除 ${displayName}。连接不会受影响。", "deleteThisProfileMessage": "移除 ${displayName}。连接不会受影响。",
"active": "当前使用", "active": "当前使用",
"viaPlexAccount": "",
"manage": "管理", "manage": "管理",
"delete": "删除", "delete": "删除",
"signOut": "退出登录", "signOut": "退出登录",
+11 -1
View File
@@ -4,6 +4,7 @@ import 'package:flutter/material.dart';
import 'package:material_symbols_icons/symbols.dart'; import 'package:material_symbols_icons/symbols.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import '../../connection/connection.dart';
import '../../connection/connection_registry.dart'; import '../../connection/connection_registry.dart';
import '../../focus/focusable_wrapper.dart'; import '../../focus/focusable_wrapper.dart';
import '../../i18n/strings.g.dart'; import '../../i18n/strings.g.dart';
@@ -331,7 +332,16 @@ class _ProfileSwitchScreenState extends State<ProfileSwitchScreen> with MountedS
final parentId = profile.parentConnectionId; final parentId = profile.parentConnectionId;
if (parentId != null) { if (parentId != null) {
final conn = view.connectionsById[parentId]; final conn = view.connectionsById[parentId];
if (conn != null) chips.add(_ChipData(backend: conn.backend, label: conn.displayLabel)); if (conn != null) {
chips.add(
_ChipData(
backend: conn.backend,
label: conn is PlexAccountConnection
? t.profiles.viaPlexAccount(name: conn.accountLabel)
: conn.displayLabel,
),
);
}
} }
} }
final pcs = visibleProfileConnections( final pcs = visibleProfileConnections(
@@ -368,6 +368,71 @@ void main() {
await tester.pumpWidget(const SizedBox.shrink()); await tester.pumpWidget(const SizedBox.shrink());
await tester.pump(); await tester.pump();
}); });
testWidgets('labels a Plex Home parent connection as an account, not as the profile', (tester) async {
final db = AppDatabase.forTesting(NativeDatabase.memory());
final profile = Profile.plexHome(
id: 'home-alice',
displayName: 'Alice',
parentConnectionId: 'plex-account',
plexHomeUserUuid: 'alice-uuid',
createdAt: DateTime(2026, 1, 1),
);
final profiles = _FakeProfileRegistry(db, [profile]);
final connections = _FakeConnectionRegistry(db, [
PlexAccountConnection(
id: 'plex-account',
accountToken: 'token',
clientIdentifier: 'client',
accountLabel: 'Bob',
createdAt: DateTime(2026, 1, 1),
),
]);
final profileConnections = _FakeProfileConnectionRegistry(db);
final storage = await StorageService.getInstance();
final plexHome = PlexHomeService(
connections: connections,
profileConnections: profileConnections,
storage: storage,
plexHomeUserFetcher: (_) async => const [],
);
final activeProfile = ActiveProfileProvider(
registry: profiles,
plexHome: plexHome,
connections: connections,
profileConnections: profileConnections,
storage: storage,
);
addTearDown(() async {
activeProfile.dispose();
await plexHome.dispose();
await db.close();
});
await tester.pumpWidget(
TranslationProvider(
child: MultiProvider(
providers: [
Provider<StorageService>.value(value: storage),
Provider<ProfileRegistry>.value(value: profiles),
Provider<ProfileConnectionRegistry>.value(value: profileConnections),
Provider<ConnectionRegistry>.value(value: connections),
Provider<PlexHomeService>.value(value: plexHome),
ChangeNotifierProvider<ActiveProfileProvider>.value(value: activeProfile),
],
child: MaterialApp(theme: monoTheme(dark: true), home: const ProfileSwitchScreen()),
),
),
);
await tester.pumpAndSettle();
expect(find.text('Alice'), findsOneWidget);
expect(find.text(t.profiles.viaPlexAccount(name: 'Bob')), findsOneWidget);
expect(find.text('Bob'), findsNothing);
await tester.pumpWidget(const SizedBox.shrink());
await tester.pump();
});
} }
/// Tile labels in painted order. Only the two names the reorder tests seed are /// Tile labels in painted order. Only the two names the reorder tests seed are