mirror of
https://github.com/Ranchero-Software/NetNewsWire
synced 2025-08-12 06:26:36 +00:00
Merge pull request #2283 from stuartbreckenridge/hotfix/inspector-tweaks
Inspector tweaks
This commit is contained in:
@@ -19,9 +19,12 @@ import UIKit
|
|||||||
|
|
||||||
class InspectorModel: ObservableObject {
|
class InspectorModel: ObservableObject {
|
||||||
|
|
||||||
@Published var notificationSettings: UNNotificationSettings?
|
// Global Inspector Variables
|
||||||
@Published var editedName: String = ""
|
@Published var editedName: String = ""
|
||||||
@Published var shouldUpdate: Bool = false
|
@Published var shouldUpdate: Bool = false
|
||||||
|
|
||||||
|
// Account Inspector Variables
|
||||||
|
@Published var notificationSettings: UNNotificationSettings?
|
||||||
@Published var notifyAboutNewArticles: Bool = false {
|
@Published var notifyAboutNewArticles: Bool = false {
|
||||||
didSet {
|
didSet {
|
||||||
updateNotificationSettings()
|
updateNotificationSettings()
|
||||||
@@ -32,6 +35,14 @@ class InspectorModel: ObservableObject {
|
|||||||
selectedWebFeed?.isArticleExtractorAlwaysOn = alwaysShowReaderView
|
selectedWebFeed?.isArticleExtractorAlwaysOn = alwaysShowReaderView
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@Published var accountIsActive: Bool = false {
|
||||||
|
didSet {
|
||||||
|
selectedAccount?.isActive = accountIsActive
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@Published var showHomePage: Bool = false // iOS only
|
||||||
|
|
||||||
|
// Private Variables
|
||||||
private let centre = UNUserNotificationCenter.current()
|
private let centre = UNUserNotificationCenter.current()
|
||||||
private var selectedWebFeed: WebFeed?
|
private var selectedWebFeed: WebFeed?
|
||||||
private var selectedFolder: Folder?
|
private var selectedFolder: Folder?
|
||||||
@@ -71,6 +82,7 @@ class InspectorModel: ObservableObject {
|
|||||||
func configure(with account: Account) {
|
func configure(with account: Account) {
|
||||||
selectedAccount = account
|
selectedAccount = account
|
||||||
editedName = account.nameForDisplay
|
editedName = account.nameForDisplay
|
||||||
|
accountIsActive = account.isActive
|
||||||
}
|
}
|
||||||
|
|
||||||
func updateNotificationSettings() {
|
func updateNotificationSettings() {
|
||||||
|
|||||||
@@ -16,24 +16,29 @@ struct InspectorPlatformModifier: ViewModifier {
|
|||||||
@ViewBuilder func body(content: Content) -> some View {
|
@ViewBuilder func body(content: Content) -> some View {
|
||||||
|
|
||||||
#if os(macOS)
|
#if os(macOS)
|
||||||
content
|
Form {
|
||||||
.textFieldStyle(RoundedBorderTextFieldStyle())
|
content
|
||||||
.frame(width: 300)
|
}
|
||||||
.padding()
|
.textFieldStyle(RoundedBorderTextFieldStyle())
|
||||||
|
.frame(width: 300)
|
||||||
|
.padding()
|
||||||
#else
|
#else
|
||||||
NavigationView {
|
NavigationView {
|
||||||
content
|
List {
|
||||||
.navigationBarTitle("Inspector", displayMode: .inline)
|
content
|
||||||
.navigationBarItems(
|
}
|
||||||
leading:
|
.listStyle(InsetGroupedListStyle())
|
||||||
Button("Cancel", action: {
|
.navigationBarTitle("Inspector", displayMode: .inline)
|
||||||
presentationMode.wrappedValue.dismiss()
|
.navigationBarItems(
|
||||||
}),
|
leading:
|
||||||
trailing:
|
Button("Cancel", action: {
|
||||||
Button("Done", action: {
|
presentationMode.wrappedValue.dismiss()
|
||||||
shouldUpdate = true
|
}),
|
||||||
})
|
trailing:
|
||||||
)
|
Button("Done", action: {
|
||||||
|
shouldUpdate = true
|
||||||
|
})
|
||||||
|
)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,17 +34,13 @@ struct InspectorView: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MARK: WebFeed Inspector
|
||||||
|
|
||||||
@ViewBuilder
|
@ViewBuilder
|
||||||
var WebFeedInspectorView: some View {
|
var WebFeedInspectorView: some View {
|
||||||
Form {
|
Group {
|
||||||
Section(header: Text("Name").bold()) {
|
Section(header: webFeedHeader) {
|
||||||
HStack(alignment: .center) {
|
TextField("", text: $inspectorModel.editedName)
|
||||||
if let image = feedIconImageLoader.image {
|
|
||||||
IconImageView(iconImage: image)
|
|
||||||
.frame(width: 30, height: 30)
|
|
||||||
}
|
|
||||||
TextField("", text: $inspectorModel.editedName)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if os(macOS)
|
#if os(macOS)
|
||||||
@@ -60,16 +56,65 @@ struct InspectorView: View {
|
|||||||
Divider()
|
Divider()
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
Section(header: Text("Home Page URL").bold()) {
|
Section(header: Text("Home Page URL")) {
|
||||||
Text((sidebarItem.feed as? WebFeed)?.homePageURL ?? "")
|
HStack {
|
||||||
|
Text((sidebarItem.feed as? WebFeed)?.homePageURL ?? "")
|
||||||
|
.fixedSize(horizontal: false, vertical: true)
|
||||||
|
Spacer()
|
||||||
|
AppAssets.openInBrowserImage
|
||||||
|
.foregroundColor(.accentColor)
|
||||||
|
}
|
||||||
|
.onTapGesture {
|
||||||
|
if let url = URL(string: (sidebarItem.feed as? WebFeed)?.homePageURL ?? "") {
|
||||||
|
#if os(macOS)
|
||||||
|
NSWorkspace.shared.open(url)
|
||||||
|
#else
|
||||||
|
inspectorModel.showHomePage = true
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.contextMenu(ContextMenu(menuItems: {
|
||||||
|
Button(action: {
|
||||||
|
if let urlString = (sidebarItem.feed as? WebFeed)?.homePageURL {
|
||||||
|
#if os(macOS)
|
||||||
|
URLPasteboardWriter.write(urlString: urlString, to: NSPasteboard.general)
|
||||||
|
#else
|
||||||
|
UIPasteboard.general.string = urlString
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}, label: {
|
||||||
|
Text("Copy Home Page URL")
|
||||||
|
})
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
.sheet(isPresented: $inspectorModel.showHomePage, onDismiss: { inspectorModel.showHomePage = false }) {
|
||||||
|
#if os(macOS)
|
||||||
|
EmptyView()
|
||||||
|
#else
|
||||||
|
SafariView(url: URL(string: (sidebarItem.feed as! WebFeed).homePageURL!)!)
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#if os(macOS)
|
#if os(macOS)
|
||||||
Divider()
|
Divider()
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
Section(header: Text("Feed URL").bold()) {
|
Section(header: Text("Feed URL")) {
|
||||||
Text((sidebarItem.feed as? WebFeed)?.url ?? "")
|
Text((sidebarItem.feed as? WebFeed)?.url ?? "")
|
||||||
|
.fixedSize(horizontal: false, vertical: true)
|
||||||
|
.contextMenu(ContextMenu(menuItems: {
|
||||||
|
Button(action: {
|
||||||
|
if let urlString = (sidebarItem.feed as? WebFeed)?.url {
|
||||||
|
#if os(macOS)
|
||||||
|
URLPasteboardWriter.write(urlString: urlString, to: NSPasteboard.general)
|
||||||
|
#else
|
||||||
|
UIPasteboard.general.string = urlString
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}, label: {
|
||||||
|
Text("Copy Feed URL")
|
||||||
|
})
|
||||||
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
#if os(macOS)
|
#if os(macOS)
|
||||||
@@ -77,7 +122,7 @@ struct InspectorView: View {
|
|||||||
Spacer()
|
Spacer()
|
||||||
Button("Cancel", action: {
|
Button("Cancel", action: {
|
||||||
presentationMode.wrappedValue.dismiss()
|
presentationMode.wrappedValue.dismiss()
|
||||||
})
|
}).keyboardShortcut(.cancelAction)
|
||||||
Button("Done", action: {
|
Button("Done", action: {
|
||||||
inspectorModel.shouldUpdate = true
|
inspectorModel.shouldUpdate = true
|
||||||
}).keyboardShortcut(.defaultAction)
|
}).keyboardShortcut(.defaultAction)
|
||||||
@@ -87,7 +132,7 @@ struct InspectorView: View {
|
|||||||
.onAppear {
|
.onAppear {
|
||||||
inspectorModel.configure(with: sidebarItem.feed as! WebFeed)
|
inspectorModel.configure(with: sidebarItem.feed as! WebFeed)
|
||||||
feedIconImageLoader.loadImage(for: sidebarItem.feed!)
|
feedIconImageLoader.loadImage(for: sidebarItem.feed!)
|
||||||
}.onChange(of: inspectorModel.shouldUpdate) { value in
|
}.onReceive(inspectorModel.$shouldUpdate) { value in
|
||||||
if value == true {
|
if value == true {
|
||||||
if inspectorModel.editedName.trimmingWhitespace.count > 0 {
|
if inspectorModel.editedName.trimmingWhitespace.count > 0 {
|
||||||
(sidebarItem.feed as? WebFeed)?.editedName = inspectorModel.editedName
|
(sidebarItem.feed as? WebFeed)?.editedName = inspectorModel.editedName
|
||||||
@@ -97,21 +142,27 @@ struct InspectorView: View {
|
|||||||
presentationMode.wrappedValue.dismiss()
|
presentationMode.wrappedValue.dismiss()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var webFeedHeader: some View {
|
||||||
|
HStack(alignment: .center) {
|
||||||
|
Spacer()
|
||||||
|
if let image = feedIconImageLoader.image {
|
||||||
|
IconImageView(iconImage: image)
|
||||||
|
.frame(width: 50, height: 50)
|
||||||
|
}
|
||||||
|
Spacer()
|
||||||
|
}.padding()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// MARK: Folder Inspector
|
||||||
|
|
||||||
@ViewBuilder
|
@ViewBuilder
|
||||||
var FolderInspectorView: some View {
|
var FolderInspectorView: some View {
|
||||||
|
Group {
|
||||||
Form {
|
Section(header: folderHeader) {
|
||||||
Section(header: Text("Name").bold()) {
|
TextField("", text: $inspectorModel.editedName)
|
||||||
HStack(alignment: .center) {
|
|
||||||
if let image = feedIconImageLoader.image {
|
|
||||||
IconImageView(iconImage: image)
|
|
||||||
.frame(width: 30, height: 30)
|
|
||||||
}
|
|
||||||
TextField("", text: $inspectorModel.editedName)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if os(macOS)
|
#if os(macOS)
|
||||||
@@ -119,7 +170,7 @@ struct InspectorView: View {
|
|||||||
Spacer()
|
Spacer()
|
||||||
Button("Cancel", action: {
|
Button("Cancel", action: {
|
||||||
presentationMode.wrappedValue.dismiss()
|
presentationMode.wrappedValue.dismiss()
|
||||||
})
|
}).keyboardShortcut(.cancelAction)
|
||||||
Button("Done", action: {
|
Button("Done", action: {
|
||||||
inspectorModel.shouldUpdate = true
|
inspectorModel.shouldUpdate = true
|
||||||
}).keyboardShortcut(.defaultAction)
|
}).keyboardShortcut(.defaultAction)
|
||||||
@@ -131,7 +182,7 @@ struct InspectorView: View {
|
|||||||
inspectorModel.configure(with: sidebarItem.represented as! Folder)
|
inspectorModel.configure(with: sidebarItem.represented as! Folder)
|
||||||
feedIconImageLoader.loadImage(for: sidebarItem.feed!)
|
feedIconImageLoader.loadImage(for: sidebarItem.feed!)
|
||||||
}
|
}
|
||||||
.onChange(of: inspectorModel.shouldUpdate) { value in
|
.onReceive(inspectorModel.$shouldUpdate) { value in
|
||||||
if value == true {
|
if value == true {
|
||||||
if inspectorModel.editedName.trimmingWhitespace.count > 0 {
|
if inspectorModel.editedName.trimmingWhitespace.count > 0 {
|
||||||
(sidebarItem.feed as? Folder)?.name = inspectorModel.editedName
|
(sidebarItem.feed as? Folder)?.name = inspectorModel.editedName
|
||||||
@@ -143,19 +194,26 @@ struct InspectorView: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var folderHeader: some View {
|
||||||
|
HStack(alignment: .center) {
|
||||||
|
Spacer()
|
||||||
|
if let image = feedIconImageLoader.image {
|
||||||
|
IconImageView(iconImage: image)
|
||||||
|
.frame(width: 50, height: 50)
|
||||||
|
}
|
||||||
|
Spacer()
|
||||||
|
}.padding()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// MARK: Account Inspector
|
||||||
|
|
||||||
@ViewBuilder
|
@ViewBuilder
|
||||||
var AccountInspectorView: some View {
|
var AccountInspectorView: some View {
|
||||||
Form {
|
Group {
|
||||||
Section(header: Text("Name").bold()) {
|
Section(header: accountHeader) {
|
||||||
HStack(alignment: .center) {
|
TextField("", text: $inspectorModel.editedName)
|
||||||
if let image = (sidebarItem.represented as? Account)?.smallIcon?.image {
|
Toggle("Active", isOn: $inspectorModel.accountIsActive)
|
||||||
Image(rsImage: image)
|
|
||||||
.resizable()
|
|
||||||
.aspectRatio(contentMode: .fit)
|
|
||||||
.frame(width: 30, height: 30)
|
|
||||||
}
|
|
||||||
TextField("", text: $inspectorModel.editedName)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if os(macOS)
|
#if os(macOS)
|
||||||
@@ -163,7 +221,7 @@ struct InspectorView: View {
|
|||||||
Spacer()
|
Spacer()
|
||||||
Button("Cancel", action: {
|
Button("Cancel", action: {
|
||||||
presentationMode.wrappedValue.dismiss()
|
presentationMode.wrappedValue.dismiss()
|
||||||
})
|
}).keyboardShortcut(.cancelAction)
|
||||||
Button("Done", action: {
|
Button("Done", action: {
|
||||||
inspectorModel.shouldUpdate = true
|
inspectorModel.shouldUpdate = true
|
||||||
}).keyboardShortcut(.defaultAction)
|
}).keyboardShortcut(.defaultAction)
|
||||||
@@ -173,7 +231,7 @@ struct InspectorView: View {
|
|||||||
.onAppear {
|
.onAppear {
|
||||||
inspectorModel.configure(with: sidebarItem.represented as! Account)
|
inspectorModel.configure(with: sidebarItem.represented as! Account)
|
||||||
}
|
}
|
||||||
.onChange(of: inspectorModel.shouldUpdate) { value in
|
.onReceive(inspectorModel.$shouldUpdate) { value in
|
||||||
if value == true {
|
if value == true {
|
||||||
if inspectorModel.editedName.trimmingWhitespace.count > 0 {
|
if inspectorModel.editedName.trimmingWhitespace.count > 0 {
|
||||||
(sidebarItem.represented as? Account)?.name = inspectorModel.editedName
|
(sidebarItem.represented as? Account)?.name = inspectorModel.editedName
|
||||||
@@ -185,6 +243,20 @@ struct InspectorView: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var accountHeader: some View {
|
||||||
|
HStack(alignment: .center) {
|
||||||
|
Spacer()
|
||||||
|
if let image = (sidebarItem.represented as? Account)?.smallIcon?.image {
|
||||||
|
Image(rsImage: image)
|
||||||
|
.resizable()
|
||||||
|
.aspectRatio(contentMode: .fit)
|
||||||
|
.frame(width: 50, height: 50)
|
||||||
|
}
|
||||||
|
Spacer()
|
||||||
|
}.padding()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user