mirror of
https://github.com/Ranchero-Software/NetNewsWire
synced 2025-08-12 06:26:36 +00:00
Merge branch 'imagecache' into mac-release
This commit is contained in:
115
Mac/MainWindow/Timeline/Cell/TimelineAvatarView.swift
Normal file
115
Mac/MainWindow/Timeline/Cell/TimelineAvatarView.swift
Normal file
@@ -0,0 +1,115 @@
|
||||
//
|
||||
// TimelineAvatarView.swift
|
||||
// NetNewsWire
|
||||
//
|
||||
// Created by Brent Simmons on 9/15/19.
|
||||
// Copyright © 2019 Ranchero Software. All rights reserved.
|
||||
//
|
||||
|
||||
import AppKit
|
||||
|
||||
final class TimelineAvatarView: NSView {
|
||||
|
||||
var image: NSImage? = nil {
|
||||
didSet {
|
||||
if image !== oldValue {
|
||||
imageView.image = image
|
||||
needsDisplay = true
|
||||
needsLayout = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override var isFlipped: Bool {
|
||||
return true
|
||||
}
|
||||
|
||||
private let imageView: NSImageView = {
|
||||
let imageView = NSImageView(frame: NSRect.zero)
|
||||
imageView.animates = false
|
||||
imageView.imageAlignment = .alignCenter
|
||||
imageView.imageScaling = .scaleProportionallyUpOrDown
|
||||
return imageView
|
||||
}()
|
||||
|
||||
private var hasExposedVerticalBackground: Bool {
|
||||
return imageView.frame.size.height < bounds.size.height
|
||||
}
|
||||
|
||||
private static var lightBackgroundColor = AppAssets.avatarLightBackgroundColor
|
||||
private static var darkBackgroundColor = AppAssets.avatarDarkBackgroundColor
|
||||
|
||||
override init(frame frameRect: NSRect) {
|
||||
super.init(frame: frameRect)
|
||||
commonInit()
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) {
|
||||
super.init(coder: coder)
|
||||
commonInit()
|
||||
}
|
||||
|
||||
convenience init() {
|
||||
self.init(frame: NSRect.zero)
|
||||
}
|
||||
|
||||
override func viewDidMoveToSuperview() {
|
||||
needsLayout = true
|
||||
needsDisplay = true
|
||||
}
|
||||
|
||||
override func layout() {
|
||||
resizeSubviews(withOldSize: NSZeroSize)
|
||||
}
|
||||
|
||||
override func resizeSubviews(withOldSize oldSize: NSSize) {
|
||||
imageView.rs_setFrameIfNotEqual(rectForImageView())
|
||||
}
|
||||
|
||||
override func draw(_ dirtyRect: NSRect) {
|
||||
guard hasExposedVerticalBackground else {
|
||||
return
|
||||
}
|
||||
|
||||
let color = NSApplication.shared.effectiveAppearance.isDarkMode ? TimelineAvatarView.darkBackgroundColor : TimelineAvatarView.lightBackgroundColor
|
||||
color.set()
|
||||
dirtyRect.fill()
|
||||
}
|
||||
}
|
||||
|
||||
private extension TimelineAvatarView {
|
||||
|
||||
func commonInit() {
|
||||
addSubview(imageView)
|
||||
wantsLayer = true
|
||||
}
|
||||
|
||||
func rectForImageView() -> NSRect {
|
||||
guard let image = image else {
|
||||
return NSRect.zero
|
||||
}
|
||||
|
||||
let imageSize = image.size
|
||||
let viewSize = bounds.size
|
||||
if imageSize.height == imageSize.width {
|
||||
if imageSize.height >= viewSize.height * 0.75 {
|
||||
// Close enough to viewSize to scale up the image.
|
||||
return NSMakeRect(0.0, 0.0, viewSize.width, viewSize.height)
|
||||
}
|
||||
let offset = floor((viewSize.height - imageSize.height) / 2.0)
|
||||
return NSMakeRect(offset, offset, imageSize.width, imageSize.height)
|
||||
}
|
||||
else if imageSize.height > imageSize.width {
|
||||
let factor = viewSize.height / imageSize.height
|
||||
let width = imageSize.width * factor
|
||||
let originX = floor((viewSize.width - width) / 2.0)
|
||||
return NSMakeRect(originX, 0.0, width, viewSize.height)
|
||||
}
|
||||
|
||||
// Wider than tall: imageSize.width > imageSize.height
|
||||
let factor = viewSize.width / imageSize.width
|
||||
let height = imageSize.height * factor
|
||||
let originY = floor((viewSize.height - height) / 2.0)
|
||||
return NSMakeRect(0.0, originY, viewSize.width, height)
|
||||
}
|
||||
}
|
||||
@@ -18,13 +18,7 @@ class TimelineTableCellView: NSTableCellView {
|
||||
private let dateView = TimelineTableCellView.singleLineTextField()
|
||||
private let feedNameView = TimelineTableCellView.singleLineTextField()
|
||||
|
||||
private lazy var avatarImageView: NSImageView = {
|
||||
let imageView = TimelineTableCellView.imageView(with: AppAssets.genericFeedImage, scaling: .scaleNone)
|
||||
imageView.imageAlignment = .alignTop
|
||||
imageView.imageScaling = .scaleProportionallyDown
|
||||
imageView.wantsLayer = true
|
||||
return imageView
|
||||
}()
|
||||
private lazy var avatarView = TimelineAvatarView()
|
||||
|
||||
private let starView = TimelineTableCellView.imageView(with: AppAssets.timelineStar, scaling: .scaleNone)
|
||||
private let separatorView = TimelineTableCellView.separatorView()
|
||||
@@ -43,7 +37,7 @@ class TimelineTableCellView: NSTableCellView {
|
||||
didSet {
|
||||
if cellAppearance != oldValue {
|
||||
updateTextFieldFonts()
|
||||
avatarImageView.layer?.cornerRadius = cellAppearance.avatarCornerRadius
|
||||
avatarView.layer?.cornerRadius = cellAppearance.avatarCornerRadius
|
||||
needsLayout = true
|
||||
}
|
||||
}
|
||||
@@ -125,7 +119,7 @@ class TimelineTableCellView: NSTableCellView {
|
||||
dateView.rs_setFrameIfNotEqual(layoutRects.dateRect)
|
||||
unreadIndicatorView.rs_setFrameIfNotEqual(layoutRects.unreadIndicatorRect)
|
||||
feedNameView.rs_setFrameIfNotEqual(layoutRects.feedNameRect)
|
||||
avatarImageView.rs_setFrameIfNotEqual(layoutRects.avatarImageRect)
|
||||
avatarView.rs_setFrameIfNotEqual(layoutRects.avatarImageRect)
|
||||
starView.rs_setFrameIfNotEqual(layoutRects.starRect)
|
||||
separatorView.rs_setFrameIfNotEqual(layoutRects.separatorRect)
|
||||
}
|
||||
@@ -213,7 +207,7 @@ private extension TimelineTableCellView {
|
||||
addSubviewAtInit(unreadIndicatorView, hidden: true)
|
||||
addSubviewAtInit(dateView, hidden: false)
|
||||
addSubviewAtInit(feedNameView, hidden: true)
|
||||
addSubviewAtInit(avatarImageView, hidden: true)
|
||||
addSubviewAtInit(avatarView, hidden: true)
|
||||
addSubviewAtInit(starView, hidden: true)
|
||||
addSubviewAtInit(separatorView, hidden: !AppDefaults.timelineShowsSeparators)
|
||||
|
||||
@@ -222,7 +216,7 @@ private extension TimelineTableCellView {
|
||||
|
||||
func updatedLayoutRects() -> TimelineCellLayout {
|
||||
|
||||
return TimelineCellLayout(width: bounds.width, height: bounds.height, cellData: cellData, appearance: cellAppearance, hasAvatar: avatarImageView.image != nil)
|
||||
return TimelineCellLayout(width: bounds.width, height: bounds.height, cellData: cellData, appearance: cellAppearance, hasAvatar: avatarView.image != nil)
|
||||
}
|
||||
|
||||
func updateTitleView() {
|
||||
@@ -277,19 +271,19 @@ private extension TimelineTableCellView {
|
||||
return
|
||||
}
|
||||
|
||||
showView(avatarImageView)
|
||||
if avatarImageView.image !== image {
|
||||
avatarImageView.image = image
|
||||
showView(avatarView)
|
||||
if avatarView.image !== image {
|
||||
avatarView.image = image
|
||||
needsLayout = true
|
||||
}
|
||||
}
|
||||
|
||||
func makeAvatarEmpty() {
|
||||
if avatarImageView.image != nil {
|
||||
avatarImageView.image = nil
|
||||
if avatarView.image != nil {
|
||||
avatarView.image = nil
|
||||
needsLayout = true
|
||||
}
|
||||
hideView(avatarImageView)
|
||||
hideView(avatarView)
|
||||
}
|
||||
|
||||
func hideView(_ view: NSView) {
|
||||
|
||||
Reference in New Issue
Block a user