feat: add media interaction for notification timeline

This commit is contained in:
CMK 2022-02-15 14:01:28 +08:00
parent c2e5bcafb2
commit caa9ab7a40
4 changed files with 136 additions and 7 deletions

View File

@ -7,7 +7,7 @@
<key>AppShared.xcscheme_^#shared#^_</key>
<dict>
<key>orderHint</key>
<integer>25</integer>
<integer>20</integer>
</dict>
<key>CoreDataStack.xcscheme_^#shared#^_</key>
<dict>
@ -97,7 +97,7 @@
<key>MastodonIntent.xcscheme_^#shared#^_</key>
<dict>
<key>orderHint</key>
<integer>27</integer>
<integer>19</integer>
</dict>
<key>MastodonIntents.xcscheme_^#shared#^_</key>
<dict>
@ -117,7 +117,7 @@
<key>ShareActionExtension.xcscheme_^#shared#^_</key>
<dict>
<key>orderHint</key>
<integer>26</integer>
<integer>18</integer>
</dict>
</dict>
<key>SuppressBuildableAutocreation</key>

View File

@ -102,6 +102,119 @@ extension NotificationTableViewCellDelegate where Self: DataSourceProvider {
}
}
private struct NotificationMediaTransitionContext {
let status: ManagedObjectRecord<Status>
let needsToggleMediaSensitive: Bool
}
extension NotificationTableViewCellDelegate where Self: DataSourceProvider & MediaPreviewableViewController {
func tableViewCell(
_ cell: UITableViewCell,
notificationView: NotificationView,
statusView: StatusView,
mediaGridContainerView: MediaGridContainerView,
mediaView: MediaView,
didSelectMediaViewAt index: Int
) {
Task {
let source = DataSourceItem.Source(tableViewCell: cell, indexPath: nil)
guard let item = await item(from: source) else {
assertionFailure()
return
}
guard case let .notification(record) = item else {
assertionFailure("only works for status data provider")
return
}
let managedObjectContext = self.context.managedObjectContext
let _mediaTransitionContext: NotificationMediaTransitionContext? = try await managedObjectContext.perform {
guard let notification = record.object(in: managedObjectContext) else { return nil }
guard let _status = notification.status else { return nil }
let status = _status.reblog ?? _status
return NotificationMediaTransitionContext(
status: .init(objectID: status.objectID),
needsToggleMediaSensitive: status.isMediaSensitiveToggled ? !status.sensitive : status.sensitive
)
}
guard let mediaTransitionContext = _mediaTransitionContext else { return }
guard !mediaTransitionContext.needsToggleMediaSensitive else {
try await DataSourceFacade.responseToToggleSensitiveAction(
dependency: self,
status: mediaTransitionContext.status
)
return
}
try await DataSourceFacade.coordinateToMediaPreviewScene(
dependency: self,
status: mediaTransitionContext.status,
previewContext: DataSourceFacade.AttachmentPreviewContext(
containerView: .mediaGridContainerView(mediaGridContainerView),
mediaView: mediaView,
index: index
)
)
} // end Task
}
func tableViewCell(
_ cell: UITableViewCell,
notificationView: NotificationView,
quoteStatusView: StatusView,
mediaGridContainerView: MediaGridContainerView,
mediaView: MediaView,
didSelectMediaViewAt index: Int
) {
Task {
let source = DataSourceItem.Source(tableViewCell: cell, indexPath: nil)
guard let item = await item(from: source) else {
assertionFailure()
return
}
guard case let .notification(record) = item else {
assertionFailure("only works for status data provider")
return
}
let managedObjectContext = self.context.managedObjectContext
let _mediaTransitionContext: NotificationMediaTransitionContext? = try await managedObjectContext.perform {
guard let notification = record.object(in: managedObjectContext) else { return nil }
guard let _status = notification.status else { return nil }
let status = _status.reblog ?? _status
return NotificationMediaTransitionContext(
status: .init(objectID: status.objectID),
needsToggleMediaSensitive: status.isMediaSensitiveToggled ? !status.sensitive : status.sensitive
)
}
guard let mediaTransitionContext = _mediaTransitionContext else { return }
guard !mediaTransitionContext.needsToggleMediaSensitive else {
try await DataSourceFacade.responseToToggleSensitiveAction(
dependency: self,
status: mediaTransitionContext.status
)
return
}
try await DataSourceFacade.coordinateToMediaPreviewScene(
dependency: self,
status: mediaTransitionContext.status,
previewContext: DataSourceFacade.AttachmentPreviewContext(
containerView: .mediaGridContainerView(mediaGridContainerView),
mediaView: mediaView,
index: index
)
)
} // end Task
}
}
// MARK: - Status Toolbar
extension NotificationTableViewCellDelegate where Self: DataSourceProvider {
func tableViewCell(
@ -142,7 +255,6 @@ extension NotificationTableViewCellDelegate where Self: DataSourceProvider {
}
}
// MARK: - Status Author Avatar
extension NotificationTableViewCellDelegate where Self: DataSourceProvider {
func tableViewCell(

View File

@ -27,10 +27,12 @@ protocol NotificationTableViewCellDelegate: AnyObject, AutoGenerateProtocolDeleg
func tableViewCell(_ cell: UITableViewCell, notificationView: NotificationView, menuButton button: UIButton, didSelectAction action: MastodonMenu.Action)
func tableViewCell(_ cell: UITableViewCell, notificationView: NotificationView, statusView: StatusView, metaText: MetaText, didSelectMeta meta: Meta)
func tableViewCell(_ cell: UITableViewCell, notificationView: NotificationView, statusView: StatusView, spoilerOverlayViewDidPressed overlayView: SpoilerOverlayView)
func tableViewCell(_ cell: UITableViewCell, notificationView: NotificationView, statusView: StatusView, mediaGridContainerView: MediaGridContainerView, mediaView: MediaView, didSelectMediaViewAt index: Int)
func tableViewCell(_ cell: UITableViewCell, notificationView: NotificationView, statusView: StatusView, actionToolbarContainer: ActionToolbarContainer, buttonDidPressed button: UIButton, action: ActionToolbarContainer.Action)
func tableViewCell(_ cell: UITableViewCell, notificationView: NotificationView, quoteStatusView: StatusView, authorAvatarButtonDidPressed button: AvatarButton)
func tableViewCell(_ cell: UITableViewCell, notificationView: NotificationView, quoteStatusView: StatusView, metaText: MetaText, didSelectMeta meta: Meta)
func tableViewCell(_ cell: UITableViewCell, notificationView: NotificationView, quoteStatusView: StatusView, spoilerOverlayViewDidPressed overlayView: SpoilerOverlayView)
func tableViewCell(_ cell: UITableViewCell, notificationView: NotificationView, quoteStatusView: StatusView, mediaGridContainerView: MediaGridContainerView, mediaView: MediaView, didSelectMediaViewAt index: Int)
func tableViewCell(_ cell: UITableViewCell, notificationView: NotificationView, accessibilityActivate: Void)
// sourcery:end
}
@ -55,6 +57,10 @@ extension NotificationViewDelegate where Self: NotificationViewContainerTableVie
delegate?.tableViewCell(self, notificationView: notificationView, statusView: statusView, spoilerOverlayViewDidPressed: overlayView)
}
func notificationView(_ notificationView: NotificationView, statusView: StatusView, mediaGridContainerView: MediaGridContainerView, mediaView: MediaView, didSelectMediaViewAt index: Int) {
delegate?.tableViewCell(self, notificationView: notificationView, statusView: statusView, mediaGridContainerView: mediaGridContainerView, mediaView: mediaView, didSelectMediaViewAt: index)
}
func notificationView(_ notificationView: NotificationView, statusView: StatusView, actionToolbarContainer: ActionToolbarContainer, buttonDidPressed button: UIButton, action: ActionToolbarContainer.Action) {
delegate?.tableViewCell(self, notificationView: notificationView, statusView: statusView, actionToolbarContainer: actionToolbarContainer, buttonDidPressed: button, action: action)
}
@ -71,6 +77,10 @@ extension NotificationViewDelegate where Self: NotificationViewContainerTableVie
delegate?.tableViewCell(self, notificationView: notificationView, quoteStatusView: quoteStatusView, spoilerOverlayViewDidPressed: overlayView)
}
func notificationView(_ notificationView: NotificationView, quoteStatusView: StatusView, mediaGridContainerView: MediaGridContainerView, mediaView: MediaView, didSelectMediaViewAt index: Int) {
delegate?.tableViewCell(self, notificationView: notificationView, quoteStatusView: quoteStatusView, mediaGridContainerView: mediaGridContainerView, mediaView: mediaView, didSelectMediaViewAt: index)
}
func notificationView(_ notificationView: NotificationView, accessibilityActivate: Void) {
delegate?.tableViewCell(self, notificationView: notificationView, accessibilityActivate: accessibilityActivate)
}

