From d4e2d44d8f5ab37572a6b00d2a87cd515bf306e1 Mon Sep 17 00:00:00 2001 From: Maurice Parker Date: Sun, 16 Jun 2019 11:19:15 -0500 Subject: [PATCH] Add OPML Export for SwiftUI --- NetNewsWire.xcodeproj/project.pbxproj | 12 ++++--- ...ubscriptionsExportDocumentPickerView.swift | 31 +++++++++++++++++ ...bscriptionsImportDocumentPickerView.swift} | 25 +++++--------- iOS/Settings/SettingsView.swift | 34 ++++++++++--------- 4 files changed, 65 insertions(+), 37 deletions(-) create mode 100644 iOS/Settings/SettingsSubscriptionsExportDocumentPickerView.swift rename iOS/Settings/{SettingsImportSubscriptionsDocumentPickerView.swift => SettingsSubscriptionsImportDocumentPickerView.swift} (57%) diff --git a/NetNewsWire.xcodeproj/project.pbxproj b/NetNewsWire.xcodeproj/project.pbxproj index 290cbee3f..48cc63bf3 100644 --- a/NetNewsWire.xcodeproj/project.pbxproj +++ b/NetNewsWire.xcodeproj/project.pbxproj @@ -49,7 +49,8 @@ 5183CCE9226F68D90010922C /* AccountRefreshTimer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5183CCE7226F68D90010922C /* AccountRefreshTimer.swift */; }; 5183CCED22711DCE0010922C /* Settings.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 5183CCEC22711DCE0010922C /* Settings.storyboard */; }; 5183CCEF227125970010922C /* SettingsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5183CCEE227125970010922C /* SettingsViewController.swift */; }; - 5194B5EE22B6965300144881 /* SettingsImportSubscriptionsDocumentPickerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5194B5ED22B6965300144881 /* SettingsImportSubscriptionsDocumentPickerView.swift */; }; + 5194B5EE22B6965300144881 /* SettingsSubscriptionsImportDocumentPickerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5194B5ED22B6965300144881 /* SettingsSubscriptionsImportDocumentPickerView.swift */; }; + 5194B5F222B69FCC00144881 /* SettingsSubscriptionsExportDocumentPickerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5194B5F122B69FCC00144881 /* SettingsSubscriptionsExportDocumentPickerView.swift */; }; 519B8D332143397200FA689C /* SharingServiceDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 519B8D322143397200FA689C /* SharingServiceDelegate.swift */; }; 51C451A9226377C200C03939 /* ArticlesDatabase.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8407167F2262A61100344432 /* ArticlesDatabase.framework */; }; 51C451AA226377C200C03939 /* ArticlesDatabase.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 8407167F2262A61100344432 /* ArticlesDatabase.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; @@ -695,7 +696,8 @@ 5183CCE7226F68D90010922C /* AccountRefreshTimer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountRefreshTimer.swift; sourceTree = ""; }; 5183CCEC22711DCE0010922C /* Settings.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = Settings.storyboard; sourceTree = ""; }; 5183CCEE227125970010922C /* SettingsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsViewController.swift; sourceTree = ""; }; - 5194B5ED22B6965300144881 /* SettingsImportSubscriptionsDocumentPickerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsImportSubscriptionsDocumentPickerView.swift; sourceTree = ""; }; + 5194B5ED22B6965300144881 /* SettingsSubscriptionsImportDocumentPickerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsSubscriptionsImportDocumentPickerView.swift; sourceTree = ""; }; + 5194B5F122B69FCC00144881 /* SettingsSubscriptionsExportDocumentPickerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsSubscriptionsExportDocumentPickerView.swift; sourceTree = ""; }; 519B8D322143397200FA689C /* SharingServiceDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SharingServiceDelegate.swift; sourceTree = ""; }; 51C4524E226506F400C03939 /* UIStoryboard-Extensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIStoryboard-Extensions.swift"; sourceTree = ""; }; 51C45250226506F400C03939 /* String-Extensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "String-Extensions.swift"; sourceTree = ""; }; @@ -1049,7 +1051,8 @@ 51F772EC22B2789B0087D9D1 /* SettingsDetailAccountView.swift */, 510D707F22B02A5F004E8F65 /* SettingsFeedbinAccountView.swift */, 510D707D22B02A4B004E8F65 /* SettingsLocalAccountView.swift */, - 5194B5ED22B6965300144881 /* SettingsImportSubscriptionsDocumentPickerView.swift */, + 5194B5F122B69FCC00144881 /* SettingsSubscriptionsExportDocumentPickerView.swift */, + 5194B5ED22B6965300144881 /* SettingsSubscriptionsImportDocumentPickerView.swift */, 51F35D0822AFD4760003CE1B /* SettingsView.swift */, 51F35CFD22AFD0350003CE1B /* UIKit */, ); @@ -2383,8 +2386,9 @@ 51C4529B22650A1000C03939 /* FaviconDownloader.swift in Sources */, 5183CCE3226F314C0010922C /* ProgressTableViewController.swift in Sources */, 512E09012268907400BDCFDD /* MasterFeedTableViewSectionHeader.swift in Sources */, + 5194B5F222B69FCC00144881 /* SettingsSubscriptionsExportDocumentPickerView.swift in Sources */, 51C45268226508F600C03939 /* MasterFeedUnreadCountView.swift in Sources */, - 5194B5EE22B6965300144881 /* SettingsImportSubscriptionsDocumentPickerView.swift in Sources */, + 5194B5EE22B6965300144881 /* SettingsSubscriptionsImportDocumentPickerView.swift in Sources */, 5183CCD0226E1E880010922C /* NonIntrinsicLabel.swift in Sources */, 51C4529F22650A1900C03939 /* AuthorAvatarDownloader.swift in Sources */, 51E595AD228E1C2100FCC42B /* AddAccountViewController.swift in Sources */, diff --git a/iOS/Settings/SettingsSubscriptionsExportDocumentPickerView.swift b/iOS/Settings/SettingsSubscriptionsExportDocumentPickerView.swift new file mode 100644 index 000000000..a471c7d27 --- /dev/null +++ b/iOS/Settings/SettingsSubscriptionsExportDocumentPickerView.swift @@ -0,0 +1,31 @@ +// +// SettingsSubscriptionsExportDocumentPickerView.swift +// NetNewsWire-iOS +// +// Created by Maurice Parker on 6/16/19. +// Copyright © 2019 Ranchero Software. All rights reserved. +// + +import SwiftUI +import Account + +struct SettingsSubscriptionsExportDocumentPickerView : UIViewControllerRepresentable { + var account: Account + + func makeUIViewController(context: UIViewControllerRepresentableContext) -> UIDocumentPickerViewController { + + let accountName = account.nameForDisplay.replacingOccurrences(of: " ", with: "").trimmingCharacters(in: .whitespaces) + let filename = "Subscriptions-\(accountName).opml" + let tempFile = FileManager.default.temporaryDirectory.appendingPathComponent(filename) + + let opmlString = OPMLExporter.OPMLString(with: account, title: filename) + try? opmlString.write(to: tempFile, atomically: true, encoding: String.Encoding.utf8) + + return UIDocumentPickerViewController(url: tempFile, in: .exportToService) + } + + func updateUIViewController(_ uiViewController: UIDocumentPickerViewController, context: UIViewControllerRepresentableContext) { + // + } + +} diff --git a/iOS/Settings/SettingsImportSubscriptionsDocumentPickerView.swift b/iOS/Settings/SettingsSubscriptionsImportDocumentPickerView.swift similarity index 57% rename from iOS/Settings/SettingsImportSubscriptionsDocumentPickerView.swift rename to iOS/Settings/SettingsSubscriptionsImportDocumentPickerView.swift index 3c8cbbeb9..4f4043a92 100644 --- a/iOS/Settings/SettingsImportSubscriptionsDocumentPickerView.swift +++ b/iOS/Settings/SettingsSubscriptionsImportDocumentPickerView.swift @@ -1,5 +1,5 @@ // -// SettingsImportSubscriptionsDocumentPickerView.swift +// SettingsSubscriptionsImportDocumentPickerView.swift // NetNewsWire-iOS // // Created by Maurice Parker on 6/16/19. @@ -9,17 +9,16 @@ import SwiftUI import Account -struct SettingsImportSubscriptionsDocumentPickerView : UIViewControllerRepresentable { - var account: Account? +struct SettingsSubscriptionsImportDocumentPickerView : UIViewControllerRepresentable { + var account: Account - func makeUIViewController(context: UIViewControllerRepresentableContext) -> UIDocumentPickerViewController { + func makeUIViewController(context: UIViewControllerRepresentableContext) -> UIDocumentPickerViewController { let docPicker = UIDocumentPickerViewController(documentTypes: ["public.xml", "org.opml.opml"], in: .import) docPicker.delegate = context.coordinator - docPicker.modalPresentationStyle = .formSheet return docPicker } - func updateUIViewController(_ uiViewController: UIDocumentPickerViewController, context: UIViewControllerRepresentableContext) { + func updateUIViewController(_ uiViewController: UIDocumentPickerViewController, context: UIViewControllerRepresentableContext) { // } @@ -28,25 +27,17 @@ struct SettingsImportSubscriptionsDocumentPickerView : UIViewControllerRepresent } class Coordinator : NSObject, UIDocumentPickerDelegate { - var parent: SettingsImportSubscriptionsDocumentPickerView + var parent: SettingsSubscriptionsImportDocumentPickerView - init(_ view: SettingsImportSubscriptionsDocumentPickerView) { + init(_ view: SettingsSubscriptionsImportDocumentPickerView) { self.parent = view } func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentsAt urls: [URL]) { for url in urls { - parent.account?.importOPML(url) { result in} + parent.account.importOPML(url) { result in} } } } } - -#if DEBUG -struct SettingsImportSubscriptionsDocumentPickerView_Previews : PreviewProvider { - static var previews: some View { - SettingsImportSubscriptionsDocumentPickerView() - } -} -#endif diff --git a/iOS/Settings/SettingsView.swift b/iOS/Settings/SettingsView.swift index 761f4a268..1ca917abc 100644 --- a/iOS/Settings/SettingsView.swift +++ b/iOS/Settings/SettingsView.swift @@ -14,9 +14,10 @@ import Account struct SettingsView : View { @ObjectBinding var viewModel: ViewModel - @State var importSubscriptionsAccounts: ActionSheet? = nil - @State var importSubscriptionsDocumentPicker: Modal? = nil - @State var showExportSubscriptions = false + @State var subscriptionsImportAccounts: ActionSheet? = nil + @State var subscriptionsImportDocumentPicker: Modal? = nil + @State var subscriptionsExportAccounts: ActionSheet? = nil + @State var subscriptionsExportDocumentPicker: Modal? = nil var body: some View { NavigationView { @@ -68,18 +69,19 @@ struct SettingsView : View { } } Button(action: { - self.importSubscriptionsAccounts = self.createImportSubscriptionsAccounts + self.subscriptionsImportAccounts = self.createSubscriptionsImportAccounts }) { Text("Import Subscriptions...") } - .presentation(importSubscriptionsAccounts) - .presentation(importSubscriptionsDocumentPicker) + .presentation(subscriptionsImportAccounts) + .presentation(subscriptionsImportDocumentPicker) Button(action: { - self.showExportSubscriptions = true + self.subscriptionsExportAccounts = self.createSubscriptionsExportAccounts }) { Text("Export Subscriptions...") } - .presentation(showExportSubscriptions ? exportSubscriptionsAccounts : nil) + .presentation(subscriptionsExportAccounts) + .presentation(subscriptionsExportDocumentPicker) } .foregroundColor(.primary) @@ -90,29 +92,29 @@ struct SettingsView : View { } } - var createImportSubscriptionsAccounts: ActionSheet { + var createSubscriptionsImportAccounts: ActionSheet { var buttons = [ActionSheet.Button]() for account in viewModel.accounts { let button = ActionSheet.Button.default(Text(verbatim: account.nameForDisplay)) { - self.importSubscriptionsAccounts = nil - self.importSubscriptionsDocumentPicker = Modal(SettingsImportSubscriptionsDocumentPickerView(account: account)) + self.subscriptionsImportAccounts = nil + self.subscriptionsImportDocumentPicker = Modal(SettingsSubscriptionsImportDocumentPickerView(account: account)) } buttons.append(button) } - buttons.append(.cancel { self.importSubscriptionsAccounts = nil }) + buttons.append(.cancel { self.subscriptionsImportAccounts = nil }) return ActionSheet(title: Text("Import Subscriptions..."), message: Text("Select the account to import your OPML file into."), buttons: buttons) } - var exportSubscriptionsAccounts: ActionSheet { + var createSubscriptionsExportAccounts: ActionSheet { var buttons = [ActionSheet.Button]() for account in viewModel.accounts { let button = ActionSheet.Button.default(Text(verbatim: account.nameForDisplay)) { - self.showExportSubscriptions = false - // Call doc picker here... + self.subscriptionsExportAccounts = nil + self.subscriptionsExportDocumentPicker = Modal(SettingsSubscriptionsExportDocumentPickerView(account: account)) } buttons.append(button) } - buttons.append(.cancel { self.showExportSubscriptions = false }) + buttons.append(.cancel { self.subscriptionsExportAccounts = nil }) return ActionSheet(title: Text("Export Subscriptions..."), message: Text("Select the account to export out of."), buttons: buttons) }