Merge branch 'ios-candidate' of https://github.com/Ranchero-Software/NetNewsWire into ios-candidate
This commit is contained in:
commit
e61d2620de
|
@ -29,7 +29,7 @@ public struct AccountBehaviors: OptionSet {
|
|||
/**
|
||||
Account doesn't support OPML imports
|
||||
*/
|
||||
public static let disallowOPMLImports = AccountBehaviors(rawValue: 3)
|
||||
public static let disallowOPMLImports = AccountBehaviors(rawValue: 4)
|
||||
|
||||
public let rawValue: Int
|
||||
public init(rawValue: Int) {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
//
|
||||
// AccountViewControllerSchemeHandler.swift
|
||||
// DetailIconSchemeHandler.swift
|
||||
// NetNewsWire-iOS
|
||||
//
|
||||
// Created by Maurice Parker on 11/7/19.
|
||||
|
@ -10,7 +10,7 @@ import Foundation
|
|||
import WebKit
|
||||
import Articles
|
||||
|
||||
class ArticleIconSchemeHandler: NSObject, WKURLSchemeHandler {
|
||||
class DetailIconSchemeHandler: NSObject, WKURLSchemeHandler {
|
||||
|
||||
var currentArticle: Article?
|
||||
|
|
@ -28,6 +28,17 @@ final class DetailWebViewController: NSViewController, WKUIDelegate {
|
|||
}
|
||||
}
|
||||
|
||||
var article: Article? {
|
||||
switch state {
|
||||
case .article(let article):
|
||||
return article
|
||||
case .extracted(let article, _):
|
||||
return article
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
#if !MAC_APP_STORE
|
||||
private var webInspectorEnabled: Bool {
|
||||
get {
|
||||
|
@ -39,7 +50,7 @@ final class DetailWebViewController: NSViewController, WKUIDelegate {
|
|||
}
|
||||
#endif
|
||||
|
||||
private let articleIconSchemeHandler = ArticleIconSchemeHandler()
|
||||
private let detailIconSchemeHandler = DetailIconSchemeHandler()
|
||||
private var waitingForFirstReload = false
|
||||
private let keyboardDelegate = DetailKeyboardDelegate()
|
||||
|
||||
|
@ -66,7 +77,7 @@ final class DetailWebViewController: NSViewController, WKUIDelegate {
|
|||
|
||||
let configuration = WKWebViewConfiguration()
|
||||
configuration.preferences = preferences
|
||||
configuration.setURLSchemeHandler(articleIconSchemeHandler, forURLScheme: ArticleRenderer.imageIconScheme)
|
||||
configuration.setURLSchemeHandler(detailIconSchemeHandler, forURLScheme: ArticleRenderer.imageIconScheme)
|
||||
|
||||
let userContentController = WKUserContentController()
|
||||
userContentController.add(self, name: MessageName.mouseDidEnter)
|
||||
|
@ -107,7 +118,7 @@ final class DetailWebViewController: NSViewController, WKUIDelegate {
|
|||
NotificationCenter.default.addObserver(self, selector: #selector(avatarDidBecomeAvailable(_:)), name: .AvatarDidBecomeAvailable, object: nil)
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(faviconDidBecomeAvailable(_:)), name: .FaviconDidBecomeAvailable, object: nil)
|
||||
|
||||
webView.loadHTMLString(ArticleRenderer.page.html, baseURL: ArticleRenderer.page.baseURL)
|
||||
webView.loadFileURL(ArticleRenderer.page.url, allowingReadAccessTo: ArticleRenderer.page.baseURL)
|
||||
|
||||
}
|
||||
|
||||
|
@ -193,7 +204,8 @@ struct TemplateData: Codable {
|
|||
private extension DetailWebViewController {
|
||||
|
||||
func reloadArticleImage() {
|
||||
webView.evaluateJavaScript("reloadArticleImage()")
|
||||
guard let article = article else { return }
|
||||
webView?.evaluateJavaScript("reloadArticleImage(\"\(article.articleID)\")")
|
||||
}
|
||||
|
||||
func reloadHTML() {
|
||||
|
@ -208,10 +220,10 @@ private extension DetailWebViewController {
|
|||
case .loading:
|
||||
rendering = ArticleRenderer.loadingHTML(style: style)
|
||||
case .article(let article):
|
||||
articleIconSchemeHandler.currentArticle = article
|
||||
detailIconSchemeHandler.currentArticle = article
|
||||
rendering = ArticleRenderer.articleHTML(article: article, style: style)
|
||||
case .extracted(let article, let extractedArticle):
|
||||
articleIconSchemeHandler.currentArticle = article
|
||||
detailIconSchemeHandler.currentArticle = article
|
||||
rendering = ArticleRenderer.articleHTML(article: article, extractedArticle: extractedArticle, style: style)
|
||||
}
|
||||
|
||||
|
|
|
@ -72,7 +72,6 @@
|
|||
513C5D0C232574DA003D4054 /* RSTree.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 84C37F9520DD8CFE00CA8CF5 /* RSTree.framework */; };
|
||||
513C5D0E232574E4003D4054 /* SyncDatabase.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 51554C01228B6EB50055115A /* SyncDatabase.framework */; };
|
||||
5141E7392373C18B0013FF27 /* WebFeedInspectorViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5141E7382373C18B0013FF27 /* WebFeedInspectorViewController.swift */; };
|
||||
5141E7562374A2890013FF27 /* ArticleIconSchemeHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5141E7552374A2890013FF27 /* ArticleIconSchemeHandler.swift */; };
|
||||
5142192A23522B5500E07E2C /* ImageViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5142192923522B5500E07E2C /* ImageViewController.swift */; };
|
||||
514219372352510100E07E2C /* ImageScrollView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 514219362352510100E07E2C /* ImageScrollView.swift */; };
|
||||
5142194B2353C1CF00E07E2C /* main_mac.js in Resources */ = {isa = PBXBuildFile; fileRef = 5142194A2353C1CF00E07E2C /* main_mac.js */; };
|
||||
|
@ -121,8 +120,8 @@
|
|||
518651DA235621840078E021 /* ImageTransition.swift in Sources */ = {isa = PBXBuildFile; fileRef = 518651D9235621840078E021 /* ImageTransition.swift */; };
|
||||
5186A635235EF3A800C97195 /* VibrantLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5186A634235EF3A800C97195 /* VibrantLabel.swift */; };
|
||||
518B2EE82351B45600400001 /* NetNewsWire_iOSTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 840D61952029031D009BC708 /* NetNewsWire_iOSTests.swift */; };
|
||||
518C3193237B00D9004D740F /* ArticleIconSchemeHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5141E7552374A2890013FF27 /* ArticleIconSchemeHandler.swift */; };
|
||||
518C3194237B00DA004D740F /* ArticleIconSchemeHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5141E7552374A2890013FF27 /* ArticleIconSchemeHandler.swift */; };
|
||||
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 */; };
|
||||
|
@ -258,6 +257,7 @@
|
|||
51F85BF92274AA7B00C787DC /* UIBarButtonItem-Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51F85BF82274AA7B00C787DC /* UIBarButtonItem-Extensions.swift */; };
|
||||
51F85BFB2275D85000C787DC /* Array-Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51F85BFA2275D85000C787DC /* Array-Extensions.swift */; };
|
||||
51F85BFD2275DCA800C787DC /* SingleLineUILabelSizer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51F85BFC2275DCA800C787DC /* SingleLineUILabelSizer.swift */; };
|
||||
51F9F3F723DF6DB200A314FD /* ArticleIconSchemeHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51F9F3F623DF6DB200A314FD /* ArticleIconSchemeHandler.swift */; };
|
||||
51FA73A42332BE110090D516 /* ArticleExtractor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51FA73A32332BE110090D516 /* ArticleExtractor.swift */; };
|
||||
51FA73A52332BE110090D516 /* ArticleExtractor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51FA73A32332BE110090D516 /* ArticleExtractor.swift */; };
|
||||
51FA73A72332BE880090D516 /* ExtractedArticle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51FA73A62332BE880090D516 /* ExtractedArticle.swift */; };
|
||||
|
@ -1265,7 +1265,7 @@
|
|||
513C5CEB232571C2003D4054 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/MainInterface.storyboard; sourceTree = "<group>"; };
|
||||
513C5CED232571C2003D4054 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
5141E7382373C18B0013FF27 /* WebFeedInspectorViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WebFeedInspectorViewController.swift; sourceTree = "<group>"; };
|
||||
5141E7552374A2890013FF27 /* ArticleIconSchemeHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ArticleIconSchemeHandler.swift; sourceTree = "<group>"; };
|
||||
5141E7552374A2890013FF27 /* DetailIconSchemeHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DetailIconSchemeHandler.swift; sourceTree = "<group>"; };
|
||||
5142192923522B5500E07E2C /* ImageViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageViewController.swift; sourceTree = "<group>"; };
|
||||
514219362352510100E07E2C /* ImageScrollView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ImageScrollView.swift; sourceTree = "<group>"; };
|
||||
5142194A2353C1CF00E07E2C /* main_mac.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; path = main_mac.js; sourceTree = "<group>"; };
|
||||
|
@ -1382,6 +1382,7 @@
|
|||
51F85BF82274AA7B00C787DC /* UIBarButtonItem-Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIBarButtonItem-Extensions.swift"; sourceTree = "<group>"; };
|
||||
51F85BFA2275D85000C787DC /* Array-Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Array-Extensions.swift"; sourceTree = "<group>"; };
|
||||
51F85BFC2275DCA800C787DC /* SingleLineUILabelSizer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SingleLineUILabelSizer.swift; sourceTree = "<group>"; };
|
||||
51F9F3F623DF6DB200A314FD /* ArticleIconSchemeHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ArticleIconSchemeHandler.swift; sourceTree = "<group>"; };
|
||||
51FA73A32332BE110090D516 /* ArticleExtractor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ArticleExtractor.swift; sourceTree = "<group>"; };
|
||||
51FA73A62332BE880090D516 /* ExtractedArticle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExtractedArticle.swift; sourceTree = "<group>"; };
|
||||
51FA73B62332D5F70090D516 /* ArticleExtractorButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ArticleExtractorButton.swift; sourceTree = "<group>"; };
|
||||
|
@ -1970,6 +1971,7 @@
|
|||
512D554323C804DE0023FFFA /* OpenInSafariActivity.swift */,
|
||||
51AB8AB223B7F4C6008F147D /* WebViewController.swift */,
|
||||
517630222336657E00E15FFF /* WebViewProvider.swift */,
|
||||
51F9F3F623DF6DB200A314FD /* ArticleIconSchemeHandler.swift */,
|
||||
);
|
||||
path = Article;
|
||||
sourceTree = "<group>";
|
||||
|
@ -1993,7 +1995,6 @@
|
|||
51C452A822650DA100C03939 /* Article Rendering */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
5141E7552374A2890013FF27 /* ArticleIconSchemeHandler.swift */,
|
||||
849A977D1ED9EC42007D329B /* ArticleRenderer.swift */,
|
||||
517630032336215100E15FFF /* main.js */,
|
||||
49F40DEF2335B71000552BF4 /* newsfoot.js */,
|
||||
|
@ -2318,6 +2319,7 @@
|
|||
84216D0222128B9D0049B9B9 /* DetailWebViewController.swift */,
|
||||
84E8E0EA202F693600562D8F /* DetailWebView.swift */,
|
||||
84D52E941FE588BB00D14F5B /* DetailStatusBarView.swift */,
|
||||
5141E7552374A2890013FF27 /* DetailIconSchemeHandler.swift */,
|
||||
B528F81D23333C7E00E735DD /* page.html */,
|
||||
5142194A2353C1CF00E07E2C /* main_mac.js */,
|
||||
848362FC2262A30800DA1D35 /* styleSheet.css */,
|
||||
|
@ -3726,7 +3728,7 @@
|
|||
65ED3FE9235DEF6C0081F399 /* FaviconURLFinder.swift in Sources */,
|
||||
65ED3FEA235DEF6C0081F399 /* SidebarViewController+ContextualMenus.swift in Sources */,
|
||||
65ED3FEC235DEF6C0081F399 /* RSHTMLMetadata+Extension.swift in Sources */,
|
||||
518C3194237B00DA004D740F /* ArticleIconSchemeHandler.swift in Sources */,
|
||||
518C3194237B00DA004D740F /* DetailIconSchemeHandler.swift in Sources */,
|
||||
65ED3FED235DEF6C0081F399 /* SendToMarsEditCommand.swift in Sources */,
|
||||
65ED3FEE235DEF6C0081F399 /* UserNotificationManager.swift in Sources */,
|
||||
65ED3FEF235DEF6C0081F399 /* ScriptingObjectContainer.swift in Sources */,
|
||||
|
@ -3889,7 +3891,6 @@
|
|||
51C45292226509C800C03939 /* TodayFeedDelegate.swift in Sources */,
|
||||
51C452A222650A1900C03939 /* RSHTMLMetadata+Extension.swift in Sources */,
|
||||
514B7D1F23219F3C00BAC947 /* AddControllerType.swift in Sources */,
|
||||
5141E7562374A2890013FF27 /* ArticleIconSchemeHandler.swift in Sources */,
|
||||
51627A93238A3836007B3B4B /* CroppingPreviewParameters.swift in Sources */,
|
||||
512AF9DD236F05230066F8BE /* InteractiveLabel.swift in Sources */,
|
||||
51E3EB3D229AB08300645299 /* ErrorHandler.swift in Sources */,
|
||||
|
@ -3919,6 +3920,7 @@
|
|||
84CAFCA522BC8C08007694F0 /* FetchRequestQueue.swift in Sources */,
|
||||
51C4529C22650A1000C03939 /* SingleFaviconDownloader.swift in Sources */,
|
||||
51E595A6228CC36500FCC42B /* ArticleStatusSyncTimer.swift in Sources */,
|
||||
51F9F3F723DF6DB200A314FD /* ArticleIconSchemeHandler.swift in Sources */,
|
||||
512AF9C2236ED52C0066F8BE /* ImageHeaderView.swift in Sources */,
|
||||
51A1699F235E10D700EB091F /* AboutViewController.swift in Sources */,
|
||||
51C45290226509C100C03939 /* PseudoFeed.swift in Sources */,
|
||||
|
@ -4074,7 +4076,7 @@
|
|||
848D578E21543519005FFAD5 /* PasteboardWebFeed.swift in Sources */,
|
||||
5144EA2F2279FAB600D19003 /* AccountsDetailViewController.swift in Sources */,
|
||||
849A97801ED9EC42007D329B /* DetailViewController.swift in Sources */,
|
||||
518C3193237B00D9004D740F /* ArticleIconSchemeHandler.swift in Sources */,
|
||||
518C3193237B00D9004D740F /* DetailIconSchemeHandler.swift in Sources */,
|
||||
84C9FC6722629B9000D921D6 /* AppDelegate.swift in Sources */,
|
||||
84C9FC7A22629E1200D921D6 /* AccountsTableViewBackgroundView.swift in Sources */,
|
||||
84CAFCAF22BC8C35007694F0 /* FetchRequestOperation.swift in Sources */,
|
||||
|
|
|
@ -14,15 +14,14 @@ import Account
|
|||
struct ArticleRenderer {
|
||||
|
||||
typealias Rendering = (style: String, html: String)
|
||||
typealias Page = (html: String, baseURL: URL)
|
||||
typealias Page = (url: URL, baseURL: URL)
|
||||
|
||||
static var imageIconScheme = "nnwImageIcon"
|
||||
|
||||
static var page: Page = {
|
||||
let pageURL = Bundle.main.url(forResource: "page", withExtension: "html")!
|
||||
let html = try! String(contentsOf: pageURL)
|
||||
let baseURL = pageURL.deletingLastPathComponent()
|
||||
return Page(html: html, baseURL: baseURL)
|
||||
let url = Bundle.main.url(forResource: "page", withExtension: "html")!
|
||||
let baseURL = url.deletingLastPathComponent()
|
||||
return Page(url: url, baseURL: baseURL)
|
||||
}()
|
||||
|
||||
private let article: Article?
|
||||
|
@ -141,7 +140,7 @@ private extension ArticleRenderer {
|
|||
d["title"] = title
|
||||
|
||||
d["body"] = body
|
||||
d["avatars"] = "<td class=\"header rightAlign avatar\"><img id=\"nnwImageIcon\" src=\"\(ArticleRenderer.imageIconScheme)://\" height=48 width=48 /></td>";
|
||||
d["avatars"] = "<td class=\"header rightAlign avatar\"><img id=\"nnwImageIcon\" src=\"\(ArticleRenderer.imageIconScheme)://\(article.articleID)\" height=48 width=48 /></td>";
|
||||
|
||||
var feedLink = ""
|
||||
if let feedTitle = article.webFeed?.nameForDisplay {
|
||||
|
|
|
@ -79,9 +79,9 @@ function flattenPreElements() {
|
|||
ElementUnwrapper.unwrapAppropriateChildren("div.articleBody td > pre");
|
||||
}
|
||||
|
||||
function reloadArticleImage() {
|
||||
function reloadArticleImage(articleID) {
|
||||
var image = document.getElementById("nnwImageIcon");
|
||||
image.src = "nnwImageIcon://";
|
||||
image.src = "nnwImageIcon://" + articleID;
|
||||
}
|
||||
|
||||
function error() {
|
||||
|
|
|
@ -49,7 +49,7 @@ struct AppAssets {
|
|||
|
||||
static var articleExtractorOffTinted: UIImage = {
|
||||
let image = UIImage(named: "articleExtractorOff")!
|
||||
return image.maskWithColor(color: AppAssets.primaryAccentColor.cgColor)!
|
||||
return image.tinted(color: AppAssets.primaryAccentColor)!
|
||||
}()
|
||||
|
||||
static var articleExtractorOn: UIImage = {
|
||||
|
@ -62,7 +62,7 @@ struct AppAssets {
|
|||
|
||||
static var articleExtractorOnTinted: UIImage = {
|
||||
let image = UIImage(named: "articleExtractorOn")!
|
||||
return image.maskWithColor(color: AppAssets.primaryAccentColor.cgColor)!
|
||||
return image.tinted(color: AppAssets.primaryAccentColor)!
|
||||
}()
|
||||
|
||||
static var iconBackgroundColor: UIColor = {
|
||||
|
|
|
@ -58,8 +58,6 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
|
|||
super.init()
|
||||
appDelegate = self
|
||||
|
||||
// Force lazy initialization of the web view provider so that it can warm up the queue of prepared web views
|
||||
let _ = WebViewProvider.shared
|
||||
AccountManager.shared = AccountManager()
|
||||
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(unreadCountDidChange(_:)), name: .UnreadCountDidChange, object: nil)
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
//
|
||||
// ArticleIconSchemeHandler.swift
|
||||
// NetNewsWire-iOS
|
||||
//
|
||||
// Created by Maurice Parker on 1/27/20.
|
||||
// Copyright © 2020 Ranchero Software. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import WebKit
|
||||
import Articles
|
||||
|
||||
class ArticleIconSchemeHandler: NSObject, WKURLSchemeHandler {
|
||||
|
||||
let coordinator: SceneCoordinator
|
||||
|
||||
init(coordinator: SceneCoordinator) {
|
||||
self.coordinator = coordinator
|
||||
}
|
||||
|
||||
func webView(_ webView: WKWebView, start urlSchemeTask: WKURLSchemeTask) {
|
||||
|
||||
guard let url = urlSchemeTask.request.url else {
|
||||
urlSchemeTask.didFailWithError(URLError(.fileDoesNotExist))
|
||||
return
|
||||
}
|
||||
|
||||
let articleID = url.absoluteString.stripping(prefix: "\(ArticleRenderer.imageIconScheme)://")
|
||||
|
||||
guard let iconImage = coordinator.articleFor(articleID)?.iconImage() else {
|
||||
urlSchemeTask.didFailWithError(URLError(.fileDoesNotExist))
|
||||
return
|
||||
}
|
||||
|
||||
let iconView = IconView(frame: CGRect(x: 0, y: 0, width: 48, height: 48))
|
||||
iconView.iconImage = iconImage
|
||||
let renderedImage = iconView.asImage()
|
||||
|
||||
guard let data = renderedImage.dataRepresentation() else {
|
||||
urlSchemeTask.didFailWithError(URLError(.fileDoesNotExist))
|
||||
return
|
||||
}
|
||||
|
||||
let headerFields = ["Cache-Control": "no-cache"]
|
||||
if let response = HTTPURLResponse(url: url, statusCode: 200, httpVersion: nil, headerFields: headerFields) {
|
||||
urlSchemeTask.didReceive(response)
|
||||
urlSchemeTask.didReceive(data)
|
||||
urlSchemeTask.didFinish()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func webView(_ webView: WKWebView, stop urlSchemeTask: WKURLSchemeTask) {
|
||||
urlSchemeTask.didFailWithError(URLError(.unknown))
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -34,10 +34,6 @@ class ArticleViewController: UIViewController {
|
|||
return button
|
||||
}()
|
||||
|
||||
private var isFullScreenAvailable: Bool {
|
||||
return traitCollection.userInterfaceIdiom == .phone && coordinator.isRootSplitCollapsed
|
||||
}
|
||||
|
||||
weak var coordinator: SceneCoordinator!
|
||||
|
||||
var article: Article? {
|
||||
|
@ -268,14 +264,18 @@ extension ArticleViewController: WebViewControllerDelegate {
|
|||
extension ArticleViewController: UIPageViewControllerDataSource {
|
||||
|
||||
func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
|
||||
guard let article = coordinator.prevArticle else {
|
||||
guard let webViewController = viewController as? WebViewController,
|
||||
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 article = coordinator.nextArticle else {
|
||||
guard let webViewController = viewController as? WebViewController,
|
||||
let currentArticle = webViewController.article,
|
||||
let article = coordinator.findNextArticle(currentArticle) else {
|
||||
return nil
|
||||
}
|
||||
return createWebViewController(article)
|
||||
|
|
|
@ -30,7 +30,6 @@ class WebViewController: UIViewController {
|
|||
private var topShowBarsViewConstraint: NSLayoutConstraint!
|
||||
private var bottomShowBarsViewConstraint: NSLayoutConstraint!
|
||||
|
||||
private var renderingTracker = 0
|
||||
private var webView: WKWebView!
|
||||
private lazy var contextMenuInteraction = UIContextMenuInteraction(delegate: self)
|
||||
private var isFullScreenAvailable: Bool {
|
||||
|
@ -44,7 +43,7 @@ class WebViewController: UIViewController {
|
|||
private var isShowingExtractedArticle = false {
|
||||
didSet {
|
||||
if isShowingExtractedArticle != oldValue {
|
||||
renderPage()
|
||||
reloadHTML()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -65,7 +64,8 @@ class WebViewController: UIViewController {
|
|||
startArticleExtractor()
|
||||
}
|
||||
if article != oldValue {
|
||||
renderPage()
|
||||
restoreWindowScrollY = 0
|
||||
reloadHTML()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -83,7 +83,7 @@ class WebViewController: UIViewController {
|
|||
webView.configuration.userContentController.removeScriptMessageHandler(forName: MessageName.imageWasClicked)
|
||||
webView.configuration.userContentController.removeScriptMessageHandler(forName: MessageName.imageWasShown)
|
||||
webView.removeFromSuperview()
|
||||
WebViewProvider.shared.enqueueWebView(webView)
|
||||
coordinator.webViewProvider.enqueueWebView(webView)
|
||||
webView = nil
|
||||
}
|
||||
}
|
||||
|
@ -96,7 +96,7 @@ class WebViewController: UIViewController {
|
|||
NotificationCenter.default.addObserver(self, selector: #selector(faviconDidBecomeAvailable(_:)), name: .FaviconDidBecomeAvailable, object: nil)
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(contentSizeCategoryDidChange(_:)), name: UIContentSizeCategory.didChangeNotification, object: nil)
|
||||
|
||||
WebViewProvider.shared.dequeueWebView() { webView in
|
||||
coordinator.webViewProvider.dequeueWebView() { webView in
|
||||
|
||||
// Add the webview
|
||||
self.webView = webView
|
||||
|
@ -266,7 +266,7 @@ extension WebViewController: ArticleExtractorDelegate {
|
|||
func articleExtractionDidFail(with: Error) {
|
||||
stopArticleExtractor()
|
||||
articleExtractorButtonState = .error
|
||||
renderPage()
|
||||
reloadHTML()
|
||||
}
|
||||
|
||||
func articleExtractionDidComplete(extractedArticle: ExtractedArticle) {
|
||||
|
@ -350,7 +350,7 @@ extension WebViewController: WKNavigationDelegate {
|
|||
}
|
||||
|
||||
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
|
||||
self.renderPage()
|
||||
renderPage()
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -450,24 +450,12 @@ private struct ImageClickMessage: Codable {
|
|||
private extension WebViewController {
|
||||
|
||||
func reloadHTML() {
|
||||
let url = Bundle.main.url(forResource: "page", withExtension: "html")!
|
||||
webView.loadFileURL(url, allowingReadAccessTo: url.deletingLastPathComponent())
|
||||
renderingTracker = 0
|
||||
webView?.loadFileURL(ArticleRenderer.page.url, allowingReadAccessTo: ArticleRenderer.page.baseURL)
|
||||
}
|
||||
|
||||
func renderPage() {
|
||||
guard let webView = webView else { return }
|
||||
|
||||
// It looks like we need to clean up the webview every once in a while by reloading it from scratch
|
||||
// Otherwise it will stop responding or cause rendering artifacts. This typically only comes into
|
||||
// play on the iPad where we aren't constantly pushing and popping this controller.
|
||||
if (renderingTracker > 10) {
|
||||
reloadHTML()
|
||||
return
|
||||
}
|
||||
|
||||
renderingTracker += 1
|
||||
|
||||
let style = ArticleStylesManager.shared.currentStyle
|
||||
let rendering: ArticleRenderer.Rendering
|
||||
|
||||
|
@ -498,7 +486,6 @@ private extension WebViewController {
|
|||
|
||||
restoreWindowScrollY = 0
|
||||
|
||||
WebViewProvider.shared.articleIconSchemeHandler.currentArticle = article
|
||||
webView.scrollView.setZoomScale(1.0, animated: false)
|
||||
webView.evaluateJavaScript(render)
|
||||
|
||||
|
@ -525,7 +512,8 @@ private extension WebViewController {
|
|||
}
|
||||
|
||||
func reloadArticleImage() {
|
||||
webView?.evaluateJavaScript("reloadArticleImage()")
|
||||
guard let article = article else { return }
|
||||
webView?.evaluateJavaScript("reloadArticleImage(\"\(article.articleID)\")")
|
||||
}
|
||||
|
||||
func imageWasClicked(body: String?) {
|
||||
|
|
|
@ -13,9 +13,7 @@ import WebKit
|
|||
/// Keep a queue of WebViews where we've already done a trivial load so that by the time we need them in the UI, they're past the flash-to-shite part of their lifecycle.
|
||||
class WebViewProvider: NSObject, WKNavigationDelegate {
|
||||
|
||||
static let shared = WebViewProvider()
|
||||
|
||||
let articleIconSchemeHandler = ArticleIconSchemeHandler()
|
||||
let articleIconSchemeHandler: ArticleIconSchemeHandler
|
||||
|
||||
private let minimumQueueDepth = 3
|
||||
private let maximumQueueDepth = 6
|
||||
|
@ -24,6 +22,12 @@ class WebViewProvider: NSObject, WKNavigationDelegate {
|
|||
private var waitingForFirstLoad = true
|
||||
private var waitingCompletionHandler: ((WKWebView) -> ())?
|
||||
|
||||
init(coordinator: SceneCoordinator) {
|
||||
articleIconSchemeHandler = ArticleIconSchemeHandler(coordinator: coordinator)
|
||||
super.init()
|
||||
replenishQueueIfNeeded()
|
||||
}
|
||||
|
||||
func dequeueWebView(completion: @escaping (WKWebView) -> ()) {
|
||||
if waitingForFirstLoad {
|
||||
waitingCompletionHandler = completion
|
||||
|
@ -40,7 +44,7 @@ class WebViewProvider: NSObject, WKNavigationDelegate {
|
|||
webView.navigationDelegate = self
|
||||
queue.insert(webView, at: 0)
|
||||
|
||||
webView.loadHTMLString(ArticleRenderer.page.html, baseURL: ArticleRenderer.page.baseURL)
|
||||
webView.loadFileURL(ArticleRenderer.page.url, allowingReadAccessTo: ArticleRenderer.page.baseURL)
|
||||
|
||||
}
|
||||
|
||||
|
@ -58,11 +62,6 @@ class WebViewProvider: NSObject, WKNavigationDelegate {
|
|||
|
||||
// MARK: Private
|
||||
|
||||
private override init() {
|
||||
super.init()
|
||||
replenishQueueIfNeeded()
|
||||
}
|
||||
|
||||
private func replenishQueueIfNeeded() {
|
||||
while queue.count < minimumQueueDepth {
|
||||
let preferences = WKPreferences()
|
||||
|
|
|
@ -117,10 +117,9 @@ class MasterFeedViewController: UITableViewController, UndoableCommandRunner {
|
|||
// completing if called to soon after a selectRow where scrolling is necessary. See discloseFeed.
|
||||
if let node = node,
|
||||
let indexPath = dataSource.indexPath(for: node),
|
||||
let cell = tableView.cellForRow(at: indexPath) as? MasterFeedTableViewCell,
|
||||
let unreadCountProvider = node.representedObject as? UnreadCountProvider {
|
||||
let cell = tableView.cellForRow(at: indexPath) as? MasterFeedTableViewCell {
|
||||
|
||||
if cell.unreadCount != unreadCountProvider.unreadCount {
|
||||
if cell.unreadCount != coordinator.unreadCountFor(node) {
|
||||
self.reloadNode(node)
|
||||
}
|
||||
|
||||
|
|
|
@ -39,6 +39,7 @@ a:hover {
|
|||
color-scheme: light dark;
|
||||
--primary-accent-color: #086AEE;
|
||||
--secondary-accent-color: #086AEE;
|
||||
--block-quote-border-color: rgba(8, 106, 238, 0.75);
|
||||
--header-table-border-color: rgba(0, 0, 0, 0.1);
|
||||
--header-color: rgba(0, 0, 0, 0.3);
|
||||
--body-code-color: #666;
|
||||
|
@ -52,6 +53,7 @@ a:hover {
|
|||
:root {
|
||||
--primary-accent-color: #2D80F1;
|
||||
--secondary-accent-color: #5E9EF4;
|
||||
--block-quote-border-color: rgba(94, 158, 244, 0.75);
|
||||
--header-table-border-color: rgba(255, 255, 255, 0.2);
|
||||
--header-color: #d2d2d2;
|
||||
--body-code-color: #b2b2b2;
|
||||
|
@ -240,7 +242,7 @@ blockquote {
|
|||
margin-inline-start: 0;
|
||||
margin-inline-end: 0;
|
||||
padding-left: 15px;
|
||||
border-left: 3px solid var(--secondary-accent-color);
|
||||
border-left: 3px solid var(--block-quote-border-color);
|
||||
}
|
||||
|
||||
/* Feed Specific */
|
||||
|
|
|
@ -30,6 +30,8 @@ class SceneCoordinator: NSObject, UndoableCommandRunner, UnreadCountProvider {
|
|||
return rootSplitViewController.undoManager
|
||||
}
|
||||
|
||||
lazy var webViewProvider = WebViewProvider(coordinator: self)
|
||||
|
||||
private var panelMode: PanelMode = .unset
|
||||
|
||||
private var activityManager = ActivityManager()
|
||||
|
@ -255,9 +257,19 @@ class SceneCoordinator: NSObject, UndoableCommandRunner, UnreadCountProvider {
|
|||
private(set) var articles = ArticleArray() {
|
||||
didSet {
|
||||
timelineMiddleIndexPath = nil
|
||||
articleDictionaryNeedsUpdate = true
|
||||
}
|
||||
}
|
||||
|
||||
private var articleDictionaryNeedsUpdate = true
|
||||
private var _idToArticleDictionary = [String: Article]()
|
||||
private var idToAticleDictionary: [String: Article] {
|
||||
if articleDictionaryNeedsUpdate {
|
||||
rebuildArticleDictionaries()
|
||||
}
|
||||
return _idToArticleDictionary
|
||||
}
|
||||
|
||||
private var currentArticleRow: Int? {
|
||||
guard let article = currentArticle else { return nil }
|
||||
return articles.firstIndex(of: article)
|
||||
|
@ -572,6 +584,10 @@ class SceneCoordinator: NSObject, UndoableCommandRunner, UnreadCountProvider {
|
|||
return shadowTable[section]
|
||||
}
|
||||
|
||||
func articleFor(_ articleID: String) -> Article? {
|
||||
return idToAticleDictionary[articleID]
|
||||
}
|
||||
|
||||
func cappedIndexPath(_ indexPath: IndexPath) -> IndexPath {
|
||||
guard indexPath.section < shadowTable.count && indexPath.row < shadowTable[indexPath.section].count else {
|
||||
return IndexPath(row: shadowTable[shadowTable.count - 1].count - 1, section: shadowTable.count - 1)
|
||||
|
@ -594,6 +610,9 @@ class SceneCoordinator: NSObject, UndoableCommandRunner, UnreadCountProvider {
|
|||
func refreshTimeline(resetScroll: Bool) {
|
||||
fetchAndReplaceArticlesAsync(animated: true) {
|
||||
self.masterTimelineViewController?.reinitializeArticles(resetScroll: resetScroll)
|
||||
if let article = self.currentArticle, self.articles.firstIndex(of: article) == nil {
|
||||
self.selectArticle(nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -654,6 +673,7 @@ class SceneCoordinator: NSObject, UndoableCommandRunner, UnreadCountProvider {
|
|||
animatingChanges = true
|
||||
rebuildShadowTable()
|
||||
animatingChanges = false
|
||||
clearTimelineIfNoLongerAvailable()
|
||||
}
|
||||
|
||||
func collapseAllFolders() {
|
||||
|
@ -668,6 +688,7 @@ class SceneCoordinator: NSObject, UndoableCommandRunner, UnreadCountProvider {
|
|||
animatingChanges = true
|
||||
rebuildShadowTable()
|
||||
animatingChanges = false
|
||||
clearTimelineIfNoLongerAvailable()
|
||||
}
|
||||
|
||||
func masterFeedIndexPathForCurrentTimeline() -> IndexPath? {
|
||||
|
@ -686,7 +707,6 @@ class SceneCoordinator: NSObject, UndoableCommandRunner, UnreadCountProvider {
|
|||
currentFeedIndexPath = indexPath
|
||||
masterFeedViewController.updateFeedSelection(animated: animated)
|
||||
|
||||
emptyTheTimeline()
|
||||
if deselectArticle {
|
||||
selectArticle(nil)
|
||||
}
|
||||
|
@ -825,6 +845,20 @@ class SceneCoordinator: NSObject, UndoableCommandRunner, UnreadCountProvider {
|
|||
|
||||
}
|
||||
|
||||
func findPrevArticle(_ article: Article) -> Article? {
|
||||
guard let index = articles.firstIndex(of: article), index > 0 else {
|
||||
return nil
|
||||
}
|
||||
return articles[index - 1]
|
||||
}
|
||||
|
||||
func findNextArticle(_ article: Article) -> Article? {
|
||||
guard let index = articles.firstIndex(of: article), index + 1 != articles.count else {
|
||||
return nil
|
||||
}
|
||||
return articles[index + 1]
|
||||
}
|
||||
|
||||
func selectPrevArticle() {
|
||||
if let article = prevArticle {
|
||||
selectArticle(article)
|
||||
|
@ -1204,12 +1238,24 @@ private extension SceneCoordinator {
|
|||
unreadCount = count
|
||||
}
|
||||
|
||||
func rebuildArticleDictionaries() {
|
||||
var idDictionary = [String: Article]()
|
||||
|
||||
articles.forEach { article in
|
||||
idDictionary[article.articleID] = article
|
||||
}
|
||||
|
||||
_idToArticleDictionary = idDictionary
|
||||
articleDictionaryNeedsUpdate = false
|
||||
}
|
||||
|
||||
func rebuildBackingStores(initialLoad: Bool = false, updateExpandedNodes: (() -> Void)? = nil) {
|
||||
if !animatingChanges && !BatchUpdate.shared.isPerforming {
|
||||
treeController.rebuild()
|
||||
updateExpandedNodes?()
|
||||
rebuildShadowTable()
|
||||
masterFeedViewController.reloadFeeds(initialLoad: initialLoad)
|
||||
clearTimelineIfNoLongerAvailable()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1248,6 +1294,12 @@ private extension SceneCoordinator {
|
|||
return false
|
||||
}
|
||||
|
||||
func clearTimelineIfNoLongerAvailable() {
|
||||
if let feed = timelineFeed, !shadowTableContains(feed) {
|
||||
selectFeed(nil, animated: false, deselectArticle: true)
|
||||
}
|
||||
}
|
||||
|
||||
func nodeFor(_ indexPath: IndexPath) -> Node? {
|
||||
guard indexPath.section < shadowTable.count && indexPath.row < shadowTable[indexPath.section].count else {
|
||||
return nil
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="15702" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="9cW-lu-HoC">
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="15705" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="9cW-lu-HoC">
|
||||
<device id="retina6_1" orientation="portrait" appearance="light"/>
|
||||
<dependencies>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="15704"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="15706"/>
|
||||
<capability name="Named colors" minToolsVersion="9.0"/>
|
||||
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
|
@ -207,7 +207,7 @@
|
|||
</constraints>
|
||||
</tableViewCellContentView>
|
||||
</tableViewCell>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" id="8Gj-qz-NMY" customClass="VibrantTableViewCell" customModule="NetNewsWire" customModuleProvider="target">
|
||||
<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="575.5" width="374" height="44"/>
|
||||
<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">
|
||||
|
@ -226,6 +226,9 @@
|
|||
<constraint firstItem="YHt-eS-KrX" firstAttribute="leading" secondItem="OTe-tG-sb4" secondAttribute="leadingMargin" id="STg-aB-F7n"/>
|
||||
</constraints>
|
||||
</tableViewCellContentView>
|
||||
<connections>
|
||||
<outlet property="label" destination="YHt-eS-KrX" id="zaC-7C-hda"/>
|
||||
</connections>
|
||||
</tableViewCell>
|
||||
</cells>
|
||||
</tableViewSection>
|
||||
|
@ -296,7 +299,7 @@
|
|||
<tableViewSection headerTitle="Help" id="TkH-4v-yhk">
|
||||
<cells>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" textLabel="40W-2p-ne4" style="IBUITableViewCellStyleDefault" id="Om7-lH-RUh" customClass="VibrantTableViewCell" customModule="NetNewsWire" customModuleProvider="target">
|
||||
<rect key="frame" x="0.0" y="819.5" width="374" height="44"/>
|
||||
<rect key="frame" x="20" y="819.5" width="374" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="Om7-lH-RUh" id="vrJ-nE-HMP">
|
||||
<rect key="frame" x="0.0" y="0.0" width="374" height="44"/>
|
||||
|
@ -313,7 +316,7 @@
|
|||
</tableViewCellContentView>
|
||||
</tableViewCell>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" textLabel="lOk-Dh-GfZ" style="IBUITableViewCellStyleDefault" id="GWZ-jk-qU6" customClass="VibrantTableViewCell" customModule="NetNewsWire" customModuleProvider="target">
|
||||
<rect key="frame" x="0.0" y="863.5" width="374" height="44"/>
|
||||
<rect key="frame" x="20" y="863.5" width="374" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="GWZ-jk-qU6" id="ZgS-bo-xDl">
|
||||
<rect key="frame" x="0.0" y="0.0" width="374" height="44"/>
|
||||
|
@ -468,7 +471,7 @@
|
|||
<sections>
|
||||
<tableViewSection id="m3P-em-PgI">
|
||||
<cells>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" rowHeight="55" id="UFl-6I-ucw" customClass="VibrantTableViewCell" customModule="NetNewsWire" customModuleProvider="target">
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" rowHeight="55" id="UFl-6I-ucw" customClass="SettingsAccountTableViewCell" customModule="NetNewsWire" customModuleProvider="target">
|
||||
<rect key="frame" x="20" y="18" width="374" height="55"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="UFl-6I-ucw" id="99i-Ge-guB">
|
||||
|
@ -500,8 +503,12 @@
|
|||
<constraint firstItem="iTt-HT-Ane" firstAttribute="centerY" secondItem="99i-Ge-guB" secondAttribute="centerY" id="UaS-Yf-Q1x"/>
|
||||
</constraints>
|
||||
</tableViewCellContentView>
|
||||
<connections>
|
||||
<outlet property="accountImage" destination="tb2-dO-AhR" id="Ucm-F4-aev"/>
|
||||
<outlet property="accountNameLabel" destination="116-rt-msI" id="nn5-2i-HqG"/>
|
||||
</connections>
|
||||
</tableViewCell>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" rowHeight="56" id="te1-L9-osf" customClass="VibrantTableViewCell" customModule="NetNewsWire" customModuleProvider="target">
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" rowHeight="56" id="te1-L9-osf" customClass="SettingsAccountTableViewCell" customModule="NetNewsWire" customModuleProvider="target">
|
||||
<rect key="frame" x="20" y="73" width="374" height="56"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="te1-L9-osf" id="DgY-u7-DRO">
|
||||
|
@ -533,8 +540,12 @@
|
|||
<constraint firstItem="7dy-NH-2zV" firstAttribute="leading" secondItem="DgY-u7-DRO" secondAttribute="leading" constant="20" symbolic="YES" id="H71-Jv-7uw"/>
|
||||
</constraints>
|
||||
</tableViewCellContentView>
|
||||
<connections>
|
||||
<outlet property="accountImage" destination="wyu-mZ-3zz" id="III-7X-cz1"/>
|
||||
<outlet property="accountNameLabel" destination="uiN-cA-Nc5" id="tvs-Fo-cvB"/>
|
||||
</connections>
|
||||
</tableViewCell>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" rowHeight="56" id="zcM-qz-glk" customClass="VibrantTableViewCell" customModule="NetNewsWire" customModuleProvider="target">
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" rowHeight="56" id="zcM-qz-glk" customClass="SettingsAccountTableViewCell" customModule="NetNewsWire" customModuleProvider="target">
|
||||
<rect key="frame" x="20" y="129" width="374" height="56"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="zcM-qz-glk" id="3VG-Ax-7gi">
|
||||
|
@ -566,8 +577,12 @@
|
|||
<constraint firstItem="cXZ-17-bhe" firstAttribute="centerY" secondItem="3VG-Ax-7gi" secondAttribute="centerY" id="r36-pZ-Siw"/>
|
||||
</constraints>
|
||||
</tableViewCellContentView>
|
||||
<connections>
|
||||
<outlet property="accountImage" destination="fAO-P0-gtD" id="z7J-sQ-zMJ"/>
|
||||
<outlet property="accountNameLabel" destination="u2M-c5-ujy" id="TFJ-Yt-NAB"/>
|
||||
</connections>
|
||||
</tableViewCell>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" rowHeight="56" id="sKj-1P-BwI" customClass="VibrantTableViewCell" customModule="NetNewsWire" customModuleProvider="target">
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" rowHeight="56" id="sKj-1P-BwI" customClass="SettingsAccountTableViewCell" customModule="NetNewsWire" customModuleProvider="target">
|
||||
<rect key="frame" x="20" y="185" width="374" height="56"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="sKj-1P-BwI" id="PdS-21-hdl">
|
||||
|
@ -599,6 +614,10 @@
|
|||
<constraint firstItem="TmQ-Hs-znP" firstAttribute="centerY" secondItem="PdS-21-hdl" secondAttribute="centerY" id="oQy-rL-HV3"/>
|
||||
</constraints>
|
||||
</tableViewCellContentView>
|
||||
<connections>
|
||||
<outlet property="accountImage" destination="pIU-f0-h1H" id="4Mm-Ym-81C"/>
|
||||
<outlet property="accountNameLabel" destination="Dur-Qf-YYi" id="DAF-c9-MJM"/>
|
||||
</connections>
|
||||
</tableViewCell>
|
||||
</cells>
|
||||
</tableViewSection>
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 5c6a61832b1cb1ed2a29e192469079eb8f9147f5
|
||||
Subproject commit c548b018beb865c2a1792d15767a2b378bbdaa89
|
Loading…
Reference in New Issue