Timeline highlight mentions (#595)
* Introduce fetchPages * Set up highlighting * Implement highlighting stage 1 * Implement highlighting stage 2 * Implement highlighting. * Fix merge * Add protocol * Remove debug prints
This commit is contained in:
parent
3e320e4b6d
commit
10946fef10
|
@ -54,11 +54,17 @@ public protocol AnyStatus {
|
||||||
var language: String? { get }
|
var language: String? { get }
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct Status: AnyStatus, Decodable, Identifiable, Equatable, Hashable {
|
protocol StatusUI {
|
||||||
|
var uiShouldHighlight: Bool? { get set }
|
||||||
|
}
|
||||||
|
|
||||||
|
public struct Status: AnyStatus, Decodable, Identifiable, Equatable, Hashable, StatusUI {
|
||||||
public var viewId: String {
|
public var viewId: String {
|
||||||
id + createdAt + (editedAt ?? "")
|
id + createdAt + (editedAt ?? "")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public var uiShouldHighlight: Bool?
|
||||||
|
|
||||||
public static func == (lhs: Status, rhs: Status) -> Bool {
|
public static func == (lhs: Status, rhs: Status) -> Bool {
|
||||||
lhs.id == rhs.id
|
lhs.id == rhs.id
|
||||||
}
|
}
|
||||||
|
|
|
@ -83,6 +83,7 @@ public struct StatusRowView: View {
|
||||||
.contextMenu {
|
.contextMenu {
|
||||||
contextMenu
|
contextMenu
|
||||||
}
|
}
|
||||||
|
.listRowBackground(viewModel.shouldHighlightRow ? theme.secondaryBackgroundColor : theme.primaryBackgroundColor)
|
||||||
.swipeActions(edge: .trailing) {
|
.swipeActions(edge: .trailing) {
|
||||||
trailinSwipeActions
|
trailinSwipeActions
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,6 +36,10 @@ public class StatusRowViewModel: ObservableObject {
|
||||||
status.reblog?.filtered?.first ?? status.filtered?.first
|
status.reblog?.filtered?.first ?? status.filtered?.first
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var shouldHighlightRow: Bool {
|
||||||
|
status.uiShouldHighlight != nil
|
||||||
|
}
|
||||||
|
|
||||||
var client: Client?
|
var client: Client?
|
||||||
|
|
||||||
public init(status: Status,
|
public init(status: Status,
|
||||||
|
|
|
@ -22,7 +22,12 @@ class TimelineViewModel: ObservableObject {
|
||||||
private var canStreamEvents: Bool = true
|
private var canStreamEvents: Bool = true
|
||||||
|
|
||||||
let pendingStatusesObserver: PendingStatusesObserver = .init()
|
let pendingStatusesObserver: PendingStatusesObserver = .init()
|
||||||
let cache: TimelineCache = .shared
|
|
||||||
|
private var accountId: String? {
|
||||||
|
CurrentAccount.shared.account?.id
|
||||||
|
}
|
||||||
|
|
||||||
|
private let cache: TimelineCache = .shared
|
||||||
|
|
||||||
@Published var scrollToStatus: String?
|
@Published var scrollToStatus: String?
|
||||||
|
|
||||||
|
@ -57,7 +62,7 @@ class TimelineViewModel: ObservableObject {
|
||||||
client?.server ?? "Error"
|
client?.server ?? "Error"
|
||||||
}
|
}
|
||||||
|
|
||||||
func fetchTag(id: String) async {
|
private func fetchTag(id: String) async {
|
||||||
guard let client else { return }
|
guard let client else { return }
|
||||||
do {
|
do {
|
||||||
tag = try await client.get(endpoint: Tags.tag(id: id))
|
tag = try await client.get(endpoint: Tags.tag(id: id))
|
||||||
|
@ -71,7 +76,13 @@ class TimelineViewModel: ObservableObject {
|
||||||
!statuses.contains(where: { $0.id == event.status.id })
|
!statuses.contains(where: { $0.id == event.status.id })
|
||||||
{
|
{
|
||||||
pendingStatusesObserver.pendingStatuses.insert(event.status.id, at: 0)
|
pendingStatusesObserver.pendingStatuses.insert(event.status.id, at: 0)
|
||||||
statuses.insert(event.status, at: 0)
|
var newStatus = event.status
|
||||||
|
if let accountId {
|
||||||
|
if newStatus.mentions.first(where: { $0.id == accountId }) != nil {
|
||||||
|
newStatus.uiShouldHighlight = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
statuses.insert(newStatus, at: 0)
|
||||||
Task {
|
Task {
|
||||||
await cacheHome()
|
await cacheHome()
|
||||||
}
|
}
|
||||||
|
@ -153,7 +164,7 @@ extension TimelineViewModel: StatusesFetcher {
|
||||||
minId: nil,
|
minId: nil,
|
||||||
offset: statuses.count))
|
offset: statuses.count))
|
||||||
|
|
||||||
|
updateMentionsToBeHighlighted(&statuses)
|
||||||
ReblogCache.shared.removeDuplicateReblogs(&statuses)
|
ReblogCache.shared.removeDuplicateReblogs(&statuses)
|
||||||
|
|
||||||
await cacheHome()
|
await cacheHome()
|
||||||
|
@ -238,6 +249,7 @@ extension TimelineViewModel: StatusesFetcher {
|
||||||
{
|
{
|
||||||
pagesLoaded += 1
|
pagesLoaded += 1
|
||||||
|
|
||||||
|
updateMentionsToBeHighlighted(&newStatuses)
|
||||||
ReblogCache.shared.removeDuplicateReblogs(&newStatuses)
|
ReblogCache.shared.removeDuplicateReblogs(&newStatuses)
|
||||||
|
|
||||||
allStatuses.insert(contentsOf: newStatuses, at: 0)
|
allStatuses.insert(contentsOf: newStatuses, at: 0)
|
||||||
|
@ -259,16 +271,28 @@ extension TimelineViewModel: StatusesFetcher {
|
||||||
minId: nil,
|
minId: nil,
|
||||||
offset: statuses.count))
|
offset: statuses.count))
|
||||||
|
|
||||||
|
|
||||||
|
updateMentionsToBeHighlighted(&newStatuses)
|
||||||
ReblogCache.shared.removeDuplicateReblogs(&newStatuses)
|
ReblogCache.shared.removeDuplicateReblogs(&newStatuses)
|
||||||
|
|
||||||
|
|
||||||
statuses.append(contentsOf: newStatuses)
|
statuses.append(contentsOf: newStatuses)
|
||||||
|
|
||||||
statusesState = .display(statuses: statuses, nextPageState: .hasNextPage)
|
statusesState = .display(statuses: statuses, nextPageState: .hasNextPage)
|
||||||
} catch {
|
} catch {
|
||||||
statusesState = .error(error: error)
|
statusesState = .error(error: error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private func updateMentionsToBeHighlighted(_ statuses: inout [Status]) {
|
||||||
|
if !statuses.isEmpty, let accountId {
|
||||||
|
for i in statuses.indices {
|
||||||
|
if statuses[i].mentions.first(where: { $0.id == accountId }) != nil {
|
||||||
|
statuses[i].uiShouldHighlight = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func statusDidAppear(status: Status) {
|
func statusDidAppear(status: Status) {
|
||||||
pendingStatusesObserver.removeStatus(status: status)
|
pendingStatusesObserver.removeStatus(status: status)
|
||||||
visibileStatusesIds.insert(status.id)
|
visibileStatusesIds.insert(status.id)
|
||||||
|
|
Loading…
Reference in New Issue