mirror of
https://github.com/Ranchero-Software/NetNewsWire
synced 2025-08-12 06:26:36 +00:00
Update to latest RSCore
This commit is contained in:
@@ -8,6 +8,8 @@
|
||||
|
||||
#if os(iOS)
|
||||
import UIKit
|
||||
#elseif os(macOS)
|
||||
import AppKit
|
||||
#endif
|
||||
|
||||
import Foundation
|
||||
@@ -530,7 +532,7 @@ public final class Account: DisplayNameProvider, UnreadCountProvider, Container,
|
||||
}
|
||||
|
||||
public func opmlDocument() -> String {
|
||||
let escapedTitle = nameForDisplay.rs_stringByEscapingSpecialXMLCharacters()
|
||||
let escapedTitle = nameForDisplay.escapingSpecialXMLCharacters
|
||||
let openingText =
|
||||
"""
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
@@ -543,7 +545,7 @@ public final class Account: DisplayNameProvider, UnreadCountProvider, Container,
|
||||
|
||||
"""
|
||||
|
||||
let middleText = OPMLString(indentLevel: 0, strictConformance: false)
|
||||
let middleText = OPMLString(indentLevel: 0, allowCustomAttributes: true)
|
||||
|
||||
let closingText =
|
||||
"""
|
||||
@@ -1177,13 +1179,13 @@ extension Account {
|
||||
|
||||
extension Account: OPMLRepresentable {
|
||||
|
||||
public func OPMLString(indentLevel: Int, strictConformance: Bool) -> String {
|
||||
public func OPMLString(indentLevel: Int, allowCustomAttributes: Bool) -> String {
|
||||
var s = ""
|
||||
for feed in topLevelFeeds {
|
||||
s += feed.OPMLString(indentLevel: indentLevel + 1, strictConformance: strictConformance)
|
||||
s += feed.OPMLString(indentLevel: indentLevel + 1, allowCustomAttributes: allowCustomAttributes)
|
||||
}
|
||||
for folder in folders! {
|
||||
s += folder.OPMLString(indentLevel: indentLevel + 1, strictConformance: strictConformance)
|
||||
s += folder.OPMLString(indentLevel: indentLevel + 1, allowCustomAttributes: allowCustomAttributes)
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ public final class AccountManager: UnreadCountProvider {
|
||||
public static let shared = AccountManager()
|
||||
public let defaultAccount: Account
|
||||
|
||||
private let accountsFolder = RSDataSubfolder(nil, "Accounts")!
|
||||
private let accountsFolder = Platform.dataSubfolder(forApplication: nil, folderName: "Accounts")!
|
||||
private var accountsDictionary = [String: Account]()
|
||||
|
||||
private let defaultAccountFolderName = "OnMyMac"
|
||||
@@ -312,7 +312,7 @@ private struct AccountSpecifier {
|
||||
|
||||
|
||||
init?(folderPath: String) {
|
||||
if !FileManager.default.rs_fileIsFolder(folderPath) {
|
||||
if !FileManager.default.isFolder(atPath: folderPath) {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ public final class Feed: DisplayNameProvider, Renamable, UnreadCountProvider, Ha
|
||||
}
|
||||
set {
|
||||
if let url = newValue {
|
||||
metadata.homePageURL = url.rs_normalizedURL()
|
||||
metadata.homePageURL = url.normalizedURL
|
||||
}
|
||||
else {
|
||||
metadata.homePageURL = nil
|
||||
@@ -226,7 +226,7 @@ public final class Feed: DisplayNameProvider, Renamable, UnreadCountProvider, Ha
|
||||
|
||||
extension Feed: OPMLRepresentable {
|
||||
|
||||
public func OPMLString(indentLevel: Int, strictConformance: Bool) -> String {
|
||||
public func OPMLString(indentLevel: Int, allowCustomAttributes: Bool) -> String {
|
||||
// https://github.com/brentsimmons/NetNewsWire/issues/527
|
||||
// Don’t use nameForDisplay because that can result in a feed name "Untitled" written to disk,
|
||||
// which NetNewsWire may take later to be the actual name.
|
||||
@@ -237,16 +237,16 @@ extension Feed: OPMLRepresentable {
|
||||
if nameToUse == nil {
|
||||
nameToUse = ""
|
||||
}
|
||||
let escapedName = nameToUse!.rs_stringByEscapingSpecialXMLCharacters()
|
||||
let escapedName = nameToUse!.escapingSpecialXMLCharacters
|
||||
|
||||
var escapedHomePageURL = ""
|
||||
if let homePageURL = homePageURL {
|
||||
escapedHomePageURL = homePageURL.rs_stringByEscapingSpecialXMLCharacters()
|
||||
escapedHomePageURL = homePageURL.escapingSpecialXMLCharacters
|
||||
}
|
||||
let escapedFeedURL = url.rs_stringByEscapingSpecialXMLCharacters()
|
||||
let escapedFeedURL = url.escapingSpecialXMLCharacters
|
||||
|
||||
var s = "<outline text=\"\(escapedName)\" title=\"\(escapedName)\" description=\"\" type=\"rss\" version=\"RSS\" htmlUrl=\"\(escapedHomePageURL)\" xmlUrl=\"\(escapedFeedURL)\"/>\n"
|
||||
s = s.rs_string(byPrependingNumberOfTabs: indentLevel)
|
||||
s = s.prepending(tabCount: indentLevel)
|
||||
|
||||
return s
|
||||
}
|
||||
|
||||
@@ -124,7 +124,7 @@ private extension FeedFinder {
|
||||
}
|
||||
|
||||
static func isHTML(_ data: Data) -> Bool {
|
||||
return (data as NSData).rs_dataIsProbablyHTML()
|
||||
return data.isProbablyHTML
|
||||
}
|
||||
|
||||
static func downloadFeedSpecifiers(_ downloadFeedSpecifiers: Set<FeedSpecifier>, feedSpecifiers: [String: FeedSpecifier], completion: @escaping (Result<Set<FeedSpecifier>, Error>) -> Void) {
|
||||
|
||||
@@ -69,13 +69,13 @@ private extension FeedSpecifier {
|
||||
score = score + 50
|
||||
}
|
||||
|
||||
if urlString.rs_caseInsensitiveContains("comments") {
|
||||
if urlString.caseInsensitiveContains("comments") {
|
||||
score = score - 10
|
||||
}
|
||||
if urlString.rs_caseInsensitiveContains("podcast") {
|
||||
if urlString.caseInsensitiveContains("podcast") {
|
||||
score = score - 10
|
||||
}
|
||||
if urlString.rs_caseInsensitiveContains("rss") {
|
||||
if urlString.caseInsensitiveContains("rss") {
|
||||
score = score + 5
|
||||
}
|
||||
if urlString.hasSuffix("/feed/") {
|
||||
@@ -84,15 +84,15 @@ private extension FeedSpecifier {
|
||||
if urlString.hasSuffix("/feed") {
|
||||
score = score + 4
|
||||
}
|
||||
if urlString.rs_caseInsensitiveContains("json") {
|
||||
if urlString.caseInsensitiveContains("json") {
|
||||
score = score + 6
|
||||
}
|
||||
|
||||
if let title = title {
|
||||
if title.rs_caseInsensitiveContains("comments") {
|
||||
if title.caseInsensitiveContains("comments") {
|
||||
score = score - 10
|
||||
}
|
||||
if title.rs_caseInsensitiveContains("json") {
|
||||
if title.caseInsensitiveContains("json") {
|
||||
score = score + 1
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ class HTMLFeedFinder {
|
||||
for oneBodyLink in bodyLinks {
|
||||
|
||||
if linkMightBeFeed(oneBodyLink) {
|
||||
let normalizedURL = oneBodyLink.urlString.rs_normalizedURL()
|
||||
let normalizedURL = oneBodyLink.urlString.normalizedURL
|
||||
let oneFeedSpecifier = FeedSpecifier(title: oneBodyLink.text, urlString: normalizedURL, source: .HTMLLink)
|
||||
addFeedSpecifier(oneFeedSpecifier)
|
||||
}
|
||||
|
||||
@@ -137,34 +137,34 @@ private extension Folder {
|
||||
|
||||
extension Folder: OPMLRepresentable {
|
||||
|
||||
public func OPMLString(indentLevel: Int, strictConformance: Bool) -> String {
|
||||
public func OPMLString(indentLevel: Int, allowCustomAttributes: Bool) -> String {
|
||||
|
||||
let attrExternalID: String = {
|
||||
if !strictConformance, let externalID = externalID {
|
||||
if allowCustomAttributes, let externalID = externalID {
|
||||
return " nnw_externalID=\"\(externalID)\""
|
||||
} else {
|
||||
return ""
|
||||
}
|
||||
}()
|
||||
|
||||
let escapedTitle = nameForDisplay.rs_stringByEscapingSpecialXMLCharacters()
|
||||
let escapedTitle = nameForDisplay.escapingSpecialXMLCharacters
|
||||
var s = "<outline text=\"\(escapedTitle)\" title=\"\(escapedTitle)\"\(attrExternalID)>\n"
|
||||
s = s.rs_string(byPrependingNumberOfTabs: indentLevel)
|
||||
s = s.prepending(tabCount: indentLevel)
|
||||
|
||||
var hasAtLeastOneChild = false
|
||||
|
||||
for feed in topLevelFeeds {
|
||||
s += feed.OPMLString(indentLevel: indentLevel + 1, strictConformance: strictConformance)
|
||||
s += feed.OPMLString(indentLevel: indentLevel + 1, allowCustomAttributes: allowCustomAttributes)
|
||||
hasAtLeastOneChild = true
|
||||
}
|
||||
|
||||
if !hasAtLeastOneChild {
|
||||
s = "<outline text=\"\(escapedTitle)\" title=\"\(escapedTitle)\"\(attrExternalID)/>\n"
|
||||
s = s.rs_string(byPrependingNumberOfTabs: indentLevel)
|
||||
s = s.prepending(tabCount: indentLevel)
|
||||
return s
|
||||
}
|
||||
|
||||
s = s + NSString.rs_string(withNumberOfTabs: indentLevel) + "</outline>\n"
|
||||
s = s + String(tabCount: indentLevel) + "</outline>\n"
|
||||
|
||||
return s
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@ extension LocalAccountRefresher: DownloadSessionDelegate {
|
||||
return
|
||||
}
|
||||
|
||||
let dataHash = (data as NSData).rs_md5HashString()
|
||||
let dataHash = data.md5String
|
||||
if dataHash == feed.contentHash {
|
||||
return
|
||||
}
|
||||
@@ -110,6 +110,6 @@ private extension Data {
|
||||
|
||||
func isDefinitelyNotFeed() -> Bool {
|
||||
// We only detect a few image types for now. This should get fleshed-out at some later date.
|
||||
return (self as NSData).rs_dataIsImage()
|
||||
return self.isImage
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ public func databaseIDWithString(_ s: String) -> String {
|
||||
return identifier
|
||||
}
|
||||
|
||||
let identifier = (s as NSString).rs_md5Hash()
|
||||
let identifier = s.md5String
|
||||
databaseIDCache[s] = identifier
|
||||
return identifier
|
||||
}
|
||||
|
||||
@@ -26,8 +26,8 @@ final class ArticlesTable: DatabaseTable {
|
||||
}()
|
||||
|
||||
// TODO: update articleCutoffDate as time passes and based on user preferences.
|
||||
private var articleCutoffDate = NSDate.rs_dateWithNumberOfDays(inThePast: 3 * 31)!
|
||||
private var maximumArticleCutoffDate = NSDate.rs_dateWithNumberOfDays(inThePast: 4 * 31)!
|
||||
private var articleCutoffDate = Date().bySubtracting(days: 3 * 31)
|
||||
private var maximumArticleCutoffDate = Date().bySubtracting(days: 4 * 31)
|
||||
|
||||
private typealias ArticlesFetchMethod = (FMDatabase) -> Set<Article>
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@ final class ArticleSearchInfo: Hashable {
|
||||
|
||||
lazy var bodyForIndex: String = {
|
||||
let s = preferredText.rsparser_stringByDecodingHTMLEntities()
|
||||
return s.rs_string(byStrippingHTML: 0).rs_stringWithCollapsedWhitespace()
|
||||
return s.strippingHTML().collapsingWhitespace
|
||||
}()
|
||||
|
||||
init(articleID: String, title: String?, contentHTML: String?, contentText: String?, summary: String?, searchRowID: Int?) {
|
||||
|
||||
@@ -30,7 +30,7 @@ struct CrashLog {
|
||||
return nil
|
||||
}
|
||||
self.content = s
|
||||
self.contentHash = s.rs_md5Hash()
|
||||
self.contentHash = s.md5String
|
||||
self.path = path
|
||||
self.modificationDate = modificationDate
|
||||
}
|
||||
|
||||
@@ -98,8 +98,8 @@ class AddFeedController: AddFeedWindowControllerDelegate {
|
||||
private extension AddFeedController {
|
||||
|
||||
var urlStringFromPasteboard: String? {
|
||||
if let urlString = NSPasteboard.rs_urlString(from: NSPasteboard.general) {
|
||||
return urlString.rs_normalizedURL()
|
||||
if let urlString = NSPasteboard.urlString(from: NSPasteboard.general) {
|
||||
return urlString.normalizedURL
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ class AddFeedWindowController : NSWindowController {
|
||||
|
||||
private var userEnteredTitle: String? {
|
||||
var s = nameTextField.stringValue
|
||||
s = s.rs_stringWithCollapsedWhitespace()
|
||||
s = s.collapsingWhitespace
|
||||
if s.isEmpty {
|
||||
return nil
|
||||
}
|
||||
@@ -94,7 +94,7 @@ class AddFeedWindowController : NSWindowController {
|
||||
|
||||
@IBAction func addFeed(_ sender: Any?) {
|
||||
let urlString = urlTextField.stringValue
|
||||
let normalizedURLString = (urlString as NSString).rs_normalizedURL()
|
||||
let normalizedURLString = urlString.normalizedURL
|
||||
|
||||
if normalizedURLString.isEmpty {
|
||||
cancelSheet()
|
||||
@@ -137,7 +137,7 @@ class AddFeedWindowController : NSWindowController {
|
||||
private extension AddFeedWindowController {
|
||||
|
||||
private func updateUI() {
|
||||
addButton.isEnabled = urlTextField.stringValue.rs_stringMayBeURL()
|
||||
addButton.isEnabled = urlTextField.stringValue.mayBeURL
|
||||
}
|
||||
|
||||
func cancelSheet() {
|
||||
|
||||
@@ -67,7 +67,7 @@ private extension DetailStatusBarView {
|
||||
|
||||
func updateLinkForDisplay() {
|
||||
if let mouseoverLink = mouseoverLink, !mouseoverLink.isEmpty {
|
||||
linkForDisplay = (mouseoverLink as NSString).rs_stringByStrippingHTTPOrHTTPSScheme()
|
||||
linkForDisplay = mouseoverLink.strippingHTTPOrHTTPSScheme
|
||||
}
|
||||
else {
|
||||
linkForDisplay = nil
|
||||
|
||||
@@ -32,7 +32,7 @@ struct NNW3Document {
|
||||
|
||||
extension NNW3Document: OPMLRepresentable {
|
||||
|
||||
func OPMLString(indentLevel: Int, strictConformance: Bool) -> String {
|
||||
func OPMLString(indentLevel: Int, allowCustomAttributes: Bool) -> String {
|
||||
var s =
|
||||
"""
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
@@ -46,7 +46,7 @@ extension NNW3Document: OPMLRepresentable {
|
||||
|
||||
if let children = children {
|
||||
for child in children {
|
||||
s += child.OPMLString(indentLevel: indentLevel + 1, strictConformance: true)
|
||||
s += child.OPMLString(indentLevel: indentLevel + 1, allowCustomAttributes: false)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -94,19 +94,19 @@ private struct NNW3Folder {
|
||||
|
||||
extension NNW3Folder: OPMLRepresentable {
|
||||
|
||||
func OPMLString(indentLevel: Int, strictConformance: Bool) -> String {
|
||||
let t = title?.rs_stringByEscapingSpecialXMLCharacters() ?? ""
|
||||
func OPMLString(indentLevel: Int, allowCustomAttributes: Bool) -> String {
|
||||
let t = title?.escapingSpecialXMLCharacters ?? ""
|
||||
guard let children = children else {
|
||||
// Empty folder.
|
||||
return "<outline text=\"\(t)\" title=\"\(t)\" />\n".rs_string(byPrependingNumberOfTabs: indentLevel)
|
||||
return "<outline text=\"\(t)\" title=\"\(t)\" />\n".prepending(tabCount: indentLevel)
|
||||
}
|
||||
|
||||
var s = "<outline text=\"\(t)\" title=\"\(t)\">\n".rs_string(byPrependingNumberOfTabs: indentLevel)
|
||||
var s = "<outline text=\"\(t)\" title=\"\(t)\">\n".prepending(tabCount: indentLevel)
|
||||
for child in children {
|
||||
s += child.OPMLString(indentLevel: indentLevel + 1, strictConformance: true)
|
||||
s += child.OPMLString(indentLevel: indentLevel + 1, allowCustomAttributes: false)
|
||||
}
|
||||
|
||||
s += "</outline>\n".rs_string(byPrependingNumberOfTabs: indentLevel)
|
||||
s += "</outline>\n".prepending(tabCount: indentLevel)
|
||||
return s
|
||||
}
|
||||
}
|
||||
@@ -130,13 +130,13 @@ private struct NNW3Feed {
|
||||
|
||||
extension NNW3Feed: OPMLRepresentable {
|
||||
|
||||
func OPMLString(indentLevel: Int, strictConformance: Bool) -> String {
|
||||
let t = title?.rs_stringByEscapingSpecialXMLCharacters() ?? ""
|
||||
let p = homePageURL?.rs_stringByEscapingSpecialXMLCharacters() ?? ""
|
||||
let f = feedURL?.rs_stringByEscapingSpecialXMLCharacters() ?? ""
|
||||
func OPMLString(indentLevel: Int, allowCustomAttributes: Bool) -> String {
|
||||
let t = title?.escapingSpecialXMLCharacters ?? ""
|
||||
let p = homePageURL?.escapingSpecialXMLCharacters ?? ""
|
||||
let f = feedURL?.escapingSpecialXMLCharacters ?? ""
|
||||
|
||||
var s = "<outline text=\"\(t)\" title=\"\(t)\" description=\"\" type=\"rss\" version=\"RSS\" htmlUrl=\"\(p)\" xmlUrl=\"\(f)\"/>\n"
|
||||
s = s.rs_string(byPrependingNumberOfTabs: indentLevel)
|
||||
s = s.prepending(tabCount: indentLevel)
|
||||
|
||||
return s
|
||||
}
|
||||
|
||||
@@ -93,7 +93,7 @@ private extension NNW3ImportController {
|
||||
guard let document = NNW3Document(subscriptionsPlistURL: url) else {
|
||||
return nil
|
||||
}
|
||||
let opml = document.OPMLString(indentLevel: 0, strictConformance: true)
|
||||
let opml = document.OPMLString(indentLevel: 0, allowCustomAttributes: false)
|
||||
|
||||
let opmlURL = FileManager.default.temporaryDirectory.appendingPathComponent("NNW3.opml")
|
||||
do {
|
||||
|
||||
@@ -143,9 +143,9 @@ private extension SidebarCell {
|
||||
}
|
||||
|
||||
func layoutWith(_ layout: SidebarCellLayout) {
|
||||
faviconImageView.rs_setFrameIfNotEqual(layout.faviconRect)
|
||||
titleView.rs_setFrameIfNotEqual(layout.titleRect)
|
||||
unreadCountView.rs_setFrameIfNotEqual(layout.unreadCountRect)
|
||||
faviconImageView.setFrame(ifNotEqualTo: layout.faviconRect)
|
||||
titleView.setFrame(ifNotEqualTo: layout.titleRect)
|
||||
unreadCountView.setFrame(ifNotEqualTo: layout.unreadCountRect)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ struct SidebarCellLayout {
|
||||
var rFavicon = NSRect.zero
|
||||
if shouldShowImage {
|
||||
rFavicon = NSRect(x: 0.0, y: 0.0, width: appearance.imageSize.width, height: appearance.imageSize.height)
|
||||
rFavicon = RSRectCenteredVerticallyInRect(rFavicon, bounds)
|
||||
rFavicon = rFavicon.centeredVertically(in: bounds)
|
||||
}
|
||||
self.faviconRect = rFavicon
|
||||
|
||||
@@ -34,7 +34,7 @@ struct SidebarCellLayout {
|
||||
if shouldShowImage {
|
||||
rTextField.origin.x = NSMaxX(rFavicon) + appearance.imageMarginRight
|
||||
}
|
||||
rTextField = RSRectCenteredVerticallyInRect(rTextField, bounds)
|
||||
rTextField = rTextField.centeredVertically(in: bounds)
|
||||
|
||||
let unreadCountSize = unreadCountView.intrinsicContentSize
|
||||
let unreadCountIsHidden = unreadCountView.unreadCount < 1
|
||||
@@ -43,7 +43,7 @@ struct SidebarCellLayout {
|
||||
if !unreadCountIsHidden {
|
||||
rUnread.size = unreadCountSize
|
||||
rUnread.origin.x = NSMaxX(bounds) - unreadCountSize.width
|
||||
rUnread = RSRectCenteredVerticallyInRect(rUnread, bounds)
|
||||
rUnread = rUnread.centeredVertically(in: bounds)
|
||||
let textFieldMaxX = NSMinX(rUnread) - appearance.unreadCountMarginLeft
|
||||
if NSMaxX(rTextField) > textFieldMaxX {
|
||||
rTextField.size.width = textFieldMaxX - NSMinX(rTextField)
|
||||
|
||||
@@ -37,9 +37,9 @@ struct PasteboardFeed: Hashable {
|
||||
let isLocalFeed: Bool
|
||||
|
||||
init(url: String, feedID: String?, homePageURL: String?, name: String?, editedName: String?, accountID: String?, accountType: AccountType?) {
|
||||
self.url = url.rs_normalizedURL()
|
||||
self.url = url.normalizedURL
|
||||
self.feedID = feedID
|
||||
self.homePageURL = homePageURL?.rs_normalizedURL()
|
||||
self.homePageURL = homePageURL?.normalizedURL
|
||||
self.name = name
|
||||
self.editedName = editedName
|
||||
self.accountID = accountID
|
||||
@@ -93,7 +93,7 @@ struct PasteboardFeed: Hashable {
|
||||
}
|
||||
if let foundType = pasteboardType {
|
||||
if let possibleURLString = pasteboardItem.string(forType: foundType) {
|
||||
if possibleURLString.rs_stringMayBeURL() {
|
||||
if possibleURLString.mayBeURL {
|
||||
self.init(url: possibleURLString, feedID: nil, homePageURL: nil, name: nil, editedName: nil, accountID: nil, accountType: nil)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -77,7 +77,7 @@ private extension ArticlePasteboardWriter {
|
||||
s += "\(summary)\n\n"
|
||||
}
|
||||
else if let html = article.contentHTML {
|
||||
let convertedHTML = html.rs_stringByConvertingToPlainText()
|
||||
let convertedHTML = html.convertingToPlainText()
|
||||
s += "\(convertedHTML)\n\n"
|
||||
}
|
||||
|
||||
|
||||
@@ -63,7 +63,7 @@ final class TimelineAvatarView: NSView {
|
||||
}
|
||||
|
||||
override func resizeSubviews(withOldSize oldSize: NSSize) {
|
||||
imageView.rs_setFrameIfNotEqual(rectForImageView())
|
||||
imageView.setFrame(ifNotEqualTo: rectForImageView())
|
||||
}
|
||||
|
||||
override func draw(_ dirtyRect: NSRect) {
|
||||
|
||||
@@ -116,12 +116,12 @@ class TimelineTableCellView: NSTableCellView {
|
||||
setFrame(for: summaryView, rect: layoutRects.summaryRect)
|
||||
setFrame(for: textView, rect: layoutRects.textRect)
|
||||
|
||||
dateView.rs_setFrameIfNotEqual(layoutRects.dateRect)
|
||||
unreadIndicatorView.rs_setFrameIfNotEqual(layoutRects.unreadIndicatorRect)
|
||||
feedNameView.rs_setFrameIfNotEqual(layoutRects.feedNameRect)
|
||||
avatarView.rs_setFrameIfNotEqual(layoutRects.avatarImageRect)
|
||||
starView.rs_setFrameIfNotEqual(layoutRects.starRect)
|
||||
separatorView.rs_setFrameIfNotEqual(layoutRects.separatorRect)
|
||||
dateView.setFrame(ifNotEqualTo: layoutRects.dateRect)
|
||||
unreadIndicatorView.setFrame(ifNotEqualTo: layoutRects.unreadIndicatorRect)
|
||||
feedNameView.setFrame(ifNotEqualTo: layoutRects.feedNameRect)
|
||||
avatarView.setFrame(ifNotEqualTo: layoutRects.avatarImageRect)
|
||||
starView.setFrame(ifNotEqualTo: layoutRects.starRect)
|
||||
separatorView.setFrame(ifNotEqualTo: layoutRects.separatorRect)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -172,7 +172,7 @@ private extension TimelineTableCellView {
|
||||
}
|
||||
else {
|
||||
showView(textField)
|
||||
textField.rs_setFrameIfNotEqual(rect)
|
||||
textField.setFrame(ifNotEqualTo: rect)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -256,7 +256,7 @@ final class TimelineViewController: NSViewController, UndoableCommandRunner, Unr
|
||||
tableView.scrollTo(row: 0, extraHeight: 0)
|
||||
}
|
||||
|
||||
tableView.rs_selectRow(nextRowIndex)
|
||||
tableView.selectRow(nextRowIndex)
|
||||
|
||||
let followingRowIndex = nextRowIndex - 1
|
||||
if followingRowIndex < 0 {
|
||||
@@ -278,7 +278,7 @@ final class TimelineViewController: NSViewController, UndoableCommandRunner, Unr
|
||||
tableView.scrollTo(row: tableMaxIndex, extraHeight: 0)
|
||||
}
|
||||
|
||||
tableView.rs_selectRow(nextRowIndex)
|
||||
tableView.selectRow(nextRowIndex)
|
||||
|
||||
let followingRowIndex = nextRowIndex + 1
|
||||
if followingRowIndex > tableMaxIndex {
|
||||
@@ -383,7 +383,7 @@ final class TimelineViewController: NSViewController, UndoableCommandRunner, Unr
|
||||
return
|
||||
}
|
||||
NSCursor.setHiddenUntilMouseMoves(true)
|
||||
tableView.rs_selectRow(ix)
|
||||
tableView.selectRow(ix)
|
||||
tableView.scrollTo(row: ix)
|
||||
}
|
||||
|
||||
@@ -405,7 +405,7 @@ final class TimelineViewController: NSViewController, UndoableCommandRunner, Unr
|
||||
|
||||
window.makeFirstResponderUnlessDescendantIsFirstResponder(tableView)
|
||||
if !hasAtLeastOneSelectedArticle && articles.count > 0 {
|
||||
tableView.rs_selectRowAndScrollToVisible(0)
|
||||
tableView.selectRowAndScrollToVisible(0)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -155,7 +155,7 @@ private extension AccountsPreferencesViewController {
|
||||
addChild(controller)
|
||||
controller.view.translatesAutoresizingMaskIntoConstraints = false
|
||||
detailView.addSubview(controller.view)
|
||||
detailView.rs_addFullSizeConstraints(forSubview: controller.view)
|
||||
detailView.addFullSizeConstraints(forSubview: controller.view)
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -177,7 +177,7 @@ private struct RSSReader: Hashable {
|
||||
let name = (path as NSString).lastPathComponent
|
||||
self.name = name
|
||||
if name.hasSuffix(".app") {
|
||||
self.nameMinusAppSuffix = name.rs_string(byStrippingSuffix: ".app", caseSensitive: false)
|
||||
self.nameMinusAppSuffix = name.stripping(suffix: ".app")
|
||||
}
|
||||
else {
|
||||
self.nameMinusAppSuffix = name
|
||||
|
||||
@@ -150,7 +150,7 @@ class ScriptableAccount: NSObject, UniqueIdScriptingObject, ScriptingObjectConta
|
||||
|
||||
@objc(opmlRepresentation)
|
||||
var opmlRepresentation:String {
|
||||
return self.account.OPMLString(indentLevel:0, strictConformance: true)
|
||||
return self.account.OPMLString(indentLevel:0, allowCustomAttributes: false)
|
||||
}
|
||||
|
||||
@objc(accountType)
|
||||
@@ -168,6 +168,6 @@ class ScriptableAccount: NSObject, UniqueIdScriptingObject, ScriptingObjectConta
|
||||
case .newsBlur:
|
||||
osType = "NBlr"
|
||||
}
|
||||
return osType.fourCharCode()
|
||||
return osType.fourCharCode
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,8 +44,8 @@ extension AppDelegate : AppDelegateAppleEvents {
|
||||
return
|
||||
}
|
||||
|
||||
let normalizedURLString = urlString.rs_normalizedURL()
|
||||
if !normalizedURLString.rs_stringMayBeURL() {
|
||||
let normalizedURLString = urlString.normalizedURL
|
||||
if !normalizedURLString.mayBeURL {
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -146,7 +146,7 @@ class ScriptableFeed: NSObject, UniqueIdScriptingObject, ScriptingObjectContaine
|
||||
|
||||
@objc(opmlRepresentation)
|
||||
var opmlRepresentation:String {
|
||||
return self.feed.OPMLString(indentLevel:0, strictConformance: true)
|
||||
return self.feed.OPMLString(indentLevel:0, allowCustomAttributes: false)
|
||||
}
|
||||
|
||||
// MARK: --- scriptable elements ---
|
||||
|
||||
@@ -101,7 +101,7 @@ class ScriptableFolder: NSObject, UniqueIdScriptingObject, ScriptingObjectContai
|
||||
|
||||
@objc(opmlRepresentation)
|
||||
var opmlRepresentation:String {
|
||||
return self.folder.OPMLString(indentLevel:0, strictConformance: true)
|
||||
return self.folder.OPMLString(indentLevel:0, allowCustomAttributes: false)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ extension NSScriptCommand {
|
||||
func isCreateCommand(forClass whatClass:String) -> Bool {
|
||||
guard let arguments = self.arguments else {return false}
|
||||
guard let newObjectClass = arguments["ObjectClass"] as? Int else {return false}
|
||||
guard (newObjectClass.fourCharCode() == whatClass.fourCharCode()) else {return false}
|
||||
guard (newObjectClass.fourCharCode == whatClass.fourCharCode) else {return false}
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -36,12 +36,12 @@ extension NSScriptCommand {
|
||||
print("insertionLocation : \(insertionLocationDescriptor)")
|
||||
// insertion location can be a typeObjectSpecifier, e.g. 'in account "Acct"'
|
||||
// or a typeInsertionLocation, e.g. 'at end of folder "
|
||||
if (insertionLocationDescriptor.descriptorType == "insl".fourCharCode()) {
|
||||
descriptorToConsider = insertionLocationDescriptor.forKeyword("kobj".fourCharCode())
|
||||
} else if ( insertionLocationDescriptor.descriptorType == "obj ".fourCharCode()) {
|
||||
if (insertionLocationDescriptor.descriptorType == "insl".fourCharCode) {
|
||||
descriptorToConsider = insertionLocationDescriptor.forKeyword("kobj".fourCharCode)
|
||||
} else if ( insertionLocationDescriptor.descriptorType == "obj ".fourCharCode) {
|
||||
descriptorToConsider = insertionLocationDescriptor
|
||||
}
|
||||
} else if let subjectDescriptor = appleEvent.attributeDescriptor(forKeyword:"subj".fourCharCode()) {
|
||||
} else if let subjectDescriptor = appleEvent.attributeDescriptor(forKeyword:"subj".fourCharCode) {
|
||||
descriptorToConsider = subjectDescriptor
|
||||
}
|
||||
|
||||
|
||||
@@ -48,7 +48,7 @@ struct ArticleRenderer {
|
||||
private extension ArticleRenderer {
|
||||
|
||||
private var articleHTML: String {
|
||||
let body = RSMacroProcessor.renderedText(withTemplate: template(), substitutions: substitutions(), macroStart: "[[", macroEnd: "]]")
|
||||
let body = try! MacroProcessor.renderedText(withTemplate: template(), substitutions: substitutions())
|
||||
return renderHTML(withBody: body)
|
||||
}
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ struct ArticleStyle: Equatable {
|
||||
|
||||
self.path = path
|
||||
|
||||
let isFolder = FileManager.default.rs_fileIsFolder(path)
|
||||
let isFolder = FileManager.default.isFolder(atPath: path)
|
||||
|
||||
if isFolder {
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ private let styleSuffixes = [styleSuffix, nnwStyleSuffix, cssStyleSuffix];
|
||||
final class ArticleStylesManager {
|
||||
|
||||
static let shared = ArticleStylesManager()
|
||||
private let folderPath = RSDataSubfolder(nil, stylesFolderName)!
|
||||
private let folderPath = Platform.dataSubfolder(forApplication: nil, folderName: stylesFolderName)!
|
||||
|
||||
var currentStyleName: String {
|
||||
get {
|
||||
@@ -133,7 +133,7 @@ final class ArticleStylesManager {
|
||||
|
||||
private func allStylePaths(_ folder: String) -> [String] {
|
||||
|
||||
let filepaths = FileManager.default.rs_filepaths(inFolder: folder)
|
||||
let filepaths = FileManager.default.filePaths(inFolder: folder)!
|
||||
return filepaths.filter { fileAtPathIsStyle($0) }
|
||||
}
|
||||
|
||||
@@ -154,7 +154,7 @@ private func filenameWithStyleSuffixRemoved(_ filename: String) -> String {
|
||||
|
||||
for oneSuffix in styleSuffixes {
|
||||
if filename.hasSuffix(oneSuffix) {
|
||||
return (filename as NSString).rs_string(byStrippingSuffix: oneSuffix, caseSensitive: false)
|
||||
return filename.stripping(suffix: oneSuffix)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -57,7 +57,7 @@ private extension SendToMarsEditCommand {
|
||||
let body = article.contentHTML ?? article.contentText ?? article.summary
|
||||
let authorName = article.authors?.first?.name
|
||||
|
||||
let sender = SendToBlogEditorApp(targetDesciptor: targetDescriptor, title: article.title, body: body, summary: article.summary, link: article.externalURL, permalink: article.url, subject: nil, creator: authorName, commentsURL: nil, guid: article.uniqueID, sourceName: article.feed?.nameForDisplay, sourceHomeURL: article.feed?.homePageURL, sourceFeedURL: article.feed?.url)
|
||||
let sender = SendToBlogEditorApp(targetDescriptor: targetDescriptor, title: article.title, body: body, summary: article.summary, link: article.externalURL, permalink: article.url, subject: nil, creator: authorName, commentsURL: nil, guid: article.uniqueID, sourceName: article.feed?.nameForDisplay, sourceHomeURL: article.feed?.homePageURL, sourceFeedURL: article.feed?.url)
|
||||
let _ = sender.send()
|
||||
}
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ struct OPMLExporter {
|
||||
|
||||
static func OPMLString(with account: Account, title: String) -> String {
|
||||
|
||||
let escapedTitle = title.rs_stringByEscapingSpecialXMLCharacters()
|
||||
let escapedTitle = title.escapingSpecialXMLCharacters
|
||||
let openingText =
|
||||
"""
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
@@ -27,7 +27,7 @@ struct OPMLExporter {
|
||||
|
||||
"""
|
||||
|
||||
let middleText = account.OPMLString(indentLevel: 0, strictConformance: true)
|
||||
let middleText = account.OPMLString(indentLevel: 0, allowCustomAttributes: false)
|
||||
|
||||
let closingText =
|
||||
"""
|
||||
|
||||
@@ -23,7 +23,7 @@ extension RSImage {
|
||||
}
|
||||
|
||||
static func scaledForAvatar(_ data: Data) -> RSImage? {
|
||||
let scaledMaxPixelSize = Int(ceil(CGFloat(RSImage.avatarSize) * RSScreen.mainScreenScale))
|
||||
let scaledMaxPixelSize = Int(ceil(CGFloat(RSImage.avatarSize) * RSScreen.maxScreenScale))
|
||||
guard var cgImage = RSImage.scaleImage(data, maxPixelSize: scaledMaxPixelSize) else {
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -93,7 +93,7 @@ final class FaviconDownloader {
|
||||
|
||||
func favicon(withHomePageURL homePageURL: String) -> RSImage? {
|
||||
|
||||
let url = homePageURL.rs_normalizedURL()
|
||||
let url = homePageURL.normalizedURL
|
||||
if homePageURLsWithNoFaviconURL.contains(url) {
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ final class SingleFaviconDownloader {
|
||||
private let queue: DispatchQueue
|
||||
|
||||
private var diskKey: String {
|
||||
return (faviconURL as NSString).rs_md5Hash()
|
||||
return faviconURL.md5String
|
||||
}
|
||||
|
||||
init(faviconURL: String, homePageURL: String?, diskCache: BinaryDiskCache, queue: DispatchQueue) {
|
||||
@@ -102,7 +102,7 @@ private extension SingleFaviconDownloader {
|
||||
queue.async {
|
||||
|
||||
if let data = self.diskCache[self.diskKey], !data.isEmpty {
|
||||
RSImage.rs_image(with: data, imageResultBlock: callback)
|
||||
RSImage.image(with: data, imageResultBlock: callback)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -137,7 +137,7 @@ private extension SingleFaviconDownloader {
|
||||
|
||||
if let data = data, !data.isEmpty, let response = response, response.statusIsOK, error == nil {
|
||||
self.saveToDisk(data)
|
||||
RSImage.rs_image(with: data, imageResultBlock: callback)
|
||||
RSImage.image(with: data, imageResultBlock: callback)
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -128,7 +128,7 @@ private extension ImageDownloader {
|
||||
|
||||
func diskKey(_ url: String) -> String {
|
||||
|
||||
return (url as NSString).rs_md5Hash()
|
||||
return url.md5String
|
||||
}
|
||||
|
||||
func postImageDidBecomeAvailableNotification(_ url: String) {
|
||||
|
||||
@@ -65,8 +65,8 @@ struct TimelineStringFormatter {
|
||||
s = s.replacingOccurrences(of: "\r", with: "")
|
||||
s = s.replacingOccurrences(of: "\t", with: "")
|
||||
s = s.rsparser_stringByDecodingHTMLEntities()
|
||||
s = s.rs_stringByTrimmingWhitespace()
|
||||
s = s.rs_stringWithCollapsedWhitespace()
|
||||
s = s.trimmingWhitespace
|
||||
s = s.collapsingWhitespace
|
||||
|
||||
let maxLength = 1000
|
||||
if s.count < maxLength {
|
||||
@@ -89,9 +89,9 @@ struct TimelineStringFormatter {
|
||||
return cachedBody
|
||||
}
|
||||
var s = body.rsparser_stringByDecodingHTMLEntities()
|
||||
s = s.rs_string(byStrippingHTML: 150)
|
||||
s = s.rs_stringByTrimmingWhitespace()
|
||||
s = s.rs_stringWithCollapsedWhitespace()
|
||||
s = s.strippingHTML(maxCharacters: 150)
|
||||
s = s.trimmingWhitespace
|
||||
s = s.collapsingWhitespace
|
||||
if s == "Comments" { // Hacker News.
|
||||
s = ""
|
||||
}
|
||||
@@ -100,7 +100,7 @@ struct TimelineStringFormatter {
|
||||
}
|
||||
|
||||
static func dateString(_ date: Date) -> String {
|
||||
if NSCalendar.rs_dateIsToday(date) {
|
||||
if Calendar.dateIsToday(date) {
|
||||
return timeFormatter.string(from: date)
|
||||
}
|
||||
return dateFormatter.string(from: date)
|
||||
|
||||
@@ -22,7 +22,7 @@ extension NSAppleEventDescriptor {
|
||||
print ("error: usrfDictionary() expected input to be a record")
|
||||
return [:]
|
||||
}
|
||||
guard let usrfList = self.forKeyword("usrf".fourCharCode()) else {
|
||||
guard let usrfList = self.forKeyword("usrf".fourCharCode) else {
|
||||
print ("error: usrfDictionary() couldn't find usrf")
|
||||
return [:]
|
||||
}
|
||||
|
||||
@@ -70,7 +70,7 @@ class AddFeedViewController: UITableViewController, AddContainerViewControllerCh
|
||||
func add() {
|
||||
|
||||
let urlString = urlTextField.text ?? ""
|
||||
let normalizedURLString = (urlString as NSString).rs_normalizedURL()
|
||||
let normalizedURLString = (urlString as NSString).normalizedURL
|
||||
|
||||
guard !normalizedURLString.isEmpty, let url = URL(string: normalizedURLString) else {
|
||||
delegate?.processingDidCancel()
|
||||
@@ -121,7 +121,7 @@ class AddFeedViewController: UITableViewController, AddContainerViewControllerCh
|
||||
}
|
||||
|
||||
@objc func textDidChange(_ note: Notification) {
|
||||
delegate?.readyToAdd(state: urlTextField.text?.rs_stringMayBeURL() ?? false)
|
||||
delegate?.readyToAdd(state: urlTextField.text?.mayBeURL ?? false)
|
||||
}
|
||||
|
||||
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
|
||||
|
||||
Submodule submodules/RSCore updated: 07ee91394d...34e67f8b5f
Reference in New Issue
Block a user