Shared media improvements

This commit is contained in:
Ali
2021-10-28 17:59:12 +04:00
parent ccd6605ecc
commit e07e91fd18
5 changed files with 129 additions and 52 deletions

View File

@@ -578,6 +578,15 @@ private final class DayComponent: Component {
}
let titleImage = dayEnvironment.imageCache.text(fontSize: titleFontSize, isSemibold: titleFontIsSemibold, color: titleColor, string: component.title)
if animateMediaIn {
let previousTitleView = UIImageView(image: self.titleView.image)
previousTitleView.frame = self.titleView.frame
self.titleView.superview?.insertSubview(previousTitleView, aboveSubview: self.titleView)
previousTitleView.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false, completion: { [weak previousTitleView] _ in
previousTitleView?.removeFromSuperview()
})
self.titleView.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.16)
}
self.titleView.image = titleImage
let titleSize = titleImage.size
@@ -595,6 +604,7 @@ private final class DayComponent: Component {
if animateMediaIn {
mediaPreviewView.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2)
self.highlightView.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2)
}
}
@@ -946,7 +956,7 @@ public final class CalendarMessageScreen: ViewController {
private let context: AccountContext
private let peerId: PeerId
private let initialTimestamp: Int32
private let navigateToDay: (Int32) -> Void
private let navigateToOffset: (Int) -> Void
private let previewDay: (MessageIndex, ASDisplayNode, CGRect, ContextGesture) -> Void
private var presentationData: PresentationData
@@ -975,13 +985,13 @@ public final class CalendarMessageScreen: ViewController {
private var ignoreContentOffset: Bool = false
init(controller: CalendarMessageScreen, context: AccountContext, peerId: PeerId, calendarSource: SparseMessageCalendar, initialTimestamp: Int32, navigateToDay: @escaping (Int32) -> Void, previewDay: @escaping (MessageIndex, ASDisplayNode, CGRect, ContextGesture) -> Void) {
init(controller: CalendarMessageScreen, context: AccountContext, peerId: PeerId, calendarSource: SparseMessageCalendar, initialTimestamp: Int32, navigateToOffset: @escaping (Int) -> Void, previewDay: @escaping (MessageIndex, ASDisplayNode, CGRect, ContextGesture) -> Void) {
self.controller = controller
self.context = context
self.peerId = peerId
self.initialTimestamp = initialTimestamp
self.calendarSource = calendarSource
self.navigateToDay = navigateToDay
self.navigateToOffset = navigateToOffset
self.previewDay = previewDay
self.presentationData = context.sharedContext.currentPresentationData.with { $0 }
@@ -1569,7 +1579,7 @@ public final class CalendarMessageScreen: ViewController {
strongSelf.selectionState = selectionState
strongSelf.updateSelectionState()
} else {
} else if let calendarState = strongSelf.calendarState {
outer: for month in strongSelf.months {
let firstDayTimestamp = Int32(month.firstDay.timeIntervalSince1970)
@@ -1577,7 +1587,15 @@ public final class CalendarMessageScreen: ViewController {
let dayTimestamp = firstDayTimestamp + 24 * 60 * 60 * Int32(day)
if dayTimestamp == timestamp {
if month.mediaByDay[day] != nil {
strongSelf.navigateToDay(timestamp)
var offset = 0
for key in calendarState.messagesByDay.keys.sorted(by: { $0 > $1 }) {
if key == dayTimestamp {
break
} else if let item = calendarState.messagesByDay[key] {
offset += item.count
}
}
strongSelf.navigateToOffset(offset)
}
break outer
@@ -1645,8 +1663,8 @@ public final class CalendarMessageScreen: ViewController {
return
}
var messageMap: [Message] = []
for (_, message) in calendarState.messagesByDay {
messageMap.append(message)
for (_, entry) in calendarState.messagesByDay {
messageMap.append(entry.message)
}
var updatedMedia: [Int: [Int: DayMedia]] = [:]
@@ -1694,12 +1712,12 @@ public final class CalendarMessageScreen: ViewController {
private let peerId: PeerId
private let calendarSource: SparseMessageCalendar
private let initialTimestamp: Int32
private let navigateToDay: (CalendarMessageScreen, Int32) -> Void
private let navigateToDay: (CalendarMessageScreen, Int) -> Void
private let previewDay: (MessageIndex, ASDisplayNode, CGRect, ContextGesture) -> Void
private var presentationData: PresentationData
public init(context: AccountContext, peerId: PeerId, calendarSource: SparseMessageCalendar, initialTimestamp: Int32, navigateToDay: @escaping (CalendarMessageScreen, Int32) -> Void, previewDay: @escaping (MessageIndex, ASDisplayNode, CGRect, ContextGesture) -> Void) {
public init(context: AccountContext, peerId: PeerId, calendarSource: SparseMessageCalendar, initialTimestamp: Int32, navigateToDay: @escaping (CalendarMessageScreen, Int) -> Void, previewDay: @escaping (MessageIndex, ASDisplayNode, CGRect, ContextGesture) -> Void) {
self.context = context
self.peerId = peerId
self.calendarSource = calendarSource
@@ -1741,11 +1759,11 @@ public final class CalendarMessageScreen: ViewController {
}
override public func loadDisplayNode() {
self.displayNode = Node(controller: self, context: self.context, peerId: self.peerId, calendarSource: self.calendarSource, initialTimestamp: self.initialTimestamp, navigateToDay: { [weak self] timestamp in
self.displayNode = Node(controller: self, context: self.context, peerId: self.peerId, calendarSource: self.calendarSource, initialTimestamp: self.initialTimestamp, navigateToOffset: { [weak self] index in
guard let strongSelf = self else {
return
}
strongSelf.navigateToDay(strongSelf, timestamp)
strongSelf.navigateToDay(strongSelf, index)
}, previewDay: self.previewDay)
self.displayNodeDidLoad()

View File

@@ -186,6 +186,10 @@ public final class SparseItemGrid: ASDisplayNode {
preconditionFailure()
}
open var holeAnchor: HoleAnchor {
preconditionFailure()
}
public init() {
}
}
@@ -971,14 +975,24 @@ public final class SparseItemGrid: ASDisplayNode {
let visibleRange = layout.visibleItemRange(for: visibleBounds, count: items.count)
for index in visibleRange.minIndex ... visibleRange.maxIndex {
if items.item(at: index) == nil {
if let holeAnchor = items.closestHole(to: index) {
let location: HoleLocation
if index < holeAnchor.index {
location = .toLower
//let closestItem = items.closestItem(at: index)
let closestHole = items.closestHole(to: index)
var closestAnchor: HoleAnchor?
/*if let closestItem = closestItem, let closestHole = closestHole {
if abs(closestItem.index - index) < abs(closestHole.index - index) {
closestAnchor = closestItem.holeAnchor
} else {
location = .toUpper
closestAnchor = closestHole
}
self.maybeLoadHoleAnchor(holeAnchor, location)
} else if let closestItem = closestItem {
closestAnchor = closestItem.holeAnchor
} else if let closestHole = closestHole {*/
closestAnchor = closestHole
//}
if let closestAnchor = closestAnchor {
self.maybeLoadHoleAnchor(closestAnchor, .toLower)
}
break
}

View File

@@ -240,6 +240,7 @@ public final class SparseMessageList {
}
var loadRange: ClosedRange<Int32>?
var loadCount: Int?
centralItemSearch: for i in 0 ..< sparseItems.items.count {
switch sparseItems.items[i] {
@@ -323,6 +324,7 @@ public final class SparseMessageList {
}
loadRange = holeRange
loadCount = holeCount
break centralItemSearch
}
@@ -331,7 +333,7 @@ public final class SparseMessageList {
}
}
guard let range = loadRange else {
guard let range = loadRange, let expectedCount = loadCount else {
completion()
return
}
@@ -343,7 +345,7 @@ public final class SparseMessageList {
}
self.loadingHole = loadingHole
let mappedDirection: MessageHistoryViewRelativeHoleDirection = .range(start: MessageId(peerId: anchor.peerId, namespace: anchor.namespace, id: range.lowerBound - 1), end: MessageId(peerId: anchor.peerId, namespace: anchor.namespace, id: range.upperBound + 1))
let mappedDirection: MessageHistoryViewRelativeHoleDirection = .range(start: MessageId(peerId: anchor.peerId, namespace: anchor.namespace, id: range.upperBound), end: MessageId(peerId: anchor.peerId, namespace: anchor.namespace, id: range.lowerBound - 1))
let account = self.account
self.loadHoleDisposable.set((fetchMessageHistoryHole(
@@ -370,6 +372,10 @@ public final class SparseMessageList {
return
}
if messages.count != expectedCount {
Logger.shared.log("SparseMessageList", "unexpected message count")
}
var lowerIndex: Int?
var upperIndex: Int?
for i in 0 ..< strongSelf.sparseItems!.items.count {
@@ -401,6 +407,15 @@ public final class SparseMessageList {
}
}
let anchors = strongSelf.sparseItems!.items.compactMap { item -> MessageId? in
if case let .anchor(id, _, _) = item {
return id
} else {
return nil
}
}
assert(anchors.sorted(by: >) == anchors)
strongSelf.updateState()
if strongSelf.loadingHole == loadingHole {
@@ -594,9 +609,9 @@ public final class SparseMessageList {
let topItemCount = items.count
var totalCount = items.count
if let minMessageId = minMessageId, let sparseItems = self.sparseItems {
if let sparseItems = self.sparseItems {
var sparseIndex = 0
let _ = minMessageId
for i in 0 ..< sparseItems.items.count {
switch sparseItems.items[i] {
case let .anchor(id, timestamp, message):
@@ -699,7 +714,7 @@ public final class SparseMessageCalendar {
struct InternalState {
var nextRequestOffset: Int32?
var minTimestamp: Int32?
var messagesByDay: [Int32: Message]
var messagesByDay: [Int32: SparseMessageCalendar.Entry]
}
private let queue: Queue
@@ -747,8 +762,8 @@ public final class SparseMessageCalendar {
func removeMessagesInRange(minTimestamp: Int32, maxTimestamp: Int32, type: InteractiveHistoryClearingType, completion: @escaping () -> Void) -> Disposable {
var removeKeys: [Int32] = []
for (id, message) in self.state.messagesByDay {
if message.timestamp >= minTimestamp && message.timestamp <= maxTimestamp {
for (id, entry) in self.state.messagesByDay {
if entry.message.timestamp >= minTimestamp && entry.message.timestamp <= maxTimestamp {
removeKeys.append(id)
}
}
@@ -771,7 +786,7 @@ public final class SparseMessageCalendar {
self.isLoadingMore = true
struct LoadResult {
var messagesByDay: [Int32: Message]
var messagesByDay: [Int32: SparseMessageCalendar.Entry]
var nextOffset: Int32?
var minMessageId: MessageId?
var minTimestamp: Int32?
@@ -831,12 +846,12 @@ public final class SparseMessageCalendar {
let _ = transaction.addMessages(parsedMessages, location: .Random)
var minMessageId: Int32?
var messagesByDay: [Int32: Message] = [:]
var messagesByDay: [Int32: SparseMessageCalendar.Entry] = [:]
for period in periods {
switch period {
case let .searchResultsCalendarPeriod(date, minMsgId, _, _):
case let .searchResultsCalendarPeriod(date, minMsgId, _, count):
if let message = transaction.getMessage(MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: minMsgId)) {
messagesByDay[date] = message
messagesByDay[date] = SparseMessageCalendar.Entry(message: message, count: Int(count))
}
if let minMessageIdValue = minMessageId {
if minMsgId < minMessageIdValue {
@@ -863,8 +878,8 @@ public final class SparseMessageCalendar {
}
strongSelf.state.nextRequestOffset = result.nextOffset
for (timestamp, message) in result.messagesByDay {
strongSelf.state.messagesByDay[timestamp] = message
for (timestamp, entry) in result.messagesByDay {
strongSelf.state.messagesByDay[timestamp] = entry
}
strongSelf.statePromise.set(.single(strongSelf.state))
@@ -873,8 +888,13 @@ public final class SparseMessageCalendar {
}
}
public struct Entry {
public var message: Message
public var count: Int
}
public struct State {
public var messagesByDay: [Int32: Message]
public var messagesByDay: [Int32: Entry]
public var minTimestamp: Int32?
public var hasMore: Bool
}

View File

@@ -664,6 +664,10 @@ private final class VisualMediaItem: SparseItemGrid.Item {
return self.localMonthTimestamp
}
override var holeAnchor: SparseItemGrid.HoleAnchor {
return VisualMediaHoleAnchor(index: self.index, messageId: self.message.id, localMonthTimestamp: self.localMonthTimestamp)
}
init(index: Int, message: Message, localMonthTimestamp: Int32) {
self.indexValue = index
self.message = message
@@ -1173,12 +1177,16 @@ private final class SparseItemGridBindingImpl: SparseItemGridBinding, ListShimme
if let result = directMediaImageCache.getImage(message: message, media: selectedMedia, width: imageWidthSpec, possibleWidths: SparseItemGridBindingImpl.widthSpecs.1, synchronous: synchronous == .full) {
if let image = result.image {
layer.contents = image.cgImage
layer.hasContents = true
switch synchronous {
case .none:
layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2)
layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2, completion: { [weak self, weak layer, weak displayItem] _ in
layer?.hasContents = true
if let displayItem = displayItem {
self?.updateShimmerLayersImpl?(displayItem)
}
})
default:
break
layer.hasContents = true
}
}
if let loadSignal = result.loadSignal {
@@ -1192,15 +1200,13 @@ private final class SparseItemGridBindingImpl: SparseItemGridBinding, ListShimme
let deltaTime = CFAbsoluteTimeGetCurrent() - startTimestamp
let synchronousValue: Bool
switch synchronous {
case .none:
case .none, .full:
synchronousValue = false
case .semi:
synchronousValue = deltaTime < 0.1
case .full:
synchronousValue = true
}
if layer.hasContents && !synchronousValue {
if layer.contents != nil && !synchronousValue {
let copyLayer = ItemLayer()
copyLayer.contents = layer.contents
copyLayer.contentsRect = layer.contentsRect
@@ -1211,18 +1217,27 @@ private final class SparseItemGridBindingImpl: SparseItemGridBinding, ListShimme
})
layer.contents = image?.cgImage
layer.hasContents = true
} else {
layer.contents = image?.cgImage
layer.hasContents = true
if !synchronousValue {
layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2)
}
layer.hasContents = true
if let displayItem = displayItem {
self?.updateShimmerLayersImpl?(displayItem)
}
} else {
layer.contents = image?.cgImage
if !synchronousValue {
layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2, completion: { [weak layer] _ in
layer?.hasContents = true
if let displayItem = displayItem {
self?.updateShimmerLayersImpl?(displayItem)
}
})
} else {
layer.hasContents = true
if let displayItem = displayItem {
self?.updateShimmerLayersImpl?(displayItem)
}
}
}
})
}
@@ -1936,13 +1951,16 @@ final class PeerInfoVisualMediaPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScro
let timezoneOffset = Int32(TimeZone.current.secondsFromGMT())
var mappedItems: [SparseItemGrid.Item] = []
var mappeHoles: [SparseItemGrid.HoleAnchor] = []
var mappedHoles: [SparseItemGrid.HoleAnchor] = []
for item in list.items {
switch item.content {
case let .message(message, _):
case let .message(message, isLocal):
mappedItems.append(VisualMediaItem(index: item.index, message: message, localMonthTimestamp: Month(localTimestamp: message.timestamp + timezoneOffset).packedValue))
if !isLocal {
mappedHoles.append(VisualMediaHoleAnchor(index: item.index, messageId: message.id, localMonthTimestamp: Month(localTimestamp: message.timestamp + timezoneOffset).packedValue))
}
case let .placeholder(id, timestamp):
mappeHoles.append(VisualMediaHoleAnchor(index: item.index, messageId: id, localMonthTimestamp: Month(localTimestamp: timestamp + timezoneOffset).packedValue))
mappedHoles.append(VisualMediaHoleAnchor(index: item.index, messageId: id, localMonthTimestamp: Month(localTimestamp: timestamp + timezoneOffset).packedValue))
}
}
@@ -1953,7 +1971,7 @@ final class PeerInfoVisualMediaPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScro
let items = SparseItemGrid.Items(
items: mappedItems,
holeAnchors: mappeHoles,
holeAnchors: mappedHoles,
count: list.totalCount,
itemBinding: strongSelf.itemGridBinding
)
@@ -2234,6 +2252,13 @@ final class PeerInfoVisualMediaPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScro
}
}
func scrollToItem(index: Int) {
guard let _ = self.items else {
return
}
self.itemGrid.scrollToItem(at: index)
}
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
guard let result = super.hitTest(point, with: event) else {
return nil

View File

@@ -6243,7 +6243,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
var dismissCalendarScreen: (() -> Void)?
let calendarScreen = CalendarMessageScreen(context: self.context, peerId: self.peerId, calendarSource: calendarSource, initialTimestamp: initialTimestamp, navigateToDay: { [weak self] c, timestamp in
let calendarScreen = CalendarMessageScreen(context: self.context, peerId: self.peerId, calendarSource: calendarSource, initialTimestamp: initialTimestamp, navigateToDay: { [weak self] c, index in
guard let strongSelf = self else {
c.dismiss()
return
@@ -6253,7 +6253,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
return
}
pane.scrollToTimestamp(timestamp: timestamp)
pane.scrollToItem(index: index)
c.dismiss()
}, previewDay: { [weak self] index, sourceNode, sourceRect, gesture in