Merge pull request #3329 from everhardt/feat-1844-scroll-mark-as-read
Add mark as read on scroll
This commit is contained in:
commit
06eae25797
|
@ -33,6 +33,7 @@ final class AppDefaults {
|
|||
static let detailFontSize = "detailFontSize"
|
||||
static let openInBrowserInBackground = "openInBrowserInBackground"
|
||||
static let subscribeToFeedsInDefaultBrowser = "subscribeToFeedsInDefaultBrowser"
|
||||
static let markArticlesAsReadOnScroll = "markArticlesAsReadOnScroll"
|
||||
static let articleTextSize = "articleTextSize"
|
||||
static let refreshInterval = "refreshInterval"
|
||||
static let addWebFeedAccountID = "addWebFeedAccountID"
|
||||
|
@ -289,6 +290,16 @@ final class AppDefaults {
|
|||
return AppDefaults.bool(for: Key.timelineShowsSeparators)
|
||||
}
|
||||
|
||||
|
||||
var markArticlesAsReadOnScroll: Bool {
|
||||
get {
|
||||
return AppDefaults.bool(for: Key.markArticlesAsReadOnScroll)
|
||||
}
|
||||
set {
|
||||
AppDefaults.setBool(for: Key.markArticlesAsReadOnScroll, newValue)
|
||||
}
|
||||
}
|
||||
|
||||
var articleTextSize: ArticleTextSize {
|
||||
get {
|
||||
let rawValue = UserDefaults.standard.integer(forKey: Key.articleTextSize)
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.Storyboard.XIB" version="3.0" toolsVersion="19162" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" initialViewController="mPU-HG-I4u">
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.Storyboard.XIB" version="3.0" toolsVersion="19455" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" initialViewController="mPU-HG-I4u">
|
||||
<dependencies>
|
||||
<deployment identifier="macosx"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="19162"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="19455"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<scenes>
|
||||
|
@ -31,23 +31,31 @@
|
|||
<scene sceneID="R4l-Wg-k7x">
|
||||
<objects>
|
||||
<viewController title="General" storyboardIdentifier="General" id="iuH-lz-18x" customClass="GeneralPreferencesViewController" customModule="NetNewsWire" customModuleProvider="target" sceneMemberID="viewController">
|
||||
<view key="view" misplaced="YES" id="WnV-px-wCT">
|
||||
<rect key="frame" x="0.0" y="0.0" width="509" height="339"/>
|
||||
<view key="view" id="WnV-px-wCT">
|
||||
<rect key="frame" x="0.0" y="0.0" width="509" height="368"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<customView horizontalHuggingPriority="1000" verticalHuggingPriority="1000" horizontalCompressionResistancePriority="1000" verticalCompressionResistancePriority="1000" translatesAutoresizingMaskIntoConstraints="NO" id="Ut3-yd-q6G">
|
||||
<rect key="frame" x="54" y="16" width="399" height="306"/>
|
||||
<rect key="frame" x="54" y="16" width="400" height="336"/>
|
||||
<subviews>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="pR2-Bf-7Fd">
|
||||
<rect key="frame" x="6" y="285" width="105" height="16"/>
|
||||
<rect key="frame" x="6" y="285" width="106" height="16"/>
|
||||
<textFieldCell key="cell" lineBreakMode="clipping" title="Article Text Size:" id="xQu-QV-91i">
|
||||
<font key="font" usesAppearanceFont="YES"/>
|
||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="4AW-o5-47e">
|
||||
<rect key="frame" x="53" y="316" width="59" height="16"/>
|
||||
<textFieldCell key="cell" lineBreakMode="clipping" title="Timeline:" id="wi9-yM-Ri0">
|
||||
<font key="font" usesAppearanceFont="YES"/>
|
||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<popUpButton verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="Z6O-Zt-V1g">
|
||||
<rect key="frame" x="114" y="278" width="289" height="25"/>
|
||||
<rect key="frame" x="115" y="278" width="289" height="25"/>
|
||||
<popUpButtonCell key="cell" type="push" title="Medium" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" tag="2" imageScaling="proportionallyDown" inset="2" selectedItem="jMV-2o-5Oh" id="6pw-Vq-tjM">
|
||||
<behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="menu"/>
|
||||
|
@ -76,7 +84,7 @@
|
|||
</popUpButtonCell>
|
||||
</popUpButton>
|
||||
<popUpButton verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="ISO-Wu-R60">
|
||||
<rect key="frame" x="114" y="244" width="289" height="25"/>
|
||||
<rect key="frame" x="115" y="244" width="289" height="25"/>
|
||||
<popUpButtonCell key="cell" type="push" title="Default" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" imageScaling="proportionallyDown" inset="2" selectedItem="Pkl-EA-Goa" id="vN9-pm-Gls">
|
||||
<behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="menu"/>
|
||||
|
@ -91,7 +99,7 @@
|
|||
</connections>
|
||||
</popUpButton>
|
||||
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="1w0-nA-DEO">
|
||||
<rect key="frame" x="110" y="207" width="161" height="32"/>
|
||||
<rect key="frame" x="111" y="207" width="161" height="32"/>
|
||||
<buttonCell key="cell" type="push" title="Open Themes Folder" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="ySX-5i-SP1">
|
||||
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
|
@ -101,10 +109,10 @@
|
|||
</connections>
|
||||
</button>
|
||||
<box verticalHuggingPriority="750" boxType="separator" translatesAutoresizingMaskIntoConstraints="NO" id="Tdg-6Y-gvW">
|
||||
<rect key="frame" x="0.0" y="197" width="399" height="5"/>
|
||||
<rect key="frame" x="0.0" y="197" width="400" height="5"/>
|
||||
</box>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="Wsb-Lr-8Q7">
|
||||
<rect key="frame" x="53" y="166" width="58" height="16"/>
|
||||
<rect key="frame" x="54" y="166" width="58" height="16"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="right" title="Browser:" id="CgU-dE-Qtb">
|
||||
<font key="font" metaFont="system"/>
|
||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||
|
@ -112,7 +120,7 @@
|
|||
</textFieldCell>
|
||||
</textField>
|
||||
<popUpButton verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="Ci4-fW-KjU">
|
||||
<rect key="frame" x="114" y="159" width="289" height="25"/>
|
||||
<rect key="frame" x="115" y="159" width="289" height="25"/>
|
||||
<popUpButtonCell key="cell" type="push" title="Safari" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" imageScaling="proportionallyDown" inset="2" selectedItem="ObP-qK-qDJ" id="hrm-aT-Rc2" userLabel="Popup">
|
||||
<behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="menu"/>
|
||||
|
@ -127,7 +135,7 @@
|
|||
</connections>
|
||||
</popUpButton>
|
||||
<button horizontalHuggingPriority="1000" verticalHuggingPriority="1000" horizontalCompressionResistancePriority="1000" translatesAutoresizingMaskIntoConstraints="NO" id="Ubm-Pk-l7x">
|
||||
<rect key="frame" x="115" y="132" width="284" height="18"/>
|
||||
<rect key="frame" x="116" y="132" width="284" height="18"/>
|
||||
<buttonCell key="cell" type="check" title="Open web pages in background in browser" bezelStyle="regularSquare" imagePosition="left" state="on" inset="2" id="t0a-LN-rCv">
|
||||
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
|
@ -147,7 +155,7 @@
|
|||
</connections>
|
||||
</button>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" translatesAutoresizingMaskIntoConstraints="NO" id="j0t-Wa-UTL">
|
||||
<rect key="frame" x="134" y="109" width="235" height="16"/>
|
||||
<rect key="frame" x="135" y="109" width="235" height="16"/>
|
||||
<textFieldCell key="cell" controlSize="small" title="Press the Shift key to do the opposite." id="EMq-9M-zTJ">
|
||||
<font key="font" usesAppearanceFont="YES"/>
|
||||
<color key="textColor" name="secondaryLabelColor" catalog="System" colorSpace="catalog"/>
|
||||
|
@ -155,10 +163,10 @@
|
|||
</textFieldCell>
|
||||
</textField>
|
||||
<box verticalHuggingPriority="750" boxType="separator" translatesAutoresizingMaskIntoConstraints="NO" id="hQy-ng-ijd">
|
||||
<rect key="frame" x="0.0" y="38" width="399" height="5"/>
|
||||
<rect key="frame" x="0.0" y="38" width="400" height="5"/>
|
||||
</box>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="ucw-vG-yLt">
|
||||
<rect key="frame" x="16" y="7" width="95" height="16"/>
|
||||
<rect key="frame" x="17" y="7" width="95" height="16"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="right" title="Refresh Feeds:" id="F7c-lm-g97">
|
||||
<font key="font" metaFont="system"/>
|
||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||
|
@ -166,7 +174,7 @@
|
|||
</textFieldCell>
|
||||
</textField>
|
||||
<popUpButton verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="SFF-mL-yc8">
|
||||
<rect key="frame" x="114" y="0.0" width="289" height="25"/>
|
||||
<rect key="frame" x="115" y="0.0" width="289" height="25"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" relation="greaterThanOrEqual" constant="200" id="N1a-qV-4Os"/>
|
||||
</constraints>
|
||||
|
@ -201,7 +209,7 @@
|
|||
</popUpButtonCell>
|
||||
</popUpButton>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="yrg-M3-Dbz">
|
||||
<rect key="frame" x="7" y="79" width="106" height="16"/>
|
||||
<rect key="frame" x="8" y="79" width="106" height="16"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="right" title="Safari Extension:" id="Eth-o0-pWM">
|
||||
<font key="font" metaFont="system"/>
|
||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||
|
@ -209,7 +217,7 @@
|
|||
</textFieldCell>
|
||||
</textField>
|
||||
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="wtY-Zd-Ps9">
|
||||
<rect key="frame" x="115" y="78" width="284" height="18"/>
|
||||
<rect key="frame" x="116" y="78" width="284" height="18"/>
|
||||
<buttonCell key="cell" type="radio" title="Open feeds in NetNewsWire" bezelStyle="regularSquare" imagePosition="left" alignment="left" state="on" inset="2" id="uvx-O8-HvU">
|
||||
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
|
@ -223,7 +231,7 @@
|
|||
</connections>
|
||||
</button>
|
||||
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="Yrc-6Q-kx8">
|
||||
<rect key="frame" x="115" y="56" width="284" height="18"/>
|
||||
<rect key="frame" x="116" y="56" width="284" height="18"/>
|
||||
<buttonCell key="cell" type="radio" title="Open feeds in default news reader" bezelStyle="regularSquare" imagePosition="left" alignment="left" inset="2" id="SkZ-tE-blK">
|
||||
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
|
@ -233,13 +241,33 @@
|
|||
</connections>
|
||||
</button>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="S2Z-bG-jYk">
|
||||
<rect key="frame" x="18" y="251" width="93" height="16"/>
|
||||
<rect key="frame" x="19" y="251" width="93" height="16"/>
|
||||
<textFieldCell key="cell" lineBreakMode="clipping" title="Article Theme:" id="MQe-Za-N8J">
|
||||
<font key="font" usesAppearanceFont="YES"/>
|
||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<button horizontalHuggingPriority="1000" verticalHuggingPriority="1000" horizontalCompressionResistancePriority="1000" translatesAutoresizingMaskIntoConstraints="NO" id="qmW-lo-ERe">
|
||||
<rect key="frame" x="116" y="315" width="208" height="18"/>
|
||||
<buttonCell key="cell" type="check" title="Mark articles as read on scroll" bezelStyle="regularSquare" imagePosition="left" state="on" inset="2" id="ANv-PZ-pn6">
|
||||
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
<connections>
|
||||
<binding destination="mAF-gO-1PI" name="value" keyPath="values.markArticlesAsReadOnScroll" id="75p-kw-A3m">
|
||||
<dictionary key="options">
|
||||
<bool key="NSAllowsEditingMultipleValuesSelection" value="NO"/>
|
||||
<bool key="NSConditionallySetsEnabled" value="NO"/>
|
||||
<integer key="NSMultipleValuesPlaceholder" value="0"/>
|
||||
<integer key="NSNoSelectionPlaceholder" value="0"/>
|
||||
<integer key="NSNotApplicablePlaceholder" value="0"/>
|
||||
<integer key="NSNullPlaceholder" value="0"/>
|
||||
<bool key="NSRaisesForNotApplicableKeys" value="NO"/>
|
||||
</dictionary>
|
||||
</binding>
|
||||
</connections>
|
||||
</button>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstItem="Wsb-Lr-8Q7" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="Ut3-yd-q6G" secondAttribute="leading" id="17A-5m-ZG0"/>
|
||||
|
@ -251,11 +279,14 @@
|
|||
<constraint firstItem="yrg-M3-Dbz" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="Ut3-yd-q6G" secondAttribute="leading" id="8KD-aE-Zer"/>
|
||||
<constraint firstItem="Ci4-fW-KjU" firstAttribute="width" secondItem="SFF-mL-yc8" secondAttribute="width" id="AE4-am-IWK"/>
|
||||
<constraint firstItem="wtY-Zd-Ps9" firstAttribute="firstBaseline" secondItem="yrg-M3-Dbz" secondAttribute="baseline" id="AeO-w1-7yq"/>
|
||||
<constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="qmW-lo-ERe" secondAttribute="trailing" id="CRn-3q-DHe"/>
|
||||
<constraint firstItem="Z6O-Zt-V1g" firstAttribute="top" secondItem="qmW-lo-ERe" secondAttribute="bottom" constant="14" id="G9G-9G-7HD"/>
|
||||
<constraint firstItem="Ubm-Pk-l7x" firstAttribute="top" secondItem="Ci4-fW-KjU" secondAttribute="bottom" constant="14" id="GNx-7d-yAo"/>
|
||||
<constraint firstItem="ISO-Wu-R60" firstAttribute="leading" secondItem="Z6O-Zt-V1g" secondAttribute="leading" id="GxL-2l-CYb"/>
|
||||
<constraint firstItem="Z6O-Zt-V1g" firstAttribute="top" secondItem="Ut3-yd-q6G" secondAttribute="top" constant="4" id="IaE-jL-vMM"/>
|
||||
<constraint firstItem="4AW-o5-47e" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="Ut3-yd-q6G" secondAttribute="leading" id="HgL-ri-piv"/>
|
||||
<constraint firstItem="hQy-ng-ijd" firstAttribute="leading" secondItem="Ut3-yd-q6G" secondAttribute="leading" id="KEI-R5-rzD"/>
|
||||
<constraint firstItem="S2Z-bG-jYk" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="Ut3-yd-q6G" secondAttribute="leading" id="KQI-3T-s6M"/>
|
||||
<constraint firstItem="4AW-o5-47e" firstAttribute="firstBaseline" secondItem="qmW-lo-ERe" secondAttribute="firstBaseline" id="KdH-x0-OD4"/>
|
||||
<constraint firstItem="pR2-Bf-7Fd" firstAttribute="leading" secondItem="Ut3-yd-q6G" secondAttribute="leading" constant="8" id="LRG-HZ-yxh"/>
|
||||
<constraint firstAttribute="trailing" secondItem="SFF-mL-yc8" secondAttribute="trailing" id="N39-Q9-X5Q"/>
|
||||
<constraint firstItem="ISO-Wu-R60" firstAttribute="trailing" secondItem="Z6O-Zt-V1g" secondAttribute="trailing" id="P3r-hD-nE8"/>
|
||||
|
@ -268,6 +299,7 @@
|
|||
<constraint firstItem="1w0-nA-DEO" firstAttribute="top" secondItem="ISO-Wu-R60" secondAttribute="bottom" constant="14" id="ZlG-V3-AAd"/>
|
||||
<constraint firstItem="pR2-Bf-7Fd" firstAttribute="firstBaseline" secondItem="Z6O-Zt-V1g" secondAttribute="firstBaseline" id="aO5-iE-L7A"/>
|
||||
<constraint firstAttribute="trailing" secondItem="Z6O-Zt-V1g" secondAttribute="trailing" id="aS9-KA-vSH"/>
|
||||
<constraint firstItem="qmW-lo-ERe" firstAttribute="leading" secondItem="Z6O-Zt-V1g" secondAttribute="leading" id="aaj-KG-JNC"/>
|
||||
<constraint firstItem="wtY-Zd-Ps9" firstAttribute="top" secondItem="j0t-Wa-UTL" secondAttribute="bottom" constant="14" id="aod-td-Gim"/>
|
||||
<constraint firstItem="SFF-mL-yc8" firstAttribute="firstBaseline" secondItem="ucw-vG-yLt" secondAttribute="firstBaseline" id="aqn-St-DJy"/>
|
||||
<constraint firstItem="Tdg-6Y-gvW" firstAttribute="leading" secondItem="Ut3-yd-q6G" secondAttribute="leading" id="b3I-JF-If3"/>
|
||||
|
@ -282,6 +314,8 @@
|
|||
<constraint firstItem="ucw-vG-yLt" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="Ut3-yd-q6G" secondAttribute="leading" id="lDL-JN-ANP"/>
|
||||
<constraint firstItem="Tdg-6Y-gvW" firstAttribute="top" secondItem="1w0-nA-DEO" secondAttribute="bottom" constant="14" id="lEK-yl-TCM"/>
|
||||
<constraint firstItem="Z6O-Zt-V1g" firstAttribute="width" secondItem="SFF-mL-yc8" secondAttribute="width" id="noW-Jf-Xbs"/>
|
||||
<constraint firstItem="qmW-lo-ERe" firstAttribute="top" secondItem="Ut3-yd-q6G" secondAttribute="top" constant="4" id="oto-bS-L2S"/>
|
||||
<constraint firstItem="4AW-o5-47e" firstAttribute="trailing" secondItem="pR2-Bf-7Fd" secondAttribute="trailing" id="qqF-kq-pPJ"/>
|
||||
<constraint firstAttribute="trailing" secondItem="Tdg-6Y-gvW" secondAttribute="trailing" id="qzz-gu-8kO"/>
|
||||
<constraint firstItem="Wsb-Lr-8Q7" firstAttribute="firstBaseline" secondItem="Ci4-fW-KjU" secondAttribute="firstBaseline" id="rPX-je-OG5"/>
|
||||
<constraint firstItem="Ci4-fW-KjU" firstAttribute="leading" secondItem="Wsb-Lr-8Q7" secondAttribute="trailing" constant="8" symbolic="YES" id="rcx-B6-zLP"/>
|
||||
|
@ -307,7 +341,7 @@
|
|||
<customObject id="bSQ-tq-wd3" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
|
||||
<userDefaultsController representsSharedInstance="YES" id="mAF-gO-1PI"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="-565.5" y="432"/>
|
||||
<point key="canvasLocation" x="-565.5" y="445"/>
|
||||
</scene>
|
||||
<!--Advanced Preferences View Controller-->
|
||||
<scene sceneID="z1G-rc-sP5">
|
||||
|
@ -487,16 +521,16 @@
|
|||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<customView translatesAutoresizingMaskIntoConstraints="NO" id="7UM-iq-OLB" customClass="PreferencesTableViewBackgroundView" customModule="NetNewsWire" customModuleProvider="target">
|
||||
<rect key="frame" x="20" y="44" width="180" height="224"/>
|
||||
<rect key="frame" x="20" y="44" width="180" height="217"/>
|
||||
<subviews>
|
||||
<scrollView borderType="none" autohidesScrollers="YES" horizontalLineScroll="26" horizontalPageScroll="10" verticalLineScroll="26" verticalPageScroll="10" hasHorizontalScroller="NO" horizontalScrollElasticity="none" translatesAutoresizingMaskIntoConstraints="NO" id="PaF-du-r3c">
|
||||
<rect key="frame" x="1" y="1" width="178" height="222"/>
|
||||
<rect key="frame" x="1" y="1" width="178" height="215"/>
|
||||
<clipView key="contentView" id="cil-Gq-akO">
|
||||
<rect key="frame" x="0.0" y="0.0" width="178" height="222"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="178" height="215"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<tableView verticalHuggingPriority="750" allowsExpansionToolTips="YES" columnAutoresizingStyle="lastColumnOnly" tableStyle="fullWidth" columnReordering="NO" columnSelection="YES" columnResizing="NO" multipleSelection="NO" autosaveColumns="NO" rowHeight="24" viewBased="YES" id="aTp-KR-y6b">
|
||||
<rect key="frame" x="0.0" y="0.0" width="178" height="222"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="178" height="215"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<size key="intercellSpacing" width="3" height="2"/>
|
||||
<color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
|
@ -603,7 +637,7 @@
|
|||
<rect key="frame" x="83" y="20" width="117" height="24"/>
|
||||
</customView>
|
||||
<customView translatesAutoresizingMaskIntoConstraints="NO" id="Y7D-xQ-wep">
|
||||
<rect key="frame" x="208" y="20" width="222" height="248"/>
|
||||
<rect key="frame" x="208" y="20" width="222" height="241"/>
|
||||
</customView>
|
||||
</subviews>
|
||||
<constraints>
|
||||
|
@ -658,16 +692,16 @@
|
|||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<customView translatesAutoresizingMaskIntoConstraints="NO" id="pjs-G4-byk" customClass="PreferencesTableViewBackgroundView" customModule="NetNewsWire" customModuleProvider="target">
|
||||
<rect key="frame" x="20" y="44" width="180" height="224"/>
|
||||
<rect key="frame" x="20" y="44" width="180" height="217"/>
|
||||
<subviews>
|
||||
<scrollView borderType="none" autohidesScrollers="YES" horizontalLineScroll="26" horizontalPageScroll="10" verticalLineScroll="26" verticalPageScroll="10" hasHorizontalScroller="NO" horizontalScrollElasticity="none" translatesAutoresizingMaskIntoConstraints="NO" id="29T-r2-ckC">
|
||||
<rect key="frame" x="1" y="1" width="178" height="222"/>
|
||||
<rect key="frame" x="1" y="1" width="178" height="215"/>
|
||||
<clipView key="contentView" id="dXw-GY-TP8">
|
||||
<rect key="frame" x="0.0" y="0.0" width="178" height="222"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="178" height="215"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<tableView verticalHuggingPriority="750" allowsExpansionToolTips="YES" columnAutoresizingStyle="lastColumnOnly" tableStyle="fullWidth" columnReordering="NO" columnSelection="YES" columnResizing="NO" multipleSelection="NO" autosaveColumns="NO" rowHeight="24" viewBased="YES" id="dfn-Vn-oDp">
|
||||
<rect key="frame" x="0.0" y="0.0" width="178" height="222"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="178" height="215"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<size key="intercellSpacing" width="3" height="2"/>
|
||||
<color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
|
@ -770,7 +804,7 @@
|
|||
<rect key="frame" x="83" y="20" width="117" height="24"/>
|
||||
</customView>
|
||||
<customView translatesAutoresizingMaskIntoConstraints="NO" id="N1N-pE-gBL">
|
||||
<rect key="frame" x="208" y="20" width="222" height="248"/>
|
||||
<rect key="frame" x="208" y="20" width="222" height="241"/>
|
||||
</customView>
|
||||
</subviews>
|
||||
<constraints>
|
||||
|
|
|
@ -111,6 +111,9 @@ private extension TimelineViewController {
|
|||
|
||||
func markArticles(_ articles: [Article], read: Bool) {
|
||||
markArticles(articles, statusKey: .read, flag: read)
|
||||
for article in articles {
|
||||
articlesWithManuallyChangedReadStatus.insert(article)
|
||||
}
|
||||
}
|
||||
|
||||
func markArticles(_ articles: [Article], starred: Bool) {
|
||||
|
|
|
@ -70,6 +70,7 @@ final class TimelineViewController: NSViewController, UndoableCommandRunner, Unr
|
|||
if showsSearchResults {
|
||||
fetchAndReplaceArticlesAsync()
|
||||
} else {
|
||||
resetMarkAsReadOnScroll()
|
||||
fetchAndReplaceArticlesSync()
|
||||
if articles.count > 0 {
|
||||
tableView.scrollRowToVisible(0)
|
||||
|
@ -138,6 +139,11 @@ final class TimelineViewController: NSViewController, UndoableCommandRunner, Unr
|
|||
}
|
||||
|
||||
var undoableCommands = [UndoableCommand]()
|
||||
|
||||
var articlesWithManuallyChangedReadStatus: Set<Article> = Set()
|
||||
|
||||
private var isScrolling = false
|
||||
|
||||
private var fetchSerialNumber = 0
|
||||
private let fetchRequestQueue = FetchRequestQueue()
|
||||
private var exceptionArticleFetcher: ArticleFetcher?
|
||||
|
@ -191,6 +197,10 @@ final class TimelineViewController: NSViewController, UndoableCommandRunner, Unr
|
|||
private let keyboardDelegate = TimelineKeyboardDelegate()
|
||||
private var timelineShowsSeparatorsObserver: NSKeyValueObservation?
|
||||
|
||||
private let scrollPositionQueue = CoalescingQueue(name: "Timeline Scroll Position", interval: 0.3, maxInterval: 1.0)
|
||||
|
||||
private var markBottomArticlesAsReadWorkItem: DispatchWorkItem?
|
||||
|
||||
convenience init(delegate: TimelineDelegate) {
|
||||
self.init(nibName: "TimelineTableView", bundle: nil)
|
||||
self.delegate = delegate
|
||||
|
@ -223,6 +233,16 @@ final class TimelineViewController: NSViewController, UndoableCommandRunner, Unr
|
|||
NotificationCenter.default.addObserver(self, selector: #selector(containerChildrenDidChange(_:)), name: .ChildrenDidChange, object: nil)
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(userDefaultsDidChange(_:)), name: UserDefaults.didChangeNotification, object: nil)
|
||||
|
||||
if let scrollView = self.tableView.enclosingScrollView {
|
||||
scrollView.contentView.postsBoundsChangedNotifications = true
|
||||
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(scrollViewDidScroll(notification:)), name: NSView.boundsDidChangeNotification, object: scrollView.contentView)
|
||||
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(scrollViewWillStartLiveScroll(notification:)), name: NSScrollView.willStartLiveScrollNotification, object: scrollView)
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(scrollViewDidEndLiveScroll(notification:)), name: NSScrollView.didEndLiveScrollNotification, object: scrollView)
|
||||
|
||||
}
|
||||
|
||||
didRegisterForNotifications = true
|
||||
}
|
||||
}
|
||||
|
@ -281,6 +301,8 @@ final class TimelineViewController: NSViewController, UndoableCommandRunner, Unr
|
|||
}
|
||||
|
||||
func restoreState(from state: [AnyHashable : Any]) {
|
||||
resetMarkAsReadOnScroll()
|
||||
|
||||
guard let readArticlesFilterStateKeys = state[UserInfoKey.readArticlesFilterStateKeys] as? [[AnyHashable: AnyHashable]],
|
||||
let readArticlesFilterStateValues = state[UserInfoKey.readArticlesFilterStateValues] as? [Bool] else {
|
||||
return
|
||||
|
@ -324,6 +346,66 @@ final class TimelineViewController: NSViewController, UndoableCommandRunner, Unr
|
|||
}
|
||||
}
|
||||
|
||||
@objc func scrollViewDidScroll(notification: Notification){
|
||||
if isScrolling {
|
||||
scrollPositionQueue.add(self, #selector(scrollPositionDidChange))
|
||||
}
|
||||
}
|
||||
|
||||
@objc func scrollViewWillStartLiveScroll(notification: Notification){
|
||||
isScrolling = true
|
||||
}
|
||||
|
||||
@objc func scrollViewDidEndLiveScroll(notification: Notification){
|
||||
isScrolling = false
|
||||
}
|
||||
|
||||
@objc func scrollPositionDidChange(){
|
||||
if !AppDefaults.shared.markArticlesAsReadOnScroll {
|
||||
return
|
||||
}
|
||||
|
||||
// Mark all articles as read when the bottom of the feed is reached
|
||||
let lastRowIndex = articles.count - 1
|
||||
let atBottom = tableView.rows(in: tableView.visibleRect).contains(lastRowIndex)
|
||||
|
||||
if atBottom && markBottomArticlesAsReadWorkItem == nil {
|
||||
let task = DispatchWorkItem {
|
||||
let articlesToMarkAsRead = self.articles.filter { !$0.status.read && !self.articlesWithManuallyChangedReadStatus.contains($0) }
|
||||
|
||||
if articlesToMarkAsRead.isEmpty { return }
|
||||
guard let undoManager = self.undoManager, let markReadCommand = MarkStatusCommand(initialArticles: articlesToMarkAsRead, markingRead: true, undoManager: undoManager) else {
|
||||
return
|
||||
}
|
||||
self.runCommand(markReadCommand)
|
||||
self.markBottomArticlesAsReadWorkItem = nil
|
||||
}
|
||||
|
||||
markBottomArticlesAsReadWorkItem = task
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + 2, execute: task)
|
||||
} else if !atBottom, let task = markBottomArticlesAsReadWorkItem {
|
||||
task.cancel()
|
||||
markBottomArticlesAsReadWorkItem = nil
|
||||
}
|
||||
|
||||
|
||||
// Mark articles scrolled out of sight at the top as read
|
||||
let firstVisibleRowIndex = tableView.rows(in: tableView.visibleRect).location
|
||||
let unreadArticlesScrolledAway = articles.articlesAbove(position: firstVisibleRowIndex).filter { !$0.status.read && !articlesWithManuallyChangedReadStatus.contains($0) }
|
||||
|
||||
if unreadArticlesScrolledAway.isEmpty { return }
|
||||
|
||||
guard let undoManager = undoManager, let markReadCommand = MarkStatusCommand(initialArticles: unreadArticlesScrolledAway, markingRead: true, undoManager: undoManager) else {
|
||||
return
|
||||
}
|
||||
runCommand(markReadCommand)
|
||||
}
|
||||
|
||||
func resetMarkAsReadOnScroll() {
|
||||
articlesWithManuallyChangedReadStatus.removeAll()
|
||||
markBottomArticlesAsReadWorkItem?.cancel()
|
||||
}
|
||||
|
||||
@IBAction func toggleStatusOfSelectedArticles(_ sender: Any?) {
|
||||
guard !selectedArticles.isEmpty else {
|
||||
return
|
||||
|
@ -345,6 +427,9 @@ final class TimelineViewController: NSViewController, UndoableCommandRunner, Unr
|
|||
return
|
||||
}
|
||||
runCommand(markReadCommand)
|
||||
for article in selectedArticles {
|
||||
articlesWithManuallyChangedReadStatus.insert(article)
|
||||
}
|
||||
}
|
||||
|
||||
@IBAction func markSelectedArticlesAsUnread(_ sender: Any?) {
|
||||
|
@ -352,6 +437,9 @@ final class TimelineViewController: NSViewController, UndoableCommandRunner, Unr
|
|||
return
|
||||
}
|
||||
runCommand(markUnreadCommand)
|
||||
for article in selectedArticles {
|
||||
articlesWithManuallyChangedReadStatus.insert(article)
|
||||
}
|
||||
}
|
||||
|
||||
@IBAction func copy(_ sender: Any?) {
|
||||
|
@ -903,6 +991,7 @@ extension TimelineViewController: NSTableViewDelegate {
|
|||
return
|
||||
}
|
||||
self.runCommand(markUnreadCommand)
|
||||
articlesWithManuallyChangedReadStatus.insert(article)
|
||||
}
|
||||
|
||||
private func toggleArticleStarred(_ article: Article) {
|
||||
|
|
|
@ -46,6 +46,7 @@ final class AppDefaults {
|
|||
static let firstRunDate = "firstRunDate"
|
||||
static let timelineGroupByFeed = "timelineGroupByFeed"
|
||||
static let refreshClearsReadArticles = "refreshClearsReadArticles"
|
||||
static let markArticlesAsReadOnScroll = "markArticlesAsReadOnScroll"
|
||||
static let timelineNumberOfLines = "timelineNumberOfLines"
|
||||
static let timelineIconDimension = "timelineIconSize"
|
||||
static let timelineSortDirection = "timelineSortDirection"
|
||||
|
@ -159,6 +160,15 @@ final class AppDefaults {
|
|||
}
|
||||
}
|
||||
|
||||
var markArticlesAsReadOnScroll: Bool {
|
||||
get {
|
||||
return AppDefaults.bool(for: Key.markArticlesAsReadOnScroll)
|
||||
}
|
||||
set {
|
||||
AppDefaults.setBool(for: Key.markArticlesAsReadOnScroll, newValue)
|
||||
}
|
||||
}
|
||||
|
||||
var timelineSortDirection: ComparisonResult {
|
||||
get {
|
||||
return AppDefaults.sortDirection(for: Key.timelineSortDirection)
|
||||
|
@ -236,6 +246,7 @@ final class AppDefaults {
|
|||
let defaults: [String : Any] = [Key.userInterfaceColorPalette: UserInterfaceColorPalette.automatic.rawValue,
|
||||
Key.timelineGroupByFeed: false,
|
||||
Key.refreshClearsReadArticles: false,
|
||||
Key.markArticlesAsReadOnScroll: false,
|
||||
Key.timelineNumberOfLines: 2,
|
||||
Key.timelineIconDimension: IconSize.medium.rawValue,
|
||||
Key.timelineSortDirection: ComparisonResult.orderedDescending.rawValue,
|
||||
|
|
|
@ -418,7 +418,9 @@ class MasterTimelineViewController: UITableViewController, UndoableCommandRunner
|
|||
}
|
||||
|
||||
override func scrollViewDidScroll(_ scrollView: UIScrollView) {
|
||||
scrollPositionQueue.add(self, #selector(scrollPositionDidChange))
|
||||
if scrollView.isTracking {
|
||||
scrollPositionQueue.add(self, #selector(scrollPositionDidChange))
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: Notifications
|
||||
|
@ -516,6 +518,53 @@ class MasterTimelineViewController: UITableViewController, UndoableCommandRunner
|
|||
|
||||
@objc func scrollPositionDidChange() {
|
||||
coordinator.timelineMiddleIndexPath = tableView.middleVisibleRow()
|
||||
|
||||
if !AppDefaults.shared.markArticlesAsReadOnScroll {
|
||||
return
|
||||
}
|
||||
|
||||
// Mark all articles as read when the bottom of the feed is reached
|
||||
if let lastVisibleRowIndexPath = tableView.indexPathsForVisibleRows?.last {
|
||||
let atBottom = dataSource.itemIdentifier(for: lastVisibleRowIndexPath) == coordinator.articles.last
|
||||
|
||||
if atBottom && coordinator.markBottomArticlesAsReadWorkItem == nil {
|
||||
let task = DispatchWorkItem {
|
||||
let articlesToMarkAsRead = self.coordinator.articles.filter { !$0.status.read && !self.coordinator.articlesWithManuallyChangedReadStatus.contains($0) }
|
||||
|
||||
if articlesToMarkAsRead.isEmpty { return }
|
||||
self.coordinator.markAllAsRead(articlesToMarkAsRead)
|
||||
self.coordinator.markBottomArticlesAsReadWorkItem = nil
|
||||
}
|
||||
|
||||
coordinator.markBottomArticlesAsReadWorkItem = task
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + 2, execute: task)
|
||||
} else if !atBottom, let task = coordinator.markBottomArticlesAsReadWorkItem {
|
||||
task.cancel()
|
||||
coordinator.markBottomArticlesAsReadWorkItem = nil
|
||||
}
|
||||
}
|
||||
|
||||
// Mark articles scrolled out of sight at the top as read
|
||||
guard let firstVisibleRowIndexPath = tableView.indexPathsForVisibleRows?[0] else { return }
|
||||
|
||||
guard let firstVisibleArticle = dataSource.itemIdentifier(for: firstVisibleRowIndexPath) else {
|
||||
return
|
||||
}
|
||||
|
||||
guard let unreadArticlesScrolledAway = coordinator.articles
|
||||
.articlesAbove(article: firstVisibleArticle)
|
||||
.filter({ !coordinator.articlesWithManuallyChangedReadStatus.contains($0) })
|
||||
.unreadArticles() else { return }
|
||||
|
||||
coordinator.markAllAsRead(unreadArticlesScrolledAway)
|
||||
|
||||
for article in unreadArticlesScrolledAway {
|
||||
if let indexPath = dataSource.indexPath(for: article) {
|
||||
if let cell = tableView.cellForRow(at: indexPath) as? MasterTimelineTableViewCell {
|
||||
configure(cell, article: article)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: Reloading
|
||||
|
|
|
@ -182,6 +182,9 @@ class SceneCoordinator: NSObject, UndoableCommandRunner {
|
|||
private(set) var showFeedNames = ShowFeedName.none
|
||||
private(set) var showIcons = false
|
||||
|
||||
var articlesWithManuallyChangedReadStatus: Set<Article> = Set()
|
||||
var markBottomArticlesAsReadWorkItem: DispatchWorkItem?
|
||||
|
||||
var prevFeedIndexPath: IndexPath? {
|
||||
guard let indexPath = currentFeedIndexPath else {
|
||||
return nil
|
||||
|
@ -783,6 +786,9 @@ class SceneCoordinator: NSObject, UndoableCommandRunner {
|
|||
return
|
||||
}
|
||||
|
||||
articlesWithManuallyChangedReadStatus.removeAll()
|
||||
markBottomArticlesAsReadWorkItem?.cancel()
|
||||
|
||||
currentFeedIndexPath = indexPath
|
||||
masterFeedViewController.updateFeedSelection(animations: animations)
|
||||
|
||||
|
@ -1073,24 +1079,28 @@ class SceneCoordinator: NSObject, UndoableCommandRunner {
|
|||
func markAsReadForCurrentArticle() {
|
||||
if let article = currentArticle {
|
||||
markArticlesWithUndo([article], statusKey: .read, flag: true)
|
||||
articlesWithManuallyChangedReadStatus.insert(article)
|
||||
}
|
||||
}
|
||||
|
||||
func markAsUnreadForCurrentArticle() {
|
||||
if let article = currentArticle {
|
||||
markArticlesWithUndo([article], statusKey: .read, flag: false)
|
||||
articlesWithManuallyChangedReadStatus.insert(article)
|
||||
}
|
||||
}
|
||||
|
||||
func toggleReadForCurrentArticle() {
|
||||
if let article = currentArticle {
|
||||
toggleRead(article)
|
||||
articlesWithManuallyChangedReadStatus.insert(article)
|
||||
}
|
||||
}
|
||||
|
||||
func toggleRead(_ article: Article) {
|
||||
guard !article.status.read || article.isAvailableToMarkUnread else { return }
|
||||
markArticlesWithUndo([article], statusKey: .read, flag: !article.status.read)
|
||||
articlesWithManuallyChangedReadStatus.insert(article)
|
||||
}
|
||||
|
||||
func toggleStarredForCurrentArticle() {
|
||||
|
|
|
@ -237,6 +237,39 @@
|
|||
</constraints>
|
||||
</tableViewCellContentView>
|
||||
</tableViewCell>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="none" indentationWidth="10" id="uZo-ol-UQR" customClass="VibrantTableViewCell" customModule="NetNewsWire" customModuleProvider="target">
|
||||
<rect key="frame" x="20" y="641" width="374" height="43.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="uZo-ol-UQR" id="riE-Jh-UIr">
|
||||
<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="Mark Articles as Read on Scroll" textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontForContentSizeCategory="YES" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="7hU-Jg-Gqb">
|
||||
<rect key="frame" x="20" y="11" width="200.5" height="21.5"/>
|
||||
<fontDescription key="fontDescription" style="UICTFontTextStyleBody"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" translatesAutoresizingMaskIntoConstraints="NO" id="eIQ-OC-hEm">
|
||||
<rect key="frame" x="307" y="6.5" width="51" height="31"/>
|
||||
<color key="onTintColor" name="primaryAccentColor"/>
|
||||
<connections>
|
||||
<action selector="switchMarkArticlesAsReadOnScroll:" destination="a0p-rk-skQ" eventType="valueChanged" id="EGi-c5-2ic"/>
|
||||
</connections>
|
||||
</switch>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstAttribute="trailing" secondItem="eIQ-OC-hEm" secondAttribute="trailing" constant="18" id="JEv-k0-ayH"/>
|
||||
<constraint firstItem="7hU-Jg-Gqb" firstAttribute="top" secondItem="riE-Jh-UIr" secondAttribute="topMargin" id="P22-FR-r7A"/>
|
||||
<constraint firstAttribute="bottomMargin" secondItem="7hU-Jg-Gqb" secondAttribute="bottom" id="VRW-kv-1x8"/>
|
||||
<constraint firstItem="eIQ-OC-hEm" firstAttribute="top" relation="greaterThanOrEqual" secondItem="riE-Jh-UIr" secondAttribute="top" constant="6" id="leW-2Y-QI0"/>
|
||||
<constraint firstItem="7hU-Jg-Gqb" firstAttribute="leading" secondItem="riE-Jh-UIr" secondAttribute="leadingMargin" id="q6H-5f-mWN"/>
|
||||
<constraint firstItem="eIQ-OC-hEm" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="7hU-Jg-Gqb" secondAttribute="trailing" constant="8" id="qlX-5H-yYc"/>
|
||||
<constraint firstItem="eIQ-OC-hEm" firstAttribute="centerY" secondItem="riE-Jh-UIr" secondAttribute="centerY" id="rnd-Gr-Eq2"/>
|
||||
<constraint firstAttribute="bottom" relation="greaterThanOrEqual" secondItem="eIQ-OC-hEm" secondAttribute="bottom" constant="6" id="zdI-d8-4Pl"/>
|
||||
</constraints>
|
||||
</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="645.5" width="374" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
|
@ -617,6 +650,7 @@
|
|||
<outlet property="colorPaletteDetailLabel" destination="16m-Ns-Y8V" id="zdj-Ag-ZUw"/>
|
||||
<outlet property="confirmMarkAllAsReadSwitch" destination="UOo-9z-IuL" id="yLZ-Kf-wDt"/>
|
||||
<outlet property="groupByFeedSwitch" destination="JNi-Wz-RbU" id="TwH-Kd-o6N"/>
|
||||
<outlet property="markArticlesAsReadOnScrollSwitch" destination="eIQ-OC-hEm" id="f5D-SM-LGr"/>
|
||||
<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"/>
|
||||
|
|
|
@ -19,6 +19,7 @@ class SettingsViewController: UITableViewController {
|
|||
@IBOutlet weak var timelineSortOrderSwitch: UISwitch!
|
||||
@IBOutlet weak var groupByFeedSwitch: UISwitch!
|
||||
@IBOutlet weak var refreshClearsReadArticlesSwitch: UISwitch!
|
||||
@IBOutlet weak var markArticlesAsReadOnScrollSwitch: UISwitch!
|
||||
@IBOutlet weak var articleThemeDetailLabel: UILabel!
|
||||
@IBOutlet weak var confirmMarkAllAsReadSwitch: UISwitch!
|
||||
@IBOutlet weak var showFullscreenArticlesSwitch: UISwitch!
|
||||
|
@ -66,6 +67,13 @@ class SettingsViewController: UITableViewController {
|
|||
} else {
|
||||
refreshClearsReadArticlesSwitch.isOn = false
|
||||
}
|
||||
|
||||
|
||||
if AppDefaults.shared.markArticlesAsReadOnScroll {
|
||||
markArticlesAsReadOnScrollSwitch.isOn = true
|
||||
} else {
|
||||
markArticlesAsReadOnScrollSwitch.isOn = false
|
||||
}
|
||||
|
||||
articleThemeDetailLabel.text = ArticleThemesManager.shared.currentTheme.name
|
||||
|
||||
|
@ -326,6 +334,14 @@ class SettingsViewController: UITableViewController {
|
|||
}
|
||||
}
|
||||
|
||||
@IBAction func switchMarkArticlesAsReadOnScroll(_ sender: Any) {
|
||||
if markArticlesAsReadOnScrollSwitch.isOn {
|
||||
AppDefaults.shared.markArticlesAsReadOnScroll = true
|
||||
} else {
|
||||
AppDefaults.shared.markArticlesAsReadOnScroll = false
|
||||
}
|
||||
}
|
||||
|
||||
@IBAction func switchConfirmMarkAllAsRead(_ sender: Any) {
|
||||
if confirmMarkAllAsReadSwitch.isOn {
|
||||
AppDefaults.shared.confirmMarkAllAsRead = true
|
||||
|
|
Loading…
Reference in New Issue