// // HDLSiriSceneListViewController.m // HdlSmartIoT // // Created by 陈嘉乐 on 2021/11/17. // #import "HDLSiriSceneListViewController.h" #import #import #import "HDLRunSceneIntent.h" //上方“设置Custom Intents”图中右边箭头指的“Class Name” #import "HDLSiriSceneListCell.h" #import "HDLSectionHeaderView.h" #import "HDLSceneSiri.h" #import "TopBarView.h" #import "HDLSiriShortcutModel.h" NSString * const HDLSiriSceneListCellIdentifier = @"HDLSiriSceneListCellIdentifier"; @interface HDLSiriSceneListViewController () /// TopBarView @property (nonatomic, strong) TopBarView *topBarView; @property (copy,nonatomic) NSArray *siriShortcutList; @end @implementation HDLSiriSceneListViewController - (instancetype)init { if (self = [super init]) { _tableViewStyle = UITableViewStylePlain; } return self; } - (void)viewDidLoad { [super viewDidLoad]; [self.navigationController setNavigationBarHidden:YES animated:YES]; self.view.backgroundColor = HEXCOLORA(0xF2F3F7,1.0); [self initView]; // Do any additional setup after loading the view. } -(void)initLlanguage{ NSString *languageName = [[[NSUserDefaults standardUserDefaults] objectForKey:@"AppleLanguages"] objectAtIndex:0]; // 简体中文 if ([languageName rangeOfString:@"zh-Hans"].location != NSNotFound) { //标题 if(self.titleName == nil || [self.titleName isEqual:@""]){ self.titleName = @"Siri快捷指令"; } }else{ //标题 if(self.titleName == nil || [self.titleName isEqual:@""]){ self.titleName = @"Siri Shortcuts"; } } } /// initView - (void)initView{ [self initLlanguage]; [self setTopBarViewWithTitle:self.titleName]; [self initTableView]; [self refreshSiri]; } #pragma mark - TopBarView - (TopBarView *)topBarView{ if (!_topBarView) { _topBarView = [[TopBarView alloc] initWithFrame: CGRectMake(0, 0, APP_SCREEN_WIDTH, 40)]; [_topBarView.backButton addTarget:self action:@selector(goBack) forControlEvents:UIControlEventTouchUpInside]; } return _topBarView; } //设置标题和返回按钮 - (void)setTopBarViewWithTitle:(NSString *)title{ [self.view addSubview:self.topBarView]; self.topBarView.backgroundColor = HEXCOLORA(0xF7F7F7, 1.0); self.topBarView.titleLabel.text = title; } //返回 - (void)goBack{ if ([self.navigationController.viewControllers indexOfObject:self] == 0) { [self dismissViewControllerAnimated:YES completion:nil]; } else { [self.navigationController popViewControllerAnimated:YES]; } } #pragma NSMutableArray - (NSMutableArray *)dataSource { if (!_dataSource) { _dataSource = [NSMutableArray new]; } return _dataSource; } #pragma mark - UITableView - (UITableView *)tableView { if (!_tableView) { _tableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 0, APP_SCREEN_WIDTH, 0) style:self.tableViewStyle]; // _tableView.backgroundColor = COLOR_MAIN_BACKGROUND; _tableView.backgroundColor = UIColor.clearColor; _tableView.showsVerticalScrollIndicator = NO; _tableView.showsHorizontalScrollIndicator = NO; _tableView.separatorStyle = NO; _tableView.contentInset = UIEdgeInsetsMake(0, 0, 0, 0); _tableView.dataSource = self; _tableView.delegate = self; } return _tableView; } - (void)initTableView{ self.tableView.frame = CGRectMake(0, APP_TOP_BAR_HEIGHT , APP_SCREEN_WIDTH, APP_VISIBLE_HEIGHT - APP_TAB_BOTTOM_HEIGHT); // self.tableView.backgroundColor = HEXCOLORA(0xF7F7FC,1.0); [self.view addSubview:self.tableView]; // [self.tableView reloadData]; } #pragma mark - 让tableView的每个section的headerview随tableview一起滚动 - (void)scrollViewDidScroll:(UIScrollView *)scrollView { if (scrollView == self.tableView) { CGFloat sectionHeaderHeight = 65.0f; if (scrollView.contentOffset.y<=sectionHeaderHeight&&scrollView.contentOffset.y>=0) { scrollView.contentInset = UIEdgeInsetsMake(-scrollView.contentOffset.y, 0, 0, 0); } else if (scrollView.contentOffset.y>=sectionHeaderHeight) { scrollView.contentInset = UIEdgeInsetsMake(-sectionHeaderHeight, 0, 0, 0); } } } #pragma mark - UITableViewDataSourceXW - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { return self.dataSource.count; } - (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section{ return 65.0f; } - (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section{ HDLSectionHeaderView *view = [[HDLSectionHeaderView alloc]init]; HDLSiriShortcutModel *model = self.dataSource[section]; if(model){ view.titleLabel.text = model.title; view.messageLabel.text = model.content; } return view; } - (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section{ return 8.0f; } - (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section{ return [[UIView alloc]init]; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { HDLSiriShortcutModel *model = self.dataSource[section]; if(model && model.list){ return model.list.count; } return 0; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { HDLSiriSceneListCell *cell = [tableView dequeueReusableCellWithIdentifier:HDLSiriSceneListCellIdentifier]; if (cell == nil) { cell = [[HDLSiriSceneListCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:HDLSiriSceneListCellIdentifier]; } cell.homeId = self.homeId; HDLSiriControlModel *model = [self getModelWithNSIndexPath:indexPath]; if(model){ if (@available(iOS 12.0, *)) { HDLRunSceneIntent *intent = [self getSceneIntent: model.controlId]; [cell initModel:model intent:intent]; } } return cell; } #pragma mark - UITableViewDelegate - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { return 50; } - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { [tableView deselectRowAtIndexPath:indexPath animated:YES]; if (@available(iOS 12.0, *)) { HDLSiriControlModel *model = [self getModelWithNSIndexPath:indexPath]; if(model){ INVoiceShortcut *voiceShortcut = [self getSceneINVoiceShortcut:model.controlId]; [self addOrEditVoiceShortcut:voiceShortcut model:model]; } } } /// 根据NSIndexPath 获取model /// @param indexPath indexPath -(HDLSiriControlModel *)getModelWithNSIndexPath:(NSIndexPath *)indexPath { HDLSiriControlModel *model = nil; HDLSiriShortcutModel *ssModel = self.dataSource[indexPath.section]; if(ssModel && ssModel.list && (ssModel.list.count > indexPath.row)){ model = ssModel.list[indexPath.row]; } return model; } /// 添加或者编辑快捷指令 /// @param voiceShortcut 快捷指令 /// @param model 场景 -(void)addOrEditVoiceShortcut:(INVoiceShortcut *)voiceShortcut model:(HDLSiriControlModel*)model API_AVAILABLE(ios(12.0)){ if(voiceShortcut==nil){ //1.如果不存在则添加 INUIAddVoiceShortcutViewController *vc = [[INUIAddVoiceShortcutViewController alloc] initWithShortcut:[self getINShortcut:model]]; vc.delegate = self; if(@available(iOS 13.0, *)) { vc.modalPresentationStyle = UIModalPresentationOverFullScreen; } [self presentViewController:vc animated:YES completion:nil]; }else{ //2.存在则编辑 INUIEditVoiceShortcutViewController* vc = [[INUIEditVoiceShortcutViewController alloc] initWithVoiceShortcut:voiceShortcut]; vc.delegate = self; if(@available(iOS 13.0, *)) { vc.modalPresentationStyle = UIModalPresentationOverFullScreen; } [self presentViewController:vc animated:YES completion:nil]; } } - (INShortcut *) getINShortcut:(HDLSiriControlModel*)sceneModel API_AVAILABLE(ios(12.0)){ NSString *title = sceneModel.controlName; HDLRunSceneIntent *intent = [[HDLRunSceneIntent alloc] init]; intent.suggestedInvocationPhrase = title; //在Siri语音设置时显示的建议设置唤起文字 intent.controlId = sceneModel.controlId; intent.controlName = title; intent.homeId = self.homeId; intent.controlType = sceneModel.controlType; intent.controlJSONStr = sceneModel.controlJSONStr; intent.actionName = sceneModel.actionName; INShortcut *shortCut = [[INShortcut alloc] initWithIntent:intent]; return shortCut; } /// 根据场景ID或者之前配置过低快捷指令 /// @param controlId 唯一标识ID - (HDLRunSceneIntent*)getSceneIntent:(NSString *)controlId API_AVAILABLE(ios(12.0)){ HDLRunSceneIntent *intentFind = nil; for (INVoiceShortcut *voiceShortcut in self.siriShortcutList) { HDLRunSceneIntent *intent = (HDLRunSceneIntent *)voiceShortcut.shortcut.intent; if(intent){ if([intent.controlId isEqualToString:controlId]){ intentFind = intent; break; } } } return intentFind; } /// 根据场景ID或者之前配置过低快捷指令 /// @param controlId 唯一标识ID - (INVoiceShortcut*)getSceneINVoiceShortcut:(NSString *)controlId API_AVAILABLE(ios(12.0)){ INVoiceShortcut *voiceShortcutFind = nil; for (INVoiceShortcut *voiceShortcut in self.siriShortcutList) { HDLRunSceneIntent *intent = (HDLRunSceneIntent *)voiceShortcut.shortcut.intent; if(intent){ if([intent.controlId isEqualToString:controlId]){ voiceShortcutFind = voiceShortcut; break; } } } return voiceShortcutFind; } #pragma mark - refreshSiri - (BOOL)checkCurrentClass:(INVoiceShortcut*)voiceShortcut API_AVAILABLE(ios(12.0)){ return [voiceShortcut.shortcut.intent isKindOfClass:[HDLRunSceneIntent class]]; } /// refreshSiri - (void)refreshSiri { if (@available(iOS 12.0, *)) { NSMutableArray *temp = [NSMutableArray array]; [[INVoiceShortcutCenter sharedCenter] getAllVoiceShortcutsWithCompletion:^(NSArray * _Nullable voiceShortcuts, NSError * _Nullable error) { //该方法不是在主线程运行的,所以如果ok了需要回到主线程来 dispatch_async(dispatch_get_main_queue(), ^{ for (INVoiceShortcut *voiceShortcut in voiceShortcuts) { if ([self checkCurrentClass:voiceShortcut]) { [temp addObject:voiceShortcut]; } } self.siriShortcutList = [NSArray arrayWithArray:temp]; [self.tableView reloadData]; }); }]; } [self.tableView reloadData]; } #pragma mark - INUIAddVoiceShortcutButtonDelegate - (void)presentAddVoiceShortcutViewController:(INUIAddVoiceShortcutViewController *)addVoiceShortcutViewController forAddVoiceShortcutButton:(INUIAddVoiceShortcutButton *)addVoiceShortcutButton API_AVAILABLE(ios(12.0)){ addVoiceShortcutViewController.delegate = self; if(@available(iOS 13.0, *)) { addVoiceShortcutViewController.modalPresentationStyle = UIModalPresentationOverFullScreen; } [self presentViewController:addVoiceShortcutViewController animated:YES completion:nil]; } - (void)presentEditVoiceShortcutViewController:(INUIEditVoiceShortcutViewController *)editVoiceShortcutViewController forAddVoiceShortcutButton:(INUIAddVoiceShortcutButton *)addVoiceShortcutButton API_AVAILABLE(ios(12.0)){ editVoiceShortcutViewController.delegate = self; if(@available(iOS 13.0, *)) { editVoiceShortcutViewController.modalPresentationStyle = UIModalPresentationOverFullScreen; } [self presentViewController:editVoiceShortcutViewController animated:YES completion:nil]; } #pragma mark - INUIAddVoiceShortcutViewControllerDelegate - (void)addVoiceShortcutViewController:(INUIAddVoiceShortcutViewController *)controller didFinishWithVoiceShortcut:(INVoiceShortcut *)voiceShortcut error:(NSError *)error API_AVAILABLE(ios(12.0)){ [self refreshSiri]; [controller dismissViewControllerAnimated:YES completion:nil]; } - (void)addVoiceShortcutViewControllerDidCancel:(INUIAddVoiceShortcutViewController *)controller API_AVAILABLE(ios(12.0)){ [self refreshSiri]; [controller dismissViewControllerAnimated:YES completion:nil]; } #pragma mark - INUIEditVoiceShortcutViewControllerDelegate - (void)editVoiceShortcutViewControllerDidCancel:(INUIEditVoiceShortcutViewController *)controller API_AVAILABLE(ios(12.0)){ [self refreshSiri]; [controller dismissViewControllerAnimated:YES completion:nil]; } - (void)editVoiceShortcutViewController:(INUIEditVoiceShortcutViewController *)controller didUpdateVoiceShortcut:(INVoiceShortcut *)voiceShortcut error:(NSError *)error API_AVAILABLE(ios(12.0)){ [self refreshSiri]; [controller dismissViewControllerAnimated:YES completion:nil]; } - (void)editVoiceShortcutViewController:(INUIEditVoiceShortcutViewController *)controller didDeleteVoiceShortcutWithIdentifier:(NSUUID *)deletedVoiceShortcutIdentifier API_AVAILABLE(ios(12.0)){ [self refreshSiri]; [controller dismissViewControllerAnimated:YES completion:nil]; } @end