diff --git a/.gitignore b/.gitignore index 3d6c797..4c5ed38 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,5 @@ build/ .idea/ example/ios/Flutter/flutter_export_environment.sh + +example/ios/Flutter/ephemeral/ \ No newline at end of file diff --git a/android/build.gradle b/android/build.gradle index 569dd6f..66f6639 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -25,6 +25,7 @@ apply plugin: 'com.android.library' apply plugin: 'kotlin-android' android { + namespace 'com.gianlucaparadise.flutter_cast_framework' compileSdkVersion 33 sourceSets { @@ -34,6 +35,13 @@ android { minSdkVersion 21 testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } + compileOptions { + sourceCompatibility JavaVersion.VERSION_17 + targetCompatibility JavaVersion.VERSION_17 + } + kotlinOptions { + jvmTarget = JavaVersion.VERSION_17.toString() + } lintOptions { disable 'InvalidPackage' } @@ -47,6 +55,7 @@ dependencies { implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" api "com.google.android.gms:play-services-cast-framework:21.3.0" + implementation "androidx.mediarouter:mediarouter:1.3.0" // Lifecycle implementation "androidx.lifecycle:lifecycle-extensions:$lifecycle_version" diff --git a/android/src/main/AndroidManifest.xml b/android/src/main/AndroidManifest.xml index 0a063a0..7e41f29 100644 --- a/android/src/main/AndroidManifest.xml +++ b/android/src/main/AndroidManifest.xml @@ -1,2 +1,5 @@ - + + + diff --git a/android/src/main/kotlin/com/gianlucaparadise/flutter_cast_framework/FlutterCastFrameworkPlugin.kt b/android/src/main/kotlin/com/gianlucaparadise/flutter_cast_framework/FlutterCastFrameworkPlugin.kt index 34c3dc2..543bc60 100644 --- a/android/src/main/kotlin/com/gianlucaparadise/flutter_cast_framework/FlutterCastFrameworkPlugin.kt +++ b/android/src/main/kotlin/com/gianlucaparadise/flutter_cast_framework/FlutterCastFrameworkPlugin.kt @@ -2,9 +2,11 @@ package com.gianlucaparadise.flutter_cast_framework import android.app.Activity import android.content.Context +import android.net.wifi.WifiManager import android.util.Log import androidx.fragment.app.FragmentActivity import androidx.lifecycle.* +import androidx.mediarouter.media.MediaRouter import com.gianlucaparadise.flutter_cast_framework.cast.CastDialogOpener import com.gianlucaparadise.flutter_cast_framework.cast.MessageCastingChannel import com.gianlucaparadise.flutter_cast_framework.media.* @@ -25,24 +27,72 @@ import io.flutter.plugin.common.BinaryMessenger import io.flutter.plugin.common.MethodCall import io.flutter.plugin.common.MethodChannel.MethodCallHandler import io.flutter.plugin.common.MethodChannel.Result -import io.flutter.plugin.common.PluginRegistry.Registrar - - class FlutterCastFrameworkPlugin : FlutterPlugin, MethodCallHandler, ActivityAware, DefaultLifecycleObserver { companion object { const val TAG = "AndroidCastPlugin" - - @JvmStatic - fun registerWith(registrar: Registrar) { - val plugin = FlutterCastFrameworkPlugin() - plugin.onAttachedToEngine(registrar.context(), registrar.messenger()) - } } init { ProcessLifecycleOwner.get().lifecycle.addObserver(this) } + // MediaRouter is used to keep an active discovery running while the app is + // in foreground. Without an active scan (normally kept alive by a native + // MediaRouteButton), CastContext.getCastState() stays at NO_DEVICES_AVAILABLE + // even when there are Cast devices reachable on the network. + private var mMediaRouter: MediaRouter? = null + private val mMediaRouterCallback = object : MediaRouter.Callback() {} + + // Some devices (notably several Wi-Fi chipsets / MIUI builds) filter inbound + // multicast frames when no app holds a MulticastLock, which silently blocks + // mDNS (224.0.0.251) Cast discovery even though unicast to the device works. + private var mMulticastLock: WifiManager.MulticastLock? = null + + private fun startActiveDiscovery(context: Context, castContext: CastContext) { + try { + val selector = castContext.mergedSelector ?: return + acquireMulticastLock(context) + val mediaRouter = mMediaRouter ?: MediaRouter.getInstance(context).also { mMediaRouter = it } + mediaRouter.addCallback( + selector, + mMediaRouterCallback, + MediaRouter.CALLBACK_FLAG_PERFORM_ACTIVE_SCAN + ) + Log.d(TAG, "Active cast discovery started") + } catch (e: Exception) { + Log.e(TAG, "Failed to start active cast discovery", e) + } + } + + private fun stopActiveDiscovery() { + mMediaRouter?.removeCallback(mMediaRouterCallback) + releaseMulticastLock() + Log.d(TAG, "Active cast discovery stopped") + } + + private fun acquireMulticastLock(context: Context) { + try { + if (mMulticastLock?.isHeld == true) return + val wifi = context.applicationContext.getSystemService(Context.WIFI_SERVICE) as? WifiManager ?: return + mMulticastLock = wifi.createMulticastLock("flutter_cast_framework").apply { + setReferenceCounted(false) + acquire() + } + Log.d(TAG, "MulticastLock acquired") + } catch (e: Exception) { + Log.e(TAG, "Failed to acquire MulticastLock", e) + } + } + + private fun releaseMulticastLock() { + try { + mMulticastLock?.let { if (it.isHeld) it.release() } + mMulticastLock = null + } catch (e: Exception) { + Log.e(TAG, "Failed to release MulticastLock", e) + } + } + //region FlutterPlugin interface override fun onAttachedToEngine(binding: FlutterPlugin.FlutterPluginBinding) { Log.d(TAG, "onAttachedToEngine") @@ -183,12 +233,15 @@ class FlutterCastFrameworkPlugin : FlutterPlugin, MethodCallHandler, ActivityAwa Log.d(TAG, "App: ON_RESUME - missing context") return } + startActiveDiscovery(context, castContext) + val castState = castContext.castState flutterApi?.onCastStateChanged(castState.toLong()) { } } override fun onPause(owner: LifecycleOwner) { Log.d(TAG, "App: ON_PAUSE") + stopActiveDiscovery() mSessionManager?.removeSessionManagerListener( mSessionManagerListener, CastSession::class.java diff --git a/android/src/main/kotlin/com/gianlucaparadise/flutter_cast_framework/cast/DefaultCastOptionsProvider.kt b/android/src/main/kotlin/com/gianlucaparadise/flutter_cast_framework/cast/DefaultCastOptionsProvider.kt index aad02ec..cd2b7ad 100644 --- a/android/src/main/kotlin/com/gianlucaparadise/flutter_cast_framework/cast/DefaultCastOptionsProvider.kt +++ b/android/src/main/kotlin/com/gianlucaparadise/flutter_cast_framework/cast/DefaultCastOptionsProvider.kt @@ -1,20 +1,28 @@ package com.gianlucaparadise.flutter_cast_framework.cast import android.content.Context +import com.google.android.gms.cast.CastMediaControlIntent import com.google.android.gms.cast.framework.CastOptions import com.google.android.gms.cast.framework.OptionsProvider import com.google.android.gms.cast.framework.SessionProvider /** - * This is here to be used as an example + * Example OptionsProvider. Copy this class into your app and set OPTIONS_PROVIDER_CLASS_NAME + * in your AndroidManifest.xml to point to it. + * + * Receiver IDs for reference: + * Debug/test (any Chromecast, no Cast Console setup needed): + * CastMediaControlIntent.DEFAULT_MEDIA_RECEIVER_APPLICATION_ID // = "CC1AD845" + * Production (must be published or device registered in Cast Console): + * "" // e.g. "6D8B5531" */ class DefaultCastOptionsProvider : OptionsProvider { - // TODO: find a way to build this from dart code. Maybe source_gen? - override fun getCastOptions(context: Context): CastOptions { return CastOptions.Builder() - .setReceiverApplicationId("4F8B3483") + // Use DEFAULT_MEDIA_RECEIVER_APPLICATION_ID for quick testing with any Chromecast. + // Replace with your production app ID once published in the Cast Console. + .setReceiverApplicationId(CastMediaControlIntent.DEFAULT_MEDIA_RECEIVER_APPLICATION_ID) .build() } diff --git a/example/ios/Runner/AppDelegate.swift b/example/ios/Runner/AppDelegate.swift index 0157a1b..645613c 100644 --- a/example/ios/Runner/AppDelegate.swift +++ b/example/ios/Runner/AppDelegate.swift @@ -4,7 +4,9 @@ import GoogleCast @UIApplicationMain @objc class AppDelegate: FlutterAppDelegate, GCKLoggerDelegate { - let kReceiverAppID = "CC1AD845" + // Use kGCKDefaultMediaReceiverApplicationID ("CC1AD845") for quick testing with any Chromecast. + // Replace with your production app ID once published in the Cast Console. e.g: "6D8B5531" + let kReceiverAppID = kGCKDefaultMediaReceiverApplicationID let kDebugLoggingEnabled = true override func application( diff --git a/example/pubspec.lock b/example/pubspec.lock index acd2587..efd3931 100644 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -29,42 +29,42 @@ packages: dependency: transitive description: name: characters - sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605" + sha256: faf38497bda5ead2a8c7615f4f7939df04333478bf32e4173fcb06d428b5716b url: "https://pub.dev" source: hosted - version: "1.3.0" + version: "1.4.1" clock: dependency: transitive description: name: clock - sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf + sha256: fddb70d9b5277016c77a80201021d40a2247104d9f4aa7bab7157b7e3f05b84b url: "https://pub.dev" source: hosted - version: "1.1.1" + version: "1.1.2" collection: dependency: transitive description: name: collection - sha256: "4a07be6cb69c84d677a6c3096fcf960cc3285a8330b4603e0d463d15d9bd934c" + sha256: "2f5709ae4d3d59dd8f7cd309b4e023046b57d8a6c82130785d2b0e5868084e76" url: "https://pub.dev" source: hosted - version: "1.17.1" + version: "1.19.1" cupertino_icons: dependency: "direct main" description: name: cupertino_icons - sha256: e35129dc44c9118cee2a5603506d823bab99c68393879edb440e0090d07586be + sha256: "41e005c33bd814be4d3096aff55b1908d419fde52ca656c8c47719ec745873cd" url: "https://pub.dev" source: hosted - version: "1.0.5" + version: "1.0.9" fake_async: dependency: transitive description: name: fake_async - sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78" + sha256: "5368f224a74523e8d2e7399ea1638b37aecfca824a3cc4dfdf77bf1fa905ac44" url: "https://pub.dev" source: hosted - version: "1.3.1" + version: "1.3.3" flutter: dependency: "direct main" description: flutter @@ -90,46 +90,62 @@ packages: description: flutter source: sdk version: "0.0.0" - js: + leak_tracker: dependency: transitive description: - name: js - sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3 + name: leak_tracker + sha256: "33e2e26bdd85a0112ec15400c8cbffea70d0f9c3407491f672a2fad47915e2de" url: "https://pub.dev" source: hosted - version: "0.6.7" + version: "11.0.2" + leak_tracker_flutter_testing: + dependency: transitive + description: + name: leak_tracker_flutter_testing + sha256: "1dbc140bb5a23c75ea9c4811222756104fbcd1a27173f0c34ca01e16bea473c1" + url: "https://pub.dev" + source: hosted + version: "3.0.10" + leak_tracker_testing: + dependency: transitive + description: + name: leak_tracker_testing + sha256: "8d5a2d49f4a66b49744b23b018848400d23e54caf9463f4eb20df3eb8acb2eb1" + url: "https://pub.dev" + source: hosted + version: "3.0.2" matcher: dependency: transitive description: name: matcher - sha256: "6501fbd55da300384b768785b83e5ce66991266cec21af89ab9ae7f5ce1c4cbb" + sha256: "12956d0ad8390bbcc63ca2e1469c0619946ccb52809807067a7020d57e647aa6" url: "https://pub.dev" source: hosted - version: "0.12.15" + version: "0.12.18" material_color_utilities: dependency: transitive description: name: material_color_utilities - sha256: d92141dc6fe1dad30722f9aa826c7fbc896d021d792f80678280601aff8cf724 + sha256: "9c337007e82b1889149c82ed242ed1cb24a66044e30979c44912381e9be4c48b" url: "https://pub.dev" source: hosted - version: "0.2.0" + version: "0.13.0" meta: dependency: transitive description: name: meta - sha256: "3c74dbf8763d36539f114c799d8a2d87343b5067e9d796ca22b5eb8437090ee3" + sha256: "23f08335362185a5ea2ad3a4e597f1375e78bce8a040df5c600c8d3552ef2394" url: "https://pub.dev" source: hosted - version: "1.9.1" + version: "1.17.0" path: dependency: transitive description: name: path - sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917" + sha256: "75cca69d1490965be98c73ceaea117e8a04dd21217b37b292c9ddbec0d955bc5" url: "https://pub.dev" source: hosted - version: "1.8.3" + version: "1.9.1" path_parsing: dependency: transitive description: @@ -158,7 +174,7 @@ packages: dependency: transitive description: flutter source: sdk - version: "0.0.99" + version: "0.0.0" source_span: dependency: transitive description: @@ -171,18 +187,18 @@ packages: dependency: transitive description: name: stack_trace - sha256: c3c7d8edb15bee7f0f74debd4b9c5f3c2ea86766fe4178eb2a18eb30a0bdaed5 + sha256: "8b27215b45d22309b5cddda1aa2b19bdfec9df0e765f2de506401c071d38d1b1" url: "https://pub.dev" source: hosted - version: "1.11.0" + version: "1.12.1" stream_channel: dependency: transitive description: name: stream_channel - sha256: "83615bee9045c1d322bbbd1ba209b7a749c2cbcdcb3fdd1df8eb488b3279c1c8" + sha256: "969e04c80b8bcdf826f8f16579c7b14d780458bd97f56d107d3950fdbeef059d" url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "2.1.4" string_scanner: dependency: transitive description: @@ -203,10 +219,10 @@ packages: dependency: transitive description: name: test_api - sha256: eb6ac1540b26de412b3403a163d919ba86f6a973fe6cc50ae3541b80092fdcfb + sha256: "93167629bfc610f71560ab9312acdda4959de4df6fac7492c89ff0d3886f6636" url: "https://pub.dev" source: hosted - version: "0.5.1" + version: "0.7.9" transparent_image: dependency: "direct main" description: @@ -243,10 +259,18 @@ packages: dependency: transitive description: name: vector_math - sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" + sha256: d530bd74fea330e6e364cda7a85019c434070188383e1cd8d9777ee586914c5b url: "https://pub.dev" source: hosted - version: "2.1.4" + version: "2.2.0" + vm_service: + dependency: transitive + description: + name: vm_service + sha256: "0016aef94fc66495ac78af5859181e3f3bf2026bd8eecc72b9565601e19ab360" + url: "https://pub.dev" + source: hosted + version: "15.2.0" xml: dependency: transitive description: @@ -256,5 +280,5 @@ packages: source: hosted version: "6.2.2" sdks: - dart: ">=3.0.0-0 <4.0.0" - flutter: ">=3.7.0-0" + dart: ">=3.9.0 <4.0.0" + flutter: ">=3.18.0-18.0.pre.54" diff --git a/example/pubspec.yaml b/example/pubspec.yaml index 7a9bac9..6a988ba 100644 --- a/example/pubspec.yaml +++ b/example/pubspec.yaml @@ -4,7 +4,7 @@ version: 0.0.1 publish_to: 'none' environment: - sdk: '>=2.17.0 <3.0.0' + sdk: '>=3.3.10 <4.0.0' dependencies: flutter: @@ -12,7 +12,7 @@ dependencies: # The following adds the Cupertino Icons font to your application. # Use with the CupertinoIcons class for iOS style icons. - cupertino_icons: ^1.0.5 + cupertino_icons: ^1.0.9 transparent_image: ^2.0.1 dev_dependencies: diff --git a/ios/flutter_cast_framework.podspec b/ios/flutter_cast_framework.podspec index f8a3b8d..a5b683a 100644 --- a/ios/flutter_cast_framework.podspec +++ b/ios/flutter_cast_framework.podspec @@ -17,11 +17,7 @@ A new flutter plugin project. s.static_framework = true s.dependency 'Flutter' - s.dependency 'google-cast-sdk-no-bluetooth', '~> 4.7.0' + s.dependency 'google-cast-sdk-no-bluetooth-xcframework', '~> 4.8.0' - s.ios.deployment_target = '10.0' - - # This is to enable build on simulator - s.pod_target_xcconfig = { 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'arm64' } - s.user_target_xcconfig = { 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'arm64' } + s.ios.deployment_target = '13.0' end diff --git a/lib/src/PlatformBridgeApis.dart b/lib/src/PlatformBridgeApis.dart index 1ec0705..4d0ab76 100644 --- a/lib/src/PlatformBridgeApis.dart +++ b/lib/src/PlatformBridgeApis.dart @@ -12,10 +12,13 @@ import 'package:flutter/services.dart'; enum StreamType { /// An invalid (unknown) stream type. invalid, + /// A stream type of "none". none, + /// A buffered stream type. buffered, + /// A live stream type. live, } @@ -24,16 +27,22 @@ enum StreamType { enum MediaType { /// A media type representing generic media content. generic, + /// A media type representing a movie. movie, + /// A media type representing an TV show. tvShow, + /// A media type representing a music track. musicTrack, + /// A media type representing a photo. photo, + /// A media type representing an audiobook chapter. audiobookChapter, + /// The smallest media type value that can be assigned for application-defined media types. user, } @@ -42,58 +51,85 @@ enum MediaType { enum MediaMetadataKey { /// String key: Album artist. albumArtist, + /// String key: Album title. albumTitle, + /// String key: Artist. artist, + /// String key: Audiobook title. bookTitle, + /// String key: Broadcast date. broadcastDate, + /// String key: Chapter number. chapterNumber, + /// String key: Chapter title. chapterTitle, + /// String key: Composer. composer, + /// String key: Creation date. creationDate, + /// Integer key: Disc number. discNumber, + /// Integer key: Episode number. episodeNumber, + /// Integer key: Height. height, + /// Double key: Location latitude. locationLatitude, + /// Double key: Location longitude. locationLongitude, + /// String key: Location name. locationName, + /// Int key: Queue item ID. queueItemId, + /// String key: Release date. releaseDate, + /// Integer key: Season number. seasonNumber, + /// Time key in milliseconds: section duration. sectionDuration, + /// Time key in milliseconds: section start absolute time. sectionStartAbsoluteTime, + /// Time key in milliseconds: section start time in the container. sectionStartTimeInContainer, + /// Time key in milliseconds: section start time in media item. sectionStartTimeInMedia, + /// String key: Series title. seriesTitle, + /// String key: Studio. studio, + /// String key: Subtitle. subtitle, + /// String key: Title. title, + /// Integer key: Track number. trackNumber, + /// Integer key: Width. width, } @@ -102,10 +138,13 @@ enum MediaMetadataKey { enum TrackType { /// A media track type indicating an unknown track type. unknown, + /// A media track type indicating a text track. text, + /// A media track type indicating an audio track. audio, + /// A media track type indicating a video track. video, } @@ -114,16 +153,22 @@ enum TrackType { enum TrackSubtype { /// A media track subtype indicating an unknown subtype. unknown, + /// A media track subtype indicating no subtype. none, + /// A media track subtype indicating subtitles. subtitles, + /// A media track subtype indicating closed captions. captions, + /// A media track subtype indicating descriptions. descriptions, + /// A media track subtype indicating chapters. chapters, + /// A media track subtype indicating metadata. metadata, } @@ -132,14 +177,19 @@ enum TrackSubtype { enum PlayerState { /// Constant indicating unknown player state. unknown, + /// Constant indicating that the media player is idle. idle, + /// Constant indicating that the media player is playing. playing, + /// Constant indicating that the media player is paused. paused, + /// Constant indicating that the media player is buffering. buffering, + /// Constant indicating that the media player is loading. loading, } @@ -171,9 +221,7 @@ class MediaLoadRequestData { return MediaLoadRequestData( shouldAutoplay: result[0] as bool?, currentTime: result[1] as int?, - mediaInfo: result[2] != null - ? MediaInfo.decode(result[2]! as List) - : null, + mediaInfo: result[2] != null ? MediaInfo.decode(result[2]! as List) : null, ); } } @@ -225,13 +273,9 @@ class MediaInfo { result as List; return MediaInfo( contentId: result[0] as String?, - streamType: result[1] != null - ? StreamType.values[result[1]! as int] - : null, + streamType: result[1] != null ? StreamType.values[result[1]! as int] : null, contentType: result[2] as String?, - mediaMetadata: result[3] != null - ? MediaMetadata.decode(result[3]! as List) - : null, + mediaMetadata: result[3] != null ? MediaMetadata.decode(result[3]! as List) : null, mediaTracks: (result[4] as List?)?.cast(), streamDuration: result[5] as int?, adBreakClips: (result[6] as List?)?.cast(), @@ -265,9 +309,7 @@ class MediaMetadata { static MediaMetadata decode(Object result) { result as List; return MediaMetadata( - mediaType: result[0] != null - ? MediaType.values[result[0]! as int] - : null, + mediaType: result[0] != null ? MediaType.values[result[0]! as int] : null, strings: (result[1] as Map?)?.cast(), webImages: (result[2] as List?)?.cast(), ); @@ -334,13 +376,9 @@ class MediaTrack { result as List; return MediaTrack( id: result[0] as int?, - trackType: result[1] != null - ? TrackType.values[result[1]! as int] - : null, + trackType: result[1] != null ? TrackType.values[result[1]! as int] : null, name: result[2] as String?, - trackSubtype: result[3] != null - ? TrackSubtype.values[result[3]! as int] - : null, + trackSubtype: result[3] != null ? TrackSubtype.values[result[3]! as int] : null, contentId: result[4] as String?, language: result[5] as String?, ); @@ -375,16 +413,10 @@ class MediaStatus { static MediaStatus decode(Object result) { result as List; return MediaStatus( - playerState: result[0] != null - ? PlayerState.values[result[0]! as int] - : null, + playerState: result[0] != null ? PlayerState.values[result[0]! as int] : null, isPlayingAd: result[1] as bool?, - mediaInfo: result[2] != null - ? MediaInfo.decode(result[2]! as List) - : null, - adBreakStatus: result[3] != null - ? AdBreakStatus.decode(result[3]! as List) - : null, + mediaInfo: result[2] != null ? MediaInfo.decode(result[2]! as List) : null, + adBreakStatus: result[3] != null ? AdBreakStatus.decode(result[3]! as List) : null, ); } } @@ -520,9 +552,7 @@ class MediaQueueItem { itemId: result[0] as int?, playbackDuration: result[1] as double?, startTime: result[2] as double?, - media: result[3] != null - ? MediaInfo.decode(result[3]! as List) - : null, + media: result[3] != null ? MediaInfo.decode(result[3]! as List) : null, autoplay: result[4] as bool?, preloadTime: result[5] as double?, ); @@ -625,23 +655,23 @@ class _CastHostApiCodec extends StandardMessageCodec { @override Object? readValueOfType(int type, ReadBuffer buffer) { switch (type) { - case 128: + case 128: return AdBreakClipInfo.decode(readValue(buffer)!); - case 129: + case 129: return CastDevice.decode(readValue(buffer)!); - case 130: + case 130: return CastMessage.decode(readValue(buffer)!); - case 131: + case 131: return MediaInfo.decode(readValue(buffer)!); - case 132: + case 132: return MediaLoadRequestData.decode(readValue(buffer)!); - case 133: + case 133: return MediaMetadata.decode(readValue(buffer)!); - case 134: + case 134: return MediaQueueItem.decode(readValue(buffer)!); - case 135: + case 135: return MediaTrack.decode(readValue(buffer)!); - case 136: + case 136: return WebImage.decode(readValue(buffer)!); default: return super.readValueOfType(type, buffer); @@ -654,8 +684,7 @@ class CastHostApi { /// Constructor for [CastHostApi]. The [binaryMessenger] named argument is /// available for dependency injection. If it is left null, the default /// BinaryMessenger will be used which routes to the host platform. - CastHostApi({BinaryMessenger? binaryMessenger}) - : _binaryMessenger = binaryMessenger; + CastHostApi({BinaryMessenger? binaryMessenger}) : _binaryMessenger = binaryMessenger; final BinaryMessenger? _binaryMessenger; static const MessageCodec codec = _CastHostApiCodec(); @@ -664,8 +693,7 @@ class CastHostApi { final BasicMessageChannel channel = BasicMessageChannel( 'dev.flutter.pigeon.CastHostApi.sendMessage', codec, binaryMessenger: _binaryMessenger); - final List? replyList = - await channel.send([arg_message]) as List?; + final List? replyList = await channel.send([arg_message]) as List?; if (replyList == null) { throw PlatformException( code: 'channel-error', @@ -686,8 +714,7 @@ class CastHostApi { final BasicMessageChannel channel = BasicMessageChannel( 'dev.flutter.pigeon.CastHostApi.showCastDialog', codec, binaryMessenger: _binaryMessenger); - final List? replyList = - await channel.send(null) as List?; + final List? replyList = await channel.send(null) as List?; if (replyList == null) { throw PlatformException( code: 'channel-error', @@ -708,8 +735,7 @@ class CastHostApi { final BasicMessageChannel channel = BasicMessageChannel( 'dev.flutter.pigeon.CastHostApi.setMute', codec, binaryMessenger: _binaryMessenger); - final List? replyList = - await channel.send([arg_muted]) as List?; + final List? replyList = await channel.send([arg_muted]) as List?; if (replyList == null) { throw PlatformException( code: 'channel-error', @@ -730,8 +756,7 @@ class CastHostApi { final BasicMessageChannel channel = BasicMessageChannel( 'dev.flutter.pigeon.CastHostApi.getCastDevice', codec, binaryMessenger: _binaryMessenger); - final List? replyList = - await channel.send(null) as List?; + final List? replyList = await channel.send(null) as List?; if (replyList == null) { throw PlatformException( code: 'channel-error', @@ -757,8 +782,7 @@ class CastHostApi { final BasicMessageChannel channel = BasicMessageChannel( 'dev.flutter.pigeon.CastHostApi.loadMediaLoadRequestData', codec, binaryMessenger: _binaryMessenger); - final List? replyList = - await channel.send([arg_request]) as List?; + final List? replyList = await channel.send([arg_request]) as List?; if (replyList == null) { throw PlatformException( code: 'channel-error', @@ -779,8 +803,7 @@ class CastHostApi { final BasicMessageChannel channel = BasicMessageChannel( 'dev.flutter.pigeon.CastHostApi.getMediaInfo', codec, binaryMessenger: _binaryMessenger); - final List? replyList = - await channel.send(null) as List?; + final List? replyList = await channel.send(null) as List?; if (replyList == null) { throw PlatformException( code: 'channel-error', @@ -803,11 +826,9 @@ class CastHostApi { } Future play() async { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.CastHostApi.play', codec, - binaryMessenger: _binaryMessenger); - final List? replyList = - await channel.send(null) as List?; + final BasicMessageChannel channel = + BasicMessageChannel('dev.flutter.pigeon.CastHostApi.play', codec, binaryMessenger: _binaryMessenger); + final List? replyList = await channel.send(null) as List?; if (replyList == null) { throw PlatformException( code: 'channel-error', @@ -825,11 +846,9 @@ class CastHostApi { } Future pause() async { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.CastHostApi.pause', codec, - binaryMessenger: _binaryMessenger); - final List? replyList = - await channel.send(null) as List?; + final BasicMessageChannel channel = + BasicMessageChannel('dev.flutter.pigeon.CastHostApi.pause', codec, binaryMessenger: _binaryMessenger); + final List? replyList = await channel.send(null) as List?; if (replyList == null) { throw PlatformException( code: 'channel-error', @@ -847,11 +866,9 @@ class CastHostApi { } Future stop() async { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.CastHostApi.stop', codec, - binaryMessenger: _binaryMessenger); - final List? replyList = - await channel.send(null) as List?; + final BasicMessageChannel channel = + BasicMessageChannel('dev.flutter.pigeon.CastHostApi.stop', codec, binaryMessenger: _binaryMessenger); + final List? replyList = await channel.send(null) as List?; if (replyList == null) { throw PlatformException( code: 'channel-error', @@ -872,8 +889,7 @@ class CastHostApi { final BasicMessageChannel channel = BasicMessageChannel( 'dev.flutter.pigeon.CastHostApi.showTracksChooserDialog', codec, binaryMessenger: _binaryMessenger); - final List? replyList = - await channel.send(null) as List?; + final List? replyList = await channel.send(null) as List?; if (replyList == null) { throw PlatformException( code: 'channel-error', @@ -891,11 +907,9 @@ class CastHostApi { } Future skipAd() async { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.CastHostApi.skipAd', codec, - binaryMessenger: _binaryMessenger); - final List? replyList = - await channel.send(null) as List?; + final BasicMessageChannel channel = + BasicMessageChannel('dev.flutter.pigeon.CastHostApi.skipAd', codec, binaryMessenger: _binaryMessenger); + final List? replyList = await channel.send(null) as List?; if (replyList == null) { throw PlatformException( code: 'channel-error', @@ -913,11 +927,9 @@ class CastHostApi { } Future seekTo(int arg_progress) async { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.CastHostApi.seekTo', codec, - binaryMessenger: _binaryMessenger); - final List? replyList = - await channel.send([arg_progress]) as List?; + final BasicMessageChannel channel = + BasicMessageChannel('dev.flutter.pigeon.CastHostApi.seekTo', codec, binaryMessenger: _binaryMessenger); + final List? replyList = await channel.send([arg_progress]) as List?; if (replyList == null) { throw PlatformException( code: 'channel-error', @@ -938,8 +950,7 @@ class CastHostApi { final BasicMessageChannel channel = BasicMessageChannel( 'dev.flutter.pigeon.CastHostApi.queueAppendItem', codec, binaryMessenger: _binaryMessenger); - final List? replyList = - await channel.send([arg_item]) as List?; + final List? replyList = await channel.send([arg_item]) as List?; if (replyList == null) { throw PlatformException( code: 'channel-error', @@ -960,8 +971,7 @@ class CastHostApi { final BasicMessageChannel channel = BasicMessageChannel( 'dev.flutter.pigeon.CastHostApi.queueNextItem', codec, binaryMessenger: _binaryMessenger); - final List? replyList = - await channel.send(null) as List?; + final List? replyList = await channel.send(null) as List?; if (replyList == null) { throw PlatformException( code: 'channel-error', @@ -982,8 +992,7 @@ class CastHostApi { final BasicMessageChannel channel = BasicMessageChannel( 'dev.flutter.pigeon.CastHostApi.queuePrevItem', codec, binaryMessenger: _binaryMessenger); - final List? replyList = - await channel.send(null) as List?; + final List? replyList = await channel.send(null) as List?; if (replyList == null) { throw PlatformException( code: 'channel-error', @@ -1004,8 +1013,7 @@ class CastHostApi { final BasicMessageChannel channel = BasicMessageChannel( 'dev.flutter.pigeon.CastHostApi.getQueueItemCount', codec, binaryMessenger: _binaryMessenger); - final List? replyList = - await channel.send(null) as List?; + final List? replyList = await channel.send(null) as List?; if (replyList == null) { throw PlatformException( code: 'channel-error', @@ -1031,8 +1039,7 @@ class CastHostApi { final BasicMessageChannel channel = BasicMessageChannel( 'dev.flutter.pigeon.CastHostApi.getQueueItemAtIndex', codec, binaryMessenger: _binaryMessenger); - final List? replyList = - await channel.send([arg_index]) as List?; + final List? replyList = await channel.send([arg_index]) as List?; if (replyList == null) { throw PlatformException( code: 'channel-error', @@ -1091,21 +1098,21 @@ class _CastFlutterApiCodec extends StandardMessageCodec { @override Object? readValueOfType(int type, ReadBuffer buffer) { switch (type) { - case 128: + case 128: return AdBreakClipInfo.decode(readValue(buffer)!); - case 129: + case 129: return AdBreakStatus.decode(readValue(buffer)!); - case 130: + case 130: return CastMessage.decode(readValue(buffer)!); - case 131: + case 131: return MediaInfo.decode(readValue(buffer)!); - case 132: + case 132: return MediaMetadata.decode(readValue(buffer)!); - case 133: + case 133: return MediaStatus.decode(readValue(buffer)!); - case 134: + case 134: return MediaTrack.decode(readValue(buffer)!); - case 135: + case 135: return WebImage.decode(readValue(buffer)!); default: return super.readValueOfType(type, buffer); @@ -1157,7 +1164,8 @@ abstract class CastFlutterApi { void onProgressUpdated(int progressMs, int durationMs); - void onAdBreakClipProgressUpdated(String adBreakId, String adBreakClipId, int progressMs, int durationMs, int whenSkippableMs); + void onAdBreakClipProgressUpdated( + String adBreakId, String adBreakClipId, int progressMs, int durationMs, int whenSkippableMs); void itemsInsertedInRange(int insertIndex, int insertCount); @@ -1196,8 +1204,7 @@ abstract class CastFlutterApi { channel.setMessageHandler(null); } else { channel.setMessageHandler((Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.CastFlutterApi.onCastStateChanged was null.'); + assert(message != null, 'Argument for dev.flutter.pigeon.CastFlutterApi.onCastStateChanged was null.'); final List args = (message as List?)!; final int? arg_castState = (args[0] as int?); assert(arg_castState != null, @@ -1215,8 +1222,7 @@ abstract class CastFlutterApi { channel.setMessageHandler(null); } else { channel.setMessageHandler((Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.CastFlutterApi.onMessageReceived was null.'); + assert(message != null, 'Argument for dev.flutter.pigeon.CastFlutterApi.onMessageReceived was null.'); final List args = (message as List?)!; final CastMessage? arg_message = (args[0] as CastMessage?); assert(arg_message != null, @@ -1360,8 +1366,7 @@ abstract class CastFlutterApi { channel.setMessageHandler(null); } else { channel.setMessageHandler((Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.CastFlutterApi.onStatusUpdated was null.'); + assert(message != null, 'Argument for dev.flutter.pigeon.CastFlutterApi.onStatusUpdated was null.'); final List args = (message as List?)!; final MediaStatus? arg_mediaStatus = (args[0] as MediaStatus?); assert(arg_mediaStatus != null, @@ -1435,8 +1440,7 @@ abstract class CastFlutterApi { channel.setMessageHandler(null); } else { channel.setMessageHandler((Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.CastFlutterApi.onAdBreakStatusUpdated was null.'); + assert(message != null, 'Argument for dev.flutter.pigeon.CastFlutterApi.onAdBreakStatusUpdated was null.'); final List args = (message as List?)!; final MediaStatus? arg_mediaStatus = (args[0] as MediaStatus?); assert(arg_mediaStatus != null, @@ -1468,8 +1472,7 @@ abstract class CastFlutterApi { channel.setMessageHandler(null); } else { channel.setMessageHandler((Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.CastFlutterApi.onProgressUpdated was null.'); + assert(message != null, 'Argument for dev.flutter.pigeon.CastFlutterApi.onProgressUpdated was null.'); final List args = (message as List?)!; final int? arg_progressMs = (args[0] as int?); assert(arg_progressMs != null, @@ -1490,8 +1493,8 @@ abstract class CastFlutterApi { channel.setMessageHandler(null); } else { channel.setMessageHandler((Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.CastFlutterApi.onAdBreakClipProgressUpdated was null.'); + assert( + message != null, 'Argument for dev.flutter.pigeon.CastFlutterApi.onAdBreakClipProgressUpdated was null.'); final List args = (message as List?)!; final String? arg_adBreakId = (args[0] as String?); assert(arg_adBreakId != null, @@ -1508,7 +1511,8 @@ abstract class CastFlutterApi { final int? arg_whenSkippableMs = (args[4] as int?); assert(arg_whenSkippableMs != null, 'Argument for dev.flutter.pigeon.CastFlutterApi.onAdBreakClipProgressUpdated was null, expected non-null int.'); - api.onAdBreakClipProgressUpdated(arg_adBreakId!, arg_adBreakClipId!, arg_progressMs!, arg_durationMs!, arg_whenSkippableMs!); + api.onAdBreakClipProgressUpdated( + arg_adBreakId!, arg_adBreakClipId!, arg_progressMs!, arg_durationMs!, arg_whenSkippableMs!); return; }); } @@ -1521,8 +1525,7 @@ abstract class CastFlutterApi { channel.setMessageHandler(null); } else { channel.setMessageHandler((Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.CastFlutterApi.itemsInsertedInRange was null.'); + assert(message != null, 'Argument for dev.flutter.pigeon.CastFlutterApi.itemsInsertedInRange was null.'); final List args = (message as List?)!; final int? arg_insertIndex = (args[0] as int?); assert(arg_insertIndex != null, @@ -1557,8 +1560,7 @@ abstract class CastFlutterApi { channel.setMessageHandler(null); } else { channel.setMessageHandler((Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.CastFlutterApi.itemsRemovedAtIndexes was null.'); + assert(message != null, 'Argument for dev.flutter.pigeon.CastFlutterApi.itemsRemovedAtIndexes was null.'); final List args = (message as List?)!; final List? arg_indexes = (args[0] as List?)?.cast(); assert(arg_indexes != null, @@ -1576,8 +1578,7 @@ abstract class CastFlutterApi { channel.setMessageHandler(null); } else { channel.setMessageHandler((Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.CastFlutterApi.itemsReorderedAtIndexes was null.'); + assert(message != null, 'Argument for dev.flutter.pigeon.CastFlutterApi.itemsReorderedAtIndexes was null.'); final List args = (message as List?)!; final List? arg_indexes = (args[0] as List?)?.cast(); assert(arg_indexes != null, @@ -1598,8 +1599,7 @@ abstract class CastFlutterApi { channel.setMessageHandler(null); } else { channel.setMessageHandler((Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.CastFlutterApi.itemsUpdatedAtIndexes was null.'); + assert(message != null, 'Argument for dev.flutter.pigeon.CastFlutterApi.itemsUpdatedAtIndexes was null.'); final List args = (message as List?)!; final List? arg_indexes = (args[0] as List?)?.cast(); assert(arg_indexes != null, diff --git a/lib/src/cast/MediaQueue.dart b/lib/src/cast/MediaQueue.dart index 7039713..bbe3d67 100644 --- a/lib/src/cast/MediaQueue.dart +++ b/lib/src/cast/MediaQueue.dart @@ -4,19 +4,15 @@ import 'package:flutter/material.dart'; import 'package:flutter_cast_framework/src/PlatformBridgeApis.dart'; import 'package:meta/meta.dart'; -typedef MediaQueueItemsInsertedInRangeCallback = void Function( - int insertIndex, int insertCount); -typedef MediaQueueItemsChangedAtIndexesCallback = void Function( - List indexes); -typedef MediaQueueItemsReorderedAtIndexesCallback = void Function( - List indexes, int insertBeforeIndex); +typedef MediaQueueItemsInsertedInRangeCallback = void Function(int insertIndex, int insertCount); +typedef MediaQueueItemsChangedAtIndexesCallback = void Function(List indexes); +typedef MediaQueueItemsReorderedAtIndexesCallback = void Function(List indexes, int insertBeforeIndex); class MediaQueue { final CastHostApi _hostApi; MediaQueue(this._hostApi) { - this.itemUpdatedAtIndexStream = - this._itemUpdatedAtIndexStreamController.stream; + this.itemUpdatedAtIndexStream = this._itemUpdatedAtIndexStreamController.stream; } void dispose() { diff --git a/lib/src/cast/RemoteMediaClient.dart b/lib/src/cast/RemoteMediaClient.dart index b6ca5fd..e2e2950 100644 --- a/lib/src/cast/RemoteMediaClient.dart +++ b/lib/src/cast/RemoteMediaClient.dart @@ -64,8 +64,7 @@ class RemoteMediaClient { /// Called when there is an outgoing request to the receiver. VoidCallback? onSendingRemoteMediaRequest; - final _mediaStatusStreamController = - StreamController.broadcast(); + final _mediaStatusStreamController = StreamController.broadcast(); late Stream mediaStatusStream; /// Called when updated ad break status information is received. diff --git a/lib/src/cast/SessionManager.dart b/lib/src/cast/SessionManager.dart index 3389669..0322263 100644 --- a/lib/src/cast/SessionManager.dart +++ b/lib/src/cast/SessionManager.dart @@ -78,8 +78,7 @@ class SessionManager { late RemoteMediaClient remoteMediaClient; } -typedef MessageReceivedCallback = void Function( - String namespace, String message); +typedef MessageReceivedCallback = void Function(String namespace, String message); /// State of the session enum SessionState { diff --git a/lib/src/cast/widgets/CastButton.dart b/lib/src/cast/widgets/CastButton.dart index c9a57b7..9514121 100644 --- a/lib/src/cast/widgets/CastButton.dart +++ b/lib/src/cast/widgets/CastButton.dart @@ -19,7 +19,7 @@ class CastButton extends StatelessWidget { return GestureDetector( child: Padding( padding: padding, - child: CastIcon( + child: CastIcon( castFramework: castFramework, color: color, ), diff --git a/lib/src/cast/widgets/expanded_controls/ExpandedControls.dart b/lib/src/cast/widgets/expanded_controls/ExpandedControls.dart index 40ac85f..f29f7c0 100644 --- a/lib/src/cast/widgets/expanded_controls/ExpandedControls.dart +++ b/lib/src/cast/widgets/expanded_controls/ExpandedControls.dart @@ -72,11 +72,9 @@ class _ExpandedControlsState extends State { void initState() { final sessionManager = widget.castFramework.castContext.sessionManager; sessionManager.state.addListener(_onSessionStateChanged); - sessionManager.remoteMediaClient.playerState - .addListener(_onPlayerStateChanged); + sessionManager.remoteMediaClient.playerState.addListener(_onPlayerStateChanged); sessionManager.remoteMediaClient.onProgressUpdated = _onProgressUpdated; - sessionManager.remoteMediaClient.onAdBreakClipProgressUpdated = - _onAdBreakClipProgressUpdated; + sessionManager.remoteMediaClient.onAdBreakClipProgressUpdated = _onAdBreakClipProgressUpdated; super.initState(); } @@ -85,8 +83,7 @@ class _ExpandedControlsState extends State { void dispose() { final sessionManager = widget.castFramework.castContext.sessionManager; sessionManager.state.removeListener(_onSessionStateChanged); - sessionManager.remoteMediaClient.playerState - .removeListener(_onPlayerStateChanged); + sessionManager.remoteMediaClient.playerState.removeListener(_onPlayerStateChanged); sessionManager.remoteMediaClient.onProgressUpdated = null; sessionManager.remoteMediaClient.onAdBreakClipProgressUpdated = null; @@ -133,15 +130,12 @@ class _ExpandedControlsState extends State { int durationMs, int whenSkippableMs, ) { - widget.adSkipBoxController - .updateProgress(progressMs, durationMs, whenSkippableMs); + widget.adSkipBoxController.updateProgress(progressMs, durationMs, whenSkippableMs); } Widget _getDecoratedToolbar(MediaInfo? mediaInfo) { - final title = mediaInfo - ?.mediaMetadata?.strings?[describeEnum(MediaMetadataKey.title)]; - final subtitle = mediaInfo - ?.mediaMetadata?.strings?[describeEnum(MediaMetadataKey.subtitle)]; + final title = mediaInfo?.mediaMetadata?.strings?[describeEnum(MediaMetadataKey.title)]; + final subtitle = mediaInfo?.mediaMetadata?.strings?[describeEnum(MediaMetadataKey.subtitle)]; return Container( decoration: _topDownBlackGradient, @@ -197,8 +191,8 @@ class _ExpandedControlsState extends State { return DecorationImage( image: NetworkImage(imgUrl), fit: BoxFit.cover, - onError: (exception, stackTrace) => debugPrint( - "ExpandedControls: error while retrieving image with url: $imgUrl"), + onError: (exception, stackTrace) => + debugPrint("ExpandedControls: error while retrieving image with url: $imgUrl"), ); } @@ -226,8 +220,7 @@ class _ExpandedControlsState extends State { @override Widget build(BuildContext context) { - var remoteMediaClient = - this.widget.castFramework.castContext.sessionManager.remoteMediaClient; + var remoteMediaClient = this.widget.castFramework.castContext.sessionManager.remoteMediaClient; return SafeArea( child: StreamBuilder( diff --git a/lib/src/cast/widgets/expanded_controls/ExpandedControlsAdInfoControls.dart b/lib/src/cast/widgets/expanded_controls/ExpandedControlsAdInfoControls.dart index 6094ff0..36c4564 100644 --- a/lib/src/cast/widgets/expanded_controls/ExpandedControlsAdInfoControls.dart +++ b/lib/src/cast/widgets/expanded_controls/ExpandedControlsAdInfoControls.dart @@ -32,15 +32,14 @@ class ExpandedControlsAdInfoControls extends StatelessWidget { final adBreakId = adBreakStatus?.adBreakId; final adBreakClipId = adBreakStatus?.adBreakClipId; - final hasAdBreakInfo = - adBreakId?.isEmpty == false || adBreakClipId?.isEmpty == false; + final hasAdBreakInfo = adBreakId?.isEmpty == false || adBreakClipId?.isEmpty == false; if (mediaStatus?.isPlayingAd != true && !hasAdBreakInfo) { return Spacer(); } - final adBreakClipInfo = mediaStatus?.mediaInfo?.adBreakClips - ?.firstWhere((a) => a?.id == adBreakClipId, orElse: () => null); + final adBreakClipInfo = + mediaStatus?.mediaInfo?.adBreakClips?.firstWhere((a) => a?.id == adBreakClipId, orElse: () => null); final adTitle = adBreakClipInfo?.title ?? ""; return Expanded( @@ -71,12 +70,10 @@ class ExpandedControlsAdInfoControls extends StatelessWidget { @override Widget build(BuildContext context) { - final remoteMediaClient = - this.castFramework.castContext.sessionManager.remoteMediaClient; + final remoteMediaClient = this.castFramework.castContext.sessionManager.remoteMediaClient; return StreamBuilder( - stream: - remoteMediaClient.mediaStatusStream.distinct(didChangeAdBreakStatus), + stream: remoteMediaClient.mediaStatusStream.distinct(didChangeAdBreakStatus), builder: (BuildContext context, AsyncSnapshot snapshot) { if (snapshot.hasData && snapshot.data?.mediaInfo != null) { var mediaStatus = snapshot.data; diff --git a/lib/src/cast/widgets/expanded_controls/ExpandedControlsAdSkipBox.dart b/lib/src/cast/widgets/expanded_controls/ExpandedControlsAdSkipBox.dart index 10bd02b..1f588aa 100644 --- a/lib/src/cast/widgets/expanded_controls/ExpandedControlsAdSkipBox.dart +++ b/lib/src/cast/widgets/expanded_controls/ExpandedControlsAdSkipBox.dart @@ -21,8 +21,7 @@ const SKIP_AD_TIMER_PLACEHOLDER = "{{skip_remaining_time}}"; class ExpandedControlsAdSkipBox extends StatefulWidget { final ExpandedControlsAdSkipBoxController controller; - final _defaultSkipAdTimerText = - "You can skip this ad in $SKIP_AD_TIMER_PLACEHOLDER..."; + final _defaultSkipAdTimerText = "You can skip this ad in $SKIP_AD_TIMER_PLACEHOLDER..."; final _defaultSkipAdButtonText = "Skip Ad"; /// Label to indicate remaining time for ad. Default is "You can skip this ad in {{skip_remaining_time}}...", @@ -43,8 +42,7 @@ class ExpandedControlsAdSkipBox extends StatefulWidget { }) : super(key: key); @override - State createState() => - _ExpandedControlsAdSkipBoxState(); + State createState() => _ExpandedControlsAdSkipBoxState(); } class _ExpandedControlsAdSkipBoxState extends State { @@ -73,10 +71,8 @@ class _ExpandedControlsAdSkipBoxState extends State { }); } - String _replaceRemainingTime( - String textWithPlaceholder, String remainingTime) { - return textWithPlaceholder.replaceAll( - SKIP_AD_TIMER_PLACEHOLDER, remainingTime); + String _replaceRemainingTime(String textWithPlaceholder, String remainingTime) { + return textWithPlaceholder.replaceAll(SKIP_AD_TIMER_PLACEHOLDER, remainingTime); } @override diff --git a/lib/src/cast/widgets/expanded_controls/ExpandedControlsBasicButton.dart b/lib/src/cast/widgets/expanded_controls/ExpandedControlsBasicButton.dart index 8bc7de0..8e5d3ae 100644 --- a/lib/src/cast/widgets/expanded_controls/ExpandedControlsBasicButton.dart +++ b/lib/src/cast/widgets/expanded_controls/ExpandedControlsBasicButton.dart @@ -15,7 +15,8 @@ class ExpandedControlsBasicButton extends StatelessWidget { return OutlinedButton( onPressed: this.onPressed, style: OutlinedButton.styleFrom( - foregroundColor: Colors.white, backgroundColor: Colors.black, + foregroundColor: Colors.white, + backgroundColor: Colors.black, shape: const RoundedRectangleBorder(), side: BorderSide( width: 1, diff --git a/lib/src/cast/widgets/expanded_controls/ExpandedControlsConnectedDeviceLabel.dart b/lib/src/cast/widgets/expanded_controls/ExpandedControlsConnectedDeviceLabel.dart index b99a803..ada7993 100644 --- a/lib/src/cast/widgets/expanded_controls/ExpandedControlsConnectedDeviceLabel.dart +++ b/lib/src/cast/widgets/expanded_controls/ExpandedControlsConnectedDeviceLabel.dart @@ -20,14 +20,12 @@ class ExpandedControlsConnectedDeviceLabel extends StatelessWidget { }) : super(key: key); String _replaceDeviceName(String textWithPlaceholder, String deviceName) { - return textWithPlaceholder.replaceAll( - CAST_DEVICE_NAME_PLACEHOLDER, deviceName); + return textWithPlaceholder.replaceAll(CAST_DEVICE_NAME_PLACEHOLDER, deviceName); } @override Widget build(BuildContext context) { - final textStyle = - Theme.of(context).textTheme.bodyMedium?.copyWith(color: Colors.white); + final textStyle = Theme.of(context).textTheme.bodyMedium?.copyWith(color: Colors.white); return FutureBuilder( future: castFramework.castContext.sessionManager.getCastDevice(), diff --git a/lib/src/cast/widgets/expanded_controls/ExpandedControlsProgress.dart b/lib/src/cast/widgets/expanded_controls/ExpandedControlsProgress.dart index 5d5ff7a..aa2523a 100644 --- a/lib/src/cast/widgets/expanded_controls/ExpandedControlsProgress.dart +++ b/lib/src/cast/widgets/expanded_controls/ExpandedControlsProgress.dart @@ -20,8 +20,7 @@ class ExpandedControlsProgress extends StatefulWidget { }) : super(key: key); @override - State createState() => - _ExpandedControlsProgressState(); + State createState() => _ExpandedControlsProgressState(); } class _ExpandedControlsProgressState extends State { @@ -50,8 +49,7 @@ class _ExpandedControlsProgressState extends State { @override Widget build(BuildContext context) { - final textStyle = - Theme.of(context).textTheme.bodyMedium?.copyWith(color: Colors.white); + final textStyle = Theme.of(context).textTheme.bodyMedium?.copyWith(color: Colors.white); // this is the denominator, can't be 0 final durationFix = this.duration == 0 ? 1 : this.duration; diff --git a/lib/src/cast/widgets/expanded_controls/ExpandedControlsToolbar.dart b/lib/src/cast/widgets/expanded_controls/ExpandedControlsToolbar.dart index 9be61ae..b839a56 100644 --- a/lib/src/cast/widgets/expanded_controls/ExpandedControlsToolbar.dart +++ b/lib/src/cast/widgets/expanded_controls/ExpandedControlsToolbar.dart @@ -18,13 +18,10 @@ class ExpandedControlsToolbar extends StatelessWidget { @override Widget build(BuildContext context) { - final titleStyle = Theme.of(context) - .textTheme - .headlineSmall - ?.copyWith(fontWeight: FontWeight.bold, color: Colors.white); + final titleStyle = + Theme.of(context).textTheme.headlineSmall?.copyWith(fontWeight: FontWeight.bold, color: Colors.white); - final subtitleStyle = - Theme.of(context).textTheme.titleMedium?.copyWith(color: Colors.grey); + final subtitleStyle = Theme.of(context).textTheme.titleMedium?.copyWith(color: Colors.grey); return Row( children: [ diff --git a/lib/src/cast/widgets/mini_controller/MiniController.dart b/lib/src/cast/widgets/mini_controller/MiniController.dart index e85a2cb..e678dc7 100644 --- a/lib/src/cast/widgets/mini_controller/MiniController.dart +++ b/lib/src/cast/widgets/mini_controller/MiniController.dart @@ -24,10 +24,8 @@ class MiniController extends StatelessWidget { final thumbnail = MiniControllerThumbnail(mediaInfo: status?.mediaInfo); final mediaInfo = status?.mediaInfo; - final titleText = mediaInfo - ?.mediaMetadata?.strings?[describeEnum(MediaMetadataKey.title)]; - final subtitleText = mediaInfo - ?.mediaMetadata?.strings?[describeEnum(MediaMetadataKey.subtitle)]; + final titleText = mediaInfo?.mediaMetadata?.strings?[describeEnum(MediaMetadataKey.title)]; + final subtitleText = mediaInfo?.mediaMetadata?.strings?[describeEnum(MediaMetadataKey.subtitle)]; final title = Text( titleText ?? "", maxLines: 1, @@ -73,8 +71,7 @@ class MiniController extends StatelessWidget { @override Widget build(BuildContext context) { - var remoteMediaClient = - this.castFramework.castContext.sessionManager.remoteMediaClient; + var remoteMediaClient = this.castFramework.castContext.sessionManager.remoteMediaClient; return Stack( children: [ diff --git a/lib/src/cast/widgets/mini_controller/MiniControllerPlayPauseButton.dart b/lib/src/cast/widgets/mini_controller/MiniControllerPlayPauseButton.dart index 4885c9d..46eb6cf 100644 --- a/lib/src/cast/widgets/mini_controller/MiniControllerPlayPauseButton.dart +++ b/lib/src/cast/widgets/mini_controller/MiniControllerPlayPauseButton.dart @@ -13,15 +13,13 @@ class MiniControllerPlayPauseButton extends StatelessWidget { }) : super(key: key); void _onPausePressed() { - var remoteMediaClient = - this.castFramework.castContext.sessionManager.remoteMediaClient; + var remoteMediaClient = this.castFramework.castContext.sessionManager.remoteMediaClient; remoteMediaClient.pause(); } void _onPlayPressed() { - var remoteMediaClient = - this.castFramework.castContext.sessionManager.remoteMediaClient; + var remoteMediaClient = this.castFramework.castContext.sessionManager.remoteMediaClient; remoteMediaClient.play(); } diff --git a/lib/src/cast/widgets/mini_controller/MiniControllerProgress.dart b/lib/src/cast/widgets/mini_controller/MiniControllerProgress.dart index 659542f..5a3a611 100644 --- a/lib/src/cast/widgets/mini_controller/MiniControllerProgress.dart +++ b/lib/src/cast/widgets/mini_controller/MiniControllerProgress.dart @@ -15,13 +15,11 @@ class MiniControllerProgress extends StatefulWidget { } class _MiniControllerProgressState extends State { - double? _newValue; @override Widget build(BuildContext context) { - final remoteMediaClient = - this.widget.castFramework.castContext.sessionManager.remoteMediaClient; + final remoteMediaClient = this.widget.castFramework.castContext.sessionManager.remoteMediaClient; return StreamBuilder( stream: remoteMediaClient.progressStream, @@ -62,8 +60,7 @@ class _MiniControllerProgressState extends State { } void _onChangeEnd(double value, int duration) { - final remoteMediaClient = - this.widget.castFramework.castContext.sessionManager.remoteMediaClient; + final remoteMediaClient = this.widget.castFramework.castContext.sessionManager.remoteMediaClient; remoteMediaClient.seekTo((value * duration).toInt()); diff --git a/lib/src/cast/widgets/queue_list/utils.dart b/lib/src/cast/widgets/queue_list/utils.dart index f08f5cf..d4c30af 100644 --- a/lib/src/cast/widgets/queue_list/utils.dart +++ b/lib/src/cast/widgets/queue_list/utils.dart @@ -1,6 +1,5 @@ import 'package:flutter/widgets.dart'; -typedef EmptyStateBuilder = Widget Function( - BuildContext context, bool isLoading, Object? error); +typedef EmptyStateBuilder = Widget Function(BuildContext context, bool isLoading, Object? error); final defaultEmptyState = () => SizedBox.shrink(); diff --git a/lib/src/flutter_cast_framework.dart b/lib/src/flutter_cast_framework.dart index 84231f2..b08c7e5 100644 --- a/lib/src/flutter_cast_framework.dart +++ b/lib/src/flutter_cast_framework.dart @@ -153,8 +153,8 @@ class _CastFlutterApiImplementor extends CastFlutterApi { } @override - void onAdBreakClipProgressUpdated(String adBreakId, String adBreakClipId, - int progressMs, int durationMs, int whenSkippableMs) { + void onAdBreakClipProgressUpdated( + String adBreakId, String adBreakClipId, int progressMs, int durationMs, int whenSkippableMs) { remoteMediaClient.onAdBreakClipProgressUpdated?.call( adBreakId, adBreakClipId, diff --git a/pubspec.lock b/pubspec.lock index dd96de2..4e4a5f9 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -45,10 +45,10 @@ packages: dependency: transitive description: name: characters - sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605" + sha256: faf38497bda5ead2a8c7615f4f7939df04333478bf32e4173fcb06d428b5716b url: "https://pub.dev" source: hosted - version: "1.3.0" + version: "1.4.1" cli_util: dependency: transitive description: @@ -61,18 +61,18 @@ packages: dependency: transitive description: name: clock - sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf + sha256: fddb70d9b5277016c77a80201021d40a2247104d9f4aa7bab7157b7e3f05b84b url: "https://pub.dev" source: hosted - version: "1.1.1" + version: "1.1.2" collection: dependency: transitive description: name: collection - sha256: "4a07be6cb69c84d677a6c3096fcf960cc3285a8330b4603e0d463d15d9bd934c" + sha256: "2f5709ae4d3d59dd8f7cd309b4e023046b57d8a6c82130785d2b0e5868084e76" url: "https://pub.dev" source: hosted - version: "1.17.1" + version: "1.19.1" convert: dependency: transitive description: @@ -109,10 +109,10 @@ packages: dependency: transitive description: name: fake_async - sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78" + sha256: "5368f224a74523e8d2e7399ea1638b37aecfca824a3cc4dfdf77bf1fa905ac44" url: "https://pub.dev" source: hosted - version: "1.3.1" + version: "1.3.3" file: dependency: transitive description: @@ -155,14 +155,30 @@ packages: url: "https://pub.dev" source: hosted version: "0.15.1" - js: + leak_tracker: + dependency: transitive + description: + name: leak_tracker + sha256: "33e2e26bdd85a0112ec15400c8cbffea70d0f9c3407491f672a2fad47915e2de" + url: "https://pub.dev" + source: hosted + version: "11.0.2" + leak_tracker_flutter_testing: dependency: transitive description: - name: js - sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3 + name: leak_tracker_flutter_testing + sha256: "1dbc140bb5a23c75ea9c4811222756104fbcd1a27173f0c34ca01e16bea473c1" url: "https://pub.dev" source: hosted - version: "0.6.7" + version: "3.0.10" + leak_tracker_testing: + dependency: transitive + description: + name: leak_tracker_testing + sha256: "8d5a2d49f4a66b49744b23b018848400d23e54caf9463f4eb20df3eb8acb2eb1" + url: "https://pub.dev" + source: hosted + version: "3.0.2" logging: dependency: transitive description: @@ -183,26 +199,26 @@ packages: dependency: transitive description: name: matcher - sha256: "6501fbd55da300384b768785b83e5ce66991266cec21af89ab9ae7f5ce1c4cbb" + sha256: "12956d0ad8390bbcc63ca2e1469c0619946ccb52809807067a7020d57e647aa6" url: "https://pub.dev" source: hosted - version: "0.12.15" + version: "0.12.18" material_color_utilities: dependency: transitive description: name: material_color_utilities - sha256: d92141dc6fe1dad30722f9aa826c7fbc896d021d792f80678280601aff8cf724 + sha256: "9c337007e82b1889149c82ed242ed1cb24a66044e30979c44912381e9be4c48b" url: "https://pub.dev" source: hosted - version: "0.2.0" + version: "0.13.0" meta: dependency: "direct main" description: name: meta - sha256: "3c74dbf8763d36539f114c799d8a2d87343b5067e9d796ca22b5eb8437090ee3" + sha256: "23f08335362185a5ea2ad3a4e597f1375e78bce8a040df5c600c8d3552ef2394" url: "https://pub.dev" source: hosted - version: "1.9.1" + version: "1.17.0" package_config: dependency: transitive description: @@ -215,10 +231,10 @@ packages: dependency: transitive description: name: path - sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917" + sha256: "75cca69d1490965be98c73ceaea117e8a04dd21217b37b292c9ddbec0d955bc5" url: "https://pub.dev" source: hosted - version: "1.8.3" + version: "1.9.1" path_parsing: dependency: transitive description: @@ -263,7 +279,7 @@ packages: dependency: transitive description: flutter source: sdk - version: "0.0.99" + version: "0.0.0" source_span: dependency: transitive description: @@ -276,18 +292,18 @@ packages: dependency: transitive description: name: stack_trace - sha256: c3c7d8edb15bee7f0f74debd4b9c5f3c2ea86766fe4178eb2a18eb30a0bdaed5 + sha256: "8b27215b45d22309b5cddda1aa2b19bdfec9df0e765f2de506401c071d38d1b1" url: "https://pub.dev" source: hosted - version: "1.11.0" + version: "1.12.1" stream_channel: dependency: transitive description: name: stream_channel - sha256: "83615bee9045c1d322bbbd1ba209b7a749c2cbcdcb3fdd1df8eb488b3279c1c8" + sha256: "969e04c80b8bcdf826f8f16579c7b14d780458bd97f56d107d3950fdbeef059d" url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "2.1.4" string_scanner: dependency: transitive description: @@ -308,10 +324,10 @@ packages: dependency: transitive description: name: test_api - sha256: eb6ac1540b26de412b3403a163d919ba86f6a973fe6cc50ae3541b80092fdcfb + sha256: "93167629bfc610f71560ab9312acdda4959de4df6fac7492c89ff0d3886f6636" url: "https://pub.dev" source: hosted - version: "0.5.1" + version: "0.7.9" typed_data: dependency: transitive description: @@ -348,10 +364,18 @@ packages: dependency: transitive description: name: vector_math - sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" + sha256: d530bd74fea330e6e364cda7a85019c434070188383e1cd8d9777ee586914c5b url: "https://pub.dev" source: hosted - version: "2.1.4" + version: "2.2.0" + vm_service: + dependency: transitive + description: + name: vm_service + sha256: "0016aef94fc66495ac78af5859181e3f3bf2026bd8eecc72b9565601e19ab360" + url: "https://pub.dev" + source: hosted + version: "15.2.0" watcher: dependency: transitive description: @@ -377,5 +401,5 @@ packages: source: hosted version: "3.1.1" sdks: - dart: ">=3.0.0-0 <4.0.0" - flutter: ">=3.7.0-0" + dart: ">=3.9.0-0 <4.0.0" + flutter: ">=3.18.0-18.0.pre.54"