diff --git a/ios/Classes/FCPEnums.swift b/ios/Classes/FCPEnums.swift index 22f209c..613afec 100644 --- a/ios/Classes/FCPEnums.swift +++ b/ios/Classes/FCPEnums.swift @@ -23,6 +23,7 @@ enum FCPChannelTypes { static let onPresentStateChanged = "onPresentStateChanged" static let popTemplate = "popTemplate" static let pushTemplate = "pushTemplate" + static let showNowPlaying = "showNowPlaying" static let closePresent = "closePresent" static let onGridButtonPressed = "onGridButtonPressed" static let setActionSheet = "setActionSheet" diff --git a/ios/Classes/SwiftFlutterCarplayPlugin.swift b/ios/Classes/SwiftFlutterCarplayPlugin.swift index f42a900..3a0cf25 100644 --- a/ios/Classes/SwiftFlutterCarplayPlugin.swift +++ b/ios/Classes/SwiftFlutterCarplayPlugin.swift @@ -13,6 +13,7 @@ public class SwiftFlutterCarplayPlugin: NSObject, FlutterPlugin { private static var streamHandler: FCPStreamHandlerPlugin? private(set) static var registrar: FlutterPluginRegistrar? private static var objcRootTemplate: FCPRootTemplate? + private static var templateStack: [FCPRootTemplate] = [] private static var _rootTemplate: CPTemplate? public static var animated: Bool = false private var objcPresentTemplate: FCPPresentTemplate? @@ -43,6 +44,8 @@ public class SwiftFlutterCarplayPlugin: NSObject, FlutterPlugin { result(false) return } + + SwiftFlutterCarplayPlugin.templateStack = [] var rootTemplate: FCPRootTemplate? switch args["runtimeType"] as! String { case String(describing: FCPTabBarTemplate.self): @@ -156,6 +159,7 @@ public class SwiftFlutterCarplayPlugin: NSObject, FlutterPlugin { return } for _ in 1...(args["count"] as! Int) { + SwiftFlutterCarplayPlugin.templateStack.removeLast() FlutterCarPlaySceneDelegate.pop(animated: args["animated"] as! Bool) } result(true) @@ -169,6 +173,16 @@ public class SwiftFlutterCarplayPlugin: NSObject, FlutterPlugin { self.objcPresentTemplate = nil result(true) break + case FCPChannelTypes.showNowPlaying: + guard let animated = call.arguments as? Bool else { + result(false) + return + } + let template = FCPSharedNowPlayingTemplate() + SwiftFlutterCarplayPlugin.templateStack.append(template) + FlutterCarPlaySceneDelegate.push(template: template.get, animated: animated) + result(true) + break case FCPChannelTypes.pushTemplate: guard let args = call.arguments as? [String : Any] else { result(false) @@ -178,17 +192,25 @@ public class SwiftFlutterCarplayPlugin: NSObject, FlutterPlugin { let animated = args["animated"] as! Bool switch args["runtimeType"] as! String { case String(describing: FCPGridTemplate.self): - pushTemplate = FCPGridTemplate(obj: args["template"] as! [String : Any]).get + let template = FCPGridTemplate(obj: args["template"] as! [String : Any]) + SwiftFlutterCarplayPlugin.templateStack.append(template) + pushTemplate = template.get break case String(describing: FCPPointOfInterestTemplate.self): - pushTemplate = FCPPointOfInterestTemplate(obj: args["template"] as! [String : Any]).get + let template = FCPPointOfInterestTemplate(obj: args["template"] as! [String : Any]) + SwiftFlutterCarplayPlugin.templateStack.append(template) + pushTemplate = template.get break case String(describing: FCPInformationTemplate.self): - pushTemplate = FCPInformationTemplate(obj: args["template"] as! [String : Any]).get + let template = FCPInformationTemplate(obj: args["template"] as! [String : Any]) + SwiftFlutterCarplayPlugin.templateStack.append(template) + pushTemplate = template.get break case String(describing: FCPListTemplate.self): - pushTemplate = FCPListTemplate(obj: args["template"] as! [String : Any], templateType: FCPListTemplateTypes.DEFAULT).get + let template = FCPListTemplate(obj: args["template"] as! [String : Any], templateType: FCPListTemplateTypes.DEFAULT) + SwiftFlutterCarplayPlugin.templateStack.append(template) + pushTemplate = template.get break default: result(false) @@ -202,6 +224,7 @@ public class SwiftFlutterCarplayPlugin: NSObject, FlutterPlugin { result(false) return } + SwiftFlutterCarplayPlugin.templateStack = [] FlutterCarPlaySceneDelegate.popToRootTemplate(animated: animated) self.objcPresentTemplate = nil result(true) @@ -228,17 +251,29 @@ public class SwiftFlutterCarplayPlugin: NSObject, FlutterPlugin { var templates: [FCPListTemplate] = [] if (objcRootTemplateType.elementsEqual(String(describing: FCPListTemplate.self))) { templates.append(SwiftFlutterCarplayPlugin.objcRootTemplate as! FCPListTemplate) + NSLog("FCP: FCPListTemplate") } else if (objcRootTemplateType.elementsEqual(String(describing: FCPTabBarTemplate.self))) { templates = (SwiftFlutterCarplayPlugin.objcRootTemplate as! FCPTabBarTemplate).getTemplates() + NSLog("FCP: FCPTabBarTemplate") } else { + NSLog("FCP: No Template") return } - l1: for t in templates { + for t in templateStack { + if (t is FCPListTemplate) { + guard let template = t as? FCPListTemplate else { + break; + } + templates.append(template) + } + } + + for t in templates { for s in t.getSections() { for i in s.getItems() { if (i.elementId == elementId) { actionWhenFound(i) - break l1 + return } } } diff --git a/ios/Classes/models/FCPSharedNowPlayingTemplate.swift b/ios/Classes/models/FCPSharedNowPlayingTemplate.swift new file mode 100644 index 0000000..e43e166 --- /dev/null +++ b/ios/Classes/models/FCPSharedNowPlayingTemplate.swift @@ -0,0 +1,18 @@ +// +// FCPSharedNowPlaying.swift +// flutter_carplay +// +// Created by Koen Van Looveren on 16/09/2022. +// + +import CarPlay + +@available(iOS 14.0, *) +class FCPSharedNowPlayingTemplate { + var get: CPNowPlayingTemplate { + return CPNowPlayingTemplate.shared + } +} + +@available(iOS 14.0, *) +extension FCPSharedNowPlayingTemplate: FCPRootTemplate { } diff --git a/lib/carplay_worker.dart b/lib/carplay_worker.dart index 50c2916..aa570d3 100644 --- a/lib/carplay_worker.dart +++ b/lib/carplay_worker.dart @@ -288,4 +288,17 @@ class FlutterCarplay { throw TypeError(); } } + + /// Navigate to the shared instance of the NowPlaying Template + /// + /// - If animated is true, CarPlay animates the transition between templates. + static Future showSharedNowPlaying({ + bool animated = true, + }) async { + bool isCompleted = await _carPlayController.reactToNativeModule( + FCPChannelTypes.showNowPlaying, + animated, + ); + return isCompleted; + } } diff --git a/lib/constants/private_constants.dart b/lib/constants/private_constants.dart index 65dfb4c..63cb643 100644 --- a/lib/constants/private_constants.dart +++ b/lib/constants/private_constants.dart @@ -11,6 +11,7 @@ enum FCPChannelTypes { popTemplate, closePresent, pushTemplate, + showNowPlaying, onGridButtonPressed, setActionSheet, onBarButtonPressed,