refactor: move macOS default app logic to dedicated class (#6120)

This commit is contained in:
Dzmitry Neviadomski
2023-10-31 03:44:32 +03:00
committed by GitHub
parent aa307d5696
commit 1c18737e67
5 changed files with 224 additions and 42 deletions

View File

@@ -449,6 +449,7 @@
ED20B87C28589274005FA6BE /* common_defs.h in Headers */ = {isa = PBXBuildFile; fileRef = ED20B87B28589274005FA6BE /* common_defs.h */; }; ED20B87C28589274005FA6BE /* common_defs.h in Headers */ = {isa = PBXBuildFile; fileRef = ED20B87B28589274005FA6BE /* common_defs.h */; };
ED20B87F285892C5005FA6BE /* crc32_multipliers.h in Headers */ = {isa = PBXBuildFile; fileRef = ED20B87D285892C5005FA6BE /* crc32_multipliers.h */; }; ED20B87F285892C5005FA6BE /* crc32_multipliers.h in Headers */ = {isa = PBXBuildFile; fileRef = ED20B87D285892C5005FA6BE /* crc32_multipliers.h */; };
ED20B880285892C5005FA6BE /* crc32_tables.h in Headers */ = {isa = PBXBuildFile; fileRef = ED20B87E285892C5005FA6BE /* crc32_tables.h */; }; ED20B880285892C5005FA6BE /* crc32_tables.h in Headers */ = {isa = PBXBuildFile; fileRef = ED20B87E285892C5005FA6BE /* crc32_tables.h */; };
ED86936F2ADAE34D00342B1A /* DefaultAppHelper.mm in Sources */ = {isa = PBXBuildFile; fileRef = ED86936E2ADAE34D00342B1A /* DefaultAppHelper.mm */; };
ED8A163F2735A8AA000D61F9 /* peer-mgr-active-requests.h in Headers */ = {isa = PBXBuildFile; fileRef = ED8A163B2735A8AA000D61F9 /* peer-mgr-active-requests.h */; }; ED8A163F2735A8AA000D61F9 /* peer-mgr-active-requests.h in Headers */ = {isa = PBXBuildFile; fileRef = ED8A163B2735A8AA000D61F9 /* peer-mgr-active-requests.h */; };
ED8A16402735A8AA000D61F9 /* peer-mgr-active-requests.cc in Sources */ = {isa = PBXBuildFile; fileRef = ED8A163C2735A8AA000D61F9 /* peer-mgr-active-requests.cc */; }; ED8A16402735A8AA000D61F9 /* peer-mgr-active-requests.cc in Sources */ = {isa = PBXBuildFile; fileRef = ED8A163C2735A8AA000D61F9 /* peer-mgr-active-requests.cc */; };
ED8A16412735A8AA000D61F9 /* peer-mgr-wishlist.h in Headers */ = {isa = PBXBuildFile; fileRef = ED8A163D2735A8AA000D61F9 /* peer-mgr-wishlist.h */; }; ED8A16412735A8AA000D61F9 /* peer-mgr-wishlist.h in Headers */ = {isa = PBXBuildFile; fileRef = ED8A163D2735A8AA000D61F9 /* peer-mgr-wishlist.h */; };
@@ -1236,6 +1237,8 @@
ED20B87B28589274005FA6BE /* common_defs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = common_defs.h; sourceTree = "<group>"; }; ED20B87B28589274005FA6BE /* common_defs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = common_defs.h; sourceTree = "<group>"; };
ED20B87D285892C5005FA6BE /* crc32_multipliers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = crc32_multipliers.h; path = lib/crc32_multipliers.h; sourceTree = "<group>"; }; ED20B87D285892C5005FA6BE /* crc32_multipliers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = crc32_multipliers.h; path = lib/crc32_multipliers.h; sourceTree = "<group>"; };
ED20B87E285892C5005FA6BE /* crc32_tables.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = crc32_tables.h; path = lib/crc32_tables.h; sourceTree = "<group>"; }; ED20B87E285892C5005FA6BE /* crc32_tables.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = crc32_tables.h; path = lib/crc32_tables.h; sourceTree = "<group>"; };
ED86936D2ADAE34D00342B1A /* DefaultAppHelper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DefaultAppHelper.h; sourceTree = "<group>"; };
ED86936E2ADAE34D00342B1A /* DefaultAppHelper.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = DefaultAppHelper.mm; sourceTree = "<group>"; };
ED8A163B2735A8AA000D61F9 /* peer-mgr-active-requests.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "peer-mgr-active-requests.h"; sourceTree = "<group>"; }; ED8A163B2735A8AA000D61F9 /* peer-mgr-active-requests.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "peer-mgr-active-requests.h"; sourceTree = "<group>"; };
ED8A163C2735A8AA000D61F9 /* peer-mgr-active-requests.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "peer-mgr-active-requests.cc"; sourceTree = "<group>"; }; ED8A163C2735A8AA000D61F9 /* peer-mgr-active-requests.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "peer-mgr-active-requests.cc"; sourceTree = "<group>"; };
ED8A163D2735A8AA000D61F9 /* peer-mgr-wishlist.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "peer-mgr-wishlist.h"; sourceTree = "<group>"; }; ED8A163D2735A8AA000D61F9 /* peer-mgr-wishlist.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "peer-mgr-wishlist.h"; sourceTree = "<group>"; };
@@ -1537,6 +1540,8 @@
A222E9860E6B21D9009FB003 /* BlocklistDownloaderViewController.mm */, A222E9860E6B21D9009FB003 /* BlocklistDownloaderViewController.mm */,
A222EA790E6C32C4009FB003 /* BlocklistScheduler.h */, A222EA790E6C32C4009FB003 /* BlocklistScheduler.h */,
A222EA7A0E6C32C4009FB003 /* BlocklistScheduler.mm */, A222EA7A0E6C32C4009FB003 /* BlocklistScheduler.mm */,
ED86936D2ADAE34D00342B1A /* DefaultAppHelper.h */,
ED86936E2ADAE34D00342B1A /* DefaultAppHelper.mm */,
A2AB883916A399A6008FAD50 /* VDKQueue */, A2AB883916A399A6008FAD50 /* VDKQueue */,
); );
name = Sources; name = Sources;
@@ -3078,6 +3083,7 @@
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
C86BCD9928228A9600F45599 /* SparkleProxy.mm in Sources */, C86BCD9928228A9600F45599 /* SparkleProxy.mm in Sources */,
ED86936F2ADAE34D00342B1A /* DefaultAppHelper.mm in Sources */,
A225A4C0187E369C00CDE823 /* ShareToolbarItem.mm in Sources */, A225A4C0187E369C00CDE823 /* ShareToolbarItem.mm in Sources */,
A2D77453154CC72B00A62B93 /* WebSeedTableView.mm in Sources */, A2D77453154CC72B00A62B93 /* WebSeedTableView.mm in Sources */,
8D11072D0486CEB800E47090 /* main.mm in Sources */, 8D11072D0486CEB800E47090 /* main.mm in Sources */,

