diff --git a/Mac/AppAssets.swift b/Mac/AppAssets.swift index aeac5c7bc..ab5eb8dc6 100644 --- a/Mac/AppAssets.swift +++ b/Mac/AppAssets.swift @@ -16,10 +16,10 @@ extension NSImage.Name { struct AppAssets { - static var genericFeedImage: RSImage? = { + static var genericFeedImage: IconImage? = { let path = "/System/Library/CoreServices/CoreTypes.bundle/Contents/Resources/BookmarkIcon.icns" let image = RSImage(contentsOfFile: path) - return image + return image != nil ? IconImage(image!) : nil }() static var timelineStar: RSImage! = { @@ -70,28 +70,32 @@ struct AppAssets { return RSImage(named: "faviconTemplateImage")! }() - static var avatarLightBackgroundColor: NSColor = { - return NSColor(named: NSColor.Name("avatarLightBackgroundColor"))! + static var iconLightBackgroundColor: NSColor = { + return NSColor(named: NSColor.Name("iconLightBackgroundColor"))! }() - static var avatarDarkBackgroundColor: NSColor = { - return NSColor(named: NSColor.Name("avatarDarkBackgroundColor"))! + static var iconDarkBackgroundColor: NSColor = { + return NSColor(named: NSColor.Name("iconDarkBackgroundColor"))! }() - static var searchFeedImage: RSImage = { - return RSImage(named: NSImage.smartBadgeTemplateName)! + static var masterFolderImage: IconImage = { + return IconImage(RSImage(named: NSImage.folderName)!) }() - static var starredFeedImage: RSImage = { - return RSImage(named: NSImage.smartBadgeTemplateName)! + static var searchFeedImage: IconImage = { + return IconImage(RSImage(named: NSImage.smartBadgeTemplateName)!) }() - static var todayFeedImage: RSImage = { - return RSImage(named: NSImage.smartBadgeTemplateName)! + static var starredFeedImage: IconImage = { + return IconImage(RSImage(named: NSImage.smartBadgeTemplateName)!) }() - static var unreadFeedImage: RSImage = { - return RSImage(named: NSImage.smartBadgeTemplateName)! + static var todayFeedImage: IconImage = { + return IconImage(RSImage(named: NSImage.smartBadgeTemplateName)!) + }() + + static var unreadFeedImage: IconImage = { + return IconImage(RSImage(named: NSImage.smartBadgeTemplateName)!) }() static var swipeMarkReadImage: RSImage = { diff --git a/Mac/Inspector/FeedInspectorViewController.swift b/Mac/Inspector/FeedInspectorViewController.swift index 0a3cef52d..0c2bbd568 100644 --- a/Mac/Inspector/FeedInspectorViewController.swift +++ b/Mac/Inspector/FeedInspectorViewController.swift @@ -107,11 +107,11 @@ private extension FeedInspectorViewController { } if let feedIcon = appDelegate.feedIconDownloader.icon(for: feed) { - imageView?.image = feedIcon + imageView?.image = feedIcon.image return } - if let favicon = appDelegate.faviconDownloader.favicon(for: feed) { + if let favicon = appDelegate.faviconDownloader.favicon(for: feed)?.image { if favicon.size.height < 16.0 && favicon.size.width < 16.0 { favicon.size = NSSize(width: 16, height: 16) } @@ -119,7 +119,7 @@ private extension FeedInspectorViewController { return } - imageView?.image = AppAssets.genericFeedImage + imageView?.image = AppAssets.genericFeedImage?.image } func updateName() { diff --git a/Mac/MainWindow/SharingServicePickerDelegate.swift b/Mac/MainWindow/SharingServicePickerDelegate.swift index 0611aeb63..5e2d38dc0 100644 --- a/Mac/MainWindow/SharingServicePickerDelegate.swift +++ b/Mac/MainWindow/SharingServicePickerDelegate.swift @@ -32,7 +32,6 @@ import RSCore }() static func customSharingServices(for items: [Any]) -> [NSSharingService] { - let customServices = sendToCommands.compactMap { (sendToCommand) -> NSSharingService? in guard let object = items.first else { @@ -42,7 +41,7 @@ import RSCore return nil } - let image = sendToCommand.image ?? AppAssets.genericFeedImage ?? NSImage() + let image = sendToCommand.image ?? AppAssets.genericFeedImage?.image ?? NSImage() return NSSharingService(title: sendToCommand.title, image: image, alternateImage: nil) { sendToCommand.sendObject(object, selectedText: nil) } diff --git a/Mac/MainWindow/Sidebar/Cell/SidebarCell.swift b/Mac/MainWindow/Sidebar/Cell/SidebarCell.swift index 3df7366e6..610a51ace 100644 --- a/Mac/MainWindow/Sidebar/Cell/SidebarCell.swift +++ b/Mac/MainWindow/Sidebar/Cell/SidebarCell.swift @@ -81,8 +81,8 @@ class SidebarCell : NSTableCellView { }() private let faviconImageView: NSImageView = { - let image = AppAssets.genericFeedImage - let imageView = image != nil ? NSImageView(image: image!) : NSImageView(frame: NSRect.zero) + let iconImage = AppAssets.genericFeedImage + let imageView = iconImage != nil ? NSImageView(image: iconImage!.image) : NSImageView(frame: NSRect.zero) imageView.animates = false imageView.imageAlignment = .alignCenter imageView.imageScaling = .scaleProportionallyDown diff --git a/Mac/MainWindow/Sidebar/SidebarViewController.swift b/Mac/MainWindow/Sidebar/SidebarViewController.swift index ae16b178c..02dd187ce 100644 --- a/Mac/MainWindow/Sidebar/SidebarViewController.swift +++ b/Mac/MainWindow/Sidebar/SidebarViewController.swift @@ -526,14 +526,14 @@ private extension SidebarViewController { } func configureFavicon(_ cell: SidebarCell, _ node: Node) { - cell.image = imageFor(node) + cell.image = imageFor(node)?.image } func configureGroupCell(_ cell: NSTableCellView, _ node: Node) { cell.textField?.stringValue = nameFor(node) } - func imageFor(_ node: Node) -> NSImage? { + func imageFor(_ node: Node) -> IconImage? { if let smallIconProvider = node.representedObject as? SmallIconProvider { return smallIconProvider.smallIcon } diff --git a/Mac/MainWindow/Timeline/Cell/TimelineCellAppearance.swift b/Mac/MainWindow/Timeline/Cell/TimelineCellAppearance.swift index 32954075c..bbb54eecb 100644 --- a/Mac/MainWindow/Timeline/Cell/TimelineCellAppearance.swift +++ b/Mac/MainWindow/Timeline/Cell/TimelineCellAppearance.swift @@ -10,7 +10,7 @@ import AppKit struct TimelineCellAppearance: Equatable { - let showAvatar: Bool + let showIcon: Bool let cellPadding = NSEdgeInsets(top: 8.0, left: 18.0, bottom: 10.0, right: 18.0) @@ -35,15 +35,15 @@ struct TimelineCellAppearance: Equatable { let drawsGrid = false - let avatarSize = NSSize(width: 48, height: 48) - let avatarMarginLeft: CGFloat = 8.0 - let avatarMarginRight: CGFloat = 8.0 - let avatarAdjustmentTop: CGFloat = 4.0 - let avatarCornerRadius: CGFloat = 4.0 + let iconSize = NSSize(width: 48, height: 48) + let iconMarginLeft: CGFloat = 8.0 + let iconMarginRight: CGFloat = 8.0 + let iconAdjustmentTop: CGFloat = 4.0 + let iconCornerRadius: CGFloat = 4.0 let boxLeftMargin: CGFloat - init(showAvatar: Bool, fontSize: FontSize) { + init(showIcon: Bool, fontSize: FontSize) { let actualFontSize = AppDefaults.actualFontSize(for: fontSize) let smallItemFontSize = actualFontSize //floor(actualFontSize * 0.95) @@ -55,7 +55,7 @@ struct TimelineCellAppearance: Equatable { self.textFont = NSFont.systemFont(ofSize: largeItemFontSize) self.textOnlyFont = NSFont.systemFont(ofSize: largeItemFontSize) - self.showAvatar = showAvatar + self.showIcon = showIcon let margin = self.cellPadding.left + self.unreadCircleDimension + self.unreadCircleMarginRight self.boxLeftMargin = margin diff --git a/Mac/MainWindow/Timeline/Cell/TimelineCellData.swift b/Mac/MainWindow/Timeline/Cell/TimelineCellData.swift index 87afcd9e3..814815eff 100644 --- a/Mac/MainWindow/Timeline/Cell/TimelineCellData.swift +++ b/Mac/MainWindow/Timeline/Cell/TimelineCellData.swift @@ -16,13 +16,13 @@ struct TimelineCellData { let dateString: String let feedName: String let showFeedName: Bool - let avatar: NSImage? // feed icon, user avatar, or favicon - let showAvatar: Bool // Make space even when avatar is nil + let iconImage: IconImage? // feed icon, user avatar, or favicon + let showIcon: Bool // Make space even when icon is nil let featuredImage: NSImage? // image from within the article let read: Bool let starred: Bool - init(article: Article, showFeedName: Bool, feedName: String?, avatar: NSImage?, showAvatar: Bool, featuredImage: NSImage?) { + init(article: Article, showFeedName: Bool, feedName: String?, iconImage: IconImage?, showIcon: Bool, featuredImage: NSImage?) { self.title = ArticleStringFormatter.truncatedTitle(article) self.text = ArticleStringFormatter.truncatedSummary(article) @@ -38,8 +38,8 @@ struct TimelineCellData { self.showFeedName = showFeedName - self.showAvatar = showAvatar - self.avatar = avatar + self.showIcon = showIcon + self.iconImage = iconImage self.featuredImage = featuredImage self.read = article.status.read @@ -52,8 +52,8 @@ struct TimelineCellData { self.dateString = "" self.feedName = "" self.showFeedName = false - self.showAvatar = false - self.avatar = nil + self.showIcon = false + self.iconImage = nil self.featuredImage = nil self.read = true self.starred = false diff --git a/Mac/MainWindow/Timeline/Cell/TimelineCellLayout.swift b/Mac/MainWindow/Timeline/Cell/TimelineCellLayout.swift index 6e6430db2..7105c6f68 100644 --- a/Mac/MainWindow/Timeline/Cell/TimelineCellLayout.swift +++ b/Mac/MainWindow/Timeline/Cell/TimelineCellLayout.swift @@ -21,11 +21,11 @@ struct TimelineCellLayout { let textRect: NSRect let unreadIndicatorRect: NSRect let starRect: NSRect - let avatarImageRect: NSRect + let iconImageRect: NSRect let separatorRect: NSRect let paddingBottom: CGFloat - init(width: CGFloat, height: CGFloat, feedNameRect: NSRect, dateRect: NSRect, titleRect: NSRect, numberOfLinesForTitle: Int, summaryRect: NSRect, textRect: NSRect, unreadIndicatorRect: NSRect, starRect: NSRect, avatarImageRect: NSRect, separatorRect: NSRect, paddingBottom: CGFloat) { + init(width: CGFloat, height: CGFloat, feedNameRect: NSRect, dateRect: NSRect, titleRect: NSRect, numberOfLinesForTitle: Int, summaryRect: NSRect, textRect: NSRect, unreadIndicatorRect: NSRect, starRect: NSRect, iconImageRect: NSRect, separatorRect: NSRect, paddingBottom: CGFloat) { self.width = width self.feedNameRect = feedNameRect @@ -36,7 +36,7 @@ struct TimelineCellLayout { self.textRect = textRect self.unreadIndicatorRect = unreadIndicatorRect self.starRect = starRect - self.avatarImageRect = avatarImageRect + self.iconImageRect = iconImageRect self.separatorRect = separatorRect self.paddingBottom = paddingBottom @@ -44,16 +44,16 @@ struct TimelineCellLayout { self.height = height } else { - self.height = [feedNameRect, dateRect, titleRect, summaryRect, textRect, unreadIndicatorRect, avatarImageRect].maxY() + paddingBottom + self.height = [feedNameRect, dateRect, titleRect, summaryRect, textRect, unreadIndicatorRect, iconImageRect].maxY() + paddingBottom } } - init(width: CGFloat, height: CGFloat, cellData: TimelineCellData, appearance: TimelineCellAppearance, hasAvatar: Bool) { + init(width: CGFloat, height: CGFloat, cellData: TimelineCellData, appearance: TimelineCellAppearance, hasIcon: Bool) { // If height == 0.0, then height is calculated. - let showAvatar = cellData.showAvatar - var textBoxRect = TimelineCellLayout.rectForTextBox(appearance, cellData, showAvatar, width) + let showIcon = cellData.showIcon + var textBoxRect = TimelineCellLayout.rectForTextBox(appearance, cellData, showIcon, width) let (titleRect, numberOfLinesForTitle) = TimelineCellLayout.rectForTitle(textBoxRect, appearance, cellData) let summaryRect = numberOfLinesForTitle > 0 ? TimelineCellLayout.rectForSummary(textBoxRect, titleRect, numberOfLinesForTitle, appearance, cellData) : NSRect.zero @@ -72,19 +72,19 @@ struct TimelineCellLayout { let feedNameRect = TimelineCellLayout.rectForFeedName(textBoxRect, dateRect, appearance, cellData) textBoxRect.size.height = ceil([titleRect, summaryRect, textRect, dateRect, feedNameRect].maxY() - textBoxRect.origin.y) - let avatarImageRect = TimelineCellLayout.rectForAvatar(cellData, appearance, showAvatar, textBoxRect, width, height) + let iconImageRect = TimelineCellLayout.rectForIcon(cellData, appearance, showIcon, textBoxRect, width, height) let unreadIndicatorRect = TimelineCellLayout.rectForUnreadIndicator(appearance, textBoxRect) let starRect = TimelineCellLayout.rectForStar(appearance, unreadIndicatorRect) - let separatorRect = TimelineCellLayout.rectForSeparator(cellData, appearance, showAvatar ? avatarImageRect : titleRect, width, height) + let separatorRect = TimelineCellLayout.rectForSeparator(cellData, appearance, showIcon ? iconImageRect : titleRect, width, height) let paddingBottom = appearance.cellPadding.bottom - self.init(width: width, height: height, feedNameRect: feedNameRect, dateRect: dateRect, titleRect: titleRect, numberOfLinesForTitle: numberOfLinesForTitle, summaryRect: summaryRect, textRect: textRect, unreadIndicatorRect: unreadIndicatorRect, starRect: starRect, avatarImageRect: avatarImageRect, separatorRect: separatorRect, paddingBottom: paddingBottom) + self.init(width: width, height: height, feedNameRect: feedNameRect, dateRect: dateRect, titleRect: titleRect, numberOfLinesForTitle: numberOfLinesForTitle, summaryRect: summaryRect, textRect: textRect, unreadIndicatorRect: unreadIndicatorRect, starRect: starRect, iconImageRect: iconImageRect, separatorRect: separatorRect, paddingBottom: paddingBottom) } static func height(for width: CGFloat, cellData: TimelineCellData, appearance: TimelineCellAppearance) -> CGFloat { - let layout = TimelineCellLayout(width: width, height: 0.0, cellData: cellData, appearance: appearance, hasAvatar: true) + let layout = TimelineCellLayout(width: width, height: 0.0, cellData: cellData, appearance: appearance, hasIcon: true) return layout.height } } @@ -93,12 +93,12 @@ struct TimelineCellLayout { private extension TimelineCellLayout { - static func rectForTextBox(_ appearance: TimelineCellAppearance, _ cellData: TimelineCellData, _ showAvatar: Bool, _ width: CGFloat) -> NSRect { + static func rectForTextBox(_ appearance: TimelineCellAppearance, _ cellData: TimelineCellData, _ showIcon: Bool, _ width: CGFloat) -> NSRect { // Returned height is a placeholder. Not needed when this is calculated. - let avatarSpace = showAvatar ? appearance.avatarSize.width + appearance.avatarMarginRight : 0.0 - let textBoxOriginX = appearance.cellPadding.left + appearance.unreadCircleDimension + appearance.unreadCircleMarginRight + avatarSpace + let iconSpace = showIcon ? appearance.iconSize.width + appearance.iconMarginRight : 0.0 + let textBoxOriginX = appearance.cellPadding.left + appearance.unreadCircleDimension + appearance.unreadCircleMarginRight + iconSpace let textBoxMaxX = floor(width - appearance.cellPadding.right) let textBoxWidth = floor(textBoxMaxX - textBoxOriginX) let textBoxRect = NSRect(x: textBoxOriginX, y: appearance.cellPadding.top, width: textBoxWidth, height: 1000000) @@ -201,15 +201,15 @@ private extension TimelineCellLayout { return r } - static func rectForAvatar(_ cellData: TimelineCellData, _ appearance: TimelineCellAppearance, _ showAvatar: Bool, _ textBoxRect: NSRect, _ width: CGFloat, _ height: CGFloat) -> NSRect { + static func rectForIcon(_ cellData: TimelineCellData, _ appearance: TimelineCellAppearance, _ showIcon: Bool, _ textBoxRect: NSRect, _ width: CGFloat, _ height: CGFloat) -> NSRect { var r = NSRect.zero - if !showAvatar { + if !showIcon { return r } - r.size = appearance.avatarSize + r.size = appearance.iconSize r.origin.x = appearance.cellPadding.left + appearance.unreadCircleDimension + appearance.unreadCircleMarginRight - r.origin.y = textBoxRect.origin.y + appearance.avatarAdjustmentTop + r.origin.y = textBoxRect.origin.y + appearance.iconAdjustmentTop return r } diff --git a/Mac/MainWindow/Timeline/Cell/TimelineAvatarView.swift b/Mac/MainWindow/Timeline/Cell/TimelineIconView.swift similarity index 83% rename from Mac/MainWindow/Timeline/Cell/TimelineAvatarView.swift rename to Mac/MainWindow/Timeline/Cell/TimelineIconView.swift index e84ec4a08..f537c3124 100644 --- a/Mac/MainWindow/Timeline/Cell/TimelineAvatarView.swift +++ b/Mac/MainWindow/Timeline/Cell/TimelineIconView.swift @@ -1,5 +1,5 @@ // -// TimelineAvatarView.swift +// TimelineIconView.swift // NetNewsWire // // Created by Brent Simmons on 9/15/19. @@ -8,12 +8,12 @@ import AppKit -final class TimelineAvatarView: NSView { +final class TimelineIconView: NSView { - var image: NSImage? = nil { + var iconImage: IconImage? = nil { didSet { - if image !== oldValue { - imageView.image = image + if iconImage !== oldValue { + imageView.image = iconImage?.image needsDisplay = true needsLayout = true } @@ -36,8 +36,8 @@ final class TimelineAvatarView: NSView { return imageView.frame.size.height < bounds.size.height } - private static var lightBackgroundColor = AppAssets.avatarLightBackgroundColor - private static var darkBackgroundColor = AppAssets.avatarDarkBackgroundColor + private static var lightBackgroundColor = AppAssets.iconLightBackgroundColor + private static var darkBackgroundColor = AppAssets.iconDarkBackgroundColor override init(frame frameRect: NSRect) { super.init(frame: frameRect) @@ -71,13 +71,13 @@ final class TimelineAvatarView: NSView { return } - let color = NSApplication.shared.effectiveAppearance.isDarkMode ? TimelineAvatarView.darkBackgroundColor : TimelineAvatarView.lightBackgroundColor + let color = NSApplication.shared.effectiveAppearance.isDarkMode ? TimelineIconView.darkBackgroundColor : TimelineIconView.lightBackgroundColor color.set() dirtyRect.fill() } } -private extension TimelineAvatarView { +private extension TimelineIconView { func commonInit() { addSubview(imageView) @@ -85,7 +85,7 @@ private extension TimelineAvatarView { } func rectForImageView() -> NSRect { - guard let image = image else { + guard let image = iconImage?.image else { return NSRect.zero } diff --git a/Mac/MainWindow/Timeline/Cell/TimelineTableCellView.swift b/Mac/MainWindow/Timeline/Cell/TimelineTableCellView.swift index 22a1628dd..219e7bdc5 100644 --- a/Mac/MainWindow/Timeline/Cell/TimelineTableCellView.swift +++ b/Mac/MainWindow/Timeline/Cell/TimelineTableCellView.swift @@ -18,7 +18,7 @@ class TimelineTableCellView: NSTableCellView { private let dateView = TimelineTableCellView.singleLineTextField() private let feedNameView = TimelineTableCellView.singleLineTextField() - private lazy var avatarView = TimelineAvatarView() + private lazy var iconView = TimelineIconView() private let starView = TimelineTableCellView.imageView(with: AppAssets.timelineStar, scaling: .scaleNone) private let separatorView = TimelineTableCellView.separatorView() @@ -37,7 +37,7 @@ class TimelineTableCellView: NSTableCellView { didSet { if cellAppearance != oldValue { updateTextFieldFonts() - avatarView.layer?.cornerRadius = cellAppearance.avatarCornerRadius + iconView.layer?.cornerRadius = cellAppearance.iconCornerRadius needsLayout = true } } @@ -119,7 +119,7 @@ class TimelineTableCellView: NSTableCellView { dateView.rs_setFrameIfNotEqual(layoutRects.dateRect) unreadIndicatorView.rs_setFrameIfNotEqual(layoutRects.unreadIndicatorRect) feedNameView.rs_setFrameIfNotEqual(layoutRects.feedNameRect) - avatarView.rs_setFrameIfNotEqual(layoutRects.avatarImageRect) + iconView.rs_setFrameIfNotEqual(layoutRects.iconImageRect) starView.rs_setFrameIfNotEqual(layoutRects.starRect) separatorView.rs_setFrameIfNotEqual(layoutRects.separatorRect) } @@ -207,7 +207,7 @@ private extension TimelineTableCellView { addSubviewAtInit(unreadIndicatorView, hidden: true) addSubviewAtInit(dateView, hidden: false) addSubviewAtInit(feedNameView, hidden: true) - addSubviewAtInit(avatarView, hidden: true) + addSubviewAtInit(iconView, hidden: true) addSubviewAtInit(starView, hidden: true) addSubviewAtInit(separatorView, hidden: !AppDefaults.timelineShowsSeparators) @@ -216,7 +216,7 @@ private extension TimelineTableCellView { func updatedLayoutRects() -> TimelineCellLayout { - return TimelineCellLayout(width: bounds.width, height: bounds.height, cellData: cellData, appearance: cellAppearance, hasAvatar: avatarView.image != nil) + return TimelineCellLayout(width: bounds.width, height: bounds.height, cellData: cellData, appearance: cellAppearance, hasIcon: iconView.iconImage != nil) } func updateTitleView() { @@ -265,25 +265,25 @@ private extension TimelineTableCellView { showOrHideView(starView, !cellData.starred) } - func updateAvatar() { - guard let image = cellData.avatar, cellData.showAvatar else { - makeAvatarEmpty() + func updateIcon() { + guard let iconImage = cellData.iconImage, cellData.showIcon else { + makeIconEmpty() return } - showView(avatarView) - if avatarView.image !== image { - avatarView.image = image + showView(iconView) + if iconView.iconImage !== iconImage { + iconView.iconImage = iconImage needsLayout = true } } - func makeAvatarEmpty() { - if avatarView.image != nil { - avatarView.image = nil + func makeIconEmpty() { + if iconView.iconImage != nil { + iconView.iconImage = nil needsLayout = true } - hideView(avatarView) + hideView(iconView) } func hideView(_ view: NSView) { @@ -310,7 +310,7 @@ private extension TimelineTableCellView { updateFeedNameView() updateUnreadIndicator() updateStarView() - updateAvatar() + updateIcon() } } diff --git a/Mac/MainWindow/Timeline/TimelineViewController.swift b/Mac/MainWindow/Timeline/TimelineViewController.swift index 422476b9f..9f4bba8b1 100644 --- a/Mac/MainWindow/Timeline/TimelineViewController.swift +++ b/Mac/MainWindow/Timeline/TimelineViewController.swift @@ -79,7 +79,7 @@ final class TimelineViewController: NSViewController, UndoableCommandRunner, Unr reloadVisibleCells() return } - updateShowAvatars() + updateShowIcons() articleRowMap = [String: Int]() tableView.reloadData() } @@ -98,18 +98,18 @@ final class TimelineViewController: NSViewController, UndoableCommandRunner, Unr private let fetchRequestQueue = FetchRequestQueue() private var articleRowMap = [String: Int]() // articleID: rowIndex private var cellAppearance: TimelineCellAppearance! - private var cellAppearanceWithAvatar: TimelineCellAppearance! + private var cellAppearanceWithIcon: TimelineCellAppearance! private var showFeedNames = false { didSet { if showFeedNames != oldValue { - updateShowAvatars() + updateShowIcons() updateTableViewRowHeight() reloadVisibleCells() } } } - private var showAvatars = false + private var showIcons = false private var rowHeightWithFeedName: CGFloat = 0.0 private var rowHeightWithoutFeedName: CGFloat = 0.0 @@ -156,8 +156,8 @@ final class TimelineViewController: NSViewController, UndoableCommandRunner, Unr } override func viewDidLoad() { - cellAppearance = TimelineCellAppearance(showAvatar: false, fontSize: fontSize) - cellAppearanceWithAvatar = TimelineCellAppearance(showAvatar: true, fontSize: fontSize) + cellAppearance = TimelineCellAppearance(showIcon: false, fontSize: fontSize) + cellAppearanceWithIcon = TimelineCellAppearance(showIcon: true, fontSize: fontSize) updateRowHeights() tableView.rowHeight = currentRowHeight @@ -438,7 +438,7 @@ final class TimelineViewController: NSViewController, UndoableCommandRunner, Unr } @objc func feedIconDidBecomeAvailable(_ note: Notification) { - guard showAvatars, let feed = note.userInfo?[UserInfoKey.feed] as? Feed else { + guard showIcons, let feed = note.userInfo?[UserInfoKey.feed] as? Feed else { return } let indexesToReload = tableView.indexesOfAvailableRowsPassingTest { (row) -> Bool in @@ -453,7 +453,7 @@ final class TimelineViewController: NSViewController, UndoableCommandRunner, Unr } @objc func avatarDidBecomeAvailable(_ note: Notification) { - guard showAvatars, let avatarURL = note.userInfo?[UserInfoKey.url] as? String else { + guard showIcons, let avatarURL = note.userInfo?[UserInfoKey.url] as? String else { return } @@ -474,7 +474,7 @@ final class TimelineViewController: NSViewController, UndoableCommandRunner, Unr } @objc func faviconDidBecomeAvailable(_ note: Notification) { - if showAvatars { + if showIcons { queueReloadAvailableCells() } } @@ -570,7 +570,7 @@ final class TimelineViewController: NSViewController, UndoableCommandRunner, Unr let status = ArticleStatus(articleID: prototypeID, read: false, starred: false, userDeleted: false, dateArrived: Date()) let prototypeArticle = Article(accountID: prototypeID, articleID: prototypeID, feedID: prototypeID, uniqueID: prototypeID, title: longTitle, contentHTML: nil, contentText: nil, url: nil, externalURL: nil, summary: nil, imageURL: nil, bannerImageURL: nil, datePublished: nil, dateModified: nil, authors: nil, attachments: nil, status: status) - let prototypeCellData = TimelineCellData(article: prototypeArticle, showFeedName: showingFeedNames, feedName: "Prototype Feed Name", avatar: nil, showAvatar: false, featuredImage: nil) + let prototypeCellData = TimelineCellData(article: prototypeArticle, showFeedName: showingFeedNames, feedName: "Prototype Feed Name", iconImage: nil, showIcon: false, featuredImage: nil) let height = TimelineCellLayout.height(for: 100, cellData: prototypeCellData, appearance: cellAppearance) return height } @@ -674,7 +674,7 @@ extension TimelineViewController: NSTableViewDelegate { func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? { func configure(_ cell: TimelineTableCellView) { - cell.cellAppearance = showAvatars ? cellAppearanceWithAvatar : cellAppearance + cell.cellAppearance = showIcons ? cellAppearanceWithIcon : cellAppearance if let article = articles.articleAtRow(row) { configureTimelineCell(cell, article: article) } @@ -716,12 +716,12 @@ extension TimelineViewController: NSTableViewDelegate { private func configureTimelineCell(_ cell: TimelineTableCellView, article: Article) { cell.objectValue = article - let avatar = article.avatarImage() - cell.cellData = TimelineCellData(article: article, showFeedName: showFeedNames, feedName: article.feed?.nameForDisplay, avatar: avatar, showAvatar: showAvatars, featuredImage: nil) + let iconImage = article.iconImage() + cell.cellData = TimelineCellData(article: article, showFeedName: showFeedNames, feedName: article.feed?.nameForDisplay, iconImage: iconImage, showIcon: showIcons, featuredImage: nil) } - private func avatarFor(_ article: Article) -> NSImage? { - if !showAvatars { + private func iconFor(_ article: Article) -> IconImage? { + if !showIcons { return nil } @@ -741,14 +741,14 @@ extension TimelineViewController: NSTableViewDelegate { return feedIcon } - if let favicon = appDelegate.faviconDownloader.faviconAsAvatar(for: feed) { + if let favicon = appDelegate.faviconDownloader.faviconAsIcon(for: feed) { return favicon } return FaviconGenerator.favicon(feed) } - private func avatarForAuthor(_ author: Author) -> NSImage? { + private func avatarForAuthor(_ author: Author) -> IconImage? { return appDelegate.authorAvatarDownloader.image(for: author) } @@ -842,9 +842,9 @@ private extension TimelineViewController { tableView.rowHeight = currentRowHeight } - func updateShowAvatars() { + func updateShowIcons() { if showFeedNames { - self.showAvatars = true + self.showIcons = true return } @@ -852,14 +852,14 @@ private extension TimelineViewController { if let authors = article.authors { for author in authors { if author.avatarURL != nil { - self.showAvatars = true + self.showIcons = true return } } } } - self.showAvatars = false + self.showIcons = false } func emptyTheTimeline() { @@ -935,8 +935,8 @@ private extension TimelineViewController { // MARK: - Appearance Change private func fontSizeDidChange() { - cellAppearance = TimelineCellAppearance(showAvatar: false, fontSize: fontSize) - cellAppearanceWithAvatar = TimelineCellAppearance(showAvatar: true, fontSize: fontSize) + cellAppearance = TimelineCellAppearance(showIcon: false, fontSize: fontSize) + cellAppearanceWithIcon = TimelineCellAppearance(showIcon: true, fontSize: fontSize) updateRowHeights() performBlockAndRestoreSelection { tableView.reloadData() diff --git a/Mac/Resources/Assets.xcassets/avatarDarkBackgroundColor.colorset/Contents.json b/Mac/Resources/Assets.xcassets/iconDarkBackgroundColor.colorset/Contents.json similarity index 100% rename from Mac/Resources/Assets.xcassets/avatarDarkBackgroundColor.colorset/Contents.json rename to Mac/Resources/Assets.xcassets/iconDarkBackgroundColor.colorset/Contents.json diff --git a/Mac/Resources/Assets.xcassets/avatarLightBackgroundColor.colorset/Contents.json b/Mac/Resources/Assets.xcassets/iconLightBackgroundColor.colorset/Contents.json similarity index 100% rename from Mac/Resources/Assets.xcassets/avatarLightBackgroundColor.colorset/Contents.json rename to Mac/Resources/Assets.xcassets/iconLightBackgroundColor.colorset/Contents.json diff --git a/NetNewsWire.xcodeproj/project.pbxproj b/NetNewsWire.xcodeproj/project.pbxproj index 9619b3fdd..a16322c6a 100644 --- a/NetNewsWire.xcodeproj/project.pbxproj +++ b/NetNewsWire.xcodeproj/project.pbxproj @@ -89,6 +89,8 @@ 516A09402361240900EAE89B /* Account.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 516A093F2361240900EAE89B /* Account.storyboard */; }; 516A09422361248000EAE89B /* Inspector.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 516A09412361248000EAE89B /* Inspector.storyboard */; }; 516AE9B32371C372007DEEAA /* MasterFeedTableViewSectionHeaderLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = 516AE9B22371C372007DEEAA /* MasterFeedTableViewSectionHeaderLayout.swift */; }; + 516AE9DF2372269A007DEEAA /* IconImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 516AE9DE2372269A007DEEAA /* IconImage.swift */; }; + 516AE9E02372269A007DEEAA /* IconImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 516AE9DE2372269A007DEEAA /* IconImage.swift */; }; 51707439232AA97100A461A3 /* ShareFolderPickerController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51707438232AA97100A461A3 /* ShareFolderPickerController.swift */; }; 5170743A232AABFC00A461A3 /* FlattenedAccountFolderPickerData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51C452812265093600C03939 /* FlattenedAccountFolderPickerData.swift */; }; 517630042336215100E15FFF /* main.js in Resources */ = {isa = PBXBuildFile; fileRef = 517630032336215100E15FFF /* main.js */; }; @@ -120,7 +122,7 @@ 51A1699F235E10D700EB091F /* AboutViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51A16995235E10D600EB091F /* AboutViewController.swift */; }; 51A169A0235E10D700EB091F /* FeedbinAccountViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51A16996235E10D700EB091F /* FeedbinAccountViewController.swift */; }; 51AF460E232488C6001742EF /* Account-Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51AF460D232488C6001742EF /* Account-Extensions.swift */; }; - 51B62E68233186730085F949 /* AvatarView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51B62E67233186730085F949 /* AvatarView.swift */; }; + 51B62E68233186730085F949 /* IconView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51B62E67233186730085F949 /* IconView.swift */; }; 51BB7C272335A8E5008E8144 /* ArticleActivityItemSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51BB7C262335A8E5008E8144 /* ArticleActivityItemSource.swift */; }; 51BB7C312335ACDE008E8144 /* page.html in Resources */ = {isa = PBXBuildFile; fileRef = 51BB7C302335ACDE008E8144 /* page.html */; }; 51C451A9226377C200C03939 /* ArticlesDatabase.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8407167F2262A61100344432 /* ArticlesDatabase.framework */; }; @@ -232,7 +234,6 @@ 51FA73AA2332C2FD0090D516 /* ArticleExtractorConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51FA73A92332C2FD0090D516 /* ArticleExtractorConfig.swift */; }; 51FA73AB2332C2FD0090D516 /* ArticleExtractorConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51FA73A92332C2FD0090D516 /* ArticleExtractorConfig.swift */; }; 51FA73B72332D5F70090D516 /* ArticleExtractorButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51FA73B62332D5F70090D516 /* ArticleExtractorButton.swift */; }; - 51FD40C72341555A00880194 /* UIImage-Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51FD40BD2341555600880194 /* UIImage-Extensions.swift */; }; 51FD413B2342BD0500880194 /* MasterTimelineUnreadCountView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51FD413A2342BD0500880194 /* MasterTimelineUnreadCountView.swift */; }; 51FE10032345529D0056195D /* UserNotificationManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51FE10022345529D0056195D /* UserNotificationManager.swift */; }; 51FE10042345529D0056195D /* UserNotificationManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51FE10022345529D0056195D /* UserNotificationManager.swift */; }; @@ -249,7 +250,7 @@ 6581C74220CED60100F4AD34 /* ToolbarItemIcon.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 6581C74120CED60100F4AD34 /* ToolbarItemIcon.pdf */; }; 65ED3FB7235DEF6C0081F399 /* ArticleArray.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84F204DF1FAACBB30076E152 /* ArticleArray.swift */; }; 65ED3FB8235DEF6C0081F399 /* CrashReporter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 848B937121C8C5540038DC0D /* CrashReporter.swift */; }; - 65ED3FB9235DEF6C0081F399 /* TimelineAvatarView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 847CD6C9232F4CBF00FAC46D /* TimelineAvatarView.swift */; }; + 65ED3FB9235DEF6C0081F399 /* TimelineIconView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 847CD6C9232F4CBF00FAC46D /* TimelineIconView.swift */; }; 65ED3FBA235DEF6C0081F399 /* ArticleExtractorConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51FA73A92332C2FD0090D516 /* ArticleExtractorConfig.swift */; }; 65ED3FBB235DEF6C0081F399 /* InspectorWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84BBB12C20142A4700F054F5 /* InspectorWindowController.swift */; }; 65ED3FBC235DEF6C0081F399 /* ColorHash.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51EF0F78227716380050506E /* ColorHash.swift */; }; @@ -486,7 +487,7 @@ 84702AA41FA27AC0006B8943 /* MarkStatusCommand.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84702AA31FA27AC0006B8943 /* MarkStatusCommand.swift */; }; 8472058120142E8900AD578B /* FeedInspectorViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8472058020142E8900AD578B /* FeedInspectorViewController.swift */; }; 8477ACBE22238E9500DF7F37 /* SearchFeedDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8477ACBD22238E9500DF7F37 /* SearchFeedDelegate.swift */; }; - 847CD6CA232F4CBF00FAC46D /* TimelineAvatarView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 847CD6C9232F4CBF00FAC46D /* TimelineAvatarView.swift */; }; + 847CD6CA232F4CBF00FAC46D /* TimelineIconView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 847CD6C9232F4CBF00FAC46D /* TimelineIconView.swift */; }; 847E64A02262783000E00365 /* NSAppleEventDescriptor+UserRecordFields.swift in Sources */ = {isa = PBXBuildFile; fileRef = 847E64942262782F00E00365 /* NSAppleEventDescriptor+UserRecordFields.swift */; }; 848362FD2262A30800DA1D35 /* styleSheet.css in Resources */ = {isa = PBXBuildFile; fileRef = 848362FC2262A30800DA1D35 /* styleSheet.css */; }; 848362FF2262A30E00DA1D35 /* template.html in Resources */ = {isa = PBXBuildFile; fileRef = 848362FE2262A30E00DA1D35 /* template.html */; }; @@ -1253,6 +1254,7 @@ 516A093F2361240900EAE89B /* Account.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = Account.storyboard; sourceTree = ""; }; 516A09412361248000EAE89B /* Inspector.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = Inspector.storyboard; sourceTree = ""; }; 516AE9B22371C372007DEEAA /* MasterFeedTableViewSectionHeaderLayout.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MasterFeedTableViewSectionHeaderLayout.swift; sourceTree = ""; }; + 516AE9DE2372269A007DEEAA /* IconImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IconImage.swift; sourceTree = ""; }; 51707438232AA97100A461A3 /* ShareFolderPickerController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShareFolderPickerController.swift; sourceTree = ""; }; 517630032336215100E15FFF /* main.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; path = main.js; sourceTree = ""; }; 517630222336657E00E15FFF /* ArticleViewControllerWebViewProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ArticleViewControllerWebViewProvider.swift; sourceTree = ""; }; @@ -1280,7 +1282,7 @@ 51A16995235E10D600EB091F /* AboutViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AboutViewController.swift; sourceTree = ""; }; 51A16996235E10D700EB091F /* FeedbinAccountViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FeedbinAccountViewController.swift; sourceTree = ""; }; 51AF460D232488C6001742EF /* Account-Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Account-Extensions.swift"; sourceTree = ""; }; - 51B62E67233186730085F949 /* AvatarView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AvatarView.swift; sourceTree = ""; }; + 51B62E67233186730085F949 /* IconView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IconView.swift; sourceTree = ""; }; 51BB7C262335A8E5008E8144 /* ArticleActivityItemSource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ArticleActivityItemSource.swift; sourceTree = ""; }; 51BB7C302335ACDE008E8144 /* page.html */ = {isa = PBXFileReference; lastKnownFileType = text.html; path = page.html; sourceTree = ""; }; 51C4524E226506F400C03939 /* UIStoryboard-Extensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIStoryboard-Extensions.swift"; sourceTree = ""; }; @@ -1336,7 +1338,6 @@ 51FA73A62332BE880090D516 /* ExtractedArticle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExtractedArticle.swift; sourceTree = ""; }; 51FA73A92332C2FD0090D516 /* ArticleExtractorConfig.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ArticleExtractorConfig.swift; sourceTree = ""; }; 51FA73B62332D5F70090D516 /* ArticleExtractorButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ArticleExtractorButton.swift; sourceTree = ""; }; - 51FD40BD2341555600880194 /* UIImage-Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIImage-Extensions.swift"; sourceTree = ""; }; 51FD413A2342BD0500880194 /* MasterTimelineUnreadCountView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MasterTimelineUnreadCountView.swift; sourceTree = ""; }; 51FE10022345529D0056195D /* UserNotificationManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserNotificationManager.swift; sourceTree = ""; }; 51FFF0C3235EE8E5002762AA /* VibrantButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VibrantButton.swift; sourceTree = ""; }; @@ -1402,7 +1403,7 @@ 8472058020142E8900AD578B /* FeedInspectorViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FeedInspectorViewController.swift; sourceTree = ""; }; 847752FE2008879500D93690 /* CoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreServices.framework; path = System/Library/Frameworks/CoreServices.framework; sourceTree = SDKROOT; }; 8477ACBD22238E9500DF7F37 /* SearchFeedDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchFeedDelegate.swift; sourceTree = ""; }; - 847CD6C9232F4CBF00FAC46D /* TimelineAvatarView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineAvatarView.swift; sourceTree = ""; }; + 847CD6C9232F4CBF00FAC46D /* TimelineIconView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineIconView.swift; sourceTree = ""; }; 847E64942262782F00E00365 /* NSAppleEventDescriptor+UserRecordFields.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSAppleEventDescriptor+UserRecordFields.swift"; sourceTree = ""; }; 848362FC2262A30800DA1D35 /* styleSheet.css */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.css; path = styleSheet.css; sourceTree = ""; }; 848362FE2262A30E00DA1D35 /* template.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = template.html; sourceTree = ""; }; @@ -1845,7 +1846,6 @@ 51934CC1230F5963006127BE /* ThemedNavigationController.swift */, 51F85BF82274AA7B00C787DC /* UIBarButtonItem-Extensions.swift */, 51F85BF622749FA100C787DC /* UIFont-Extensions.swift */, - 51FD40BD2341555600880194 /* UIImage-Extensions.swift */, 512E092B2268B25500BDCFDD /* UISplitViewController-Extensions.swift */, 51C4524E226506F400C03939 /* UIStoryboard-Extensions.swift */, 51FFF0C3235EE8E5002762AA /* VibrantButton.swift */, @@ -2246,7 +2246,7 @@ 84E185C2203BB12600F69BFA /* MultilineTextFieldSizer.swift */, 849A97711ED9EC04007D329B /* TimelineCellData.swift */, 849A97751ED9EC04007D329B /* UnreadIndicatorView.swift */, - 847CD6C9232F4CBF00FAC46D /* TimelineAvatarView.swift */, + 847CD6C9232F4CBF00FAC46D /* TimelineIconView.swift */, ); path = Cell; sourceTree = ""; @@ -2283,6 +2283,7 @@ 849A97971ED9EFAA007D329B /* Node-Extensions.swift */, 8405DD9B22153BD7008CE1BF /* NSView-Extensions.swift */, 51126DA3225FDE2F00722696 /* RSImage-Extensions.swift */, + 516AE9DE2372269A007DEEAA /* IconImage.swift */, ); path = Extensions; sourceTree = ""; @@ -2537,7 +2538,7 @@ 51C45255226507D200C03939 /* AppDefaults.swift */, 51E3EB3C229AB08300645299 /* ErrorHandler.swift */, 51BB7C262335A8E5008E8144 /* ArticleActivityItemSource.swift */, - 51B62E67233186730085F949 /* AvatarView.swift */, + 51B62E67233186730085F949 /* IconView.swift */, 51C4525D226508F600C03939 /* MasterFeed */, 51C4526D2265091600C03939 /* MasterTimeline */, 51C4527D2265092C00C03939 /* Article */, @@ -3723,7 +3724,7 @@ files = ( 65ED3FB7235DEF6C0081F399 /* ArticleArray.swift in Sources */, 65ED3FB8235DEF6C0081F399 /* CrashReporter.swift in Sources */, - 65ED3FB9235DEF6C0081F399 /* TimelineAvatarView.swift in Sources */, + 65ED3FB9235DEF6C0081F399 /* TimelineIconView.swift in Sources */, 65ED3FBA235DEF6C0081F399 /* ArticleExtractorConfig.swift in Sources */, 65ED3FBB235DEF6C0081F399 /* InspectorWindowController.swift in Sources */, 65ED3FBC235DEF6C0081F399 /* ColorHash.swift in Sources */, @@ -3886,7 +3887,7 @@ 5186A635235EF3A800C97195 /* VibrantLabel.swift in Sources */, 51F85BF92274AA7B00C787DC /* UIBarButtonItem-Extensions.swift in Sources */, 512AF9DF236F074B0066F8BE /* FeedInspectorLabelView.swift in Sources */, - 51B62E68233186730085F949 /* AvatarView.swift in Sources */, + 51B62E68233186730085F949 /* IconView.swift in Sources */, 51C45296226509D300C03939 /* OPMLExporter.swift in Sources */, 51C45291226509C800C03939 /* SmartFeed.swift in Sources */, 51C452A722650A3D00C03939 /* RSImage-Extensions.swift in Sources */, @@ -3914,7 +3915,6 @@ 51C452852265093600C03939 /* FlattenedAccountFolderPickerData.swift in Sources */, 51C4526B226508F600C03939 /* MasterFeedViewController.swift in Sources */, 5126EE97226CB48A00C22AFC /* SceneCoordinator.swift in Sources */, - 51FD40C72341555A00880194 /* UIImage-Extensions.swift in Sources */, 84CAFCB022BC8C35007694F0 /* FetchRequestOperation.swift in Sources */, 51EF0F77227716200050506E /* FaviconGenerator.swift in Sources */, 51938DF3231AFC660055A1A0 /* SearchTimelineFeedDelegate.swift in Sources */, @@ -3977,6 +3977,7 @@ 51C4529B22650A1000C03939 /* FaviconDownloader.swift in Sources */, 84DEE56622C32CA4005FC42C /* SmartFeedDelegate.swift in Sources */, 512E09012268907400BDCFDD /* MasterFeedTableViewSectionHeader.swift in Sources */, + 516AE9E02372269A007DEEAA /* IconImage.swift in Sources */, 519D740623243CC0008BB345 /* RefreshInterval-Extensions.swift in Sources */, 51C45268226508F600C03939 /* MasterFeedUnreadCountView.swift in Sources */, 5183CCD0226E1E880010922C /* NonIntrinsicLabel.swift in Sources */, @@ -4006,7 +4007,7 @@ files = ( 84F204E01FAACBB30076E152 /* ArticleArray.swift in Sources */, 848B937221C8C5540038DC0D /* CrashReporter.swift in Sources */, - 847CD6CA232F4CBF00FAC46D /* TimelineAvatarView.swift in Sources */, + 847CD6CA232F4CBF00FAC46D /* TimelineIconView.swift in Sources */, 51FA73AA2332C2FD0090D516 /* ArticleExtractorConfig.swift in Sources */, 84BBB12E20142A4700F054F5 /* InspectorWindowController.swift in Sources */, 51EF0F7A22771B890050506E /* ColorHash.swift in Sources */, @@ -4022,6 +4023,7 @@ 84F2D53A1FC2308B00998D64 /* UnreadFeed.swift in Sources */, 513228FB233037630033D4ED /* Reachability.swift in Sources */, 845A29221FC9251E007B49E3 /* SidebarCellLayout.swift in Sources */, + 516AE9DF2372269A007DEEAA /* IconImage.swift in Sources */, 84AD1EBA2031649C00BC20B7 /* SmartFeedPasteboardWriter.swift in Sources */, 849C78922362AB04009A71E4 /* ExportOPMLWindowController.swift in Sources */, 84CC88181FE59CBF00644329 /* SmartFeedsController.swift in Sources */, diff --git a/Shared/Activity/ActivityManager.swift b/Shared/Activity/ActivityManager.swift index 16cf6df2c..2c871b48e 100644 --- a/Shared/Activity/ActivityManager.swift +++ b/Shared/Activity/ActivityManager.swift @@ -226,8 +226,8 @@ private extension ActivityManager { attributeSet.keywords = makeKeywords(article) attributeSet.relatedUniqueIdentifier = ActivityManager.identifer(for: article) - if let image = article.avatarImage() { - attributeSet.thumbnailData = image.pngData() + if let iconImage = article.iconImage() { + attributeSet.thumbnailData = iconImage.image.pngData() } readingActivity?.contentAttributeSet = attributeSet @@ -252,18 +252,10 @@ private extension ActivityManager { attributeSet.title = feed.nameForDisplay attributeSet.keywords = makeKeywords(feed.nameForDisplay) attributeSet.relatedUniqueIdentifier = ActivityManager.identifer(for: feed) - if let image = appDelegate.feedIconDownloader.icon(for: feed) { - #if os(iOS) - attributeSet.thumbnailData = image.pngData() - #else - attributeSet.thumbnailData = image.tiffRepresentation - #endif - } else if let image = appDelegate.faviconDownloader.faviconAsAvatar(for: feed) { - #if os(iOS) - attributeSet.thumbnailData = image.pngData() - #else - attributeSet.thumbnailData = image.tiffRepresentation - #endif + if let iconImage = appDelegate.feedIconDownloader.icon(for: feed) { + attributeSet.thumbnailData = iconImage.image.dataRepresentation() + } else if let iconImage = appDelegate.faviconDownloader.faviconAsIcon(for: feed) { + attributeSet.thumbnailData = iconImage.image.dataRepresentation() } selectingActivity!.contentAttributeSet = attributeSet diff --git a/Shared/Article Rendering/ArticleRenderer.swift b/Shared/Article Rendering/ArticleRenderer.swift index 37f90a440..a4990719e 100644 --- a/Shared/Article Rendering/ArticleRenderer.swift +++ b/Shared/Article Rendering/ArticleRenderer.swift @@ -202,9 +202,9 @@ private extension ArticleRenderer { return cachedImgTag } - if let favicon = appDelegate.faviconDownloader.faviconAsAvatar(for: feed) { - if let s = base64String(forImage: favicon) { - var dimension = min(favicon.size.height, CGFloat(ArticleRenderer.avatarDimension)) // Assuming square images. + if let iconImage = appDelegate.faviconDownloader.faviconAsIcon(for: feed) { + if let s = base64String(forImage: iconImage.image) { + var dimension = min(iconImage.image.size.height, CGFloat(ArticleRenderer.avatarDimension)) // Assuming square images. dimension = max(dimension, 16) // Some favicons say they’re < 16. Force them larger. if dimension >= CGFloat(ArticleRenderer.avatarDimension) * 0.8 { //Close enough to scale up. dimension = CGFloat(ArticleRenderer.avatarDimension) @@ -231,8 +231,8 @@ private extension ArticleRenderer { return cachedImgTag } - if let icon = appDelegate.feedIconDownloader.icon(for: feed) { - if let s = base64String(forImage: icon) { + if let iconImage = appDelegate.feedIconDownloader.icon(for: feed) { + if let s = base64String(forImage: iconImage.image) { #if os(macOS) let imgTag = "" #else diff --git a/Shared/Data/ArticleUtilities.swift b/Shared/Data/ArticleUtilities.swift index e3b2eb88e..4ca5c8250 100644 --- a/Shared/Data/ArticleUtilities.swift +++ b/Shared/Data/ArticleUtilities.swift @@ -64,7 +64,7 @@ extension Article { return datePublished ?? dateModified ?? status.dateArrived } - func avatarImage() -> RSImage? { + func iconImage() -> IconImage? { if let authors = authors { for author in authors { if let image = appDelegate.authorAvatarDownloader.image(for: author) { @@ -82,7 +82,7 @@ extension Article { return feedIconImage } - if let faviconImage = appDelegate.faviconDownloader.faviconAsAvatar(for: feed) { + if let faviconImage = appDelegate.faviconDownloader.faviconAsIcon(for: feed) { return faviconImage } diff --git a/Shared/Data/SmallIconProvider.swift b/Shared/Data/SmallIconProvider.swift index 96cac60a4..968a9767c 100644 --- a/Shared/Data/SmallIconProvider.swift +++ b/Shared/Data/SmallIconProvider.swift @@ -13,14 +13,14 @@ import RSCore protocol SmallIconProvider { - var smallIcon: RSImage? { get } + var smallIcon: IconImage? { get } } extension Feed: SmallIconProvider { - var smallIcon: RSImage? { - if let image = appDelegate.faviconDownloader.favicon(for: self) { - return image + var smallIcon: IconImage? { + if let iconImage = appDelegate.faviconDownloader.favicon(for: self) { + return iconImage } #if os(macOS) return AppAssets.genericFeedImage @@ -31,13 +31,7 @@ extension Feed: SmallIconProvider { } extension Folder: SmallIconProvider { - - var smallIcon: RSImage? { - #if os(macOS) - return RSImage(named: NSImage.folderName) - #else - return AppAssets.masterFolderImage - #endif + var smallIcon: IconImage? { + AppAssets.masterFolderImage } - } diff --git a/iOS/UIKit Extensions/UIImage-Extensions.swift b/Shared/Extensions/IconImage.swift similarity index 58% rename from iOS/UIKit Extensions/UIImage-Extensions.swift rename to Shared/Extensions/IconImage.swift index 0875d2961..c02d32926 100644 --- a/iOS/UIKit Extensions/UIImage-Extensions.swift +++ b/Shared/Extensions/IconImage.swift @@ -1,12 +1,41 @@ // -// UIImage-Extensions.swift +// IconImage.swift // NetNewsWire // -// Created by Maurice Parker on 9/29/19. +// Created by Maurice Parker on 11/5/19. // Copyright © 2019 Ranchero Software. All rights reserved. // -import UIKit +import Foundation +import RSCore + +final class IconImage { + + lazy var isDark: Bool = { + return image.isDark() + }() + + let image: RSImage + + init(_ image: RSImage) { + self.image = image + } + +} + +#if os(macOS) + extension NSImage { + func isDark() -> Bool { + return self.cgImage(forProposedRect: nil, context: nil, hints: nil)?.isDark() ?? false + } + } +#else + extension UIImage { + func isDark() -> Bool { + return self.cgImage?.isDark() ?? false + } + } +#endif extension CGImage { @@ -35,9 +64,3 @@ extension CGImage { } } - -extension UIImage { - func isDark() -> Bool { - return self.cgImage?.isDark() ?? false - } -} diff --git a/Shared/Extensions/RSImage-Extensions.swift b/Shared/Extensions/RSImage-Extensions.swift index 985fb7d36..505079fbb 100644 --- a/Shared/Extensions/RSImage-Extensions.swift +++ b/Shared/Extensions/RSImage-Extensions.swift @@ -11,19 +11,19 @@ import RSCore extension RSImage { - static let avatarSize = 48 + static let maxIconSize = 48 - static func scaledForAvatar(_ data: Data, imageResultBlock: @escaping (RSImage?) -> Void) { + static func scaledForIcon(_ data: Data, imageResultBlock: @escaping (RSImage?) -> Void) { DispatchQueue.global(qos: .default).async { - let image = RSImage.scaledForAvatar(data) + let image = RSImage.scaledForIcon(data) DispatchQueue.main.async { imageResultBlock(image) } } } - static func scaledForAvatar(_ data: Data) -> RSImage? { - let scaledMaxPixelSize = Int(ceil(CGFloat(RSImage.avatarSize) * RSScreen.mainScreenScale)) + static func scaledForIcon(_ data: Data) -> RSImage? { + let scaledMaxPixelSize = Int(ceil(CGFloat(RSImage.maxIconSize) * RSScreen.mainScreenScale)) guard var cgImage = RSImage.scaleImage(data, maxPixelSize: scaledMaxPixelSize) else { return nil } diff --git a/Shared/Favicons/FaviconDownloader.swift b/Shared/Favicons/FaviconDownloader.swift index 8605c29cd..610caf94b 100644 --- a/Shared/Favicons/FaviconDownloader.swift +++ b/Shared/Favicons/FaviconDownloader.swift @@ -41,7 +41,7 @@ final class FaviconDownloader { } private let queue: DispatchQueue - private var cache = [Feed: RSImage]() // faviconURL: RSImage + private var cache = [Feed: IconImage]() // faviconURL: RSImage struct UserInfoKey { static let faviconURL = "faviconURL" @@ -64,10 +64,10 @@ final class FaviconDownloader { // MARK: - API func resetCache() { - cache = [Feed: RSImage]() + cache = [Feed: IconImage]() } - func favicon(for feed: Feed) -> RSImage? { + func favicon(for feed: Feed) -> IconImage? { assert(Thread.isMainThread) @@ -89,29 +89,30 @@ final class FaviconDownloader { return nil } - func faviconAsAvatar(for feed: Feed) -> RSImage? { + func faviconAsIcon(for feed: Feed) -> IconImage? { if let image = cache[feed] { return image } - if let image = favicon(for: feed), let imageData = image.dataRepresentation() { - if let scaledImage = RSImage.scaledForAvatar(imageData) { - cache[feed] = scaledImage - return scaledImage + if let iconImage = favicon(for: feed), let imageData = iconImage.image.dataRepresentation() { + if let scaledImage = RSImage.scaledForIcon(imageData) { + let scaledIconImage = IconImage(scaledImage) + cache[feed] = scaledIconImage + return scaledIconImage } } return nil } - func favicon(with faviconURL: String) -> RSImage? { + func favicon(with faviconURL: String) -> IconImage? { let downloader = faviconDownloader(withURL: faviconURL) - return downloader.image + return downloader.iconImage } - func favicon(withHomePageURL homePageURL: String) -> RSImage? { + func favicon(withHomePageURL homePageURL: String) -> IconImage? { let url = homePageURL.rs_normalizedURL() if homePageURLsWithNoFaviconURLCache.contains(url) { @@ -144,7 +145,7 @@ final class FaviconDownloader { guard let singleFaviconDownloader = note.object as? SingleFaviconDownloader else { return } - guard let _ = singleFaviconDownloader.image else { + guard let _ = singleFaviconDownloader.iconImage else { return } diff --git a/Shared/Favicons/FaviconGenerator.swift b/Shared/Favicons/FaviconGenerator.swift index 1fdef31ee..787bf56db 100644 --- a/Shared/Favicons/FaviconGenerator.swift +++ b/Shared/Favicons/FaviconGenerator.swift @@ -12,9 +12,9 @@ import Account final class FaviconGenerator { - private static var faviconGeneratorCache = [String: RSImage]() // feedURL: RSImage + private static var faviconGeneratorCache = [String: IconImage]() // feedURL: RSImage - static func favicon(_ feed: Feed) -> RSImage { + static func favicon(_ feed: Feed) -> IconImage { if let favicon = FaviconGenerator.faviconGeneratorCache[feed.url] { return favicon @@ -22,10 +22,11 @@ final class FaviconGenerator { let colorHash = ColorHash(feed.url) if let favicon = AppAssets.faviconTemplateImage.maskWithColor(color: colorHash.color.cgColor) { - FaviconGenerator.faviconGeneratorCache[feed.url] = favicon - return favicon + let iconImage = IconImage(favicon) + FaviconGenerator.faviconGeneratorCache[feed.url] = iconImage + return iconImage } else { - return AppAssets.faviconTemplateImage + return IconImage(AppAssets.faviconTemplateImage) } } diff --git a/Shared/Favicons/SingleFaviconDownloader.swift b/Shared/Favicons/SingleFaviconDownloader.swift index 57730a903..55d9f96ff 100644 --- a/Shared/Favicons/SingleFaviconDownloader.swift +++ b/Shared/Favicons/SingleFaviconDownloader.swift @@ -25,7 +25,7 @@ final class SingleFaviconDownloader { } let faviconURL: String - var image: RSImage? + var iconImage: IconImage? private var lastDownloadAttemptDate: Date private var diskStatus = DiskStatus.unknown @@ -50,7 +50,7 @@ final class SingleFaviconDownloader { // If we don’t have an image, and lastDownloadAttemptDate is a while ago, try again. - if let _ = image { + if let _ = iconImage { return } @@ -72,7 +72,7 @@ private extension SingleFaviconDownloader { if let image = image { self.diskStatus = .onDisk - self.image = image + self.iconImage = IconImage(image) self.postDidLoadFaviconNotification() return } @@ -82,7 +82,7 @@ private extension SingleFaviconDownloader { self.downloadFavicon { (image) in if let image = image { - self.image = image + self.iconImage = IconImage(image) self.postDidLoadFaviconNotification() } } diff --git a/Shared/Images/AuthorAvatarDownloader.swift b/Shared/Images/AuthorAvatarDownloader.swift index ef0b04eba..c69077c0d 100644 --- a/Shared/Images/AuthorAvatarDownloader.swift +++ b/Shared/Images/AuthorAvatarDownloader.swift @@ -18,7 +18,7 @@ extension Notification.Name { final class AuthorAvatarDownloader { private let imageDownloader: ImageDownloader - private var cache = [String: RSImage]() // avatarURL: RSImage + private var cache = [String: IconImage]() // avatarURL: RSImage private var waitingForAvatarURLs = Set() init(imageDownloader: ImageDownloader) { @@ -28,10 +28,10 @@ final class AuthorAvatarDownloader { } func resetCache() { - cache = [String: RSImage]() + cache = [String: IconImage]() } - func image(for author: Author) -> RSImage? { + func image(for author: Author) -> IconImage? { guard let avatarURL = author.avatarURL else { return nil @@ -68,7 +68,7 @@ final class AuthorAvatarDownloader { private extension AuthorAvatarDownloader { func scaleAndCacheImageData(_ imageData: Data, _ avatarURL: String) { - RSImage.scaledForAvatar(imageData) { (image) in + RSImage.scaledForIcon(imageData) { (image) in if let image = image { self.handleImageDidBecomeAvailable(avatarURL, image) } @@ -77,7 +77,7 @@ private extension AuthorAvatarDownloader { func handleImageDidBecomeAvailable(_ avatarURL: String, _ image: RSImage) { if cache[avatarURL] == nil { - cache[avatarURL] = image + cache[avatarURL] = IconImage(image) } if waitingForAvatarURLs.contains(avatarURL) { waitingForAvatarURLs.remove(avatarURL) diff --git a/Shared/Images/FeedIconDownloader.swift b/Shared/Images/FeedIconDownloader.swift index e1edec0e3..4b12c8721 100644 --- a/Shared/Images/FeedIconDownloader.swift +++ b/Shared/Images/FeedIconDownloader.swift @@ -41,7 +41,7 @@ public final class FeedIconDownloader { } private var urlsInProgress = Set() - private var cache = [Feed: RSImage]() + private var cache = [Feed: IconImage]() private var waitingForFeedURLs = [String: Feed]() init(imageDownloader: ImageDownloader, folder: String) { @@ -54,10 +54,10 @@ public final class FeedIconDownloader { } func resetCache() { - cache = [Feed: RSImage]() + cache = [Feed: IconImage]() } - func icon(for feed: Feed) -> RSImage? { + func icon(for feed: Feed) -> IconImage? { if let cachedImage = cache[feed] { return cachedImage @@ -70,7 +70,7 @@ public final class FeedIconDownloader { icon(forHomePageURL: homePageURL, feed: feed) { (image) in if let image = image { self.postFeedIconDidBecomeAvailableNotification(feed) - self.cache[feed] = image + self.cache[feed] = IconImage(image) } } } @@ -79,7 +79,7 @@ public final class FeedIconDownloader { icon(forURL: iconURL, feed: feed) { (image) in if let image = image { self.postFeedIconDidBecomeAvailableNotification(feed) - self.cache[feed] = image + self.cache[feed] = IconImage(image) } else { checkHomePageURL() @@ -139,7 +139,7 @@ private extension FeedIconDownloader { imageResultBlock(nil) return } - RSImage.scaledForAvatar(imageData, imageResultBlock: imageResultBlock) + RSImage.scaledForIcon(imageData, imageResultBlock: imageResultBlock) } func postFeedIconDidBecomeAvailableNotification(_ feed: Feed) { diff --git a/Shared/SmartFeeds/SearchFeedDelegate.swift b/Shared/SmartFeeds/SearchFeedDelegate.swift index b5c2b4b66..413d0bc31 100644 --- a/Shared/SmartFeeds/SearchFeedDelegate.swift +++ b/Shared/SmartFeeds/SearchFeedDelegate.swift @@ -20,7 +20,7 @@ struct SearchFeedDelegate: SmartFeedDelegate { let nameForDisplayPrefix = NSLocalizedString("Search: ", comment: "Search smart feed title prefix") let searchString: String let fetchType: FetchType - var smallIcon: RSImage? = AppAssets.searchFeedImage + var smallIcon: IconImage? = AppAssets.searchFeedImage init(searchString: String) { self.searchString = searchString diff --git a/Shared/SmartFeeds/SearchTimelineFeedDelegate.swift b/Shared/SmartFeeds/SearchTimelineFeedDelegate.swift index 443f248ed..84df490ac 100644 --- a/Shared/SmartFeeds/SearchTimelineFeedDelegate.swift +++ b/Shared/SmartFeeds/SearchTimelineFeedDelegate.swift @@ -20,7 +20,7 @@ struct SearchTimelineFeedDelegate: SmartFeedDelegate { let nameForDisplayPrefix = NSLocalizedString("Search: ", comment: "Search smart feed title prefix") let searchString: String let fetchType: FetchType - var smallIcon: RSImage? = AppAssets.searchFeedImage + var smallIcon: IconImage? = AppAssets.searchFeedImage init(searchString: String, articleIDs: Set) { self.searchString = searchString diff --git a/Shared/SmartFeeds/SmartFeed.swift b/Shared/SmartFeeds/SmartFeed.swift index 888c6ab01..4bba4d7a1 100644 --- a/Shared/SmartFeeds/SmartFeed.swift +++ b/Shared/SmartFeeds/SmartFeed.swift @@ -25,7 +25,7 @@ final class SmartFeed: PseudoFeed { } } - var smallIcon: RSImage? { + var smallIcon: IconImage? { return delegate.smallIcon } diff --git a/Shared/SmartFeeds/StarredFeedDelegate.swift b/Shared/SmartFeeds/StarredFeedDelegate.swift index 10e5b7957..796f13b7a 100644 --- a/Shared/SmartFeeds/StarredFeedDelegate.swift +++ b/Shared/SmartFeeds/StarredFeedDelegate.swift @@ -17,7 +17,7 @@ struct StarredFeedDelegate: SmartFeedDelegate { let nameForDisplay = NSLocalizedString("Starred", comment: "Starred pseudo-feed title") let fetchType: FetchType = .starred - var smallIcon: RSImage? = AppAssets.starredFeedImage + var smallIcon: IconImage? = AppAssets.starredFeedImage func fetchUnreadCount(for account: Account, callback: @escaping (Int) -> Void) { account.fetchUnreadCountForStarredArticles(callback) diff --git a/Shared/SmartFeeds/TodayFeedDelegate.swift b/Shared/SmartFeeds/TodayFeedDelegate.swift index 936d3bf42..2d350c577 100644 --- a/Shared/SmartFeeds/TodayFeedDelegate.swift +++ b/Shared/SmartFeeds/TodayFeedDelegate.swift @@ -15,7 +15,7 @@ struct TodayFeedDelegate: SmartFeedDelegate { let nameForDisplay = NSLocalizedString("Today", comment: "Today pseudo-feed title") let fetchType = FetchType.today - var smallIcon: RSImage? = AppAssets.todayFeedImage + var smallIcon: IconImage? = AppAssets.todayFeedImage func fetchUnreadCount(for account: Account, callback: @escaping (Int) -> Void) { account.fetchUnreadCountForToday(callback) diff --git a/Shared/SmartFeeds/UnreadFeed.swift b/Shared/SmartFeeds/UnreadFeed.swift index 115070885..20c3926df 100644 --- a/Shared/SmartFeeds/UnreadFeed.swift +++ b/Shared/SmartFeeds/UnreadFeed.swift @@ -30,7 +30,7 @@ final class UnreadFeed: PseudoFeed { } } - var smallIcon: RSImage? = AppAssets.unreadFeedImage + var smallIcon: IconImage? = AppAssets.unreadFeedImage #if os(macOS) var pasteboardWriter: NSPasteboardWriting { diff --git a/iOS/AppAssets.swift b/iOS/AppAssets.swift index d07600d18..2c365c1ba 100644 --- a/iOS/AppAssets.swift +++ b/iOS/AppAssets.swift @@ -49,8 +49,8 @@ struct AppAssets { return image.maskWithColor(color: AppAssets.primaryAccentColor.cgColor)! }() - static var avatarBackgroundColor: UIColor = { - return UIColor(named: "avatarBackgroundColor")! + static var iconBackgroundColor: UIColor = { + return UIColor(named: "iconBackgroundColor")! }() static var barBackgroundColor: UIColor = { @@ -105,8 +105,8 @@ struct AppAssets { return UIImage(systemName: "arrowtriangle.up.circle")! }() - static var masterFolderImage: UIImage = { - return UIImage(systemName: "folder.fill")! + static var masterFolderImage: IconImage = { + return IconImage(UIImage(systemName: "folder.fill")!) }() static var moreImage: UIImage = { @@ -125,8 +125,8 @@ struct AppAssets { return UIImage(systemName: "safari")! }() - static var searchFeedImage: UIImage = { - return UIImage(systemName: "magnifyingglass")! + static var searchFeedImage: IconImage = { + return IconImage(UIImage(systemName: "magnifyingglass")!) }() static var secondaryAccentColor: UIColor = { @@ -157,8 +157,8 @@ struct AppAssets { return UIImage(systemName: "star")! }() - static var starredFeedImage: UIImage = { - return UIImage(systemName: "star.fill")! + static var starredFeedImage: IconImage = { + return IconImage(UIImage(systemName: "star.fill")!) }() static var timelineStarImage: UIImage = { @@ -166,16 +166,16 @@ struct AppAssets { return image.withTintColor(AppAssets.starColor, renderingMode: .alwaysOriginal) }() - static var todayFeedImage: UIImage = { - return UIImage(systemName: "sun.max.fill")! + static var todayFeedImage: IconImage = { + return IconImage(UIImage(systemName: "sun.max.fill")!) }() static var trashImage: UIImage = { return UIImage(systemName: "trash")! }() - static var unreadFeedImage: UIImage = { - return UIImage(systemName: "largecircle.fill.circle")! + static var unreadFeedImage: IconImage = { + return IconImage(UIImage(systemName: "largecircle.fill.circle")!) }() static var vibrantTextColor: UIColor = { diff --git a/iOS/AvatarView.swift b/iOS/IconView.swift similarity index 84% rename from iOS/AvatarView.swift rename to iOS/IconView.swift index 3bce3e986..e604f5f4f 100644 --- a/iOS/AvatarView.swift +++ b/iOS/IconView.swift @@ -1,5 +1,5 @@ // -// AvatarView.swift +// IconView.swift // NetNewsWire-iOS // // Created by Maurice Parker on 9/17/19. @@ -8,16 +8,16 @@ import UIKit -final class AvatarView: UIView { +final class IconView: UIView { - var image: UIImage? = nil { + var iconImage: IconImage? = nil { didSet { - if image !== oldValue { - imageView.image = image + if iconImage !== oldValue { + imageView.image = iconImage?.image if self.traitCollection.userInterfaceStyle == .dark { DispatchQueue.global(qos: .default).async { - if self.image?.isDark() ?? false { + if self.iconImage?.isDark ?? false { DispatchQueue.main.async { self.isDisconcernable = false self.setNeedsLayout() @@ -74,8 +74,8 @@ final class AvatarView: UIView { override func layoutSubviews() { imageView.setFrameIfNotEqual(rectForImageView()) - if (image != nil && isVerticalBackgroundExposed && !isSymbolImage) || !isDisconcernable { - backgroundColor = AppAssets.avatarBackgroundColor + if (iconImage != nil && isVerticalBackgroundExposed && !isSymbolImage) || !isDisconcernable { + backgroundColor = AppAssets.iconBackgroundColor } else { backgroundColor = nil } @@ -83,16 +83,16 @@ final class AvatarView: UIView { } -private extension AvatarView { +private extension IconView { func commonInit() { - layer.cornerRadius = MasterTimelineDefaultCellLayout.avatarCornerRadius + layer.cornerRadius = MasterTimelineDefaultCellLayout.iconCornerRadius clipsToBounds = true addSubview(imageView) } func rectForImageView() -> CGRect { - guard let image = image else { + guard let image = iconImage?.image else { return CGRect.zero } diff --git a/iOS/Inspector/FeedInspectorView.swift b/iOS/Inspector/FeedInspectorView.swift index 43510276e..4ef59ef28 100644 --- a/iOS/Inspector/FeedInspectorView.swift +++ b/iOS/Inspector/FeedInspectorView.swift @@ -22,28 +22,28 @@ struct FeedInspectorView : View { Section(header: HStack { Spacer() - if self.viewModel.image.size.width < 32 || self.viewModel.image.size.height < 32 { - if colorScheme == .dark && self.viewModel.image.isDark() { - Image(uiImage: self.viewModel.image) + if self.viewModel.iconImage.image.size.width < 32 || self.viewModel.iconImage.image.size.height < 32 { + if colorScheme == .dark && self.viewModel.iconImage.isDark { + Image(uiImage: self.viewModel.iconImage.image) .resizable() - .background(Color(AppAssets.avatarBackgroundColor)) + .background(Color(AppAssets.iconBackgroundColor)) .frame(width: 24.0, height: 24.0) .cornerRadius(2.0) } else { - Image(uiImage: self.viewModel.image) + Image(uiImage: self.viewModel.iconImage.image) .resizable() .frame(width: 24.0, height: 24.0) .cornerRadius(2.0) } } else { - if colorScheme == .dark && self.viewModel.image.isDark() { - Image(uiImage: self.viewModel.image) + if colorScheme == .dark && self.viewModel.iconImage.isDark { + Image(uiImage: self.viewModel.iconImage.image) .resizable() - .background(Color(AppAssets.avatarBackgroundColor)) + .background(Color(AppAssets.iconBackgroundColor)) .frame(width: 48.0, height: 48.0) .cornerRadius(5.0) } else { - Image(uiImage: self.viewModel.image) + Image(uiImage: self.viewModel.iconImage.image) .resizable() .frame(width: 48.0, height: 48.0) .cornerRadius(5.0) @@ -88,7 +88,7 @@ struct FeedInspectorView : View { NotificationCenter.default.addObserver(self, selector: #selector(feedIconDidBecomeAvailable(_:)), name: .FeedIconDidBecomeAvailable, object: nil) } - var image: UIImage { + var iconImage: IconImage { if let feedIcon = appDelegate.feedIconDownloader.icon(for: feed) { return feedIcon } diff --git a/iOS/MasterFeed/Cell/MasterFeedTableViewCell.swift b/iOS/MasterFeed/Cell/MasterFeedTableViewCell.swift index 3483bf17d..96c2f3772 100644 --- a/iOS/MasterFeed/Cell/MasterFeedTableViewCell.swift +++ b/iOS/MasterFeed/Cell/MasterFeedTableViewCell.swift @@ -31,9 +31,9 @@ class MasterFeedTableViewCell : VibrantTableViewCell { } } - var avatarImage: UIImage? { + var iconImage: IconImage? { didSet { - avatarView.image = avatarImage + iconView.iconImage = iconImage } } @@ -92,7 +92,7 @@ class MasterFeedTableViewCell : VibrantTableViewCell { return label }() - private let avatarView = AvatarView() + private let iconView = IconView() private let bottomSeparatorView: UIView = { let view = UIView() @@ -154,9 +154,9 @@ class MasterFeedTableViewCell : VibrantTableViewCell { override func updateVibrancy(animated: Bool) { super.updateVibrancy(animated: animated) - let avatarTintColor = isHighlighted || isSelected ? AppAssets.vibrantTextColor : AppAssets.secondaryAccentColor + let iconTintColor = isHighlighted || isSelected ? AppAssets.vibrantTextColor : AppAssets.secondaryAccentColor UIView.animate(withDuration: duration(animated: animated)) { - self.avatarView.tintColor = avatarTintColor + self.iconView.tintColor = iconTintColor } updateLabelVibrancy(titleView, color: labelColor, animated: animated) } @@ -167,7 +167,7 @@ private extension MasterFeedTableViewCell { func commonInit() { addSubviewAtInit(unreadCountView) - addSubviewAtInit(avatarView) + addSubviewAtInit(iconView) addSubviewAtInit(titleView) addDisclosureView() addSubviewAtInit(bottomSeparatorView) @@ -189,7 +189,7 @@ private extension MasterFeedTableViewCell { } func layoutWith(_ layout: MasterFeedTableViewCellLayout) { - avatarView.setFrameIfNotEqual(layout.faviconRect) + iconView.setFrameIfNotEqual(layout.faviconRect) titleView.setFrameIfNotEqual(layout.titleRect) unreadCountView.setFrameIfNotEqual(layout.unreadCountRect) disclosureButton?.setFrameIfNotEqual(layout.disclosureButtonRect) diff --git a/iOS/MasterFeed/MasterFeedViewController.swift b/iOS/MasterFeed/MasterFeedViewController.swift index 7a2158b65..1b405adb1 100644 --- a/iOS/MasterFeed/MasterFeedViewController.swift +++ b/iOS/MasterFeed/MasterFeedViewController.swift @@ -105,11 +105,11 @@ class MasterFeedViewController: UITableViewController, UndoableCommandRunner { } @objc func faviconDidBecomeAvailable(_ note: Notification) { - applyToAvailableCells(configureAvatar) + applyToAvailableCells(configureIcon) } @objc func feedIconDidBecomeAvailable(_ note: Notification) { - applyToAvailableCells(configureAvatar) + applyToAvailableCells(configureIcon) } @objc func feedSettingDidChange(_ note: Notification) { @@ -640,7 +640,7 @@ private extension MasterFeedViewController { cell.name = nameFor(node) cell.unreadCount = coordinator.unreadCountFor(node) - configureAvatar(cell, node) + configureIcon(cell, node) guard let indexPath = dataSource.indexPath(for: node) else { return } let rowsInSection = tableView.numberOfRows(inSection: indexPath.section) @@ -652,11 +652,11 @@ private extension MasterFeedViewController { } - func configureAvatar(_ cell: MasterFeedTableViewCell, _ node: Node) { - cell.avatarImage = imageFor(node) + func configureIcon(_ cell: MasterFeedTableViewCell, _ node: Node) { + cell.iconImage = imageFor(node) } - func imageFor(_ node: Node) -> UIImage? { + func imageFor(_ node: Node) -> IconImage? { if let feed = node.representedObject as? Feed { let feedIconImage = appDelegate.feedIconDownloader.icon(for: feed) diff --git a/iOS/MasterTimeline/Cell/MasterTimelineAccessibilityCellLayout.swift b/iOS/MasterTimeline/Cell/MasterTimelineAccessibilityCellLayout.swift index 9640660ae..e702516b9 100644 --- a/iOS/MasterTimeline/Cell/MasterTimelineAccessibilityCellLayout.swift +++ b/iOS/MasterTimeline/Cell/MasterTimelineAccessibilityCellLayout.swift @@ -14,7 +14,7 @@ struct MasterTimelineAccessibilityCellLayout: MasterTimelineCellLayout { let height: CGFloat let unreadIndicatorRect: CGRect let starRect: CGRect - let avatarImageRect: CGRect + let iconImageRect: CGRect let titleRect: CGRect let summaryRect: CGRect let feedNameRect: CGRect @@ -37,12 +37,12 @@ struct MasterTimelineAccessibilityCellLayout: MasterTimelineCellLayout { // Separator Insets self.separatorInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0) - // Avatar - if cellData.showAvatar { - self.avatarImageRect = MasterTimelineAccessibilityCellLayout.rectForAvatar(currentPoint) - currentPoint.y = self.avatarImageRect.maxY + // Icon Image + if cellData.showIcon { + self.iconImageRect = MasterTimelineAccessibilityCellLayout.rectForIconView(currentPoint) + currentPoint.y = self.iconImageRect.maxY } else { - self.avatarImageRect = CGRect.zero + self.iconImageRect = CGRect.zero } let textAreaWidth = width - (currentPoint.x + MasterTimelineDefaultCellLayout.cellPadding.right + insets.right) diff --git a/iOS/MasterTimeline/Cell/MasterTimelineCellData.swift b/iOS/MasterTimeline/Cell/MasterTimelineCellData.swift index 26cc4f3d3..4edda1db1 100644 --- a/iOS/MasterTimeline/Cell/MasterTimelineCellData.swift +++ b/iOS/MasterTimeline/Cell/MasterTimelineCellData.swift @@ -16,14 +16,14 @@ struct MasterTimelineCellData { let dateString: String let feedName: String let showFeedName: Bool - let avatar: UIImage? // feed icon, user avatar, or favicon - let showAvatar: Bool // Make space even when avatar is nil + let iconImage: IconImage? // feed icon, user avatar, or favicon + let showIcon: Bool // Make space even when icon is nil let featuredImage: UIImage? // image from within the article let read: Bool let starred: Bool let numberOfLines: Int - init(article: Article, showFeedName: Bool, feedName: String?, avatar: UIImage?, showAvatar: Bool, featuredImage: UIImage?, numberOfLines: Int) { + init(article: Article, showFeedName: Bool, feedName: String?, iconImage: IconImage?, showIcon: Bool, featuredImage: UIImage?, numberOfLines: Int) { self.title = ArticleStringFormatter.truncatedTitle(article) self.summary = ArticleStringFormatter.truncatedSummary(article) @@ -39,8 +39,8 @@ struct MasterTimelineCellData { self.showFeedName = showFeedName - self.showAvatar = showAvatar - self.avatar = avatar + self.showIcon = showIcon + self.iconImage = iconImage self.featuredImage = featuredImage self.read = article.status.read @@ -55,8 +55,8 @@ struct MasterTimelineCellData { self.dateString = "" self.feedName = "" self.showFeedName = false - self.showAvatar = false - self.avatar = nil + self.showIcon = false + self.iconImage = nil self.featuredImage = nil self.read = true self.starred = false diff --git a/iOS/MasterTimeline/Cell/MasterTimelineCellLayout.swift b/iOS/MasterTimeline/Cell/MasterTimelineCellLayout.swift index f4b25aff5..bd37476e3 100644 --- a/iOS/MasterTimeline/Cell/MasterTimelineCellLayout.swift +++ b/iOS/MasterTimeline/Cell/MasterTimelineCellLayout.swift @@ -13,7 +13,7 @@ protocol MasterTimelineCellLayout { var height: CGFloat {get} var unreadIndicatorRect: CGRect {get} var starRect: CGRect {get} - var avatarImageRect: CGRect {get} + var iconImageRect: CGRect {get} var titleRect: CGRect {get} var summaryRect: CGRect {get} var feedNameRect: CGRect {get} @@ -42,9 +42,9 @@ extension MasterTimelineCellLayout { return r } - static func rectForAvatar(_ point: CGPoint) -> CGRect { + static func rectForIconView(_ point: CGPoint) -> CGRect { var r = CGRect.zero - r.size = MasterTimelineDefaultCellLayout.avatarSize + r.size = MasterTimelineDefaultCellLayout.iconImageSize r.origin.x = point.x r.origin.y = point.y + 4 return r diff --git a/iOS/MasterTimeline/Cell/MasterTimelineDefaultCellLayout.swift b/iOS/MasterTimeline/Cell/MasterTimelineDefaultCellLayout.swift index f72f8cdaa..1bbd83cb3 100644 --- a/iOS/MasterTimeline/Cell/MasterTimelineDefaultCellLayout.swift +++ b/iOS/MasterTimeline/Cell/MasterTimelineDefaultCellLayout.swift @@ -21,9 +21,9 @@ struct MasterTimelineDefaultCellLayout: MasterTimelineCellLayout { static let starDimension = CGFloat(integerLiteral: 16) static let starSize = CGSize(width: MasterTimelineDefaultCellLayout.starDimension, height: MasterTimelineDefaultCellLayout.starDimension) - static let avatarSize = CGSize(width: 32.0, height: 32.0) - static let avatarMarginRight = CGFloat(integerLiteral: 8) - static let avatarCornerRadius = CGFloat(integerLiteral: 4) + static let iconImageSize = CGSize(width: 32.0, height: 32.0) + static let iconMarginRight = CGFloat(integerLiteral: 8) + static let iconCornerRadius = CGFloat(integerLiteral: 4) static var titleFont: UIFont { return UIFont.preferredFont(forTextStyle: .headline) @@ -47,7 +47,7 @@ struct MasterTimelineDefaultCellLayout: MasterTimelineCellLayout { let height: CGFloat let unreadIndicatorRect: CGRect let starRect: CGRect - let avatarImageRect: CGRect + let iconImageRect: CGRect let titleRect: CGRect let summaryRect: CGRect let feedNameRect: CGRect @@ -70,12 +70,12 @@ struct MasterTimelineDefaultCellLayout: MasterTimelineCellLayout { // Separator Insets self.separatorInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0) - // Avatar - if cellData.showAvatar { - self.avatarImageRect = MasterTimelineDefaultCellLayout.rectForAvatar(currentPoint) - currentPoint.x = self.avatarImageRect.maxX + MasterTimelineDefaultCellLayout.avatarMarginRight + // Icon Image + if cellData.showIcon { + self.iconImageRect = MasterTimelineDefaultCellLayout.rectForIconView(currentPoint) + currentPoint.x = self.iconImageRect.maxX + MasterTimelineDefaultCellLayout.iconMarginRight } else { - self.avatarImageRect = CGRect.zero + self.iconImageRect = CGRect.zero } let textAreaWidth = width - (currentPoint.x + MasterTimelineDefaultCellLayout.cellPadding.right + insets.right) @@ -98,7 +98,7 @@ struct MasterTimelineDefaultCellLayout: MasterTimelineCellLayout { let feedNameWidth = textAreaWidth - (MasterTimelineDefaultCellLayout.feedRightMargin + self.dateRect.size.width) self.feedNameRect = MasterTimelineDefaultCellLayout.rectForFeedName(cellData, currentPoint, feedNameWidth) - self.height = [self.avatarImageRect, self.feedNameRect].maxY() + MasterTimelineDefaultCellLayout.cellPadding.bottom + self.height = [self.iconImageRect, self.feedNameRect].maxY() + MasterTimelineDefaultCellLayout.cellPadding.bottom } diff --git a/iOS/MasterTimeline/Cell/MasterTimelineTableViewCell.swift b/iOS/MasterTimeline/Cell/MasterTimelineTableViewCell.swift index 16f0c6ca5..796d468f6 100644 --- a/iOS/MasterTimeline/Cell/MasterTimelineTableViewCell.swift +++ b/iOS/MasterTimeline/Cell/MasterTimelineTableViewCell.swift @@ -17,7 +17,7 @@ class MasterTimelineTableViewCell: VibrantTableViewCell { private let dateView = MasterTimelineTableViewCell.singleLineUILabel() private let feedNameView = MasterTimelineTableViewCell.singleLineUILabel() - private lazy var avatarView = AvatarView() + private lazy var iconView = IconView() private lazy var starView = { return NonIntrinsicImageView(image: AppAssets.timelineStarImage) @@ -68,7 +68,7 @@ class MasterTimelineTableViewCell: VibrantTableViewCell { unreadIndicatorView.setFrameIfNotEqual(layout.unreadIndicatorRect) starView.setFrameIfNotEqual(layout.starRect) - avatarView.setFrameIfNotEqual(layout.avatarImageRect) + iconView.setFrameIfNotEqual(layout.iconImageRect) setFrame(for: titleView, rect: layout.titleRect) setFrame(for: summaryView, rect: layout.summaryRect) feedNameView.setFrameIfNotEqual(layout.feedNameRect) @@ -77,8 +77,8 @@ class MasterTimelineTableViewCell: VibrantTableViewCell { separatorInset = layout.separatorInsets } - func setAvatarImage(_ image: UIImage) { - avatarView.image = image + func setIconImage(_ image: IconImage) { + iconView.iconImage = image } } @@ -128,7 +128,7 @@ private extension MasterTimelineTableViewCell { addSubviewAtInit(unreadIndicatorView, hidden: true) addSubviewAtInit(dateView, hidden: false) addSubviewAtInit(feedNameView, hidden: true) - addSubviewAtInit(avatarView, hidden: true) + addSubviewAtInit(iconView, hidden: true) addSubviewAtInit(starView, hidden: true) } @@ -167,7 +167,6 @@ private extension MasterTimelineTableViewCell { } func updateFeedNameView() { - if cellData.showFeedName { showView(feedNameView) feedNameView.font = MasterTimelineDefaultCellLayout.feedNameFont @@ -187,28 +186,26 @@ private extension MasterTimelineTableViewCell { showOrHideView(starView, !cellData.starred) } - func updateAvatar() { - - guard let image = cellData.avatar, cellData.showAvatar else { - makeAvatarEmpty() + func updateIconImage() { + guard let image = cellData.iconImage, cellData.showIcon else { + makeIconEmpty() return } - showView(avatarView) + showView(iconView) - if avatarView.image !== cellData.avatar { - avatarView.image = image + if iconView.iconImage !== cellData.iconImage { + iconView.iconImage = image setNeedsLayout() } } - func makeAvatarEmpty() { - - if avatarView.image != nil { - avatarView.image = nil + func makeIconEmpty() { + if iconView.iconImage != nil { + iconView.iconImage = nil setNeedsLayout() } - hideView(avatarView) + hideView(iconView) } func hideView(_ view: UIView) { @@ -234,7 +231,7 @@ private extension MasterTimelineTableViewCell { updateFeedNameView() updateUnreadIndicator() updateStarView() - updateAvatar() + updateIconImage() } } diff --git a/iOS/MasterTimeline/MasterTimelineTitleView.swift b/iOS/MasterTimeline/MasterTimelineTitleView.swift index 54e88f097..3046f079a 100644 --- a/iOS/MasterTimeline/MasterTimelineTitleView.swift +++ b/iOS/MasterTimeline/MasterTimelineTitleView.swift @@ -10,7 +10,7 @@ import UIKit class MasterTimelineTitleView: UIView { - @IBOutlet weak var avatarView: AvatarView! + @IBOutlet weak var iconView: IconView! @IBOutlet weak var label: UILabel! @IBOutlet weak var unreadCountView: MasterTimelineUnreadCountView! diff --git a/iOS/MasterTimeline/MasterTimelineTitleView.xib b/iOS/MasterTimeline/MasterTimelineTitleView.xib index b926f96bb..7d5b53ce6 100644 --- a/iOS/MasterTimeline/MasterTimelineTitleView.xib +++ b/iOS/MasterTimeline/MasterTimelineTitleView.xib @@ -23,7 +23,7 @@ - + @@ -47,7 +47,7 @@ - + diff --git a/iOS/MasterTimeline/MasterTimelineViewController.swift b/iOS/MasterTimeline/MasterTimelineViewController.swift index acd450992..a96a2edd8 100644 --- a/iOS/MasterTimeline/MasterTimelineViewController.swift +++ b/iOS/MasterTimeline/MasterTimelineViewController.swift @@ -310,7 +310,7 @@ class MasterTimelineViewController: UITableViewController, UndoableCommandRunner } @objc func feedIconDidBecomeAvailable(_ note: Notification) { - titleView?.avatarView.image = coordinator.timelineAvatar + titleView?.iconView.iconImage = coordinator.timelineIconImage guard let feed = note.userInfo?[UserInfoKey.feed] as? Feed else { return } @@ -318,14 +318,14 @@ class MasterTimelineViewController: UITableViewController, UndoableCommandRunner guard let article = dataSource.itemIdentifier(for: indexPath) else { return } - if article.feed == feed, let cell = tableView.cellForRow(at: indexPath) as? MasterTimelineTableViewCell, let image = avatarFor(article) { - cell.setAvatarImage(image) + if article.feed == feed, let cell = tableView.cellForRow(at: indexPath) as? MasterTimelineTableViewCell, let image = iconImageFor(article) { + cell.setIconImage(image) } } } @objc func avatarDidBecomeAvailable(_ note: Notification) { - guard coordinator.showAvatars, let avatarURL = note.userInfo?[UserInfoKey.url] as? String else { + guard coordinator.showIcons, let avatarURL = note.userInfo?[UserInfoKey.url] as? String else { return } tableView.indexPathsForVisibleRows?.forEach { indexPath in @@ -333,16 +333,16 @@ class MasterTimelineViewController: UITableViewController, UndoableCommandRunner return } for author in authors { - if author.avatarURL == avatarURL, let cell = tableView.cellForRow(at: indexPath) as? MasterTimelineTableViewCell, let image = avatarFor(article) { - cell.setAvatarImage(image) + if author.avatarURL == avatarURL, let cell = tableView.cellForRow(at: indexPath) as? MasterTimelineTableViewCell, let image = iconImageFor(article) { + cell.setIconImage(image) } } } } @objc func faviconDidBecomeAvailable(_ note: Notification) { - titleView?.avatarView.image = coordinator.timelineAvatar - if coordinator.showAvatars { + titleView?.iconView.iconImage = coordinator.timelineIconImage + if coordinator.showIcons { queueReloadAvailableCells() } } @@ -392,7 +392,7 @@ class MasterTimelineViewController: UITableViewController, UndoableCommandRunner let status = ArticleStatus(articleID: prototypeID, read: false, starred: false, userDeleted: false, dateArrived: Date()) let prototypeArticle = Article(accountID: prototypeID, articleID: prototypeID, feedID: prototypeID, uniqueID: prototypeID, title: longTitle, contentHTML: nil, contentText: nil, url: nil, externalURL: nil, summary: nil, imageURL: nil, bannerImageURL: nil, datePublished: nil, dateModified: nil, authors: nil, attachments: nil, status: status) - let prototypeCellData = MasterTimelineCellData(article: prototypeArticle, showFeedName: true, feedName: "Prototype Feed Name", avatar: nil, showAvatar: false, featuredImage: nil, numberOfLines: numberOfTextLines) + let prototypeCellData = MasterTimelineCellData(article: prototypeArticle, showFeedName: true, feedName: "Prototype Feed Name", iconImage: nil, showIcon: false, featuredImage: nil, numberOfLines: numberOfTextLines) if UIApplication.shared.preferredContentSizeCategory.isAccessibilityCategory { let layout = MasterTimelineAccessibilityCellLayout(width: tableView.bounds.width, insets: tableView.safeAreaInsets, cellData: prototypeCellData) @@ -448,7 +448,7 @@ private extension MasterTimelineViewController { if let titleView = Bundle.main.loadNibNamed("MasterTimelineTitleView", owner: self, options: nil)?[0] as? MasterTimelineTitleView { self.titleView = titleView - titleView.avatarView.image = coordinator.timelineAvatar + titleView.iconView.iconImage = coordinator.timelineIconImage titleView.label.text = coordinator.timelineName updateTitleUnreadCount() @@ -508,20 +508,20 @@ private extension MasterTimelineViewController { func configure(_ cell: MasterTimelineTableViewCell, article: Article) { - let avatar = avatarFor(article) + let iconImage = iconImageFor(article) let featuredImage = featuredImageFor(article) let showFeedNames = coordinator.showFeedNames - let showAvatar = coordinator.showAvatars && avatar != nil - cell.cellData = MasterTimelineCellData(article: article, showFeedName: showFeedNames, feedName: article.feed?.nameForDisplay, avatar: avatar, showAvatar: showAvatar, featuredImage: featuredImage, numberOfLines: numberOfTextLines) + let showIcon = coordinator.showIcons && iconImage != nil + cell.cellData = MasterTimelineCellData(article: article, showFeedName: showFeedNames, feedName: article.feed?.nameForDisplay, iconImage: iconImage, showIcon: showIcon, featuredImage: featuredImage, numberOfLines: numberOfTextLines) } - func avatarFor(_ article: Article) -> RSImage? { - if !coordinator.showAvatars { + func iconImageFor(_ article: Article) -> IconImage? { + if !coordinator.showIcons { return nil } - return article.avatarImage() + return article.iconImage() } func featuredImageFor(_ article: Article) -> UIImage? { diff --git a/iOS/Resources/Assets.xcassets/avatarBackgroundColor.colorset/Contents.json b/iOS/Resources/Assets.xcassets/iconBackgroundColor.colorset/Contents.json similarity index 100% rename from iOS/Resources/Assets.xcassets/avatarBackgroundColor.colorset/Contents.json rename to iOS/Resources/Assets.xcassets/iconBackgroundColor.colorset/Contents.json diff --git a/iOS/SceneCoordinator.swift b/iOS/SceneCoordinator.swift index 7826e09cb..516c4a901 100644 --- a/iOS/SceneCoordinator.swift +++ b/iOS/SceneCoordinator.swift @@ -111,7 +111,7 @@ class SceneCoordinator: NSObject, UndoableCommandRunner, UnreadCountProvider { private(set) var currentFeedIndexPath: IndexPath? - var timelineAvatar: RSImage? { + var timelineIconImage: IconImage? { if let feed = timelineFetcher as? Feed { let feedIconImage = appDelegate.feedIconDownloader.icon(for: feed) @@ -119,8 +119,8 @@ class SceneCoordinator: NSObject, UndoableCommandRunner, UnreadCountProvider { return feedIconImage } - if let faviconImage = appDelegate.faviconDownloader.faviconAsAvatar(for: feed) { - return faviconImage + if let faviconIconImage = appDelegate.faviconDownloader.faviconAsIcon(for: feed) { + return faviconIconImage } } @@ -154,7 +154,7 @@ class SceneCoordinator: NSObject, UndoableCommandRunner, UnreadCountProvider { } private(set) var showFeedNames = false - private(set) var showAvatars = false + private(set) var showIcons = false var isPrevFeedAvailable: Bool { guard let indexPath = currentFeedIndexPath else { @@ -1087,10 +1087,10 @@ private extension SceneCoordinator { return indexPathFor(node) } - func updateShowAvatars() { + func updateShowIcons() { if showFeedNames { - self.showAvatars = true + self.showIcons = true return } @@ -1098,14 +1098,14 @@ private extension SceneCoordinator { if let authors = article.authors { for author in authors { if author.avatarURL != nil { - self.showAvatars = true + self.showIcons = true return } } } } - self.showAvatars = false + self.showIcons = false } // MARK: Select Prev Unread @@ -1350,7 +1350,7 @@ private extension SceneCoordinator { if articles != sortedArticles { articles = sortedArticles - updateShowAvatars() + updateShowIcons() updateUnreadCount() masterTimelineViewController?.reloadArticles(animate: animate)