Add Feed Inspector
This commit is contained in:
parent
17c33b75e9
commit
ca4a7f8b0b
@ -19,6 +19,7 @@
|
|||||||
511D43D2231FA62C00FB1562 /* GlobalKeyboardShortcuts.plist in Resources */ = {isa = PBXBuildFile; fileRef = 844B5B641FEA11F200C7C76A /* GlobalKeyboardShortcuts.plist */; };
|
511D43D2231FA62C00FB1562 /* GlobalKeyboardShortcuts.plist in Resources */ = {isa = PBXBuildFile; fileRef = 844B5B641FEA11F200C7C76A /* GlobalKeyboardShortcuts.plist */; };
|
||||||
511D43EF231FBDE900FB1562 /* LaunchScreenPad.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 511D43ED231FBDE800FB1562 /* LaunchScreenPad.storyboard */; };
|
511D43EF231FBDE900FB1562 /* LaunchScreenPad.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 511D43ED231FBDE800FB1562 /* LaunchScreenPad.storyboard */; };
|
||||||
511D4419231FC02D00FB1562 /* KeyboardManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 511D4410231FC02D00FB1562 /* KeyboardManager.swift */; };
|
511D4419231FC02D00FB1562 /* KeyboardManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 511D4410231FC02D00FB1562 /* KeyboardManager.swift */; };
|
||||||
|
5123DB9F233EC6FD00282CC9 /* FeedInspectorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5123DB9E233EC6FD00282CC9 /* FeedInspectorView.swift */; };
|
||||||
5126EE97226CB48A00C22AFC /* SceneCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5126EE96226CB48A00C22AFC /* SceneCoordinator.swift */; };
|
5126EE97226CB48A00C22AFC /* SceneCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5126EE96226CB48A00C22AFC /* SceneCoordinator.swift */; };
|
||||||
5127B238222B4849006D641D /* DetailKeyboardDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5127B236222B4849006D641D /* DetailKeyboardDelegate.swift */; };
|
5127B238222B4849006D641D /* DetailKeyboardDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5127B236222B4849006D641D /* DetailKeyboardDelegate.swift */; };
|
||||||
5127B23A222B4849006D641D /* DetailKeyboardShortcuts.plist in Resources */ = {isa = PBXBuildFile; fileRef = 5127B237222B4849006D641D /* DetailKeyboardShortcuts.plist */; };
|
5127B23A222B4849006D641D /* DetailKeyboardShortcuts.plist in Resources */ = {isa = PBXBuildFile; fileRef = 5127B237222B4849006D641D /* DetailKeyboardShortcuts.plist */; };
|
||||||
@ -787,6 +788,7 @@
|
|||||||
51126DA3225FDE2F00722696 /* RSImage-Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "RSImage-Extensions.swift"; sourceTree = "<group>"; };
|
51126DA3225FDE2F00722696 /* RSImage-Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "RSImage-Extensions.swift"; sourceTree = "<group>"; };
|
||||||
511D43EE231FBDE800FB1562 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreenPad.storyboard; sourceTree = "<group>"; };
|
511D43EE231FBDE800FB1562 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreenPad.storyboard; sourceTree = "<group>"; };
|
||||||
511D4410231FC02D00FB1562 /* KeyboardManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = KeyboardManager.swift; sourceTree = "<group>"; };
|
511D4410231FC02D00FB1562 /* KeyboardManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = KeyboardManager.swift; sourceTree = "<group>"; };
|
||||||
|
5123DB9E233EC6FD00282CC9 /* FeedInspectorView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FeedInspectorView.swift; sourceTree = "<group>"; };
|
||||||
5126EE96226CB48A00C22AFC /* SceneCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneCoordinator.swift; sourceTree = "<group>"; };
|
5126EE96226CB48A00C22AFC /* SceneCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneCoordinator.swift; sourceTree = "<group>"; };
|
||||||
5127B236222B4849006D641D /* DetailKeyboardDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DetailKeyboardDelegate.swift; sourceTree = "<group>"; };
|
5127B236222B4849006D641D /* DetailKeyboardDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DetailKeyboardDelegate.swift; sourceTree = "<group>"; };
|
||||||
5127B237222B4849006D641D /* DetailKeyboardShortcuts.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = DetailKeyboardShortcuts.plist; sourceTree = "<group>"; };
|
5127B237222B4849006D641D /* DetailKeyboardShortcuts.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = DetailKeyboardShortcuts.plist; sourceTree = "<group>"; };
|
||||||
@ -1176,6 +1178,14 @@
|
|||||||
path = Resources;
|
path = Resources;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
|
5123DB95233EC69300282CC9 /* Inspector */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
5123DB9E233EC6FD00282CC9 /* FeedInspectorView.swift */,
|
||||||
|
);
|
||||||
|
path = Inspector;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
5127B235222B4849006D641D /* Keyboard */ = {
|
5127B235222B4849006D641D /* Keyboard */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
@ -1968,6 +1978,7 @@
|
|||||||
51C4526D2265091600C03939 /* MasterTimeline */,
|
51C4526D2265091600C03939 /* MasterTimeline */,
|
||||||
51C4527D2265092C00C03939 /* Article */,
|
51C4527D2265092C00C03939 /* Article */,
|
||||||
51C452802265093600C03939 /* Add */,
|
51C452802265093600C03939 /* Add */,
|
||||||
|
5123DB95233EC69300282CC9 /* Inspector */,
|
||||||
5183CCEB227117C70010922C /* Settings */,
|
5183CCEB227117C70010922C /* Settings */,
|
||||||
5183CCDB226F1EEB0010922C /* Progress */,
|
5183CCDB226F1EEB0010922C /* Progress */,
|
||||||
519D740423243C68008BB345 /* Model Extensions */,
|
519D740423243C68008BB345 /* Model Extensions */,
|
||||||
@ -2828,6 +2839,7 @@
|
|||||||
51C452AE2265104D00C03939 /* TimelineStringFormatter.swift in Sources */,
|
51C452AE2265104D00C03939 /* TimelineStringFormatter.swift in Sources */,
|
||||||
512E08E62268800D00BDCFDD /* FolderTreeControllerDelegate.swift in Sources */,
|
512E08E62268800D00BDCFDD /* FolderTreeControllerDelegate.swift in Sources */,
|
||||||
51C4529922650A0000C03939 /* ArticleStylesManager.swift in Sources */,
|
51C4529922650A0000C03939 /* ArticleStylesManager.swift in Sources */,
|
||||||
|
5123DB9F233EC6FD00282CC9 /* FeedInspectorView.swift in Sources */,
|
||||||
51EF0F802277A8330050506E /* MasterTimelineCellLayout.swift in Sources */,
|
51EF0F802277A8330050506E /* MasterTimelineCellLayout.swift in Sources */,
|
||||||
51F85BF722749FA100C787DC /* UIFont-Extensions.swift in Sources */,
|
51F85BF722749FA100C787DC /* UIFont-Extensions.swift in Sources */,
|
||||||
51C452AF2265108300C03939 /* ArticleArray.swift in Sources */,
|
51C452AF2265108300C03939 /* ArticleArray.swift in Sources */,
|
||||||
|
99
iOS/Inspector/FeedInspectorView.swift
Normal file
99
iOS/Inspector/FeedInspectorView.swift
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
//
|
||||||
|
// FeedInspector.swift
|
||||||
|
// NetNewsWire-iOS
|
||||||
|
//
|
||||||
|
// Created by Maurice Parker on 9/27/19.
|
||||||
|
// Copyright © 2019 Ranchero Software. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import SwiftUI
|
||||||
|
import Combine
|
||||||
|
import Account
|
||||||
|
|
||||||
|
struct FeedInspectorView : View {
|
||||||
|
|
||||||
|
@ObservedObject var viewModel: ViewModel
|
||||||
|
@Environment(\.viewController) private var viewController: UIViewController?
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
NavigationView {
|
||||||
|
Form {
|
||||||
|
Section(header:
|
||||||
|
HStack {
|
||||||
|
Spacer()
|
||||||
|
Image(uiImage: self.viewModel.image).resizable().frame(width: 48.0, height: 48.0)
|
||||||
|
Spacer()
|
||||||
|
}) {
|
||||||
|
TextField("Feed Name", text: $viewModel.name)
|
||||||
|
Toggle(isOn: $viewModel.isArticleExtractorAlwaysOn) {
|
||||||
|
Text("Reader View is always on")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Section(header: Text("HOME PAGE")) {
|
||||||
|
Text(verbatim: self.viewModel.homePageURL)
|
||||||
|
}
|
||||||
|
Section(header: Text("FEED URL")) {
|
||||||
|
Text(verbatim: self.viewModel.feedLinkURL)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.navigationBarTitle(Text(verbatim: self.viewModel.nameForDisplay), displayMode: .inline)
|
||||||
|
.navigationBarItems(leading: Button(action: { self.viewController?.dismiss(animated: true) }) { Text("Done") } )
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: ViewModel
|
||||||
|
|
||||||
|
class ViewModel: ObservableObject {
|
||||||
|
|
||||||
|
let objectWillChange = ObservableObjectPublisher()
|
||||||
|
let feed: Feed
|
||||||
|
|
||||||
|
init(feed: Feed) {
|
||||||
|
self.feed = feed
|
||||||
|
}
|
||||||
|
|
||||||
|
var image: UIImage {
|
||||||
|
if let feedIcon = appDelegate.feedIconDownloader.icon(for: feed) {
|
||||||
|
return feedIcon
|
||||||
|
}
|
||||||
|
if let favicon = appDelegate.faviconDownloader.favicon(for: feed) {
|
||||||
|
return favicon
|
||||||
|
}
|
||||||
|
return FaviconGenerator.favicon(feed)
|
||||||
|
}
|
||||||
|
|
||||||
|
var nameForDisplay: String {
|
||||||
|
return feed.nameForDisplay
|
||||||
|
}
|
||||||
|
|
||||||
|
var name: String {
|
||||||
|
get {
|
||||||
|
return feed.editedName ?? feed.name ?? ""
|
||||||
|
}
|
||||||
|
set {
|
||||||
|
objectWillChange.send()
|
||||||
|
feed.editedName = newValue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var isArticleExtractorAlwaysOn: Bool {
|
||||||
|
get {
|
||||||
|
return feed.isArticleExtractorAlwaysOn ?? false
|
||||||
|
}
|
||||||
|
set {
|
||||||
|
objectWillChange.send()
|
||||||
|
feed.isArticleExtractorAlwaysOn = newValue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var homePageURL: String {
|
||||||
|
return feed.homePageURL ?? ""
|
||||||
|
}
|
||||||
|
|
||||||
|
var feedLinkURL: String {
|
||||||
|
return feed.url
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -46,6 +46,8 @@ class MasterTimelineViewController: UITableViewController, UndoableCommandRunner
|
|||||||
NotificationCenter.default.addObserver(self, selector: #selector(userDefaultsDidChange(_:)), name: UserDefaults.didChangeNotification, object: nil)
|
NotificationCenter.default.addObserver(self, selector: #selector(userDefaultsDidChange(_:)), name: UserDefaults.didChangeNotification, object: nil)
|
||||||
NotificationCenter.default.addObserver(self, selector: #selector(progressDidChange(_:)), name: .AccountRefreshProgressDidChange, object: nil)
|
NotificationCenter.default.addObserver(self, selector: #selector(progressDidChange(_:)), name: .AccountRefreshProgressDidChange, object: nil)
|
||||||
NotificationCenter.default.addObserver(self, selector: #selector(contentSizeCategoryDidChange), name: UIContentSizeCategory.didChangeNotification, object: nil)
|
NotificationCenter.default.addObserver(self, selector: #selector(contentSizeCategoryDidChange), name: UIContentSizeCategory.didChangeNotification, object: nil)
|
||||||
|
NotificationCenter.default.addObserver(self, selector: #selector(displayNameDidChange), name: .DisplayNameDidChange, object: nil)
|
||||||
|
|
||||||
|
|
||||||
// Setup the Search Controller
|
// Setup the Search Controller
|
||||||
searchController.delegate = self
|
searchController.delegate = self
|
||||||
@ -129,6 +131,10 @@ class MasterTimelineViewController: UITableViewController, UndoableCommandRunner
|
|||||||
coordinator.navigateToDetail()
|
coordinator.navigateToDetail()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@objc func showFeedInspector(_ sender: UITapGestureRecognizer) {
|
||||||
|
coordinator.showFeedInspector()
|
||||||
|
}
|
||||||
|
|
||||||
// MARK: API
|
// MARK: API
|
||||||
|
|
||||||
func restoreSelectionIfNecessary() {
|
func restoreSelectionIfNecessary() {
|
||||||
@ -365,6 +371,10 @@ class MasterTimelineViewController: UITableViewController, UndoableCommandRunner
|
|||||||
updateProgressIndicatorIfNeeded()
|
updateProgressIndicatorIfNeeded()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@objc func displayNameDidChange(_ note: Notification) {
|
||||||
|
titleView?.label.text = coordinator.timelineName
|
||||||
|
}
|
||||||
|
|
||||||
// MARK: Reloading
|
// MARK: Reloading
|
||||||
|
|
||||||
func queueReloadAvailableCells() {
|
func queueReloadAvailableCells() {
|
||||||
@ -454,12 +464,21 @@ private extension MasterTimelineViewController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func resetUI() {
|
func resetUI() {
|
||||||
|
|
||||||
title = coordinator.timelineName
|
title = coordinator.timelineName
|
||||||
|
|
||||||
if let titleView = Bundle.main.loadNibNamed("MasterTimelineTitleView", owner: self, options: nil)?[0] as? MasterTimelineTitleView {
|
if let titleView = Bundle.main.loadNibNamed("MasterTimelineTitleView", owner: self, options: nil)?[0] as? MasterTimelineTitleView {
|
||||||
self.titleView = titleView
|
self.titleView = titleView
|
||||||
titleView.imageView.image = coordinator.timelineFavicon
|
titleView.imageView.image = coordinator.timelineFavicon
|
||||||
titleView.label.text = coordinator.timelineName
|
titleView.label.text = coordinator.timelineName
|
||||||
|
|
||||||
|
if coordinator.timelineFetcher is Feed {
|
||||||
|
let width = titleView.sizeThatFits(CGSize(width: CGFloat.greatestFiniteMagnitude, height: CGFloat.greatestFiniteMagnitude)).width
|
||||||
|
titleView.widthAnchor.constraint(equalToConstant: width).isActive = true
|
||||||
|
titleView.heightAnchor.constraint(equalToConstant: 44.0).isActive = true
|
||||||
|
let tap = UITapGestureRecognizer(target: self, action:#selector(showFeedInspector(_:)))
|
||||||
|
titleView.addGestureRecognizer(tap)
|
||||||
|
}
|
||||||
|
|
||||||
navigationItem.titleView = titleView
|
navigationItem.titleView = titleView
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -788,6 +788,15 @@ class SceneCoordinator: NSObject, UndoableCommandRunner, UnreadCountProvider {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func showFeedInspector() {
|
||||||
|
guard let feed = timelineFetcher as? Feed else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
rootSplitViewController.present(style: .formSheet) {
|
||||||
|
FeedInspectorView(viewModel: FeedInspectorView.ViewModel(feed: feed))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func showAdd(_ type: AddControllerType, initialFeed: String? = nil, initialFeedName: String? = nil) {
|
func showAdd(_ type: AddControllerType, initialFeed: String? = nil, initialFeedName: String? = nil) {
|
||||||
selectFeed(nil)
|
selectFeed(nil)
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user