Skip to content

Commit

Permalink
Download media as it becomes visible in a chat
Browse files Browse the repository at this point in the history
  • Loading branch information
sashaweiss-signal committed Mar 6, 2025
1 parent b70d35a commit f7c2fad
Show file tree
Hide file tree
Showing 10 changed files with 87 additions and 36 deletions.
4 changes: 0 additions & 4 deletions Signal/ConversationView/CVCell.swift
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,6 @@ public class CVCell: UICollectionViewCell, CVRootComponentHost {
public var isCellVisible: Bool = false {
didSet {
componentView?.setIsCellVisible(isCellVisible)

if isCellVisible, let renderItem {
renderItem.rootComponent.cellDidBecomeVisible()
}
}
}

Expand Down
4 changes: 2 additions & 2 deletions Signal/ConversationView/Components/CVComponent.swift
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ public protocol CVComponent: AnyObject {
renderItem: CVRenderItem,
messageSwipeActionState: CVMessageSwipeActionState)

func cellDidBecomeVisible()
func cellWillBecomeVisible(componentDelegate: CVComponentDelegate)

func updateScrollingContent(componentView: CVComponentView)

Expand Down Expand Up @@ -157,7 +157,7 @@ public class CVComponentBase: NSObject {
owsFailDebug("No pan in progress.")
}

public func cellDidBecomeVisible() {
public func cellWillBecomeVisible(componentDelegate: CVComponentDelegate) {
// Do nothing.
}

Expand Down
8 changes: 6 additions & 2 deletions Signal/ConversationView/Components/CVComponentDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,12 @@ public protocol CVComponentDelegate: AnyObject, AudioMessageViewDelegate {

// MARK: -

func willBecomeVisibleWithFailedOrPendingDownloads(_ message: TSMessage)

func didTapFailedOrPendingDownloads(_ message: TSMessage)

// MARK: -

func didTapReplyToItem(_ itemViewModel: CVItemViewModelImpl)

func didTapSenderAvatar(_ interaction: TSInteraction)
Expand All @@ -86,8 +92,6 @@ public protocol CVComponentDelegate: AnyObject, AudioMessageViewDelegate {

func didTapTruncatedTextMessage(_ itemViewModel: CVItemViewModelImpl)

func didTapFailedOrPendingDownloads(_ message: TSMessage)

func didTapUndownloadableMedia()

func didTapUndownloadableGenericFile()
Expand Down
26 changes: 18 additions & 8 deletions Signal/ConversationView/Components/CVComponentMessage.swift
Original file line number Diff line number Diff line change
Expand Up @@ -1647,11 +1647,25 @@ public class CVComponentMessage: CVComponentBase, CVRootComponent {

// MARK: - Events

public override func handleTap(sender: UIGestureRecognizer,
componentDelegate: CVComponentDelegate,
componentView: CVComponentView,
renderItem: CVRenderItem) -> Bool {
public override func cellWillBecomeVisible(
componentDelegate: CVComponentDelegate
) {
AssertIsOnMainThread()

if
let message = interaction as? TSMessage,
componentState.failedOrPendingDownloads != nil
{
componentDelegate.willBecomeVisibleWithFailedOrPendingDownloads(message)
}
}

public override func handleTap(
sender: UIGestureRecognizer,
componentDelegate: CVComponentDelegate,
componentView: CVComponentView,
renderItem: CVRenderItem
) -> Bool {
guard let componentView = componentView as? CVComponentViewMessage else {
owsFailDebug("Unexpected componentView.")
return false
Expand Down Expand Up @@ -2346,10 +2360,6 @@ public class CVComponentMessage: CVComponentBase, CVRootComponent {
}
}

public override func cellDidBecomeVisible() {
AssertIsOnMainThread()
}

public override func contextMenuAccessoryViews(componentView: CVComponentView) -> [ContextMenuTargetedPreviewAccessory]? {
if hasSenderAvatar {
guard let componentView = componentView as? CVComponentViewMessage else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,38 @@ extension ConversationViewController: CVComponentDelegate {

// MARK: -

public func willBecomeVisibleWithFailedOrPendingDownloads(_ message: TSMessage) {
AssertIsOnMainThread()

// Avoid doing this on the main actor, as this isn't user-initiated.
Task.detached {
let db = DependenciesBridge.shared.db
let attachmentDownloadManager = DependenciesBridge.shared.attachmentDownloadManager

await db.awaitableWrite { tx in
attachmentDownloadManager.enqueueDownloadOfAttachmentsForMessage(
message,
priority: .default,
tx: tx
)
}
}
}

public func didTapFailedOrPendingDownloads(_ message: TSMessage) {
AssertIsOnMainThread()

SSKEnvironment.shared.databaseStorageRef.write { tx in
DependenciesBridge.shared.attachmentDownloadManager.enqueueDownloadOfAttachmentsForMessage(
message,
priority: .userInitiated,
tx: tx.asV2Write
)
}
}

// MARK: -

public func didTapReplyToItem(_ itemViewModel: CVItemViewModelImpl) {
AssertIsOnMainThread()

Expand Down Expand Up @@ -220,18 +252,6 @@ extension ConversationViewController: CVComponentDelegate {
self.present(sheet, animated: true)
}

public func didTapFailedOrPendingDownloads(_ message: TSMessage) {
AssertIsOnMainThread()

SSKEnvironment.shared.databaseStorageRef.write { tx in
DependenciesBridge.shared.attachmentDownloadManager.enqueueDownloadOfAttachmentsForMessage(
message,
priority: .userInitiated,
tx: tx.asV2Write
)
}
}

public func didTapUndownloadableMedia() {
let toast = ToastController(text: OWSLocalizedString(
"UNAVAILABLE_MEDIA_TAP_TOAST",
Expand Down
5 changes: 5 additions & 0 deletions Signal/ConversationView/Loading/CVLoadCoordinator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -718,7 +718,12 @@ extension CVLoadCoordinator: UICollectionViewDelegate {
owsFailDebug("Unexpected cell type.")
return
}

cell.isCellVisible = true
if let componentDelegate {
cell.renderItem?.rootComponent.cellWillBecomeVisible(componentDelegate: componentDelegate)
}

let delegate = self.delegate
DispatchQueue.main.async {
delegate?.updateScrollingContent()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -337,6 +337,12 @@ extension EditHistoryTableSheetViewController: CVComponentDelegate {

// MARK: -

func willBecomeVisibleWithFailedOrPendingDownloads(_ message: TSMessage) {}

func didTapFailedOrPendingDownloads(_ message: TSMessage) {}

// MARK: -

func didTapReplyToItem(_ itemViewModel: CVItemViewModelImpl) {}

func didTapSenderAvatar(_ interaction: TSInteraction) {}
Expand All @@ -353,8 +359,6 @@ extension EditHistoryTableSheetViewController: CVComponentDelegate {

var hasPendingMessageRequest: Bool { false }

func didTapFailedOrPendingDownloads(_ message: TSMessage) {}

func didTapUndownloadableMedia() {}

func didTapUndownloadableGenericFile() {}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -346,6 +346,12 @@ extension MediaGalleryFileCell: CVComponentDelegate {

// MARK: -

func willBecomeVisibleWithFailedOrPendingDownloads(_ message: TSMessage) {}

func didTapFailedOrPendingDownloads(_ message: TSMessage) {}

// MARK: -

func didTapReplyToItem(_ itemViewModel: CVItemViewModelImpl) {}

func didTapSenderAvatar(_ interaction: TSInteraction) {}
Expand All @@ -362,8 +368,6 @@ extension MediaGalleryFileCell: CVComponentDelegate {

var hasPendingMessageRequest: Bool { false }

func didTapFailedOrPendingDownloads(_ message: TSMessage) {}

func didTapUndownloadableMedia() {}

func didTapUndownloadableGenericFile() {}
Expand Down
8 changes: 6 additions & 2 deletions Signal/src/ViewControllers/MessageDetailViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -1040,6 +1040,12 @@ extension MessageDetailViewController: CVComponentDelegate {

// MARK: -

func willBecomeVisibleWithFailedOrPendingDownloads(_ message: TSMessage) {}

func didTapFailedOrPendingDownloads(_ message: TSMessage) {}

// MARK: -

// TODO:
func didTapReplyToItem(_ itemViewModel: CVItemViewModelImpl) {}

Expand All @@ -1058,8 +1064,6 @@ extension MessageDetailViewController: CVComponentDelegate {
// TODO:
var hasPendingMessageRequest: Bool { false }

func didTapFailedOrPendingDownloads(_ message: TSMessage) {}

func didTapUndownloadableMedia() {}

func didTapUndownloadableGenericFile() {}
Expand Down
8 changes: 6 additions & 2 deletions Signal/src/views/MockConversationView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,12 @@ extension MockConversationView: CVComponentDelegate {

// MARK: -

func willBecomeVisibleWithFailedOrPendingDownloads(_ message: TSMessage) {}

func didTapFailedOrPendingDownloads(_ message: TSMessage) {}

// MARK: -

func didTapReplyToItem(_ itemViewModel: CVItemViewModelImpl) {}

func didTapSenderAvatar(_ interaction: TSInteraction) {}
Expand All @@ -331,8 +337,6 @@ extension MockConversationView: CVComponentDelegate {

var hasPendingMessageRequest: Bool { false }

func didTapFailedOrPendingDownloads(_ message: TSMessage) {}

func didTapUndownloadableMedia() {}

func didTapUndownloadableGenericFile() {}
Expand Down

0 comments on commit f7c2fad

Please sign in to comment.