Add menu and keyboard shortcut to Reader
This commit is contained in:
parent
6a7d1df423
commit
76056e4fef
@ -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>
|
||||||
|
@ -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>
|
||||||
|
@ -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 {
|
||||||
|
@ -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()
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user