commit
883590b50f
|
@ -10,49 +10,6 @@ import SwiftUI
|
||||||
import Account
|
import Account
|
||||||
import RSCore
|
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 {
|
struct AddWebFeedView: View {
|
||||||
|
|
||||||
|
@ -62,15 +19,28 @@ struct AddWebFeedView: View {
|
||||||
@ViewBuilder var body: some View {
|
@ViewBuilder var body: some View {
|
||||||
#if os(iOS)
|
#if os(iOS)
|
||||||
iosForm
|
iosForm
|
||||||
|
.onAppear {
|
||||||
|
viewModel.pasteUrlFromPasteboard()
|
||||||
|
}
|
||||||
|
.onReceive(viewModel.$shouldDismiss, perform: { dismiss in
|
||||||
|
if dismiss == true {
|
||||||
|
presentationMode.wrappedValue.dismiss()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
#else
|
#else
|
||||||
macForm
|
macForm
|
||||||
.onAppear {
|
.onAppear {
|
||||||
pasteUrlFromPasteboard()
|
viewModel.pasteUrlFromPasteboard()
|
||||||
}.alert(isPresented: $viewModel.showError) {
|
}.alert(isPresented: $viewModel.showError) {
|
||||||
Alert(title: Text("Oops"), message: Text(viewModel.addFeedError!.localizedDescription), dismissButton: Alert.Button.cancel({
|
Alert(title: Text("Oops"), message: Text(viewModel.addFeedError!.localizedDescription), dismissButton: Alert.Button.cancel({
|
||||||
viewModel.addFeedError = .none
|
viewModel.addFeedError = AddWebFeedError.none
|
||||||
}))
|
}))
|
||||||
}
|
}.onReceive(viewModel.$shouldDismiss, perform: { dismiss in
|
||||||
|
if dismiss == true {
|
||||||
|
presentationMode.wrappedValue.dismiss()
|
||||||
|
}
|
||||||
|
})
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -117,7 +87,7 @@ struct AddWebFeedView: View {
|
||||||
.help("Cancel Add Feed")
|
.help("Cancel Add Feed")
|
||||||
, trailing:
|
, trailing:
|
||||||
Button("Add", action: {
|
Button("Add", action: {
|
||||||
addWebFeed()
|
viewModel.addWebFeed()
|
||||||
})
|
})
|
||||||
.disabled(!viewModel.providedURL.isValidURL)
|
.disabled(!viewModel.providedURL.isValidURL)
|
||||||
.help("Add Feed")
|
.help("Add Feed")
|
||||||
|
@ -168,94 +138,17 @@ struct AddWebFeedView: View {
|
||||||
.help("Cancel Add Feed")
|
.help("Cancel Add Feed")
|
||||||
|
|
||||||
Button("Add", action: {
|
Button("Add", action: {
|
||||||
addWebFeed()
|
viewModel.addWebFeed()
|
||||||
})
|
})
|
||||||
.disabled(!viewModel.providedURL.isValidURL)
|
.disabled(!viewModel.providedURL.isValidURL)
|
||||||
.help("Add Feed")
|
.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 {
|
struct AddFeedView_Previews: PreviewProvider {
|
||||||
static var previews: some View {
|
static var previews: some View {
|
||||||
AddWebFeedView()
|
AddWebFeedView()
|
||||||
|
|
|
@ -0,0 +1,132 @@
|
||||||
|
//
|
||||||
|
// AddWebFeedViewModel.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 AddWebFeedViewModel: 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")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -27,6 +27,8 @@
|
||||||
17930ED524AF10EE00A9BA52 /* 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 */; };
|
||||||
|
17D232A824AFF10A0005F075 /* AddWebFeedViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17D232A724AFF10A0005F075 /* AddWebFeedViewModel.swift */; };
|
||||||
|
17D232A924AFF10A0005F075 /* AddWebFeedViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17D232A724AFF10A0005F075 /* AddWebFeedViewModel.swift */; };
|
||||||
3B3A32A5238B820900314204 /* FeedWranglerAccountViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B3A328B238B820900314204 /* FeedWranglerAccountViewController.swift */; };
|
3B3A32A5238B820900314204 /* FeedWranglerAccountViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B3A328B238B820900314204 /* FeedWranglerAccountViewController.swift */; };
|
||||||
3B826DCB2385C84800FC1ADB /* AccountsFeedWrangler.xib in Resources */ = {isa = PBXBuildFile; fileRef = 3B826DB02385C84800FC1ADB /* AccountsFeedWrangler.xib */; };
|
3B826DCB2385C84800FC1ADB /* AccountsFeedWrangler.xib in Resources */ = {isa = PBXBuildFile; fileRef = 3B826DB02385C84800FC1ADB /* AccountsFeedWrangler.xib */; };
|
||||||
3B826DCC2385C84800FC1ADB /* AccountsFeedWranglerWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B826DCA2385C84800FC1ADB /* AccountsFeedWranglerWindowController.swift */; };
|
3B826DCC2385C84800FC1ADB /* AccountsFeedWranglerWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B826DCA2385C84800FC1ADB /* AccountsFeedWranglerWindowController.swift */; };
|
||||||
|
@ -1728,6 +1730,7 @@
|
||||||
17930ED324AF10EE00A9BA52 /* AddWebFeedView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddWebFeedView.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>"; };
|
||||||
|
17D232A724AFF10A0005F075 /* AddWebFeedViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddWebFeedViewModel.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>"; };
|
||||||
3B826DB02385C84800FC1ADB /* AccountsFeedWrangler.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = AccountsFeedWrangler.xib; sourceTree = "<group>"; };
|
3B826DB02385C84800FC1ADB /* AccountsFeedWrangler.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = AccountsFeedWrangler.xib; sourceTree = "<group>"; };
|
||||||
3B826DCA2385C84800FC1ADB /* AccountsFeedWranglerWindowController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AccountsFeedWranglerWindowController.swift; sourceTree = "<group>"; };
|
3B826DCA2385C84800FC1ADB /* AccountsFeedWranglerWindowController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AccountsFeedWranglerWindowController.swift; sourceTree = "<group>"; };
|
||||||
|
@ -2408,6 +2411,7 @@
|
||||||
17930ED224AF10CD00A9BA52 /* Add */ = {
|
17930ED224AF10CD00A9BA52 /* Add */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
17D232A724AFF10A0005F075 /* AddWebFeedViewModel.swift */,
|
||||||
17930ED324AF10EE00A9BA52 /* AddWebFeedView.swift */,
|
17930ED324AF10EE00A9BA52 /* AddWebFeedView.swift */,
|
||||||
);
|
);
|
||||||
path = Add;
|
path = Add;
|
||||||
|
@ -4841,6 +4845,7 @@
|
||||||
51A576BE24AE637400078888 /* ArticleView.swift in Sources */,
|
51A576BE24AE637400078888 /* ArticleView.swift in Sources */,
|
||||||
51E4995324A8734D00B667CB /* RedditFeedProvider-Extensions.swift in Sources */,
|
51E4995324A8734D00B667CB /* RedditFeedProvider-Extensions.swift in Sources */,
|
||||||
172199C924AB228900A31D04 /* SettingsView.swift in Sources */,
|
172199C924AB228900A31D04 /* SettingsView.swift in Sources */,
|
||||||
|
17D232A824AFF10A0005F075 /* AddWebFeedViewModel.swift in Sources */,
|
||||||
51E4994224A8713C00B667CB /* ArticleStatusSyncTimer.swift in Sources */,
|
51E4994224A8713C00B667CB /* ArticleStatusSyncTimer.swift in Sources */,
|
||||||
51E498F624A8085D00B667CB /* SearchFeedDelegate.swift in Sources */,
|
51E498F624A8085D00B667CB /* SearchFeedDelegate.swift in Sources */,
|
||||||
51E498F224A8085D00B667CB /* SmartFeedsController.swift in Sources */,
|
51E498F224A8085D00B667CB /* SmartFeedsController.swift in Sources */,
|
||||||
|
@ -4915,6 +4920,7 @@
|
||||||
51E4992224A8095600B667CB /* URL-Extensions.swift in Sources */,
|
51E4992224A8095600B667CB /* URL-Extensions.swift in Sources */,
|
||||||
51E4990424A808C300B667CB /* WebFeedIconDownloader.swift in Sources */,
|
51E4990424A808C300B667CB /* WebFeedIconDownloader.swift in Sources */,
|
||||||
51E498CB24A8085D00B667CB /* TodayFeedDelegate.swift in Sources */,
|
51E498CB24A8085D00B667CB /* TodayFeedDelegate.swift in Sources */,
|
||||||
|
17D232A924AFF10A0005F075 /* AddWebFeedViewModel.swift in Sources */,
|
||||||
51E4993324A867E700B667CB /* AppNotifications.swift in Sources */,
|
51E4993324A867E700B667CB /* AppNotifications.swift in Sources */,
|
||||||
51E4990624A808C300B667CB /* ImageDownloader.swift in Sources */,
|
51E4990624A808C300B667CB /* ImageDownloader.swift in Sources */,
|
||||||
51E4994F24A8734C00B667CB /* TwitterFeedProvider-Extensions.swift in Sources */,
|
51E4994F24A8734C00B667CB /* TwitterFeedProvider-Extensions.swift in Sources */,
|
||||||
|
|
Loading…
Reference in New Issue