mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-03 06:02:10 +00:00
Remove unused SwiftUI timeline version
This commit is contained in:
committed by
Stefan Ceriu
parent
31ca8ed7f2
commit
d6b7212b5a
@@ -88,35 +88,18 @@ struct RoomScreen: View {
|
||||
context.send(viewAction: .cancelSend(itemID: info.itemID))
|
||||
}
|
||||
}
|
||||
.onChange(of: context.isScrolledToBottom) { isScrolledToBottom in
|
||||
if isScrolledToBottom {
|
||||
context.send(viewAction: .scrolledToBottom)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private var timeline: some View {
|
||||
timelineSwitch
|
||||
UITimelineView()
|
||||
.id(context.viewState.roomID)
|
||||
.environmentObject(context)
|
||||
.environment(\.timelineStyle, context.viewState.timelineStyle)
|
||||
}
|
||||
|
||||
@ViewBuilder
|
||||
private var timelineSwitch: some View {
|
||||
if context.viewState.swiftUITimelineEnabled {
|
||||
TimelineView(viewState: context.viewState.timelineViewState,
|
||||
isScrolledToBottom: $context.isScrolledToBottom) {
|
||||
context.send(viewAction: .paginateBackwards)
|
||||
.overlay(alignment: .bottomTrailing) {
|
||||
scrollToBottomButton
|
||||
}
|
||||
} else {
|
||||
UITimelineView()
|
||||
.overlay(alignment: .bottomTrailing) {
|
||||
scrollToBottomButton
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private var scrollToBottomButton: some View {
|
||||
Button { context.viewState.timelineViewState.scrollToBottomPublisher.send(()) } label: {
|
||||
Image(systemName: "chevron.down")
|
||||
|
||||
@@ -1,187 +0,0 @@
|
||||
//
|
||||
// Copyright 2022 New Vector Ltd
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
import Combine
|
||||
import SwiftUI
|
||||
|
||||
import SwiftUIIntrospect
|
||||
import WysiwygComposer
|
||||
|
||||
struct TimelineView: View {
|
||||
let viewState: TimelineViewState
|
||||
@Binding var isScrolledToBottom: Bool
|
||||
let paginationAction: () -> Void
|
||||
|
||||
@Environment(\.timelineStyle) private var timelineStyle
|
||||
|
||||
private let bottomID = "RoomTimelineBottomPinIdentifier"
|
||||
private let topID = "RoomTimelineTopPinIdentifier"
|
||||
|
||||
@State private var scrollViewAdapter = ScrollViewAdapter()
|
||||
@State private var paginateBackwardsPublisher = PassthroughSubject<Void, Never>()
|
||||
|
||||
var body: some View {
|
||||
ScrollViewReader { scrollView in
|
||||
timelineScrollView
|
||||
.introspect(.scrollView, on: .supportedVersions) { uiScrollView in
|
||||
guard uiScrollView != scrollViewAdapter.scrollView else {
|
||||
return
|
||||
}
|
||||
|
||||
scrollViewAdapter.scrollView = uiScrollView
|
||||
scrollViewAdapter.shouldScrollToTopClosure = { _ in
|
||||
withElementAnimation {
|
||||
scrollView.scrollTo(topID)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Allows the scroll to top to work properly
|
||||
uiScrollView.contentOffset.y -= 1
|
||||
paginateBackwardsPublisher.send()
|
||||
}
|
||||
.scaleEffect(x: 1, y: -1)
|
||||
.onReceive(viewState.scrollToBottomPublisher) { _ in
|
||||
withElementAnimation {
|
||||
scrollView.scrollTo(bottomID)
|
||||
}
|
||||
}
|
||||
.scrollDismissesKeyboard(.immediately)
|
||||
}
|
||||
.overlay(scrollToBottomButton, alignment: .bottomTrailing)
|
||||
.onReceive(scrollViewAdapter.didScroll) { _ in
|
||||
guard let scrollView = scrollViewAdapter.scrollView else {
|
||||
return
|
||||
}
|
||||
let offset = scrollView.contentOffset.y + scrollView.contentInset.top
|
||||
|
||||
let isScrolledToBottom = offset <= 0
|
||||
|
||||
// Only update the binding on changes to avoid needlessly recomputing the hierarchy when scrolling.
|
||||
if self.isScrolledToBottom != isScrolledToBottom {
|
||||
self.isScrolledToBottom = isScrolledToBottom
|
||||
}
|
||||
|
||||
// Allows the scroll to top to work properly
|
||||
if offset == 0 {
|
||||
scrollView.contentOffset.y -= 1
|
||||
}
|
||||
|
||||
paginateBackwardsPublisher.send()
|
||||
}
|
||||
.onReceive(paginateBackwardsPublisher.collect(.byTime(DispatchQueue.main, 0.1))) { _ in
|
||||
paginateBackwardsIfNeeded()
|
||||
}
|
||||
.onAppear {
|
||||
paginateBackwardsPublisher.send()
|
||||
}
|
||||
}
|
||||
|
||||
private var timelineScrollView: some View {
|
||||
ScrollView {
|
||||
bottomPin
|
||||
LazyVStack(spacing: 0) {
|
||||
ForEach(viewState.itemViewStates.reversed()) { viewState in
|
||||
RoomTimelineItemView(viewState: viewState)
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
.padding(timelineStyle.rowInsets)
|
||||
.scaleEffect(x: 1, y: -1)
|
||||
}
|
||||
}
|
||||
.animation(.elementDefault, value: viewState.itemViewStates)
|
||||
topPin
|
||||
}
|
||||
}
|
||||
|
||||
/// Used to mark the top of the scroll view and easily scroll to it
|
||||
private var topPin: some View {
|
||||
Divider()
|
||||
.id(topID)
|
||||
.hidden()
|
||||
.frame(height: 0)
|
||||
}
|
||||
|
||||
/// Used to mark the bottom of the scroll view and easily scroll to it
|
||||
private var bottomPin: some View {
|
||||
Divider()
|
||||
.id(bottomID)
|
||||
.hidden()
|
||||
.frame(height: 0)
|
||||
}
|
||||
|
||||
private var scrollToBottomButton: some View {
|
||||
Button {
|
||||
viewState.scrollToBottomPublisher.send()
|
||||
} label: {
|
||||
Image(systemName: "chevron.down")
|
||||
.font(.compound.bodyLG)
|
||||
.fontWeight(.semibold)
|
||||
.foregroundColor(.compound.iconSecondary)
|
||||
.padding(13)
|
||||
.offset(y: 1)
|
||||
.background {
|
||||
Circle()
|
||||
.fill(Color.compound.iconOnSolidPrimary)
|
||||
// Intentionally using system primary colour to get white/black.
|
||||
.shadow(color: .primary.opacity(0.33), radius: 2.0)
|
||||
}
|
||||
.padding()
|
||||
}
|
||||
.opacity(isScrolledToBottom ? 0.0 : 1.0)
|
||||
.accessibilityHidden(isScrolledToBottom)
|
||||
.animation(.elementDefault, value: isScrolledToBottom)
|
||||
}
|
||||
|
||||
private func paginateBackwardsIfNeeded() {
|
||||
guard let scrollView = scrollViewAdapter.scrollView,
|
||||
viewState.canBackPaginate,
|
||||
!viewState.isBackPaginating else {
|
||||
return
|
||||
}
|
||||
|
||||
let visibleHeight = scrollView.visibleSize.height
|
||||
let contentHeight = scrollView.contentSize.height
|
||||
let offset = scrollView.contentOffset.y + scrollView.contentInset.top
|
||||
let threshold = contentHeight - visibleHeight * 2
|
||||
|
||||
guard offset > threshold else {
|
||||
return
|
||||
}
|
||||
|
||||
paginationAction()
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Previews
|
||||
|
||||
struct TimelineView_Previews: PreviewProvider, TestablePreview {
|
||||
static let viewModel = RoomScreenViewModel(roomProxy: RoomProxyMock(with: .init(displayName: "Preview room")),
|
||||
timelineController: MockRoomTimelineController(),
|
||||
mediaProvider: MockMediaProvider(),
|
||||
mediaPlayerProvider: MediaPlayerProviderMock(),
|
||||
voiceMessageMediaManager: VoiceMessageMediaManagerMock(),
|
||||
userIndicatorController: ServiceLocator.shared.userIndicatorController,
|
||||
application: ApplicationMock.default,
|
||||
appSettings: ServiceLocator.shared.settings,
|
||||
analyticsService: ServiceLocator.shared.analytics,
|
||||
notificationCenter: NotificationCenterMock())
|
||||
|
||||
static var previews: some View {
|
||||
NavigationStack {
|
||||
RoomScreen(context: viewModel.context, composerToolbar: ComposerToolbar.mock())
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user