mirror of
https://github.com/ksherlock/ample.git
synced 2025-02-08 12:30:52 +00:00
download manager improvements
- better dark mode support - open roms button - refresh button - UI to specify file location and file extension - check for 404, etc errors which aren't auto converted to an NSError.
This commit is contained in:
parent
f9d4489e48
commit
d06bf9b1d6
@ -154,7 +154,7 @@
|
|||||||
</connections>
|
</connections>
|
||||||
</textField>
|
</textField>
|
||||||
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Fhd-vr-Q2G">
|
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Fhd-vr-Q2G">
|
||||||
<rect key="frame" x="20" y="19" width="124" height="23"/>
|
<rect key="frame" x="192" y="18" width="124" height="23"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||||
<buttonCell key="cell" type="roundTextured" title="Download Missing" bezelStyle="texturedRounded" alignment="center" lineBreakMode="truncatingTail" state="on" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="AKx-eg-iLS">
|
<buttonCell key="cell" type="roundTextured" title="Download Missing" bezelStyle="texturedRounded" alignment="center" lineBreakMode="truncatingTail" state="on" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="AKx-eg-iLS">
|
||||||
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||||
@ -169,6 +169,52 @@
|
|||||||
</binding>
|
</binding>
|
||||||
</connections>
|
</connections>
|
||||||
</button>
|
</button>
|
||||||
|
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="d2z-4T-Wh1">
|
||||||
|
<rect key="frame" x="10" y="104" width="30" height="16"/>
|
||||||
|
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||||
|
<textFieldCell key="cell" lineBreakMode="clipping" title="URL" id="lcZ-R4-WsS">
|
||||||
|
<font key="font" metaFont="system"/>
|
||||||
|
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||||
|
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||||
|
</textFieldCell>
|
||||||
|
</textField>
|
||||||
|
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="ZXO-bJ-btp">
|
||||||
|
<rect key="frame" x="10" y="66" width="34" height="16"/>
|
||||||
|
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||||
|
<textFieldCell key="cell" lineBreakMode="clipping" title="Type" id="KGI-t9-OMF">
|
||||||
|
<font key="font" metaFont="system"/>
|
||||||
|
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||||
|
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||||
|
</textFieldCell>
|
||||||
|
</textField>
|
||||||
|
<box verticalHuggingPriority="750" fixedFrame="YES" boxType="separator" translatesAutoresizingMaskIntoConstraints="NO" id="AuM-pD-Gul">
|
||||||
|
<rect key="frame" x="12" y="52" width="368" height="5"/>
|
||||||
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxY="YES"/>
|
||||||
|
</box>
|
||||||
|
<button verticalHuggingPriority="750" fixedFrame="YES" imageHugsTitle="YES" translatesAutoresizingMaskIntoConstraints="NO" id="dpY-qZ-2Nk">
|
||||||
|
<rect key="frame" x="90" y="13" width="100" height="32"/>
|
||||||
|
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||||
|
<buttonCell key="cell" type="push" title="ROMs" bezelStyle="rounded" image="NSFolder" imagePosition="leading" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="E0t-sX-rgE">
|
||||||
|
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||||
|
<font key="font" metaFont="system"/>
|
||||||
|
</buttonCell>
|
||||||
|
<connections>
|
||||||
|
<action selector="showRomFolder:" target="-2" id="bys-Vs-b4m"/>
|
||||||
|
</connections>
|
||||||
|
</button>
|
||||||
|
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Lnv-mh-zAr">
|
||||||
|
<rect key="frame" x="6" y="13" width="87" height="32"/>
|
||||||
|
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||||
|
<buttonCell key="cell" type="push" title="Refresh" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="mYS-h7-GUa">
|
||||||
|
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||||
|
<font key="font" metaFont="system"/>
|
||||||
|
<string key="keyEquivalent">r</string>
|
||||||
|
<modifierMask key="keyEquivalentModifierMask" command="YES"/>
|
||||||
|
</buttonCell>
|
||||||
|
<connections>
|
||||||
|
<action selector="refreshROMs:" target="-2" id="E7j-Fa-IN1"/>
|
||||||
|
</connections>
|
||||||
|
</button>
|
||||||
<popUpButton verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="2Rg-eX-DUq">
|
<popUpButton verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="2Rg-eX-DUq">
|
||||||
<rect key="frame" x="49" y="60" width="98" height="25"/>
|
<rect key="frame" x="49" y="60" width="98" height="25"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||||
@ -191,28 +237,6 @@
|
|||||||
</binding>
|
</binding>
|
||||||
</connections>
|
</connections>
|
||||||
</popUpButton>
|
</popUpButton>
|
||||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="d2z-4T-Wh1">
|
|
||||||
<rect key="frame" x="10" y="104" width="30" height="16"/>
|
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
|
||||||
<textFieldCell key="cell" lineBreakMode="clipping" title="URL" id="lcZ-R4-WsS">
|
|
||||||
<font key="font" metaFont="system"/>
|
|
||||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
|
||||||
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
|
||||||
</textFieldCell>
|
|
||||||
</textField>
|
|
||||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="ZXO-bJ-btp">
|
|
||||||
<rect key="frame" x="11" y="66" width="34" height="16"/>
|
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
|
||||||
<textFieldCell key="cell" lineBreakMode="clipping" title="Type" id="KGI-t9-OMF">
|
|
||||||
<font key="font" metaFont="system"/>
|
|
||||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
|
||||||
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
|
||||||
</textFieldCell>
|
|
||||||
</textField>
|
|
||||||
<box verticalHuggingPriority="750" fixedFrame="YES" boxType="separator" translatesAutoresizingMaskIntoConstraints="NO" id="AuM-pD-Gul">
|
|
||||||
<rect key="frame" x="12" y="52" width="368" height="5"/>
|
|
||||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxY="YES"/>
|
|
||||||
</box>
|
|
||||||
</subviews>
|
</subviews>
|
||||||
</view>
|
</view>
|
||||||
<connections>
|
<connections>
|
||||||
@ -248,4 +272,7 @@
|
|||||||
</menu>
|
</menu>
|
||||||
<userDefaultsController representsSharedInstance="YES" id="721-9N-Bma"/>
|
<userDefaultsController representsSharedInstance="YES" id="721-9N-Bma"/>
|
||||||
</objects>
|
</objects>
|
||||||
|
<resources>
|
||||||
|
<image name="NSFolder" width="32" height="32"/>
|
||||||
|
</resources>
|
||||||
</document>
|
</document>
|
||||||
|
@ -177,7 +177,6 @@ enum {
|
|||||||
NSDictionary *d = [NSDictionary dictionaryWithContentsOfURL: url];
|
NSDictionary *d = [NSDictionary dictionaryWithContentsOfURL: url];
|
||||||
|
|
||||||
NSURL *sd = SupportDirectory();
|
NSURL *sd = SupportDirectory();
|
||||||
NSString *romdir = [SupportDirectoryPath() stringByAppendingPathComponent: @"roms"];
|
|
||||||
|
|
||||||
_romFolder = [sd URLByAppendingPathComponent: @"roms"];
|
_romFolder = [sd URLByAppendingPathComponent: @"roms"];
|
||||||
|
|
||||||
@ -215,26 +214,11 @@ enum {
|
|||||||
[item setIndex: ix++];
|
[item setIndex: ix++];
|
||||||
|
|
||||||
[tmp addObject: item];
|
[tmp addObject: item];
|
||||||
|
|
||||||
// check if the file exists.
|
|
||||||
NSString *s = [romdir stringByAppendingPathComponent: name];
|
|
||||||
NSString *path;
|
|
||||||
|
|
||||||
path = [s stringByAppendingPathExtension: @"zip"];
|
|
||||||
if ([fm fileExistsAtPath: path]) {
|
|
||||||
[item setStatus: ItemFound];
|
|
||||||
[item setLocalURL: [NSURL fileURLWithPath: path]];
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
path = [s stringByAppendingPathExtension: @"7z"];
|
|
||||||
if ([fm fileExistsAtPath: path]) {
|
|
||||||
[item setStatus: ItemFound];
|
|
||||||
[item setLocalURL: [NSURL fileURLWithPath: path]];
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
_items = tmp;
|
_items = tmp;
|
||||||
|
[self refreshROMs: nil];
|
||||||
|
|
||||||
|
//[_tableView reloadData];
|
||||||
NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
|
NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
|
||||||
_session = [NSURLSession sessionWithConfiguration: config delegate: self delegateQueue: nil];
|
_session = [NSURLSession sessionWithConfiguration: config delegate: self delegateQueue: nil];
|
||||||
_taskIndex = [NSMutableDictionary dictionaryWithCapacity: [_items count]];
|
_taskIndex = [NSMutableDictionary dictionaryWithCapacity: [_items count]];
|
||||||
@ -242,6 +226,8 @@ enum {
|
|||||||
//[self download];
|
//[self download];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
-(void)validateURL: (NSString *)url {
|
-(void)validateURL: (NSString *)url {
|
||||||
NSURL *v;
|
NSURL *v;
|
||||||
@ -385,6 +371,40 @@ enum {
|
|||||||
[_tableView reloadData];
|
[_tableView reloadData];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
- (IBAction)showRomFolder:(id)sender {
|
||||||
|
NSWorkspace *ws = [NSWorkspace sharedWorkspace];
|
||||||
|
|
||||||
|
[ws openURL: _romFolder];
|
||||||
|
}
|
||||||
|
|
||||||
|
-(IBAction)refreshROMs: (id)sender {
|
||||||
|
|
||||||
|
NSString *romdir = [SupportDirectoryPath() stringByAppendingPathComponent: @"roms"];
|
||||||
|
NSFileManager *fm = [NSFileManager defaultManager];
|
||||||
|
|
||||||
|
for (DownloadItem *item in _items) {
|
||||||
|
NSString *name = [item name];
|
||||||
|
NSString *s = [romdir stringByAppendingPathComponent: name];
|
||||||
|
NSString *path;
|
||||||
|
path = [s stringByAppendingPathExtension: @"zip"];
|
||||||
|
if ([fm fileExistsAtPath: path]) {
|
||||||
|
[item setStatus: ItemFound];
|
||||||
|
[item setLocalURL: [NSURL fileURLWithPath: path]];
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
path = [s stringByAppendingPathExtension: @"7z"];
|
||||||
|
if ([fm fileExistsAtPath: path]) {
|
||||||
|
[item setStatus: ItemFound];
|
||||||
|
[item setLocalURL: [NSURL fileURLWithPath: path]];
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
// only needed if items aren't bound.
|
||||||
|
[_tableView reloadData];
|
||||||
|
}
|
||||||
|
|
||||||
- (IBAction)showInFinder:(id)sender {
|
- (IBAction)showInFinder:(id)sender {
|
||||||
DownloadItem *item = [self clickedItem];
|
DownloadItem *item = [self clickedItem];
|
||||||
@ -431,11 +451,31 @@ enum {
|
|||||||
|
|
||||||
#pragma mark - NSURLSessionDelegate
|
#pragma mark - NSURLSessionDelegate
|
||||||
|
|
||||||
|
static NSInteger TaskStatusCode(NSURLSessionTask *task) {
|
||||||
|
NSURLResponse *response = [task response];
|
||||||
|
if ([response isKindOfClass: [NSHTTPURLResponse class]]) {
|
||||||
|
return [(NSHTTPURLResponse *)response statusCode];
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
-(void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error {
|
-(void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error {
|
||||||
|
|
||||||
|
|
||||||
if (error) NSLog(@"Download error: %@", error);
|
if (error) NSLog(@"Download error: %@", error);
|
||||||
|
|
||||||
|
NSInteger statusCode = TaskStatusCode(task);
|
||||||
|
if (!error && statusCode != 200) {
|
||||||
|
// treat as an error.
|
||||||
|
NSDictionary *info = @{
|
||||||
|
NSURLErrorKey: [[task originalRequest] URL],
|
||||||
|
NSLocalizedDescriptionKey: [NSHTTPURLResponse localizedStringForStatusCode: statusCode],
|
||||||
|
};
|
||||||
|
error = [NSError errorWithDomain: NSURLErrorDomain code: NSURLErrorFileDoesNotExist userInfo: info];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// not sure if strictly necessary but this happens in a background thread
|
// not sure if strictly necessary but this happens in a background thread
|
||||||
// and these are used in KVO binding. Also, main thread only
|
// and these are used in KVO binding. Also, main thread only
|
||||||
// means no race conditions.
|
// means no race conditions.
|
||||||
@ -465,7 +505,13 @@ enum {
|
|||||||
|
|
||||||
- (void)URLSession:(NSURLSession *)session downloadTask:(nonnull NSURLSessionDownloadTask *)task didFinishDownloadingToURL:(nonnull NSURL *)location {
|
- (void)URLSession:(NSURLSession *)session downloadTask:(nonnull NSURLSessionDownloadTask *)task didFinishDownloadingToURL:(nonnull NSURL *)location {
|
||||||
|
|
||||||
|
|
||||||
// NSLog(@"%@", task);
|
// NSLog(@"%@", task);
|
||||||
|
// NSLog(@"%@", [task response]);
|
||||||
|
|
||||||
|
if (TaskStatusCode(task) != 200) return;
|
||||||
|
|
||||||
|
|
||||||
// need to move to the destination directory...
|
// need to move to the destination directory...
|
||||||
// file deleted after this function returns, so can't move asynchronously.
|
// file deleted after this function returns, so can't move asynchronously.
|
||||||
NSFileManager *fm = [NSFileManager defaultManager];
|
NSFileManager *fm = [NSFileManager defaultManager];
|
||||||
@ -585,7 +631,7 @@ enum {
|
|||||||
@"Canceled",
|
@"Canceled",
|
||||||
@"Error"
|
@"Error"
|
||||||
};
|
};
|
||||||
if (_error) return [_error description];
|
if (_error) return [_error localizedDescription];
|
||||||
|
|
||||||
if (_status > sizeof(Names)/sizeof(Names[0])) return @"Unknown";
|
if (_status > sizeof(Names)/sizeof(Names[0])) return @"Unknown";
|
||||||
return Names[_status];
|
return Names[_status];
|
||||||
|
Loading…
x
Reference in New Issue
Block a user