View File

@@ -62,6 +62,8 @@ target_sources(${TR_NAME}-mac
Controller.mm Controller.mm
CreatorWindowController.h CreatorWindowController.h
CreatorWindowController.mm CreatorWindowController.mm
DefaultAppHelper.h
DefaultAppHelper.mm
DragOverlayView.h DragOverlayView.h
DragOverlayView.mm DragOverlayView.mm
DragOverlayWindow.h DragOverlayWindow.h

15
macosx/DefaultAppHelper.h Normal file
View File

@@ -0,0 +1,15 @@
// This file Copyright © 2007-2023 Transmission authors and contributors.
// It may be used under the MIT (SPDX: MIT) license.
// License text can be found in the licenses/ folder.
#import <Foundation/Foundation.h>
@interface DefaultAppHelper : NSObject
- (BOOL)isDefaultForTorrentFiles;
- (void)setDefaultForTorrentFiles:(void (^_Nullable)())completionHandler;
- (BOOL)isDefaultForMagnetURLs;
- (void)setDefaultForMagnetURLs:(void (^_Nullable)())completionHandler;
@end

183
macosx/DefaultAppHelper.mm Normal file
View File

@@ -0,0 +1,183 @@
// This file Copyright © 2007-2023 Transmission authors and contributors.
// It may be used under the MIT (SPDX: MIT) license.
// License text can be found in the licenses/ folder.
#import "DefaultAppHelper.h"
#import <AppKit/AppKit.h>
#import <UniformTypeIdentifiers/UniformTypeIdentifiers.h>
static NSString* const kMagnetURLScheme = @"magnet";
static NSString* const kTorrentFileType = @"org.bittorrent.torrent";
UTType* GetTorrentFileType(void) API_AVAILABLE(macos(11.0))
{
static UTType* result = nil;
static dispatch_once_t once;
dispatch_once(&once, ^{
result = [UTType exportedTypeWithIdentifier:kTorrentFileType conformingToType:UTTypeData];
});
return result;
}
@interface DefaultAppHelper ()
@property(nonatomic, readonly) NSString* bundleIdentifier;
@end
@implementation DefaultAppHelper
- (instancetype)init
{
if (self = [super init])
{
_bundleIdentifier = NSBundle.mainBundle.bundleIdentifier;
}
return self;
}
- (BOOL)isDefaultForTorrentFiles
{
if (@available(macOS 12, *))
{
UTType* fileType = GetTorrentFileType();
NSURL* appUrl = [NSWorkspace.sharedWorkspace URLForApplicationToOpenContentType:fileType];
if (!appUrl)
{
return NO;
}
NSString* bundleId = [NSBundle bundleWithURL:appUrl].bundleIdentifier;
if ([self.bundleIdentifier isEqualToString:bundleId])
{
return YES;
}
}
else
{
NSString* bundleId = (__bridge NSString*)LSCopyDefaultRoleHandlerForContentType((__bridge CFStringRef)kTorrentFileType, kLSRolesViewer);
if (!bundleId)
{
return NO;
}
if ([self.bundleIdentifier isEqualToString:bundleId])
{
return YES;
}
}
return NO;
}
- (void)setDefaultForTorrentFiles:(void (^_Nullable)())completionHandler
{
if (@available(macOS 12, *))
{
UTType* fileType = GetTorrentFileType();
NSURL* appUrl = [NSWorkspace.sharedWorkspace URLForApplicationWithBundleIdentifier:self.bundleIdentifier];
[NSWorkspace.sharedWorkspace setDefaultApplicationAtURL:appUrl toOpenContentType:fileType completionHandler:^(NSError* error) {
if (error)
{
NSLog(@"Failed setting default torrent file handler: %@", error.localizedDescription);
}
if (completionHandler != nil)
{
dispatch_async(dispatch_get_main_queue(), ^{
completionHandler();
});
}
}];
}
else
{
OSStatus const result = LSSetDefaultRoleHandlerForContentType(
(__bridge CFStringRef)kTorrentFileType,
kLSRolesViewer,
(__bridge CFStringRef)self.bundleIdentifier);
if (result != noErr)
{
NSLog(@"Failed setting default torrent file handler");
}
if (completionHandler != nil)
{
completionHandler();
}
}
}
- (BOOL)isDefaultForMagnetURLs
{
if (@available(macOS 12, *))
{
NSURL* schemeUrl = [NSURL URLWithString:[kMagnetURLScheme stringByAppendingString:@":"]];
NSURL* appUrl = [NSWorkspace.sharedWorkspace URLForApplicationToOpenURL:schemeUrl];
if (!appUrl)
{
return NO;
}
NSString* bundleId = [NSBundle bundleWithURL:appUrl].bundleIdentifier;
if ([self.bundleIdentifier isEqualToString:bundleId])
{
return YES;
}
}
else
{
NSString* bundleId = (__bridge NSString*)LSCopyDefaultHandlerForURLScheme((__bridge CFStringRef)kMagnetURLScheme);
if (!bundleId)
{
return NO;
}
if ([self.bundleIdentifier isEqualToString:bundleId])
{
return YES;
}
}
return NO;
}
- (void)setDefaultForMagnetURLs:(void (^_Nullable)())completionHandler
{
if (@available(macOS 12, *))
{
NSURL* appUrl = [NSWorkspace.sharedWorkspace URLForApplicationWithBundleIdentifier:self.bundleIdentifier];
[NSWorkspace.sharedWorkspace setDefaultApplicationAtURL:appUrl toOpenURLsWithScheme:kMagnetURLScheme
completionHandler:^(NSError* error) {
if (error)
{
NSLog(@"Failed setting default magnet link handler: %@", error.localizedDescription);
}
if (completionHandler != nil)
{
dispatch_async(dispatch_get_main_queue(), ^{
completionHandler();
});
}
}];
}
else
{
OSStatus const result = LSSetDefaultHandlerForURLScheme(
(__bridge CFStringRef)kMagnetURLScheme,
(__bridge CFStringRef)self.bundleIdentifier);
if (result != noErr)
{
NSLog(@"Failed setting default magnet link handler");
}
if (completionHandler != nil)
{
completionHandler();
}
}
}
@end

View File

@@ -11,6 +11,7 @@
#import "BlocklistDownloaderViewController.h" #import "BlocklistDownloaderViewController.h"
#import "BlocklistScheduler.h" #import "BlocklistScheduler.h"
#import "Controller.h" #import "Controller.h"
#import "DefaultAppHelper.h"
#import "PortChecker.h" #import "PortChecker.h"
#import "BonjourController.h" #import "BonjourController.h"
#import "NSImageAdditions.h" #import "NSImageAdditions.h"
@@ -103,6 +104,7 @@ static NSString* const kWebUIURLFormat = @"http://localhost:%ld/";
@property(nonatomic, readonly) NSMutableArray<NSString*>* fRPCWhitelistArray; @property(nonatomic, readonly) NSMutableArray<NSString*>* fRPCWhitelistArray;
@property(nonatomic) IBOutlet NSSegmentedControl* fRPCAddRemoveControl; @property(nonatomic) IBOutlet NSSegmentedControl* fRPCAddRemoveControl;
@property(nonatomic, copy) NSString* fRPCPassword; @property(nonatomic, copy) NSString* fRPCPassword;
@property(nonatomic, readonly) DefaultAppHelper* fDefaultAppHelper;
@end @end
@@ -177,6 +179,8 @@ static NSString* const kWebUIURLFormat = @"http://localhost:%ld/";
} }
[self setAutoUpdateToBeta:nil]; [self setAutoUpdateToBeta:nil];
_fDefaultAppHelper = [[DefaultAppHelper alloc] init];
} }
return self; return self;
@@ -215,7 +219,7 @@ static NSString* const kWebUIURLFormat = @"http://localhost:%ld/";
[self setPrefView:nil]; [self setPrefView:nil];
[self updateDefaultsStatus]; [self updateDefaultsStates];
//set special-handling of magnet link add window checkbox //set special-handling of magnet link add window checkbox
[self updateShowAddMagnetWindowField]; [self updateShowAddMagnetWindowField];
@@ -859,55 +863,27 @@ static NSString* const kWebUIURLFormat = @"http://localhost:%ld/";
- (IBAction)setDefaultForMagnets:(id)sender - (IBAction)setDefaultForMagnets:(id)sender
{ {
NSString* bundleID = NSBundle.mainBundle.bundleIdentifier; PrefsController* __weak weakSelf = self;
OSStatus const result = LSSetDefaultHandlerForURLScheme((CFStringRef) @"magnet", (__bridge CFStringRef)bundleID); [self.fDefaultAppHelper setDefaultForMagnetURLs:^{
if (result != noErr) [weakSelf updateDefaultsStates];
{ }];
NSLog(@"Failed setting default magnet link handler");
}
[self updateDefaultsStatus];
} }
- (IBAction)setDefaultForTorrentFiles:(id)sender - (IBAction)setDefaultForTorrentFiles:(id)sender
{ {
NSString* bundleID = NSBundle.mainBundle.bundleIdentifier; PrefsController* __weak weakSelf = self;
OSStatus const result = LSSetDefaultRoleHandlerForContentType((CFStringRef) @"org.bittorrent.torrent", kLSRolesViewer, (__bridge CFStringRef)bundleID); [self.fDefaultAppHelper setDefaultForTorrentFiles:^{
if (result != noErr) [weakSelf updateDefaultsStates];
{ }];
NSLog(@"Failed setting default torrent file handler");
}
[self updateDefaultsStatus];
} }
- (void)updateDefaultsStatus - (void)updateDefaultsStates
{ {
BOOL isDefaultForMagnetSet = NO; BOOL const isDefaultForMagnetURLs = [self.fDefaultAppHelper isDefaultForMagnetURLs];
BOOL isDefaultForTorrentSet = NO; self.fSetDefaultForMagnetButton.enabled = !isDefaultForMagnetURLs;
NSString* bundleID = NSBundle.mainBundle.bundleIdentifier; BOOL const isDefaultForTorrentFiles = [self.fDefaultAppHelper isDefaultForTorrentFiles];
self.fSetDefaultForTorrentButton.enabled = !isDefaultForTorrentFiles;
NSString* const defaultBundleIdForMagnet = (__bridge NSString*)LSCopyDefaultHandlerForURLScheme((CFStringRef) @"magnet");
if (defaultBundleIdForMagnet)
{
if ([bundleID isEqualToString:defaultBundleIdForMagnet])
{
isDefaultForMagnetSet = YES;
}
}
NSString* const defaultBundleIdForTorrent = (__bridge NSString*)LSCopyDefaultRoleHandlerForContentType(
(CFStringRef) @"org.bittorrent.torrent",
kLSRolesViewer);
if (defaultBundleIdForTorrent)
{
if ([bundleID isEqualToString:defaultBundleIdForTorrent])
{
isDefaultForTorrentSet = YES;
}
}
self.fSetDefaultForMagnetButton.enabled = !isDefaultForMagnetSet;
self.fSetDefaultForTorrentButton.enabled = !isDefaultForTorrentSet;
} }
- (void)setQueue:(id)sender - (void)setQueue:(id)sender