From 17b3533261a4154b6c04b26694ac003e9ff67303 Mon Sep 17 00:00:00 2001 From: Frederik Feichtmeier Date: Tue, 20 Aug 2024 21:09:43 +0200 Subject: [PATCH] fix: constrain podcast html descriptions (#879) Also: hopefully fix release.yml + remove unused variables, constants and image cache read/write --- .github/workflows/release.yml | 64 ++++---- .../audio_page_header_html_description.dart | 145 ++++++++++-------- lib/common/view/theme.dart | 16 -- lib/local_audio/cover_store.dart | 2 + lib/local_audio/local_audio_service.dart | 13 +- .../view/player_remote_source_image.dart | 1 + lib/podcasts/view/podcast_page.dart | 13 +- 7 files changed, 130 insertions(+), 124 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 27c281be..c4550d41 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -84,34 +84,36 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: gh release upload ${{ steps.release.outputs.tag_name }} /Users/runner/work/musicpod/musicpod/build/macos/Build/Products/Release/musicpod.dmg - release_linux_edge: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - with: - fetch-depth: 5 - - uses: subosito/flutter-action@v2 - with: - channel: 'stable' - flutter-version: ${{env.FLUTTER_VERSION}} - - run: sudo apt update - - run: sudo apt install -y clang cmake curl libgtk-3-dev ninja-build pkg-config unzip libunwind-dev libmpv-dev - - run: flutter pub get - # Disabled until linux arm runners are available - # - uses: snapcore/action-build@v1 - # id: build - # - uses: snapcore/action-publish@v1 - # if: steps.build.outcome == 'success' - # env: - # SNAPCRAFT_STORE_CREDENTIALS: ${{ secrets.SNAPCRAFT_STORE_CREDENTIALS }} - # with: - # snap: ${{ steps.build.outputs.snap }} - # release: edge - # - run: flutter clean - # remove this when snap build is back, since this is included in the snapcraft musicpod->override-build phase - - run: flutter build linux --release -v - - uses: AppImageCrafters/build-appimage@master - with: - recipe: "./appimage/AppImageBuilder.yml" - env: - UPDATE_INFO: gh-releases-zsync|ubuntu-flutter-community|musicpod|latest|*x86_64.AppImage.zsync \ No newline at end of file + # Disabled until linux arm runners are available + # release_linux_edge: + # runs-on: ubuntu-latest + # steps: + # - uses: actions/checkout@v4 + # with: + # fetch-depth: 5 + # - uses: subosito/flutter-action@v2 + # with: + # channel: 'stable' + # flutter-version: ${{env.FLUTTER_VERSION}} + # - run: sudo apt update + # - run: sudo apt install -y clang cmake curl libgtk-3-dev ninja-build pkg-config unzip libunwind-dev libmpv-dev + # - run: flutter pub get + + # - uses: snapcore/action-build@v1 + # id: build + # - uses: snapcore/action-publish@v1 + # if: steps.build.outcome == 'success' + # env: + # SNAPCRAFT_STORE_CREDENTIALS: ${{ secrets.SNAPCRAFT_STORE_CREDENTIALS }} + # with: + # snap: ${{ steps.build.outputs.snap }} + # release: edge + # - run: flutter clean + # remove this when snap build is back, since this is included in the snapcraft musicpod->override-build phase + # - run: flutter build linux --release -v + # Disabled because it does not work + # - uses: AppImageCrafters/build-appimage@master + # with: + # recipe: "./appimage/AppImageBuilder.yml" + # env: + # UPDATE_INFO: gh-releases-zsync|ubuntu-flutter-community|musicpod|latest|*x86_64.AppImage.zsync \ No newline at end of file diff --git a/lib/common/view/audio_page_header_html_description.dart b/lib/common/view/audio_page_header_html_description.dart index 4be7abee..0d71319b 100644 --- a/lib/common/view/audio_page_header_html_description.dart +++ b/lib/common/view/audio_page_header_html_description.dart @@ -14,7 +14,7 @@ class AudioPageHeaderHtmlDescription extends StatelessWidget { required this.title, }); - final String? description; + final String description; final String title; @override @@ -22,75 +22,98 @@ class AudioPageHeaderHtmlDescription extends StatelessWidget { final descriptionStyle = context.t.pageHeaderDescription; return Padding( padding: const EdgeInsets.symmetric(horizontal: kYaruPagePadding), - child: SizedBox( - width: kAudioHeaderDescriptionWidth, + child: ConstrainedBox( + constraints: const BoxConstraints( + minWidth: kAudioHeaderDescriptionWidth, + maxWidth: kAudioHeaderDescriptionWidth, + maxHeight: 100, + ), child: InkWell( borderRadius: BorderRadius.circular(kYaruButtonRadius), onTap: () => showDialog( context: context, - builder: (context) => SimpleDialog( - titlePadding: EdgeInsets.zero, - contentPadding: EdgeInsets.zero, - title: YaruDialogTitleBar( - title: Text(title), - backgroundColor: Colors.transparent, - border: BorderSide.none, - ), - children: [ - SizedBox( - width: 400, - child: Html( - data: description, - onAnchorTap: (url, attributes, element) { - if (url == null) return; - launchUrl(Uri.parse(url)); - }, - style: { - 'img': Style(display: Display.none), - 'body': Style( - height: Height.auto(), - textOverflow: TextOverflow.ellipsis, - maxLines: 400, - textAlign: TextAlign.center, - fontSize: FontSize( - descriptionStyle?.fontSize ?? 10, - ), - fontWeight: descriptionStyle?.fontWeight, - fontFamily: descriptionStyle?.fontFamily, - ), - }, - ), - ), - ], + builder: (context) => _HtmlDialog( + title: title, + description: description, + descriptionStyle: descriptionStyle, ), ), - child: description == null - ? const SizedBox.shrink() - : Html( - data: description, - onAnchorTap: (url, attributes, element) { - if (url == null) return; - launchUrl(Uri.parse(url)); - }, - style: { - 'img': Style(display: Display.none), - 'body': Style( - height: Height.auto(), - margin: Margins.zero, - padding: HtmlPaddings.zero, - textOverflow: TextOverflow.ellipsis, - maxLines: 4, - textAlign: TextAlign.center, - fontSize: FontSize( - descriptionStyle?.fontSize ?? 10, - ), - fontWeight: descriptionStyle?.fontWeight, - fontFamily: descriptionStyle?.fontFamily, - ), - }, + child: Html( + data: description, + onAnchorTap: (url, attributes, element) { + if (url == null) return; + launchUrl(Uri.parse(url)); + }, + style: { + 'img': Style(display: Display.none), + 'body': Style( + height: Height.auto(), + margin: Margins.zero, + padding: HtmlPaddings.zero, + textOverflow: TextOverflow.ellipsis, + maxLines: 4, + textAlign: TextAlign.center, + fontSize: FontSize( + descriptionStyle?.fontSize ?? 10, ), + fontWeight: descriptionStyle?.fontWeight, + fontFamily: descriptionStyle?.fontFamily, + ), + }, + ), ), ), ); } } + +class _HtmlDialog extends StatelessWidget { + const _HtmlDialog({ + required this.title, + required this.description, + required this.descriptionStyle, + }); + + final String title; + final String? description; + final TextStyle? descriptionStyle; + + @override + Widget build(BuildContext context) { + return SimpleDialog( + titlePadding: EdgeInsets.zero, + contentPadding: EdgeInsets.zero, + title: YaruDialogTitleBar( + title: Text(title), + backgroundColor: Colors.transparent, + border: BorderSide.none, + ), + children: [ + SizedBox( + width: 400, + child: Html( + data: description, + onAnchorTap: (url, attributes, element) { + if (url == null) return; + launchUrl(Uri.parse(url)); + }, + style: { + 'img': Style(display: Display.none), + 'body': Style( + height: Height.auto(), + textOverflow: TextOverflow.ellipsis, + maxLines: 400, + textAlign: TextAlign.center, + fontSize: FontSize( + descriptionStyle?.fontSize ?? 10, + ), + fontWeight: descriptionStyle?.fontWeight, + fontFamily: descriptionStyle?.fontFamily, + ), + }, + ), + ), + ], + ); + } +} diff --git a/lib/common/view/theme.dart b/lib/common/view/theme.dart index 370ce6d0..44088311 100644 --- a/lib/common/view/theme.dart +++ b/lib/common/view/theme.dart @@ -170,10 +170,6 @@ double? get avatarIconSize => yaruStyled ? kYaruTitleBarItemHeight / 2 : null; double get bigPlayButtonSize => 25; -double get searchBarWidth => isMobile ? kSearchBarWidth : 600; - -bool get showSideBarFilter => yaruStyled ? true : false; - FontWeight get smallTextFontWeight => yaruStyled ? FontWeight.w100 : FontWeight.w400; @@ -183,16 +179,8 @@ FontWeight get mediumTextWeight => FontWeight get largeTextWeight => yaruStyled ? FontWeight.w200 : FontWeight.w300; -bool get shrinkTitleBarItems => yaruStyled; - double get chipHeight => 36.0; -EdgeInsetsGeometry get tabViewPadding => - isMobile ? const EdgeInsets.only(top: 15) : const EdgeInsets.only(top: 5); - -EdgeInsetsGeometry get gridPadding => - isMobile ? kMobileGridPadding : kGridPadding; - SliverGridDelegate get audioCardGridDelegate => isMobile ? kMobileAudioCardGridDelegate : kAudioCardGridDelegate; @@ -213,7 +201,3 @@ EdgeInsets get countryPillPadding => yaruStyled : const EdgeInsets.only(top: 11, bottom: 11, left: 15, right: 15); double get inputHeight => yaruStyled ? kYaruTitleBarItemHeight : 36; - -TextStyle getControlPanelStyle(TextTheme textTheme) => - textTheme.headlineSmall?.copyWith(fontWeight: largeTextWeight) ?? - const TextStyle(fontSize: 25); diff --git a/lib/local_audio/cover_store.dart b/lib/local_audio/cover_store.dart index c21b94ad..cd72e21f 100644 --- a/lib/local_audio/cover_store.dart +++ b/lib/local_audio/cover_store.dart @@ -41,6 +41,8 @@ class CoverStore { Future write() async => writeUint8ListMap(_value, kCoverStore); + // This does not make much sense except for small libs, where the store is filled + // fast anyways. Let's keep it for eventual use... Future read() async => _value = await computeIsolate(() => readUint8ListMap(kCoverStore)) ?? []; } diff --git a/lib/local_audio/local_audio_service.dart b/lib/local_audio/local_audio_service.dart index 09ad52a0..f7293497 100644 --- a/lib/local_audio/local_audio_service.dart +++ b/lib/local_audio/local_audio_service.dart @@ -230,12 +230,7 @@ class LocalAudioService { bool forceInit = false, }) async { if (forceInit == false && _audios?.isNotEmpty == true) return; - // TODO: Add a dialog for when people have X (too many) music files - // ask them to confirm that for them no local cache is being loaded and saved - // because such a cache will always be to big - if (kDebugMode && !Platform.environment.containsKey('FLUTTER_TEST')) { - await CoverStore().read(); - } + final result = await compute( _readAudiosFromDirectory, directory ?? _settingsService?.directory, @@ -249,11 +244,7 @@ class LocalAudioService { _audiosController.add(true); } - Future dispose() async { - // TODO: delete this when the setting is added - if (kDebugMode) await CoverStore().write(); - return _audiosController.close(); - } + Future dispose() async => _audiosController.close(); } FutureOr _readAudiosFromDirectory(String? directory) async { diff --git a/lib/player/view/player_remote_source_image.dart b/lib/player/view/player_remote_source_image.dart index e821e626..5a3bb0e7 100644 --- a/lib/player/view/player_remote_source_image.dart +++ b/lib/player/view/player_remote_source_image.dart @@ -52,6 +52,7 @@ class PlayerRemoteSourceImage extends StatelessWidget { ? IcyImage( mpvMetaData: mpvMetaData!, fallBackWidget: safeNetworkImage, + errorWidget: safeNetworkImage, height: height, width: width, fit: fit, diff --git a/lib/podcasts/view/podcast_page.dart b/lib/podcasts/view/podcast_page.dart index c7013b34..8ba62160 100644 --- a/lib/podcasts/view/podcast_page.dart +++ b/lib/podcasts/view/podcast_page.dart @@ -116,11 +116,14 @@ class PodcastPage extends StatelessWidget with WatchItMixin { ?.genre ?? context.l10n.podcast, subTitle: episodesWithDownloads.firstOrNull?.artist, - description: AudioPageHeaderHtmlDescription( - description: - episodesWithDownloads.firstOrNull?.albumArtist, - title: title, - ), + description: + episodesWithDownloads.firstOrNull?.albumArtist == null + ? null + : AudioPageHeaderHtmlDescription( + description: episodesWithDownloads + .firstOrNull!.albumArtist!, + title: title, + ), title: title, onLabelTab: (text) => _onGenreTap( context: context,