mirror of
https://github.com/kiwix/kiwix-apple.git
synced 2025-09-27 22:10:57 -04:00
DownloadBookOperation
This commit is contained in:
parent
e524c5325c
commit
710cbc50d7
@ -27,7 +27,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
|
|||||||
|
|
||||||
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
|
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
|
||||||
NSURLProtocol.registerClass(KiwixURLProtocol)
|
NSURLProtocol.registerClass(KiwixURLProtocol)
|
||||||
Network.shared.restoreProgresses()
|
// Network.shared.restoreProgresses()
|
||||||
|
|
||||||
// Register notification
|
// Register notification
|
||||||
let settings = UIUserNotificationSettings(forTypes: [.Sound, .Alert, .Badge], categories: nil) // Here are the notification permission the app wants
|
let settings = UIUserNotificationSettings(forTypes: [.Sound, .Alert, .Badge], categories: nil) // Here are the notification permission the app wants
|
||||||
@ -132,7 +132,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func application(application: UIApplication, handleEventsForBackgroundURLSession identifier: String, completionHandler: () -> Void) {
|
func application(application: UIApplication, handleEventsForBackgroundURLSession identifier: String, completionHandler: () -> Void) {
|
||||||
Network.shared.rejoinSessionWithIdentifier(identifier, completionHandler: completionHandler)
|
// Network.shared.rejoinSessionWithIdentifier(identifier, completionHandler: completionHandler)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: Background Refresh
|
// MARK: Background Refresh
|
||||||
|
@ -80,19 +80,23 @@ class BookDetailController: UITableViewController, CenterButtonCellDelegate, DZN
|
|||||||
|
|
||||||
switch title {
|
switch title {
|
||||||
case Strings.downloadNow:
|
case Strings.downloadNow:
|
||||||
|
func startDownload() {
|
||||||
|
guard let bookID = book.id,
|
||||||
|
let download = DownloadBookOperation(bookID: bookID) else {return}
|
||||||
|
Network.shared.queue.addOperation(download)
|
||||||
|
}
|
||||||
|
|
||||||
if book.spaceState == .Caution {
|
if book.spaceState == .Caution {
|
||||||
let cancel = UIAlertAction(title: Strings.cancel, style: .Cancel, handler: nil)
|
let cancel = UIAlertAction(title: Strings.cancel, style: .Cancel, handler: nil)
|
||||||
let download = UIAlertAction(title: Strings.SpaceAlert.downloadAnyway, style: .Destructive, handler: { (alert) in
|
let download = UIAlertAction(title: Strings.SpaceAlert.downloadAnyway, style: .Destructive, handler: { (alert) in
|
||||||
|
startDownload()
|
||||||
})
|
})
|
||||||
let alertController = UIAlertController(title: Strings.SpaceAlert.spaceAlert, message: Strings.SpaceAlert.message, actions: [download, cancel])
|
let alertController = UIAlertController(title: Strings.SpaceAlert.spaceAlert, message: Strings.SpaceAlert.message, actions: [download, cancel])
|
||||||
presentViewController(alertController, animated: true, completion: nil)
|
presentViewController(alertController, animated: true, completion: nil)
|
||||||
} else {
|
} else {
|
||||||
|
startDownload()
|
||||||
}
|
}
|
||||||
// guard let download = DownloadBookOperation(book: book) else {return}
|
default:
|
||||||
// GlobalOperationQueue.sharedInstance.addOperation(download)
|
|
||||||
default:
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -47,8 +47,7 @@ class DownloadTasksController: UITableViewController, NSFetchedResultsController
|
|||||||
}
|
}
|
||||||
|
|
||||||
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
|
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
|
||||||
let cellIdentifier = "Cell"
|
let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath)
|
||||||
let cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier, forIndexPath: indexPath)
|
|
||||||
self.configureCell(cell, atIndexPath: indexPath)
|
self.configureCell(cell, atIndexPath: indexPath)
|
||||||
return cell
|
return cell
|
||||||
}
|
}
|
||||||
@ -60,9 +59,9 @@ class DownloadTasksController: UITableViewController, NSFetchedResultsController
|
|||||||
|
|
||||||
cell.titleLabel.text = book.title
|
cell.titleLabel.text = book.title
|
||||||
cell.favIcon.image = UIImage(data: book.favIcon ?? NSData())
|
cell.favIcon.image = UIImage(data: book.favIcon ?? NSData())
|
||||||
|
//
|
||||||
guard let progress = Network.shared.progresses[id] else {return}
|
// guard let progress = Network.shared.progresses[id] else {return}
|
||||||
cell.progressView.progress = Float(progress.fractionCompleted)
|
// cell.progressView.progress = Float(progress.fractionCompleted)
|
||||||
|
|
||||||
// switch downloadTask.state {
|
// switch downloadTask.state {
|
||||||
// case .Queued, .Downloading:
|
// case .Queued, .Downloading:
|
||||||
|
@ -49,7 +49,7 @@
|
|||||||
</dict>
|
</dict>
|
||||||
</array>
|
</array>
|
||||||
<key>CFBundleVersion</key>
|
<key>CFBundleVersion</key>
|
||||||
<string>1.7.1326</string>
|
<string>1.7.1353</string>
|
||||||
<key>ITSAppUsesNonExemptEncryption</key>
|
<key>ITSAppUsesNonExemptEncryption</key>
|
||||||
<false/>
|
<false/>
|
||||||
<key>LSRequiresIPhoneOS</key>
|
<key>LSRequiresIPhoneOS</key>
|
||||||
|
@ -14,7 +14,7 @@ class Network: NSObject, NSURLSessionDelegate, NSURLSessionDownloadDelegate, NSU
|
|||||||
weak var delegate: DownloadProgressReporting?
|
weak var delegate: DownloadProgressReporting?
|
||||||
|
|
||||||
private let context = NSManagedObjectContext.mainQueueContext
|
private let context = NSManagedObjectContext.mainQueueContext
|
||||||
let operationQueue = OperationQueue()
|
let queue = OperationQueue()
|
||||||
|
|
||||||
var progresses = [String: DownloadProgress]()
|
var progresses = [String: DownloadProgress]()
|
||||||
private var timer: NSTimer?
|
private var timer: NSTimer?
|
||||||
@ -30,7 +30,7 @@ class Network: NSObject, NSURLSessionDelegate, NSURLSessionDownloadDelegate, NSU
|
|||||||
|
|
||||||
override init() {
|
override init() {
|
||||||
super.init()
|
super.init()
|
||||||
operationQueue.delegate = self
|
queue.delegate = self
|
||||||
}
|
}
|
||||||
|
|
||||||
func restoreProgresses() {
|
func restoreProgresses() {
|
||||||
@ -44,7 +44,7 @@ class Network: NSObject, NSURLSessionDelegate, NSURLSessionDownloadDelegate, NSU
|
|||||||
let operation = URLSessionDownloadTaskOperation(downloadTask: task)
|
let operation = URLSessionDownloadTaskOperation(downloadTask: task)
|
||||||
operation.name = task.taskDescription
|
operation.name = task.taskDescription
|
||||||
operation.addObserver(NetworkObserver())
|
operation.addObserver(NetworkObserver())
|
||||||
self.operationQueue.addOperation(operation)
|
self.queue.addOperation(operation)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -77,13 +77,13 @@ class Network: NSObject, NSURLSessionDelegate, NSURLSessionDownloadDelegate, NSU
|
|||||||
|
|
||||||
func pause(book: Book) {
|
func pause(book: Book) {
|
||||||
guard let id = book.id,
|
guard let id = book.id,
|
||||||
let operation = operationQueue.getOperation(id) as? URLSessionDownloadTaskOperation else {return}
|
let operation = queue.getOperation(id) as? URLSessionDownloadTaskOperation else {return}
|
||||||
operation.cancel(produceResumeData: true)
|
operation.cancel(produceResumeData: true)
|
||||||
}
|
}
|
||||||
|
|
||||||
func cancel(book: Book) {
|
func cancel(book: Book) {
|
||||||
guard let id = book.id,
|
guard let id = book.id,
|
||||||
let operation = operationQueue.getOperation(id) as? URLSessionDownloadTaskOperation else {return}
|
let operation = queue.getOperation(id) as? URLSessionDownloadTaskOperation else {return}
|
||||||
operation.cancel(produceResumeData: false)
|
operation.cancel(produceResumeData: false)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -97,7 +97,7 @@ class Network: NSObject, NSURLSessionDelegate, NSURLSessionDownloadDelegate, NSU
|
|||||||
let operation = URLSessionDownloadTaskOperation(downloadTask: task)
|
let operation = URLSessionDownloadTaskOperation(downloadTask: task)
|
||||||
operation.name = id
|
operation.name = id
|
||||||
operation.addObserver(NetworkObserver())
|
operation.addObserver(NetworkObserver())
|
||||||
operationQueue.addOperation(operation)
|
queue.addOperation(operation)
|
||||||
|
|
||||||
let progress = DownloadProgress(book: book)
|
let progress = DownloadProgress(book: book)
|
||||||
progress.downloadStarted(task)
|
progress.downloadStarted(task)
|
||||||
@ -107,7 +107,7 @@ class Network: NSObject, NSURLSessionDelegate, NSURLSessionDownloadDelegate, NSU
|
|||||||
// MARK: - OperationQueueDelegate
|
// MARK: - OperationQueueDelegate
|
||||||
|
|
||||||
func operationQueue(queue: OperationQueue, willAddOperation operation: NSOperation) {
|
func operationQueue(queue: OperationQueue, willAddOperation operation: NSOperation) {
|
||||||
guard operationQueue.operationCount == 0 else {return}
|
guard queue.operationCount == 0 else {return}
|
||||||
shouldReportProgress = true
|
shouldReportProgress = true
|
||||||
NSOperationQueue.mainQueue().addOperationWithBlock { () -> Void in
|
NSOperationQueue.mainQueue().addOperationWithBlock { () -> Void in
|
||||||
self.timer = NSTimer.scheduledTimerWithTimeInterval(1.0, target: self, selector: #selector(Network.resetProgressReportingFlag), userInfo: nil, repeats: true)
|
self.timer = NSTimer.scheduledTimerWithTimeInterval(1.0, target: self, selector: #selector(Network.resetProgressReportingFlag), userInfo: nil, repeats: true)
|
||||||
@ -117,7 +117,7 @@ class Network: NSObject, NSURLSessionDelegate, NSURLSessionDownloadDelegate, NSU
|
|||||||
func operationQueue(queue: OperationQueue, willFinishOperation operation: NSOperation, withErrors errors: [ErrorType]) {}
|
func operationQueue(queue: OperationQueue, willFinishOperation operation: NSOperation, withErrors errors: [ErrorType]) {}
|
||||||
|
|
||||||
func operationQueue(queue: OperationQueue, didFinishOperation operation: NSOperation, withErrors errors: [ErrorType]) {
|
func operationQueue(queue: OperationQueue, didFinishOperation operation: NSOperation, withErrors errors: [ErrorType]) {
|
||||||
guard operationQueue.operationCount == 1 else {return}
|
guard queue.operationCount == 1 else {return}
|
||||||
NSOperationQueue.mainQueue().addOperationWithBlock { () -> Void in
|
NSOperationQueue.mainQueue().addOperationWithBlock { () -> Void in
|
||||||
self.timer?.invalidate()
|
self.timer?.invalidate()
|
||||||
self.shouldReportProgress = false
|
self.shouldReportProgress = false
|
@ -21,7 +21,7 @@
|
|||||||
<rect key="frame" x="0.0" y="92" width="375" height="44"/>
|
<rect key="frame" x="0.0" y="92" width="375" height="44"/>
|
||||||
<autoresizingMask key="autoresizingMask"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="CVW-Rc-hA9" id="xiL-PL-4ko">
|
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="CVW-Rc-hA9" id="xiL-PL-4ko">
|
||||||
<frame key="frameInset" width="375" height="43"/>
|
<frame key="frameInset" width="375" height="43.5"/>
|
||||||
<autoresizingMask key="autoresizingMask"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="" lineBreakMode="tailTruncation" minimumFontSize="8" adjustsLetterSpacingToFitWidth="YES" translatesAutoresizingMaskIntoConstraints="NO" id="epH-ai-QrA">
|
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="" lineBreakMode="tailTruncation" minimumFontSize="8" adjustsLetterSpacingToFitWidth="YES" translatesAutoresizingMaskIntoConstraints="NO" id="epH-ai-QrA">
|
||||||
@ -219,21 +219,21 @@
|
|||||||
</view>
|
</view>
|
||||||
<prototypes>
|
<prototypes>
|
||||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="none" indentationWidth="10" reuseIdentifier="RightDetailCell" textLabel="iyO-rf-lDN" detailTextLabel="iHv-oK-qrR" style="IBUITableViewCellStyleValue1" id="eB8-dt-BPR">
|
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="none" indentationWidth="10" reuseIdentifier="RightDetailCell" textLabel="iyO-rf-lDN" detailTextLabel="iHv-oK-qrR" style="IBUITableViewCellStyleValue1" id="eB8-dt-BPR">
|
||||||
<rect key="frame" x="0.0" y="185" width="375" height="44"/>
|
<rect key="frame" x="0.0" y="184.5" width="375" height="44"/>
|
||||||
<autoresizingMask key="autoresizingMask"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="eB8-dt-BPR" id="KR4-kV-SZd">
|
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="eB8-dt-BPR" id="KR4-kV-SZd">
|
||||||
<frame key="frameInset" width="375" height="43"/>
|
<frame key="frameInset" width="375" height="43.5"/>
|
||||||
<autoresizingMask key="autoresizingMask"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Title" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="iyO-rf-lDN">
|
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Title" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="iyO-rf-lDN">
|
||||||
<frame key="frameInset" minX="15" minY="12" width="32" height="20"/>
|
<frame key="frameInset" minX="15" minY="12" width="31.5" height="19.5"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||||
<fontDescription key="fontDescription" type="system" pointSize="16"/>
|
<fontDescription key="fontDescription" type="system" pointSize="16"/>
|
||||||
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
<nil key="highlightedColor"/>
|
<nil key="highlightedColor"/>
|
||||||
</label>
|
</label>
|
||||||
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Detail" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="iHv-oK-qrR">
|
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Detail" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="iHv-oK-qrR">
|
||||||
<frame key="frameInset" minX="318" minY="12" width="42" height="20"/>
|
<frame key="frameInset" minX="318.5" minY="12" width="41.5" height="19.5"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||||
<fontDescription key="fontDescription" type="system" pointSize="16"/>
|
<fontDescription key="fontDescription" type="system" pointSize="16"/>
|
||||||
<color key="textColor" red="0.55686274509803924" green="0.55686274509803924" blue="0.57647058823529407" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
<color key="textColor" red="0.55686274509803924" green="0.55686274509803924" blue="0.57647058823529407" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
@ -243,10 +243,10 @@
|
|||||||
</tableViewCellContentView>
|
</tableViewCellContentView>
|
||||||
</tableViewCell>
|
</tableViewCell>
|
||||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="none" indentationWidth="10" reuseIdentifier="CenterButtonCell" id="B0D-Hu-sVM" customClass="CenterButtonCell" customModule="Kiwix" customModuleProvider="target">
|
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="none" indentationWidth="10" reuseIdentifier="CenterButtonCell" id="B0D-Hu-sVM" customClass="CenterButtonCell" customModule="Kiwix" customModuleProvider="target">
|
||||||
<rect key="frame" x="0.0" y="229" width="375" height="44"/>
|
<rect key="frame" x="0.0" y="228.5" width="375" height="44"/>
|
||||||
<autoresizingMask key="autoresizingMask"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="B0D-Hu-sVM" id="Fhf-jb-Urf">
|
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="B0D-Hu-sVM" id="Fhf-jb-Urf">
|
||||||
<frame key="frameInset" width="375" height="43"/>
|
<frame key="frameInset" width="375" height="43.5"/>
|
||||||
<autoresizingMask key="autoresizingMask"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="TLs-eg-B0R">
|
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="TLs-eg-B0R">
|
||||||
@ -268,10 +268,10 @@
|
|||||||
</connections>
|
</connections>
|
||||||
</tableViewCell>
|
</tableViewCell>
|
||||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="none" indentationWidth="10" reuseIdentifier="TextSwitchCell" id="c4v-9p-eEF" customClass="TextSwitchCell" customModule="Kiwix" customModuleProvider="target">
|
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="none" indentationWidth="10" reuseIdentifier="TextSwitchCell" id="c4v-9p-eEF" customClass="TextSwitchCell" customModule="Kiwix" customModuleProvider="target">
|
||||||
<rect key="frame" x="0.0" y="273" width="375" height="44"/>
|
<rect key="frame" x="0.0" y="272.5" width="375" height="44"/>
|
||||||
<autoresizingMask key="autoresizingMask"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="c4v-9p-eEF" id="Lt6-0C-r4i">
|
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="c4v-9p-eEF" id="Lt6-0C-r4i">
|
||||||
<frame key="frameInset" width="375" height="43"/>
|
<frame key="frameInset" width="375" height="43.5"/>
|
||||||
<autoresizingMask key="autoresizingMask"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Ksx-E1-lZ2">
|
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Ksx-E1-lZ2">
|
||||||
@ -295,14 +295,14 @@
|
|||||||
</connections>
|
</connections>
|
||||||
</tableViewCell>
|
</tableViewCell>
|
||||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="none" indentationWidth="10" reuseIdentifier="DescCell" textLabel="noJ-ab-bVV" style="IBUITableViewCellStyleDefault" id="J0v-iU-gZ5">
|
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="none" indentationWidth="10" reuseIdentifier="DescCell" textLabel="noJ-ab-bVV" style="IBUITableViewCellStyleDefault" id="J0v-iU-gZ5">
|
||||||
<rect key="frame" x="0.0" y="317" width="375" height="44"/>
|
<rect key="frame" x="0.0" y="316.5" width="375" height="44"/>
|
||||||
<autoresizingMask key="autoresizingMask"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="J0v-iU-gZ5" id="bXv-ic-E7x">
|
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="J0v-iU-gZ5" id="bXv-ic-E7x">
|
||||||
<frame key="frameInset" width="375" height="43"/>
|
<frame key="frameInset" width="375" height="43.5"/>
|
||||||
<autoresizingMask key="autoresizingMask"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Title" textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="noJ-ab-bVV">
|
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Title" textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="noJ-ab-bVV">
|
||||||
<frame key="frameInset" minX="15" width="345" height="43"/>
|
<frame key="frameInset" minX="15" width="345" height="43.5"/>
|
||||||
<autoresizingMask key="autoresizingMask"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
<fontDescription key="fontDescription" style="UICTFontTextStyleSubhead"/>
|
<fontDescription key="fontDescription" style="UICTFontTextStyleSubhead"/>
|
||||||
<nil key="textColor"/>
|
<nil key="textColor"/>
|
||||||
@ -362,7 +362,7 @@
|
|||||||
<rect key="frame" x="0.0" y="92" width="375" height="44"/>
|
<rect key="frame" x="0.0" y="92" width="375" height="44"/>
|
||||||
<autoresizingMask key="autoresizingMask"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="nka-b0-ZmD" id="8e2-Je-FJO">
|
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="nka-b0-ZmD" id="8e2-Je-FJO">
|
||||||
<frame key="frameInset" width="375" height="43"/>
|
<frame key="frameInset" width="375" height="43.5"/>
|
||||||
<autoresizingMask key="autoresizingMask"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="" lineBreakMode="tailTruncation" minimumFontSize="8" adjustsLetterSpacingToFitWidth="YES" translatesAutoresizingMaskIntoConstraints="NO" id="oQE-dD-h38">
|
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="" lineBreakMode="tailTruncation" minimumFontSize="8" adjustsLetterSpacingToFitWidth="YES" translatesAutoresizingMaskIntoConstraints="NO" id="oQE-dD-h38">
|
||||||
@ -473,7 +473,7 @@
|
|||||||
<rect key="frame" x="0.0" y="92" width="375" height="100"/>
|
<rect key="frame" x="0.0" y="92" width="375" height="100"/>
|
||||||
<autoresizingMask key="autoresizingMask"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="ekT-ed-PU9" id="oM4-Hy-Mkf">
|
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="ekT-ed-PU9" id="oM4-Hy-Mkf">
|
||||||
<frame key="frameInset" width="375" height="99"/>
|
<frame key="frameInset" width="375" height="99.5"/>
|
||||||
<autoresizingMask key="autoresizingMask"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="" lineBreakMode="tailTruncation" minimumFontSize="8" adjustsLetterSpacingToFitWidth="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Hji-3G-yaJ">
|
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="" lineBreakMode="tailTruncation" minimumFontSize="8" adjustsLetterSpacingToFitWidth="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Hji-3G-yaJ">
|
||||||
@ -514,7 +514,6 @@
|
|||||||
<outlet property="detailLabel" destination="v8H-ZV-HNV" id="nxi-1k-SWg"/>
|
<outlet property="detailLabel" destination="v8H-ZV-HNV" id="nxi-1k-SWg"/>
|
||||||
<outlet property="favIcon" destination="Too-68-SzG" id="nfU-AD-1Ji"/>
|
<outlet property="favIcon" destination="Too-68-SzG" id="nfU-AD-1Ji"/>
|
||||||
<outlet property="progressView" destination="g0o-rT-qxm" id="Jaw-Zr-uJY"/>
|
<outlet property="progressView" destination="g0o-rT-qxm" id="Jaw-Zr-uJY"/>
|
||||||
<outlet property="subtitleLabel" destination="v8H-ZV-HNV" id="sve-r0-ewd"/>
|
|
||||||
<outlet property="titleLabel" destination="Hji-3G-yaJ" id="mZ2-S6-XEO"/>
|
<outlet property="titleLabel" destination="Hji-3G-yaJ" id="mZ2-S6-XEO"/>
|
||||||
</connections>
|
</connections>
|
||||||
</tableViewCell>
|
</tableViewCell>
|
||||||
@ -580,21 +579,21 @@
|
|||||||
</view>
|
</view>
|
||||||
<prototypes>
|
<prototypes>
|
||||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" reuseIdentifier="Cell" textLabel="qXz-1G-wA2" detailTextLabel="AMO-pu-z25" style="IBUITableViewCellStyleValue1" id="Zpf-Mi-m0A">
|
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" reuseIdentifier="Cell" textLabel="qXz-1G-wA2" detailTextLabel="AMO-pu-z25" style="IBUITableViewCellStyleValue1" id="Zpf-Mi-m0A">
|
||||||
<rect key="frame" x="0.0" y="110" width="375" height="44"/>
|
<rect key="frame" x="0.0" y="109.5" width="375" height="44"/>
|
||||||
<autoresizingMask key="autoresizingMask"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="Zpf-Mi-m0A" id="S9T-Ce-Uax">
|
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="Zpf-Mi-m0A" id="S9T-Ce-Uax">
|
||||||
<frame key="frameInset" width="375" height="43"/>
|
<frame key="frameInset" width="375" height="43.5"/>
|
||||||
<autoresizingMask key="autoresizingMask"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Title" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="qXz-1G-wA2">
|
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Title" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="qXz-1G-wA2">
|
||||||
<frame key="frameInset" minX="15" minY="11" width="34" height="21"/>
|
<frame key="frameInset" minX="15" minY="12" width="33.5" height="20.5"/>
|
||||||
<autoresizingMask key="autoresizingMask"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||||
<nil key="textColor"/>
|
<nil key="textColor"/>
|
||||||
<nil key="highlightedColor"/>
|
<nil key="highlightedColor"/>
|
||||||
</label>
|
</label>
|
||||||
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Detail" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="AMO-pu-z25">
|
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Detail" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="AMO-pu-z25">
|
||||||
<frame key="frameInset" minX="316" minY="11" width="44" height="21"/>
|
<frame key="frameInset" minX="316" minY="12" width="44" height="20.5"/>
|
||||||
<autoresizingMask key="autoresizingMask"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||||
<nil key="textColor"/>
|
<nil key="textColor"/>
|
||||||
|
@ -21,7 +21,7 @@
|
|||||||
<key>CFBundleSignature</key>
|
<key>CFBundleSignature</key>
|
||||||
<string>????</string>
|
<string>????</string>
|
||||||
<key>CFBundleVersion</key>
|
<key>CFBundleVersion</key>
|
||||||
<string>1.7.1570</string>
|
<string>1.7.1627</string>
|
||||||
<key>NSExtension</key>
|
<key>NSExtension</key>
|
||||||
<dict>
|
<dict>
|
||||||
<key>NSExtensionMainStoryboard</key>
|
<key>NSExtensionMainStoryboard</key>
|
||||||
|
@ -39,7 +39,6 @@
|
|||||||
971A104B1D022CBE007FC62C /* SearchBooksVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 971A10481D022CBE007FC62C /* SearchBooksVC.swift */; };
|
971A104B1D022CBE007FC62C /* SearchBooksVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 971A10481D022CBE007FC62C /* SearchBooksVC.swift */; };
|
||||||
971A10521D022D9D007FC62C /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 971A10511D022D9D007FC62C /* AppDelegate.swift */; };
|
971A10521D022D9D007FC62C /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 971A10511D022D9D007FC62C /* AppDelegate.swift */; };
|
||||||
971A106F1D022E62007FC62C /* DownloadProgress.swift in Sources */ = {isa = PBXBuildFile; fileRef = 971A106D1D022E62007FC62C /* DownloadProgress.swift */; };
|
971A106F1D022E62007FC62C /* DownloadProgress.swift in Sources */ = {isa = PBXBuildFile; fileRef = 971A106D1D022E62007FC62C /* DownloadProgress.swift */; };
|
||||||
971A10701D022E62007FC62C /* Network.swift in Sources */ = {isa = PBXBuildFile; fileRef = 971A106E1D022E62007FC62C /* Network.swift */; };
|
|
||||||
971A10771D022F05007FC62C /* Localizable.stringsdict in Resources */ = {isa = PBXBuildFile; fileRef = 971A10791D022F05007FC62C /* Localizable.stringsdict */; };
|
971A10771D022F05007FC62C /* Localizable.stringsdict in Resources */ = {isa = PBXBuildFile; fileRef = 971A10791D022F05007FC62C /* Localizable.stringsdict */; };
|
||||||
971A107E1D022F74007FC62C /* DownloaderLearnMore.html in Resources */ = {isa = PBXBuildFile; fileRef = 971A107A1D022F74007FC62C /* DownloaderLearnMore.html */; };
|
971A107E1D022F74007FC62C /* DownloaderLearnMore.html in Resources */ = {isa = PBXBuildFile; fileRef = 971A107A1D022F74007FC62C /* DownloaderLearnMore.html */; };
|
||||||
971A107F1D022F74007FC62C /* ImportBookLearnMore.html in Resources */ = {isa = PBXBuildFile; fileRef = 971A107B1D022F74007FC62C /* ImportBookLearnMore.html */; };
|
971A107F1D022F74007FC62C /* ImportBookLearnMore.html in Resources */ = {isa = PBXBuildFile; fileRef = 971A107B1D022F74007FC62C /* ImportBookLearnMore.html */; };
|
||||||
@ -119,7 +118,6 @@
|
|||||||
97D681261D6F70AC00E5FA99 /* SearchOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 97D6811F1D6F70AC00E5FA99 /* SearchOperation.swift */; };
|
97D681261D6F70AC00E5FA99 /* SearchOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 97D6811F1D6F70AC00E5FA99 /* SearchOperation.swift */; };
|
||||||
97D681271D6F70AC00E5FA99 /* UIOperations.swift in Sources */ = {isa = PBXBuildFile; fileRef = 97D681201D6F70AC00E5FA99 /* UIOperations.swift */; };
|
97D681271D6F70AC00E5FA99 /* UIOperations.swift in Sources */ = {isa = PBXBuildFile; fileRef = 97D681201D6F70AC00E5FA99 /* UIOperations.swift */; };
|
||||||
97D681281D6F70AC00E5FA99 /* UpdateWidgetDataSourceOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 97D681211D6F70AC00E5FA99 /* UpdateWidgetDataSourceOperation.swift */; };
|
97D681281D6F70AC00E5FA99 /* UpdateWidgetDataSourceOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 97D681211D6F70AC00E5FA99 /* UpdateWidgetDataSourceOperation.swift */; };
|
||||||
97D681291D6F70AC00E5FA99 /* URLSessionDownloadTaskOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 97D681221D6F70AC00E5FA99 /* URLSessionDownloadTaskOperation.swift */; };
|
|
||||||
97D6812E1D6F70DE00E5FA99 /* Kiwix.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = 97D6812A1D6F70DE00E5FA99 /* Kiwix.xcdatamodeld */; };
|
97D6812E1D6F70DE00E5FA99 /* Kiwix.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = 97D6812A1D6F70DE00E5FA99 /* Kiwix.xcdatamodeld */; };
|
||||||
97D681311D6F70EC00E5FA99 /* 1.5.xcmappingmodel in Sources */ = {isa = PBXBuildFile; fileRef = 97D6812F1D6F70EC00E5FA99 /* 1.5.xcmappingmodel */; };
|
97D681311D6F70EC00E5FA99 /* 1.5.xcmappingmodel in Sources */ = {isa = PBXBuildFile; fileRef = 97D6812F1D6F70EC00E5FA99 /* 1.5.xcmappingmodel */; };
|
||||||
97D681321D6F70EC00E5FA99 /* MigrationPolicy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 97D681301D6F70EC00E5FA99 /* MigrationPolicy.swift */; };
|
97D681321D6F70EC00E5FA99 /* MigrationPolicy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 97D681301D6F70EC00E5FA99 /* MigrationPolicy.swift */; };
|
||||||
@ -134,6 +132,8 @@
|
|||||||
97D681441D6F713200E5FA99 /* CoreDataExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 97D681431D6F713200E5FA99 /* CoreDataExtension.swift */; };
|
97D681441D6F713200E5FA99 /* CoreDataExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 97D681431D6F713200E5FA99 /* CoreDataExtension.swift */; };
|
||||||
97DB65DA1D4576B600A2CC42 /* BookmarkWidgetCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 97DB65D91D4576B600A2CC42 /* BookmarkWidgetCell.swift */; };
|
97DB65DA1D4576B600A2CC42 /* BookmarkWidgetCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 97DB65D91D4576B600A2CC42 /* BookmarkWidgetCell.swift */; };
|
||||||
97DF259C1D6F7613001648A3 /* DownloadBookOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 97DF259B1D6F7612001648A3 /* DownloadBookOperation.swift */; };
|
97DF259C1D6F7613001648A3 /* DownloadBookOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 97DF259B1D6F7612001648A3 /* DownloadBookOperation.swift */; };
|
||||||
|
97DF259D1D6F9053001648A3 /* URLSessionDownloadTaskOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 97D681221D6F70AC00E5FA99 /* URLSessionDownloadTaskOperation.swift */; };
|
||||||
|
97DF25A01D6F996B001648A3 /* Network.swift in Sources */ = {isa = PBXBuildFile; fileRef = 97DF259F1D6F996B001648A3 /* Network.swift */; };
|
||||||
97E60A021D10423A00EBCB9D /* ShadowViews.swift in Sources */ = {isa = PBXBuildFile; fileRef = 97E60A011D10423A00EBCB9D /* ShadowViews.swift */; };
|
97E60A021D10423A00EBCB9D /* ShadowViews.swift in Sources */ = {isa = PBXBuildFile; fileRef = 97E60A011D10423A00EBCB9D /* ShadowViews.swift */; };
|
||||||
97E60A061D10504000EBCB9D /* LibraryBackupTBVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 97E60A051D10504000EBCB9D /* LibraryBackupTBVC.swift */; };
|
97E60A061D10504000EBCB9D /* LibraryBackupTBVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 97E60A051D10504000EBCB9D /* LibraryBackupTBVC.swift */; };
|
||||||
97E850CB1D2DA5B300A9F688 /* About.html in Resources */ = {isa = PBXBuildFile; fileRef = 97E850CA1D2DA5B300A9F688 /* About.html */; };
|
97E850CB1D2DA5B300A9F688 /* About.html in Resources */ = {isa = PBXBuildFile; fileRef = 97E850CA1D2DA5B300A9F688 /* About.html */; };
|
||||||
@ -240,7 +240,7 @@
|
|||||||
971A10481D022CBE007FC62C /* SearchBooksVC.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = SearchBooksVC.swift; path = "Kiwix-iOS/Controller/SearchBooksVC.swift"; sourceTree = SOURCE_ROOT; };
|
971A10481D022CBE007FC62C /* SearchBooksVC.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = SearchBooksVC.swift; path = "Kiwix-iOS/Controller/SearchBooksVC.swift"; sourceTree = SOURCE_ROOT; };
|
||||||
971A10511D022D9D007FC62C /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
971A10511D022D9D007FC62C /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
||||||
971A106D1D022E62007FC62C /* DownloadProgress.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = DownloadProgress.swift; path = "Kiwix-iOS/Model/DownloadProgress.swift"; sourceTree = SOURCE_ROOT; };
|
971A106D1D022E62007FC62C /* DownloadProgress.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = DownloadProgress.swift; path = "Kiwix-iOS/Model/DownloadProgress.swift"; sourceTree = SOURCE_ROOT; };
|
||||||
971A106E1D022E62007FC62C /* Network.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Network.swift; path = "Kiwix-iOS/Model/Network.swift"; sourceTree = SOURCE_ROOT; };
|
971A106E1D022E62007FC62C /* Network_old.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Network_old.swift; path = "Kiwix-iOS/Model/Network_old.swift"; sourceTree = SOURCE_ROOT; };
|
||||||
971A10781D022F05007FC62C /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = en; path = en.lproj/Localizable.stringsdict; sourceTree = "<group>"; };
|
971A10781D022F05007FC62C /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = en; path = en.lproj/Localizable.stringsdict; sourceTree = "<group>"; };
|
||||||
971A107A1D022F74007FC62C /* DownloaderLearnMore.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; name = DownloaderLearnMore.html; path = Kiwix/HelpDocuments/DownloaderLearnMore.html; sourceTree = SOURCE_ROOT; };
|
971A107A1D022F74007FC62C /* DownloaderLearnMore.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; name = DownloaderLearnMore.html; path = Kiwix/HelpDocuments/DownloaderLearnMore.html; sourceTree = SOURCE_ROOT; };
|
||||||
971A107B1D022F74007FC62C /* ImportBookLearnMore.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; name = ImportBookLearnMore.html; path = Kiwix/HelpDocuments/ImportBookLearnMore.html; sourceTree = SOURCE_ROOT; };
|
971A107B1D022F74007FC62C /* ImportBookLearnMore.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; name = ImportBookLearnMore.html; path = Kiwix/HelpDocuments/ImportBookLearnMore.html; sourceTree = SOURCE_ROOT; };
|
||||||
@ -358,6 +358,7 @@
|
|||||||
97D681431D6F713200E5FA99 /* CoreDataExtension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = CoreDataExtension.swift; path = Classes/CoreDataExtension.swift; sourceTree = "<group>"; };
|
97D681431D6F713200E5FA99 /* CoreDataExtension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = CoreDataExtension.swift; path = Classes/CoreDataExtension.swift; sourceTree = "<group>"; };
|
||||||
97DB65D91D4576B600A2CC42 /* BookmarkWidgetCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BookmarkWidgetCell.swift; sourceTree = "<group>"; };
|
97DB65D91D4576B600A2CC42 /* BookmarkWidgetCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BookmarkWidgetCell.swift; sourceTree = "<group>"; };
|
||||||
97DF259B1D6F7612001648A3 /* DownloadBookOperation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DownloadBookOperation.swift; sourceTree = "<group>"; };
|
97DF259B1D6F7612001648A3 /* DownloadBookOperation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DownloadBookOperation.swift; sourceTree = "<group>"; };
|
||||||
|
97DF259F1D6F996B001648A3 /* Network.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Network.swift; sourceTree = "<group>"; };
|
||||||
97E609F01D103DED00EBCB9D /* NotificationCenter.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = NotificationCenter.framework; path = System/Library/Frameworks/NotificationCenter.framework; sourceTree = SDKROOT; };
|
97E609F01D103DED00EBCB9D /* NotificationCenter.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = NotificationCenter.framework; path = System/Library/Frameworks/NotificationCenter.framework; sourceTree = SDKROOT; };
|
||||||
97E60A011D10423A00EBCB9D /* ShadowViews.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ShadowViews.swift; sourceTree = "<group>"; };
|
97E60A011D10423A00EBCB9D /* ShadowViews.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ShadowViews.swift; sourceTree = "<group>"; };
|
||||||
97E60A051D10504000EBCB9D /* LibraryBackupTBVC.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = LibraryBackupTBVC.swift; path = "Kiwix-iOS/Controller/LibraryBackupTBVC.swift"; sourceTree = SOURCE_ROOT; };
|
97E60A051D10504000EBCB9D /* LibraryBackupTBVC.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = LibraryBackupTBVC.swift; path = "Kiwix-iOS/Controller/LibraryBackupTBVC.swift"; sourceTree = SOURCE_ROOT; };
|
||||||
@ -570,7 +571,7 @@
|
|||||||
971904A41CA3204B002E9CFF /* Network */ = {
|
971904A41CA3204B002E9CFF /* Network */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
971A106E1D022E62007FC62C /* Network.swift */,
|
971A106E1D022E62007FC62C /* Network_old.swift */,
|
||||||
971A106D1D022E62007FC62C /* DownloadProgress.swift */,
|
971A106D1D022E62007FC62C /* DownloadProgress.swift */,
|
||||||
);
|
);
|
||||||
name = Network;
|
name = Network;
|
||||||
@ -665,6 +666,7 @@
|
|||||||
9711872D1CEB507600B9909D /* CoreData */,
|
9711872D1CEB507600B9909D /* CoreData */,
|
||||||
97163D321CD7E79F008BE2D6 /* Help Docs */,
|
97163D321CD7E79F008BE2D6 /* Help Docs */,
|
||||||
971187051CEB426E00B9909D /* libkiwix */,
|
971187051CEB426E00B9909D /* libkiwix */,
|
||||||
|
97DF259E1D6F9942001648A3 /* Network */,
|
||||||
97E5712A1CA0525300FF4F1D /* Operation */,
|
97E5712A1CA0525300FF4F1D /* Operation */,
|
||||||
97A1FD3C1D6F728200A80EE2 /* Tools */,
|
97A1FD3C1D6F728200A80EE2 /* Tools */,
|
||||||
97BAA8EA1D3D2D0A0038F57F /* URLProtocol */,
|
97BAA8EA1D3D2D0A0038F57F /* URLProtocol */,
|
||||||
@ -944,6 +946,14 @@
|
|||||||
name = Reading;
|
name = Reading;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
|
97DF259E1D6F9942001648A3 /* Network */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
97DF259F1D6F996B001648A3 /* Network.swift */,
|
||||||
|
);
|
||||||
|
path = Network;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
97E108221C5D5A0D00E27FD3 /* Search */ = {
|
97E108221C5D5A0D00E27FD3 /* Search */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
@ -1482,20 +1492,20 @@
|
|||||||
971A102C1D022AD5007FC62C /* BarButtonItems.swift in Sources */,
|
971A102C1D022AD5007FC62C /* BarButtonItems.swift in Sources */,
|
||||||
971A10301D022AD5007FC62C /* LTBarButtonItem.swift in Sources */,
|
971A10301D022AD5007FC62C /* LTBarButtonItem.swift in Sources */,
|
||||||
971A103F1D022C42007FC62C /* LibraryAutoRefreshTBVC.swift in Sources */,
|
971A103F1D022C42007FC62C /* LibraryAutoRefreshTBVC.swift in Sources */,
|
||||||
|
97DF25A01D6F996B001648A3 /* Network.swift in Sources */,
|
||||||
97A1FD391D6F724E00A80EE2 /* pathTools.cpp in Sources */,
|
97A1FD391D6F724E00A80EE2 /* pathTools.cpp in Sources */,
|
||||||
970E68B61D37E224001E8514 /* SettingSearchHistoryTBVC.swift in Sources */,
|
970E68B61D37E224001E8514 /* SettingSearchHistoryTBVC.swift in Sources */,
|
||||||
97C005D81D64B99E004352E8 /* LibrarySplitViewController.swift in Sources */,
|
97C005D81D64B99E004352E8 /* LibrarySplitViewController.swift in Sources */,
|
||||||
97A7017F1D2C59CA00AAE2D8 /* GetStartedController.swift in Sources */,
|
97A7017F1D2C59CA00AAE2D8 /* GetStartedController.swift in Sources */,
|
||||||
97A8AD871D6CF38000584ED1 /* EmptyTableConfigExtension.swift in Sources */,
|
97A8AD871D6CF38000584ED1 /* EmptyTableConfigExtension.swift in Sources */,
|
||||||
97D681291D6F70AC00E5FA99 /* URLSessionDownloadTaskOperation.swift in Sources */,
|
|
||||||
97D452BC1D16FF010033666F /* RecentSearchCVC.swift in Sources */,
|
97D452BC1D16FF010033666F /* RecentSearchCVC.swift in Sources */,
|
||||||
971A106F1D022E62007FC62C /* DownloadProgress.swift in Sources */,
|
971A106F1D022E62007FC62C /* DownloadProgress.swift in Sources */,
|
||||||
971A102E1D022AD5007FC62C /* TableViewCells.swift in Sources */,
|
971A102E1D022AD5007FC62C /* TableViewCells.swift in Sources */,
|
||||||
|
97DF259D1D6F9053001648A3 /* URLSessionDownloadTaskOperation.swift in Sources */,
|
||||||
97E60A021D10423A00EBCB9D /* ShadowViews.swift in Sources */,
|
97E60A021D10423A00EBCB9D /* ShadowViews.swift in Sources */,
|
||||||
970E68BA1D3809A3001E8514 /* MainController.swift in Sources */,
|
970E68BA1D3809A3001E8514 /* MainController.swift in Sources */,
|
||||||
970C65501D398D5A007032F8 /* BookmarkControllerAnimator.swift in Sources */,
|
970C65501D398D5A007032F8 /* BookmarkControllerAnimator.swift in Sources */,
|
||||||
97D6813A1D6F711A00E5FA99 /* Language.swift in Sources */,
|
97D6813A1D6F711A00E5FA99 /* Language.swift in Sources */,
|
||||||
971A10701D022E62007FC62C /* Network.swift in Sources */,
|
|
||||||
97D681401D6F712800E5FA99 /* Book+CoreDataProperties.swift in Sources */,
|
97D681401D6F712800E5FA99 /* Book+CoreDataProperties.swift in Sources */,
|
||||||
97A1FD421D6F728200A80EE2 /* Extensions.swift in Sources */,
|
97A1FD421D6F728200A80EE2 /* Extensions.swift in Sources */,
|
||||||
97A1FD431D6F728200A80EE2 /* FileManager.swift in Sources */,
|
97A1FD431D6F728200A80EE2 /* FileManager.swift in Sources */,
|
||||||
|
40
Kiwix/Network/Network.swift
Normal file
40
Kiwix/Network/Network.swift
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
//
|
||||||
|
// Network.swift
|
||||||
|
// Kiwix
|
||||||
|
//
|
||||||
|
// Created by Chris Li on 8/25/16.
|
||||||
|
// Copyright © 2016 Chris. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
import Operations
|
||||||
|
|
||||||
|
// , NSURLSessionDownloadDelegate, NSURLSessionTaskDelegate
|
||||||
|
class Network: NSObject, NSURLSessionDelegate, OperationQueueDelegate {
|
||||||
|
static let shared = Network()
|
||||||
|
let queue = OperationQueue()
|
||||||
|
|
||||||
|
private override init() {
|
||||||
|
super.init()
|
||||||
|
queue.delegate = self
|
||||||
|
}
|
||||||
|
|
||||||
|
lazy var session: NSURLSession = {
|
||||||
|
let configuration = NSURLSessionConfiguration.backgroundSessionConfigurationWithIdentifier("org.kiwix.www")
|
||||||
|
configuration.allowsCellularAccess = false
|
||||||
|
configuration.discretionary = false
|
||||||
|
return NSURLSession(configuration: configuration, delegate: self, delegateQueue: nil)
|
||||||
|
}()
|
||||||
|
|
||||||
|
func operationQueue(queue: OperationQueue, willAddOperation operation: NSOperation) {
|
||||||
|
print(queue.operationCount)
|
||||||
|
}
|
||||||
|
|
||||||
|
func operationQueue(queue: OperationQueue, willFinishOperation operation: NSOperation, withErrors errors: [ErrorType]) {}
|
||||||
|
|
||||||
|
func operationQueue(queue: OperationQueue, didFinishOperation operation: NSOperation, withErrors errors: [ErrorType]) {
|
||||||
|
print(queue.operationCount)
|
||||||
|
}
|
||||||
|
|
||||||
|
func operationQueue(queue: OperationQueue, willProduceOperation operation: NSOperation) {}
|
||||||
|
}
|
@ -10,34 +10,26 @@ import UIKit
|
|||||||
import CoreData
|
import CoreData
|
||||||
import Operations
|
import Operations
|
||||||
|
|
||||||
class DownloadBookOperation: Operation {
|
class DownloadBookOperation: URLSessionDownloadTaskOperation {
|
||||||
|
|
||||||
private let bookID: String
|
convenience init?(bookID: String) {
|
||||||
private let url: NSURL
|
let context = NSManagedObjectContext.mainQueueContext
|
||||||
private let spaceState: BookSpaceState
|
guard let book = Book.fetch(bookID, context: context),
|
||||||
|
let url = book.url else { return nil }
|
||||||
init?(book: Book) {
|
|
||||||
assert(NSThread.isMainThread(), "DownloadBookOperation has to be initialized on main thread")
|
|
||||||
assert(book.managedObjectContext === NSManagedObjectContext.mainQueueContext, "DownloadBookOperation has to be initialized with a Book managed object belongs to the main queue context")
|
|
||||||
self.bookID = book.id ?? ""
|
|
||||||
self.url = book.url ?? NSURL()
|
|
||||||
self.spaceState = book.spaceState
|
|
||||||
|
|
||||||
super.init()
|
// book
|
||||||
|
let task = Network.shared.session.downloadTaskWithURL(url)
|
||||||
|
|
||||||
if self.bookID == "" || self.url.absoluteString == "" {return nil}
|
let downloadTask = DownloadTask.addOrUpdate(book, context: context)
|
||||||
|
downloadTask?.state = .Queued
|
||||||
|
|
||||||
|
task.taskDescription = bookID
|
||||||
|
self.init(downloadTask: task)
|
||||||
}
|
}
|
||||||
|
|
||||||
override func execute() {
|
override func operationDidFinish(errors: [ErrorType]) {
|
||||||
defer { finish() }
|
guard let bookID = task.taskDescription else {return}
|
||||||
|
print("Book download op finished")
|
||||||
switch spaceState {
|
|
||||||
case .Caution:
|
|
||||||
print("caution")
|
|
||||||
case .NotEnough:
|
|
||||||
print("not enough")
|
|
||||||
default:
|
|
||||||
print("down")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,20 +11,6 @@ import Operations
|
|||||||
|
|
||||||
// MARK: - Alerts
|
// MARK: - Alerts
|
||||||
|
|
||||||
class SpaceCautionAlert: AlertOperation<CloudBooksController> {
|
|
||||||
let comment = "Library: Download Space Caution Alert"
|
|
||||||
init(book: Book, presentationContext: CloudBooksController) {
|
|
||||||
super.init(presentAlertFrom: presentationContext)
|
|
||||||
|
|
||||||
title = NSLocalizedString("Space Caution", comment: comment)
|
|
||||||
message = NSLocalizedString("This book takes up more than 80% of the remaining space on your device. Are you sure you want to download it?", comment: comment)
|
|
||||||
addActionWithTitle(NSLocalizedString("Download Anyway", comment: comment), style: .Default) { (alert) in
|
|
||||||
Network.shared.download(book)
|
|
||||||
}
|
|
||||||
addActionWithTitle(LocalizedStrings.cancel)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class SpaceNotEnoughAlert: AlertOperation<CloudBooksController> {
|
class SpaceNotEnoughAlert: AlertOperation<CloudBooksController> {
|
||||||
let comment = "Library: Download Space Not Enough Alert"
|
let comment = "Library: Download Space Not Enough Alert"
|
||||||
init(book: Book, presentationContext: CloudBooksController) {
|
init(book: Book, presentationContext: CloudBooksController) {
|
||||||
|
@ -8,22 +8,26 @@
|
|||||||
|
|
||||||
import Operations
|
import Operations
|
||||||
|
|
||||||
private var URLSessionTaskOperationKVOContext = 0
|
class URLSessionDownloadTaskOperation: Operation {
|
||||||
|
|
||||||
public class URLSessionDownloadTaskOperation: Operation {
|
|
||||||
let task: NSURLSessionDownloadTask
|
|
||||||
private var produceResumeData = false
|
|
||||||
private var observerRemoved = false
|
|
||||||
private let stateLock = NSLock()
|
|
||||||
|
|
||||||
public init(downloadTask: NSURLSessionDownloadTask) {
|
enum KeyPath: String {
|
||||||
|
case State = "state"
|
||||||
|
}
|
||||||
|
|
||||||
|
let task: NSURLSessionTask
|
||||||
|
|
||||||
|
private var produceResumeData = false
|
||||||
|
private var removedObserved = false
|
||||||
|
private let lock = NSLock()
|
||||||
|
|
||||||
|
init(downloadTask: NSURLSessionDownloadTask) {
|
||||||
self.task = downloadTask
|
self.task = downloadTask
|
||||||
super.init()
|
super.init()
|
||||||
|
|
||||||
|
addObserver(NetworkObserver())
|
||||||
addObserver(DidCancelObserver { _ in
|
addObserver(DidCancelObserver { _ in
|
||||||
if self.produceResumeData {
|
if self.produceResumeData {
|
||||||
downloadTask.cancelByProducingResumeData({ (data) in
|
downloadTask.cancelByProducingResumeData({ (data) in })
|
||||||
})
|
|
||||||
} else {
|
} else {
|
||||||
downloadTask.cancel()
|
downloadTask.cancel()
|
||||||
}
|
}
|
||||||
@ -31,12 +35,12 @@ public class URLSessionDownloadTaskOperation: Operation {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func cancel(produceResumeData produceResumeData: Bool) {
|
func cancel(produceResumeData produceResumeData: Bool) {
|
||||||
self.produceResumeData = produceResumeData
|
self.produceResumeData = produceResumeData
|
||||||
cancel()
|
cancel()
|
||||||
}
|
}
|
||||||
|
|
||||||
override public func execute() {
|
override func execute() {
|
||||||
guard task.state == .Suspended || task.state == .Running else {
|
guard task.state == .Suspended || task.state == .Running else {
|
||||||
finish()
|
finish()
|
||||||
return
|
return
|
||||||
@ -47,31 +51,37 @@ public class URLSessionDownloadTaskOperation: Operation {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override public func observeValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, change: [String : AnyObject]?, context: UnsafeMutablePointer<Void>) {
|
override func observeValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, change: [String : AnyObject]?, context: UnsafeMutablePointer<Void>) {
|
||||||
guard context == &URLSessionTaskOperationKVOContext else { return }
|
guard context == &URLSessionTaskOperationKVOContext else { return }
|
||||||
|
|
||||||
stateLock.withCriticalScope {
|
lock.withCriticalScope {
|
||||||
if object === task && keyPath == "state" && !observerRemoved {
|
if object === task && keyPath == KeyPath.State.rawValue && !removedObserved {
|
||||||
|
|
||||||
|
if case .Completed = task.state {
|
||||||
|
finish(task.error)
|
||||||
|
}
|
||||||
|
|
||||||
switch task.state {
|
switch task.state {
|
||||||
case .Completed:
|
case .Completed, .Canceling:
|
||||||
finish()
|
task.removeObserver(self, forKeyPath: KeyPath.State.rawValue)
|
||||||
fallthrough
|
removedObserved = true
|
||||||
case .Canceling:
|
|
||||||
observerRemoved = true
|
|
||||||
task.removeObserver(self, forKeyPath: "state")
|
|
||||||
default:
|
default:
|
||||||
return
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private extension NSLock {
|
// swiftlint:disable variable_name
|
||||||
func withCriticalScope<T>(@noescape block: Void -> T) -> T {
|
private var URLSessionTaskOperationKVOContext = 0
|
||||||
|
// swiftlint:enable variable_name
|
||||||
|
|
||||||
|
extension NSLock {
|
||||||
|
func withCriticalScope<T>(@noescape block: () -> T) -> T {
|
||||||
lock()
|
lock()
|
||||||
let value = block()
|
let value = block()
|
||||||
unlock()
|
unlock()
|
||||||
return value
|
return value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user