mirror of
https://github.com/Ranchero-Software/NetNewsWire
synced 2025-08-12 06:26:36 +00:00
Merge branch 'main' into iOS-Custom-notification-tone
This commit is contained in:
@@ -1058,7 +1058,7 @@ private extension ReaderAPIAccountDelegate {
|
||||
uniqueID: entry.uniqueID(variant: variant),
|
||||
feedURL: streamID,
|
||||
url: nil,
|
||||
externalURL: entry.alternates.first?.url,
|
||||
externalURL: entry.alternates?.first?.url,
|
||||
title: entry.title,
|
||||
language: nil,
|
||||
contentHTML: entry.summary.content,
|
||||
|
||||
@@ -58,7 +58,7 @@ struct ReaderAPIEntry: Codable {
|
||||
let timestampUsec: String?
|
||||
|
||||
let summary: ReaderAPIArticleSummary
|
||||
let alternates: [ReaderAPIAlternateLocation]
|
||||
let alternates: [ReaderAPIAlternateLocation]?
|
||||
let categories: [String]
|
||||
let origin: ReaderAPIEntryOrigin
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
<dependencies>
|
||||
<deployment identifier="macosx"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="21225"/>
|
||||
<capability name="NSView safe area layout guides" minToolsVersion="12.0"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<scenes>
|
||||
@@ -294,27 +295,23 @@
|
||||
<action selector="toggleReadArticlesFilter:" target="Ebq-4s-EwK" id="tcC-72-Npk"/>
|
||||
</connections>
|
||||
</button>
|
||||
<box verticalHuggingPriority="750" boxType="separator" translatesAutoresizingMaskIntoConstraints="NO" id="7p6-pA-iw6">
|
||||
<rect key="frame" x="0.0" y="195" width="375" height="5"/>
|
||||
</box>
|
||||
<customView translatesAutoresizingMaskIntoConstraints="NO" id="Zpk-pq-9nW" customClass="TimelineContainerView" customModule="NetNewsWire" customModuleProvider="target">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="197"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="198"/>
|
||||
</customView>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstAttribute="trailing" secondItem="Zpk-pq-9nW" secondAttribute="trailing" id="67d-pI-I9C"/>
|
||||
<constraint firstItem="Zpk-pq-9nW" firstAttribute="leading" secondItem="Dnl-L5-xFP" secondAttribute="leading" id="0f9-sc-5AE"/>
|
||||
<constraint firstAttribute="trailing" secondItem="iA5-go-AO0" secondAttribute="trailing" constant="12" id="9Dl-n9-vRI"/>
|
||||
<constraint firstItem="lSU-OC-sEC" firstAttribute="leading" secondItem="Dnl-L5-xFP" secondAttribute="leading" constant="8" id="Ceb-sA-ECJ"/>
|
||||
<constraint firstItem="Zpk-pq-9nW" firstAttribute="top" secondItem="7p6-pA-iw6" secondAttribute="bottom" id="KCa-8b-a6y"/>
|
||||
<constraint firstAttribute="trailing" secondItem="Zpk-pq-9nW" secondAttribute="trailing" id="Eod-fp-EiM"/>
|
||||
<constraint firstItem="lSU-OC-sEC" firstAttribute="centerY" secondItem="iA5-go-AO0" secondAttribute="centerY" id="OeL-Zp-iRT"/>
|
||||
<constraint firstItem="Zpk-pq-9nW" firstAttribute="leading" secondItem="Dnl-L5-xFP" secondAttribute="leading" id="XF2-31-E1x"/>
|
||||
<constraint firstAttribute="trailing" secondItem="7p6-pA-iw6" secondAttribute="trailing" id="fG3-fe-Stb"/>
|
||||
<constraint firstAttribute="bottom" secondItem="Zpk-pq-9nW" secondAttribute="bottom" id="fyv-EG-PC8"/>
|
||||
<constraint firstItem="7p6-pA-iw6" firstAttribute="leading" secondItem="Dnl-L5-xFP" secondAttribute="leading" id="pZU-jW-B1h"/>
|
||||
<constraint firstItem="7p6-pA-iw6" firstAttribute="top" secondItem="Dnl-L5-xFP" secondAttribute="top" id="tUm-nX-Jce"/>
|
||||
<constraint firstAttribute="bottom" secondItem="Zpk-pq-9nW" secondAttribute="bottom" id="RvS-Aa-GdA"/>
|
||||
<constraint firstItem="Zpk-pq-9nW" firstAttribute="top" secondItem="Dnl-L5-xFP" secondAttribute="top" id="sVz-yt-sFq"/>
|
||||
<constraint firstItem="iA5-go-AO0" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="lSU-OC-sEC" secondAttribute="trailing" constant="8" id="yCg-gc-exN"/>
|
||||
<constraint firstItem="lSU-OC-sEC" firstAttribute="top" secondItem="Dnl-L5-xFP" secondAttribute="top" constant="3" id="zay-ZJ-od3"/>
|
||||
</constraints>
|
||||
<viewLayoutGuide key="safeArea" id="PqV-qK-ND9"/>
|
||||
<viewLayoutGuide key="layoutMargins" id="Lb7-Qr-9rC"/>
|
||||
</view>
|
||||
<connections>
|
||||
<outlet property="containerView" destination="Zpk-pq-9nW" id="Kye-yX-Wyn"/>
|
||||
@@ -332,16 +329,24 @@
|
||||
</connections>
|
||||
</customObject>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="62" y="394"/>
|
||||
<point key="canvasLocation" x="61.5" y="394"/>
|
||||
</scene>
|
||||
<!--Detail View Controller-->
|
||||
<scene sceneID="HMt-bN-oMN">
|
||||
<objects>
|
||||
<viewController id="Vho-7i-T8m" userLabel="Detail View Controller" customClass="DetailViewController" customModule="NetNewsWire" customModuleProvider="target" sceneMemberID="viewController">
|
||||
<customView key="view" id="cJ9-6s-66u" customClass="DetailContainerView" customModule="NetNewsWire" customModuleProvider="target">
|
||||
<customView key="view" id="cJ9-6s-66u">
|
||||
<rect key="frame" x="0.0" y="0.0" width="730" height="300"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<subviews>
|
||||
<customView translatesAutoresizingMaskIntoConstraints="NO" id="EAt-cc-a4X" customClass="DetailContainerView" customModule="NetNewsWire" customModuleProvider="target">
|
||||
<rect key="frame" x="0.0" y="0.0" width="730" height="300"/>
|
||||
<connections>
|
||||
<outlet property="detailStatusBarView" destination="xI5-lx-RD8" id="2lM-To-54v"/>
|
||||
<outlet property="findBarContainerView" destination="lMN-Bl-G9Q" id="coK-s3-CKs"/>
|
||||
<outlet property="findBarHeightConstraint" destination="C1e-J5-baX" id="dk9-ah-mc0"/>
|
||||
</connections>
|
||||
</customView>
|
||||
<customView hidden="YES" alphaValue="0.90000000000000002" translatesAutoresizingMaskIntoConstraints="NO" id="xI5-lx-RD8" customClass="DetailStatusBarView" customModule="NetNewsWire" customModuleProvider="target">
|
||||
<rect key="frame" x="6" y="2" width="12" height="20"/>
|
||||
<subviews>
|
||||
@@ -374,19 +379,20 @@
|
||||
<constraints>
|
||||
<constraint firstItem="xI5-lx-RD8" firstAttribute="leading" secondItem="cJ9-6s-66u" secondAttribute="leading" constant="6" id="5vz-ys-CAo"/>
|
||||
<constraint firstItem="lMN-Bl-G9Q" firstAttribute="top" secondItem="cJ9-6s-66u" secondAttribute="top" placeholder="YES" id="Qyj-r4-LOb"/>
|
||||
<constraint firstItem="EAt-cc-a4X" firstAttribute="top" secondItem="cJ9-6s-66u" secondAttribute="top" id="Sb7-eK-hUs"/>
|
||||
<constraint firstItem="EAt-cc-a4X" firstAttribute="bottom" secondItem="cJ9-6s-66u" secondAttribute="bottom" id="dvJ-B7-cYU"/>
|
||||
<constraint firstItem="lMN-Bl-G9Q" firstAttribute="leading" secondItem="cJ9-6s-66u" secondAttribute="leading" id="fjq-7Z-e0q"/>
|
||||
<constraint firstItem="EAt-cc-a4X" firstAttribute="leading" secondItem="cJ9-6s-66u" secondAttribute="leading" id="mYI-QQ-pG2"/>
|
||||
<constraint firstAttribute="trailing" secondItem="lMN-Bl-G9Q" secondAttribute="trailing" id="oth-5X-F9R"/>
|
||||
<constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="xI5-lx-RD8" secondAttribute="trailing" constant="6" id="pbD-LN-Gk1"/>
|
||||
<constraint firstAttribute="trailing" secondItem="EAt-cc-a4X" secondAttribute="trailing" id="yWN-Th-puZ"/>
|
||||
<constraint firstAttribute="bottom" secondItem="xI5-lx-RD8" secondAttribute="bottom" constant="2" id="zsv-B0-ChW"/>
|
||||
</constraints>
|
||||
<connections>
|
||||
<outlet property="detailStatusBarView" destination="xI5-lx-RD8" id="yIZ-aP-fKF"/>
|
||||
<outlet property="findBarContainerView" destination="lMN-Bl-G9Q" id="zMP-iV-uSN"/>
|
||||
<outlet property="findBarHeightConstraint" destination="C1e-J5-baX" id="Q4g-LU-JWK"/>
|
||||
</connections>
|
||||
<viewLayoutGuide key="safeArea" id="kji-Gx-zvn"/>
|
||||
<viewLayoutGuide key="layoutMargins" id="Nri-tr-pWM"/>
|
||||
</customView>
|
||||
<connections>
|
||||
<outlet property="containerView" destination="cJ9-6s-66u" id="gXc-Pz-9sQ"/>
|
||||
<outlet property="containerView" destination="EAt-cc-a4X" id="oqf-yI-VIb"/>
|
||||
<outlet property="statusBarView" destination="xI5-lx-RD8" id="meP-4g-U63"/>
|
||||
</connections>
|
||||
</viewController>
|
||||
|
||||
@@ -30,11 +30,10 @@ final class DetailContainerView: NSView, NSTextFinderBarContainer {
|
||||
contentView.translatesAutoresizingMaskIntoConstraints = false
|
||||
addSubview(contentView, positioned: .below, relativeTo: detailStatusBarView)
|
||||
|
||||
// Constrain the content view to fill the available space on all sides except the top, which we'll constrain to the find bar
|
||||
var constraints = constraintsToMakeSubViewFullSize(contentView).filter { $0.firstAttribute != .top }
|
||||
// Constrain the content view to fill the available space on all sides
|
||||
var constraints = constraintsToMakeSubViewFullSize(contentView)
|
||||
|
||||
constraints.append(findBarContainerView.topAnchor.constraint(equalTo: self.safeAreaLayoutGuide.topAnchor))
|
||||
constraints.append(findBarContainerView.bottomAnchor.constraint(equalTo: contentView.topAnchor))
|
||||
NSLayoutConstraint.activate(constraints)
|
||||
contentViewConstraints = constraints
|
||||
}
|
||||
|
||||
@@ -299,7 +299,6 @@
|
||||
51A1699B235E10D700EB091F /* AccountInspectorViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51A16991235E10D600EB091F /* AccountInspectorViewController.swift */; };
|
||||
51A1699C235E10D700EB091F /* AddAccountViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51A16992235E10D600EB091F /* AddAccountViewController.swift */; };
|
||||
51A1699D235E10D700EB091F /* SettingsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51A16993235E10D600EB091F /* SettingsViewController.swift */; };
|
||||
51A1699F235E10D700EB091F /* AboutViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51A16995235E10D600EB091F /* AboutViewController.swift */; };
|
||||
51A169A0235E10D700EB091F /* FeedbinAccountViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51A16996235E10D700EB091F /* FeedbinAccountViewController.swift */; };
|
||||
51A66685238075AE00CB272D /* AddWebFeedDefaultContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51A66684238075AE00CB272D /* AddWebFeedDefaultContainer.swift */; };
|
||||
51A737AE24DB19730015FA66 /* RSCore in Frameworks */ = {isa = PBXBuildFile; productRef = 51A737AD24DB19730015FA66 /* RSCore */; };
|
||||
@@ -439,10 +438,6 @@
|
||||
51EF0F7E2277A57D0050506E /* MasterTimelineAccessibilityCellLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51EF0F7D2277A57D0050506E /* MasterTimelineAccessibilityCellLayout.swift */; };
|
||||
51EF0F802277A8330050506E /* MasterTimelineCellLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51EF0F7F2277A8330050506E /* MasterTimelineCellLayout.swift */; };
|
||||
51EFDA1B24E6D16A0085C3D6 /* SafariExt.js in Resources */ = {isa = PBXBuildFile; fileRef = 515D4FCB2325815A00EE1167 /* SafariExt.js */; };
|
||||
51F85BEB22724CB600C787DC /* About.rtf in Resources */ = {isa = PBXBuildFile; fileRef = 51F85BEA22724CB600C787DC /* About.rtf */; };
|
||||
51F85BEF2272520B00C787DC /* Thanks.rtf in Resources */ = {isa = PBXBuildFile; fileRef = 51F85BEE2272520B00C787DC /* Thanks.rtf */; };
|
||||
51F85BF12272524100C787DC /* Credits.rtf in Resources */ = {isa = PBXBuildFile; fileRef = 51F85BF02272524100C787DC /* Credits.rtf */; };
|
||||
51F85BF32272531500C787DC /* Dedication.rtf in Resources */ = {isa = PBXBuildFile; fileRef = 51F85BF22272531500C787DC /* Dedication.rtf */; };
|
||||
51F85BF52273625800C787DC /* Bundle-Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51F85BF42273625800C787DC /* Bundle-Extensions.swift */; };
|
||||
51F85BF722749FA100C787DC /* UIFont-Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51F85BF622749FA100C787DC /* UIFont-Extensions.swift */; };
|
||||
51F85BF92274AA7B00C787DC /* UIBarButtonItem-Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51F85BF82274AA7B00C787DC /* UIBarButtonItem-Extensions.swift */; };
|
||||
@@ -857,10 +852,14 @@
|
||||
DDF9E1D828EDF2FC000BC355 /* notificationSoundBlip.mp3 in Resources */ = {isa = PBXBuildFile; fileRef = DDF9E1D628EDF2FC000BC355 /* notificationSoundBlip.mp3 */; };
|
||||
DDF9E1D928EDF2FC000BC355 /* notificationSoundBlip.mp3 in Resources */ = {isa = PBXBuildFile; fileRef = DDF9E1D628EDF2FC000BC355 /* notificationSoundBlip.mp3 */; };
|
||||
DF5AD10128D6922200CA3BF7 /* SmartFeedSummaryWidget.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1768144D2564BCE000D98635 /* SmartFeedSummaryWidget.swift */; };
|
||||
DF790D6028E9769300455FC7 /* Thanks.md in Resources */ = {isa = PBXBuildFile; fileRef = DF790D5F28E9769300455FC7 /* Thanks.md */; };
|
||||
DF790D6228E990A900455FC7 /* AboutData.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF790D6128E990A900455FC7 /* AboutData.swift */; };
|
||||
DFD6AACF27ADE86E00463FAD /* NewsFax.nnwtheme in Resources */ = {isa = PBXBuildFile; fileRef = DFD6AACD27ADE86E00463FAD /* NewsFax.nnwtheme */; };
|
||||
DFFB8FC2279B75E300AC21D7 /* Account in Embed Frameworks */ = {isa = PBXBuildFile; productRef = 51BC2F4A24D343A500E90810 /* Account */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; };
|
||||
DFFC199827A0D0D7004B7AEF /* NotificationsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DFFC199727A0D0D7004B7AEF /* NotificationsViewController.swift */; };
|
||||
DFFC199A27A0D32A004B7AEF /* NotificationsTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = DFFC199927A0D32A004B7AEF /* NotificationsTableViewCell.swift */; };
|
||||
DFFC4E7428E95C01006B82AF /* AboutView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DFFC4E7328E95C01006B82AF /* AboutView.swift */; };
|
||||
DFFC4E7628E95F78006B82AF /* About.plist in Resources */ = {isa = PBXBuildFile; fileRef = DFFC4E7528E95F78006B82AF /* About.plist */; };
|
||||
FF3ABF13232599810074C542 /* ArticleSorterTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF3ABF09232599450074C542 /* ArticleSorterTests.swift */; };
|
||||
FF3ABF1523259DDB0074C542 /* ArticleSorter.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF3ABF1423259DDB0074C542 /* ArticleSorter.swift */; };
|
||||
FF3ABF162325AF5D0074C542 /* ArticleSorter.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF3ABF1423259DDB0074C542 /* ArticleSorter.swift */; };
|
||||
@@ -1298,7 +1297,6 @@
|
||||
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>"; };
|
||||
51A16993235E10D600EB091F /* SettingsViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SettingsViewController.swift; sourceTree = "<group>"; };
|
||||
51A16995235E10D600EB091F /* AboutViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AboutViewController.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>"; };
|
||||
51A9A5E32380C8870033AADF /* ShareFolderPickerAccountCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = ShareFolderPickerAccountCell.xib; sourceTree = "<group>"; };
|
||||
@@ -1374,10 +1372,6 @@
|
||||
51EF0F7F2277A8330050506E /* MasterTimelineCellLayout.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MasterTimelineCellLayout.swift; sourceTree = "<group>"; };
|
||||
51F805D32428499E0022C792 /* NetNewsWire-dev.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = "NetNewsWire-dev.entitlements"; sourceTree = "<group>"; };
|
||||
51F805ED24284C1C0022C792 /* NetNewsWire-dev.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = "NetNewsWire-dev.entitlements"; sourceTree = "<group>"; };
|
||||
51F85BEA22724CB600C787DC /* About.rtf */ = {isa = PBXFileReference; lastKnownFileType = text.rtf; path = About.rtf; sourceTree = "<group>"; };
|
||||
51F85BEE2272520B00C787DC /* Thanks.rtf */ = {isa = PBXFileReference; lastKnownFileType = text.rtf; path = Thanks.rtf; sourceTree = "<group>"; };
|
||||
51F85BF02272524100C787DC /* Credits.rtf */ = {isa = PBXFileReference; lastKnownFileType = text.rtf; path = Credits.rtf; sourceTree = "<group>"; };
|
||||
51F85BF22272531500C787DC /* Dedication.rtf */ = {isa = PBXFileReference; lastKnownFileType = text.rtf; path = Dedication.rtf; sourceTree = "<group>"; };
|
||||
51F85BF42273625800C787DC /* Bundle-Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Bundle-Extensions.swift"; sourceTree = "<group>"; };
|
||||
51F85BF622749FA100C787DC /* UIFont-Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIFont-Extensions.swift"; sourceTree = "<group>"; };
|
||||
51F85BF82274AA7B00C787DC /* UIBarButtonItem-Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIBarButtonItem-Extensions.swift"; sourceTree = "<group>"; };
|
||||
@@ -1599,10 +1593,14 @@
|
||||
D5F4EDB820074D7C00B9E363 /* Folder+Scriptability.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Folder+Scriptability.swift"; sourceTree = "<group>"; };
|
||||
DD82AB09231003F6002269DF /* SharingTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SharingTests.swift; sourceTree = "<group>"; };
|
||||
DDF9E1D628EDF2FC000BC355 /* notificationSoundBlip.mp3 */ = {isa = PBXFileReference; lastKnownFileType = audio.mp3; path = notificationSoundBlip.mp3; sourceTree = "<group>"; };
|
||||
DF790D5F28E9769300455FC7 /* Thanks.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = Thanks.md; sourceTree = "<group>"; };
|
||||
DF790D6128E990A900455FC7 /* AboutData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AboutData.swift; sourceTree = "<group>"; };
|
||||
DFD6AACB27ADE80900463FAD /* NewsFax.nnwtheme */ = {isa = PBXFileReference; lastKnownFileType = wrapper; path = NewsFax.nnwtheme; sourceTree = "<group>"; };
|
||||
DFD6AACD27ADE86E00463FAD /* NewsFax.nnwtheme */ = {isa = PBXFileReference; lastKnownFileType = wrapper; path = NewsFax.nnwtheme; sourceTree = "<group>"; };
|
||||
DFFC199727A0D0D7004B7AEF /* NotificationsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationsViewController.swift; sourceTree = "<group>"; };
|
||||
DFFC199927A0D32A004B7AEF /* NotificationsTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationsTableViewCell.swift; sourceTree = "<group>"; };
|
||||
DFFC4E7328E95C01006B82AF /* AboutView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AboutView.swift; sourceTree = "<group>"; };
|
||||
DFFC4E7528E95F78006B82AF /* About.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = About.plist; sourceTree = "<group>"; };
|
||||
FF3ABF09232599450074C542 /* ArticleSorterTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ArticleSorterTests.swift; sourceTree = "<group>"; };
|
||||
FF3ABF1423259DDB0074C542 /* ArticleSorter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ArticleSorter.swift; sourceTree = "<group>"; };
|
||||
FFD43E372340F320009E5CA3 /* MarkAsReadAlertController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MarkAsReadAlertController.swift; sourceTree = "<group>"; };
|
||||
@@ -1996,7 +1994,8 @@
|
||||
5183CCEB227117C70010922C /* Settings */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
51A16995235E10D600EB091F /* AboutViewController.swift */,
|
||||
DFFC4E7328E95C01006B82AF /* AboutView.swift */,
|
||||
DF790D6128E990A900455FC7 /* AboutData.swift */,
|
||||
51A16992235E10D600EB091F /* AddAccountViewController.swift */,
|
||||
519ED455244828C3007F8E94 /* AddExtensionPointViewController.swift */,
|
||||
5137C2E926F63AE6009EFEDB /* ArticleThemeImporter.swift */,
|
||||
@@ -2736,10 +2735,8 @@
|
||||
84C9FC9A2262A1A900D921D6 /* Resources */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
51F85BEA22724CB600C787DC /* About.rtf */,
|
||||
51F85BF02272524100C787DC /* Credits.rtf */,
|
||||
51F85BEE2272520B00C787DC /* Thanks.rtf */,
|
||||
51F85BF22272531500C787DC /* Dedication.rtf */,
|
||||
DFFC4E7528E95F78006B82AF /* About.plist */,
|
||||
DF790D5F28E9769300455FC7 /* Thanks.md */,
|
||||
5103A9B324216A4200410853 /* blank.html */,
|
||||
51BB7C302335ACDE008E8144 /* page.html */,
|
||||
514219572353C28900E07E2C /* main_ios.js */,
|
||||
@@ -3444,11 +3441,11 @@
|
||||
51C452862265093600C03939 /* Add.storyboard in Resources */,
|
||||
511D43EF231FBDE900FB1562 /* LaunchScreenPad.storyboard in Resources */,
|
||||
511D43D2231FA62C00FB1562 /* GlobalKeyboardShortcuts.plist in Resources */,
|
||||
DFFC4E7628E95F78006B82AF /* About.plist in Resources */,
|
||||
84C9FCA12262A1B300D921D6 /* Main.storyboard in Resources */,
|
||||
51BB7C312335ACDE008E8144 /* page.html in Resources */,
|
||||
512392C324E3451400F11704 /* TwitterAdd.storyboard in Resources */,
|
||||
516A093723609A3600EAE89B /* SettingsComboTableViewCell.xib in Resources */,
|
||||
51F85BF32272531500C787DC /* Dedication.rtf in Resources */,
|
||||
51077C5A27A86D16000C71DB /* Hyperlegible.nnwtheme in Resources */,
|
||||
516A09422361248000EAE89B /* Inspector.storyboard in Resources */,
|
||||
DDF9E1D928EDF2FC000BC355 /* notificationSoundBlip.mp3 in Resources */,
|
||||
@@ -3457,19 +3454,17 @@
|
||||
5103A9B424216A4200410853 /* blank.html in Resources */,
|
||||
51D0214826ED617100FF2E0F /* core.css in Resources */,
|
||||
84C9FCA42262A1B800D921D6 /* LaunchScreenPhone.storyboard in Resources */,
|
||||
51F85BEB22724CB600C787DC /* About.rtf in Resources */,
|
||||
516A093B2360A4A000EAE89B /* SettingsTableViewCell.xib in Resources */,
|
||||
511D43D1231FA62800FB1562 /* SidebarKeyboardShortcuts.plist in Resources */,
|
||||
516A09402361240900EAE89B /* Account.storyboard in Resources */,
|
||||
51C452AB22650DC600C03939 /* template.html in Resources */,
|
||||
51F85BF12272524100C787DC /* Credits.rtf in Resources */,
|
||||
84A3EE61223B667F00557320 /* DefaultFeeds.opml in Resources */,
|
||||
B27EEBFB244D15F3000932E6 /* stylesheet.css in Resources */,
|
||||
511D43CF231FA62200FB1562 /* DetailKeyboardShortcuts.plist in Resources */,
|
||||
51A1699A235E10D700EB091F /* Settings.storyboard in Resources */,
|
||||
49F40DF92335B71000552BF4 /* newsfoot.js in Resources */,
|
||||
512392C024E33A3C00F11704 /* RedditAdd.storyboard in Resources */,
|
||||
51F85BEF2272520B00C787DC /* Thanks.rtf in Resources */,
|
||||
DF790D6028E9769300455FC7 /* Thanks.md in Resources */,
|
||||
5177C21327B07CFE00643901 /* NewsFax.nnwtheme in Resources */,
|
||||
51CE1C0923621EDA005548FC /* RefreshProgressView.xib in Resources */,
|
||||
84C9FC9D2262A1A900D921D6 /* Assets.xcassets in Resources */,
|
||||
@@ -4079,6 +4074,7 @@
|
||||
51C4525C226508DF00C03939 /* String-Extensions.swift in Sources */,
|
||||
51F9F3F923DFB16300A314FD /* UITableView-Extensions.swift in Sources */,
|
||||
51C452792265091600C03939 /* MasterTimelineTableViewCell.swift in Sources */,
|
||||
DFFC4E7428E95C01006B82AF /* AboutView.swift in Sources */,
|
||||
51C4526B226508F600C03939 /* MasterFeedViewController.swift in Sources */,
|
||||
5126EE97226CB48A00C22AFC /* SceneCoordinator.swift in Sources */,
|
||||
84CAFCB022BC8C35007694F0 /* FetchRequestOperation.swift in Sources */,
|
||||
@@ -4089,6 +4085,7 @@
|
||||
517A745B2443665000B553B9 /* UIPageViewController-Extensions.swift in Sources */,
|
||||
51BB7C272335A8E5008E8144 /* ArticleActivityItemSource.swift in Sources */,
|
||||
51F85BF52273625800C787DC /* Bundle-Extensions.swift in Sources */,
|
||||
DF790D6228E990A900455FC7 /* AboutData.swift in Sources */,
|
||||
177A0C2D25454AAB00D7EAF6 /* ReaderAPIAccountViewController.swift in Sources */,
|
||||
51C452A622650A3500C03939 /* Node-Extensions.swift in Sources */,
|
||||
51C45294226509C800C03939 /* SearchFeedDelegate.swift in Sources */,
|
||||
@@ -4145,7 +4142,6 @@
|
||||
512AF9C2236ED52C0066F8BE /* ImageHeaderView.swift in Sources */,
|
||||
512392C124E33A3C00F11704 /* RedditSelectTypeTableViewController.swift in Sources */,
|
||||
515A5181243E90260089E588 /* ExtensionPointIdentifer.swift in Sources */,
|
||||
51A1699F235E10D700EB091F /* AboutViewController.swift in Sources */,
|
||||
51C45290226509C100C03939 /* PseudoFeed.swift in Sources */,
|
||||
512392C624E3451400F11704 /* TwitterSelectAccountTableViewController.swift in Sources */,
|
||||
51C452A922650DC600C03939 /* ArticleRenderer.swift in Sources */,
|
||||
|
||||
@@ -96,8 +96,8 @@
|
||||
"repositoryURL": "https://github.com/Ranchero-Software/RSWeb.git",
|
||||
"state": {
|
||||
"branch": null,
|
||||
"revision": "2f7849a9ad2cb461b3d6c9c920e163596e6b5d7b",
|
||||
"version": "1.0.3"
|
||||
"revision": "a69f0d74c8f7bc4abdad5407aafca471fc3277f1",
|
||||
"version": "1.0.5"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
@@ -31,19 +31,18 @@ final class ArticleThemesManager: NSObject, NSFilePresenter, Logging {
|
||||
set {
|
||||
if newValue != currentThemeName {
|
||||
AppDefaults.shared.currentThemeName = newValue
|
||||
updateThemeNames()
|
||||
updateCurrentTheme()
|
||||
currentTheme = articleThemeWithThemeName(newValue)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var currentTheme: ArticleTheme {
|
||||
lazy var currentTheme = { articleThemeWithThemeName(currentThemeName) }() {
|
||||
didSet {
|
||||
NotificationCenter.default.post(name: .CurrentArticleThemeDidChangeNotification, object: self)
|
||||
}
|
||||
}
|
||||
|
||||
var themeNames = [AppDefaults.defaultThemeName] {
|
||||
lazy var themeNames = { buildThemeNames() }() {
|
||||
didSet {
|
||||
NotificationCenter.default.post(name: .ArticleThemeNamesDidChangeNotification, object: self)
|
||||
}
|
||||
@@ -51,7 +50,6 @@ final class ArticleThemesManager: NSObject, NSFilePresenter, Logging {
|
||||
|
||||
init(folderPath: String) {
|
||||
self.folderPath = folderPath
|
||||
self.currentTheme = ArticleTheme.defaultTheme
|
||||
|
||||
super.init()
|
||||
|
||||
@@ -63,15 +61,12 @@ final class ArticleThemesManager: NSObject, NSFilePresenter, Logging {
|
||||
abort()
|
||||
}
|
||||
|
||||
updateThemeNames()
|
||||
updateCurrentTheme()
|
||||
|
||||
NSFileCoordinator.addFilePresenter(self)
|
||||
}
|
||||
|
||||
func presentedSubitemDidChange(at url: URL) {
|
||||
updateThemeNames()
|
||||
updateCurrentTheme()
|
||||
themeNames = buildThemeNames()
|
||||
currentTheme = articleThemeWithThemeName(currentThemeName)
|
||||
}
|
||||
|
||||
// MARK: API
|
||||
@@ -93,7 +88,7 @@ final class ArticleThemesManager: NSObject, NSFilePresenter, Logging {
|
||||
try FileManager.default.copyItem(atPath: filename, toPath: toFilename)
|
||||
}
|
||||
|
||||
func articleThemeWithThemeName(_ themeName: String) -> ArticleTheme? {
|
||||
func articleThemeWithThemeName(_ themeName: String) -> ArticleTheme {
|
||||
if themeName == AppDefaults.defaultThemeName {
|
||||
return ArticleTheme.defaultTheme
|
||||
}
|
||||
@@ -107,7 +102,7 @@ final class ArticleThemesManager: NSObject, NSFilePresenter, Logging {
|
||||
path = installedPath
|
||||
isAppTheme = false
|
||||
} else {
|
||||
return nil
|
||||
return ArticleTheme.defaultTheme
|
||||
}
|
||||
|
||||
do {
|
||||
@@ -115,7 +110,7 @@ final class ArticleThemesManager: NSObject, NSFilePresenter, Logging {
|
||||
} catch {
|
||||
NotificationCenter.default.post(name: .didFailToImportThemeWithError, object: nil, userInfo: ["error": error])
|
||||
logger.error("Failed to import theme: \(error.localizedDescription, privacy: .public)")
|
||||
return nil
|
||||
return ArticleTheme.defaultTheme
|
||||
}
|
||||
|
||||
}
|
||||
@@ -132,7 +127,7 @@ final class ArticleThemesManager: NSObject, NSFilePresenter, Logging {
|
||||
|
||||
private extension ArticleThemesManager {
|
||||
|
||||
func updateThemeNames() {
|
||||
func buildThemeNames() -> [String] {
|
||||
let appThemeFilenames = Bundle.main.paths(forResourcesOfType: ArticleTheme.nnwThemeSuffix, inDirectory: nil)
|
||||
let appThemeNames = Set(appThemeFilenames.map { ArticleTheme.themeNameForPath($0) })
|
||||
|
||||
@@ -140,32 +135,7 @@ private extension ArticleThemesManager {
|
||||
|
||||
let allThemeNames = appThemeNames.union(installedThemeNames)
|
||||
|
||||
let sortedThemeNames = allThemeNames.sorted(by: { $0.compare($1, options: .caseInsensitive) == .orderedAscending })
|
||||
if sortedThemeNames != themeNames {
|
||||
themeNames = sortedThemeNames
|
||||
}
|
||||
}
|
||||
|
||||
func defaultArticleTheme() -> ArticleTheme {
|
||||
return articleThemeWithThemeName(AppDefaults.defaultThemeName)!
|
||||
}
|
||||
|
||||
func updateCurrentTheme() {
|
||||
var themeName = currentThemeName
|
||||
if !themeNames.contains(themeName) {
|
||||
themeName = AppDefaults.defaultThemeName
|
||||
currentThemeName = AppDefaults.defaultThemeName
|
||||
}
|
||||
|
||||
var articleTheme = articleThemeWithThemeName(themeName)
|
||||
if articleTheme == nil {
|
||||
articleTheme = defaultArticleTheme()
|
||||
currentThemeName = AppDefaults.defaultThemeName
|
||||
}
|
||||
|
||||
if let articleTheme = articleTheme, articleTheme != currentTheme {
|
||||
currentTheme = articleTheme
|
||||
}
|
||||
return allThemeNames.sorted(by: { $0.compare($1, options: .caseInsensitive) == .orderedAscending })
|
||||
}
|
||||
|
||||
func allThemePaths(_ folder: String) -> [String] {
|
||||
|
||||
@@ -11,20 +11,10 @@ import AppKit
|
||||
extension NSView {
|
||||
|
||||
func constraintsToMakeSubViewFullSize(_ subview: NSView) -> [NSLayoutConstraint] {
|
||||
|
||||
if #available(macOS 11, *) {
|
||||
let leadingConstraint = NSLayoutConstraint(item: subview, attribute: .leading, relatedBy: .equal, toItem: self.safeAreaLayoutGuide, attribute: .leading, multiplier: 1.0, constant: 0.0)
|
||||
let trailingConstraint = NSLayoutConstraint(item: subview, attribute: .trailing, relatedBy: .equal, toItem: self.safeAreaLayoutGuide, attribute: .trailing, multiplier: 1.0, constant: 0.0)
|
||||
let topConstraint = NSLayoutConstraint(item: subview, attribute: .top, relatedBy: .equal, toItem: self.safeAreaLayoutGuide, attribute: .top, multiplier: 1.0, constant: 0.0)
|
||||
let bottomConstraint = NSLayoutConstraint(item: subview, attribute: .bottom, relatedBy: .equal, toItem: self.safeAreaLayoutGuide, attribute: .bottom, multiplier: 1.0, constant: 0.0)
|
||||
return [leadingConstraint, trailingConstraint, topConstraint, bottomConstraint]
|
||||
} else {
|
||||
let leadingConstraint = NSLayoutConstraint(item: subview, attribute: .leading, relatedBy: .equal, toItem: self, attribute: .leading, multiplier: 1.0, constant: 0.0)
|
||||
let trailingConstraint = NSLayoutConstraint(item: subview, attribute: .trailing, relatedBy: .equal, toItem: self, attribute: .trailing, multiplier: 1.0, constant: 0.0)
|
||||
let topConstraint = NSLayoutConstraint(item: subview, attribute: .top, relatedBy: .equal, toItem: self, attribute: .top, multiplier: 1.0, constant: 0.0)
|
||||
let bottomConstraint = NSLayoutConstraint(item: subview, attribute: .bottom, relatedBy: .equal, toItem: self, attribute: .bottom, multiplier: 1.0, constant: 0.0)
|
||||
return [leadingConstraint, trailingConstraint, topConstraint, bottomConstraint]
|
||||
}
|
||||
|
||||
let leadingConstraint = NSLayoutConstraint(item: subview, attribute: .leading, relatedBy: .equal, toItem: self, attribute: .leading, multiplier: 1.0, constant: 0.0)
|
||||
let trailingConstraint = NSLayoutConstraint(item: subview, attribute: .trailing, relatedBy: .equal, toItem: self, attribute: .trailing, multiplier: 1.0, constant: 0.0)
|
||||
let topConstraint = NSLayoutConstraint(item: subview, attribute: .top, relatedBy: .equal, toItem: self, attribute: .top, multiplier: 1.0, constant: 0.0)
|
||||
let bottomConstraint = NSLayoutConstraint(item: subview, attribute: .bottom, relatedBy: .equal, toItem: self, attribute: .bottom, multiplier: 1.0, constant: 0.0)
|
||||
return [leadingConstraint, trailingConstraint, topConstraint, bottomConstraint]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -102,7 +102,6 @@ class ArticleViewController: UIViewController, MainControllerIdentifiable {
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(willEnterForeground(_:)), name: UIApplication.willEnterForegroundNotification, object: nil)
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(reloadDueToThemeChange(_:)), name: .CurrentArticleThemeDidChangeNotification, object: nil)
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(configureAppearanceMenu(_:)), name: .ArticleThemeNamesDidChangeNotification, object: nil)
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(updateUnreadCountIndicator(_:)), name: UIDevice.orientationDidChangeNotification, object: nil)
|
||||
|
||||
articleExtractorButton.addTarget(self, action: #selector(toggleArticleExtractor(_:)), for: .touchUpInside)
|
||||
toolbarItems?.insert(UIBarButtonItem(customView: articleExtractorButton), at: 6)
|
||||
@@ -349,9 +348,8 @@ class ArticleViewController: UIViewController, MainControllerIdentifiable {
|
||||
/// For iPad, this indicator is visible if it is in `portrait` or `unknown`
|
||||
/// orientation, **and** the unread count is > 0.
|
||||
/// - Parameter sender: `Any` (optional)
|
||||
@objc
|
||||
public func updateUnreadCountIndicator(_ sender: Any? = nil) {
|
||||
if UIDevice.current.userInterfaceIdiom == .phone {
|
||||
public func updateUnreadCountIndicator(forDisplayMode displayMode: UISplitViewController.DisplayMode? = nil) {
|
||||
func changeUnreadCountIndicator() {
|
||||
if currentUnreadCount > 0 {
|
||||
let unreadCountView = MasterTimelineUnreadCountView(frame: .zero)
|
||||
unreadCountView.unreadCount = currentUnreadCount
|
||||
@@ -360,17 +358,13 @@ class ArticleViewController: UIViewController, MainControllerIdentifiable {
|
||||
} else {
|
||||
navigationItem.leftBarButtonItem = nil
|
||||
}
|
||||
}
|
||||
|
||||
if UIDevice.current.userInterfaceIdiom == .phone {
|
||||
changeUnreadCountIndicator()
|
||||
} else {
|
||||
|
||||
if UIDevice.current.orientation.isPortrait || !UIDevice.current.orientation.isValidInterfaceOrientation {
|
||||
if currentUnreadCount > 0 {
|
||||
let unreadCountView = MasterTimelineUnreadCountView(frame: .zero)
|
||||
unreadCountView.unreadCount = currentUnreadCount
|
||||
unreadCountView.setFrameIfNotEqual(CGRect(x: 0, y: 0, width: unreadCountView.intrinsicContentSize.width, height: unreadCountView.intrinsicContentSize.height))
|
||||
navigationItem.leftBarButtonItem = UIBarButtonItem(customView: unreadCountView)
|
||||
} else {
|
||||
navigationItem.leftBarButtonItem = nil
|
||||
}
|
||||
if displayMode == nil || displayMode == .secondaryOnly {
|
||||
changeUnreadCountIndicator()
|
||||
} else {
|
||||
navigationItem.leftBarButtonItem = nil
|
||||
}
|
||||
|
||||
110
iOS/Resources/About.plist
Normal file
110
iOS/Resources/About.plist
Normal file
@@ -0,0 +1,110 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>AppCredits</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>role</key>
|
||||
<string>Lead Developer</string>
|
||||
<key>name</key>
|
||||
<string>Maurice Parker</string>
|
||||
<key>url</key>
|
||||
<string>https://vincode.io</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>url</key>
|
||||
<string>https://twitter.com/BradEllis</string>
|
||||
<key>name</key>
|
||||
<string>Brad Ellis</string>
|
||||
<key>role</key>
|
||||
<string>App Icon</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>url</key>
|
||||
<string>https://twitter.com/kielgillard</string>
|
||||
<key>name</key>
|
||||
<string>Kiel Gillard</string>
|
||||
<key>role</key>
|
||||
<string>Feedly Syncing</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>url</key>
|
||||
<string>https://twitter.com/quanganhdo</string>
|
||||
<key>name</key>
|
||||
<string>Anh Do</string>
|
||||
<key>role</key>
|
||||
<string>NewsBlur Syncing</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>url</key>
|
||||
<string>https://github.com/wevah</string>
|
||||
<key>name</key>
|
||||
<string>Nate Weaver</string>
|
||||
<key>role</key>
|
||||
<string>Under-the-hood magic and CSS stylin’s</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>url</key>
|
||||
<string>https://github.com/brehaut/</string>
|
||||
<key>name</key>
|
||||
<string>Andrew Brehaut</string>
|
||||
<key>role</key>
|
||||
<string>Newsfoot (JS footnote displayer)</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>url</key>
|
||||
<string>https://nostodnayr.net</string>
|
||||
<key>name</key>
|
||||
<string>Ryan Dotson</string>
|
||||
<key>role</key>
|
||||
<string>Help Book</string>
|
||||
</dict>
|
||||
</array>
|
||||
<key>AdditionalContributors</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>Daniel Jalkut</string>
|
||||
<key>url</key>
|
||||
<string>https://github.com/danielpunkass</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>Joe Heck</string>
|
||||
<key>url</key>
|
||||
<string>https://rhonabwy.com</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>Olof Hellman</string>
|
||||
<key>url</key>
|
||||
<string>https://github.com/olofhellman</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>Rizwan Mohamed Ibrahim</string>
|
||||
<key>url</key>
|
||||
<string>https://blog.rizwan.dev/</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>Stuart Breckenridge</string>
|
||||
<key>url</key>
|
||||
<string>https://stuartbreckenridge.net</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>Phil Viso</string>
|
||||
<key>url</key>
|
||||
<string>https://twitter.com/philviso</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>...and many more</string>
|
||||
<key>url</key>
|
||||
<string>https://github.com/Ranchero-Software/NetNewsWire/graphs/contributors</string>
|
||||
</dict>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -1,12 +0,0 @@
|
||||
{\rtf1\ansi\ansicpg1252\cocoartf2513
|
||||
\cocoatextscaling0\cocoaplatform0{\fonttbl\f0\fnil\fcharset0 LucidaGrande-Bold;}
|
||||
{\colortbl;\red255\green255\blue255;\red0\green0\blue0;\red10\green96\blue255;}
|
||||
{\*\expandedcolortbl;;\cssrgb\c0\c0\c0;\cssrgb\c0\c47843\c100000\cname systemBlueColor;}
|
||||
\margl1440\margr1440\vieww8340\viewh9300\viewkind0
|
||||
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\li363\fi-364\pardirnatural\partightenfactor0
|
||||
|
||||
\f0\b\fs28 \cf2 By Brent Simmons and the Ranchero Software team
|
||||
\fs22 \
|
||||
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\partightenfactor0
|
||||
{\field{\*\fldinst{HYPERLINK "https://netnewswire.com/"}}{\fldrslt
|
||||
\fs28 \cf3 netnewswire.com}}}
|
||||
BIN
iOS/Resources/Assets.xcassets/About.imageset/AppIcon-1024px 1.png
vendored
Normal file
BIN
iOS/Resources/Assets.xcassets/About.imageset/AppIcon-1024px 1.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 930 KiB |
BIN
iOS/Resources/Assets.xcassets/About.imageset/AppIcon-1024px.png
vendored
Normal file
BIN
iOS/Resources/Assets.xcassets/About.imageset/AppIcon-1024px.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 930 KiB |
22
iOS/Resources/Assets.xcassets/About.imageset/Contents.json
vendored
Normal file
22
iOS/Resources/Assets.xcassets/About.imageset/Contents.json
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"filename" : "AppIcon-1024px 1.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"filename" : "AppIcon-1024px.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
{\rtf1\ansi\ansicpg1252\cocoartf2513
|
||||
\cocoatextscaling0\cocoaplatform0{\fonttbl\f0\fnil\fcharset0 LucidaGrande;}
|
||||
{\colortbl;\red255\green255\blue255;\red0\green0\blue0;}
|
||||
{\*\expandedcolortbl;;\cssrgb\c0\c0\c0\cname textColor;}
|
||||
\margl1440\margr1440\vieww14220\viewh13280\viewkind0
|
||||
\deftab720
|
||||
\pard\pardeftab720\sa60\partightenfactor0
|
||||
|
||||
\f0\fs22 \cf2 Lead developer: {\field{\*\fldinst{HYPERLINK "https://github.com/vincode-io"}}{\fldrslt Maurice Parker}}\
|
||||
App icon: {\field{\*\fldinst{HYPERLINK "https://twitter.com/BradEllis"}}{\fldrslt Brad Ellis}}\
|
||||
Feedly syncing: {\field{\*\fldinst{HYPERLINK "https://twitter.com/kielgillard"}}{\fldrslt Kiel Gillard}}\
|
||||
NewsBlur syncing: {\field{\*\fldinst{HYPERLINK "https://twitter.com/quanganhdo"}}{\fldrslt Anh Do}}\
|
||||
Under-the-hood magic and CSS stylin\'92s: {\field{\*\fldinst{HYPERLINK "https://github.com/wevah"}}{\fldrslt Nate Weaver}}\
|
||||
Newsfoot (JS footnote displayer): {\field{\*\fldinst{HYPERLINK "https://github.com/brehaut/"}}{\fldrslt Andrew Brehaut}}\
|
||||
Help book: {\field{\*\fldinst{HYPERLINK "https://nostodnayr.net/"}}{\fldrslt Ryan Dotson}}\
|
||||
And featuring contributions from {\field{\*\fldinst{HYPERLINK "https://github.com/danielpunkass"}}{\fldrslt Daniel Jalkut}}, {\field{\*\fldinst{HYPERLINK "https://rhonabwy.com/"}}{\fldrslt Joe Heck}}, {\field{\*\fldinst{HYPERLINK "https://github.com/olofhellman"}}{\fldrslt Olof Hellman}}, {\field{\*\fldinst{HYPERLINK "https://blog.rizwan.dev/"}}{\fldrslt Rizwan Mohamed Ibrahim}}, {\field{\*\fldinst{HYPERLINK "https://mynameisstuart.com/"}}{\fldrslt Stuart Breckenridge}}, {\field{\*\fldinst{HYPERLINK "https://twitter.com/philviso"}}{\fldrslt Phil Viso}}, and {\field{\*\fldinst{HYPERLINK "https://github.com/Ranchero-Software/NetNewsWire/graphs/contributors"}}{\fldrslt many more}}!\
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
{\rtf1\ansi\ansicpg1252\cocoartf2513
|
||||
\cocoatextscaling0\cocoaplatform0{\fonttbl\f0\fnil\fcharset0 LucidaGrande;}
|
||||
{\colortbl;\red255\green255\blue255;\red0\green0\blue0;}
|
||||
{\*\expandedcolortbl;;\cssrgb\c0\c0\c0\cname textColor;}
|
||||
\margl1440\margr1440\vieww9000\viewh8400\viewkind0
|
||||
\deftab720
|
||||
\pard\pardeftab720\sa60\partightenfactor0
|
||||
|
||||
\f0\fs22 \cf2 NetNewsWire 6 is dedicated to everyone working to save democracy around the world.}
|
||||
5
iOS/Resources/Thanks.md
Normal file
5
iOS/Resources/Thanks.md
Normal file
@@ -0,0 +1,5 @@
|
||||
Thanks to Sheila and my family; thanks to my friends in Seattle and around the globe; thanks to the ever-patient and ever-awesome NetNewsWire beta testers.
|
||||
|
||||
Thanks to [Gus Mueller](https://shapeof.com/) for [FMDB](https://github.com/ccgus/fmdb) by [Flying Meat Software](http://flyingmeat.com/). Thanks to [GitHub](https://github.com) and [Slack](https://slack.com) for making open source collaboration easy and fun. Thanks to [Ben Ubois](https://benubois.com/) at [Feedbin](https://feedbin.com/) for all the extra help with syncing and article rendering — and for [hosting the server for the Reader view](https://feedbin.com/blog/2019/03/11/the-future-of-full-content/).
|
||||
|
||||
NetNewsWire 6 is dedicated to everyone working to save democracy around the world.
|
||||
@@ -1,11 +0,0 @@
|
||||
{\rtf1\ansi\ansicpg1252\cocoartf2511
|
||||
\cocoatextscaling0\cocoaplatform0{\fonttbl\f0\fnil\fcharset0 LucidaGrande;}
|
||||
{\colortbl;\red255\green255\blue255;\red0\green0\blue0;}
|
||||
{\*\expandedcolortbl;;\cssrgb\c0\c0\c0\cname textColor;}
|
||||
\margl1440\margr1440\vieww11780\viewh11640\viewkind0
|
||||
\deftab720
|
||||
\pard\pardeftab720\li365\fi-366\sa60\partightenfactor0
|
||||
|
||||
\f0\fs22 \cf2 Thanks to Sheila and my family; thanks to my friends in Seattle and around the globe; thanks to the ever-patient and ever-awesome NetNewsWire beta testers. \
|
||||
\pard\tx0\pardeftab720\li360\fi-361\sa60\partightenfactor0
|
||||
\cf2 Thanks to {\field{\*\fldinst{HYPERLINK "https://shapeof.com/"}}{\fldrslt Gus Mueller}} for {\field{\*\fldinst{HYPERLINK "https://github.com/ccgus/fmdb"}}{\fldrslt FMDB}} by {\field{\*\fldinst{HYPERLINK "http://flyingmeat.com/"}}{\fldrslt Flying Meat Software}}. Thanks to {\field{\*\fldinst{HYPERLINK "https://github.com"}}{\fldrslt GitHub}} and {\field{\*\fldinst{HYPERLINK "https://slack.com"}}{\fldrslt Slack}} for making open source collaboration easy and fun. Thanks to {\field{\*\fldinst{HYPERLINK "https://benubois.com/"}}{\fldrslt Ben Ubois}} at {\field{\*\fldinst{HYPERLINK "https://feedbin.com/"}}{\fldrslt Feedbin}} for all the extra help with syncing and article rendering \'97\'a0and for {\field{\*\fldinst{HYPERLINK "https://feedbin.com/blog/2019/03/11/the-future-of-full-content/"}}{\fldrslt hosting the server for the Reader view}}.}
|
||||
@@ -289,15 +289,24 @@ class SceneCoordinator: NSObject, UndoableCommandRunner, Logging {
|
||||
|
||||
self.masterFeedViewController = rootSplitViewController.viewController(for: .primary) as? MasterFeedViewController
|
||||
self.masterFeedViewController.coordinator = self
|
||||
self.masterFeedViewController?.navigationController?.delegate = self
|
||||
|
||||
if let navController = self.masterFeedViewController?.navigationController {
|
||||
navController.delegate = self
|
||||
configureNavigationController(navController)
|
||||
}
|
||||
|
||||
self.masterTimelineViewController = rootSplitViewController.viewController(for: .supplementary) as? MasterTimelineViewController
|
||||
self.masterTimelineViewController?.coordinator = self
|
||||
self.masterTimelineViewController?.navigationController?.delegate = self
|
||||
if let navController = self.masterTimelineViewController?.navigationController {
|
||||
navController.delegate = self
|
||||
configureNavigationController(navController)
|
||||
}
|
||||
|
||||
self.articleViewController = rootSplitViewController.viewController(for: .secondary) as? ArticleViewController
|
||||
self.articleViewController?.coordinator = self
|
||||
|
||||
if let navController = self.articleViewController?.navigationController {
|
||||
configureNavigationController(navController)
|
||||
}
|
||||
|
||||
for sectionNode in treeController.rootNode.childNodes {
|
||||
markExpanded(sectionNode)
|
||||
shadowTable.append((sectionID: "", feedNodes: [FeedNode]()))
|
||||
@@ -1314,6 +1323,10 @@ extension SceneCoordinator: UISplitViewControllerDelegate {
|
||||
}
|
||||
}
|
||||
|
||||
func splitViewController(_ svc: UISplitViewController, willChangeTo displayMode: UISplitViewController.DisplayMode) {
|
||||
articleViewController?.updateUnreadCountIndicator(forDisplayMode: displayMode)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// MARK: UINavigationControllerDelegate
|
||||
@@ -1370,6 +1383,31 @@ extension SceneCoordinator: UINavigationControllerDelegate {
|
||||
|
||||
private extension SceneCoordinator {
|
||||
|
||||
func configureNavigationController(_ navController: UINavigationController) {
|
||||
|
||||
let scrollEdge = UINavigationBarAppearance()
|
||||
scrollEdge.configureWithOpaqueBackground()
|
||||
scrollEdge.shadowColor = nil
|
||||
scrollEdge.shadowImage = UIImage()
|
||||
|
||||
let standard = UINavigationBarAppearance()
|
||||
standard.shadowColor = .opaqueSeparator
|
||||
standard.shadowImage = UIImage()
|
||||
|
||||
navController.navigationBar.standardAppearance = standard
|
||||
navController.navigationBar.compactAppearance = standard
|
||||
navController.navigationBar.scrollEdgeAppearance = scrollEdge
|
||||
navController.navigationBar.compactScrollEdgeAppearance = scrollEdge
|
||||
|
||||
navController.navigationBar.tintColor = AppAssets.primaryAccentColor
|
||||
|
||||
let toolbarAppearance = UIToolbarAppearance()
|
||||
navController.toolbar.standardAppearance = toolbarAppearance
|
||||
navController.toolbar.compactAppearance = toolbarAppearance
|
||||
navController.toolbar.scrollEdgeAppearance = toolbarAppearance
|
||||
navController.toolbar.tintColor = AppAssets.primaryAccentColor
|
||||
}
|
||||
|
||||
func markArticlesWithUndo(_ articles: [Article], statusKey: ArticleStatus.Key, flag: Bool, completion: (() -> Void)? = nil) {
|
||||
guard let undoManager = undoManager,
|
||||
let markReadCommand = MarkStatusCommand(initialArticles: articles, statusKey: statusKey, flag: flag, undoManager: undoManager, completion: completion) else {
|
||||
|
||||
@@ -28,6 +28,7 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate, Logging {
|
||||
coordinator = SceneCoordinator(rootSplitViewController: rootViewController)
|
||||
rootViewController.coordinator = coordinator
|
||||
rootViewController.delegate = coordinator
|
||||
rootViewController.showsSecondaryOnlyButton = true
|
||||
|
||||
coordinator.restoreWindowState(session.stateRestorationActivity)
|
||||
|
||||
|
||||
32
iOS/Settings/AboutData.swift
Normal file
32
iOS/Settings/AboutData.swift
Normal file
@@ -0,0 +1,32 @@
|
||||
//
|
||||
// AboutData.swift
|
||||
// NetNewsWire-iOS
|
||||
//
|
||||
// Created by Stuart Breckenridge on 02/10/2022.
|
||||
// Copyright © 2022 Ranchero Software. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
struct AboutData: Codable {
|
||||
var AppCredits: [AppCredit]
|
||||
var AdditionalContributors: [Contributor]
|
||||
|
||||
|
||||
var ThanksMarkdown: AttributedString {
|
||||
let dataURL = Bundle.main.url(forResource: "Thanks", withExtension: "md")!
|
||||
return try! AttributedString(markdown: Data(contentsOf: dataURL), options: AttributedString.MarkdownParsingOptions(interpretedSyntax: .inlineOnlyPreservingWhitespace))
|
||||
}
|
||||
|
||||
struct AppCredit: Codable {
|
||||
var name: String
|
||||
var role: String
|
||||
var url: String?
|
||||
}
|
||||
|
||||
struct Contributor: Codable {
|
||||
var name: String
|
||||
var url: String?
|
||||
}
|
||||
|
||||
}
|
||||
117
iOS/Settings/AboutView.swift
Normal file
117
iOS/Settings/AboutView.swift
Normal file
@@ -0,0 +1,117 @@
|
||||
//
|
||||
// AboutView.swift
|
||||
// NetNewsWire-iOS
|
||||
//
|
||||
// Created by Stuart Breckenridge on 02/10/2022.
|
||||
// Copyright © 2022 Ranchero Software. All rights reserved.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
struct AboutView: View {
|
||||
|
||||
private var about: AboutData!
|
||||
|
||||
init() {
|
||||
guard let path = Bundle.main.path(forResource: "About", ofType: "plist") else {
|
||||
fatalError("The about plist really should exist.")
|
||||
}
|
||||
let url = URL(fileURLWithPath: path)
|
||||
let data = try! Data(contentsOf: url)
|
||||
about = try! PropertyListDecoder().decode(AboutData.self, from: data)
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
List {
|
||||
Section(header: aboutHeaderView) {}
|
||||
Section(header: Text("Credits")) {
|
||||
ForEach(0..<about.AppCredits.count, id: \.self) { i in
|
||||
creditView(about.AppCredits[i])
|
||||
}
|
||||
}
|
||||
Section(header: Text("Additional Contributors")) {
|
||||
ForEach(0..<about.AdditionalContributors.count, id: \.self) { i in
|
||||
contributorView(about.AdditionalContributors[i])
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
Section(header: Text("Thanks"), footer: thanks, content: {})
|
||||
Section(footer: copyright, content: {})
|
||||
}
|
||||
.listStyle(.insetGrouped)
|
||||
.navigationTitle(Text("About"))
|
||||
.navigationBarTitleDisplayMode(.inline)
|
||||
}
|
||||
|
||||
var aboutHeaderView: some View {
|
||||
HStack {
|
||||
Spacer()
|
||||
VStack(alignment: .center, spacing: 8) {
|
||||
Image("About")
|
||||
.resizable()
|
||||
.frame(width: 75, height: 75)
|
||||
|
||||
Text(Bundle.main.appName)
|
||||
.font(.headline)
|
||||
|
||||
Text("By Brent Simmons and the Ranchero Software team.")
|
||||
.font(.subheadline)
|
||||
|
||||
Text("[netnewswire.com](https://netnewswire.com)")
|
||||
|
||||
}
|
||||
Spacer()
|
||||
}
|
||||
.textCase(.none)
|
||||
.multilineTextAlignment(.center)
|
||||
}
|
||||
|
||||
func creditView(_ appCredit: AboutData.AppCredit) -> some View {
|
||||
HStack {
|
||||
Text(appCredit.role)
|
||||
Spacer()
|
||||
Text(appCredit.name)
|
||||
.foregroundColor(.secondary)
|
||||
}
|
||||
.onTapGesture {
|
||||
guard let url = appCredit.url else { return }
|
||||
if let creditURL = URL(string: url) {
|
||||
UIApplication.shared.open(creditURL)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func contributorView(_ contributor: AboutData.Contributor) -> some View {
|
||||
HStack {
|
||||
Text(contributor.name)
|
||||
Spacer()
|
||||
}
|
||||
.onTapGesture {
|
||||
guard let url = contributor.url else { return }
|
||||
if let contributorURL = URL(string: url) {
|
||||
UIApplication.shared.open(contributorURL)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var thanks: some View {
|
||||
Text(about.ThanksMarkdown)
|
||||
.multilineTextAlignment(.center)
|
||||
.font(.callout)
|
||||
}
|
||||
|
||||
var copyright: some View {
|
||||
Text(verbatim: "Copyright © Brent Simmons 2002 - \(Calendar.current.component(.year, from: .now))")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
struct AboutView_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
NavigationView {
|
||||
AboutView()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,59 +0,0 @@
|
||||
//
|
||||
// AboutViewController.swift
|
||||
// NetNewsWire-iOS
|
||||
//
|
||||
// Created by Maurice Parker on 4/25/19.
|
||||
// Copyright © 2019 Ranchero Software. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
class AboutViewController: UITableViewController {
|
||||
|
||||
@IBOutlet weak var aboutTextView: UITextView!
|
||||
@IBOutlet weak var creditsTextView: UITextView!
|
||||
@IBOutlet weak var acknowledgmentsTextView: UITextView!
|
||||
@IBOutlet weak var thanksTextView: UITextView!
|
||||
@IBOutlet weak var dedicationTextView: UITextView!
|
||||
|
||||
override func viewDidLoad() {
|
||||
|
||||
super.viewDidLoad()
|
||||
|
||||
configureCell(file: "About", textView: aboutTextView)
|
||||
configureCell(file: "Credits", textView: creditsTextView)
|
||||
configureCell(file: "Thanks", textView: thanksTextView)
|
||||
configureCell(file: "Dedication", textView: dedicationTextView)
|
||||
|
||||
let buildLabel = NonIntrinsicLabel(frame: CGRect(x: 32.0, y: 0.0, width: 0.0, height: 0.0))
|
||||
buildLabel.font = UIFont.systemFont(ofSize: 11.0)
|
||||
buildLabel.textColor = UIColor.gray
|
||||
buildLabel.text = NSLocalizedString("Copyright © 2002-2022 Brent Simmons", comment: "Copyright")
|
||||
buildLabel.numberOfLines = 0
|
||||
buildLabel.sizeToFit()
|
||||
buildLabel.translatesAutoresizingMaskIntoConstraints = false
|
||||
|
||||
let wrapperView = UIView(frame: CGRect(x: 0, y: 0, width: buildLabel.frame.width, height: buildLabel.frame.height + 10.0))
|
||||
wrapperView.translatesAutoresizingMaskIntoConstraints = false
|
||||
wrapperView.addSubview(buildLabel)
|
||||
tableView.tableFooterView = wrapperView
|
||||
}
|
||||
|
||||
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
|
||||
return UITableView.automaticDimension
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private extension AboutViewController {
|
||||
|
||||
func configureCell(file: String, textView: UITextView) {
|
||||
let url = Bundle.main.url(forResource: file, withExtension: "rtf")!
|
||||
let string = try! NSAttributedString(url: url, options: [NSAttributedString.DocumentReadingOptionKey.documentType: NSAttributedString.DocumentType.rtf], documentAttributes: nil)
|
||||
textView.attributedText = string
|
||||
textView.textColor = UIColor.label
|
||||
textView.adjustsFontForContentSizeCategory = true
|
||||
textView.font = .preferredFont(forTextStyle: .body)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -72,9 +72,9 @@ class ArticleThemesTableViewController: UITableViewController, Logging {
|
||||
|
||||
override func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
|
||||
guard let cell = tableView.cellForRow(at: indexPath),
|
||||
let themeName = cell.textLabel?.text,
|
||||
let theme = ArticleThemesManager.shared.articleThemeWithThemeName(themeName),
|
||||
!theme.isAppTheme else { return nil }
|
||||
let themeName = cell.textLabel?.text else { return nil }
|
||||
|
||||
guard !ArticleThemesManager.shared.articleThemeWithThemeName(themeName).isAppTheme else { return nil }
|
||||
|
||||
let deleteTitle = NSLocalizedString("Delete", comment: "Delete")
|
||||
let deleteAction = UIContextualAction(style: .normal, title: deleteTitle) { [weak self] (action, view, completion) in
|
||||
|
||||
@@ -283,8 +283,8 @@ class SettingsViewController: UITableViewController, Logging {
|
||||
openURL("https://netnewswire.com/slack")
|
||||
tableView.selectRow(at: nil, animated: true, scrollPosition: .none)
|
||||
case 8:
|
||||
let timeline = UIStoryboard.settings.instantiateController(ofType: AboutViewController.self)
|
||||
self.navigationController?.pushViewController(timeline, animated: true)
|
||||
let hosting = UIHostingController(rootView: AboutView())
|
||||
self.navigationController?.pushViewController(hosting, animated: true)
|
||||
default:
|
||||
break
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user