diff options
author | leonid lokhmatov, Luxoft <zaqqqqqqqq@gmail.com> | 2021-02-25 13:33:20 +0200 |
---|---|---|
committer | leonid lokhmatov, Luxoft <zaqqqqqqqq@gmail.com> | 2021-02-25 13:33:20 +0200 |
commit | 146229f0529f76c33cbc862c74ea7f6d6f4da669 (patch) | |
tree | a36c0b2da7d573951dc5f2ca5a358202adaaf3e7 | |
parent | f237c0a49b4c67cdce720bb609d0f73206f0ffb6 (diff) | |
parent | c9db35d11bc18c8f7a341f0f4231a381f9e3be2e (diff) | |
download | sdl_ios-146229f0529f76c33cbc862c74ea7f6d6f4da669.tar.gz |
[0296] 'upd video stream cap (5)' : Merge branch 'develop' into this. Conflicts in xcodeproj/project.pbxproj resolved
66 files changed, 1871 insertions, 266 deletions
diff --git a/Example Apps/Example ObjC/MenuManager.m b/Example Apps/Example ObjC/MenuManager.m index ff6385196..b4f370477 100644 --- a/Example Apps/Example ObjC/MenuManager.m +++ b/Example Apps/Example ObjC/MenuManager.m @@ -43,7 +43,7 @@ NS_ASSUME_NONNULL_BEGIN #pragma mark - Menu Items + (SDLMenuCell *)sdlex_menuCellSpeakNameWithManager:(SDLManager *)manager { - return [[SDLMenuCell alloc] initWithTitle:ACSpeakAppNameMenuName icon:[SDLArtwork artworkWithImage:[[UIImage imageNamed:SpeakBWIconImageName] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate] asImageFormat:SDLArtworkImageFormatPNG] voiceCommands:@[ACSpeakAppNameMenuName] handler:^(SDLTriggerSource _Nonnull triggerSource) { + return [[SDLMenuCell alloc] initWithTitle:ACSpeakAppNameMenuName icon:[SDLArtwork artworkWithImage:[[UIImage imageNamed:SpeakBWIconImageName] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate] asImageFormat:SDLArtworkImageFormatPNG] voiceCommands:@[ACSpeakAppNameMenuName] secondaryText:nil tertiaryText:nil secondaryArtwork:nil handler:^(SDLTriggerSource _Nonnull triggerSource) { [manager sendRequest:[[SDLSpeak alloc] initWithTTS:ExampleAppNameTTS]]; }]; } @@ -52,13 +52,13 @@ NS_ASSUME_NONNULL_BEGIN NSMutableArray *submenuItems = [[NSMutableArray alloc] init]; NSArray<NSString *> *allVehicleDataTypes = [self sdlex_allVehicleDataTypes]; for (NSString *vehicleDataType in allVehicleDataTypes) { - SDLMenuCell *cell = [[SDLMenuCell alloc] initWithTitle:vehicleDataType icon:[SDLArtwork artworkWithStaticIcon:SDLStaticIconNameSettings] voiceCommands:nil handler:^(SDLTriggerSource _Nonnull triggerSource) { + SDLMenuCell *cell = [[SDLMenuCell alloc] initWithTitle:vehicleDataType icon:[SDLArtwork artworkWithStaticIcon:SDLStaticIconNameSettings] voiceCommands:nil secondaryText:nil tertiaryText:nil secondaryArtwork:nil handler:^(SDLTriggerSource _Nonnull triggerSource) { [VehicleDataManager getAllVehicleDataWithManager:manager triggerSource:triggerSource vehicleDataType:vehicleDataType]; }]; [submenuItems addObject:cell]; } - return [[SDLMenuCell alloc] initWithTitle:ACGetAllVehicleDataMenuName icon:[SDLArtwork artworkWithImage:[[UIImage imageNamed:CarBWIconImageName] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate] asImageFormat:SDLArtworkImageFormatPNG] submenuLayout:SDLMenuLayoutTiles subCells:submenuItems]; + return [[SDLMenuCell alloc] initWithTitle:ACGetAllVehicleDataMenuName icon:[SDLArtwork artworkWithImage:[[UIImage imageNamed:CarBWIconImageName] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate] asImageFormat:SDLArtworkImageFormatPNG] submenuLayout:SDLMenuLayoutTiles subCells:submenuItems secondaryText:nil tertiaryText:nil secondaryArtwork:nil]; } + (NSArray<NSString *> *)sdlex_allVehicleDataTypes { @@ -66,20 +66,20 @@ NS_ASSUME_NONNULL_BEGIN } + (SDLMenuCell *)sdlex_menuCellShowPerformInteractionWithManager:(SDLManager *)manager performManager:(PerformInteractionManager *)performManager { - return [[SDLMenuCell alloc] initWithTitle:ACShowChoiceSetMenuName icon:[SDLArtwork artworkWithImage:[[UIImage imageNamed:MenuBWIconImageName] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate] asImageFormat:SDLArtworkImageFormatPNG] voiceCommands:@[ACShowChoiceSetMenuName] handler:^(SDLTriggerSource _Nonnull triggerSource) { + return [[SDLMenuCell alloc] initWithTitle:ACShowChoiceSetMenuName icon:[SDLArtwork artworkWithImage:[[UIImage imageNamed:MenuBWIconImageName] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate] asImageFormat:SDLArtworkImageFormatPNG] voiceCommands:@[ACShowChoiceSetMenuName] secondaryText:nil tertiaryText:nil secondaryArtwork:nil handler:^(SDLTriggerSource _Nonnull triggerSource) { [performManager showWithTriggerSource:triggerSource]; }]; } + (SDLMenuCell *)sdlex_menuCellRecordInCarMicrophoneAudioWithManager:(SDLManager *)manager { AudioManager *audioManager = [[AudioManager alloc] initWithManager:manager]; - return [[SDLMenuCell alloc] initWithTitle:ACRecordInCarMicrophoneAudioMenuName icon:[SDLArtwork artworkWithImage:[[UIImage imageNamed:MicrophoneBWIconImageName] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate] asImageFormat:SDLArtworkImageFormatPNG] voiceCommands:@[ACRecordInCarMicrophoneAudioMenuName] handler:^(SDLTriggerSource _Nonnull triggerSource) { + return [[SDLMenuCell alloc] initWithTitle:ACRecordInCarMicrophoneAudioMenuName icon:[SDLArtwork artworkWithImage:[[UIImage imageNamed:MicrophoneBWIconImageName] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate] asImageFormat:SDLArtworkImageFormatPNG] voiceCommands:@[ACRecordInCarMicrophoneAudioMenuName] secondaryText:nil tertiaryText:nil secondaryArtwork:nil handler:^(SDLTriggerSource _Nonnull triggerSource) { [audioManager startRecording]; }]; } + (SDLMenuCell *)sdlex_menuCellDialNumberWithManager:(SDLManager *)manager { - return [[SDLMenuCell alloc] initWithTitle:ACDialPhoneNumberMenuName icon:[SDLArtwork artworkWithImage:[[UIImage imageNamed:PhoneBWIconImageName] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate] asImageFormat:SDLArtworkImageFormatPNG] voiceCommands:@[ACDialPhoneNumberMenuName] handler:^(SDLTriggerSource _Nonnull triggerSource) { + return [[SDLMenuCell alloc] initWithTitle:ACDialPhoneNumberMenuName icon:[SDLArtwork artworkWithImage:[[UIImage imageNamed:PhoneBWIconImageName] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate] asImageFormat:SDLArtworkImageFormatPNG] voiceCommands:@[ACDialPhoneNumberMenuName] secondaryText:nil tertiaryText:nil secondaryArtwork:nil handler:^(SDLTriggerSource _Nonnull triggerSource) { if (![RPCPermissionsManager isDialNumberRPCAllowedWithManager:manager]) { [AlertManager sendAlertWithManager:manager image:nil textField1:AlertDialNumberPermissionsWarningText textField2:nil]; return; @@ -96,7 +96,7 @@ NS_ASSUME_NONNULL_BEGIN NSString *errorMessage = @"Changing the template failed"; // Non - Media - SDLMenuCell *cell = [[SDLMenuCell alloc] initWithTitle:@"Non - Media (Default)" icon:nil voiceCommands:nil handler:^(SDLTriggerSource _Nonnull triggerSource) { + SDLMenuCell *cell = [[SDLMenuCell alloc] initWithTitle:@"Non - Media (Default)" icon:nil voiceCommands:nil secondaryText:nil tertiaryText:nil secondaryArtwork:nil handler:^(SDLTriggerSource _Nonnull triggerSource) { [manager.screenManager changeLayout:[[SDLTemplateConfiguration alloc] initWithPredefinedLayout:SDLPredefinedLayoutNonMedia] withCompletionHandler:^(NSError * _Nullable error) { if (error != nil) { [AlertManager sendAlertWithManager:manager image:nil textField1:errorMessage textField2:nil]; @@ -106,7 +106,7 @@ NS_ASSUME_NONNULL_BEGIN [submenuItems addObject:cell]; // Graphic With Text - SDLMenuCell *cell2 = [[SDLMenuCell alloc] initWithTitle:@"Graphic With Text" icon:nil voiceCommands:nil handler:^(SDLTriggerSource _Nonnull triggerSource) { + SDLMenuCell *cell2 = [[SDLMenuCell alloc] initWithTitle:@"Graphic With Text" icon:nil voiceCommands:nil secondaryText:nil tertiaryText:nil secondaryArtwork:nil handler:^(SDLTriggerSource _Nonnull triggerSource) { [manager.screenManager changeLayout:[[SDLTemplateConfiguration alloc] initWithPredefinedLayout:SDLPredefinedLayoutGraphicWithText] withCompletionHandler:^(NSError * _Nullable error) { if (error != nil) { [AlertManager sendAlertWithManager:manager image:nil textField1:errorMessage textField2:nil]; @@ -115,23 +115,23 @@ NS_ASSUME_NONNULL_BEGIN }]; [submenuItems addObject:cell2]; - return [[SDLMenuCell alloc] initWithTitle:ACSubmenuTemplateMenuName icon:nil submenuLayout:SDLMenuLayoutList subCells:[submenuItems copy]]; + return [[SDLMenuCell alloc] initWithTitle:ACSubmenuTemplateMenuName icon:nil submenuLayout:SDLMenuLayoutList subCells:[submenuItems copy] secondaryText:nil tertiaryText:nil secondaryArtwork:nil]; } + (SDLMenuCell *)sdlex_menuCellWithSubmenuWithManager:(SDLManager *)manager { NSMutableArray *submenuItems = [NSMutableArray array]; for (int i = 0; i < 75; i++) { - SDLMenuCell *cell = [[SDLMenuCell alloc] initWithTitle:[NSString stringWithFormat:@"%@ %i", ACSubmenuItemMenuName, i] icon:[SDLArtwork artworkWithImage:[[UIImage imageNamed:MenuBWIconImageName] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate] asImageFormat:SDLArtworkImageFormatPNG] voiceCommands:nil handler:^(SDLTriggerSource _Nonnull triggerSource) { + SDLMenuCell *cell = [[SDLMenuCell alloc] initWithTitle:[NSString stringWithFormat:@"%@ %i", ACSubmenuItemMenuName, i] icon:[SDLArtwork artworkWithImage:[[UIImage imageNamed:MenuBWIconImageName] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate] asImageFormat:SDLArtworkImageFormatPNG] voiceCommands:nil secondaryText:nil tertiaryText:nil secondaryArtwork:nil handler:^(SDLTriggerSource _Nonnull triggerSource) { [AlertManager sendAlertWithManager:manager image:nil textField1:[NSString stringWithFormat:@"You selected %@ %i", ACSubmenuItemMenuName, i] textField2:nil]; }]; [submenuItems addObject:cell]; } - return [[SDLMenuCell alloc] initWithTitle:ACSubmenuMenuName icon:[SDLArtwork artworkWithImage:[[UIImage imageNamed:MenuBWIconImageName] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate] asImageFormat:SDLArtworkImageFormatPNG] submenuLayout:SDLMenuLayoutList subCells:[submenuItems copy]]; + return [[SDLMenuCell alloc] initWithTitle:ACSubmenuMenuName icon:[SDLArtwork artworkWithImage:[[UIImage imageNamed:MenuBWIconImageName] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate] asImageFormat:SDLArtworkImageFormatPNG] submenuLayout:SDLMenuLayoutList subCells:[submenuItems copy] secondaryText:nil tertiaryText:nil secondaryArtwork:nil]; } + (SDLMenuCell *)sdlex_sliderMenuCellWithManager:(SDLManager *)manager { - return [[SDLMenuCell alloc] initWithTitle:ACSliderMenuName icon:nil voiceCommands:@[ACSliderMenuName] handler:^(SDLTriggerSource _Nonnull triggerSource) { + return [[SDLMenuCell alloc] initWithTitle:ACSliderMenuName icon:nil voiceCommands:@[ACSliderMenuName] secondaryText:nil tertiaryText:nil secondaryArtwork:nil handler:^(SDLTriggerSource _Nonnull triggerSource) { SDLSlider *sliderRPC = [[SDLSlider alloc] initWithNumTicks:3 position:1 sliderHeader:@"Select a letter" sliderFooters:@[@"A", @"B", @"C"] timeout:10000]; [manager sendRequest:sliderRPC withResponseHandler:^(__kindof SDLRPCRequest * _Nullable request, __kindof SDLRPCResponse * _Nullable response, NSError * _Nullable error) { if(![response.resultCode isEqualToEnum:SDLResultSuccess]) { @@ -148,7 +148,7 @@ NS_ASSUME_NONNULL_BEGIN } + (SDLMenuCell *)sdlex_scrollableMessageMenuCellWithManager:(SDLManager *)manager { - return [[SDLMenuCell alloc] initWithTitle:ACScrollableMessageMenuName icon:nil voiceCommands:@[ACScrollableMessageMenuName] handler:^(SDLTriggerSource _Nonnull triggerSource) { + return [[SDLMenuCell alloc] initWithTitle:ACScrollableMessageMenuName icon:nil voiceCommands:@[ACScrollableMessageMenuName] secondaryText:nil tertiaryText:nil secondaryArtwork:nil handler:^(SDLTriggerSource _Nonnull triggerSource) { SDLScrollableMessage *messageRPC = [[SDLScrollableMessage alloc] initWithMessage:@"This is a scrollable message\nIt can contain many lines"]; [manager sendRequest:messageRPC withResponseHandler:^(__kindof SDLRPCRequest * _Nullable request, __kindof SDLRPCResponse * _Nullable response, NSError * _Nullable error) { if(![response.resultCode isEqualToEnum:SDLResultSuccess]) { diff --git a/Example Apps/Example Swift/MenuManager.swift b/Example Apps/Example Swift/MenuManager.swift index e21a05e10..f7466f06d 100644 --- a/Example Apps/Example Swift/MenuManager.swift +++ b/Example Apps/Example Swift/MenuManager.swift @@ -48,7 +48,7 @@ private extension MenuManager { /// - Parameter manager: The SDL Manager /// - Returns: A SDLMenuCell object class func menuCellSpeakName(with manager: SDLManager) -> SDLMenuCell { - return SDLMenuCell(title: ACSpeakAppNameMenuName, icon: SDLArtwork(image: UIImage(named: SpeakBWIconImageName)!.withRenderingMode(.alwaysTemplate), persistent: true, as: .PNG), voiceCommands: [ACSpeakAppNameMenuName], handler: { _ in + return SDLMenuCell(title: ACSpeakAppNameMenuName, icon: SDLArtwork(image: UIImage(named: SpeakBWIconImageName)!.withRenderingMode(.alwaysTemplate), persistent: true, as: .PNG), voiceCommands: [ACSpeakAppNameMenuName], secondaryText: nil, tertiaryText: nil, secondaryArtwork: nil, handler: { _ in manager.send(request: SDLSpeak(tts: ExampleAppNameTTS), responseHandler: { (_, response, error) in guard response?.resultCode == .success else { return } SDLLog.e("Error sending the Speak RPC: \(error?.localizedDescription ?? "no error message")") @@ -62,12 +62,12 @@ private extension MenuManager { /// - Returns: A SDLMenuCell object class func menuCellGetAllVehicleData(with manager: SDLManager) -> SDLMenuCell { let submenuItems = allVehicleDataTypes.map { submenuName in - SDLMenuCell(title: submenuName, icon: SDLArtwork(staticIcon: .settings), voiceCommands: nil, handler: { triggerSource in + SDLMenuCell(title: submenuName, icon: SDLArtwork(staticIcon: .settings), voiceCommands: nil, secondaryText: nil, tertiaryText: nil, secondaryArtwork: nil, handler: { triggerSource in VehicleDataManager.getAllVehicleData(with: manager, triggerSource: triggerSource, vehicleDataType: submenuName) }) } - return SDLMenuCell(title: ACGetAllVehicleDataMenuName, icon: SDLArtwork(image: UIImage(named: CarBWIconImageName)!.withRenderingMode(.alwaysTemplate), persistent: true, as: .PNG), submenuLayout: .tiles, subCells: submenuItems) + return SDLMenuCell(title: ACGetAllVehicleDataMenuName, icon: SDLArtwork(image: UIImage(named: CarBWIconImageName)!.withRenderingMode(.alwaysTemplate), persistent: true, as: .PNG), submenuLayout: .tiles, subCells: submenuItems, secondaryText: nil, tertiaryText: nil, secondaryArtwork: nil) } /// A list of all possible vehicle data types @@ -80,7 +80,7 @@ private extension MenuManager { /// - Parameter manager: The SDL Manager /// - Returns: A SDLMenuCell object class func menuCellShowPerformInteraction(with manager: SDLManager, choiceSetManager: PerformInteractionManager) -> SDLMenuCell { - return SDLMenuCell(title: ACShowChoiceSetMenuName, icon: SDLArtwork(image: UIImage(named: MenuBWIconImageName)!.withRenderingMode(.alwaysTemplate), persistent: true, as: .PNG), voiceCommands: [ACShowChoiceSetMenuName], handler: { triggerSource in + return SDLMenuCell(title: ACShowChoiceSetMenuName, icon: SDLArtwork(image: UIImage(named: MenuBWIconImageName)!.withRenderingMode(.alwaysTemplate), persistent: true, as: .PNG), voiceCommands: [ACShowChoiceSetMenuName], secondaryText: nil, tertiaryText: nil, secondaryArtwork: nil, handler: { triggerSource in choiceSetManager.show(from: triggerSource) }) } @@ -91,7 +91,7 @@ private extension MenuManager { /// - Returns: A SDLMenuCell object class func menuCellRecordInCarMicrophoneAudio(with manager: SDLManager) -> SDLMenuCell { let audioManager = AudioManager(sdlManager: manager) - return SDLMenuCell(title: ACRecordInCarMicrophoneAudioMenuName, icon: SDLArtwork(image: UIImage(named: MicrophoneBWIconImageName)!.withRenderingMode(.alwaysTemplate), persistent: true, as: .PNG), voiceCommands: [ACRecordInCarMicrophoneAudioMenuName], handler: { _ in + return SDLMenuCell(title: ACRecordInCarMicrophoneAudioMenuName, icon: SDLArtwork(image: UIImage(named: MicrophoneBWIconImageName)!.withRenderingMode(.alwaysTemplate), persistent: true, as: .PNG), voiceCommands: [ACRecordInCarMicrophoneAudioMenuName], secondaryText: nil, tertiaryText: nil, secondaryArtwork: nil, handler: { _ in audioManager.startRecording() }) } @@ -101,7 +101,7 @@ private extension MenuManager { /// - Parameter manager: The SDL Manager /// - Returns: A SDLMenuCell object class func menuCellDialNumber(with manager: SDLManager) -> SDLMenuCell { - return SDLMenuCell(title: ACDialPhoneNumberMenuName, icon: SDLArtwork(image: UIImage(named: PhoneBWIconImageName)!.withRenderingMode(.alwaysTemplate), persistent: true, as: .PNG), voiceCommands: [ACDialPhoneNumberMenuName], handler: { _ in + return SDLMenuCell(title: ACDialPhoneNumberMenuName, icon: SDLArtwork(image: UIImage(named: PhoneBWIconImageName)!.withRenderingMode(.alwaysTemplate), persistent: true, as: .PNG), voiceCommands: [ACDialPhoneNumberMenuName], secondaryText: nil, tertiaryText: nil, secondaryArtwork: nil, handler: { _ in guard RPCPermissionsManager.isDialNumberRPCAllowed(with: manager) else { AlertManager.sendAlert(textField1: AlertDialNumberPermissionsWarningText, sdlManager: manager) return @@ -123,7 +123,7 @@ private extension MenuManager { /// Non-Media let submenuTitleNonMedia = "Non - Media (Default)" - submenuItems.append(SDLMenuCell(title: submenuTitleNonMedia, icon: nil, voiceCommands: nil, handler: { (triggerSource) in + submenuItems.append(SDLMenuCell(title: submenuTitleNonMedia, icon: nil, voiceCommands: nil, secondaryText: nil, tertiaryText: nil, secondaryArtwork: nil, handler: { (triggerSource) in manager.screenManager.changeLayout(SDLTemplateConfiguration(predefinedLayout: .nonMedia)) { err in if err != nil { AlertManager.sendAlert(textField1: errorMessage, sdlManager: manager) @@ -134,7 +134,7 @@ private extension MenuManager { /// Graphic with Text let submenuTitleGraphicText = "Graphic With Text" - submenuItems.append(SDLMenuCell(title: submenuTitleGraphicText, icon: nil, voiceCommands: nil, handler: { (triggerSource) in + submenuItems.append(SDLMenuCell(title: submenuTitleGraphicText, icon: nil, voiceCommands: nil, secondaryText: nil, tertiaryText: nil, secondaryArtwork: nil, handler: { (triggerSource) in manager.screenManager.changeLayout(SDLTemplateConfiguration(predefinedLayout: .graphicWithText)) { err in if err != nil { AlertManager.sendAlert(textField1: errorMessage, sdlManager: manager) @@ -143,7 +143,7 @@ private extension MenuManager { } })) - return SDLMenuCell(title: ACSubmenuTemplateMenuName, icon: nil, submenuLayout: .list, subCells: submenuItems) + return SDLMenuCell(title: ACSubmenuTemplateMenuName, icon: nil, submenuLayout: .list, subCells: submenuItems, secondaryText: nil, tertiaryText: nil, secondaryArtwork: nil) } /// Menu item that opens a submenu when selected @@ -154,7 +154,7 @@ private extension MenuManager { var submenuItems = [SDLMenuCell]() for i in 0 ..< 10 { let submenuTitle = "Submenu Item \(i)" - submenuItems.append(SDLMenuCell(title: submenuTitle, icon: SDLArtwork(image: UIImage(named: MenuBWIconImageName)!.withRenderingMode(.alwaysTemplate), persistent: true, as: .PNG), voiceCommands: nil, handler: { (triggerSource) in + submenuItems.append(SDLMenuCell(title: submenuTitle, icon: SDLArtwork(image: UIImage(named: MenuBWIconImageName)!.withRenderingMode(.alwaysTemplate), persistent: true, as: .PNG), voiceCommands: nil, secondaryText: nil, tertiaryText: nil, secondaryArtwork: nil, handler: { (triggerSource) in let message = "\(submenuTitle) selected!" switch triggerSource { case .menu: @@ -166,11 +166,11 @@ private extension MenuManager { })) } - return SDLMenuCell(title: ACSubmenuMenuName, icon: SDLArtwork(image: #imageLiteral(resourceName: "choice_set").withRenderingMode(.alwaysTemplate), persistent: true, as: .PNG), submenuLayout: .list, subCells: submenuItems) + return SDLMenuCell(title: ACSubmenuMenuName, icon: SDLArtwork(image: #imageLiteral(resourceName: "choice_set").withRenderingMode(.alwaysTemplate), persistent: true, as: .PNG), submenuLayout: .list, subCells: submenuItems, secondaryText: nil, tertiaryText: nil, secondaryArtwork: nil) } private class func sliderMenuCell(with manager: SDLManager) -> SDLMenuCell { - return SDLMenuCell(title: ACSliderMenuName, icon: nil, voiceCommands: [ACSliderMenuName], handler: { _ in + return SDLMenuCell(title: ACSliderMenuName, icon: nil, voiceCommands: [ACSliderMenuName], secondaryText: nil, tertiaryText: nil, secondaryArtwork: nil, handler: { _ in let slider = SDLSlider(numTicks: 3, position: 1, sliderHeader: "Select a letter", sliderFooters: ["A", "B", "C"], timeout: 3000) manager.send(request: slider, responseHandler: { (request, response, error) in guard let response = response else { return } @@ -189,7 +189,7 @@ private extension MenuManager { } private class func scrollableMessageMenuCell(with manager: SDLManager) -> SDLMenuCell { - return SDLMenuCell(title: ACScrollableMessageMenuName, icon: nil, voiceCommands: [ACScrollableMessageMenuName], handler: { _ in + return SDLMenuCell(title: ACScrollableMessageMenuName, icon: nil, voiceCommands: [ACScrollableMessageMenuName], secondaryText: nil, tertiaryText: nil, secondaryArtwork: nil, handler: { _ in let scrollableMessage = SDLScrollableMessage(message: "This is a scrollable message\nIt can contain many lines") manager.send(request: scrollableMessage, responseHandler: { (request, response, error) in guard let response = response else { return } diff --git a/SmartDeviceLink-iOS.xcodeproj/project.pbxproj b/SmartDeviceLink-iOS.xcodeproj/project.pbxproj index c063c468a..5843ad0f4 100644 --- a/SmartDeviceLink-iOS.xcodeproj/project.pbxproj +++ b/SmartDeviceLink-iOS.xcodeproj/project.pbxproj @@ -1704,6 +1704,15 @@ B3DF19ED251225300090D7BA /* TestSmartConnectionManager.m in Sources */ = {isa = PBXBuildFile; fileRef = B3DF19EB251225300090D7BA /* TestSmartConnectionManager.m */; }; B3DF19F0251225770090D7BA /* TestStreamingMediaDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = B3DF19EE251225760090D7BA /* TestStreamingMediaDelegate.m */; }; B3DF19F3251225AA0090D7BA /* TestSmartConnection.m in Sources */ = {isa = PBXBuildFile; fileRef = B3DF19F1251225A90090D7BA /* TestSmartConnection.m */; }; + B3A9D9E125D2571000CDFD21 /* SDLKeyboardCapabilities.m in Sources */ = {isa = PBXBuildFile; fileRef = B3A9D9DF25D2571000CDFD21 /* SDLKeyboardCapabilities.m */; }; + B3A9D9E225D2571000CDFD21 /* SDLKeyboardCapabilities.h in Headers */ = {isa = PBXBuildFile; fileRef = B3A9D9E025D2571000CDFD21 /* SDLKeyboardCapabilities.h */; settings = {ATTRIBUTES = (Public, ); }; }; + B3A9D9E725D2578F00CDFD21 /* SDLKeyboardLayoutCapability.m in Sources */ = {isa = PBXBuildFile; fileRef = B3A9D9E525D2578F00CDFD21 /* SDLKeyboardLayoutCapability.m */; }; + B3A9D9E825D2578F00CDFD21 /* SDLKeyboardLayoutCapability.h in Headers */ = {isa = PBXBuildFile; fileRef = B3A9D9E625D2578F00CDFD21 /* SDLKeyboardLayoutCapability.h */; settings = {ATTRIBUTES = (Public, ); }; }; + B3A9D9ED25D2586C00CDFD21 /* SDLKeyboardInputMask.h in Headers */ = {isa = PBXBuildFile; fileRef = B3A9D9EB25D2586C00CDFD21 /* SDLKeyboardInputMask.h */; settings = {ATTRIBUTES = (Public, ); }; }; + B3A9D9EE25D2586C00CDFD21 /* SDLKeyboardInputMask.m in Sources */ = {isa = PBXBuildFile; fileRef = B3A9D9EC25D2586C00CDFD21 /* SDLKeyboardInputMask.m */; }; + B3A9DA0425D26D8500CDFD21 /* SDLKeyboardInputMaskSpec.m in Sources */ = {isa = PBXBuildFile; fileRef = B3A9DA0325D26D8500CDFD21 /* SDLKeyboardInputMaskSpec.m */; }; + B3A9DA0A25D26E1800CDFD21 /* SDLKeyboardCapabilitiesSpec.m in Sources */ = {isa = PBXBuildFile; fileRef = B3A9DA0925D26E1800CDFD21 /* SDLKeyboardCapabilitiesSpec.m */; }; + B3A9DA1225D270EA00CDFD21 /* SDLKeyboardLayoutCapabilitySpec.m in Sources */ = {isa = PBXBuildFile; fileRef = B3A9DA1125D270E900CDFD21 /* SDLKeyboardLayoutCapabilitySpec.m */; }; B3EC9E6E2579AA010039F3AA /* SDLClimateDataSpec.m in Sources */ = {isa = PBXBuildFile; fileRef = B3EC9E6D2579AA010039F3AA /* SDLClimateDataSpec.m */; }; B3F7918324E062C200DB5CAF /* SDLGetVehicleDataSpec.m in Sources */ = {isa = PBXBuildFile; fileRef = 162E824C1A9BDE8A00906325 /* SDLGetVehicleDataSpec.m */; }; C975877F257AEFDB0066F271 /* SDLSeekIndicatorTypeSpec.m in Sources */ = {isa = PBXBuildFile; fileRef = C975877E257AEFDB0066F271 /* SDLSeekIndicatorTypeSpec.m */; }; @@ -3580,6 +3589,15 @@ B3DF19EF251225760090D7BA /* TestStreamingMediaDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TestStreamingMediaDelegate.h; sourceTree = "<group>"; }; B3DF19F1251225A90090D7BA /* TestSmartConnection.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TestSmartConnection.m; sourceTree = "<group>"; }; B3DF19F2251225A90090D7BA /* TestSmartConnection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TestSmartConnection.h; sourceTree = "<group>"; }; + B3A9D9DF25D2571000CDFD21 /* SDLKeyboardCapabilities.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SDLKeyboardCapabilities.m; path = public/SDLKeyboardCapabilities.m; sourceTree = "<group>"; }; + B3A9D9E025D2571000CDFD21 /* SDLKeyboardCapabilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SDLKeyboardCapabilities.h; path = public/SDLKeyboardCapabilities.h; sourceTree = "<group>"; }; + B3A9D9E525D2578F00CDFD21 /* SDLKeyboardLayoutCapability.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SDLKeyboardLayoutCapability.m; path = public/SDLKeyboardLayoutCapability.m; sourceTree = "<group>"; }; + B3A9D9E625D2578F00CDFD21 /* SDLKeyboardLayoutCapability.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SDLKeyboardLayoutCapability.h; path = public/SDLKeyboardLayoutCapability.h; sourceTree = "<group>"; }; + B3A9D9EB25D2586C00CDFD21 /* SDLKeyboardInputMask.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SDLKeyboardInputMask.h; path = public/SDLKeyboardInputMask.h; sourceTree = "<group>"; }; + B3A9D9EC25D2586C00CDFD21 /* SDLKeyboardInputMask.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SDLKeyboardInputMask.m; path = public/SDLKeyboardInputMask.m; sourceTree = "<group>"; }; + B3A9DA0325D26D8500CDFD21 /* SDLKeyboardInputMaskSpec.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDLKeyboardInputMaskSpec.m; sourceTree = "<group>"; }; + B3A9DA0925D26E1800CDFD21 /* SDLKeyboardCapabilitiesSpec.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDLKeyboardCapabilitiesSpec.m; sourceTree = "<group>"; }; + B3A9DA1125D270E900CDFD21 /* SDLKeyboardLayoutCapabilitySpec.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDLKeyboardLayoutCapabilitySpec.m; sourceTree = "<group>"; }; B3EC9E6D2579AA010039F3AA /* SDLClimateDataSpec.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDLClimateDataSpec.m; sourceTree = "<group>"; }; BB3C600D221AEF37007DD4CA /* NSMutableDictionary+StoreSpec.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = "NSMutableDictionary+StoreSpec.m"; path = "DevAPISpecs/NSMutableDictionary+StoreSpec.m"; sourceTree = "<group>"; }; C975877E257AEFDB0066F271 /* SDLSeekIndicatorTypeSpec.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SDLSeekIndicatorTypeSpec.m; sourceTree = "<group>"; }; @@ -3797,6 +3815,7 @@ 162E81FD1A9BDE8A00906325 /* SDLImageTypeSpec.m */, 162E81FE1A9BDE8A00906325 /* SDLInteractionModeSpec.m */, 162E81FF1A9BDE8A00906325 /* SDLKeyboardEventSpec.m */, + B3A9DA0325D26D8500CDFD21 /* SDLKeyboardInputMaskSpec.m */, 162E82001A9BDE8A00906325 /* SDLKeyboardLayoutSpec.m */, 162E82011A9BDE8A00906325 /* SDLKeypressModeSpec.m */, 162E82021A9BDE8A00906325 /* SDLLanguageSpec.m */, @@ -4071,6 +4090,7 @@ B3EC9E6D2579AA010039F3AA /* SDLClimateDataSpec.m */, 885468372225CBA400994D8D /* SDLCloudAppPropertiesSpec.m */, 162E82951A9BDE8A00906325 /* SDLClusterModeStatusSpec.m */, + B3992641258FAADF0048F09B /* SDLConfigurableKeyboardsSpec.m */, DA9F7EB31DCC086400ACAE48 /* SDLDateTimeSpec.m */, 162E82961A9BDE8A00906325 /* SDLDeviceInfoSpec.m */, 162E82971A9BDE8A00906325 /* SDLDeviceStatusSpec.m */, @@ -4095,6 +4115,8 @@ 162E829F1A9BDE8A00906325 /* SDLImageFieldSpec.m */, 5DB202261F5F2D030061D189 /* SDLImageResolutionSpec.m */, 162E82A01A9BDE8A00906325 /* SDLImageSpec.m */, + B3A9DA0925D26E1800CDFD21 /* SDLKeyboardCapabilitiesSpec.m */, + B3A9DA1125D270E900CDFD21 /* SDLKeyboardLayoutCapabilitySpec.m */, 162E82A11A9BDE8A00906325 /* SDLKeyboardPropertiesSpec.m */, 1EAA476B2036A52F000FE74B /* SDLLightCapabilitiesSpec.m */, 1EAA476920369ECC000FE74B /* SDLLightControlCapabilitiesSpec.m */, @@ -5124,6 +5146,8 @@ 4ABB2B2124F84EF00061BF55 /* SDLCloudAppProperties.m */, 4ABB2B3224F84EF30061BF55 /* SDLClusterModeStatus.h */, 4ABB2B3024F84EF30061BF55 /* SDLClusterModeStatus.m */, + B3992632258C276B0048F09B /* SDLConfigurableKeyboards.h */, + B3992631258C276A0048F09B /* SDLConfigurableKeyboards.m */, 4ABB2B2D24F84EF20061BF55 /* SDLDateTime.h */, 4ABB2B2324F84EF00061BF55 /* SDLDateTime.m */, 4ABB2B1F24F84EF00061BF55 /* SDLDeviceInfo.h */, @@ -5176,6 +5200,12 @@ 4ABB2B9824F850AD0061BF55 /* SDLImageField.m */, 4ABB2B9B24F850AD0061BF55 /* SDLImageResolution.h */, 4ABB2B9124F850AC0061BF55 /* SDLImageResolution.m */, + B3A9D9E025D2571000CDFD21 /* SDLKeyboardCapabilities.h */, + B3A9D9DF25D2571000CDFD21 /* SDLKeyboardCapabilities.m */, + B3A9D9EB25D2586C00CDFD21 /* SDLKeyboardInputMask.h */, + B3A9D9EC25D2586C00CDFD21 /* SDLKeyboardInputMask.m */, + B3A9D9E625D2578F00CDFD21 /* SDLKeyboardLayoutCapability.h */, + B3A9D9E525D2578F00CDFD21 /* SDLKeyboardLayoutCapability.m */, 4ABB2B9224F850AC0061BF55 /* SDLLightCapabilities.h */, 4ABB2B9624F850AD0061BF55 /* SDLLightCapabilities.m */, 4ABB2B8F24F850AB0061BF55 /* SDLLightControlCapabilities.h */, @@ -5184,6 +5214,8 @@ 4ABB2B9724F850AD0061BF55 /* SDLLightControlData.m */, 4ABB2B9424F850AC0061BF55 /* SDLLightState.h */, 4ABB2B9A24F850AD0061BF55 /* SDLLightState.m */, + B3992622258C1E480048F09B /* SDLKeyboardCapabilities.h */, + B3992621258C1E480048F09B /* SDLKeyboardCapabilities.m */, 4A8BD22724F93132000945E3 /* SDLKeyboardProperties.h */, 4A8BD23A24F93135000945E3 /* SDLKeyboardProperties.m */, 4A8BD22824F93132000945E3 /* SDLLocationCoordinate.h */, @@ -5417,6 +5449,8 @@ 4ABB278224F7FF090061BF55 /* SDLInteractionMode.m */, 4ABB278624F7FF0A0061BF55 /* SDLKeyboardEvent.h */, 4ABB277E24F7FF090061BF55 /* SDLKeyboardEvent.m */, + B3992627258C24120048F09B /* SDLKeyboardInputMask.h */, + B3992628258C24130048F09B /* SDLKeyboardInputMask.m */, 4ABB278B24F7FF0B0061BF55 /* SDLKeyboardLayout.h */, 4ABB277F24F7FF090061BF55 /* SDLKeyboardLayout.m */, 4ABB278824F7FF0A0061BF55 /* SDLKeypressMode.h */, @@ -7070,6 +7104,7 @@ B3838A20257C5BB000420C11 /* SDLRoofStatus.h in Headers */, 4ABB271824F7FC4E0061BF55 /* SDLCompassDirection.h in Headers */, 4ABB2B5924F84EF50061BF55 /* SDLDeviceStatus.h in Headers */, + B3992629258C24130048F09B /* SDLKeyboardInputMask.h in Headers */, 4A8BD2CF24F93803000945E3 /* SDLTouchEvent.h in Headers */, 4ABB264B24F7F5580061BF55 /* SDLManagerDelegate.h in Headers */, 4A8BD28B24F934F3000945E3 /* SDLRGBColor.h in Headers */, @@ -7094,6 +7129,7 @@ 4ABB2AB524F847F40061BF55 /* SDLShowAppMenuResponse.h in Headers */, 4A8BD3C724F998A8000945E3 /* SDLWindowState.h in Headers */, 4ABB286424F828E00061BF55 /* SDLVehicleDataNotificationStatus.h in Headers */, + B3992624258C1E490048F09B /* SDLKeyboardCapabilities.h in Headers */, 4ABB287C24F8294A0061BF55 /* SDLVentilationMode.h in Headers */, 4ABB292F24F842A00061BF55 /* SDLDeleteFile.h in Headers */, 4ABB294924F843440061BF55 /* SDLEncodedSyncPData.h in Headers */, @@ -7316,6 +7352,7 @@ 4ABB275224F7FD9C0061BF55 /* SDLFuelCutoffStatus.h in Headers */, 4ABB24BE24F592620061BF55 /* NSBundle+SDLBundle.h in Headers */, 4ABB286124F828E00061BF55 /* SDLVehicleDataResultCode.h in Headers */, + B3A9D9E825D2578F00CDFD21 /* SDLKeyboardLayoutCapability.h in Headers */, 4ABB2BA024F850AE0061BF55 /* SDLLightCapabilities.h in Headers */, 4ABB284124F828630061BF55 /* SDLTurnSignal.h in Headers */, 4ABB299D24F845440061BF55 /* SDLScrollableMessage.h in Headers */, @@ -7331,6 +7368,7 @@ 4ABB2A3124F847980061BF55 /* SDLDeleteFileResponse.h in Headers */, 4ABB294C24F843440061BF55 /* SDLEndAudioPassThru.h in Headers */, 4ABB2AD524F848130061BF55 /* SDLSubscribeVehicleDataResponse.h in Headers */, + B3992634258C276B0048F09B /* SDLConfigurableKeyboards.h in Headers */, 4ABB251224F7E3A30061BF55 /* SDLLifecycleConfiguration.h in Headers */, 4ABB25F624F7E7EF0061BF55 /* SDLTouch.h in Headers */, 4ABB2A8324F847DF0061BF55 /* SDLResetGlobalPropertiesResponse.h in Headers */, @@ -7385,6 +7423,7 @@ 4ABB26D724F7FAFD0061BF55 /* SDLRPCMessage.h in Headers */, 4A8BD24A24F93135000945E3 /* SDLMyKey.h in Headers */, 4ABB24F924F5959E0061BF55 /* SDLAsynchronousOperation.h in Headers */, + B3A9D9E225D2571000CDFD21 /* SDLKeyboardCapabilities.h in Headers */, 4ABB29B324F845DB0061BF55 /* SDLShow.h in Headers */, 4ABB25B424F7E6F60061BF55 /* SDLSoftButtonReplaceOperation.h in Headers */, 4ABB269C24F7F9710061BF55 /* SDLRPCParameterNames.h in Headers */, @@ -7521,6 +7560,7 @@ 4A8BD36E24F94636000945E3 /* SDLProtocolMessageAssembler.h in Headers */, 4ABB28C024F82A6A0061BF55 /* SDLOnCommand.h in Headers */, 4ABB26A824F7F9CF0061BF55 /* SDLLogTargetAppleSystemLog.h in Headers */, + B3A9D9ED25D2586C00CDFD21 /* SDLKeyboardInputMask.h in Headers */, 4ABB250524F596450061BF55 /* SDLListFilesOperation.h in Headers */, 4ABB268F24F7F8FC0061BF55 /* SDLHexUtility.h in Headers */, 4A8BD28124F9343F000945E3 /* SDLRemoteControlCapabilities.h in Headers */, @@ -7912,18 +7952,21 @@ 4ABB2AD224F848130061BF55 /* SDLSubscribeWayPointsResponse.m in Sources */, 4ABB286224F828E00061BF55 /* SDLVehicleDataResultCode.m in Sources */, 4ABB2B8A24F8504A0061BF55 /* SDLHMISettingsControlCapabilities.m in Sources */, + B3992623258C1E490048F09B /* SDLKeyboardCapabilities.m in Sources */, 4ABB257A24F7E5FF0061BF55 /* SDLPresentKeyboardOperation.m in Sources */, 4ABB27CA24F8006D0061BF55 /* SDLMediaType.m in Sources */, 4ABB264524F7F5340061BF55 /* SDLSystemCapabilityManager.m in Sources */, 4A8BD2B124F935BC000945E3 /* SDLSoftButtonCapabilities.m in Sources */, 4ABB2A5524F847B10061BF55 /* SDLGetInteriorVehicleDataConsentResponse.m in Sources */, 4ABED25B257681ED005BDF61 /* SDLVoiceCommandUpdateOperation.m in Sources */, + B3A9D9E125D2571000CDFD21 /* SDLKeyboardCapabilities.m in Sources */, 4ABB2AA924F847F40061BF55 /* SDLSetAppIconResponse.m in Sources */, 4A8BD2D224F93803000945E3 /* SDLTemplateColorScheme.m in Sources */, 4A8BD3C124F994D5000945E3 /* SDLFileManager.m in Sources */, 4ABB25A324F7E6CE0061BF55 /* SDLDynamicMenuUpdateAlgorithm.m in Sources */, 4A8BD30C24F938D6000945E3 /* SDLWeatherAlert.m in Sources */, 4ABB250924F596920061BF55 /* SDLFileWrapper.m in Sources */, + B399262A258C24130048F09B /* SDLKeyboardInputMask.m in Sources */, 4ABB24E324F5948D0061BF55 /* SDLEncryptionConfiguration.m in Sources */, 4ABB273D24F7FD1D0061BF55 /* SDLDimension.m in Sources */, 4ABB267B24F7F6840061BF55 /* SDLIconArchiveFile.m in Sources */, @@ -8155,6 +8198,7 @@ 4ABB269224F7F9060061BF55 /* SDLTimer.m in Sources */, 4ABB25C624F7E73C0061BF55 /* SDLSubscribeButtonManager.m in Sources */, 4ABB278E24F7FF0B0061BF55 /* SDLKeyboardEvent.m in Sources */, + B3A9D9E725D2578F00CDFD21 /* SDLKeyboardLayoutCapability.m in Sources */, 4ABB279024F7FF0B0061BF55 /* SDLImageType.m in Sources */, 4ABB28CB24F82A6A0061BF55 /* SDLOnTouchEvent.m in Sources */, 4ABB2B4E24F84EF50061BF55 /* SDLClusterModeStatus.m in Sources */, @@ -8219,6 +8263,7 @@ 4ABB2AB924F847F40061BF55 /* SDLSetInteriorVehicleDataResponse.m in Sources */, 4ABB295424F843440061BF55 /* SDLEndAudioPassThru.m in Sources */, 4ABB2A2924F847980061BF55 /* SDLDeleteFileResponse.m in Sources */, + B3A9D9EE25D2586C00CDFD21 /* SDLKeyboardInputMask.m in Sources */, 4ABB284524F828630061BF55 /* SDLTouchType.m in Sources */, 4ABB2B8024F8504A0061BF55 /* SDLHapticRect.m in Sources */, 4A8BD38A24F94712000945E3 /* SDLSecondaryTransportManager.m in Sources */, @@ -8249,6 +8294,7 @@ 4ABB251724F7E3AC0061BF55 /* SDLLifecycleConfigurationUpdate.m in Sources */, 4ABB24F824F5959E0061BF55 /* SDLAsynchronousOperation.m in Sources */, 4A8BD37624F9465E000945E3 /* SDLProtocol.m in Sources */, + B3992633258C276B0048F09B /* SDLConfigurableKeyboards.m in Sources */, 4A8BD34D24F945E8000945E3 /* SDLControlFramePayloadRPCStartService.m in Sources */, 4A8BD36524F9461A000945E3 /* SDLV2ProtocolMessage.m in Sources */, 4ABB29BE24F845DB0061BF55 /* SDLSlider.m in Sources */, @@ -8458,6 +8504,7 @@ 1680B11E1A9CD7AD00DBD79E /* SDLProtocolReceivedMessageRouterSpec.m in Sources */, 162E82FD1A9BDE8B00906325 /* SDLSystemContextSpec.m in Sources */, 162E82E21A9BDE8B00906325 /* SDLIgnitionStableStatusSpec.m in Sources */, + B3992642258FAAE00048F09B /* SDLConfigurableKeyboardsSpec.m in Sources */, 162E82EE1A9BDE8B00906325 /* SDLMediaClockFormatSpec.m in Sources */, 5D76751822D921CB00E8D71A /* SDLMenuLayoutSpec.m in Sources */, 5DA026901AD44EE700019F86 /* SDLDialNumberResponseSpec.m in Sources */, @@ -8497,6 +8544,7 @@ 162E837D1A9BDE8B00906325 /* SDLEmergencyEventSpec.m in Sources */, 162E82D31A9BDE8A00906325 /* SDLCarModeStatusSpec.m in Sources */, 8B7B31A91F2FB8BC00BDC38D /* SDLVideoStreamingProtocolSpec.m in Sources */, + B3A9DA0A25D26E1800CDFD21 /* SDLKeyboardCapabilitiesSpec.m in Sources */, 88EED83B1F33BECB00E6C42E /* SDLHapticRectSpec.m in Sources */, 162E82EA1A9BDE8B00906325 /* SDLLanguageSpec.m in Sources */, 5D76E3291D3D0A8800647CFA /* SDLFakeViewControllerPresenter.m in Sources */, @@ -8573,6 +8621,7 @@ 162E835B1A9BDE8B00906325 /* SDLPerformInteractionResponseSpec.m in Sources */, 880E35B82088F78E00181259 /* SDLSystemCapabilityManagerSpec.m in Sources */, 162E832D1A9BDE8B00906325 /* SDLEncodedSyncPDataSpec.m in Sources */, + B3A9DA0425D26D8500CDFD21 /* SDLKeyboardInputMaskSpec.m in Sources */, 1EE8C44C1F385C7100FDC2CF /* SDLRDSDataSpec.m in Sources */, 5DB92D241AC47B2C00C15BB0 /* SDLHexUtilitySpec.m in Sources */, 8815D0F022330765000F24E6 /* SDLRPCRequestNotificationSpec.m in Sources */, @@ -8747,6 +8796,7 @@ 162E82FE1A9BDE8B00906325 /* SDLTBTStateSpec.m in Sources */, 5DB1BCD41D243A8E002FFC37 /* SDLListFilesOperationSpec.m in Sources */, 8863747E22D650DE00D2671F /* SDLCloseApplicationSpec.m in Sources */, + B3992650258FABF70048F09B /* SDLKeyboardInputMaskSpec.m in Sources */, 162E834B1A9BDE8B00906325 /* SDLAlertManeuverResponseSpec.m in Sources */, 162E833E1A9BDE8B00906325 /* SDLShowSpec.m in Sources */, 5D6035D8202CF5C900A429C9 /* TestRequestProgressResponse.m in Sources */, @@ -8756,6 +8806,7 @@ 162E82EF1A9BDE8B00906325 /* SDLPermissionStatusSpec.m in Sources */, 881F388D22D904BE00DF6DCE /* SDLCancelInteractionResponseSpec.m in Sources */, 8BA12B1822DCF59700371E82 /* SDLUnpublishAppServiceResponseSpec.m in Sources */, + B399264A258FAB6B0048F09B /* SDLKeyboardCapabilitiesSpec.m in Sources */, DA9F7EA61DCC05F500ACAE48 /* SDLUnsubscribeWaypointsSpec.m in Sources */, 1E89B0E2203196B800A47992 /* SDLSeatControlCapabilitiesSpec.m in Sources */, 162E82F01A9BDE8B00906325 /* SDLPowerModeQualificationStatusSpec.m in Sources */, @@ -8878,6 +8929,7 @@ 162E830F1A9BDE8B00906325 /* SDLOnAppInterfaceUnregisteredSpec.m in Sources */, 162E83971A9BDE8B00906325 /* SDLVehicleTypeSpec.m in Sources */, 887BE4D422272B2200B397C2 /* SDLControlFramePayloadConstantsSpec.m in Sources */, + B3A9DA1225D270EA00CDFD21 /* SDLKeyboardLayoutCapabilitySpec.m in Sources */, 885468382225CBA400994D8D /* SDLCloudAppPropertiesSpec.m in Sources */, 88A795D5210678E000056542 /* SDLStaticIconNameSpec.m in Sources */, 1680B1131A9CD7AD00DBD79E /* SDLProtocolHeaderSpec.m in Sources */, @@ -8942,6 +8994,7 @@ B3A3CEA025222A2900A7121D /* SDLOnAppCapabilityUpdatedSpec.m in Sources */, 162E831E1A9BDE8B00906325 /* SDLOnTBTClientStateSpec.m in Sources */, 162E83351A9BDE8B00906325 /* SDLReadDIDSpec.m in Sources */, + 5DF40B28208FDA9700DD6FDA /* SDLVoiceCommandManagerSpec.m in Sources */, 4AD1F1742559957100637FE1 /* SDLVoiceCommandUpdateOperationSpec.m in Sources */, 88B3BFA020DA8FD000943565 /* SDLFuelTypeSpec.m in Sources */, 162E836F1A9BDE8B00906325 /* SDLUnsubscribeVehicleDataResponseSpec.m in Sources */, diff --git a/SmartDeviceLink/private/SDLChoiceSetManager.m b/SmartDeviceLink/private/SDLChoiceSetManager.m index 51dd32b9e..0f2cb67ad 100644 --- a/SmartDeviceLink/private/SDLChoiceSetManager.m +++ b/SmartDeviceLink/private/SDLChoiceSetManager.m @@ -379,10 +379,10 @@ UInt16 const ChoiceCellCancelIdMin = 1; SDLPresentChoiceSetOperation *presentOp = nil; if (delegate == nil) { // Non-searchable choice set - presentOp = [[SDLPresentChoiceSetOperation alloc] initWithConnectionManager:self.connectionManager choiceSet:self.pendingPresentationSet mode:mode keyboardProperties:nil keyboardDelegate:nil cancelID:self.nextCancelId]; + presentOp = [[SDLPresentChoiceSetOperation alloc] initWithConnectionManager:self.connectionManager choiceSet:self.pendingPresentationSet mode:mode keyboardProperties:nil keyboardDelegate:nil cancelID:self.nextCancelId windowCapability:self.currentWindowCapability]; } else { // Searchable choice set - presentOp = [[SDLPresentChoiceSetOperation alloc] initWithConnectionManager:self.connectionManager choiceSet:self.pendingPresentationSet mode:mode keyboardProperties:self.keyboardConfiguration keyboardDelegate:delegate cancelID:self.nextCancelId]; + presentOp = [[SDLPresentChoiceSetOperation alloc] initWithConnectionManager:self.connectionManager choiceSet:self.pendingPresentationSet mode:mode keyboardProperties:self.keyboardConfiguration keyboardDelegate:delegate cancelID:self.nextCancelId windowCapability:self.currentWindowCapability]; } self.pendingPresentOperation = presentOp; @@ -421,7 +421,7 @@ UInt16 const ChoiceCellCancelIdMin = 1; SDLLogD(@"Presenting keyboard with initial text: %@", initialText); // Present a keyboard with the choice set that we used to test VR's optional state UInt16 keyboardCancelId = self.nextCancelId; - self.pendingPresentOperation = [[SDLPresentKeyboardOperation alloc] initWithConnectionManager:self.connectionManager keyboardProperties:self.keyboardConfiguration initialText:initialText keyboardDelegate:delegate cancelID:keyboardCancelId]; + self.pendingPresentOperation = [[SDLPresentKeyboardOperation alloc] initWithConnectionManager:self.connectionManager keyboardProperties:self.keyboardConfiguration initialText:initialText keyboardDelegate:delegate cancelID:keyboardCancelId windowCapability:self.currentWindowCapability]; [self.transactionQueue addOperation:self.pendingPresentOperation]; return @(keyboardCancelId); } @@ -515,7 +515,7 @@ UInt16 const ChoiceCellCancelIdMin = 1; } - (SDLKeyboardProperties *)sdl_defaultKeyboardConfiguration { - return [[SDLKeyboardProperties alloc] initWithLanguage:SDLLanguageEnUs keyboardLayout:SDLKeyboardLayoutQWERTY keypressMode:SDLKeypressModeResendCurrentEntry limitedCharacterList:nil autoCompleteList:nil]; + return [[SDLKeyboardProperties alloc] initWithLanguage:SDLLanguageEnUs keyboardLayout:SDLKeyboardLayoutQWERTY keypressMode:SDLKeypressModeResendCurrentEntry limitedCharacterList:nil autoCompleteList:nil maskInputCharacters:nil customKeys:nil]; } #pragma mark - Getters diff --git a/SmartDeviceLink/private/SDLMenuManager.m b/SmartDeviceLink/private/SDLMenuManager.m index b78f8ee99..a01861d6f 100644 --- a/SmartDeviceLink/private/SDLMenuManager.m +++ b/SmartDeviceLink/private/SDLMenuManager.m @@ -543,6 +543,16 @@ UInt32 const MenuCellIdMin = 1; [mutableArtworks addObject:cell.icon]; } + if (cell.subCells.count > 0 && [self.windowCapability hasImageFieldOfName:SDLImageFieldNameMenuSubMenuSecondaryImage]) { + if ([self.fileManager fileNeedsUpload:cell.secondaryArtwork]) { + [mutableArtworks addObject:cell.secondaryArtwork]; + } + } else if (cell.subCells.count == 0 && [self.windowCapability hasImageFieldOfName:SDLImageFieldNameMenuCommandSecondaryImage]) { + if ([self.fileManager fileNeedsUpload:cell.secondaryArtwork]) { + [mutableArtworks addObject:cell.secondaryArtwork]; + } + } + if (cell.subCells.count > 0) { [mutableArtworks addObjectsFromArray:[self sdl_findAllArtworksToBeUploadedFromCells:cell.subCells]]; } @@ -554,8 +564,17 @@ UInt32 const MenuCellIdMin = 1; - (BOOL)sdl_shouldRPCsIncludeImages:(NSArray<SDLMenuCell *> *)cells { for (SDLMenuCell *cell in cells) { SDLArtwork *artwork = cell.icon; + SDLArtwork *secondaryArtwork = cell.secondaryArtwork; if (artwork != nil && !artwork.isStaticIcon && ![self.fileManager hasUploadedFile:artwork]) { return NO; + } else if (cell.subCells.count > 0 && [self.windowCapability hasImageFieldOfName:SDLImageFieldNameMenuSubMenuSecondaryImage]) { + if (secondaryArtwork != nil && !secondaryArtwork.isStaticIcon && ![self.fileManager hasUploadedFile:secondaryArtwork]) { + return NO; + } + } else if (cell.subCells.count == 0 && [self.windowCapability hasImageFieldOfName:SDLImageFieldNameMenuCommandSecondaryImage]) { + if (secondaryArtwork != nil && !secondaryArtwork.isStaticIcon && ![self.fileManager hasUploadedFile:secondaryArtwork]) { + return NO; + } } else if (cell.subCells.count > 0) { return [self sdl_shouldRPCsIncludeImages:cell.subCells]; } @@ -654,17 +673,21 @@ UInt32 const MenuCellIdMin = 1; params.menuName = cell.title; params.parentID = cell.parentCellId != UINT32_MAX ? @(cell.parentCellId) : nil; params.position = @(position); + params.tertiaryText = cell.tertiaryText; + params.secondaryText = cell.secondaryText; command.menuParams = params; command.vrCommands = (cell.voiceCommands.count == 0) ? nil : cell.voiceCommands; command.cmdIcon = (cell.icon && shouldHaveArtwork) ? cell.icon.imageRPC : nil; command.cmdID = @(cell.cellId); + command.secondaryImage = (cell.secondaryArtwork && shouldHaveArtwork && ![self.fileManager fileNeedsUpload:cell.secondaryArtwork]) ? cell.secondaryArtwork.imageRPC : nil; return command; } - (SDLAddSubMenu *)sdl_subMenuCommandForMenuCell:(SDLMenuCell *)cell withArtwork:(BOOL)shouldHaveArtwork position:(UInt16)position { SDLImage *icon = (shouldHaveArtwork && (cell.icon.name != nil)) ? cell.icon.imageRPC : nil; + SDLImage *secondaryImage = (shouldHaveArtwork && ![self.fileManager fileNeedsUpload:cell.secondaryArtwork] && (cell.secondaryArtwork.name != nil)) ? cell.secondaryArtwork.imageRPC : nil; SDLMenuLayout submenuLayout = nil; if (cell.submenuLayout && [self.systemCapabilityManager.defaultMainWindowCapability.menuLayoutsAvailable containsObject:cell.submenuLayout]) { @@ -672,8 +695,7 @@ UInt32 const MenuCellIdMin = 1; } else { submenuLayout = self.menuConfiguration.defaultSubmenuLayout; } - - return [[SDLAddSubMenu alloc] initWithMenuID:cell.cellId menuName:cell.title position:@(position) menuIcon:icon menuLayout:submenuLayout parentID:nil]; + return [[SDLAddSubMenu alloc] initWithMenuID:cell.cellId menuName:cell.title position:@(position) menuIcon:icon menuLayout:submenuLayout parentID:nil secondaryText:cell.secondaryText tertiaryText:cell.tertiaryText secondaryImage:secondaryImage]; } #pragma mark - Calling handlers diff --git a/SmartDeviceLink/private/SDLPresentChoiceSetOperation.h b/SmartDeviceLink/private/SDLPresentChoiceSetOperation.h index df82bfa22..b2589a280 100644 --- a/SmartDeviceLink/private/SDLPresentChoiceSetOperation.h +++ b/SmartDeviceLink/private/SDLPresentChoiceSetOperation.h @@ -15,6 +15,7 @@ @class SDLChoiceCell; @class SDLChoiceSet; @class SDLKeyboardProperties; +@class SDLWindowCapability; @protocol SDLConnectionManagerType; @protocol SDLKeyboardDelegate; @@ -54,7 +55,7 @@ NS_ASSUME_NONNULL_BEGIN @param cancelID A unique ID for this specific choice set that allows cancellation through the `CancelInteraction` RPC. @return A SDLPresentChoiceSetOperation object */ -- (instancetype)initWithConnectionManager:(id<SDLConnectionManagerType>)connectionManager choiceSet:(SDLChoiceSet *)choiceSet mode:(SDLInteractionMode)mode keyboardProperties:(nullable SDLKeyboardProperties *)originalKeyboardProperties keyboardDelegate:(nullable id<SDLKeyboardDelegate>)keyboardDelegate cancelID:(UInt16)cancelID; +- (instancetype)initWithConnectionManager:(id<SDLConnectionManagerType>)connectionManager choiceSet:(SDLChoiceSet *)choiceSet mode:(SDLInteractionMode)mode keyboardProperties:(nullable SDLKeyboardProperties *)originalKeyboardProperties keyboardDelegate:(nullable id<SDLKeyboardDelegate>)keyboardDelegate cancelID:(UInt16)cancelID windowCapability:(SDLWindowCapability *)windowCapability; @end diff --git a/SmartDeviceLink/private/SDLPresentChoiceSetOperation.m b/SmartDeviceLink/private/SDLPresentChoiceSetOperation.m index f0fbbf28a..121383ce7 100644 --- a/SmartDeviceLink/private/SDLPresentChoiceSetOperation.m +++ b/SmartDeviceLink/private/SDLPresentChoiceSetOperation.m @@ -24,6 +24,7 @@ #import "SDLRPCNotificationNotification.h" #import "SDLSetGlobalProperties.h" #import "SDLVersion.h" +#import "SDLWindowCapability+ScreenManagerExtensions.h" NS_ASSUME_NONNULL_BEGIN @@ -60,12 +61,13 @@ NS_ASSUME_NONNULL_BEGIN @property (strong, nonatomic, readwrite, nullable) SDLChoiceCell *selectedCell; @property (strong, nonatomic, readwrite, nullable) SDLTriggerSource selectedTriggerSource; @property (assign, nonatomic, readwrite) NSUInteger selectedCellRow; +@property (strong, nonatomic) SDLWindowCapability *windowCapability; @end @implementation SDLPresentChoiceSetOperation -- (instancetype)initWithConnectionManager:(id<SDLConnectionManagerType>)connectionManager choiceSet:(SDLChoiceSet *)choiceSet mode:(SDLInteractionMode)mode keyboardProperties:(nullable SDLKeyboardProperties *)originalKeyboardProperties keyboardDelegate:(nullable id<SDLKeyboardDelegate>)keyboardDelegate cancelID:(UInt16)cancelID { +- (instancetype)initWithConnectionManager:(id<SDLConnectionManagerType>)connectionManager choiceSet:(SDLChoiceSet *)choiceSet mode:(SDLInteractionMode)mode keyboardProperties:(nullable SDLKeyboardProperties *)originalKeyboardProperties keyboardDelegate:(nullable id<SDLKeyboardDelegate>)keyboardDelegate cancelID:(UInt16)cancelID windowCapability:(SDLWindowCapability *)windowCapability { self = [super init]; if (!self) { return self; } @@ -86,6 +88,7 @@ NS_ASSUME_NONNULL_BEGIN _cancelId = cancelID; _selectedCellRow = NSNotFound; + _windowCapability = windowCapability; return self; } @@ -121,15 +124,16 @@ NS_ASSUME_NONNULL_BEGIN #pragma mark - Sending Requests - (void)sdl_updateKeyboardPropertiesWithCompletionHandler:(nullable void(^)(void))completionHandler { - if (self.keyboardProperties == nil) { + // Create the keyboard configuration based on the window capability's keyboard capabilities + SDLKeyboardProperties *modifiedKeyboardConfig = [self.windowCapability createValidKeyboardConfigurationBasedOnKeyboardCapabilitiesFromConfiguration:self.keyboardProperties]; + if (modifiedKeyboardConfig == nil) { if (completionHandler != nil) { completionHandler(); } return; } - SDLSetGlobalProperties *setProperties = [[SDLSetGlobalProperties alloc] init]; - setProperties.keyboardProperties = self.keyboardProperties; + setProperties.keyboardProperties = modifiedKeyboardConfig; __weak typeof(self) weakself = self; [self.connectionManager sendConnectionRequest:setProperties withResponseHandler:^(__kindof SDLRPCRequest * _Nullable request, __kindof SDLRPCResponse * _Nullable response, NSError * _Nullable error) { @@ -295,6 +299,12 @@ NS_ASSUME_NONNULL_BEGIN } else if ([onKeyboard.event isEqualToEnum:SDLKeyboardEventAborted] || [onKeyboard.event isEqualToEnum:SDLKeyboardEventCancelled]) { // Notify of abort / cancellation [self.keyboardDelegate keyboardDidAbortWithReason:onKeyboard.event]; + } else if ([onKeyboard.event isEqualToEnum:SDLKeyboardEventInputKeyMaskEnabled] || [onKeyboard.event isEqualToEnum:SDLKeyboardEventInputKeyMaskDisabled]) { + // Notify of key mask change + if ([self.keyboardDelegate respondsToSelector:@selector(keyboardDidUpdateInputMask:)]) { + BOOL isEnabled = [onKeyboard.event isEqualToEnum:SDLKeyboardEventInputKeyMaskEnabled]; + [self.keyboardDelegate keyboardDidUpdateInputMask:isEnabled]; + } } } diff --git a/SmartDeviceLink/private/SDLPresentKeyboardOperation.h b/SmartDeviceLink/private/SDLPresentKeyboardOperation.h index 9a5a6cfb5..508c948b4 100644 --- a/SmartDeviceLink/private/SDLPresentKeyboardOperation.h +++ b/SmartDeviceLink/private/SDLPresentKeyboardOperation.h @@ -10,6 +10,8 @@ #import "NSNumber+NumberType.h" @class SDLKeyboardProperties; +@class SDLWindowCapability; + @protocol SDLConnectionManagerType; @protocol SDLKeyboardDelegate; @@ -33,7 +35,7 @@ NS_ASSUME_NONNULL_BEGIN @param cancelID An ID for this specific keyboard to allow cancellation through the `CancelInteraction` RPC. @return A SDLPresentKeyboardOperation object */ -- (instancetype)initWithConnectionManager:(id<SDLConnectionManagerType>)connectionManager keyboardProperties:(SDLKeyboardProperties *)originalKeyboardProperties initialText:(NSString *)initialText keyboardDelegate:(id<SDLKeyboardDelegate>)keyboardDelegate cancelID:(UInt16)cancelID; +- (instancetype)initWithConnectionManager:(id<SDLConnectionManagerType>)connectionManager keyboardProperties:(SDLKeyboardProperties *)originalKeyboardProperties initialText:(NSString *)initialText keyboardDelegate:(id<SDLKeyboardDelegate>)keyboardDelegate cancelID:(UInt16)cancelID windowCapability:(SDLWindowCapability *)windowCapability; /** Cancels the keyboard-only interface if it is currently showing. If the keyboard has not yet been sent to Core, it will not be sent. diff --git a/SmartDeviceLink/private/SDLPresentKeyboardOperation.m b/SmartDeviceLink/private/SDLPresentKeyboardOperation.m index 798e046af..939869680 100644 --- a/SmartDeviceLink/private/SDLPresentKeyboardOperation.m +++ b/SmartDeviceLink/private/SDLPresentKeyboardOperation.m @@ -21,6 +21,7 @@ #import "SDLRPCNotificationNotification.h" #import "SDLSetGlobalProperties.h" #import "SDLVersion.h" +#import "SDLWindowCapability+ScreenManagerExtensions.h" NS_ASSUME_NONNULL_BEGIN @@ -37,12 +38,13 @@ NS_ASSUME_NONNULL_BEGIN @property (strong, nonatomic, readonly) SDLPerformInteraction *performInteraction; @property (copy, nonatomic, nullable) NSError *internalError; +@property (strong, nonatomic) SDLWindowCapability *windowCapability; @end @implementation SDLPresentKeyboardOperation -- (instancetype)initWithConnectionManager:(id<SDLConnectionManagerType>)connectionManager keyboardProperties:(SDLKeyboardProperties *)originalKeyboardProperties initialText:(NSString *)initialText keyboardDelegate:(id<SDLKeyboardDelegate>)keyboardDelegate cancelID:(UInt16)cancelID { +- (instancetype)initWithConnectionManager:(id<SDLConnectionManagerType>)connectionManager keyboardProperties:(SDLKeyboardProperties *)originalKeyboardProperties initialText:(NSString *)initialText keyboardDelegate:(id<SDLKeyboardDelegate>)keyboardDelegate cancelID:(UInt16)cancelID windowCapability:(SDLWindowCapability *)windowCapability { self = [super init]; if (!self) { return self; } @@ -53,6 +55,7 @@ NS_ASSUME_NONNULL_BEGIN _keyboardProperties = originalKeyboardProperties; _cancelId = cancelID; _operationId = [NSUUID UUID]; + _windowCapability = windowCapability; return self; } @@ -87,8 +90,16 @@ NS_ASSUME_NONNULL_BEGIN #pragma mark - Sending Requests - (void)sdl_updateKeyboardPropertiesWithCompletionHandler:(nullable void(^)(void))completionHandler { + // Create the keyboard configuration based on the window capability's keyboard capabilities + SDLKeyboardProperties *keyboardConfiguration = [self.windowCapability createValidKeyboardConfigurationBasedOnKeyboardCapabilitiesFromConfiguration:self.keyboardProperties]; + if (keyboardConfiguration == nil) { + if (completionHandler != nil) { + completionHandler(); + } + return; + } SDLSetGlobalProperties *setProperties = [[SDLSetGlobalProperties alloc] init]; - setProperties.keyboardProperties = self.keyboardProperties; + setProperties.keyboardProperties = keyboardConfiguration; [self.connectionManager sendConnectionRequest:setProperties withResponseHandler:^(__kindof SDLRPCRequest * _Nullable request, __kindof SDLRPCResponse * _Nullable response, NSError * _Nullable error) { if (error != nil) { @@ -209,6 +220,12 @@ NS_ASSUME_NONNULL_BEGIN } else if ([onKeyboard.event isEqualToEnum:SDLKeyboardEventAborted] || [onKeyboard.event isEqualToEnum:SDLKeyboardEventCancelled]) { // Notify of abort / cancellation [self.keyboardDelegate keyboardDidAbortWithReason:onKeyboard.event]; + } else if ([onKeyboard.event isEqualToEnum:SDLKeyboardEventInputKeyMaskEnabled] || [onKeyboard.event isEqualToEnum:SDLKeyboardEventInputKeyMaskDisabled]) { + // Notify of key mask change + if ([self.keyboardDelegate respondsToSelector:@selector(keyboardDidUpdateInputMask:)]) { + BOOL isEnabled = [onKeyboard.event isEqualToEnum:SDLKeyboardEventInputKeyMaskEnabled]; + [self.keyboardDelegate keyboardDidUpdateInputMask:isEnabled]; + } } } diff --git a/SmartDeviceLink/private/SDLRPCParameterNames.h b/SmartDeviceLink/private/SDLRPCParameterNames.h index 629b36748..ba1281533 100644 --- a/SmartDeviceLink/private/SDLRPCParameterNames.h +++ b/SmartDeviceLink/private/SDLRPCParameterNames.h @@ -169,6 +169,7 @@ extern SDLRPCParameterName const SDLRPCParameterNameCurrentForecastSupported; extern SDLRPCParameterName const SDLRPCParameterNameCurrentTemperature; extern SDLRPCParameterName const SDLRPCParameterNameCushion; extern SDLRPCParameterName const SDLRPCParameterNameCustomButtonId; +extern SDLRPCParameterName const SDLRPCParameterNameCustomKeys; extern SDLRPCParameterName const SDLRPCParameterNameCustomPresets; extern SDLRPCParameterName const SDLRPCParameterNameOEMCustomDataType; extern SDLRPCParameterName const SDLRPCParameterNameData; @@ -357,6 +358,7 @@ extern SDLRPCParameterName const SDLRPCParameterNameIsSubscribed; extern SDLRPCParameterName const SDLRPCParameterNameJunctionType; extern SDLRPCParameterName const SDLRPCParameterNameKeepContext; extern SDLRPCParameterName const SDLRPCParameterNameKeepContextAvailable; +extern SDLRPCParameterName const SDLRPCParameterNameKeyboardCapabilities; extern SDLRPCParameterName const SDLRPCParameterNameKeyboardLayout; extern SDLRPCParameterName const SDLRPCParameterNameKeyboardProperties; extern SDLRPCParameterName const SDLRPCParameterNameKeypressMode; @@ -403,6 +405,8 @@ extern SDLRPCParameterName const SDLRPCParameterNameMajorVersion; extern SDLRPCParameterName const SDLRPCParameterNameMake; extern SDLRPCParameterName const SDLRPCParameterNameManeuverComplete; extern SDLRPCParameterName const SDLRPCParameterNameManualTextEntry; +extern SDLRPCParameterName const SDLRPCParameterNameMaskInputCharacters; +extern SDLRPCParameterName const SDLRPCParameterNameMaskInputCharactersSupported; extern SDLRPCParameterName const SDLRPCParameterNameMassageCushionFirmness; extern SDLRPCParameterName const SDLRPCParameterNameMassageCushionFirmnessAvailable; extern SDLRPCParameterName const SDLRPCParameterNameMassageEnabled; @@ -488,6 +492,7 @@ extern SDLRPCParameterName const SDLRPCParameterNameNotification; extern SDLRPCParameterName const SDLRPCParameterNameNumber; extern SDLRPCParameterName const SDLRPCParameterNameNumberCustomPresetsAvailable; extern SDLRPCParameterName const SDLRPCParameterNameNumberTicks; +extern SDLRPCParameterName const SDLRPCParameterNameNumConfigurableKeys; extern SDLRPCParameterName const SDLRPCParameterNameOdometer; extern SDLRPCParameterName const SDLRPCParameterNameOffset; extern SDLRPCParameterName const SDLRPCParameterNameOnLockScreenStatus; @@ -678,6 +683,7 @@ extern SDLRPCParameterName const SDLRPCParameterNameSupportedDiagnosticModes; extern SDLRPCParameterName const SDLRPCParameterNameSupportedDynamicImageFieldNames; extern SDLRPCParameterName const SDLRPCParameterNameSupportsDynamicSubMenus; extern SDLRPCParameterName const SDLRPCParameterNameSupportedFormats; +extern SDLRPCParameterName const SDLRPCParameterNameSupportedKeyboards; extern SDLRPCParameterName const SDLRPCParameterNameSupportedLights; extern SDLRPCParameterName const SDLRPCParameterNameSyncFileName; extern SDLRPCParameterName const SDLRPCParameterNameSyncMessageVersion; diff --git a/SmartDeviceLink/private/SDLRPCParameterNames.m b/SmartDeviceLink/private/SDLRPCParameterNames.m index 427444968..b951c763d 100644 --- a/SmartDeviceLink/private/SDLRPCParameterNames.m +++ b/SmartDeviceLink/private/SDLRPCParameterNames.m @@ -168,6 +168,7 @@ SDLRPCParameterName const SDLRPCParameterNameCurrentForecastSupported = @"curren SDLRPCParameterName const SDLRPCParameterNameCurrentTemperature = @"currentTemperature"; SDLRPCParameterName const SDLRPCParameterNameCushion = @"cushion"; SDLRPCParameterName const SDLRPCParameterNameCustomButtonId = @"customButtonID"; +SDLRPCParameterName const SDLRPCParameterNameCustomKeys = @"customKeys"; SDLRPCParameterName const SDLRPCParameterNameCustomPresets = @"customPresets"; SDLRPCParameterName const SDLRPCParameterNameData = @"data"; SDLRPCParameterName const SDLRPCParameterNameDataResult = @"dataResult"; @@ -356,6 +357,7 @@ SDLRPCParameterName const SDLRPCParameterNameIsSubscribed = @"isSubscribed"; SDLRPCParameterName const SDLRPCParameterNameJunctionType = @"junctionType"; SDLRPCParameterName const SDLRPCParameterNameKeepContext = @"keepContext"; SDLRPCParameterName const SDLRPCParameterNameKeepContextAvailable = @"keepContextAvailable"; +SDLRPCParameterName const SDLRPCParameterNameKeyboardCapabilities = @"keyboardCapabilities"; SDLRPCParameterName const SDLRPCParameterNameKeyboardLayout = @"keyboardLayout"; SDLRPCParameterName const SDLRPCParameterNameKeyboardProperties = @"keyboardProperties"; SDLRPCParameterName const SDLRPCParameterNameKeypressMode = @"keypressMode"; @@ -398,6 +400,8 @@ SDLRPCParameterName const SDLRPCParameterNameMajorVersion = @"majorVersion"; SDLRPCParameterName const SDLRPCParameterNameMake = @"make"; SDLRPCParameterName const SDLRPCParameterNameManeuverComplete = @"maneuverComplete"; SDLRPCParameterName const SDLRPCParameterNameManualTextEntry = @"manualTextEntry"; +SDLRPCParameterName const SDLRPCParameterNameMaskInputCharacters = @"maskInputCharacters"; +SDLRPCParameterName const SDLRPCParameterNameMaskInputCharactersSupported = @"maskInputCharactersSupported"; SDLRPCParameterName const SDLRPCParameterNameMassageCushionFirmness = @"massageCushionFirmness"; SDLRPCParameterName const SDLRPCParameterNameMassageCushionFirmnessAvailable = @"massageCushionFirmnessAvailable"; SDLRPCParameterName const SDLRPCParameterNameMassageEnabled = @"massageEnabled"; @@ -483,6 +487,7 @@ SDLRPCParameterName const SDLRPCParameterNameNotification = @"notification"; SDLRPCParameterName const SDLRPCParameterNameNumber = @"number"; SDLRPCParameterName const SDLRPCParameterNameNumberCustomPresetsAvailable = @"numCustomPresetsAvailable"; SDLRPCParameterName const SDLRPCParameterNameNumberTicks = @"numTicks"; +SDLRPCParameterName const SDLRPCParameterNameNumConfigurableKeys = @"numConfigurableKeys"; SDLRPCParameterName const SDLRPCParameterNameOdometer = @"odometer"; SDLRPCParameterName const SDLRPCParameterNameOEMCustomDataType = @"oemCustomDataType"; SDLRPCParameterName const SDLRPCParameterNameOffset = @"offset"; @@ -674,6 +679,7 @@ SDLRPCParameterName const SDLRPCParameterNameSupportedDiagnosticModes = @"suppor SDLRPCParameterName const SDLRPCParameterNameSupportedDynamicImageFieldNames = @"supportedDynamicImageFieldNames"; SDLRPCParameterName const SDLRPCParameterNameSupportsDynamicSubMenus = @"supportsDynamicSubMenus"; SDLRPCParameterName const SDLRPCParameterNameSupportedFormats = @"supportedFormats"; +SDLRPCParameterName const SDLRPCParameterNameSupportedKeyboards = @"supportedKeyboards"; SDLRPCParameterName const SDLRPCParameterNameSupportedLights = @"supportedLights"; SDLRPCParameterName const SDLRPCParameterNameSyncFileName = @"syncFileName"; SDLRPCParameterName const SDLRPCParameterNameSyncMessageVersion = @"syncMsgVersion"; diff --git a/SmartDeviceLink/private/SDLTextField+ScreenManagerExtensions.m b/SmartDeviceLink/private/SDLTextField+ScreenManagerExtensions.m index cbc062d93..3086e67e9 100644 --- a/SmartDeviceLink/private/SDLTextField+ScreenManagerExtensions.m +++ b/SmartDeviceLink/private/SDLTextField+ScreenManagerExtensions.m @@ -13,7 +13,7 @@ + (NSArray<SDLTextFieldName> *)sdl_allTextFieldNames { #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" - return @[SDLTextFieldNameETA, SDLTextFieldNameMenuName, SDLTextFieldNameMenuTitle, SDLTextFieldNameStatusBar, SDLTextFieldNameAlertText1, SDLTextFieldNameAlertText2, SDLTextFieldNameAlertText3, SDLTextFieldNameMainField1, SDLTextFieldNameMainField2, SDLTextFieldNameMainField3, SDLTextFieldNameMainField4, SDLTextFieldNameMediaClock, SDLTextFieldNameMediaTrack, SDLTextFieldNamePhoneNumber, SDLTextFieldNameAddressLines, SDLTextFieldNameLocationName, SDLTextFieldNameSliderFooter, SDLTextFieldNameSliderHeader, SDLTextFieldNameTertiaryText, SDLTextFieldNameSecondaryText, SDLTextFieldNameTemplateTitle, SDLTextFieldNameTotalDistance, SDLTextFieldNameNavigationText1, SDLTextFieldNameNavigationText2, SDLTextFieldNameLocationDescription, SDLTextFieldNameScrollableMessageBody, SDLTextFieldNameInitialInteractionText, SDLTextFieldNameAudioPassThruDisplayText1, SDLTextFieldNameAudioPassThruDisplayText2]; + return @[SDLTextFieldNameETA, SDLTextFieldNameMenuName, SDLTextFieldNameMenuTitle, SDLTextFieldNameStatusBar, SDLTextFieldNameAlertText1, SDLTextFieldNameAlertText2, SDLTextFieldNameAlertText3, SDLTextFieldNameMainField1, SDLTextFieldNameMainField2, SDLTextFieldNameMainField3, SDLTextFieldNameMainField4, SDLTextFieldNameMediaClock, SDLTextFieldNameMediaTrack, SDLTextFieldNamePhoneNumber, SDLTextFieldNameAddressLines, SDLTextFieldNameLocationName, SDLTextFieldNameSliderFooter, SDLTextFieldNameSliderHeader, SDLTextFieldNameTertiaryText, SDLTextFieldNameSecondaryText, SDLTextFieldNameTemplateTitle, SDLTextFieldNameTotalDistance, SDLTextFieldNameNavigationText1, SDLTextFieldNameNavigationText2, SDLTextFieldNameLocationDescription, SDLTextFieldNameScrollableMessageBody, SDLTextFieldNameInitialInteractionText, SDLTextFieldNameAudioPassThruDisplayText1, SDLTextFieldNameAudioPassThruDisplayText2, SDLTextFieldNameTimeToDestination, SDLTextFieldNameTurnText]; } #pragma clang diagnostic pop diff --git a/SmartDeviceLink/private/SDLWindowCapability+ScreenManagerExtensions.h b/SmartDeviceLink/private/SDLWindowCapability+ScreenManagerExtensions.h index 9321c98cd..ca095da24 100644 --- a/SmartDeviceLink/private/SDLWindowCapability+ScreenManagerExtensions.h +++ b/SmartDeviceLink/private/SDLWindowCapability+ScreenManagerExtensions.h @@ -12,6 +12,8 @@ #import "SDLTextFieldName.h" #import "SDLWindowCapability.h" +@class SDLKeyboardProperties; + NS_ASSUME_NONNULL_BEGIN @interface SDLWindowCapability (ScreenManagerExtensions) @@ -21,6 +23,13 @@ NS_ASSUME_NONNULL_BEGIN - (BOOL)hasTextFieldOfName:(SDLTextFieldName)name; - (BOOL)hasImageFieldOfName:(SDLImageFieldName)name; +/// Takes a keyboard configuration (SDLKeyboardProperties) and creates a valid version of it, if possible, based on this object's internal keyboardCapabilities (SDLKeyboardCapabilities). +/// If there is no internal keyboardCapabilities, it will just return the passed configuration as-is. +/// If no valid configuration can be determined based on the internal keyboard capabilities, it will return nil. +/// @param keyboardConfiguration The configuration to use to determine a valid configuration +/// @return The passed keyboardConfiguration if there are no changes needed or possible, a modified keyboardConfiguration if a valid version of the configuration could be determined, or nil if a valid configuration could not be created +- (nullable SDLKeyboardProperties *)createValidKeyboardConfigurationBasedOnKeyboardCapabilitiesFromConfiguration:(nullable SDLKeyboardProperties *)keyboardConfiguration; + @end NS_ASSUME_NONNULL_END diff --git a/SmartDeviceLink/private/SDLWindowCapability+ScreenManagerExtensions.m b/SmartDeviceLink/private/SDLWindowCapability+ScreenManagerExtensions.m index 441356a83..9aa00fa62 100644 --- a/SmartDeviceLink/private/SDLWindowCapability+ScreenManagerExtensions.m +++ b/SmartDeviceLink/private/SDLWindowCapability+ScreenManagerExtensions.m @@ -10,6 +10,10 @@ #import "SDLWindowCapability+ScreenManagerExtensions.h" #import "SDLImageField.h" +#import "SDLKeyboardCapabilities.h" +#import "SDLKeyboardLayoutCapability.h" +#import "SDLKeyboardProperties.h" +#import "SDLLogMacros.h" #import "SDLTextField.h" @implementation SDLWindowCapability (ScreenManagerExtensions) @@ -52,4 +56,44 @@ return NO; } +- (nullable SDLKeyboardProperties *)createValidKeyboardConfigurationBasedOnKeyboardCapabilitiesFromConfiguration:(nullable SDLKeyboardProperties *)keyboardConfiguration { + // If there are no keyboard capabilities, if there is no passed keyboard configuration, or if there is no layout to the passed keyboard configuration, just pass back the passed in configuration + if ((self.keyboardCapabilities == nil) || (keyboardConfiguration == nil) || (keyboardConfiguration.keyboardLayout == nil)) { + return keyboardConfiguration; + } + + // Find the capability for the keyboard configuration's layout + SDLKeyboardLayoutCapability *selectedLayoutCapability = nil; + for (SDLKeyboardLayoutCapability *layoutCapability in self.keyboardCapabilities.supportedKeyboards) { + if ([layoutCapability.keyboardLayout isEqualToEnum:keyboardConfiguration.keyboardLayout]) { + selectedLayoutCapability = layoutCapability; + break; + } + } + if (selectedLayoutCapability == nil) { + SDLLogE(@"Configured keyboard layout is not supported: %@", keyboardConfiguration.keyboardLayout); + return nil; + } + + // Modify the keyboard configuration if there are fewer customKeys allowed than were set, or if an empty array was set. + SDLKeyboardProperties *modifiedKeyboardConfiguration = [keyboardConfiguration copy]; + if (keyboardConfiguration.customKeys.count == 0) { + modifiedKeyboardConfiguration.customKeys = nil; + } else { + NSUInteger numConfigurableKeys = selectedLayoutCapability.numConfigurableKeys.unsignedIntegerValue; + if (modifiedKeyboardConfiguration.customKeys.count > numConfigurableKeys) { + SDLLogW(@"%lu custom keys set, but the selected layout: %@ only supports %lu. Dropping the rest.", (unsigned long)modifiedKeyboardConfiguration.customKeys.count, modifiedKeyboardConfiguration.keyboardLayout, (unsigned long)numConfigurableKeys); + // If there are more custom keys than are allowed for the selected keyboard layout, we need to trim the number of keys to only use the first n number of custom keys, where n is the number of allowed custom keys for that layout. + modifiedKeyboardConfiguration.customKeys = [modifiedKeyboardConfiguration.customKeys subarrayWithRange:NSMakeRange(0, numConfigurableKeys)]; + } + } + + // If the keyboard does not support masking input characters, we will remove it from the keyboard configuration + if (!self.keyboardCapabilities.maskInputCharactersSupported.boolValue) { + modifiedKeyboardConfiguration.maskInputCharacters = nil; + } + + return modifiedKeyboardConfiguration; +} + @end diff --git a/SmartDeviceLink/public/SDLAddCommand.h b/SmartDeviceLink/public/SDLAddCommand.h index ea5968970..e07c774a3 100644 --- a/SmartDeviceLink/public/SDLAddCommand.h +++ b/SmartDeviceLink/public/SDLAddCommand.h @@ -37,7 +37,7 @@ NS_ASSUME_NONNULL_BEGIN * * @return A SDLAddCommand object */ -- (instancetype)initWithHandler:(nullable SDLRPCCommandNotificationHandler)handler; +- (instancetype)initWithHandler:(nullable SDLRPCCommandNotificationHandler)handler __deprecated_msg("Use initWithCmdID:menuParams:vrCommands:cmdIcon:secondaryImage: instead"); /** * Convenience init for creating a voice command menu item. @@ -49,7 +49,7 @@ NS_ASSUME_NONNULL_BEGIN * @param handler Called when the VR system recognizes a phrase in `vrCommands` * @return A SDLAddCommand object */ -- (instancetype)initWithId:(UInt32)commandId vrCommands:(nullable NSArray<NSString *> *)vrCommands handler:(nullable SDLRPCCommandNotificationHandler)handler; +- (instancetype)initWithId:(UInt32)commandId vrCommands:(nullable NSArray<NSString *> *)vrCommands handler:(nullable SDLRPCCommandNotificationHandler)handler __deprecated_msg("Use initWithCmdID:menuParams:vrCommands:cmdIcon:secondaryImage: instead"); /** * Convenience init for creating a menu item with text. @@ -60,7 +60,7 @@ NS_ASSUME_NONNULL_BEGIN * @param handler Called when the menu item is selected and/or when the VR system recognizes a phrase in `vrCommands` * @return A SDLAddCommand object */ -- (instancetype)initWithId:(UInt32)commandId vrCommands:(nullable NSArray<NSString *> *)vrCommands menuName:(NSString *)menuName handler:(nullable SDLRPCCommandNotificationHandler)handler; +- (instancetype)initWithId:(UInt32)commandId vrCommands:(nullable NSArray<NSString *> *)vrCommands menuName:(NSString *)menuName handler:(nullable SDLRPCCommandNotificationHandler)handler __deprecated_msg("Use initWithCmdID:menuParams:vrCommands:cmdIcon:secondaryImage: instead"); /** * Convenience init for creating a menu item with text and a custom icon. @@ -78,7 +78,7 @@ NS_ASSUME_NONNULL_BEGIN * @param handler Called when the menu item is selected and/or when the VR system recognizes a phrase in `vrCommands` * @return A SDLAddCommand object */ -- (instancetype)initWithId:(UInt32)commandId vrCommands:(nullable NSArray<NSString *> *)vrCommands menuName:(NSString *)menuName parentId:(UInt32)parentId position:(UInt16)position iconValue:(nullable NSString *)iconValue iconType:(nullable SDLImageType)iconType iconIsTemplate:(BOOL)iconIsTemplate handler:(nullable SDLRPCCommandNotificationHandler)handler; +- (instancetype)initWithId:(UInt32)commandId vrCommands:(nullable NSArray<NSString *> *)vrCommands menuName:(NSString *)menuName parentId:(UInt32)parentId position:(UInt16)position iconValue:(nullable NSString *)iconValue iconType:(nullable SDLImageType)iconType iconIsTemplate:(BOOL)iconIsTemplate handler:(nullable SDLRPCCommandNotificationHandler)handler __deprecated_msg("Use initWithCmdID:menuParams:vrCommands:cmdIcon:secondaryImage: instead"); /** * Convenience init for creating a menu item with text and a custom icon. @@ -94,7 +94,23 @@ NS_ASSUME_NONNULL_BEGIN * @param handler Called when the menu item is selected and/or when the VR system recognizes a phrase in `vrCommands` * @return A SDLAddCommand object */ -- (instancetype)initWithId:(UInt32)commandId vrCommands:(nullable NSArray<NSString *> *)vrCommands menuName:(NSString *)menuName parentId:(UInt32)parentId position:(UInt16)position icon:(nullable SDLImage *)icon handler:(nullable SDLRPCCommandNotificationHandler)handler; +- (instancetype)initWithId:(UInt32)commandId vrCommands:(nullable NSArray<NSString *> *)vrCommands menuName:(NSString *)menuName parentId:(UInt32)parentId position:(UInt16)position icon:(nullable SDLImage *)icon handler:(nullable SDLRPCCommandNotificationHandler)handler __deprecated_msg("Use initWithCmdID:menuParams:vrCommands:cmdIcon:secondaryImage: instead"); + +/** + * @param cmdID - @(cmdID) + * @return A SDLAddCommand object + */ +- (instancetype)initWithCmdID:(UInt32)cmdID; + +/** + * @param cmdID - @(cmdID) + * @param menuParams - menuParams + * @param vrCommands - vrCommands + * @param cmdIcon - cmdIcon + * @param secondaryImage - secondaryImage + * @return A SDLAddCommand object + */ +- (instancetype)initWithCmdID:(UInt32)cmdID menuParams:(nullable SDLMenuParams *)menuParams vrCommands:(nullable NSArray<NSString *> *)vrCommands cmdIcon:(nullable SDLImage *)cmdIcon secondaryImage:(nullable SDLImage *)secondaryImage; /** * A handler that will let you know when the button you created is subscribed. @@ -139,6 +155,13 @@ NS_ASSUME_NONNULL_BEGIN */ @property (nullable, strong, nonatomic) SDLImage *cmdIcon; +/** + * Optional secondary image struct for menu cell + * + * @added in SmartDeviceLink 7.1.0 + */ +@property (nullable, strong, nonatomic) SDLImage *secondaryImage; + @end NS_ASSUME_NONNULL_END diff --git a/SmartDeviceLink/public/SDLAddCommand.m b/SmartDeviceLink/public/SDLAddCommand.m index 83da5658f..c86004e97 100644 --- a/SmartDeviceLink/public/SDLAddCommand.m +++ b/SmartDeviceLink/public/SDLAddCommand.m @@ -87,6 +87,27 @@ NS_ASSUME_NONNULL_BEGIN return self; } +- (instancetype)initWithCmdID:(UInt32)cmdID { + self = [self init]; + if (!self) { + return nil; + } + self.cmdID = @(cmdID); + return self; +} + +- (instancetype)initWithCmdID:(UInt32)cmdID menuParams:(nullable SDLMenuParams *)menuParams vrCommands:(nullable NSArray<NSString *> *)vrCommands cmdIcon:(nullable SDLImage *)cmdIcon secondaryImage:(nullable SDLImage *)secondaryImage { + self = [self initWithCmdID:cmdID]; + if (!self) { + return nil; + } + self.menuParams = menuParams; + self.vrCommands = vrCommands; + self.cmdIcon = cmdIcon; + self.secondaryImage = secondaryImage; + return self; +} + #pragma mark - Getters / Setters - (void)setCmdID:(NSNumber<SDLInt> *)cmdID { @@ -122,6 +143,14 @@ NS_ASSUME_NONNULL_BEGIN return [self.parameters sdl_objectForName:SDLRPCParameterNameCommandIcon ofClass:SDLImage.class error:nil]; } +- (void)setSecondaryImage:(nullable SDLImage *)secondaryImage { + [self.parameters sdl_setObject:secondaryImage forName:SDLRPCParameterNameSecondaryImage]; +} + +- (nullable SDLImage *)secondaryImage { + return [self.parameters sdl_objectForName:SDLRPCParameterNameSecondaryImage ofClass:SDLImage.class error:nil]; +} + -(id)copyWithZone:(nullable NSZone *)zone { SDLAddCommand *newCommand = [super copyWithZone:zone]; newCommand->_handler = self.handler; diff --git a/SmartDeviceLink/public/SDLAddSubMenu.h b/SmartDeviceLink/public/SDLAddSubMenu.h index 2de2f466d..948060aef 100644 --- a/SmartDeviceLink/public/SDLAddSubMenu.h +++ b/SmartDeviceLink/public/SDLAddSubMenu.h @@ -71,7 +71,21 @@ NS_ASSUME_NONNULL_BEGIN * @param parentID - parentID * @return A SDLAddSubMenu object */ -- (instancetype)initWithMenuID:(UInt32)menuID menuName:(NSString *)menuName position:(nullable NSNumber<SDLUInt> *)position menuIcon:(nullable SDLImage *)menuIcon menuLayout:(nullable SDLMenuLayout)menuLayout parentID:(nullable NSNumber<SDLUInt> *)parentID; +- (instancetype)initWithMenuID:(UInt32)menuID menuName:(NSString *)menuName position:(nullable NSNumber<SDLUInt> *)position menuIcon:(nullable SDLImage *)menuIcon menuLayout:(nullable SDLMenuLayout)menuLayout parentID:(nullable NSNumber<SDLUInt> *)parentID __deprecated_msg("Use initWithMenuID:menuName:position:menuIcon:menuLayout:parentID:secondaryText:tertiaryText:secondaryImage: instead"); + +/** + * @param menuID - @(menuID) + * @param menuName - menuName + * @param position - position + * @param menuIcon - menuIcon + * @param menuLayout - menuLayout + * @param parentID - parentID + * @param secondaryText - secondaryText + * @param tertiaryText - tertiaryText + * @param secondaryImage - secondaryImage + * @return A SDLAddSubMenu object + */ +- (instancetype)initWithMenuID:(UInt32)menuID menuName:(NSString *)menuName position:(nullable NSNumber<SDLUInt> *)position menuIcon:(nullable SDLImage *)menuIcon menuLayout:(nullable SDLMenuLayout)menuLayout parentID:(nullable NSNumber<SDLUInt> *)parentID secondaryText:(nullable NSString *)secondaryText tertiaryText:(nullable NSString *)tertiaryText secondaryImage:(nullable SDLImage *)secondaryImage; /** * a Menu ID that identifies a sub menu @@ -125,6 +139,29 @@ NS_ASSUME_NONNULL_BEGIN */ @property (nullable, strong, nonatomic) NSNumber<SDLUInt> *parentID; +/** + * Optional secondary text to display + * {"string_min_length": 1, "string_max_length": 500} + * + * @added in SmartDeviceLink 7.1.0 + */ +@property (nullable, strong, nonatomic) NSString *secondaryText; + +/** + * Optional tertiary text to display + * {"string_min_length": 1, "string_max_length": 500} + * + * @added in SmartDeviceLink 7.1.0 + */ +@property (nullable, strong, nonatomic) NSString *tertiaryText; + +/** + * Optional secondary image struct for sub-menu cell + * + * @added in SmartDeviceLink 7.1.0 + */ +@property (nullable, strong, nonatomic) SDLImage *secondaryImage; + @end NS_ASSUME_NONNULL_END diff --git a/SmartDeviceLink/public/SDLAddSubMenu.m b/SmartDeviceLink/public/SDLAddSubMenu.m index 06a615df1..5524e9220 100644 --- a/SmartDeviceLink/public/SDLAddSubMenu.m +++ b/SmartDeviceLink/public/SDLAddSubMenu.m @@ -61,6 +61,10 @@ NS_ASSUME_NONNULL_BEGIN } - (instancetype)initWithMenuID:(UInt32)menuID menuName:(NSString *)menuName position:(nullable NSNumber<SDLUInt> *)position menuIcon:(nullable SDLImage *)menuIcon menuLayout:(nullable SDLMenuLayout)menuLayout parentID:(nullable NSNumber<SDLUInt> *)parentID { + return [self initWithMenuID:menuID menuName:menuName position:position menuIcon:menuIcon menuLayout:menuLayout parentID:parentID secondaryText:nil tertiaryText:nil secondaryImage:nil]; +} + +- (instancetype)initWithMenuID:(UInt32)menuID menuName:(NSString *)menuName position:(nullable NSNumber<SDLUInt> *)position menuIcon:(nullable SDLImage *)menuIcon menuLayout:(nullable SDLMenuLayout)menuLayout parentID:(nullable NSNumber<SDLUInt> *)parentID secondaryText:(nullable NSString *)secondaryText tertiaryText:(nullable NSString *)tertiaryText secondaryImage:(nullable SDLImage *)secondaryImage { self = [self initWithMenuID:menuID menuName:menuName]; if (!self) { return nil; @@ -69,6 +73,9 @@ NS_ASSUME_NONNULL_BEGIN self.menuIcon = menuIcon; self.menuLayout = menuLayout; self.parentID = parentID; + self.secondaryText = secondaryText; + self.tertiaryText = tertiaryText; + self.secondaryImage = secondaryImage; return self; } @@ -122,6 +129,30 @@ NS_ASSUME_NONNULL_BEGIN return [self.parameters sdl_objectForName:SDLRPCParameterNameParentID ofClass:NSNumber.class error:nil]; } +- (void)setSecondaryText:(nullable NSString *)secondaryText { + [self.parameters sdl_setObject:secondaryText forName:SDLRPCParameterNameSecondaryText]; +} + +- (nullable NSString *)secondaryText { + return [self.parameters sdl_objectForName:SDLRPCParameterNameSecondaryText ofClass:NSString.class error:nil]; +} + +- (void)setTertiaryText:(nullable NSString *)tertiaryText { + [self.parameters sdl_setObject:tertiaryText forName:SDLRPCParameterNameTertiaryText]; +} + +- (nullable NSString *)tertiaryText { + return [self.parameters sdl_objectForName:SDLRPCParameterNameTertiaryText ofClass:NSString.class error:nil]; +} + +- (void)setSecondaryImage:(nullable SDLImage *)secondaryImage { + [self.parameters sdl_setObject:secondaryImage forName:SDLRPCParameterNameSecondaryImage]; +} + +- (nullable SDLImage *)secondaryImage { + return [self.parameters sdl_objectForName:SDLRPCParameterNameSecondaryImage ofClass:SDLImage.class error:nil]; +} + @end NS_ASSUME_NONNULL_END diff --git a/SmartDeviceLink/public/SDLImageFieldName.h b/SmartDeviceLink/public/SDLImageFieldName.h index 0bac7e2a8..16eefd736 100644 --- a/SmartDeviceLink/public/SDLImageFieldName.h +++ b/SmartDeviceLink/public/SDLImageFieldName.h @@ -125,3 +125,17 @@ extern SDLImageFieldName const SDLImageFieldNameSubMenuIcon; * @since SDL 7.0 */ extern SDLImageFieldName const SDLImageFieldNameSubtleAlertIcon; + +/** + * The secondary image field for AddCommand + * + * @added in SmartDeviceLink 7.0.0 + */ +extern SDLImageFieldName const SDLImageFieldNameMenuCommandSecondaryImage; + +/** + * The secondary image field for AddSubMenu + * + * @added in SmartDeviceLink 7.0.0 + */ +extern SDLImageFieldName const SDLImageFieldNameMenuSubMenuSecondaryImage; diff --git a/SmartDeviceLink/public/SDLImageFieldName.m b/SmartDeviceLink/public/SDLImageFieldName.m index dd195ce82..ecefa251b 100644 --- a/SmartDeviceLink/public/SDLImageFieldName.m +++ b/SmartDeviceLink/public/SDLImageFieldName.m @@ -49,3 +49,5 @@ SDLImageFieldName const SDLImageFieldNameShowConstantTBTNextTurnIcon = @"showCon SDLImageFieldName const SDLImageFieldNameLocationImage = @"locationImage"; SDLImageFieldName const SDLImageFieldNameSubMenuIcon = @"subMenuIcon"; SDLImageFieldName const SDLImageFieldNameSubtleAlertIcon = @"subtleAlertIcon"; +SDLImageFieldName const SDLImageFieldNameMenuCommandSecondaryImage = @"menuCommandSecondaryImage"; +SDLImageFieldName const SDLImageFieldNameMenuSubMenuSecondaryImage = @"menuSubMenuSecondaryImage"; diff --git a/SmartDeviceLink/public/SDLKeyboardCapabilities.h b/SmartDeviceLink/public/SDLKeyboardCapabilities.h new file mode 100644 index 000000000..9ed4e831e --- /dev/null +++ b/SmartDeviceLink/public/SDLKeyboardCapabilities.h @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2021, SmartDeviceLink Consortium, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the + * distribution. + * + * Neither the name of the SmartDeviceLink Consortium Inc. nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#import "SDLRPCStruct.h" + +@class SDLKeyboardLayoutCapability; + +NS_ASSUME_NONNULL_BEGIN + +/** + * @added in SmartDeviceLink 7.1.0 + */ +@interface SDLKeyboardCapabilities : SDLRPCStruct + +/** + * @param maskInputCharactersSupported - maskInputCharactersSupported + * @param supportedKeyboards - supportedKeyboards + * @return A SDLKeyboardCapabilities object + */ +- (instancetype)initWithMaskInputCharactersSupported:(nullable NSNumber<SDLBool> *)maskInputCharactersSupported supportedKeyboards:(nullable NSArray<SDLKeyboardLayoutCapability *> *)supportedKeyboards; + +/** + * Availability of capability to mask input characters using keyboard. True: Available, False: Not Available + */ +@property (nullable, strong, nonatomic) NSNumber<SDLBool> *maskInputCharactersSupported; + +/** + * Capabilities of supported keyboard layouts by HMI. + * {"array_min_size": 1, "array_max_size": 1000} + */ +@property (nullable, strong, nonatomic) NSArray<SDLKeyboardLayoutCapability *> *supportedKeyboards; + +@end + +NS_ASSUME_NONNULL_END diff --git a/SmartDeviceLink/public/SDLKeyboardCapabilities.m b/SmartDeviceLink/public/SDLKeyboardCapabilities.m new file mode 100644 index 000000000..27799f17a --- /dev/null +++ b/SmartDeviceLink/public/SDLKeyboardCapabilities.m @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2021, SmartDeviceLink Consortium, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the + * distribution. + * + * Neither the name of the SmartDeviceLink Consortium Inc. nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#import "NSMutableDictionary+Store.h" +#import "SDLKeyboardCapabilities.h" +#import "SDLKeyboardLayoutCapability.h" +#import "SDLRPCParameterNames.h" + +NS_ASSUME_NONNULL_BEGIN + +@implementation SDLKeyboardCapabilities + +- (instancetype)initWithMaskInputCharactersSupported:(nullable NSNumber<SDLBool> *)maskInputCharactersSupported supportedKeyboards:(nullable NSArray<SDLKeyboardLayoutCapability *> *)supportedKeyboards { + self = [self init]; + if (!self) { + return nil; + } + self.maskInputCharactersSupported = maskInputCharactersSupported; + self.supportedKeyboards = supportedKeyboards; + return self; +} + +- (void)setMaskInputCharactersSupported:(nullable NSNumber<SDLBool> *)maskInputCharactersSupported { + [self.store sdl_setObject:maskInputCharactersSupported forName:SDLRPCParameterNameMaskInputCharactersSupported]; +} + +- (nullable NSNumber<SDLBool> *)maskInputCharactersSupported { + return [self.store sdl_objectForName:SDLRPCParameterNameMaskInputCharactersSupported ofClass:NSNumber.class error:nil]; +} + +- (void)setSupportedKeyboards:(nullable NSArray<SDLKeyboardLayoutCapability *> *)supportedKeyboards { + [self.store sdl_setObject:supportedKeyboards forName:SDLRPCParameterNameSupportedKeyboards]; +} + +- (nullable NSArray<SDLKeyboardLayoutCapability *> *)supportedKeyboards { + return [self.store sdl_objectsForName:SDLRPCParameterNameSupportedKeyboards ofClass:SDLKeyboardLayoutCapability.class error:nil]; +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/SmartDeviceLink/public/SDLKeyboardDelegate.h b/SmartDeviceLink/public/SDLKeyboardDelegate.h index 652066d64..33da49969 100644 --- a/SmartDeviceLink/public/SDLKeyboardDelegate.h +++ b/SmartDeviceLink/public/SDLKeyboardDelegate.h @@ -93,6 +93,14 @@ typedef void(^SDLKeyboardCharacterSetCompletionHandler)(NSArray<NSString *> *_Nu */ - (void)keyboardDidSendEvent:(SDLKeyboardEvent)event text:(NSString *)currentInputText; +/** + Implement this to be notified of input key mask update (whether or not the user has changed the input to be hidden, like passwords) + + @param isEnabled - YES if the mask is enabled, NO if the mask is disabled + @added in SmartDeviceLink 7.1.0 + */ +- (void)keyboardDidUpdateInputMask:(BOOL)isEnabled; + @end NS_ASSUME_NONNULL_END diff --git a/SmartDeviceLink/public/SDLKeyboardEvent.h b/SmartDeviceLink/public/SDLKeyboardEvent.h index 1ac7b67e4..9e017c8d6 100644 --- a/SmartDeviceLink/public/SDLKeyboardEvent.h +++ b/SmartDeviceLink/public/SDLKeyboardEvent.h @@ -37,3 +37,13 @@ extern SDLKeyboardEvent const SDLKeyboardEventAborted; @since SDL 4.0 */ extern SDLKeyboardEvent const SDLKeyboardEventVoice; + +/** + * @added in SmartDeviceLink 7.1.0 + */ +extern SDLKeyboardEvent const SDLKeyboardEventInputKeyMaskEnabled; + +/** + * @added in SmartDeviceLink 7.1.0 + */ +extern SDLKeyboardEvent const SDLKeyboardEventInputKeyMaskDisabled; diff --git a/SmartDeviceLink/public/SDLKeyboardEvent.m b/SmartDeviceLink/public/SDLKeyboardEvent.m index 67f4e60f2..f55ac3597 100644 --- a/SmartDeviceLink/public/SDLKeyboardEvent.m +++ b/SmartDeviceLink/public/SDLKeyboardEvent.m @@ -9,3 +9,5 @@ SDLKeyboardEvent const SDLKeyboardEventSubmitted = @"ENTRY_SUBMITTED"; SDLKeyboardEvent const SDLKeyboardEventCancelled = @"ENTRY_CANCELLED"; SDLKeyboardEvent const SDLKeyboardEventAborted = @"ENTRY_ABORTED"; SDLKeyboardEvent const SDLKeyboardEventVoice = @"ENTRY_VOICE"; +SDLKeyboardEvent const SDLKeyboardEventInputKeyMaskEnabled = @"INPUT_KEY_MASK_ENABLED"; +SDLKeyboardEvent const SDLKeyboardEventInputKeyMaskDisabled = @"INPUT_KEY_MASK_DISABLED"; diff --git a/SmartDeviceLink/public/SDLKeyboardInputMask.h b/SmartDeviceLink/public/SDLKeyboardInputMask.h new file mode 100644 index 000000000..fc16b1756 --- /dev/null +++ b/SmartDeviceLink/public/SDLKeyboardInputMask.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2021, SmartDeviceLink Consortium, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the + * distribution. + * + * Neither the name of the SmartDeviceLink Consortium Inc. nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#import "SDLEnum.h" + +/** + * Enumeration listing possible input character masking. + * + * @added in SmartDeviceLink 7.1.0 + */ +typedef SDLEnum SDLKeyboardInputMask NS_TYPED_ENUM; + +extern SDLKeyboardInputMask const SDLKeyboardInputMaskEnableInputKeyMask; + +extern SDLKeyboardInputMask const SDLKeyboardInputMaskDisableInputKeyMask; + +extern SDLKeyboardInputMask const SDLKeyboardInputMaskUserChoiceInputKeyMask; diff --git a/SmartDeviceLink/public/SDLKeyboardInputMask.m b/SmartDeviceLink/public/SDLKeyboardInputMask.m new file mode 100644 index 000000000..e8be72db1 --- /dev/null +++ b/SmartDeviceLink/public/SDLKeyboardInputMask.m @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2021, SmartDeviceLink Consortium, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the + * distribution. + * + * Neither the name of the SmartDeviceLink Consortium Inc. nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#import "SDLKeyboardInputMask.h" + +SDLKeyboardInputMask const SDLKeyboardInputMaskEnableInputKeyMask = @"ENABLE_INPUT_KEY_MASK"; +SDLKeyboardInputMask const SDLKeyboardInputMaskDisableInputKeyMask = @"DISABLE_INPUT_KEY_MASK"; +SDLKeyboardInputMask const SDLKeyboardInputMaskUserChoiceInputKeyMask = @"USER_CHOICE_INPUT_KEY_MASK"; diff --git a/SmartDeviceLink/public/SDLKeyboardLayout.h b/SmartDeviceLink/public/SDLKeyboardLayout.h index 4b4e97550..181836146 100644 --- a/SmartDeviceLink/public/SDLKeyboardLayout.h +++ b/SmartDeviceLink/public/SDLKeyboardLayout.h @@ -25,3 +25,8 @@ extern SDLKeyboardLayout const SDLKeyboardLayoutQWERTZ; AZERTY layout (the name comes from the first six keys<br> appearing on the top left letter row of the keyboard and read from left to right) */ extern SDLKeyboardLayout const SDLKeyboardLayoutAZERTY; + +/** + * @added in SmartDeviceLink 7.1.0 + */ +extern SDLKeyboardLayout const SDLKeyboardLayoutNumeric; diff --git a/SmartDeviceLink/public/SDLKeyboardLayout.m b/SmartDeviceLink/public/SDLKeyboardLayout.m index 7fa8e1958..0bc5ecc3b 100644 --- a/SmartDeviceLink/public/SDLKeyboardLayout.m +++ b/SmartDeviceLink/public/SDLKeyboardLayout.m @@ -7,3 +7,4 @@ SDLKeyboardLayout const SDLKeyboardLayoutQWERTY = @"QWERTY"; SDLKeyboardLayout const SDLKeyboardLayoutQWERTZ = @"QWERTZ"; SDLKeyboardLayout const SDLKeyboardLayoutAZERTY = @"AZERTY"; +SDLKeyboardLayout const SDLKeyboardLayoutNumeric = @"NUMERIC"; diff --git a/SmartDeviceLink/public/SDLKeyboardLayoutCapability.h b/SmartDeviceLink/public/SDLKeyboardLayoutCapability.h new file mode 100644 index 000000000..b78218663 --- /dev/null +++ b/SmartDeviceLink/public/SDLKeyboardLayoutCapability.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2021, SmartDeviceLink Consortium, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the + * distribution. + * + * Neither the name of the SmartDeviceLink Consortium Inc. nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#import "SDLKeyboardLayout.h" +#import "SDLRPCStruct.h" + +NS_ASSUME_NONNULL_BEGIN + +/** + * Describes the capabilities of a single keyboard layout. + * + * @added in SmartDeviceLink 7.1.0 + */ +@interface SDLKeyboardLayoutCapability : SDLRPCStruct + +/** + * @param keyboardLayout - keyboardLayout + * @param numConfigurableKeys - @(numConfigurableKeys) + * @return A SDLKeyboardLayoutCapability object + */ +- (instancetype)initWithKeyboardLayout:(SDLKeyboardLayout)keyboardLayout numConfigurableKeys:(UInt8)numConfigurableKeys; + +@property (strong, nonatomic) SDLKeyboardLayout keyboardLayout; + +/** + * Number of keys available for special characters, App can customize as per their needs. + * {"num_min_value": 0, "num_max_value": 10} + */ +@property (strong, nonatomic) NSNumber<SDLUInt> *numConfigurableKeys; + +@end + +NS_ASSUME_NONNULL_END diff --git a/SmartDeviceLink/public/SDLKeyboardLayoutCapability.m b/SmartDeviceLink/public/SDLKeyboardLayoutCapability.m new file mode 100644 index 000000000..57cb9a81c --- /dev/null +++ b/SmartDeviceLink/public/SDLKeyboardLayoutCapability.m @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2021, SmartDeviceLink Consortium, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the + * distribution. + * + * Neither the name of the SmartDeviceLink Consortium Inc. nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#import "NSMutableDictionary+Store.h" +#import "SDLKeyboardLayout.h" +#import "SDLKeyboardLayoutCapability.h" +#import "SDLRPCParameterNames.h" + +NS_ASSUME_NONNULL_BEGIN + +@implementation SDLKeyboardLayoutCapability + +- (instancetype)initWithKeyboardLayout:(SDLKeyboardLayout)keyboardLayout numConfigurableKeys:(UInt8)numConfigurableKeys { + self = [self init]; + if (!self) { + return nil; + } + self.keyboardLayout = keyboardLayout; + self.numConfigurableKeys = @(numConfigurableKeys); + return self; +} + +- (void)setKeyboardLayout:(SDLKeyboardLayout)keyboardLayout { + [self.store sdl_setObject:keyboardLayout forName:SDLRPCParameterNameKeyboardLayout]; +} + +- (SDLKeyboardLayout)keyboardLayout { + NSError *error = nil; + return [self.store sdl_enumForName:SDLRPCParameterNameKeyboardLayout error:&error]; +} + +- (void)setNumConfigurableKeys:(NSNumber<SDLUInt> *)numConfigurableKeys { + [self.store sdl_setObject:numConfigurableKeys forName:SDLRPCParameterNameNumConfigurableKeys]; +} + +- (NSNumber<SDLUInt> *)numConfigurableKeys { + NSError *error = nil; + return [self.store sdl_objectForName:SDLRPCParameterNameNumConfigurableKeys ofClass:NSNumber.class error:&error]; +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/SmartDeviceLink/public/SDLKeyboardProperties.h b/SmartDeviceLink/public/SDLKeyboardProperties.h index a538b52bd..55a3ed1b0 100644 --- a/SmartDeviceLink/public/SDLKeyboardProperties.h +++ b/SmartDeviceLink/public/SDLKeyboardProperties.h @@ -1,11 +1,11 @@ // SDLKeyboardProperties.h // -#import "SDLRPCMessage.h" - +#import "SDLKeyboardInputMask.h" #import "SDLKeyboardLayout.h" #import "SDLKeypressMode.h" #import "SDLLanguage.h" +#import "SDLRPCStruct.h" NS_ASSUME_NONNULL_BEGIN @@ -25,7 +25,7 @@ NS_ASSUME_NONNULL_BEGIN @param autoCompleteList A list of strings to show the user to complete what they are typing. @return The RPC object */ -- (instancetype)initWithLanguage:(nullable SDLLanguage)language layout:(nullable SDLKeyboardLayout)layout keypressMode:(nullable SDLKeypressMode)keypressMode limitedCharacterList:(nullable NSArray<NSString *> *)limitedCharacterList autoCompleteText:(nullable NSString *)autoCompleteText autoCompleteList:(nullable NSArray<NSString *> *)autoCompleteList __deprecated_msg("Use initWithLanguage:keyboardLayout:keypressMode:limitedCharacterList:autoCompleteList: instead"); +- (instancetype)initWithLanguage:(nullable SDLLanguage)language layout:(nullable SDLKeyboardLayout)layout keypressMode:(nullable SDLKeypressMode)keypressMode limitedCharacterList:(nullable NSArray<NSString *> *)limitedCharacterList autoCompleteText:(nullable NSString *)autoCompleteText autoCompleteList:(nullable NSArray<NSString *> *)autoCompleteList __deprecated_msg("Use initWithLanguage:keyboardLayout:keypressMode:limitedCharacterList:autoCompleteList:maskInputCharacters:customKeys: instead"); /** * Convenience init with all properties. @@ -37,7 +37,19 @@ NS_ASSUME_NONNULL_BEGIN * @param autoCompleteList - autoCompleteList * @return A SDLKeyboardProperties object */ -- (instancetype)initWithLanguage:(nullable SDLLanguage)language keyboardLayout:(nullable SDLKeyboardLayout)keyboardLayout keypressMode:(nullable SDLKeypressMode)keypressMode limitedCharacterList:(nullable NSArray<NSString *> *)limitedCharacterList autoCompleteList:(nullable NSArray<NSString *> *)autoCompleteList; +- (instancetype)initWithLanguage:(nullable SDLLanguage)language keyboardLayout:(nullable SDLKeyboardLayout)keyboardLayout keypressMode:(nullable SDLKeypressMode)keypressMode limitedCharacterList:(nullable NSArray<NSString *> *)limitedCharacterList autoCompleteList:(nullable NSArray<NSString *> *)autoCompleteList __deprecated_msg("Use initWithLanguage:keyboardLayout:keypressMode:limitedCharacterList:autoCompleteList:maskInputCharacters:customKeys: instead"); + +/** + * @param language - language + * @param keyboardLayout - keyboardLayout + * @param keypressMode - keypressMode + * @param limitedCharacterList - limitedCharacterList + * @param autoCompleteList - autoCompleteList + * @param maskInputCharacters - maskInputCharacters + * @param customKeys - customKeys + * @return A SDLKeyboardProperties object + */ +- (instancetype)initWithLanguage:(nullable SDLLanguage)language keyboardLayout:(nullable SDLKeyboardLayout)keyboardLayout keypressMode:(nullable SDLKeypressMode)keypressMode limitedCharacterList:(nullable NSArray<NSString *> *)limitedCharacterList autoCompleteList:(nullable NSArray<NSString *> *)autoCompleteList maskInputCharacters:(nullable SDLKeyboardInputMask)maskInputCharacters customKeys:(nullable NSArray<NSString *> *)customKeys; /** The keyboard language @@ -85,6 +97,21 @@ NS_ASSUME_NONNULL_BEGIN */ @property (nullable, strong, nonatomic) NSArray<NSString *> *autoCompleteList; +/** + * Allows an app to mask entered characters on HMI + * + * @added in SmartDeviceLink 7.1.0 + */ +@property (nullable, strong, nonatomic) SDLKeyboardInputMask maskInputCharacters; + +/** + * Array of special characters to show in customizable keys. If omitted, keyboard will show default special characters + * {"array_min_size": 1, "array_max_size": 10, "string_min_length": 1, "string_max_length": 1} + * + * @added in SmartDeviceLink 7.1.0 + */ +@property (nullable, strong, nonatomic) NSArray<NSString *> *customKeys; + @end NS_ASSUME_NONNULL_END diff --git a/SmartDeviceLink/public/SDLKeyboardProperties.m b/SmartDeviceLink/public/SDLKeyboardProperties.m index c21c91bc7..d57a21c2c 100644 --- a/SmartDeviceLink/public/SDLKeyboardProperties.m +++ b/SmartDeviceLink/public/SDLKeyboardProperties.m @@ -11,7 +11,7 @@ NS_ASSUME_NONNULL_BEGIN @implementation SDLKeyboardProperties - (instancetype)initWithLanguage:(nullable SDLLanguage)language layout:(nullable SDLKeyboardLayout)layout keypressMode:(nullable SDLKeypressMode)keypressMode limitedCharacterList:(nullable NSArray<NSString *> *)limitedCharacterList autoCompleteText:(nullable NSString *)autoCompleteText autoCompleteList:(nullable NSArray<NSString *> *)autoCompleteList { - self = [[self init] initWithLanguage:language keyboardLayout:layout keypressMode:keypressMode limitedCharacterList:limitedCharacterList autoCompleteList:autoCompleteList]; + self = [self initWithLanguage:language keyboardLayout:layout keypressMode:keypressMode limitedCharacterList:limitedCharacterList autoCompleteList:autoCompleteList maskInputCharacters:nil customKeys:nil]; if (!self) { return nil; } self.autoCompleteText = autoCompleteText; @@ -19,17 +19,21 @@ NS_ASSUME_NONNULL_BEGIN } - (instancetype)initWithLanguage:(nullable SDLLanguage)language keyboardLayout:(nullable SDLKeyboardLayout)keyboardLayout keypressMode:(nullable SDLKeypressMode)keypressMode limitedCharacterList:(nullable NSArray<NSString *> *)limitedCharacterList autoCompleteList:(nullable NSArray<NSString *> *)autoCompleteList { + return [self initWithLanguage:language keyboardLayout:keyboardLayout keypressMode:keypressMode limitedCharacterList:limitedCharacterList autoCompleteList:autoCompleteList maskInputCharacters:nil customKeys:nil]; +} + +- (instancetype)initWithLanguage:(nullable SDLLanguage)language keyboardLayout:(nullable SDLKeyboardLayout)keyboardLayout keypressMode:(nullable SDLKeypressMode)keypressMode limitedCharacterList:(nullable NSArray<NSString *> *)limitedCharacterList autoCompleteList:(nullable NSArray<NSString *> *)autoCompleteList maskInputCharacters:(nullable SDLKeyboardInputMask)maskInputCharacters customKeys:(nullable NSArray<NSString *> *)customKeys { self = [self init]; if (!self) { return nil; } - self.language = language; self.keyboardLayout = keyboardLayout; self.keypressMode = keypressMode; self.limitedCharacterList = limitedCharacterList; self.autoCompleteList = autoCompleteList; - + self.maskInputCharacters = maskInputCharacters; + self.customKeys = customKeys; return self; } @@ -81,6 +85,22 @@ NS_ASSUME_NONNULL_BEGIN return [self.store sdl_objectsForName:SDLRPCParameterNameAutoCompleteList ofClass:NSString.class error:nil]; } +- (void)setMaskInputCharacters:(nullable SDLKeyboardInputMask)maskInputCharacters { + [self.store sdl_setObject:maskInputCharacters forName:SDLRPCParameterNameMaskInputCharacters]; +} + +- (nullable SDLKeyboardInputMask)maskInputCharacters { + return [self.store sdl_enumForName:SDLRPCParameterNameMaskInputCharacters error:nil]; +} + +- (void)setCustomKeys:(nullable NSArray<NSString *> *)customKeys { + [self.store sdl_setObject:customKeys forName:SDLRPCParameterNameCustomKeys]; +} + +- (nullable NSArray<NSString *> *)customKeys { + return [self.store sdl_objectsForName:SDLRPCParameterNameCustomKeys ofClass:NSString.class error:nil]; +} + @end NS_ASSUME_NONNULL_END diff --git a/SmartDeviceLink/public/SDLMenuCell.h b/SmartDeviceLink/public/SDLMenuCell.h index 403294612..b3181156d 100644 --- a/SmartDeviceLink/public/SDLMenuCell.h +++ b/SmartDeviceLink/public/SDLMenuCell.h @@ -56,6 +56,21 @@ typedef void(^SDLMenuCellSelectionHandler)(SDLTriggerSource triggerSource); @property (strong, nonatomic, readonly, nullable) SDLMenuLayout submenuLayout; /** + The cell's secondary text to be displayed + */ +@property (copy, nonatomic, readonly, nullable) NSString *secondaryText; + +/** + The cell's tertiary text to be displayed + */ +@property (copy, nonatomic, readonly, nullable) NSString *tertiaryText; + +/** + The cell's secondary icon to be displayed + */ +@property (strong, nonatomic, readonly, nullable) SDLArtwork *secondaryArtwork; + +/** Create a menu cell that has no subcells. @param title The cell's primary text @@ -64,7 +79,7 @@ typedef void(^SDLMenuCellSelectionHandler)(SDLTriggerSource triggerSource); @param handler The code that will be run when the menu cell is selected @return The menu cell */ -- (instancetype)initWithTitle:(NSString *)title icon:(nullable SDLArtwork *)icon voiceCommands:(nullable NSArray<NSString *> *)voiceCommands handler:(SDLMenuCellSelectionHandler)handler; +- (instancetype)initWithTitle:(NSString *)title icon:(nullable SDLArtwork *)icon voiceCommands:(nullable NSArray<NSString *> *)voiceCommands handler:(SDLMenuCellSelectionHandler)handler __deprecated_msg("Use initWithTitle:icon:voiceCommands:secondaryText:tertiaryText:secondaryArtwork:handler: instead"); /** Create a menu cell that has subcells and when selected will go into a deeper part of the menu @@ -75,8 +90,35 @@ typedef void(^SDLMenuCellSelectionHandler)(SDLTriggerSource triggerSource); @param subCells The subcells that will appear when the cell is selected @return The menu cell */ -- (instancetype)initWithTitle:(NSString *)title icon:(nullable SDLArtwork *)icon submenuLayout:(nullable SDLMenuLayout)layout subCells:(NSArray<SDLMenuCell *> *)subCells; +- (instancetype)initWithTitle:(NSString *)title icon:(nullable SDLArtwork *)icon submenuLayout:(nullable SDLMenuLayout)layout subCells:(NSArray<SDLMenuCell *> *)subCells __deprecated_msg("Use initWithTitle:icon:submenuLayout:subCells:secondaryText:tertiaryText:secondaryArtwork: instead"); + +/** + Create a menu cell that has no subcells. + + @param title The cell's primary text + @param icon The cell's image + @param voiceCommands Voice commands that will activate the menu cell + @param secondaryText - secondaryText + @param tertiaryText - tertiaryText + @param secondaryArtwork - secondaryArtwork + @param handler The code that will be run when the menu cell is selected + @return The menu cell + */ +- (instancetype)initWithTitle:(NSString *)title icon:(nullable SDLArtwork *)icon voiceCommands:(nullable NSArray<NSString *> *)voiceCommands secondaryText:(nullable NSString *)secondaryText tertiaryText:(nullable NSString *)tertiaryText secondaryArtwork:(nullable SDLArtwork *)secondaryArtwork handler:(SDLMenuCellSelectionHandler)handler; + +/** + Create a menu cell that has subcells and when selected will go into a deeper part of the menu + @param title The cell's primary text + @param icon The cell's image + @param layout The layout that the subCells will be layed out in if that submenu is entered + @param subCells The subcells that will appear when the cell is selected + @param secondaryText - secondaryText + @param tertiaryText - tertiaryText + @param secondaryArtwork - secondaryArtwork + @return The menu cell + */ +- (instancetype)initWithTitle:(NSString *)title icon:(nullable SDLArtwork *)icon submenuLayout:(nullable SDLMenuLayout)layout subCells:(NSArray<SDLMenuCell *> *)subCells secondaryText:(nullable NSString *)secondaryText tertiaryText:(nullable NSString *)tertiaryText secondaryArtwork:(nullable SDLArtwork *)secondaryArtwork; @end diff --git a/SmartDeviceLink/public/SDLMenuCell.m b/SmartDeviceLink/public/SDLMenuCell.m index 9a06411bc..963f31995 100644 --- a/SmartDeviceLink/public/SDLMenuCell.m +++ b/SmartDeviceLink/public/SDLMenuCell.m @@ -22,6 +22,14 @@ NS_ASSUME_NONNULL_BEGIN @implementation SDLMenuCell - (instancetype)initWithTitle:(NSString *)title icon:(nullable SDLArtwork *)icon voiceCommands:(nullable NSArray<NSString *> *)voiceCommands handler:(SDLMenuCellSelectionHandler)handler { + return [self initWithTitle:title icon:icon voiceCommands:voiceCommands secondaryText:nil tertiaryText:nil secondaryArtwork:nil handler:handler]; +} + +- (instancetype)initWithTitle:(NSString *)title icon:(nullable SDLArtwork *)icon submenuLayout:(nullable SDLMenuLayout)layout subCells:(NSArray<SDLMenuCell *> *)subCells { + return [self initWithTitle:title icon:icon submenuLayout:layout subCells:subCells secondaryText:nil tertiaryText:nil secondaryArtwork:nil]; +} + +- (instancetype)initWithTitle:(NSString *)title icon:(nullable SDLArtwork *)icon voiceCommands:(nullable NSArray<NSString *> *)voiceCommands secondaryText:(nullable NSString *)secondaryText tertiaryText:(nullable NSString *)tertiaryText secondaryArtwork:(nullable SDLArtwork *)secondaryArtwork handler:(SDLMenuCellSelectionHandler)handler { self = [super init]; if (!self) { return nil; } @@ -33,10 +41,15 @@ NS_ASSUME_NONNULL_BEGIN _cellId = UINT32_MAX; _parentCellId = UINT32_MAX; + _secondaryText = secondaryText; + _tertiaryText = tertiaryText; + _secondaryArtwork = secondaryArtwork; + return self; } -- (instancetype)initWithTitle:(NSString *)title icon:(nullable SDLArtwork *)icon submenuLayout:(nullable SDLMenuLayout)layout subCells:(NSArray<SDLMenuCell *> *)subCells { +- (instancetype)initWithTitle:(NSString *)title icon:(nullable SDLArtwork *)icon submenuLayout:(nullable SDLMenuLayout)layout subCells:(NSArray<SDLMenuCell *> *)subCells secondaryText:(nullable NSString *)secondaryText tertiaryText:(nullable NSString *)tertiaryText secondaryArtwork:(nullable SDLArtwork *)secondaryArtwork { + self = [super init]; if (!self) { return nil; } @@ -48,6 +61,10 @@ NS_ASSUME_NONNULL_BEGIN _cellId = UINT32_MAX; _parentCellId = UINT32_MAX; + _secondaryText = secondaryText; + _tertiaryText = tertiaryText; + _secondaryArtwork = secondaryArtwork; + return self; } @@ -67,7 +84,10 @@ NSUInteger NSUIntRotateCell(NSUInteger val, NSUInteger howMuch) { ^ NSUIntRotateCell(self.icon.name.hash, NSUIntBitCell / 3) ^ NSUIntRotateCell(self.voiceCommands.hash, NSUIntBitCell / 4) ^ NSUIntRotateCell(self.subCells.count !=0, NSUIntBitCell / 5) - ^ NSUIntRotateCell(self.submenuLayout.hash, NSUIntBitCell / 6); + ^ NSUIntRotateCell(self.secondaryText.hash, NSUIntBitCell / 6) + ^ NSUIntRotateCell(self.tertiaryText.hash, NSUIntBitCell / 7) + ^ NSUIntRotateCell(self.secondaryArtwork.name.hash, NSUIntBitCell / 8) + ^ NSUIntRotateCell(self.submenuLayout.hash, NSUIntBitCell / 9); } - (BOOL)isEqual:(id)object { diff --git a/SmartDeviceLink/public/SDLMenuParams.h b/SmartDeviceLink/public/SDLMenuParams.h index 89d807f9e..cd4c9aa5e 100644 --- a/SmartDeviceLink/public/SDLMenuParams.h +++ b/SmartDeviceLink/public/SDLMenuParams.h @@ -26,7 +26,17 @@ NS_ASSUME_NONNULL_BEGIN /// @param parentId The unique ID of an existing submenu to which a command will be added /// @param position The position within the items of the parent Command Menu /// @return An instance of the add submenu class -- (instancetype)initWithMenuName:(NSString *)menuName parentId:(UInt32)parentId position:(UInt16)position; +- (instancetype)initWithMenuName:(NSString *)menuName parentId:(UInt32)parentId position:(UInt16)position __deprecated_msg("Use initWithMenuName:parentID:position:secondaryText:tertiaryText: instead"); + +/** + * @param menuName - menuName + * @param parentID - parentID + * @param position - position + * @param secondaryText - secondaryText + * @param tertiaryText - tertiaryText + * @return A SDLMenuParams object + */ +- (instancetype)initWithMenuName:(NSString *)menuName parentID:(nullable NSNumber<SDLUInt> *)parentID position:(nullable NSNumber<SDLUInt> *)position secondaryText:(nullable NSString *)secondaryText tertiaryText:(nullable NSString *)tertiaryText; /** * The unique ID of an existing submenu to which a command will be added @@ -59,6 +69,22 @@ NS_ASSUME_NONNULL_BEGIN */ @property (strong, nonatomic) NSString *menuName; +/** + * Optional secondary text to display + * {"string_min_length": 1, "string_max_length": 500} + * + * @added in SmartDeviceLink 7.1.0 + */ +@property (nullable, strong, nonatomic) NSString *secondaryText; + +/** + * Optional tertiary text to display + * {"string_min_length": 1, "string_max_length": 500} + * + * @added in SmartDeviceLink 7.1.0 + */ +@property (nullable, strong, nonatomic) NSString *tertiaryText; + @end NS_ASSUME_NONNULL_END diff --git a/SmartDeviceLink/public/SDLMenuParams.m b/SmartDeviceLink/public/SDLMenuParams.m index 85cf5880a..9d96781ed 100644 --- a/SmartDeviceLink/public/SDLMenuParams.m +++ b/SmartDeviceLink/public/SDLMenuParams.m @@ -12,14 +12,18 @@ NS_ASSUME_NONNULL_BEGIN @implementation SDLMenuParams - (instancetype)initWithMenuName:(NSString *)menuName parentId:(UInt32)parentId position:(UInt16)position { + return [self initWithMenuName:menuName parentID:@(parentId) position:@(position) secondaryText:nil tertiaryText:nil]; +} + +- (instancetype)initWithMenuName:(NSString *)menuName parentID:(nullable NSNumber<SDLUInt> *)parentID position:(nullable NSNumber<SDLUInt> *)position secondaryText:(nullable NSString *)secondaryText tertiaryText:(nullable NSString *)tertiaryText { self = [self initWithMenuName:menuName]; if (!self) { return nil; } - - self.parentID = @(parentId); - self.position = @(position); - + self.parentID = parentID; + self.position = position; + self.secondaryText = secondaryText; + self.tertiaryText = tertiaryText; return self; } @@ -58,6 +62,22 @@ NS_ASSUME_NONNULL_BEGIN return [self.store sdl_objectForName:SDLRPCParameterNameMenuName ofClass:NSString.class error:nil]; } +- (void)setSecondaryText:(nullable NSString *)secondaryText { + [self.store sdl_setObject:secondaryText forName:SDLRPCParameterNameSecondaryText]; +} + +- (nullable NSString *)secondaryText { + return [self.store sdl_objectForName:SDLRPCParameterNameSecondaryText ofClass:NSString.class error:nil]; +} + +- (void)setTertiaryText:(nullable NSString *)tertiaryText { + [self.store sdl_setObject:tertiaryText forName:SDLRPCParameterNameTertiaryText]; +} + +- (nullable NSString *)tertiaryText { + return [self.store sdl_objectForName:SDLRPCParameterNameTertiaryText ofClass:NSString.class error:nil]; +} + @end NS_ASSUME_NONNULL_END diff --git a/SmartDeviceLink/public/SDLTextFieldName.h b/SmartDeviceLink/public/SDLTextFieldName.h index abd2d57fc..33fb61eaf 100644 --- a/SmartDeviceLink/public/SDLTextFieldName.h +++ b/SmartDeviceLink/public/SDLTextFieldName.h @@ -232,6 +232,20 @@ extern SDLTextFieldName const SDLTextFieldNameAddressLines; extern SDLTextFieldName const SDLTextFieldNamePhoneNumber; /** + * Optional time to destination field for ShowConstantTBT + * + * @added in SmartDeviceLink 7.1.0 + */ +extern SDLTextFieldName const SDLTextFieldNameTimeToDestination; + +/** + * Turn text for turnList parameter of UpdateTurnList + * + * @added in SmartDeviceLink 7.1.0 + */ +extern SDLTextFieldName const SDLTextFieldNameTurnText; + +/** * The first line of the subtle alert text field; applies to `SubtleAlert` `alertText1` * * @since SDL 7.0.0 @@ -251,3 +265,31 @@ extern SDLTextFieldName const SDLTextFieldNameSubtleAlertText2; * @since SDL 7.0.0 */ extern SDLTextFieldName const SDLTextFieldNameSubtleAlertSoftButtonText; + +/** + * Secondary text for AddCommand + * + * @added in SmartDeviceLink 7.0.0 + */ +extern SDLTextFieldName const SDLTextFieldNameMenuCommandSecondaryText; + +/** + * Tertiary text for AddCommand + * + * @added in SmartDeviceLink 7.0.0 + */ +extern SDLTextFieldName const SDLTextFieldNameMenuCommandTertiaryText; + +/** + * Secondary text for AddSubMenu + * + * @added in SmartDeviceLink 7.0.0 + */ +extern SDLTextFieldName const SDLTextFieldNameMenuSubMenuSecondaryText; + +/** + * Tertiary text for AddSubMenu + * + * @added in SmartDeviceLink 7.0.0 + */ +extern SDLTextFieldName const SDLTextFieldNameMenuSubMenuTertiaryText; diff --git a/SmartDeviceLink/public/SDLTextFieldName.m b/SmartDeviceLink/public/SDLTextFieldName.m index 54f8c781e..d02826ca2 100644 --- a/SmartDeviceLink/public/SDLTextFieldName.m +++ b/SmartDeviceLink/public/SDLTextFieldName.m @@ -61,6 +61,12 @@ SDLTextFieldName const SDLTextFieldNameLocationName = @"locationName"; SDLTextFieldName const SDLTextFieldNameLocationDescription = @"locationDescription"; SDLTextFieldName const SDLTextFieldNameAddressLines = @"addressLines"; SDLTextFieldName const SDLTextFieldNamePhoneNumber = @"phoneNumber"; +SDLTextFieldName const SDLTextFieldNameTimeToDestination = @"timeToDestination"; +SDLTextFieldName const SDLTextFieldNameTurnText = @"turnText"; SDLTextFieldName const SDLTextFieldNameSubtleAlertText1 = @"subtleAlertText1"; SDLTextFieldName const SDLTextFieldNameSubtleAlertText2 = @"subtleAlertText2"; SDLTextFieldName const SDLTextFieldNameSubtleAlertSoftButtonText = @"subtleAlertSoftButtonText"; +SDLTextFieldName const SDLTextFieldNameMenuCommandSecondaryText = @"menuCommandSecondaryText"; +SDLTextFieldName const SDLTextFieldNameMenuCommandTertiaryText = @"menuCommandTertiaryText"; +SDLTextFieldName const SDLTextFieldNameMenuSubMenuSecondaryText = @"menuSubMenuSecondaryText"; +SDLTextFieldName const SDLTextFieldNameMenuSubMenuTertiaryText = @"menuSubMenuTertiaryText"; diff --git a/SmartDeviceLink/public/SDLWindowCapability.h b/SmartDeviceLink/public/SDLWindowCapability.h index 4795e667b..afb7a905e 100644 --- a/SmartDeviceLink/public/SDLWindowCapability.h +++ b/SmartDeviceLink/public/SDLWindowCapability.h @@ -38,10 +38,10 @@ @class SDLButtonCapabilities; @class SDLDynamicUpdateCapabilities; @class SDLImageField; +@class SDLKeyboardCapabilities; @class SDLSoftButtonCapabilities; @class SDLTextField; - NS_ASSUME_NONNULL_BEGIN /** @@ -64,7 +64,23 @@ NS_ASSUME_NONNULL_BEGIN * @param dynamicUpdateCapabilities - dynamicUpdateCapabilities * @return A SDLWindowCapability object */ -- (instancetype)initWithWindowID:(nullable NSNumber<SDLInt> *)windowID textFields:(nullable NSArray<SDLTextField *> *)textFields imageFields:(nullable NSArray<SDLImageField *> *)imageFields imageTypeSupported:(nullable NSArray<SDLImageType> *)imageTypeSupported templatesAvailable:(nullable NSArray<NSString *> *)templatesAvailable numCustomPresetsAvailable:(nullable NSNumber<SDLUInt> *)numCustomPresetsAvailable buttonCapabilities:(nullable NSArray<SDLButtonCapabilities *> *)buttonCapabilities softButtonCapabilities:(nullable NSArray<SDLSoftButtonCapabilities *> *)softButtonCapabilities menuLayoutsAvailable:(nullable NSArray<SDLMenuLayout> *)menuLayoutsAvailable dynamicUpdateCapabilities:(nullable SDLDynamicUpdateCapabilities *)dynamicUpdateCapabilities; +- (instancetype)initWithWindowID:(nullable NSNumber<SDLInt> *)windowID textFields:(nullable NSArray<SDLTextField *> *)textFields imageFields:(nullable NSArray<SDLImageField *> *)imageFields imageTypeSupported:(nullable NSArray<SDLImageType> *)imageTypeSupported templatesAvailable:(nullable NSArray<NSString *> *)templatesAvailable numCustomPresetsAvailable:(nullable NSNumber<SDLUInt> *)numCustomPresetsAvailable buttonCapabilities:(nullable NSArray<SDLButtonCapabilities *> *)buttonCapabilities softButtonCapabilities:(nullable NSArray<SDLSoftButtonCapabilities *> *)softButtonCapabilities menuLayoutsAvailable:(nullable NSArray<SDLMenuLayout> *)menuLayoutsAvailable dynamicUpdateCapabilities:(nullable SDLDynamicUpdateCapabilities *)dynamicUpdateCapabilities __deprecated_msg("please use initWithWindowID:textFields:imageFields:imageTypeSupported:templatesAvailable:numCustomPresetsAvailable:buttonCapabilities:softButtonCapabilities:menuLayoutsAvailable:dynamicUpdateCapabilities:keyboardCapabilities: instead"); + +/** + * @param windowID - windowID + * @param textFields - textFields + * @param imageFields - imageFields + * @param imageTypeSupported - imageTypeSupported + * @param templatesAvailable - templatesAvailable + * @param numCustomPresetsAvailable - numCustomPresetsAvailable + * @param buttonCapabilities - buttonCapabilities + * @param softButtonCapabilities - softButtonCapabilities + * @param menuLayoutsAvailable - menuLayoutsAvailable + * @param dynamicUpdateCapabilities - dynamicUpdateCapabilities + * @param keyboardCapabilities - keyboardCapabilities + * @return A SDLWindowCapability object + */ +- (instancetype)initWithWindowID:(nullable NSNumber<SDLInt> *)windowID textFields:(nullable NSArray<SDLTextField *> *)textFields imageFields:(nullable NSArray<SDLImageField *> *)imageFields imageTypeSupported:(nullable NSArray<SDLImageType> *)imageTypeSupported templatesAvailable:(nullable NSArray<NSString *> *)templatesAvailable numCustomPresetsAvailable:(nullable NSNumber<SDLUInt> *)numCustomPresetsAvailable buttonCapabilities:(nullable NSArray<SDLButtonCapabilities *> *)buttonCapabilities softButtonCapabilities:(nullable NSArray<SDLSoftButtonCapabilities *> *)softButtonCapabilities menuLayoutsAvailable:(nullable NSArray<SDLMenuLayout> *)menuLayoutsAvailable dynamicUpdateCapabilities:(nullable SDLDynamicUpdateCapabilities *)dynamicUpdateCapabilities keyboardCapabilities:(nullable SDLKeyboardCapabilities *)keyboardCapabilities; /** The specified ID of the window. Can be set to a predefined window, or omitted for the main window on the main display. @@ -136,6 +152,13 @@ NS_ASSUME_NONNULL_BEGIN */ @property (nullable, strong, nonatomic) SDLDynamicUpdateCapabilities *dynamicUpdateCapabilities; +/** + * See KeyboardCapabilities + * + * @added in SmartDeviceLink 7.1.0 + */ +@property (nullable, strong, nonatomic) SDLKeyboardCapabilities *keyboardCapabilities; + @end NS_ASSUME_NONNULL_END diff --git a/SmartDeviceLink/public/SDLWindowCapability.m b/SmartDeviceLink/public/SDLWindowCapability.m index 9c3ebe7e2..3db3195ff 100644 --- a/SmartDeviceLink/public/SDLWindowCapability.m +++ b/SmartDeviceLink/public/SDLWindowCapability.m @@ -36,6 +36,7 @@ #import "SDLButtonCapabilities.h" #import "SDLDynamicUpdateCapabilities.h" #import "SDLImageField.h" +#import "SDLKeyboardCapabilities.h" #import "SDLRPCParameterNames.h" #import "SDLSoftButtonCapabilities.h" #import "SDLTextField.h" @@ -43,6 +44,10 @@ @implementation SDLWindowCapability - (instancetype)initWithWindowID:(nullable NSNumber<SDLInt> *)windowID textFields:(nullable NSArray<SDLTextField *> *)textFields imageFields:(nullable NSArray<SDLImageField *> *)imageFields imageTypeSupported:(nullable NSArray<SDLImageType> *)imageTypeSupported templatesAvailable:(nullable NSArray<NSString *> *)templatesAvailable numCustomPresetsAvailable:(nullable NSNumber<SDLUInt> *)numCustomPresetsAvailable buttonCapabilities:(nullable NSArray<SDLButtonCapabilities *> *)buttonCapabilities softButtonCapabilities:(nullable NSArray<SDLSoftButtonCapabilities *> *)softButtonCapabilities menuLayoutsAvailable:(nullable NSArray<SDLMenuLayout> *)menuLayoutsAvailable dynamicUpdateCapabilities:(nullable SDLDynamicUpdateCapabilities *)dynamicUpdateCapabilities { + return [self initWithWindowID:windowID textFields:textFields imageFields:imageFields imageTypeSupported:imageTypeSupported templatesAvailable:templatesAvailable numCustomPresetsAvailable:numCustomPresetsAvailable buttonCapabilities:buttonCapabilities softButtonCapabilities:softButtonCapabilities menuLayoutsAvailable:menuLayoutsAvailable dynamicUpdateCapabilities:dynamicUpdateCapabilities keyboardCapabilities:nil]; +} + +- (instancetype)initWithWindowID:(nullable NSNumber<SDLInt> *)windowID textFields:(nullable NSArray<SDLTextField *> *)textFields imageFields:(nullable NSArray<SDLImageField *> *)imageFields imageTypeSupported:(nullable NSArray<SDLImageType> *)imageTypeSupported templatesAvailable:(nullable NSArray<NSString *> *)templatesAvailable numCustomPresetsAvailable:(nullable NSNumber<SDLUInt> *)numCustomPresetsAvailable buttonCapabilities:(nullable NSArray<SDLButtonCapabilities *> *)buttonCapabilities softButtonCapabilities:(nullable NSArray<SDLSoftButtonCapabilities *> *)softButtonCapabilities menuLayoutsAvailable:(nullable NSArray<SDLMenuLayout> *)menuLayoutsAvailable dynamicUpdateCapabilities:(nullable SDLDynamicUpdateCapabilities *)dynamicUpdateCapabilities keyboardCapabilities:(nullable SDLKeyboardCapabilities *)keyboardCapabilities { self = [super init]; if (!self) { return nil; @@ -57,6 +62,7 @@ self.softButtonCapabilities = softButtonCapabilities; self.menuLayoutsAvailable = menuLayoutsAvailable; self.dynamicUpdateCapabilities = dynamicUpdateCapabilities; + self.keyboardCapabilities = keyboardCapabilities; return self; } @@ -141,4 +147,12 @@ return [self.store sdl_objectForName:SDLRPCParameterNameDynamicUpdateCapabilities ofClass:SDLDynamicUpdateCapabilities.class error:nil]; } +- (void)setKeyboardCapabilities:(nullable SDLKeyboardCapabilities *)keyboardCapabilities { + [self.store sdl_setObject:keyboardCapabilities forName:SDLRPCParameterNameKeyboardCapabilities]; +} + +- (nullable SDLKeyboardCapabilities *)keyboardCapabilities { + return [self.store sdl_objectForName:SDLRPCParameterNameKeyboardCapabilities ofClass:SDLKeyboardCapabilities.class error:nil]; +} + @end diff --git a/SmartDeviceLink/public/SmartDeviceLink.h b/SmartDeviceLink/public/SmartDeviceLink.h index 712580dda..4f309d669 100644 --- a/SmartDeviceLink/public/SmartDeviceLink.h +++ b/SmartDeviceLink/public/SmartDeviceLink.h @@ -228,6 +228,8 @@ FOUNDATION_EXPORT const unsigned char SmartDeviceLinkVersionString[]; #import "SDLImage.h" #import "SDLImageField.h" #import "SDLImageResolution.h" +#import "SDLKeyboardCapabilities.h" +#import "SDLKeyboardLayoutCapability.h" #import "SDLKeyboardProperties.h" #import "SDLLightCapabilities.h" #import "SDLLightControlCapabilities.h" @@ -344,6 +346,7 @@ FOUNDATION_EXPORT const unsigned char SmartDeviceLinkVersionString[]; #import "SDLImageType.h" #import "SDLInteractionMode.h" #import "SDLKeyboardEvent.h" +#import "SDLKeyboardInputMask.h" #import "SDLKeyboardLayout.h" #import "SDLKeypressMode.h" #import "SDLLanguage.h" diff --git a/SmartDeviceLinkTests/DevAPISpecs/SDLChoiceSetManagerSpec.m b/SmartDeviceLinkTests/DevAPISpecs/SDLChoiceSetManagerSpec.m index 321a2dde6..2d3fa0707 100644 --- a/SmartDeviceLinkTests/DevAPISpecs/SDLChoiceSetManagerSpec.m +++ b/SmartDeviceLinkTests/DevAPISpecs/SDLChoiceSetManagerSpec.m @@ -105,7 +105,7 @@ describe(@"choice set manager tests", ^{ it(@"should be in the correct startup state", ^{ expect(testManager.currentState).to(equal(SDLChoiceManagerStateShutdown)); - SDLKeyboardProperties *defaultProperties = [[SDLKeyboardProperties alloc] initWithLanguage:SDLLanguageEnUs keyboardLayout:SDLKeyboardLayoutQWERTY keypressMode:SDLKeypressModeResendCurrentEntry limitedCharacterList:nil autoCompleteList:nil]; + SDLKeyboardProperties *defaultProperties = [[SDLKeyboardProperties alloc] initWithLanguage:SDLLanguageEnUs keyboardLayout:SDLKeyboardLayoutQWERTY keypressMode:SDLKeypressModeResendCurrentEntry limitedCharacterList:nil autoCompleteList:nil maskInputCharacters:nil customKeys:nil]; expect(testManager.keyboardConfiguration).to(equal(defaultProperties)); }); diff --git a/SmartDeviceLinkTests/DevAPISpecs/SDLLifecycleSystemRequestHandlerSpec.m b/SmartDeviceLinkTests/DevAPISpecs/SDLLifecycleSystemRequestHandlerSpec.m index d606b9fc0..683d3caf1 100644 --- a/SmartDeviceLinkTests/DevAPISpecs/SDLLifecycleSystemRequestHandlerSpec.m +++ b/SmartDeviceLinkTests/DevAPISpecs/SDLLifecycleSystemRequestHandlerSpec.m @@ -123,7 +123,7 @@ describe(@"SDLLifecycleSystemRequestHandler tests", ^{ }); context(@"of type LOCK_SCREEN_URL", ^{ - __block id lockScreenIconObserver = nil; + __block XCTNSNotificationExpectation *lockScreenIconExpectation; beforeEach(^{ receivedSystemRequest.requestType = SDLRequestTypeLockScreenIconURL; @@ -131,20 +131,19 @@ describe(@"SDLLifecycleSystemRequestHandler tests", ^{ UIImage *testImage = [UIImage imageNamed:@"testImagePNG" inBundle:[NSBundle bundleForClass:self.class] compatibleWithTraitCollection:nil]; OCMStub([mockCacheManager retrieveImageForRequest:[OCMArg any] withCompletionHandler:([OCMArg invokeBlockWithArgs:testImage, [NSNull null], nil])]); - lockScreenIconObserver = OCMObserverMock(); - [[NSNotificationCenter defaultCenter] addMockObserver:lockScreenIconObserver name:SDLDidReceiveLockScreenIcon object:nil]; - [[lockScreenIconObserver expect] notificationWithName:SDLDidReceiveLockScreenIcon object:[OCMArg any] userInfo:[OCMArg any]]; + lockScreenIconExpectation = [[XCTNSNotificationExpectation alloc] initWithName:SDLDidReceiveLockScreenIcon object:nil]; SDLRPCNotificationNotification *notification = [[SDLRPCNotificationNotification alloc] initWithName:SDLDidReceiveSystemRequestNotification object:nil rpcNotification:receivedSystemRequest]; [[NSNotificationCenter defaultCenter] postNotification:notification]; }); it(@"should pass the url to the cache manager and then send a notification", ^{ - OCMVerifyAll(lockScreenIconObserver); + XCTWaiterResult waiter = [XCTWaiter waitForExpectations:@[lockScreenIconExpectation] timeout:4]; + XCTAssertEqual(waiter, XCTWaiterResultCompleted); }); afterEach(^{ - lockScreenIconObserver = nil; + lockScreenIconExpectation = nil; }); }); diff --git a/SmartDeviceLinkTests/DevAPISpecs/SDLMenuCellSpec.m b/SmartDeviceLinkTests/DevAPISpecs/SDLMenuCellSpec.m index 485b02b6d..e2b34727d 100644 --- a/SmartDeviceLinkTests/DevAPISpecs/SDLMenuCellSpec.m +++ b/SmartDeviceLinkTests/DevAPISpecs/SDLMenuCellSpec.m @@ -10,52 +10,118 @@ describe(@"a menu cell", ^{ __block SDLMenuCell *testCell = nil; __block SDLMenuCell *testCell2 = nil; __block SDLMenuLayout testLayout = SDLMenuLayoutList; + __block NSString *someTitle = nil; + __block NSString *someSecondaryTitle = nil; + __block NSString *someTertiaryTitle = nil; + __block SDLArtwork *someArtwork = nil; + __block SDLArtwork *someSecondaryArtwork = nil; + + beforeEach(^{ + someTitle = @"Some Title"; + someSecondaryTitle = @"Some Title 2"; + someTertiaryTitle = @"Some Title 3"; + someArtwork = [[SDLArtwork alloc] initWithData:[[NSData alloc] initWithBase64EncodedString:@"data" options:kNilOptions] name:@"Some artwork" fileExtension:@"png" persistent:NO]; + someSecondaryArtwork = [[SDLArtwork alloc] initWithData:[[NSData alloc] initWithBase64EncodedString:@"data" options:kNilOptions] name:@"Some artwork 2" fileExtension:@"png" persistent:NO]; + }); describe(@"initializing", ^{ - __block NSString *someTitle = nil; - __block SDLArtwork *someArtwork = nil; __block NSArray<NSString *> *someVoiceCommands = nil; __block NSArray<SDLMenuCell *> *someSubcells = nil; beforeEach(^{ - someTitle = @"Some Title"; - someArtwork = [[SDLArtwork alloc] initWithData:[[NSData alloc] initWithBase64EncodedString:@"data" options:kNilOptions] name:@"Some artwork" fileExtension:@"png" persistent:NO]; someVoiceCommands = @[@"some command"]; - SDLMenuCell *subcell = [[SDLMenuCell alloc] initWithTitle:@"Hello" icon:nil voiceCommands:nil handler:^(SDLTriggerSource _Nonnull triggerSource) {}]; + SDLMenuCell *subcell = [[SDLMenuCell alloc] initWithTitle:@"Hello" icon:nil voiceCommands:nil secondaryText:nil tertiaryText:nil secondaryArtwork:nil handler:^(SDLTriggerSource _Nonnull triggerSource) {}]; someSubcells = @[subcell]; }); - it(@"should initialize properly as a menu item", ^{ + it(@"should set initWithTitle:icon:submenuLayout:subCells: propertly", ^{ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + testCell = [[SDLMenuCell alloc] initWithTitle:someTitle icon:someArtwork submenuLayout:testLayout subCells:someSubcells]; +#pragma clang diagnostic pop + + expect(testCell.title).to(equal(someTitle)); + expect(testCell.icon).to(equal(someArtwork)); + expect(testCell.voiceCommands).to(beNil()); + expect(testCell.subCells).to(equal(someSubcells)); + expect(testCell.secondaryText).to(beNil()); + expect(testCell.tertiaryText).to(beNil()); + expect(testCell.secondaryArtwork).to(beNil()); + }); + + it(@"should set initWithTitle:icon:voiceCommands:handler: properly", ^{ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" testCell = [[SDLMenuCell alloc] initWithTitle:someTitle icon:someArtwork voiceCommands:someVoiceCommands handler:^(SDLTriggerSource _Nonnull triggerSource) {}]; +#pragma clang diagnostic pop expect(testCell.title).to(equal(someTitle)); expect(testCell.icon).to(equal(someArtwork)); expect(testCell.voiceCommands).to(equal(someVoiceCommands)); expect(testCell.subCells).to(beNil()); + expect(testCell.secondaryText).to(beNil()); + expect(testCell.tertiaryText).to(beNil()); + expect(testCell.secondaryArtwork).to(beNil()); }); - it(@"should initialize properly as a submenu item with icon and layout", ^{ - testCell = [[SDLMenuCell alloc] initWithTitle:someTitle icon:someArtwork submenuLayout:testLayout subCells:someSubcells]; + it(@"should set initWithTitle:icon:voiceCommands:secondaryText:tertiaryText:secondaryArtwork:handler: properly", ^{ + testCell = [[SDLMenuCell alloc] initWithTitle:someTitle icon:someArtwork voiceCommands:someVoiceCommands secondaryText:someSecondaryTitle tertiaryText:someTertiaryTitle secondaryArtwork:someSecondaryArtwork handler:^(SDLTriggerSource _Nonnull triggerSource) {}]; + + expect(testCell.title).to(equal(someTitle)); + expect(testCell.icon).to(equal(someArtwork)); + expect(testCell.voiceCommands).to(equal(someVoiceCommands)); + expect(testCell.subCells).to(beNil()); + expect(testCell.secondaryText).to(equal(someSecondaryTitle)); + expect(testCell.tertiaryText).to(equal(someTertiaryTitle)); + expect(testCell.secondaryArtwork).to(equal(someSecondaryArtwork)); + }); + + it(@"should initWithTitle:icon:submenuLayout:subCells:secondaryText:tertiaryText:secondaryArtwork: initialize", ^{ + testCell = [[SDLMenuCell alloc] initWithTitle:someTitle icon:someArtwork submenuLayout:testLayout subCells:someSubcells secondaryText:someSecondaryTitle tertiaryText:someTertiaryTitle secondaryArtwork:someSecondaryArtwork]; expect(testCell.title).to(equal(someTitle)); expect(testCell.icon).to(equal(someArtwork)); expect(testCell.voiceCommands).to(beNil()); expect(testCell.subCells).to(equal(someSubcells)); expect(testCell.submenuLayout).to(equal(testLayout)); + expect(testCell.secondaryText).to(equal(someSecondaryTitle)); + expect(testCell.tertiaryText).to(equal(someTertiaryTitle)); + expect(testCell.secondaryArtwork).to(equal(someSecondaryArtwork)); }); }); + describe(@"check cell eqality", ^{ it(@"should compare cells and return true if cells equal", ^{ - testCell = [[SDLMenuCell alloc] initWithTitle:@"Title" icon:nil submenuLayout:testLayout subCells:@[]]; - testCell2 = [[SDLMenuCell alloc] initWithTitle:@"Title" icon:nil submenuLayout:testLayout subCells:@[]]; + testCell = [[SDLMenuCell alloc] initWithTitle:someTitle icon:nil submenuLayout:testLayout subCells:@[] secondaryText:someSecondaryTitle tertiaryText:someTertiaryTitle secondaryArtwork:someSecondaryArtwork]; + testCell2 = [[SDLMenuCell alloc] initWithTitle:someTitle icon:nil submenuLayout:testLayout subCells:@[] secondaryText:someSecondaryTitle tertiaryText:someTertiaryTitle secondaryArtwork:someSecondaryArtwork]; + + expect([testCell isEqual:testCell2]).to(equal(true)); + }); + + it(@"should compare cells and return false if not equal ", ^{ + testCell = [[SDLMenuCell alloc] initWithTitle:@"True" icon:nil submenuLayout:testLayout subCells:@[] secondaryText:someSecondaryTitle tertiaryText:someTertiaryTitle secondaryArtwork:someSecondaryArtwork]; + testCell2 = [[SDLMenuCell alloc] initWithTitle:@"False" icon:nil submenuLayout:testLayout subCells:@[] secondaryText:nil tertiaryText:nil secondaryArtwork:nil]; + + expect([testCell isEqual:testCell2]).to(equal(false)); + }); + + it(@"should compare cells and return true if cells equal", ^{ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + testCell = [[SDLMenuCell alloc] initWithTitle:someTitle icon:nil submenuLayout:testLayout subCells:@[]]; + testCell2 = [[SDLMenuCell alloc] initWithTitle:someTitle icon:nil submenuLayout:testLayout subCells:@[]]; +#pragma clang diagnostic pop expect([testCell isEqual:testCell2]).to(equal(true)); }); it(@"should compare cells and return false if not equal ", ^{ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" testCell = [[SDLMenuCell alloc] initWithTitle:@"True" icon:nil submenuLayout:testLayout subCells:@[]]; testCell2 = [[SDLMenuCell alloc] initWithTitle:@"False" icon:nil submenuLayout:testLayout subCells:@[]]; +#pragma clang diagnostic pop expect([testCell isEqual:testCell2]).to(equal(false)); }); diff --git a/SmartDeviceLinkTests/DevAPISpecs/SDLMenuManagerSpec.m b/SmartDeviceLinkTests/DevAPISpecs/SDLMenuManagerSpec.m index 9bde38ac7..0a4045f5a 100644 --- a/SmartDeviceLinkTests/DevAPISpecs/SDLMenuManagerSpec.m +++ b/SmartDeviceLinkTests/DevAPISpecs/SDLMenuManagerSpec.m @@ -64,11 +64,11 @@ describe(@"menu manager", ^{ testArtwork3 = [[SDLArtwork alloc] initWithData:[@"Test data 3" dataUsingEncoding:NSUTF8StringEncoding] name:@"some artwork name" fileExtension:@"png" persistent:NO]; testArtwork3.overwrite = YES; - textOnlyCell = [[SDLMenuCell alloc] initWithTitle:@"Test 1" icon:nil voiceCommands:nil handler:^(SDLTriggerSource _Nonnull triggerSource) {}]; - textAndImageCell = [[SDLMenuCell alloc] initWithTitle:@"Test 2" icon:testArtwork voiceCommands:nil handler:^(SDLTriggerSource _Nonnull triggerSource) {}]; - submenuCell = [[SDLMenuCell alloc] initWithTitle:@"Test 3" icon:nil submenuLayout:nil subCells:@[textOnlyCell, textAndImageCell]]; - submenuImageCell = [[SDLMenuCell alloc] initWithTitle:@"Test 4" icon:testArtwork2 submenuLayout:SDLMenuLayoutTiles subCells:@[textOnlyCell]]; - textOnlyCell2 = [[SDLMenuCell alloc] initWithTitle:@"Test 5" icon:nil voiceCommands:nil handler:^(SDLTriggerSource _Nonnull triggerSource) {}]; + textOnlyCell = [[SDLMenuCell alloc] initWithTitle:@"Test 1" icon:nil voiceCommands:nil secondaryText:nil tertiaryText:nil secondaryArtwork:nil handler:^(SDLTriggerSource _Nonnull triggerSource) {}]; + textAndImageCell = [[SDLMenuCell alloc] initWithTitle:@"Test 2" icon:testArtwork voiceCommands:nil secondaryText:nil tertiaryText:nil secondaryArtwork:nil handler:^(SDLTriggerSource _Nonnull triggerSource) {}]; + submenuCell = [[SDLMenuCell alloc] initWithTitle:@"Test 3" icon:nil submenuLayout:nil subCells:@[textOnlyCell, textAndImageCell] secondaryText:nil tertiaryText:nil secondaryArtwork:nil]; + submenuImageCell = [[SDLMenuCell alloc] initWithTitle:@"Test 4" icon:testArtwork2 submenuLayout:SDLMenuLayoutTiles subCells:@[textOnlyCell] secondaryText:nil tertiaryText:nil secondaryArtwork:nil]; + textOnlyCell2 = [[SDLMenuCell alloc] initWithTitle:@"Test 5" icon:nil voiceCommands:nil secondaryText:nil tertiaryText:nil secondaryArtwork:nil handler:^(SDLTriggerSource _Nonnull triggerSource) {}]; testMenuConfiguration = [[SDLMenuConfiguration alloc] initWithMainMenuLayout:SDLMenuLayoutTiles defaultSubmenuLayout:SDLMenuLayoutList]; @@ -80,9 +80,13 @@ describe(@"menu manager", ^{ SDLImageField *commandIconField = [[SDLImageField alloc] init]; commandIconField.name = SDLImageFieldNameCommandIcon; + SDLImageField *subMenuSecondaryArtworkField = [[SDLImageField alloc] init]; + subMenuSecondaryArtworkField.name = SDLImageFieldNameMenuSubMenuSecondaryImage; + SDLImageField *commandSecondaryArtworkField = [[SDLImageField alloc] init]; + commandSecondaryArtworkField.name = SDLImageFieldNameMenuCommandSecondaryImage; SDLWindowCapability *windowCapability = [[SDLWindowCapability alloc] init]; windowCapability.windowID = @(SDLPredefinedWindowsDefaultWindow); - windowCapability.imageFields = @[commandIconField]; + windowCapability.imageFields = @[commandIconField, subMenuSecondaryArtworkField, commandSecondaryArtworkField]; windowCapability.imageTypeSupported = @[SDLImageTypeDynamic, SDLImageTypeStatic]; windowCapability.menuLayoutsAvailable = @[SDLMenuLayoutList, SDLMenuLayoutTiles]; testManager.windowCapability = windowCapability; @@ -176,8 +180,8 @@ describe(@"menu manager", ^{ }); context(@"duplicate VR commands", ^{ - __block SDLMenuCell *textAndVRCell1 = [[SDLMenuCell alloc] initWithTitle:@"Test 1" icon:nil voiceCommands:@[@"Cat", @"Turtle"] handler:^(SDLTriggerSource _Nonnull triggerSource) {}]; - __block SDLMenuCell *textAndVRCell2 = [[SDLMenuCell alloc] initWithTitle:@"Test 3" icon:nil voiceCommands:@[@"Cat", @"Dog"] handler:^(SDLTriggerSource _Nonnull triggerSource) {}]; + __block SDLMenuCell *textAndVRCell1 = [[SDLMenuCell alloc] initWithTitle:@"Test 1" icon:nil voiceCommands:@[@"Cat", @"Turtle"] secondaryText:nil tertiaryText:nil secondaryArtwork:nil handler:^(SDLTriggerSource _Nonnull triggerSource) {}]; + __block SDLMenuCell *textAndVRCell2 = [[SDLMenuCell alloc] initWithTitle:@"Test 3" icon:nil voiceCommands:@[@"Cat", @"Dog"] secondaryText:nil tertiaryText:nil secondaryArtwork:nil handler:^(SDLTriggerSource _Nonnull triggerSource) {}]; it(@"should fail when menu items have duplicate vr commands", ^{ testManager.menuCells = @[textAndVRCell1, textAndVRCell2]; @@ -186,7 +190,14 @@ describe(@"menu manager", ^{ }); it(@"should check if all artworks are uploaded and return NO", ^{ - textAndImageCell = [[SDLMenuCell alloc] initWithTitle:@"Test 2" icon:testArtwork3 voiceCommands:nil handler:^(SDLTriggerSource _Nonnull triggerSource) {}]; + textAndImageCell = [[SDLMenuCell alloc] initWithTitle:@"Test 2" icon:nil voiceCommands:nil secondaryText:nil tertiaryText:nil secondaryArtwork:testArtwork handler:^(SDLTriggerSource _Nonnull triggerSource) {}]; + testManager.menuCells = @[textAndImageCell, textOnlyCell]; + OCMVerify([testManager sdl_shouldRPCsIncludeImages:testManager.menuCells]); + expect([testManager sdl_shouldRPCsIncludeImages:testManager.menuCells]).to(beFalse()); + }); + + it(@"should check if all artworks are uploaded and return NO", ^{ + textAndImageCell = [[SDLMenuCell alloc] initWithTitle:@"Test 2" icon:testArtwork3 voiceCommands:nil secondaryText:nil tertiaryText:nil secondaryArtwork:nil handler:^(SDLTriggerSource _Nonnull triggerSource) {}]; testManager.menuCells = @[textAndImageCell, textOnlyCell]; OCMVerify([testManager sdl_shouldRPCsIncludeImages:testManager.menuCells]); expect([testManager sdl_shouldRPCsIncludeImages:testManager.menuCells]).to(beFalse()); @@ -226,7 +237,7 @@ describe(@"menu manager", ^{ }); it(@"should check if all artworks are uploaded", ^{ - textAndImageCell = [[SDLMenuCell alloc] initWithTitle:@"Test 2" icon:testArtwork3 voiceCommands:nil handler:^(SDLTriggerSource _Nonnull triggerSource) {}]; + textAndImageCell = [[SDLMenuCell alloc] initWithTitle:@"Test 2" icon:testArtwork3 voiceCommands:nil secondaryText:nil tertiaryText:nil secondaryArtwork:nil handler:^(SDLTriggerSource _Nonnull triggerSource) {}]; testManager.menuCells = @[textAndImageCell, textOnlyCell]; OCMVerify([testManager sdl_shouldRPCsIncludeImages:testManager.menuCells]); expect([testManager sdl_shouldRPCsIncludeImages:testManager.menuCells]).to(beTrue()); @@ -252,7 +263,7 @@ describe(@"menu manager", ^{ it(@"should properly overwrite an image cell", ^{ OCMStub([mockFileManager fileNeedsUpload:[OCMArg isNotNil]]).andReturn(YES); - textAndImageCell = [[SDLMenuCell alloc] initWithTitle:@"Test 2" icon:testArtwork3 voiceCommands:nil handler:^(SDLTriggerSource _Nonnull triggerSource) {}]; + textAndImageCell = [[SDLMenuCell alloc] initWithTitle:@"Test 2" icon:testArtwork3 voiceCommands:nil secondaryText:nil tertiaryText:nil secondaryArtwork:nil handler:^(SDLTriggerSource _Nonnull triggerSource) {}]; testManager.menuCells = @[textAndImageCell, submenuImageCell]; OCMVerify([mockFileManager uploadArtworks:[OCMArg any] completionHandler:[OCMArg any]]); }); @@ -538,7 +549,7 @@ describe(@"menu manager", ^{ context(@"on a main menu cell", ^{ beforeEach(^{ - cellWithHandler = [[SDLMenuCell alloc] initWithTitle:@"Hello" icon:nil voiceCommands:nil handler:^(SDLTriggerSource _Nonnull triggerSource) { + cellWithHandler = [[SDLMenuCell alloc] initWithTitle:@"Hello" icon:nil voiceCommands:nil secondaryText:nil tertiaryText:nil secondaryArtwork:nil handler:^(SDLTriggerSource _Nonnull triggerSource) { cellCalled = YES; testTriggerSource = triggerSource; }]; @@ -561,12 +572,12 @@ describe(@"menu manager", ^{ context(@"on a submenu menu cell", ^{ beforeEach(^{ - cellWithHandler = [[SDLMenuCell alloc] initWithTitle:@"Hello" icon:nil voiceCommands:nil handler:^(SDLTriggerSource _Nonnull triggerSource) { + cellWithHandler = [[SDLMenuCell alloc] initWithTitle:@"Hello" icon:nil voiceCommands:nil secondaryText:nil tertiaryText:nil secondaryArtwork:nil handler:^(SDLTriggerSource _Nonnull triggerSource) { cellCalled = YES; testTriggerSource = triggerSource; }]; - SDLMenuCell *submenuCell = [[SDLMenuCell alloc] initWithTitle:@"Submenu" icon:nil submenuLayout:SDLMenuLayoutTiles subCells:@[cellWithHandler]]; + SDLMenuCell *submenuCell = [[SDLMenuCell alloc] initWithTitle:@"Submenu" icon:nil submenuLayout:SDLMenuLayoutTiles subCells:@[cellWithHandler] secondaryText:nil tertiaryText:nil secondaryArtwork:nil]; testManager.menuCells = @[submenuCell]; }); diff --git a/SmartDeviceLinkTests/DevAPISpecs/SDLPresentChoiceSetOperationSpec.m b/SmartDeviceLinkTests/DevAPISpecs/SDLPresentChoiceSetOperationSpec.m index 883720b82..f918c6909 100644 --- a/SmartDeviceLinkTests/DevAPISpecs/SDLPresentChoiceSetOperationSpec.m +++ b/SmartDeviceLinkTests/DevAPISpecs/SDLPresentChoiceSetOperationSpec.m @@ -46,6 +46,7 @@ describe(@"present choice operation", ^{ __block BOOL hasCalledOperationCompletionHandler = NO; __block NSError *resultError = nil; + __block SDLWindowCapability *windowCapability = nil; beforeEach(^{ resultError = nil; @@ -58,9 +59,10 @@ describe(@"present choice operation", ^{ testChoices = @[cell1]; testChoiceSet = [[SDLChoiceSet alloc] initWithTitle:@"Test Title" delegate:testChoiceDelegate layout:SDLChoiceSetLayoutTiles timeout:13 initialPromptString:@"Test initial prompt" timeoutPromptString:@"Test timeout prompt" helpPromptString:@"Test help prompt" vrHelpList:nil choices:testChoices]; + windowCapability = [[SDLWindowCapability alloc] init]; testKeyboardDelegate = OCMProtocolMock(@protocol(SDLKeyboardDelegate)); OCMStub([testKeyboardDelegate customKeyboardConfiguration]).andReturn(nil); - testKeyboardProperties = [[SDLKeyboardProperties alloc] initWithLanguage:SDLLanguageArSa keyboardLayout:SDLKeyboardLayoutAZERTY keypressMode:SDLKeypressModeResendCurrentEntry limitedCharacterList:nil autoCompleteList:nil]; + testKeyboardProperties = [[SDLKeyboardProperties alloc] initWithLanguage:SDLLanguageArSa keyboardLayout:SDLKeyboardLayoutAZERTY keypressMode:SDLKeypressModeResendCurrentEntry limitedCharacterList:nil autoCompleteList:nil maskInputCharacters:nil customKeys:nil]; }); it(@"should have a priority of 'normal'", ^{ @@ -71,7 +73,7 @@ describe(@"present choice operation", ^{ describe(@"running a non-searchable choice set operation", ^{ beforeEach(^{ - testOp = [[SDLPresentChoiceSetOperation alloc] initWithConnectionManager:testConnectionManager choiceSet:testChoiceSet mode:testInteractionMode keyboardProperties:nil keyboardDelegate:nil cancelID:testCancelID]; + testOp = [[SDLPresentChoiceSetOperation alloc] initWithConnectionManager:testConnectionManager choiceSet:testChoiceSet mode:testInteractionMode keyboardProperties:nil keyboardDelegate:nil cancelID:testCancelID windowCapability:windowCapability]; testOp.completionBlock = ^{ hasCalledOperationCompletionHandler = YES; }; @@ -125,7 +127,7 @@ describe(@"present choice operation", ^{ __block SDLPresentChoiceSetOperation *testCancelOp = nil; beforeEach(^{ - testCancelOp = [[SDLPresentChoiceSetOperation alloc] initWithConnectionManager:testConnectionManager choiceSet:testChoiceSet mode:testInteractionMode keyboardProperties:nil keyboardDelegate:nil cancelID:testCancelID]; + testCancelOp = [[SDLPresentChoiceSetOperation alloc] initWithConnectionManager:testConnectionManager choiceSet:testChoiceSet mode:testInteractionMode keyboardProperties:nil keyboardDelegate:nil cancelID:testCancelID windowCapability:windowCapability]; testCancelOp.completionBlock = ^{ hasCalledOperationCompletionHandler = YES; }; @@ -313,7 +315,7 @@ describe(@"present choice operation", ^{ describe(@"running a searchable choice set operation", ^{ beforeEach(^{ - testOp = [[SDLPresentChoiceSetOperation alloc] initWithConnectionManager:testConnectionManager choiceSet:testChoiceSet mode:testInteractionMode keyboardProperties:testKeyboardProperties keyboardDelegate:testKeyboardDelegate cancelID:testCancelID]; + testOp = [[SDLPresentChoiceSetOperation alloc] initWithConnectionManager:testConnectionManager choiceSet:testChoiceSet mode:testInteractionMode keyboardProperties:testKeyboardProperties keyboardDelegate:testKeyboardDelegate cancelID:testCancelID windowCapability:windowCapability]; testOp.completionBlock = ^{ hasCalledOperationCompletionHandler = YES; @@ -414,6 +416,25 @@ describe(@"present choice operation", ^{ }]]); }); + it(@"should respond to enabled keyboard event", ^{ + SDLRPCNotificationNotification *notification = nil; + + // Submit notification + SDLOnKeyboardInput *input = [[SDLOnKeyboardInput alloc] init]; + input.event = SDLKeyboardEventInputKeyMaskEnabled; + notification = [[SDLRPCNotificationNotification alloc] initWithName:SDLDidReceiveKeyboardInputNotification object:nil rpcNotification:input]; + + [[NSNotificationCenter defaultCenter] postNotification:notification]; + + OCMVerify([testKeyboardDelegate keyboardDidSendEvent:[OCMArg checkWithBlock:^BOOL(id obj) { + return [(SDLKeyboardEvent)obj isEqualToEnum:SDLKeyboardEventInputKeyMaskEnabled]; + }] text:[OCMArg isNil]]); + + OCMVerify([testKeyboardDelegate keyboardDidUpdateInputMask:[OCMArg checkWithBlock:^BOOL(id obj) { + return [(SDLKeyboardEvent)obj isEqualToEnum:SDLKeyboardEventInputKeyMaskEnabled]; + }]]); + }); + it(@"should respond to cancellation notifications", ^{ SDLRPCNotificationNotification *notification = nil; diff --git a/SmartDeviceLinkTests/DevAPISpecs/SDLPresentKeyboardOperationSpec.m b/SmartDeviceLinkTests/DevAPISpecs/SDLPresentKeyboardOperationSpec.m index 29ed6d0b0..389e0367d 100644 --- a/SmartDeviceLinkTests/DevAPISpecs/SDLPresentKeyboardOperationSpec.m +++ b/SmartDeviceLinkTests/DevAPISpecs/SDLPresentKeyboardOperationSpec.m @@ -33,6 +33,7 @@ describe(@"present keyboard operation", ^{ __block BOOL hasCalledOperationCompletionHandler = NO; __block NSError *resultError = nil; + __block SDLWindowCapability *windowCapability = nil; beforeEach(^{ testOp = nil; @@ -43,7 +44,17 @@ describe(@"present keyboard operation", ^{ testDelegate = OCMProtocolMock(@protocol(SDLKeyboardDelegate)); OCMStub([testDelegate customKeyboardConfiguration]).andReturn(nil); - testInitialProperties = [[SDLKeyboardProperties alloc] initWithLanguage:SDLLanguageArSa keyboardLayout:SDLKeyboardLayoutAZERTY keypressMode:SDLKeypressModeResendCurrentEntry limitedCharacterList:nil autoCompleteList:nil]; + windowCapability = [[SDLWindowCapability alloc] init]; + testInitialProperties = [[SDLKeyboardProperties alloc] initWithLanguage:SDLLanguageArSa keyboardLayout:SDLKeyboardLayoutAZERTY keypressMode:SDLKeypressModeResendCurrentEntry limitedCharacterList:nil autoCompleteList:nil maskInputCharacters:nil customKeys:nil]; + }); + + afterEach(^{ + if (testOp) { + // rationale: every test run creates a new operation to test, the old operation from a previous test + // stays 'undead' undefined time and can receive notifications causing a test fail at random + [[NSNotificationCenter defaultCenter] removeObserver:testOp]; + testOp = nil; + } }); it(@"should have a priority of 'normal'", ^{ @@ -54,7 +65,7 @@ describe(@"present keyboard operation", ^{ describe(@"running the operation", ^{ beforeEach(^{ - testOp = [[SDLPresentKeyboardOperation alloc] initWithConnectionManager:testConnectionManager keyboardProperties:testInitialProperties initialText:testInitialText keyboardDelegate:testDelegate cancelID:testCancelID]; + testOp = [[SDLPresentKeyboardOperation alloc] initWithConnectionManager:testConnectionManager keyboardProperties:testInitialProperties initialText:testInitialText keyboardDelegate:testDelegate cancelID:testCancelID windowCapability:windowCapability]; testOp.completionBlock = ^{ hasCalledOperationCompletionHandler = YES; }; @@ -148,6 +159,25 @@ describe(@"present keyboard operation", ^{ }]]); }); + it(@"should respond to enabled keyboard event", ^{ + SDLRPCNotificationNotification *notification = nil; + + // Submit notification + SDLOnKeyboardInput *input = [[SDLOnKeyboardInput alloc] init]; + input.event = SDLKeyboardEventInputKeyMaskEnabled; + notification = [[SDLRPCNotificationNotification alloc] initWithName:SDLDidReceiveKeyboardInputNotification object:nil rpcNotification:input]; + + [[NSNotificationCenter defaultCenter] postNotification:notification]; + + OCMVerify([testDelegate keyboardDidSendEvent:[OCMArg checkWithBlock:^BOOL(id obj) { + return [(SDLKeyboardEvent)obj isEqualToEnum:SDLKeyboardEventInputKeyMaskEnabled]; + }] text:[OCMArg isNil]]); + + OCMVerify([testDelegate keyboardDidUpdateInputMask:[OCMArg checkWithBlock:^BOOL(id obj) { + return [(SDLKeyboardEvent)obj isEqualToEnum:SDLKeyboardEventInputKeyMaskEnabled]; + }]]); + }); + it(@"should respond to cancellation notifications", ^{ SDLRPCNotificationNotification *notification = nil; @@ -260,7 +290,7 @@ describe(@"present keyboard operation", ^{ describe(@"Canceling the keyboard", ^{ beforeEach(^{ - testOp = [[SDLPresentKeyboardOperation alloc] initWithConnectionManager:testConnectionManager keyboardProperties:testInitialProperties initialText:testInitialText keyboardDelegate:testDelegate cancelID:testCancelID]; + testOp = [[SDLPresentKeyboardOperation alloc] initWithConnectionManager:testConnectionManager keyboardProperties:testInitialProperties initialText:testInitialText keyboardDelegate:testDelegate cancelID:testCancelID windowCapability:windowCapability]; testOp.completionBlock = ^{ hasCalledOperationCompletionHandler = YES; }; diff --git a/SmartDeviceLinkTests/DevAPISpecs/SDLTextAndGraphicManagerSpec.m b/SmartDeviceLinkTests/DevAPISpecs/SDLTextAndGraphicManagerSpec.m index 41ff4ba56..c3e95144a 100644 --- a/SmartDeviceLinkTests/DevAPISpecs/SDLTextAndGraphicManagerSpec.m +++ b/SmartDeviceLinkTests/DevAPISpecs/SDLTextAndGraphicManagerSpec.m @@ -489,7 +489,7 @@ describe(@"text and graphic manager", ^{ beforeEach(^{ testHMIStatus = [[SDLOnHMIStatus alloc] init]; - testWindowCapability = [[SDLWindowCapability alloc] initWithWindowID:@(SDLPredefinedWindowsDefaultWindow) textFields:nil imageFields:nil imageTypeSupported:nil templatesAvailable:nil numCustomPresetsAvailable:nil buttonCapabilities:nil softButtonCapabilities:nil menuLayoutsAvailable:nil dynamicUpdateCapabilities:nil]; + testWindowCapability = [[SDLWindowCapability alloc] initWithWindowID:@(SDLPredefinedWindowsDefaultWindow) textFields:nil imageFields:nil imageTypeSupported:nil templatesAvailable:nil numCustomPresetsAvailable:nil buttonCapabilities:nil softButtonCapabilities:nil menuLayoutsAvailable:nil dynamicUpdateCapabilities:nil keyboardCapabilities:nil]; testDisplayCapability = [[SDLDisplayCapability alloc] initWithDisplayName:@"Test display" windowCapabilities:@[testWindowCapability] windowTypeSupported:nil]; testSystemCapability = [[SDLSystemCapability alloc] initWithDisplayCapabilities:@[testDisplayCapability]]; @@ -554,7 +554,7 @@ describe(@"text and graphic manager", ^{ SDLRPCNotificationNotification *notification = [[SDLRPCNotificationNotification alloc] initWithName:SDLDidChangeHMIStatusNotification object:nil rpcNotification:testHMIStatus]; [[NSNotificationCenter defaultCenter] postNotification:notification]; - testWindowCapability = [[SDLWindowCapability alloc] initWithWindowID:@(SDLPredefinedWindowsDefaultWindow) textFields:nil imageFields:nil imageTypeSupported:nil templatesAvailable:nil numCustomPresetsAvailable:nil buttonCapabilities:nil softButtonCapabilities:nil menuLayoutsAvailable:nil dynamicUpdateCapabilities:nil]; + testWindowCapability = [[SDLWindowCapability alloc] initWithWindowID:@(SDLPredefinedWindowsDefaultWindow) textFields:nil imageFields:nil imageTypeSupported:nil templatesAvailable:nil numCustomPresetsAvailable:nil buttonCapabilities:nil softButtonCapabilities:nil menuLayoutsAvailable:nil dynamicUpdateCapabilities:nil keyboardCapabilities:nil]; testDisplayCapability = [[SDLDisplayCapability alloc] initWithDisplayName:@"Test display" windowCapabilities:@[testWindowCapability] windowTypeSupported:nil]; testSystemCapability = [[SDLSystemCapability alloc] initWithDisplayCapabilities:@[testDisplayCapability]]; }); diff --git a/SmartDeviceLinkTests/Notifications/SDLResponseDispatcherSpec.m b/SmartDeviceLinkTests/Notifications/SDLResponseDispatcherSpec.m index 4ff829470..9dcff09b7 100644 --- a/SmartDeviceLinkTests/Notifications/SDLResponseDispatcherSpec.m +++ b/SmartDeviceLinkTests/Notifications/SDLResponseDispatcherSpec.m @@ -242,8 +242,11 @@ describe(@"a response dispatcher", ^{ testCommandId = 1; testAddCommandCorrelationId = @42; numTimesHandlerCalled = 0; - + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" testAddCommand = [[SDLAddCommand alloc] initWithId:testCommandId vrCommands:nil handler:^(__kindof SDLRPCNotification * _Nonnull notification) { +#pragma clang diagnostic pop numTimesHandlerCalled++; }]; testAddCommand.correlationID = testAddCommandCorrelationId; @@ -343,7 +346,10 @@ describe(@"a response dispatcher", ^{ context(@"without a handler", ^{ beforeEach(^{ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" testAddCommand = [[SDLAddCommand alloc] initWithId:1 vrCommands:nil handler:nil]; +#pragma clang diagnostic pop }); it(@"should not add the command", ^{ diff --git a/SmartDeviceLinkTests/RPCSpecs/EnumSpecs/SDLImageFieldNameSpec.m b/SmartDeviceLinkTests/RPCSpecs/EnumSpecs/SDLImageFieldNameSpec.m index 6363714eb..f3a539e71 100644 --- a/SmartDeviceLinkTests/RPCSpecs/EnumSpecs/SDLImageFieldNameSpec.m +++ b/SmartDeviceLinkTests/RPCSpecs/EnumSpecs/SDLImageFieldNameSpec.m @@ -29,6 +29,8 @@ describe(@"Individual Enum Value Tests", ^ { expect(SDLImageFieldNameLocationImage).to(equal(@"locationImage")); expect(SDLImageFieldNameSubMenuIcon).to(equal(@"subMenuIcon")); expect(SDLImageFieldNameSubtleAlertIcon).to(equal(@"subtleAlertIcon")); + expect(SDLImageFieldNameMenuCommandSecondaryImage).to(equal(@"menuCommandSecondaryImage")); + expect(SDLImageFieldNameMenuSubMenuSecondaryImage).to(equal(@"menuSubMenuSecondaryImage")); }); }); diff --git a/SmartDeviceLinkTests/RPCSpecs/EnumSpecs/SDLKeyboardEventSpec.m b/SmartDeviceLinkTests/RPCSpecs/EnumSpecs/SDLKeyboardEventSpec.m index ce2782d3f..d47e87d4c 100644 --- a/SmartDeviceLinkTests/RPCSpecs/EnumSpecs/SDLKeyboardEventSpec.m +++ b/SmartDeviceLinkTests/RPCSpecs/EnumSpecs/SDLKeyboardEventSpec.m @@ -12,13 +12,15 @@ QuickSpecBegin(SDLKeyboardEventSpec) -describe(@"Individual Enum Value Tests", ^ { - it(@"Should match internal values", ^ { +describe(@"individual enum value tests", ^{ + it(@"should match internal values", ^{ expect(SDLKeyboardEventKeypress).to(equal(@"KEYPRESS")); expect(SDLKeyboardEventSubmitted).to(equal(@"ENTRY_SUBMITTED")); expect(SDLKeyboardEventCancelled).to(equal(@"ENTRY_CANCELLED")); expect(SDLKeyboardEventAborted).to(equal(@"ENTRY_ABORTED")); expect(SDLKeyboardEventVoice).to(equal(@"ENTRY_VOICE")); + expect(SDLKeyboardEventInputKeyMaskEnabled).to(equal(@"INPUT_KEY_MASK_ENABLED")); + expect(SDLKeyboardEventInputKeyMaskDisabled).to(equal(@"INPUT_KEY_MASK_DISABLED")); }); }); diff --git a/SmartDeviceLinkTests/RPCSpecs/EnumSpecs/SDLKeyboardInputMaskSpec.m b/SmartDeviceLinkTests/RPCSpecs/EnumSpecs/SDLKeyboardInputMaskSpec.m new file mode 100644 index 000000000..dd7bd708e --- /dev/null +++ b/SmartDeviceLinkTests/RPCSpecs/EnumSpecs/SDLKeyboardInputMaskSpec.m @@ -0,0 +1,23 @@ +// +// SDLAppHMITypeSpec.m +// SmartDeviceLink + + +#import <Foundation/Foundation.h> + +#import <Quick/Quick.h> +#import <Nimble/Nimble.h> + +#import "SDLKeyboardInputMask.h" + +QuickSpecBegin(SDLKeyboardInputMaskSpec) + +describe(@"individual enum value tests", ^{ + it(@"should match internal values", ^{ + expect(SDLKeyboardInputMaskEnableInputKeyMask).to(equal(@"ENABLE_INPUT_KEY_MASK")); + expect(SDLKeyboardInputMaskDisableInputKeyMask).to(equal(@"DISABLE_INPUT_KEY_MASK")); + expect(SDLKeyboardInputMaskUserChoiceInputKeyMask).to(equal(@"USER_CHOICE_INPUT_KEY_MASK")); + }); +}); + +QuickSpecEnd diff --git a/SmartDeviceLinkTests/RPCSpecs/EnumSpecs/SDLKeyboardLayoutSpec.m b/SmartDeviceLinkTests/RPCSpecs/EnumSpecs/SDLKeyboardLayoutSpec.m index ec0298852..d254c9d06 100644 --- a/SmartDeviceLinkTests/RPCSpecs/EnumSpecs/SDLKeyboardLayoutSpec.m +++ b/SmartDeviceLinkTests/RPCSpecs/EnumSpecs/SDLKeyboardLayoutSpec.m @@ -12,11 +12,12 @@ QuickSpecBegin(SDLKeyboardLayoutSpec) -describe(@"Individual Enum Value Tests", ^ { - it(@"Should match internal values", ^ { +describe(@"individual enum value tests", ^{ + it(@"should match internal values", ^{ expect(SDLKeyboardLayoutQWERTY).to(equal(@"QWERTY")); expect(SDLKeyboardLayoutQWERTZ).to(equal(@"QWERTZ")); expect(SDLKeyboardLayoutAZERTY).to(equal(@"AZERTY")); + expect(SDLKeyboardLayoutNumeric).to(equal(@"NUMERIC")); }); }); diff --git a/SmartDeviceLinkTests/RPCSpecs/EnumSpecs/SDLTextFieldNameSpec.m b/SmartDeviceLinkTests/RPCSpecs/EnumSpecs/SDLTextFieldNameSpec.m index 423c68b77..b9827e75c 100644 --- a/SmartDeviceLinkTests/RPCSpecs/EnumSpecs/SDLTextFieldNameSpec.m +++ b/SmartDeviceLinkTests/RPCSpecs/EnumSpecs/SDLTextFieldNameSpec.m @@ -49,6 +49,12 @@ describe(@"Individual Enum Value Tests", ^ { expect(SDLTextFieldNameSubtleAlertText1).to(equal(@"subtleAlertText1")); expect(SDLTextFieldNameSubtleAlertText2).to(equal(@"subtleAlertText2")); expect(SDLTextFieldNameSubtleAlertSoftButtonText).to(equal("subtleAlertSoftButtonText")); + expect(SDLTextFieldNameTimeToDestination).to(equal(@"timeToDestination")); + expect(SDLTextFieldNameTurnText).to(equal(@"turnText")); + expect(SDLTextFieldNameMenuCommandSecondaryText).to(equal(@"menuCommandSecondaryText")); + expect(SDLTextFieldNameMenuCommandTertiaryText).to(equal(@"menuCommandTertiaryText")); + expect(SDLTextFieldNameMenuSubMenuSecondaryText).to(equal(@"menuSubMenuSecondaryText")); + expect(SDLTextFieldNameMenuSubMenuTertiaryText).to(equal(@"menuSubMenuTertiaryText")); }); }); diff --git a/SmartDeviceLinkTests/RPCSpecs/RequestSpecs/SDLAddCommandSpec.m b/SmartDeviceLinkTests/RPCSpecs/RequestSpecs/SDLAddCommandSpec.m index 3d636db9e..570b9eb23 100644 --- a/SmartDeviceLinkTests/RPCSpecs/RequestSpecs/SDLAddCommandSpec.m +++ b/SmartDeviceLinkTests/RPCSpecs/RequestSpecs/SDLAddCommandSpec.m @@ -18,7 +18,8 @@ QuickSpecBegin(SDLAddCommandSpec) describe(@"Getter/Setter Tests", ^ { SDLMenuParams* menu = [[SDLMenuParams alloc] init]; - SDLImage* image = [[SDLImage alloc] init]; + SDLImage *image = [[SDLImage alloc] initWithName:@"Icon" ofType:SDLImageTypeDynamic isTemplate:YES]; + SDLImage *testSecondaryImage = [[SDLImage alloc] initWithStaticIconName:SDLStaticIconNameKey]; it(@"Should set and get correctly", ^ { SDLAddCommand* testRequest = [[SDLAddCommand alloc] init]; @@ -27,27 +28,31 @@ describe(@"Getter/Setter Tests", ^ { testRequest.menuParams = menu; testRequest.vrCommands = [@[@"name", @"anotherName"] mutableCopy]; testRequest.cmdIcon = image; + testRequest.secondaryImage = testSecondaryImage; expect(testRequest.cmdID).to(equal(@434577)); expect(testRequest.menuParams).to(equal(menu)); expect(testRequest.vrCommands).to(equal([@[@"name", @"anotherName"] mutableCopy])); expect(testRequest.cmdIcon).to(equal(image)); + expect(testRequest.secondaryImage).to(equal(testSecondaryImage)); }); - + it(@"Should get correctly when initialized", ^ { NSMutableDictionary<NSString *, id> *dict = [@{SDLRPCParameterNameRequest: @{SDLRPCParameterNameParameters: @{SDLRPCParameterNameCommandId:@434577, SDLRPCParameterNameMenuParams:menu, SDLRPCParameterNameVRCommands:[@[@"name", @"anotherName"] mutableCopy], - SDLRPCParameterNameCommandIcon:image}, - SDLRPCParameterNameOperationName:SDLRPCFunctionNameAddCommand}} mutableCopy]; + SDLRPCParameterNameCommandIcon:image, + SDLRPCParameterNameSecondaryImage: testSecondaryImage}, + SDLRPCParameterNameOperationName:SDLRPCFunctionNameAddCommand}} mutableCopy]; SDLAddCommand* testRequest = [[SDLAddCommand alloc] initWithDictionary:dict]; expect(testRequest.cmdID).to(equal(@434577)); expect(testRequest.menuParams).to(equal(menu)); expect(testRequest.vrCommands).to(equal([@[@"name", @"anotherName"] mutableCopy])); expect(testRequest.cmdIcon).to(equal(image)); + expect(testRequest.secondaryImage).to(equal(testSecondaryImage)); }); it(@"Should return nil if not set", ^ { @@ -57,6 +62,7 @@ describe(@"Getter/Setter Tests", ^ { expect(testRequest.menuParams).to(beNil()); expect(testRequest.vrCommands).to(beNil()); expect(testRequest.cmdIcon).to(beNil()); + expect(testRequest.secondaryImage).to(beNil()); }); }); @@ -65,6 +71,9 @@ describe(@"initializers", ^{ __block UInt32 commandId = 1234; __block NSArray<NSString *> *vrCommands = @[@"commands"]; __block NSString *menuName = @"Menu Name"; + SDLImage *image = [[SDLImage alloc] initWithName:@"Icon" ofType:SDLImageTypeDynamic isTemplate:YES]; + SDLImage *testSecondaryImage = [[SDLImage alloc] initWithStaticIconName:SDLStaticIconNameKey]; + SDLMenuParams *testMenuParams = [[SDLMenuParams alloc] initWithMenuName:menuName]; void (^handler)(SDLOnCommand *) = ^(SDLOnCommand *command) {}; beforeEach(^{ @@ -83,7 +92,10 @@ describe(@"initializers", ^{ context(@"initWithHandler:", ^{ it(@"should initialize correctly", ^{ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" testCommand = [[SDLAddCommand alloc] initWithHandler:handler]; +#pragma clang diagnostic pop expect(testCommand).toNot(beNil()); expect(testCommand.vrCommands).to(beNil()); @@ -94,7 +106,10 @@ describe(@"initializers", ^{ context(@"initWithId:vrCommands:handler:", ^{ it(@"should initialize correctly", ^{ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" testCommand = [[SDLAddCommand alloc] initWithId:commandId vrCommands:vrCommands handler:nil]; +#pragma clang diagnostic pop expect(testCommand.cmdID).to(equal(commandId)); expect(testCommand.vrCommands).to(equal(vrCommands)); @@ -105,7 +120,10 @@ describe(@"initializers", ^{ context(@"initWithId:vrCommands:menuName:handler:", ^{ it(@"should initialize correctly", ^{ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" testCommand = [[SDLAddCommand alloc] initWithId:commandId vrCommands:vrCommands menuName:menuName handler:nil]; +#pragma clang diagnostic pop expect(testCommand.cmdID).to(equal(commandId)); expect(testCommand.vrCommands).to(equal(vrCommands)); @@ -122,8 +140,10 @@ describe(@"initializers", ^{ NSString *iconValue = @"Icon"; SDLImageType imageType = SDLImageTypeDynamic; BOOL imageIsTemplate = YES; - +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" testCommand = [[SDLAddCommand alloc] initWithId:commandId vrCommands:vrCommands menuName:menuName parentId:parentId position:position iconValue:iconValue iconType:imageType iconIsTemplate:imageIsTemplate handler:nil]; +#pragma clang diagnostic pop expect(testCommand.cmdID).to(equal(commandId)); expect(testCommand.vrCommands).to(equal(vrCommands)); @@ -138,7 +158,10 @@ describe(@"initializers", ^{ }); it(@"should initialize without an image", ^{ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" testCommand = [[SDLAddCommand alloc] initWithId:commandId vrCommands:vrCommands menuName:menuName parentId:parentId position:position iconValue:nil iconType:nil iconIsTemplate:NO handler:nil]; +#pragma clang diagnostic pop expect(testCommand.cmdID).to(equal(commandId)); expect(testCommand.vrCommands).to(equal(vrCommands)); @@ -155,8 +178,10 @@ describe(@"initializers", ^{ it(@"should initialize with an image", ^{ SDLImage *image = [[SDLImage alloc] initWithName:@"Icon" ofType:SDLImageTypeDynamic isTemplate:YES]; - +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" testCommand = [[SDLAddCommand alloc] initWithId:commandId vrCommands:vrCommands menuName:menuName parentId:parentId position:position icon:image handler:nil]; +#pragma clang diagnostic pop expect(testCommand.cmdID).to(equal(commandId)); expect(testCommand.vrCommands).to(equal(vrCommands)); @@ -171,7 +196,10 @@ describe(@"initializers", ^{ }); it(@"should initialize without an image", ^{ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" testCommand = [[SDLAddCommand alloc] initWithId:commandId vrCommands:vrCommands menuName:menuName parentId:parentId position:position icon:nil handler:nil]; +#pragma clang diagnostic pop expect(testCommand.cmdID).to(equal(commandId)); expect(testCommand.vrCommands).to(equal(vrCommands)); @@ -182,6 +210,41 @@ describe(@"initializers", ^{ expect(testCommand.cmdIcon).to(beNil()); }); }); + + context(@"initWithCmdID:menuParams:vrCommands:cmdIcon:secondaryImage", ^{ + it(@"should initialize with an image", ^{ + testCommand = [[SDLAddCommand alloc] initWithCmdID:commandId menuParams:testMenuParams vrCommands:vrCommands cmdIcon:image secondaryImage:testSecondaryImage]; + + expect(testCommand.cmdID).to(equal(commandId)); + expect(testCommand.vrCommands).to(equal(vrCommands)); + expect(testCommand.menuParams).to(equal(testMenuParams)); + + expect(testCommand.cmdIcon).toNot(beNil()); + expect(testCommand.cmdIcon.value).to(equal(image.value)); + expect(testCommand.cmdIcon.imageType).to(equal(image.imageType)); + expect(testCommand.cmdIcon.isTemplate).to(equal(image.isTemplate)); + + expect(testCommand.secondaryImage).toNot(beNil()); + expect(testCommand.secondaryImage.value).to(equal(testSecondaryImage.value)); + expect(testCommand.secondaryImage.imageType).to(equal(testSecondaryImage.imageType)); + expect(testCommand.secondaryImage.isTemplate).to(equal(testSecondaryImage.isTemplate)); + }); + + it(@"should initialize without an image", ^{ + testCommand = [[SDLAddCommand alloc] initWithCmdID:commandId menuParams:testMenuParams vrCommands:vrCommands cmdIcon:image secondaryImage:nil]; + + expect(testCommand.cmdID).to(equal(commandId)); + expect(testCommand.vrCommands).to(equal(vrCommands)); + expect(testCommand.menuParams).to(equal(testMenuParams)); + + expect(testCommand.cmdIcon).toNot(beNil()); + expect(testCommand.cmdIcon.value).to(equal(image.value)); + expect(testCommand.cmdIcon.imageType).to(equal(image.imageType)); + expect(testCommand.cmdIcon.isTemplate).to(equal(image.isTemplate)); + + expect(testCommand.secondaryImage).to(beNil()); + }); + }); }); QuickSpecEnd diff --git a/SmartDeviceLinkTests/RPCSpecs/RequestSpecs/SDLAddSubMenuSpec.m b/SmartDeviceLinkTests/RPCSpecs/RequestSpecs/SDLAddSubMenuSpec.m index 3dffd0961..a3cc333e2 100644 --- a/SmartDeviceLinkTests/RPCSpecs/RequestSpecs/SDLAddSubMenuSpec.m +++ b/SmartDeviceLinkTests/RPCSpecs/RequestSpecs/SDLAddSubMenuSpec.m @@ -19,12 +19,16 @@ describe(@"Getter/Setter Tests", ^ { __block UInt32 menuId = 4345645; __block UInt8 position = 27; __block NSString *menuName = @"Welcome to the menu"; + __block NSString *secondaryText = @"Secondary text"; + __block NSString *tertiaryText = @"Tertiary text"; __block SDLImage *image = nil; + __block SDLImage *secondaryImage = nil; __block SDLMenuLayout testLayout = SDLMenuLayoutList; __block NSNumber *parentID = @44; beforeEach(^{ image = [[SDLImage alloc] initWithName:@"Test" isTemplate:false]; + secondaryImage = [[SDLImage alloc] initWithStaticIconName:SDLStaticIconNameKey]; }); it(@"should correctly initialize with initWithMenuID:menuName:", ^{ @@ -35,10 +39,16 @@ describe(@"Getter/Setter Tests", ^ { expect(testRequest.menuName).to(equal(menuName)); expect(testRequest.menuIcon).to(beNil()); expect(testRequest.parentID).to(beNil()); + expect(testRequest.secondaryText).to(beNil()); + expect(testRequest.tertiaryText).to(beNil()); + expect(testRequest.secondaryImage).to(beNil()); }); it(@"should correctly initialize with initWithMenuID:menuName:menuLayout:menuIcon:position:parentID:", ^{ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" SDLAddSubMenu *testRequest = [[SDLAddSubMenu alloc] initWithMenuID:menuId menuName:menuName position:@(position) menuIcon:image menuLayout:testLayout parentID:parentID]; +#pragma clang diagnostic pop expect(testRequest.menuID).to(equal(@(menuId))); expect(testRequest.position).to(equal(@(position))); @@ -46,6 +56,23 @@ describe(@"Getter/Setter Tests", ^ { expect(testRequest.menuIcon).to(equal(image)); expect(testRequest.menuLayout).to(equal(testLayout)); expect(testRequest.parentID).to(equal(parentID)); + expect(testRequest.secondaryText).to(beNil()); + expect(testRequest.tertiaryText).to(beNil()); + expect(testRequest.secondaryImage).to(beNil()); + }); + + it(@"should correctly initialize with initWithMenuID:menuName:position:menuIcon:menuLayout:parentID:secondaryText:tertiaryText:secondaryImage:", ^{ + SDLAddSubMenu *testRequest = [[SDLAddSubMenu alloc] initWithMenuID:menuId menuName:menuName position:@(position) menuIcon:image menuLayout:testLayout parentID:parentID secondaryText:secondaryText tertiaryText:tertiaryText secondaryImage:secondaryImage]; + + expect(testRequest.menuID).to(equal(@(menuId))); + expect(testRequest.position).to(equal(@(position))); + expect(testRequest.menuName).to(equal(menuName)); + expect(testRequest.menuIcon).to(equal(image)); + expect(testRequest.menuLayout).to(equal(testLayout)); + expect(testRequest.parentID).to(equal(parentID)); + expect(testRequest.secondaryText).to(equal(secondaryText)); + expect(testRequest.tertiaryText).to(equal(tertiaryText)); + expect(testRequest.secondaryImage).to(equal(secondaryImage)); }); it(@"Should set and get correctly", ^ { @@ -57,6 +84,9 @@ describe(@"Getter/Setter Tests", ^ { testRequest.menuIcon = image; testRequest.menuLayout = testLayout; testRequest.parentID = parentID; + testRequest.secondaryText = secondaryText; + testRequest.tertiaryText = tertiaryText; + testRequest.secondaryImage = secondaryImage; expect(testRequest.menuID).to(equal(@(menuId))); expect(testRequest.position).to(equal(@(position))); @@ -64,6 +94,9 @@ describe(@"Getter/Setter Tests", ^ { expect(testRequest.menuIcon).to(equal(image)); expect(testRequest.menuLayout).to(equal(testLayout)); expect(testRequest.parentID).to(equal(parentID)); + expect(testRequest.secondaryText).to(equal(secondaryText)); + expect(testRequest.tertiaryText).to(equal(tertiaryText)); + expect(testRequest.secondaryImage).to(equal(secondaryImage)); }); it(@"Should get correctly when initialized", ^ { @@ -76,6 +109,9 @@ describe(@"Getter/Setter Tests", ^ { SDLRPCParameterNameValue: image.value }, SDLRPCParameterNameMenuLayout: testLayout, + SDLRPCParameterNameSecondaryText: secondaryText, + SDLRPCParameterNameTertiaryText: tertiaryText, + SDLRPCParameterNameSecondaryImage: secondaryImage, SDLRPCParameterNameParentID: parentID }, SDLRPCParameterNameOperationName:SDLRPCFunctionNameAddSubMenu}}; @@ -87,6 +123,9 @@ describe(@"Getter/Setter Tests", ^ { expect(testRequest.menuIcon.value).to(equal(@"Test")); expect(testRequest.menuLayout).to(equal(testLayout)); expect(testRequest.parentID).to(equal(parentID)); + expect(testRequest.secondaryText).to(equal(secondaryText)); + expect(testRequest.tertiaryText).to(equal(tertiaryText)); + expect(testRequest.secondaryImage).to(equal(secondaryImage)); }); it(@"Should return nil if not set", ^ { @@ -98,6 +137,9 @@ describe(@"Getter/Setter Tests", ^ { expect(testRequest.menuIcon).to(beNil()); expect(testRequest.menuLayout).to(beNil()); expect(testRequest.parentID).to(beNil()); + expect(testRequest.secondaryText).to(beNil()); + expect(testRequest.tertiaryText).to(beNil()); + expect(testRequest.secondaryImage).to(beNil()); }); }); diff --git a/SmartDeviceLinkTests/RPCSpecs/StructSpecs/SDLKeyboardCapabilitiesSpec.m b/SmartDeviceLinkTests/RPCSpecs/StructSpecs/SDLKeyboardCapabilitiesSpec.m new file mode 100644 index 000000000..18abde7e6 --- /dev/null +++ b/SmartDeviceLinkTests/RPCSpecs/StructSpecs/SDLKeyboardCapabilitiesSpec.m @@ -0,0 +1,75 @@ +// +// SDLKeyboardCapabilitiesSpec.m +// SmartDeviceLink + + +#import <Foundation/Foundation.h> + +#import <Quick/Quick.h> +#import <Nimble/Nimble.h> + +#import "SDLKeyboardCapabilities.h" +#import "SDLRPCParameterNames.h" +#import "SDLKeyboardLayoutCapability.h" + +QuickSpecBegin(SDLKeyboardCapabilitiesSpec) + +NSNumber *maskInputCharactersSupported = @YES; +SDLKeyboardLayoutCapability *keyboardLayoutCapability = [[SDLKeyboardLayoutCapability alloc] init]; +NSArray<SDLKeyboardLayoutCapability *> *supportedKeyboards = @[keyboardLayoutCapability]; +__block SDLKeyboardCapabilities* testStruct = nil; + +describe(@"getter/setter tests", ^{ + context(@"init", ^{ + beforeEach(^{ + testStruct = [[SDLKeyboardCapabilities alloc] init]; + }); + + it(@"should return nil if not set", ^{ + expect(testStruct.maskInputCharactersSupported).to(beNil()); + expect(testStruct.supportedKeyboards).to(beNil()); + }); + }); + + context(@"init and assign", ^{ + beforeEach(^{ + testStruct = [[SDLKeyboardCapabilities alloc] init]; + testStruct.maskInputCharactersSupported = maskInputCharactersSupported; + testStruct.supportedKeyboards = supportedKeyboards; + }); + + it(@"expect all properties to be set properly", ^{ + expect(testStruct.maskInputCharactersSupported).to(equal(maskInputCharactersSupported)); + expect(testStruct.supportedKeyboards).to(equal(supportedKeyboards)); + }); + }); + + context(@"initWithDictionary:", ^{ + beforeEach(^{ + NSDictionary<NSString *, id> *dict = @{ + SDLRPCParameterNameMaskInputCharactersSupported: maskInputCharactersSupported, + SDLRPCParameterNameSupportedKeyboards: supportedKeyboards, + }; + testStruct = [[SDLKeyboardCapabilities alloc] initWithDictionary:dict]; + }); + + it(@"expect all properties to be set properly", ^{ + expect(testStruct.maskInputCharactersSupported).to(equal(maskInputCharactersSupported)); + expect(testStruct.supportedKeyboards).to(equal(supportedKeyboards)); + }); + }); + + context(@"initWithMaskInputCharactersSupported:supportedKeyboards:", ^{ + beforeEach(^{ + testStruct = [[SDLKeyboardCapabilities alloc] initWithMaskInputCharactersSupported:maskInputCharactersSupported supportedKeyboards:supportedKeyboards]; + }); + + it(@"expect all properties to be set properly", ^{ + expect(testStruct).notTo(beNil()); + expect(testStruct.maskInputCharactersSupported).to(equal(maskInputCharactersSupported)); + expect(testStruct.supportedKeyboards).to(equal(supportedKeyboards)); + }); + }); +}); + +QuickSpecEnd diff --git a/SmartDeviceLinkTests/RPCSpecs/StructSpecs/SDLKeyboardLayoutCapabilitySpec.m b/SmartDeviceLinkTests/RPCSpecs/StructSpecs/SDLKeyboardLayoutCapabilitySpec.m new file mode 100644 index 000000000..f938c30a9 --- /dev/null +++ b/SmartDeviceLinkTests/RPCSpecs/StructSpecs/SDLKeyboardLayoutCapabilitySpec.m @@ -0,0 +1,75 @@ +// +// SDLKeyboardLayoutCapabilitySpec.m +// SmartDeviceLink + + +#import <Foundation/Foundation.h> + +#import <Quick/Quick.h> +#import <Nimble/Nimble.h> + +#import "SDLKeyboardCapabilities.h" +#import "SDLKeyboardLayout.h" +#import "SDLRPCParameterNames.h" +#import "SDLKeyboardLayoutCapability.h" + +QuickSpecBegin(SDLKeyboardLayoutCapabilitySpec) + +SDLKeyboardLayout keyboardLayout = SDLKeyboardLayoutNumeric; +UInt8 numConfigurableKeys = 9; +__block SDLKeyboardLayoutCapability* testStruct = nil; + +describe(@"getter/setter tests", ^{ + context(@"init", ^{ + beforeEach(^{ + testStruct = [[SDLKeyboardLayoutCapability alloc] init]; + }); + + it(@"should return nil if not set", ^{ + expect(testStruct.keyboardLayout).to(beNil()); + expect(testStruct.numConfigurableKeys).to(beNil()); + }); + }); + + context(@"init and assign", ^{ + beforeEach(^{ + testStruct = [[SDLKeyboardLayoutCapability alloc] init]; + testStruct.numConfigurableKeys = @(numConfigurableKeys); + testStruct.keyboardLayout = keyboardLayout; + }); + + it(@"expect all properties to be set properly", ^{ + expect(testStruct.numConfigurableKeys).to(equal(@(numConfigurableKeys))); + expect(testStruct.keyboardLayout).to(equal(keyboardLayout)); + }); + }); + + context(@"initWithDictionary:", ^{ + beforeEach(^{ + NSDictionary<NSString *, id> *dict = @{ + SDLRPCParameterNameNumConfigurableKeys: @(numConfigurableKeys), + SDLRPCParameterNameKeyboardLayout: keyboardLayout, + }; + testStruct = [[SDLKeyboardLayoutCapability alloc] initWithDictionary:dict]; + }); + + it(@"expect all properties to be set properly", ^{ + expect(testStruct.numConfigurableKeys).to(equal(@(numConfigurableKeys))); + expect(testStruct.keyboardLayout).to(equal(keyboardLayout)); + }); + }); + + context(@"initWithKeyboardLayout:numConfigurableKeys:", ^{ + beforeEach(^{ + testStruct = [[SDLKeyboardLayoutCapability alloc] initWithKeyboardLayout:keyboardLayout numConfigurableKeys:numConfigurableKeys]; + }); + + it(@"expect all properties to be set properly", ^{ + expect(testStruct).notTo(beNil()); + expect(testStruct.numConfigurableKeys).to(equal(@(numConfigurableKeys))); + expect(testStruct.keyboardLayout).to(equal(keyboardLayout)); + }); + }); +}); + +QuickSpecEnd diff --git a/SmartDeviceLinkTests/RPCSpecs/StructSpecs/SDLKeyboardPropertiesSpec.m b/SmartDeviceLinkTests/RPCSpecs/StructSpecs/SDLKeyboardPropertiesSpec.m index b1f15a63f..8735babca 100644 --- a/SmartDeviceLinkTests/RPCSpecs/StructSpecs/SDLKeyboardPropertiesSpec.m +++ b/SmartDeviceLinkTests/RPCSpecs/StructSpecs/SDLKeyboardPropertiesSpec.m @@ -8,109 +8,182 @@ #import <Quick/Quick.h> #import <Nimble/Nimble.h> +#import "SDLKeyboardInputMask.h" #import "SDLKeyboardLayout.h" #import "SDLKeypressMode.h" #import "SDLKeyboardProperties.h" #import "SDLLanguage.h" #import "SDLRPCParameterNames.h" - QuickSpecBegin(SDLKeyboardPropertiesSpec) -describe(@"Getter/Setter Tests", ^ { - __block SDLLanguage testLanguage = SDLLanguageDaDk; - __block SDLKeyboardLayout testLayout = SDLKeyboardLayoutAZERTY; - __block SDLKeypressMode testMode = SDLKeypressModeSingleKeypress; - __block NSArray<NSString *> *testLimitedCharacterList = @[@"s", @"r", @"f"]; - __block NSString *testAutoCompleteText = @"Auto Carrot"; - __block NSArray<NSString *> *testAutoCompleteList = @[@"Hello World", @"How are you"]; - - it(@"Should set and get correctly", ^ { - SDLKeyboardProperties* testStruct = [[SDLKeyboardProperties alloc] init]; - - testStruct.language = testLanguage; - testStruct.keyboardLayout = testLayout; - testStruct.keypressMode = testMode; - testStruct.limitedCharacterList = testLimitedCharacterList; - testStruct.autoCompleteList = testAutoCompleteList; +__block SDLLanguage testLanguage = nil; +__block SDLKeyboardLayout testLayout = nil; +__block SDLKeypressMode testMode = nil; +__block NSArray<NSString *> *testLimitedCharacterList = nil; +__block NSString *testAutoCompleteText = nil; +__block NSArray<NSString *> *testAutoCompleteList = nil; +__block SDLKeyboardInputMask maskInputCharacters = nil; +__block NSArray<NSString *> *customKeys = nil; +__block SDLKeyboardProperties* testStruct = nil; + +describe(@"getter/setter tests", ^{ + beforeEach(^{ + testLanguage = SDLLanguageDaDk; + testLayout = SDLKeyboardLayoutAZERTY; + testMode = SDLKeypressModeSingleKeypress; + testLimitedCharacterList = @[@"s", @"r", @"f"]; + testAutoCompleteText = @"Auto Carrot"; + testAutoCompleteList = @[@"Hello World", @"How are you"]; + maskInputCharacters = SDLKeyboardInputMaskEnableInputKeyMask; + customKeys = @[@"abc", @"DEF"]; + }); + + context(@"init", ^{ + beforeEach(^{ + testStruct = [[SDLKeyboardProperties alloc] init]; + }); + + it(@"expect all properties to be nil", ^{ + expect(testStruct.language).to(beNil()); + expect(testStruct.keyboardLayout).to(beNil()); + expect(testStruct.keypressMode).to(beNil()); + expect(testStruct.limitedCharacterList).to(beNil()); + expect(testStruct.autoCompleteList).to(beNil()); + expect(testStruct.maskInputCharacters).to(beNil()); + expect(testStruct.customKeys).to(beNil()); +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + expect(testStruct.autoCompleteText).to(beNil()); +#pragma clang diagnostic pop + }); + }); + + context(@"init and assign", ^{ + beforeEach(^{ + testStruct = [[SDLKeyboardProperties alloc] init]; + testStruct.language = testLanguage; + testStruct.keyboardLayout = testLayout; + testStruct.keypressMode = testMode; + testStruct.limitedCharacterList = testLimitedCharacterList; + testStruct.autoCompleteList = testAutoCompleteList; + testStruct.maskInputCharacters = maskInputCharacters; + testStruct.customKeys = customKeys; #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" - testStruct.autoCompleteText = testAutoCompleteText; + testStruct.autoCompleteText = testAutoCompleteText; #pragma clang diagnostic pop + testStruct.maskInputCharacters = maskInputCharacters; + }); - expect(testStruct.language).to(equal(testLanguage)); - expect(testStruct.keyboardLayout).to(equal(testLayout)); - expect(testStruct.keypressMode).to(equal(testMode)); - expect(testStruct.limitedCharacterList).to(equal(testLimitedCharacterList)); - expect(testStruct.autoCompleteList).to(equal(testAutoCompleteList)); + it(@"should be set properly", ^{ + expect(testStruct.language).to(equal(testLanguage)); + expect(testStruct.keyboardLayout).to(equal(testLayout)); + expect(testStruct.keypressMode).to(equal(testMode)); + expect(testStruct.limitedCharacterList).to(equal(testLimitedCharacterList)); + expect(testStruct.autoCompleteList).to(equal(testAutoCompleteList)); + expect(testStruct.maskInputCharacters).to(equal(maskInputCharacters)); + expect(testStruct.customKeys).to(equal(customKeys)); #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" - expect(testStruct.autoCompleteText).to(equal(testAutoCompleteText)); + expect(testStruct.autoCompleteText).to(equal(testAutoCompleteText)); #pragma clang diagnostic pop + }); }); - - it(@"Should get correctly when initialized with a dictionary", ^ { - NSDictionary* dict = @{SDLRPCParameterNameLanguage: testLanguage, - SDLRPCParameterNameKeyboardLayout: testLayout, - SDLRPCParameterNameKeypressMode: testMode, - SDLRPCParameterNameLimitedCharacterList: testLimitedCharacterList, - SDLRPCParameterNameAutoCompleteList: testAutoCompleteList, - SDLRPCParameterNameAutoCompleteText: testAutoCompleteText - }; - SDLKeyboardProperties* testStruct = [[SDLKeyboardProperties alloc] initWithDictionary:dict]; - - expect(testStruct.language).to(equal(testLanguage)); - expect(testStruct.keyboardLayout).to(equal(testLayout)); - expect(testStruct.keypressMode).to(equal(testMode)); - expect(testStruct.limitedCharacterList).to(equal(testLimitedCharacterList)); - expect(testStruct.autoCompleteList).to(equal(testAutoCompleteList)); + + context(@"initWithDictionary:", ^{ + beforeEach(^{ + NSDictionary* dict = @{SDLRPCParameterNameLanguage: testLanguage, + SDLRPCParameterNameKeyboardLayout: testLayout, + SDLRPCParameterNameKeypressMode: testMode, + SDLRPCParameterNameLimitedCharacterList: testLimitedCharacterList, + SDLRPCParameterNameAutoCompleteList: testAutoCompleteList, + SDLRPCParameterNameAutoCompleteText: testAutoCompleteText, + SDLRPCParameterNameMaskInputCharacters: maskInputCharacters, + SDLRPCParameterNameCustomKeys: customKeys, + }; + testStruct = [[SDLKeyboardProperties alloc] initWithDictionary:dict]; + }); + + it(@"should be set properly", ^{ + expect(testStruct.language).to(equal(testLanguage)); + expect(testStruct.keyboardLayout).to(equal(testLayout)); + expect(testStruct.keypressMode).to(equal(testMode)); + expect(testStruct.limitedCharacterList).to(equal(testLimitedCharacterList)); + expect(testStruct.autoCompleteList).to(equal(testAutoCompleteList)); + expect(testStruct.maskInputCharacters).to(equal(maskInputCharacters)); + expect(testStruct.customKeys).to(equal(customKeys)); #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" - expect(testStruct.autoCompleteText).to(equal(testAutoCompleteText)); + expect(testStruct.autoCompleteText).to(equal(testAutoCompleteText)); #pragma clang diagnostic pop + }); }); - it(@"Should get correctly when initialized with initWithLanguage:layout:keypressMode:limitedCharacterList:autoCompleteText:autoCompleteList:", ^ { + context(@"initWithLanguage:layout:keypressMode:limitedCharacterList:autoCompleteText:autoCompleteList:", ^{ + beforeEach(^{ #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" - SDLKeyboardProperties *testStruct = [[SDLKeyboardProperties alloc] initWithLanguage:testLanguage layout:testLayout keypressMode:testMode limitedCharacterList:testLimitedCharacterList autoCompleteText:testAutoCompleteText autoCompleteList:testAutoCompleteList]; + testStruct = [[SDLKeyboardProperties alloc] initWithLanguage:testLanguage layout:testLayout keypressMode:testMode limitedCharacterList:testLimitedCharacterList autoCompleteText:testAutoCompleteText autoCompleteList:testAutoCompleteList]; #pragma clang diagnostic pop - expect(testStruct.language).to(equal(testLanguage)); - expect(testStruct.keyboardLayout).to(equal(testLayout)); - expect(testStruct.keypressMode).to(equal(testMode)); - expect(testStruct.limitedCharacterList).to(equal(testLimitedCharacterList)); + }); + + it(@"should be set properly", ^{ + expect(testStruct.language).to(equal(testLanguage)); + expect(testStruct.keyboardLayout).to(equal(testLayout)); + expect(testStruct.keypressMode).to(equal(testMode)); + expect(testStruct.limitedCharacterList).to(equal(testLimitedCharacterList)); + expect(testStruct.autoCompleteList).to(equal(testAutoCompleteList)); + expect(testStruct.maskInputCharacters).to(beNil()); + expect(testStruct.customKeys).to(beNil()); #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" - expect(testStruct.autoCompleteText).to(equal(testAutoCompleteText)); + expect(testStruct.autoCompleteText).to(equal(testAutoCompleteText)); #pragma clang diagnostic pop - expect(testStruct.autoCompleteList).to(equal(testAutoCompleteList)); + }); }); - it(@"Should get correctly when initialized with initWithLanguage:keyboardLayout:keypressMode:limitedCharacterList:autoCompleteList:", ^ { - SDLKeyboardProperties *testStruct = [[SDLKeyboardProperties alloc] initWithLanguage:testLanguage keyboardLayout:testLayout keypressMode:testMode limitedCharacterList:testLimitedCharacterList autoCompleteList:testAutoCompleteList]; - expect(testStruct.language).to(equal(testLanguage)); - expect(testStruct.keyboardLayout).to(equal(testLayout)); - expect(testStruct.keypressMode).to(equal(testMode)); - expect(testStruct.limitedCharacterList).to(equal(testLimitedCharacterList)); - expect(testStruct.autoCompleteList).to(equal(testAutoCompleteList)); + context(@"initWithLanguage:keyboardLayout:keypressMode:limitedCharacterList:autoCompleteList:", ^{ + beforeEach(^{ #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" - expect(testStruct.autoCompleteText).to(beNil()); + testStruct = [[SDLKeyboardProperties alloc] initWithLanguage:testLanguage keyboardLayout:testLayout keypressMode:testMode limitedCharacterList:testLimitedCharacterList autoCompleteList:testAutoCompleteList]; #pragma clang diagnostic pop + }); + + it(@"should be set properly", ^{ + expect(testStruct.language).to(equal(testLanguage)); + expect(testStruct.keyboardLayout).to(equal(testLayout)); + expect(testStruct.keypressMode).to(equal(testMode)); + expect(testStruct.limitedCharacterList).to(equal(testLimitedCharacterList)); + expect(testStruct.autoCompleteList).to(equal(testAutoCompleteList)); + expect(testStruct.maskInputCharacters).to(beNil()); + expect(testStruct.customKeys).to(beNil()); +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + expect(testStruct.autoCompleteText).to(beNil()); +#pragma clang diagnostic pop + }); }); - - it(@"Should return nil if not set", ^ { - SDLKeyboardProperties* testStruct = [[SDLKeyboardProperties alloc] init]; - - expect(testStruct.language).to(beNil()); - expect(testStruct.keyboardLayout).to(beNil()); - expect(testStruct.keypressMode).to(beNil()); - expect(testStruct.limitedCharacterList).to(beNil()); - expect(testStruct.autoCompleteList).to(beNil()); + + context(@"initWithLanguage:keyboardLayout:keypressMode:limitedCharacterList:autoCompleteList:maskInputCharacters:customKeys:", ^{ + beforeEach(^{ + testStruct = [[SDLKeyboardProperties alloc] initWithLanguage:testLanguage keyboardLayout:testLayout keypressMode:testMode limitedCharacterList:testLimitedCharacterList autoCompleteList:testAutoCompleteList maskInputCharacters:maskInputCharacters customKeys:customKeys]; + }); + + it(@"should be set properly", ^{ + expect(testStruct.language).to(equal(testLanguage)); + expect(testStruct.keyboardLayout).to(equal(testLayout)); + expect(testStruct.keypressMode).to(equal(testMode)); + expect(testStruct.limitedCharacterList).to(equal(testLimitedCharacterList)); + expect(testStruct.autoCompleteList).to(equal(testAutoCompleteList)); + expect(testStruct.maskInputCharacters).to(equal(maskInputCharacters)); + expect(testStruct.customKeys).to(equal(customKeys)); #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" - expect(testStruct.autoCompleteText).to(beNil()); + expect(testStruct.autoCompleteText).to(beNil()); #pragma clang diagnostic pop + }); }); }); diff --git a/SmartDeviceLinkTests/RPCSpecs/StructSpecs/SDLMenuParamsSpec.m b/SmartDeviceLinkTests/RPCSpecs/StructSpecs/SDLMenuParamsSpec.m index d0a63bae5..194b47058 100644 --- a/SmartDeviceLinkTests/RPCSpecs/StructSpecs/SDLMenuParamsSpec.m +++ b/SmartDeviceLinkTests/RPCSpecs/StructSpecs/SDLMenuParamsSpec.m @@ -9,6 +9,7 @@ #import <Nimble/Nimble.h> #import "SDLMenuParams.h" +#import "NSMutableDictionary+Store.h" #import "SDLRPCParameterNames.h" QuickSpecBegin(SDLMenuParamsSpec) @@ -17,6 +18,8 @@ describe(@"Initialization tests", ^{ __block UInt32 testParentId = 504320489; __block UInt16 testPosition = testPosition; __block NSString *testMenuName = @"Test Menu"; + __block NSString *testSecondaryText = @"Test text 2"; + __block NSString *testTertiaryText = @"Test text 3"; it(@"should properly initialize init", ^{ SDLMenuParams* testStruct = [[SDLMenuParams alloc] init]; @@ -24,17 +27,23 @@ describe(@"Initialization tests", ^{ expect(testStruct.parentID).to(beNil()); expect(testStruct.position).to(beNil()); expect(testStruct.menuName).to(beNil()); + expect(testStruct.secondaryText).to(beNil()); + expect(testStruct.tertiaryText).to(beNil()); }); it(@"should properly initialize initWithDictionary", ^{ NSDictionary *dict = @{SDLRPCParameterNameParentID:@(testParentId), SDLRPCParameterNamePosition:@(testPosition), - SDLRPCParameterNameMenuName:testMenuName}; + SDLRPCParameterNameMenuName:testMenuName, + SDLRPCParameterNameSecondaryText:testSecondaryText, + SDLRPCParameterNameTertiaryText:testTertiaryText}; SDLMenuParams* testStruct = [[SDLMenuParams alloc] initWithDictionary:dict]; expect(testStruct.parentID).to(equal(@(testParentId))); expect(testStruct.position).to(equal(@(testPosition))); expect(testStruct.menuName).to(equal(testMenuName)); + expect(testStruct.secondaryText).to(equal(testSecondaryText)); + expect(testStruct.tertiaryText).to(equal(testTertiaryText)); }); it(@"should properly initialize initWithMenuName", ^{ @@ -46,12 +55,25 @@ describe(@"Initialization tests", ^{ }); it(@"should properly initialize initWithMenuName:parentId:position:", ^{ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" SDLMenuParams* testStruct = [[SDLMenuParams alloc] initWithMenuName:testMenuName parentId:testParentId position:testPosition]; +#pragma clang diagnostic pop expect(testStruct.parentID).to(equal(@(testParentId))); expect(testStruct.position).to(equal(@(testPosition))); expect(testStruct.menuName).to(equal(testMenuName)); }); + + it(@"should properly initialize initWithMenuName:parentID:position:secondaryText:tertiaryText:", ^{ + SDLMenuParams* testStruct = [[SDLMenuParams alloc] initWithMenuName:testMenuName parentID:[[NSNumber alloc] initWithInt:testParentId] position:[[NSNumber alloc] initWithInt:testPosition] secondaryText:testSecondaryText tertiaryText:testTertiaryText]; + + expect(testStruct.parentID).to(equal(@(testParentId))); + expect(testStruct.position).to(equal(@(testPosition))); + expect(testStruct.menuName).to(equal(testMenuName)); + expect(testStruct.secondaryText).to(equal(testSecondaryText)); + expect(testStruct.tertiaryText).to(equal(testTertiaryText)); + }); }); describe(@"Getter/Setter Tests", ^ { diff --git a/SmartDeviceLinkTests/RPCSpecs/StructSpecs/SDLWindowCapabilitySpec.m b/SmartDeviceLinkTests/RPCSpecs/StructSpecs/SDLWindowCapabilitySpec.m index e8c2514b4..ee5d34ef5 100644 --- a/SmartDeviceLinkTests/RPCSpecs/StructSpecs/SDLWindowCapabilitySpec.m +++ b/SmartDeviceLinkTests/RPCSpecs/StructSpecs/SDLWindowCapabilitySpec.m @@ -5,16 +5,18 @@ #import <Quick/Quick.h> #import <Nimble/Nimble.h> -#import "SDLWindowCapability.h" - #import "SDLButtonCapabilities.h" #import "SDLDynamicUpdateCapabilities.h" #import "SDLImageField.h" #import "SDLImageType.h" +#import "SDLKeyboardCapabilities.h" +#import "SDLKeyboardLayoutCapability.h" +#import "SDLKeyboardProperties.h" #import "SDLRPCParameterNames.h" #import "SDLSoftButtonCapabilities.h" #import "SDLTextField.h" #import "SDLTextFieldName.h" +#import "SDLWindowCapability+ScreenManagerExtensions.h" QuickSpecBegin(SDLWindowCapabilitySpec) @@ -30,89 +32,253 @@ __block NSString *testImageName = nil; __block NSString *testTemplateAvailable = nil; __block SDLMenuLayout testMenuLayout = SDLMenuLayoutTiles; __block SDLDynamicUpdateCapabilities *testDynamicUpdates = nil; +__block NSArray<SDLTextField *> *textFields = nil; +__block NSArray<SDLImageField *> *imageFields = nil; +__block NSArray<SDLButtonCapabilities *> *buttonCapabilities = nil; +__block SDLKeyboardCapabilities *keyboardCapabilities = nil; +__block id windowID = nil; +__block id numCustomPresetsAvailable = nil; +__block NSArray<SDLImageType> *imageTypeSupported = nil; +__block NSArray<NSString *> *templatesAvailable = nil; +__block NSArray<SDLSoftButtonCapabilities *> *softButtonCapabilities = nil; +__block NSArray<SDLMenuLayout> *menuLayoutsAvailable = nil; -describe(@"Getter/Setter Tests", ^ { +describe(@"getter/setter tests", ^{ beforeEach(^{ testImageType = SDLImageTypeDynamic; testTextName = @"test Text field"; testImageName = @"test Image field"; - + testTextField = [[SDLTextField alloc] init]; testTextField.name = SDLTextFieldNameTertiaryText; testImageField = [[SDLImageField alloc] init]; testImageField.name = testImageName; - + testButtonCapabilities = [[SDLButtonCapabilities alloc] init]; testButtonCapabilities.name = SDLButtonNameOk; testButtonCapabilities.shortPressAvailable = @YES; testButtonCapabilities.longPressAvailable = @YES; testButtonCapabilities.upDownAvailable = @YES; - + testSoftButtonsCapabilities = [[SDLSoftButtonCapabilities alloc] init]; testSoftButtonsCapabilities.imageSupported = @YES; testTemplateAvailable = @"myTemplate"; testDynamicUpdates = [[SDLDynamicUpdateCapabilities alloc] initWithSupportedDynamicImageFieldNames:@[SDLImageFieldNameSubMenuIcon] supportsDynamicSubMenus:@YES]; + + textFields = @[testTextField]; + imageFields = @[testImageField]; + buttonCapabilities = @[testButtonCapabilities]; + keyboardCapabilities = [[SDLKeyboardCapabilities alloc] init]; + windowID = @444; + numCustomPresetsAvailable = @10; + imageTypeSupported = @[testImageType]; + templatesAvailable = @[testTemplateAvailable]; + softButtonCapabilities = @[testSoftButtonsCapabilities]; + menuLayoutsAvailable = @[testMenuLayout]; }); - - it(@"Should set and get correctly", ^ { - testStruct = [[SDLWindowCapability alloc] init]; - testStruct.windowID = @444; - testStruct.numCustomPresetsAvailable = @10; - testStruct.textFields = @[testTextField]; - testStruct.imageFields = @[testImageField]; - testStruct.imageTypeSupported = @[testImageType]; - testStruct.buttonCapabilities = @[testButtonCapabilities]; - testStruct.softButtonCapabilities = @[testSoftButtonsCapabilities]; - testStruct.menuLayoutsAvailable = @[testMenuLayout]; - testStruct.templatesAvailable = @[testTemplateAvailable]; - testStruct.dynamicUpdateCapabilities = testDynamicUpdates; - - expect(testStruct.windowID).to(equal(@444)); - expect(testStruct.textFields.firstObject.name).to(equal(SDLTextFieldNameTertiaryText)); - expect(testStruct.imageFields.firstObject.name).to(equal(testImageName)); - expect(testStruct.numCustomPresetsAvailable).to(equal(@10)); - expect(testStruct.buttonCapabilities.firstObject.name).to(equal(SDLButtonNameOk)); - expect(testStruct.buttonCapabilities.firstObject.shortPressAvailable).to(equal(@YES)); - expect(testStruct.buttonCapabilities.firstObject.longPressAvailable).to(equal(@YES)); - expect(testStruct.buttonCapabilities.firstObject.name).to(equal(SDLButtonNameOk)); - expect(testStruct.softButtonCapabilities.firstObject.imageSupported).to(equal(@YES)); - expect(testStruct.menuLayoutsAvailable).to(equal(@[testMenuLayout])); - expect(testStruct.templatesAvailable).to(equal(@[testTemplateAvailable])); - expect(testStruct.dynamicUpdateCapabilities).to(equal(testDynamicUpdates)); + + context(@"init", ^{ + beforeEach(^{ + testStruct = [[SDLWindowCapability alloc] init]; + }); + + it(@"expect all properties to be nil", ^{ + expect(testStruct.windowID).to(beNil()); + expect(testStruct.textFields.firstObject.name).to(beNil()); + expect(testStruct.imageFields.firstObject.name).to(beNil()); + expect(testStruct.numCustomPresetsAvailable).to(beNil()); + expect(testStruct.buttonCapabilities.firstObject.name).to(beNil()); + expect(testStruct.buttonCapabilities.firstObject.shortPressAvailable).to(beNil()); + expect(testStruct.buttonCapabilities.firstObject.longPressAvailable).to(beNil()); + expect(testStruct.buttonCapabilities.firstObject.name).to(beNil()); + expect(testStruct.softButtonCapabilities.firstObject.imageSupported).to(beNil()); + expect(testStruct.menuLayoutsAvailable).to(beNil()); + expect(testStruct.templatesAvailable).to(beNil()); + expect(testStruct.dynamicUpdateCapabilities).to(beNil()); + expect(testStruct.imageTypeSupported).to(beNil()); + expect(testStruct.keyboardCapabilities).to(beNil()); + }); + }); + + context(@"init and assign", ^{ + beforeEach(^{ + testStruct = [[SDLWindowCapability alloc] init]; + testStruct.windowID = windowID; + testStruct.numCustomPresetsAvailable = numCustomPresetsAvailable; + testStruct.textFields = @[testTextField]; + testStruct.imageFields = @[testImageField]; + testStruct.imageTypeSupported = @[testImageType]; + testStruct.buttonCapabilities = @[testButtonCapabilities]; + testStruct.softButtonCapabilities = @[testSoftButtonsCapabilities]; + testStruct.menuLayoutsAvailable = @[testMenuLayout]; + testStruct.templatesAvailable = @[testTemplateAvailable]; + testStruct.dynamicUpdateCapabilities = testDynamicUpdates; + testStruct.keyboardCapabilities = keyboardCapabilities; + }); + + it(@"expect all properties to be set properly", ^{ + expect(testStruct.windowID).to(equal(windowID)); + expect(testStruct.textFields.firstObject.name).to(equal(SDLTextFieldNameTertiaryText)); + expect(testStruct.imageFields.firstObject.name).to(equal(testImageName)); + expect(testStruct.numCustomPresetsAvailable).to(equal(numCustomPresetsAvailable)); + expect(testStruct.buttonCapabilities.firstObject.name).to(equal(SDLButtonNameOk)); + expect(testStruct.buttonCapabilities.firstObject.shortPressAvailable).to(equal(@YES)); + expect(testStruct.buttonCapabilities.firstObject.longPressAvailable).to(equal(@YES)); + expect(testStruct.buttonCapabilities.firstObject.name).to(equal(SDLButtonNameOk)); + expect(testStruct.softButtonCapabilities.firstObject.imageSupported).to(equal(@YES)); + expect(testStruct.menuLayoutsAvailable).to(equal(@[testMenuLayout])); + expect(testStruct.templatesAvailable).to(equal(@[testTemplateAvailable])); + expect(testStruct.dynamicUpdateCapabilities).to(equal(testDynamicUpdates)); + expect(testStruct.imageTypeSupported).to(equal(@[testImageType])); + expect(testStruct.keyboardCapabilities).to(equal(keyboardCapabilities)); + }); + }); + + context(@"initWithWindowID:textFields:imageFields:imageTypeSupported:templatesAvailable:numCustomPresetsAvailable:buttonCapabilities:softButtonCapabilities:menuLayoutsAvailable:dynamicUpdateCapabilities:", ^{ + beforeEach(^{ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + testStruct = [[SDLWindowCapability alloc] initWithWindowID:windowID textFields:textFields imageFields:imageFields imageTypeSupported:imageTypeSupported templatesAvailable:templatesAvailable numCustomPresetsAvailable:numCustomPresetsAvailable buttonCapabilities:buttonCapabilities softButtonCapabilities:softButtonCapabilities menuLayoutsAvailable:menuLayoutsAvailable dynamicUpdateCapabilities:testDynamicUpdates]; +#pragma clang diagnostic pop + }); + + it(@"expect all properties to be set properly", ^{ + expect(testStruct.windowID).to(equal(windowID)); + expect(testStruct.textFields.firstObject.name).to(equal(SDLTextFieldNameTertiaryText)); + expect(testStruct.imageFields.firstObject.name).to(equal(testImageName)); + expect(testStruct.numCustomPresetsAvailable).to(equal(numCustomPresetsAvailable)); + expect(testStruct.buttonCapabilities.firstObject.name).to(equal(SDLButtonNameOk)); + expect(testStruct.buttonCapabilities.firstObject.shortPressAvailable).to(equal(@YES)); + expect(testStruct.buttonCapabilities.firstObject.longPressAvailable).to(equal(@YES)); + expect(testStruct.buttonCapabilities.firstObject.name).to(equal(SDLButtonNameOk)); + expect(testStruct.softButtonCapabilities.firstObject.imageSupported).to(equal(@YES)); + expect(testStruct.menuLayoutsAvailable).to(equal(@[testMenuLayout])); + expect(testStruct.templatesAvailable).to(equal(@[testTemplateAvailable])); + expect(testStruct.dynamicUpdateCapabilities).to(equal(testDynamicUpdates)); + expect(testStruct.imageTypeSupported).to(equal(@[testImageType])); + expect(testStruct.keyboardCapabilities).to(beNil()); + }); + }); + + context(@"initWithWindowID:textFields:imageFields:imageTypeSupported:templatesAvailable:numCustomPresetsAvailable:buttonCapabilities:softButtonCapabilities:menuLayoutsAvailable:dynamicUpdateCapabilities:keyboardCapabilities:", ^{ + beforeEach(^{ + testStruct = [[SDLWindowCapability alloc] initWithWindowID:windowID textFields:textFields imageFields:imageFields imageTypeSupported:imageTypeSupported templatesAvailable:templatesAvailable numCustomPresetsAvailable:numCustomPresetsAvailable buttonCapabilities:buttonCapabilities softButtonCapabilities:softButtonCapabilities menuLayoutsAvailable:menuLayoutsAvailable dynamicUpdateCapabilities:testDynamicUpdates keyboardCapabilities:keyboardCapabilities]; + }); + + it(@"expect all properties to be set properly", ^{ + expect(testStruct.windowID).to(equal(windowID)); + expect(testStruct.textFields.firstObject.name).to(equal(SDLTextFieldNameTertiaryText)); + expect(testStruct.imageFields.firstObject.name).to(equal(testImageName)); + expect(testStruct.numCustomPresetsAvailable).to(equal(numCustomPresetsAvailable)); + expect(testStruct.buttonCapabilities.firstObject.name).to(equal(SDLButtonNameOk)); + expect(testStruct.buttonCapabilities.firstObject.shortPressAvailable).to(equal(@YES)); + expect(testStruct.buttonCapabilities.firstObject.longPressAvailable).to(equal(@YES)); + expect(testStruct.buttonCapabilities.firstObject.name).to(equal(SDLButtonNameOk)); + expect(testStruct.softButtonCapabilities.firstObject.imageSupported).to(equal(@YES)); + expect(testStruct.menuLayoutsAvailable).to(equal(@[testMenuLayout])); + expect(testStruct.templatesAvailable).to(equal(@[testTemplateAvailable])); + expect(testStruct.dynamicUpdateCapabilities).to(equal(testDynamicUpdates)); + expect(testStruct.imageTypeSupported).to(equal(@[testImageType])); + expect(testStruct.keyboardCapabilities).to(equal(keyboardCapabilities)); + }); }); }); -describe(@"initializing with ", ^{ +describe(@"creating a valid keyboard configuration based on keyboard capabilities", ^{ + UInt8 numConfigurableKeys = 7; + beforeEach(^{ - testStruct = [[SDLWindowCapability alloc] initWithWindowID:@444 textFields:@[testTextField] imageFields:@[testImageField] imageTypeSupported:@[testImageType] templatesAvailable:@[testTemplateAvailable] numCustomPresetsAvailable:@10 buttonCapabilities:@[testButtonCapabilities] softButtonCapabilities:@[testSoftButtonsCapabilities] menuLayoutsAvailable:@[testMenuLayout] dynamicUpdateCapabilities:testDynamicUpdates]; + testStruct = [[SDLWindowCapability alloc] init]; + testStruct.keyboardCapabilities = nil; }); - it(@"Should set and get correctly", ^ { - testStruct = [[SDLWindowCapability alloc] init]; - testStruct.windowID = @444; - testStruct.numCustomPresetsAvailable = @10; - testStruct.textFields = @[testTextField]; - testStruct.imageFields = @[testImageField]; - testStruct.imageTypeSupported = @[testImageType]; - testStruct.buttonCapabilities = @[testButtonCapabilities]; - testStruct.softButtonCapabilities = @[testSoftButtonsCapabilities]; - testStruct.menuLayoutsAvailable = @[testMenuLayout]; - testStruct.templatesAvailable = @[testTemplateAvailable]; - testStruct.dynamicUpdateCapabilities = testDynamicUpdates; - - expect(testStruct.windowID).to(equal(@444)); - expect(testStruct.textFields.firstObject.name).to(equal(SDLTextFieldNameTertiaryText)); - expect(testStruct.imageFields.firstObject.name).to(equal(testImageName)); - expect(testStruct.numCustomPresetsAvailable).to(equal(@10)); - expect(testStruct.buttonCapabilities.firstObject.name).to(equal(SDLButtonNameOk)); - expect(testStruct.buttonCapabilities.firstObject.shortPressAvailable).to(equal(@YES)); - expect(testStruct.buttonCapabilities.firstObject.longPressAvailable).to(equal(@YES)); - expect(testStruct.buttonCapabilities.firstObject.name).to(equal(SDLButtonNameOk)); - expect(testStruct.softButtonCapabilities.firstObject.imageSupported).to(equal(@YES)); - expect(testStruct.menuLayoutsAvailable).to(equal(@[testMenuLayout])); - expect(testStruct.templatesAvailable).to(equal(@[testTemplateAvailable])); - expect(testStruct.dynamicUpdateCapabilities).to(equal(testDynamicUpdates)); + context(@"when keyboardCapabilities is nil or empty", ^{ + it(@"result should be nil when the argument is nil", ^{ + SDLKeyboardProperties *resultProperties = [testStruct createValidKeyboardConfigurationBasedOnKeyboardCapabilitiesFromConfiguration:nil]; + expect(resultProperties).to(beNil()); + }); + + it(@"result should be equal to the argument when keyboardLayout is nil", ^{ + SDLKeyboardProperties *testKeyboardProperties = [[SDLKeyboardProperties alloc] init]; + testKeyboardProperties.maskInputCharacters = SDLKeyboardInputMaskUserChoiceInputKeyMask; + SDLKeyboardProperties *resultProperties = [testStruct createValidKeyboardConfigurationBasedOnKeyboardCapabilitiesFromConfiguration:testKeyboardProperties]; + expect(resultProperties).notTo(beNil()); + expect(resultProperties).to(equal(testKeyboardProperties)); + expect(resultProperties.maskInputCharacters).to(equal(SDLKeyboardInputMaskUserChoiceInputKeyMask)); + }); + + it(@"result should be nil when the argument is not nil and keyboardCapabilities is empty", ^{ + testStruct.keyboardCapabilities = [[SDLKeyboardCapabilities alloc] init]; + SDLKeyboardProperties *testKeyboardProperties = [[SDLKeyboardProperties alloc] init]; + testKeyboardProperties.keyboardLayout = SDLKeyboardLayoutNumeric; + testKeyboardProperties.maskInputCharacters = SDLKeyboardInputMaskUserChoiceInputKeyMask; + SDLKeyboardProperties *resultProperties = [testStruct createValidKeyboardConfigurationBasedOnKeyboardCapabilitiesFromConfiguration:testKeyboardProperties]; + expect(resultProperties).to(beNil()); + }); + + context(@"when keyboardCapabilities is not empty", ^{ + __block SDLKeyboardProperties *testKeyboardProperties = nil; + __block SDLKeyboardCapabilities *keyboardCapabilities = nil; + __block NSArray *testCustomKeysLong = nil; + + beforeEach(^{ + // create a long array that contains more custom keys than <numConfigurableKeys> + testCustomKeysLong = [@"a ä æ b c d e ê f j h i j k l m n o p q r s ß t u v w x y z" componentsSeparatedByString:@" "]; + NSArray *arrayLayouts = @[SDLKeyboardLayoutQWERTY, SDLKeyboardLayoutQWERTZ, SDLKeyboardLayoutAZERTY, SDLKeyboardLayoutNumeric]; + NSMutableArray *arrayLayoutCapability = [[NSMutableArray alloc] initWithCapacity:arrayLayouts.count]; + for (SDLKeyboardLayout layout in arrayLayouts) { + SDLKeyboardLayoutCapability *layoutCapability = [[SDLKeyboardLayoutCapability alloc] initWithKeyboardLayout:layout numConfigurableKeys:numConfigurableKeys]; + [arrayLayoutCapability addObject:layoutCapability]; + } + keyboardCapabilities = [[SDLKeyboardCapabilities alloc] init]; + keyboardCapabilities.supportedKeyboards = arrayLayoutCapability; + testStruct.keyboardCapabilities = keyboardCapabilities; + + testKeyboardProperties = [[SDLKeyboardProperties alloc] init]; + testKeyboardProperties.keyboardLayout = SDLKeyboardLayoutNumeric; + // create custom keys array longer than <numConfigurableKeys> + testKeyboardProperties.customKeys = testCustomKeysLong; + testKeyboardProperties.maskInputCharacters = SDLKeyboardInputMaskUserChoiceInputKeyMask; + testKeyboardProperties.keyboardLayout = SDLKeyboardLayoutAZERTY; + }); + + it(@"maskInputCharacters should not be nil when maskInputCharactersSupported = YES", ^{ + keyboardCapabilities.maskInputCharactersSupported = @YES; + SDLKeyboardProperties *resultProperties = [testStruct createValidKeyboardConfigurationBasedOnKeyboardCapabilitiesFromConfiguration:testKeyboardProperties]; + expect(resultProperties).notTo(beNil()); + expect(resultProperties).notTo(equal(testKeyboardProperties)); + expect(resultProperties.customKeys.count).to(equal(numConfigurableKeys)); + expect(resultProperties.maskInputCharacters).to(equal(SDLKeyboardInputMaskUserChoiceInputKeyMask)); + }); + + it(@"maskInputCharacters should be nil when maskInputCharactersSupported = NO", ^{ + keyboardCapabilities.maskInputCharactersSupported = @NO; + SDLKeyboardProperties *resultProperties = [testStruct createValidKeyboardConfigurationBasedOnKeyboardCapabilitiesFromConfiguration:testKeyboardProperties]; + expect(resultProperties).notTo(beNil()); + expect(resultProperties).notTo(equal(testKeyboardProperties)); + expect(resultProperties.customKeys.count).to(equal(numConfigurableKeys)); + expect(resultProperties.maskInputCharacters).to(beNil()); + }); + + it(@"customKeys should be trimmed to contain <numConfigurableKeys> items", ^{ + NSArray *expectedCustomKeys = [testCustomKeysLong subarrayWithRange:NSMakeRange(0, numConfigurableKeys)]; + testKeyboardProperties.customKeys = testCustomKeysLong; + SDLKeyboardProperties *resultProperties = [testStruct createValidKeyboardConfigurationBasedOnKeyboardCapabilitiesFromConfiguration:testKeyboardProperties]; + expect(resultProperties).notTo(beNil()); + expect(resultProperties.customKeys.count).to(equal(numConfigurableKeys)); + expect(resultProperties.customKeys).to(equal(expectedCustomKeys)); + }); + + it(@"customKeys should not be trimmed and should be equal to the initial array", ^{ + NSArray *testCustomKeys = [testCustomKeysLong subarrayWithRange:NSMakeRange(0, numConfigurableKeys)]; + testKeyboardProperties.customKeys = testCustomKeys; + SDLKeyboardProperties *resultProperties = [testStruct createValidKeyboardConfigurationBasedOnKeyboardCapabilitiesFromConfiguration:testKeyboardProperties]; + expect(resultProperties).notTo(beNil()); + expect(resultProperties.customKeys.count).to(equal(numConfigurableKeys)); + expect(resultProperties.customKeys).to(equal(testCustomKeys)); + }); + }); }); }); diff --git a/SmartDeviceLinkTests/SDLMenuUpdateAlgorithmSpec.m b/SmartDeviceLinkTests/SDLMenuUpdateAlgorithmSpec.m index a8a666fb6..9c554c02c 100644 --- a/SmartDeviceLinkTests/SDLMenuUpdateAlgorithmSpec.m +++ b/SmartDeviceLinkTests/SDLMenuUpdateAlgorithmSpec.m @@ -42,19 +42,19 @@ describe(@"menuUpdateAlgorithm", ^{ // 0 = Delete 1 = Add 2 = Keep describe(@"compare old and new menu cells", ^{ beforeEach(^{ - oldCell1 = [[SDLMenuCell alloc] initWithTitle:@"Cell 1" icon:nil voiceCommands:nil handler:^(SDLTriggerSource _Nonnull triggerSource) {}]; - oldCell2 = [[SDLMenuCell alloc] initWithTitle:@"Cell 2" icon:nil voiceCommands:nil handler:^(SDLTriggerSource _Nonnull triggerSource) {}]; - oldCell3 = [[SDLMenuCell alloc] initWithTitle:@"Cell 3" icon:nil voiceCommands:nil handler:^(SDLTriggerSource _Nonnull triggerSource) {}]; - oldCell4 = [[SDLMenuCell alloc] initWithTitle:@"Cell 4" icon:nil voiceCommands:nil handler:^(SDLTriggerSource _Nonnull triggerSource) {}]; - oldCell5 = [[SDLMenuCell alloc] initWithTitle:@"Cell 5" icon:nil voiceCommands:nil handler:^(SDLTriggerSource _Nonnull triggerSource) {}]; - oldCell6 = [[SDLMenuCell alloc] initWithTitle:@"Cell 6" icon:nil voiceCommands:nil handler:^(SDLTriggerSource _Nonnull triggerSource) {}]; - - newCell1 = [[SDLMenuCell alloc] initWithTitle:@"Cell 1" icon:nil voiceCommands:nil handler:^(SDLTriggerSource _Nonnull triggerSource) {}]; - newCell2 = [[SDLMenuCell alloc] initWithTitle:@"Cell 2" icon:nil voiceCommands:nil handler:^(SDLTriggerSource _Nonnull triggerSource) {}]; - newCell3 = [[SDLMenuCell alloc] initWithTitle:@"Cell 3" icon:nil voiceCommands:nil handler:^(SDLTriggerSource _Nonnull triggerSource) {}]; - newCell4 = [[SDLMenuCell alloc] initWithTitle:@"Cell 4" icon:nil voiceCommands:nil handler:^(SDLTriggerSource _Nonnull triggerSource) {}]; - newCell5 = [[SDLMenuCell alloc] initWithTitle:@"Cell 5" icon:nil voiceCommands:nil handler:^(SDLTriggerSource _Nonnull triggerSource) {}]; - newCell6 = [[SDLMenuCell alloc] initWithTitle:@"Cell 6" icon:nil voiceCommands:nil handler:^(SDLTriggerSource _Nonnull triggerSource) {}]; + oldCell1 = [[SDLMenuCell alloc] initWithTitle:@"Cell 1" icon:nil voiceCommands:nil secondaryText:nil tertiaryText:nil secondaryArtwork:nil handler:^(SDLTriggerSource _Nonnull triggerSource) {}]; + oldCell2 = [[SDLMenuCell alloc] initWithTitle:@"Cell 2" icon:nil voiceCommands:nil secondaryText:nil tertiaryText:nil secondaryArtwork:nil handler:^(SDLTriggerSource _Nonnull triggerSource) {}]; + oldCell3 = [[SDLMenuCell alloc] initWithTitle:@"Cell 3" icon:nil voiceCommands:nil secondaryText:nil tertiaryText:nil secondaryArtwork:nil handler:^(SDLTriggerSource _Nonnull triggerSource) {}]; + oldCell4 = [[SDLMenuCell alloc] initWithTitle:@"Cell 4" icon:nil voiceCommands:nil secondaryText:nil tertiaryText:nil secondaryArtwork:nil handler:^(SDLTriggerSource _Nonnull triggerSource) {}]; + oldCell5 = [[SDLMenuCell alloc] initWithTitle:@"Cell 5" icon:nil voiceCommands:nil secondaryText:nil tertiaryText:nil secondaryArtwork:nil handler:^(SDLTriggerSource _Nonnull triggerSource) {}]; + oldCell6 = [[SDLMenuCell alloc] initWithTitle:@"Cell 6" icon:nil voiceCommands:nil secondaryText:nil tertiaryText:nil secondaryArtwork:nil handler:^(SDLTriggerSource _Nonnull triggerSource) {}]; + + newCell1 = [[SDLMenuCell alloc] initWithTitle:@"Cell 1" icon:nil voiceCommands:nil secondaryText:nil tertiaryText:nil secondaryArtwork:nil handler:^(SDLTriggerSource _Nonnull triggerSource) {}]; + newCell2 = [[SDLMenuCell alloc] initWithTitle:@"Cell 2" icon:nil voiceCommands:nil secondaryText:nil tertiaryText:nil secondaryArtwork:nil handler:^(SDLTriggerSource _Nonnull triggerSource) {}]; + newCell3 = [[SDLMenuCell alloc] initWithTitle:@"Cell 3" icon:nil voiceCommands:nil secondaryText:nil tertiaryText:nil secondaryArtwork:nil handler:^(SDLTriggerSource _Nonnull triggerSource) {}]; + newCell4 = [[SDLMenuCell alloc] initWithTitle:@"Cell 4" icon:nil voiceCommands:nil secondaryText:nil tertiaryText:nil secondaryArtwork:nil handler:^(SDLTriggerSource _Nonnull triggerSource) {}]; + newCell5 = [[SDLMenuCell alloc] initWithTitle:@"Cell 5" icon:nil voiceCommands:nil secondaryText:nil tertiaryText:nil secondaryArtwork:nil handler:^(SDLTriggerSource _Nonnull triggerSource) {}]; + newCell6 = [[SDLMenuCell alloc] initWithTitle:@"Cell 6" icon:nil voiceCommands:nil secondaryText:nil tertiaryText:nil secondaryArtwork:nil handler:^(SDLTriggerSource _Nonnull triggerSource) {}]; }); it(@"should have a new menu status of 22221 and an old menu status of 2222 on best run", ^{ diff --git a/SmartDeviceLinkTests/SDLSystemCapabilityManagerSpec.m b/SmartDeviceLinkTests/SDLSystemCapabilityManagerSpec.m index 18747dbc7..df4842bd3 100644 --- a/SmartDeviceLinkTests/SDLSystemCapabilityManagerSpec.m +++ b/SmartDeviceLinkTests/SDLSystemCapabilityManagerSpec.m @@ -544,7 +544,7 @@ describe(@"System capability manager", ^{ it(@"should should save the capabilities", ^{ // All the text fields and image fields should be available - expect(testSystemCapabilityManager.defaultMainWindowCapability.textFields).to(haveCount(29)); + expect(testSystemCapabilityManager.defaultMainWindowCapability.textFields).to(haveCount(31)); expect(testSystemCapabilityManager.defaultMainWindowCapability.imageFields).to(haveCount(14)); }); }); diff --git a/generator/test/test_functions.py b/generator/test/test_functions.py index d2b885e21..ad4dcc6cb 100644 --- a/generator/test/test_functions.py +++ b/generator/test/test_functions.py @@ -68,7 +68,8 @@ class TestFunctionsProducer(TestCase): structs = { 'SoftButton': Struct(name='SoftButton', members={ 'image': Param(name='image', param_type=String(), since='1.0.0', description=['image description']), - 'ignore': Param(name='ignore', param_type=Struct(name='ignore'))}), + 'dayColorScheme': Param(name='dayColorScheme', param_type=Struct(name='TemplateColorScheme', description=[ + '\nA color scheme for all display layout templates.\n']))}), 'PresetBankCapabilities': Struct(name='PresetBankCapabilities', members={ 'availableHdChannelsAvailable': Param(name='availableHdChannelsAvailable', param_type=Boolean(), since='2.0.0', @@ -89,11 +90,8 @@ class TestFunctionsProducer(TestCase): self.producer.common_names(description=['availableHDChannelsAvailable description'], since='2.0.0', name='AvailableHdChannelsAvailable', origin='availableHdChannelsAvailable'), - self.producer.common_names(description=[], name='Ignore', origin='ignore', since=None), + self.producer.common_names(description=[], name='DayColorScheme', origin='dayColorScheme', since=None), self.producer.common_names(description=['image description'], name='Image', origin='image', since='1.0.0'), - self.producer.common_names(description=[], name='PresetBankCapabilities', origin='PresetBankCapabilities', - since=None), - self.producer.common_names(description=[], name='SoftButton', origin='SoftButton', since=None), self.producer.common_names(description=['syncMsgVersion description'], name='SdlMsgVersion', origin='syncMsgVersion', since='3.5.0')] actual = self.producer.get_simple_params(functions, structs) diff --git a/generator/transformers/functions_producer.py b/generator/transformers/functions_producer.py index 73091fe12..eaf84bf55 100644 --- a/generator/transformers/functions_producer.py +++ b/generator/transformers/functions_producer.py @@ -88,17 +88,15 @@ class FunctionsProducer(InterfaceProducerCommon): """ origin = element.name name = self._replace_sync(element.name) - # if isinstance(element.param_type, (Integer, Float, Boolean, String)): return {name: self.common_names(**{ 'name': self.title(name), 'origin': origin, 'description': self.extract_description(element.description), 'since': element.since})} - # return OrderedDict() def get_simple_params(self, functions: dict, structs: dict) -> dict: """ - Standalone method used for preparing SDLRPCParameterNames collection ready to be applied to Jinja2 template + Creates a list of all parameter names used in functions and structs. This list is used by a Jinja2 template to generate the SDLRPCParameterNames class. :param functions: collection with all functions from initial Model :param structs: collection with all structs from initial Model :return: collection with transformed element ready to be applied to Jinja2 template @@ -110,8 +108,8 @@ class FunctionsProducer(InterfaceProducerCommon): render.update(self.evaluate(param)) for struct in structs.values(): - render.update(self.evaluate(struct)) for param in struct.members.values(): render.update(self.evaluate(param)) + unique = dict(zip(list(map(lambda l: l.name, render.values())), render.values())) return {'params': sorted(unique.values(), key=lambda a: a.name)} |