mirror of
https://github.com/Ranchero-Software/NetNewsWire.git
synced 2025-01-27 09:21:21 +01:00
673f0ce718
If a single sync failure is encountered a sheet is presented which allows the user to update their credentials. If multiple sync failures are encountered an alert is shown listing the accounts which encountered errors. On iOS, this alert can take the user into Settings, but there is no obvious way to programatically pesent macOS preferences.
220 lines
5.6 KiB
Swift
220 lines
5.6 KiB
Swift
//
|
|
// SceneNavigationView.swift
|
|
// NetNewsWire
|
|
//
|
|
// Created by Maurice Parker on 6/28/20.
|
|
// Copyright © 2020 Ranchero Software. All rights reserved.
|
|
//
|
|
|
|
import SwiftUI
|
|
import Account
|
|
|
|
struct SceneNavigationView: View {
|
|
|
|
@StateObject private var sceneModel = SceneModel()
|
|
@State private var showSheet = false
|
|
@State private var showShareSheet = false
|
|
@State private var sheetToShow: SidebarSheets = .none
|
|
@State private var showAccountSyncErrorAlert = false // multiple sync errors
|
|
|
|
#if os(iOS)
|
|
@Environment(\.horizontalSizeClass) private var horizontalSizeClass
|
|
#endif
|
|
|
|
var body: some View {
|
|
NavigationView {
|
|
#if os(macOS)
|
|
SidebarContainerView()
|
|
.frame(minWidth: 100, idealWidth: 150, maxHeight: .infinity)
|
|
#else
|
|
SidebarContainerView()
|
|
#endif
|
|
|
|
#if os(iOS)
|
|
if horizontalSizeClass != .compact {
|
|
TimelineContainerView()
|
|
}
|
|
#else
|
|
TimelineContainerView()
|
|
#endif
|
|
|
|
ArticleContainerView()
|
|
}
|
|
.environmentObject(sceneModel)
|
|
.onAppear {
|
|
sceneModel.startup()
|
|
}
|
|
.onChange(of: sheetToShow) { value in
|
|
value != .none ? (showSheet = true) : (showSheet = false)
|
|
}
|
|
.onReceive(sceneModel.$accountSyncErrors) { errors in
|
|
if errors.count == 0 {
|
|
showAccountSyncErrorAlert = false
|
|
} else {
|
|
if errors.count > 1 {
|
|
showAccountSyncErrorAlert = true
|
|
} else {
|
|
sheetToShow = .fixCredentials
|
|
}
|
|
}
|
|
}
|
|
.sheet(isPresented: $showSheet,
|
|
onDismiss: {
|
|
sheetToShow = .none
|
|
sceneModel.accountSyncErrors = []
|
|
}) {
|
|
if sheetToShow == .web {
|
|
AddWebFeedView()
|
|
}
|
|
if sheetToShow == .folder {
|
|
AddFolderView()
|
|
}
|
|
#if os(iOS)
|
|
if sheetToShow == .settings {
|
|
SettingsView()
|
|
}
|
|
#endif
|
|
if sheetToShow == .fixCredentials {
|
|
FixAccountCredentialView(accountSyncError: sceneModel.accountSyncErrors[0])
|
|
}
|
|
}
|
|
.alert(isPresented: $showAccountSyncErrorAlert, content: {
|
|
#if os(macOS)
|
|
return Alert(title: Text("Account Sync Error"),
|
|
message: Text("The following accounts failed to sync: ") + Text(sceneModel.accountSyncErrors.map({ $0.account.nameForDisplay }).joined(separator: ", ")) + Text(". You can update credentials in Preferences"),
|
|
dismissButton: .default(Text("Dismiss")))
|
|
#else
|
|
return Alert(title: Text("Account Sync Error"),
|
|
message: Text("The following accounts failed to sync: ") + Text(sceneModel.accountSyncErrors.map({ $0.account.nameForDisplay }).joined(separator: ", ")) + Text(". You can update credentials in Settings"),
|
|
primaryButton: .default(Text("Show Settings"), action: {
|
|
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5, execute: {
|
|
sheetToShow = .settings
|
|
})
|
|
|
|
}),
|
|
secondaryButton: .cancel(Text("Dismiss")))
|
|
|
|
#endif
|
|
})
|
|
.toolbar {
|
|
|
|
#if os(macOS)
|
|
ToolbarItem() {
|
|
Menu {
|
|
Button("Add Web Feed", action: { sheetToShow = .web })
|
|
Button("Add Reddit Feed", action: { })
|
|
Button("Add Twitter Feed", action: { })
|
|
Button("Add Folder", action: { sheetToShow = .folder})
|
|
} label : {
|
|
AppAssets.addMenuImage
|
|
}
|
|
}
|
|
ToolbarItem {
|
|
Button {
|
|
// AccountManager.shared.refreshAll(errorHandler: handleRefreshError)
|
|
|
|
AccountManager.shared.refreshAll(completion: nil)
|
|
|
|
} label: {
|
|
AppAssets.refreshImage
|
|
}
|
|
.help("Refresh").padding(.trailing, 40)
|
|
}
|
|
ToolbarItem {
|
|
Button {
|
|
sceneModel.markAllAsRead()
|
|
} label: {
|
|
AppAssets.markAllAsReadImagePNG
|
|
.offset(y: 7)
|
|
}
|
|
.disabled(sceneModel.markAllAsReadButtonState == nil)
|
|
.help("Mark All as Read")
|
|
}
|
|
ToolbarItem {
|
|
MacSearchField()
|
|
.frame(width: 200)
|
|
}
|
|
ToolbarItem {
|
|
Button {
|
|
sceneModel.goToNextUnread()
|
|
} label: {
|
|
AppAssets.nextUnreadArticleImage
|
|
}
|
|
.disabled(sceneModel.nextUnreadButtonState == nil)
|
|
.help("Go to Next Unread").padding(.trailing, 40)
|
|
}
|
|
ToolbarItem {
|
|
Button {
|
|
sceneModel.toggleReadStatusForSelectedArticles()
|
|
} label: {
|
|
if sceneModel.readButtonState ?? false {
|
|
AppAssets.readClosedImage
|
|
} else {
|
|
AppAssets.readOpenImage
|
|
}
|
|
}
|
|
.disabled(sceneModel.readButtonState == nil)
|
|
.help(sceneModel.readButtonState ?? false ? "Mark as Unread" : "Mark as Read")
|
|
}
|
|
ToolbarItem {
|
|
Button {
|
|
sceneModel.toggleStarredStatusForSelectedArticles()
|
|
} label: {
|
|
if sceneModel.starButtonState ?? false {
|
|
AppAssets.starClosedImage
|
|
} else {
|
|
AppAssets.starOpenImage
|
|
}
|
|
}
|
|
.disabled(sceneModel.starButtonState == nil)
|
|
.help(sceneModel.starButtonState ?? false ? "Mark as Unstarred" : "Mark as Starred")
|
|
}
|
|
ToolbarItem {
|
|
Button {
|
|
} label: {
|
|
AppAssets.articleExtractorOff
|
|
}
|
|
.disabled(sceneModel.extractorButtonState == nil)
|
|
.help("Show Reader View")
|
|
}
|
|
ToolbarItem {
|
|
Button {
|
|
sceneModel.openSelectedArticleInBrowser()
|
|
} label: {
|
|
AppAssets.openInBrowserImage
|
|
}
|
|
.disabled(sceneModel.openInBrowserButtonState == nil)
|
|
.help("Open in Browser")
|
|
}
|
|
ToolbarItem {
|
|
ZStack {
|
|
if showShareSheet {
|
|
SharingServiceView(articles: sceneModel.selectedArticles, showing: $showShareSheet)
|
|
.frame(width: 20, height: 20)
|
|
}
|
|
Button {
|
|
showShareSheet = true
|
|
} label: {
|
|
AppAssets.shareImage
|
|
}
|
|
}
|
|
.disabled(sceneModel.shareButtonState == nil)
|
|
.help("Share")
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
|
|
func handleRefreshError(_ error: Error) {
|
|
sceneModel.accountErrorMessage = error.localizedDescription
|
|
}
|
|
|
|
}
|
|
|
|
struct NavigationView_Previews: PreviewProvider {
|
|
static var previews: some View {
|
|
SceneNavigationView()
|
|
.environmentObject(SceneModel())
|
|
}
|
|
}
|