Files
letro-ios/ElementX/Sources/Other/ReversedScrollView.swift
Stefan Ceriu 4def45a57b New timeline (#276) (#280)
* Fixes #276 - Rebuilt room timeline:
    - Removed the need for the ListCollectionViewAdapter
    - Rewrote the TimelineItemList without using introspection
    - Added ReversedScrollView for laying out items at the bottom/trailing
    - Rewrote TimelineProvider diffing through CollectionDifference (similar to the RoomSummaryProvider)
    - Added back `scrollDismissesKeyboard`  behavior
    - Various other tweaks and fixes
- Fixed various warnings:
    - removed async AttributedStringBuilder as AttributedString is non-sendable, made the RoomTimelineItemFactory synchronous
    - removed unused virtual timeline items
    - removed unused isOutgoing property from the FormattedBodyText
* Make TimelineItemContextMenuActions indentifiable and specify contextMenu identifiers
* Bump the matrix-rust-components-swift to v1.0.16-alpha
* Add changes file and changelog contribution guide
* Fix attributed string builder unit tests
2022-11-02 13:03:34 +02:00

83 lines
2.4 KiB
Swift

//
// 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 SwiftUI
/// A SwiftUI scroll view that lays out its content starting at the bottom or trailing
/// https://www.thirdrocktechkno.com/blog/implementing-reversed-scrolling-behaviour-in-swiftui/
struct ReversedScrollView<Content: View>: View {
private let axis: Axis.Set
private let leadingSpace: CGFloat
private let content: Content
init(_ axis: Axis.Set = .horizontal, leadingSpace: CGFloat = 0, @ViewBuilder builder: () -> Content) {
self.axis = axis
self.leadingSpace = leadingSpace
content = builder()
}
var body: some View {
GeometryReader { proxy in
ScrollView(axis, showsIndicators: false) {
Stack(axis) {
Spacer(minLength: leadingSpace)
content
}
.frame(
minWidth: minWidth(in: proxy, for: axis),
minHeight: minHeight(in: proxy, for: axis)
)
}
}
}
private func minWidth(in proxy: GeometryProxy, for axis: Axis.Set) -> CGFloat? {
axis.contains(.horizontal) ? proxy.size.width : nil
}
private func minHeight(in proxy: GeometryProxy, for axis: Axis.Set) -> CGFloat? {
axis.contains(.vertical) ? proxy.size.height : nil
}
}
private struct Stack<Content: View>: View {
var axis: Axis.Set
var content: Content
init(_ axis: Axis.Set = .vertical, @ViewBuilder builder: () -> Content) {
self.axis = axis
content = builder()
}
var body: some View {
switch axis {
case .horizontal:
HStack {
content
}
case .vertical:
VStack {
content
}
default:
VStack {
content
}
}
}
}