diff --git a/Multiplatform/Shared/Add/AddWebFeedModel.swift b/Multiplatform/Shared/Add/AddWebFeedModel.swift new file mode 100644 index 000000000..1520d312e --- /dev/null +++ b/Multiplatform/Shared/Add/AddWebFeedModel.swift @@ -0,0 +1,132 @@ +// +// AddWebFeedModel.swift +// NetNewsWire +// +// Created by Stuart Breckenridge on 4/7/20. +// Copyright © 2020 Ranchero Software. All rights reserved. +// + +import Foundation +import Account +import RSCore +import SwiftUI + +enum AddWebFeedError: LocalizedError { + + case none, alreadySubscribed, initialDownload, noFeeds + + var errorDescription: String? { + switch self { + case .alreadySubscribed: + return NSLocalizedString("Can’t add this feed because you’ve already subscribed to it.", comment: "Feed finder") + case .initialDownload: + return NSLocalizedString("Can’t add this feed because of a download error.", comment: "Feed finder") + case .noFeeds: + return NSLocalizedString("Can’t add a feed because no feed was found.", comment: "Feed finder") + default: + return nil + } + } + +} + +class AddWebFeedModel: ObservableObject { + + @Published var shouldDismiss: Bool = false + @Published var providedURL: String = "" + @Published var providedName: String = "" + @Published var selectedFolderIndex: Int = 0 + @Published var addFeedError: AddWebFeedError? { + didSet { + addFeedError != AddWebFeedError.none ? (showError = true) : (showError = false) + } + } + @Published var showError: Bool = false + @Published var containers: [Container] = [] + @Published var showProgressIndicator: Bool = false + + init() { + for account in AccountManager.shared.sortedActiveAccounts { + containers.append(account) + if let sortedFolders = account.sortedFolders { + containers.append(contentsOf: sortedFolders) + } + } + } + + func pasteUrlFromPasteboard() { + guard let stringFromPasteboard = urlStringFromPasteboard, stringFromPasteboard.isValidURL else { + return + } + providedURL = stringFromPasteboard + } + + #if os(macOS) + var urlStringFromPasteboard: String? { + if let urlString = NSPasteboard.urlString(from: NSPasteboard.general) { + return urlString.normalizedURL + } + return nil + } + #else + var urlStringFromPasteboard: String? { + if let urlString = UIPasteboard.general.url?.absoluteString { + return urlString.normalizedURL + } + return nil + } + #endif + + struct AccountAndFolderSpecifier { + let account: Account + let folder: Folder? + } + + func accountAndFolderFromContainer(_ container: Container) -> AccountAndFolderSpecifier? { + if let account = container as? Account { + return AccountAndFolderSpecifier(account: account, folder: nil) + } + if let folder = container as? Folder, let account = folder.account { + return AccountAndFolderSpecifier(account: account, folder: folder) + } + return nil + } + + func addWebFeed() { + if let account = accountAndFolderFromContainer(containers[selectedFolderIndex])?.account { + + showProgressIndicator = true + + let container = containers[selectedFolderIndex] + + if account.hasWebFeed(withURL: providedURL) { + addFeedError = .alreadySubscribed + showProgressIndicator = false + return + } + + account.createWebFeed(url: providedURL, name: providedName, container: container, completion: { [weak self] result in + self?.showProgressIndicator = false + switch result { + case .success(let feed): + NotificationCenter.default.post(name: .UserDidAddFeed, object: self, userInfo: [UserInfoKey.webFeed: feed]) + self?.shouldDismiss = true + case .failure(let error): + switch error { + case AccountError.createErrorAlreadySubscribed: + self?.addFeedError = .alreadySubscribed + return + case AccountError.createErrorNotFound: + self?.addFeedError = .noFeeds + return + default: + print("Error") + } + } + }) + } + } + + + +} diff --git a/Multiplatform/Shared/Add/AddWebFeedView.swift b/Multiplatform/Shared/Add/AddWebFeedView.swift new file mode 100644 index 000000000..5741e6e1b --- /dev/null +++ b/Multiplatform/Shared/Add/AddWebFeedView.swift @@ -0,0 +1,163 @@ +// +// AddWebFeedView.swift +// NetNewsWire +// +// Created by Stuart Breckenridge on 3/7/20. +// Copyright © 2020 Ranchero Software. All rights reserved. +// + +import SwiftUI +import Account +import RSCore + + +struct AddWebFeedView: View { + + @Environment(\.presentationMode) private var presentationMode + @ObservedObject private var viewModel = AddWebFeedModel() + + @ViewBuilder var body: some View { + #if os(iOS) + iosForm + .onAppear { + viewModel.pasteUrlFromPasteboard() + } + .onReceive(viewModel.$shouldDismiss, perform: { dismiss in + if dismiss == true { + presentationMode.wrappedValue.dismiss() + } + }) + + #else + macForm + .onAppear { + viewModel.pasteUrlFromPasteboard() + }.alert(isPresented: $viewModel.showError) { + Alert(title: Text("Oops"), message: Text(viewModel.addFeedError!.localizedDescription), dismissButton: Alert.Button.cancel({ + viewModel.addFeedError = AddWebFeedError.none + })) + }.onReceive(viewModel.$shouldDismiss, perform: { dismiss in + if dismiss == true { + presentationMode.wrappedValue.dismiss() + } + }) + #endif + } + + #if os(macOS) + var macForm: some View { + Form { + HStack { + Spacer() + Image(systemName: "globe").foregroundColor(.accentColor).font(.title) + Text("Add a Web Feed") + .font(.title) + Spacer() + } + urlTextField + .textFieldStyle(RoundedBorderTextFieldStyle()) + .help("The URL of the feed you want to add.") + providedNameTextField + .textFieldStyle(RoundedBorderTextFieldStyle()) + .help("The name of the feed. (Optional.)") + folderPicker + .help("Pick the folder you want to add the feed to.") + buttonStack + } + .padding() + .frame(minWidth: 450) + } + #endif + + #if os(iOS) + @ViewBuilder var iosForm: some View { + NavigationView { + Form { + urlTextField + providedNameTextField + folderPicker + } + .listStyle(InsetGroupedListStyle()) + .navigationBarTitle("Add Web Feed") + .navigationBarTitleDisplayMode(.inline) + .navigationBarItems(leading: + Button("Cancel", action: { + presentationMode.wrappedValue.dismiss() + }) + .help("Cancel Add Feed") + , trailing: + Button("Add", action: { + viewModel.addWebFeed() + }) + .disabled(!viewModel.providedURL.isValidURL) + .help("Add Feed") + ) + } + } + #endif + + var urlTextField: some View { + HStack { + Text("Feed:") + #if os(iOS) + TextField("URL", text: $viewModel.providedURL) + .disableAutocorrection(true) + .autocapitalization(UITextAutocapitalizationType.none) + #else + TextField("URL", text: $viewModel.providedURL) + .disableAutocorrection(true) + #endif + } + } + + var providedNameTextField: some View { + HStack(alignment: .lastTextBaseline) { + Text("Name:") + TextField("Optional", text: $viewModel.providedName) + } + } + + var folderPicker: some View { + Picker("Folder:", selection: $viewModel.selectedFolderIndex, content: { + ForEach(0.. RSImage? { switch accountType { diff --git a/Multiplatform/Shared/Article/ArticleContainerView.swift b/Multiplatform/Shared/Article/ArticleContainerView.swift index 021c39d62..8db0c6318 100644 --- a/Multiplatform/Shared/Article/ArticleContainerView.swift +++ b/Multiplatform/Shared/Article/ArticleContainerView.swift @@ -13,19 +13,15 @@ struct ArticleContainerView: View { @EnvironmentObject private var sceneModel: SceneModel @StateObject private var articleModel = ArticleModel() - var article: Article? = nil + var article: Article @ViewBuilder var body: some View { - if let article = article { - ArticleView() - .environmentObject(articleModel) - .onAppear { - sceneModel.articleModel = articleModel - articleModel.delegate = sceneModel - } - } else { - EmptyView() - } + ArticleView() + .environmentObject(articleModel) + .onAppear { + sceneModel.articleModel = articleModel + articleModel.delegate = sceneModel + } } } diff --git a/Multiplatform/Shared/Assets.xcassets/AccentColor.colorset/Contents.json b/Multiplatform/Shared/Assets.xcassets/AccentColor.colorset/Contents.json index bf3d625ad..4f1440c52 100644 --- a/Multiplatform/Shared/Assets.xcassets/AccentColor.colorset/Contents.json +++ b/Multiplatform/Shared/Assets.xcassets/AccentColor.colorset/Contents.json @@ -23,9 +23,9 @@ "color-space" : "srgb", "components" : { "alpha" : "1.000", - "blue" : "0.945", - "green" : "0.502", - "red" : "0.176" + "blue" : "0.957", + "green" : "0.620", + "red" : "0.369" } }, "idiom" : "universal" diff --git a/Multiplatform/Shared/Assets.xcassets/MarkAllAsReadPDF.imageset/Contents.json b/Multiplatform/Shared/Assets.xcassets/MarkAllAsReadPDF.imageset/Contents.json new file mode 100644 index 000000000..f23296bcc --- /dev/null +++ b/Multiplatform/Shared/Assets.xcassets/MarkAllAsReadPDF.imageset/Contents.json @@ -0,0 +1,16 @@ +{ + "images" : [ + { + "filename" : "MarkAllAsReadPDF.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true, + "template-rendering-intent" : "template" + } +} diff --git a/Multiplatform/Shared/Assets.xcassets/MarkAllAsReadPDF.imageset/MarkAllAsReadPDF.pdf b/Multiplatform/Shared/Assets.xcassets/MarkAllAsReadPDF.imageset/MarkAllAsReadPDF.pdf new file mode 100644 index 000000000..e2a044d56 Binary files /dev/null and b/Multiplatform/Shared/Assets.xcassets/MarkAllAsReadPDF.imageset/MarkAllAsReadPDF.pdf differ diff --git a/Multiplatform/Shared/Assets.xcassets/SidebarUnreadCountBackground.colorset/Contents.json b/Multiplatform/Shared/Assets.xcassets/SidebarUnreadCountBackground.colorset/Contents.json new file mode 100644 index 000000000..ceb10be63 --- /dev/null +++ b/Multiplatform/Shared/Assets.xcassets/SidebarUnreadCountBackground.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "0.500", + "blue" : "0.000", + "green" : "0.000", + "red" : "0.000" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Multiplatform/Shared/Assets.xcassets/SidebarUnreadCountForeground.colorset/Contents.json b/Multiplatform/Shared/Assets.xcassets/SidebarUnreadCountForeground.colorset/Contents.json new file mode 100644 index 000000000..91ae93460 --- /dev/null +++ b/Multiplatform/Shared/Assets.xcassets/SidebarUnreadCountForeground.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "0.900", + "blue" : "1.000", + "green" : "1.000", + "red" : "1.000" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Multiplatform/Shared/Assets.xcassets/StarColor.colorset/Contents.json b/Multiplatform/Shared/Assets.xcassets/StarColor.colorset/Contents.json new file mode 100644 index 000000000..c464941a7 --- /dev/null +++ b/Multiplatform/Shared/Assets.xcassets/StarColor.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.204", + "green" : "0.776", + "red" : "0.976" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Multiplatform/Shared/Assets.xcassets/markAllAsRead.symbolset/markAllAsRead.svg b/Multiplatform/Shared/Assets.xcassets/markAllAsRead.symbolset/markAllAsRead.svg index 58170a6ba..10e23abd9 100644 --- a/Multiplatform/Shared/Assets.xcassets/markAllAsRead.symbolset/markAllAsRead.svg +++ b/Multiplatform/Shared/Assets.xcassets/markAllAsRead.symbolset/markAllAsRead.svg @@ -1,7 +1,7 @@ - - Untitled + + markAllAsRead Created with Sketch. @@ -136,6 +136,11 @@ + + + + + diff --git a/Multiplatform/Shared/MainApp.swift b/Multiplatform/Shared/MainApp.swift index 634dea81c..1be5b3720 100644 --- a/Multiplatform/Shared/MainApp.swift +++ b/Multiplatform/Shared/MainApp.swift @@ -20,6 +20,7 @@ struct MainApp: App { @StateObject private var sceneModel = SceneModel() @StateObject private var defaults = AppDefaults.shared + @State private var showSheet = false @SceneBuilder var body: some Scene { #if os(macOS) @@ -28,63 +29,70 @@ struct MainApp: App { .frame(minWidth: 600, idealWidth: 1000, maxWidth: .infinity, minHeight: 600, idealHeight: 700, maxHeight: .infinity) .environmentObject(sceneModel) .environmentObject(defaults) + .sheet(isPresented: $showSheet, onDismiss: { showSheet = false }) { + AddWebFeedView() + } .toolbar { - ToolbarItem { - Button(action: {}, label: { - Image(systemName: "plus").foregroundColor(.secondary) - }).help("New Feed") + ToolbarItem() { + Menu { + Button("Add Web Feed", action: { showSheet = true }) + Button("Add Reddit Feed", action: { }) + Button("Add Twitter Feed", action: { }) + Button("Add Folder", action: { }) + } label : { + AppAssets.addMenuImage + } } ToolbarItem { Button(action: {}, label: { - Image(systemName: "folder.fill.badge.plus").foregroundColor(.pink) - }).help("New Folder") - } - - ToolbarItem { - Button(action: {}, label: { - Image(systemName: "arrow.clockwise").foregroundColor(.secondary) + AppAssets.refreshImage }).help("Refresh").padding(.trailing, 40) } - + ToolbarItem { Button(action: {}, label: { - Image(systemName: "circle.dashed").foregroundColor(.orange) + AppAssets.markAllAsReadImagePDF + .resizable() + .scaledToFit() + .frame(width: 20, height: 20, alignment: .center) }).help("Mark All as Read") } ToolbarItem { - Button(action: {}, label: { - Image(systemName: "arrow.triangle.turn.up.right.circle.fill").foregroundColor(.purple) - }).help("Go to Next Unread") + MacSearchField() + .frame(width: 200) } - + ToolbarItem { Button(action: {}, label: { - Image(systemName: "star.fill").foregroundColor(.yellow) + AppAssets.nextUnreadArticleImage + }).help("Go to Next Unread").padding(.trailing, 40) + } + + ToolbarItem { + Button(action: {}, label: { + AppAssets.toggleStarred }).help("Mark as Starred") } ToolbarItem { Button(action: {}, label: { - Image(systemName: "checkmark.circle.fill").foregroundColor(.green) + AppAssets.toggleRead }).help("Mark as Unread") } ToolbarItem { Button(action: {}, label: { - Image(systemName: "safari").foregroundColor(.blue) + AppAssets.openInBrowserImage }).help("Open in Browser") } ToolbarItem { Button(action: {}, label: { - Image(systemName: "square.and.arrow.up") + AppAssets.shareImage }).help("Share") } - ToolbarItem { - MacSearchField() - .frame(width: 300) - } + } } .commands { @@ -146,7 +154,9 @@ struct MainApp: App { SceneNavigationView() .environmentObject(sceneModel) .environmentObject(defaults) - }.commands { + .modifier(PreferredColorSchemeModifier(preferredColorScheme: defaults.userInterfaceColorPalette)) + } + .commands { CommandGroup(after: .newItem, addition: { Button("New Feed", action: {}) .keyboardShortcut("N") diff --git a/Multiplatform/Shared/Sidebar/SidebarToolbar.swift b/Multiplatform/Shared/Sidebar/SidebarToolbar.swift index 70123ddc3..90d4a7e39 100644 --- a/Multiplatform/Shared/Sidebar/SidebarToolbar.swift +++ b/Multiplatform/Shared/Sidebar/SidebarToolbar.swift @@ -8,43 +8,60 @@ import SwiftUI +fileprivate enum ToolbarSheets { + case none, web, twitter, reddit, folder, settings +} + +fileprivate class SidebarToolbarViewModel: ObservableObject { + + @Published var showSheet: Bool = false + @Published var sheetToShow: ToolbarSheets = .none { + didSet { + sheetToShow != .none ? (showSheet = true) : (showSheet = false) + } + } + @Published var showActionSheet: Bool = false + @Published var showAddSheet: Bool = false + +} + struct SidebarToolbar: View { - @State private var showSettings: Bool = false - @State private var showAddSheet: Bool = false + @EnvironmentObject private var appSettings: AppDefaults + @StateObject private var viewModel = SidebarToolbarViewModel() - var addActionSheetButtons = [ - Button(action: {}, label: { Text("Add Feed") }) - ] - var body: some View { VStack { Divider() HStack(alignment: .center) { Button(action: { - showSettings = true + viewModel.sheetToShow = .settings }, label: { - Image(systemName: "gear") + AppAssets.settingsImage .font(.title3) .foregroundColor(.accentColor) }).help("Settings") + Spacer() + Text("Last updated") .font(.caption) .foregroundColor(.secondary) + Spacer() + Button(action: { - showAddSheet = true + viewModel.showActionSheet = true }, label: { - Image(systemName: "plus") + AppAssets.addMenuImage .font(.title3) .foregroundColor(.accentColor) }) .help("Add") - .actionSheet(isPresented: $showAddSheet) { + .actionSheet(isPresented: $viewModel.showActionSheet) { ActionSheet(title: Text("Add"), buttons: [ .cancel(), - .default(Text("Add Web Feed")), + .default(Text("Add Web Feed"), action: { viewModel.sheetToShow = .web }), .default(Text("Add Twitter Feed")), .default(Text("Add Reddit Feed")), .default(Text("Add Folder")) @@ -56,8 +73,13 @@ struct SidebarToolbar: View { .padding(.top, 4) } .background(VisualEffectBlur(blurStyle: .systemChromeMaterial).edgesIgnoringSafeArea(.bottom)) - .sheet(isPresented: $showSettings, onDismiss: { showSettings = false }) { - SettingsView() + .sheet(isPresented: $viewModel.showSheet, onDismiss: { viewModel.sheetToShow = .none }) { + if viewModel.sheetToShow == .web { + AddWebFeedView() + } + if viewModel.sheetToShow == .settings { + SettingsView().modifier(PreferredColorSchemeModifier(preferredColorScheme: appSettings.userInterfaceColorPalette)) + } } } diff --git a/Multiplatform/Shared/Sidebar/UnreadCountView.swift b/Multiplatform/Shared/Sidebar/UnreadCountView.swift index f1c760bfd..72cf9d5ec 100644 --- a/Multiplatform/Shared/Sidebar/UnreadCountView.swift +++ b/Multiplatform/Shared/Sidebar/UnreadCountView.swift @@ -14,10 +14,12 @@ struct UnreadCountView: View { var body: some View { Text(verbatim: String(count)) - .font(.footnote) + .font(.caption) + .fontWeight(.bold) .padding(.horizontal, 7) .padding(.vertical, 1) - .background(SwiftUI.Color.gray.opacity(0.5)) + .background(AppAssets.sidebarUnreadCountBackground) + .foregroundColor(AppAssets.sidebarUnreadCountForeground) .cornerRadius(8) } } diff --git a/Multiplatform/Shared/String+URLChecker.swift b/Multiplatform/Shared/String+URLChecker.swift new file mode 100644 index 000000000..c1994b1b1 --- /dev/null +++ b/Multiplatform/Shared/String+URLChecker.swift @@ -0,0 +1,19 @@ +// +// String+URLChecker.swift +// NetNewsWire +// +// Created by Stuart Breckenridge on 3/7/20. +// Copyright © 2020 Ranchero Software. All rights reserved. +// + +import Foundation + +extension String { + + /// Reference: [StackOverflow](https://stackoverflow.com/questions/161738/what-is-the-best-regular-expression-to-check-if-a-string-is-a-valid-url) + var isValidURL: Bool { + let regEx = "^([a-zA-Z0-9\\.\\-]+(\\:[a-zA-Z0-9\\.&%\\$\\-]+)*@)*((25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9])\\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)\\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)\\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[0-9])|localhost|([a-zA-Z0-9\\-]+\\.)*[a-zA-Z0-9\\-]+\\.(com|edu|gov|int|mil|net|org|biz|arpa|info|name|pro|aero|coop|museum|[a-zA-Z]{2}))(\\:[0-9]+)*(/($|[a-zA-Z0-9\\.\\,\\?\\'\\\\\\+&%\\$#\\=~_\\-]+))*$" + let predicate = NSPredicate(format:"SELF MATCHES %@", argumentArray:[regEx]) + return predicate.evaluate(with: self) + } +} diff --git a/Multiplatform/Shared/SwiftUI Extensions/PreferredColorSchemeModifier.swift b/Multiplatform/Shared/SwiftUI Extensions/PreferredColorSchemeModifier.swift new file mode 100644 index 000000000..ba9a04d36 --- /dev/null +++ b/Multiplatform/Shared/SwiftUI Extensions/PreferredColorSchemeModifier.swift @@ -0,0 +1,27 @@ +// +// PreferredColorSchemeModifier.swift +// NetNewsWire +// +// Created by Maurice Parker on 7/3/20. +// Copyright © 2020 Ranchero Software. All rights reserved. +// + +import SwiftUI + +struct PreferredColorSchemeModifier: ViewModifier { + + var preferredColorScheme: UserInterfaceColorPalette + + @ViewBuilder + func body(content: Content) -> some View { + switch preferredColorScheme { + case .automatic: + content.preferredColorScheme(nil) + case .dark: + content.preferredColorScheme(.dark) + case .light: + content.preferredColorScheme(.light) + } + } + +} diff --git a/Multiplatform/Shared/Timeline/TimelineContainerView.swift b/Multiplatform/Shared/Timeline/TimelineContainerView.swift index 008e28d42..a258638b5 100644 --- a/Multiplatform/Shared/Timeline/TimelineContainerView.swift +++ b/Multiplatform/Shared/Timeline/TimelineContainerView.swift @@ -24,6 +24,37 @@ struct TimelineContainerView: View { timelineModel.delegate = sceneModel timelineModel.rebuildTimelineItems(feed) } + .toolbar { + #if os(iOS) + ToolbarItem { + Button(action: { + }, label: { + AppAssets.markAllAsReadImage + .foregroundColor(.accentColor) + }).help("Mark All As Read") + } + ToolbarItem { + Spacer() + } + ToolbarItem { + Text("Last updated") + .font(.caption) + .foregroundColor(.secondary) + } + ToolbarItem { + Spacer() + } + ToolbarItem { + Button(action: { + }, label: { + AppAssets.nextUnreadArticleImage + .resizable() + .scaledToFit() + .frame(width: 22, height: 22, alignment: .center) + }) + } + #endif + } } else { EmptyView() } diff --git a/Multiplatform/Shared/Timeline/TimelineItemStatusView.swift b/Multiplatform/Shared/Timeline/TimelineItemStatusView.swift index bef9ff233..0db428879 100644 --- a/Multiplatform/Shared/Timeline/TimelineItemStatusView.swift +++ b/Multiplatform/Shared/Timeline/TimelineItemStatusView.swift @@ -19,12 +19,10 @@ struct TimelineItemStatusView: View { .resizable() .frame(width: 8, height: 8, alignment: .center) .padding(.all, 2) - .foregroundColor(.accentColor) case .showStar: AppAssets.timelineStarred .resizable() .frame(width: 10, height: 10, alignment: .center) - .foregroundColor(.yellow) case .showNone: AppAssets.timelineUnread .resizable() diff --git a/Multiplatform/Shared/Timeline/TimelineItemView.swift b/Multiplatform/Shared/Timeline/TimelineItemView.swift index 1e1a25ae8..252ef97ac 100644 --- a/Multiplatform/Shared/Timeline/TimelineItemView.swift +++ b/Multiplatform/Shared/Timeline/TimelineItemView.swift @@ -14,7 +14,14 @@ struct TimelineItemView: View { @StateObject var articleIconImageLoader = ArticleIconImageLoader() var timelineItem: TimelineItem - + + #if os(macOS) + var verticalPadding: CGFloat = 10 + #endif + #if os(iOS) + var verticalPadding: CGFloat = 0 + #endif + var body: some View { VStack { HStack(alignment: .top) { @@ -46,6 +53,7 @@ struct TimelineItemView: View { } } } + .padding(.vertical, verticalPadding) .onAppear { articleIconImageLoader.loadImage(for: timelineItem.article) } diff --git a/Multiplatform/iOS/AppDelegate.swift b/Multiplatform/iOS/AppDelegate.swift index b9d62d6c1..f97bef0c6 100644 --- a/Multiplatform/iOS/AppDelegate.swift +++ b/Multiplatform/iOS/AppDelegate.swift @@ -103,6 +103,9 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD UNUserNotificationCenter.current().delegate = self userNotificationManager = UserNotificationManager() + NotificationCenter.default.addObserver(self, selector: #selector(userDefaultsDidChange), name: UserDefaults.didChangeNotification, object: nil) + + // extensionContainersFile = ExtensionContainersFile() // extensionFeedAddRequestFile = ExtensionFeedAddRequestFile() @@ -388,3 +391,29 @@ private extension AppDelegate { } } + +private extension AppDelegate { + @objc func userDefaultsDidChange() { + updateUserInterfaceStyle() + } + + var window: UIWindow? { + guard let scene = UIApplication.shared.connectedScenes.first, + let windowSceneDelegate = scene.delegate as? UIWindowSceneDelegate, + let window = windowSceneDelegate.window else { + return nil + } + return window + } + + func updateUserInterfaceStyle() { +// switch AppDefaults.shared.userInterfaceColorPalette { +// case .automatic: +// window?.overrideUserInterfaceStyle = .unspecified +// case .light: +// window?.overrideUserInterfaceStyle = .light +// case .dark: +// window?.overrideUserInterfaceStyle = .dark +// } + } +} diff --git a/Multiplatform/iOS/Settings/SettingsView.swift b/Multiplatform/iOS/Settings/SettingsView.swift index 727aa93c7..9aca56100 100644 --- a/Multiplatform/iOS/Settings/SettingsView.swift +++ b/Multiplatform/iOS/Settings/SettingsView.swift @@ -155,12 +155,12 @@ struct SettingsView: View { var appearance: some View { Section(header: Text("Appearance"), content: { NavigationLink( - destination: EmptyView(), + destination: ColorPaletteContainerView().environmentObject(settings), label: { HStack { Text("Color Palette") Spacer() - Text("Automatic") + Text(settings.userInterfaceColorPalette.description) .foregroundColor(.secondary) } }) diff --git a/Multiplatform/iOS/Settings/Submenus/ColorPaletteContainerView.swift b/Multiplatform/iOS/Settings/Submenus/ColorPaletteContainerView.swift new file mode 100644 index 000000000..3cf4ee25a --- /dev/null +++ b/Multiplatform/iOS/Settings/Submenus/ColorPaletteContainerView.swift @@ -0,0 +1,60 @@ +// +// ColorPaletteContainerView.swift +// Multiplatform iOS +// +// Created by Rizwan on 02/07/20. +// Copyright © 2020 Ranchero Software. All rights reserved. +// + +import SwiftUI + +struct ColorPaletteContainerView: View { + private let colorPalettes = UserInterfaceColorPalette.allCases + @EnvironmentObject private var appSettings: AppDefaults + @Environment(\.presentationMode) var presentationMode + + var body: some View { + List { + ForEach.init(0 ..< colorPalettes.count) { index in + Button(action: { + onTapColorPalette(at:index) + }) { + ColorPaletteView(colorPalette: colorPalettes[index]) + } + } + } + .listStyle(InsetGroupedListStyle()) + .navigationBarTitle("Color Palette", displayMode: .inline) + } + + func onTapColorPalette(at index: Int) { + if let colorPalette = UserInterfaceColorPalette(rawValue: index) { + appSettings.userInterfaceColorPalette = colorPalette + } + self.presentationMode.wrappedValue.dismiss() + } +} + +struct ColorPaletteView: View { + var colorPalette: UserInterfaceColorPalette + @EnvironmentObject private var appSettings: AppDefaults + + var body: some View { + HStack { + Text(colorPalette.description).foregroundColor(.primary) + Spacer() + if colorPalette == appSettings.userInterfaceColorPalette { + Image(systemName: "checkmark") + .foregroundColor(.blue) + } + } + } +} + +struct ColorPaletteContainerView_Previews: PreviewProvider { + static var previews: some View { + NavigationView { + ColorPaletteContainerView() + } + } +} diff --git a/NetNewsWire.xcodeproj/project.pbxproj b/NetNewsWire.xcodeproj/project.pbxproj index eabc431a0..bdb2dc841 100644 --- a/NetNewsWire.xcodeproj/project.pbxproj +++ b/NetNewsWire.xcodeproj/project.pbxproj @@ -21,8 +21,14 @@ 175942AB24AD533200585066 /* RefreshInterval.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5183CCE4226F4DFA0010922C /* RefreshInterval.swift */; }; 1776E88E24AC5F8A00E78166 /* AppDefaults.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1776E88D24AC5F8A00E78166 /* AppDefaults.swift */; }; 1776E88F24AC5F8A00E78166 /* AppDefaults.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1776E88D24AC5F8A00E78166 /* AppDefaults.swift */; }; + 17925E1724AF41D000D3A4F6 /* String+URLChecker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17925E1624AF41D000D3A4F6 /* String+URLChecker.swift */; }; + 17925E1824AF41D000D3A4F6 /* String+URLChecker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17925E1624AF41D000D3A4F6 /* String+URLChecker.swift */; }; + 17930ED424AF10EE00A9BA52 /* AddWebFeedView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17930ED324AF10EE00A9BA52 /* AddWebFeedView.swift */; }; + 17930ED524AF10EE00A9BA52 /* AddWebFeedView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17930ED324AF10EE00A9BA52 /* AddWebFeedView.swift */; }; 179DB1DFBCF9177104B12E0F /* AccountsNewsBlurWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 179DBBA2B22A659F81EED6F9 /* AccountsNewsBlurWindowController.swift */; }; 179DB3CE822BFCC2D774D9F4 /* AccountsNewsBlurWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 179DBBA2B22A659F81EED6F9 /* AccountsNewsBlurWindowController.swift */; }; + 17D232A824AFF10A0005F075 /* AddWebFeedModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17D232A724AFF10A0005F075 /* AddWebFeedModel.swift */; }; + 17D232A924AFF10A0005F075 /* AddWebFeedModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17D232A724AFF10A0005F075 /* AddWebFeedModel.swift */; }; 3B3A32A5238B820900314204 /* FeedWranglerAccountViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B3A328B238B820900314204 /* FeedWranglerAccountViewController.swift */; }; 3B826DCB2385C84800FC1ADB /* AccountsFeedWrangler.xib in Resources */ = {isa = PBXBuildFile; fileRef = 3B826DB02385C84800FC1ADB /* AccountsFeedWrangler.xib */; }; 3B826DCC2385C84800FC1ADB /* AccountsFeedWranglerWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B826DCA2385C84800FC1ADB /* AccountsFeedWranglerWindowController.swift */; }; @@ -214,6 +220,8 @@ 517A757A24451C0700B553B9 /* OAuthSwift.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 517A755524451BD500B553B9 /* OAuthSwift.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 517A757B24451C1500B553B9 /* OAuthSwift.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 517A755324451BD500B553B9 /* OAuthSwift.framework */; }; 517A757C24451C1500B553B9 /* OAuthSwift.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 517A755324451BD500B553B9 /* OAuthSwift.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 5181C5AD24AF89B1002E0F70 /* PreferredColorSchemeModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5181C5AC24AF89B1002E0F70 /* PreferredColorSchemeModifier.swift */; }; + 5181C5AE24AF89B1002E0F70 /* PreferredColorSchemeModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5181C5AC24AF89B1002E0F70 /* PreferredColorSchemeModifier.swift */; }; 5183CCD0226E1E880010922C /* NonIntrinsicLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5183CCCF226E1E880010922C /* NonIntrinsicLabel.swift */; }; 5183CCDA226E31A50010922C /* NonIntrinsicImageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5183CCD9226E31A50010922C /* NonIntrinsicImageView.swift */; }; 5183CCE5226F4DFA0010922C /* RefreshInterval.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5183CCE4226F4DFA0010922C /* RefreshInterval.swift */; }; @@ -627,6 +635,7 @@ 6581C73D20CED60100F4AD34 /* SafariExtensionViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6581C73B20CED60100F4AD34 /* SafariExtensionViewController.xib */; }; 6581C74020CED60100F4AD34 /* netnewswire-subscribe-to-feed.js in Resources */ = {isa = PBXBuildFile; fileRef = 6581C73F20CED60100F4AD34 /* netnewswire-subscribe-to-feed.js */; }; 6581C74220CED60100F4AD34 /* ToolbarItemIcon.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 6581C74120CED60100F4AD34 /* ToolbarItemIcon.pdf */; }; + 65CBAD5A24AE03C20006DD91 /* ColorPaletteContainerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 65CBAD5924AE03C20006DD91 /* ColorPaletteContainerView.swift */; }; 65ED3FB7235DEF6C0081F399 /* ArticleArray.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84F204DF1FAACBB30076E152 /* ArticleArray.swift */; }; 65ED3FB8235DEF6C0081F399 /* CrashReporter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 848B937121C8C5540038DC0D /* CrashReporter.swift */; }; 65ED3FB9235DEF6C0081F399 /* IconView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 847CD6C9232F4CBF00FAC46D /* IconView.swift */; }; @@ -1717,8 +1726,11 @@ 1729529A24AA1FD200D65E66 /* MacSearchField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MacSearchField.swift; sourceTree = ""; }; 172952AF24AA287100D65E66 /* CompactSidebarContainerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CompactSidebarContainerView.swift; sourceTree = ""; }; 1776E88D24AC5F8A00E78166 /* AppDefaults.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDefaults.swift; sourceTree = ""; }; + 17925E1624AF41D000D3A4F6 /* String+URLChecker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "String+URLChecker.swift"; sourceTree = ""; }; + 17930ED324AF10EE00A9BA52 /* AddWebFeedView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddWebFeedView.swift; sourceTree = ""; }; 179DBBA2B22A659F81EED6F9 /* AccountsNewsBlurWindowController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AccountsNewsBlurWindowController.swift; sourceTree = ""; }; 17B223DB24AC24D2001E4592 /* TimelineLayoutView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineLayoutView.swift; sourceTree = ""; }; + 17D232A724AFF10A0005F075 /* AddWebFeedModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddWebFeedModel.swift; sourceTree = ""; }; 3B3A328B238B820900314204 /* FeedWranglerAccountViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FeedWranglerAccountViewController.swift; sourceTree = ""; }; 3B826DB02385C84800FC1ADB /* AccountsFeedWrangler.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = AccountsFeedWrangler.xib; sourceTree = ""; }; 3B826DCA2385C84800FC1ADB /* AccountsFeedWranglerWindowController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AccountsFeedWranglerWindowController.swift; sourceTree = ""; }; @@ -1835,6 +1847,7 @@ 517630222336657E00E15FFF /* WebViewProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WebViewProvider.swift; sourceTree = ""; }; 517A745A2443665000B553B9 /* UIPageViewController-Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIPageViewController-Extensions.swift"; sourceTree = ""; }; 517A754424451BD500B553B9 /* OAuthSwift.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = OAuthSwift.xcodeproj; path = submodules/OAuthSwift/OAuthSwift.xcodeproj; sourceTree = ""; }; + 5181C5AC24AF89B1002E0F70 /* PreferredColorSchemeModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PreferredColorSchemeModifier.swift; sourceTree = ""; }; 5183CCCF226E1E880010922C /* NonIntrinsicLabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NonIntrinsicLabel.swift; sourceTree = ""; }; 5183CCD9226E31A50010922C /* NonIntrinsicImageView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NonIntrinsicImageView.swift; sourceTree = ""; }; 5183CCE4226F4DFA0010922C /* RefreshInterval.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RefreshInterval.swift; sourceTree = ""; }; @@ -1994,6 +2007,7 @@ 6581C73F20CED60100F4AD34 /* netnewswire-subscribe-to-feed.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; path = "netnewswire-subscribe-to-feed.js"; sourceTree = ""; }; 6581C74120CED60100F4AD34 /* ToolbarItemIcon.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = ToolbarItemIcon.pdf; sourceTree = ""; }; 6581C74320CED60100F4AD34 /* Subscribe_to_Feed.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Subscribe_to_Feed.entitlements; sourceTree = ""; }; + 65CBAD5924AE03C20006DD91 /* ColorPaletteContainerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ColorPaletteContainerView.swift; sourceTree = ""; }; 65ED4083235DEF6C0081F399 /* NetNewsWire.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = NetNewsWire.app; sourceTree = BUILT_PRODUCTS_DIR; }; 65ED409D235DEF770081F399 /* Subscribe to Feed.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = "Subscribe to Feed.appex"; sourceTree = BUILT_PRODUCTS_DIR; }; 65ED409F235DEFF00081F399 /* container-migration.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "container-migration.plist"; sourceTree = ""; }; @@ -2394,10 +2408,20 @@ path = View; sourceTree = ""; }; + 17930ED224AF10CD00A9BA52 /* Add */ = { + isa = PBXGroup; + children = ( + 17D232A724AFF10A0005F075 /* AddWebFeedModel.swift */, + 17930ED324AF10EE00A9BA52 /* AddWebFeedView.swift */, + ); + path = Add; + sourceTree = ""; + }; 17B223B924AC24A8001E4592 /* Submenus */ = { isa = PBXGroup; children = ( 17B223DB24AC24D2001E4592 /* TimelineLayoutView.swift */, + 65CBAD5924AE03C20006DD91 /* ColorPaletteContainerView.swift */, ); path = Submenus; sourceTree = ""; @@ -2557,6 +2581,7 @@ isa = PBXGroup; children = ( 514E6C0524AD2B5F00AC6F6E /* Image-Extensions.swift */, + 5181C5AC24AF89B1002E0F70 /* PreferredColorSchemeModifier.swift */, ); path = "SwiftUI Extensions"; sourceTree = ""; @@ -2663,10 +2688,10 @@ children = ( 51919FED24AB85E400541E64 /* TimelineContainerView.swift */, 51919FF324AB869C00541E64 /* TimelineItem.swift */, + 514E6C0124AD29A300AC6F6E /* TimelineItemStatusView.swift */, 514E6BD924ACEA0400AC6F6E /* TimelineItemView.swift */, 51919FF024AB864A00541E64 /* TimelineModel.swift */, 51919FF624AB8B7700541E64 /* TimelineView.swift */, - 514E6C0124AD29A300AC6F6E /* TimelineItemStatusView.swift */, ); path = Timeline; sourceTree = ""; @@ -2748,12 +2773,14 @@ 51E499D724A912C200B667CB /* SceneModel.swift */, 51E49A0224A91FF600B667CB /* SceneNavigationView.swift */, 51C0513824A77DF800194D5E /* Assets.xcassets */, + 17930ED224AF10CD00A9BA52 /* Add */, 51A576B924AE617B00078888 /* Article */, 51919FB124AAB95300541E64 /* Images */, 514E6BFD24AD252400AC6F6E /* Previews */, 51E499FB24A9135A00B667CB /* Sidebar */, 514E6C0424AD2B0400AC6F6E /* SwiftUI Extensions */, 51919FCB24AB855000541E64 /* Timeline */, + 17925E1624AF41D000D3A4F6 /* String+URLChecker.swift */, ); path = Shared; sourceTree = ""; @@ -4794,6 +4821,7 @@ 51E498F524A8085D00B667CB /* TodayFeedDelegate.swift in Sources */, 172952B024AA287100D65E66 /* CompactSidebarContainerView.swift in Sources */, 172199F124AB716900A31D04 /* SidebarToolbar.swift in Sources */, + 65CBAD5A24AE03C20006DD91 /* ColorPaletteContainerView.swift in Sources */, 51E4990B24A808C500B667CB /* ImageDownloader.swift in Sources */, 51E498F424A8085D00B667CB /* SmartFeedDelegate.swift in Sources */, 514E6BFF24AD255D00AC6F6E /* PreviewArticles.swift in Sources */, @@ -4808,6 +4836,7 @@ 51E4996924A8760C00B667CB /* ArticleStylesManager.swift in Sources */, 51E498F324A8085D00B667CB /* PseudoFeed.swift in Sources */, 51A5769624AE617200078888 /* ArticleContainerView.swift in Sources */, + 5181C5AD24AF89B1002E0F70 /* PreferredColorSchemeModifier.swift in Sources */, 51E4996B24A8762D00B667CB /* ArticleExtractor.swift in Sources */, 51E49A0324A91FF600B667CB /* SceneNavigationView.swift in Sources */, 51E4990124A808BB00B667CB /* FaviconURLFinder.swift in Sources */, @@ -4816,6 +4845,7 @@ 51A576BE24AE637400078888 /* ArticleView.swift in Sources */, 51E4995324A8734D00B667CB /* RedditFeedProvider-Extensions.swift in Sources */, 172199C924AB228900A31D04 /* SettingsView.swift in Sources */, + 17D232A824AFF10A0005F075 /* AddWebFeedModel.swift in Sources */, 51E4994224A8713C00B667CB /* ArticleStatusSyncTimer.swift in Sources */, 51E498F624A8085D00B667CB /* SearchFeedDelegate.swift in Sources */, 51E498F224A8085D00B667CB /* SmartFeedsController.swift in Sources */, @@ -4828,6 +4858,7 @@ 514E6C0624AD2B5F00AC6F6E /* Image-Extensions.swift in Sources */, 51E4995624A8734D00B667CB /* TwitterFeedProvider-Extensions.swift in Sources */, 5125E6CA24AE461D002A7562 /* TimelineLayoutView.swift in Sources */, + 17925E1724AF41D000D3A4F6 /* String+URLChecker.swift in Sources */, 51E4996824A8760C00B667CB /* ArticleStyle.swift in Sources */, 51E4990024A808BB00B667CB /* FaviconGenerator.swift in Sources */, 51E4997124A8764C00B667CB /* ActivityType.swift in Sources */, @@ -4839,6 +4870,7 @@ 51E4993C24A8709900B667CB /* AppDelegate.swift in Sources */, 51E498F924A8085D00B667CB /* SmartFeed.swift in Sources */, 51A576BB24AE621800078888 /* ArticleModel.swift in Sources */, + 17930ED424AF10EE00A9BA52 /* AddWebFeedView.swift in Sources */, 51E4995124A8734D00B667CB /* ExtensionPointManager.swift in Sources */, 51E4990C24A808C500B667CB /* AuthorAvatarDownloader.swift in Sources */, 51E4992124A8095000B667CB /* RSImage-Extensions.swift in Sources */, @@ -4865,6 +4897,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 17930ED524AF10EE00A9BA52 /* AddWebFeedView.swift in Sources */, 51E4993A24A8708800B667CB /* AppDelegate.swift in Sources */, 51E498CE24A8085D00B667CB /* UnreadFeed.swift in Sources */, 51E498C724A8085D00B667CB /* StarredFeedDelegate.swift in Sources */, @@ -4887,11 +4920,13 @@ 51E4992224A8095600B667CB /* URL-Extensions.swift in Sources */, 51E4990424A808C300B667CB /* WebFeedIconDownloader.swift in Sources */, 51E498CB24A8085D00B667CB /* TodayFeedDelegate.swift in Sources */, + 17D232A924AFF10A0005F075 /* AddWebFeedModel.swift in Sources */, 51E4993324A867E700B667CB /* AppNotifications.swift in Sources */, 51E4990624A808C300B667CB /* ImageDownloader.swift in Sources */, 51E4994F24A8734C00B667CB /* TwitterFeedProvider-Extensions.swift in Sources */, 51E498CA24A8085D00B667CB /* SmartFeedDelegate.swift in Sources */, 51E4990524A808C300B667CB /* FeaturedImageDownloader.swift in Sources */, + 5181C5AE24AF89B1002E0F70 /* PreferredColorSchemeModifier.swift in Sources */, 51E4991624A8090300B667CB /* ArticleUtilities.swift in Sources */, 51919FF224AB864A00541E64 /* TimelineModel.swift in Sources */, 51E4991A24A8090F00B667CB /* IconImage.swift in Sources */, @@ -4901,6 +4936,7 @@ 51E4993424A867E700B667CB /* UserInfoKey.swift in Sources */, 1776E88F24AC5F8A00E78166 /* AppDefaults.swift in Sources */, 1729529724AA1CD000D65E66 /* MacPreferencesView.swift in Sources */, + 17925E1824AF41D000D3A4F6 /* String+URLChecker.swift in Sources */, 51E4994C24A8734C00B667CB /* RedditFeedProvider-Extensions.swift in Sources */, 1729529324AA1CAA00D65E66 /* AccountsPreferencesView.swift in Sources */, 51919FAD24AA8CCA00541E64 /* UnreadCountView.swift in Sources */, diff --git a/NetNewsWire.xcodeproj/xcshareddata/xcschemes/Multiplatform iOS.xcscheme b/NetNewsWire.xcodeproj/xcshareddata/xcschemes/Multiplatform iOS.xcscheme index eafbe066c..e06266bca 100644 --- a/NetNewsWire.xcodeproj/xcshareddata/xcschemes/Multiplatform iOS.xcscheme +++ b/NetNewsWire.xcodeproj/xcshareddata/xcschemes/Multiplatform iOS.xcscheme @@ -1,10 +1,28 @@ + version = "1.7"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Shared/Extensions/NSAttributedString+NetNewsWire.swift b/Shared/Extensions/NSAttributedString+NetNewsWire.swift index 4037b2489..f778dfb75 100644 --- a/Shared/Extensions/NSAttributedString+NetNewsWire.swift +++ b/Shared/Extensions/NSAttributedString+NetNewsWire.swift @@ -12,7 +12,6 @@ import RSParser import AppKit typealias Font = NSFont typealias FontDescriptor = NSFontDescriptor -typealias Color = NSColor private let boldTrait = NSFontDescriptor.SymbolicTraits.bold private let italicTrait = NSFontDescriptor.SymbolicTraits.italic @@ -21,7 +20,6 @@ private let monoSpaceTrait = NSFontDescriptor.SymbolicTraits.monoSpace import UIKit typealias Font = UIFont typealias FontDescriptor = UIFontDescriptor -typealias Color = UIColor private let boldTrait = UIFontDescriptor.SymbolicTraits.traitBold private let italicTrait = UIFontDescriptor.SymbolicTraits.traitItalic diff --git a/iOS/Resources/Assets.xcassets/secondaryAccentColor.colorset/Contents.json b/iOS/Resources/Assets.xcassets/secondaryAccentColor.colorset/Contents.json index 750f4b573..b94873d3d 100644 --- a/iOS/Resources/Assets.xcassets/secondaryAccentColor.colorset/Contents.json +++ b/iOS/Resources/Assets.xcassets/secondaryAccentColor.colorset/Contents.json @@ -1,23 +1,18 @@ { - "info" : { - "version" : 1, - "author" : "xcode" - }, "colors" : [ { - "idiom" : "universal", "color" : { "color-space" : "srgb", "components" : { - "red" : "0x08", "alpha" : "1.000", "blue" : "0xEE", - "green" : "0x6A" + "green" : "0x6A", + "red" : "0x08" } - } + }, + "idiom" : "universal" }, { - "idiom" : "universal", "appearances" : [ { "appearance" : "luminosity", @@ -27,12 +22,17 @@ "color" : { "color-space" : "srgb", "components" : { - "red" : "0x5E", "alpha" : "1.000", "blue" : "0xF4", - "green" : "0x9E" + "green" : "0x9E", + "red" : "0x5E" } - } + }, + "idiom" : "universal" } - ] -} \ No newline at end of file + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/iOS/Resources/Assets.xcassets/starColor.colorset/Contents.json b/iOS/Resources/Assets.xcassets/starColor.colorset/Contents.json index b1d4071d7..4811237e1 100644 --- a/iOS/Resources/Assets.xcassets/starColor.colorset/Contents.json +++ b/iOS/Resources/Assets.xcassets/starColor.colorset/Contents.json @@ -1,20 +1,20 @@ { - "info" : { - "version" : 1, - "author" : "xcode" - }, "colors" : [ { - "idiom" : "universal", "color" : { "color-space" : "srgb", "components" : { - "red" : "249", "alpha" : "1.000", "blue" : "52", - "green" : "198" + "green" : "198", + "red" : "249" } - } + }, + "idiom" : "universal" } - ] -} \ No newline at end of file + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +}