Merge branch 'feature/collapse-long-descriptions'
This commit is contained in:
@@ -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",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -34,7 +34,9 @@
|
||||
"no": "Non",
|
||||
"delete": "Supprimer",
|
||||
"shuffle": "Mélanger",
|
||||
"addTo": "Ajouter à..."
|
||||
"addTo": "Ajouter à...",
|
||||
"showMore": "Voir plus",
|
||||
"showLess": "Voir moins"
|
||||
},
|
||||
"screens": {
|
||||
"licenses": "Licenses",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -34,7 +34,9 @@
|
||||
"no": "아니오",
|
||||
"delete": "삭제",
|
||||
"shuffle": "무작위 재생",
|
||||
"addTo": "추가하기..."
|
||||
"addTo": "추가하기...",
|
||||
"showMore": "더 보기",
|
||||
"showLess": "접기"
|
||||
},
|
||||
"screens": {
|
||||
"licenses": "라이선스",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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?',
|
||||
|
||||
@@ -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?',
|
||||
|
||||
@@ -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 ?',
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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' => '참가 중...',
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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' => '输入合集名称',
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -34,7 +34,9 @@
|
||||
"no": "否",
|
||||
"delete": "删除",
|
||||
"shuffle": "随机播放",
|
||||
"addTo": "添加到..."
|
||||
"addTo": "添加到...",
|
||||
"showMore": "展开",
|
||||
"showLess": "收起"
|
||||
},
|
||||
"screens": {
|
||||
"licenses": "许可证",
|
||||
|
||||
@@ -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<MediaDetailScreen> 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<MediaDetailScreen> 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),
|
||||
],
|
||||
|
||||
|
||||
@@ -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<CollapsibleText> createState() => _CollapsibleTextState();
|
||||
}
|
||||
|
||||
class _CollapsibleTextState extends State<CollapsibleText> {
|
||||
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,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -48,6 +48,7 @@ dependencies:
|
||||
in_app_review: ^2.0.11
|
||||
dart_discord_presence: ^1.1.0
|
||||
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
sdk: flutter
|
||||
|
||||
Reference in New Issue
Block a user