mirror of
https://github.com/Dimillian/IceCubesApp.git
synced 2024-11-29 19:51:08 +00:00
Improve the display of replies (#1672)
Threads/replies are now shown more clearly. Each reply has an indentation level (and therefore the number of vertical lines) one more than its direct parent. This leads to siblings having the same indentation level. It makes understanding somewhat complex thread structures way easier. Previously, a reply was only indented if it came directly after its parent. If a toot had more than one reply, the structure was nearly indecipherable, as it wasn't clear which the parent post of the second (or later) toot was. An example is "https://mastodon.social/@mhoye/110452462852364819" and all of its replies. Signed-off-by: Paul Schuetz <pa.schuetz@web.de>
This commit is contained in:
parent
4b74532048
commit
59e5eba860
4 changed files with 31 additions and 31 deletions
|
@ -25,8 +25,8 @@ private struct IsStatusFocused: EnvironmentKey {
|
|||
static let defaultValue: Bool = false
|
||||
}
|
||||
|
||||
private struct IsStatusReplyToPrevious: EnvironmentKey {
|
||||
static let defaultValue: Bool = false
|
||||
private struct IndentationLevel: EnvironmentKey {
|
||||
static let defaultValue: UInt = 0
|
||||
}
|
||||
|
||||
public extension EnvironmentValues {
|
||||
|
@ -60,8 +60,8 @@ public extension EnvironmentValues {
|
|||
set { self[IsStatusFocused.self] = newValue }
|
||||
}
|
||||
|
||||
var isStatusReplyToPrevious: Bool {
|
||||
get { self[IsStatusReplyToPrevious.self] }
|
||||
set { self[IsStatusReplyToPrevious.self] = newValue }
|
||||
var indentationLevel: UInt {
|
||||
get { self[IndentationLevel.self] }
|
||||
set { self[IndentationLevel.self] = newValue }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -103,15 +103,15 @@ public struct StatusDetailView: View {
|
|||
|
||||
private func makeStatusesListView(statuses: [Status]) -> some View {
|
||||
ForEach(statuses) { status in
|
||||
let isReplyToPrevious = viewModel.isReplyToPreviousCache[status.id] ?? false
|
||||
let indentationLevel = viewModel.getIndentationLevel(id: status.id)
|
||||
let viewModel: StatusRowViewModel = .init(status: status,
|
||||
client: client,
|
||||
routerPath: routerPath)
|
||||
let isFocused = self.viewModel.statusId == status.id
|
||||
|
||||
StatusRowView(viewModel: viewModel)
|
||||
.environment(\.extraLeadingInset, isReplyToPrevious ? 10 : 0)
|
||||
.environment(\.isStatusReplyToPrevious, isReplyToPrevious)
|
||||
.environment(\.extraLeadingInset, (indentationLevel > 0) ? 10 : 0)
|
||||
.environment(\.indentationLevel, indentationLevel)
|
||||
.environment(\.isStatusFocused, isFocused)
|
||||
.overlay {
|
||||
if isFocused {
|
||||
|
|
|
@ -19,9 +19,10 @@ import SwiftUI
|
|||
var state: State = .loading
|
||||
var title: LocalizedStringKey = ""
|
||||
var scrollToId: String?
|
||||
static var maxIndent = UInt(7)
|
||||
|
||||
@ObservationIgnored
|
||||
var isReplyToPreviousCache: [String: Bool] = [:]
|
||||
var indentationLevelPreviousCache: [String: UInt] = [:]
|
||||
|
||||
init(statusId: String) {
|
||||
state = .loading
|
||||
|
@ -35,7 +36,7 @@ import SwiftUI
|
|||
statusId = status.id
|
||||
remoteStatusURL = nil
|
||||
if status.inReplyToId != nil {
|
||||
isReplyToPreviousCache[status.id] = true
|
||||
indentationLevelPreviousCache[status.id] = 1
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -111,24 +112,15 @@ import SwiftUI
|
|||
}
|
||||
|
||||
private func cacheReplyTopPrevious(statuses: [Status]) {
|
||||
isReplyToPreviousCache = [:]
|
||||
indentationLevelPreviousCache = [:]
|
||||
for status in statuses {
|
||||
var isReplyToPrevious: Bool = false
|
||||
if let index = statuses.firstIndex(where: { $0.id == status.id }),
|
||||
index > 0,
|
||||
statuses[index - 1].id == status.inReplyToId
|
||||
{
|
||||
if index == 1, statuses.count > 2 {
|
||||
let nextStatus = statuses[2]
|
||||
isReplyToPrevious = nextStatus.inReplyToId == status.id
|
||||
} else if statuses.count == 2 {
|
||||
isReplyToPrevious = false
|
||||
if let inReplyToId = status.inReplyToId,
|
||||
let prevIndent = indentationLevelPreviousCache[inReplyToId] {
|
||||
indentationLevelPreviousCache[status.id] = prevIndent + 1
|
||||
} else {
|
||||
isReplyToPrevious = true
|
||||
indentationLevelPreviousCache[status.id] = 0
|
||||
}
|
||||
}
|
||||
isReplyToPreviousCache[status.id] = isReplyToPrevious
|
||||
}
|
||||
}
|
||||
|
||||
func handleEvent(event: any StreamEvent, currentAccount: Account?) {
|
||||
|
@ -146,4 +138,8 @@ import SwiftUI
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
func getIndentationLevel(id: String) -> UInt {
|
||||
min(indentationLevelPreviousCache[id] ?? 0, Self.maxIndent)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@ public struct StatusRowView: View {
|
|||
@Environment(\.isCompact) private var isCompact: Bool
|
||||
@Environment(\.accessibilityVoiceOverEnabled) private var accessibilityVoiceOverEnabled
|
||||
@Environment(\.isStatusFocused) private var isFocused
|
||||
@Environment(\.isStatusReplyToPrevious) private var isStatusReplyToPrevious
|
||||
@Environment(\.indentationLevel) private var indentationLevel
|
||||
|
||||
@Environment(QuickLook.self) private var quickLook
|
||||
@Environment(Theme.self) private var theme
|
||||
|
@ -32,11 +32,15 @@ public struct StatusRowView: View {
|
|||
|
||||
public var body: some View {
|
||||
HStack(spacing: 0) {
|
||||
if isStatusReplyToPrevious {
|
||||
HStack(spacing: 3) {
|
||||
ForEach(0..<indentationLevel, id: \.self) {_ in
|
||||
Rectangle()
|
||||
.fill(theme.tintColor)
|
||||
.frame(width: 2)
|
||||
.accessibilityHidden(true)
|
||||
}
|
||||
}
|
||||
if indentationLevel > 0 {
|
||||
Spacer(minLength: 8)
|
||||
}
|
||||
VStack(alignment: .leading) {
|
||||
|
|
Loading…
Reference in a new issue