Convert remainder of iOS to using folders instead of groups.

This commit is contained in:
Brent Simmons
2024-12-24 18:26:09 -08:00
parent aec8122047
commit fafb5f2b5a
5 changed files with 34 additions and 794 deletions

View File

@@ -3,7 +3,7 @@
archiveVersion = 1;
classes = {
};
objectVersion = 70;
objectVersion = 76;
objects = {
/* Begin PBXBuildFile section */
@@ -86,9 +86,6 @@
511D43D0231FA62500FB1562 /* TimelineKeyboardShortcuts.plist in Resources */ = {isa = PBXBuildFile; fileRef = 845479871FEB77C000AD8B59 /* TimelineKeyboardShortcuts.plist */; };
511D43D1231FA62800FB1562 /* SidebarKeyboardShortcuts.plist in Resources */ = {isa = PBXBuildFile; fileRef = 844B5B681FEA20DF00C7C76A /* SidebarKeyboardShortcuts.plist */; };
511D43D2231FA62C00FB1562 /* GlobalKeyboardShortcuts.plist in Resources */ = {isa = PBXBuildFile; fileRef = 844B5B641FEA11F200C7C76A /* GlobalKeyboardShortcuts.plist */; };
511D43EF231FBDE900FB1562 /* LaunchScreenPad.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 511D43ED231FBDE800FB1562 /* LaunchScreenPad.storyboard */; };
511D4419231FC02D00FB1562 /* KeyboardManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 511D4410231FC02D00FB1562 /* KeyboardManager.swift */; };
5126EE97226CB48A00C22AFC /* SceneCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5126EE96226CB48A00C22AFC /* SceneCoordinator.swift */; };
5127B238222B4849006D641D /* DetailKeyboardDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5127B236222B4849006D641D /* DetailKeyboardDelegate.swift */; };
5127B23A222B4849006D641D /* DetailKeyboardShortcuts.plist in Resources */ = {isa = PBXBuildFile; fileRef = 5127B237222B4849006D641D /* DetailKeyboardShortcuts.plist */; };
512E08E62268800D00BDCFDD /* FolderTreeControllerDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 849A97A11ED9F180007D329B /* FolderTreeControllerDelegate.swift */; };
@@ -142,7 +139,6 @@
5144EA40227A37EC00D19003 /* ImportOPMLWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5144EA3E227A37EC00D19003 /* ImportOPMLWindowController.swift */; };
5144EA51227B8E4500D19003 /* AccountsFeedbinWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5144EA4F227B8E4500D19003 /* AccountsFeedbinWindowController.swift */; };
5144EA52227B8E4500D19003 /* AccountsFeedbin.xib in Resources */ = {isa = PBXBuildFile; fileRef = 5144EA50227B8E4500D19003 /* AccountsFeedbin.xib */; };
514B7C8323205EFB00BAC947 /* RootSplitViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 514B7C8223205EFB00BAC947 /* RootSplitViewController.swift */; };
514C16CE24D2E63F009A3AFA /* Account in Frameworks */ = {isa = PBXBuildFile; productRef = 514C16CD24D2E63F009A3AFA /* Account */; };
514C16DE24D2EF15009A3AFA /* RSTree in Frameworks */ = {isa = PBXBuildFile; productRef = 514C16DD24D2EF15009A3AFA /* RSTree */; };
514C16DF24D2EF15009A3AFA /* RSTree in Embed Frameworks */ = {isa = PBXBuildFile; productRef = 514C16DD24D2EF15009A3AFA /* RSTree */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; };
@@ -167,7 +163,6 @@
51938DF3231AFC660055A1A0 /* SearchTimelineFeedDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51938DF1231AFC660055A1A0 /* SearchTimelineFeedDelegate.swift */; };
519B8D332143397200FA689C /* SharingServiceDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 519B8D322143397200FA689C /* SharingServiceDelegate.swift */; };
519CA8E525841DB700EB079A /* CrashReporter in Frameworks */ = {isa = PBXBuildFile; productRef = 519CA8E425841DB700EB079A /* CrashReporter */; };
519E743D22C663F900A78E47 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 519E743422C663F900A78E47 /* SceneDelegate.swift */; };
51A052CE244FB9D7006C2024 /* AddFeedWIndowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51A052CD244FB9D6006C2024 /* AddFeedWIndowController.swift */; };
51A66685238075AE00CB272D /* AddWebFeedDefaultContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51A66684238075AE00CB272D /* AddWebFeedDefaultContainer.swift */; };
51A737AE24DB19730015FA66 /* RSCore in Frameworks */ = {isa = PBXBuildFile; productRef = 51A737AD24DB19730015FA66 /* RSCore */; };
@@ -176,8 +171,6 @@
51A737C024DB197F0015FA66 /* RSDatabase in Embed Frameworks */ = {isa = PBXBuildFile; productRef = 51A737BE24DB197F0015FA66 /* RSDatabase */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; };
51A737C824DB19CC0015FA66 /* RSParser in Frameworks */ = {isa = PBXBuildFile; productRef = 51A737C724DB19CC0015FA66 /* RSParser */; };
51A737C924DB19CC0015FA66 /* RSParser in Embed Frameworks */ = {isa = PBXBuildFile; productRef = 51A737C724DB19CC0015FA66 /* RSParser */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; };
51A9A5E12380C4FE0033AADF /* AppDefaults.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51C45255226507D200C03939 /* AppDefaults.swift */; };
51A9A5ED2380D6000033AADF /* AppAssets.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51C45254226507D200C03939 /* AppAssets.swift */; };
51A9A5EF2380D63B0033AADF /* IconImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 516AE9DE2372269A007DEEAA /* IconImage.swift */; };
51A9A5F32380DE530033AADF /* AddWebFeedDefaultContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51A66684238075AE00CB272D /* AddWebFeedDefaultContainer.swift */; };
51B5C87723F22B8200032075 /* ExtensionContainers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51B5C87623F22B8200032075 /* ExtensionContainers.swift */; };
@@ -193,8 +186,6 @@
51B5C8E523F4BBFA00032075 /* ExtensionContainersFile.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51B5C87C23F2346200032075 /* ExtensionContainersFile.swift */; };
51B5C8E623F4BBFA00032075 /* ExtensionFeedAddRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51B5C87A23F2317700032075 /* ExtensionFeedAddRequest.swift */; };
51B5C8E723F4BBFA00032075 /* ExtensionFeedAddRequestFile.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51B5C8BF23F3866C00032075 /* ExtensionFeedAddRequestFile.swift */; };
51B62E68233186730085F949 /* IconView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51B62E67233186730085F949 /* IconView.swift */; };
51BB7C272335A8E5008E8144 /* ArticleActivityItemSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51BB7C262335A8E5008E8144 /* ArticleActivityItemSource.swift */; };
51BC2F3824D3439A00E90810 /* Account in Frameworks */ = {isa = PBXBuildFile; productRef = 51BC2F3724D3439A00E90810 /* Account */; };
51BC2F4824D3439E00E90810 /* RSTree in Frameworks */ = {isa = PBXBuildFile; productRef = 51BC2F4724D3439E00E90810 /* RSTree */; };
51BC2F4924D3439E00E90810 /* RSTree in Embed Frameworks */ = {isa = PBXBuildFile; productRef = 51BC2F4724D3439E00E90810 /* RSTree */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; };
@@ -203,8 +194,6 @@
51BC4AFF247277E0000A6ED8 /* URL-Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51BC4ADD247277DF000A6ED8 /* URL-Extensions.swift */; };
51BC4B01247277E0000A6ED8 /* URL-Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51BC4ADD247277DF000A6ED8 /* URL-Extensions.swift */; };
51C03081257D815A00609262 /* UnifiedWindow.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 51C0307F257D815A00609262 /* UnifiedWindow.storyboard */; };
51C45258226508CF00C03939 /* AppAssets.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51C45254226507D200C03939 /* AppAssets.swift */; };
51C45259226508D300C03939 /* AppDefaults.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51C45255226507D200C03939 /* AppDefaults.swift */; };
51C4528E2265099C00C03939 /* SmartFeedsController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84CC88171FE59CBF00644329 /* SmartFeedsController.swift */; };
51C4528F226509BD00C03939 /* UnreadFeed.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84F2D5391FC2308B00998D64 /* UnreadFeed.swift */; };
51C45290226509C100C03939 /* PseudoFeed.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84F2D5351FC22FCB00998D64 /* PseudoFeed.swift */; };
@@ -248,7 +237,6 @@
51DEE81826FBFF84006DAA56 /* Promenade.nnwtheme in Resources */ = {isa = PBXBuildFile; fileRef = 51DEE81726FBFF84006DAA56 /* Promenade.nnwtheme */; };
51DEE81A26FBFF84006DAA56 /* Promenade.nnwtheme in Resources */ = {isa = PBXBuildFile; fileRef = 51DEE81726FBFF84006DAA56 /* Promenade.nnwtheme */; };
51E3EB33229AB02C00645299 /* ErrorHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51E3EB32229AB02C00645299 /* ErrorHandler.swift */; };
51E3EB3D229AB08300645299 /* ErrorHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51E3EB3C229AB08300645299 /* ErrorHandler.swift */; };
51E4DAED2425F6940091EB5B /* CloudKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 51E4DAEC2425F6940091EB5B /* CloudKit.framework */; };
51E4DB082425F9EB0091EB5B /* CloudKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 51E4DB072425F9EB0091EB5B /* CloudKit.framework */; };
51E595A5228CC36500FCC42B /* ArticleStatusSyncTimer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51E595A4228CC36500FCC42B /* ArticleStatusSyncTimer.swift */; };
@@ -282,7 +270,6 @@
8405DDA522168C62008CE1BF /* TimelineContainerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8405DDA422168C62008CE1BF /* TimelineContainerViewController.swift */; };
840958632201629A002C1579 /* Subscribe to Feed.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = 6581C73320CED60000F4AD34 /* Subscribe to Feed.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
840BEE4121D70E64009BBAFA /* CrashReportWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 840BEE4021D70E64009BBAFA /* CrashReportWindowController.swift */; };
840D617F2029031C009BC708 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 840D617E2029031C009BC708 /* AppDelegate.swift */; };
8413C1382D050A1E002E3D0F /* UniformTypeIdentifiers+Extras.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8413C1372D050A1E002E3D0F /* UniformTypeIdentifiers+Extras.swift */; };
8413C1392D050A1E002E3D0F /* UniformTypeIdentifiers+Extras.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8413C1372D050A1E002E3D0F /* UniformTypeIdentifiers+Extras.swift */; };
84162A152038C12C00035290 /* MarkCommandValidationStatus.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84162A142038C12C00035290 /* MarkCommandValidationStatus.swift */; };
@@ -389,8 +376,6 @@
84C9FC8C22629E8F00D921D6 /* KeyboardShortcuts.html in Resources */ = {isa = PBXBuildFile; fileRef = 84C9FC8722629E8F00D921D6 /* KeyboardShortcuts.html */; };
84C9FC8E22629E8F00D921D6 /* Credits.rtf in Resources */ = {isa = PBXBuildFile; fileRef = 84C9FC8922629E8F00D921D6 /* Credits.rtf */; };
84C9FC8F22629E8F00D921D6 /* NetNewsWire.sdef in Resources */ = {isa = PBXBuildFile; fileRef = 84C9FC8A22629E8F00D921D6 /* NetNewsWire.sdef */; };
84C9FCA12262A1B300D921D6 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 84C9FC9F2262A1B300D921D6 /* Main.storyboard */; };
84C9FCA42262A1B800D921D6 /* LaunchScreenPhone.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 84C9FCA22262A1B800D921D6 /* LaunchScreenPhone.storyboard */; };
84CAFCA422BC8C08007694F0 /* FetchRequestQueue.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84CAFCA322BC8C08007694F0 /* FetchRequestQueue.swift */; };
84CAFCA522BC8C08007694F0 /* FetchRequestQueue.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84CAFCA322BC8C08007694F0 /* FetchRequestQueue.swift */; };
84CAFCAF22BC8C35007694F0 /* FetchRequestOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84CAFCAE22BC8C35007694F0 /* FetchRequestOperation.swift */; };
@@ -434,7 +419,6 @@
B2B80778239C4C7000F191E0 /* RSImage-AppIcons.swift in Sources */ = {isa = PBXBuildFile; fileRef = B2B8075D239C49D300F191E0 /* RSImage-AppIcons.swift */; };
B528F81E23333C7E00E735DD /* page.html in Resources */ = {isa = PBXBuildFile; fileRef = B528F81D23333C7E00E735DD /* page.html */; };
BDCB516724282C8A00102A80 /* AccountsNewsBlur.xib in Resources */ = {isa = PBXBuildFile; fileRef = BDCB514D24282C8A00102A80 /* AccountsNewsBlur.xib */; };
C5A6ED5223C9AF4300AB6BE2 /* TitleActivityItemSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = C5A6ED5123C9AF4300AB6BE2 /* TitleActivityItemSource.swift */; };
D553738B20186C20006D8857 /* Article+Scriptability.swift in Sources */ = {isa = PBXBuildFile; fileRef = D553737C20186C1F006D8857 /* Article+Scriptability.swift */; };
D57BE6E0204CD35F00D11AAC /* NSScriptCommand+NetNewsWire.swift in Sources */ = {isa = PBXBuildFile; fileRef = D57BE6DF204CD35F00D11AAC /* NSScriptCommand+NetNewsWire.swift */; };
D5907D7F2004AC00005947E5 /* NSApplication+Scriptability.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5907D7E2004AC00005947E5 /* NSApplication+Scriptability.swift */; };
@@ -704,9 +688,6 @@
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>"; };
511B9805237DCAC90028BCAA /* UserInfoKey.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserInfoKey.swift; sourceTree = "<group>"; };
511D43EE231FBDE800FB1562 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreenPad.storyboard; sourceTree = "<group>"; };
511D4410231FC02D00FB1562 /* KeyboardManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = KeyboardManager.swift; sourceTree = "<group>"; };
5126EE96226CB48A00C22AFC /* SceneCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneCoordinator.swift; sourceTree = "<group>"; };
5127B236222B4849006D641D /* DetailKeyboardDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DetailKeyboardDelegate.swift; sourceTree = "<group>"; };
5127B237222B4849006D641D /* DetailKeyboardShortcuts.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = DetailKeyboardShortcuts.plist; sourceTree = "<group>"; };
51314617235A797400387FDC /* NetNewsWire_iOSintentextension_target.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = NetNewsWire_iOSintentextension_target.xcconfig; sourceTree = "<group>"; };
@@ -727,7 +708,6 @@
5144EA3E227A37EC00D19003 /* ImportOPMLWindowController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImportOPMLWindowController.swift; sourceTree = "<group>"; };
5144EA4F227B8E4500D19003 /* AccountsFeedbinWindowController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountsFeedbinWindowController.swift; sourceTree = "<group>"; };
5144EA50227B8E4500D19003 /* AccountsFeedbin.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = AccountsFeedbin.xib; sourceTree = "<group>"; };
514B7C8223205EFB00BAC947 /* RootSplitViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RootSplitViewController.swift; sourceTree = "<group>"; };
515D4FCB2325815A00EE1167 /* SafariExt.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = SafariExt.js; sourceTree = "<group>"; };
515D4FCE2325B3D000EE1167 /* NetNewsWire_iOSshareextension_target.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = NetNewsWire_iOSshareextension_target.xcconfig; sourceTree = "<group>"; };
516AE9DE2372269A007DEEAA /* IconImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IconImage.swift; sourceTree = "<group>"; };
@@ -741,7 +721,6 @@
51934CCD2310792F006127BE /* ActivityManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActivityManager.swift; sourceTree = "<group>"; };
51938DF1231AFC660055A1A0 /* SearchTimelineFeedDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchTimelineFeedDelegate.swift; sourceTree = "<group>"; };
519B8D322143397200FA689C /* SharingServiceDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SharingServiceDelegate.swift; sourceTree = "<group>"; };
519E743422C663F900A78E47 /* SceneDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = "<group>"; };
51A052CD244FB9D6006C2024 /* AddFeedWIndowController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = AddFeedWIndowController.swift; path = AddFeed/AddFeedWIndowController.swift; sourceTree = "<group>"; };
51A66684238075AE00CB272D /* AddWebFeedDefaultContainer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddWebFeedDefaultContainer.swift; sourceTree = "<group>"; };
51B5C87623F22B8200032075 /* ExtensionContainers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExtensionContainers.swift; sourceTree = "<group>"; };
@@ -749,12 +728,8 @@
51B5C87C23F2346200032075 /* ExtensionContainersFile.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExtensionContainersFile.swift; sourceTree = "<group>"; };
51B5C8BC23F3780900032075 /* ShareDefaultContainer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShareDefaultContainer.swift; sourceTree = "<group>"; };
51B5C8BF23F3866C00032075 /* ExtensionFeedAddRequestFile.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExtensionFeedAddRequestFile.swift; sourceTree = "<group>"; };
51B62E67233186730085F949 /* IconView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IconView.swift; sourceTree = "<group>"; };
51BB7C262335A8E5008E8144 /* ArticleActivityItemSource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ArticleActivityItemSource.swift; sourceTree = "<group>"; };
51BC4ADD247277DF000A6ED8 /* URL-Extensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "URL-Extensions.swift"; sourceTree = "<group>"; };
51C03080257D815A00609262 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Mac/Base.lproj/UnifiedWindow.storyboard; sourceTree = SOURCE_ROOT; };
51C45254226507D200C03939 /* AppAssets.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppAssets.swift; sourceTree = "<group>"; };
51C45255226507D200C03939 /* AppDefaults.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDefaults.swift; sourceTree = "<group>"; };
51C452B32265141B00C03939 /* WebKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WebKit.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS12.2.sdk/System/Library/Frameworks/WebKit.framework; sourceTree = DEVELOPER_DIR; };
51C4CFEF24D37D1F00AF9874 /* Secrets.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Secrets.swift; sourceTree = "<group>"; };
51CD32A824D2CB25009ABAEF /* SyncDatabase */ = {isa = PBXFileReference; lastKnownFileType = folder; path = SyncDatabase; sourceTree = "<group>"; };
@@ -768,7 +743,6 @@
51DEE81126FB9233006DAA56 /* Appanoose.nnwtheme */ = {isa = PBXFileReference; lastKnownFileType = wrapper; path = Appanoose.nnwtheme; sourceTree = "<group>"; };
51DEE81726FBFF84006DAA56 /* Promenade.nnwtheme */ = {isa = PBXFileReference; lastKnownFileType = wrapper; path = Promenade.nnwtheme; sourceTree = "<group>"; };
51E3EB32229AB02C00645299 /* ErrorHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ErrorHandler.swift; sourceTree = "<group>"; };
51E3EB3C229AB08300645299 /* ErrorHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ErrorHandler.swift; sourceTree = "<group>"; };
51E4989624A8065700B667CB /* CloudKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CloudKit.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS14.0.sdk/System/Library/Frameworks/CloudKit.framework; sourceTree = DEVELOPER_DIR; };
51E4989824A8067000B667CB /* WebKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WebKit.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS14.0.sdk/System/Library/Frameworks/WebKit.framework; sourceTree = DEVELOPER_DIR; };
51E498B224A806AA00B667CB /* WebKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WebKit.framework; path = System/Library/Frameworks/WebKit.framework; sourceTree = SDKROOT; };
@@ -804,7 +778,6 @@
840BEE4021D70E64009BBAFA /* CrashReportWindowController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CrashReportWindowController.swift; sourceTree = "<group>"; };
840C544F2D0C9A4A00A240DB /* Core */ = {isa = PBXFileReference; lastKnownFileType = wrapper; path = Core; sourceTree = "<group>"; };
840D617C2029031C009BC708 /* NetNewsWire.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = NetNewsWire.app; sourceTree = BUILT_PRODUCTS_DIR; };
840D617E2029031C009BC708 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
840D61952029031D009BC708 /* NetNewsWire_iOSTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetNewsWire_iOSTests.swift; sourceTree = "<group>"; };
840D61972029031D009BC708 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
8413C1372D050A1E002E3D0F /* UniformTypeIdentifiers+Extras.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UniformTypeIdentifiers+Extras.swift"; sourceTree = "<group>"; };
@@ -911,8 +884,6 @@
84C9FC8A22629E8F00D921D6 /* NetNewsWire.sdef */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = NetNewsWire.sdef; sourceTree = "<group>"; };
84C9FC9022629ECB00D921D6 /* NetNewsWire.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = NetNewsWire.entitlements; sourceTree = "<group>"; };
84C9FC9122629F2200D921D6 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
84C9FCA02262A1B300D921D6 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
84C9FCA32262A1B800D921D6 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreenPhone.storyboard; sourceTree = "<group>"; };
84CAFCA322BC8C08007694F0 /* FetchRequestQueue.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FetchRequestQueue.swift; sourceTree = "<group>"; };
84CAFCAE22BC8C35007694F0 /* FetchRequestOperation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FetchRequestOperation.swift; sourceTree = "<group>"; };
84CBDDAE1FD3674C005A61AA /* Technotes */ = {isa = PBXFileReference; lastKnownFileType = folder; path = Technotes; sourceTree = "<group>"; };
@@ -956,7 +927,6 @@
B2B8075D239C49D300F191E0 /* RSImage-AppIcons.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "RSImage-AppIcons.swift"; sourceTree = "<group>"; };
B528F81D23333C7E00E735DD /* page.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = page.html; sourceTree = "<group>"; };
BDCB514D24282C8A00102A80 /* AccountsNewsBlur.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = AccountsNewsBlur.xib; sourceTree = "<group>"; };
C5A6ED5123C9AF4300AB6BE2 /* TitleActivityItemSource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TitleActivityItemSource.swift; sourceTree = "<group>"; };
D519E74722EE553300923F27 /* NetNewsWire_safariextension_target.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = NetNewsWire_safariextension_target.xcconfig; sourceTree = "<group>"; };
D553737C20186C1F006D8857 /* Article+Scriptability.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Article+Scriptability.swift"; sourceTree = "<group>"; };
D57BE6DF204CD35F00D11AAC /* NSScriptCommand+NetNewsWire.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NSScriptCommand+NetNewsWire.swift"; sourceTree = "<group>"; };
@@ -981,48 +951,48 @@
/* End PBXFileReference section */
/* Begin PBXFileSystemSynchronizedBuildFileExceptionSet section */
84A6CEFD2D1B4E1600F23315 /* PBXFileSystemSynchronizedBuildFileExceptionSet */ = {
84A6D03F2D1B4EC500F23315 /* PBXFileSystemSynchronizedBuildFileExceptionSet */ = {
isa = PBXFileSystemSynchronizedBuildFileExceptionSet;
membershipExceptions = (
Info.plist,
);
target = 513C5CE5232571C2003D4054 /* NetNewsWire iOS Share Extension */;
};
84A6CF032D1B4E5400F23315 /* PBXFileSystemSynchronizedBuildFileExceptionSet */ = {
isa = PBXFileSystemSynchronizedBuildFileExceptionSet;
membershipExceptions = (
IntentHandler.swift,
);
target = 51314636235A7BBE00387FDC /* NetNewsWire iOS Intents Extension */;
};
84A6CF1D2D1B4E7C00F23315 /* PBXFileSystemSynchronizedBuildFileExceptionSet */ = {
isa = PBXFileSystemSynchronizedBuildFileExceptionSet;
membershipExceptions = (
Info.plist,
/Localized/ShareExtension/MainInterface.storyboard,
IntentsExtension/Info.plist,
IntentsExtension/IntentHandler.swift,
Resources/Info.plist,
ShareExtension/Info.plist,
ShareExtension/ShareFolderPickerAccountCell.xib,
ShareExtension/ShareFolderPickerCell.swift,
ShareExtension/ShareFolderPickerController.swift,
ShareExtension/ShareFolderPickerFolderCell.xib,
ShareExtension/ShareViewController.swift,
);
target = 840D617B2029031C009BC708 /* NetNewsWire-iOS */;
};
84A6CF1E2D1B4E7C00F23315 /* PBXFileSystemSynchronizedBuildFileExceptionSet */ = {
84A6D0402D1B4EC500F23315 /* PBXFileSystemSynchronizedBuildFileExceptionSet */ = {
isa = PBXFileSystemSynchronizedBuildFileExceptionSet;
membershipExceptions = (
Assets.xcassets,
/Localized/ShareExtension/MainInterface.storyboard,
AppAssets.swift,
AppDefaults.swift,
Resources/Assets.xcassets,
ShareExtension/ShareFolderPickerAccountCell.xib,
ShareExtension/ShareFolderPickerCell.swift,
ShareExtension/ShareFolderPickerController.swift,
ShareExtension/ShareFolderPickerFolderCell.xib,
ShareExtension/ShareViewController.swift,
);
target = 513C5CE5232571C2003D4054 /* NetNewsWire iOS Share Extension */;
};
84A6D0412D1B4EC500F23315 /* PBXFileSystemSynchronizedBuildFileExceptionSet */ = {
isa = PBXFileSystemSynchronizedBuildFileExceptionSet;
membershipExceptions = (
IntentsExtension/IntentHandler.swift,
);
target = 51314636235A7BBE00387FDC /* NetNewsWire iOS Intents Extension */;
};
/* End PBXFileSystemSynchronizedBuildFileExceptionSet section */
/* Begin PBXFileSystemSynchronizedRootGroup section */
84352B8A2D1B446D0002B64E /* MainFeed */ = {isa = PBXFileSystemSynchronizedRootGroup; explicitFileTypes = {}; explicitFolders = (); path = MainFeed; sourceTree = "<group>"; };
84A6CE4F2D1B457500F23315 /* MainTimeline */ = {isa = PBXFileSystemSynchronizedRootGroup; explicitFileTypes = {}; explicitFolders = (); path = MainTimeline; sourceTree = "<group>"; };
84A6CE6C2D1B4D1300F23315 /* Article */ = {isa = PBXFileSystemSynchronizedRootGroup; explicitFileTypes = {}; explicitFolders = (); path = Article; sourceTree = "<group>"; };
84A6CE812D1B4D2700F23315 /* Account */ = {isa = PBXFileSystemSynchronizedRootGroup; explicitFileTypes = {}; explicitFolders = (); path = Account; sourceTree = "<group>"; };
84A6CE902D1B4D8300F23315 /* Add */ = {isa = PBXFileSystemSynchronizedRootGroup; explicitFileTypes = {}; explicitFolders = (); path = Add; sourceTree = "<group>"; };
84A6CE9D2D1B4D9A00F23315 /* Inspector */ = {isa = PBXFileSystemSynchronizedRootGroup; explicitFileTypes = {}; explicitFolders = (); path = Inspector; sourceTree = "<group>"; };
84A6CEAE2D1B4DD000F23315 /* Settings */ = {isa = PBXFileSystemSynchronizedRootGroup; explicitFileTypes = {}; explicitFolders = (); path = Settings; sourceTree = "<group>"; };
84A6CED32D1B4DF700F23315 /* UIKit Extensions */ = {isa = PBXFileSystemSynchronizedRootGroup; explicitFileTypes = {}; explicitFolders = (); path = "UIKit Extensions"; sourceTree = "<group>"; };
84A6CEF52D1B4E1600F23315 /* ShareExtension */ = {isa = PBXFileSystemSynchronizedRootGroup; exceptions = (84A6CEFD2D1B4E1600F23315 /* PBXFileSystemSynchronizedBuildFileExceptionSet */, ); explicitFileTypes = {}; explicitFolders = (); path = ShareExtension; sourceTree = "<group>"; };
84A6CF012D1B4E5400F23315 /* IntentsExtension */ = {isa = PBXFileSystemSynchronizedRootGroup; exceptions = (84A6CF032D1B4E5400F23315 /* PBXFileSystemSynchronizedBuildFileExceptionSet */, ); explicitFileTypes = {}; explicitFolders = (); path = IntentsExtension; sourceTree = "<group>"; };
84A6CF112D1B4E7C00F23315 /* Resources */ = {isa = PBXFileSystemSynchronizedRootGroup; exceptions = (84A6CF1D2D1B4E7C00F23315 /* PBXFileSystemSynchronizedBuildFileExceptionSet */, 84A6CF1E2D1B4E7C00F23315 /* PBXFileSystemSynchronizedBuildFileExceptionSet */, ); explicitFileTypes = {}; explicitFolders = (); path = Resources; sourceTree = "<group>"; };
84A6CFB52D1B4EC500F23315 /* iOS */ = {isa = PBXFileSystemSynchronizedRootGroup; exceptions = (84A6D03F2D1B4EC500F23315 /* PBXFileSystemSynchronizedBuildFileExceptionSet */, 84A6D0402D1B4EC500F23315 /* PBXFileSystemSynchronizedBuildFileExceptionSet */, 84A6D0412D1B4EC500F23315 /* PBXFileSystemSynchronizedBuildFileExceptionSet */, ); explicitFileTypes = {}; explicitFolders = (); path = iOS; sourceTree = "<group>"; };
/* End PBXFileSystemSynchronizedRootGroup section */
/* Begin PBXFrameworksBuildPhase section */
@@ -1621,7 +1591,8 @@
84D2200922B0BC4B0019E085 /* CONTRIBUTING.md */,
84CBDDAE1FD3674C005A61AA /* Technotes */,
84C9FC6522629B3900D921D6 /* Mac */,
84C9FC922262A0E600D921D6 /* iOS */,
84A6CFB52D1B4EC500F23315 /* iOS */,
513145F9235A55A700387FDC /* Intents */,
176813F82564BB2C00D98635 /* Widget */,
84C9FC6822629C9A00D921D6 /* Shared */,
84C9FCA52262A1E600D921D6 /* Tests */,
@@ -1813,39 +1784,6 @@
path = KeyboardShortcuts;
sourceTree = "<group>";
};
84C9FC922262A0E600D921D6 /* iOS */ = {
isa = PBXGroup;
children = (
84C9FCA22262A1B800D921D6 /* LaunchScreenPhone.storyboard */,
511D43ED231FBDE800FB1562 /* LaunchScreenPad.storyboard */,
84C9FC9F2262A1B300D921D6 /* Main.storyboard */,
840D617E2029031C009BC708 /* AppDelegate.swift */,
519E743422C663F900A78E47 /* SceneDelegate.swift */,
5126EE96226CB48A00C22AFC /* SceneCoordinator.swift */,
514B7C8223205EFB00BAC947 /* RootSplitViewController.swift */,
511D4410231FC02D00FB1562 /* KeyboardManager.swift */,
51C45254226507D200C03939 /* AppAssets.swift */,
51C45255226507D200C03939 /* AppDefaults.swift */,
51E3EB3C229AB08300645299 /* ErrorHandler.swift */,
51BB7C262335A8E5008E8144 /* ArticleActivityItemSource.swift */,
C5A6ED5123C9AF4300AB6BE2 /* TitleActivityItemSource.swift */,
51B62E67233186730085F949 /* IconView.swift */,
84352B8A2D1B446D0002B64E /* MainFeed */,
84A6CE4F2D1B457500F23315 /* MainTimeline */,
84A6CE6C2D1B4D1300F23315 /* Article */,
84A6CE812D1B4D2700F23315 /* Account */,
84A6CE902D1B4D8300F23315 /* Add */,
84A6CE9D2D1B4D9A00F23315 /* Inspector */,
513145F9235A55A700387FDC /* Intents */,
84A6CEAE2D1B4DD000F23315 /* Settings */,
84A6CED32D1B4DF700F23315 /* UIKit Extensions */,
84A6CEF52D1B4E1600F23315 /* ShareExtension */,
84A6CF012D1B4E5400F23315 /* IntentsExtension */,
84A6CF112D1B4E7C00F23315 /* Resources */,
);
path = iOS;
sourceTree = "<group>";
};
84C9FCA52262A1E600D921D6 /* Tests */ = {
isa = PBXGroup;
children = (
@@ -2058,9 +1996,6 @@
);
dependencies = (
);
fileSystemSynchronizedGroups = (
84A6CEF52D1B4E1600F23315 /* ShareExtension */,
);
name = "NetNewsWire iOS Share Extension";
packageProductDependencies = (
51BC2F3724D3439A00E90810 /* Account */,
@@ -2125,15 +2060,7 @@
176813FF2564BB2D00D98635 /* PBXTargetDependency */,
);
fileSystemSynchronizedGroups = (
84352B8A2D1B446D0002B64E /* MainFeed */,
84A6CE4F2D1B457500F23315 /* MainTimeline */,
84A6CE6C2D1B4D1300F23315 /* Article */,
84A6CE812D1B4D2700F23315 /* Account */,
84A6CE902D1B4D8300F23315 /* Add */,
84A6CE9D2D1B4D9A00F23315 /* Inspector */,
84A6CEAE2D1B4DD000F23315 /* Settings */,
84A6CED32D1B4DF700F23315 /* UIKit Extensions */,
84A6CF112D1B4E7C00F23315 /* Resources */,
84A6CFB52D1B4EC500F23315 /* iOS */,
);
name = "NetNewsWire-iOS";
packageProductDependencies = (
@@ -2286,7 +2213,6 @@
};
};
buildConfigurationList = 849C645B1ED37A5D003D8FC0 /* Build configuration list for PBXProject "NetNewsWire" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = en;
hasScannedForEncodings = 0;
knownRegions = (
@@ -2303,6 +2229,7 @@
519CA8E325841DB700EB079A /* XCRemoteSwiftPackageReference "plcrashreporter" */,
179D280926F6F93D003B2E0A /* XCRemoteSwiftPackageReference "Zip" */,
);
preferredProjectObjectVersion = 46;
productRefGroup = 849C64611ED37A5D003D8FC0 /* Products */;
projectDirPath = "";
projectRoot = "";
@@ -2381,14 +2308,11 @@
5137C2E626F3F52D009EFEDB /* Sepia.nnwtheme in Resources */,
517630052336215100E15FFF /* main.js in Resources */,
511D43D0231FA62500FB1562 /* TimelineKeyboardShortcuts.plist in Resources */,
511D43EF231FBDE900FB1562 /* LaunchScreenPad.storyboard in Resources */,
511D43D2231FA62C00FB1562 /* GlobalKeyboardShortcuts.plist in Resources */,
84C9FCA12262A1B300D921D6 /* Main.storyboard in Resources */,
51077C5627A86C9E000C71DB /* Hyperlegible.nnwtheme in Resources */,
51DEE81A26FBFF84006DAA56 /* Promenade.nnwtheme in Resources */,
1768140B2564BB8300D98635 /* NetNewsWire_iOSwidgetextension_target.xcconfig in Resources */,
51D0214826ED617100FF2E0F /* core.css in Resources */,
84C9FCA42262A1B800D921D6 /* LaunchScreenPhone.storyboard in Resources */,
511D43D1231FA62800FB1562 /* SidebarKeyboardShortcuts.plist in Resources */,
51C452AB22650DC600C03939 /* template.html in Resources */,
84A3EE61223B667F00557320 /* DefaultFeeds.opml in Resources */,
@@ -2685,9 +2609,7 @@
51B5C8BA23F368D000032075 /* ExtensionContainersFile.swift in Sources */,
51B5C8BB23F368D000032075 /* ExtensionFeedAddRequest.swift in Sources */,
51A9A5EF2380D63B0033AADF /* IconImage.swift in Sources */,
51A9A5ED2380D6000033AADF /* AppAssets.swift in Sources */,
51B5C8C123F3A0DB00032075 /* ExtensionFeedAddRequestFile.swift in Sources */,
51A9A5E12380C4FE0033AADF /* AppDefaults.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -2712,12 +2634,10 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
840D617F2029031C009BC708 /* AppDelegate.swift in Sources */,
512E08E72268801200BDCFDD /* WebFeedTreeControllerDelegate.swift in Sources */,
51C452A422650A2D00C03939 /* ArticleUtilities.swift in Sources */,
51EF0F79227716380050506E /* ColorHash.swift in Sources */,
B2B80778239C4C7000F191E0 /* RSImage-AppIcons.swift in Sources */,
51B62E68233186730085F949 /* IconView.swift in Sources */,
179D280D26F73D83003B2E0A /* ArticleThemePlist.swift in Sources */,
51C45296226509D300C03939 /* OPMLExporter.swift in Sources */,
51C45291226509C800C03939 /* SmartFeed.swift in Sources */,
@@ -2731,15 +2651,12 @@
51D5948722668EFA00DFC836 /* MarkStatusCommand.swift in Sources */,
176813D12564BA5900D98635 /* WidgetDataDecoder.swift in Sources */,
176813D02564BA5900D98635 /* WidgetData.swift in Sources */,
514B7C8323205EFB00BAC947 /* RootSplitViewController.swift in Sources */,
51FA73A52332BE110090D516 /* ArticleExtractor.swift in Sources */,
51314704235C41FC00387FDC /* Intents.intentdefinition in Sources */,
FF3ABF162325AF5D0074C542 /* ArticleSorter.swift in Sources */,
5126EE97226CB48A00C22AFC /* SceneCoordinator.swift in Sources */,
84CAFCB022BC8C35007694F0 /* FetchRequestOperation.swift in Sources */,
51EF0F77227716200050506E /* FaviconGenerator.swift in Sources */,
51938DF3231AFC660055A1A0 /* SearchTimelineFeedDelegate.swift in Sources */,
51BB7C272335A8E5008E8144 /* ArticleActivityItemSource.swift in Sources */,
51C452A622650A3500C03939 /* Node-Extensions.swift in Sources */,
51C45294226509C800C03939 /* SearchFeedDelegate.swift in Sources */,
51FE10042345529D0056195D /* UserNotificationManager.swift in Sources */,
@@ -2752,9 +2669,7 @@
51C45292226509C800C03939 /* TodayFeedDelegate.swift in Sources */,
51C452A222650A1900C03939 /* RSHTMLMetadata+Extension.swift in Sources */,
51B5C87B23F2317700032075 /* ExtensionFeedAddRequest.swift in Sources */,
51E3EB3D229AB08300645299 /* ErrorHandler.swift in Sources */,
5183CCE5226F4DFA0010922C /* RefreshInterval.swift in Sources */,
51C45258226508CF00C03939 /* AppAssets.swift in Sources */,
51FA73A82332BE880090D516 /* ExtractedArticle.swift in Sources */,
51C4529A22650A0400C03939 /* ArticleTheme.swift in Sources */,
51C452AE2265104D00C03939 /* ArticleStringFormatter.swift in Sources */,
@@ -2779,16 +2694,12 @@
173A642C2547BE9600267F6E /* AccountType+Helpers.swift in Sources */,
8454C3F3263F2D8700E3F9C7 /* IconImageCache.swift in Sources */,
B24E9ADE245AB88400DA5718 /* NSAttributedString+NetNewsWire.swift in Sources */,
C5A6ED5223C9AF4300AB6BE2 /* TitleActivityItemSource.swift in Sources */,
17071EF126F8137400F5E71D /* ArticleTheme+Notifications.swift in Sources */,
51C4529B22650A1000C03939 /* FaviconDownloader.swift in Sources */,
84DEE56622C32CA4005FC42C /* SmartFeedDelegate.swift in Sources */,
516AE9E02372269A007DEEAA /* IconImage.swift in Sources */,
51C4529F22650A1900C03939 /* AuthorAvatarDownloader.swift in Sources */,
519E743D22C663F900A78E47 /* SceneDelegate.swift in Sources */,
8413C1382D050A1E002E3D0F /* UniformTypeIdentifiers+Extras.swift in Sources */,
51C45259226508D300C03939 /* AppDefaults.swift in Sources */,
511D4419231FC02D00FB1562 /* KeyboardManager.swift in Sources */,
51C45293226509C800C03939 /* StarredFeedDelegate.swift in Sources */,
51BC4B01247277E0000A6ED8 /* URL-Extensions.swift in Sources */,
);
@@ -3044,14 +2955,6 @@
name = ShareViewController.xib;
sourceTree = "<group>";
};
511D43ED231FBDE800FB1562 /* LaunchScreenPad.storyboard */ = {
isa = PBXVariantGroup;
children = (
511D43EE231FBDE800FB1562 /* Base */,
);
name = LaunchScreenPad.storyboard;
sourceTree = "<group>";
};
51314707235C41FC00387FDC /* Intents.intentdefinition */ = {
isa = PBXVariantGroup;
children = (
@@ -3117,22 +3020,6 @@
name = Preferences.storyboard;
sourceTree = "<group>";
};
84C9FC9F2262A1B300D921D6 /* Main.storyboard */ = {
isa = PBXVariantGroup;
children = (
84C9FCA02262A1B300D921D6 /* Base */,
);
name = Main.storyboard;
sourceTree = "<group>";
};
84C9FCA22262A1B800D921D6 /* LaunchScreenPhone.storyboard */ = {
isa = PBXVariantGroup;
children = (
84C9FCA32262A1B800D921D6 /* Base */,
);
name = LaunchScreenPhone.storyboard;
sourceTree = "<group>";
};
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */

View File

@@ -1,647 +0,0 @@
//
// NavigationModelController.swift
// NetNewsWire-iOS
//
// Created by Maurice Parker on 4/21/19.
// Copyright © 2019 Ranchero Software. All rights reserved.
//
import Foundation
import Account
import Articles
import RSCore
import RSTree
public extension Notification.Name {
static let MasterSelectionDidChange = Notification.Name(rawValue: "MasterSelectionDidChange")
static let BackingStoresDidRebuild = Notification.Name(rawValue: "BackingStoresDidRebuild")
static let ArticlesReinitialized = Notification.Name(rawValue: "ArticlesReinitialized")
static let ArticleDataDidChange = Notification.Name(rawValue: "ArticleDataDidChange")
static let ArticlesDidChange = Notification.Name(rawValue: "ArticlesDidChange")
static let ArticleSelectionDidChange = Notification.Name(rawValue: "ArticleSelectionDidChange")
}
class NavigationStateController {
static let fetchAndMergeArticlesQueue = CoalescingQueue(name: "Fetch and Merge Articles", interval: 0.5)
private var articleRowMap = [String: Int]() // articleID: rowIndex
private var animatingChanges = false
private var expandedNodes = [Node]()
private var shadowTable = [[Node]]()
private var sortDirection = AppDefaults.timelineSortDirection {
didSet {
if sortDirection != oldValue {
sortDirectionDidChange()
}
}
}
private let treeControllerDelegate = FeedTreeControllerDelegate()
lazy var treeController: TreeController = {
return TreeController(delegate: treeControllerDelegate)
}()
var rootNode: Node {
return treeController.rootNode
}
var numberOfSections: Int {
return shadowTable.count
}
var currentMasterIndexPath: IndexPath? {
didSet {
guard let ip = currentMasterIndexPath, let node = nodeFor(ip) else {
assertionFailure()
return
}
if let fetcher = node.representedObject as? ArticleFetcher {
timelineFetcher = fetcher
}
NotificationCenter.default.post(name: .MasterSelectionDidChange, object: self, userInfo: nil)
}
}
var timelineName: String? {
return (timelineFetcher as? DisplayNameProvider)?.nameForDisplay
}
var timelineFetcher: ArticleFetcher? {
didSet {
currentArticleIndexPath = nil
if timelineFetcher is Feed {
showFeedNames = false
} else {
showFeedNames = true
}
fetchArticles()
NotificationCenter.default.post(name: .ArticlesReinitialized, object: self, userInfo: nil)
}
}
var showFeedNames = false
var showAvatars = false
var isPrevArticleAvailable: Bool {
guard let indexPath = currentArticleIndexPath else {
return false
}
return indexPath.row > 0
}
var isNextArticleAvailable: Bool {
guard let indexPath = currentArticleIndexPath else {
return false
}
return indexPath.row + 1 < articles.count
}
var prevArticleIndexPath: IndexPath? {
guard let indexPath = currentArticleIndexPath else {
return nil
}
return IndexPath(row: indexPath.row - 1, section: indexPath.section)
}
var nextArticleIndexPath: IndexPath? {
guard let indexPath = currentArticleIndexPath else {
return nil
}
return IndexPath(row: indexPath.row + 1, section: indexPath.section)
}
var firstUnreadArticleIndexPath: IndexPath? {
for (row, article) in articles.enumerated() {
if !article.status.read {
return IndexPath(row: row, section: 0)
}
}
return nil
}
var currentArticle: Article? {
if let indexPath = currentArticleIndexPath {
return articles[indexPath.row]
}
return nil
}
var currentArticleIndexPath: IndexPath? {
didSet {
if currentArticleIndexPath != oldValue {
NotificationCenter.default.post(name: .ArticleSelectionDidChange, object: self, userInfo: nil)
}
}
}
var articles = ArticleArray() {
didSet {
if articles == oldValue {
return
}
if articles.representSameArticlesInSameOrder(as: oldValue) {
articleRowMap = [String: Int]()
NotificationCenter.default.post(name: .ArticleDataDidChange, object: self, userInfo: nil)
return
}
updateShowAvatars()
articleRowMap = [String: Int]()
NotificationCenter.default.post(name: .ArticlesDidChange, object: self, userInfo: nil)
}
}
var isTimelineUnreadAvailable: Bool {
if let unreadProvider = timelineFetcher as? UnreadCountProvider {
return unreadProvider.unreadCount > 0
}
return false
}
var isAnyUnreadAvailable: Bool {
return appDelegate.unreadCount > 0
}
init() {
for section in treeController.rootNode.childNodes {
expandedNodes.append(section)
shadowTable.append([Node]())
}
rebuildShadowTable()
NotificationCenter.default.addObserver(self, selector: #selector(containerChildrenDidChange(_:)), name: .ChildrenDidChange, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(batchUpdateDidPerform(_:)), name: .BatchUpdateDidPerform, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(displayNameDidChange(_:)), name: .DisplayNameDidChange, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(accountStateDidChange(_:)), name: .AccountStateDidChange, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(accountsDidChange(_:)), name: .AccountsDidChange, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(userDefaultsDidChange(_:)), name: UserDefaults.didChangeNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(accountDidDownloadArticles(_:)), name: .AccountDidDownloadArticles, object: nil)
}
// MARK: Notifications
@objc func containerChildrenDidChange(_ note: Notification) {
rebuildBackingStores()
}
@objc func batchUpdateDidPerform(_ notification: Notification) {
rebuildBackingStores()
}
@objc func displayNameDidChange(_ note: Notification) {
rebuildBackingStores()
}
@objc func accountStateDidChange(_ note: Notification) {
rebuildBackingStores()
}
@objc func accountsDidChange(_ note: Notification) {
rebuildBackingStores()
}
@objc func userDefaultsDidChange(_ note: Notification) {
self.sortDirection = AppDefaults.timelineSortDirection
}
@objc func accountDidDownloadArticles(_ note: Notification) {
guard let feeds = note.userInfo?[Account.UserInfoKey.feeds] as? Set<Feed> else {
return
}
let shouldFetchAndMergeArticles = timelineFetcherContainsAnyFeed(feeds) || timelineFetcherContainsAnyPseudoFeed()
if shouldFetchAndMergeArticles {
queueFetchAndMergeArticles()
}
}
// MARK: API
func beginUpdates() {
animatingChanges = true
}
func endUpdates() {
animatingChanges = false
}
func rowsInSection(_ section: Int) -> Int {
return shadowTable[section].count
}
func rebuildShadowTable() {
shadowTable = [[Node]]()
for i in 0..<treeController.rootNode.numberOfChildNodes {
var result = [Node]()
if let nodes = treeController.rootNode.childAtIndex(i)?.childNodes {
for node in nodes {
result.append(node)
if expandedNodes.contains(node) {
for child in node.childNodes {
result.append(child)
}
}
}
}
shadowTable.append(result)
}
}
func isExpanded(_ node: Node) -> Bool {
return expandedNodes.contains(node)
}
func nodeFor(_ indexPath: IndexPath) -> Node? {
guard indexPath.section < shadowTable.count || indexPath.row < shadowTable[indexPath.section].count else {
return nil
}
return shadowTable[indexPath.section][indexPath.row]
}
func indexPathFor(_ node: Node) -> IndexPath? {
for i in 0..<shadowTable.count {
if let row = shadowTable[i].firstIndex(of: node) {
return IndexPath(row: row, section: i)
}
}
return nil
}
func expand(section: Int, completion: ([IndexPath]) -> ()) {
guard let expandNode = treeController.rootNode.childAtIndex(section) else {
return
}
expandedNodes.append(expandNode)
animatingChanges = true
var indexPathsToInsert = [IndexPath]()
var i = 0
func addNode(_ node: Node) {
indexPathsToInsert.append(IndexPath(row: i, section: section))
shadowTable[section].insert(node, at: i)
i = i + 1
}
for child in expandNode.childNodes {
addNode(child)
if expandedNodes.contains(child) {
for gChild in child.childNodes {
addNode(gChild)
}
}
}
completion(indexPathsToInsert)
animatingChanges = false
}
func expand(_ indexPath: IndexPath, completion: ([IndexPath]) -> ()) {
let expandNode = shadowTable[indexPath.section][indexPath.row]
expandedNodes.append(expandNode)
animatingChanges = true
var indexPathsToInsert = [IndexPath]()
for i in 0..<expandNode.childNodes.count {
if let child = expandNode.childAtIndex(i) {
let nextIndex = indexPath.row + i + 1
indexPathsToInsert.append(IndexPath(row: nextIndex, section: indexPath.section))
shadowTable[indexPath.section].insert(child, at: nextIndex)
}
}
completion(indexPathsToInsert)
animatingChanges = false
}
func collapse(section: Int, completion: ([IndexPath]) -> ()) {
animatingChanges = true
guard let collapseNode = treeController.rootNode.childAtIndex(section) else {
return
}
if let removeNode = expandedNodes.firstIndex(of: collapseNode) {
expandedNodes.remove(at: removeNode)
}
var indexPathsToRemove = [IndexPath]()
for i in 0..<shadowTable[section].count {
indexPathsToRemove.append(IndexPath(row: i, section: section))
}
shadowTable[section] = [Node]()
completion(indexPathsToRemove)
animatingChanges = false
}
func collapse(_ indexPath: IndexPath, completion: ([IndexPath]) -> ()) {
animatingChanges = true
let collapseNode = shadowTable[indexPath.section][indexPath.row]
if let removeNode = expandedNodes.firstIndex(of: collapseNode) {
expandedNodes.remove(at: removeNode)
}
var indexPathsToRemove = [IndexPath]()
for child in collapseNode.childNodes {
if let index = shadowTable[indexPath.section].firstIndex(of: child) {
indexPathsToRemove.append(IndexPath(row: index, section: indexPath.section))
}
}
for child in collapseNode.childNodes {
if let index = shadowTable[indexPath.section].firstIndex(of: child) {
shadowTable[indexPath.section].remove(at: index)
}
}
completion(indexPathsToRemove)
animatingChanges = false
}
func indexesForArticleIDs(_ articleIDs: Set<String>) -> IndexSet {
var indexes = IndexSet()
articleIDs.forEach { (articleID) in
guard let oneIndex = row(for: articleID) else {
return
}
if oneIndex != NSNotFound {
indexes.insert(oneIndex)
}
}
return indexes
}
func selectNextUnread() {
// This should never happen, but I don't want to risk throwing us
// into an infinate loop searching for an unread that isn't there.
if appDelegate.unreadCount < 1 {
return
}
if selectNextUnreadArticleInTimeline() {
return
}
selectNextUnreadFeedFetcher()
selectNextUnreadArticleInTimeline()
}
}
private extension NavigationStateController {
func rebuildBackingStores() {
if !animatingChanges && !BatchUpdate.shared.isPerforming {
treeController.rebuild()
rebuildShadowTable()
NotificationCenter.default.post(name: .BackingStoresDidRebuild, object: self, userInfo: nil)
}
}
func updateShowAvatars() {
if showFeedNames {
self.showAvatars = true
return
}
for article in articles {
if let authors = article.authors {
for author in authors {
if author.avatarURL != nil {
self.showAvatars = true
return
}
}
}
}
self.showAvatars = false
}
// MARK: Select Next Unread
@discardableResult
func selectNextUnreadArticleInTimeline() -> Bool {
let startingRow: Int = {
if let indexPath = currentArticleIndexPath {
return indexPath.row
} else {
return 0
}
}()
for i in startingRow..<articles.count {
let article = articles[i]
if !article.status.read {
currentArticleIndexPath = IndexPath(row: i, section: 0)
return true
}
}
return false
}
func selectNextUnreadFeedFetcher() {
guard let indexPath = currentMasterIndexPath else {
assertionFailure()
return
}
// Increment or wrap around the IndexPath
let nextIndexPath: IndexPath = {
if indexPath.row + 1 >= shadowTable[indexPath.section].count {
if indexPath.section + 1 >= shadowTable.count {
return IndexPath(row: 0, section: 0)
} else {
return IndexPath(row: 0, section: indexPath.section + 1)
}
} else {
return IndexPath(row: indexPath.row + 1, section: indexPath.section)
}
}()
if selectNextUnreadFeedFetcher(startingWith: nextIndexPath) {
return
}
selectNextUnreadFeedFetcher(startingWith: IndexPath(row: 0, section: 0))
}
@discardableResult
func selectNextUnreadFeedFetcher(startingWith indexPath: IndexPath) -> Bool {
for i in indexPath.section..<shadowTable.count {
for j in indexPath.row..<shadowTable[indexPath.section].count {
let nextIndexPath = IndexPath(row: j, section: i)
guard let node = nodeFor(nextIndexPath), let unreadCountProvider = node.representedObject as? UnreadCountProvider else {
assertionFailure()
return true
}
if expandedNodes.contains(node) {
continue
}
if unreadCountProvider.unreadCount > 0 {
currentMasterIndexPath = nextIndexPath
return true
}
}
}
return false
}
// MARK: Fetching Articles
func fetchArticles() {
guard let timelineFetcher = timelineFetcher else {
articles = ArticleArray()
return
}
let fetchedArticles = timelineFetcher.fetchArticles()
updateArticles(with: fetchedArticles)
}
func emptyTheTimeline() {
if !articles.isEmpty {
articles = [Article]()
}
}
func sortDirectionDidChange() {
updateArticles(with: Set(articles))
}
func updateArticles(with unsortedArticles: Set<Article>) {
let sortedArticles = Array(unsortedArticles).sortedByDate(sortDirection)
if articles != sortedArticles {
articles = sortedArticles
}
}
func row(for articleID: String) -> Int? {
updateArticleRowMapIfNeeded()
return articleRowMap[articleID]
}
func updateArticleRowMap() {
var rowMap = [String: Int]()
var index = 0
articles.forEach { (article) in
rowMap[article.articleID] = index
index += 1
}
articleRowMap = rowMap
}
func updateArticleRowMapIfNeeded() {
if articleRowMap.isEmpty {
updateArticleRowMap()
}
}
func queueFetchAndMergeArticles() {
NavigationStateController.fetchAndMergeArticlesQueue.add(self, #selector(fetchAndMergeArticles))
}
@objc func fetchAndMergeArticles() {
guard let timelineFetcher = timelineFetcher else {
return
}
var unsortedArticles = timelineFetcher.fetchArticles()
// Merge articles by articleID. For any unique articleID in current articles, add to unsortedArticles.
let unsortedArticleIDs = unsortedArticles.articleIDs()
for article in articles {
if !unsortedArticleIDs.contains(article.articleID) {
unsortedArticles.insert(article)
}
}
updateArticles(with: unsortedArticles)
}
func timelineFetcherContainsAnyPseudoFeed() -> Bool {
if timelineFetcher is PseudoFeed {
return true
}
return false
}
func timelineFetcherContainsAnyFeed(_ feeds: Set<Feed>) -> Bool {
// Return true if theres a match or if a folder contains (recursively) one of feeds
if let feed = timelineFetcher as? Feed {
for oneFeed in feeds {
if feed.feedID == oneFeed.feedID || feed.url == oneFeed.url {
return true
}
}
} else if let folder = timelineFetcher as? Folder {
for oneFeed in feeds {
if folder.hasFeed(with: oneFeed.feedID) || folder.hasFeed(withURL: oneFeed.url) {
return true
}
}
}
return false
}
}