commit
88e29f2998
|
@ -0,0 +1,263 @@
|
||||||
|
//
|
||||||
|
// AddWebFeedView.swift
|
||||||
|
// NetNewsWire
|
||||||
|
//
|
||||||
|
// Created by Stuart Breckenridge on 3/7/20.
|
||||||
|
// Copyright © 2020 Ranchero Software. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import SwiftUI
|
||||||
|
import Account
|
||||||
|
import RSCore
|
||||||
|
|
||||||
|
fileprivate 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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
fileprivate class AddWebFeedViewModel: ObservableObject {
|
||||||
|
|
||||||
|
@Published var providedURL: String = ""
|
||||||
|
@Published var providedName: String = ""
|
||||||
|
@Published var selectedFolderIndex: Int = 0
|
||||||
|
@Published var addFeedError: AddWebFeedError? {
|
||||||
|
didSet {
|
||||||
|
addFeedError != .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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
struct AddWebFeedView: View {
|
||||||
|
|
||||||
|
@Environment(\.presentationMode) private var presentationMode
|
||||||
|
@ObservedObject private var viewModel = AddWebFeedViewModel()
|
||||||
|
|
||||||
|
@ViewBuilder var body: some View {
|
||||||
|
#if os(iOS)
|
||||||
|
iosForm
|
||||||
|
#else
|
||||||
|
macForm
|
||||||
|
.onAppear {
|
||||||
|
pasteUrlFromPasteboard()
|
||||||
|
}.alert(isPresented: $viewModel.showError) {
|
||||||
|
Alert(title: Text("Oops"), message: Text(viewModel.addFeedError!.localizedDescription), dismissButton: Alert.Button.cancel({
|
||||||
|
viewModel.addFeedError = .none
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
#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())
|
||||||
|
.navigationTitle("Add Web Feed")
|
||||||
|
.navigationBarTitleDisplayMode(.inline)
|
||||||
|
.navigationBarItems(leading:
|
||||||
|
Button("Cancel", action: {
|
||||||
|
presentationMode.wrappedValue.dismiss()
|
||||||
|
})
|
||||||
|
.help("Cancel Add Feed")
|
||||||
|
, trailing:
|
||||||
|
Button("Add", action: {
|
||||||
|
addWebFeed()
|
||||||
|
})
|
||||||
|
.disabled(!viewModel.providedURL.isValidURL)
|
||||||
|
.help("Add Feed")
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
var urlTextField: some View {
|
||||||
|
HStack {
|
||||||
|
Text("Feed:")
|
||||||
|
TextField("URL", text: $viewModel.providedURL)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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..<viewModel.containers.count, id: \.self, content: { index in
|
||||||
|
if let containerName = (viewModel.containers[index] as? DisplayNameProvider)?.nameForDisplay {
|
||||||
|
if viewModel.containers[index] is Folder {
|
||||||
|
Text("\(viewModel.containers[index].account?.nameForDisplay ?? "") / \(containerName)").tag(index)
|
||||||
|
} else {
|
||||||
|
Text(containerName).tag(index)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
var buttonStack: some View {
|
||||||
|
HStack {
|
||||||
|
if viewModel.showProgressIndicator == true {
|
||||||
|
ProgressView()
|
||||||
|
.frame(width: 25, height: 25)
|
||||||
|
.help("Adding Feed")
|
||||||
|
}
|
||||||
|
Spacer()
|
||||||
|
Button("Cancel", action: {
|
||||||
|
presentationMode.wrappedValue.dismiss()
|
||||||
|
})
|
||||||
|
.help("Cancel Add Feed")
|
||||||
|
|
||||||
|
Button("Add", action: {
|
||||||
|
addWebFeed()
|
||||||
|
})
|
||||||
|
.disabled(!viewModel.providedURL.isValidURL)
|
||||||
|
.help("Add Feed")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if os(macOS)
|
||||||
|
func pasteUrlFromPasteboard() {
|
||||||
|
guard let stringFromPasteboard = urlStringFromPasteboard, stringFromPasteboard.isValidURL else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
viewModel.providedURL = stringFromPasteboard
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private extension AddWebFeedView {
|
||||||
|
|
||||||
|
#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(viewModel.containers[viewModel.selectedFolderIndex])?.account {
|
||||||
|
|
||||||
|
viewModel.showProgressIndicator = true
|
||||||
|
|
||||||
|
let container = viewModel.containers[viewModel.selectedFolderIndex]
|
||||||
|
|
||||||
|
if account.hasWebFeed(withURL: viewModel.providedURL) {
|
||||||
|
viewModel.addFeedError = .alreadySubscribed
|
||||||
|
viewModel.showProgressIndicator = false
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
account.createWebFeed(url: viewModel.providedURL, name: viewModel.providedName, container: container, completion: { result in
|
||||||
|
viewModel.showProgressIndicator = false
|
||||||
|
switch result {
|
||||||
|
case .success(let feed):
|
||||||
|
NotificationCenter.default.post(name: .UserDidAddFeed, object: self, userInfo: [UserInfoKey.webFeed: feed])
|
||||||
|
presentationMode.wrappedValue.dismiss()
|
||||||
|
case .failure(let error):
|
||||||
|
switch error {
|
||||||
|
case AccountError.createErrorAlreadySubscribed:
|
||||||
|
self.viewModel.addFeedError = .alreadySubscribed
|
||||||
|
return
|
||||||
|
case AccountError.createErrorNotFound:
|
||||||
|
self.viewModel.addFeedError = .noFeeds
|
||||||
|
return
|
||||||
|
default:
|
||||||
|
print("Error")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct AddFeedView_Previews: PreviewProvider {
|
||||||
|
static var previews: some View {
|
||||||
|
AddWebFeedView()
|
||||||
|
}
|
||||||
|
}
|
|
@ -20,6 +20,7 @@ struct MainApp: App {
|
||||||
|
|
||||||
@StateObject private var sceneModel = SceneModel()
|
@StateObject private var sceneModel = SceneModel()
|
||||||
@StateObject private var defaults = AppDefaults.shared
|
@StateObject private var defaults = AppDefaults.shared
|
||||||
|
@State private var showSheet = false
|
||||||
|
|
||||||
@SceneBuilder var body: some Scene {
|
@SceneBuilder var body: some Scene {
|
||||||
#if os(macOS)
|
#if os(macOS)
|
||||||
|
@ -28,12 +29,15 @@ struct MainApp: App {
|
||||||
.frame(minWidth: 600, idealWidth: 1000, maxWidth: .infinity, minHeight: 600, idealHeight: 700, maxHeight: .infinity)
|
.frame(minWidth: 600, idealWidth: 1000, maxWidth: .infinity, minHeight: 600, idealHeight: 700, maxHeight: .infinity)
|
||||||
.environmentObject(sceneModel)
|
.environmentObject(sceneModel)
|
||||||
.environmentObject(defaults)
|
.environmentObject(defaults)
|
||||||
|
.sheet(isPresented: $showSheet, onDismiss: { showSheet = false }) {
|
||||||
|
AddWebFeedView()
|
||||||
|
}
|
||||||
.toolbar {
|
.toolbar {
|
||||||
|
|
||||||
ToolbarItem {
|
ToolbarItem {
|
||||||
Button(action: {}, label: {
|
Button(action: { showSheet = true }, label: {
|
||||||
Image(systemName: "plus").foregroundColor(.secondary)
|
Image(systemName: "plus").foregroundColor(.secondary)
|
||||||
}).help("New Feed")
|
}).help("Add Feed")
|
||||||
}
|
}
|
||||||
|
|
||||||
ToolbarItem {
|
ToolbarItem {
|
||||||
|
|
|
@ -8,11 +8,28 @@
|
||||||
|
|
||||||
import SwiftUI
|
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 {
|
struct SidebarToolbar: View {
|
||||||
|
|
||||||
@EnvironmentObject private var appSettings: AppDefaults
|
@EnvironmentObject private var appSettings: AppDefaults
|
||||||
@State private var showSettings: Bool = false
|
@StateObject private var viewModel = SidebarToolbarViewModel()
|
||||||
@State private var showAddSheet: Bool = false
|
|
||||||
|
|
||||||
var addActionSheetButtons = [
|
var addActionSheetButtons = [
|
||||||
Button(action: {}, label: { Text("Add Feed") })
|
Button(action: {}, label: { Text("Add Feed") })
|
||||||
|
@ -23,29 +40,33 @@ struct SidebarToolbar: View {
|
||||||
Divider()
|
Divider()
|
||||||
HStack(alignment: .center) {
|
HStack(alignment: .center) {
|
||||||
Button(action: {
|
Button(action: {
|
||||||
showSettings = true
|
viewModel.sheetToShow = .settings
|
||||||
}, label: {
|
}, label: {
|
||||||
Image(systemName: "gear")
|
Image(systemName: "gear")
|
||||||
.font(.title3)
|
.font(.title3)
|
||||||
.foregroundColor(.accentColor)
|
.foregroundColor(.accentColor)
|
||||||
}).help("Settings")
|
}).help("Settings")
|
||||||
|
|
||||||
Spacer()
|
Spacer()
|
||||||
|
|
||||||
Text("Last updated")
|
Text("Last updated")
|
||||||
.font(.caption)
|
.font(.caption)
|
||||||
.foregroundColor(.secondary)
|
.foregroundColor(.secondary)
|
||||||
|
|
||||||
Spacer()
|
Spacer()
|
||||||
|
|
||||||
Button(action: {
|
Button(action: {
|
||||||
showAddSheet = true
|
viewModel.showActionSheet = true
|
||||||
}, label: {
|
}, label: {
|
||||||
Image(systemName: "plus")
|
Image(systemName: "plus")
|
||||||
.font(.title3)
|
.font(.title3)
|
||||||
.foregroundColor(.accentColor)
|
.foregroundColor(.accentColor)
|
||||||
})
|
})
|
||||||
.help("Add")
|
.help("Add")
|
||||||
.actionSheet(isPresented: $showAddSheet) {
|
.actionSheet(isPresented: $viewModel.showActionSheet) {
|
||||||
ActionSheet(title: Text("Add"), buttons: [
|
ActionSheet(title: Text("Add"), buttons: [
|
||||||
.cancel(),
|
.cancel(),
|
||||||
.default(Text("Add Web Feed")),
|
.default(Text("Add Web Feed"), action: { viewModel.sheetToShow = .web }),
|
||||||
.default(Text("Add Twitter Feed")),
|
.default(Text("Add Twitter Feed")),
|
||||||
.default(Text("Add Reddit Feed")),
|
.default(Text("Add Reddit Feed")),
|
||||||
.default(Text("Add Folder"))
|
.default(Text("Add Folder"))
|
||||||
|
@ -57,8 +78,13 @@ struct SidebarToolbar: View {
|
||||||
.padding(.top, 4)
|
.padding(.top, 4)
|
||||||
}
|
}
|
||||||
.background(VisualEffectBlur(blurStyle: .systemChromeMaterial).edgesIgnoringSafeArea(.bottom))
|
.background(VisualEffectBlur(blurStyle: .systemChromeMaterial).edgesIgnoringSafeArea(.bottom))
|
||||||
.sheet(isPresented: $showSettings, onDismiss: { showSettings = false }) {
|
.sheet(isPresented: $viewModel.showSheet, onDismiss: { viewModel.sheetToShow = .none }) {
|
||||||
SettingsView().modifier(PreferredColorSchemeModifier(preferredColorScheme: appSettings.userInterfaceColorPalette))
|
if viewModel.sheetToShow == .web {
|
||||||
|
AddWebFeedView()
|
||||||
|
}
|
||||||
|
if viewModel.sheetToShow == .settings {
|
||||||
|
SettingsView().modifier(PreferredColorSchemeModifier(preferredColorScheme: appSettings.userInterfaceColorPalette))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 = "^(http|https|feed)\\://([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)
|
||||||
|
}
|
||||||
|
}
|
|
@ -21,6 +21,10 @@
|
||||||
175942AB24AD533200585066 /* RefreshInterval.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5183CCE4226F4DFA0010922C /* RefreshInterval.swift */; };
|
175942AB24AD533200585066 /* RefreshInterval.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5183CCE4226F4DFA0010922C /* RefreshInterval.swift */; };
|
||||||
1776E88E24AC5F8A00E78166 /* AppDefaults.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1776E88D24AC5F8A00E78166 /* AppDefaults.swift */; };
|
1776E88E24AC5F8A00E78166 /* AppDefaults.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1776E88D24AC5F8A00E78166 /* AppDefaults.swift */; };
|
||||||
1776E88F24AC5F8A00E78166 /* 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 */; };
|
179DB1DFBCF9177104B12E0F /* AccountsNewsBlurWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 179DBBA2B22A659F81EED6F9 /* AccountsNewsBlurWindowController.swift */; };
|
||||||
179DB3CE822BFCC2D774D9F4 /* AccountsNewsBlurWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 179DBBA2B22A659F81EED6F9 /* AccountsNewsBlurWindowController.swift */; };
|
179DB3CE822BFCC2D774D9F4 /* AccountsNewsBlurWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 179DBBA2B22A659F81EED6F9 /* AccountsNewsBlurWindowController.swift */; };
|
||||||
3B3A32A5238B820900314204 /* FeedWranglerAccountViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B3A328B238B820900314204 /* FeedWranglerAccountViewController.swift */; };
|
3B3A32A5238B820900314204 /* FeedWranglerAccountViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B3A328B238B820900314204 /* FeedWranglerAccountViewController.swift */; };
|
||||||
|
@ -1719,6 +1723,8 @@
|
||||||
1729529A24AA1FD200D65E66 /* MacSearchField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MacSearchField.swift; sourceTree = "<group>"; };
|
1729529A24AA1FD200D65E66 /* MacSearchField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MacSearchField.swift; sourceTree = "<group>"; };
|
||||||
172952AF24AA287100D65E66 /* CompactSidebarContainerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CompactSidebarContainerView.swift; sourceTree = "<group>"; };
|
172952AF24AA287100D65E66 /* CompactSidebarContainerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CompactSidebarContainerView.swift; sourceTree = "<group>"; };
|
||||||
1776E88D24AC5F8A00E78166 /* AppDefaults.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDefaults.swift; sourceTree = "<group>"; };
|
1776E88D24AC5F8A00E78166 /* AppDefaults.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDefaults.swift; sourceTree = "<group>"; };
|
||||||
|
17925E1624AF41D000D3A4F6 /* String+URLChecker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "String+URLChecker.swift"; sourceTree = "<group>"; };
|
||||||
|
17930ED324AF10EE00A9BA52 /* AddWebFeedView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddWebFeedView.swift; sourceTree = "<group>"; };
|
||||||
179DBBA2B22A659F81EED6F9 /* AccountsNewsBlurWindowController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AccountsNewsBlurWindowController.swift; sourceTree = "<group>"; };
|
179DBBA2B22A659F81EED6F9 /* AccountsNewsBlurWindowController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AccountsNewsBlurWindowController.swift; sourceTree = "<group>"; };
|
||||||
17B223DB24AC24D2001E4592 /* TimelineLayoutView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineLayoutView.swift; sourceTree = "<group>"; };
|
17B223DB24AC24D2001E4592 /* TimelineLayoutView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineLayoutView.swift; sourceTree = "<group>"; };
|
||||||
3B3A328B238B820900314204 /* FeedWranglerAccountViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FeedWranglerAccountViewController.swift; sourceTree = "<group>"; };
|
3B3A328B238B820900314204 /* FeedWranglerAccountViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FeedWranglerAccountViewController.swift; sourceTree = "<group>"; };
|
||||||
|
@ -2397,6 +2403,14 @@
|
||||||
path = View;
|
path = View;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
|
17930ED224AF10CD00A9BA52 /* Add */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
17930ED324AF10EE00A9BA52 /* AddWebFeedView.swift */,
|
||||||
|
);
|
||||||
|
path = Add;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
17B223B924AC24A8001E4592 /* Submenus */ = {
|
17B223B924AC24A8001E4592 /* Submenus */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
@ -2752,12 +2766,14 @@
|
||||||
51E499D724A912C200B667CB /* SceneModel.swift */,
|
51E499D724A912C200B667CB /* SceneModel.swift */,
|
||||||
51E49A0224A91FF600B667CB /* SceneNavigationView.swift */,
|
51E49A0224A91FF600B667CB /* SceneNavigationView.swift */,
|
||||||
51C0513824A77DF800194D5E /* Assets.xcassets */,
|
51C0513824A77DF800194D5E /* Assets.xcassets */,
|
||||||
|
17930ED224AF10CD00A9BA52 /* Add */,
|
||||||
51A576B924AE617B00078888 /* Article */,
|
51A576B924AE617B00078888 /* Article */,
|
||||||
51919FB124AAB95300541E64 /* Images */,
|
51919FB124AAB95300541E64 /* Images */,
|
||||||
514E6BFD24AD252400AC6F6E /* Previews */,
|
514E6BFD24AD252400AC6F6E /* Previews */,
|
||||||
51E499FB24A9135A00B667CB /* Sidebar */,
|
51E499FB24A9135A00B667CB /* Sidebar */,
|
||||||
514E6C0424AD2B0400AC6F6E /* SwiftUI Extensions */,
|
514E6C0424AD2B0400AC6F6E /* SwiftUI Extensions */,
|
||||||
51919FCB24AB855000541E64 /* Timeline */,
|
51919FCB24AB855000541E64 /* Timeline */,
|
||||||
|
17925E1624AF41D000D3A4F6 /* String+URLChecker.swift */,
|
||||||
);
|
);
|
||||||
path = Shared;
|
path = Shared;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
@ -3949,46 +3965,46 @@
|
||||||
TargetAttributes = {
|
TargetAttributes = {
|
||||||
51314636235A7BBE00387FDC = {
|
51314636235A7BBE00387FDC = {
|
||||||
CreatedOnToolsVersion = 11.2;
|
CreatedOnToolsVersion = 11.2;
|
||||||
DevelopmentTeam = SHJK2V3AJG;
|
DevelopmentTeam = FQLBNX3GP7;
|
||||||
LastSwiftMigration = 1120;
|
LastSwiftMigration = 1120;
|
||||||
ProvisioningStyle = Automatic;
|
ProvisioningStyle = Automatic;
|
||||||
};
|
};
|
||||||
513C5CE5232571C2003D4054 = {
|
513C5CE5232571C2003D4054 = {
|
||||||
CreatedOnToolsVersion = 11.0;
|
CreatedOnToolsVersion = 11.0;
|
||||||
DevelopmentTeam = SHJK2V3AJG;
|
DevelopmentTeam = FQLBNX3GP7;
|
||||||
ProvisioningStyle = Automatic;
|
ProvisioningStyle = Automatic;
|
||||||
};
|
};
|
||||||
518B2ED12351B3DD00400001 = {
|
518B2ED12351B3DD00400001 = {
|
||||||
CreatedOnToolsVersion = 11.2;
|
CreatedOnToolsVersion = 11.2;
|
||||||
DevelopmentTeam = SHJK2V3AJG;
|
DevelopmentTeam = FQLBNX3GP7;
|
||||||
ProvisioningStyle = Automatic;
|
ProvisioningStyle = Automatic;
|
||||||
TestTargetID = 840D617B2029031C009BC708;
|
TestTargetID = 840D617B2029031C009BC708;
|
||||||
};
|
};
|
||||||
51C0513C24A77DF800194D5E = {
|
51C0513C24A77DF800194D5E = {
|
||||||
CreatedOnToolsVersion = 12.0;
|
CreatedOnToolsVersion = 12.0;
|
||||||
DevelopmentTeam = SHJK2V3AJG;
|
DevelopmentTeam = FQLBNX3GP7;
|
||||||
ProvisioningStyle = Automatic;
|
ProvisioningStyle = Automatic;
|
||||||
};
|
};
|
||||||
51C0514324A77DF800194D5E = {
|
51C0514324A77DF800194D5E = {
|
||||||
CreatedOnToolsVersion = 12.0;
|
CreatedOnToolsVersion = 12.0;
|
||||||
DevelopmentTeam = SHJK2V3AJG;
|
DevelopmentTeam = FQLBNX3GP7;
|
||||||
ProvisioningStyle = Automatic;
|
ProvisioningStyle = Automatic;
|
||||||
};
|
};
|
||||||
6581C73220CED60000F4AD34 = {
|
6581C73220CED60000F4AD34 = {
|
||||||
DevelopmentTeam = SHJK2V3AJG;
|
DevelopmentTeam = FQLBNX3GP7;
|
||||||
ProvisioningStyle = Automatic;
|
ProvisioningStyle = Automatic;
|
||||||
};
|
};
|
||||||
65ED3FA2235DEF6C0081F399 = {
|
65ED3FA2235DEF6C0081F399 = {
|
||||||
DevelopmentTeam = SHJK2V3AJG;
|
DevelopmentTeam = FQLBNX3GP7;
|
||||||
ProvisioningStyle = Automatic;
|
ProvisioningStyle = Automatic;
|
||||||
};
|
};
|
||||||
65ED4090235DEF770081F399 = {
|
65ED4090235DEF770081F399 = {
|
||||||
DevelopmentTeam = SHJK2V3AJG;
|
DevelopmentTeam = FQLBNX3GP7;
|
||||||
ProvisioningStyle = Automatic;
|
ProvisioningStyle = Automatic;
|
||||||
};
|
};
|
||||||
840D617B2029031C009BC708 = {
|
840D617B2029031C009BC708 = {
|
||||||
CreatedOnToolsVersion = 9.3;
|
CreatedOnToolsVersion = 9.3;
|
||||||
DevelopmentTeam = SHJK2V3AJG;
|
DevelopmentTeam = FQLBNX3GP7;
|
||||||
ProvisioningStyle = Automatic;
|
ProvisioningStyle = Automatic;
|
||||||
SystemCapabilities = {
|
SystemCapabilities = {
|
||||||
com.apple.BackgroundModes = {
|
com.apple.BackgroundModes = {
|
||||||
|
@ -3998,7 +4014,7 @@
|
||||||
};
|
};
|
||||||
849C645F1ED37A5D003D8FC0 = {
|
849C645F1ED37A5D003D8FC0 = {
|
||||||
CreatedOnToolsVersion = 8.2.1;
|
CreatedOnToolsVersion = 8.2.1;
|
||||||
DevelopmentTeam = SHJK2V3AJG;
|
DevelopmentTeam = FQLBNX3GP7;
|
||||||
ProvisioningStyle = Automatic;
|
ProvisioningStyle = Automatic;
|
||||||
SystemCapabilities = {
|
SystemCapabilities = {
|
||||||
com.apple.HardenedRuntime = {
|
com.apple.HardenedRuntime = {
|
||||||
|
@ -4008,7 +4024,7 @@
|
||||||
};
|
};
|
||||||
849C64701ED37A5D003D8FC0 = {
|
849C64701ED37A5D003D8FC0 = {
|
||||||
CreatedOnToolsVersion = 8.2.1;
|
CreatedOnToolsVersion = 8.2.1;
|
||||||
DevelopmentTeam = SHJK2V3AJG;
|
DevelopmentTeam = FQLBNX3GP7;
|
||||||
ProvisioningStyle = Automatic;
|
ProvisioningStyle = Automatic;
|
||||||
TestTargetID = 849C645F1ED37A5D003D8FC0;
|
TestTargetID = 849C645F1ED37A5D003D8FC0;
|
||||||
};
|
};
|
||||||
|
@ -4833,6 +4849,7 @@
|
||||||
514E6C0624AD2B5F00AC6F6E /* Image-Extensions.swift in Sources */,
|
514E6C0624AD2B5F00AC6F6E /* Image-Extensions.swift in Sources */,
|
||||||
51E4995624A8734D00B667CB /* TwitterFeedProvider-Extensions.swift in Sources */,
|
51E4995624A8734D00B667CB /* TwitterFeedProvider-Extensions.swift in Sources */,
|
||||||
5125E6CA24AE461D002A7562 /* TimelineLayoutView.swift in Sources */,
|
5125E6CA24AE461D002A7562 /* TimelineLayoutView.swift in Sources */,
|
||||||
|
17925E1724AF41D000D3A4F6 /* String+URLChecker.swift in Sources */,
|
||||||
51E4996824A8760C00B667CB /* ArticleStyle.swift in Sources */,
|
51E4996824A8760C00B667CB /* ArticleStyle.swift in Sources */,
|
||||||
51E4990024A808BB00B667CB /* FaviconGenerator.swift in Sources */,
|
51E4990024A808BB00B667CB /* FaviconGenerator.swift in Sources */,
|
||||||
51E4997124A8764C00B667CB /* ActivityType.swift in Sources */,
|
51E4997124A8764C00B667CB /* ActivityType.swift in Sources */,
|
||||||
|
@ -4844,6 +4861,7 @@
|
||||||
51E4993C24A8709900B667CB /* AppDelegate.swift in Sources */,
|
51E4993C24A8709900B667CB /* AppDelegate.swift in Sources */,
|
||||||
51E498F924A8085D00B667CB /* SmartFeed.swift in Sources */,
|
51E498F924A8085D00B667CB /* SmartFeed.swift in Sources */,
|
||||||
51A576BB24AE621800078888 /* ArticleModel.swift in Sources */,
|
51A576BB24AE621800078888 /* ArticleModel.swift in Sources */,
|
||||||
|
17930ED424AF10EE00A9BA52 /* AddWebFeedView.swift in Sources */,
|
||||||
51E4995124A8734D00B667CB /* ExtensionPointManager.swift in Sources */,
|
51E4995124A8734D00B667CB /* ExtensionPointManager.swift in Sources */,
|
||||||
51E4990C24A808C500B667CB /* AuthorAvatarDownloader.swift in Sources */,
|
51E4990C24A808C500B667CB /* AuthorAvatarDownloader.swift in Sources */,
|
||||||
51E4992124A8095000B667CB /* RSImage-Extensions.swift in Sources */,
|
51E4992124A8095000B667CB /* RSImage-Extensions.swift in Sources */,
|
||||||
|
@ -4870,6 +4888,7 @@
|
||||||
isa = PBXSourcesBuildPhase;
|
isa = PBXSourcesBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
|
17930ED524AF10EE00A9BA52 /* AddWebFeedView.swift in Sources */,
|
||||||
51E4993A24A8708800B667CB /* AppDelegate.swift in Sources */,
|
51E4993A24A8708800B667CB /* AppDelegate.swift in Sources */,
|
||||||
51E498CE24A8085D00B667CB /* UnreadFeed.swift in Sources */,
|
51E498CE24A8085D00B667CB /* UnreadFeed.swift in Sources */,
|
||||||
51E498C724A8085D00B667CB /* StarredFeedDelegate.swift in Sources */,
|
51E498C724A8085D00B667CB /* StarredFeedDelegate.swift in Sources */,
|
||||||
|
@ -4906,6 +4925,7 @@
|
||||||
51E4993424A867E700B667CB /* UserInfoKey.swift in Sources */,
|
51E4993424A867E700B667CB /* UserInfoKey.swift in Sources */,
|
||||||
1776E88F24AC5F8A00E78166 /* AppDefaults.swift in Sources */,
|
1776E88F24AC5F8A00E78166 /* AppDefaults.swift in Sources */,
|
||||||
1729529724AA1CD000D65E66 /* MacPreferencesView.swift in Sources */,
|
1729529724AA1CD000D65E66 /* MacPreferencesView.swift in Sources */,
|
||||||
|
17925E1824AF41D000D3A4F6 /* String+URLChecker.swift in Sources */,
|
||||||
51E4994C24A8734C00B667CB /* RedditFeedProvider-Extensions.swift in Sources */,
|
51E4994C24A8734C00B667CB /* RedditFeedProvider-Extensions.swift in Sources */,
|
||||||
1729529324AA1CAA00D65E66 /* AccountsPreferencesView.swift in Sources */,
|
1729529324AA1CAA00D65E66 /* AccountsPreferencesView.swift in Sources */,
|
||||||
51919FAD24AA8CCA00541E64 /* UnreadCountView.swift in Sources */,
|
51919FAD24AA8CCA00541E64 /* UnreadCountView.swift in Sources */,
|
||||||
|
|
Loading…
Reference in New Issue