Add menu and keyboard shortcut to Reader

This commit is contained in:
Maurice Parker 2019-09-19 17:25:36 -05:00
parent 6a7d1df423
commit 76056e4fef
4 changed files with 69 additions and 40 deletions

View File

@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.Storyboard.XIB" version="3.0" toolsVersion="14865.1" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES"> <document type="com.apple.InterfaceBuilder3.Cocoa.Storyboard.XIB" version="3.0" toolsVersion="14868" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
<dependencies> <dependencies>
<deployment identifier="macosx"/> <deployment identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="14865.1"/> <plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="14868"/>
</dependencies> </dependencies>
<scenes> <scenes>
<!--Application--> <!--Application-->
@ -440,6 +440,11 @@
</connections> </connections>
</menuItem> </menuItem>
<menuItem isSeparatorItem="YES" id="qgr-Gl-Xhw"/> <menuItem isSeparatorItem="YES" id="qgr-Gl-Xhw"/>
<menuItem title="Show Reader View" keyEquivalent="R" id="p5x-Xq-1fW">
<connections>
<action selector="toggleArticleExtractor:" target="Ady-hI-5gd" id="H3B-RR-1tB"/>
</connections>
</menuItem>
<menuItem title="Open in Browser" keyEquivalent="" id="4iQ-1v-dTa"> <menuItem title="Open in Browser" keyEquivalent="" id="4iQ-1v-dTa">
<connections> <connections>
<action selector="openArticleInBrowser:" target="Ady-hI-5gd" id="KeH-ES-fpo"/> <action selector="openArticleInBrowser:" target="Ady-hI-5gd" id="KeH-ES-fpo"/>
@ -595,8 +600,8 @@
<connections> <connections>
<outlet property="checkForUpdatesMenuItem" destination="1nF-7O-aKU" id="JmT-jc-DJ8"/> <outlet property="checkForUpdatesMenuItem" destination="1nF-7O-aKU" id="JmT-jc-DJ8"/>
<outlet property="debugMenuItem" destination="UqE-mp-gtV" id="OnR-lr-Zlt"/> <outlet property="debugMenuItem" destination="UqE-mp-gtV" id="OnR-lr-Zlt"/>
<outlet property="groupArticlesByFeedMenuItem" destination="Zxm-O6-NRE" id="gwn-VT-2YZ"/>
<outlet property="enableWebInspectorMenuItem" destination="EwI-z4-ZA3" id="EGp-lP-f91"/> <outlet property="enableWebInspectorMenuItem" destination="EwI-z4-ZA3" id="EGp-lP-f91"/>
<outlet property="groupArticlesByFeedMenuItem" destination="Zxm-O6-NRE" id="gwn-VT-2YZ"/>
<outlet property="sortByNewestArticleOnTopMenuItem" destination="TNS-TV-n0U" id="gix-Nd-9k4"/> <outlet property="sortByNewestArticleOnTopMenuItem" destination="TNS-TV-n0U" id="gix-Nd-9k4"/>
<outlet property="sortByOldestArticleOnTopMenuItem" destination="iii-kP-qoF" id="fTe-Tf-EWG"/> <outlet property="sortByOldestArticleOnTopMenuItem" destination="iii-kP-qoF" id="fTe-Tf-EWG"/>
</connections> </connections>

View File

@ -208,7 +208,6 @@
</connections> </connections>
</window> </window>
<connections> <connections>
<outlet property="articleExtractorButton" destination="1b9-Tf-u5V" id="W8P-DA-hmV"/>
<segue destination="reS-fe-pD8" kind="relationship" relationship="window.shadowedContentViewController" id="WS2-WB-dc4"/> <segue destination="reS-fe-pD8" kind="relationship" relationship="window.shadowedContentViewController" id="WS2-WB-dc4"/>
</connections> </connections>
</windowController> </windowController>

View File

@ -17,8 +17,7 @@ enum TimelineSourceMode {
class MainWindowController : NSWindowController, NSUserInterfaceValidations { class MainWindowController : NSWindowController, NSUserInterfaceValidations {
@IBOutlet weak var articleExtractorButton: ArticleExtractorButton! private var isShowingExtractedArticle = false
private var articleExtractor: ArticleExtractor? = nil private var articleExtractor: ArticleExtractor? = nil
private var sharingServicePickerDelegate: NSSharingServicePickerDelegate? private var sharingServicePickerDelegate: NSSharingServicePickerDelegate?
@ -305,14 +304,27 @@ class MainWindowController : NSWindowController, NSUserInterfaceValidations {
return return
} }
guard articleExtractorButton.state == .on else { defer {
let detailState = DetailState.article(article) makeToolbarValidate()
detailViewController?.setState(detailState, mode: timelineSourceMode) }
guard articleExtractor?.state != .processing else {
articleExtractor?.cancel()
articleExtractor = nil
isShowingExtractedArticle = false
detailViewController?.setState(DetailState.article(article), mode: timelineSourceMode)
return
}
guard !isShowingExtractedArticle else {
isShowingExtractedArticle = false
detailViewController?.setState(DetailState.article(article), mode: timelineSourceMode)
return return
} }
if let articleExtractor = articleExtractor, let extractedArticle = articleExtractor.article { if let articleExtractor = articleExtractor, let extractedArticle = articleExtractor.article {
if currentLink == articleExtractor.articleLink { if currentLink == articleExtractor.articleLink {
isShowingExtractedArticle = true
let detailState = DetailState.extracted(article, extractedArticle) let detailState = DetailState.extracted(article, extractedArticle)
detailViewController?.setState(detailState, mode: timelineSourceMode) detailViewController?.setState(detailState, mode: timelineSourceMode)
} }
@ -322,7 +334,6 @@ class MainWindowController : NSWindowController, NSUserInterfaceValidations {
extractor.process() extractor.process()
articleExtractor = extractor articleExtractor = extractor
} }
makeToolbarValidate()
} }
} }
@ -442,10 +453,12 @@ extension MainWindowController: SidebarDelegate {
extension MainWindowController: TimelineContainerViewControllerDelegate { extension MainWindowController: TimelineContainerViewControllerDelegate {
func timelineSelectionDidChange(_: TimelineContainerViewController, articles: [Article]?, mode: TimelineSourceMode) { func timelineSelectionDidChange(_: TimelineContainerViewController, articles: [Article]?, mode: TimelineSourceMode) {
articleExtractorButton.isError = false
articleExtractorButton.isInProgress = false articleExtractor?.cancel()
articleExtractorButton.state = .off
articleExtractor = nil articleExtractor = nil
isShowingExtractedArticle = false
makeToolbarValidate()
let detailState: DetailState let detailState: DetailState
if let articles = articles { if let articles = articles {
@ -531,10 +544,11 @@ extension MainWindowController: ArticleExtractorDelegate {
} }
func articleExtractionDidComplete(extractedArticle: ExtractedArticle) { func articleExtractionDidComplete(extractedArticle: ExtractedArticle) {
makeToolbarValidate() if let article = oneSelectedArticle, articleExtractor?.state != .cancelled {
if articleExtractorButton.state == .on, let article = oneSelectedArticle { isShowingExtractedArticle = true
let detailState = DetailState.extracted(article, extractedArticle) let detailState = DetailState.extracted(article, extractedArticle)
detailViewController?.setState(detailState, mode: timelineSourceMode) detailViewController?.setState(detailState, mode: timelineSourceMode)
makeToolbarValidate()
} }
} }
@ -692,32 +706,35 @@ private extension MainWindowController {
} }
func validateToggleArticleExtractor(_ item: NSValidatedUserInterfaceItem) -> Bool { func validateToggleArticleExtractor(_ item: NSValidatedUserInterfaceItem) -> Bool {
guard let articleExtractorState = articleExtractor?.state else { guard let toolbarItem = item as? NSToolbarItem, let toolbarButton = toolbarItem.view as? ArticleExtractorButton else {
articleExtractorButton.isError = false if let menuItem = item as? NSMenuItem {
articleExtractorButton.isInProgress = false menuItem.state = isShowingExtractedArticle ? .on : .off
articleExtractorButton.state = .off }
return currentLink != nil return currentLink != nil
} }
switch articleExtractorState { toolbarButton.state = isShowingExtractedArticle ? .on : .off
case .ready:
articleExtractorButton.isError = false guard let state = articleExtractor?.state else {
articleExtractorButton.isInProgress = false toolbarButton.isError = false
return currentLink != nil toolbarButton.isInProgress = false
case .processing: toolbarButton.state = .off
articleExtractorButton.isError = false
articleExtractorButton.isInProgress = true
return true
case .failedToParse:
articleExtractorButton.isError = true
articleExtractorButton.isInProgress = false
articleExtractorButton.state = .off
return true
case .complete:
articleExtractorButton.isError = false
articleExtractorButton.isInProgress = false
return currentLink != nil return currentLink != nil
} }
switch state {
case .processing:
toolbarButton.isError = false
toolbarButton.isInProgress = true
case .failedToParse:
toolbarButton.isError = true
toolbarButton.isInProgress = false
case .ready, .cancelled, .complete:
toolbarButton.isError = false
toolbarButton.isInProgress = false
}
return true
} }
func canMarkOlderArticlesAsRead() -> Bool { func canMarkOlderArticlesAsRead() -> Bool {

View File

@ -13,6 +13,7 @@ public enum ArticleExtractorState {
case processing case processing
case failedToParse case failedToParse
case complete case complete
case cancelled
} }
protocol ArticleExtractorDelegate { protocol ArticleExtractorDelegate {
@ -28,6 +29,8 @@ enum ArticleExtractorError: Error {
class ArticleExtractor { class ArticleExtractor {
private var dataTask: URLSessionDataTask? = nil
var state: ArticleExtractorState! var state: ArticleExtractorState!
var article: ExtractedArticle? var article: ExtractedArticle?
var delegate: ArticleExtractorDelegate? var delegate: ArticleExtractorDelegate?
@ -57,7 +60,7 @@ class ArticleExtractor {
state = .processing state = .processing
let dataTask = URLSession.shared.dataTask(with: url) { [weak self] data, response, error in dataTask = URLSession.shared.dataTask(with: url) { [weak self] data, response, error in
guard let self = self else { return } guard let self = self else { return }
@ -95,8 +98,13 @@ class ArticleExtractor {
} }
dataTask.resume() dataTask!.resume()
} }
public func cancel() {
state = .cancelled
dataTask?.cancel()
}
} }