diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index d4e642ae8..e37a1c047 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -121,6 +121,8 @@ jobs: # with: # distribution: 'zulu' # java-version: '17' + - name: Set up Rust (for smtc_windows) + uses: hecrj/setup-rust-action@v2 - name: Set up Flutter uses: subosito/flutter-action@v2 with: diff --git a/lib/components/LanguageSelectionScreen/language_list.dart b/lib/components/LanguageSelectionScreen/language_list.dart index ff91f64c0..3e7b02a39 100644 --- a/lib/components/LanguageSelectionScreen/language_list.dart +++ b/lib/components/LanguageSelectionScreen/language_list.dart @@ -67,19 +67,20 @@ class LanguageListTile extends StatelessWidget { this.locale, }); - final Locale? locale; + final Locale? locale; // null if system language @override Widget build(BuildContext context) { return RadioListTile( title: Text(locale?.nativeDisplayLanguage ?? AppLocalizations.of(context)!.system), - subtitle: locale == null - ? null - : Text((LocaleHelper.locale == null - ? locale!.defaultDisplayLanguage - : locale!.displayLanguageIn(LocaleHelper.locale!)) ?? - "???"), + subtitle: locale != null + ? Text( + LocaleHelper.locale != null + ? locale!.displayLanguageIn(LocaleHelper.locale!) + : locale!.defaultDisplayLanguage, + ) + : null, value: locale, groupValue: LocaleHelper.locale, onChanged: (_) { diff --git a/lib/components/LoginScreen/login_flow.dart b/lib/components/LoginScreen/login_flow.dart index 4b5dd9da7..8fcdc89c2 100644 --- a/lib/components/LoginScreen/login_flow.dart +++ b/lib/components/LoginScreen/login_flow.dart @@ -270,21 +270,25 @@ class ConnectionState { class JellyfinServerClientDiscovery { static final _clientDiscoveryLogger = Logger("JellyfinServerClientDiscovery"); - late RawDatagramSocket socket; - bool isDisposed = false; + RawDatagramSocket? _socket; + bool _isDisposed = false; void discoverServers( void Function(ClientDiscoveryResponse response) onServerFound) async { - isDisposed = false; + _isDisposed = false; - socket = await RawDatagramSocket.bind(InternetAddress.anyIPv4, 0); - socket.broadcastEnabled = + _socket = await RawDatagramSocket.bind(InternetAddress.anyIPv4, 0); + + // We have to use ? throughout since _socket isn't final, although at this + // point in the code it should never be null + + _socket?.broadcastEnabled = true; // important to allow sending to broadcast address - socket.multicastHops = 5; // to account for weird network setups + _socket?.multicastHops = 5; // to account for weird network setups - socket.listen((event) { + _socket?.listen((event) { if (event == RawSocketEvent.read) { - final datagram = socket.receive(); + final datagram = _socket?.receive(); if (datagram != null) { _clientDiscoveryLogger .finest("Received datagram: ${utf8.decode(datagram.data)}"); @@ -305,16 +309,16 @@ class JellyfinServerClientDiscovery { _clientDiscoveryLogger.fine("Sending discovery messages"); - socket.send(message.codeUnits, broadcastAddress, destinationPort); + _socket?.send(message.codeUnits, broadcastAddress, destinationPort); - while (!isDisposed) { + while (!_isDisposed) { await Future.delayed(const Duration(milliseconds: 1500)); - socket.send(message.codeUnits, broadcastAddress, destinationPort); + _socket?.send(message.codeUnits, broadcastAddress, destinationPort); } } void dispose() { - isDisposed = true; - socket.close(); + _isDisposed = true; + _socket?.close(); } } diff --git a/lib/components/PlaybackHistoryScreen/playback_history_list.dart b/lib/components/PlaybackHistoryScreen/playback_history_list.dart index b5259cea9..cc0dd3792 100644 --- a/lib/components/PlaybackHistoryScreen/playback_history_list.dart +++ b/lib/components/PlaybackHistoryScreen/playback_history_list.dart @@ -4,16 +4,15 @@ import 'package:finamp/services/audio_service_helper.dart'; import 'package:finamp/services/locale_helper.dart'; import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; -import 'package:intl/date_symbol_data_local.dart'; import 'package:get_it/get_it.dart'; import 'package:intl/intl.dart'; -import '../../services/playback_history_service.dart'; import '../../models/jellyfin_models.dart' as jellyfin_models; +import '../../services/playback_history_service.dart'; import 'playback_history_list_tile.dart'; class PlaybackHistoryList extends StatelessWidget { - const PlaybackHistoryList({Key? key}) : super(key: key); + const PlaybackHistoryList({super.key}); @override Widget build(BuildContext context) { @@ -28,13 +27,9 @@ class PlaybackHistoryList extends StatelessWidget { builder: (context, snapshot) { if (snapshot.hasData) { history = snapshot.data; - // groupedHistory = playbackHistoryService.getHistoryGroupedByDate(); - // groupedHistory = playbackHistoryService.getHistoryGroupedByHour(); groupedHistory = playbackHistoryService.getHistoryGroupedDynamically(); - print(groupedHistory); - return CustomScrollView( // use nested SliverList.builder()s to show history items grouped by date slivers: groupedHistory.map((group) { @@ -73,11 +68,7 @@ class PlaybackHistoryList extends StatelessWidget { ); final now = DateTime.now(); - final String localeString = (LocaleHelper.locale != null) - ? ((LocaleHelper.locale?.countryCode != null) - ? "${LocaleHelper.locale?.languageCode.toLowerCase()}_${LocaleHelper.locale?.countryCode?.toUpperCase()}" - : LocaleHelper.locale.toString()) - : "en_US"; + final String? localeString = LocaleHelper.localeString; return index == 0 ? Column( diff --git a/lib/components/PlayerScreen/artist_chip.g.dart b/lib/components/PlayerScreen/artist_chip.g.dart index b023dc96a..46a95db06 100644 --- a/lib/components/PlayerScreen/artist_chip.g.dart +++ b/lib/components/PlayerScreen/artist_chip.g.dart @@ -142,6 +142,8 @@ class ArtistItemProvider extends AutoDisposeFutureProvider { } } +@Deprecated('Will be removed in 3.0. Use Ref instead') +// ignore: unused_element mixin ArtistItemRef on AutoDisposeFutureProviderRef { /// The parameter `id` of this provider. String get id; @@ -155,4 +157,4 @@ class _ArtistItemProviderElement String get id => (origin as ArtistItemProvider).id; } // ignore_for_file: type=lint -// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member +// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member, deprecated_member_use_from_same_package diff --git a/lib/components/PlayerScreen/feature_chips.dart b/lib/components/PlayerScreen/feature_chips.dart index 29ef8a8e7..3347fa7da 100644 --- a/lib/components/PlayerScreen/feature_chips.dart +++ b/lib/components/PlayerScreen/feature_chips.dart @@ -30,6 +30,9 @@ class FeatureState { final FinampSettings settings; final MetadataProvider? metadata; + FinampFeatureChipsConfiguration get configuration => + settings.featureChipsConfiguration; + bool get isDownloaded => metadata?.isDownloaded ?? false; bool get isTranscoding => !isDownloaded && (currentTrack?.item.extras?["shouldTranscode"] ?? false); @@ -63,102 +66,124 @@ class FeatureState { ), ); } + + for (var feature in configuration.features) { - // TODO this will likely be extremely outdated if offline, hide? - if (currentTrack?.baseItem?.userData?.playCount != null) { - features.add( - FeatureProperties( - text: AppLocalizations.of(context)! - .playCountValue(currentTrack!.baseItem!.userData?.playCount ?? 0), - ), - ); - } - - if (currentTrack?.baseItem?.people?.isNotEmpty ?? false) { - currentTrack?.baseItem?.people?.forEach((person) { - features.add( - FeatureProperties( - text: "${person.role}: ${person.name}", - ), - ); - }); - } - - if (currentTrack?.item.extras?["downloadedSongPath"] != null) { - features.add( - FeatureProperties( - text: AppLocalizations.of(context)!.playbackModeLocal, - ), - ); - } else { - if (isTranscoding) { + // TODO this will likely be extremely outdated if offline, hide? + if (feature == FinampFeatureChipType.playCount && + currentTrack?.baseItem?.userData?.playCount != null) { features.add( FeatureProperties( - text: AppLocalizations.of(context)!.playbackModeTranscoding, - ), - ); - } else { - features.add( - //TODO differentiate between direct streaming and direct playing - // const FeatureProperties( - // text: "Direct Streaming", - // ), - FeatureProperties( - text: AppLocalizations.of(context)!.playbackModeDirectPlaying, + type: feature, + text: AppLocalizations.of(context)!.playCountValue( + currentTrack!.baseItem!.userData?.playCount ?? 0), ), ); } - } - if (metadata?.mediaSourceInfo != null) { - if (bitrate != null) { - features.add( - FeatureProperties( - text: - "${container.toUpperCase()} @ ${AppLocalizations.of(context)!.kiloBitsPerSecondLabel(bitrate! ~/ 1000)}", - ), - ); + if (feature == FinampFeatureChipType.additionalPeople && + (currentTrack?.baseItem?.people?.isNotEmpty ?? false)) { + currentTrack?.baseItem?.people?.forEach((person) { + features.add( + FeatureProperties( + type: feature, + text: "${person.role}: ${person.name}", + ), + ); + }); } - if (bitDepth != null) { - features.add( - FeatureProperties( - text: AppLocalizations.of(context)!.numberAsBit(bitDepth!), - ), - ); + if (feature == FinampFeatureChipType.playbackMode) { + if (currentTrack?.item.extras?["downloadedSongPath"] != null) { + features.add( + FeatureProperties( + type: feature, + text: AppLocalizations.of(context)!.playbackModeLocal, + ), + ); + } else { + if (isTranscoding) { + features.add( + FeatureProperties( + type: feature, + text: AppLocalizations.of(context)!.playbackModeTranscoding, + ), + ); + } else { + features.add( + //TODO differentiate between direct streaming and direct playing + // const FeatureProperties( + // text: "Direct Streaming", + // ), + FeatureProperties( + type: feature, + text: AppLocalizations.of(context)!.playbackModeDirectPlaying, + ), + ); + } + } } - if (sampleRate != null) { - features.add( - FeatureProperties( - text: AppLocalizations.of(context)! - .numberAsKiloHertz(sampleRate! / 1000.0), - ), - ); + if (metadata?.mediaSourceInfo != null) { + if (feature == FinampFeatureChipType.codec || + feature == FinampFeatureChipType.bitRate) { + // only add this feature the first time + if (!features.any((f) => f.type == FinampFeatureChipType.codec)) { + features.add( + FeatureProperties( + type: feature, + text: + "${configuration.features.contains(FinampFeatureChipType.codec) ? container.toUpperCase() : ""}${configuration.features.contains(FinampFeatureChipType.codec) && configuration.features.contains(FinampFeatureChipType.bitRate) ? " @ " : ""}${configuration.features.contains(FinampFeatureChipType.bitRate) && bitrate != null ? AppLocalizations.of(context)!.kiloBitsPerSecondLabel(bitrate! ~/ 1000) : ""}", + ), + ); + } + } + + if (feature == FinampFeatureChipType.bitDepth && bitDepth != null) { + features.add( + FeatureProperties( + type: feature, + text: AppLocalizations.of(context)!.numberAsBit(bitDepth!), + ), + ); + } + + if (feature == FinampFeatureChipType.sampleRate && sampleRate != null) { + features.add( + FeatureProperties( + type: feature, + text: AppLocalizations.of(context)! + .numberAsKiloHertz(sampleRate! / 1000.0), + ), + ); + } + + if (feature == FinampFeatureChipType.size && size != null) { + features.add( + FeatureProperties( + type: feature, + text: FileSize.getSize(size), + ), + ); + } } - if (size != null) { - features.add( - FeatureProperties( - text: FileSize.getSize(size), - ), - ); + if (feature == FinampFeatureChipType.normalizationGain && + FinampSettingsHelper.finampSettings.volumeNormalizationActive) { + double? effectiveGainChange = + getEffectiveGainChange(currentTrack!.item, currentTrack!.baseItem); + if (effectiveGainChange != null) { + features.add( + FeatureProperties( + type: feature, + text: AppLocalizations.of(context)!.numberAsDecibel( + double.parse(effectiveGainChange.toStringAsFixed(1))), + ), + ); + } } - } - if (FinampSettingsHelper.finampSettings.volumeNormalizationActive) { - double? effectiveGainChange = - getEffectiveGainChange(currentTrack!.item, currentTrack!.baseItem); - if (effectiveGainChange != null) { - features.add( - FeatureProperties( - text: AppLocalizations.of(context)!.numberAsDecibel( - double.parse(effectiveGainChange.toStringAsFixed(1))), - ), - ); - } } - return features; } } @@ -166,9 +191,11 @@ class FeatureState { class FeatureProperties { const FeatureProperties({ required this.text, + this.type, }); final String text; + final FinampFeatureChipType? type; } class FeatureChips extends ConsumerWidget { diff --git a/lib/components/PlayerScreen/progress_slider.dart b/lib/components/PlayerScreen/progress_slider.dart index 1f697dec4..29ba26448 100644 --- a/lib/components/PlayerScreen/progress_slider.dart +++ b/lib/components/PlayerScreen/progress_slider.dart @@ -226,9 +226,10 @@ class __PlaybackProgressSliderState min: 0.0, max: widget.mediaItem?.duration == null ? widget.playbackState.bufferedPosition.inMicroseconds.toDouble() - : widget.mediaItem!.duration!.inMicroseconds.toDouble(), + : widget.mediaItem?.duration?.inMicroseconds.toDouble() ?? 0, value: (_dragValue ?? widget.position.inMicroseconds) - .clamp(0, widget.mediaItem!.duration!.inMicroseconds.toDouble()) + .clamp( + 0, widget.mediaItem?.duration?.inMicroseconds.toDouble() ?? 0) .toDouble(), semanticFormatterCallback: (double value) { final positionFullMinutes = @@ -254,9 +255,9 @@ class __PlaybackProgressSliderState ? widget.playbackState.bufferedPosition.inMicroseconds .clamp( 0.0, - widget.mediaItem!.duration == null + widget.mediaItem?.duration == null ? widget.playbackState.bufferedPosition.inMicroseconds - : widget.mediaItem!.duration!.inMicroseconds, + : widget.mediaItem?.duration?.inMicroseconds ?? 0, ) .toDouble() : 0, diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index cad9562fd..6aaf8d0c7 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -385,7 +385,7 @@ } }, "offlineSongCountArtist": "{count,plural,=1{{count} Track} other{{count} Tracks}} Downloaded", - "@offlineSongCountArtis": { + "@offlineSongCountArtist": { "placeholders": { "count": { "type": "int" @@ -507,7 +507,7 @@ "@playbackSpeedControlSettingSubtitle": { "description": "Subtitle for the playback speed visibility setting" }, - "playbackSpeedControlSettingDescription": "Automatic:\nFinamp tries to identify whether the track you are playing is a podcast or (part of) an audiobook. This is considered to be the case if the track is longer than {trackDuration} minutes, if the track's album is longer than {albumDuration} hours, or if the track has at least one of these genres assigned: {genreList}\nPlayback speed controls will then be shown in the player screen menu.\n\nShown:\nThe playback speed controls will always be shown in the player screen menu.\n\nHidden:\nThe playback speed controls in the player screen menu are always hidden.", + "playbackSpeedControlSettingDescription": "Automatic:\nFinamp tries to identify whether the track you are playing is a podcast or (part of) an audiobook. This is considered to be the case if the track is longer than {trackDuration} minutes, if the track''s album is longer than {albumDuration} hours, or if the track has at least one of these genres assigned: {genreList}\nPlayback speed controls will then be shown in the player screen menu.\n\nShown:\nThe playback speed controls will always be shown in the player screen menu.\n\nHidden:\nThe playback speed controls in the player screen menu are always hidden.", "@playbackSpeedControlSettingDescription": { "description": "Description for the dropdown that selects the replay gain mode, shown in a dialog that opens when the user presses the info icon next to the dropdown", "placeholders": { @@ -1070,14 +1070,20 @@ "@periodicPlaybackSessionUpdateFrequencySubtitle": { "description": "Description of the setting that controls how frequently (in seconds) the current playback session is reported to the Jellyfin server" }, -"periodicPlaybackSessionUpdateFrequencyDetails": "If the Jellyfin server hasn't received any updates from a client in the last 5 minutes, it assumes that playback has ended. This means that for tracks longer than 5 minutes, that playback could be incorrectly reported as having ended, which reduced the quality of the playback reporting data.", + "periodicPlaybackSessionUpdateFrequencyDetails": "If the Jellyfin server hasn''t received any updates from a client in the last 5 minutes, it assumes that playback has ended. This means that for tracks longer than 5 minutes, that playback could be incorrectly reported as having ended, which reduced the quality of the playback reporting data.", "@periodicPlaybackSessionUpdateFrequencyDetails": { "description": "Additional details for the setting that controls how frequently (in seconds) the current playback session is reported to the Jellyfin server" }, "topSongs": "Top Tracks", "@topSongs": {}, "albumCount": "{count,plural,=1{{count} Album} other{{count} Albums}}", - "@albumCount": {}, + "@albumCount": { + "placeholders": { + "count": { + "type": "int" + } + } + }, "shuffleAlbums": "Shuffle Albums", "@shuffleAlbums": { "description": "Label for action that shuffles all albums of an artist or genre" @@ -1103,8 +1109,14 @@ } } }, - "couldNotLoad": "Couldn't load {source, select, album{album} playlist{playlist} songMix{track mix} artistMix{artist mix} albumMix{album mix} genreMix{genre mix} favorites{favorites} allSongs{all tracks} filteredList{tracks} genre{genre} artist{artist} song{track} nextUpAlbum{album in next up} nextUpPlaylist{playlist in next up} nextUpArtist{artist in next up} other{}}", - "@couldNotLoad": {}, + "couldNotLoad": "Couldn''t load {source, select, album{album} playlist{playlist} songMix{track mix} artistMix{artist mix} albumMix{album mix} genreMix{genre mix} favorites{favorites} allSongs{all tracks} filteredList{tracks} genre{genre} artist{artist} song{track} nextUpAlbum{album in next up} nextUpPlaylist{playlist in next up} nextUpArtist{artist in next up} other{}}", + "@couldNotLoad": { + "placeholders": { + "source": { + "type": "String" + } + } + }, "confirm": "Confirm", "close": "Close", "showUncensoredLogMessage": "This log contains your login information. Show?", @@ -1137,7 +1149,7 @@ "@volumeNormalizationModeSelectorSubtitle": { "description": "Subtitle for the dropdown that selects the replay gain mode" }, - "volumeNormalizationModeSelectorDescription": "Hybrid (Track + Album):\nTrack gain is used for regular playback, but if an album is playing (either because it's the main playback queue source, or because it was added to the queue at some point), the album gain is used instead.\n\nTrack-based:\nTrack gain is always used, regardless of whether an album is playing or not.\n\nAlbums Only:\nVolume Normalization is only applied while playing albums (using the album gain), but not for individual tracks.", + "volumeNormalizationModeSelectorDescription": "Hybrid (Track + Album):\nTrack gain is used for regular playback, but if an album is playing (either because it''s the main playback queue source, or because it was added to the queue at some point), the album gain is used instead.\n\nTrack-based:\nTrack gain is always used, regardless of whether an album is playing or not.\n\nAlbums Only:\nVolume Normalization is only applied while playing albums (using the album gain), but not for individual tracks.", "@volumeNormalizationModeSelectorDescription": { "description": "Description for the dropdown that selects the replay gain mode, shown in a dialog that opens when the user presses the info icon next to the dropdown" }, @@ -1161,7 +1173,7 @@ "@volumeNormalizationIOSBaseGainEditorTitle": { "description": "Title for the input that sets the replay gain base gain on iOS and other non-Android platforms" }, - "volumeNormalizationIOSBaseGainEditorSubtitle": "Currently, Volume Normalization on iOS requires changing the playback volume to emulate the gain change. Since we can't increase the volume above 100%, we need to decrease the volume by default so that we can boost the volume of quiet tracks. The value is in decibels (dB), where -10 dB is ~30% volume, -4.5 dB is ~60% volume and -2 dB is ~80% volume.", + "volumeNormalizationIOSBaseGainEditorSubtitle": "Currently, Volume Normalization on iOS requires changing the playback volume to emulate the gain change. Since we can''t increase the volume above 100%, we need to decrease the volume by default so that we can boost the volume of quiet tracks. The value is in decibels (dB), where -10 dB is ~30% volume, -4.5 dB is ~60% volume and -2 dB is ~80% volume.", "@volumeNormalizationIOSBaseGainEditorSubtitle": { "description": "Subtitle for the input that sets the replay gain base gain on iOS and other non-Android platforms" }, @@ -1190,7 +1202,7 @@ "description": "Option to download item in long-press menu." }, "deleteItem": "Delete from device", - "@deletedItem": { + "@deleteItem": { "description": "Option to delete item in long-press menu." }, "repairComplete": "Downloads Repair complete.", @@ -1222,7 +1234,7 @@ } } }, - "activeDownloadsListHeader": "{itemCount} {typeName, select, downloading{Running} failed{Failed} syncFailed{Repeatedly Unsynced} enqueued{Queued} other{}} {itemCount, plural, =1{Download} other{Downloads}}}", + "activeDownloadsListHeader": "{itemCount} {typeName, select, downloading{Running} failed{Failed} syncFailed{Repeatedly Unsynced} enqueued{Queued} other{}} {itemCount, plural, =1{Download} other{Downloads}}", "@activeDownloadsListHeader": { "description": "Header text for lists of active downloads of a particular state.", "placeholders": { @@ -1234,7 +1246,7 @@ } } }, - "downloadLibraryPrompt": "Are you sure you want to download all contents of the library '{ libraryName }'?", + "downloadLibraryPrompt": "Are you sure you want to download all contents of the library ''{libraryName}''?", "@downloadLibraryPrompt": { "description": "Confirmation prompt before downloading entire library, which may be large.", "placeholders": { @@ -1297,7 +1309,7 @@ "@maxConcurrentDownloadsSubtitle": { "description": "Description of setting controlling max concurrent downloads." }, - "maxConcurrentDownloadsLabel": "{ count} Concurrent Downloads", + "maxConcurrentDownloadsLabel": "{count} Concurrent Downloads", "@maxConcurrentDownloadsLabel": { "description": "Label of values on max concurrent downloads slider", "placeholders": { @@ -1314,7 +1326,7 @@ "@downloadsWorkersSettingSubtitle": { "description": "Description of setting controlling download worker count." }, - "downloadsWorkersSettingLabel": "{ count} Download Workers", + "downloadsWorkersSettingLabel": "{count} Download Workers", "@downloadsWorkersSettingLabel": { "description": "Label of values on download worker count slider", "placeholders": { @@ -1721,5 +1733,45 @@ "nowPlayingBarTooltip": "Open Player Screen", "@nowPlayingBarTooltip": { "description": "Tooltip for the now playing bar at the bottom of the screen" + }, + "additionalPeople": "People", + "@additionalPeople": { + "description": "Label for the feature chips showing additional people in the credits of a track or album" + }, + "playbackMode": "Playback Mode", + "@playbackMode": { + "description": "Label for the feature chips showing the playback mode of a track. See [playbackModeLocal], [playbackModeDirectPlaying], and [playbackModeTranscoding]" + }, + "codec": "Codec", + "@codec": { + "description": "Label for the feature chips showing the codec of a track" + }, + "bitRate": "Bit Rate", + "@bitRate": { + "description": "Label for the feature chips showing the bit rate of a track" + }, + "bitDepth": "Bit Depth", + "@bitDepth": { + "description": "Label for the feature chips showing the bit depth of a track" + }, + "size": "Size", + "@size": { + "description": "Label for the feature chips showing the size (original file size or transcoded size, if available) of a track" + }, + "normalizationGain": "Gain", + "@normalizationGain": { + "description": "Label for the feature chips showing the normalization gain / LUFS offset of a track" + }, + "sampleRate": "Sample Rate", + "@sampleRate": { + "description": "Label for the feature chips showing the sample rate of a track" + }, + "showFeatureChipsToggleTitle": "Show Advanced Track Info", + "@showFeatureChipsToggleTitle": { + "description": "Title for the setting that controls if the feature chips showing advanced track info are shown on the player screen" + }, + "showFeatureChipsToggleSubtitle": "Show advanced track info like codec, bit rate, and more on the player screen.", + "@showFeatureChipsToggleSubtitle": { + "description": "Subtitle for the setting that controls if the feature chips showing advanced track info are shown on the player screen" } } diff --git a/lib/main.dart b/lib/main.dart index da46ca791..1fdb2af9b 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,6 +1,9 @@ import 'dart:async'; import 'dart:io'; +import 'package:audio_service/audio_service.dart'; +import 'package:audio_session/audio_session.dart'; +import 'package:background_downloader/background_downloader.dart'; import 'package:finamp/color_schemes.g.dart'; import 'package:finamp/gen/assets.gen.dart'; import 'package:finamp/screens/downloads_settings_screen.dart'; @@ -21,9 +24,6 @@ import 'package:finamp/services/offline_listen_helper.dart'; import 'package:finamp/services/playback_history_service.dart'; import 'package:finamp/services/queue_service.dart'; import 'package:finamp/services/theme_provider.dart'; -import 'package:audio_service/audio_service.dart'; -import 'package:audio_session/audio_session.dart'; -import 'package:background_downloader/background_downloader.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; @@ -32,12 +32,13 @@ import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:get_it/get_it.dart'; import 'package:hive_flutter/hive_flutter.dart'; import 'package:intl/date_symbol_data_local.dart'; +import 'package:intl/intl_standalone.dart'; import 'package:isar/isar.dart'; import 'package:logging/logging.dart'; +import 'package:path/path.dart' as path_helper; import 'package:path_provider/path_provider.dart'; import 'package:uuid/uuid.dart'; import 'package:window_manager/window_manager.dart'; -import 'package:path/path.dart' as path_helper; import 'components/LogsScreen/copy_logs_button.dart'; import 'components/LogsScreen/share_logs_button.dart'; @@ -111,12 +112,8 @@ void main() async { SystemChrome.setSystemUIOverlayStyle( const SystemUiOverlayStyle(statusBarBrightness: Brightness.dark)); - final String localeString = (LocaleHelper.locale != null) - ? ((LocaleHelper.locale?.countryCode != null) - ? "${LocaleHelper.locale?.languageCode.toLowerCase()}_${LocaleHelper.locale?.countryCode?.toUpperCase()}" - : LocaleHelper.locale.toString()) - : "en_US"; - await initializeDateFormatting(localeString, null); + await findSystemLocale(); + await initializeDateFormatting(); runApp(const Finamp()); } @@ -222,6 +219,8 @@ Future setupHive() async { Hive.registerAdapter(LyricsFontSizeAdapter()); Hive.registerAdapter(KeepScreenOnOptionAdapter()); Hive.registerAdapter(FinampSegmentContainerAdapter()); + Hive.registerAdapter(FinampFeatureChipsConfigurationAdapter()); + Hive.registerAdapter(FinampFeatureChipTypeAdapter()); final dir = (Platform.isAndroid || Platform.isIOS) ? await getApplicationDocumentsDirectory() @@ -318,8 +317,8 @@ Future _setupPlaybackServices() async { // notificationColor: TODO use the theme color for older versions of Android, preloadArtwork: false, androidBrowsableRootExtras: { - "android.media.browse.SEARCH_SUPPORTED": - true, // support showing search button on Android Auto as well as alternative search results on the player screen after voice search + // support showing search button on Android Auto as well as alternative search results on the player screen after voice search + "android.media.browse.SEARCH_SUPPORTED": true, // see https://developer.android.com/reference/androidx/media/utils/MediaConstants#DESCRIPTION_EXTRAS_VALUE_CONTENT_STYLE_GRID_ITEM() "android.media.browse.CONTENT_STYLE_BROWSABLE_HINT": FinampSettingsHelper.finampSettings.contentViewType == @@ -333,8 +332,6 @@ Future _setupPlaybackServices() async { : 2, }), ); - // GetIt.instance.registerSingletonAsync( - // () async => ); GetIt.instance.registerSingleton(audioHandler); GetIt.instance.registerSingleton(QueueService()); diff --git a/lib/models/finamp_models.dart b/lib/models/finamp_models.dart index 16667d7e2..2d78ebbcb 100644 --- a/lib/models/finamp_models.dart +++ b/lib/models/finamp_models.dart @@ -115,6 +115,18 @@ const _keepScreenOnOption = KeepScreenOnOption.whileLyrics; const _keepScreenOnWhilePluggedIn = true; const _defaultTranscodingSegmentContainer = FinampSegmentContainer.fragmentedMp4; +const _featureChipsConfigurationDefault = + FinampFeatureChipsConfiguration(enabled: true, features: [ + FinampFeatureChipType.playCount, + FinampFeatureChipType.additionalPeople, + FinampFeatureChipType.playbackMode, + FinampFeatureChipType.codec, + FinampFeatureChipType.bitRate, + FinampFeatureChipType.bitDepth, + FinampFeatureChipType.sampleRate, + FinampFeatureChipType.size, + FinampFeatureChipType.normalizationGain, +]); @HiveType(typeId: 28) class FinampSettings { @@ -198,9 +210,9 @@ class FinampSettings { this.showSeekControlsOnMediaNotification = _showSeekControlsOnMediaNotificationDefault, this.keepScreenOnOption = _keepScreenOnOption, - this.keepScreenOnWhilePluggedIn = _keepScreenOnWhilePluggedIn, - this.transcodingSegmentContainer = _defaultTranscodingSegmentContainer, - }); + this.keepScreenOnWhilePluggedIn = _keepScreenOnWhilePluggedIn, + this.transcodingSegmentContainer = _defaultTranscodingSegmentContainer, + this.featureChipsConfiguration = _featureChipsConfigurationDefault}); @HiveField(0, defaultValue: _isOfflineDefault) bool isOffline; @@ -440,6 +452,9 @@ class FinampSettings { @HiveField(74, defaultValue: _defaultTranscodingSegmentContainer) FinampSegmentContainer transcodingSegmentContainer; + @HiveField(75, defaultValue: _featureChipsConfigurationDefault) + FinampFeatureChipsConfiguration featureChipsConfiguration; + static Future create() async { final downloadLocation = await DownloadLocation.create( name: "Internal Storage", @@ -2242,7 +2257,6 @@ enum KeepScreenOnOption { } } - @HiveType(typeId: 73) enum FinampSegmentContainer { @HiveField(0) @@ -2255,3 +2269,117 @@ enum FinampSegmentContainer { /// The container to use to transport the segments final String container; } + +@HiveType(typeId: 74) +enum FinampFeatureChipType { + @HiveField(0) + playCount, + @HiveField(1) + additionalPeople, + @HiveField(2) + playbackMode, + @HiveField(3) + codec, + @HiveField(4) + bitRate, + @HiveField(5) + bitDepth, + @HiveField(6) + size, + @HiveField(7) + normalizationGain, + @HiveField(8) + sampleRate; + + /// Human-readable version of the [FinampFeatureChipType] + @override + @Deprecated("Use toLocalisedString when possible") + String toString() => _humanReadableName(this); + + String toLocalisedString(BuildContext context) => + _humanReadableLocalisedName(this, context); + + String _humanReadableName(FinampFeatureChipType featureChipType) { + switch (featureChipType) { + case FinampFeatureChipType.playCount: + return "Play Count"; + case FinampFeatureChipType.additionalPeople: + return "Additional People"; + case FinampFeatureChipType.playbackMode: + return "Playback Mode"; + case FinampFeatureChipType.codec: + return "codec"; + case FinampFeatureChipType.bitRate: + return "Bit Rate"; + case FinampFeatureChipType.bitDepth: + return "Bit Depth"; + case FinampFeatureChipType.size: + return "size"; + case FinampFeatureChipType.normalizationGain: + return "Normalization Gain"; + case FinampFeatureChipType.sampleRate: + return "Sample Rate"; + } + } + + String _humanReadableLocalisedName( + FinampFeatureChipType featureChipType, BuildContext context) { + switch (featureChipType) { + case FinampFeatureChipType.playCount: + return AppLocalizations.of(context)!.playCount; + case FinampFeatureChipType.additionalPeople: + return AppLocalizations.of(context)!.additionalPeople; + case FinampFeatureChipType.playbackMode: + return AppLocalizations.of(context)!.playbackMode; + case FinampFeatureChipType.codec: + return AppLocalizations.of(context)!.codec; + case FinampFeatureChipType.bitRate: + return AppLocalizations.of(context)!.bitRate; + case FinampFeatureChipType.bitDepth: + return AppLocalizations.of(context)!.bitDepth; + case FinampFeatureChipType.size: + return AppLocalizations.of(context)!.size; + case FinampFeatureChipType.normalizationGain: + return AppLocalizations.of(context)!.normalizationGain; + case FinampFeatureChipType.sampleRate: + return AppLocalizations.of(context)!.sampleRate; + } + } +} + +@JsonSerializable() +@HiveType(typeId: 75) +class FinampFeatureChipsConfiguration { + const FinampFeatureChipsConfiguration({ + required this.enabled, + required this.features, + }); + + @HiveField(0) + final bool enabled; + + @HiveField(1) + final List features; + + factory FinampFeatureChipsConfiguration.fromJson(Map json) => + _$FinampFeatureChipsConfigurationFromJson(json); + + Map toJson() => + _$FinampFeatureChipsConfigurationToJson(this); + + @override + String toString() { + return jsonEncode(toJson()); + } + + // implement copyWith + FinampFeatureChipsConfiguration copyWith({ + bool? enabled, + List? features, + }) { + return FinampFeatureChipsConfiguration( + enabled: enabled ?? this.enabled, + features: features ?? this.features, + ); + } +} diff --git a/lib/models/finamp_models.g.dart b/lib/models/finamp_models.g.dart index b2f922687..5d98677cd 100644 --- a/lib/models/finamp_models.g.dart +++ b/lib/models/finamp_models.g.dart @@ -188,6 +188,19 @@ class FinampSettingsAdapter extends TypeAdapter { transcodingSegmentContainer: fields[74] == null ? FinampSegmentContainer.fragmentedMp4 : fields[74] as FinampSegmentContainer, + featureChipsConfiguration: fields[75] == null + ? const FinampFeatureChipsConfiguration(enabled: true, features: [ + FinampFeatureChipType.playCount, + FinampFeatureChipType.additionalPeople, + FinampFeatureChipType.playbackMode, + FinampFeatureChipType.codec, + FinampFeatureChipType.bitRate, + FinampFeatureChipType.bitDepth, + FinampFeatureChipType.sampleRate, + FinampFeatureChipType.size, + FinampFeatureChipType.normalizationGain + ]) + : fields[75] as FinampFeatureChipsConfiguration, ) ..disableGesture = fields[19] == null ? false : fields[19] as bool ..showFastScroller = fields[25] == null ? true : fields[25] as bool @@ -197,7 +210,7 @@ class FinampSettingsAdapter extends TypeAdapter { @override void write(BinaryWriter writer, FinampSettings obj) { writer - ..writeByte(73) + ..writeByte(74) ..writeByte(0) ..write(obj.isOffline) ..writeByte(1) @@ -343,7 +356,9 @@ class FinampSettingsAdapter extends TypeAdapter { ..writeByte(73) ..write(obj.keepScreenOnWhilePluggedIn) ..writeByte(74) - ..write(obj.transcodingSegmentContainer); + ..write(obj.transcodingSegmentContainer) + ..writeByte(75) + ..write(obj.featureChipsConfiguration); } @override @@ -965,6 +980,44 @@ class MediaItemIdAdapter extends TypeAdapter { typeId == other.typeId; } +class FinampFeatureChipsConfigurationAdapter + extends TypeAdapter { + @override + final int typeId = 75; + + @override + FinampFeatureChipsConfiguration read(BinaryReader reader) { + final numOfFields = reader.readByte(); + final fields = { + for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(), + }; + return FinampFeatureChipsConfiguration( + enabled: fields[0] as bool, + features: (fields[1] as List).cast(), + ); + } + + @override + void write(BinaryWriter writer, FinampFeatureChipsConfiguration obj) { + writer + ..writeByte(2) + ..writeByte(0) + ..write(obj.enabled) + ..writeByte(1) + ..write(obj.features); + } + + @override + int get hashCode => typeId.hashCode; + + @override + bool operator ==(Object other) => + identical(this, other) || + other is FinampFeatureChipsConfigurationAdapter && + runtimeType == other.runtimeType && + typeId == other.typeId; +} + class TabContentTypeAdapter extends TypeAdapter { @override final int typeId = 36; @@ -1923,6 +1976,80 @@ class FinampSegmentContainerAdapter typeId == other.typeId; } +class FinampFeatureChipTypeAdapter extends TypeAdapter { + @override + final int typeId = 74; + + @override + FinampFeatureChipType read(BinaryReader reader) { + switch (reader.readByte()) { + case 0: + return FinampFeatureChipType.playCount; + case 1: + return FinampFeatureChipType.additionalPeople; + case 2: + return FinampFeatureChipType.playbackMode; + case 3: + return FinampFeatureChipType.codec; + case 4: + return FinampFeatureChipType.bitRate; + case 5: + return FinampFeatureChipType.bitDepth; + case 6: + return FinampFeatureChipType.size; + case 7: + return FinampFeatureChipType.normalizationGain; + case 8: + return FinampFeatureChipType.sampleRate; + default: + return FinampFeatureChipType.playCount; + } + } + + @override + void write(BinaryWriter writer, FinampFeatureChipType obj) { + switch (obj) { + case FinampFeatureChipType.playCount: + writer.writeByte(0); + break; + case FinampFeatureChipType.additionalPeople: + writer.writeByte(1); + break; + case FinampFeatureChipType.playbackMode: + writer.writeByte(2); + break; + case FinampFeatureChipType.codec: + writer.writeByte(3); + break; + case FinampFeatureChipType.bitRate: + writer.writeByte(4); + break; + case FinampFeatureChipType.bitDepth: + writer.writeByte(5); + break; + case FinampFeatureChipType.size: + writer.writeByte(6); + break; + case FinampFeatureChipType.normalizationGain: + writer.writeByte(7); + break; + case FinampFeatureChipType.sampleRate: + writer.writeByte(8); + break; + } + } + + @override + int get hashCode => typeId.hashCode; + + @override + bool operator ==(Object other) => + identical(this, other) || + other is FinampFeatureChipTypeAdapter && + runtimeType == other.runtimeType && + typeId == other.typeId; +} + // ************************************************************************** // IsarCollectionGenerator // ************************************************************************** @@ -7009,3 +7136,33 @@ const _$MediaItemParentTypeEnumMap = { MediaItemParentType.rootCollection: 'rootCollection', MediaItemParentType.instantMix: 'instantMix', }; + +FinampFeatureChipsConfiguration _$FinampFeatureChipsConfigurationFromJson( + Map json) => + FinampFeatureChipsConfiguration( + enabled: json['enabled'] as bool, + features: (json['features'] as List) + .map((e) => $enumDecode(_$FinampFeatureChipTypeEnumMap, e)) + .toList(), + ); + +Map _$FinampFeatureChipsConfigurationToJson( + FinampFeatureChipsConfiguration instance) => + { + 'enabled': instance.enabled, + 'features': instance.features + .map((e) => _$FinampFeatureChipTypeEnumMap[e]!) + .toList(), + }; + +const _$FinampFeatureChipTypeEnumMap = { + FinampFeatureChipType.playCount: 'playCount', + FinampFeatureChipType.additionalPeople: 'additionalPeople', + FinampFeatureChipType.playbackMode: 'playbackMode', + FinampFeatureChipType.codec: 'codec', + FinampFeatureChipType.bitRate: 'bitRate', + FinampFeatureChipType.bitDepth: 'bitDepth', + FinampFeatureChipType.size: 'size', + FinampFeatureChipType.normalizationGain: 'normalizationGain', + FinampFeatureChipType.sampleRate: 'sampleRate', +}; diff --git a/lib/screens/customization_settings_screen.dart b/lib/screens/customization_settings_screen.dart index d89050353..b8797c127 100644 --- a/lib/screens/customization_settings_screen.dart +++ b/lib/screens/customization_settings_screen.dart @@ -41,6 +41,7 @@ class _CustomizationSettingsScreenState const PlaybackSpeedControlVisibilityDropdownListTile(), if (!Platform.isIOS) const ShowStopButtonOnMediaNotificationToggle(), const ShowSeekControlsOnMediaNotificationToggle(), + const ShowFeatureChipsToggle(), ], ), ); @@ -109,3 +110,36 @@ class ShowSeekControlsOnMediaNotificationToggle extends StatelessWidget { ); } } + +class ShowFeatureChipsToggle extends StatelessWidget { + const ShowFeatureChipsToggle({super.key}); + + @override + Widget build(BuildContext context) { + return ValueListenableBuilder>( + valueListenable: FinampSettingsHelper.finampSettingsListener, + builder: (context, box, child) { + bool? featureChipsEnabled = + box.get("FinampSettings")?.featureChipsConfiguration.enabled; + + return SwitchListTile.adaptive( + title: + Text(AppLocalizations.of(context)!.showFeatureChipsToggleTitle), + subtitle: Text( + AppLocalizations.of(context)!.showFeatureChipsToggleSubtitle), + value: featureChipsEnabled ?? false, + onChanged: featureChipsEnabled == null + ? null + : (value) { + FinampSettings finampSettingsTemp = + box.get("FinampSettings")!; + finampSettingsTemp.featureChipsConfiguration = + finampSettingsTemp.featureChipsConfiguration + .copyWith(enabled: value); + box.put("FinampSettings", finampSettingsTemp); + }, + ); + }, + ); + } +} diff --git a/lib/screens/music_screen.dart b/lib/screens/music_screen.dart index b97bb6e27..b3478d3de 100644 --- a/lib/screens/music_screen.dart +++ b/lib/screens/music_screen.dart @@ -1,3 +1,4 @@ +import 'dart:async'; import 'dart:io'; import 'package:finamp/services/queue_service.dart'; @@ -203,6 +204,8 @@ class _MusicScreenState extends ConsumerState _buildTabController(); } + Timer? _debounce; + return PopScope( canPop: !isSearching, onPopInvoked: (popped) { @@ -218,8 +221,22 @@ class _MusicScreenState extends ConsumerState title: isSearching ? TextField( controller: textEditingController, + autocorrect: false, // avoid autocorrect + enableSuggestions: + true, // keep suggestions which can be manually selected autofocus: true, - onChanged: (value) => setState(() { + keyboardType: TextInputType.text, + textInputAction: TextInputAction.search, + onChanged: (value) { + if (_debounce?.isActive ?? false) _debounce!.cancel(); + _debounce = + Timer(const Duration(milliseconds: 400), () { + setState(() { + searchQuery = value; + }); + }); + }, + onSubmitted: (value) => setState(() { searchQuery = value; }), decoration: InputDecoration( diff --git a/lib/screens/player_screen.dart b/lib/screens/player_screen.dart index 1f786163b..f700e01da 100644 --- a/lib/screens/player_screen.dart +++ b/lib/screens/player_screen.dart @@ -612,6 +612,10 @@ class PlayerHideableController { _visible.remove(PlayerHideable.controlsPaddingSmall); _visible.remove(PlayerHideable.controlsPaddingBig); } + if (!FinampSettingsHelper + .finampSettings.featureChipsConfiguration.enabled) { + _visible.remove(PlayerHideable.features); + } } /// If we have space for vertical padding, put 33% between control elements and diff --git a/lib/services/audio_service_smtc.dart b/lib/services/audio_service_smtc.dart index 0f576bf51..45ba15571 100644 --- a/lib/services/audio_service_smtc.dart +++ b/lib/services/audio_service_smtc.dart @@ -15,6 +15,7 @@ class AudioServiceSMTC extends AudioServicePlatform { // initialize SMTC //TODO we should call smtc.dispose() before the app is closed to prevent a background process from continuing to run // https://pub.dev/packages/flutter_window_close could be used to detect when the app is closed + await SMTCWindows.initialize(); smtc = SMTCWindows( // Which buttons to show in the OS media player config: const SMTCConfig( @@ -62,12 +63,12 @@ class AudioServiceSMTC extends AudioServicePlatform { if (request.state.playing && !smtc.enabled) { await smtc .enableSmtc() - .then((value) => smtc.setPlaybackStatus(PlaybackStatus.Playing)); + .then((value) => smtc.setPlaybackStatus(PlaybackStatus.playing)); } else { await smtc.setPosition(request.state.updatePosition); await smtc.setPlaybackStatus(request.state.playing - ? PlaybackStatus.Playing - : PlaybackStatus.Paused); + ? PlaybackStatus.playing + : PlaybackStatus.paused); await smtc.setRepeatMode(switch (request.state.repeatMode) { AudioServiceRepeatModeMessage.none => RepeatMode.none, diff --git a/lib/services/favorite_provider.g.dart b/lib/services/favorite_provider.g.dart index 55974192c..a5df6812b 100644 --- a/lib/services/favorite_provider.g.dart +++ b/lib/services/favorite_provider.g.dart @@ -155,6 +155,8 @@ class IsFavoriteProvider } } +@Deprecated('Will be removed in 3.0. Use Ref instead') +// ignore: unused_element mixin IsFavoriteRef on AutoDisposeNotifierProviderRef { /// The parameter `value` of this provider. FavoriteRequest get value; @@ -169,4 +171,4 @@ class _IsFavoriteProviderElement FavoriteRequest get value => (origin as IsFavoriteProvider).value; } // ignore_for_file: type=lint -// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member +// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member, deprecated_member_use_from_same_package diff --git a/lib/services/finamp_logs_helper.dart b/lib/services/finamp_logs_helper.dart index 157f2f31e..3d86a8a38 100644 --- a/lib/services/finamp_logs_helper.dart +++ b/lib/services/finamp_logs_helper.dart @@ -34,7 +34,7 @@ class FinampLogsHelper { var message = log.censoredMessage; if (log.stackTrace == null) { // Truncate long messages from chopper, but leave long stack traces - message = message.substring(0, min(1024, message.length)); + message = message.substring(0, min(1024 * 5, message.length)); } _logFileWriter!.writeln(message); } diff --git a/lib/services/finamp_settings_helper.g.dart b/lib/services/finamp_settings_helper.g.dart index 52790116d..ee94256fd 100644 --- a/lib/services/finamp_settings_helper.g.dart +++ b/lib/services/finamp_settings_helper.g.dart @@ -21,6 +21,8 @@ final finampSettingsProvider = allTransitiveDependencies: null, ); +@Deprecated('Will be removed in 3.0. Use Ref instead') +// ignore: unused_element typedef FinampSettingsRef = AutoDisposeStreamProviderRef; // ignore_for_file: type=lint -// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member +// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member, deprecated_member_use_from_same_package diff --git a/lib/services/locale_helper.dart b/lib/services/locale_helper.dart index 34f401d30..1f81fa52a 100644 --- a/lib/services/locale_helper.dart +++ b/lib/services/locale_helper.dart @@ -10,6 +10,15 @@ class LocaleHelper { static Locale? get locale => Hive.box(boxName).get(boxName); + static String? get localeString { + final locale = LocaleHelper.locale; + return locale != null + ? (locale.countryCode != null + ? "${locale.languageCode.toLowerCase()}_${locale.countryCode?.toUpperCase()}" + : locale.toString()) + : null; + } + static void setLocale(Locale? locale) { Hive.box(boxName).put(boxName, locale); } diff --git a/lib/services/music_player_background_task.dart b/lib/services/music_player_background_task.dart index 553c3c161..73941aa59 100644 --- a/lib/services/music_player_background_task.dart +++ b/lib/services/music_player_background_task.dart @@ -202,11 +202,14 @@ class MusicPlayerBackgroundTask extends BaseAudioHandler { } on PlayerException catch (e) { _audioServiceBackgroundTaskLogger .severe("Player error code ${e.code}: ${e.message}"); + GlobalSnackbar.error(e); } on PlayerInterruptedException catch (e) { _audioServiceBackgroundTaskLogger .warning("Player interrupted: ${e.message}"); + GlobalSnackbar.error(e); } catch (e) { _audioServiceBackgroundTaskLogger.severe("Player error ${e.toString()}"); + GlobalSnackbar.error(e); } } diff --git a/linux/flutter/generated_plugin_registrant.cc b/linux/flutter/generated_plugin_registrant.cc index 5138914fa..ce4bfd2c8 100644 --- a/linux/flutter/generated_plugin_registrant.cc +++ b/linux/flutter/generated_plugin_registrant.cc @@ -8,7 +8,7 @@ #include #include -#include +#include #include #include @@ -19,9 +19,9 @@ void fl_register_plugins(FlPluginRegistry* registry) { g_autoptr(FlPluginRegistrar) media_kit_libs_linux_registrar = fl_plugin_registry_get_registrar_for_plugin(registry, "MediaKitLibsLinuxPlugin"); media_kit_libs_linux_plugin_register_with_registrar(media_kit_libs_linux_registrar); - g_autoptr(FlPluginRegistrar) screen_retriever_registrar = - fl_plugin_registry_get_registrar_for_plugin(registry, "ScreenRetrieverPlugin"); - screen_retriever_plugin_register_with_registrar(screen_retriever_registrar); + g_autoptr(FlPluginRegistrar) screen_retriever_linux_registrar = + fl_plugin_registry_get_registrar_for_plugin(registry, "ScreenRetrieverLinuxPlugin"); + screen_retriever_linux_plugin_register_with_registrar(screen_retriever_linux_registrar); g_autoptr(FlPluginRegistrar) url_launcher_linux_registrar = fl_plugin_registry_get_registrar_for_plugin(registry, "UrlLauncherPlugin"); url_launcher_plugin_register_with_registrar(url_launcher_linux_registrar); diff --git a/linux/flutter/generated_plugins.cmake b/linux/flutter/generated_plugins.cmake index c9db8aad5..62e6ea32f 100644 --- a/linux/flutter/generated_plugins.cmake +++ b/linux/flutter/generated_plugins.cmake @@ -5,7 +5,7 @@ list(APPEND FLUTTER_PLUGIN_LIST isar_flutter_libs media_kit_libs_linux - screen_retriever + screen_retriever_linux url_launcher_linux window_manager ) diff --git a/macos/Podfile.lock b/macos/Podfile.lock index c40c5a8e4..0ef2d098d 100644 --- a/macos/Podfile.lock +++ b/macos/Podfile.lock @@ -99,7 +99,7 @@ SPEC CHECKSUMS: screen_retriever: 59634572a57080243dd1bf715e55b6c54f241a38 share_plus: 36537c04ce0c3e3f5bd297ce4318b6d5ee5fd6cf sqflite: 673a0e54cc04b7d6dba8d24fb8095b31c3a99eec - url_launcher_macos: 5f437abeda8c85500ceb03f5c1938a8c5a705399 + url_launcher_macos: c82c93949963e55b228a30115bd219499a6fe404 wakelock_plus: 4783562c9a43d209c458cb9b30692134af456269 window_manager: 3a1844359a6295ab1e47659b1a777e36773cd6e8 diff --git a/pubspec.lock b/pubspec.lock index d640da1ca..3f668f3d0 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -15,7 +15,7 @@ packages: source: sdk version: "0.3.2" analyzer: - dependency: transitive + dependency: "direct overridden" description: name: analyzer sha256: b652861553cd3990d8ed361f7979dc6d7053a9ac8843fa73820ab68ce5410139 @@ -34,10 +34,10 @@ packages: dependency: "direct main" description: name: app_set_id - sha256: "455b04bc03fd9b1b66a50bbca74278d973ac4e6f2c03d5dd4707bb071613a7e5" + sha256: "362d61e013f400666c6e0f57d56ab9d32505e011e4ca4dfb779fd80c9d9505b0" url: "https://pub.dev" source: hosted - version: "1.2.0" + version: "1.2.1" archive: dependency: transitive description: @@ -114,10 +114,10 @@ packages: dependency: "direct main" description: name: background_downloader - sha256: "6b73fa5d20c47e855f6ef3ed6fb3e0d164141d8ae7d43ca0a42c78f90eaa15e7" + sha256: "91448c0fcb41af14ede14485c33b8ca684fcd6c0ac0a439be9f83fa964753e13" url: "https://pub.dev" source: hosted - version: "8.5.6" + version: "8.6.0" balanced_text: dependency: "direct main" description: @@ -131,10 +131,10 @@ packages: dependency: "direct main" description: name: battery_plus - sha256: ccc1322fee1153a0f89e663e0eac2f64d659da506454cf24dcad75eb08ae138b + sha256: "220c8f1961efb01d6870493b5ac5a80afaeaffc8757f7a11ed3025a8570d29e7" url: "https://pub.dev" source: hosted - version: "6.0.2" + version: "6.2.0" battery_plus_platform_interface: dependency: transitive description: @@ -395,10 +395,10 @@ packages: dependency: "direct main" description: name: device_info_plus - sha256: a7fd703482b391a87d60b6061d04dfdeab07826b96f9abd8f5ed98068acc0074 + sha256: c4af09051b4f0508f6c1dc0a5c085bf014d5c9a4a0678ce1799c2b4d716387a0 url: "https://pub.dev" source: hosted - version: "10.1.2" + version: "11.1.0" device_info_plus_platform_interface: dependency: transitive description: @@ -419,10 +419,10 @@ packages: dependency: transitive description: name: fading_edge_scrollview - sha256: c25c2231652ce774cc31824d0112f11f653881f43d7f5302c05af11942052031 + sha256: "1f84fe3ea8e251d00d5735e27502a6a250e4aa3d3b330d3fdcb475af741464ef" url: "https://pub.dev" source: hosted - version: "3.0.0" + version: "4.1.1" fake_async: dependency: transitive description: @@ -451,10 +451,10 @@ packages: dependency: "direct main" description: name: file_picker - sha256: "825aec673606875c33cd8d3c4083f1a3c3999015a84178b317b7ef396b7384f3" + sha256: aac85f20436608e01a6ffd1fdd4e746a7f33c93a2c83752e626bdfaea139b877 url: "https://pub.dev" source: hosted - version: "8.0.7" + version: "8.1.3" file_sizes: dependency: "direct main" description: @@ -488,10 +488,10 @@ packages: dependency: "direct main" description: name: flutter_cache_manager - sha256: "8207f27539deb83732fdda03e259349046a39a4c767269285f449ade355d54ba" + sha256: "400b6592f16a4409a7f2bb929a9a7e38c72cceb8ffb99ee57bbf2cb2cecf8386" url: "https://pub.dev" source: hosted - version: "3.3.1" + version: "3.4.1" flutter_gen_core: dependency: transitive description: @@ -512,18 +512,18 @@ packages: dependency: "direct dev" description: name: flutter_launcher_icons - sha256: "526faf84284b86a4cb36d20a5e45147747b7563d921373d4ee0559c54fcdbcea" + sha256: "619817c4b65b322b5104b6bb6dfe6cda62d9729bd7ad4303ecc8b4e690a67a77" url: "https://pub.dev" source: hosted - version: "0.13.1" + version: "0.14.1" flutter_lints: dependency: "direct dev" description: name: flutter_lints - sha256: "3f41d009ba7172d5ff9be5f6e6e6abb4300e263aab8866d2a0842ed2a70f8f0c" + sha256: "5398f14efa795ffb7a33e9b6a08798b26a180edac4ad7db3f231e40f82ce11e1" url: "https://pub.dev" source: hosted - version: "4.0.0" + version: "5.0.0" flutter_localizations: dependency: "direct main" description: flutter @@ -541,18 +541,18 @@ packages: dependency: "direct main" description: name: flutter_riverpod - sha256: "0f1974eff5bbe774bf1d870e406fc6f29e3d6f1c46bd9c58e7172ff68a785d7d" + sha256: "9532ee6db4a943a1ed8383072a2e3eeda041db5657cdf6d2acecf3c21ecbe7e1" url: "https://pub.dev" source: hosted - version: "2.5.1" + version: "2.6.1" flutter_rust_bridge: dependency: transitive description: name: flutter_rust_bridge - sha256: e12415c3bce49bcbc3fed383f0ea41ad7d828f6cf0eccba0588ffa5a812fe522 + sha256: "0ad5079de35d317650fec59b26cb4d0c116ebc2ce703a29f9367513b8a91c287" url: "https://pub.dev" source: hosted - version: "1.82.1" + version: "2.5.0" flutter_staggered_grid_view: dependency: transitive description: @@ -565,10 +565,10 @@ packages: dependency: "direct main" description: name: flutter_sticky_header - sha256: "017f398fbb45a589e01491861ca20eb6570a763fd9f3888165a978e11248c709" + sha256: "7f76d24d119424ca0c95c146b8627a457e8de8169b0d584f766c2c545db8f8be" url: "https://pub.dev" source: hosted - version: "0.6.5" + version: "0.7.0" flutter_svg: dependency: "direct main" description: @@ -782,11 +782,10 @@ packages: isar_generator: dependency: "direct dev" description: - path: "packages/isar_generator" - ref: "70a5abd2b36d265a2eef0141f98f312a8710e60c" - resolved-ref: "70a5abd2b36d265a2eef0141f98f312a8710e60c" - url: "https://github.com/ndelanou/isar.git" - source: git + name: isar_generator + sha256: "76c121e1295a30423604f2f819bc255bc79f852f3bc8743a24017df6068ad133" + url: "https://pub.dev" + source: hosted version: "3.1.0+1" js: dependency: transitive @@ -816,18 +815,18 @@ packages: dependency: "direct main" description: name: just_audio - sha256: d8e8aaf417d33e345299c17f6457f72bd4ba0c549dc34607abb5183a354edc4d + sha256: b41646a8241688f1d99c2e69c4da2bb26aa4b3a99795f6ff205c2a165e033fda url: "https://pub.dev" source: hosted - version: "0.9.40" + version: "0.9.41" just_audio_media_kit: dependency: "direct main" description: name: just_audio_media_kit - sha256: "7f57d317fafa04cb3e70b924e8f632ffb7eca7a97a369e1e44738ed89fbd5da1" + sha256: "9f3517213dfc7bbaf6980656feb66c35600f114c7efc0b5b3f4476cd5c18b45e" url: "https://pub.dev" source: hosted - version: "2.0.5" + version: "2.0.6" just_audio_platform_interface: dependency: transitive description: @@ -872,10 +871,10 @@ packages: dependency: transitive description: name: lints - sha256: "976c774dd944a42e83e2467f4cc670daef7eed6295b10b36ae8c85bcbf828235" + sha256: "3315600f3fb3b135be672bf4a178c55f274bebe368325ae18462c89ac1e3b413" url: "https://pub.dev" source: hosted - version: "4.0.0" + version: "5.0.0" locale_names: dependency: "direct main" description: @@ -888,10 +887,10 @@ packages: dependency: "direct main" description: name: logging - sha256: "623a88c9594aa774443aa3eb2d41807a48486b5613e67599fb4c41c0ad47c340" + sha256: c8245ada5f1717ed44271ed1c26b8ce85ca3228fd2ffdb75468ab01979309d61 url: "https://pub.dev" source: hosted - version: "1.2.0" + version: "1.3.0" macros: dependency: transitive description: @@ -904,10 +903,10 @@ packages: dependency: "direct main" description: name: marquee - sha256: "4b5243d2804373bdc25fc93d42c3b402d6ec1f4ee8d0bb72276edd04ae7addb8" + sha256: a87e7e80c5d21434f90ad92add9f820cf68be374b226404fe881d2bba7be0862 url: "https://pub.dev" source: hosted - version: "2.2.3" + version: "2.3.0" matcher: dependency: transitive description: @@ -1198,14 +1197,6 @@ packages: url: "https://pub.dev" source: hosted version: "1.3.0" - puppeteer: - dependency: transitive - description: - name: puppeteer - sha256: fc33b2a12731e0b9e16c40cd91ea2b6886bcc24037a435fceb59b786d4074f2b - url: "https://pub.dev" - source: hosted - version: "3.15.0" qs_dart: dependency: transitive description: @@ -1226,42 +1217,42 @@ packages: dependency: transitive description: name: riverpod - sha256: f21b32ffd26a36555e501b04f4a5dca43ed59e16343f1a30c13632b2351dfa4d + sha256: "59062512288d3056b2321804332a13ffdd1bf16df70dcc8e506e411280a72959" url: "https://pub.dev" source: hosted - version: "2.5.1" + version: "2.6.1" riverpod_analyzer_utils: dependency: transitive description: name: riverpod_analyzer_utils - sha256: ee72770090078e6841d51355292335f1bc254907c6694283389dcb8156d99a4d + sha256: "0dcb0af32d561f8fa000c6a6d95633c9fb08ea8a8df46e3f9daca59f11218167" url: "https://pub.dev" source: hosted - version: "0.5.3" + version: "0.5.6" riverpod_annotation: dependency: "direct main" description: name: riverpod_annotation - sha256: e5e796c0eba4030c704e9dae1b834a6541814963292839dcf9638d53eba84f5c + sha256: e14b0bf45b71326654e2705d462f21b958f987087be850afd60578fcd502d1b8 url: "https://pub.dev" source: hosted - version: "2.3.5" + version: "2.6.1" riverpod_generator: dependency: "direct dev" description: name: riverpod_generator - sha256: "1ad626afbd8b01d168870b13c0b036f8a5bdb57c14cd426dc5b4595466bd6e2f" + sha256: "851aedac7ad52693d12af3bf6d92b1626d516ed6b764eb61bf19e968b5e0b931" url: "https://pub.dev" source: hosted - version: "2.4.2" + version: "2.6.1" riverpod_lint: dependency: "direct dev" description: name: riverpod_lint - sha256: b95a8cdc6102397f7d51037131c25ce7e51be900be021af4bf0c2d6f1b8f7aa7 + sha256: "0684c21a9a4582c28c897d55c7b611fa59a351579061b43f8c92c005804e63a8" url: "https://pub.dev" source: hosted - version: "2.3.12" + version: "2.6.1" rxdart: dependency: "direct main" description: @@ -1282,10 +1273,42 @@ packages: dependency: transitive description: name: screen_retriever - sha256: "6ee02c8a1158e6dae7ca430da79436e3b1c9563c8cf02f524af997c201ac2b90" + sha256: "570dbc8e4f70bac451e0efc9c9bb19fa2d6799a11e6ef04f946d7886d2e23d0c" + url: "https://pub.dev" + source: hosted + version: "0.2.0" + screen_retriever_linux: + dependency: transitive + description: + name: screen_retriever_linux + sha256: f7f8120c92ef0784e58491ab664d01efda79a922b025ff286e29aa123ea3dd18 + url: "https://pub.dev" + source: hosted + version: "0.2.0" + screen_retriever_macos: + dependency: transitive + description: + name: screen_retriever_macos + sha256: "71f956e65c97315dd661d71f828708bd97b6d358e776f1a30d5aa7d22d78a149" + url: "https://pub.dev" + source: hosted + version: "0.2.0" + screen_retriever_platform_interface: + dependency: transitive + description: + name: screen_retriever_platform_interface + sha256: ee197f4581ff0d5608587819af40490748e1e39e648d7680ecf95c05197240c0 url: "https://pub.dev" source: hosted - version: "0.1.9" + version: "0.2.0" + screen_retriever_windows: + dependency: transitive + description: + name: screen_retriever_windows + sha256: "449ee257f03ca98a57288ee526a301a430a344a161f9202b4fcc38576716fe13" + url: "https://pub.dev" + source: hosted + version: "0.2.0" scroll_to_index: dependency: "direct main" description: @@ -1298,18 +1321,18 @@ packages: dependency: "direct main" description: name: share_plus - sha256: ef3489a969683c4f3d0239010cc8b7a2a46543a8d139e111c06c558875083544 + sha256: "3af2cda1752e5c24f2fc04b6083b40f013ffe84fb90472f30c6499a9213d5442" url: "https://pub.dev" source: hosted - version: "9.0.0" + version: "10.1.1" share_plus_platform_interface: dependency: transitive description: name: share_plus_platform_interface - sha256: "0f9e4418835d1b2c3ae78fdb918251959106cefdbc4dd43526e182f80e82f6d4" + sha256: c57c0bbfec7142e3a0f55633be504b796af72e60e3c791b44d5a017b985f7a48 url: "https://pub.dev" source: hosted - version: "4.0.0" + version: "5.0.1" shelf: dependency: transitive description: @@ -1318,14 +1341,6 @@ packages: url: "https://pub.dev" source: hosted version: "1.4.1" - shelf_static: - dependency: transitive - description: - name: shelf_static - sha256: c87c3875f91262785dade62d135760c2c69cb217ac759485334c5857ad89f6e3 - url: "https://pub.dev" - source: hosted - version: "1.1.3" shelf_web_socket: dependency: transitive description: @@ -1359,10 +1374,10 @@ packages: dependency: "direct main" description: name: smtc_windows - sha256: "799bbe0f8e4436da852c5dcc0be482c97b8ae0f504f65c6b750cd239b4835aa0" + sha256: "80f7c10867da485ffdf87f842bf27e6763589933c18c11af5dc1cd1e158c3154" url: "https://pub.dev" source: hosted - version: "0.1.2" + version: "1.0.0" source_gen: dependency: transitive description: @@ -1396,6 +1411,14 @@ packages: url: "https://github.com/odriverobotics/split_view.git" source: git version: "3.2.1" + sprintf: + dependency: transitive + description: + name: sprintf + sha256: "1fc9ffe69d4df602376b52949af107d8f5703b77cda567c4d7d86a0693120f23" + url: "https://pub.dev" + source: hosted + version: "7.0.0" sqflite: dependency: transitive description: @@ -1492,14 +1515,6 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.1" - tuple: - dependency: transitive - description: - name: tuple - sha256: a97ce2013f240b2f3807bcbaf218765b6f301c3eff91092bcfa23a039e7dd151 - url: "https://pub.dev" - source: hosted - version: "2.0.2" typed_data: dependency: transitive description: @@ -1544,10 +1559,10 @@ packages: dependency: "direct main" description: name: url_launcher - sha256: "21b704ce5fa560ea9f3b525b43601c678728ba46725bab9b01187b4831377ed3" + sha256: "9d06212b1362abc2f0f0d78e6f09f726608c74e3b9462e8368bb03314aa8d603" url: "https://pub.dev" source: hosted - version: "6.3.0" + version: "6.3.1" url_launcher_android: dependency: transitive description: @@ -1608,18 +1623,18 @@ packages: dependency: "direct main" description: name: uuid - sha256: "648e103079f7c64a36dc7d39369cabb358d377078a051d6ae2ad3aa539519313" + sha256: a5be9ef6618a7ac1e964353ef476418026db906c4facdedaa299b7a2e71690ff url: "https://pub.dev" source: hosted - version: "3.0.7" + version: "4.5.1" value_layout_builder: dependency: transitive description: name: value_layout_builder - sha256: "98202ec1807e94ac72725b7f0d15027afde513c55c69ff3f41bcfccb950831bc" + sha256: c02511ea91ca5c643b514a33a38fa52536f74aa939ec367d02938b5ede6807fa url: "https://pub.dev" source: hosted - version: "0.3.1" + version: "0.4.0" vector_graphics: dependency: transitive description: @@ -1704,18 +1719,18 @@ packages: dependency: transitive description: name: web - sha256: "97da13628db363c635202ad97068d47c5b8aa555808e7a9411963c533b449b27" + sha256: cd3543bd5798f6ad290ea73d210f423502e71900302dde696f8bff84bf89a1cb url: "https://pub.dev" source: hosted - version: "0.5.1" + version: "1.1.0" web_socket_channel: dependency: transitive description: name: web_socket_channel - sha256: "58c6666b342a38816b2e7e50ed0f1e261959630becd4c879c4f26bfa14aa5a42" + sha256: d88238e5eac9a42bb43ca4e721edba3c08c6354d4a53063afaa568516217621b url: "https://pub.dev" source: hosted - version: "2.4.5" + version: "2.4.0" win32: dependency: transitive description: @@ -1736,10 +1751,10 @@ packages: dependency: "direct main" description: name: window_manager - sha256: "8699323b30da4cdbe2aa2e7c9de567a6abd8a97d9a5c850a3c86dcd0b34bbfbf" + sha256: "732896e1416297c63c9e3fb95aea72d0355f61390263982a47fd519169dc5059" url: "https://pub.dev" source: hosted - version: "0.3.9" + version: "0.4.3" xdg_directories: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 34ddcee09..b7b6eeaad 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -26,12 +26,12 @@ dependencies: flutter_localizations: sdk: flutter - background_downloader: ^8.4.1 + background_downloader: ^8.6.0 json_annotation: ^4.8.1 chopper: ^8.0.0 get_it: ^7.2.0 - just_audio: ^0.9.37 - just_audio_media_kit: ^2.0.4 + just_audio: ^0.9.41 + just_audio_media_kit: ^2.0.6 media_kit_libs_linux: ^1.1.3 # Transcoding does not work on windows with current media-kit release. This fork uses the most recent @@ -41,7 +41,7 @@ dependencies: url: https://github.com/Komodo5197/media-kit.git ref: 475a08cc97b94702f774bc906e1472b5bddc932b path: libs/windows/media_kit_libs_windows_audio - smtc_windows: ^0.1.2 + smtc_windows: ^1.0.0 audio_service: ^0.18.13 audio_service_mpris: ^0.1.3 audio_service_platform_interface: ^0.1.1 @@ -52,17 +52,17 @@ dependencies: hive: ^2.2.3 hive_flutter: ^1.1.0 file_sizes: ^1.0.6 - logging: ^1.1.1 + logging: ^1.3.0 collection: ^1.18.0 clipboard: ^0.1.3 - file_picker: ^8.0.3 + file_picker: ^8.1.3 permission_handler: ^11.3.1 provider: ^6.0.5 - uuid: ^3.0.7 + uuid: ^4.5.1 infinite_scroll_pagination: ^4.0.0 - flutter_sticky_header: ^0.6.5 - device_info_plus: ^10.0.1 - app_set_id: ^1.2.0 + flutter_sticky_header: ^0.7.0 + device_info_plus: ^11.1.0 + app_set_id: ^1.2.1 package_info_plus: ^8.0.0 octo_image: ^2.0.0 # Main split view package does not seem actively maintained. Use fork with ability to specify @@ -71,14 +71,14 @@ dependencies: git: url: https://github.com/odriverobotics/split_view.git ref: 8b2b0f0e1c8470183cb2df40815a05bfdb3fe219 - share_plus: ^9.0.0 + share_plus: ^10.1.1 isar: ^3.1.0 isar_flutter_libs: ^3.1.0 path: ^1.9.0 intl: '>=0.18.1 < 1.0.0' auto_size_text: ^3.0.0 - marquee: ^2.2.3 + marquee: ^2.3.0 palette_generator: git: url: https://github.com/jmshrv/packages.git @@ -86,12 +86,12 @@ dependencies: ref: 4992c3b path: packages/palette_generator flutter_tabler_icons: ^1.27.0 - flutter_riverpod: ^2.4.9 - riverpod_annotation: ^2.3.3 + flutter_riverpod: ^2.6.1 + riverpod_annotation: ^2.6.1 locale_names: ^1.1.1 flutter_vibrate: ^1.3.0 mini_music_visualizer: ^1.0.2 - flutter_cache_manager: ^3.3.1 + flutter_cache_manager: ^3.4.1 # fix not showing elipses when maxLines==1 balanced_text: git: @@ -100,10 +100,10 @@ dependencies: flutter_to_airplay: ^2.0.4 flutter_blurhash: ^0.8.2 scroll_to_index: ^3.0.1 - window_manager: ^0.3.8 - url_launcher: ^6.2.6 + window_manager: ^0.4.3 + url_launcher: ^6.3.1 wakelock_plus: ^1.2.8 - battery_plus: ^6.0.2 + battery_plus: ^6.2.0 focus_on_it: ^2.0.1 flutter_svg: ^2.0.10+1 @@ -115,20 +115,19 @@ dev_dependencies: chopper_generator: ^8.0.0 hive_generator: ^2.0.0 json_serializable: ^6.7.1 - flutter_launcher_icons: ^0.13.1 - flutter_lints: ^4.0.0 - riverpod_generator: ^2.3.9 + flutter_launcher_icons: ^0.14.1 + flutter_lints: ^5.0.0 + riverpod_generator: ^2.6.1 custom_lint: - riverpod_lint: ^2.3.7 - # isar_generator requires analyzer <6.0.0 by default, but 6.x.0 doesn't have breaking changes - # Using fork of 3.1.0+1 with pubspec updated to analyzer: "^6.0.0" - isar_generator: - git: - url: https://github.com/ndelanou/isar.git - ref: 70a5abd2b36d265a2eef0141f98f312a8710e60c - path: packages/isar_generator + riverpod_lint: ^2.6.1 + isar_generator: ^3.1.0+1 msix: ^3.16.7 +dependency_overrides: + # isar_generator requires analyzer <6.0.0 by default, but 6.x.0 doesn't have breaking changes + # Overriding the package version allows us to use the latest version. + analyzer: ^6.0.0 + # For information on the generic Dart part of this file, see the # following page: https://dart.dev/tools/pub/pubspec diff --git a/windows/flutter/generated_plugin_registrant.cc b/windows/flutter/generated_plugin_registrant.cc index 8c09f956d..9cb075195 100644 --- a/windows/flutter/generated_plugin_registrant.cc +++ b/windows/flutter/generated_plugin_registrant.cc @@ -10,7 +10,7 @@ #include #include #include -#include +#include #include #include #include @@ -24,8 +24,8 @@ void RegisterPlugins(flutter::PluginRegistry* registry) { registry->GetRegistrarForPlugin("MediaKitLibsWindowsAudioPluginCApi")); PermissionHandlerWindowsPluginRegisterWithRegistrar( registry->GetRegistrarForPlugin("PermissionHandlerWindowsPlugin")); - ScreenRetrieverPluginRegisterWithRegistrar( - registry->GetRegistrarForPlugin("ScreenRetrieverPlugin")); + ScreenRetrieverWindowsPluginCApiRegisterWithRegistrar( + registry->GetRegistrarForPlugin("ScreenRetrieverWindowsPluginCApi")); SharePlusWindowsPluginCApiRegisterWithRegistrar( registry->GetRegistrarForPlugin("SharePlusWindowsPluginCApi")); UrlLauncherWindowsRegisterWithRegistrar( diff --git a/windows/flutter/generated_plugins.cmake b/windows/flutter/generated_plugins.cmake index 41be227b4..315d05f47 100644 --- a/windows/flutter/generated_plugins.cmake +++ b/windows/flutter/generated_plugins.cmake @@ -7,7 +7,7 @@ list(APPEND FLUTTER_PLUGIN_LIST isar_flutter_libs media_kit_libs_windows_audio permission_handler_windows - screen_retriever + screen_retriever_windows share_plus url_launcher_windows window_manager