diff --git a/Mini vMac/AppDelegate.h b/Mini vMac/AppDelegate.h index 99811e8..4c1cfe5 100644 --- a/Mini vMac/AppDelegate.h +++ b/Mini vMac/AppDelegate.h @@ -28,6 +28,7 @@ extern NSString *DocumentsChangedNotification; - (void)showAlertWithTitle:(NSString *)title message:(NSString *)message; - (IBAction)showInsertDisk:(id)sender; - (IBAction)showSettings:(id)sender; +- (IBAction)showGestureHelp:(id)sender; @end diff --git a/Mini vMac/AppDelegate.m b/Mini vMac/AppDelegate.m index 321bb33..ec16606 100644 --- a/Mini vMac/AppDelegate.m +++ b/Mini vMac/AppDelegate.m @@ -156,7 +156,7 @@ NSString *DocumentsChangedNotification = @"documentsChanged"; } } -#pragma mark - Settings / Insert Disk panels +#pragma mark - Settings / Insert Disk / Help - (void)showSettings:(id)sender { [self.window.rootViewController performSelector:@selector(showSettings:) withObject:sender]; @@ -166,6 +166,10 @@ NSString *DocumentsChangedNotification = @"documentsChanged"; [self.window.rootViewController performSelector:@selector(showInsertDisk:) withObject:sender]; } +- (void)showGestureHelp:(id)sender { + [self.window.rootViewController performSelector:@selector(showGestureHelp:) withObject:sender]; +} + #pragma mark - Files - (BOOL)isSandboxed { diff --git a/Mini vMac/Assets.xcassets/Swipe2Down.imageset/Contents.json b/Mini vMac/Assets.xcassets/Swipe2Down.imageset/Contents.json new file mode 100644 index 0000000..c7b9c6b --- /dev/null +++ b/Mini vMac/Assets.xcassets/Swipe2Down.imageset/Contents.json @@ -0,0 +1,26 @@ +{ + "images" : [ + { + "filename" : "Swipe2Down.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "Swipe2Down@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "Swipe2Down@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "template-rendering-intent" : "template" + } +} diff --git a/Mini vMac/Assets.xcassets/Swipe2Down.imageset/Swipe2Down.png b/Mini vMac/Assets.xcassets/Swipe2Down.imageset/Swipe2Down.png new file mode 100644 index 0000000..d82ea61 Binary files /dev/null and b/Mini vMac/Assets.xcassets/Swipe2Down.imageset/Swipe2Down.png differ diff --git a/Mini vMac/Assets.xcassets/Swipe2Down.imageset/Swipe2Down@2x.png b/Mini vMac/Assets.xcassets/Swipe2Down.imageset/Swipe2Down@2x.png new file mode 100644 index 0000000..10e87f2 Binary files /dev/null and b/Mini vMac/Assets.xcassets/Swipe2Down.imageset/Swipe2Down@2x.png differ diff --git a/Mini vMac/Assets.xcassets/Swipe2Down.imageset/Swipe2Down@3x.png b/Mini vMac/Assets.xcassets/Swipe2Down.imageset/Swipe2Down@3x.png new file mode 100644 index 0000000..369dce2 Binary files /dev/null and b/Mini vMac/Assets.xcassets/Swipe2Down.imageset/Swipe2Down@3x.png differ diff --git a/Mini vMac/Assets.xcassets/Swipe2Left.imageset/Contents.json b/Mini vMac/Assets.xcassets/Swipe2Left.imageset/Contents.json new file mode 100644 index 0000000..24f7662 --- /dev/null +++ b/Mini vMac/Assets.xcassets/Swipe2Left.imageset/Contents.json @@ -0,0 +1,26 @@ +{ + "images" : [ + { + "filename" : "Swipe2Left.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "Swipe2Left@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "Swipe2Left@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "template-rendering-intent" : "template" + } +} diff --git a/Mini vMac/Assets.xcassets/Swipe2Left.imageset/Swipe2Left.png b/Mini vMac/Assets.xcassets/Swipe2Left.imageset/Swipe2Left.png new file mode 100644 index 0000000..41e70b1 Binary files /dev/null and b/Mini vMac/Assets.xcassets/Swipe2Left.imageset/Swipe2Left.png differ diff --git a/Mini vMac/Assets.xcassets/Swipe2Left.imageset/Swipe2Left@2x.png b/Mini vMac/Assets.xcassets/Swipe2Left.imageset/Swipe2Left@2x.png new file mode 100644 index 0000000..b200c04 Binary files /dev/null and b/Mini vMac/Assets.xcassets/Swipe2Left.imageset/Swipe2Left@2x.png differ diff --git a/Mini vMac/Assets.xcassets/Swipe2Left.imageset/Swipe2Left@3x.png b/Mini vMac/Assets.xcassets/Swipe2Left.imageset/Swipe2Left@3x.png new file mode 100644 index 0000000..4104bad Binary files /dev/null and b/Mini vMac/Assets.xcassets/Swipe2Left.imageset/Swipe2Left@3x.png differ diff --git a/Mini vMac/Assets.xcassets/Swipe2Right.imageset/Contents.json b/Mini vMac/Assets.xcassets/Swipe2Right.imageset/Contents.json new file mode 100644 index 0000000..27efc0f --- /dev/null +++ b/Mini vMac/Assets.xcassets/Swipe2Right.imageset/Contents.json @@ -0,0 +1,26 @@ +{ + "images" : [ + { + "filename" : "Swipe2Right.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "Swipe2Right@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "Swipe2Right@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "template-rendering-intent" : "template" + } +} diff --git a/Mini vMac/Assets.xcassets/Swipe2Right.imageset/Swipe2Right.png b/Mini vMac/Assets.xcassets/Swipe2Right.imageset/Swipe2Right.png new file mode 100644 index 0000000..fa4221c Binary files /dev/null and b/Mini vMac/Assets.xcassets/Swipe2Right.imageset/Swipe2Right.png differ diff --git a/Mini vMac/Assets.xcassets/Swipe2Right.imageset/Swipe2Right@2x.png b/Mini vMac/Assets.xcassets/Swipe2Right.imageset/Swipe2Right@2x.png new file mode 100644 index 0000000..2f099c4 Binary files /dev/null and b/Mini vMac/Assets.xcassets/Swipe2Right.imageset/Swipe2Right@2x.png differ diff --git a/Mini vMac/Assets.xcassets/Swipe2Right.imageset/Swipe2Right@3x.png b/Mini vMac/Assets.xcassets/Swipe2Right.imageset/Swipe2Right@3x.png new file mode 100644 index 0000000..06a4040 Binary files /dev/null and b/Mini vMac/Assets.xcassets/Swipe2Right.imageset/Swipe2Right@3x.png differ diff --git a/Mini vMac/Assets.xcassets/Swipe2Up.imageset/Contents.json b/Mini vMac/Assets.xcassets/Swipe2Up.imageset/Contents.json new file mode 100644 index 0000000..0c9fcea --- /dev/null +++ b/Mini vMac/Assets.xcassets/Swipe2Up.imageset/Contents.json @@ -0,0 +1,26 @@ +{ + "images" : [ + { + "filename" : "Swipe2Up.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "Swipe2Up@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "Swipe2Up@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "template-rendering-intent" : "template" + } +} diff --git a/Mini vMac/Assets.xcassets/Swipe2Up.imageset/Swipe2Up.png b/Mini vMac/Assets.xcassets/Swipe2Up.imageset/Swipe2Up.png new file mode 100644 index 0000000..9a26f42 Binary files /dev/null and b/Mini vMac/Assets.xcassets/Swipe2Up.imageset/Swipe2Up.png differ diff --git a/Mini vMac/Assets.xcassets/Swipe2Up.imageset/Swipe2Up@2x.png b/Mini vMac/Assets.xcassets/Swipe2Up.imageset/Swipe2Up@2x.png new file mode 100644 index 0000000..bbad13d Binary files /dev/null and b/Mini vMac/Assets.xcassets/Swipe2Up.imageset/Swipe2Up@2x.png differ diff --git a/Mini vMac/Assets.xcassets/Swipe2Up.imageset/Swipe2Up@3x.png b/Mini vMac/Assets.xcassets/Swipe2Up.imageset/Swipe2Up@3x.png new file mode 100644 index 0000000..64136cb Binary files /dev/null and b/Mini vMac/Assets.xcassets/Swipe2Up.imageset/Swipe2Up@3x.png differ diff --git a/Mini vMac/Base.lproj/Main.storyboard b/Mini vMac/Base.lproj/Main.storyboard index b3b6d95..a1cc6da 100644 --- a/Mini vMac/Base.lproj/Main.storyboard +++ b/Mini vMac/Base.lproj/Main.storyboard @@ -23,24 +23,194 @@ + + + + + + + + + - + @@ -359,6 +529,10 @@ + + + + diff --git a/Mini vMac/SettingsViewController.m b/Mini vMac/SettingsViewController.m index c498b3c..b3fd446 100644 --- a/Mini vMac/SettingsViewController.m +++ b/Mini vMac/SettingsViewController.m @@ -92,6 +92,7 @@ typedef enum : NSInteger { footerView.textColor = [UIColor darkGrayColor]; footerView.font = [UIFont systemFontOfSize:[UIFont smallSystemFontSize]]; footerView.backgroundColor = [UIColor clearColor]; + footerView.scrollEnabled = NO; } - (void)viewDidAppear:(BOOL)animated { @@ -147,6 +148,12 @@ typedef enum : NSInteger { } } +- (void)changeAutoShowGestureHelp:(UISwitch*)sender { + if ([sender isKindOfClass:[UISwitch class]]) { + [[NSUserDefaults standardUserDefaults] setBool:sender.on forKey:@"autoShowGestureHelp"]; + } +} + #pragma mark - Table view data source - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { @@ -165,7 +172,7 @@ typedef enum : NSInteger { case SettingsSectionMachine: return machineList.count; case SettingsSectionAbout: - return aboutItems.count; + return aboutItems.count + 1; default: return 1; } @@ -270,18 +277,12 @@ typedef enum : NSInteger { cell.accessoryType = (item == selectedEmulatorBundle) ? UITableViewCellAccessoryCheckmark : UITableViewCellAccessoryNone; cell.selectionStyle = rowIsHeader ? UITableViewCellSelectionStyleNone : UITableViewCellSelectionStyleDefault; } else if (section == SettingsSectionAbout) { - cell = [tableView dequeueReusableCellWithIdentifier:@"about" forIndexPath:indexPath]; - NSDictionary *item = aboutItems[indexPath.row]; - cell.textLabel.text = item[@"text"]; - NSString *detailText = item[@"detailText"]; - if ([detailText isEqualToString:@"$version"]) { - NSString *versionString = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleShortVersionString"]; - NSString *commitString = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"GitVersion"]; - cell.detailTextLabel.text = commitString.length > 0 ? [NSString stringWithFormat:@"%@ (%@)", versionString, commitString] : versionString; + if (indexPath.row >= aboutItems.count) { + cell = [self switchCellForTableView:tableView indexPath:indexPath action:@selector(changeAutoShowGestureHelp:) on:[defaults boolForKey:@"autoShowGestureHelp"]]; + cell.textLabel.text = NSLocalizedString(@"Show Gesture Help", nil); } else { - cell.detailTextLabel.text = detailText; + cell = [self aboutCellForTableView:tableView indexPath:indexPath]; } - cell.accessoryType = item[@"link"] == nil ? UITableViewCellAccessoryNone : UITableViewCellAccessoryDisclosureIndicator; } else if (section == SettingsSectionDisplay) { cell = [tableView dequeueReusableCellWithIdentifier:@"display" forIndexPath:indexPath]; UISegmentedControl *filterControl = (UISegmentedControl*)[cell viewWithTag:128]; @@ -297,6 +298,22 @@ typedef enum : NSInteger { return cell; } +- (UITableViewCell*)aboutCellForTableView:(UITableView *)tableView indexPath:(NSIndexPath *)indexPath { + UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"about" forIndexPath:indexPath]; + NSDictionary *item = aboutItems[indexPath.row]; + cell.textLabel.text = item[@"text"]; + NSString *detailText = item[@"detailText"]; + if ([detailText isEqualToString:@"$version"]) { + NSString *versionString = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleShortVersionString"]; + NSString *commitString = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"GitVersion"]; + cell.detailTextLabel.text = commitString.length > 0 ? [NSString stringWithFormat:@"%@ (%@)", versionString, commitString] : versionString; + } else { + cell.detailTextLabel.text = detailText; + } + cell.accessoryType = item[@"link"] == nil ? UITableViewCellAccessoryNone : UITableViewCellAccessoryDisclosureIndicator; + return cell; +} + - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; [tableView deselectRowAtIndexPath:indexPath animated:YES]; @@ -322,10 +339,17 @@ typedef enum : NSInteger { selectedEmulatorBundle = bundle; [tableView reloadSections:[NSIndexSet indexSetWithIndex:SettingsSectionSpeed] withRowAnimation:UITableViewRowAnimationAutomatic]; } else if (indexPath.section == SettingsSectionAbout) { - // links in about - NSString *linkURL = aboutItems[indexPath.row][@"link"]; - if (linkURL != nil) { - [[UIApplication sharedApplication] openURL:[NSURL URLWithString:linkURL]]; + if (indexPath.row >= aboutItems.count) { + // show gesture help + [self dismissViewControllerAnimated:YES completion:^{ + [[AppDelegate sharedInstance] showGestureHelp:self]; + }]; + } else { + // links in about + NSString *linkURL = aboutItems[indexPath.row][@"link"]; + if (linkURL != nil) { + [[UIApplication sharedApplication] openURL:[NSURL URLWithString:linkURL]]; + } } } } diff --git a/Mini vMac/ViewController.h b/Mini vMac/ViewController.h index 2577cc8..ce89689 100644 --- a/Mini vMac/ViewController.h +++ b/Mini vMac/ViewController.h @@ -19,6 +19,10 @@ API_AVAILABLE(ios(13.4)) @property (weak, nonatomic) IBOutlet ScreenView *screenView; @property (nonatomic, getter=isKeyboardVisible) BOOL keyboardVisible; +@property (weak, nonatomic) IBOutlet UIView *helpView; + +- (IBAction)showGestureHelp:(id)sender; +- (IBAction)hideGestureHelp:(id)sender; @end diff --git a/Mini vMac/ViewController.m b/Mini vMac/ViewController.m index b566c7d..2e1af5b 100644 --- a/Mini vMac/ViewController.m +++ b/Mini vMac/ViewController.m @@ -69,6 +69,8 @@ [self.view addGestureRecognizer:showSettingsGesture]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(emulatorDidShutDown:) name:[AppDelegate sharedEmulator].shutdownNotification object:nil]; + + [self scheduleHelpPresentationIfNeededAfterDelay:6.0]; } - (void)showSettings:(id)sender { @@ -80,6 +82,7 @@ } - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { + [self cancelHelpPresentation]; if ([sender isKindOfClass:[UIGestureRecognizer class]]) { UISwipeGestureRecognizer *gestureRecognizer = (UISwipeGestureRecognizer*)sender; modalPanePresentationDirection = gestureRecognizer.direction; @@ -240,6 +243,50 @@ } } +#pragma mark - Gesture Help + +- (void)showGestureHelp:(id)sender { + [self setGestureHelpHidden:NO]; +} + +- (void)hideGestureHelp:(id)sender { + [self setGestureHelpHidden:YES]; +} + +- (void)setGestureHelpHidden:(BOOL)hidden { + if (self.helpView.hidden == hidden) { + return; + } else if (!hidden) { + // prepare to show + self.helpView.alpha = 0.0; + self.helpView.hidden = NO; + } + [UIView animateWithDuration:0.2 + animations:^{ + self.helpView.alpha = hidden ? 0.0 : 1.0; + } + completion:^(BOOL finished) { + self.helpView.hidden = hidden; + }]; +} + +- (void)showGestureHelpIfNeeded:(id)sender { + // show help if no disks have been inserted + if (![AppDelegate sharedEmulator].anyDiskInserted) { + [self showGestureHelp:sender]; + } +} + +- (void)scheduleHelpPresentationIfNeededAfterDelay:(NSTimeInterval)delay { + if ([[NSUserDefaults standardUserDefaults] boolForKey:@"autoShowGestureHelp"]) { + [self performSelector:@selector(showGestureHelpIfNeeded:) withObject:self afterDelay:delay]; + } +} + +- (void)cancelHelpPresentation { + [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(showGestureHelpIfNeeded:) object:self]; +} + #pragma mark - Keyboard - (void)installKeyboardGestures {