mirror of
https://github.com/Ranchero-Software/NetNewsWire
synced 2025-08-12 06:26:36 +00:00
Merge branch 'ios-ui-notifications' of https://github.com/stuartbreckenridge/NetNewsWire into ios-ui-notifications
This commit is contained in:
@@ -508,6 +508,9 @@ public final class Account: DisplayNameProvider, UnreadCountProvider, Container,
|
||||
} else {
|
||||
if let title = item.titleFromAttributes, let folder = ensureFolder(with: title) {
|
||||
folder.externalID = item.attributes?["nnw_externalID"] as? String
|
||||
if let isSyncingPaused = item.attributes?["nnw_isSyncingPaused"] as? String, isSyncingPaused == "true" {
|
||||
folder.isSyncingPaused = true
|
||||
}
|
||||
item.children?.forEach { itemChild in
|
||||
if let feedSpecifier = itemChild.feedSpecifier {
|
||||
folder.addWebFeed(newWebFeed(with: feedSpecifier))
|
||||
|
||||
@@ -44,6 +44,7 @@ public final class Folder: Feed, Renamable, Container, Hashable {
|
||||
|
||||
static let untitledName = NSLocalizedString("Untitled ƒ", comment: "Folder name")
|
||||
public let folderID: Int // not saved: per-run only
|
||||
public var isSyncingPaused = false
|
||||
public var externalID: String? = nil
|
||||
static var incrementingID = 0
|
||||
|
||||
@@ -183,8 +184,16 @@ extension Folder: OPMLRepresentable {
|
||||
}
|
||||
}()
|
||||
|
||||
let attrPauseSyncing: String = {
|
||||
if allowCustomAttributes && isSyncingPaused {
|
||||
return " nnw_isSyncingPaused=\"true\""
|
||||
} else {
|
||||
return ""
|
||||
}
|
||||
}()
|
||||
|
||||
let escapedTitle = nameForDisplay.escapingSpecialXMLCharacters
|
||||
var s = "<outline text=\"\(escapedTitle)\" title=\"\(escapedTitle)\"\(attrExternalID)>\n"
|
||||
var s = "<outline text=\"\(escapedTitle)\" title=\"\(escapedTitle)\"\(attrExternalID)\(attrPauseSyncing)>\n"
|
||||
s = s.prepending(tabCount: indentLevel)
|
||||
|
||||
var hasAtLeastOneChild = false
|
||||
|
||||
@@ -192,6 +192,15 @@ public final class WebFeed: Feed, Renamable, Hashable {
|
||||
}
|
||||
}
|
||||
|
||||
public var isSyncingPaused: Bool {
|
||||
get {
|
||||
return metadata.isSyncingPaused ?? false
|
||||
}
|
||||
set {
|
||||
metadata.isSyncingPaused = newValue
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - DisplayNameProvider
|
||||
|
||||
public var nameForDisplay: String {
|
||||
|
||||
@@ -30,6 +30,7 @@ final class WebFeedMetadata: Codable {
|
||||
case sinceToken
|
||||
case externalID = "subscriptionID"
|
||||
case folderRelationship
|
||||
case isSyncingPaused
|
||||
}
|
||||
|
||||
var webFeedID: String {
|
||||
@@ -136,6 +137,14 @@ final class WebFeedMetadata: Codable {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var isSyncingPaused: Bool? {
|
||||
didSet {
|
||||
if isSyncingPaused != oldValue {
|
||||
valueDidChange(.isSyncingPaused)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
weak var delegate: WebFeedMetadataDelegate?
|
||||
|
||||
|
||||
@@ -150,8 +150,7 @@ struct AppAssets {
|
||||
static var masterFolderImage: IconImage {
|
||||
let image = NSImage(systemSymbolName: "folder", accessibilityDescription: nil)!
|
||||
let preferredColor = NSColor(named: "AccentColor")!
|
||||
let coloredImage = image.tinted(with: preferredColor)
|
||||
return IconImage(coloredImage, isSymbol: true, isBackgroundSupressed: true, preferredColor: preferredColor.cgColor)
|
||||
return IconImage(image, isSymbol: true, isBackgroundSupressed: true, preferredColor: preferredColor.cgColor)
|
||||
}
|
||||
|
||||
static var markAllAsReadImage: RSImage = {
|
||||
@@ -226,8 +225,7 @@ struct AppAssets {
|
||||
static var starredFeedImage: IconImage = {
|
||||
let image = NSImage(systemSymbolName: "star.fill", accessibilityDescription: nil)!
|
||||
let preferredColor = NSColor(named: "StarColor")!
|
||||
let coloredImage = image.tinted(with: preferredColor)
|
||||
return IconImage(coloredImage, isSymbol: true, isBackgroundSupressed: true, preferredColor: preferredColor.cgColor)
|
||||
return IconImage(image, isSymbol: true, isBackgroundSupressed: true, preferredColor: preferredColor.cgColor)
|
||||
}()
|
||||
|
||||
static var timelineSeparatorColor: NSColor = {
|
||||
@@ -245,15 +243,13 @@ struct AppAssets {
|
||||
static var todayFeedImage: IconImage = {
|
||||
let image = NSImage(systemSymbolName: "sun.max.fill", accessibilityDescription: nil)!
|
||||
let preferredColor = NSColor.orange
|
||||
let coloredImage = image.tinted(with: preferredColor)
|
||||
return IconImage(coloredImage, isSymbol: true, isBackgroundSupressed: true, preferredColor: preferredColor.cgColor)
|
||||
return IconImage(image, isSymbol: true, isBackgroundSupressed: true, preferredColor: preferredColor.cgColor)
|
||||
}()
|
||||
|
||||
static var unreadFeedImage: IconImage = {
|
||||
let image = NSImage(systemSymbolName: "largecircle.fill.circle", accessibilityDescription: nil)!
|
||||
let preferredColor = NSColor(named: "AccentColor")!
|
||||
let coloredImage = image.tinted(with: preferredColor)
|
||||
return IconImage(coloredImage, isSymbol: true, isBackgroundSupressed: true, preferredColor: preferredColor.cgColor)
|
||||
return IconImage(image, isSymbol: true, isBackgroundSupressed: true, preferredColor: preferredColor.cgColor)
|
||||
}()
|
||||
|
||||
static var swipeMarkReadImage: RSImage = {
|
||||
|
||||
@@ -396,7 +396,7 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserInterfaceValidations,
|
||||
|
||||
func createMainWindowController() -> MainWindowController {
|
||||
let controller: MainWindowController
|
||||
controller = windowControllerWithName("UnifiedWindow") as! MainWindowController
|
||||
controller = windowControllerWithName("MainWindow") as! MainWindowController
|
||||
|
||||
if !(mainWindowController?.isOpen ?? false) {
|
||||
mainWindowControllers.removeAll()
|
||||
@@ -675,7 +675,7 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserInterfaceValidations,
|
||||
|
||||
@IBAction func showHelp(_ sender: Any?) {
|
||||
|
||||
Browser.open("https://netnewswire.com/help/mac/6.0/en/", inBackground: false)
|
||||
Browser.open("https://netnewswire.com/help/mac/6.1/en/", inBackground: false)
|
||||
}
|
||||
|
||||
@IBAction func donateToAppCampForGirls(_ sender: Any?) {
|
||||
@@ -813,7 +813,7 @@ internal extension AppDelegate {
|
||||
guard let window = mainWindowController?.window else { return }
|
||||
|
||||
do {
|
||||
let theme = try ArticleTheme(path: filename)
|
||||
let theme = try ArticleTheme(path: filename, isAppTheme: false)
|
||||
let alert = NSAlert()
|
||||
alert.alertStyle = .informational
|
||||
|
||||
@@ -829,7 +829,7 @@ internal extension AppDelegate {
|
||||
attrs[.paragraphStyle] = titleParagraphStyle
|
||||
|
||||
let websiteText = NSMutableAttributedString()
|
||||
websiteText.append(NSAttributedString(string: NSLocalizedString("Author's Website", comment: "Author's Website"), attributes: attrs))
|
||||
websiteText.append(NSAttributedString(string: NSLocalizedString("Author‘s website:", comment: "Author's Website"), attributes: attrs))
|
||||
|
||||
websiteText.append(NSAttributedString(string: "\n"))
|
||||
|
||||
|
||||
@@ -11,241 +11,22 @@
|
||||
<objects>
|
||||
<windowController id="B8D-0N-5wS" customClass="MainWindowController" customModule="NetNewsWire" customModuleProvider="target" sceneMemberID="viewController">
|
||||
<window key="window" title="NetNewsWire" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" releasedWhenClosed="NO" visibleAtLaunch="NO" frameAutosaveName="" animationBehavior="default" id="IQv-IB-iLA">
|
||||
<windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES" resizable="YES"/>
|
||||
<windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES" resizable="YES" fullSizeContentView="YES"/>
|
||||
<windowCollectionBehavior key="collectionBehavior" fullScreenPrimary="YES"/>
|
||||
<windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
|
||||
<rect key="contentRect" x="196" y="240" width="480" height="270"/>
|
||||
<rect key="screenRect" x="0.0" y="0.0" width="1680" height="1027"/>
|
||||
<toolbar key="toolbar" implicitIdentifier="3C53153F-2D4C-441B-B551-D28ADBB5869C" explicitIdentifier="MainWindowToolbar" displayMode="iconOnly" sizeMode="regular" id="463-wM-1ZF">
|
||||
<allowedToolbarItems>
|
||||
<toolbarItem implicitItemIdentifier="NSToolbarSpaceItem" id="d4b-Sp-qek"/>
|
||||
<toolbarItem implicitItemIdentifier="NSToolbarFlexibleSpaceItem" id="YMs-P5-Xhn"/>
|
||||
<toolbarItem implicitItemIdentifier="DD0FA79F-72C1-488B-B113-0D2DE89AA468" explicitItemIdentifier="search" label="Search" paletteLabel="Search" toolTip="Search Articles" id="1Ql-WJ-KYi">
|
||||
<size key="minSize" width="96" height="22"/>
|
||||
<size key="maxSize" width="320" height="28"/>
|
||||
<searchField key="view" wantsLayer="YES" verticalHuggingPriority="750" id="Fcs-4u-xuP">
|
||||
<rect key="frame" x="0.0" y="14" width="320" height="22"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<searchFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" borderStyle="bezel" usesSingleLineMode="YES" bezelStyle="round" id="syc-TO-rPc">
|
||||
<font key="font" metaFont="system"/>
|
||||
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</searchFieldCell>
|
||||
</searchField>
|
||||
</toolbarItem>
|
||||
<toolbarItem implicitItemIdentifier="C3050605-E4B0-40CB-BA19-F64DF68BCFFA" explicitItemIdentifier="share" label="Share" paletteLabel="Share" toolTip="Share" image="NSShareTemplate" id="nv0-Ju-lP7" customClass="RSToolbarItem" customModule="RSCore">
|
||||
<size key="minSize" width="38" height="25"/>
|
||||
<size key="maxSize" width="38" height="27"/>
|
||||
<button key="view" verticalHuggingPriority="750" id="ypo-pI-PTN">
|
||||
<rect key="frame" x="0.0" y="14" width="38" height="25"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<buttonCell key="cell" type="roundTextured" bezelStyle="texturedRounded" image="NSShareTemplate" imagePosition="overlaps" alignment="center" state="on" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="XW2-7k-h4r">
|
||||
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
</button>
|
||||
<connections>
|
||||
<action selector="toolbarShowShareMenu:" target="Oky-zY-oP4" id="zUk-sS-frQ"/>
|
||||
</connections>
|
||||
</toolbarItem>
|
||||
<toolbarItem implicitItemIdentifier="3552D790-D29C-4BF2-AF02-5BEFE49C7FB9" explicitItemIdentifier="newFeed" label="New Feed" paletteLabel="New Feed" toolTip="New Feed" image="NSAddTemplate" id="Skp-5r-70Q" customClass="RSToolbarItem" customModule="RSCore">
|
||||
<size key="minSize" width="38" height="25"/>
|
||||
<size key="maxSize" width="38" height="27"/>
|
||||
<button key="view" verticalHuggingPriority="750" id="rHO-y7-lG9">
|
||||
<rect key="frame" x="11" y="14" width="38" height="25"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<buttonCell key="cell" type="roundTextured" bezelStyle="texturedRounded" image="NSAddTemplate" imagePosition="overlaps" alignment="center" lineBreakMode="truncatingTail" state="on" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="eHD-pU-GaN">
|
||||
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
</button>
|
||||
<connections>
|
||||
<action selector="showAddWebFeedWindow:" target="Oky-zY-oP4" id="pEy-MV-Lnd"/>
|
||||
</connections>
|
||||
</toolbarItem>
|
||||
<toolbarItem implicitItemIdentifier="25C9E98A-867B-4EE2-BC1A-7B453D6B40BF" explicitItemIdentifier="newFolder" label="New Folder" paletteLabel="New Folder" toolTip="New Folder" image="newFolder" id="st0-Wp-nPK" customClass="RSToolbarItem" customModule="RSCore">
|
||||
<size key="minSize" width="38" height="25"/>
|
||||
<size key="maxSize" width="38" height="27"/>
|
||||
<button key="view" verticalHuggingPriority="750" id="nvZ-IA-qOA">
|
||||
<rect key="frame" x="15" y="14" width="38" height="25"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<buttonCell key="cell" type="roundTextured" bezelStyle="texturedRounded" image="newFolder" imagePosition="only" alignment="center" lineBreakMode="truncatingTail" state="on" borderStyle="border" inset="2" id="Huj-Sy-XeN">
|
||||
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
</button>
|
||||
<connections>
|
||||
<action selector="showAddFolderWindow:" target="Oky-zY-oP4" id="JH4-ym-YWq"/>
|
||||
</connections>
|
||||
</toolbarItem>
|
||||
<toolbarItem implicitItemIdentifier="D783290E-C822-40DF-8CB8-925D92EA4D83" explicitItemIdentifier="nextUnread" label="Next Unread" paletteLabel="Next Unread" toolTip="Go to Next Unread" image="nextUnread" id="p7Y-Vm-ILH" customClass="RSToolbarItem" customModule="RSCore">
|
||||
<size key="minSize" width="38" height="25"/>
|
||||
<size key="maxSize" width="38" height="27"/>
|
||||
<button key="view" verticalHuggingPriority="750" id="1g8-XX-BhA" customClass="RSDarkModeAdaptingToolbarButton" customModule="RSCore">
|
||||
<rect key="frame" x="18" y="14" width="38" height="25"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<buttonCell key="cell" type="roundTextured" bezelStyle="texturedRounded" image="nextUnread" imagePosition="only" alignment="center" lineBreakMode="truncatingTail" state="on" borderStyle="border" inset="2" id="aBl-Z6-Tfa">
|
||||
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
</button>
|
||||
<connections>
|
||||
<action selector="nextUnread:" target="Oky-zY-oP4" id="tR6-kc-nFc"/>
|
||||
</connections>
|
||||
</toolbarItem>
|
||||
<toolbarItem implicitItemIdentifier="4A460A5C-B005-4797-AA95-FD667F0A61C2" explicitItemIdentifier="markAllAsRead" label="Mark All as Read" paletteLabel="Mark All as Read" toolTip="Mark All as Read" image="markAllRead" id="lst-vn-0Iw" customClass="RSToolbarItem" customModule="RSCore">
|
||||
<size key="minSize" width="38" height="25"/>
|
||||
<size key="maxSize" width="38" height="27"/>
|
||||
<button key="view" verticalHuggingPriority="750" id="0d4-hY-S6r">
|
||||
<rect key="frame" x="29" y="14" width="38" height="25"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<buttonCell key="cell" type="roundTextured" bezelStyle="texturedRounded" image="markAllRead" imagePosition="overlaps" alignment="center" lineBreakMode="truncatingTail" state="on" borderStyle="border" inset="2" id="e9z-YJ-Rib">
|
||||
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
</button>
|
||||
<connections>
|
||||
<action selector="markAllAsRead:" target="Oky-zY-oP4" id="qQg-Wj-NpN"/>
|
||||
</connections>
|
||||
</toolbarItem>
|
||||
<toolbarItem implicitItemIdentifier="540B93C9-F805-41C8-A638-3DC0825A020B" explicitItemIdentifier="markRead" label="Mark Read" paletteLabel="Mark Read" toolTip="Mark Read or Unread" image="markRead" id="N7D-g2-EPD" customClass="RSToolbarItem" customModule="RSCore">
|
||||
<size key="minSize" width="38" height="25"/>
|
||||
<size key="maxSize" width="38" height="27"/>
|
||||
<button key="view" verticalHuggingPriority="750" id="Pe3-wh-G7e">
|
||||
<rect key="frame" x="13" y="14" width="38" height="25"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<buttonCell key="cell" type="roundTextured" bezelStyle="texturedRounded" image="markRead" imagePosition="overlaps" alignment="center" lineBreakMode="truncatingTail" state="on" borderStyle="border" inset="2" id="2FV-93-DIY">
|
||||
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
</button>
|
||||
<connections>
|
||||
<action selector="toggleRead:" target="B8D-0N-5wS" id="r02-sN-noB"/>
|
||||
</connections>
|
||||
</toolbarItem>
|
||||
<toolbarItem implicitItemIdentifier="09CE2FC7-B9B6-4A74-85B3-2DED57082923" explicitItemIdentifier="markStar" label="Star" paletteLabel="Star" toolTip="Star or Unstar" image="star" id="Gxg-WQ-ufC" customClass="RSToolbarItem" customModule="RSCore">
|
||||
<size key="minSize" width="38" height="25"/>
|
||||
<size key="maxSize" width="38" height="27"/>
|
||||
<button key="view" verticalHuggingPriority="750" id="Ehx-31-ELo">
|
||||
<rect key="frame" x="0.0" y="14" width="38" height="25"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<buttonCell key="cell" type="roundTextured" bezelStyle="texturedRounded" image="star" imagePosition="overlaps" alignment="center" lineBreakMode="truncatingTail" state="on" borderStyle="border" inset="2" id="xYM-n6-bee">
|
||||
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
</button>
|
||||
<connections>
|
||||
<action selector="toggleStarred:" target="Oky-zY-oP4" id="44J-UK-89l"/>
|
||||
</connections>
|
||||
</toolbarItem>
|
||||
<toolbarItem implicitItemIdentifier="4DED27B7-8961-48F3-A995-9C961E2C0257" explicitItemIdentifier="openInBrowser" label="Open in Browser" paletteLabel="Open in Browser" toolTip="Open in Browser" image="openInBrowser" id="tid-SB-me3" customClass="RSToolbarItem" customModule="RSCore">
|
||||
<size key="minSize" width="38" height="25"/>
|
||||
<size key="maxSize" width="38" height="27"/>
|
||||
<button key="view" verticalHuggingPriority="750" allowsExpansionToolTips="YES" id="pgp-lZ-j6S">
|
||||
<rect key="frame" x="28" y="14" width="38" height="25"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<buttonCell key="cell" type="roundTextured" bezelStyle="texturedRounded" image="openInBrowser" imagePosition="overlaps" alignment="center" lineBreakMode="truncatingTail" state="on" borderStyle="border" inset="2" id="PNN-ND-sO0">
|
||||
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
</button>
|
||||
<connections>
|
||||
<action selector="openArticleInBrowser:" target="Oky-zY-oP4" id="txK-8m-Gcm"/>
|
||||
</connections>
|
||||
</toolbarItem>
|
||||
<toolbarItem implicitItemIdentifier="94C3EB28-587B-4C5C-9647-F8A2A240A1FD" explicitItemIdentifier="refresh" label="Refresh" paletteLabel="Refresh" toolTip="Refresh" image="NSRefreshTemplate" id="QD0-SQ-OIM" customClass="RSToolbarItem" customModule="RSCore">
|
||||
<size key="minSize" width="38" height="25"/>
|
||||
<size key="maxSize" width="38" height="27"/>
|
||||
<button key="view" verticalHuggingPriority="750" id="tRb-KW-Z3i">
|
||||
<rect key="frame" x="5" y="14" width="38" height="25"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<buttonCell key="cell" type="roundTextured" bezelStyle="texturedRounded" image="NSRefreshTemplate" imagePosition="overlaps" alignment="center" lineBreakMode="truncatingTail" state="on" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="aGM-Q8-k4r">
|
||||
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
</button>
|
||||
<connections>
|
||||
<action selector="refreshAll:" target="Oky-zY-oP4" id="KRz-Df-3zA"/>
|
||||
</connections>
|
||||
</toolbarItem>
|
||||
<toolbarItem implicitItemIdentifier="642D2379-B9AF-4990-8E09-A1115C60ED1A" explicitItemIdentifier="readerView" label="Reader" paletteLabel="Reader" toolTip="Reader View" id="6Vm-OW-3mR" customClass="RSToolbarItem" customModule="RSCore">
|
||||
<size key="minSize" width="38" height="25"/>
|
||||
<size key="maxSize" width="38" height="27"/>
|
||||
<button key="view" verticalHuggingPriority="750" id="1b9-Tf-u5V" customClass="LegacyArticleExtractorButton" customModule="NetNewsWire" customModuleProvider="target">
|
||||
<rect key="frame" x="3" y="14" width="38" height="25"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<buttonCell key="cell" type="roundTextured" bezelStyle="texturedRounded" imagePosition="overlaps" alignment="center" lineBreakMode="truncatingTail" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="sXz-Xe-Kd7">
|
||||
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES" changeBackground="YES" changeGray="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
</button>
|
||||
<connections>
|
||||
<action selector="toggleArticleExtractor:" target="B8D-0N-5wS" id="ZKQ-SK-5YJ"/>
|
||||
</connections>
|
||||
</toolbarItem>
|
||||
<toolbarItem implicitItemIdentifier="ACB5604B-4543-4985-BA1A-54ADA9DF5845" explicitItemIdentifier="cleanUp" label="Clean UP" paletteLabel="Clean Up" toolTip="Clean Up" image="cleanUp" sizingBehavior="auto" id="SsT-iS-pKE" customClass="RSToolbarItem" customModule="RSCore">
|
||||
<button key="view" verticalHuggingPriority="750" id="9At-yP-WNY">
|
||||
<rect key="frame" x="7" y="14" width="42" height="25"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<buttonCell key="cell" type="roundTextured" bezelStyle="texturedRounded" image="cleanUp" imagePosition="only" alignment="center" lineBreakMode="truncatingTail" state="on" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="Zwg-74-ZkZ">
|
||||
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
</button>
|
||||
<connections>
|
||||
<action selector="cleanUp:" target="Oky-zY-oP4" id="UCH-DG-yk4"/>
|
||||
</connections>
|
||||
</toolbarItem>
|
||||
<toolbarItem implicitItemIdentifier="596363B5-CE41-417C-B8AB-11CC2C99BCA5" label="Article Theme" paletteLabel="Article Theme" sizingBehavior="auto" id="3Hc-al-vK2">
|
||||
<nil key="toolTip"/>
|
||||
<popUpButton key="view" verticalHuggingPriority="750" id="MFT-nb-eLG">
|
||||
<rect key="frame" x="0.0" y="14" width="100" height="24"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<popUpButtonCell key="cell" type="roundTextured" title="Item 1" bezelStyle="texturedRounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="border" imageScaling="proportionallyDown" inset="2" selectedItem="xAs-IL-tMv" id="ior-Gb-LTq">
|
||||
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="menu"/>
|
||||
<menu key="menu" id="1Ac-Uq-Yeu">
|
||||
<items>
|
||||
<menuItem title="Item 1" state="on" id="xAs-IL-tMv"/>
|
||||
<menuItem title="Item 2" id="T8e-ib-OTb"/>
|
||||
<menuItem title="Item 3" id="Gfy-76-Njz"/>
|
||||
</items>
|
||||
</menu>
|
||||
</popUpButtonCell>
|
||||
</popUpButton>
|
||||
</toolbarItem>
|
||||
</allowedToolbarItems>
|
||||
<defaultToolbarItems>
|
||||
<toolbarItem reference="Skp-5r-70Q"/>
|
||||
<toolbarItem reference="st0-Wp-nPK"/>
|
||||
<toolbarItem reference="QD0-SQ-OIM"/>
|
||||
<toolbarItem reference="YMs-P5-Xhn"/>
|
||||
<toolbarItem reference="lst-vn-0Iw"/>
|
||||
<toolbarItem reference="1Ql-WJ-KYi"/>
|
||||
<toolbarItem reference="YMs-P5-Xhn"/>
|
||||
<toolbarItem reference="p7Y-Vm-ILH"/>
|
||||
<toolbarItem reference="Gxg-WQ-ufC"/>
|
||||
<toolbarItem reference="N7D-g2-EPD"/>
|
||||
<toolbarItem reference="6Vm-OW-3mR"/>
|
||||
<toolbarItem reference="tid-SB-me3"/>
|
||||
<toolbarItem reference="nv0-Ju-lP7"/>
|
||||
</defaultToolbarItems>
|
||||
<connections>
|
||||
<outlet property="delegate" destination="B8D-0N-5wS" id="bgf-8m-klH"/>
|
||||
</connections>
|
||||
</toolbar>
|
||||
<connections>
|
||||
<outlet property="delegate" destination="B8D-0N-5wS" id="JSn-lq-Uwe"/>
|
||||
</connections>
|
||||
</window>
|
||||
<connections>
|
||||
<outlet property="articleThemePopUpButton" destination="MFT-nb-eLG" id="lHc-ej-PrT"/>
|
||||
<segue destination="reS-fe-pD8" kind="relationship" relationship="window.shadowedContentViewController" id="WS2-WB-dc4"/>
|
||||
</connections>
|
||||
</windowController>
|
||||
<customObject id="Oky-zY-oP4" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="-666" y="-124"/>
|
||||
<point key="canvasLocation" x="-639" y="-140"/>
|
||||
</scene>
|
||||
<!--Split View Controller-->
|
||||
<scene sceneID="vhK-r2-b3N">
|
||||
@@ -309,20 +90,20 @@
|
||||
<rect key="frame" x="0.0" y="0.0" width="240" height="307"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<scrollView borderType="none" autohidesScrollers="YES" horizontalLineScroll="26" horizontalPageScroll="10" verticalLineScroll="26" verticalPageScroll="10" hasHorizontalScroller="NO" horizontalScrollElasticity="none" translatesAutoresizingMaskIntoConstraints="NO" id="cJj-Wv-9ep">
|
||||
<scrollView borderType="none" autohidesScrollers="YES" horizontalLineScroll="28" horizontalPageScroll="10" verticalLineScroll="28" verticalPageScroll="10" hasHorizontalScroller="NO" horizontalScrollElasticity="none" translatesAutoresizingMaskIntoConstraints="NO" id="cJj-Wv-9ep">
|
||||
<rect key="frame" x="0.0" y="0.0" width="240" height="307"/>
|
||||
<clipView key="contentView" drawsBackground="NO" copiesOnScroll="NO" id="2eU-Wz-F9g">
|
||||
<rect key="frame" x="0.0" y="0.0" width="240" height="307"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<outlineView verticalHuggingPriority="750" allowsExpansionToolTips="YES" columnAutoresizingStyle="firstColumnOnly" selectionHighlightStyle="sourceList" columnReordering="NO" columnResizing="NO" autosaveColumns="NO" typeSelect="NO" rowHeight="24" rowSizeStyle="systemDefault" viewBased="YES" floatsGroupRows="NO" indentationPerLevel="16" outlineTableColumn="ih9-mJ-EA7" id="cnV-kg-Dn2" customClass="SidebarOutlineView" customModule="NetNewsWire" customModuleProvider="target">
|
||||
<rect key="frame" x="0.0" y="0.0" width="241" height="307"/>
|
||||
<outlineView verticalHuggingPriority="750" allowsExpansionToolTips="YES" columnAutoresizingStyle="firstColumnOnly" selectionHighlightStyle="sourceList" columnReordering="NO" columnResizing="NO" autosaveColumns="NO" typeSelect="NO" rowHeight="28" rowSizeStyle="systemDefault" viewBased="YES" floatsGroupRows="NO" indentationPerLevel="13" outlineTableColumn="ih9-mJ-EA7" id="cnV-kg-Dn2" customClass="SidebarOutlineView" customModule="NetNewsWire" customModuleProvider="target">
|
||||
<rect key="frame" x="0.0" y="0.0" width="240" height="307"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<size key="intercellSpacing" width="3" height="2"/>
|
||||
<size key="intercellSpacing" width="3" height="0.0"/>
|
||||
<color key="backgroundColor" name="_sourceListBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="gridColor" name="gridColor" catalog="System" colorSpace="catalog"/>
|
||||
<tableColumns>
|
||||
<tableColumn width="238" minWidth="23" maxWidth="1000" id="ih9-mJ-EA7">
|
||||
<tableColumn width="208" minWidth="23" maxWidth="1000" id="ih9-mJ-EA7">
|
||||
<tableHeaderCell key="headerCell" lineBreakMode="truncatingTail" borderStyle="border">
|
||||
<color key="textColor" name="headerTextColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="headerColor" catalog="System" colorSpace="catalog"/>
|
||||
@@ -335,7 +116,7 @@
|
||||
<tableColumnResizingMask key="resizingMask" resizeWithTable="YES"/>
|
||||
<prototypeCellViews>
|
||||
<tableCellView identifier="HeaderCell" id="qkt-WA-5tB">
|
||||
<rect key="frame" x="1" y="1" width="238" height="17"/>
|
||||
<rect key="frame" x="11" y="0.0" width="217" height="17"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<textField verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="fNJ-z1-0Up">
|
||||
@@ -353,7 +134,7 @@
|
||||
</connections>
|
||||
</tableCellView>
|
||||
<tableCellView identifier="DataCell" id="HJn-Tm-YNO" customClass="SidebarCell" customModule="NetNewsWire" customModuleProvider="target">
|
||||
<rect key="frame" x="1" y="20" width="238" height="17"/>
|
||||
<rect key="frame" x="11" y="17" width="217" height="17"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
</tableCellView>
|
||||
</prototypeCellViews>
|
||||
@@ -469,7 +250,7 @@
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<popUpButton verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="lSU-OC-sEC">
|
||||
<rect key="frame" x="8" y="176" width="51" height="19"/>
|
||||
<rect key="frame" x="8" y="176" width="47" height="19"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="18" id="DoO-KI-ena"/>
|
||||
</constraints>
|
||||
@@ -503,7 +284,7 @@
|
||||
</popUpButtonCell>
|
||||
</popUpButton>
|
||||
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="iA5-go-AO0">
|
||||
<rect key="frame" x="350" y="179" width="13" height="14"/>
|
||||
<rect key="frame" x="350" y="180" width="13" height="13"/>
|
||||
<buttonCell key="cell" type="bevel" bezelStyle="rounded" image="filterInactive" imagePosition="overlaps" alignment="center" imageScaling="proportionallyDown" inset="2" id="j7d-36-DO5">
|
||||
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
@@ -514,10 +295,10 @@
|
||||
</connections>
|
||||
</button>
|
||||
<box verticalHuggingPriority="750" boxType="separator" translatesAutoresizingMaskIntoConstraints="NO" id="7p6-pA-iw6">
|
||||
<rect key="frame" x="0.0" y="172" width="375" height="5"/>
|
||||
<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="174"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="197"/>
|
||||
</customView>
|
||||
</subviews>
|
||||
<constraints>
|
||||
@@ -530,7 +311,7 @@
|
||||
<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" constant="23" id="tUm-nX-Jce"/>
|
||||
<constraint firstItem="7p6-pA-iw6" firstAttribute="top" secondItem="Dnl-L5-xFP" secondAttribute="top" id="tUm-nX-Jce"/>
|
||||
<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>
|
||||
@@ -604,16 +385,6 @@
|
||||
</scene>
|
||||
</scenes>
|
||||
<resources>
|
||||
<image name="NSAddTemplate" width="11" height="11"/>
|
||||
<image name="NSRefreshTemplate" width="11" height="15"/>
|
||||
<image name="NSShareTemplate" width="11" height="16"/>
|
||||
<image name="cleanUp" width="149" height="113"/>
|
||||
<image name="filterInactive" width="13" height="13"/>
|
||||
<image name="markAllRead" width="22" height="19"/>
|
||||
<image name="markRead" width="19" height="19"/>
|
||||
<image name="newFolder" width="19" height="19"/>
|
||||
<image name="nextUnread" width="24" height="19"/>
|
||||
<image name="openInBrowser" width="19" height="19"/>
|
||||
<image name="star" width="19" height="19"/>
|
||||
</resources>
|
||||
</document>
|
||||
|
||||
@@ -1,390 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.Storyboard.XIB" version="3.0" toolsVersion="17701" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" initialViewController="B8D-0N-5wS">
|
||||
<dependencies>
|
||||
<deployment identifier="macosx"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="17701"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<scenes>
|
||||
<!--Window Controller-->
|
||||
<scene sceneID="R2V-B0-nI4">
|
||||
<objects>
|
||||
<windowController id="B8D-0N-5wS" customClass="MainWindowController" customModule="NetNewsWire" customModuleProvider="target" sceneMemberID="viewController">
|
||||
<window key="window" title="NetNewsWire" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" releasedWhenClosed="NO" visibleAtLaunch="NO" frameAutosaveName="" animationBehavior="default" id="IQv-IB-iLA">
|
||||
<windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES" resizable="YES" fullSizeContentView="YES"/>
|
||||
<windowCollectionBehavior key="collectionBehavior" fullScreenPrimary="YES"/>
|
||||
<windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
|
||||
<rect key="contentRect" x="196" y="240" width="480" height="270"/>
|
||||
<rect key="screenRect" x="0.0" y="0.0" width="1680" height="1027"/>
|
||||
<connections>
|
||||
<outlet property="delegate" destination="B8D-0N-5wS" id="JSn-lq-Uwe"/>
|
||||
</connections>
|
||||
</window>
|
||||
<connections>
|
||||
<segue destination="reS-fe-pD8" kind="relationship" relationship="window.shadowedContentViewController" id="WS2-WB-dc4"/>
|
||||
</connections>
|
||||
</windowController>
|
||||
<customObject id="Oky-zY-oP4" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="-639" y="-140"/>
|
||||
</scene>
|
||||
<!--Split View Controller-->
|
||||
<scene sceneID="vhK-r2-b3N">
|
||||
<objects>
|
||||
<splitViewController id="wEf-EP-9Fq" sceneMemberID="viewController">
|
||||
<splitViewItems>
|
||||
<splitViewItem canCollapse="YES" holdingPriority="260" behavior="sidebar" id="XVW-Gk-g7U"/>
|
||||
<splitViewItem holdingPriority="255" behavior="contentList" id="UkR-qu-7uT"/>
|
||||
<splitViewItem id="EtR-h8-kPm"/>
|
||||
</splitViewItems>
|
||||
<splitView key="splitView" wantsLayer="YES" dividerStyle="thin" vertical="YES" id="3QF-bA-qOw">
|
||||
<rect key="frame" x="0.0" y="0.0" width="450" height="300"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<connections>
|
||||
<outlet property="delegate" destination="wEf-EP-9Fq" id="0ic-vQ-NKS"/>
|
||||
</connections>
|
||||
</splitView>
|
||||
<connections>
|
||||
<outlet property="splitView" destination="3QF-bA-qOw" id="YxK-5q-cOe"/>
|
||||
<segue destination="XML-A3-pDn" kind="relationship" relationship="splitItems" id="Dul-5N-qJu"/>
|
||||
<segue destination="36G-bQ-b96" kind="relationship" relationship="splitItems" id="yFZ-cm-NcZ"/>
|
||||
<segue destination="Vho-7i-T8m" kind="relationship" relationship="splitItems" id="Foq-XC-qoZ"/>
|
||||
</connections>
|
||||
</splitViewController>
|
||||
<customObject id="FnK-xf-eZm" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="-607" y="805"/>
|
||||
</scene>
|
||||
<!--View Controller-->
|
||||
<scene sceneID="ZPA-jO-OkH">
|
||||
<objects>
|
||||
<viewController id="reS-fe-pD8" sceneMemberID="viewController">
|
||||
<customView key="view" wantsLayer="YES" id="hWY-jP-A4m">
|
||||
<rect key="frame" x="0.0" y="0.0" width="581" height="300"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<subviews>
|
||||
<containerView translatesAutoresizingMaskIntoConstraints="NO" id="K1o-Ws-XMQ">
|
||||
<rect key="frame" x="0.0" y="0.0" width="581" height="300"/>
|
||||
<connections>
|
||||
<segue destination="wEf-EP-9Fq" kind="embed" id="IT3-aj-bSe"/>
|
||||
</connections>
|
||||
</containerView>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstItem="K1o-Ws-XMQ" firstAttribute="top" secondItem="hWY-jP-A4m" secondAttribute="top" id="JPX-I3-QMN"/>
|
||||
<constraint firstItem="K1o-Ws-XMQ" firstAttribute="leading" secondItem="hWY-jP-A4m" secondAttribute="leading" id="Vqi-IQ-2V0"/>
|
||||
<constraint firstAttribute="trailing" secondItem="K1o-Ws-XMQ" secondAttribute="trailing" id="Y9X-7J-odJ"/>
|
||||
<constraint firstAttribute="bottom" secondItem="K1o-Ws-XMQ" secondAttribute="bottom" id="spp-4y-rEm"/>
|
||||
</constraints>
|
||||
</customView>
|
||||
</viewController>
|
||||
<customObject id="6Eo-XA-2Zy" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="-638.5" y="401"/>
|
||||
</scene>
|
||||
<!--Sidebar View Controller-->
|
||||
<scene sceneID="Yae-mu-VsH">
|
||||
<objects>
|
||||
<viewController id="XML-A3-pDn" userLabel="Sidebar View Controller" customClass="SidebarViewController" customModule="NetNewsWire" customModuleProvider="target" sceneMemberID="viewController">
|
||||
<view key="view" wantsLayer="YES" id="bJZ-bH-vgc">
|
||||
<rect key="frame" x="0.0" y="0.0" width="240" height="307"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<scrollView borderType="none" autohidesScrollers="YES" horizontalLineScroll="28" horizontalPageScroll="10" verticalLineScroll="28" verticalPageScroll="10" hasHorizontalScroller="NO" horizontalScrollElasticity="none" translatesAutoresizingMaskIntoConstraints="NO" id="cJj-Wv-9ep">
|
||||
<rect key="frame" x="0.0" y="0.0" width="240" height="307"/>
|
||||
<clipView key="contentView" drawsBackground="NO" copiesOnScroll="NO" id="2eU-Wz-F9g">
|
||||
<rect key="frame" x="0.0" y="0.0" width="240" height="307"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<outlineView verticalHuggingPriority="750" allowsExpansionToolTips="YES" columnAutoresizingStyle="firstColumnOnly" selectionHighlightStyle="sourceList" columnReordering="NO" columnResizing="NO" autosaveColumns="NO" typeSelect="NO" rowHeight="28" rowSizeStyle="systemDefault" viewBased="YES" floatsGroupRows="NO" indentationPerLevel="13" outlineTableColumn="ih9-mJ-EA7" id="cnV-kg-Dn2" customClass="SidebarOutlineView" customModule="NetNewsWire" customModuleProvider="target">
|
||||
<rect key="frame" x="0.0" y="0.0" width="240" height="307"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<size key="intercellSpacing" width="3" height="0.0"/>
|
||||
<color key="backgroundColor" name="_sourceListBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="gridColor" name="gridColor" catalog="System" colorSpace="catalog"/>
|
||||
<tableColumns>
|
||||
<tableColumn width="208" minWidth="23" maxWidth="1000" id="ih9-mJ-EA7">
|
||||
<tableHeaderCell key="headerCell" lineBreakMode="truncatingTail" borderStyle="border">
|
||||
<color key="textColor" name="headerTextColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="headerColor" catalog="System" colorSpace="catalog"/>
|
||||
</tableHeaderCell>
|
||||
<textFieldCell key="dataCell" lineBreakMode="truncatingTail" selectable="YES" editable="YES" title="Text Cell" id="sXh-y7-12P">
|
||||
<font key="font" metaFont="system"/>
|
||||
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
<tableColumnResizingMask key="resizingMask" resizeWithTable="YES"/>
|
||||
<prototypeCellViews>
|
||||
<tableCellView identifier="HeaderCell" id="qkt-WA-5tB">
|
||||
<rect key="frame" x="11" y="0.0" width="217" height="17"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<textField verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="fNJ-z1-0Up">
|
||||
<rect key="frame" x="0.0" y="1" width="145" height="14"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<textFieldCell key="cell" lineBreakMode="truncatingTail" sendsActionOnEndEditing="YES" title="HEADER CELL" id="dRB-0K-qxz">
|
||||
<font key="font" metaFont="smallSystemBold"/>
|
||||
<color key="textColor" name="headerColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
</subviews>
|
||||
<connections>
|
||||
<outlet property="textField" destination="fNJ-z1-0Up" id="jEh-Oo-s62"/>
|
||||
</connections>
|
||||
</tableCellView>
|
||||
<tableCellView identifier="DataCell" id="HJn-Tm-YNO" customClass="SidebarCell" customModule="NetNewsWire" customModuleProvider="target">
|
||||
<rect key="frame" x="11" y="17" width="217" height="17"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
</tableCellView>
|
||||
</prototypeCellViews>
|
||||
</tableColumn>
|
||||
</tableColumns>
|
||||
<accessibility description="Feeds"/>
|
||||
<connections>
|
||||
<outlet property="delegate" destination="XML-A3-pDn" id="fPE-cv-p5c"/>
|
||||
<outlet property="keyboardDelegate" destination="h5K-zR-cUa" id="BlT-aW-sea"/>
|
||||
<outlet property="menu" destination="p3f-EZ-sSD" id="KTA-tl-UrO"/>
|
||||
</connections>
|
||||
</outlineView>
|
||||
</subviews>
|
||||
<nil key="backgroundColor"/>
|
||||
</clipView>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" relation="greaterThanOrEqual" constant="166" id="pzy-wh-tgi"/>
|
||||
</constraints>
|
||||
<scroller key="horizontalScroller" hidden="YES" wantsLayer="YES" verticalHuggingPriority="750" horizontal="YES" id="vs5-5h-CXe">
|
||||
<rect key="frame" x="-100" y="-100" width="238" height="15"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
</scroller>
|
||||
<scroller key="verticalScroller" hidden="YES" wantsLayer="YES" verticalHuggingPriority="750" horizontal="NO" id="FWV-kB-qct">
|
||||
<rect key="frame" x="224" y="17" width="15" height="102"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
</scroller>
|
||||
</scrollView>
|
||||
<customView translatesAutoresizingMaskIntoConstraints="NO" id="HZs-Zf-G8s" customClass="SidebarStatusBarView" customModule="NetNewsWire" customModuleProvider="target">
|
||||
<rect key="frame" x="0.0" y="-28" width="240" height="28"/>
|
||||
<subviews>
|
||||
<box verticalHuggingPriority="750" boxType="separator" translatesAutoresizingMaskIntoConstraints="NO" id="agw-l1-HkL">
|
||||
<rect key="frame" x="0.0" y="25" width="240" height="5"/>
|
||||
</box>
|
||||
<progressIndicator hidden="YES" wantsLayer="YES" maxValue="100" style="bar" translatesAutoresizingMaskIntoConstraints="NO" id="y9c-Xf-2fS">
|
||||
<rect key="frame" x="20" y="3" width="40" height="20"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="40" id="1Yw-ER-8pT"/>
|
||||
</constraints>
|
||||
</progressIndicator>
|
||||
<textField hidden="YES" horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="iyL-pW-cT6">
|
||||
<rect key="frame" x="62" y="6" width="160" height="16"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Label" id="dVE-XG-mlU">
|
||||
<font key="font" metaFont="system"/>
|
||||
<color key="textColor" name="secondaryLabelColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstItem="y9c-Xf-2fS" firstAttribute="centerY" secondItem="HZs-Zf-G8s" secondAttribute="centerY" constant="1" id="5Du-sw-hBK"/>
|
||||
<constraint firstItem="agw-l1-HkL" firstAttribute="leading" secondItem="HZs-Zf-G8s" secondAttribute="leading" id="FVd-l8-q2q"/>
|
||||
<constraint firstItem="iyL-pW-cT6" firstAttribute="centerY" secondItem="HZs-Zf-G8s" secondAttribute="centerY" id="Hht-GZ-3Ls"/>
|
||||
<constraint firstAttribute="trailing" secondItem="agw-l1-HkL" secondAttribute="trailing" id="MaE-c5-LIY"/>
|
||||
<constraint firstItem="iyL-pW-cT6" firstAttribute="leading" secondItem="y9c-Xf-2fS" secondAttribute="trailing" constant="4" id="TAM-VN-Syu"/>
|
||||
<constraint firstItem="y9c-Xf-2fS" firstAttribute="leading" secondItem="HZs-Zf-G8s" secondAttribute="leading" constant="20" symbolic="YES" id="TV9-iE-nuE"/>
|
||||
<constraint firstItem="agw-l1-HkL" firstAttribute="top" secondItem="HZs-Zf-G8s" secondAttribute="top" id="rBv-S6-j3b"/>
|
||||
<constraint firstAttribute="height" constant="28" id="xOq-XX-qcd"/>
|
||||
</constraints>
|
||||
<connections>
|
||||
<outlet property="bottomConstraint" destination="UN9-Wa-uxb" id="SYv-ax-8md"/>
|
||||
<outlet property="heightConstraint" destination="xOq-XX-qcd" id="ktU-yd-g8x"/>
|
||||
<outlet property="progressIndicator" destination="y9c-Xf-2fS" id="gaf-6e-siu"/>
|
||||
<outlet property="progressLabel" destination="iyL-pW-cT6" id="Zpv-44-cfX"/>
|
||||
</connections>
|
||||
</customView>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstItem="HZs-Zf-G8s" firstAttribute="top" secondItem="cJj-Wv-9ep" secondAttribute="bottom" id="0Zg-oW-o7U"/>
|
||||
<constraint firstItem="cJj-Wv-9ep" firstAttribute="leading" secondItem="bJZ-bH-vgc" secondAttribute="leading" id="5Rs-9M-TKq"/>
|
||||
<constraint firstItem="cJj-Wv-9ep" firstAttribute="top" secondItem="bJZ-bH-vgc" secondAttribute="top" id="A7C-VI-drt"/>
|
||||
<constraint firstAttribute="trailing" secondItem="iyL-pW-cT6" secondAttribute="trailing" constant="20" id="Mnm-9S-Qpm"/>
|
||||
<constraint firstAttribute="bottom" secondItem="HZs-Zf-G8s" secondAttribute="bottom" constant="-28" id="UN9-Wa-uxb"/>
|
||||
<constraint firstAttribute="trailing" secondItem="HZs-Zf-G8s" secondAttribute="trailing" id="iNE-nb-QEB"/>
|
||||
<constraint firstItem="HZs-Zf-G8s" firstAttribute="leading" secondItem="bJZ-bH-vgc" secondAttribute="leading" id="tPp-xB-CgB"/>
|
||||
<constraint firstAttribute="trailing" secondItem="cJj-Wv-9ep" secondAttribute="trailing" id="vo7-3F-Fd3"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<connections>
|
||||
<outlet property="outlineView" destination="cnV-kg-Dn2" id="FVf-OT-E3h"/>
|
||||
</connections>
|
||||
</viewController>
|
||||
<customObject id="Jih-JO-hIE" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
|
||||
<menu id="p3f-EZ-sSD">
|
||||
<items>
|
||||
<menuItem title="Item 1" id="ZDH-CV-Y2s">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
</menuItem>
|
||||
<menuItem title="Item 2" id="1F7-qu-7oN">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
</menuItem>
|
||||
<menuItem title="Item 3" id="r9E-FO-GoU">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
</menuItem>
|
||||
</items>
|
||||
<connections>
|
||||
<outlet property="delegate" destination="XML-A3-pDn" id="XJm-Ua-9UB"/>
|
||||
</connections>
|
||||
</menu>
|
||||
<customObject id="h5K-zR-cUa" customClass="SidebarKeyboardDelegate" customModule="NetNewsWire" customModuleProvider="target">
|
||||
<connections>
|
||||
<outlet property="sidebarViewController" destination="XML-A3-pDn" id="kwd-Zc-HJm"/>
|
||||
</connections>
|
||||
</customObject>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="-74" y="-186.5"/>
|
||||
</scene>
|
||||
<!--Timeline Container View Controller-->
|
||||
<scene sceneID="zUD-i8-QYC">
|
||||
<objects>
|
||||
<viewController id="36G-bQ-b96" customClass="TimelineContainerViewController" customModule="NetNewsWire" customModuleProvider="target" sceneMemberID="viewController">
|
||||
<view key="view" id="Dnl-L5-xFP">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="198"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<popUpButton verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="lSU-OC-sEC">
|
||||
<rect key="frame" x="8" y="176" width="47" height="19"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="18" id="DoO-KI-ena"/>
|
||||
</constraints>
|
||||
<popUpButtonCell key="cell" type="recessed" title="Sort" bezelStyle="recessed" alignment="center" lineBreakMode="truncatingTail" borderStyle="border" tag="1" imageScaling="proportionallyDown" inset="2" pullsDown="YES" id="bl0-6I-cH2">
|
||||
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES" changeBackground="YES" changeGray="YES"/>
|
||||
<font key="font" metaFont="smallSystemBold"/>
|
||||
<menu key="menu" id="dN0-S2-uqU">
|
||||
<items>
|
||||
<menuItem title="Sort" tag="1" hidden="YES" id="4BZ-ya-evy">
|
||||
<attributedString key="attributedTitle"/>
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
</menuItem>
|
||||
<menuItem title="Newest Article on Top" state="on" tag="2" id="40c-kt-vhO">
|
||||
<connections>
|
||||
<action selector="sortByNewestArticleOnTop:" target="Ebq-4s-EwK" id="vYg-MZ-zve"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Oldest Article on Top" tag="3" id="sOF-Ez-vIL">
|
||||
<connections>
|
||||
<action selector="sortByOldestArticleOnTop:" target="Ebq-4s-EwK" id="KFG-M7-blB"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="xQP-gm-iO9"/>
|
||||
<menuItem title="Group by Feed" tag="4" id="YSR-5C-Yjd">
|
||||
<connections>
|
||||
<action selector="groupByFeedToggled:" target="Ebq-4s-EwK" id="4y9-5l-ToF"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</popUpButtonCell>
|
||||
</popUpButton>
|
||||
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="iA5-go-AO0">
|
||||
<rect key="frame" x="350" y="180" width="13" height="13"/>
|
||||
<buttonCell key="cell" type="bevel" bezelStyle="rounded" image="filterInactive" imagePosition="overlaps" alignment="center" imageScaling="proportionallyDown" inset="2" id="j7d-36-DO5">
|
||||
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
<color key="contentTintColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
|
||||
<connections>
|
||||
<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"/>
|
||||
</customView>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstAttribute="trailing" secondItem="Zpk-pq-9nW" secondAttribute="trailing" id="67d-pI-I9C"/>
|
||||
<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 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 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>
|
||||
</view>
|
||||
<connections>
|
||||
<outlet property="containerView" destination="Zpk-pq-9nW" id="Kye-yX-Wyn"/>
|
||||
<outlet property="groupByFeedMenuItem" destination="YSR-5C-Yjd" id="1aN-9S-nE1"/>
|
||||
<outlet property="newestToOldestMenuItem" destination="40c-kt-vhO" id="AGa-fX-EVy"/>
|
||||
<outlet property="oldestToNewestMenuItem" destination="sOF-Ez-vIL" id="qSg-ST-ww9"/>
|
||||
<outlet property="readFilteredButton" destination="iA5-go-AO0" id="kQg-2g-zNZ"/>
|
||||
<outlet property="viewOptionsPopUpButton" destination="lSU-OC-sEC" id="Z8V-rm-n2m"/>
|
||||
</connections>
|
||||
</viewController>
|
||||
<customObject id="Ebq-4s-EwK" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
|
||||
<customObject id="ZOV-xh-WJE" customClass="TimelineKeyboardDelegate" customModule="NetNewsWire" customModuleProvider="target">
|
||||
<connections>
|
||||
<outlet property="timelineViewController" destination="36G-bQ-b96" id="rED-2Z-kh6"/>
|
||||
</connections>
|
||||
</customObject>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="62" 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">
|
||||
<rect key="frame" x="0.0" y="0.0" width="730" height="300"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<subviews>
|
||||
<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>
|
||||
<textField horizontalHuggingPriority="850" verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" translatesAutoresizingMaskIntoConstraints="NO" id="Dim-ed-Dcz" userLabel="URL Label">
|
||||
<rect key="frame" x="4" y="2" width="4" height="16"/>
|
||||
<textFieldCell key="cell" lineBreakMode="truncatingMiddle" selectable="YES" allowsUndo="NO" sendsActionOnEndEditing="YES" alignment="left" usesSingleLineMode="YES" id="znU-Fh-L7H">
|
||||
<font key="font" metaFont="system"/>
|
||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstItem="Dim-ed-Dcz" firstAttribute="centerY" secondItem="xI5-lx-RD8" secondAttribute="centerY" id="Hna-uB-3F7"/>
|
||||
<constraint firstAttribute="trailing" secondItem="Dim-ed-Dcz" secondAttribute="trailing" constant="6" id="O5q-ZN-DjZ"/>
|
||||
<constraint firstAttribute="height" constant="20" id="Sfk-Ri-WoD"/>
|
||||
<constraint firstItem="Dim-ed-Dcz" firstAttribute="leading" secondItem="xI5-lx-RD8" secondAttribute="leading" constant="6" id="Y9c-WR-ZBY"/>
|
||||
</constraints>
|
||||
<connections>
|
||||
<outlet property="urlLabel" destination="Dim-ed-Dcz" id="8fY-oo-cGT"/>
|
||||
</connections>
|
||||
</customView>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstItem="xI5-lx-RD8" firstAttribute="leading" secondItem="cJ9-6s-66u" secondAttribute="leading" constant="6" id="5vz-ys-CAo"/>
|
||||
<constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="xI5-lx-RD8" secondAttribute="trailing" constant="6" id="pbD-LN-Gk1"/>
|
||||
<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"/>
|
||||
</connections>
|
||||
</customView>
|
||||
<connections>
|
||||
<outlet property="containerView" destination="cJ9-6s-66u" id="gXc-Pz-9sQ"/>
|
||||
<outlet property="statusBarView" destination="xI5-lx-RD8" id="meP-4g-U63"/>
|
||||
</connections>
|
||||
</viewController>
|
||||
<customObject id="vzM-Vn-mEn" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="68" y="946"/>
|
||||
</scene>
|
||||
</scenes>
|
||||
<resources>
|
||||
<image name="filterInactive" width="13" height="13"/>
|
||||
</resources>
|
||||
</document>
|
||||
@@ -14,6 +14,9 @@ final class IconView: NSView {
|
||||
didSet {
|
||||
if iconImage !== oldValue {
|
||||
imageView.image = iconImage?.image
|
||||
if let tintColor = iconImage?.preferredColor {
|
||||
imageView.contentTintColor = NSColor(cgColor: tintColor)
|
||||
}
|
||||
|
||||
if NSApplication.shared.effectiveAppearance.isDarkMode {
|
||||
if self.iconImage?.isDark ?? false {
|
||||
|
||||
@@ -1273,6 +1273,8 @@ private extension MainWindowController {
|
||||
|
||||
let widths = splitView.arrangedSubviews.map{ Int(floor($0.frame.width)) }
|
||||
state[MainWindowController.mainWindowWidthsStateKey] = widths
|
||||
|
||||
state[UserInfoKey.isSidebarHidden] = sidebarSplitViewItem?.isCollapsed
|
||||
}
|
||||
|
||||
func restoreSplitViewState(from state: [AnyHashable : Any]) {
|
||||
@@ -1295,6 +1297,12 @@ private extension MainWindowController {
|
||||
|
||||
splitView.setPosition(CGFloat(sidebarWidth), ofDividerAt: 0)
|
||||
splitView.setPosition(CGFloat(sidebarWidth + dividerThickness + timelineWidth), ofDividerAt: 1)
|
||||
|
||||
let isSidebarHidden = state[UserInfoKey.isSidebarHidden] as? Bool ?? false
|
||||
|
||||
if !(sidebarSplitViewItem?.isCollapsed ?? false) && isSidebarHidden {
|
||||
sidebarSplitViewItem?.isCollapsed = true
|
||||
}
|
||||
}
|
||||
|
||||
func buildToolbarButton(_ itemIdentifier: NSToolbarItem.Identifier, _ title: String, _ image: NSImage, _ selector: String) -> NSToolbarItem {
|
||||
|
||||
@@ -143,18 +143,17 @@ private extension SidebarCell {
|
||||
var updatedIconImage = iconImage
|
||||
|
||||
if let iconImage = iconImage, iconImage.isSymbol {
|
||||
var tintColor: CGColor
|
||||
if backgroundStyle != .normal {
|
||||
let image = iconImage.image.tinted(with: .white)
|
||||
updatedIconImage = IconImage(image, isSymbol: iconImage.isSymbol, isBackgroundSupressed: iconImage.isBackgroundSupressed)
|
||||
tintColor = NSColor.white.cgColor
|
||||
} else {
|
||||
if let preferredColor = iconImage.preferredColor {
|
||||
let image = iconImage.image.tinted(with: NSColor(cgColor: preferredColor)!)
|
||||
updatedIconImage = IconImage(image, isSymbol: iconImage.isSymbol, isBackgroundSupressed: iconImage.isBackgroundSupressed)
|
||||
tintColor = preferredColor
|
||||
} else {
|
||||
let image = iconImage.image.tinted(with: .controlAccentColor)
|
||||
updatedIconImage = IconImage(image, isSymbol: iconImage.isSymbol, isBackgroundSupressed: iconImage.isBackgroundSupressed)
|
||||
tintColor = NSColor.controlAccentColor.cgColor
|
||||
}
|
||||
}
|
||||
updatedIconImage = IconImage(iconImage.image, isSymbol: iconImage.isSymbol, isBackgroundSupressed: iconImage.isBackgroundSupressed, preferredColor: tintColor)
|
||||
}
|
||||
|
||||
if let image = updatedIconImage {
|
||||
|
||||
@@ -809,6 +809,12 @@ extension TimelineViewController: NSTableViewDataSource {
|
||||
}
|
||||
return ArticlePasteboardWriter(article: article)
|
||||
}
|
||||
|
||||
func tableView(_ tableView: NSTableView, heightOfRow row: Int) -> CGFloat {
|
||||
// Keeping -[NSTableViewDelegate tableView:heightOfRow:] implemented fixes
|
||||
// an issue that the bottom inset of NSTableView disappears on macOS Monterey.
|
||||
return tableView.rowHeight
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - NSTableViewDelegate
|
||||
|
||||
Binary file not shown.
@@ -80,6 +80,9 @@
|
||||
5103A9F5242258C600410853 /* AccountsAddCloudKit.xib in Resources */ = {isa = PBXBuildFile; fileRef = 5103A9DA242258C600410853 /* AccountsAddCloudKit.xib */; };
|
||||
5103A9F724225E4C00410853 /* AccountsAddCloudKitWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5103A9F624225E4C00410853 /* AccountsAddCloudKitWindowController.swift */; };
|
||||
5103A9F824225E4C00410853 /* AccountsAddCloudKitWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5103A9F624225E4C00410853 /* AccountsAddCloudKitWindowController.swift */; };
|
||||
51077C5827A86D16000C71DB /* Hyperlegible.nnwtheme in Resources */ = {isa = PBXBuildFile; fileRef = 51077C5727A86D16000C71DB /* Hyperlegible.nnwtheme */; };
|
||||
51077C5927A86D16000C71DB /* Hyperlegible.nnwtheme in Resources */ = {isa = PBXBuildFile; fileRef = 51077C5727A86D16000C71DB /* Hyperlegible.nnwtheme */; };
|
||||
51077C5A27A86D16000C71DB /* Hyperlegible.nnwtheme in Resources */ = {isa = PBXBuildFile; fileRef = 51077C5727A86D16000C71DB /* Hyperlegible.nnwtheme */; };
|
||||
5108F6B62375E612001ABC45 /* CacheCleaner.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5108F6B52375E612001ABC45 /* CacheCleaner.swift */; };
|
||||
5108F6B72375E612001ABC45 /* CacheCleaner.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5108F6B52375E612001ABC45 /* CacheCleaner.swift */; };
|
||||
5108F6D22375EED2001ABC45 /* TimelineCustomizerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5108F6D12375EED2001ABC45 /* TimelineCustomizerViewController.swift */; };
|
||||
@@ -254,6 +257,9 @@
|
||||
517630042336215100E15FFF /* main.js in Resources */ = {isa = PBXBuildFile; fileRef = 517630032336215100E15FFF /* main.js */; };
|
||||
517630052336215100E15FFF /* main.js in Resources */ = {isa = PBXBuildFile; fileRef = 517630032336215100E15FFF /* main.js */; };
|
||||
517630232336657E00E15FFF /* WebViewProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 517630222336657E00E15FFF /* WebViewProvider.swift */; };
|
||||
5177C21227B07C9E00643901 /* NewsFax.nnwtheme in Resources */ = {isa = PBXBuildFile; fileRef = DFD6AACB27ADE80900463FAD /* NewsFax.nnwtheme */; };
|
||||
5177C21327B07CFE00643901 /* NewsFax.nnwtheme in Resources */ = {isa = PBXBuildFile; fileRef = DFD6AACB27ADE80900463FAD /* NewsFax.nnwtheme */; };
|
||||
5177C21427B07D1E00643901 /* NewsFax.nnwtheme in Resources */ = {isa = PBXBuildFile; fileRef = DFD6AACB27ADE80900463FAD /* NewsFax.nnwtheme */; };
|
||||
517A745B2443665000B553B9 /* UIPageViewController-Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 517A745A2443665000B553B9 /* UIPageViewController-Extensions.swift */; };
|
||||
5183CCD0226E1E880010922C /* NonIntrinsicLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5183CCCF226E1E880010922C /* NonIntrinsicLabel.swift */; };
|
||||
5183CCDA226E31A50010922C /* NonIntrinsicImageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5183CCD9226E31A50010922C /* NonIntrinsicImageView.swift */; };
|
||||
@@ -271,7 +277,6 @@
|
||||
518C3193237B00D9004D740F /* DetailIconSchemeHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5141E7552374A2890013FF27 /* DetailIconSchemeHandler.swift */; };
|
||||
518C3194237B00DA004D740F /* DetailIconSchemeHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5141E7552374A2890013FF27 /* DetailIconSchemeHandler.swift */; };
|
||||
518ED21D23D0F26000E0A862 /* UIViewController-Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 518ED21C23D0F26000E0A862 /* UIViewController-Extensions.swift */; };
|
||||
51934CCB230F599B006127BE /* InteractiveNavigationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51934CC1230F5963006127BE /* InteractiveNavigationController.swift */; };
|
||||
51934CCE2310792F006127BE /* ActivityManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51934CCD2310792F006127BE /* ActivityManager.swift */; };
|
||||
51938DF2231AFC660055A1A0 /* SearchTimelineFeedDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51938DF1231AFC660055A1A0 /* SearchTimelineFeedDelegate.swift */; };
|
||||
51938DF3231AFC660055A1A0 /* SearchTimelineFeedDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51938DF1231AFC660055A1A0 /* SearchTimelineFeedDelegate.swift */; };
|
||||
@@ -340,8 +345,6 @@
|
||||
51BC4AFF247277E0000A6ED8 /* URL-Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51BC4ADD247277DF000A6ED8 /* URL-Extensions.swift */; };
|
||||
51BC4B00247277E0000A6ED8 /* 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 */; };
|
||||
51C03082257D815A00609262 /* UnifiedWindow.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 51C0307F257D815A00609262 /* UnifiedWindow.storyboard */; };
|
||||
51C266EA238C334800F53014 /* ContextMenuPreviewViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51C266E9238C334800F53014 /* ContextMenuPreviewViewController.swift */; };
|
||||
51C45258226508CF00C03939 /* AppAssets.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51C45254226507D200C03939 /* AppAssets.swift */; };
|
||||
51C45259226508D300C03939 /* AppDefaults.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51C45255226507D200C03939 /* AppDefaults.swift */; };
|
||||
@@ -849,6 +852,7 @@
|
||||
D5F4EDB720074D6500B9E363 /* WebFeed+Scriptability.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5F4EDB620074D6500B9E363 /* WebFeed+Scriptability.swift */; };
|
||||
D5F4EDB920074D7C00B9E363 /* Folder+Scriptability.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5F4EDB820074D7C00B9E363 /* Folder+Scriptability.swift */; };
|
||||
DD82AB0A231003F6002269DF /* SharingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD82AB09231003F6002269DF /* SharingTests.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 */; };
|
||||
@@ -1165,6 +1169,7 @@
|
||||
5103A9B324216A4200410853 /* blank.html */ = {isa = PBXFileReference; lastKnownFileType = text.html; path = blank.html; sourceTree = "<group>"; };
|
||||
5103A9DA242258C600410853 /* AccountsAddCloudKit.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = AccountsAddCloudKit.xib; sourceTree = "<group>"; };
|
||||
5103A9F624225E4C00410853 /* AccountsAddCloudKitWindowController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountsAddCloudKitWindowController.swift; sourceTree = "<group>"; };
|
||||
51077C5727A86D16000C71DB /* Hyperlegible.nnwtheme */ = {isa = PBXFileReference; lastKnownFileType = wrapper; path = Hyperlegible.nnwtheme; sourceTree = "<group>"; };
|
||||
5108F6B52375E612001ABC45 /* CacheCleaner.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CacheCleaner.swift; sourceTree = "<group>"; };
|
||||
5108F6D12375EED2001ABC45 /* TimelineCustomizerViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineCustomizerViewController.swift; sourceTree = "<group>"; };
|
||||
5108F6D32375EEEF001ABC45 /* TimelinePreviewTableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelinePreviewTableViewController.swift; sourceTree = "<group>"; };
|
||||
@@ -1272,7 +1277,6 @@
|
||||
518B2ED22351B3DD00400001 /* NetNewsWire-iOSTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "NetNewsWire-iOSTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
518B2EE92351B4C200400001 /* NetNewsWire_iOSTests_target.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = NetNewsWire_iOSTests_target.xcconfig; sourceTree = "<group>"; };
|
||||
518ED21C23D0F26000E0A862 /* UIViewController-Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIViewController-Extensions.swift"; sourceTree = "<group>"; };
|
||||
51934CC1230F5963006127BE /* InteractiveNavigationController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InteractiveNavigationController.swift; sourceTree = "<group>"; };
|
||||
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>"; };
|
||||
5193CD57245E44A90092735E /* RedditFeedProvider-Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "RedditFeedProvider-Extensions.swift"; sourceTree = "<group>"; };
|
||||
@@ -1308,7 +1312,6 @@
|
||||
51BB7C302335ACDE008E8144 /* page.html */ = {isa = PBXFileReference; lastKnownFileType = text.html; path = page.html; sourceTree = "<group>"; };
|
||||
51BC4ADD247277DF000A6ED8 /* URL-Extensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "URL-Extensions.swift"; sourceTree = "<group>"; };
|
||||
51BEB22C2451E8340066DEDD /* TwitterEnterDetailTableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TwitterEnterDetailTableViewController.swift; sourceTree = "<group>"; };
|
||||
51C03080257D815A00609262 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Mac/Base.lproj/UnifiedWindow.storyboard; sourceTree = SOURCE_ROOT; };
|
||||
51C266E9238C334800F53014 /* ContextMenuPreviewViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContextMenuPreviewViewController.swift; sourceTree = "<group>"; };
|
||||
51C4524E226506F400C03939 /* UIStoryboard-Extensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIStoryboard-Extensions.swift"; sourceTree = "<group>"; };
|
||||
51C45250226506F400C03939 /* String-Extensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "String-Extensions.swift"; sourceTree = "<group>"; };
|
||||
@@ -1590,6 +1593,8 @@
|
||||
D5F4EDB620074D6500B9E363 /* WebFeed+Scriptability.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "WebFeed+Scriptability.swift"; sourceTree = "<group>"; };
|
||||
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>"; };
|
||||
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>"; };
|
||||
FF3ABF09232599450074C542 /* ArticleSorterTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ArticleSorterTests.swift; sourceTree = "<group>"; };
|
||||
@@ -1850,7 +1855,9 @@
|
||||
511D43CE231FA51100FB1562 /* Resources */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
DFD6AACB27ADE80900463FAD /* NewsFax.nnwtheme */,
|
||||
51DEE81126FB9233006DAA56 /* Appanoose.nnwtheme */,
|
||||
51077C5727A86D16000C71DB /* Hyperlegible.nnwtheme */,
|
||||
51DEE81726FBFF84006DAA56 /* Promenade.nnwtheme */,
|
||||
5137C2E326F3F52D009EFEDB /* Sepia.nnwtheme */,
|
||||
5127B237222B4849006D641D /* DetailKeyboardShortcuts.plist */,
|
||||
@@ -1961,6 +1968,14 @@
|
||||
path = Reddit;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
5177C21027B07C8400643901 /* Recovered References */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
DFD6AACD27ADE86E00463FAD /* NewsFax.nnwtheme */,
|
||||
);
|
||||
name = "Recovered References";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
5183CCEA226F70350010922C /* Timer */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@@ -2036,7 +2051,6 @@
|
||||
51627A92238A3836007B3B4B /* CroppingPreviewParameters.swift */,
|
||||
512AF9C1236ED52C0066F8BE /* ImageHeaderView.swift */,
|
||||
512AF9DC236F05230066F8BE /* InteractiveLabel.swift */,
|
||||
51934CC1230F5963006127BE /* InteractiveNavigationController.swift */,
|
||||
51A9A5F42380F6A60033AADF /* ModalNavigationController.swift */,
|
||||
51EAED95231363EF00A9EEE3 /* NonIntrinsicButton.swift */,
|
||||
5183CCD9226E31A50010922C /* NonIntrinsicImageView.swift */,
|
||||
@@ -2245,7 +2259,6 @@
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
8483630C2262A3FE00DA1D35 /* MainWindow.storyboard */,
|
||||
51C0307F257D815A00609262 /* UnifiedWindow.storyboard */,
|
||||
849A975D1ED9EB72007D329B /* MainWindowController.swift */,
|
||||
519B8D322143397200FA689C /* SharingServiceDelegate.swift */,
|
||||
849EE72020391F560082A1EA /* SharingServicePickerDelegate.swift */,
|
||||
@@ -2494,6 +2507,7 @@
|
||||
51CD32C324D2CD57009ABAEF /* ArticlesDatabase */,
|
||||
51CD32C724D2E06C009ABAEF /* Secrets */,
|
||||
51CD32A824D2CB25009ABAEF /* SyncDatabase */,
|
||||
5177C21027B07C8400643901 /* Recovered References */,
|
||||
);
|
||||
sourceTree = "<group>";
|
||||
usesTabs = 1;
|
||||
@@ -2871,7 +2885,6 @@
|
||||
176813F12564BB2C00D98635 /* Resources */,
|
||||
1701E1BF25689B44009453D8 /* SwiftGen Localization */,
|
||||
17EF6A1725C4E59D002C9F81 /* Embed Frameworks */,
|
||||
84BB8F7F26224B5F00DB61F8 /* Delete Unnecessary Frameworks */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
@@ -2915,7 +2928,6 @@
|
||||
51314634235A7BBE00387FDC /* Frameworks */,
|
||||
51314635235A7BBE00387FDC /* Resources */,
|
||||
5102AE7724D17FB50050839C /* Embed Frameworks */,
|
||||
513F328A2593EFCE0003048F /* Delete Unnecessary Frameworks */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
@@ -2939,7 +2951,6 @@
|
||||
513C5CE3232571C2003D4054 /* Frameworks */,
|
||||
513C5CE4232571C2003D4054 /* Resources */,
|
||||
5102AE7324D17FAA0050839C /* Embed Frameworks */,
|
||||
513F328B2593F03F0003048F /* Delete Unnecessary Frameworks */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
@@ -3077,6 +3088,7 @@
|
||||
51C451DF2264C7F200C03939 /* Embed Frameworks */,
|
||||
513C5CF1232571C2003D4054 /* Embed App Extensions */,
|
||||
515D50802326D02600EE1167 /* Run Script: Verify No Build Settings */,
|
||||
5170CA5A279E468000702605 /* Delete Unnecessary Frameworks */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
@@ -3376,10 +3388,11 @@
|
||||
5103A9F5242258C600410853 /* AccountsAddCloudKit.xib in Resources */,
|
||||
65ED405E235DEF6C0081F399 /* DefaultFeeds.opml in Resources */,
|
||||
51333D3C2468615D00EB5C91 /* AddRedditFeedSheet.xib in Resources */,
|
||||
51C03082257D815A00609262 /* UnifiedWindow.storyboard in Resources */,
|
||||
65ED405F235DEF6C0081F399 /* Preferences.storyboard in Resources */,
|
||||
65ED4061235DEF6C0081F399 /* Assets.xcassets in Resources */,
|
||||
65ED4063235DEF6C0081F399 /* RenameSheet.xib in Resources */,
|
||||
DFD6AACF27ADE86E00463FAD /* NewsFax.nnwtheme in Resources */,
|
||||
5177C21227B07C9E00643901 /* NewsFax.nnwtheme in Resources */,
|
||||
65ED4064235DEF6C0081F399 /* AddFolderSheet.xib in Resources */,
|
||||
65ED4065235DEF6C0081F399 /* AccountsFeedbin.xib in Resources */,
|
||||
65ED4066235DEF6C0081F399 /* TimelineTableView.xib in Resources */,
|
||||
@@ -3395,6 +3408,7 @@
|
||||
65ED406C235DEF6C0081F399 /* Credits.rtf in Resources */,
|
||||
65ED406D235DEF6C0081F399 /* Inspector.storyboard in Resources */,
|
||||
65ED406E235DEF6C0081F399 /* AddWebFeedSheet.xib in Resources */,
|
||||
51077C5927A86D16000C71DB /* Hyperlegible.nnwtheme in Resources */,
|
||||
51DEE81326FB9233006DAA56 /* Appanoose.nnwtheme in Resources */,
|
||||
B27EEBFA244D15F3000932E6 /* stylesheet.css in Resources */,
|
||||
);
|
||||
@@ -3426,6 +3440,7 @@
|
||||
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 */,
|
||||
51DEE81A26FBFF84006DAA56 /* Promenade.nnwtheme in Resources */,
|
||||
1768140B2564BB8300D98635 /* NetNewsWire_iOSwidgetextension_target.xcconfig in Resources */,
|
||||
@@ -3445,6 +3460,7 @@
|
||||
49F40DF92335B71000552BF4 /* newsfoot.js in Resources */,
|
||||
512392C024E33A3C00F11704 /* RedditAdd.storyboard in Resources */,
|
||||
51F85BEF2272520B00C787DC /* Thanks.rtf in Resources */,
|
||||
5177C21327B07CFE00643901 /* NewsFax.nnwtheme in Resources */,
|
||||
51CE1C0923621EDA005548FC /* RefreshProgressView.xib in Resources */,
|
||||
84C9FC9D2262A1A900D921D6 /* Assets.xcassets in Resources */,
|
||||
514219582353C28900E07E2C /* main_ios.js in Resources */,
|
||||
@@ -3477,12 +3493,13 @@
|
||||
5144EA3B227A379E00D19003 /* ImportOPMLSheet.xib in Resources */,
|
||||
844B5B691FEA20DF00C7C76A /* SidebarKeyboardShortcuts.plist in Resources */,
|
||||
5103A9F4242258C600410853 /* AccountsAddCloudKit.xib in Resources */,
|
||||
51077C5827A86D16000C71DB /* Hyperlegible.nnwtheme in Resources */,
|
||||
84A3EE5F223B667F00557320 /* DefaultFeeds.opml in Resources */,
|
||||
51C03081257D815A00609262 /* UnifiedWindow.storyboard in Resources */,
|
||||
849C78902362AAFC009A71E4 /* ExportOPMLSheet.xib in Resources */,
|
||||
84C9FC8222629E4800D921D6 /* Preferences.storyboard in Resources */,
|
||||
849C64681ED37A5D003D8FC0 /* Assets.xcassets in Resources */,
|
||||
8483630B2262A3F000DA1D35 /* RenameSheet.xib in Resources */,
|
||||
5177C21427B07D1E00643901 /* NewsFax.nnwtheme in Resources */,
|
||||
848363052262A3CC00DA1D35 /* AddFolderSheet.xib in Resources */,
|
||||
5144EA52227B8E4500D19003 /* AccountsFeedbin.xib in Resources */,
|
||||
8405DDA222168920008CE1BF /* TimelineTableView.xib in Resources */,
|
||||
@@ -3532,42 +3549,6 @@
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "if ! command -v swiftgen &> /dev/null\nthen\n echo \"swiftgen could not be found\"\n exit\nfi\n\nswiftgen run strings -t structured-swift5 \"$PROJECT_DIR/Widget/Resources/en.lproj/Localizable.strings\" \"$PROJECT_DIR/Widget/Resources/Localizable.stringsdict\" --output \"$PROJECT_DIR/Widget/Resources/Localized.swift\";\n";
|
||||
};
|
||||
513F328A2593EFCE0003048F /* Delete Unnecessary Frameworks */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
name = "Delete Unnecessary Frameworks";
|
||||
outputFileListPaths = (
|
||||
);
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "# Delete the framework that Xcode should have never included\n# https://forums.swift.org/t/is-this-an-xcode-bug-or-somehow-related-to-spm/33987\nrm -rf \"${TARGET_BUILD_DIR}/NetNewsWire iOS Intents Extension.appex/Frameworks\"\n";
|
||||
};
|
||||
513F328B2593F03F0003048F /* Delete Unnecessary Frameworks */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
name = "Delete Unnecessary Frameworks";
|
||||
outputFileListPaths = (
|
||||
);
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "# Delete the framework that Xcode should have never included\n# https://forums.swift.org/t/is-this-an-xcode-bug-or-somehow-related-to-spm/33987\nrm -rf \"${TARGET_BUILD_DIR}/NetNewsWire iOS Share Extension.appex/Frameworks\"\n";
|
||||
};
|
||||
515D50802326D02600EE1167 /* Run Script: Verify No Build Settings */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 8;
|
||||
@@ -3584,7 +3565,25 @@
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 1;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "xcrun -sdk macosx swiftc -target x86_64-macosx10.11 buildscripts/VerifyNoBuildSettings.swift -o $CONFIGURATION_TEMP_DIR/VerifyNoBS\n$CONFIGURATION_TEMP_DIR/VerifyNoBS ${PROJECT_NAME}.xcodeproj/project.pbxproj\n\n\nif [ $? -ne 0 ]\nthen\n echo \"error: Build Setting were found in the project.pbxproj file. Most likely you didn't intend to change this file and should revert it.\"\n exit 1\nfi\n";
|
||||
shellScript = "xcrun -sdk macosx swiftc -target x86_64-macosx10.11 buildscripts/VerifyNoBS.swift -o $CONFIGURATION_TEMP_DIR/VerifyNoBS\n$CONFIGURATION_TEMP_DIR/VerifyNoBS ${PROJECT_NAME}.xcodeproj/project.pbxproj\n\n\nif [ $? -ne 0 ]\nthen\n echo \"error: Build Setting were found in the project.pbxproj file. Most likely you didn't intend to change this file and should revert it.\"\n exit 1\nfi\n";
|
||||
};
|
||||
5170CA5A279E468000702605 /* Delete Unnecessary Frameworks */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
name = "Delete Unnecessary Frameworks";
|
||||
outputFileListPaths = (
|
||||
);
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "cd \"${CODESIGNING_FOLDER_PATH}/PlugIns/\"\n\nfor plugin in *; do\n if [ -d \"$plugin\" ]; then\n if [ -d \"${plugin}/Frameworks\" ]; then\n rm -rf \"${plugin}/Frameworks\"\n fi\n fi\ndone\n\n# codesign for Debugging on device\nif [ \"${CONFIGURATION}\" == \"Debug\" ] & [ \"${SDKROOT}\" != *Simulator* ] ; then\n\n echo \"Code signing frameworks...\"\n find \"${CODESIGNING_FOLDER_PATH}/Frameworks\" -maxdepth 1 -name '*.framework' -print0 | while read -d $'\\0' framework\n do\n # only sign frameworks without a signature\n if ! codesign -v \"${framework}\"; then\n codesign --force --sign \"${EXPANDED_CODE_SIGN_IDENTITY}\" --preserve-metadata=identifier,entitlements --timestamp=none \"${framework}\"\n echo \"Added missing signature to '${framework}'\"\n fi\n done\nfi\n";
|
||||
};
|
||||
652832CF2683DD0400E6F37C /* Run Script: Delete Unnecessary Frameworks For Share Extension */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
@@ -3690,24 +3689,6 @@
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "# Remove unused Sparkle components\nSPARKLE_DIR=\"${CODESIGNING_FOLDER_PATH}/Contents/Frameworks/Sparkle.framework\"\nfind \"${SPARKLE_DIR}\" -name Updater.app -execdir rm -rf {} \\;\nfind \"${SPARKLE_DIR}\" -name Autoupdate -execdir rm -rf {} \\;\n\nPLUGINS_DIR=\"${CODESIGNING_FOLDER_PATH}/Contents/PlugIns\"\nXPC_DIR=\"${CODESIGNING_FOLDER_PATH}/Contents/XPCServices\"\nfind \"${PLUGINS_DIR}\" -name Sparkle* -execdir rm -rf {} \\;\nfind \"${XPC_DIR}\" -name Sparkle* -execdir rm -rf {} \\;\n\n# Re-sign Sparkle after removing components\ncodesign --verbose --force -o runtime --preserve-metadata=entitlements --sign \"${EXPANDED_CODE_SIGN_IDENTITY}\" \"${CODESIGNING_FOLDER_PATH}/Contents/Frameworks/Sparkle.framework\"\n\n# Sign XPC Helpers and their internal binaries\ncodesign --verbose --force -o runtime --preserve-metadata=entitlements --sign \"${EXPANDED_CODE_SIGN_IDENTITY}\" \"${CODESIGNING_FOLDER_PATH}/Contents/XPCServices/org.sparkle-project.InstallerLauncher.xpc/Contents/MacOS/Updater.app\"\ncodesign --verbose --force -o runtime --preserve-metadata=entitlements --sign \"${EXPANDED_CODE_SIGN_IDENTITY}\" \"${CODESIGNING_FOLDER_PATH}/Contents/XPCServices/org.sparkle-project.InstallerLauncher.xpc/Contents/MacOS/Autoupdate\"\ncodesign --verbose --entitlements \"${PROJECT_DIR}/submodules/Sparkle/Downloader/org.sparkle-project.Downloader.entitlements\" --force -o runtime --sign \"${EXPANDED_CODE_SIGN_IDENTITY}\" \"${CODESIGNING_FOLDER_PATH}/Contents/XPCServices/org.sparkle-project.Downloader.xpc\"\ncodesign --verbose --force -o runtime --preserve-metadata=entitlements --sign \"${EXPANDED_CODE_SIGN_IDENTITY}\" \"${CODESIGNING_FOLDER_PATH}/Contents/XPCServices/org.sparkle-project.InstallerLauncher.xpc\"\ncodesign --verbose --force -o runtime --preserve-metadata=entitlements --sign \"${EXPANDED_CODE_SIGN_IDENTITY}\" \"${CODESIGNING_FOLDER_PATH}/Contents/XPCServices/org.sparkle-project.InstallerConnection.xpc\"\ncodesign --verbose --force -o runtime --preserve-metadata=entitlements --sign \"${EXPANDED_CODE_SIGN_IDENTITY}\" \"${CODESIGNING_FOLDER_PATH}/Contents/XPCServices/org.sparkle-project.InstallerStatus.xpc\"\n";
|
||||
};
|
||||
84BB8F7F26224B5F00DB61F8 /* Delete Unnecessary Frameworks */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
name = "Delete Unnecessary Frameworks";
|
||||
outputFileListPaths = (
|
||||
);
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "# Delete the framework that Xcode should have never included\n# https://forums.swift.org/t/is-this-an-xcode-bug-or-somehow-related-to-spm/33987\nrm -rf \"${TARGET_BUILD_DIR}/NetNewsWire iOS Widget Extension.appex/Frameworks\"\n";
|
||||
};
|
||||
84C987A52000AC9E0066B150 /* Run Script: Automated build numbers */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
@@ -4215,7 +4196,6 @@
|
||||
51A1699D235E10D700EB091F /* SettingsViewController.swift in Sources */,
|
||||
51C45293226509C800C03939 /* StarredFeedDelegate.swift in Sources */,
|
||||
51D6A5BC23199C85001C27D8 /* MasterTimelineDataSource.swift in Sources */,
|
||||
51934CCB230F599B006127BE /* InteractiveNavigationController.swift in Sources */,
|
||||
769F2ED513DA03EE75B993A8 /* NewsBlurAccountViewController.swift in Sources */,
|
||||
51BC4B01247277E0000A6ED8 /* URL-Extensions.swift in Sources */,
|
||||
);
|
||||
@@ -4536,14 +4516,6 @@
|
||||
name = AddTwitterFeedSheet.xib;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
51C0307F257D815A00609262 /* UnifiedWindow.storyboard */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
51C03080257D815A00609262 /* Base */,
|
||||
);
|
||||
name = UnifiedWindow.storyboard;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
6581C73B20CED60100F4AD34 /* SafariExtensionViewController.xib */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
|
||||
@@ -26,6 +26,7 @@ struct ArticleTheme: Equatable {
|
||||
let path: String?
|
||||
let template: String?
|
||||
let css: String?
|
||||
let isAppTheme: Bool
|
||||
|
||||
var name: String {
|
||||
guard let path = path else { return Self.defaultThemeName }
|
||||
@@ -56,9 +57,11 @@ struct ArticleTheme: Equatable {
|
||||
|
||||
let templatePath = Bundle.main.path(forResource: "template", ofType: "html")!
|
||||
template = Self.stringAtPath(templatePath)!
|
||||
|
||||
isAppTheme = true
|
||||
}
|
||||
|
||||
init(path: String) throws {
|
||||
init(path: String, isAppTheme: Bool) throws {
|
||||
self.path = path
|
||||
|
||||
let infoPath = (path as NSString).appendingPathComponent("Info.plist")
|
||||
@@ -75,6 +78,8 @@ struct ArticleTheme: Equatable {
|
||||
|
||||
let templatePath = (path as NSString).appendingPathComponent("template.html")
|
||||
self.template = Self.stringAtPath(templatePath)
|
||||
|
||||
self.isAppTheme = isAppTheme
|
||||
}
|
||||
|
||||
static func stringAtPath(_ f: String) -> String? {
|
||||
|
||||
@@ -31,6 +31,7 @@ final class ArticleThemesManager: NSObject, NSFilePresenter {
|
||||
set {
|
||||
if newValue != currentThemeName {
|
||||
AppDefaults.shared.currentThemeName = newValue
|
||||
updateThemeNames()
|
||||
updateCurrentTheme()
|
||||
}
|
||||
}
|
||||
@@ -61,15 +62,6 @@ final class ArticleThemesManager: NSObject, NSFilePresenter {
|
||||
abort()
|
||||
}
|
||||
|
||||
let themeFilenames = Bundle.main.paths(forResourcesOfType: ArticleTheme.nnwThemeSuffix, inDirectory: nil)
|
||||
let installedThemes = readInstalledThemes() ?? [String: Date]()
|
||||
for themeFilename in themeFilenames {
|
||||
let themeName = ArticleTheme.themeNameForPath(themeFilename)
|
||||
if !installedThemes.keys.contains(themeName) {
|
||||
try? importTheme(filename: themeFilename)
|
||||
}
|
||||
}
|
||||
|
||||
updateThemeNames()
|
||||
updateCurrentTheme()
|
||||
|
||||
@@ -98,13 +90,34 @@ final class ArticleThemesManager: NSObject, NSFilePresenter {
|
||||
}
|
||||
|
||||
try FileManager.default.copyItem(atPath: filename, toPath: toFilename)
|
||||
|
||||
let themeName = ArticleTheme.themeNameForPath(filename)
|
||||
var installedThemes = readInstalledThemes() ?? [String: Date]()
|
||||
installedThemes[themeName] = Date()
|
||||
writeInstalledThemes(installedThemes)
|
||||
}
|
||||
|
||||
func articleThemeWithThemeName(_ themeName: String) -> ArticleTheme? {
|
||||
if themeName == AppDefaults.defaultThemeName {
|
||||
return ArticleTheme.defaultTheme
|
||||
}
|
||||
|
||||
let path: String
|
||||
let isAppTheme: Bool
|
||||
if let appThemePath = Bundle.main.url(forResource: themeName, withExtension: ArticleTheme.nnwThemeSuffix)?.path {
|
||||
path = appThemePath
|
||||
isAppTheme = true
|
||||
} else if let installedPath = pathForThemeName(themeName, folder: folderPath) {
|
||||
path = installedPath
|
||||
isAppTheme = false
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
|
||||
do {
|
||||
return try ArticleTheme(path: path, isAppTheme: isAppTheme)
|
||||
} catch {
|
||||
NotificationCenter.default.post(name: .didFailToImportThemeWithError, object: nil, userInfo: ["error": error])
|
||||
return nil
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func deleteTheme(themeName: String) {
|
||||
if let filename = pathForThemeName(themeName, folder: folderPath) {
|
||||
try? FileManager.default.removeItem(atPath: filename)
|
||||
@@ -118,30 +131,19 @@ final class ArticleThemesManager: NSObject, NSFilePresenter {
|
||||
private extension ArticleThemesManager {
|
||||
|
||||
func updateThemeNames() {
|
||||
let updatedThemeNames = allThemePaths(folderPath).map { ArticleTheme.themeNameForPath($0) }
|
||||
let sortedThemeNames = updatedThemeNames.sorted(by: { $0.compare($1, options: .caseInsensitive) == .orderedAscending })
|
||||
let appThemeFilenames = Bundle.main.paths(forResourcesOfType: ArticleTheme.nnwThemeSuffix, inDirectory: nil)
|
||||
let appThemeNames = Set(appThemeFilenames.map { ArticleTheme.themeNameForPath($0) })
|
||||
|
||||
let installedThemeNames = Set(allThemePaths(folderPath).map { ArticleTheme.themeNameForPath($0) })
|
||||
|
||||
let allThemeNames = appThemeNames.union(installedThemeNames)
|
||||
|
||||
let sortedThemeNames = allThemeNames.sorted(by: { $0.compare($1, options: .caseInsensitive) == .orderedAscending })
|
||||
if sortedThemeNames != themeNames {
|
||||
themeNames = sortedThemeNames
|
||||
}
|
||||
}
|
||||
|
||||
func articleThemeWithThemeName(_ themeName: String) -> ArticleTheme? {
|
||||
if themeName == AppDefaults.defaultThemeName {
|
||||
return ArticleTheme.defaultTheme
|
||||
}
|
||||
|
||||
guard let path = pathForThemeName(themeName, folder: folderPath) else {
|
||||
return nil
|
||||
}
|
||||
do {
|
||||
return try ArticleTheme(path: path)
|
||||
} catch {
|
||||
NotificationCenter.default.post(name: .didFailToImportThemeWithError, object: nil, userInfo: ["error": error])
|
||||
return nil
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func defaultArticleTheme() -> ArticleTheme {
|
||||
return articleThemeWithThemeName(AppDefaults.defaultThemeName)!
|
||||
}
|
||||
@@ -178,14 +180,4 @@ private extension ArticleThemesManager {
|
||||
return nil
|
||||
}
|
||||
|
||||
func readInstalledThemes() -> [String: Date]? {
|
||||
let filePath = (folderPath as NSString).appendingPathComponent("InstalledThemes.plist")
|
||||
return NSDictionary(contentsOfFile: filePath) as? [String: Date]
|
||||
}
|
||||
|
||||
func writeInstalledThemes(_ dict: [String: Date]) {
|
||||
let filePath = (folderPath as NSString).appendingPathComponent("InstalledThemes.plist")
|
||||
(dict as NSDictionary).write(toFile: filePath, atomically: true)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>Name</key>
|
||||
<string>Starter</string>
|
||||
<string>Appanoose</string>
|
||||
<key>ThemeIdentifier</key>
|
||||
<string>com.netnewswire.themes.starter</string>
|
||||
<key>CreatorHomePage</key>
|
||||
|
||||
16
Shared/Resources/Hyperlegible.nnwtheme/Info.plist
Normal file
16
Shared/Resources/Hyperlegible.nnwtheme/Info.plist
Normal file
@@ -0,0 +1,16 @@
|
||||
<?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>Name</key>
|
||||
<string>Hyperlegible</string>
|
||||
<key>ThemeIdentifier</key>
|
||||
<string>com.netnewswire.themes.hyperlegible</string>
|
||||
<key>CreatorHomePage</key>
|
||||
<string>http://netnewswire.com/</string>
|
||||
<key>CreatorName</key>
|
||||
<string>Ranchero Software</string>
|
||||
<key>Version</key>
|
||||
<integer>1</integer>
|
||||
</dict>
|
||||
</plist>
|
||||
509
Shared/Resources/Hyperlegible.nnwtheme/stylesheet.css
Normal file
509
Shared/Resources/Hyperlegible.nnwtheme/stylesheet.css
Normal file
File diff suppressed because one or more lines are too long
47
Shared/Resources/Hyperlegible.nnwtheme/template.html
Normal file
47
Shared/Resources/Hyperlegible.nnwtheme/template.html
Normal file
@@ -0,0 +1,47 @@
|
||||
<!-- Template Variables
|
||||
|
||||
title: The title of the article
|
||||
preferred_link: The best link to associate with the article for linking out.
|
||||
|
||||
external_link_label: A localized label for the external link.
|
||||
external_link_stripped: The external link minus the scheme. Useful for displaying the external link.
|
||||
external_link: The external link of the article if there is one provided by the author.
|
||||
|
||||
feed_link_title: The name of the feed associated with this article.
|
||||
feed_link: The URL of the feed associated with this article.
|
||||
byline: HTML that combines all the authors and links to them if available.
|
||||
avatar_src: The image source URL for the feed icon / avatar.
|
||||
dateline_style: Either "articleDateline" or "articleDatelineTitle" depending on if the title was populated or not.
|
||||
|
||||
datetime_long: Long version of a combined publish date and time.
|
||||
datetime_medium: Medium length version of a combined publish date and time.
|
||||
datetime_short: Short version of a combined publish date and time.
|
||||
|
||||
date_long: Long version of the publish date.
|
||||
date_medium: Medium version of the publish date.
|
||||
date_short: Long version of the publish date.
|
||||
|
||||
time_long: Long version of the publish time.
|
||||
time_medium: Medium version of the publish time.
|
||||
time_short: Long version of the publish time.
|
||||
|
||||
text_size_class: The size class that the user has selected in Preferences for article text.
|
||||
body: The body of the article.
|
||||
|
||||
-->
|
||||
|
||||
<header class="headerContainer">
|
||||
<table cellpadding=0 cellspacing=0 border=0 class="headerTable">
|
||||
<tr>
|
||||
<td class="header leftAlign"><a class="feedlink" href="[[feed_link]]">[[feed_link_title]]</a><br />[[byline]]</td>
|
||||
<td class="header rightAlign avatar"><img id="nnwImageIcon" src="[[avatar_src]]" height=48 width=48 /></td>
|
||||
</tr>
|
||||
</table>
|
||||
</header>
|
||||
|
||||
<article>
|
||||
<div class="articleTitle"><h1><a href="[[preferred_link]]">[[title]]</a></h1></div>
|
||||
<div class="[[dateline_style]]"><a href="[[preferred_link]]">[[datetime_medium]]</a></div>
|
||||
<div class="externalLink">[[external_link_label]] <a href="[[external_link]]">[[external_link_stripped]]</a></div>
|
||||
<div id="bodyContainer" class="articleBody [[text_size_class]]">[[body]]</div>
|
||||
</article>
|
||||
16
Shared/Resources/NewsFax.nnwtheme/Info.plist
Normal file
16
Shared/Resources/NewsFax.nnwtheme/Info.plist
Normal file
@@ -0,0 +1,16 @@
|
||||
<?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>Name</key>
|
||||
<string>NewsFax</string>
|
||||
<key>ThemeIdentifier</key>
|
||||
<string>com.mynameisstuart.themes.newsfax</string>
|
||||
<key>CreatorHomePage</key>
|
||||
<string>https://mynameisstuart.com/</string>
|
||||
<key>CreatorName</key>
|
||||
<string>Stuart Breckenridge</string>
|
||||
<key>Version</key>
|
||||
<integer>3</integer>
|
||||
</dict>
|
||||
</plist>
|
||||
19
Shared/Resources/NewsFax.nnwtheme/License.md
Normal file
19
Shared/Resources/NewsFax.nnwtheme/License.md
Normal file
@@ -0,0 +1,19 @@
|
||||
The NewsFax themes uses the ModeSeven font throughout, which is available as Freeware.
|
||||
|
||||
Find out more [here](https://www.fontspace.com/modeseven-font-f2369).
|
||||
|
||||
ModeSeven is based on the bitmap font in Teletext televisions,
|
||||
1980s-vintage Videotext terminals (such as the Prestel system used in
|
||||
the UK), and the BBC Micro computer. (The name derives from the BBC
|
||||
Micro screen mode which used the teletext character generator.)
|
||||
|
||||
This font looks "natural" at a size of 20 pixels, or any multiple thereof.
|
||||
However, it has been hinted as to scale as well as an ex-bitmap font
|
||||
can be expected to.
|
||||
|
||||
This font was created by hand with Fontographer 4.1.2 on a Macintosh.
|
||||
The character definitions were worked out from a bitmap version of the
|
||||
Teletext font created by James Fidell, and included in xbeeb (a BBC
|
||||
Micro emulator for UNIX/X11). The spacing of the original has been
|
||||
preserved, which is why many character shapes are aligned to the right
|
||||
of their cells.
|
||||
685
Shared/Resources/NewsFax.nnwtheme/stylesheet.css
Normal file
685
Shared/Resources/NewsFax.nnwtheme/stylesheet.css
Normal file
File diff suppressed because one or more lines are too long
90
Shared/Resources/NewsFax.nnwtheme/template.html
Normal file
90
Shared/Resources/NewsFax.nnwtheme/template.html
Normal file
@@ -0,0 +1,90 @@
|
||||
|
||||
<!-- Template Variables
|
||||
|
||||
title: The title of the article
|
||||
preferred_link: The best link to associate with the article for linking out.
|
||||
|
||||
external_link_label: A localized label for the external link.
|
||||
external_link_stripped: The external link minus the scheme. Useful for displaying the external link.
|
||||
external_link: The external link of the article if there is one provided by the author.
|
||||
|
||||
feed_link_title: The name of the feed associated with this article.
|
||||
feed_link: The URL of the feed associated with this article.
|
||||
byline: HTML that combines all the authors and links to them if available.
|
||||
avatar_src: The image source URL for the feed icon / avatar.
|
||||
dateline_style: Either "articleDateline" or "articleDatelineTitle" depending on if the title was populated or not.
|
||||
|
||||
datetime_long: Long version of a combined publish date and time.
|
||||
datetime_medium: Medium length version of a combined publish date and time.
|
||||
datetime_short: Short version of a combined publish date and time.
|
||||
|
||||
date_long: Long version of the publish date.
|
||||
date_medium: Medium version of the publish date.
|
||||
date_short: Long version of the publish date.
|
||||
|
||||
time_long: Long version of the publish time.
|
||||
time_medium: Medium version of the publish time.
|
||||
time_short: Long version of the publish time.
|
||||
|
||||
text_size_class: The size class that the user has selected in Preferences for article text.
|
||||
body: The body of the article.
|
||||
|
||||
-->
|
||||
|
||||
<div class="feedHeader">
|
||||
<table width="100%">
|
||||
<tr>
|
||||
<th class="newsfax" align="left">NEWSFAX</th>
|
||||
<th class="newsfax-page" align="left"></th>
|
||||
<th></th>
|
||||
<th align="right">[[datetime_short]]</th>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
|
||||
<div class="articleTitle">
|
||||
<h1><a href="[[preferred_link]]">[[title]]</a></h1>
|
||||
</div>
|
||||
<div><a href="[[feed_link]]">[[feed_link_title]]</a></div>
|
||||
<div>[[byline]]</div>
|
||||
</div>
|
||||
<hr />
|
||||
|
||||
<article>
|
||||
<div id="bodyContainer" class="articleBody [[text_size_class]]">[[body]]</div>
|
||||
<div class="externalLink"><a href="[[external_link]]">[[external_link]]</a></div>
|
||||
|
||||
<table class="newsfax-footer" width="100%">
|
||||
<tr>
|
||||
<th class="newsfax-footer-cell-red"><a href="https://duckduckgo.com/?q=news&t=h_&iar=news&ia=news">Headlines</a></th>
|
||||
<th class="newsfax-footer-cell-green"><a href="https://duckduckgo.com/?q=sports+news&t=h_&ia=web">Sport</a></th>
|
||||
<th class="newsfax-footer-cell-yellow"><a href="https://duckduckgo.com/?q=local+tv&t=h_&ia=places">Local TV<a></th>
|
||||
<th class="newsfax-footer-cell-blue"><a href="[[feed_link]]">Website</a></th>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
</article>
|
||||
<script type="text/javascript">
|
||||
/* Generate a random Newsfax page number */
|
||||
function getRandomIntInclusive(min, max) {
|
||||
min = Math.ceil(min);
|
||||
max = Math.floor(max);
|
||||
return Math.floor(Math.random() * (max - min + 1) + min); //The maximum is inclusive and the minimum is inclusive
|
||||
}
|
||||
|
||||
let random = getRandomIntInclusive(100, 999);
|
||||
let newsFaxElement = document.body.getElementsByClassName('newsfax-page')[0];
|
||||
newsFaxElement.innerHTML = "P" + random;
|
||||
|
||||
|
||||
/*
|
||||
The arrow-circle-right SVG is provided by Font Awesome under the Creative Commons Attribution 4.0 International License.
|
||||
For more details view the license here: https://fontawesome.com/license
|
||||
*/
|
||||
let externalLinkElement = document.body.getElementsByClassName('externalLink')[0].querySelectorAll('a')[0];
|
||||
if (externalLinkElement.innerText != '') {
|
||||
let host = externalLinkElement.hostname;
|
||||
externalLinkElement.innerHTML = host + " " + '->';
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -25,5 +25,6 @@ struct UserInfoKey {
|
||||
static let selectedFeedsState = "selectedFeedsState"
|
||||
static let isShowingExtractedArticle = "isShowingExtractedArticle"
|
||||
static let articleWindowScrollY = "articleWindowScrollY"
|
||||
static let isSidebarHidden = "isSidebarHidden"
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,19 @@
|
||||
# iOS Release Notes
|
||||
|
||||
### 6.1 TestFlight build 6103 - 25 Jan 2022
|
||||
|
||||
Fixed regression with keyboard shortcuts.
|
||||
Fixed crashing bug adding an account.
|
||||
|
||||
### 6.1 TestFlight build 6102 - 23 Jan 2022
|
||||
|
||||
Article themes. Several themes ship with the app, and you can create your own. You can change the theme in Preferences.
|
||||
Copy URLs using repaired, rather than raw, feed links.
|
||||
Disallow creation of iCloud account in the app if iCloud and iCloud Drive aren’t both enabled.
|
||||
Fixed bug showing quote tweets that only included an image.
|
||||
Video autoplay is now disallowed.
|
||||
Article view now supports RTL layout.
|
||||
|
||||
### 6.0.1 TestFlight build 608 - 28 Aug 2021
|
||||
|
||||
Fixed our top crashing bug — it could happen when updating a table view
|
||||
|
||||
@@ -257,6 +257,10 @@ struct AppAssets {
|
||||
let image = UIImage(systemName: "star.fill")!
|
||||
return IconImage(image, isSymbol: true, isBackgroundSupressed: true, preferredColor: AppAssets.starColor.cgColor)
|
||||
}
|
||||
|
||||
static var themeImage: UIImage = {
|
||||
return UIImage(systemName: "doc.richtext")!
|
||||
}()
|
||||
|
||||
static var tickMarkColor: UIColor = {
|
||||
return UIColor(named: "tickMarkColor")!
|
||||
|
||||
@@ -28,7 +28,7 @@ enum UserInterfaceColorPalette: Int, CustomStringConvertible, CaseIterable {
|
||||
|
||||
final class AppDefaults {
|
||||
|
||||
static let defaultThemeName = "Defaults"
|
||||
static let defaultThemeName = "Default"
|
||||
|
||||
static let shared = AppDefaults()
|
||||
private init() {}
|
||||
@@ -168,15 +168,6 @@ final class AppDefaults {
|
||||
}
|
||||
}
|
||||
|
||||
var articleFullscreenAvailable: Bool {
|
||||
get {
|
||||
return AppDefaults.bool(for: Key.articleFullscreenAvailable)
|
||||
}
|
||||
set {
|
||||
AppDefaults.setBool(for: Key.articleFullscreenAvailable, newValue)
|
||||
}
|
||||
}
|
||||
|
||||
var articleFullscreenEnabled: Bool {
|
||||
get {
|
||||
return AppDefaults.bool(for: Key.articleFullscreenEnabled)
|
||||
|
||||
@@ -12,19 +12,20 @@ import Account
|
||||
import Articles
|
||||
import SafariServices
|
||||
|
||||
class ArticleViewController: UIViewController {
|
||||
class ArticleViewController: UIViewController, MainControllerIdentifiable {
|
||||
|
||||
typealias State = (extractedArticle: ExtractedArticle?,
|
||||
isShowingExtractedArticle: Bool,
|
||||
articleExtractorButtonState: ArticleExtractorButtonState,
|
||||
windowScrollY: Int)
|
||||
|
||||
isShowingExtractedArticle: Bool,
|
||||
articleExtractorButtonState: ArticleExtractorButtonState,
|
||||
windowScrollY: Int)
|
||||
|
||||
@IBOutlet private weak var nextUnreadBarButtonItem: UIBarButtonItem!
|
||||
@IBOutlet private weak var prevArticleBarButtonItem: UIBarButtonItem!
|
||||
@IBOutlet private weak var nextArticleBarButtonItem: UIBarButtonItem!
|
||||
@IBOutlet private weak var readBarButtonItem: UIBarButtonItem!
|
||||
@IBOutlet private weak var starBarButtonItem: UIBarButtonItem!
|
||||
@IBOutlet private weak var actionBarButtonItem: UIBarButtonItem!
|
||||
@IBOutlet private weak var appearanceBarButtonItem: UIBarButtonItem!
|
||||
|
||||
@IBOutlet private var searchBar: ArticleSearchBar!
|
||||
@IBOutlet private var searchBarBottomConstraint: NSLayoutConstraint!
|
||||
@@ -43,8 +44,12 @@ class ArticleViewController: UIViewController {
|
||||
return button
|
||||
}()
|
||||
|
||||
var mainControllerIdentifer = MainControllerIdentifier.article
|
||||
|
||||
weak var coordinator: SceneCoordinator!
|
||||
|
||||
private let poppableDelegate = PoppableGestureRecognizerDelegate()
|
||||
|
||||
var article: Article? {
|
||||
didSet {
|
||||
if let controller = currentWebViewController, controller.article != article {
|
||||
@@ -84,34 +89,33 @@ class ArticleViewController: UIViewController {
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
||||
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(unreadCountDidChange(_:)), name: .UnreadCountDidChange, object: nil)
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(statusesDidChange(_:)), name: .StatusesDidChange, object: nil)
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(contentSizeCategoryDidChange(_:)), name: UIContentSizeCategory.didChangeNotification, object: nil)
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(willEnterForeground(_:)), name: UIApplication.willEnterForegroundNotification, object: nil)
|
||||
|
||||
let fullScreenTapZone = UIView()
|
||||
NSLayoutConstraint.activate([
|
||||
fullScreenTapZone.widthAnchor.constraint(equalToConstant: 150),
|
||||
fullScreenTapZone.heightAnchor.constraint(equalToConstant: 44)
|
||||
])
|
||||
fullScreenTapZone.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(didTapNavigationBar)))
|
||||
navigationItem.titleView = fullScreenTapZone
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(reloadDueToThemeChange(_:)), name: .CurrentArticleThemeDidChangeNotification, object: nil)
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(configureAppearanceMenu(_:)), name: .ArticleThemeNamesDidChangeNotification, object: nil)
|
||||
|
||||
articleExtractorButton.addTarget(self, action: #selector(toggleArticleExtractor(_:)), for: .touchUpInside)
|
||||
toolbarItems?.insert(UIBarButtonItem(customView: articleExtractorButton), at: 6)
|
||||
|
||||
if let parentNavController = navigationController?.parent as? UINavigationController {
|
||||
poppableDelegate.navigationController = parentNavController
|
||||
parentNavController.interactivePopGestureRecognizer?.delegate = poppableDelegate
|
||||
}
|
||||
|
||||
pageViewController = UIPageViewController(transitionStyle: .scroll, navigationOrientation: .horizontal, options: [:])
|
||||
pageViewController.delegate = self
|
||||
pageViewController.dataSource = self
|
||||
|
||||
|
||||
// This code is to disallow paging if we scroll from the left edge. If this code is removed
|
||||
// PoppableGestureRecognizerDelegate will allow us to both navigate back and page back at the
|
||||
// same time. That is really weird when it happens.
|
||||
let panGestureRecognizer = UIPanGestureRecognizer()
|
||||
panGestureRecognizer.delegate = self
|
||||
pageViewController.scrollViewInsidePageControl?.addGestureRecognizer(panGestureRecognizer)
|
||||
|
||||
|
||||
pageViewController.view.translatesAutoresizingMaskIntoConstraints = false
|
||||
view.addSubview(pageViewController.view)
|
||||
addChild(pageViewController!)
|
||||
@@ -121,7 +125,7 @@ class ArticleViewController: UIViewController {
|
||||
view.topAnchor.constraint(equalTo: pageViewController.view.topAnchor),
|
||||
view.bottomAnchor.constraint(equalTo: pageViewController.view.bottomAnchor)
|
||||
])
|
||||
|
||||
|
||||
let controller: WebViewController
|
||||
if let state = restoreState {
|
||||
controller = createWebViewController(article, updateView: false)
|
||||
@@ -136,13 +140,10 @@ class ArticleViewController: UIViewController {
|
||||
if let rsp = restoreScrollPosition {
|
||||
controller.setScrollPosition(isShowingExtractedArticle: rsp.isShowingExtractedArticle, articleWindowScrollY: rsp.articleWindowScrollY)
|
||||
}
|
||||
|
||||
|
||||
articleExtractorButton.buttonState = controller.articleExtractorButtonState
|
||||
|
||||
self.pageViewController.setViewControllers([controller], direction: .forward, animated: false, completion: nil)
|
||||
if AppDefaults.shared.articleFullscreenEnabled {
|
||||
controller.hideBars()
|
||||
}
|
||||
|
||||
// Search bar
|
||||
searchBar.translatesAutoresizingMaskIntoConstraints = false
|
||||
@@ -152,15 +153,21 @@ class ArticleViewController: UIViewController {
|
||||
searchBar.delegate = self
|
||||
view.bringSubviewToFront(searchBar)
|
||||
|
||||
configureAppearanceMenu()
|
||||
updateUI()
|
||||
}
|
||||
|
||||
override func viewDidAppear(_ animated: Bool) {
|
||||
super.viewDidAppear(true)
|
||||
coordinator.isArticleViewControllerPending = false
|
||||
|
||||
override func viewWillAppear(_ animated: Bool) {
|
||||
navigationController?.isToolbarHidden = false
|
||||
if AppDefaults.shared.articleFullscreenEnabled {
|
||||
currentWebViewController?.hideBars()
|
||||
}
|
||||
|
||||
super.viewWillAppear(animated)
|
||||
}
|
||||
|
||||
override func viewWillDisappear(_ animated: Bool) {
|
||||
super.viewWillDisappear(animated)
|
||||
if searchBar != nil && !searchBar.isHidden {
|
||||
endFind()
|
||||
}
|
||||
@@ -181,14 +188,16 @@ class ArticleViewController: UIViewController {
|
||||
readBarButtonItem.isEnabled = false
|
||||
starBarButtonItem.isEnabled = false
|
||||
actionBarButtonItem.isEnabled = false
|
||||
appearanceBarButtonItem.isEnabled = false
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
nextUnreadBarButtonItem.isEnabled = coordinator.isAnyUnreadAvailable
|
||||
prevArticleBarButtonItem.isEnabled = coordinator.isPrevArticleAvailable
|
||||
nextArticleBarButtonItem.isEnabled = coordinator.isNextArticleAvailable
|
||||
readBarButtonItem.isEnabled = true
|
||||
starBarButtonItem.isEnabled = true
|
||||
appearanceBarButtonItem.isEnabled = true
|
||||
|
||||
let permalinkPresent = article.preferredLink != nil
|
||||
var isFeedProvider = false
|
||||
@@ -218,6 +227,66 @@ class ArticleViewController: UIViewController {
|
||||
|
||||
}
|
||||
|
||||
override func contentScrollView(for edge: NSDirectionalRectEdge) -> UIScrollView? {
|
||||
return currentWebViewController?.webView?.scrollView
|
||||
}
|
||||
|
||||
@objc
|
||||
func configureAppearanceMenu(_ sender: Any? = nil) {
|
||||
|
||||
var themeActions = [UIAction]()
|
||||
|
||||
for themeName in ArticleThemesManager.shared.themeNames {
|
||||
let action = UIAction(title: themeName,
|
||||
image: nil,
|
||||
identifier: nil,
|
||||
discoverabilityTitle: nil,
|
||||
attributes: [],
|
||||
state: ArticleThemesManager.shared.currentThemeName == themeName ? .on : .off,
|
||||
handler: { action in
|
||||
ArticleThemesManager.shared.currentThemeName = themeName
|
||||
})
|
||||
themeActions.append(action)
|
||||
}
|
||||
|
||||
let defaultThemeAction = UIAction(title: NSLocalizedString("Default", comment: "Default"), image: nil, identifier: nil, discoverabilityTitle: nil, attributes: [], state: ArticleThemesManager.shared.currentThemeName == AppDefaults.defaultThemeName ? .on : .off) { _ in
|
||||
ArticleThemesManager.shared.currentThemeName = AppDefaults.defaultThemeName
|
||||
}
|
||||
themeActions.append(defaultThemeAction)
|
||||
|
||||
let themeMenu = UIMenu(title: "Theme", image: AppAssets.themeImage, identifier: nil, options: .singleSelection, children: themeActions)
|
||||
themeMenu.subtitle = NSLocalizedString("Change the look of articles.", comment: "Change theme")
|
||||
|
||||
var children: [UIMenuElement] = [themeMenu]
|
||||
|
||||
if let currentWebViewController = currentWebViewController {
|
||||
if currentWebViewController.isFullScreenAvailable {
|
||||
let fullScreenAction = UIAction(title: NSLocalizedString("Full Screen", comment: "Full Screen"),
|
||||
image: UIImage(systemName: "arrow.up.backward.and.arrow.down.forward"),
|
||||
identifier: nil,
|
||||
discoverabilityTitle: nil,
|
||||
attributes: [],
|
||||
state: .off) { [weak self] _ in
|
||||
self?.currentWebViewController?.hideBars()
|
||||
}
|
||||
fullScreenAction.subtitle = NSLocalizedString("Tap the top of the screen to exit Full Screen.", comment: "Exit criteria.")
|
||||
children.append(fullScreenAction)
|
||||
}
|
||||
}
|
||||
|
||||
let appearanceMenu = UIMenu(title: NSLocalizedString("Article Appearance", comment: "Appearance"), image: UIImage(systemName: "textformat.size") , identifier: nil, options: .displayInline, children: children)
|
||||
|
||||
appearanceBarButtonItem.menu = appearanceMenu
|
||||
|
||||
}
|
||||
|
||||
@objc
|
||||
func reloadDueToThemeChange(_ notification: Notification) {
|
||||
currentWebViewController?.fullReload()
|
||||
configureAppearanceMenu()
|
||||
}
|
||||
|
||||
|
||||
// MARK: Notifications
|
||||
|
||||
@objc dynamic func unreadCountDidChange(_ notification: Notification) {
|
||||
@@ -235,7 +304,7 @@ class ArticleViewController: UIViewController {
|
||||
updateUI()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@objc func contentSizeCategoryDidChange(_ note: Notification) {
|
||||
currentWebViewController?.fullReload()
|
||||
}
|
||||
@@ -248,15 +317,11 @@ class ArticleViewController: UIViewController {
|
||||
}
|
||||
|
||||
// MARK: Actions
|
||||
|
||||
@objc func didTapNavigationBar() {
|
||||
currentWebViewController?.hideBars()
|
||||
}
|
||||
|
||||
|
||||
@objc func showBars(_ sender: Any) {
|
||||
currentWebViewController?.showBars()
|
||||
}
|
||||
|
||||
|
||||
@IBAction func toggleArticleExtractor(_ sender: Any) {
|
||||
currentWebViewController?.toggleArticleExtractor()
|
||||
}
|
||||
@@ -284,35 +349,35 @@ class ArticleViewController: UIViewController {
|
||||
@IBAction func showActivityDialog(_ sender: Any) {
|
||||
currentWebViewController?.showActivityDialog(popOverBarButtonItem: actionBarButtonItem)
|
||||
}
|
||||
|
||||
|
||||
@objc func toggleReaderView(_ sender: Any?) {
|
||||
currentWebViewController?.toggleArticleExtractor()
|
||||
}
|
||||
|
||||
// MARK: Keyboard Shortcuts
|
||||
|
||||
|
||||
@objc func navigateToTimeline(_ sender: Any?) {
|
||||
coordinator.navigateToTimeline()
|
||||
}
|
||||
|
||||
// MARK: API
|
||||
|
||||
|
||||
func focus() {
|
||||
currentWebViewController?.focus()
|
||||
}
|
||||
|
||||
|
||||
func canScrollDown() -> Bool {
|
||||
return currentWebViewController?.canScrollDown() ?? false
|
||||
}
|
||||
|
||||
|
||||
func canScrollUp() -> Bool {
|
||||
return currentWebViewController?.canScrollUp() ?? false
|
||||
}
|
||||
|
||||
|
||||
func scrollPageDown() {
|
||||
currentWebViewController?.scrollPageDown()
|
||||
}
|
||||
|
||||
|
||||
func scrollPageUp() {
|
||||
currentWebViewController?.scrollPageUp()
|
||||
}
|
||||
@@ -320,7 +385,7 @@ class ArticleViewController: UIViewController {
|
||||
func stopArticleExtractorIfProcessing() {
|
||||
currentWebViewController?.stopArticleExtractorIfProcessing()
|
||||
}
|
||||
|
||||
|
||||
func openInAppBrowser() {
|
||||
currentWebViewController?.openInAppBrowser()
|
||||
}
|
||||
@@ -387,9 +452,9 @@ extension ArticleViewController {
|
||||
|
||||
@objc func keyboardWillChangeFrame(_ notification: Notification) {
|
||||
if !searchBar.isHidden,
|
||||
let duration = notification.userInfo?[UIWindow.keyboardAnimationDurationUserInfoKey] as? Double,
|
||||
let curveRaw = notification.userInfo?[UIWindow.keyboardAnimationCurveUserInfoKey] as? UInt,
|
||||
let frame = notification.userInfo?[UIWindow.keyboardFrameEndUserInfoKey] as? CGRect {
|
||||
let duration = notification.userInfo?[UIWindow.keyboardAnimationDurationUserInfoKey] as? Double,
|
||||
let curveRaw = notification.userInfo?[UIWindow.keyboardAnimationCurveUserInfoKey] as? UInt,
|
||||
let frame = notification.userInfo?[UIWindow.keyboardFrameEndUserInfoKey] as? CGRect {
|
||||
|
||||
let curve = UIView.AnimationOptions(rawValue: curveRaw)
|
||||
let newHeight = view.safeAreaLayoutGuide.layoutFrame.maxY - frame.minY
|
||||
@@ -422,19 +487,19 @@ extension ArticleViewController: UIPageViewControllerDataSource {
|
||||
|
||||
func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
|
||||
guard let webViewController = viewController as? WebViewController,
|
||||
let currentArticle = webViewController.article,
|
||||
let article = coordinator.findPrevArticle(currentArticle) else {
|
||||
return nil
|
||||
}
|
||||
let currentArticle = webViewController.article,
|
||||
let article = coordinator.findPrevArticle(currentArticle) else {
|
||||
return nil
|
||||
}
|
||||
return createWebViewController(article)
|
||||
}
|
||||
|
||||
func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
|
||||
guard let webViewController = viewController as? WebViewController,
|
||||
let currentArticle = webViewController.article,
|
||||
let article = coordinator.findNextArticle(currentArticle) else {
|
||||
return nil
|
||||
}
|
||||
let currentArticle = webViewController.article,
|
||||
let article = coordinator.findNextArticle(currentArticle) else {
|
||||
return nil
|
||||
}
|
||||
return createWebViewController(article)
|
||||
}
|
||||
|
||||
@@ -443,7 +508,7 @@ extension ArticleViewController: UIPageViewControllerDataSource {
|
||||
// MARK: UIPageViewControllerDelegate
|
||||
|
||||
extension ArticleViewController: UIPageViewControllerDelegate {
|
||||
|
||||
|
||||
func pageViewController(_ pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool) {
|
||||
guard finished, completed else { return }
|
||||
guard let article = currentWebViewController?.article else { return }
|
||||
@@ -460,17 +525,17 @@ extension ArticleViewController: UIPageViewControllerDelegate {
|
||||
|
||||
extension ArticleViewController: UIGestureRecognizerDelegate {
|
||||
|
||||
func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
|
||||
func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
|
||||
let point = gestureRecognizer.location(in: nil)
|
||||
if point.x > 40 {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -19,8 +19,8 @@ class PreloadedWebView: WKWebView {
|
||||
preferences.javaScriptCanOpenWindowsAutomatically = false
|
||||
|
||||
/// The defaults for `preferredContentMode` and `allowsContentJavaScript` are suitable
|
||||
/// and don't need to be explicity set.
|
||||
/// `allowsContentJavaScript` replaces `WKPreferences.javascriptEnbaled`.
|
||||
/// and don't need to be explicitly set.
|
||||
/// `allowsContentJavaScript` replaces `WKPreferences.javascriptEnabled`.
|
||||
let webpagePreferences = WKWebpagePreferences()
|
||||
|
||||
let configuration = WKWebViewConfiguration()
|
||||
|
||||
@@ -31,13 +31,13 @@ class WebViewController: UIViewController {
|
||||
private var topShowBarsViewConstraint: NSLayoutConstraint!
|
||||
private var bottomShowBarsViewConstraint: NSLayoutConstraint!
|
||||
|
||||
private var webView: PreloadedWebView? {
|
||||
var webView: PreloadedWebView? {
|
||||
return view.subviews[0] as? PreloadedWebView
|
||||
}
|
||||
|
||||
private lazy var contextMenuInteraction = UIContextMenuInteraction(delegate: self)
|
||||
private var isFullScreenAvailable: Bool {
|
||||
return AppDefaults.shared.articleFullscreenAvailable && traitCollection.userInterfaceIdiom == .phone && coordinator.isRootSplitCollapsed
|
||||
public var isFullScreenAvailable: Bool {
|
||||
return traitCollection.userInterfaceIdiom == .phone && coordinator.isRootSplitCollapsed
|
||||
}
|
||||
private lazy var transition = ImageTransition(controller: self)
|
||||
private var clickedImageCompletion: (() -> Void)?
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="19529" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="19529" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="AJQ-jq-uMa">
|
||||
<device id="retina6_1" orientation="portrait" appearance="light"/>
|
||||
<dependencies>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="19519"/>
|
||||
@@ -17,7 +17,7 @@
|
||||
<rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<view hidden="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="h1Q-FS-jlg" customClass="ArticleSearchBar" customModule="NetNewsWire" customModuleProvider="target">
|
||||
<view hidden="YES" contentMode="scaleToFill" ambiguous="YES" translatesAutoresizingMaskIntoConstraints="NO" id="h1Q-FS-jlg" customClass="ArticleSearchBar" customModule="NetNewsWire" customModuleProvider="target">
|
||||
<rect key="frame" x="0.0" y="782" width="414" height="31"/>
|
||||
<color key="backgroundColor" name="barBackgroundColor"/>
|
||||
</view>
|
||||
@@ -90,12 +90,18 @@
|
||||
<action selector="prevArticle:" destination="JEX-9P-axG" id="cMZ-tk-I4W"/>
|
||||
</connections>
|
||||
</barButtonItem>
|
||||
<barButtonItem image="textformat.size" catalog="system" id="SoN-ax-tEE">
|
||||
<userDefinedRuntimeAttributes>
|
||||
<userDefinedRuntimeAttribute type="string" keyPath="accLabelText" value="Appearance"/>
|
||||
</userDefinedRuntimeAttributes>
|
||||
</barButtonItem>
|
||||
</rightBarButtonItems>
|
||||
</navigationItem>
|
||||
<simulatedNavigationBarMetrics key="simulatedTopBarMetrics" prompted="NO"/>
|
||||
<simulatedToolbarMetrics key="simulatedBottomBarMetrics"/>
|
||||
<connections>
|
||||
<outlet property="actionBarButtonItem" destination="9Ut-5B-JKP" id="9bO-kz-cTz"/>
|
||||
<outlet property="appearanceBarButtonItem" destination="SoN-ax-tEE" id="UZr-ut-0fn"/>
|
||||
<outlet property="nextArticleBarButtonItem" destination="2qz-M5-Yhk" id="IQd-jx-qEr"/>
|
||||
<outlet property="nextUnreadBarButtonItem" destination="2w5-e9-C2V" id="Ekf-My-AHN"/>
|
||||
<outlet property="prevArticleBarButtonItem" destination="v4j-fq-23N" id="Gny-Oh-cQa"/>
|
||||
@@ -107,7 +113,7 @@
|
||||
</viewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="FJe-Yq-33r" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="2318.840579710145" y="-759.375"/>
|
||||
<point key="canvasLocation" x="451" y="-431"/>
|
||||
</scene>
|
||||
<!--Timeline-->
|
||||
<scene sceneID="fag-XH-avP">
|
||||
@@ -153,12 +159,26 @@
|
||||
</tableViewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="nzm-Gf-Xce" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="1620" y="-759"/>
|
||||
<point key="canvasLocation" x="451" y="-1124"/>
|
||||
</scene>
|
||||
<!--Root Split View Controller-->
|
||||
<scene sceneID="FfI-oe-67h">
|
||||
<objects>
|
||||
<splitViewController storyboardIdentifier="RootSplitViewController" allowDoubleColumnStyle="YES" preferredDisplayMode="twoBeside" id="AJQ-jq-uMa" customClass="RootSplitViewController" customModule="NetNewsWire" customModuleProvider="target" sceneMemberID="viewController">
|
||||
<connections>
|
||||
<segue destination="Kyk-vK-QRX" kind="relationship" relationship="supplementaryViewController" id="FW6-KM-3C4"/>
|
||||
<segue destination="JEX-9P-axG" kind="relationship" relationship="detailViewController" id="JbU-kn-u7r"/>
|
||||
<segue destination="7bK-jq-Zjz" kind="relationship" relationship="masterViewController" id="rFx-mT-r7a"/>
|
||||
</connections>
|
||||
</splitViewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="9SW-km-PuE" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="-1320" y="-1123"/>
|
||||
</scene>
|
||||
<!--Feeds-->
|
||||
<scene sceneID="smW-Zh-WAh">
|
||||
<objects>
|
||||
<tableViewController storyboardIdentifier="MasterFeedViewController" useStoryboardIdentifierAsRestorationIdentifier="YES" clearsSelectionOnViewWillAppear="NO" id="7bK-jq-Zjz" customClass="MasterFeedViewController" customModule="NetNewsWire" customModuleProvider="target" sceneMemberID="viewController">
|
||||
<tableViewController storyboardIdentifier="MasterFeedViewController" extendedLayoutIncludesOpaqueBars="YES" useStoryboardIdentifierAsRestorationIdentifier="YES" clearsSelectionOnViewWillAppear="NO" id="7bK-jq-Zjz" customClass="MasterFeedViewController" customModule="NetNewsWire" customModuleProvider="target" sceneMemberID="viewController">
|
||||
<tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="grouped" separatorStyle="default" rowHeight="-1" estimatedRowHeight="-1" sectionHeaderHeight="18" sectionFooterHeight="18" id="r7i-6Z-zg0">
|
||||
<rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
@@ -216,7 +236,7 @@
|
||||
</tableViewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="Rux-fX-hf1" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="900" y="-759"/>
|
||||
<point key="canvasLocation" x="452" y="-1794"/>
|
||||
</scene>
|
||||
<!--Image View Controller-->
|
||||
<scene sceneID="TT4-oA-DBw">
|
||||
@@ -407,6 +427,7 @@
|
||||
<image name="square.and.arrow.up" catalog="system" width="115" height="128"/>
|
||||
<image name="square.and.arrow.up.fill" catalog="system" width="115" height="128"/>
|
||||
<image name="star" catalog="system" width="128" height="116"/>
|
||||
<image name="textformat.size" catalog="system" width="128" height="80"/>
|
||||
<namedColor name="barBackgroundColor">
|
||||
<color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
</namedColor>
|
||||
|
||||
@@ -47,7 +47,11 @@ class KeyboardManager {
|
||||
|
||||
static func createKeyCommand(title: String, action: String, input: String, modifiers: UIKeyModifierFlags) -> UIKeyCommand {
|
||||
let selector = NSSelectorFromString(action)
|
||||
return UIKeyCommand(title: title, image: nil, action: selector, input: input, modifierFlags: modifiers, propertyList: nil, alternates: [], discoverabilityTitle: nil, attributes: [], state: .on)
|
||||
let keyCommand = UIKeyCommand(title: title, image: nil, action: selector, input: input, modifierFlags: modifiers, propertyList: nil, alternates: [], discoverabilityTitle: nil, attributes: [], state: .on)
|
||||
if #available(iOS 15.0, *) {
|
||||
keyCommand.wantsPriorityOverSystemBehavior = true
|
||||
}
|
||||
return keyCommand
|
||||
}
|
||||
|
||||
}
|
||||
@@ -62,7 +66,11 @@ private extension KeyboardManager {
|
||||
if let title = keyEntry["title"] as? String {
|
||||
return KeyboardManager.createKeyCommand(title: title, action: action, input: input, modifiers: modifiers)
|
||||
} else {
|
||||
return UIKeyCommand(input: input, modifierFlags: modifiers, action: NSSelectorFromString(action))
|
||||
let keyCommand = UIKeyCommand(input: input, modifierFlags: modifiers, action: NSSelectorFromString(action))
|
||||
if #available(iOS 15.0, *) {
|
||||
keyCommand.wantsPriorityOverSystemBehavior = true
|
||||
}
|
||||
return keyCommand
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@ struct MasterFeedTableViewCellLayout {
|
||||
var rDisclosure = CGRect.zero
|
||||
if shouldShowDisclosure {
|
||||
rDisclosure.size = MasterFeedTableViewCellLayout.disclosureButtonSize
|
||||
rDisclosure.origin.x = bounds.origin.x
|
||||
rDisclosure.origin.x = insets.left
|
||||
}
|
||||
|
||||
// Favicon
|
||||
@@ -73,7 +73,7 @@ struct MasterFeedTableViewCellLayout {
|
||||
}
|
||||
|
||||
// Title
|
||||
var rLabelx = MasterFeedTableViewCellLayout.disclosureButtonSize.width
|
||||
var rLabelx = MasterFeedTableViewCellLayout.disclosureButtonSize.width + insets.left
|
||||
if itemIsInFolder {
|
||||
rLabelx += MasterFeedTableViewCellLayout.disclosureButtonSize.width - (rFavicon.width / 2)
|
||||
}
|
||||
|
||||
@@ -62,8 +62,6 @@ class MasterFeedTableViewSectionHeader: UITableViewHeaderFooterView {
|
||||
return label
|
||||
}()
|
||||
|
||||
private let unreadCountView = MasterFeedUnreadCountView(frame: CGRect.zero)
|
||||
|
||||
private lazy var disclosureButton: UIButton = {
|
||||
let button = NonIntrinsicButton()
|
||||
button.tintColor = AppAssets.secondaryAccentColor
|
||||
@@ -97,7 +95,7 @@ class MasterFeedTableViewSectionHeader: UITableViewHeaderFooterView {
|
||||
}
|
||||
|
||||
override func sizeThatFits(_ size: CGSize) -> CGSize {
|
||||
let layout = MasterFeedTableViewSectionHeaderLayout(cellWidth: size.width, insets: safeAreaInsets, label: titleView, unreadCountView: unreadCountView)
|
||||
let layout = MasterFeedTableViewSectionHeaderLayout(cellWidth: size.width, insets: safeAreaInsets, label: titleView)
|
||||
return CGSize(width: bounds.width, height: layout.height)
|
||||
|
||||
}
|
||||
@@ -106,8 +104,7 @@ class MasterFeedTableViewSectionHeader: UITableViewHeaderFooterView {
|
||||
super.layoutSubviews()
|
||||
let layout = MasterFeedTableViewSectionHeaderLayout(cellWidth: contentView.bounds.size.width,
|
||||
insets: contentView.safeAreaInsets,
|
||||
label: titleView,
|
||||
unreadCountView: unreadCountView)
|
||||
label: titleView)
|
||||
layoutWith(layout)
|
||||
}
|
||||
|
||||
@@ -157,7 +154,6 @@ private extension MasterFeedTableViewSectionHeader {
|
||||
|
||||
func layoutWith(_ layout: MasterFeedTableViewSectionHeaderLayout) {
|
||||
titleView.setFrameIfNotEqual(layout.titleRect)
|
||||
unreadCountView.setFrameIfNotEqual(layout.unreadCountRect)
|
||||
disclosureButton.setFrameIfNotEqual(layout.disclosureButtonRect)
|
||||
|
||||
let top = CGRect(x: safeAreaInsets.left, y: 0, width: frame.width - safeAreaInsets.right - safeAreaInsets.left, height: 0.33)
|
||||
|
||||
@@ -12,19 +12,17 @@ import RSCore
|
||||
struct MasterFeedTableViewSectionHeaderLayout {
|
||||
|
||||
private static let labelMarginRight = CGFloat(integerLiteral: 8)
|
||||
private static let unreadCountMarginRight = CGFloat(integerLiteral: 0)
|
||||
private static let disclosureButtonSize = CGSize(width: 44, height: 44)
|
||||
private static let verticalPadding = CGFloat(integerLiteral: 11)
|
||||
|
||||
private static let minRowHeight = CGFloat(integerLiteral: 44)
|
||||
|
||||
let titleRect: CGRect
|
||||
let unreadCountRect: CGRect
|
||||
let disclosureButtonRect: CGRect
|
||||
|
||||
let height: CGFloat
|
||||
|
||||
init(cellWidth: CGFloat, insets: UIEdgeInsets, label: UILabel, unreadCountView: MasterFeedUnreadCountView) {
|
||||
init(cellWidth: CGFloat, insets: UIEdgeInsets, label: UILabel) {
|
||||
|
||||
let bounds = CGRect(x: insets.left, y: 0.0, width: floor(cellWidth - insets.right), height: 0.0)
|
||||
|
||||
@@ -33,35 +31,20 @@ struct MasterFeedTableViewSectionHeaderLayout {
|
||||
rDisclosure.size = MasterFeedTableViewSectionHeaderLayout.disclosureButtonSize
|
||||
rDisclosure.origin.x = bounds.maxX - rDisclosure.size.width
|
||||
|
||||
// Unread Count
|
||||
let unreadCountSize = unreadCountView.contentSize
|
||||
let unreadCountIsHidden = unreadCountView.unreadCount < 1
|
||||
|
||||
var rUnread = CGRect.zero
|
||||
if !unreadCountIsHidden {
|
||||
rUnread.size = unreadCountSize
|
||||
rUnread.origin.x = bounds.maxX - (MasterFeedTableViewSectionHeaderLayout.unreadCountMarginRight + unreadCountSize.width + rDisclosure.size.width)
|
||||
}
|
||||
|
||||
// Max Unread Count
|
||||
// We can't reload Section Headers so we don't let the title extend into the (probably) worse case Unread Count area.
|
||||
let maxUnreadCountView = MasterFeedUnreadCountView(frame: CGRect.zero)
|
||||
maxUnreadCountView.unreadCount = 888
|
||||
let maxUnreadCountSize = maxUnreadCountView.contentSize
|
||||
|
||||
// Title
|
||||
let rLabelx = 15.0
|
||||
let rLabely = UIFontMetrics.default.scaledValue(for: MasterFeedTableViewSectionHeaderLayout.verticalPadding)
|
||||
|
||||
var labelWidth = CGFloat.zero
|
||||
labelWidth = cellWidth - (rLabelx + MasterFeedTableViewSectionHeaderLayout.labelMarginRight + maxUnreadCountSize.width + MasterFeedTableViewSectionHeaderLayout.unreadCountMarginRight)
|
||||
labelWidth = cellWidth - (rLabelx + MasterFeedTableViewSectionHeaderLayout.labelMarginRight)
|
||||
|
||||
let labelSizeInfo = MultilineUILabelSizer.size(for: label.text ?? "", font: label.font, numberOfLines: 0, width: Int(floor(labelWidth)))
|
||||
var rLabel = CGRect(x: rLabelx, y: rLabely, width: labelWidth, height: labelSizeInfo.size.height)
|
||||
|
||||
// Determine cell height
|
||||
let paddedLabelHeight = rLabel.maxY + UIFontMetrics.default.scaledValue(for: MasterFeedTableViewSectionHeaderLayout.verticalPadding)
|
||||
let maxGraphicsHeight = [rUnread, rDisclosure].maxY()
|
||||
let maxGraphicsHeight = [rDisclosure].maxY()
|
||||
var cellHeight = max(paddedLabelHeight, maxGraphicsHeight)
|
||||
if cellHeight < MasterFeedTableViewSectionHeaderLayout.minRowHeight {
|
||||
cellHeight = MasterFeedTableViewSectionHeaderLayout.minRowHeight
|
||||
@@ -69,9 +52,6 @@ struct MasterFeedTableViewSectionHeaderLayout {
|
||||
|
||||
// Center in Cell
|
||||
let newBounds = CGRect(x: bounds.origin.x, y: bounds.origin.y, width: bounds.width, height: cellHeight)
|
||||
if !unreadCountIsHidden {
|
||||
rUnread = MasterFeedTableViewCellLayout.centerVertically(rUnread, newBounds)
|
||||
}
|
||||
rDisclosure = MasterFeedTableViewCellLayout.centerVertically(rDisclosure, newBounds)
|
||||
|
||||
// Small fonts need centered if we hit the minimum row height
|
||||
@@ -81,7 +61,6 @@ struct MasterFeedTableViewSectionHeaderLayout {
|
||||
|
||||
// Assign the properties
|
||||
self.height = cellHeight
|
||||
self.unreadCountRect = rUnread
|
||||
self.disclosureButtonRect = rDisclosure
|
||||
self.titleRect = rLabel
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ import RSCore
|
||||
import RSTree
|
||||
import SafariServices
|
||||
|
||||
class MasterFeedViewController: UITableViewController, UndoableCommandRunner {
|
||||
class MasterFeedViewController: UITableViewController, UndoableCommandRunner, MainControllerIdentifiable {
|
||||
|
||||
@IBOutlet weak var filterButton: UIBarButtonItem!
|
||||
private var refreshProgressView: RefreshProgressView?
|
||||
@@ -23,9 +23,11 @@ class MasterFeedViewController: UITableViewController, UndoableCommandRunner {
|
||||
}
|
||||
}
|
||||
|
||||
var undoableCommands = [UndoableCommand]()
|
||||
weak var coordinator: SceneCoordinator!
|
||||
var mainControllerIdentifer = MainControllerIdentifier.masterFeed
|
||||
|
||||
weak var coordinator: SceneCoordinator!
|
||||
var undoableCommands = [UndoableCommand]()
|
||||
|
||||
private let keyboardManager = KeyboardManager(type: .sidebar)
|
||||
override var keyCommands: [UIKeyCommand]? {
|
||||
|
||||
@@ -78,6 +80,7 @@ class MasterFeedViewController: UITableViewController, UndoableCommandRunner {
|
||||
}
|
||||
|
||||
override func viewWillAppear(_ animated: Bool) {
|
||||
navigationController?.isToolbarHidden = false
|
||||
updateUI()
|
||||
super.viewWillAppear(animated)
|
||||
}
|
||||
|
||||
@@ -27,8 +27,9 @@ struct MasterTimelineCellData {
|
||||
let starred: Bool
|
||||
let numberOfLines: Int
|
||||
let iconSize: IconSize
|
||||
|
||||
init(article: Article, showFeedName: ShowFeedName, feedName: String?, byline: String?, iconImage: IconImage?, showIcon: Bool, featuredImage: UIImage?, numberOfLines: Int, iconSize: IconSize) {
|
||||
let hideSeparator: Bool
|
||||
|
||||
init(article: Article, showFeedName: ShowFeedName, feedName: String?, byline: String?, iconImage: IconImage?, showIcon: Bool, featuredImage: UIImage?, numberOfLines: Int, iconSize: IconSize, hideSeparator: Bool) {
|
||||
|
||||
self.title = ArticleStringFormatter.truncatedTitle(article)
|
||||
self.attributedTitle = ArticleStringFormatter.attributedTruncatedTitle(article)
|
||||
@@ -65,6 +66,7 @@ struct MasterTimelineCellData {
|
||||
self.starred = article.status.starred
|
||||
self.numberOfLines = numberOfLines
|
||||
self.iconSize = iconSize
|
||||
self.hideSeparator = hideSeparator
|
||||
|
||||
}
|
||||
|
||||
@@ -83,6 +85,7 @@ struct MasterTimelineCellData {
|
||||
self.starred = false
|
||||
self.numberOfLines = 0
|
||||
self.iconSize = .medium
|
||||
self.hideSeparator = false
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -82,7 +82,6 @@ class MasterTimelineTableViewCell: VibrantTableViewCell {
|
||||
}
|
||||
|
||||
override func layoutSubviews() {
|
||||
|
||||
super.layoutSubviews()
|
||||
|
||||
let layout = updatedLayout(width: bounds.width)
|
||||
@@ -94,8 +93,6 @@ class MasterTimelineTableViewCell: VibrantTableViewCell {
|
||||
setFrame(for: summaryView, rect: layout.summaryRect)
|
||||
feedNameView.setFrameIfNotEqual(layout.feedNameRect)
|
||||
dateView.setFrameIfNotEqual(layout.dateRect)
|
||||
|
||||
separatorInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
|
||||
}
|
||||
|
||||
func setIconImage(_ image: IconImage) {
|
||||
@@ -272,6 +269,14 @@ private extension MasterTimelineTableViewCell {
|
||||
accessibilityLabel = label
|
||||
}
|
||||
|
||||
func updateSeparator() {
|
||||
if cellData?.hideSeparator ?? false {
|
||||
separatorInset = UIEdgeInsets(top: 0, left: bounds.width + 1, bottom: 0, right: 0)
|
||||
} else {
|
||||
separatorInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
|
||||
}
|
||||
}
|
||||
|
||||
func makeIconEmpty() {
|
||||
if iconView.iconImage != nil {
|
||||
iconView.iconImage = nil
|
||||
@@ -305,6 +310,7 @@ private extension MasterTimelineTableViewCell {
|
||||
updateStarView()
|
||||
updateIconImage()
|
||||
updateAccessiblityLabel()
|
||||
updateSeparator()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -11,22 +11,25 @@ import RSCore
|
||||
import Account
|
||||
import Articles
|
||||
|
||||
class MasterTimelineViewController: UITableViewController, UndoableCommandRunner {
|
||||
class MasterTimelineViewController: UITableViewController, UndoableCommandRunner, MainControllerIdentifiable {
|
||||
|
||||
private var numberOfTextLines = 0
|
||||
private var iconSize = IconSize.medium
|
||||
private lazy var feedTapGestureRecognizer = UITapGestureRecognizer(target: self, action:#selector(showFeedInspector(_:)))
|
||||
|
||||
private var refreshProgressView: RefreshProgressView?
|
||||
private var filterButton: UIBarButtonItem!
|
||||
|
||||
@IBOutlet weak var markAllAsReadButton: UIBarButtonItem!
|
||||
|
||||
private var filterButton: UIBarButtonItem!
|
||||
private var refreshProgressView: RefreshProgressView!
|
||||
private var refreshProgressItemButton: UIBarButtonItem!
|
||||
private var firstUnreadButton: UIBarButtonItem!
|
||||
|
||||
private lazy var dataSource = makeDataSource()
|
||||
private let searchController = UISearchController(searchResultsController: nil)
|
||||
|
||||
var mainControllerIdentifer = MainControllerIdentifier.masterTimeline
|
||||
|
||||
weak var coordinator: SceneCoordinator!
|
||||
var undoableCommands = [UndoableCommand]()
|
||||
let scrollPositionQueue = CoalescingQueue(name: "Timeline Scroll Position", interval: 0.3, maxInterval: 1.0)
|
||||
@@ -79,6 +82,9 @@ class MasterTimelineViewController: UITableViewController, UndoableCommandRunner
|
||||
|
||||
// Configure the table
|
||||
tableView.dataSource = dataSource
|
||||
if #available(iOS 15.0, *) {
|
||||
tableView.isPrefetchingEnabled = false
|
||||
}
|
||||
numberOfTextLines = AppDefaults.shared.timelineNumberOfLines
|
||||
iconSize = AppDefaults.shared.timelineIconSize
|
||||
resetEstimatedRowHeight()
|
||||
@@ -89,8 +95,13 @@ class MasterTimelineViewController: UITableViewController, UndoableCommandRunner
|
||||
|
||||
refreshControl = UIRefreshControl()
|
||||
refreshControl!.addTarget(self, action: #selector(refreshAccounts(_:)), for: .valueChanged)
|
||||
|
||||
|
||||
configureToolbar()
|
||||
|
||||
refreshProgressView = Bundle.main.loadNibNamed("RefreshProgressView", owner: self, options: nil)?[0] as? RefreshProgressView
|
||||
refreshProgressItemButton = UIBarButtonItem(customView: refreshProgressView!)
|
||||
|
||||
|
||||
resetUI(resetScroll: true)
|
||||
|
||||
// Load the table and then scroll to the saved position if available
|
||||
@@ -109,15 +120,18 @@ class MasterTimelineViewController: UITableViewController, UndoableCommandRunner
|
||||
}
|
||||
|
||||
override func viewWillAppear(_ animated: Bool) {
|
||||
navigationController?.isToolbarHidden = false
|
||||
|
||||
// If the nav bar is hidden, fade it in to avoid it showing stuff as it is getting laid out
|
||||
if navigationController?.navigationBar.isHidden ?? false {
|
||||
navigationController?.navigationBar.alpha = 0
|
||||
}
|
||||
|
||||
super.viewWillAppear(animated)
|
||||
}
|
||||
|
||||
override func viewDidAppear(_ animated: Bool) {
|
||||
super.viewDidAppear(true)
|
||||
coordinator.isTimelineViewControllerPending = false
|
||||
|
||||
if navigationController?.navigationBar.alpha == 0 {
|
||||
UIView.animate(withDuration: 0.5) {
|
||||
@@ -436,7 +450,7 @@ class MasterTimelineViewController: UITableViewController, UndoableCommandRunner
|
||||
for article in visibleUpdatedArticles {
|
||||
if let indexPath = dataSource.indexPath(for: article) {
|
||||
if let cell = tableView.cellForRow(at: indexPath) as? MasterTimelineTableViewCell {
|
||||
configure(cell, article: article)
|
||||
configure(cell, article: article, indexPath: indexPath)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -523,7 +537,8 @@ class MasterTimelineViewController: UITableViewController, UndoableCommandRunner
|
||||
}
|
||||
|
||||
@objc private func reloadAllVisibleCells() {
|
||||
reconfigureCells(coordinator.articles)
|
||||
let visibleArticles = tableView.indexPathsForVisibleRows!.compactMap { return dataSource.itemIdentifier(for: $0) }
|
||||
reloadCells(visibleArticles)
|
||||
}
|
||||
|
||||
private func reloadCells(_ articles: [Article]) {
|
||||
@@ -534,15 +549,6 @@ class MasterTimelineViewController: UITableViewController, UndoableCommandRunner
|
||||
}
|
||||
}
|
||||
|
||||
private func reconfigureCells(_ articles: [Article]) {
|
||||
guard #available(iOS 15, *) else { return }
|
||||
var snapshot = dataSource.snapshot()
|
||||
snapshot.reconfigureItems(articles)
|
||||
dataSource.apply(snapshot, animatingDifferences: false) { [weak self] in
|
||||
self?.restoreSelectionIfNecessary(adjustScroll: false)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: Cell Configuring
|
||||
|
||||
private func resetEstimatedRowHeight() {
|
||||
@@ -553,7 +559,7 @@ class MasterTimelineViewController: UITableViewController, UndoableCommandRunner
|
||||
let status = ArticleStatus(articleID: prototypeID, read: false, starred: false, dateArrived: Date())
|
||||
let prototypeArticle = Article(accountID: prototypeID, articleID: prototypeID, webFeedID: prototypeID, uniqueID: prototypeID, title: longTitle, contentHTML: nil, contentText: nil, url: nil, externalURL: nil, summary: nil, imageURL: nil, datePublished: nil, dateModified: nil, authors: nil, status: status)
|
||||
|
||||
let prototypeCellData = MasterTimelineCellData(article: prototypeArticle, showFeedName: .feed, feedName: "Prototype Feed Name", byline: nil, iconImage: nil, showIcon: false, featuredImage: nil, numberOfLines: numberOfTextLines, iconSize: iconSize)
|
||||
let prototypeCellData = MasterTimelineCellData(article: prototypeArticle, showFeedName: .feed, feedName: "Prototype Feed Name", byline: nil, iconImage: nil, showIcon: false, featuredImage: nil, numberOfLines: numberOfTextLines, iconSize: iconSize, hideSeparator: false)
|
||||
|
||||
if UIApplication.shared.preferredContentSizeCategory.isAccessibilityCategory {
|
||||
let layout = MasterTimelineAccessibilityCellLayout(width: tableView.bounds.width, insets: tableView.safeAreaInsets, cellData: prototypeCellData)
|
||||
@@ -603,9 +609,8 @@ extension MasterTimelineViewController: UISearchBarDelegate {
|
||||
|
||||
private extension MasterTimelineViewController {
|
||||
|
||||
func configureToolbar() {
|
||||
|
||||
guard !coordinator.isThreePanelMode else {
|
||||
func configureToolbar() {
|
||||
guard splitViewController?.isCollapsed ?? true else {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -679,16 +684,9 @@ private extension MasterTimelineViewController {
|
||||
firstUnreadButton.isEnabled = coordinator.isTimelineUnreadAvailable
|
||||
|
||||
if coordinator.isRootSplitCollapsed {
|
||||
if let toolbarItems = toolbarItems, toolbarItems.last != firstUnreadButton {
|
||||
var items = toolbarItems
|
||||
items.append(firstUnreadButton)
|
||||
setToolbarItems(items, animated: false)
|
||||
}
|
||||
setToolbarItems([markAllAsReadButton, .flexibleSpace(), refreshProgressItemButton, .flexibleSpace(), firstUnreadButton], animated: false)
|
||||
} else {
|
||||
if let toolbarItems = toolbarItems, toolbarItems.last == firstUnreadButton {
|
||||
let items = Array(toolbarItems[0..<toolbarItems.count - 1])
|
||||
setToolbarItems(items, animated: false)
|
||||
}
|
||||
setToolbarItems([markAllAsReadButton, .flexibleSpace()], animated: false)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -719,22 +717,23 @@ private extension MasterTimelineViewController {
|
||||
let dataSource: UITableViewDiffableDataSource<Int, Article> =
|
||||
MasterTimelineDataSource(tableView: tableView, cellProvider: { [weak self] tableView, indexPath, article in
|
||||
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! MasterTimelineTableViewCell
|
||||
self?.configure(cell, article: article)
|
||||
self?.configure(cell, article: article, indexPath: indexPath)
|
||||
return cell
|
||||
})
|
||||
dataSource.defaultRowAnimation = .middle
|
||||
return dataSource
|
||||
}
|
||||
|
||||
func configure(_ cell: MasterTimelineTableViewCell, article: Article) {
|
||||
func configure(_ cell: MasterTimelineTableViewCell, article: Article, indexPath: IndexPath) {
|
||||
|
||||
let iconImage = iconImageFor(article)
|
||||
let featuredImage = featuredImageFor(article)
|
||||
|
||||
let showFeedNames = coordinator.showFeedNames
|
||||
let showIcon = coordinator.showIcons && iconImage != nil
|
||||
cell.cellData = MasterTimelineCellData(article: article, showFeedName: showFeedNames, feedName: article.webFeed?.nameForDisplay, byline: article.byline(), iconImage: iconImage, showIcon: showIcon, featuredImage: featuredImage, numberOfLines: numberOfTextLines, iconSize: iconSize)
|
||||
let hideSeparater = indexPath.row == coordinator.articles.count - 1
|
||||
|
||||
cell.cellData = MasterTimelineCellData(article: article, showFeedName: showFeedNames, feedName: article.webFeed?.nameForDisplay, byline: article.byline(), iconImage: iconImage, showIcon: showIcon, featuredImage: featuredImage, numberOfLines: numberOfTextLines, iconSize: iconSize, hideSeparator: hideSeparater)
|
||||
}
|
||||
|
||||
func iconImageFor(_ article: Article) -> IconImage? {
|
||||
|
||||
@@ -204,6 +204,8 @@
|
||||
</array>
|
||||
<key>CFBundleTypeName</key>
|
||||
<string>NetNewsWire Theme</string>
|
||||
<key>LSHandlerRank</key>
|
||||
<string>Owner</string>
|
||||
<key>CFBundleTypeRole</key>
|
||||
<string>Viewer</string>
|
||||
<key>LSItemContentTypes</key>
|
||||
|
||||
@@ -25,11 +25,6 @@ class RootSplitViewController: UISplitViewController {
|
||||
coordinator.resetFocus()
|
||||
}
|
||||
|
||||
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
|
||||
self.coordinator.configurePanelMode(for: size)
|
||||
super.viewWillTransition(to: size, with: coordinator)
|
||||
}
|
||||
|
||||
// MARK: Keyboard Shortcuts
|
||||
|
||||
@objc func scrollOrGoToNextUnread(_ sender: Any?) {
|
||||
|
||||
@@ -14,10 +14,15 @@ import RSCore
|
||||
import RSTree
|
||||
import SafariServices
|
||||
|
||||
enum PanelMode {
|
||||
case unset
|
||||
case three
|
||||
case standard
|
||||
protocol MainControllerIdentifiable {
|
||||
var mainControllerIdentifer: MainControllerIdentifier { get }
|
||||
}
|
||||
|
||||
enum MainControllerIdentifier {
|
||||
case none
|
||||
case masterFeed
|
||||
case masterTimeline
|
||||
case article
|
||||
}
|
||||
|
||||
enum SearchScope: Int {
|
||||
@@ -54,34 +59,15 @@ class SceneCoordinator: NSObject, UndoableCommandRunner {
|
||||
|
||||
lazy var webViewProvider = WebViewProvider(coordinator: self)
|
||||
|
||||
private var panelMode: PanelMode = .unset
|
||||
|
||||
private var activityManager = ActivityManager()
|
||||
|
||||
private var rootSplitViewController: RootSplitViewController!
|
||||
private var masterNavigationController: UINavigationController!
|
||||
private var masterFeedViewController: MasterFeedViewController!
|
||||
private var masterTimelineViewController: MasterTimelineViewController?
|
||||
private var subSplitViewController: UISplitViewController?
|
||||
|
||||
private var articleViewController: ArticleViewController? {
|
||||
if let detail = masterNavigationController.viewControllers.last as? ArticleViewController {
|
||||
return detail
|
||||
}
|
||||
if let subSplit = subSplitViewController {
|
||||
if let navController = subSplit.viewControllers.last as? UINavigationController {
|
||||
return navController.topViewController as? ArticleViewController
|
||||
}
|
||||
} else {
|
||||
if let navController = rootSplitViewController.viewControllers.last as? UINavigationController {
|
||||
return navController.topViewController as? ArticleViewController
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
private var wasRootSplitViewControllerCollapsed = false
|
||||
|
||||
private var articleViewController: ArticleViewController?
|
||||
|
||||
private var lastMainControllerToAppear = MainControllerIdentifier.none
|
||||
|
||||
private let fetchAndMergeArticlesQueue = CoalescingQueue(name: "Fetch and Merge Articles", interval: 0.5)
|
||||
private let rebuildBackingStoresQueue = CoalescingQueue(name: "Rebuild The Backing Stores", interval: 0.5)
|
||||
private var fetchSerialNumber = 0
|
||||
@@ -98,9 +84,6 @@ class SceneCoordinator: NSObject, UndoableCommandRunner {
|
||||
private var savedSearchArticles: ArticleArray? = nil
|
||||
private var savedSearchArticleIds: Set<String>? = nil
|
||||
|
||||
var isTimelineViewControllerPending = false
|
||||
var isArticleViewControllerPending = false
|
||||
|
||||
private(set) var sortDirection = AppDefaults.shared.timelineSortDirection {
|
||||
didSet {
|
||||
if sortDirection != oldValue {
|
||||
@@ -140,10 +123,6 @@ class SceneCoordinator: NSObject, UndoableCommandRunner {
|
||||
return rootSplitViewController.isCollapsed
|
||||
}
|
||||
|
||||
var isThreePanelMode: Bool {
|
||||
return panelMode == .three
|
||||
}
|
||||
|
||||
var isReadFeedsFiltered: Bool {
|
||||
return treeControllerDelegate.isReadFiltered
|
||||
}
|
||||
@@ -294,11 +273,32 @@ class SceneCoordinator: NSObject, UndoableCommandRunner {
|
||||
|
||||
var timelineUnreadCount: Int = 0
|
||||
|
||||
override init() {
|
||||
treeController = TreeController(delegate: treeControllerDelegate)
|
||||
init(rootSplitViewController: RootSplitViewController) {
|
||||
self.rootSplitViewController = rootSplitViewController
|
||||
self.treeController = TreeController(delegate: treeControllerDelegate)
|
||||
|
||||
super.init()
|
||||
|
||||
|
||||
self.masterFeedViewController = rootSplitViewController.viewController(for: .primary) as? MasterFeedViewController
|
||||
self.masterFeedViewController.coordinator = self
|
||||
if let navController = self.masterFeedViewController?.navigationController {
|
||||
navController.delegate = self
|
||||
configureNavigationController(navController)
|
||||
}
|
||||
|
||||
self.masterTimelineViewController = rootSplitViewController.viewController(for: .supplementary) as? MasterTimelineViewController
|
||||
self.masterTimelineViewController?.coordinator = 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]()))
|
||||
@@ -321,30 +321,6 @@ class SceneCoordinator: NSObject, UndoableCommandRunner {
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(themeDownloadDidFail(_:)), name: .didFailToImportThemeWithError, object: nil)
|
||||
}
|
||||
|
||||
func start(for size: CGSize) -> UIViewController {
|
||||
rootSplitViewController = RootSplitViewController()
|
||||
rootSplitViewController.coordinator = self
|
||||
rootSplitViewController.preferredDisplayMode = .oneBesideSecondary
|
||||
rootSplitViewController.viewControllers = [InteractiveNavigationController.template()]
|
||||
rootSplitViewController.delegate = self
|
||||
|
||||
masterNavigationController = (rootSplitViewController.viewControllers.first as! UINavigationController)
|
||||
masterNavigationController.delegate = self
|
||||
|
||||
masterFeedViewController = UIStoryboard.main.instantiateController(ofType: MasterFeedViewController.self)
|
||||
masterFeedViewController.coordinator = self
|
||||
masterNavigationController.pushViewController(masterFeedViewController, animated: false)
|
||||
|
||||
let articleViewController = UIStoryboard.main.instantiateController(ofType: ArticleViewController.self)
|
||||
articleViewController.coordinator = self
|
||||
let detailNavigationController = addNavControllerIfNecessary(articleViewController, showButton: true)
|
||||
rootSplitViewController.showDetailViewController(detailNavigationController, sender: self)
|
||||
|
||||
configurePanelMode(for: size)
|
||||
|
||||
return rootSplitViewController
|
||||
}
|
||||
|
||||
func restoreWindowState(_ activity: NSUserActivity?) {
|
||||
if let activity = activity, let windowState = activity.userInfo?[UserInfoKey.windowState] as? [AnyHashable: Any] {
|
||||
|
||||
@@ -399,26 +375,6 @@ class SceneCoordinator: NSObject, UndoableCommandRunner {
|
||||
handleReadArticle(userInfo)
|
||||
}
|
||||
|
||||
func configurePanelMode(for size: CGSize) {
|
||||
guard rootSplitViewController.traitCollection.userInterfaceIdiom == .pad else {
|
||||
return
|
||||
}
|
||||
|
||||
if (size.width / size.height) > 1.2 {
|
||||
if panelMode == .unset || panelMode == .standard {
|
||||
panelMode = .three
|
||||
configureThreePanelMode()
|
||||
}
|
||||
} else {
|
||||
if panelMode == .unset || panelMode == .three {
|
||||
panelMode = .standard
|
||||
configureStandardPanelMode()
|
||||
}
|
||||
}
|
||||
|
||||
wasRootSplitViewControllerCollapsed = rootSplitViewController.isCollapsed
|
||||
}
|
||||
|
||||
func resetFocus() {
|
||||
if currentArticle != nil {
|
||||
masterTimelineViewController?.focus()
|
||||
@@ -438,7 +394,7 @@ class SceneCoordinator: NSObject, UndoableCommandRunner {
|
||||
|
||||
func showSearch() {
|
||||
selectFeed(indexPath: nil) {
|
||||
self.installTimelineControllerIfNecessary(animated: false)
|
||||
self.rootSplitViewController.show(.supplementary)
|
||||
DispatchQueue.main.asyncAfter(deadline: .now()) {
|
||||
self.masterTimelineViewController!.showSearchAll()
|
||||
}
|
||||
@@ -793,7 +749,7 @@ class SceneCoordinator: NSObject, UndoableCommandRunner {
|
||||
if let ip = indexPath, let node = nodeFor(ip), let feed = node.representedObject as? Feed {
|
||||
|
||||
self.activityManager.selecting(feed: feed)
|
||||
self.installTimelineControllerIfNecessary(animated: animations.contains(.navigation))
|
||||
self.rootSplitViewController.show(.supplementary)
|
||||
setTimelineFeed(feed, animated: false) {
|
||||
if self.isReadFeedsFiltered {
|
||||
self.rebuildBackingStores()
|
||||
@@ -808,9 +764,7 @@ class SceneCoordinator: NSObject, UndoableCommandRunner {
|
||||
self.rebuildBackingStores()
|
||||
}
|
||||
self.activityManager.invalidateSelecting()
|
||||
if self.rootSplitViewController.isCollapsed && self.navControllerForTimeline().viewControllers.last is MasterTimelineViewController {
|
||||
self.navControllerForTimeline().popViewController(animated: animations.contains(.navigation))
|
||||
}
|
||||
self.rootSplitViewController.show(.primary)
|
||||
completion?()
|
||||
}
|
||||
|
||||
@@ -858,31 +812,21 @@ class SceneCoordinator: NSObject, UndoableCommandRunner {
|
||||
activityManager.reading(feed: timelineFeed, article: article)
|
||||
|
||||
if article == nil {
|
||||
if rootSplitViewController.isCollapsed {
|
||||
if masterNavigationController.children.last is ArticleViewController {
|
||||
masterNavigationController.popViewController(animated: animations.contains(.navigation))
|
||||
}
|
||||
} else {
|
||||
articleViewController?.article = nil
|
||||
}
|
||||
rootSplitViewController.show(.supplementary)
|
||||
masterTimelineViewController?.updateArticleSelection(animations: animations)
|
||||
articleViewController?.article = nil
|
||||
return
|
||||
}
|
||||
|
||||
let currentArticleViewController: ArticleViewController
|
||||
if articleViewController == nil {
|
||||
currentArticleViewController = installArticleController(animated: animations.contains(.navigation))
|
||||
} else {
|
||||
currentArticleViewController = articleViewController!
|
||||
}
|
||||
rootSplitViewController.show(.secondary)
|
||||
|
||||
// Mark article as read before navigating to it, so the read status does not flash unread/read on display
|
||||
markArticles(Set([article!]), statusKey: .read, flag: true)
|
||||
|
||||
masterTimelineViewController?.updateArticleSelection(animations: animations)
|
||||
currentArticleViewController.article = article
|
||||
articleViewController?.article = article
|
||||
if let isShowingExtractedArticle = isShowingExtractedArticle, let articleWindowScrollY = articleWindowScrollY {
|
||||
currentArticleViewController.restoreScrollPosition = (isShowingExtractedArticle, articleWindowScrollY)
|
||||
articleViewController?.restoreScrollPosition = (isShowingExtractedArticle, articleWindowScrollY)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1029,7 +973,7 @@ class SceneCoordinator: NSObject, UndoableCommandRunner {
|
||||
|
||||
func markAllAsReadInTimeline(completion: (() -> Void)? = nil) {
|
||||
markAllAsRead(articles) {
|
||||
self.masterNavigationController.popViewController(animated: true)
|
||||
self.rootSplitViewController.show(.primary)
|
||||
completion?()
|
||||
}
|
||||
}
|
||||
@@ -1339,45 +1283,28 @@ class SceneCoordinator: NSObject, UndoableCommandRunner {
|
||||
// MARK: UISplitViewControllerDelegate
|
||||
|
||||
extension SceneCoordinator: UISplitViewControllerDelegate {
|
||||
|
||||
func splitViewController(_ splitViewController: UISplitViewController, collapseSecondary secondaryViewController:UIViewController, onto primaryViewController:UIViewController) -> Bool {
|
||||
masterTimelineViewController?.updateUI()
|
||||
|
||||
guard !isThreePanelMode else {
|
||||
return true
|
||||
}
|
||||
|
||||
if let articleViewController = (secondaryViewController as? UINavigationController)?.topViewController as? ArticleViewController {
|
||||
if currentArticle != nil {
|
||||
masterNavigationController.pushViewController(articleViewController, animated: false)
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func splitViewController(_ splitViewController: UISplitViewController, separateSecondaryFrom primaryViewController: UIViewController) -> UIViewController? {
|
||||
masterTimelineViewController?.updateUI()
|
||||
|
||||
guard !isThreePanelMode else {
|
||||
return subSplitViewController
|
||||
func splitViewController(_ svc: UISplitViewController, topColumnForCollapsingToProposedTopColumn proposedTopColumn: UISplitViewController.Column) -> UISplitViewController.Column {
|
||||
switch proposedTopColumn {
|
||||
case .supplementary:
|
||||
if currentFeedIndexPath != nil {
|
||||
return .supplementary
|
||||
} else {
|
||||
return .primary
|
||||
}
|
||||
case .secondary:
|
||||
if currentArticle != nil {
|
||||
return .secondary
|
||||
} else {
|
||||
if currentFeedIndexPath != nil {
|
||||
return .supplementary
|
||||
} else {
|
||||
return .primary
|
||||
}
|
||||
}
|
||||
default:
|
||||
return .primary
|
||||
}
|
||||
|
||||
if let articleViewController = masterNavigationController.viewControllers.last as? ArticleViewController {
|
||||
articleViewController.showBars(self)
|
||||
masterNavigationController.popViewController(animated: false)
|
||||
let controller = addNavControllerIfNecessary(articleViewController, showButton: true)
|
||||
return controller
|
||||
}
|
||||
|
||||
if currentArticle == nil {
|
||||
let articleViewController = UIStoryboard.main.instantiateController(ofType: ArticleViewController.self)
|
||||
articleViewController.coordinator = self
|
||||
let controller = addNavControllerIfNecessary(articleViewController, showButton: true)
|
||||
return controller
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1387,13 +1314,24 @@ extension SceneCoordinator: UISplitViewControllerDelegate {
|
||||
extension SceneCoordinator: UINavigationControllerDelegate {
|
||||
|
||||
func navigationController(_ navigationController: UINavigationController, didShow viewController: UIViewController, animated: Bool) {
|
||||
guard UIApplication.shared.applicationState != .background else {
|
||||
return
|
||||
}
|
||||
|
||||
if UIApplication.shared.applicationState == .background {
|
||||
guard rootSplitViewController.isCollapsed else {
|
||||
return
|
||||
}
|
||||
|
||||
defer {
|
||||
if let mainController = viewController as? MainControllerIdentifiable {
|
||||
lastMainControllerToAppear = mainController.mainControllerIdentifer
|
||||
} else if let mainController = (viewController as? UINavigationController)?.topViewController as? MainControllerIdentifiable {
|
||||
lastMainControllerToAppear = mainController.mainControllerIdentifer
|
||||
}
|
||||
}
|
||||
|
||||
// If we are showing the Feeds and only the feeds start clearing stuff
|
||||
if viewController === masterFeedViewController && !isThreePanelMode && !isTimelineViewControllerPending {
|
||||
if viewController === masterFeedViewController && lastMainControllerToAppear == .masterTimeline {
|
||||
activityManager.invalidateCurrentActivities()
|
||||
selectFeed(nil, animations: [.scroll, .select, .navigation])
|
||||
return
|
||||
@@ -1403,25 +1341,51 @@ extension SceneCoordinator: UINavigationControllerDelegate {
|
||||
// Don't clear it if we have pushed an ArticleViewController, but don't yet see it on the navigation stack.
|
||||
// This happens when we are going to the next unread and we need to grab another timeline to continue. The
|
||||
// ArticleViewController will be pushed, but we will briefly show the Timeline. Don't clear things out when that happens.
|
||||
if viewController === masterTimelineViewController && !isThreePanelMode && rootSplitViewController.isCollapsed && !isArticleViewControllerPending {
|
||||
currentArticle = nil
|
||||
masterTimelineViewController?.updateArticleSelection(animations: [.scroll, .select, .navigation])
|
||||
activityManager.invalidateReading()
|
||||
if viewController === masterTimelineViewController && lastMainControllerToAppear == .article {
|
||||
selectArticle(nil)
|
||||
|
||||
// Restore any bars hidden by the article controller
|
||||
showStatusBar()
|
||||
navigationController.setNavigationBarHidden(false, animated: true)
|
||||
|
||||
// We delay the showing of the navigation bars because it freaks out on iOS 15 with the new split view controller
|
||||
// if it is trying to show at the same time as the show timeline animation
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
|
||||
navigationController.setNavigationBarHidden(false, animated: true)
|
||||
}
|
||||
navigationController.setToolbarHidden(false, animated: true)
|
||||
return
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
// MARK: Private
|
||||
|
||||
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.tintColor = AppAssets.primaryAccentColor
|
||||
}
|
||||
|
||||
func markArticlesWithUndo(_ articles: [Article], statusKey: ArticleStatus.Key, flag: Bool, completion: (() -> Void)? = nil) {
|
||||
guard let undoManager = undoManager,
|
||||
@@ -2077,134 +2041,6 @@ private extension SceneCoordinator {
|
||||
|
||||
}
|
||||
|
||||
// MARK: Three Panel Mode
|
||||
|
||||
func installTimelineControllerIfNecessary(animated: Bool) {
|
||||
if navControllerForTimeline().viewControllers.filter({ $0 is MasterTimelineViewController }).count < 1 {
|
||||
isTimelineViewControllerPending = true
|
||||
masterTimelineViewController = UIStoryboard.main.instantiateController(ofType: MasterTimelineViewController.self)
|
||||
masterTimelineViewController!.coordinator = self
|
||||
navControllerForTimeline().pushViewController(masterTimelineViewController!, animated: animated)
|
||||
}
|
||||
}
|
||||
|
||||
@discardableResult
|
||||
func installArticleController(state: ArticleViewController.State? = nil, animated: Bool) -> ArticleViewController {
|
||||
|
||||
isArticleViewControllerPending = true
|
||||
|
||||
let articleController = UIStoryboard.main.instantiateController(ofType: ArticleViewController.self)
|
||||
articleController.coordinator = self
|
||||
articleController.article = currentArticle
|
||||
articleController.restoreState = state
|
||||
|
||||
if let subSplit = subSplitViewController {
|
||||
let controller = addNavControllerIfNecessary(articleController, showButton: false)
|
||||
subSplit.showDetailViewController(controller, sender: self)
|
||||
} else if rootSplitViewController.isCollapsed || wasRootSplitViewControllerCollapsed {
|
||||
masterNavigationController.pushViewController(articleController, animated: animated)
|
||||
} else {
|
||||
let controller = addNavControllerIfNecessary(articleController, showButton: true)
|
||||
rootSplitViewController.showDetailViewController(controller, sender: self)
|
||||
}
|
||||
|
||||
return articleController
|
||||
|
||||
}
|
||||
|
||||
func addNavControllerIfNecessary(_ controller: UIViewController, showButton: Bool) -> UIViewController {
|
||||
|
||||
// You will sometimes get a compact horizontal size class while in three panel mode. Dunno why it lies.
|
||||
if rootSplitViewController.traitCollection.horizontalSizeClass == .compact && !isThreePanelMode {
|
||||
|
||||
return controller
|
||||
|
||||
} else {
|
||||
|
||||
let navController = InteractiveNavigationController.template(rootViewController: controller)
|
||||
navController.isToolbarHidden = false
|
||||
|
||||
if showButton {
|
||||
controller.navigationItem.leftBarButtonItem = rootSplitViewController.displayModeButtonItem
|
||||
controller.navigationItem.leftItemsSupplementBackButton = true
|
||||
} else {
|
||||
controller.navigationItem.leftBarButtonItem = nil
|
||||
controller.navigationItem.leftItemsSupplementBackButton = false
|
||||
}
|
||||
|
||||
return navController
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func installSubSplit() {
|
||||
rootSplitViewController.preferredPrimaryColumnWidthFraction = 0.30
|
||||
|
||||
subSplitViewController = UISplitViewController()
|
||||
subSplitViewController!.preferredDisplayMode = .oneBesideSecondary
|
||||
subSplitViewController!.viewControllers = [InteractiveNavigationController.template()]
|
||||
subSplitViewController!.preferredPrimaryColumnWidthFraction = 0.4285
|
||||
|
||||
rootSplitViewController.showDetailViewController(subSplitViewController!, sender: self)
|
||||
rootSplitViewController.setOverrideTraitCollection(UITraitCollection(horizontalSizeClass: .regular), forChild: subSplitViewController!)
|
||||
}
|
||||
|
||||
func navControllerForTimeline() -> UINavigationController {
|
||||
if let subSplit = subSplitViewController {
|
||||
return subSplit.viewControllers.first as! UINavigationController
|
||||
} else {
|
||||
return masterNavigationController
|
||||
}
|
||||
}
|
||||
|
||||
func configureThreePanelMode() {
|
||||
articleViewController?.stopArticleExtractorIfProcessing()
|
||||
let articleViewControllerState = articleViewController?.currentState
|
||||
defer {
|
||||
masterNavigationController.viewControllers = [masterFeedViewController]
|
||||
}
|
||||
|
||||
if rootSplitViewController.viewControllers.last is InteractiveNavigationController {
|
||||
_ = rootSplitViewController.viewControllers.popLast()
|
||||
}
|
||||
|
||||
installSubSplit()
|
||||
installTimelineControllerIfNecessary(animated: false)
|
||||
masterTimelineViewController?.navigationItem.leftBarButtonItem = rootSplitViewController.displayModeButtonItem
|
||||
masterTimelineViewController?.navigationItem.leftItemsSupplementBackButton = true
|
||||
|
||||
installArticleController(state: articleViewControllerState, animated: false)
|
||||
|
||||
masterFeedViewController.restoreSelectionIfNecessary(adjustScroll: true)
|
||||
masterTimelineViewController!.restoreSelectionIfNecessary(adjustScroll: false)
|
||||
}
|
||||
|
||||
func configureStandardPanelMode() {
|
||||
articleViewController?.stopArticleExtractorIfProcessing()
|
||||
let articleViewControllerState = articleViewController?.currentState
|
||||
rootSplitViewController.preferredPrimaryColumnWidthFraction = UISplitViewController.automaticDimension
|
||||
|
||||
// Set the is Pending flags early to prevent the navigation controller delegate from thinking that we
|
||||
// swiping around in the user interface
|
||||
isTimelineViewControllerPending = true
|
||||
isArticleViewControllerPending = true
|
||||
|
||||
masterNavigationController.viewControllers = [masterFeedViewController]
|
||||
if rootSplitViewController.viewControllers.last is UISplitViewController {
|
||||
subSplitViewController = nil
|
||||
_ = rootSplitViewController.viewControllers.popLast()
|
||||
}
|
||||
|
||||
if currentFeedIndexPath != nil {
|
||||
masterTimelineViewController = UIStoryboard.main.instantiateController(ofType: MasterTimelineViewController.self)
|
||||
masterTimelineViewController!.coordinator = self
|
||||
masterNavigationController.pushViewController(masterTimelineViewController!, animated: false)
|
||||
}
|
||||
|
||||
installArticleController(state: articleViewControllerState, animated: false)
|
||||
}
|
||||
|
||||
// MARK: NSUserActivity
|
||||
|
||||
func windowState() -> [AnyHashable: Any] {
|
||||
|
||||
@@ -14,35 +14,35 @@ import Zip
|
||||
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
|
||||
|
||||
var window: UIWindow?
|
||||
var coordinator = SceneCoordinator()
|
||||
var coordinator: SceneCoordinator!
|
||||
|
||||
// UIWindowScene delegate
|
||||
|
||||
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
|
||||
|
||||
window = UIWindow(windowScene: scene as! UIWindowScene)
|
||||
window!.tintColor = AppAssets.primaryAccentColor
|
||||
updateUserInterfaceStyle()
|
||||
window!.rootViewController = coordinator.start(for: window!.frame.size)
|
||||
|
||||
let rootViewController = window!.rootViewController as! RootSplitViewController
|
||||
coordinator = SceneCoordinator(rootSplitViewController: rootViewController)
|
||||
rootViewController.coordinator = coordinator
|
||||
rootViewController.delegate = coordinator
|
||||
|
||||
coordinator.restoreWindowState(session.stateRestorationActivity)
|
||||
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(userDefaultsDidChange), name: UserDefaults.didChangeNotification, object: nil)
|
||||
|
||||
if let _ = connectionOptions.urlContexts.first?.url {
|
||||
window?.makeKeyAndVisible()
|
||||
self.scene(scene, openURLContexts: connectionOptions.urlContexts)
|
||||
return
|
||||
}
|
||||
|
||||
if let shortcutItem = connectionOptions.shortcutItem {
|
||||
window!.makeKeyAndVisible()
|
||||
handleShortcutItem(shortcutItem)
|
||||
return
|
||||
}
|
||||
|
||||
if let notificationResponse = connectionOptions.notificationResponse {
|
||||
window!.makeKeyAndVisible()
|
||||
coordinator.handle(notificationResponse)
|
||||
return
|
||||
}
|
||||
@@ -50,8 +50,7 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate {
|
||||
if let userActivity = connectionOptions.userActivities.first ?? session.stateRestorationActivity {
|
||||
coordinator.handle(userActivity)
|
||||
}
|
||||
|
||||
window!.makeKeyAndVisible()
|
||||
|
||||
}
|
||||
|
||||
func windowScene(_ windowScene: UIWindowScene, performActionFor shortcutItem: UIApplicationShortcutItem, completionHandler: @escaping (Bool) -> Void) {
|
||||
@@ -74,7 +73,6 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate {
|
||||
func sceneWillEnterForeground(_ scene: UIScene) {
|
||||
appDelegate.resumeDatabaseProcessingIfNecessary()
|
||||
appDelegate.prepareAccountsForForeground()
|
||||
coordinator.configurePanelMode(for: window!.frame.size)
|
||||
coordinator.resetFocus()
|
||||
}
|
||||
|
||||
|
||||
@@ -11,12 +11,12 @@ import UIKit
|
||||
struct ArticleThemeImporter {
|
||||
|
||||
static func importTheme(controller: UIViewController, filename: String) throws {
|
||||
let theme = try ArticleTheme(path: filename)
|
||||
let theme = try ArticleTheme(path: filename, isAppTheme: false)
|
||||
|
||||
let localizedTitleText = NSLocalizedString("Install theme “%@” by %@?", comment: "Theme message text")
|
||||
let title = NSString.localizedStringWithFormat(localizedTitleText as NSString, theme.name, theme.creatorName) as String
|
||||
|
||||
let localizedMessageText = NSLocalizedString("Author's Website:\n%@", comment: "Authors website")
|
||||
let localizedMessageText = NSLocalizedString("Author‘s website:\n%@", comment: "Authors website")
|
||||
let message = NSString.localizedStringWithFormat(localizedMessageText as NSString, theme.creatorHomePage) as String
|
||||
|
||||
let alertController = UIAlertController(title: title, message: message, preferredStyle: .alert)
|
||||
|
||||
@@ -71,9 +71,10 @@ class ArticleThemesTableViewController: UITableViewController {
|
||||
}
|
||||
|
||||
override func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
|
||||
guard indexPath.row != 0,
|
||||
let cell = tableView.cellForRow(at: indexPath),
|
||||
let themeName = cell.textLabel?.text else { return nil }
|
||||
guard let cell = tableView.cellForRow(at: indexPath),
|
||||
let themeName = cell.textLabel?.text,
|
||||
let theme = ArticleThemesManager.shared.articleThemeWithThemeName(themeName),
|
||||
!theme.isAppTheme else { return nil }
|
||||
|
||||
let deleteTitle = NSLocalizedString("Delete", comment: "Delete")
|
||||
let deleteAction = UIContextualAction(style: .normal, title: deleteTitle) { [weak self] (action, view, completion) in
|
||||
|
||||
@@ -20,14 +20,14 @@
|
||||
<tableViewSection headerTitle="Notifications, Badge, Data, & More" id="Bmb-Oi-RZK">
|
||||
<cells>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" textLabel="F9H-Kr-npj" style="IBUITableViewCellStyleDefault" id="zvg-7C-BlH" customClass="VibrantTableViewCell" customModule="NetNewsWire" customModuleProvider="target">
|
||||
<rect key="frame" x="20" y="49.5" width="374" height="43.5"/>
|
||||
<rect key="frame" x="20" y="49.5" width="374" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="zvg-7C-BlH" id="Tqk-Tu-E6K">
|
||||
<rect key="frame" x="0.0" y="0.0" width="374" height="43.5"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="374" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Open System Settings" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontForContentSizeCategory="YES" adjustsFontSizeToFit="NO" id="F9H-Kr-npj">
|
||||
<rect key="frame" x="20" y="0.0" width="334" height="43.5"/>
|
||||
<rect key="frame" x="20" y="0.0" width="334" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<fontDescription key="fontDescription" style="UICTFontTextStyleBody"/>
|
||||
<nil key="textColor"/>
|
||||
@@ -37,10 +37,10 @@
|
||||
</tableViewCellContentView>
|
||||
</tableViewCell>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" textLabel="l7X-8L-61m" style="IBUITableViewCellStyleDefault" id="xdC-t4-59D" customClass="VibrantTableViewCell" customModule="NetNewsWire" customModuleProvider="target">
|
||||
<rect key="frame" x="20" y="93" width="374" height="43.5"/>
|
||||
<rect key="frame" x="20" y="93.5" width="374" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="xdC-t4-59D" id="aDf-bJ-EHn">
|
||||
<rect key="frame" x="0.0" y="0.0" width="345.5" height="43.5"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="345.5" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="New Article Notifications" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontForContentSizeCategory="YES" adjustsFontSizeToFit="NO" id="l7X-8L-61m">
|
||||
@@ -58,14 +58,14 @@
|
||||
<tableViewSection headerTitle="Accounts" id="0ac-Ze-Dh4">
|
||||
<cells>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" textLabel="6sn-wY-hHH" style="IBUITableViewCellStyleDefault" id="XHc-rQ-7FK" customClass="VibrantTableViewCell" customModule="NetNewsWire" customModuleProvider="target">
|
||||
<rect key="frame" x="20" y="186.5" width="374" height="43.5"/>
|
||||
<rect key="frame" x="20" y="187.5" width="374" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="XHc-rQ-7FK" id="nmL-EM-Bsi">
|
||||
<rect key="frame" x="0.0" y="0.0" width="345.5" height="43.5"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="345.5" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Add Account" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontForContentSizeCategory="YES" adjustsFontSizeToFit="NO" id="6sn-wY-hHH">
|
||||
<rect key="frame" x="20" y="0.0" width="317.5" height="43.5"/>
|
||||
<rect key="frame" x="20" y="0.0" width="317.5" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<fontDescription key="fontDescription" style="UICTFontTextStyleBody"/>
|
||||
<nil key="textColor"/>
|
||||
@@ -79,7 +79,7 @@
|
||||
<tableViewSection headerTitle="Extensions" id="oRB-NZ-WpG">
|
||||
<cells>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" textLabel="QFr-Rs-eW2" style="IBUITableViewCellStyleDefault" id="6QJ-fX-278" customClass="VibrantTableViewCell" customModule="NetNewsWire" customModuleProvider="target">
|
||||
<rect key="frame" x="20" y="280" width="374" height="43.5"/>
|
||||
<rect key="frame" x="20" y="281.5" width="374" height="43.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="6QJ-fX-278" id="PDs-8c-XUa">
|
||||
<rect key="frame" x="0.0" y="0.0" width="345.5" height="43.5"/>
|
||||
@@ -100,7 +100,7 @@
|
||||
<tableViewSection headerTitle="Feeds" id="hAC-uA-RbS">
|
||||
<cells>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" textLabel="4Hg-B3-zAE" style="IBUITableViewCellStyleDefault" id="glf-Pg-s3P" customClass="VibrantTableViewCell" customModule="NetNewsWire" customModuleProvider="target">
|
||||
<rect key="frame" x="20" y="373.5" width="374" height="43.5"/>
|
||||
<rect key="frame" x="20" y="375" width="374" height="43.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="glf-Pg-s3P" id="bPA-43-Oqh">
|
||||
<rect key="frame" x="0.0" y="0.0" width="374" height="43.5"/>
|
||||
@@ -117,7 +117,7 @@
|
||||
</tableViewCellContentView>
|
||||
</tableViewCell>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" textLabel="25J-iX-3at" style="IBUITableViewCellStyleDefault" id="qke-Ha-PXl" customClass="VibrantTableViewCell" customModule="NetNewsWire" customModuleProvider="target">
|
||||
<rect key="frame" x="20" y="417" width="374" height="43.5"/>
|
||||
<rect key="frame" x="20" y="418.5" width="374" height="43.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="qke-Ha-PXl" id="pZi-ck-RV5">
|
||||
<rect key="frame" x="0.0" y="0.0" width="374" height="43.5"/>
|
||||
@@ -134,7 +134,7 @@
|
||||
</tableViewCellContentView>
|
||||
</tableViewCell>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" textLabel="dXN-Mw-yf2" style="IBUITableViewCellStyleDefault" id="F0L-Ut-reX" customClass="VibrantTableViewCell" customModule="NetNewsWire" customModuleProvider="target">
|
||||
<rect key="frame" x="20" y="460.5" width="374" height="43.5"/>
|
||||
<rect key="frame" x="20" y="462" width="374" height="43.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="F0L-Ut-reX" id="5SX-M2-2jR">
|
||||
<rect key="frame" x="0.0" y="0.0" width="374" height="43.5"/>
|
||||
@@ -155,7 +155,7 @@
|
||||
<tableViewSection headerTitle="Timeline" id="9Pk-Y8-JVJ">
|
||||
<cells>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="none" indentationWidth="10" id="MpA-w1-Wwh" customClass="VibrantTableViewCell" customModule="NetNewsWire" customModuleProvider="target">
|
||||
<rect key="frame" x="20" y="554" width="374" height="43.5"/>
|
||||
<rect key="frame" x="20" y="555.5" width="374" height="43.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="MpA-w1-Wwh" id="GhU-ib-Mz8">
|
||||
<rect key="frame" x="0.0" y="0.0" width="374" height="43.5"/>
|
||||
@@ -188,7 +188,7 @@
|
||||
</tableViewCellContentView>
|
||||
</tableViewCell>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="none" indentationWidth="10" id="f7r-AZ-aDn" customClass="VibrantTableViewCell" customModule="NetNewsWire" customModuleProvider="target">
|
||||
<rect key="frame" x="20" y="597.5" width="374" height="43.5"/>
|
||||
<rect key="frame" x="20" y="599" width="374" height="43.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="f7r-AZ-aDn" id="KHC-cc-tOC">
|
||||
<rect key="frame" x="0.0" y="0.0" width="374" height="43.5"/>
|
||||
@@ -221,7 +221,7 @@
|
||||
</tableViewCellContentView>
|
||||
</tableViewCell>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="none" indentationWidth="10" id="5wo-fM-0l6" customClass="VibrantTableViewCell" customModule="NetNewsWire" customModuleProvider="target">
|
||||
<rect key="frame" x="20" y="641" width="374" height="43.5"/>
|
||||
<rect key="frame" x="20" y="642.5" width="374" height="43.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="5wo-fM-0l6" id="XAn-lK-LoN">
|
||||
<rect key="frame" x="0.0" y="0.0" width="374" height="43.5"/>
|
||||
@@ -254,7 +254,7 @@
|
||||
</tableViewCellContentView>
|
||||
</tableViewCell>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" id="8Gj-qz-NMY" customClass="VibrantBasicTableViewCell" customModule="NetNewsWire" customModuleProvider="target">
|
||||
<rect key="frame" x="20" y="684.5" width="374" height="43.5"/>
|
||||
<rect key="frame" x="20" y="686" width="374" height="43.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="8Gj-qz-NMY" id="OTe-tG-sb4">
|
||||
<rect key="frame" x="0.0" y="0.0" width="345.5" height="43.5"/>
|
||||
@@ -281,7 +281,7 @@
|
||||
<tableViewSection headerTitle="Articles" id="TRr-Ew-IvU">
|
||||
<cells>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" id="WFP-zj-Pve" customClass="VibrantBasicTableViewCell" customModule="NetNewsWire" customModuleProvider="target">
|
||||
<rect key="frame" x="20" y="778" width="374" height="43.5"/>
|
||||
<rect key="frame" x="20" y="779.5" width="374" height="43.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="WFP-zj-Pve" id="DCX-wc-LSo">
|
||||
<rect key="frame" x="0.0" y="0.0" width="345.5" height="43.5"/>
|
||||
@@ -313,14 +313,14 @@
|
||||
</connections>
|
||||
</tableViewCell>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="none" indentationWidth="10" id="SXs-NQ-y3U" customClass="VibrantTableViewCell" customModule="NetNewsWire" customModuleProvider="target">
|
||||
<rect key="frame" x="20" y="821.5" width="374" height="44"/>
|
||||
<rect key="frame" x="20" y="823" width="374" height="43.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="SXs-NQ-y3U" id="BpI-Hz-KH2">
|
||||
<rect key="frame" x="0.0" y="0.0" width="374" height="44"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="374" height="43.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" horizontalCompressionResistancePriority="749" text="Confirm Mark All as Read" textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontForContentSizeCategory="YES" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="5tY-5k-v2g">
|
||||
<rect key="frame" x="20" y="11" width="163" height="22"/>
|
||||
<rect key="frame" x="20" y="11" width="163" height="21.5"/>
|
||||
<fontDescription key="fontDescription" style="UICTFontTextStyleBody"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
@@ -346,20 +346,20 @@
|
||||
</tableViewCellContentView>
|
||||
</tableViewCell>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" id="EYf-v1-lNi" customClass="VibrantBasicTableViewCell" customModule="NetNewsWire" customModuleProvider="target">
|
||||
<rect key="frame" x="20" y="865.5" width="374" height="44"/>
|
||||
<rect key="frame" x="20" y="866.5" width="374" height="44.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="EYf-v1-lNi" id="7nz-0Y-HaW">
|
||||
<rect key="frame" x="0.0" y="0.0" width="374" height="44"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="374" height="44.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" ambiguous="YES" text="Open Links in NetNewsWire" textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontForContentSizeCategory="YES" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Wm4-Y1-7nX">
|
||||
<rect key="frame" x="20" y="14" width="319" height="17.5"/>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Open Links in NetNewsWire" textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontForContentSizeCategory="YES" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Wm4-Y1-7nX">
|
||||
<rect key="frame" x="20" y="14" width="279" height="17.5"/>
|
||||
<fontDescription key="fontDescription" style="UICTFontTextStyleBody"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" ambiguous="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" on="YES" translatesAutoresizingMaskIntoConstraints="NO" id="dhR-L2-PX3" userLabel="Open Links in NetNewsWire">
|
||||
<rect key="frame" x="347" y="7" width="51" height="31"/>
|
||||
<switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" on="YES" translatesAutoresizingMaskIntoConstraints="NO" id="dhR-L2-PX3" userLabel="Open Links in NetNewsWire">
|
||||
<rect key="frame" x="307" y="7" width="51" height="31"/>
|
||||
<color key="onTintColor" name="primaryAccentColor"/>
|
||||
<connections>
|
||||
<action selector="switchBrowserPreference:" destination="a0p-rk-skQ" eventType="valueChanged" id="hLC-cV-Wjj"/>
|
||||
@@ -379,65 +379,24 @@
|
||||
<outlet property="label" destination="Wm4-Y1-7nX" id="R62-za-yVz"/>
|
||||
</connections>
|
||||
</tableViewCell>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="none" indentationWidth="10" id="WR6-xo-ty2" customClass="VibrantTableViewCell" customModule="NetNewsWire" customModuleProvider="target">
|
||||
<rect key="frame" x="20" y="909.5" width="374" height="80.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="WR6-xo-ty2" id="zX8-l2-bVH">
|
||||
<rect key="frame" x="0.0" y="0.0" width="374" height="80.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" horizontalCompressionResistancePriority="749" verticalCompressionResistancePriority="751" ambiguous="YES" text="Enable Full Screen Articles" textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontForContentSizeCategory="YES" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="79e-5s-vd0">
|
||||
<rect key="frame" x="20" y="11" width="172" height="15.5"/>
|
||||
<fontDescription key="fontDescription" style="UICTFontTextStyleBody"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" ambiguous="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" translatesAutoresizingMaskIntoConstraints="NO" id="2Md-2E-7Z4">
|
||||
<rect key="frame" x="347" y="6" width="51" height="31"/>
|
||||
<color key="onTintColor" name="primaryAccentColor"/>
|
||||
<connections>
|
||||
<action selector="switchFullscreenArticles:" destination="a0p-rk-skQ" eventType="valueChanged" id="5fa-Ad-e0j"/>
|
||||
</connections>
|
||||
</switch>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" horizontalCompressionResistancePriority="749" ambiguous="YES" text="Tap the article top bar to enter Full Screen. Tap the top or bottom to exit." textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontForContentSizeCategory="YES" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="a30-nc-ZS4">
|
||||
<rect key="frame" x="20" y="33" width="313" height="0.0"/>
|
||||
<fontDescription key="fontDescription" style="UICTFontTextStyleFootnote"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstItem="2Md-2E-7Z4" firstAttribute="centerY" secondItem="79e-5s-vd0" secondAttribute="centerY" id="3KV-rT-Dfb"/>
|
||||
<constraint firstItem="a30-nc-ZS4" firstAttribute="leading" secondItem="zX8-l2-bVH" secondAttribute="leadingMargin" id="52y-SY-gbp"/>
|
||||
<constraint firstItem="79e-5s-vd0" firstAttribute="top" secondItem="zX8-l2-bVH" secondAttribute="topMargin" id="9bF-Q1-sYE"/>
|
||||
<constraint firstItem="2Md-2E-7Z4" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="a30-nc-ZS4" secondAttribute="trailing" constant="8" id="E9l-8S-WBL"/>
|
||||
<constraint firstAttribute="trailing" secondItem="2Md-2E-7Z4" secondAttribute="trailing" constant="18" id="ELH-06-H2j"/>
|
||||
<constraint firstItem="2Md-2E-7Z4" firstAttribute="top" relation="greaterThanOrEqual" secondItem="zX8-l2-bVH" secondAttribute="top" constant="6" id="aBe-aC-mva"/>
|
||||
<constraint firstItem="a30-nc-ZS4" firstAttribute="bottom" secondItem="zX8-l2-bVH" secondAttribute="bottomMargin" id="b3g-at-rjh"/>
|
||||
<constraint firstItem="2Md-2E-7Z4" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="79e-5s-vd0" secondAttribute="trailing" constant="8" id="lUn-8D-X20"/>
|
||||
<constraint firstItem="79e-5s-vd0" firstAttribute="leading" secondItem="zX8-l2-bVH" secondAttribute="leadingMargin" id="tdZ-30-ACC"/>
|
||||
<constraint firstItem="a30-nc-ZS4" firstAttribute="top" secondItem="79e-5s-vd0" secondAttribute="bottom" constant="6.5" id="wuJ-LG-d6p"/>
|
||||
</constraints>
|
||||
</tableViewCellContentView>
|
||||
</tableViewCell>
|
||||
</cells>
|
||||
</tableViewSection>
|
||||
<tableViewSection headerTitle="Appearance" id="TkH-4v-yhk">
|
||||
<cells>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" id="EvG-yE-gDF" customClass="VibrantBasicTableViewCell" customModule="NetNewsWire" customModuleProvider="target">
|
||||
<rect key="frame" x="20" y="1040" width="374" height="43.5"/>
|
||||
<rect key="frame" x="20" y="961" width="374" height="43.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="EvG-yE-gDF" id="wBN-zJ-6pN">
|
||||
<rect key="frame" x="0.0" y="0.0" width="357.5" height="43.5"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="345.5" height="43.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" ambiguous="YES" text="Color Palette" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontForContentSizeCategory="YES" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="2Fp-li-dGP">
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Color Palette" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontForContentSizeCategory="YES" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="2Fp-li-dGP">
|
||||
<rect key="frame" x="20" y="13.5" width="83.5" height="17"/>
|
||||
<fontDescription key="fontDescription" style="UICTFontTextStyleBody"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" ambiguous="YES" text="Automatic" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontForContentSizeCategory="YES" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="16m-Ns-Y8V">
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Automatic" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontForContentSizeCategory="YES" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="16m-Ns-Y8V">
|
||||
<rect key="frame" x="272" y="13.5" width="65.5" height="17"/>
|
||||
<fontDescription key="fontDescription" style="UICTFontTextStyleBody"/>
|
||||
<nil key="textColor"/>
|
||||
@@ -461,13 +420,13 @@
|
||||
<tableViewSection headerTitle="Help" id="CS8-fJ-ghn">
|
||||
<cells>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" textLabel="uGk-2d-oFc" style="IBUITableViewCellStyleDefault" id="Tle-IV-D40" customClass="VibrantTableViewCell" customModule="NetNewsWire" customModuleProvider="target">
|
||||
<rect key="frame" x="20" y="1133.5" width="374" height="43.5"/>
|
||||
<rect key="frame" x="20" y="1054.5" width="374" height="43.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="Tle-IV-D40" id="IJD-ZB-8Wm">
|
||||
<rect key="frame" x="0.0" y="0.0" width="374" height="43.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" ambiguous="YES" insetsLayoutMarginsFromSafeArea="NO" text="NetNewsWire Help" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontForContentSizeCategory="YES" adjustsFontSizeToFit="NO" id="uGk-2d-oFc">
|
||||
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="NetNewsWire Help" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontForContentSizeCategory="YES" adjustsFontSizeToFit="NO" id="uGk-2d-oFc">
|
||||
<rect key="frame" x="8" y="0.0" width="358" height="43.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<fontDescription key="fontDescription" style="UICTFontTextStyleBody"/>
|
||||
@@ -478,13 +437,13 @@
|
||||
</tableViewCellContentView>
|
||||
</tableViewCell>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" textLabel="6G3-yV-Eyh" style="IBUITableViewCellStyleDefault" id="Tbf-fE-nfx" customClass="VibrantTableViewCell" customModule="NetNewsWire" customModuleProvider="target">
|
||||
<rect key="frame" x="20" y="1177" width="374" height="43.5"/>
|
||||
<rect key="frame" x="20" y="1098" width="374" height="43.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="Tbf-fE-nfx" id="beV-vI-g3r">
|
||||
<rect key="frame" x="0.0" y="0.0" width="374" height="43.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" ambiguous="YES" insetsLayoutMarginsFromSafeArea="NO" text="Website" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontForContentSizeCategory="YES" adjustsFontSizeToFit="NO" id="6G3-yV-Eyh">
|
||||
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Website" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontForContentSizeCategory="YES" adjustsFontSizeToFit="NO" id="6G3-yV-Eyh">
|
||||
<rect key="frame" x="8" y="0.0" width="358" height="43.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<fontDescription key="fontDescription" style="UICTFontTextStyleBody"/>
|
||||
@@ -495,13 +454,13 @@
|
||||
</tableViewCellContentView>
|
||||
</tableViewCell>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" textLabel="NeD-y8-KrM" style="IBUITableViewCellStyleDefault" id="TIX-yK-rC6" customClass="VibrantTableViewCell" customModule="NetNewsWire" customModuleProvider="target">
|
||||
<rect key="frame" x="20" y="1220.5" width="374" height="43.5"/>
|
||||
<rect key="frame" x="20" y="1141.5" width="374" height="43.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="TIX-yK-rC6" id="qr8-EN-Ofg">
|
||||
<rect key="frame" x="0.0" y="0.0" width="374" height="43.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" ambiguous="YES" insetsLayoutMarginsFromSafeArea="NO" text="Release Notes" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontForContentSizeCategory="YES" adjustsFontSizeToFit="NO" id="NeD-y8-KrM">
|
||||
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Release Notes" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontForContentSizeCategory="YES" adjustsFontSizeToFit="NO" id="NeD-y8-KrM">
|
||||
<rect key="frame" x="8" y="0.0" width="358" height="43.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<fontDescription key="fontDescription" style="UICTFontTextStyleBody"/>
|
||||
@@ -512,7 +471,7 @@
|
||||
</tableViewCellContentView>
|
||||
</tableViewCell>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" textLabel="lfL-bQ-sOp" style="IBUITableViewCellStyleDefault" id="mFn-fE-zqa" customClass="VibrantTableViewCell" customModule="NetNewsWire" customModuleProvider="target">
|
||||
<rect key="frame" x="20" y="1264" width="374" height="43.5"/>
|
||||
<rect key="frame" x="20" y="1185" width="374" height="43.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="mFn-fE-zqa" id="jTe-mf-MRj">
|
||||
<rect key="frame" x="0.0" y="0.0" width="374" height="43.5"/>
|
||||
@@ -529,7 +488,7 @@
|
||||
</tableViewCellContentView>
|
||||
</tableViewCell>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" textLabel="DDJ-8P-3YY" style="IBUITableViewCellStyleDefault" id="iGs-ze-4gQ" customClass="VibrantTableViewCell" customModule="NetNewsWire" customModuleProvider="target">
|
||||
<rect key="frame" x="20" y="1307.5" width="374" height="43.5"/>
|
||||
<rect key="frame" x="20" y="1228.5" width="374" height="43.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="iGs-ze-4gQ" id="EqZ-rF-N0l">
|
||||
<rect key="frame" x="0.0" y="0.0" width="374" height="43.5"/>
|
||||
@@ -546,7 +505,7 @@
|
||||
</tableViewCellContentView>
|
||||
</tableViewCell>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" textLabel="DsV-Qv-X4K" style="IBUITableViewCellStyleDefault" id="taJ-sg-wnU" customClass="VibrantTableViewCell" customModule="NetNewsWire" customModuleProvider="target">
|
||||
<rect key="frame" x="20" y="1351" width="374" height="43.5"/>
|
||||
<rect key="frame" x="20" y="1272" width="374" height="43.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="taJ-sg-wnU" id="axB-si-1KM">
|
||||
<rect key="frame" x="0.0" y="0.0" width="374" height="43.5"/>
|
||||
@@ -563,7 +522,7 @@
|
||||
</tableViewCellContentView>
|
||||
</tableViewCell>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" textLabel="zMz-hU-UYU" style="IBUITableViewCellStyleDefault" id="OXi-cg-ab9" customClass="VibrantTableViewCell" customModule="NetNewsWire" customModuleProvider="target">
|
||||
<rect key="frame" x="20" y="1394.5" width="374" height="43.5"/>
|
||||
<rect key="frame" x="20" y="1315.5" width="374" height="43.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="OXi-cg-ab9" id="npR-a0-9wv">
|
||||
<rect key="frame" x="0.0" y="0.0" width="374" height="43.5"/>
|
||||
@@ -580,7 +539,7 @@
|
||||
</tableViewCellContentView>
|
||||
</tableViewCell>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" textLabel="T7x-zl-6Yf" style="IBUITableViewCellStyleDefault" id="VpI-0o-3Px" customClass="VibrantTableViewCell" customModule="NetNewsWire" customModuleProvider="target">
|
||||
<rect key="frame" x="20" y="1438" width="374" height="43.5"/>
|
||||
<rect key="frame" x="20" y="1359" width="374" height="43.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="VpI-0o-3Px" id="xRH-i4-vne">
|
||||
<rect key="frame" x="0.0" y="0.0" width="374" height="43.5"/>
|
||||
@@ -597,7 +556,7 @@
|
||||
</tableViewCellContentView>
|
||||
</tableViewCell>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" textLabel="76A-Ng-kfs" style="IBUITableViewCellStyleDefault" id="jK8-tv-hBD" customClass="VibrantTableViewCell" customModule="NetNewsWire" customModuleProvider="target">
|
||||
<rect key="frame" x="20" y="1481.5" width="374" height="43.5"/>
|
||||
<rect key="frame" x="20" y="1402.5" width="374" height="43.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="jK8-tv-hBD" id="I7Q-GQ-u8Y">
|
||||
<rect key="frame" x="0.0" y="0.0" width="357.5" height="43.5"/>
|
||||
@@ -635,7 +594,6 @@
|
||||
<outlet property="groupByFeedSwitch" destination="JNi-Wz-RbU" id="TwH-Kd-o6N"/>
|
||||
<outlet property="openLinksInNetNewsWire" destination="dhR-L2-PX3" id="z1b-pX-bwG"/>
|
||||
<outlet property="refreshClearsReadArticlesSwitch" destination="duV-CN-JmH" id="xTd-jF-Ei1"/>
|
||||
<outlet property="showFullscreenArticlesSwitch" destination="2Md-2E-7Z4" id="lEN-VP-wEO"/>
|
||||
<outlet property="timelineSortOrderSwitch" destination="Keq-Np-l9O" id="Zm7-HG-r5h"/>
|
||||
</connections>
|
||||
</tableViewController>
|
||||
|
||||
@@ -81,12 +81,6 @@ class SettingsViewController: UITableViewController {
|
||||
} else {
|
||||
confirmMarkAllAsReadSwitch.isOn = false
|
||||
}
|
||||
|
||||
if AppDefaults.shared.articleFullscreenAvailable {
|
||||
showFullscreenArticlesSwitch.isOn = true
|
||||
} else {
|
||||
showFullscreenArticlesSwitch.isOn = false
|
||||
}
|
||||
|
||||
colorPaletteDetailLabel.text = String(describing: AppDefaults.userInterfaceColorPalette)
|
||||
openLinksInNetNewsWire.isOn = !AppDefaults.shared.useSystemBrowser
|
||||
@@ -144,7 +138,7 @@ class SettingsViewController: UITableViewController {
|
||||
}
|
||||
return defaultNumberOfRows
|
||||
case 5:
|
||||
return traitCollection.userInterfaceIdiom == .phone ? 4 : 3
|
||||
return 3
|
||||
default:
|
||||
return super.tableView(tableView, numberOfRowsInSection: section)
|
||||
}
|
||||
@@ -264,7 +258,7 @@ class SettingsViewController: UITableViewController {
|
||||
case 7:
|
||||
switch indexPath.row {
|
||||
case 0:
|
||||
openURL("https://netnewswire.com/help/ios/6.0/en/")
|
||||
openURL("https://netnewswire.com/help/ios/6.1/en/")
|
||||
tableView.selectRow(at: nil, animated: true, scrollPosition: .none)
|
||||
case 1:
|
||||
openURL("https://netnewswire.com/")
|
||||
@@ -356,14 +350,6 @@ class SettingsViewController: UITableViewController {
|
||||
}
|
||||
}
|
||||
|
||||
@IBAction func switchFullscreenArticles(_ sender: Any) {
|
||||
if showFullscreenArticlesSwitch.isOn {
|
||||
AppDefaults.shared.articleFullscreenAvailable = true
|
||||
} else {
|
||||
AppDefaults.shared.articleFullscreenAvailable = false
|
||||
}
|
||||
}
|
||||
|
||||
@IBAction func switchBrowserPreference(_ sender: Any) {
|
||||
if openLinksInNetNewsWire.isOn {
|
||||
AppDefaults.shared.useSystemBrowser = false
|
||||
|
||||
@@ -71,7 +71,7 @@ private extension TimelinePreviewTableViewController {
|
||||
|
||||
let iconImage = IconImage(AppAssets.faviconTemplateImage.withTintColor(AppAssets.secondaryAccentColor))
|
||||
|
||||
return MasterTimelineCellData(article: prototypeArticle, showFeedName: .feed, feedName: "Feed Name", byline: nil, iconImage: iconImage, showIcon: true, featuredImage: nil, numberOfLines: AppDefaults.shared.timelineNumberOfLines, iconSize: AppDefaults.shared.timelineIconSize)
|
||||
return MasterTimelineCellData(article: prototypeArticle, showFeedName: .feed, feedName: "Feed Name", byline: nil, iconImage: iconImage, showIcon: true, featuredImage: nil, numberOfLines: AppDefaults.shared.timelineNumberOfLines, iconSize: AppDefaults.shared.timelineIconSize, hideSeparator: false)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,72 +0,0 @@
|
||||
//
|
||||
// InteractiveNavigationController.swift
|
||||
// NetNewsWire
|
||||
//
|
||||
// Created by Maurice Parker on 8/22/19.
|
||||
// Copyright © 2019 Ranchero Software. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
class InteractiveNavigationController: UINavigationController {
|
||||
|
||||
private let poppableDelegate = PoppableGestureRecognizerDelegate()
|
||||
|
||||
static func template() -> UINavigationController {
|
||||
let navController = InteractiveNavigationController()
|
||||
navController.configure()
|
||||
return navController
|
||||
}
|
||||
|
||||
static func template(rootViewController: UIViewController) -> UINavigationController {
|
||||
let navController = InteractiveNavigationController(rootViewController: rootViewController)
|
||||
navController.configure()
|
||||
return navController
|
||||
}
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
poppableDelegate.navigationController = self
|
||||
interactivePopGestureRecognizer?.delegate = poppableDelegate
|
||||
}
|
||||
|
||||
override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
|
||||
super.traitCollectionDidChange(previousTraitCollection)
|
||||
if traitCollection.userInterfaceStyle != previousTraitCollection?.userInterfaceStyle {
|
||||
configure()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// MARK: Private
|
||||
|
||||
private extension InteractiveNavigationController {
|
||||
|
||||
func configure() {
|
||||
isToolbarHidden = false
|
||||
|
||||
// Standard appearance with system background
|
||||
let standardAppearance = UINavigationBarAppearance()
|
||||
standardAppearance.backgroundColor = .clear
|
||||
standardAppearance.shadowColor = nil
|
||||
|
||||
let scrollEdgeAppearance = UINavigationBarAppearance()
|
||||
scrollEdgeAppearance.backgroundColor = .systemBackground
|
||||
scrollEdgeAppearance.shadowColor = nil
|
||||
|
||||
navigationBar.standardAppearance = standardAppearance
|
||||
navigationBar.scrollEdgeAppearance = scrollEdgeAppearance
|
||||
navigationBar.compactAppearance = standardAppearance
|
||||
navigationBar.compactScrollEdgeAppearance = scrollEdgeAppearance
|
||||
|
||||
|
||||
let toolbarAppearance = UIToolbarAppearance()
|
||||
toolbarAppearance.shadowColor = nil
|
||||
toolbar.standardAppearance = toolbarAppearance
|
||||
toolbar.compactAppearance = nil
|
||||
toolbar.scrollEdgeAppearance = nil
|
||||
toolbar.tintColor = AppAssets.primaryAccentColor
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
|
||||
// High Level Settings common to both the iOS application and any extensions we bundle with it
|
||||
MARKETING_VERSION = 6.0.2
|
||||
CURRENT_PROJECT_VERSION = 609
|
||||
MARKETING_VERSION = 6.1
|
||||
CURRENT_PROJECT_VERSION = 6103
|
||||
|
||||
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon
|
||||
|
||||
Reference in New Issue
Block a user