Initial work on #2287

This commit is contained in:
Stuart Breckenridge
2020-07-21 16:05:31 +08:00
parent c0e9f28398
commit 7639ea2780
6 changed files with 148 additions and 3 deletions

View File

@@ -7,9 +7,14 @@
//
import SwiftUI
import RSCore
import Account
struct SidebarContextMenu: View {
@Environment(\.undoManager) var undoManager
@Environment(\.openURL) var openURL
@EnvironmentObject private var sidebarModel: SidebarModel
@Binding var showInspector: Bool
var sidebarItem: SidebarItem
@@ -26,6 +31,7 @@ struct SidebarContextMenu: View {
#endif
}
Button {
sidebarModel.markAllAsRead(account: sidebarItem.represented as! Account)
} label: {
Text("Mark All As Read")
#if os(iOS)
@@ -36,6 +42,10 @@ struct SidebarContextMenu: View {
if sidebarItem.representedType == .pseudoFeed {
Button {
guard let feed = sidebarItem.feed else {
return
}
sidebarModel.markAllAsRead(feed: feed)
} label: {
Text("Mark All As Read")
#if os(iOS)
@@ -54,6 +64,10 @@ struct SidebarContextMenu: View {
#endif
}
Button {
guard let feed = sidebarItem.feed else {
return
}
sidebarModel.markAllAsRead(feed: feed)
} label: {
Text("Mark All As Read")
#if os(iOS)
@@ -62,6 +76,11 @@ struct SidebarContextMenu: View {
}
Divider()
Button {
guard let homepage = (sidebarItem.feed as? WebFeed)?.homePageURL,
let url = URL(string: homepage) else {
return
}
openURL(url)
} label: {
Text("Open Home Page")
#if os(iOS)
@@ -70,6 +89,15 @@ struct SidebarContextMenu: View {
}
Divider()
Button {
guard let feedUrl = (sidebarItem.feed as? WebFeed)?.url else {
return
}
#if os(macOS)
URLPasteboardWriter.write(urlString: feedUrl, to: NSPasteboard.general)
#else
UIPasteboard.general.string = feedUrl
#endif
} label: {
Text("Copy Feed URL")
#if os(iOS)
@@ -77,6 +105,14 @@ struct SidebarContextMenu: View {
#endif
}
Button {
guard let homepage = (sidebarItem.feed as? WebFeed)?.homePageURL else {
return
}
#if os(macOS)
URLPasteboardWriter.write(urlString: homepage, to: NSPasteboard.general)
#else
UIPasteboard.general.string = homepage
#endif
} label: {
Text("Copy Home Page URL")
#if os(iOS)
@@ -85,6 +121,7 @@ struct SidebarContextMenu: View {
}
Divider()
Button {
sidebarModel.deleteItems(item: sidebarItem)
} label: {
Text("Delete")
#if os(iOS)
@@ -103,6 +140,10 @@ struct SidebarContextMenu: View {
#endif
}
Button {
guard let feed = sidebarItem.feed else {
return
}
sidebarModel.markAllAsRead(feed: feed)
} label: {
Text("Mark All As Read")
#if os(iOS)
@@ -111,6 +152,7 @@ struct SidebarContextMenu: View {
}
Divider()
Button {
sidebarModel.deleteItems(item: sidebarItem)
} label: {
Text("Delete")
#if os(iOS)

View File

@@ -6,7 +6,7 @@
// Copyright © 2020 Ranchero Software. All rights reserved.
//
import Foundation
import SwiftUI
import RSCore
import Account

View File

@@ -12,6 +12,7 @@ import Account
struct SidebarItemView: View {
@StateObject var feedIconImageLoader = FeedIconImageLoader()
@EnvironmentObject private var sidebarModel: SidebarModel
@State private var showInspector: Bool = false
var sidebarItem: SidebarItem
@@ -39,6 +40,7 @@ struct SidebarItemView: View {
}
}.contextMenu {
SidebarContextMenu(showInspector: $showInspector, sidebarItem: sidebarItem)
.environmentObject(sidebarModel)
}
.sheet(isPresented: $showInspector, onDismiss: { showInspector = false}) {
InspectorView(sidebarItem: sidebarItem)

View File

@@ -10,6 +10,7 @@ import Foundation
import Combine
import RSCore
import Account
import Articles
protocol SidebarModelDelegate: class {
func unreadCount(for: Feed) -> Int
@@ -54,6 +55,90 @@ class SidebarModel: ObservableObject, UndoableCommandRunner {
}
// MARK: Side Context Menu Actions
extension SidebarModel {
func markAllAsRead(feed: Feed) {
var articles = Set<Article>()
let fetchedArticles = try! feed.fetchArticles()
for article in fetchedArticles {
articles.insert(article)
}
for selectedFeed in selectedFeeds {
let fetchedArticles = try! selectedFeed.fetchArticles()
for article in fetchedArticles {
articles.insert(article)
}
}
markAllAsRead(Array(articles))
}
func markAllAsRead(account: Account) {
var articles = Set<Article>()
for feed in account.flattenedWebFeeds() {
let unreadArticles = try! feed.fetchUnreadArticles()
articles.formUnion(unreadArticles)
}
markAllAsRead(Array(articles))
}
/// Marks provided artices as read.
/// - Parameter articles: An array of `Article`s.
/// - Warning: An `UndoManager` is created here as the `Environment`'s undo manager appears to be `nil`.
private func markAllAsRead(_ articles: [Article]) {
guard let undoManager = undoManager ?? UndoManager(),
let markAsReadCommand = MarkStatusCommand(initialArticles: articles, markingRead: true, undoManager: undoManager) else {
return
}
runCommand(markAsReadCommand)
}
func deleteItems(item: SidebarItem) {
if selectedFeeds.count > 0 {
for feed in selectedFeeds {
if feed is WebFeed {
let account = (feed as! WebFeed).account
account?.removeWebFeed(feed as! WebFeed)
}
if feed is Folder {
let account = (feed as! Folder).account
account?.removeFolder(feed as! Folder, completion: { (result) in
switch result {
case .success( _):
print("Deleted folder")
case .failure(let err):
print(err.localizedDescription)
}
})
}
}
} else {
if item.feed is WebFeed {
let account = (item.feed as! WebFeed).account
account?.removeWebFeed(item.feed as! WebFeed)
}
if item.feed is Folder {
let account = (item.feed as! Folder).account
account?.removeFolder(item.feed as! Folder, completion: { (result) in
switch result {
case .success( _):
print("Deleted folder")
case .failure(let err):
print(err.localizedDescription)
}
})
}
}
}
}
// MARK: Private
private extension SidebarModel {

View File

@@ -13,11 +13,12 @@ struct SidebarView: View {
// I had to comment out SceneStorage because it blows up if used on macOS
// @SceneStorage("expandedContainers") private var expandedContainerData = Data()
@Environment(\.undoManager) var undoManager
@StateObject private var expandedContainers = SidebarExpandedContainers()
@EnvironmentObject private var refreshProgress: RefreshProgressModel
@EnvironmentObject private var sceneModel: SceneModel
@EnvironmentObject private var sidebarModel: SidebarModel
private let threshold: CGFloat = 80
@State private var previousScrollOffset: CGFloat = 0
@State private var scrollOffset: CGFloat = 0
@@ -60,6 +61,9 @@ struct SidebarView: View {
.transition(.move(edge: .bottom))
}
}
.onAppear {
sidebarModel.undoManager = undoManager
}
#else
ZStack(alignment: .top) {
List {
@@ -74,7 +78,11 @@ struct SidebarView: View {
ProgressView().offset(y: -40)
}
}
.onAppear {
sidebarModel.undoManager = undoManager
}
#endif
// .onAppear {
// expandedContainers.data = expandedContainerData
// }
@@ -158,15 +166,19 @@ struct SidebarView: View {
}
} label: {
#if os(macOS)
SidebarItemView(sidebarItem: sidebarItem).padding(.leading, 4)
SidebarItemView(sidebarItem: sidebarItem)
.padding(.leading, 4)
.environmentObject(sidebarModel)
#else
if sidebarItem.representedType == .smartFeedController {
GeometryReader { proxy in
SidebarItemView(sidebarItem: sidebarItem)
.preference(key: RefreshKeyTypes.PrefKey.self, value: [RefreshKeyTypes.PrefData(vType: .movingView, bounds: proxy.frame(in: .global))])
.environmentObject(sidebarModel)
}
} else {
SidebarItemView(sidebarItem: sidebarItem)
.environmentObject(sidebarModel)
}
#endif
}

View File

@@ -17,6 +17,8 @@
1729529524AA1CAA00D65E66 /* GeneralPreferencesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1729529224AA1CAA00D65E66 /* GeneralPreferencesView.swift */; };
1729529724AA1CD000D65E66 /* MacPreferencesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1729529624AA1CD000D65E66 /* MacPreferencesView.swift */; };
1729529B24AA1FD200D65E66 /* MacSearchField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1729529A24AA1FD200D65E66 /* MacSearchField.swift */; };
173A66B024C6C5C800DDA840 /* DeleteCommand.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84B99C9C1FAE83C600ECDEDB /* DeleteCommand.swift */; };
173A66D224C6C5C800DDA840 /* DeleteCommand.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84B99C9C1FAE83C600ECDEDB /* DeleteCommand.swift */; };
175942AA24AD533200585066 /* RefreshInterval.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5183CCE4226F4DFA0010922C /* RefreshInterval.swift */; };
175942AB24AD533200585066 /* RefreshInterval.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5183CCE4226F4DFA0010922C /* RefreshInterval.swift */; };
1769E32224BC5925000E1E8E /* AccountsPreferencesModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1769E32124BC5925000E1E8E /* AccountsPreferencesModel.swift */; };
@@ -5255,6 +5257,7 @@
51E498F724A8085D00B667CB /* SearchTimelineFeedDelegate.swift in Sources */,
175942AA24AD533200585066 /* RefreshInterval.swift in Sources */,
51E4993524A867E800B667CB /* AppNotifications.swift in Sources */,
173A66D224C6C5C800DDA840 /* DeleteCommand.swift in Sources */,
51C0515E24A77DF800194D5E /* MainApp.swift in Sources */,
51919FF724AB8B7700541E64 /* TimelineView.swift in Sources */,
51E4993D24A870F800B667CB /* UserNotificationManager.swift in Sources */,
@@ -5400,6 +5403,7 @@
1799E6CE24C320D600511E91 /* InspectorModel.swift in Sources */,
514E6C0024AD255D00AC6F6E /* PreviewArticles.swift in Sources */,
1729529524AA1CAA00D65E66 /* GeneralPreferencesView.swift in Sources */,
173A66B024C6C5C800DDA840 /* DeleteCommand.swift in Sources */,
1769E32724BC5B6C000E1E8E /* AddAccountModel.swift in Sources */,
1729529424AA1CAA00D65E66 /* AdvancedPreferencesView.swift in Sources */,
5177470424B2657F00EB0F74 /* TimelineToolbarModifier.swift in Sources */,