All iOS Inspectors are now SwiftUI

This commit is contained in:
Stuart Breckenridge
2022-12-15 21:12:37 +08:00
parent f42b6e5473
commit b526f05e68
22 changed files with 411 additions and 1184 deletions

View File

@@ -103,7 +103,6 @@
51102165233A7D6C0007A5F7 /* ArticleExtractorButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51102164233A7D6C0007A5F7 /* ArticleExtractorButton.swift */; };
51107746243BEE2500D97C8C /* ExtensionPointPreferencesViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51107745243BEE2500D97C8C /* ExtensionPointPreferencesViewController.swift */; };
51107747243BEE2500D97C8C /* ExtensionPointPreferencesViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51107745243BEE2500D97C8C /* ExtensionPointPreferencesViewController.swift */; };
5110C37D2373A8D100A9C04F /* InspectorIconHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5110C37C2373A8D100A9C04F /* InspectorIconHeaderView.swift */; };
51126DA4225FDE2F00722696 /* RSImage-Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51126DA3225FDE2F00722696 /* RSImage-Extensions.swift */; };
5117715524E1EA0F00A2A836 /* ArticleExtractorButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5117715424E1EA0F00A2A836 /* ArticleExtractorButton.swift */; };
5117715624E1EA0F00A2A836 /* ArticleExtractorButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5117715424E1EA0F00A2A836 /* ArticleExtractorButton.swift */; };
@@ -191,7 +190,6 @@
513F32812593EF180003048F /* Account in Embed Frameworks */ = {isa = PBXBuildFile; productRef = 516B695E24D2F33B00B5702F /* Account */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; };
513F32882593EF8F0003048F /* RSCore in Frameworks */ = {isa = PBXBuildFile; productRef = 513F32872593EF8F0003048F /* RSCore */; };
513F32892593EF8F0003048F /* RSCore in Embed Frameworks */ = {isa = PBXBuildFile; productRef = 513F32872593EF8F0003048F /* RSCore */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; };
5141E7392373C18B0013FF27 /* WebFeedInspectorViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5141E7382373C18B0013FF27 /* WebFeedInspectorViewController.swift */; };
514217062921C9DD00963F14 /* Bundle-Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51F85BF42273625800C787DC /* Bundle-Extensions.swift */; };
5142192A23522B5500E07E2C /* ImageViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5142192923522B5500E07E2C /* ImageViewController.swift */; };
514219372352510100E07E2C /* ImageScrollView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 514219362352510100E07E2C /* ImageScrollView.swift */; };
@@ -240,7 +238,6 @@
51627A93238A3836007B3B4B /* CroppingPreviewParameters.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51627A92238A3836007B3B4B /* CroppingPreviewParameters.swift */; };
516A093B2360A4A000EAE89B /* SettingsTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 516A093A2360A4A000EAE89B /* SettingsTableViewCell.xib */; };
516A09402361240900EAE89B /* Account.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 516A093F2361240900EAE89B /* Account.storyboard */; };
516A09422361248000EAE89B /* Inspector.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 516A09412361248000EAE89B /* Inspector.storyboard */; };
516AE9B32371C372007DEEAA /* MasterFeedTableViewSectionHeaderLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = 516AE9B22371C372007DEEAA /* MasterFeedTableViewSectionHeaderLayout.swift */; };
516AE9DF2372269A007DEEAA /* IconImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 516AE9DE2372269A007DEEAA /* IconImage.swift */; };
516AE9E02372269A007DEEAA /* IconImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 516AE9DE2372269A007DEEAA /* IconImage.swift */; };
@@ -288,12 +285,10 @@
519E743D22C663F900A78E47 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 519E743422C663F900A78E47 /* SceneDelegate.swift */; };
519ED456244828C3007F8E94 /* AddExtensionPointViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 519ED455244828C3007F8E94 /* AddExtensionPointViewController.swift */; };
519ED47A24482AEB007F8E94 /* EnableExtensionPointViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 519ED47924482AEB007F8E94 /* EnableExtensionPointViewController.swift */; };
519ED47C24488C6F007F8E94 /* ExtensionInspectorViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 519ED47B24488C6F007F8E94 /* ExtensionInspectorViewController.swift */; };
51A052CE244FB9D7006C2024 /* AddFeedWIndowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51A052CD244FB9D6006C2024 /* AddFeedWIndowController.swift */; };
51A052CF244FB9D7006C2024 /* AddFeedWIndowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51A052CD244FB9D6006C2024 /* AddFeedWIndowController.swift */; };
51A16999235E10D700EB091F /* LocalAccountViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51A1698F235E10D600EB091F /* LocalAccountViewController.swift */; };
51A1699A235E10D700EB091F /* Settings.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 51A16990235E10D600EB091F /* Settings.storyboard */; };
51A1699B235E10D700EB091F /* AccountInspectorViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51A16991235E10D600EB091F /* AccountInspectorViewController.swift */; };
51A1699C235E10D700EB091F /* AddAccountViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51A16992235E10D600EB091F /* AddAccountViewController.swift */; };
51A169A0235E10D700EB091F /* FeedbinAccountViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51A16996235E10D700EB091F /* FeedbinAccountViewController.swift */; };
51A66685238075AE00CB272D /* AddWebFeedDefaultContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51A66684238075AE00CB272D /* AddWebFeedDefaultContainer.swift */; };
@@ -864,6 +859,12 @@
DF766FED29377FD9006FBBE2 /* ExtensionsManagementView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF766FEC29377FD9006FBBE2 /* ExtensionsManagementView.swift */; };
DF790D6228E990A900455FC7 /* AboutData.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF790D6128E990A900455FC7 /* AboutData.swift */; };
DFB3497A294A962D00BC81AD /* AddAccountView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DFB34979294A962D00BC81AD /* AddAccountView.swift */; };
DFB34980294B085100BC81AD /* AccountInspectorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DFB3497F294B085100BC81AD /* AccountInspectorView.swift */; };
DFB34982294B0B9B00BC81AD /* Inspector.strings in Resources */ = {isa = PBXBuildFile; fileRef = DFB34981294B0B9B00BC81AD /* Inspector.strings */; };
DFB34984294B3AFF00BC81AD /* Buttons.strings in Resources */ = {isa = PBXBuildFile; fileRef = DFB34983294B3AFF00BC81AD /* Buttons.strings */; };
DFB34988294B447F00BC81AD /* InjectedNavigationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DFB34987294B447F00BC81AD /* InjectedNavigationView.swift */; };
DFB3498A294B45AC00BC81AD /* ExtensionInspectorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DFB34989294B45AC00BC81AD /* ExtensionInspectorView.swift */; };
DFB3498C294B4CA700BC81AD /* WebFeedInspectorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DFB3498B294B4CA700BC81AD /* WebFeedInspectorView.swift */; };
DFC14F0F28EA55BD00F6EE86 /* AboutWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DFC14F0E28EA55BD00F6EE86 /* AboutWindowController.swift */; };
DFC14F1228EA5DC500F6EE86 /* AboutData.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF790D6128E990A900455FC7 /* AboutData.swift */; };
DFC14F1328EA677C00F6EE86 /* Bundle-Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51F85BF42273625800C787DC /* Bundle-Extensions.swift */; };
@@ -1205,7 +1206,6 @@
510FFAB226EEA22C00F32265 /* ArticleThemesTableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ArticleThemesTableViewController.swift; sourceTree = "<group>"; };
51102164233A7D6C0007A5F7 /* ArticleExtractorButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ArticleExtractorButton.swift; sourceTree = "<group>"; };
51107745243BEE2500D97C8C /* ExtensionPointPreferencesViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExtensionPointPreferencesViewController.swift; sourceTree = "<group>"; };
5110C37C2373A8D100A9C04F /* InspectorIconHeaderView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InspectorIconHeaderView.swift; sourceTree = "<group>"; };
51121AA12265430A00BC0EC1 /* NetNewsWire_iOSapp_target.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = NetNewsWire_iOSapp_target.xcconfig; sourceTree = "<group>"; };
51126DA3225FDE2F00722696 /* RSImage-Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "RSImage-Extensions.swift"; sourceTree = "<group>"; };
5117715424E1EA0F00A2A836 /* ArticleExtractorButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ArticleExtractorButton.swift; sourceTree = "<group>"; };
@@ -1238,7 +1238,6 @@
513C5CE8232571C2003D4054 /* ShareViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShareViewController.swift; sourceTree = "<group>"; };
513C5CEB232571C2003D4054 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/MainInterface.storyboard; sourceTree = "<group>"; };
513C5CED232571C2003D4054 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
5141E7382373C18B0013FF27 /* WebFeedInspectorViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WebFeedInspectorViewController.swift; sourceTree = "<group>"; };
5141E7552374A2890013FF27 /* DetailIconSchemeHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DetailIconSchemeHandler.swift; sourceTree = "<group>"; };
5142192923522B5500E07E2C /* ImageViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageViewController.swift; sourceTree = "<group>"; };
514219362352510100E07E2C /* ImageScrollView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ImageScrollView.swift; sourceTree = "<group>"; };
@@ -1270,7 +1269,6 @@
51627A92238A3836007B3B4B /* CroppingPreviewParameters.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CroppingPreviewParameters.swift; sourceTree = "<group>"; };
516A093A2360A4A000EAE89B /* SettingsTableViewCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = SettingsTableViewCell.xib; sourceTree = "<group>"; };
516A093F2361240900EAE89B /* Account.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = Account.storyboard; sourceTree = "<group>"; };
516A09412361248000EAE89B /* Inspector.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = Inspector.storyboard; sourceTree = "<group>"; };
516AE5FF246AF34100731738 /* RedditAdd.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = RedditAdd.storyboard; sourceTree = "<group>"; };
516AE601246AF36100731738 /* RedditSelectTypeTableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RedditSelectTypeTableViewController.swift; sourceTree = "<group>"; };
516AE603246AF37B00731738 /* RedditSelectAccountTableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RedditSelectAccountTableViewController.swift; sourceTree = "<group>"; };
@@ -1306,11 +1304,9 @@
519E743422C663F900A78E47 /* SceneDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = "<group>"; };
519ED455244828C3007F8E94 /* AddExtensionPointViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddExtensionPointViewController.swift; sourceTree = "<group>"; };
519ED47924482AEB007F8E94 /* EnableExtensionPointViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EnableExtensionPointViewController.swift; sourceTree = "<group>"; };
519ED47B24488C6F007F8E94 /* ExtensionInspectorViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExtensionInspectorViewController.swift; sourceTree = "<group>"; };
51A052CD244FB9D6006C2024 /* AddFeedWIndowController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = AddFeedWIndowController.swift; path = AddFeed/AddFeedWIndowController.swift; sourceTree = "<group>"; };
51A1698F235E10D600EB091F /* LocalAccountViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LocalAccountViewController.swift; sourceTree = "<group>"; };
51A16990235E10D600EB091F /* Settings.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = Settings.storyboard; sourceTree = "<group>"; };
51A16991235E10D600EB091F /* AccountInspectorViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AccountInspectorViewController.swift; sourceTree = "<group>"; };
51A16992235E10D600EB091F /* AddAccountViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AddAccountViewController.swift; sourceTree = "<group>"; };
51A16996235E10D700EB091F /* FeedbinAccountViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FeedbinAccountViewController.swift; sourceTree = "<group>"; };
51A66684238075AE00CB272D /* AddWebFeedDefaultContainer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddWebFeedDefaultContainer.swift; sourceTree = "<group>"; };
@@ -1621,6 +1617,12 @@
DF766FEC29377FD9006FBBE2 /* ExtensionsManagementView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExtensionsManagementView.swift; sourceTree = "<group>"; };
DF790D6128E990A900455FC7 /* AboutData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AboutData.swift; sourceTree = "<group>"; };
DFB34979294A962D00BC81AD /* AddAccountView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddAccountView.swift; sourceTree = "<group>"; };
DFB3497F294B085100BC81AD /* AccountInspectorView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountInspectorView.swift; sourceTree = "<group>"; };
DFB34981294B0B9B00BC81AD /* Inspector.strings */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; path = Inspector.strings; sourceTree = "<group>"; };
DFB34983294B3AFF00BC81AD /* Buttons.strings */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; path = Buttons.strings; sourceTree = "<group>"; };
DFB34987294B447F00BC81AD /* InjectedNavigationView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InjectedNavigationView.swift; sourceTree = "<group>"; };
DFB34989294B45AC00BC81AD /* ExtensionInspectorView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExtensionInspectorView.swift; sourceTree = "<group>"; };
DFB3498B294B4CA700BC81AD /* WebFeedInspectorView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WebFeedInspectorView.swift; sourceTree = "<group>"; };
DFC14F0E28EA55BD00F6EE86 /* AboutWindowController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AboutWindowController.swift; sourceTree = "<group>"; };
DFC14F1428EB177000F6EE86 /* AboutNetNewsWireView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AboutNetNewsWireView.swift; sourceTree = "<group>"; };
DFC14F1628EB17A800F6EE86 /* CreditsNetNewsWireView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CreditsNetNewsWireView.swift; sourceTree = "<group>"; };
@@ -1911,11 +1913,8 @@
5123DB95233EC69300282CC9 /* Inspector */ = {
isa = PBXGroup;
children = (
516A09412361248000EAE89B /* Inspector.storyboard */,
51A16991235E10D600EB091F /* AccountInspectorViewController.swift */,
519ED47B24488C6F007F8E94 /* ExtensionInspectorViewController.swift */,
5110C37C2373A8D100A9C04F /* InspectorIconHeaderView.swift */,
5141E7382373C18B0013FF27 /* WebFeedInspectorViewController.swift */,
DFB34981294B0B9B00BC81AD /* Inspector.strings */,
DFB3497D294B076C00BC81AD /* Views */,
);
path = Inspector;
sourceTree = "<group>";
@@ -2179,6 +2178,7 @@
51C452802265093600C03939 /* Add */ = {
isa = PBXGroup;
children = (
DFB3497E294B07D900BC81AD /* Views */,
51C452822265093600C03939 /* Add.storyboard */,
51E4397F23805EBC00015C31 /* AddComboTableViewCell.swift */,
51E43961238037C400015C31 /* AddFeedFolderViewController.swift */,
@@ -2637,6 +2637,7 @@
511D43CE231FA51100FB1562 /* Resources */,
176813A22564B9D100D98635 /* Widget */,
173A64162547BE0900267F6E /* AccountType+Helpers.swift */,
DFB34985294B3B0800BC81AD /* Translations */,
);
path = Shared;
sourceTree = "<group>";
@@ -2748,6 +2749,7 @@
5123DB95233EC69300282CC9 /* Inspector */,
513145F9235A55A700387FDC /* Intents */,
5183CCEB227117C70010922C /* Settings */,
DFB34986294B446300BC81AD /* SwiftUI Extensions */,
51C45245226506C800C03939 /* UIKit Extensions */,
513C5CE7232571C2003D4054 /* ShareExtension */,
51314643235A7C2300387FDC /* IntentsExtension */,
@@ -2940,8 +2942,8 @@
DFB3497B294AA95200BC81AD /* Accounts */ = {
isa = PBXGroup;
children = (
DFB34979294A962D00BC81AD /* AddAccountView.swift */,
DF59F0732920DB5100ACD33D /* AccountsManagementView.swift */,
DFB34979294A962D00BC81AD /* AddAccountView.swift */,
);
path = Accounts;
sourceTree = "<group>";
@@ -2955,6 +2957,39 @@
path = Extensions;
sourceTree = "<group>";
};
DFB3497D294B076C00BC81AD /* Views */ = {
isa = PBXGroup;
children = (
DFB3497F294B085100BC81AD /* AccountInspectorView.swift */,
DFB34989294B45AC00BC81AD /* ExtensionInspectorView.swift */,
DFB3498B294B4CA700BC81AD /* WebFeedInspectorView.swift */,
);
path = Views;
sourceTree = "<group>";
};
DFB3497E294B07D900BC81AD /* Views */ = {
isa = PBXGroup;
children = (
);
path = Views;
sourceTree = "<group>";
};
DFB34985294B3B0800BC81AD /* Translations */ = {
isa = PBXGroup;
children = (
DFB34983294B3AFF00BC81AD /* Buttons.strings */,
);
path = Translations;
sourceTree = "<group>";
};
DFB34986294B446300BC81AD /* SwiftUI Extensions */ = {
isa = PBXGroup;
children = (
DFB34987294B447F00BC81AD /* InjectedNavigationView.swift */,
);
path = "SwiftUI Extensions";
sourceTree = "<group>";
};
DFC14F0928EA51AB00F6EE86 /* About */ = {
isa = PBXGroup;
children = (
@@ -3551,9 +3586,9 @@
511D43D2231FA62C00FB1562 /* GlobalKeyboardShortcuts.plist in Resources */,
84C9FCA12262A1B300D921D6 /* Main.storyboard in Resources */,
51BB7C312335ACDE008E8144 /* page.html in Resources */,
DFB34982294B0B9B00BC81AD /* Inspector.strings in Resources */,
512392C324E3451400F11704 /* TwitterAdd.storyboard in Resources */,
51077C5A27A86D16000C71DB /* Hyperlegible.nnwtheme in Resources */,
516A09422361248000EAE89B /* Inspector.storyboard in Resources */,
DDF9E1D928EDF2FC000BC355 /* notificationSoundBlip.mp3 in Resources */,
DF32ABEB29494CF1008E3A12 /* Settings.strings in Resources */,
51DEE81A26FBFF84006DAA56 /* Promenade.nnwtheme in Resources */,
@@ -3567,6 +3602,7 @@
51C452AB22650DC600C03939 /* template.html in Resources */,
84A3EE61223B667F00557320 /* DefaultFeeds.opml in Resources */,
B27EEBFB244D15F3000932E6 /* stylesheet.css in Resources */,
DFB34984294B3AFF00BC81AD /* Buttons.strings in Resources */,
511D43CF231FA62200FB1562 /* DetailKeyboardShortcuts.plist in Resources */,
51A1699A235E10D700EB091F /* Settings.storyboard in Resources */,
49F40DF92335B71000552BF4 /* newsfoot.js in Resources */,
@@ -4143,6 +4179,7 @@
51EF0F79227716380050506E /* ColorHash.swift in Sources */,
DF59F072292085B800ACD33D /* ColorPaletteSelectorView.swift in Sources */,
51F9F3FB23DFB25700A314FD /* Animations.swift in Sources */,
DFB34988294B447F00BC81AD /* InjectedNavigationView.swift in Sources */,
5195C1DA2720205F00888867 /* ShadowTableChanges.swift in Sources */,
5183CCDA226E31A50010922C /* NonIntrinsicImageView.swift in Sources */,
B2B80778239C4C7000F191E0 /* RSImage-AppIcons.swift in Sources */,
@@ -4194,6 +4231,7 @@
5126EE97226CB48A00C22AFC /* SceneCoordinator.swift in Sources */,
84CAFCB022BC8C35007694F0 /* FetchRequestOperation.swift in Sources */,
DFD406FA291FB5E400C02962 /* SettingsRows.swift in Sources */,
DFB3498C294B4CA700BC81AD /* WebFeedInspectorView.swift in Sources */,
5193CD5A245E44A90092735E /* RedditFeedProvider-Extensions.swift in Sources */,
51EF0F77227716200050506E /* FaviconGenerator.swift in Sources */,
51938DF3231AFC660055A1A0 /* SearchTimelineFeedDelegate.swift in Sources */,
@@ -4208,7 +4246,6 @@
51C45294226509C800C03939 /* SearchFeedDelegate.swift in Sources */,
5F323809231DF9F000706F6B /* VibrantTableViewCell.swift in Sources */,
51FE10042345529D0056195D /* UserNotificationManager.swift in Sources */,
519ED47C24488C6F007F8E94 /* ExtensionInspectorViewController.swift in Sources */,
51C4CFF224D37D1F00AF9874 /* Secrets.swift in Sources */,
51C452A022650A1900C03939 /* WebFeedIconDownloader.swift in Sources */,
51C4529E22650A1900C03939 /* ImageDownloader.swift in Sources */,
@@ -4221,6 +4258,7 @@
51B5C87B23F2317700032075 /* ExtensionFeedAddRequest.swift in Sources */,
51627A93238A3836007B3B4B /* CroppingPreviewParameters.swift in Sources */,
512AF9DD236F05230066F8BE /* InteractiveLabel.swift in Sources */,
DFB3498A294B45AC00BC81AD /* ExtensionInspectorView.swift in Sources */,
51E3EB3D229AB08300645299 /* ErrorHandler.swift in Sources */,
5183CCE5226F4DFA0010922C /* RefreshInterval.swift in Sources */,
51C4529D22650A1000C03939 /* FaviconURLFinder.swift in Sources */,
@@ -4245,7 +4283,6 @@
51C9DE5823EA2EF4003D5A6D /* WrapperScriptMessageHandler.swift in Sources */,
51B5C87D23F2346200032075 /* ExtensionContainersFile.swift in Sources */,
51102165233A7D6C0007A5F7 /* ArticleExtractorButton.swift in Sources */,
5141E7392373C18B0013FF27 /* WebFeedInspectorViewController.swift in Sources */,
C5A6ED6D23C9B0C800AB6BE2 /* UIActivityViewController-Extensions.swift in Sources */,
5108F6D42375EEEF001ABC45 /* TimelinePreviewTableViewController.swift in Sources */,
84CAFCA522BC8C08007694F0 /* FetchRequestQueue.swift in Sources */,
@@ -4266,12 +4303,10 @@
51C45297226509E300C03939 /* DefaultFeedsImporter.swift in Sources */,
512E094D2268B8AB00BDCFDD /* DeleteCommand.swift in Sources */,
DFD406FC291FB63B00C02962 /* SettingsHelpSheets.swift in Sources */,
5110C37D2373A8D100A9C04F /* InspectorIconHeaderView.swift in Sources */,
51F85BFB2275D85000C787DC /* Array-Extensions.swift in Sources */,
515A5180243E90260089E588 /* TwitterFeedProvider-Extensions.swift in Sources */,
51C452AC22650FD200C03939 /* AppNotifications.swift in Sources */,
51EF0F7E2277A57D0050506E /* MasterTimelineAccessibilityCellLayout.swift in Sources */,
51A1699B235E10D700EB091F /* AccountInspectorViewController.swift in Sources */,
512D554423C804DE0023FFFA /* OpenInSafariActivity.swift in Sources */,
DF47CDB2294803AB00FCD57E /* AddExtensionListView.swift in Sources */,
512392C224E33A3C00F11704 /* RedditEnterDetailTableViewController.swift in Sources */,
@@ -4283,6 +4318,7 @@
51B5C8C023F3866C00032075 /* ExtensionFeedAddRequestFile.swift in Sources */,
51A169A0235E10D700EB091F /* FeedbinAccountViewController.swift in Sources */,
51934CCE2310792F006127BE /* ActivityManager.swift in Sources */,
DFB34980294B085100BC81AD /* AccountInspectorView.swift in Sources */,
5108F6B72375E612001ABC45 /* CacheCleaner.swift in Sources */,
DF59F0742920DB5100ACD33D /* AccountsManagementView.swift in Sources */,
518651DA235621840078E021 /* ImageTransition.swift in Sources */,

View File

@@ -38,7 +38,7 @@ final class ExtensionPointManager: FeedProviderManagerDelegate {
let activeExtensionPointTypes = activeExtensionPoints.keys.compactMap({ ObjectIdentifier($0.extensionPointType) })
var available = [ExtensionPoint.Type]()
for possibleExtensionPointType in possibleExtensionPointTypes {
if !(AppDefaults.shared.isDeveloperBuild && possibleExtensionPointType.isDeveloperBuildRestricted) {
if (AppDefaults.shared.isDeveloperBuild && possibleExtensionPointType.isDeveloperBuildRestricted) {
if possibleExtensionPointType.isSinglton {
if !activeExtensionPointTypes.contains(ObjectIdentifier(possibleExtensionPointType)) {
available.append(possibleExtensionPointType)

View File

@@ -0,0 +1,10 @@
/*
Buttons.strings
NetNewsWire
Created by Stuart Breckenridge on 15/12/2022.
Copyright © 2022 Ranchero Software. All rights reserved.
*/
"CANCEL_BUTTON_TITLE" = "Cancel";
"DONE_BUTTON_TITLE" = "Done";

View File

@@ -1,231 +0,0 @@
//
// AccountInspectorViewController.swift
// NetNewsWire-iOS
//
// Created by Maurice Parker on 5/17/19.
// Copyright © 2019 Ranchero Software. All rights reserved.
//
import UIKit
import SafariServices
import Account
import SwiftUI
struct AccountInspectorWrapper: UIViewControllerRepresentable {
var account: Account
func makeUIViewController(context: Context) -> AccountInspectorViewController {
let controller = UIStoryboard.inspector.instantiateViewController(withIdentifier: "AccountInspectorViewController") as! AccountInspectorViewController
controller.account = account
return controller
}
func updateUIViewController(_ uiViewController: AccountInspectorViewController, context: Context) {
//
}
typealias UIViewControllerType = AccountInspectorViewController
}
class AccountInspectorViewController: UITableViewController {
static let preferredContentSizeForFormSheetDisplay = CGSize(width: 460.0, height: 400.0)
@IBOutlet weak var nameTextField: UITextField!
@IBOutlet weak var activeSwitch: UISwitch!
@IBOutlet weak var deleteAccountButton: VibrantButton!
@IBOutlet weak var limitationsAndSolutionsView: UIView!
var isModal = false
weak var account: Account?
override func viewDidLoad() {
super.viewDidLoad()
guard let account = account else { return }
nameTextField.placeholder = account.defaultName
nameTextField.text = account.name
nameTextField.delegate = self
activeSwitch.isOn = account.isActive
navigationItem.title = account.nameForDisplay
if account.type != .onMyMac {
deleteAccountButton.setTitle(NSLocalizedString("Remove Account", comment: "Remove Account"), for: .normal)
}
if account.type != .cloudKit {
limitationsAndSolutionsView.isHidden = true
}
if isModal {
let doneBarButtonItem = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(done))
navigationItem.leftBarButtonItem = doneBarButtonItem
}
tableView.register(ImageHeaderView.self, forHeaderFooterViewReuseIdentifier: "SectionHeader")
}
override func viewWillDisappear(_ animated: Bool) {
account?.name = nameTextField.text
account?.isActive = activeSwitch.isOn
}
@objc func done() {
dismiss(animated: true)
}
@IBAction func credentials(_ sender: Any) {
guard let account = account else { return }
switch account.type {
case .feedbin:
let navController = UIStoryboard.account.instantiateViewController(withIdentifier: "FeedbinAccountNavigationViewController") as! UINavigationController
let addViewController = navController.topViewController as! FeedbinAccountViewController
addViewController.account = account
navController.modalPresentationStyle = .currentContext
present(navController, animated: true)
case .newsBlur:
let navController = UIStoryboard.account.instantiateViewController(withIdentifier: "NewsBlurAccountNavigationViewController") as! UINavigationController
let addViewController = navController.topViewController as! NewsBlurAccountViewController
addViewController.account = account
navController.modalPresentationStyle = .currentContext
present(navController, animated: true)
case .inoreader, .bazQux, .theOldReader, .freshRSS:
let navController = UIStoryboard.account.instantiateViewController(withIdentifier: "ReaderAPIAccountNavigationViewController") as! UINavigationController
let addViewController = navController.topViewController as! ReaderAPIAccountViewController
addViewController.accountType = account.type
addViewController.account = account
navController.modalPresentationStyle = .currentContext
present(navController, animated: true)
default:
break
}
}
@IBAction func deleteAccount(_ sender: Any) {
guard let account = account else {
return
}
let title = NSLocalizedString("Remove Account", comment: "Remove Account")
let message: String = {
switch account.type {
case .feedly:
return NSLocalizedString("Are you sure you want to remove this account? NetNewsWire will no longer be able to access articles and feeds unless the account is added again.", comment: "Log Out and Remove Account")
default:
return NSLocalizedString("Are you sure you want to remove this account? This cannot be undone.", comment: "Remove Account")
}
}()
let alertController = UIAlertController(title: title, message: message, preferredStyle: .alert)
let cancelTitle = NSLocalizedString("Cancel", comment: "Cancel")
let cancelAction = UIAlertAction(title: cancelTitle, style: .cancel)
alertController.addAction(cancelAction)
let markTitle = NSLocalizedString("Remove", comment: "Remove")
let markAction = UIAlertAction(title: markTitle, style: .default) { [weak self] (action) in
guard let self = self, let account = self.account else { return }
AccountManager.shared.deleteAccount(account)
if self.isModal {
self.dismiss(animated: true)
} else {
self.navigationController?.popViewController(animated: true)
}
}
alertController.addAction(markAction)
alertController.preferredAction = markAction
present(alertController, animated: true)
}
@IBAction func openLimitationsAndSolutions(_ sender: Any) {
let vc = SFSafariViewController(url: CloudKitWebDocumentation.limitationsAndSolutionsURL)
vc.modalPresentationStyle = .pageSheet
present(vc, animated: true)
}
}
// MARK: Table View
extension AccountInspectorViewController {
var hidesCredentialsSection: Bool {
guard let account = account else {
return true
}
switch account.type {
case .onMyMac, .cloudKit, .feedly:
return true
default:
return false
}
}
override func numberOfSections(in tableView: UITableView) -> Int {
guard let account = account else { return 0 }
if account == AccountManager.shared.defaultAccount {
return 1
} else if hidesCredentialsSection {
return 2
} else {
return super.numberOfSections(in: tableView)
}
}
override func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return section == 0 ? ImageHeaderView.rowHeight : super.tableView(tableView, heightForHeaderInSection: section)
}
override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
guard let account = account else { return nil }
if section == 0 {
let headerView = tableView.dequeueReusableHeaderFooterView(withIdentifier: "SectionHeader") as! ImageHeaderView
headerView.imageView.image = AppAssets.image(for: account.type)
return headerView
} else {
return super.tableView(tableView, viewForHeaderInSection: section)
}
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell: UITableViewCell
if indexPath.section == 1, hidesCredentialsSection {
cell = super.tableView(tableView, cellForRowAt: IndexPath(row: 0, section: 2))
} else {
cell = super.tableView(tableView, cellForRowAt: indexPath)
}
return cell
}
override func tableView(_ tableView: UITableView, shouldHighlightRowAt indexPath: IndexPath) -> Bool {
if indexPath.section > 0 {
return true
}
return false
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.selectRow(at: nil, animated: true, scrollPosition: .none)
}
}
// MARK: UITextFieldDelegate
extension AccountInspectorViewController: UITextFieldDelegate {
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
textField.resignFirstResponder()
return true
}
}

View File

@@ -1,102 +0,0 @@
//
// ExtensionPointInspectorViewController.swift
// NetNewsWire-iOS
//
// Created by Maurice Parker on 4/16/20.
// Copyright © 2020 Ranchero Software. All rights reserved.
//
import UIKit
import SwiftUI
struct ExtensionPointInspectorWrapper: UIViewControllerRepresentable {
var extensionPoint: ExtensionPoint?
func makeUIViewController(context: Context) -> ExtensionPointInspectorViewController {
let controller = UIStoryboard.inspector.instantiateViewController(withIdentifier: "ExtensionPointInspectorViewController") as! ExtensionPointInspectorViewController
controller.extensionPoint = extensionPoint
return controller
}
func updateUIViewController(_ uiViewController: ExtensionPointInspectorViewController, context: Context) {
//
}
typealias UIViewControllerType = ExtensionPointInspectorViewController
}
class ExtensionPointInspectorViewController: UITableViewController {
@IBOutlet weak var extensionDescription: UILabel!
var extensionPoint: ExtensionPoint?
override func viewDidLoad() {
super.viewDidLoad()
guard let extensionPoint = extensionPoint else { return }
navigationItem.title = extensionPoint.title
extensionDescription.attributedText = extensionPoint.description
tableView.register(ImageHeaderView.self, forHeaderFooterViewReuseIdentifier: "SectionHeader")
}
@IBAction func disable(_ sender: Any) {
guard let extensionPoint = extensionPoint else { return }
let title = NSLocalizedString("Deactivate Extension", comment: "Deactivate Extension")
let extensionPointTypeTitle = extensionPoint.extensionPointID.extensionPointType.title
let message = NSLocalizedString("Are you sure you want to deactivate the \(extensionPointTypeTitle) extension “\(extensionPoint.title)”?", comment: "Deactivate text")
let alertController = UIAlertController(title: title, message: message, preferredStyle: .alert)
let cancelTitle = NSLocalizedString("Cancel", comment: "Cancel")
let cancelAction = UIAlertAction(title: cancelTitle, style: .cancel)
alertController.addAction(cancelAction)
let markTitle = NSLocalizedString("Deactivate", comment: "Deactivate")
let markAction = UIAlertAction(title: markTitle, style: .default) { [weak self] (action) in
ExtensionPointManager.shared.deactivateExtensionPoint(extensionPoint.extensionPointID)
self?.navigationController?.popViewController(animated: true)
}
alertController.addAction(markAction)
alertController.preferredAction = markAction
present(alertController, animated: true)
}
}
// MARK: Table View
extension ExtensionPointInspectorViewController {
override func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return section == 0 ? ImageHeaderView.rowHeight : super.tableView(tableView, heightForHeaderInSection: section)
}
override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
guard let extensionPoint = extensionPoint else { return nil }
if section == 0 {
let headerView = tableView.dequeueReusableHeaderFooterView(withIdentifier: "SectionHeader") as! ImageHeaderView
headerView.imageView.image = extensionPoint.image
return headerView
} else {
return super.tableView(tableView, viewForHeaderInSection: section)
}
}
override func tableView(_ tableView: UITableView, shouldHighlightRowAt indexPath: IndexPath) -> Bool {
if indexPath.section > 0 {
return true
}
return false
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.selectRow(at: nil, animated: true, scrollPosition: .none)
}
}

View File

@@ -1,516 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="21507" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
<device id="retina6_1" orientation="portrait" appearance="light"/>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="21505"/>
<capability name="Named colors" minToolsVersion="9.0"/>
<capability name="System colors in document resources" minToolsVersion="11.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
<!--Account Inspector View Controller-->
<scene sceneID="nCF-Ns-xpY">
<objects>
<tableViewController storyboardIdentifier="AccountInspectorViewController" id="1m3-fZ-n7g" customClass="AccountInspectorViewController" customModule="NetNewsWire" customModuleProvider="target" sceneMemberID="viewController">
<tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="static" style="insetGrouped" separatorStyle="default" rowHeight="-1" estimatedRowHeight="-1" sectionHeaderHeight="18" sectionFooterHeight="18" id="xcc-i3-tPS">
<rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<view key="tableFooterView" contentMode="scaleToFill" id="3V2-Cm-ezj">
<rect key="frame" x="0.0" y="282" width="414" height="44"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<subviews>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="dgD-uX-vcx">
<rect key="frame" x="75" y="7" width="264" height="30"/>
<fontDescription key="fontDescription" style="UICTFontTextStyleSubhead"/>
<inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/>
<state key="normal" title="iCloud Syncing Limitations &amp; Solutions"/>
<connections>
<action selector="openLimitationsAndSolutions:" destination="1m3-fZ-n7g" eventType="touchUpInside" id="DKt-dF-a6L"/>
</connections>
</button>
</subviews>
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
<constraints>
<constraint firstItem="dgD-uX-vcx" firstAttribute="centerX" secondItem="3V2-Cm-ezj" secondAttribute="centerX" id="IDg-5p-aZs"/>
<constraint firstItem="dgD-uX-vcx" firstAttribute="centerY" secondItem="3V2-Cm-ezj" secondAttribute="centerY" id="w0c-Qa-ADC"/>
</constraints>
</view>
<sections>
<tableViewSection id="vec-ab-Ylg">
<cells>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" id="4Ue-UW-e0l" customClass="VibrantTableViewCell" customModule="NetNewsWire" customModuleProvider="target">
<rect key="frame" x="20" y="18" width="374" height="43.5"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="4Ue-UW-e0l" id="9E1-ww-kYn">
<rect key="frame" x="0.0" y="0.0" width="374" height="43.5"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<stackView opaque="NO" contentMode="scaleToFill" spacing="19" translatesAutoresizingMaskIntoConstraints="NO" id="mQa-0W-eVS">
<rect key="frame" x="20" y="11" width="334" height="22"/>
<subviews>
<textField opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" placeholder="Name (Optional)" adjustsFontForContentSizeCategory="YES" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="LUW-uv-piz">
<rect key="frame" x="0.0" y="0.0" width="334" height="22"/>
<fontDescription key="fontDescription" style="UICTFontTextStyleBody"/>
<textInputTraits key="textInputTraits" autocapitalizationType="words"/>
</textField>
</subviews>
</stackView>
</subviews>
<constraints>
<constraint firstItem="mQa-0W-eVS" firstAttribute="leading" secondItem="9E1-ww-kYn" secondAttribute="leading" constant="20" symbolic="YES" id="ATM-Pf-PSm"/>
<constraint firstItem="mQa-0W-eVS" firstAttribute="centerY" secondItem="9E1-ww-kYn" secondAttribute="centerY" id="DWl-vJ-i3I"/>
<constraint firstAttribute="trailing" secondItem="mQa-0W-eVS" secondAttribute="trailing" constant="20" symbolic="YES" id="aIV-cb-QTV"/>
</constraints>
</tableViewCellContentView>
</tableViewCell>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" id="zQY-gY-BOY" customClass="VibrantTableViewCell" customModule="NetNewsWire" customModuleProvider="target">
<rect key="frame" x="20" y="61.5" width="374" height="43.5"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="zQY-gY-BOY" id="dBp-J5-ZsY">
<rect key="frame" x="0.0" y="0.0" width="374" height="43.5"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Active" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontForContentSizeCategory="YES" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="zf0-Gm-p4F">
<rect key="frame" x="20" y="11.5" width="47.5" height="20.5"/>
<fontDescription key="fontDescription" style="UICTFontTextStyleBody"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" on="YES" translatesAutoresizingMaskIntoConstraints="NO" id="6YV-K0-yPS">
<rect key="frame" x="305" y="6.5" width="51" height="31"/>
<color key="onTintColor" name="primaryAccentColor"/>
</switch>
</subviews>
<constraints>
<constraint firstItem="zf0-Gm-p4F" firstAttribute="leading" secondItem="dBp-J5-ZsY" secondAttribute="leading" constant="20" symbolic="YES" id="lAQ-Ps-JwD"/>
<constraint firstItem="zf0-Gm-p4F" firstAttribute="centerY" secondItem="dBp-J5-ZsY" secondAttribute="centerY" id="ofD-kM-lP4"/>
<constraint firstItem="6YV-K0-yPS" firstAttribute="centerY" secondItem="dBp-J5-ZsY" secondAttribute="centerY" id="yOM-Bc-HU8"/>
<constraint firstAttribute="trailing" secondItem="6YV-K0-yPS" secondAttribute="trailing" constant="20" symbolic="YES" id="yk4-Dh-YVh"/>
</constraints>
</tableViewCellContentView>
</tableViewCell>
</cells>
</tableViewSection>
<tableViewSection id="9UW-s0-NPI">
<cells>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" id="FsT-vH-rTo" customClass="VibrantTableViewCell" customModule="NetNewsWire" customModuleProvider="target">
<rect key="frame" x="20" y="141" width="374" height="43.5"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="FsT-vH-rTo" id="rJW-6J-9DM">
<rect key="frame" x="0.0" y="0.0" width="374" height="43.5"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="TYD-py-8IF" customClass="VibrantButton" customModule="NetNewsWire" customModuleProvider="target">
<rect key="frame" x="0.0" y="-0.5" width="374" height="44.5"/>
<constraints>
<constraint firstAttribute="height" constant="44" id="WmU-wG-RLQ"/>
</constraints>
<fontDescription key="fontDescription" style="UICTFontTextStyleBody"/>
<state key="normal" title="Credentials">
<color key="titleColor" name="secondaryAccentColor"/>
</state>
<connections>
<action selector="credentials:" destination="1m3-fZ-n7g" eventType="touchUpInside" id="Kkh-Ag-aGX"/>
</connections>
</button>
</subviews>
<constraints>
<constraint firstItem="TYD-py-8IF" firstAttribute="centerY" secondItem="rJW-6J-9DM" secondAttribute="centerY" id="We5-ck-yMq"/>
<constraint firstItem="TYD-py-8IF" firstAttribute="leading" secondItem="rJW-6J-9DM" secondAttribute="leading" id="gIs-Z2-bBf"/>
<constraint firstAttribute="trailing" secondItem="TYD-py-8IF" secondAttribute="trailing" id="uFe-xv-QBo"/>
</constraints>
</tableViewCellContentView>
</tableViewCell>
</cells>
</tableViewSection>
<tableViewSection id="mgY-wW-xiO">
<cells>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" id="lgY-im-vCo" customClass="VibrantTableViewCell" customModule="NetNewsWire" customModuleProvider="target">
<rect key="frame" x="20" y="220.5" width="374" height="43.5"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="lgY-im-vCo" id="fIH-xP-nza">
<rect key="frame" x="0.0" y="0.0" width="374" height="43.5"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="obv-a5-Pl6" customClass="VibrantButton" customModule="NetNewsWire" customModuleProvider="target">
<rect key="frame" x="0.0" y="-0.5" width="374" height="44.5"/>
<constraints>
<constraint firstAttribute="height" constant="44" id="WtN-fp-Ldt"/>
</constraints>
<fontDescription key="fontDescription" style="UICTFontTextStyleBody"/>
<state key="normal" title="Remove Account">
<color key="titleColor" systemColor="systemRedColor"/>
</state>
<state key="highlighted">
<color key="titleColor" systemColor="systemRedColor"/>
</state>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="color" keyPath="backgroundHighlightColor">
<color key="value" name="deleteBackgroundColor"/>
</userDefinedRuntimeAttribute>
</userDefinedRuntimeAttributes>
<connections>
<action selector="deleteAccount:" destination="1m3-fZ-n7g" eventType="touchUpInside" id="gYt-Fi-Eqe"/>
</connections>
</button>
</subviews>
<constraints>
<constraint firstAttribute="trailing" secondItem="obv-a5-Pl6" secondAttribute="trailing" id="1Po-cv-lMZ"/>
<constraint firstItem="obv-a5-Pl6" firstAttribute="leading" secondItem="fIH-xP-nza" secondAttribute="leading" id="4Xk-ff-eUv"/>
<constraint firstItem="obv-a5-Pl6" firstAttribute="centerY" secondItem="fIH-xP-nza" secondAttribute="centerY" id="Vs4-U1-hKv"/>
</constraints>
</tableViewCellContentView>
</tableViewCell>
</cells>
</tableViewSection>
</sections>
<connections>
<outlet property="dataSource" destination="1m3-fZ-n7g" id="eTZ-Uy-P3l"/>
<outlet property="delegate" destination="1m3-fZ-n7g" id="ZUV-ww-yOH"/>
</connections>
</tableView>
<navigationItem key="navigationItem" id="Fkf-MF-Fdf"/>
<connections>
<outlet property="activeSwitch" destination="6YV-K0-yPS" id="d9M-GP-aTR"/>
<outlet property="deleteAccountButton" destination="obv-a5-Pl6" id="idW-gm-BIJ"/>
<outlet property="limitationsAndSolutionsView" destination="3V2-Cm-ezj" id="Na9-t7-crH"/>
<outlet property="nameTextField" destination="LUW-uv-piz" id="e2P-Hq-guh"/>
</connections>
</tableViewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="zcI-Zg-28D" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="863.768115942029" y="-591.29464285714278"/>
</scene>
<!--Web Feed Inspector View Controller-->
<scene sceneID="jnI-2I-AcU">
<objects>
<tableViewController storyboardIdentifier="FeedInspectorViewControllelr" id="lEH-bG-pQW" customClass="WebFeedInspectorViewController" customModule="NetNewsWire" customModuleProvider="target" sceneMemberID="viewController">
<tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="static" style="insetGrouped" separatorStyle="default" rowHeight="-1" estimatedRowHeight="-1" sectionHeaderHeight="18" sectionFooterHeight="18" id="26V-ZC-Q2R">
<rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<sections>
<tableViewSection id="LEk-I1-Kkn">
<cells>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="none" indentationWidth="10" id="FPJ-5s-QTm">
<rect key="frame" x="20" y="18" width="374" height="43.5"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="FPJ-5s-QTm" id="S7f-Et-p8x">
<rect key="frame" x="0.0" y="0.0" width="374" height="43.5"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<textField opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" placeholder="Name" textAlignment="natural" adjustsFontForContentSizeCategory="YES" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="ZdA-rl-9eP">
<rect key="frame" x="20" y="11" width="334" height="22"/>
<fontDescription key="fontDescription" style="UICTFontTextStyleBody"/>
<textInputTraits key="textInputTraits" autocapitalizationType="words"/>
</textField>
</subviews>
<constraints>
<constraint firstItem="ZdA-rl-9eP" firstAttribute="leading" secondItem="S7f-Et-p8x" secondAttribute="leading" constant="20" symbolic="YES" id="9aN-eQ-OxO"/>
<constraint firstAttribute="trailing" secondItem="ZdA-rl-9eP" secondAttribute="trailing" constant="20" symbolic="YES" id="AAZ-un-HNQ"/>
<constraint firstItem="ZdA-rl-9eP" firstAttribute="centerY" secondItem="S7f-Et-p8x" secondAttribute="centerY" id="CDZ-Wg-H0P"/>
</constraints>
</tableViewCellContentView>
</tableViewCell>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="none" indentationWidth="10" id="6Yy-4a-kYM">
<rect key="frame" x="20" y="61.5" width="374" height="43.5"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="6Yy-4a-kYM" id="FfV-P4-TNg">
<rect key="frame" x="0.0" y="0.0" width="374" height="43.5"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Notify About New Articles" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontForContentSizeCategory="YES" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="YV2-gG-lMP">
<rect key="frame" x="24" y="11.5" width="196.5" height="20.5"/>
<fontDescription key="fontDescription" style="UICTFontTextStyleBody"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" on="YES" translatesAutoresizingMaskIntoConstraints="NO" id="g39-wK-xUs">
<rect key="frame" x="305" y="6.5" width="51" height="31"/>
<color key="onTintColor" name="primaryAccentColor"/>
<connections>
<action selector="notifyAboutNewArticlesChanged:" destination="lEH-bG-pQW" eventType="valueChanged" id="1Mv-Im-H5v"/>
</connections>
</switch>
</subviews>
<constraints>
<constraint firstItem="g39-wK-xUs" firstAttribute="centerY" secondItem="FfV-P4-TNg" secondAttribute="centerY" id="2bF-Jp-tob"/>
<constraint firstItem="YV2-gG-lMP" firstAttribute="centerY" secondItem="FfV-P4-TNg" secondAttribute="centerY" id="IaF-U5-CVN"/>
<constraint firstItem="g39-wK-xUs" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="YV2-gG-lMP" secondAttribute="trailing" constant="8" id="PfE-bK-rrS"/>
<constraint firstItem="YV2-gG-lMP" firstAttribute="leading" secondItem="FfV-P4-TNg" secondAttribute="leadingMargin" constant="4" id="dT8-rP-umA"/>
<constraint firstAttribute="trailing" secondItem="g39-wK-xUs" secondAttribute="trailing" constant="20" symbolic="YES" id="hMe-jH-tbS"/>
</constraints>
</tableViewCellContentView>
</tableViewCell>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="none" indentationWidth="10" id="glX-68-wCa">
<rect key="frame" x="20" y="105" width="374" height="43.5"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="glX-68-wCa" id="FQk-5f-EtL">
<rect key="frame" x="0.0" y="0.0" width="374" height="43.5"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Always Use Reader View" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontForContentSizeCategory="YES" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Bf4-3X-Rfr">
<rect key="frame" x="24" y="11.5" width="187" height="20.5"/>
<fontDescription key="fontDescription" style="UICTFontTextStyleBody"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" on="YES" translatesAutoresizingMaskIntoConstraints="NO" id="fUd-JB-UMK">
<rect key="frame" x="305" y="6.5" width="51" height="31"/>
<color key="onTintColor" name="primaryAccentColor"/>
<connections>
<action selector="alwaysShowReaderViewChanged:" destination="lEH-bG-pQW" eventType="valueChanged" id="grg-EM-T3u"/>
</connections>
</switch>
</subviews>
<constraints>
<constraint firstAttribute="trailing" secondItem="fUd-JB-UMK" secondAttribute="trailing" constant="20" symbolic="YES" id="4vJ-pa-iCa"/>
<constraint firstItem="fUd-JB-UMK" firstAttribute="centerY" secondItem="FQk-5f-EtL" secondAttribute="centerY" id="BT1-8x-hrj"/>
<constraint firstItem="Bf4-3X-Rfr" firstAttribute="leading" secondItem="FQk-5f-EtL" secondAttribute="leadingMargin" constant="4" id="vqc-MM-8vz"/>
<constraint firstItem="Bf4-3X-Rfr" firstAttribute="centerY" secondItem="FQk-5f-EtL" secondAttribute="centerY" id="wyr-Kk-g5H"/>
<constraint firstItem="fUd-JB-UMK" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="Bf4-3X-Rfr" secondAttribute="trailing" constant="8" id="ywd-qz-cAd"/>
</constraints>
</tableViewCellContentView>
</tableViewCell>
</cells>
</tableViewSection>
<tableViewSection headerTitle="Home Page" id="dTd-6q-SZd">
<cells>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" id="0zc-o6-Sjh" customClass="VibrantBasicTableViewCell" customModule="NetNewsWire" customModuleProvider="target">
<rect key="frame" x="20" y="204.5" width="374" height="22.5"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="0zc-o6-Sjh" id="vJs-XK-ebf">
<rect key="frame" x="0.0" y="0.0" width="374" height="22.5"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="" textAlignment="natural" lineBreakMode="characterWrap" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontForContentSizeCategory="YES" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="HUP-Cu-FGT">
<rect key="frame" x="20" y="11" width="301" height="0.5"/>
<fontDescription key="fontDescription" style="UICTFontTextStyleBody"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="safari" catalog="system" translatesAutoresizingMaskIntoConstraints="NO" id="p82-kn-lfh">
<rect key="frame" x="329" y="-1" width="25" height="24.5"/>
<color key="tintColor" name="primaryAccentColor"/>
<constraints>
<constraint firstAttribute="width" constant="25" id="Suu-bu-Lar"/>
<constraint firstAttribute="height" constant="25" id="gD0-zu-2pr"/>
</constraints>
</imageView>
</subviews>
<constraints>
<constraint firstItem="p82-kn-lfh" firstAttribute="leading" secondItem="HUP-Cu-FGT" secondAttribute="trailing" constant="8" symbolic="YES" id="4Ze-t9-SMR"/>
<constraint firstAttribute="trailing" secondItem="p82-kn-lfh" secondAttribute="trailing" constant="20" symbolic="YES" id="69m-bk-BHO"/>
<constraint firstItem="HUP-Cu-FGT" firstAttribute="leading" secondItem="vJs-XK-ebf" secondAttribute="leadingMargin" id="GrO-sc-ZMe"/>
<constraint firstAttribute="bottomMargin" secondItem="HUP-Cu-FGT" secondAttribute="bottom" id="Jtq-bB-vJN"/>
<constraint firstItem="p82-kn-lfh" firstAttribute="centerY" secondItem="vJs-XK-ebf" secondAttribute="centerY" id="f1u-Mm-Arn"/>
<constraint firstItem="HUP-Cu-FGT" firstAttribute="top" secondItem="vJs-XK-ebf" secondAttribute="topMargin" id="lBd-G7-RdW"/>
</constraints>
</tableViewCellContentView>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="image" keyPath="imageNormal" value="safari" catalog="system"/>
<userDefinedRuntimeAttribute type="image" keyPath="imageSelected" value="safari.fill" catalog="system"/>
</userDefinedRuntimeAttributes>
<connections>
<outlet property="icon" destination="p82-kn-lfh" id="qYr-gp-cbS"/>
<outlet property="label" destination="HUP-Cu-FGT" id="FWP-ba-TIm"/>
</connections>
</tableViewCell>
</cells>
</tableViewSection>
<tableViewSection headerTitle="Feed URL" id="MtQ-oG-lrU">
<cells>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="none" indentationWidth="10" id="fKD-Vi-B8O">
<rect key="frame" x="20" y="283" width="374" height="22.5"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="fKD-Vi-B8O" id="2G0-9f-qwN">
<rect key="frame" x="0.0" y="0.0" width="374" height="22.5"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="" textAlignment="natural" lineBreakMode="characterWrap" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontForContentSizeCategory="YES" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="rOV-XS-bNW" customClass="InteractiveLabel" customModule="NetNewsWire" customModuleProvider="target">
<rect key="frame" x="20" y="11" width="334" height="0.5"/>
<fontDescription key="fontDescription" style="UICTFontTextStyleBody"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<constraints>
<constraint firstAttribute="trailingMargin" secondItem="rOV-XS-bNW" secondAttribute="trailing" id="M1N-hj-51g"/>
<constraint firstItem="rOV-XS-bNW" firstAttribute="top" secondItem="2G0-9f-qwN" secondAttribute="topMargin" id="SCe-Ln-xRa"/>
<constraint firstAttribute="bottomMargin" secondItem="rOV-XS-bNW" secondAttribute="bottom" id="cfZ-oe-dTK"/>
<constraint firstItem="rOV-XS-bNW" firstAttribute="leading" secondItem="2G0-9f-qwN" secondAttribute="leadingMargin" id="kTa-5N-K3n"/>
</constraints>
</tableViewCellContentView>
</tableViewCell>
</cells>
</tableViewSection>
</sections>
<connections>
<outlet property="dataSource" destination="lEH-bG-pQW" id="B83-a4-nKt"/>
<outlet property="delegate" destination="lEH-bG-pQW" id="M6w-j0-89G"/>
</connections>
</tableView>
<navigationItem key="navigationItem" id="RpI-ip-5vN">
<barButtonItem key="leftBarButtonItem" style="done" systemItem="done" id="jly-Cb-Ezg">
<connections>
<action selector="done:" destination="lEH-bG-pQW" id="Jie-OM-mje"/>
</connections>
</barButtonItem>
</navigationItem>
<connections>
<outlet property="alwaysShowReaderViewSwitch" destination="fUd-JB-UMK" id="kUh-ob-Ego"/>
<outlet property="feedURLLabel" destination="rOV-XS-bNW" id="mPv-yb-H4I"/>
<outlet property="homePageLabel" destination="HUP-Cu-FGT" id="EDm-vt-2r0"/>
<outlet property="nameTextField" destination="ZdA-rl-9eP" id="GzR-uc-fpV"/>
<outlet property="notifyAboutNewArticlesSwitch" destination="g39-wK-xUs" id="ahS-ZK-6xN"/>
</connections>
</tableViewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="qKF-0N-vfa" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="864" y="58"/>
</scene>
<!--Navigation Controller-->
<scene sceneID="fZt-Nz-Jvk">
<objects>
<navigationController storyboardIdentifier="FeedInspectorNavigationViewController" id="Ybm-En-qAg" sceneMemberID="viewController">
<navigationBar key="navigationBar" contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" id="YQK-Se-EBX">
<rect key="frame" x="0.0" y="48" width="414" height="44"/>
<autoresizingMask key="autoresizingMask"/>
</navigationBar>
<connections>
<segue destination="lEH-bG-pQW" kind="relationship" relationship="rootViewController" id="zEG-1X-hgE"/>
</connections>
</navigationController>
<placeholder placeholderIdentifier="IBFirstResponder" id="8Yb-xu-2p2" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="168" y="58"/>
</scene>
<!--Navigation Controller-->
<scene sceneID="Oea-QH-lLX">
<objects>
<navigationController storyboardIdentifier="AccountInspectorNavigationViewController" id="5wr-gz-V2t" sceneMemberID="viewController">
<navigationBar key="navigationBar" contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" id="3Os-JI-n4e">
<rect key="frame" x="0.0" y="48" width="414" height="44"/>
<autoresizingMask key="autoresizingMask"/>
</navigationBar>
<connections>
<segue destination="1m3-fZ-n7g" kind="relationship" relationship="rootViewController" id="N6Y-D7-T01"/>
</connections>
</navigationController>
<placeholder placeholderIdentifier="IBFirstResponder" id="Uz1-sQ-sSV" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="157" y="-591"/>
</scene>
<!--Extension Point Inspector View Controller-->
<scene sceneID="OYN-w4-caJ">
<objects>
<tableViewController storyboardIdentifier="ExtensionPointInspectorViewController" id="1B7-3Y-VYf" customClass="ExtensionPointInspectorViewController" customModule="NetNewsWire" customModuleProvider="target" sceneMemberID="viewController">
<tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="static" style="insetGrouped" separatorStyle="default" rowHeight="-1" estimatedRowHeight="-1" sectionHeaderHeight="18" sectionFooterHeight="18" id="sMo-hq-Gps">
<rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<sections>
<tableViewSection id="hGI-fH-ovr">
<cells>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" id="hx7-HU-HV2" customClass="VibrantTableViewCell" customModule="NetNewsWire" customModuleProvider="target">
<rect key="frame" x="20" y="18" width="374" height="43"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="hx7-HU-HV2" id="fEV-cR-i6h">
<rect key="frame" x="0.0" y="0.0" width="374" height="43"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontForContentSizeCategory="YES" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="YJL-5w-N2S">
<rect key="frame" x="20" y="11" width="334" height="21"/>
<fontDescription key="fontDescription" style="UICTFontTextStyleBody"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<constraints>
<constraint firstItem="YJL-5w-N2S" firstAttribute="leading" secondItem="fEV-cR-i6h" secondAttribute="leadingMargin" id="kx6-6v-VNw"/>
<constraint firstItem="YJL-5w-N2S" firstAttribute="top" secondItem="fEV-cR-i6h" secondAttribute="topMargin" id="l6Y-A0-BFs"/>
<constraint firstAttribute="bottomMargin" secondItem="YJL-5w-N2S" secondAttribute="bottom" id="nKi-1U-g6E"/>
<constraint firstAttribute="trailingMargin" secondItem="YJL-5w-N2S" secondAttribute="trailing" id="o5n-Co-7RG"/>
</constraints>
</tableViewCellContentView>
</tableViewCell>
</cells>
</tableViewSection>
<tableViewSection id="OcC-FF-jGv">
<cells>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" id="k4j-va-uaO" customClass="VibrantTableViewCell" customModule="NetNewsWire" customModuleProvider="target">
<rect key="frame" x="20" y="97" width="374" height="43.5"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="k4j-va-uaO" id="bQ8-mc-QAj">
<rect key="frame" x="0.0" y="0.0" width="374" height="43.5"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="IhW-3B-PM7" customClass="VibrantButton" customModule="NetNewsWire" customModuleProvider="target">
<rect key="frame" x="0.0" y="-0.5" width="374" height="44.5"/>
<constraints>
<constraint firstAttribute="height" constant="44" id="qwy-Nb-VrG"/>
</constraints>
<fontDescription key="fontDescription" style="UICTFontTextStyleBody"/>
<state key="normal" title="Deactivate Extension">
<color key="titleColor" systemColor="systemRedColor"/>
</state>
<state key="highlighted">
<color key="titleColor" systemColor="systemRedColor"/>
</state>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="color" keyPath="backgroundHighlightColor">
<color key="value" name="deleteBackgroundColor"/>
</userDefinedRuntimeAttribute>
</userDefinedRuntimeAttributes>
<connections>
<action selector="disable:" destination="1B7-3Y-VYf" eventType="touchUpInside" id="hVd-LH-FhC"/>
</connections>
</button>
</subviews>
<constraints>
<constraint firstItem="IhW-3B-PM7" firstAttribute="centerY" secondItem="bQ8-mc-QAj" secondAttribute="centerY" id="DLY-b7-amc"/>
<constraint firstItem="IhW-3B-PM7" firstAttribute="leading" secondItem="bQ8-mc-QAj" secondAttribute="leading" id="LlY-8t-XJf"/>
<constraint firstAttribute="trailing" secondItem="IhW-3B-PM7" secondAttribute="trailing" id="Ua9-qY-YaN"/>
</constraints>
</tableViewCellContentView>
</tableViewCell>
</cells>
</tableViewSection>
</sections>
<connections>
<outlet property="dataSource" destination="1B7-3Y-VYf" id="Ro3-xz-VDK"/>
<outlet property="delegate" destination="1B7-3Y-VYf" id="X3w-Zg-zKw"/>
</connections>
</tableView>
<navigationItem key="navigationItem" id="bBU-mK-vL1"/>
<connections>
<outlet property="extensionDescription" destination="YJL-5w-N2S" id="zam-r3-KIC"/>
</connections>
</tableViewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="cc3-yd-zmS" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="1549" y="-591"/>
</scene>
</scenes>
<designables>
<designable name="rOV-XS-bNW"/>
</designables>
<resources>
<image name="safari" catalog="system" width="128" height="123"/>
<image name="safari.fill" catalog="system" width="128" height="123"/>
<namedColor name="deleteBackgroundColor">
<color red="1" green="0.23100003600120544" blue="0.18799999356269836" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</namedColor>
<namedColor name="primaryAccentColor">
<color red="0.031372549019607843" green="0.41568627450980394" blue="0.93333333333333335" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</namedColor>
<namedColor name="secondaryAccentColor">
<color red="0.031372549019607843" green="0.41568627450980394" blue="0.93333333333333335" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</namedColor>
<systemColor name="systemBackgroundColor">
<color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</systemColor>
<systemColor name="systemRedColor">
<color red="1" green="0.23137254901960785" blue="0.18823529411764706" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</systemColor>
</resources>
</document>

View File

@@ -0,0 +1,23 @@
/*
Inspector.strings
NetNewsWire
Created by Stuart Breckenridge on 15/12/2022.
Copyright © 2022 Ranchero Software. All rights reserved.
*/
/* Account Inspector */
"ACCOUNT_NAME_FIELD" = "Account Name";
"ACTIVE" = "Active";
"CLOUDKIT_LIMITATIONS_TITLE" = "[iCloud Syncing Limitations & Solutions](https://netnewswire.com/help/iCloud)";
"REMOVE_ACCOUNT_TITLE" = "Remove Account";
"REMOVE_ACCOUNT_BUTTON_TITLE" = "Remove Account";
"REMOVE_FEEDLY_MESSAGE" = "Are you sure you want to remove this account? NetNewsWire will no longer be able to access articles and feeds unless the account is added again.";
"REMOVE_ACCOUNT_MESSAGE" = "Are you sure you want to remove this account? This cannot be undone.";
"REMOVE_ACCOUNT_TITLE" = "Remove Account";
"NOTIFY_ABOUT_NEW_ARTICLES" = "Notify About New Articles";
"ALWAYS_SHOW_READER_VIEW" = "Always Show Reader View";
"HOME_PAGE" = "Home Page";
"FEED_URL" = "Feed URL";

View File

@@ -1,34 +0,0 @@
//
// InspectorIconHeaderView.swift
// NetNewsWire-iOS
//
// Created by Maurice Parker on 11/6/19.
// Copyright © 2019 Ranchero Software. All rights reserved.
//
import UIKit
class InspectorIconHeaderView: UITableViewHeaderFooterView {
var iconView = IconView()
override init(reuseIdentifier: String?) {
super.init(reuseIdentifier: reuseIdentifier)
commonInit()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
commonInit()
}
func commonInit() {
addSubview(iconView)
}
override func layoutSubviews() {
let x = (bounds.width - 48.0) / 2
let y = (bounds.height - 48.0) / 2
iconView.frame = CGRect(x: x, y: y, width: 48.0, height: 48.0)
}
}

View File

@@ -0,0 +1,105 @@
//
// AccountInspectorView.swift
// NetNewsWire-iOS
//
// Created by Stuart Breckenridge on 15/12/2022.
// Copyright © 2022 Ranchero Software. All rights reserved.
//
import SwiftUI
import SafariServices
import Account
struct AccountInspectorView: View {
@Environment(\.dismiss) var dismiss
@State private var showRemoveAccountAlert: Bool = false
var account: Account
var body: some View {
Form {
Section(header: accountHeaderView){}
TextField(text: Binding(
get: { account.name ?? account.defaultName },
set: { account.name = $0 }),
prompt: Text(account.defaultName)) {
Text("ACCOUNT_NAME", tableName: "Inspector")
}
Toggle(isOn: Binding(get: {
account.isActive
}, set: { account.isActive = $0 })) {
Text("ACTIVE", tableName: "Inspector")
}
if account != AccountManager.shared.defaultAccount {
Section {
Button(role: .destructive) {
showRemoveAccountAlert = true
} label: {
HStack {
Spacer()
Text("REMOVE_ACCOUNT_BUTTON_TITLE", tableName: "Inspector")
Spacer()
}
}
.confirmationDialog(Text("REMOVE_ACCOUNT_TITLE", tableName: "Inspector"), isPresented: $showRemoveAccountAlert, titleVisibility: .visible) {
Button(role: .destructive) {
AccountManager.shared.deleteAccount(account)
dismiss()
} label: {
Text("REMOVE_ACCOUNT_BUTTON_TITLE", tableName: "Inspector")
}
Button(role: .cancel) {
//
} label: {
Text("CANCEL_BUTTON_TITLE", tableName: "Buttons")
}
} message: {
if account.type == .feedly {
Text("REMOVE_FEEDLY_MESSAGE", tableName: "Inspector")
} else {
Text("REMOVE_ACCOUNT_MESSAGE", tableName: "Inspector")
}
}
}
}
if account.type == .cloudKit {
Section(footer: cloudKitLimitations){}
}
}
.navigationBarTitleDisplayMode(.inline)
.navigationTitle(account.nameForDisplay)
.tint(Color(uiColor: AppAssets.primaryAccentColor))
.edgesIgnoringSafeArea(.bottom) // Fix to make sure view is not offset from the top when presented
}
var accountHeaderView: some View {
HStack {
Spacer()
Image(uiImage: account.smallIcon!.image)
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: 30, height: 30)
Spacer()
}
}
var cloudKitLimitations: some View {
HStack {
Spacer()
Text("CLOUDKIT_LIMITATIONS_TITLE", tableName: "Inspector")
Spacer()
}
}
}
struct AccountInspectorView_Previews: PreviewProvider {
static var previews: some View {
AccountInspectorView(account: AccountManager.shared.defaultAccount)
}
}

View File

@@ -0,0 +1,72 @@
//
// ExtensionInspectorView.swift
// NetNewsWire-iOS
//
// Created by Stuart Breckenridge on 15/12/2022.
// Copyright © 2022 Ranchero Software. All rights reserved.
//
import SwiftUI
struct ExtensionInspectorView: View {
@State private var showDeactivateConfirmation: Bool = false
var extensionPoint: ExtensionPoint?
var body: some View {
Form {
Section(header: extensionHeader) {}
Section(footer: Text(extensionPoint?.description.string ?? ""), content: {
//
})
HStack {
Spacer()
Button(role: .destructive) {
showDeactivateConfirmation = true
} label: {
Text("DEACTIVATE_EXTENSION_TITLE", tableName: "Settings")
}
.confirmationDialog(Text("DEACTIVATE_EXTENSION_TITLE", tableName: "Settings") , isPresented: $showDeactivateConfirmation, titleVisibility: .visible) {
Button(role: .destructive) {
ExtensionPointManager.shared.deactivateExtensionPoint(extensionPoint!.extensionPointID)
} label: {
Text("DEACTIVATE", tableName: "Settings")
}
Button(role: .cancel) {
//
} label: {
Text("CANCEL_BUTTON_TITLE", tableName: "Buttons")
}
} message: {
Text("DEACTIVATE_EXTENSION \(extensionPoint?.title ?? "")", tableName: "Settings")
}
Spacer()
}
}
.navigationTitle(Text(extensionPoint?.title ?? ""))
.edgesIgnoringSafeArea(.bottom)
}
var extensionHeader: some View {
HStack {
Spacer()
Image(uiImage: extensionPoint!.image)
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: 30, height: 30)
Spacer()
}
}
}
struct ExtensionInspectorView_Previews: PreviewProvider {
static var previews: some View {
ExtensionInspectorView()
}
}

View File

@@ -0,0 +1,85 @@
//
// WebFeedInspectorView.swift
// NetNewsWire-iOS
//
// Created by Stuart Breckenridge on 15/12/2022.
// Copyright © 2022 Ranchero Software. All rights reserved.
//
import SwiftUI
import Account
import SafariServices
import UserNotifications
struct WebFeedInspectorView: View {
var webFeed: WebFeed!
@State private var showHomePage: Bool = false
var body: some View {
Form {
Section(header: webFeedHeaderView) {}
Section {
TextField(webFeed.nameForDisplay,
text: Binding(
get: { webFeed.name ?? webFeed.nameForDisplay },
set: { webFeed.name = $0 }),
prompt: nil)
Toggle(isOn: Binding(get: { webFeed.isNotifyAboutNewArticles ?? false }, set: { webFeed.isNotifyAboutNewArticles = $0 })) {
Text("NOTIFY_ABOUT_NEW_ARTICLES", tableName: "Inspector")
}
if webFeed.isFeedProvider == false {
Toggle(isOn: Binding(
get: { webFeed.isArticleExtractorAlwaysOn ?? false },
set: { webFeed.isArticleExtractorAlwaysOn = $0 })) {
Text("ALWAYS_SHOW_READER_VIEW", tableName: "Inspector")
}
}
}
Section(header: Text("HOME_PAGE", tableName: "Inspector")) {
HStack {
Text(webFeed.homePageURL?.decodedURLString ?? "")
Spacer()
Image(uiImage: AppAssets.safariImage)
.renderingMode(.template)
.foregroundColor(Color(uiColor: AppAssets.primaryAccentColor))
}
.onTapGesture {
if webFeed.homePageURL != nil { showHomePage = true }
}
}
Section(header: Text("FEED_URL", tableName: "Inspector")) {
Text(webFeed.url.description)
}
}
.navigationBarTitleDisplayMode(.inline)
.navigationTitle(webFeed.nameForDisplay)
.sheet(isPresented: $showHomePage, onDismiss: nil) {
//SwiftUISafariView(url: URL(string: webFeed.homePageURL!)!)
SafariView(url: URL(string: webFeed.homePageURL!)!)
}
}
var webFeedHeaderView: some View {
HStack {
Spacer()
Image(uiImage: webFeed.smallIcon!.image)
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: 30, height: 30)
Spacer()
}
}
}
struct WebFeedInspectorView_Previews: PreviewProvider {
static var previews: some View {
WebFeedInspectorView()
}
}

View File

@@ -1,233 +0,0 @@
//
// WebFeedInspectorViewController.swift
// NetNewsWire-iOS
//
// Created by Maurice Parker on 11/6/19.
// Copyright © 2019 Ranchero Software. All rights reserved.
//
import UIKit
import Account
import SafariServices
import UserNotifications
class WebFeedInspectorViewController: UITableViewController {
static let preferredContentSizeForFormSheetDisplay = CGSize(width: 460.0, height: 500.0)
var webFeed: WebFeed!
@IBOutlet weak var nameTextField: UITextField!
@IBOutlet weak var notifyAboutNewArticlesSwitch: UISwitch!
@IBOutlet weak var alwaysShowReaderViewSwitch: UISwitch!
@IBOutlet weak var homePageLabel: InteractiveLabel!
@IBOutlet weak var feedURLLabel: InteractiveLabel!
private var headerView: InspectorIconHeaderView?
private var iconImage: IconImage? {
return IconImageCache.shared.imageForFeed(webFeed)
}
private let homePageIndexPath = IndexPath(row: 0, section: 1)
private var shouldHideHomePageSection: Bool {
return webFeed.homePageURL == nil
}
private var userNotificationSettings: UNNotificationSettings?
override func viewDidLoad() {
tableView.register(InspectorIconHeaderView.self, forHeaderFooterViewReuseIdentifier: "SectionHeader")
navigationItem.title = webFeed.nameForDisplay
nameTextField.text = webFeed.nameForDisplay
notifyAboutNewArticlesSwitch.setOn(webFeed.isNotifyAboutNewArticles ?? false, animated: false)
if webFeed.isFeedProvider {
alwaysShowReaderViewSwitch.isOn = false
alwaysShowReaderViewSwitch.isEnabled = false
} else {
alwaysShowReaderViewSwitch.setOn(webFeed.isArticleExtractorAlwaysOn ?? false, animated: false)
}
homePageLabel.text = webFeed.homePageURL?.decodedURLString
feedURLLabel.text = webFeed.url.decodedURLString
NotificationCenter.default.addObserver(self, selector: #selector(webFeedIconDidBecomeAvailable(_:)), name: .WebFeedIconDidBecomeAvailable, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(updateNotificationSettings), name: UIApplication.willEnterForegroundNotification, object: nil)
}
override func viewDidAppear(_ animated: Bool) {
updateNotificationSettings()
}
override func viewDidDisappear(_ animated: Bool) {
if nameTextField.text != webFeed.nameForDisplay {
let nameText = nameTextField.text ?? ""
let newName = nameText.isEmpty ? (webFeed.name ?? NSLocalizedString("Untitled", comment: "Feed name")) : nameText
webFeed.rename(to: newName) { _ in }
}
}
// MARK: Notifications
@objc func webFeedIconDidBecomeAvailable(_ notification: Notification) {
headerView?.iconView.iconImage = iconImage
}
@IBAction func notifyAboutNewArticlesChanged(_ sender: Any) {
guard let settings = userNotificationSettings else {
notifyAboutNewArticlesSwitch.isOn = !notifyAboutNewArticlesSwitch.isOn
return
}
if settings.authorizationStatus == .denied {
notifyAboutNewArticlesSwitch.isOn = !notifyAboutNewArticlesSwitch.isOn
present(notificationUpdateErrorAlert(), animated: true, completion: nil)
} else if settings.authorizationStatus == .authorized {
webFeed.isNotifyAboutNewArticles = notifyAboutNewArticlesSwitch.isOn
} else {
UNUserNotificationCenter.current().requestAuthorization(options:[.badge, .sound, .alert]) { (granted, error) in
self.updateNotificationSettings()
if granted {
DispatchQueue.main.async {
self.webFeed.isNotifyAboutNewArticles = self.notifyAboutNewArticlesSwitch.isOn
UIApplication.shared.registerForRemoteNotifications()
}
} else {
DispatchQueue.main.async {
self.notifyAboutNewArticlesSwitch.isOn = !self.notifyAboutNewArticlesSwitch.isOn
}
}
}
}
}
@IBAction func alwaysShowReaderViewChanged(_ sender: Any) {
webFeed.isArticleExtractorAlwaysOn = alwaysShowReaderViewSwitch.isOn
}
@IBAction func done(_ sender: Any) {
dismiss(animated: true)
}
/// Returns a new indexPath, taking into consideration any
/// conditions that may require the tableView to be
/// displayed differently than what is setup in the storyboard.
private func shift(_ indexPath: IndexPath) -> IndexPath {
return IndexPath(row: indexPath.row, section: shift(indexPath.section))
}
/// Returns a new section, taking into consideration any
/// conditions that may require the tableView to be
/// displayed differently than what is setup in the storyboard.
private func shift(_ section: Int) -> Int {
if section >= homePageIndexPath.section && shouldHideHomePageSection {
return section + 1
}
return section
}
}
// MARK: Table View
extension WebFeedInspectorViewController {
override func numberOfSections(in tableView: UITableView) -> Int {
let numberOfSections = super.numberOfSections(in: tableView)
return shouldHideHomePageSection ? numberOfSections - 1 : numberOfSections
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return super.tableView(tableView, numberOfRowsInSection: shift(section))
}
override func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return section == 0 ? ImageHeaderView.rowHeight : super.tableView(tableView, heightForHeaderInSection: shift(section))
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = super.tableView(tableView, cellForRowAt: shift(indexPath))
if indexPath.section == 0 && indexPath.row == 1 {
guard let label = cell.contentView.subviews.filter({ $0.isKind(of: UILabel.self) })[0] as? UILabel else {
return cell
}
label.numberOfLines = 2
label.text = webFeed.notificationDisplayName.capitalized
}
return cell
}
override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
super.tableView(tableView, titleForHeaderInSection: shift(section))
}
override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
if shift(section) == 0 {
headerView = tableView.dequeueReusableHeaderFooterView(withIdentifier: "SectionHeader") as? InspectorIconHeaderView
headerView?.iconView.iconImage = iconImage
return headerView
} else {
return super.tableView(tableView, viewForHeaderInSection: shift(section))
}
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if shift(indexPath) == homePageIndexPath,
let homePageUrlString = webFeed.homePageURL,
let homePageUrl = URL(string: homePageUrlString) {
let safari = SFSafariViewController(url: homePageUrl)
safari.modalPresentationStyle = .pageSheet
present(safari, animated: true) {
tableView.deselectRow(at: indexPath, animated: true)
}
}
}
}
// MARK: UITextFieldDelegate
extension WebFeedInspectorViewController: UITextFieldDelegate {
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
textField.resignFirstResponder()
return true
}
}
// MARK: UNUserNotificationCenter
extension WebFeedInspectorViewController {
@objc
func updateNotificationSettings() {
UNUserNotificationCenter.current().getNotificationSettings { (settings) in
DispatchQueue.main.async {
self.userNotificationSettings = settings
if settings.authorizationStatus == .authorized {
UIApplication.shared.registerForRemoteNotifications()
}
}
}
}
func notificationUpdateErrorAlert() -> UIAlertController {
let alert = UIAlertController(title: NSLocalizedString("Enable Notifications", comment: "Notifications"),
message: NSLocalizedString("Notifications need to be enabled in the Settings app.", comment: "Notifications need to be enabled in the Settings app."), preferredStyle: .alert)
let openSettings = UIAlertAction(title: NSLocalizedString("Open Settings", comment: "Open Settings"), style: .default) { (action) in
UIApplication.shared.open(URL(string: UIApplication.openSettingsURLString)!, options: [UIApplication.OpenExternalURLOptionsKey.universalLinksOnly : false], completionHandler: nil)
}
let dismiss = UIAlertAction(title: NSLocalizedString("Dismiss", comment: "Dismiss"), style: .cancel, handler: nil)
alert.addAction(openSettings)
alert.addAction(dismiss)
alert.preferredAction = openSettings
return alert
}
}

View File

@@ -1,16 +1,6 @@
{
"images" : [
{
"filename" : "feedbin-logo-filled-1.pdf",
"idiom" : "universal"
},
{
"appearances" : [
{
"appearance" : "luminosity",
"value" : "dark"
}
],
"filename" : "feedbin-logo-filled.pdf",
"idiom" : "universal"
}

View File

@@ -1167,14 +1167,17 @@ class SceneCoordinator: NSObject, UndoableCommandRunner, Logging {
}
func showAccountInspector(for account: Account) {
let accountInspectorNavController =
UIStoryboard.inspector.instantiateViewController(identifier: "AccountInspectorNavigationViewController") as! UINavigationController
let accountInspectorController = accountInspectorNavController.topViewController as! AccountInspectorViewController
accountInspectorNavController.modalPresentationStyle = .formSheet
accountInspectorNavController.preferredContentSize = AccountInspectorViewController.preferredContentSizeForFormSheetDisplay
accountInspectorController.isModal = true
accountInspectorController.account = account
rootSplitViewController.present(accountInspectorNavController, animated: true)
let hosting = UIHostingController(rootView: InjectedNavigationView(injectedView: AccountInspectorView(account: account)))
rootSplitViewController.present(hosting, animated: true, completion: nil)
// let accountInspectorNavController =
// UIStoryboard.inspector.instantiateViewController(identifier: "AccountInspectorNavigationViewController") as! UINavigationController
// let accountInspectorController = accountInspectorNavController.topViewController as! AccountInspectorViewController
// accountInspectorNavController.modalPresentationStyle = .formSheet
// accountInspectorNavController.preferredContentSize = AccountInspectorViewController.preferredContentSizeForFormSheetDisplay
// accountInspectorController.isModal = true
// accountInspectorController.account = account
// rootSplitViewController.present(accountInspectorNavController, animated: true)
}
func showFeedInspector() {
@@ -1187,13 +1190,10 @@ class SceneCoordinator: NSObject, UndoableCommandRunner, Logging {
}
func showFeedInspector(for feed: WebFeed) {
let feedInspectorNavController =
UIStoryboard.inspector.instantiateViewController(identifier: "FeedInspectorNavigationViewController") as! UINavigationController
let feedInspectorController = feedInspectorNavController.topViewController as! WebFeedInspectorViewController
feedInspectorNavController.modalPresentationStyle = .formSheet
feedInspectorNavController.preferredContentSize = WebFeedInspectorViewController.preferredContentSizeForFormSheetDisplay
feedInspectorController.webFeed = feed
rootSplitViewController.present(feedInspectorNavController, animated: true)
let hosting = UIHostingController(rootView: InjectedNavigationView(injectedView: WebFeedInspectorView(webFeed: feed)))
rootSplitViewController.present(hosting, animated: true)
}
func showAddWebFeed(initialFeed: String? = nil, initialFeedName: String? = nil) {

View File

@@ -46,7 +46,6 @@
"OPEN_LINKS_IN_APP" = "Open Links in NetNewsWire";
/* Account Management */
"ADD_ACCOUNT" = "Add Account";
"NO_INACTIVE_ACCOUNT_FOOTER" = "There are no inactive accounts.";
"ACCOUNT_REMOVE %@" = "Are you sure you want to remove “%@”?";
@@ -56,21 +55,18 @@
"INACTIVE_ACCOUNTS_HEADER" = "Inactive Accounts";
/* Extension Management */
"DEACTIVATE" = "Deactivate";
"DEACTIVATE_EXTENSION_TITLE" = "Deactivate Extension";
"DEACTIVATE_EXTENSION %@" = "Deactivate “%@”";
"DEACTIVATE_EXTENSION %@" = "Are you sure you want to deactivate the “%@” extension?";
"ACTIVE_EXTENSIONS" = "Active Extensions";
"FEED_PROVIDER_HEADER" = "Feed Provider";
"FEED_PROVIDER_FOOTER" = "Feed Providers allow you to subscribe to some pages as if they were RSS Feeds.";
"ADD_EXTENSIONS_TITLE" = "Add Extension";
/* New Article Notifications */
"NEW_ARTICLE_NOTIFICATIONS_TITLE" = "New Article Notifications";
/* About */
"ABOUT_TITLE" = "About";
"PRIMARY_CONTRIBUTORS" = "Primary Contributors";
"ADDITIONAL_CONTRIBUTORS" = "Additional Contributors";
@@ -89,7 +85,6 @@
/* Alerts */
"IMPORT_OPML_CONFIRMATION" = "Choose an account to receive the imported feeds and folders";
"IMPORT_OPML_SUCCESS_TITLE" = "Imported Successfully";
"IMPORT_OPML_SUCCESS_MESSAGE %@" = "Subscriptions have been imported to your %@ account.";
@@ -98,5 +93,3 @@
"EXPORT_OPML_SUCCESS_MESSAGE" = "Your OPML file has been successfully exported.";
"ERROR_TITLE" = "Error";
"REMOVE" = "Remove";
"CANCEL" = "Cancel";
"DONE" = "Done";

View File

@@ -73,7 +73,7 @@ struct AccountsManagementView: View {
Button(role: .cancel) {
accountToRemove = nil
} label: {
Text("CANCEL", tableName: "Settings")
Text("CANCEL_BUTTON_TITLE", tableName: "Buttons")
}
} message: {
switch accountToRemove {
@@ -91,14 +91,15 @@ struct AccountsManagementView: View {
}
func refreshAccounts() {
sortedActiveAccounts = []
sortedInactiveAccounts = []
sortedActiveAccounts = AccountManager.shared.sortedActiveAccounts
sortedInactiveAccounts = AccountManager.shared.sortedAccounts.filter({ $0.isActive == false })
}
func accountRow(_ account: Account, showRemoveAccountAlert: Binding<Bool>, accountToRemove: Binding<Account?>) -> some View {
NavigationLink {
AccountInspectorWrapper(account: account)
.edgesIgnoringSafeArea(.all)
AccountInspectorView(account: account)
} label: {
Image(uiImage: account.smallIcon!.image)
.resizable()
@@ -112,7 +113,7 @@ struct AccountsManagementView: View {
showRemoveAccountAlert.wrappedValue = true
} label: {
Label {
Text("REMOVE_ACCOUNT", tableName: "Settings")
Text("REMOVE_ACCOUNT_TITLE", tableName: "Settings")
} icon: {
Image(systemName: "trash")
}

View File

@@ -76,11 +76,11 @@ struct AddAccountView: View {
.navigationBarTitleDisplayMode(.inline)
.listItemTint(.primary)
.toolbar {
ToolbarItem(placement: .navigationBarTrailing) {
ToolbarItem(placement: .navigationBarLeading) {
Button(role: .cancel) {
dismiss()
} label: {
Text("DONE", tableName: "Settings")
Text("CANCEL_BUTTON_TITLE", tableName: "Buttons")
}
}
}

View File

@@ -37,11 +37,11 @@ struct AddExtensionListView: View {
.navigationBarTitleDisplayMode(.inline)
.navigationTitle(Text("ADD_EXTENSIONS_TITLE", tableName: "Settings"))
.toolbar {
ToolbarItem(placement: .navigationBarTrailing) {
ToolbarItem(placement: .navigationBarLeading) {
Button(role: .cancel) {
dismiss()
} label: {
Text("DONE", tableName: "Settings")
Text("CANCEL_BUTTON_TITLE", tableName: "Buttons")
}
}
}

View File

@@ -45,7 +45,7 @@ struct ExtensionsManagementView: View {
Button(role: .cancel) {
extensionToDeactivate = nil
} label: {
Text("DISMISS", tableName: "Settings")
Text("CANCEL_BUTTON_TITLE", tableName: "Buttons")
}
} message: {
@@ -62,9 +62,7 @@ struct ExtensionsManagementView: View {
ForEach(0..<ExtensionPointManager.shared.activeExtensionPoints.count, id: \.self) { i in
let point = Array(ExtensionPointManager.shared.activeExtensionPoints)[i]
NavigationLink {
ExtensionPointInspectorWrapper(extensionPoint: point.value)
.navigationBarTitle(Text(point.value.title))
.edgesIgnoringSafeArea(.all)
ExtensionInspectorView(extensionPoint: point.value)
} label: {
Image(uiImage: point.value.image)
.resizable()
@@ -77,7 +75,7 @@ struct ExtensionsManagementView: View {
showDeactivateAlert = true
} label: {
Text("DEACTIVATE", tableName: "Settings")
Image(systemName: "poweroff")
Image(systemName: "minus.circle")
}.tint(.red)
}
}

View File

@@ -0,0 +1,30 @@
//
// InjectedNavigationView.swift
// NetNewsWire-iOS
//
// Created by Stuart Breckenridge on 15/12/2022.
// Copyright © 2022 Ranchero Software. All rights reserved.
//
import SwiftUI
struct InjectedNavigationView: View {
@Environment(\.dismiss) var dismiss
var injectedView: any View
var body: some View {
NavigationView {
AnyView(injectedView)
.toolbar {
ToolbarItem(placement: .navigationBarLeading) {
Button(role: .cancel) {
dismiss()
} label: {
Text("DONE_BUTTON_TITLE", tableName: "Buttons")
}
}
}
}.navigationViewStyle(.stack)
}
}