View File

@ -19,14 +19,14 @@ public protocol NotificationViewDelegate: AnyObject {
func notificationView(_ notificationView: NotificationView, statusView: StatusView, metaText: MetaText, didSelectMeta meta: Meta)
func notificationView(_ notificationView: NotificationView, statusView: StatusView, spoilerOverlayViewDidPressed overlayView: SpoilerOverlayView)
// func notificationView(_ notificationView: NotificationView, statusView: StatusView, spoilerBannerViewDidPressed bannerView: SpoilerBannerView)
func notificationView(_ notificationView: NotificationView, statusView: StatusView, mediaGridContainerView: MediaGridContainerView, mediaView: MediaView, didSelectMediaViewAt index: Int)
func notificationView(_ notificationView: NotificationView, statusView: StatusView, actionToolbarContainer: ActionToolbarContainer, buttonDidPressed button: UIButton, action: ActionToolbarContainer.Action)
func notificationView(_ notificationView: NotificationView, quoteStatusView: StatusView, authorAvatarButtonDidPressed button: AvatarButton)
func notificationView(_ notificationView: NotificationView, quoteStatusView: StatusView, metaText: MetaText, didSelectMeta meta: Meta)
func notificationView(_ notificationView: NotificationView, quoteStatusView: StatusView, spoilerOverlayViewDidPressed overlayView: SpoilerOverlayView)
// func notificationView(_ notificationView: NotificationView, quoteStatusView: StatusView, spoilerBannerViewDidPressed bannerView: SpoilerBannerView)
func notificationView(_ notificationView: NotificationView, quoteStatusView: StatusView, mediaGridContainerView: MediaGridContainerView, mediaView: MediaView, didSelectMediaViewAt index: Int)
// a11y
func notificationView(_ notificationView: NotificationView, accessibilityActivate: Void)
@ -366,7 +366,14 @@ extension NotificationView: StatusViewDelegate {
}
public func statusView(_ statusView: StatusView, mediaGridContainerView: MediaGridContainerView, mediaView: MediaView, didSelectMediaViewAt index: Int) {
assertionFailure()
switch statusView {
case self.statusView:
delegate?.notificationView(self, statusView: statusView, mediaGridContainerView: mediaGridContainerView, mediaView: mediaView, didSelectMediaViewAt: index)
case quoteStatusView:
delegate?.notificationView(self, quoteStatusView: statusView, mediaGridContainerView: mediaGridContainerView, mediaView: mediaView, didSelectMediaViewAt: index)
default:
assertionFailure()
}
}
public func statusView(_ statusView: StatusView, pollTableView tableView: UITableView, didSelectRowAt indexPath: IndexPath) {