Files
Luma/Sources/Shared/Models/ChatTimelineEntry.swift
T
wt cbb820a86e
iOS CI / Build and Test SwiftUI App (push) Canceled after 0s
Build Unsigned iOS and macOS Apps / Build Unsigned iOS IPA (push) Canceled after 0s
Build Unsigned iOS and macOS Apps / Build macOS ZIP (push) Canceled after 0s
migrate persistence from JSON to SwiftData
Models:
- Convert Conversation and ChatMessage to SwiftData @Model classes with
  a
  one-to-many relationship and cascade delete.
- Rename ChatMessage.id to clientID and drop Conversation.id in favor of
  jid
  (the string id would clash with PersistentIdentifier).
- Keep MessageReaction as a Codable value stored in an array attribute.

Persistence:
- Add ArchiveStore, a per-account ModelContainer/ModelContext that
  replaces
  the JSON ChatArchive with load/save/erase.
- Add ArchiveMetadataRecord for the durable MAM checkpoints, cursor,
  locally
  deleted message IDs and roster contact JIDs.
- Add LegacyArchiveImporter to import the old JSON snapshot once and
  delete
  the file afterwards, preserving existing history.

AppModel:
- Replace ChatArchive with ArchiveStore and persist via context.save();
  insert new models and delete the replaced object on upsert merges so
  SwiftData never keeps an orphaned duplicate.

Tests:
- Replace ChatArchiveTests with ArchiveStoreTests (store round-trip and
  legacy import) and drop the now-obsolete Codable round-trip
  assertions.
2026-08-18 22:58:18 +07:00

39 lines
1.2 KiB
Swift

import Foundation
/// A cached presentation row for the selected chat. Building day boundaries
/// once per message mutation avoids walking the full history during every
/// scroll-position or composer-state update.
struct ChatTimelineEntry: Identifiable, Hashable {
let message: ChatMessage
let startsNewDay: Bool
var id: String { message.clientID }
static func == (lhs: Self, rhs: Self) -> Bool {
lhs.message.clientID == rhs.message.clientID
&& lhs.startsNewDay == rhs.startsNewDay
}
func hash(into hasher: inout Hasher) {
hasher.combine(message.clientID)
hasher.combine(startsNewDay)
}
static func make(
from messages: [ChatMessage],
calendar: Calendar = .autoupdatingCurrent
) -> [ChatTimelineEntry] {
var previousTimestamp: Date?
return messages.map { message in
let startsNewDay = previousTimestamp.map {
!calendar.isDate($0, inSameDayAs: message.timestamp)
} ?? true
previousTimestamp = message.timestamp
return ChatTimelineEntry(
message: message,
startsNewDay: startsNewDay
)
}
}
}