From 3bc70769df3cf1ab466ca95d71386cdc7b11cc8b Mon Sep 17 00:00:00 2001 From: Lukhnos Liu Date: Sat, 17 Oct 2020 10:00:46 -0700 Subject: [PATCH] Show no update available when checking explicitly This imports OpenVanilla's OVNonModalAlertWindowController for the alerts. --- McBopomofo.xcodeproj/project.pbxproj | 10 ++ Source/AppDelegate.h | 1 + Source/AppDelegate.m | 39 +++++- .../AlertIcon.imageset/128X128.png | Bin 0 -> 2910 bytes .../AlertIcon.imageset/192x192.png | Bin 0 -> 4096 bytes .../AlertIcon.imageset/64X64.png | Bin 0 -> 1568 bytes .../AlertIcon.imageset/Contents.json | 23 +++ Source/OVNonModalAlertWindowController.h | 39 ++++++ Source/OVNonModalAlertWindowController.m | 131 ++++++++++++++++++ Source/OVNonModalAlertWindowController.xib | 85 ++++++++++++ Source/en.lproj/Localizable.strings | 19 +++ Source/zh-Hant.lproj/Localizable.strings | 19 +++ 12 files changed, 365 insertions(+), 1 deletion(-) create mode 100644 Source/Images/Images.xcassets/AlertIcon.imageset/128X128.png create mode 100644 Source/Images/Images.xcassets/AlertIcon.imageset/192x192.png create mode 100644 Source/Images/Images.xcassets/AlertIcon.imageset/64X64.png create mode 100644 Source/Images/Images.xcassets/AlertIcon.imageset/Contents.json create mode 100644 Source/OVNonModalAlertWindowController.h create mode 100644 Source/OVNonModalAlertWindowController.m create mode 100644 Source/OVNonModalAlertWindowController.xib diff --git a/McBopomofo.xcodeproj/project.pbxproj b/McBopomofo.xcodeproj/project.pbxproj index 181a86b4..3637abf6 100644 --- a/McBopomofo.xcodeproj/project.pbxproj +++ b/McBopomofo.xcodeproj/project.pbxproj @@ -47,6 +47,8 @@ 6AD7CBC815FE555000691B5B /* data-plain-bpmf.txt in Resources */ = {isa = PBXBuildFile; fileRef = 6AD7CBC715FE555000691B5B /* data-plain-bpmf.txt */; }; 6AE210B215FC63CC003659FE /* PlainBopomofo.tiff in Resources */ = {isa = PBXBuildFile; fileRef = 6AE210B015FC63CC003659FE /* PlainBopomofo.tiff */; }; 6AE210B315FC63CC003659FE /* PlainBopomofo@2x.tiff in Resources */ = {isa = PBXBuildFile; fileRef = 6AE210B115FC63CC003659FE /* PlainBopomofo@2x.tiff */; }; + 6AFF97F2253B299E007F1C49 /* OVNonModalAlertWindowController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6AFF97F0253B299E007F1C49 /* OVNonModalAlertWindowController.xib */; }; + 6AFF97F3253B299E007F1C49 /* OVNonModalAlertWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6AFF97F1253B299E007F1C49 /* OVNonModalAlertWindowController.m */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -209,6 +211,9 @@ 6AD7CBC715FE555000691B5B /* data-plain-bpmf.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "data-plain-bpmf.txt"; sourceTree = ""; }; 6AE210B015FC63CC003659FE /* PlainBopomofo.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = PlainBopomofo.tiff; sourceTree = ""; }; 6AE210B115FC63CC003659FE /* PlainBopomofo@2x.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = "PlainBopomofo@2x.tiff"; sourceTree = ""; }; + 6AFF97EF253B299E007F1C49 /* OVNonModalAlertWindowController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OVNonModalAlertWindowController.h; sourceTree = ""; }; + 6AFF97F0253B299E007F1C49 /* OVNonModalAlertWindowController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = OVNonModalAlertWindowController.xib; sourceTree = ""; }; + 6AFF97F1253B299E007F1C49 /* OVNonModalAlertWindowController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OVNonModalAlertWindowController.m; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -277,6 +282,8 @@ 6A0D4EC715FC0D6400ABF4B3 /* InputMethodController.mm */, 6A0D4EC815FC0D6400ABF4B3 /* main.m */, 6A0D4EF615FC0DA600ABF4B3 /* McBopomofo-Prefix.pch */, + 6AFF97EF253B299E007F1C49 /* OVNonModalAlertWindowController.h */, + 6AFF97F1253B299E007F1C49 /* OVNonModalAlertWindowController.m */, 6A0D4EC915FC0D6400ABF4B3 /* OVInputSourceHelper.h */, 6A0D4ECA15FC0D6400ABF4B3 /* OVInputSourceHelper.m */, 6A0D4ECB15FC0D6400ABF4B3 /* PreferencesWindowController.h */, @@ -399,6 +406,7 @@ 6A0D4F4715FC0EB900ABF4B3 /* Resources */ = { isa = PBXGroup; children = ( + 6AFF97F0253B299E007F1C49 /* OVNonModalAlertWindowController.xib */, 6A0D4EEE15FC0DA600ABF4B3 /* Images */, 6A0D4EF515FC0DA600ABF4B3 /* McBopomofo-Info.plist */, 6A0D4F4815FC0EE100ABF4B3 /* InfoPlist.strings */, @@ -575,6 +583,7 @@ 6A0D4F5815FC0EF900ABF4B3 /* Localizable.strings in Resources */, 6A2E40F6253A69DA00D1AE1D /* Images.xcassets in Resources */, 6A38BC1515FC117A00A8A51F /* data.txt in Resources */, + 6AFF97F2253B299E007F1C49 /* OVNonModalAlertWindowController.xib in Resources */, 6AE210B215FC63CC003659FE /* PlainBopomofo.tiff in Resources */, 6AE210B315FC63CC003659FE /* PlainBopomofo@2x.tiff in Resources */, 6AD7CBC815FE555000691B5B /* data-plain-bpmf.txt in Resources */, @@ -632,6 +641,7 @@ 6A0D4EFE15FC0DA600ABF4B3 /* VTCandidateController.m in Sources */, 6A0D4EFF15FC0DA600ABF4B3 /* VTHorizontalCandidateController.m in Sources */, 6A0D4F0015FC0DA600ABF4B3 /* VTHorizontalCandidateView.m in Sources */, + 6AFF97F3253B299E007F1C49 /* OVNonModalAlertWindowController.m in Sources */, 6A0D4F0115FC0DA600ABF4B3 /* VTVerticalCandidateController.m in Sources */, 6A0D4F0215FC0DA600ABF4B3 /* VTVerticalCandidateTableView.m in Sources */, 6A0D4F0315FC0DA600ABF4B3 /* VTVerticalKeyLabelStripView.m in Sources */, diff --git a/Source/AppDelegate.h b/Source/AppDelegate.h index eb216be0..88f94c78 100644 --- a/Source/AppDelegate.h +++ b/Source/AppDelegate.h @@ -42,6 +42,7 @@ @private NSWindow *_window; NSURLConnection *_updateCheckConnection; + BOOL _currentUpdateCheckIsForced; NSMutableData *_receivingData; PreferencesWindowController *_preferencesWindowController; UpdateNotificationController *_updateNotificationController; diff --git a/Source/AppDelegate.m b/Source/AppDelegate.m index e972e13e..fa1bc467 100644 --- a/Source/AppDelegate.m +++ b/Source/AppDelegate.m @@ -33,6 +33,7 @@ // #import "AppDelegate.h" +#import "OVNonModalAlertWindowController.h" #import "UpdateNotificationController.h" #import "PreferencesWindowController.h" @@ -44,7 +45,7 @@ static NSString *kUpdateInfoSiteKey = @"UpdateInfoSite"; static const NSTimeInterval kNextCheckInterval = 86400.0; static const NSTimeInterval kTimeoutInterval = 60.0; -@interface AppDelegate () +@interface AppDelegate () @end @implementation AppDelegate @@ -77,6 +78,8 @@ static const NSTimeInterval kTimeoutInterval = 60.0; return; } + _currentUpdateCheckIsForced = forced; + // time for update? if (!forced) { NSDate *now = [NSDate date]; @@ -134,10 +137,22 @@ static const NSTimeInterval kTimeoutInterval = 60.0; - (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error { + BOOL isForcedCheck = _currentUpdateCheckIsForced; + [_receivingData release]; _receivingData = nil; [_updateCheckConnection release]; _updateCheckConnection = nil; + _currentUpdateCheckIsForced = NO; + + if (isForcedCheck) { + [[OVNonModalAlertWindowController sharedInstance] showWithTitle:NSLocalizedString(@"Update Check Failed", nil) content:[NSString stringWithFormat:NSLocalizedString(@"There may be no internet connection or the server failed to respond.\n\nError message: %@", nil), [error localizedDescription]] confirmButtonTitle:NSLocalizedString(@"Dismiss", nil) cancelButtonTitle:nil cancelAsDefault:NO delegate:nil]; + } +} + +- (void)showNoUpdateAvailableAlert +{ + [[OVNonModalAlertWindowController sharedInstance] showWithTitle:NSLocalizedString(@"Check for Update Completed", nil) content:NSLocalizedString(@"You are already using the latest version of McBopomofo.", nil) confirmButtonTitle:NSLocalizedString(@"OK", nil) cancelButtonTitle:nil cancelAsDefault:NO delegate:nil]; } - (void)connectionDidFinishLoading:(NSURLConnection *)connection @@ -147,12 +162,18 @@ static const NSTimeInterval kTimeoutInterval = 60.0; NSLog(@"plist %@",plist); #endif + BOOL isForcedCheck = _currentUpdateCheckIsForced; + [_receivingData release]; _receivingData = nil; [_updateCheckConnection release]; _updateCheckConnection = nil; + _currentUpdateCheckIsForced = NO; if (!plist) { + if (isForcedCheck) { + [self showNoUpdateAvailableAlert]; + } return; } @@ -161,6 +182,9 @@ static const NSTimeInterval kTimeoutInterval = 60.0; NSLog(@"the remoteversion is %@",remoteVersion); #endif if (!remoteVersion) { + if (isForcedCheck) { + [self showNoUpdateAvailableAlert]; + } return; } @@ -172,17 +196,26 @@ static const NSTimeInterval kTimeoutInterval = 60.0; NSComparisonResult result = [currentVersion compare:remoteVersion options:NSNumericSearch]; if (result != NSOrderedAscending) { + if (isForcedCheck) { + [self showNoUpdateAvailableAlert]; + } return; } NSString *siteInfoURLString = [plist objectForKey:kUpdateInfoSiteKey]; if (!siteInfoURLString) { + if (isForcedCheck) { + [self showNoUpdateAvailableAlert]; + } return; } NSURL *siteInfoURL = [NSURL URLWithString:siteInfoURLString]; if (!siteInfoURL) { + if (isForcedCheck) { + [self showNoUpdateAvailableAlert]; + } return; } @@ -210,4 +243,8 @@ static const NSTimeInterval kTimeoutInterval = 60.0; { [_receivingData appendData:data]; } + +- (void)nonModalAlertWindowControllerDidConfirm:(OVNonModalAlertWindowController *)controller +{ +} @end diff --git a/Source/Images/Images.xcassets/AlertIcon.imageset/128X128.png b/Source/Images/Images.xcassets/AlertIcon.imageset/128X128.png new file mode 100644 index 0000000000000000000000000000000000000000..1a599df979101d94f100c41c0ad1362746ec28a1 GIT binary patch literal 2910 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 S#=A}c0000 + +@class OVNonModalAlertWindowController; + +@protocol OVNonModalAlertWindowControllerDelegate +- (void)nonModalAlertWindowControllerDidConfirm:(OVNonModalAlertWindowController *)controller; + +@optional +- (void)nonModalAlertWindowControllerDidCancel:(OVNonModalAlertWindowController *)controller; +@end + +@interface OVNonModalAlertWindowController : NSWindowController +{ +@private + NSTextField *_titleTextField; + NSTextField *_contentTextField; + NSButton *_confirmButton; + NSButton *_cancelButton; + id _delegate; +} + ++ (OVNonModalAlertWindowController *)sharedInstance; +- (void)showWithTitle:(NSString *)title content:(NSString *)content confirmButtonTitle:(NSString *)confirmTitle cancelButtonTitle:(NSString *)cancelButtonTitle cancelAsDefault:(BOOL)cancelAsDefault delegate:(id)delegate; +- (IBAction)confirmButtonAction:(id)sender; +- (IBAction)cancelButtonAction:(id)sender; +@property (assign, nonatomic) IBOutlet NSTextField *titleTextField; +@property (assign, nonatomic) IBOutlet NSTextField *contentTextField; +@property (assign, nonatomic) IBOutlet NSButton *confirmButton; +@property (assign, nonatomic) IBOutlet NSButton *cancelButton; +@property (assign, nonatomic) id delegate; +@end diff --git a/Source/OVNonModalAlertWindowController.m b/Source/OVNonModalAlertWindowController.m new file mode 100644 index 00000000..25ce7a24 --- /dev/null +++ b/Source/OVNonModalAlertWindowController.m @@ -0,0 +1,131 @@ +// +// OVNonModalAlertWindowController.m +// OpenVanilla +// +// Created by Lukhnos Liu on 10/17/12. +// Copyright (c) 2012 The OpenVanilla Project. All rights reserved. +// + +#import "OVNonModalAlertWindowController.h" + +@implementation OVNonModalAlertWindowController +@synthesize titleTextField = _titleTextField; +@synthesize contentTextField = _contentTextField; +@synthesize confirmButton = _confirmButton; +@synthesize cancelButton = _cancelButton; +@synthesize delegate = _delegate; + ++ (OVNonModalAlertWindowController *)sharedInstance +{ + static OVNonModalAlertWindowController *instance; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + instance = [[OVNonModalAlertWindowController alloc] initWithWindowNibName:@"OVNonModalAlertWindowController"]; + [instance window]; + }); + return instance; +} + +// Suppress the use of the MIN/MAX macros +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wgnu-statement-expression" + +- (void)showWithTitle:(NSString *)title content:(NSString *)content confirmButtonTitle:(NSString *)confirmTitle cancelButtonTitle:(NSString *)cancelButtonTitle cancelAsDefault:(BOOL)cancelAsDefault delegate:(id)delegate; +{ + // cancel previous alert + if ([[self window] isVisible]) { + if ([_delegate respondsToSelector:@selector(nonModalAlertWindowControllerDidCancel:)]) { + [_delegate nonModalAlertWindowControllerDidCancel:self]; + } + } + + _delegate = delegate; + + NSRect oldFrame = [self.confirmButton frame]; + [self.confirmButton setTitle:confirmTitle]; + [self.confirmButton sizeToFit]; + + NSRect newFrame = [self.confirmButton frame]; + + newFrame.size.width = MAX(90.0, (newFrame.size.width + 10.0)); + newFrame.origin.x += (oldFrame.size.width - newFrame.size.width); + [self.confirmButton setFrame:newFrame]; + + if (cancelButtonTitle) { + [self.cancelButton setTitle:cancelButtonTitle]; + [self.cancelButton sizeToFit]; + NSRect adjustedFrame = [self.cancelButton frame]; + adjustedFrame.size.width = MAX(90.0, (adjustedFrame.size.width + 10.0)); + adjustedFrame.origin.x = newFrame.origin.x - adjustedFrame.size.width; + [self.cancelButton setFrame:adjustedFrame]; + [self.cancelButton setHidden:NO]; + } + else { + [self.cancelButton setHidden:YES]; + } + + [self.cancelButton setNextKeyView:self.confirmButton]; + [self.confirmButton setNextKeyView:self.cancelButton]; + + if (cancelButtonTitle) { + if (cancelAsDefault) { + [[self window] setDefaultButtonCell:[self.cancelButton cell]]; + } + else { + [self.cancelButton setKeyEquivalent:@" "]; + [[self window] setDefaultButtonCell:[self.confirmButton cell]]; + } + } + else { + [[self window] setDefaultButtonCell:[self.confirmButton cell]]; + } + + [self.titleTextField setStringValue:title]; + + oldFrame = [self.contentTextField frame]; + [self.contentTextField setStringValue:content]; + + NSRect infiniteHeightFrame = oldFrame; + infiniteHeightFrame.size.width -= 4.0; + infiniteHeightFrame.size.height = 10240; + newFrame = [content boundingRectWithSize:infiniteHeightFrame.size options:NSStringDrawingUsesLineFragmentOrigin attributes:[NSDictionary dictionaryWithObjectsAndKeys:[self.contentTextField font], NSFontAttributeName, nil]]; + newFrame.size.width = MAX(newFrame.size.width, oldFrame.size.width); + newFrame.size.height += 4.0; + newFrame.origin = oldFrame.origin; + newFrame.origin.y -= (newFrame.size.height - oldFrame.size.height); + [self.contentTextField setFrame:newFrame]; + + NSRect windowFrame = [[self window] frame]; + windowFrame.size.height += (newFrame.size.height - oldFrame.size.height); + + [[self window] setLevel:CGShieldingWindowLevel() + 1]; + [[self window] setFrame:windowFrame display:YES]; + [[self window] center]; + [[self window] makeKeyAndOrderFront:self]; + [[NSApplication sharedApplication] activateIgnoringOtherApps:YES]; +} +#pragma GCC diagnostic pop + +- (IBAction)confirmButtonAction:(id)sender +{ + [_delegate nonModalAlertWindowControllerDidConfirm:self]; + [[self window] orderOut:self]; +} + +- (IBAction)cancelButtonAction:(id)sender +{ + [self cancel:sender]; +} + +- (void)cancel:(id)sender +{ + if ([_delegate respondsToSelector:@selector(nonModalAlertWindowControllerDidCancel:)]) { + [_delegate nonModalAlertWindowControllerDidCancel:self]; + } + + _delegate = nil; + + [[self window] orderOut:self]; +} + +@end diff --git a/Source/OVNonModalAlertWindowController.xib b/Source/OVNonModalAlertWindowController.xib new file mode 100644 index 00000000..430b3b36 --- /dev/null +++ b/Source/OVNonModalAlertWindowController.xib @@ -0,0 +1,85 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/en.lproj/Localizable.strings b/Source/en.lproj/Localizable.strings index 8024204c..671501f5 100644 --- a/Source/en.lproj/Localizable.strings +++ b/Source/en.lproj/Localizable.strings @@ -27,3 +27,22 @@ /* No comment provided by engineer. */ "Check for Updates…" = "Check for Updates…"; + +/* No comment provided by engineer. */ +"Check for Update Completed" = "Check for Update Completed"; + +/* No comment provided by engineer. */ +"You are already using the latest version of McBopomofo." = "You are already using the latest version of McBopomofo."; + +/* No comment provided by engineer. */ +"Update Check Failed" = "Update Check Failed"; + +/* No comment provided by engineer. */ +"There may be no internet connection or the server failed to respond.\n\nError message: %@" = "There may be no internet connection or the server failed to respond.\n\nError message: %@"; + +/* No comment provided by engineer. */ +"OK" = "OK"; + +/* No comment provided by engineer. */ +"Dismiss" = "Dismiss"; + diff --git a/Source/zh-Hant.lproj/Localizable.strings b/Source/zh-Hant.lproj/Localizable.strings index 2ebe96de..d13db3d2 100644 --- a/Source/zh-Hant.lproj/Localizable.strings +++ b/Source/zh-Hant.lproj/Localizable.strings @@ -27,3 +27,22 @@ /* No comment provided by engineer. */ "Check for Updates…" = "檢查是否有新版…"; + +/* No comment provided by engineer. */ +"Check for Update Completed" = "新版檢查完畢"; + +/* No comment provided by engineer. */ +"You are already using the latest version of McBopomofo." = "目前使用的已經是最新版本。"; + +/* No comment provided by engineer. */ +"Update Check Failed" = "無法檢查新版"; + +/* No comment provided by engineer. */ +"There may be no internet connection or the server failed to respond.\n\nError message: %@" = "網路連線失敗,或是伺服器沒有回應。\n\n錯誤說明:%@"; + +/* No comment provided by engineer. */ +"OK" = "好"; + +/* No comment provided by engineer. */ +"Dismiss" = "關閉本視窗"; +