Skip to content

Commit

Permalink
Fix the media gallery's empty state showing up at wrong times.
Browse files Browse the repository at this point in the history
  • Loading branch information
stefanceriu committed Dec 16, 2024
1 parent 3a82b88 commit f9be39e
Show file tree
Hide file tree
Showing 19 changed files with 80 additions and 60 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,9 @@ extension View {
}
}
}

@ViewBuilder
func mediaGalleryTimelineAspectRatio(imageInfo: ImageInfoProxy?) -> some View {
aspectRatio(imageInfo?.aspectRatio, contentMode: .fill)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ struct MediaEventsTimelineGroup: Identifiable {
}

struct MediaEventsTimelineScreenViewState: BindableState {
var hasReachedTimelineStart = false
var isBackPaginating = false
var groups = [MediaEventsTimelineGroup]()

Expand All @@ -31,6 +32,10 @@ struct MediaEventsTimelineScreenViewState: BindableState {
var bindings: MediaEventsTimelineScreenViewStateBindings

var currentPreviewItemID: TimelineItemIdentifier?

var shouldShowEmptyState: Bool {
groups.isEmpty && hasReachedTimelineStart
}
}

struct MediaEventsTimelineScreenViewStateBindings {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,13 @@ class MediaEventsTimelineScreenViewModel: MediaEventsTimelineScreenViewModelType
init(mediaTimelineViewModel: TimelineViewModelProtocol,
filesTimelineViewModel: TimelineViewModelProtocol,
mediaProvider: MediaProviderProtocol,
screenMode: MediaEventsTimelineScreenMode = .media,
initialViewState: MediaEventsTimelineScreenViewState = .init(bindings: .init(screenMode: .media)),
userIndicatorController: UserIndicatorControllerProtocol) {
self.mediaTimelineViewModel = mediaTimelineViewModel
self.filesTimelineViewModel = filesTimelineViewModel
self.userIndicatorController = userIndicatorController

super.init(initialViewState: .init(bindings: .init(screenMode: screenMode)), mediaProvider: mediaProvider)
super.init(initialViewState: initialViewState, mediaProvider: mediaProvider)

state.activeTimelineContextProvider = { [weak self] in
guard let self else { fatalError() }
Expand Down Expand Up @@ -131,6 +131,7 @@ class MediaEventsTimelineScreenViewModel: MediaEventsTimelineScreenViewModelType
state.groups = newGroups

state.isBackPaginating = (timelineViewState.timelineState.paginationState.backward == .paginating)
// state.hasReachedTimelineStart = (timelineViewState.timelineState.paginationState.backward == .timelineEndReached)
backPaginateIfNecessary(paginationStatus: timelineViewState.timelineState.paginationState.backward)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ struct MediaEventsTimelineScreen: View {
}
.environmentObject(context.viewState.activeTimelineContextProvider())
.environment(\.timelineContext, context.viewState.activeTimelineContextProvider())
.onChange(of: context.screenMode) { _, _ in
context.send(viewAction: .changedScreenMode)
}
}

// The scale effects do the following:
Expand All @@ -44,7 +47,7 @@ struct MediaEventsTimelineScreen: View {
// * flip the items on both axes have them render correctly
@ViewBuilder
private var mainContent: some View {
if context.viewState.groups.isEmpty, !context.viewState.isBackPaginating {
if context.viewState.shouldShowEmptyState {
emptyState
} else {
ScrollView {
Expand All @@ -60,9 +63,6 @@ struct MediaEventsTimelineScreen: View {
}
}
.scaleEffect(.init(width: 1, height: -1))
.onChange(of: context.screenMode) { _, _ in
context.send(viewAction: .changedScreenMode)
}
}
}

Expand All @@ -76,12 +76,7 @@ struct MediaEventsTimelineScreen: View {
Button {
tappedItem(item)
} label: {
Color.clear // Let the image aspect fill in place
.aspectRatio(1, contentMode: .fill)
.overlay {
viewForTimelineItem(item)
}
.clipped()
viewForTimelineItem(item)
.scaleEffect(scale(for: item, isGridLayout: true))
}
.zoomTransitionSource(id: item.identifier, in: zoomTransition)
Expand Down Expand Up @@ -260,7 +255,8 @@ struct MediaEventsTimelineScreen_Previews: PreviewProvider, TestablePreview {
MediaEventsTimelineScreenViewModel(mediaTimelineViewModel: makeTimelineViewModel(timelineKind: timelineKind),
filesTimelineViewModel: makeTimelineViewModel(timelineKind: timelineKind),
mediaProvider: MediaProviderMock(configuration: .init()),
screenMode: screenMode,
initialViewState: .init(hasReachedTimelineStart: true,
bindings: .init(screenMode: screenMode)),
userIndicatorController: UserIndicatorControllerMock())
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,12 @@ struct ImageMediaEventsTimelineView: View {
let timelineItem: ImageRoomTimelineItem

var body: some View {
loadableImage
Color.clear // Let the image aspect fill in place
.aspectRatio(1, contentMode: .fill)
.overlay {
loadableImage
}
.clipped()
.accessibilityElement(children: .ignore)
.accessibilityLabel(L10n.commonImage)
}
Expand Down Expand Up @@ -48,13 +53,6 @@ struct ImageMediaEventsTimelineView: View {
}
}

private extension View {
@ViewBuilder
func mediaGalleryTimelineAspectRatio(imageInfo: ImageInfoProxy?) -> some View {
aspectRatio(imageInfo?.aspectRatio, contentMode: .fill)
}
}

struct ImageMediaEventsTimelineView_Previews: PreviewProvider, TestablePreview {
static let viewModel = TimelineViewModel.mock

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,13 @@ struct VideoMediaEventsTimelineView: View {
let timelineItem: VideoRoomTimelineItem

var body: some View {
thumbnail
Color.clear // Let the image aspect fill in place
.aspectRatio(1, contentMode: .fill)
.overlay {
thumbnail
}
.clipped()
.overlay(alignment: .bottom) { overlay }
.accessibilityElement(children: .ignore)
.accessibilityLabel(L10n.commonVideo)
}
Expand All @@ -25,23 +31,30 @@ struct VideoMediaEventsTimelineView: View {
mediaType: .timelineItem(uniqueID: timelineItem.id.uniqueID.id),
blurhash: timelineItem.content.blurhash,
size: timelineItem.content.thumbnailInfo?.size,
mediaProvider: context?.mediaProvider) { imageView in
imageView
.overlay { playIcon }
} placeholder: {
mediaProvider: context?.mediaProvider) {
placeholder
}
.mediaGalleryTimelineAspectRatio(imageInfo: timelineItem.content.thumbnailInfo)
} else {
playIcon
overlay
}
}

var playIcon: some View {
Image(systemName: "play.circle.fill")
.resizable()
.frame(width: 50, height: 50)
.background(.ultraThinMaterial, in: Circle())
.foregroundColor(.white)
var overlay: some View {
HStack(spacing: 0) {
CompoundIcon(\.videoCallSolid)
Spacer()
Text(Date(timeIntervalSince1970: timelineItem.content.videoInfo.duration).formattedTime())
}
.padding(8)
.background {
LinearGradient(stops: [.init(color: .clear, location: 0.0),
.init(color: .compound.bgCanvasDefault, location: 1.0)],
startPoint: .top,
endPoint: .bottom)
}
.font(.compound.bodyXSSemibold)
.foregroundStyle(.compound.textPrimary)
}

var placeholder: some View {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,18 +36,20 @@ class MockRoomTimelineController: RoomTimelineControllerProtocol {

init(timelineKind: TimelineKind = .live, listenForSignals: Bool = false) {
self.timelineKind = timelineKind
paginationState = PaginationState(backward: .idle, forward: .timelineEndReached)
callbacks.send(.isLive(true))

switch timelineKind {
case .media:
paginationState = PaginationState(backward: .timelineEndReached, forward: .timelineEndReached)
timelineItems = (0..<5).reduce([]) { partialResult, _ in
partialResult + [RoomTimelineItemFixtures.separator] + RoomTimelineItemFixtures.mediaChunk
}
default:
break
paginationState = PaginationState(backward: .idle, forward: .timelineEndReached)
}

callbacks.send(.paginationState(paginationState))
callbacks.send(.isLive(true))

guard listenForSignals else { return }

do {
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit f9be39e

Please sign in to comment.