- Drive chat list, timeline and forward picker from SwiftData @Query instead of AppModel's in-memory arrays; inject the per-account ModelContext from RootView with an in-memory fallback. - Physically delete locally deleted messages (context.delete) and purge rows marked deleted by older builds on store open, so @Query views never resurrect them. - Delete the legacy JSON snapshot only after a successful import save and restore the completeUntilFirstUserAuthentication data protection attribute on the store file. - Mirror the old ChatArchive tolerant decoding in LegacyArchiveImporter so snapshots from older schema versions (missing reactions, isGroupMessage, roster fields) still import. - Cover the new behaviour in ArchiveStoreTests and guard it with new verify.sh invariants; update AGENTS.md, ARCHITECTURE.md and SECURITY.md.
49 lines
1.6 KiB
Swift
49 lines
1.6 KiB
Swift
import QuickLook
|
|
import SwiftData
|
|
import SwiftUI
|
|
|
|
struct RootView: View {
|
|
@ObservedObject var model: AppModel
|
|
|
|
var body: some View {
|
|
ZStack {
|
|
Group {
|
|
if model.account == nil {
|
|
LoginView(model: model)
|
|
} else {
|
|
MainChatView(model: model)
|
|
.environment(\.modelContext, model.modelContext)
|
|
}
|
|
}
|
|
|
|
if let item = model.mediaViewerItem {
|
|
MediaViewer(item: item, onClose: model.closeMediaViewer)
|
|
.transition(.opacity.combined(with: .scale(scale: 0.98)))
|
|
.zIndex(100)
|
|
}
|
|
|
|
if let call = model.activeCall {
|
|
CallView(model: model, call: call)
|
|
.transition(.opacity.combined(with: .scale(scale: 1.015)))
|
|
.zIndex(200)
|
|
}
|
|
}
|
|
.animation(.easeInOut(duration: 0.22), value: model.account?.id)
|
|
.animation(.easeInOut(duration: 0.2), value: model.mediaViewerItem?.id)
|
|
.animation(.easeInOut(duration: 0.2), value: model.activeCall?.id)
|
|
.alert("Luma", isPresented: errorBinding) {
|
|
Button("OK") { model.clearError() }
|
|
} message: {
|
|
Text(model.errorMessage ?? "Неизвестная ошибка")
|
|
}
|
|
.quickLookPreview($model.previewURL)
|
|
}
|
|
|
|
private var errorBinding: Binding<Bool> {
|
|
Binding(
|
|
get: { model.errorMessage != nil },
|
|
set: { visible in if !visible { model.clearError() } }
|
|
)
|
|
}
|
|
}
|