2009-11-10 16:48:42 +01:00
//
// QuietUnrarAppDelegate . m
// QuietUnrar
//
// Created by Robert McGovern on 2009 / 09 / 06.
// Copyright 2009 Tarasis . All rights reserved .
//
# import < Carbon / Carbon . h >
2021-05-31 14:07:27 +02:00
# import < Cocoa / Cocoa . h >
# import < UserNotifications / UserNotifications . h >
2021-05-26 14:49:40 +02:00
2021-05-31 14:07:27 +02:00
# import "QuietUnrarAppDelegate.h"
# import "TDNUnarchiver.h"
2021-05-31 21:42:30 +02:00
# import "TDNUserDefaults.h"
# import "TDNPreferencesWindowController.h"
2021-05-26 14:49:40 +02:00
2021-05-31 14:07:27 +02:00
@ interface QuietUnrarAppDelegate ( )
2021-05-26 14:49:40 +02:00
2021-05-31 14:07:27 +02:00
@ property TDNUnarchiver * unarchiver ;
2021-05-31 21:42:30 +02:00
@ property TDNUserDefaults * userDefaults ;
@ property NSStatusItem * statusBarItem ;
@ property NSArray * arrayOfFilesToProcess ;
2021-05-26 14:49:40 +02:00
2021-05-31 14:07:27 +02:00
@ end
2009-11-15 00:18:58 +01:00
2009-11-16 15:00:11 +01:00
# pragma mark
2009-11-10 16:48:42 +01:00
@ implementation QuietUnrarAppDelegate
2021-05-31 21:42:30 +02:00
@ synthesize window , passwordView , passwordField , preferencesWindowController , unarchiver , userDefaults , statusBarItem , arrayOfFilesToProcess ;
2009-11-10 16:48:42 +01:00
2021-05-31 23:31:45 +02:00
BOOL appRunning = NO ;
2009-11-14 23:12:16 +01:00
- ( void ) applicationWillFinishLaunching : ( NSNotification * ) notification {
2021-05-31 14:07:27 +02:00
NSLog ( @ "applicationWillFinishLaunching" ) ;
2021-05-31 23:40:09 +02:00
// The following is used to determine is the left or right shift keys were depressed
// as the application was launched . Could be used to display a gui on Application start .
KeyMap map ;
GetKeys ( map ) ;
if ( KEYMAP_GET ( map , kVKC_Shift ) || KEYMAP_GET ( map , kVKC_rShift ) )
NSLog ( @ "Shift or Right Shift" ) ;
2021-05-31 21:42:30 +02:00
userDefaults = [ TDNUserDefaults sharedInstance ] ;
2021-05-31 23:31:45 +02:00
if ( userDefaults . hideDock ) {
[ self hideDockIcon : TRUE ] ;
}
2009-11-10 16:48:42 +01:00
}
2009-11-14 23:12:16 +01:00
- ( void ) applicationDidFinishLaunching : ( NSNotification * ) aNotification {
2021-05-31 14:07:27 +02:00
NSLog ( @ "applicationDidFinishLaunching" ) ;
[ self requestUserPermissionForNotifications ] ;
2021-05-31 21:42:30 +02:00
if ( arrayOfFilesToProcess = = nil || arrayOfFilesToProcess . count = = 0 ) {
preferencesWindowController = [ [ TDNPreferencesWindowController alloc ] init ] ;
preferencesWindowController . quietUnrar = self ;
2021-05-31 14:07:27 +02:00
2021-05-31 23:31:45 +02:00
dispatch_after ( dispatch_time ( DISPATCH_TIME _NOW , ( int64_t ) ( 0.5 * NSEC_PER _SEC ) ) , dispatch_get _main _queue ( ) , ^ {
[ self -> preferencesWindowController . window makeKeyAndOrderFront : self ] ;
[ NSApp activateIgnoringOtherApps : YES ] ;
} ) ;
appRunning = YES ;
2021-05-31 21:42:30 +02:00
} else {
unarchiver = [ [ TDNUnarchiver alloc ] init ] ;
unarchiver . quietUnrar = self ;
2021-05-31 23:31:45 +02:00
dispatch_async ( dispatch_get _global _queue ( DISPATCH_QUEUE _PRIORITY _HIGH , 0 ) , ^ {
for ( NSString * filename in self -> arrayOfFilesToProcess ) {
BOOL extracted = [ self -> unarchiver extractArchiveWithFilename : filename ] ;
if ( extracted ) {
// post notification based on user preference
if ( self -> userDefaults . showNotification && self -> userDefaults . notificationsAllowed ) { // if show notification + permission granted . . .
[ self postNotificationUncompressedFile : filename ] ;
// maybe don ' t want to spam lots of notifications if unarchiving a lot of archives
}
2021-05-31 21:42:30 +02:00
}
}
2021-05-31 23:31:45 +02:00
[ [ NSApplication sharedApplication ] terminate : self ] ;
} ) ;
2021-05-31 21:42:30 +02:00
}
2009-11-10 16:48:42 +01:00
}
2009-11-16 15:00:11 +01:00
// Call one at a time for each file selected when app is run
2021-05-26 18:15:39 +02:00
// This is seemingly never called , even when only selecting a single file .
2009-11-10 16:48:42 +01:00
- ( BOOL ) application : ( NSApplication * ) theApplication openFile : ( NSString * ) filename {
2021-05-31 23:40:09 +02:00
// NSLog ( @ "openFile: %@" , filename ) ;
2021-05-24 11:24:32 +02:00
2021-05-31 23:40:09 +02:00
// [ self extractRarWith : filename ] ;
// [ self extractRarUsingUnrarKitWithFilename : filename ] ;
// Always return YES even if there is an error to avoid dialog indicating unable to
// handle files of type RAR if the archive is corrupt or part of it is missing
return YES ;
2009-11-10 16:48:42 +01:00
}
2009-11-16 22:11:00 +01:00
- ( void ) application : ( NSApplication * ) theApplication openFiles : ( NSArray * ) arrayOfFilenames {
2021-05-31 23:40:09 +02:00
NSLog ( @ "openFiles: %@" , arrayOfFilenames ) ;
2021-05-31 14:07:27 +02:00
2021-05-31 21:42:30 +02:00
arrayOfFilesToProcess = arrayOfFilenames ;
2021-05-24 11:24:32 +02:00
2021-05-31 23:31:45 +02:00
if ( appRunning ) {
if ( ! unarchiver ) {
unarchiver = [ [ TDNUnarchiver alloc ] init ] ;
unarchiver . quietUnrar = self ;
}
dispatch_async ( dispatch_get _global _queue ( DISPATCH_QUEUE _PRIORITY _HIGH , 0 ) , ^ {
for ( NSString * filename in self -> arrayOfFilesToProcess ) {
BOOL extracted = [ self -> unarchiver extractArchiveWithFilename : filename ] ;
if ( extracted ) {
// post notification based on user preference
if ( self -> userDefaults . showNotification && self -> userDefaults . notificationsAllowed ) { // if show notification + permission granted . . .
[ self postNotificationUncompressedFile : filename ] ;
// maybe don ' t want to spam lots of notifications if unarchiving a lot of archives
}
}
}
} ) ;
}
2021-05-31 14:07:27 +02:00
}
2009-11-15 00:18:58 +01:00
2021-05-31 23:31:45 +02:00
- ( BOOL ) application : ( id ) sender openFileWithoutUI : ( NSString * ) filename {
NSLog ( @ "called openFileWithoutUI %@" , filename ) ;
2021-05-31 14:07:27 +02:00
return YES ;
2009-11-14 23:12:16 +01:00
}
2021-05-31 23:31:45 +02:00
- ( BOOL ) applicationShouldTerminateAfterLastWindowClosed : ( NSApplication * ) sender {
// Possibly not the behaviour wanted
if ( userDefaults . hideDock ) {
NSLog ( @ "applicationShouldTerminateAfterLastWindowClosed -- NO" ) ;
return NO ;
} else {
NSLog ( @ "applicationShouldTerminateAfterLastWindowClosed -- YES" ) ;
return YES ;
}
}
2021-05-31 14:07:27 +02:00
# pragma mark UI Methods
2009-11-16 15:00:11 +01:00
// Presents a dialog to the user allowing them to Skip a file or overwrite an existing version
// returns YES or NO
2009-11-15 13:54:07 +01:00
- ( BOOL ) shouldFileBeReplaced : ( NSString * ) filename {
2021-05-31 23:40:09 +02:00
BOOL result = NO ;
NSAlert * alert = [ [ NSAlert alloc ] init ] ;
[ alert addButtonWithTitle : @ "Overwrite" ] ;
NSButton * skipButton = [ alert addButtonWithTitle : @ "Skip" ] ;
[ skipButton setKeyEquivalent : @ "\e" ] ;
[ alert setMessageText : [ NSString stringWithFormat : @ "Overwrite %@?" , filename ] ] ;
[ alert setInformativeText : [ NSString stringWithFormat : @ "The file %@ already exists. Do you wish to extract it again, overwriting the original file?" , filename ] ] ;
2021-05-24 11:24:32 +02:00
[ alert setAlertStyle : NSAlertStyleWarning ] ;
2021-05-31 23:40:09 +02:00
if ( [ alert runModal ] = = NSAlertFirstButtonReturn ) {
result = YES ;
}
2021-05-24 11:24:32 +02:00
2021-05-31 23:40:09 +02:00
return result ;
2009-11-15 13:54:07 +01:00
}
2009-11-16 15:00:11 +01:00
// Indicate to the user that part of the RAR volume is missing .
2009-11-15 15:43:54 +01:00
- ( void ) alertUserOfMissing : ( const char * ) volume {
2021-05-31 23:40:09 +02:00
NSAlert * alert = [ [ NSAlert alloc ] init ] ;
[ alert addButtonWithTitle : @ "OK" ] ;
[ alert setMessageText : [ NSString stringWithFormat : @ "Archive part %s is missing." , volume ] ] ;
[ alert setInformativeText : @ "Unable to extract all files from RAR archive as part of it is missing" ] ;
2021-05-24 11:24:32 +02:00
[ alert setAlertStyle : NSAlertStyleCritical ] ;
2021-05-31 23:40:09 +02:00
[ alert runModal ] ;
2009-11-15 15:43:54 +01:00
}
2009-11-16 15:00:11 +01:00
// Creates a dialog with a custom view with a NSSecureTextField which is displayed
// to the user so they can provide a password . Returns the entered password or nil
- ( NSString * ) requestArchivePassword {
2021-05-31 23:40:09 +02:00
if ( ! passwordView ) {
2021-05-24 11:24:32 +02:00
NSBundle * bundle = [ NSBundle bundleForClass : [ self class ] ] ;
[ bundle loadNibNamed : @ "PasswordView" owner : self topLevelObjects : nil ] ;
2021-05-24 17:37:15 +02:00
} else {
[ passwordField setStringValue : @ "" ] ;
}
2021-05-24 11:24:32 +02:00
2021-05-31 23:40:09 +02:00
NSString * password = nil ;
2021-05-24 11:24:32 +02:00
2021-05-31 23:40:09 +02:00
NSAlert * alert = [ [ NSAlert alloc ] init ] ;
2009-11-15 18:50:12 +01:00
[ alert addButtonWithTitle : @ "OK" ] ;
[ alert addButtonWithTitle : @ "Cancel" ] ;
[ alert setMessageText : @ "Archive Requires a password" ] ;
[ alert setInformativeText : @ "To extract the contents of this archive a password is required." ] ;
2021-05-31 23:40:09 +02:00
[ alert setAccessoryView : passwordView ] ;
2021-05-24 11:24:32 +02:00
[ alert setAlertStyle : NSAlertStyleWarning ] ;
2021-05-31 23:40:09 +02:00
if ( [ alert runModal ] = = NSAlertFirstButtonReturn ) {
password = [ passwordField stringValue ] ;
}
2021-05-24 11:24:32 +02:00
2021-05-31 23:40:09 +02:00
return password ;
2009-11-15 18:50:12 +01:00
}
2021-05-31 21:42:30 +02:00
- ( void ) hideDockIcon : ( BOOL ) hide {
BOOL result ;
if ( hide ) {
2021-05-31 23:31:45 +02:00
NSLog ( @ "Setting Policy to Accessory" ) ;
2021-05-31 21:42:30 +02:00
result = [ NSApp setActivationPolicy : NSApplicationActivationPolicyAccessory ] ;
NSLog ( @ "Result of setting ActivationPolicy %d" , result ) ;
[ self showStatusBarItem : TRUE ] ;
} else {
NSLog ( @ "Setting Policy to Regular" ) ;
result = [ NSApp setActivationPolicy : NSApplicationActivationPolicyRegular ] ;
NSLog ( @ "Result of setting ActivationPolicy %d" , result ) ;
[ self showStatusBarItem : FALSE ] ;
}
}
- ( void ) showStatusBarItem : ( BOOL ) show {
if ( show ) {
2021-05-31 23:42:01 +02:00
statusBarItem = [ NSStatusBar . systemStatusBar statusItemWithLength : NSVariableStatusItemLength ] ;
statusBarItem . button . title = @ "🎫" ; // RMCG change to something more appropriate
[ statusBarItem setMenu : [ self makeStatusBarMenu ] ] ;
} else {
[ NSStatusBar . systemStatusBar removeStatusItem : statusBarItem ] ;
}
}
2021-05-31 21:42:30 +02:00
2021-05-31 23:42:01 +02:00
- ( NSMenu * ) makeStatusBarMenu {
NSMenu * statusBarMenu = [ [ NSMenu alloc ] init ] ;
[ statusBarMenu setTitle : @ "QuietUnrar Menu" ] ;
2021-05-31 21:42:30 +02:00
2021-05-31 23:42:01 +02:00
NSMenuItem * preferencesMenuItem = [ [ NSMenuItem alloc ] initWithTitle : @ "Show Preferences" action : @ selector ( showPreferencesWindow ) keyEquivalent : @ "" ] ;
[ statusBarMenu addItem : preferencesMenuItem ] ;
2021-05-31 21:42:30 +02:00
2021-05-31 23:42:01 +02:00
// NSMenuItem * showDockItem = [ [ NSMenuItem alloc ] initWithTitle : @ "Show Dock " action : @ selector ( showPreferencesWindow ) keyEquivalent : @ "" ] ;
// [ statusBarMenu addItem : showDockItem ] ;
//
NSMenuItem * quitMenuItem = [ [ NSMenuItem alloc ] initWithTitle : @ "Quit QuietUnrar" action : @ selector ( quit ) keyEquivalent : @ "" ] ;
[ statusBarMenu addItem : quitMenuItem ] ;
2021-05-31 21:42:30 +02:00
2021-05-31 23:42:01 +02:00
return statusBarMenu ;
2021-05-31 21:42:30 +02:00
}
- ( void ) showPreferencesWindow {
if ( preferencesWindowController = = nil ) {
preferencesWindowController = [ [ TDNPreferencesWindowController alloc ] init ] ;
preferencesWindowController . quietUnrar = self ;
}
2021-06-01 00:03:20 +02:00
[ preferencesWindowController . window makeKeyAndOrderFront : self ] ;
[ NSApp activateIgnoringOtherApps : YES ] ;
2021-05-31 21:42:30 +02:00
}
- ( void ) quit {
[ [ NSApplication sharedApplication ] terminate : self ] ;
}
2021-05-31 14:07:27 +02:00
# pragma mark "Notifications"
- ( void ) requestUserPermissionForNotifications {
UNUserNotificationCenter * center = [ UNUserNotificationCenter currentNotificationCenter ] ;
[ center requestAuthorizationWithOptions : ( UNAuthorizationOptionAlert + UNAuthorizationOptionSound )
2021-05-31 23:40:09 +02:00
completionHandler : ^ ( BOOL granted , NSError * _Nullable error ) {
// Enable or disable features based on authorization .
2021-05-31 14:07:27 +02:00
if ( granted ) {
// set some flag , that would be used to see if notifications should be posted
NSLog ( @ "Notification Permission Granted" ) ;
2021-05-31 21:42:30 +02:00
self -> userDefaults . notificationsAllowed = TRUE ;
2021-05-31 14:07:27 +02:00
}
} ] ;
}
- ( void ) postNotificationUncompressedFile : ( NSString * ) filename {
// add details of notification
2021-05-31 21:42:30 +02:00
NSLog ( @ "Posting notification for %@" , filename ) ;
2021-05-31 14:07:27 +02:00
}
2009-11-10 16:48:42 +01:00
@ end