diff --git a/lib/i18n/de.i18n.json b/lib/i18n/de.i18n.json index b036b6dd..855372ef 100644 --- a/lib/i18n/de.i18n.json +++ b/lib/i18n/de.i18n.json @@ -34,7 +34,9 @@ "no": "Nein", "delete": "Löschen", "shuffle": "Zufall", - "addTo": "Hinzufügen zu..." + "addTo": "Hinzufügen zu...", + "showMore": "Mehr anzeigen", + "showLess": "Weniger anzeigen" }, "screens": { "licenses": "Lizenzen", diff --git a/lib/i18n/en.i18n.json b/lib/i18n/en.i18n.json index 52da572c..10f37cf6 100644 --- a/lib/i18n/en.i18n.json +++ b/lib/i18n/en.i18n.json @@ -34,7 +34,9 @@ "no": "No", "delete": "Delete", "shuffle": "Shuffle", - "addTo": "Add to..." + "addTo": "Add to...", + "showMore": "Show more", + "showLess": "Show less" }, "screens": { "licenses": "Licenses", diff --git a/lib/i18n/es.i18n.json b/lib/i18n/es.i18n.json index 2ea13e86..cc427c93 100644 --- a/lib/i18n/es.i18n.json +++ b/lib/i18n/es.i18n.json @@ -34,7 +34,9 @@ "no": "No", "delete": "Eliminar", "shuffle": "Aleatorio", - "addTo": "Añadir a..." + "addTo": "Añadir a...", + "showMore": "Ver más", + "showLess": "Ver menos" }, "screens": { "licenses": "Licencias", diff --git a/lib/i18n/fr.i18n.json b/lib/i18n/fr.i18n.json index acdf3120..b07ea5bd 100644 --- a/lib/i18n/fr.i18n.json +++ b/lib/i18n/fr.i18n.json @@ -34,7 +34,9 @@ "no": "Non", "delete": "Supprimer", "shuffle": "Mélanger", - "addTo": "Ajouter à..." + "addTo": "Ajouter à...", + "showMore": "Voir plus", + "showLess": "Voir moins" }, "screens": { "licenses": "Licenses", diff --git a/lib/i18n/it.i18n.json b/lib/i18n/it.i18n.json index 3fdbc969..bf530502 100644 --- a/lib/i18n/it.i18n.json +++ b/lib/i18n/it.i18n.json @@ -34,7 +34,9 @@ "no": "No", "delete": "Elimina", "shuffle": "Casuale", - "addTo": "Aggiungi a..." + "addTo": "Aggiungi a...", + "showMore": "Mostra di più", + "showLess": "Mostra meno" }, "screens": { "licenses": "Licenze", diff --git a/lib/i18n/ko.i18n.json b/lib/i18n/ko.i18n.json index 0e487096..2a23a5c8 100644 --- a/lib/i18n/ko.i18n.json +++ b/lib/i18n/ko.i18n.json @@ -34,7 +34,9 @@ "no": "아니오", "delete": "삭제", "shuffle": "무작위 재생", - "addTo": "추가하기..." + "addTo": "추가하기...", + "showMore": "더 보기", + "showLess": "접기" }, "screens": { "licenses": "라이선스", diff --git a/lib/i18n/nl.i18n.json b/lib/i18n/nl.i18n.json index 8055b195..c74b09c9 100644 --- a/lib/i18n/nl.i18n.json +++ b/lib/i18n/nl.i18n.json @@ -34,7 +34,9 @@ "no": "Nee", "delete": "Verwijderen", "shuffle": "Willekeurig", - "addTo": "Toevoegen aan..." + "addTo": "Toevoegen aan...", + "showMore": "Meer tonen", + "showLess": "Minder tonen" }, "screens": { "licenses": "Licenties", diff --git a/lib/i18n/strings.g.dart b/lib/i18n/strings.g.dart index 5adf79ad..2d11d028 100644 --- a/lib/i18n/strings.g.dart +++ b/lib/i18n/strings.g.dart @@ -4,9 +4,9 @@ /// To regenerate, run: `dart run slang` /// /// Locales: 9 -/// Strings: 5169 (574 per locale) +/// Strings: 5187 (576 per locale) /// -/// Built on 2026-02-03 at 01:03 UTC +/// Built on 2026-02-03 at 19:20 UTC // coverage:ignore-file // ignore_for_file: type=lint, unused_import diff --git a/lib/i18n/strings_de.g.dart b/lib/i18n/strings_de.g.dart index 88f229c9..a390e222 100644 --- a/lib/i18n/strings_de.g.dart +++ b/lib/i18n/strings_de.g.dart @@ -128,6 +128,8 @@ class _TranslationsCommonDe implements TranslationsCommonEn { @override String get delete => 'Löschen'; @override String get shuffle => 'Zufall'; @override String get addTo => 'Hinzufügen zu...'; + @override String get showMore => 'Mehr anzeigen'; + @override String get showLess => 'Weniger anzeigen'; } // Path: screens @@ -1023,6 +1025,8 @@ extension on TranslationsDe { 'common.delete' => 'Löschen', 'common.shuffle' => 'Zufall', 'common.addTo' => 'Hinzufügen zu...', + 'common.showMore' => 'Mehr anzeigen', + 'common.showLess' => 'Weniger anzeigen', 'screens.licenses' => 'Lizenzen', 'screens.selectServer' => 'Server auswählen', 'screens.switchProfile' => 'Profil wechseln', @@ -1502,10 +1506,10 @@ extension on TranslationsDe { 'collections.deleted' => 'Sammlung gelöscht', 'collections.deleteFailed' => 'Sammlung konnte nicht gelöscht werden', 'collections.deleteFailedWithError' => ({required Object error}) => 'Sammlung konnte nicht gelöscht werden: ${error}', - 'collections.failedToLoadItems' => ({required Object error}) => 'Sammlungselemente konnten nicht geladen werden: ${error}', - 'collections.selectCollection' => 'Sammlung auswählen', _ => null, } ?? switch (path) { + 'collections.failedToLoadItems' => ({required Object error}) => 'Sammlungselemente konnten nicht geladen werden: ${error}', + 'collections.selectCollection' => 'Sammlung auswählen', 'collections.createNewCollection' => 'Neue Sammlung erstellen', 'collections.collectionName' => 'Sammlungsname', 'collections.enterCollectionName' => 'Sammlungsnamen eingeben', diff --git a/lib/i18n/strings_en.g.dart b/lib/i18n/strings_en.g.dart index b9e5f771..3c7a817b 100644 --- a/lib/i18n/strings_en.g.dart +++ b/lib/i18n/strings_en.g.dart @@ -193,6 +193,12 @@ class TranslationsCommonEn { /// en: 'Add to...' String get addTo => 'Add to...'; + + /// en: 'Show more' + String get showMore => 'Show more'; + + /// en: 'Show less' + String get showLess => 'Show less'; } // Path: screens @@ -2173,6 +2179,8 @@ extension on Translations { 'common.delete' => 'Delete', 'common.shuffle' => 'Shuffle', 'common.addTo' => 'Add to...', + 'common.showMore' => 'Show more', + 'common.showLess' => 'Show less', 'screens.licenses' => 'Licenses', 'screens.switchProfile' => 'Switch Profile', 'screens.subtitleStyling' => 'Subtitle Styling', @@ -2652,10 +2660,10 @@ extension on Translations { 'watchTogether.title' => 'Watch Together', 'watchTogether.description' => 'Watch content in sync with friends and family', 'watchTogether.createSession' => 'Create Session', - 'watchTogether.creating' => 'Creating...', - 'watchTogether.joinSession' => 'Join Session', _ => null, } ?? switch (path) { + 'watchTogether.creating' => 'Creating...', + 'watchTogether.joinSession' => 'Join Session', 'watchTogether.joining' => 'Joining...', 'watchTogether.controlMode' => 'Control Mode', 'watchTogether.controlModeQuestion' => 'Who can control playback?', diff --git a/lib/i18n/strings_es.g.dart b/lib/i18n/strings_es.g.dart index 905767cb..306ef62b 100644 --- a/lib/i18n/strings_es.g.dart +++ b/lib/i18n/strings_es.g.dart @@ -128,6 +128,8 @@ class _TranslationsCommonEs implements TranslationsCommonEn { @override String get delete => 'Eliminar'; @override String get shuffle => 'Aleatorio'; @override String get addTo => 'Añadir a...'; + @override String get showMore => 'Ver más'; + @override String get showLess => 'Ver menos'; } // Path: screens @@ -1021,6 +1023,8 @@ extension on TranslationsEs { 'common.delete' => 'Eliminar', 'common.shuffle' => 'Aleatorio', 'common.addTo' => 'Añadir a...', + 'common.showMore' => 'Ver más', + 'common.showLess' => 'Ver menos', 'screens.licenses' => 'Licencias', 'screens.switchProfile' => 'Cambiar Perfil', 'screens.subtitleStyling' => 'Estilo de Subtítulos', @@ -1500,10 +1504,10 @@ extension on TranslationsEs { 'watchTogether.title' => 'Ver Juntos', 'watchTogether.description' => 'Mira contenido en sincronía con amigos y familiares', 'watchTogether.createSession' => 'Crear Sesión', - 'watchTogether.creating' => 'Creando...', - 'watchTogether.joinSession' => 'Unirse a Sesión', _ => null, } ?? switch (path) { + 'watchTogether.creating' => 'Creando...', + 'watchTogether.joinSession' => 'Unirse a Sesión', 'watchTogether.joining' => 'Uniendo...', 'watchTogether.controlMode' => 'Modo de Control', 'watchTogether.controlModeQuestion' => '¿Quién puede controlar la reproducción?', diff --git a/lib/i18n/strings_fr.g.dart b/lib/i18n/strings_fr.g.dart index 5062e4f3..937e6f7d 100644 --- a/lib/i18n/strings_fr.g.dart +++ b/lib/i18n/strings_fr.g.dart @@ -128,6 +128,8 @@ class _TranslationsCommonFr implements TranslationsCommonEn { @override String get delete => 'Supprimer'; @override String get shuffle => 'Mélanger'; @override String get addTo => 'Ajouter à...'; + @override String get showMore => 'Voir plus'; + @override String get showLess => 'Voir moins'; } // Path: screens @@ -1021,6 +1023,8 @@ extension on TranslationsFr { 'common.delete' => 'Supprimer', 'common.shuffle' => 'Mélanger', 'common.addTo' => 'Ajouter à...', + 'common.showMore' => 'Voir plus', + 'common.showLess' => 'Voir moins', 'screens.licenses' => 'Licenses', 'screens.switchProfile' => 'Changer de profil', 'screens.subtitleStyling' => 'Configuration des sous-titres', @@ -1500,10 +1504,10 @@ extension on TranslationsFr { 'watchTogether.title' => 'Regarder ensemble', 'watchTogether.description' => 'Regardez du contenu en synchronisation avec vos amis et votre famille', 'watchTogether.createSession' => 'Créer une session', - 'watchTogether.creating' => 'Création...', - 'watchTogether.joinSession' => 'Rejoindre la session', _ => null, } ?? switch (path) { + 'watchTogether.creating' => 'Création...', + 'watchTogether.joinSession' => 'Rejoindre la session', 'watchTogether.joining' => 'Rejoindre...', 'watchTogether.controlMode' => 'Mode de contrôle', 'watchTogether.controlModeQuestion' => 'Qui peut contrôler la lecture ?', diff --git a/lib/i18n/strings_it.g.dart b/lib/i18n/strings_it.g.dart index 895f47c3..25cd6c4c 100644 --- a/lib/i18n/strings_it.g.dart +++ b/lib/i18n/strings_it.g.dart @@ -128,6 +128,8 @@ class _TranslationsCommonIt implements TranslationsCommonEn { @override String get delete => 'Elimina'; @override String get shuffle => 'Casuale'; @override String get addTo => 'Aggiungi a...'; + @override String get showMore => 'Mostra di più'; + @override String get showLess => 'Mostra meno'; } // Path: screens @@ -1023,6 +1025,8 @@ extension on TranslationsIt { 'common.delete' => 'Elimina', 'common.shuffle' => 'Casuale', 'common.addTo' => 'Aggiungi a...', + 'common.showMore' => 'Mostra di più', + 'common.showLess' => 'Mostra meno', 'screens.licenses' => 'Licenze', 'screens.selectServer' => 'Seleziona server', 'screens.switchProfile' => 'Cambia profilo', @@ -1502,10 +1506,10 @@ extension on TranslationsIt { 'collections.deleted' => 'Raccolta eliminata', 'collections.deleteFailed' => 'Impossibile eliminare la raccolta', 'collections.deleteFailedWithError' => ({required Object error}) => 'Impossibile eliminare la raccolta: ${error}', - 'collections.failedToLoadItems' => ({required Object error}) => 'Impossibile caricare gli elementi della raccolta: ${error}', - 'collections.selectCollection' => 'Seleziona raccolta', _ => null, } ?? switch (path) { + 'collections.failedToLoadItems' => ({required Object error}) => 'Impossibile caricare gli elementi della raccolta: ${error}', + 'collections.selectCollection' => 'Seleziona raccolta', 'collections.createNewCollection' => 'Crea nuova raccolta', 'collections.collectionName' => 'Nome raccolta', 'collections.enterCollectionName' => 'Inserisci nome raccolta', diff --git a/lib/i18n/strings_ko.g.dart b/lib/i18n/strings_ko.g.dart index de1b1b79..bb59ae66 100644 --- a/lib/i18n/strings_ko.g.dart +++ b/lib/i18n/strings_ko.g.dart @@ -128,6 +128,8 @@ class _TranslationsCommonKo implements TranslationsCommonEn { @override String get delete => '삭제'; @override String get shuffle => '무작위 재생'; @override String get addTo => '추가하기...'; + @override String get showMore => '더 보기'; + @override String get showLess => '접기'; } // Path: screens @@ -1023,6 +1025,8 @@ extension on TranslationsKo { 'common.delete' => '삭제', 'common.shuffle' => '무작위 재생', 'common.addTo' => '추가하기...', + 'common.showMore' => '더 보기', + 'common.showLess' => '접기', 'screens.licenses' => '라이선스', 'screens.selectServer' => '서버 선택', 'screens.switchProfile' => '프로필 전환', @@ -1502,10 +1506,10 @@ extension on TranslationsKo { 'playlists.errorReordering' => '재생 목록 항목 재정렬 실패', 'playlists.errorRemoving' => '재생 목록에서 제거 실패', 'watchTogether.title' => '함께 보기', - 'watchTogether.description' => '친구 및 가족과 콘텐츠를 동시에 시청하세요', - 'watchTogether.createSession' => '세션 생성', _ => null, } ?? switch (path) { + 'watchTogether.description' => '친구 및 가족과 콘텐츠를 동시에 시청하세요', + 'watchTogether.createSession' => '세션 생성', 'watchTogether.creating' => '생성 중...', 'watchTogether.joinSession' => '세션 참여', 'watchTogether.joining' => '참가 중...', diff --git a/lib/i18n/strings_nl.g.dart b/lib/i18n/strings_nl.g.dart index 33947129..2cd61834 100644 --- a/lib/i18n/strings_nl.g.dart +++ b/lib/i18n/strings_nl.g.dart @@ -128,6 +128,8 @@ class _TranslationsCommonNl implements TranslationsCommonEn { @override String get delete => 'Verwijderen'; @override String get shuffle => 'Willekeurig'; @override String get addTo => 'Toevoegen aan...'; + @override String get showMore => 'Meer tonen'; + @override String get showLess => 'Minder tonen'; } // Path: screens @@ -1023,6 +1025,8 @@ extension on TranslationsNl { 'common.delete' => 'Verwijderen', 'common.shuffle' => 'Willekeurig', 'common.addTo' => 'Toevoegen aan...', + 'common.showMore' => 'Meer tonen', + 'common.showLess' => 'Minder tonen', 'screens.licenses' => 'Licenties', 'screens.selectServer' => 'Selecteer server', 'screens.switchProfile' => 'Wissel van profiel', @@ -1502,10 +1506,10 @@ extension on TranslationsNl { 'collections.deleted' => 'Collectie verwijderd', 'collections.deleteFailed' => 'Collectie verwijderen mislukt', 'collections.deleteFailedWithError' => ({required Object error}) => 'Collectie verwijderen mislukt: ${error}', - 'collections.failedToLoadItems' => ({required Object error}) => 'Collectie-items laden mislukt: ${error}', - 'collections.selectCollection' => 'Selecteer collectie', _ => null, } ?? switch (path) { + 'collections.failedToLoadItems' => ({required Object error}) => 'Collectie-items laden mislukt: ${error}', + 'collections.selectCollection' => 'Selecteer collectie', 'collections.createNewCollection' => 'Nieuwe collectie maken', 'collections.collectionName' => 'Collectienaam', 'collections.enterCollectionName' => 'Voer collectienaam in', diff --git a/lib/i18n/strings_sv.g.dart b/lib/i18n/strings_sv.g.dart index 9f420c73..9e0d2a29 100644 --- a/lib/i18n/strings_sv.g.dart +++ b/lib/i18n/strings_sv.g.dart @@ -128,6 +128,8 @@ class _TranslationsCommonSv implements TranslationsCommonEn { @override String get delete => 'Ta bort'; @override String get shuffle => 'Blanda'; @override String get addTo => 'Lägg till i...'; + @override String get showMore => 'Visa mer'; + @override String get showLess => 'Visa mindre'; } // Path: screens @@ -1023,6 +1025,8 @@ extension on TranslationsSv { 'common.delete' => 'Ta bort', 'common.shuffle' => 'Blanda', 'common.addTo' => 'Lägg till i...', + 'common.showMore' => 'Visa mer', + 'common.showLess' => 'Visa mindre', 'screens.licenses' => 'Licenser', 'screens.selectServer' => 'Välj server', 'screens.switchProfile' => 'Byt profil', @@ -1502,10 +1506,10 @@ extension on TranslationsSv { 'collections.deleted' => 'Samling borttagen', 'collections.deleteFailed' => 'Det gick inte att ta bort samlingen', 'collections.deleteFailedWithError' => ({required Object error}) => 'Det gick inte att ta bort samlingen: ${error}', - 'collections.failedToLoadItems' => ({required Object error}) => 'Det gick inte att läsa in samlingsobjekt: ${error}', - 'collections.selectCollection' => 'Välj samling', _ => null, } ?? switch (path) { + 'collections.failedToLoadItems' => ({required Object error}) => 'Det gick inte att läsa in samlingsobjekt: ${error}', + 'collections.selectCollection' => 'Välj samling', 'collections.createNewCollection' => 'Skapa ny samling', 'collections.collectionName' => 'Samlingsnamn', 'collections.enterCollectionName' => 'Ange samlingsnamn', diff --git a/lib/i18n/strings_zh.g.dart b/lib/i18n/strings_zh.g.dart index bf258372..98c924be 100644 --- a/lib/i18n/strings_zh.g.dart +++ b/lib/i18n/strings_zh.g.dart @@ -128,6 +128,8 @@ class _TranslationsCommonZh implements TranslationsCommonEn { @override String get delete => '删除'; @override String get shuffle => '随机播放'; @override String get addTo => '添加到...'; + @override String get showMore => '展开'; + @override String get showLess => '收起'; } // Path: screens @@ -1023,6 +1025,8 @@ extension on TranslationsZh { 'common.delete' => '删除', 'common.shuffle' => '随机播放', 'common.addTo' => '添加到...', + 'common.showMore' => '展开', + 'common.showLess' => '收起', 'screens.licenses' => '许可证', 'screens.selectServer' => '选择服务器', 'screens.switchProfile' => '切换用户', @@ -1502,10 +1506,10 @@ extension on TranslationsZh { 'collections.deleted' => '已删除合集', 'collections.deleteFailed' => '删除合集失败', 'collections.deleteFailedWithError' => ({required Object error}) => '删除合集失败:${error}', - 'collections.failedToLoadItems' => ({required Object error}) => '加载合集项目失败:${error}', - 'collections.selectCollection' => '选择合集', _ => null, } ?? switch (path) { + 'collections.failedToLoadItems' => ({required Object error}) => '加载合集项目失败:${error}', + 'collections.selectCollection' => '选择合集', 'collections.createNewCollection' => '创建新合集', 'collections.collectionName' => '合集名称', 'collections.enterCollectionName' => '输入合集名称', diff --git a/lib/i18n/sv.i18n.json b/lib/i18n/sv.i18n.json index 69257ae1..799cfbb4 100644 --- a/lib/i18n/sv.i18n.json +++ b/lib/i18n/sv.i18n.json @@ -34,7 +34,9 @@ "no": "Nej", "delete": "Ta bort", "shuffle": "Blanda", - "addTo": "Lägg till i..." + "addTo": "Lägg till i...", + "showMore": "Visa mer", + "showLess": "Visa mindre" }, "screens": { "licenses": "Licenser", diff --git a/lib/i18n/zh.i18n.json b/lib/i18n/zh.i18n.json index e1cfcd3b..d0f57222 100644 --- a/lib/i18n/zh.i18n.json +++ b/lib/i18n/zh.i18n.json @@ -34,7 +34,9 @@ "no": "否", "delete": "删除", "shuffle": "随机播放", - "addTo": "添加到..." + "addTo": "添加到...", + "showMore": "展开", + "showLess": "收起" }, "screens": { "licenses": "许可证", diff --git a/lib/screens/media_detail_screen.dart b/lib/screens/media_detail_screen.dart index 17354e72..f32dc7d9 100644 --- a/lib/screens/media_detail_screen.dart +++ b/lib/screens/media_detail_screen.dart @@ -4,9 +4,11 @@ import 'dart:io'; import 'package:cached_network_image/cached_network_image.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; +import 'package:plezy/utils/platform_detector.dart'; import 'package:plezy/widgets/app_icon.dart'; import 'package:material_symbols_icons/symbols.dart'; import 'package:provider/provider.dart'; +import '../widgets/collapsible_text.dart'; import '../focus/dpad_navigator.dart'; import '../focus/focusable_wrapper.dart'; @@ -1216,6 +1218,8 @@ class _MediaDetailScreenState extends State with WatchStateAw // Use full metadata if loaded, otherwise use passed metadata final metadata = _fullMetadata ?? widget.metadata; final isShow = metadata.isShow; + final isMobile = PlatformDetector.isMobile(context); + final isTv = PlatformDetector.isTV(); KeyEventResult handleBack(FocusNode _, KeyEvent event) => handleBackKeyNavigation(context, event, result: _watchStateChanged); @@ -1466,7 +1470,14 @@ class _MediaDetailScreenState extends State with WatchStateAw style: Theme.of(context).textTheme.titleLarge?.copyWith(fontWeight: FontWeight.bold), ), const SizedBox(height: 12), - Text(metadata.summary!, style: Theme.of(context).textTheme.bodyLarge?.copyWith(height: 1.6)), + if (isTv) + Text(metadata.summary!, style: Theme.of(context).textTheme.bodyLarge?.copyWith(height: 1.6)) + else + CollapsibleText( + text: metadata.summary!, + maxLines: isMobile ? 6 : 4, + style: Theme.of(context).textTheme.bodyLarge?.copyWith(height: 1.6), + ), const SizedBox(height: 24), ], diff --git a/lib/widgets/collapsible_text.dart b/lib/widgets/collapsible_text.dart new file mode 100644 index 00000000..8b6974e7 --- /dev/null +++ b/lib/widgets/collapsible_text.dart @@ -0,0 +1,84 @@ +import 'package:flutter/material.dart'; + +class CollapsibleText extends StatefulWidget { + final String text; + final int maxLines; + final TextStyle? style; + + const CollapsibleText({super.key, required this.text, this.maxLines = 4, this.style}); + + @override + State createState() => _CollapsibleTextState(); +} + +class _CollapsibleTextState extends State { + bool _expanded = false; + + @override + Widget build(BuildContext context) { + final style = widget.style ?? DefaultTextStyle.of(context).style; + + return LayoutBuilder( + builder: (context, constraints) { + final textPainter = TextPainter( + text: TextSpan(text: widget.text, style: style), + maxLines: widget.maxLines, + textDirection: TextDirection.ltr, + )..layout(maxWidth: constraints.maxWidth); + + final overflows = textPainter.didExceedMaxLines; + + if (!overflows) { + textPainter.dispose(); + return Text(widget.text, style: style); + } + + String displayText = widget.text; + if (!_expanded) { + // Find where to truncate to leave room for the badge on the last line + final cutPoint = textPainter.getPositionForOffset( + Offset(constraints.maxWidth - 54, textPainter.height - 1), + ); + displayText = widget.text.substring(0, cutPoint.offset).trimRight(); + } + textPainter.dispose(); + + return GestureDetector( + onTap: () => setState(() => _expanded = !_expanded), + child: Text.rich( + TextSpan( + children: [ + TextSpan(text: displayText, style: style), + if (!_expanded) + WidgetSpan( + alignment: PlaceholderAlignment.middle, + child: _buildBadge(context), + ), + ], + ), + ), + ); + }, + ); + } + + Widget _buildBadge(BuildContext context) { + return Container( + margin: const EdgeInsets.only(left: 6), + padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 2), + decoration: BoxDecoration( + color: Theme.of(context).colorScheme.onSurface.withValues(alpha: 0.12), + borderRadius: BorderRadius.circular(10), + ), + child: Text( + '\u00B7\u00B7\u00B7', + style: TextStyle( + fontSize: 12, + fontWeight: FontWeight.bold, + color: Theme.of(context).colorScheme.onSurfaceVariant, + letterSpacing: 2, + ), + ), + ); + } +} diff --git a/pubspec.yaml b/pubspec.yaml index 460ab4b1..21a0d727 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -48,6 +48,7 @@ dependencies: in_app_review: ^2.0.11 dart_discord_presence: ^1.1.0 + dev_dependencies: flutter_test: sdk: flutter