Handle feed renames in the inspector. Handle multiple selection. Fix #137.
This commit is contained in:
parent
aa32b09d2d
commit
f109237bfa
|
@ -62,6 +62,13 @@ final class FeedInspectorViewController: NSViewController, Inspector {
|
||||||
|
|
||||||
extension FeedInspectorViewController: NSTextFieldDelegate {
|
extension FeedInspectorViewController: NSTextFieldDelegate {
|
||||||
|
|
||||||
|
override func controlTextDidChange(_ note: Notification) {
|
||||||
|
|
||||||
|
guard let feed = feed, let nameTextField = nameTextField else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
feed.editedName = nameTextField.stringValue
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private extension FeedInspectorViewController {
|
private extension FeedInspectorViewController {
|
||||||
|
|
|
@ -195,7 +195,7 @@ Field</string>
|
||||||
</imageView>
|
</imageView>
|
||||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="4Xp-FX-kn3">
|
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="4Xp-FX-kn3">
|
||||||
<rect key="frame" x="18" y="20" width="220" height="17"/>
|
<rect key="frame" x="18" y="20" width="220" height="17"/>
|
||||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Label" id="3v9-Z7-d7l">
|
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="center" title="Label" id="3v9-Z7-d7l">
|
||||||
<font key="font" metaFont="system"/>
|
<font key="font" metaFont="system"/>
|
||||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||||
|
@ -228,20 +228,37 @@ Field</string>
|
||||||
<autoresizingMask key="autoresizingMask"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="icb-M6-R2N">
|
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="icb-M6-R2N">
|
||||||
<rect key="frame" x="70" y="20" width="116" height="17"/>
|
<rect key="frame" x="18" y="20" width="220" height="17"/>
|
||||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Nothing to inspect" id="iLD-8q-EAJ">
|
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="center" title="Nothing to inspect" id="iLD-8q-EAJ">
|
||||||
<font key="font" metaFont="system"/>
|
<font key="font" metaFont="system"/>
|
||||||
<color key="textColor" name="secondaryLabelColor" catalog="System" colorSpace="catalog"/>
|
<color key="textColor" name="secondaryLabelColor" catalog="System" colorSpace="catalog"/>
|
||||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||||
</textFieldCell>
|
</textFieldCell>
|
||||||
</textField>
|
</textField>
|
||||||
|
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="zQp-oc-Qtc">
|
||||||
|
<rect key="frame" x="18" y="20" width="220" height="17"/>
|
||||||
|
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="center" title="Multiple selection" id="5oG-0x-T8O">
|
||||||
|
<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>
|
</subviews>
|
||||||
<constraints>
|
<constraints>
|
||||||
<constraint firstItem="icb-M6-R2N" firstAttribute="centerX" secondItem="FDE-PJ-bJl" secondAttribute="centerX" id="gdT-lP-d9M"/>
|
<constraint firstAttribute="trailing" secondItem="zQp-oc-Qtc" secondAttribute="trailing" constant="20" symbolic="YES" id="AX5-4f-csi"/>
|
||||||
|
<constraint firstItem="zQp-oc-Qtc" firstAttribute="leading" secondItem="FDE-PJ-bJl" secondAttribute="leading" constant="20" symbolic="YES" id="MQU-Eu-Fvu"/>
|
||||||
|
<constraint firstItem="zQp-oc-Qtc" firstAttribute="top" secondItem="FDE-PJ-bJl" secondAttribute="top" constant="20" symbolic="YES" id="Qd0-JW-cPX"/>
|
||||||
|
<constraint firstAttribute="trailing" secondItem="icb-M6-R2N" secondAttribute="trailing" constant="20" symbolic="YES" id="WFs-kc-gZB"/>
|
||||||
|
<constraint firstAttribute="bottom" secondItem="zQp-oc-Qtc" secondAttribute="bottom" constant="20" symbolic="YES" id="eY5-EF-RuC"/>
|
||||||
|
<constraint firstItem="icb-M6-R2N" firstAttribute="leading" secondItem="FDE-PJ-bJl" secondAttribute="leading" constant="20" symbolic="YES" id="kRD-dY-9aD"/>
|
||||||
<constraint firstAttribute="bottom" secondItem="icb-M6-R2N" secondAttribute="bottom" constant="20" symbolic="YES" id="pNA-7w-eB8"/>
|
<constraint firstAttribute="bottom" secondItem="icb-M6-R2N" secondAttribute="bottom" constant="20" symbolic="YES" id="pNA-7w-eB8"/>
|
||||||
<constraint firstItem="icb-M6-R2N" firstAttribute="top" secondItem="FDE-PJ-bJl" secondAttribute="top" constant="20" symbolic="YES" id="qis-c5-6m9"/>
|
<constraint firstItem="icb-M6-R2N" firstAttribute="top" secondItem="FDE-PJ-bJl" secondAttribute="top" constant="20" symbolic="YES" id="qis-c5-6m9"/>
|
||||||
</constraints>
|
</constraints>
|
||||||
</view>
|
</view>
|
||||||
|
<connections>
|
||||||
|
<outlet property="multipleTextField" destination="zQp-oc-Qtc" id="gIq-xK-QDe"/>
|
||||||
|
<outlet property="nothingTextField" destination="icb-M6-R2N" id="l68-BS-fhy"/>
|
||||||
|
</connections>
|
||||||
</viewController>
|
</viewController>
|
||||||
<customObject id="B1q-CC-IfW" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
|
<customObject id="B1q-CC-IfW" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
|
||||||
</objects>
|
</objects>
|
||||||
|
|
|
@ -10,15 +10,38 @@ import AppKit
|
||||||
|
|
||||||
final class NothingInspectorViewController: NSViewController, Inspector {
|
final class NothingInspectorViewController: NSViewController, Inspector {
|
||||||
|
|
||||||
|
@IBOutlet var nothingTextField: NSTextField?
|
||||||
|
@IBOutlet var multipleTextField: NSTextField?
|
||||||
|
|
||||||
let isFallbackInspector = true
|
let isFallbackInspector = true
|
||||||
var objects: [Any]?
|
var objects: [Any]? {
|
||||||
|
didSet {
|
||||||
|
updateTextFields()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func canInspect(_ objects: [Any]) -> Bool {
|
func canInspect(_ objects: [Any]) -> Bool {
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func willEndInspectingObjects() {
|
override func viewDidLoad() {
|
||||||
|
|
||||||
|
updateTextFields()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private extension NothingInspectorViewController {
|
||||||
|
|
||||||
|
func updateTextFields() {
|
||||||
|
|
||||||
|
if let objects = objects, objects.count > 1 {
|
||||||
|
nothingTextField?.isHidden = true
|
||||||
|
multipleTextField?.isHidden = false
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
nothingTextField?.isHidden = false
|
||||||
|
multipleTextField?.isHidden = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -129,12 +129,11 @@ public final class Account: DisplayNameProvider, UnreadCountProvider, Container,
|
||||||
self.database = Database(databaseFilePath: databaseFilePath, accountID: accountID)
|
self.database = Database(databaseFilePath: databaseFilePath, accountID: accountID)
|
||||||
|
|
||||||
NotificationCenter.default.addObserver(self, selector: #selector(downloadProgressDidChange(_:)), name: .DownloadProgressDidChange, object: nil)
|
NotificationCenter.default.addObserver(self, selector: #selector(downloadProgressDidChange(_:)), name: .DownloadProgressDidChange, object: nil)
|
||||||
|
|
||||||
NotificationCenter.default.addObserver(self, selector: #selector(unreadCountDidChange(_:)), name: .UnreadCountDidChange, object: nil)
|
NotificationCenter.default.addObserver(self, selector: #selector(unreadCountDidChange(_:)), name: .UnreadCountDidChange, object: nil)
|
||||||
|
|
||||||
NotificationCenter.default.addObserver(self, selector: #selector(batchUpdateDidPerform(_:)), name: .BatchUpdateDidPerform, object: nil)
|
|
||||||
|
|
||||||
|
NotificationCenter.default.addObserver(self, selector: #selector(batchUpdateDidPerform(_:)), name: .BatchUpdateDidPerform, object: nil)
|
||||||
NotificationCenter.default.addObserver(self, selector: #selector(feedSettingDidChange(_:)), name: .FeedSettingDidChange, object: nil)
|
NotificationCenter.default.addObserver(self, selector: #selector(feedSettingDidChange(_:)), name: .FeedSettingDidChange, object: nil)
|
||||||
|
NotificationCenter.default.addObserver(self, selector: #selector(displayNameDidChange(_:)), name: .DisplayNameDidChange, object: nil)
|
||||||
|
|
||||||
pullObjectsFromDisk()
|
pullObjectsFromDisk()
|
||||||
|
|
||||||
|
@ -438,6 +437,16 @@ public final class Account: DisplayNameProvider, UnreadCountProvider, Container,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@objc func displayNameDidChange(_ note: Notification) {
|
||||||
|
|
||||||
|
if let feed = note.object as? Feed, let feedAccount = feed.account, feedAccount === self {
|
||||||
|
dirty = true
|
||||||
|
}
|
||||||
|
if let folder = note.object as? Folder, let folderAccount = folder.account, folderAccount === self {
|
||||||
|
dirty = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// MARK: - Equatable
|
// MARK: - Equatable
|
||||||
|
|
||||||
public class func ==(lhs: Account, rhs: Account) -> Bool {
|
public class func ==(lhs: Account, rhs: Account) -> Bool {
|
||||||
|
|
|
@ -17,7 +17,6 @@ public final class Folder: DisplayNameProvider, Container, UnreadCountProvider,
|
||||||
|
|
||||||
public var name: String? {
|
public var name: String? {
|
||||||
didSet {
|
didSet {
|
||||||
account?.dirty = true
|
|
||||||
postDisplayNameDidChangeNotification()
|
postDisplayNameDidChangeNotification()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,13 @@ public final class Feed: DisplayNameProvider, UnreadCountProvider, Hashable {
|
||||||
public var faviconURL: String?
|
public var faviconURL: String?
|
||||||
public var name: String?
|
public var name: String?
|
||||||
public var authors: Set<Author>?
|
public var authors: Set<Author>?
|
||||||
public var editedName: String?
|
|
||||||
|
public var editedName: String? {
|
||||||
|
didSet {
|
||||||
|
postDisplayNameDidChangeNotification()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public var conditionalGetInfo: HTTPConditionalGetInfo?
|
public var conditionalGetInfo: HTTPConditionalGetInfo?
|
||||||
public var contentHash: String?
|
public var contentHash: String?
|
||||||
public let hashValue: Int
|
public let hashValue: Int
|
||||||
|
@ -29,7 +35,13 @@ public final class Feed: DisplayNameProvider, UnreadCountProvider, Hashable {
|
||||||
|
|
||||||
public var nameForDisplay: String {
|
public var nameForDisplay: String {
|
||||||
get {
|
get {
|
||||||
return (editedName ?? name) ?? NSLocalizedString("Untitled", comment: "Feed name")
|
if let s = editedName, !s.isEmpty {
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
if let s = name, !s.isEmpty {
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
return NSLocalizedString("Untitled", comment: "Feed name")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue