91 lines
3.1 KiB
Swift
91 lines
3.1 KiB
Swift
//
|
|
// ComposeReplyView.swift
|
|
// Tusker
|
|
//
|
|
// Created by Shadowfacts on 8/22/20.
|
|
// Copyright © 2020 Shadowfacts. All rights reserved.
|
|
//
|
|
|
|
import SwiftUI
|
|
|
|
struct ComposeReplyView: View {
|
|
let status: StatusMO
|
|
let stackPadding: CGFloat
|
|
|
|
@State private var displayNameHeight: CGFloat?
|
|
@State private var contentHeight: CGFloat?
|
|
|
|
@ObservedObject private var preferences = Preferences.shared
|
|
|
|
private let horizSpacing: CGFloat = 8
|
|
|
|
var body: some View {
|
|
HStack(alignment: .top, spacing: horizSpacing) {
|
|
GeometryReader(content: self.replyAvatarImage)
|
|
.frame(width: 50)
|
|
|
|
VStack(alignment: .leading, spacing: 0) {
|
|
HStack {
|
|
AccountDisplayNameLabel(account: status.account, fontSize: 17)
|
|
.lineLimit(1)
|
|
.layoutPriority(1)
|
|
|
|
Text(verbatim: "@\(status.account.acct)")
|
|
.font(.system(size: 17, weight: .light))
|
|
.foregroundColor(.secondary)
|
|
.lineLimit(1)
|
|
|
|
Spacer()
|
|
}
|
|
.background(GeometryReader { proxy in
|
|
Color.clear
|
|
.preference(key: DisplayNameHeightPrefKey.self, value: proxy.size.height)
|
|
.onPreferenceChange(DisplayNameHeightPrefKey.self) { newValue in
|
|
displayNameHeight = newValue
|
|
}
|
|
})
|
|
|
|
ComposeReplyContentView(status: status) { newHeight in
|
|
contentHeight = newHeight
|
|
}
|
|
.frame(height: contentHeight ?? 0)
|
|
}
|
|
}
|
|
}
|
|
|
|
private func replyAvatarImage(geometry: GeometryProxy) -> some View {
|
|
let scrollOffset = -geometry.frame(in: .named(ComposeView.coordinateSpaceOutsideOfScrollView)).minY
|
|
|
|
// add stackPadding so that the image is always at least stackPadding away from the top
|
|
var offset = scrollOffset + stackPadding
|
|
|
|
// offset can never be less than 0 (i.e., above the top of the in-reply-to content)
|
|
offset = max(offset, 0)
|
|
|
|
// subtract 50, because we care about where the bottom of the view is but the offset is relative to the top of the view
|
|
let maxOffset = (contentHeight ?? 0) + (displayNameHeight ?? 0) - 50
|
|
|
|
// once you scroll past the in-reply-to-content, the bottom of the avatar should be pinned to the bottom of the content
|
|
offset = min(offset, maxOffset)
|
|
|
|
return ComposeAvatarImageView(url: status.account.avatar)
|
|
.frame(width: 50, height: 50)
|
|
.cornerRadius(preferences.avatarStyle.cornerRadiusFraction * 50)
|
|
.offset(x: 0, y: offset)
|
|
}
|
|
|
|
}
|
|
|
|
private struct DisplayNameHeightPrefKey: PreferenceKey {
|
|
static var defaultValue: CGFloat = 0
|
|
static func reduce(value: inout CGFloat, nextValue: () -> CGFloat) {
|
|
value = nextValue()
|
|
}
|
|
}
|
|
|
|
//struct ComposeReplyView_Previews: PreviewProvider {
|
|
// static var previews: some View {
|
|
// ComposeReplyView()
|
|
// }
|
|
//}
|