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 */; };
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 */; };
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 */; };
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 */; };
@@ -1236,6 +1237,8 @@
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>"; };
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>"; };
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>"; };
@@ -1537,6 +1540,8 @@
A222E9860E6B21D9009FB003 /* BlocklistDownloaderViewController.mm */,
A222EA790E6C32C4009FB003 /* BlocklistScheduler.h */,
A222EA7A0E6C32C4009FB003 /* BlocklistScheduler.mm */,
ED86936D2ADAE34D00342B1A /* DefaultAppHelper.h */,
ED86936E2ADAE34D00342B1A /* DefaultAppHelper.mm */,
A2AB883916A399A6008FAD50 /* VDKQueue */,
);
name = Sources;
@@ -3078,6 +3083,7 @@
buildActionMask = 2147483647;
files = (
C86BCD9928228A9600F45599 /* SparkleProxy.mm in Sources */,
ED86936F2ADAE34D00342B1A /* DefaultAppHelper.mm in Sources */,
A225A4C0187E369C00CDE823 /* ShareToolbarItem.mm in Sources */,
A2D77453154CC72B00A62B93 /* WebSeedTableView.mm in Sources */,
8D11072D0486CEB800E47090 /* main.mm in Sources */,

View File

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