Add 1-hour cache timeout and fix pull-to-refresh across iOS
- Add configurable cache timeout (CACHE_TIMEOUT_MS) to DataManager - Fix cache to work with empty results (contractors, documents, residences) - Change Documents/Warranties view to use client-side filtering for cache efficiency - Add pull-to-refresh support for empty state views in ListAsyncContentView - Fix ContractorsListView to pass forceRefresh parameter correctly - Fix TaskViewModel loading spinner not stopping after refresh completes - Remove duplicate cache checks in iOS ViewModels, delegate to Kotlin APILayer 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -56,8 +56,6 @@ class DocumentViewModelWrapper: ObservableObject {
|
||||
@Published var deleteState: DeleteState = DeleteStateIdle()
|
||||
@Published var deleteImageState: DeleteImageState = DeleteImageStateIdle()
|
||||
|
||||
private let documentApi = DocumentApi(client: ApiClient_iosKt.createHttpClient())
|
||||
|
||||
func loadDocuments(
|
||||
residenceId: Int32? = nil,
|
||||
documentType: String? = nil,
|
||||
@@ -68,29 +66,22 @@ class DocumentViewModelWrapper: ObservableObject {
|
||||
tags: String? = nil,
|
||||
search: String? = nil
|
||||
) {
|
||||
guard let token = TokenStorage.shared.getToken() else {
|
||||
DispatchQueue.main.async {
|
||||
self.documentsState = DocumentStateError(message: "Not authenticated")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
DispatchQueue.main.async {
|
||||
self.documentsState = DocumentStateLoading()
|
||||
}
|
||||
|
||||
Task {
|
||||
do {
|
||||
let result = try await documentApi.getDocuments(
|
||||
token: token,
|
||||
residenceId: residenceId != nil ? KotlinInt(integerLiteral: Int(residenceId!)) : nil,
|
||||
let result = try await APILayer.shared.getDocuments(
|
||||
residenceId: residenceId != nil ? KotlinInt(int: residenceId!) : nil,
|
||||
documentType: documentType,
|
||||
category: category,
|
||||
contractorId: contractorId != nil ? KotlinInt(integerLiteral: Int(contractorId!)) : nil,
|
||||
contractorId: contractorId != nil ? KotlinInt(int: contractorId!) : nil,
|
||||
isActive: isActive != nil ? KotlinBoolean(bool: isActive!) : nil,
|
||||
expiringSoon: expiringSoon != nil ? KotlinInt(integerLiteral: Int(expiringSoon!)) : nil,
|
||||
expiringSoon: expiringSoon != nil ? KotlinInt(int: expiringSoon!) : nil,
|
||||
tags: tags,
|
||||
search: search
|
||||
search: search,
|
||||
forceRefresh: false
|
||||
)
|
||||
|
||||
await MainActor.run {
|
||||
@@ -110,20 +101,13 @@ class DocumentViewModelWrapper: ObservableObject {
|
||||
}
|
||||
|
||||
func loadDocumentDetail(id: Int32) {
|
||||
guard let token = TokenStorage.shared.getToken() else {
|
||||
DispatchQueue.main.async {
|
||||
self.documentDetailState = DocumentDetailStateError(message: "Not authenticated")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
DispatchQueue.main.async {
|
||||
self.documentDetailState = DocumentDetailStateLoading()
|
||||
}
|
||||
|
||||
Task {
|
||||
do {
|
||||
let result = try await documentApi.getDocument(token: token, id: id)
|
||||
let result = try await APILayer.shared.getDocument(id: id, forceRefresh: false)
|
||||
|
||||
await MainActor.run {
|
||||
if let success = result as? ApiResultSuccess<Document>, let document = success.data {
|
||||
@@ -161,21 +145,13 @@ class DocumentViewModelWrapper: ObservableObject {
|
||||
startDate: String? = nil,
|
||||
endDate: String? = nil
|
||||
) {
|
||||
guard let token = TokenStorage.shared.getToken() else {
|
||||
DispatchQueue.main.async {
|
||||
self.updateState = UpdateStateError(message: "Not authenticated")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
DispatchQueue.main.async {
|
||||
self.updateState = UpdateStateLoading()
|
||||
}
|
||||
|
||||
Task {
|
||||
do {
|
||||
let result = try await documentApi.updateDocument(
|
||||
token: token,
|
||||
let result = try await APILayer.shared.updateDocument(
|
||||
id: id,
|
||||
title: title,
|
||||
documentType: documentType,
|
||||
@@ -184,7 +160,7 @@ class DocumentViewModelWrapper: ObservableObject {
|
||||
tags: tags,
|
||||
notes: notes,
|
||||
contractorId: nil,
|
||||
isActive: KotlinBoolean(bool: isActive),
|
||||
isActive: isActive,
|
||||
itemName: itemName,
|
||||
modelNumber: modelNumber,
|
||||
serialNumber: serialNumber,
|
||||
@@ -195,10 +171,7 @@ class DocumentViewModelWrapper: ObservableObject {
|
||||
claimWebsite: claimWebsite,
|
||||
purchaseDate: purchaseDate,
|
||||
startDate: startDate,
|
||||
endDate: endDate,
|
||||
fileBytes: nil,
|
||||
fileName: nil,
|
||||
mimeType: nil
|
||||
endDate: endDate
|
||||
)
|
||||
|
||||
await MainActor.run {
|
||||
@@ -219,20 +192,13 @@ class DocumentViewModelWrapper: ObservableObject {
|
||||
}
|
||||
|
||||
func deleteDocument(id: Int32) {
|
||||
guard let token = TokenStorage.shared.getToken() else {
|
||||
DispatchQueue.main.async {
|
||||
self.deleteState = DeleteStateError(message: "Not authenticated")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
DispatchQueue.main.async {
|
||||
self.deleteState = DeleteStateLoading()
|
||||
}
|
||||
|
||||
Task {
|
||||
do {
|
||||
let result = try await documentApi.deleteDocument(token: token, id: id)
|
||||
let result = try await APILayer.shared.deleteDocument(id: id)
|
||||
|
||||
await MainActor.run {
|
||||
if result is ApiResultSuccess<KotlinUnit> {
|
||||
@@ -262,20 +228,13 @@ class DocumentViewModelWrapper: ObservableObject {
|
||||
}
|
||||
|
||||
func deleteDocumentImage(imageId: Int32) {
|
||||
guard let token = TokenStorage.shared.getToken() else {
|
||||
DispatchQueue.main.async {
|
||||
self.deleteImageState = DeleteImageStateError(message: "Not authenticated")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
DispatchQueue.main.async {
|
||||
self.deleteImageState = DeleteImageStateLoading()
|
||||
}
|
||||
|
||||
Task {
|
||||
do {
|
||||
let result = try await documentApi.deleteDocumentImage(token: token, imageId: imageId)
|
||||
let result = try await APILayer.shared.deleteDocumentImage(imageId: imageId)
|
||||
|
||||
await MainActor.run {
|
||||
if result is ApiResultSuccess<KotlinUnit> {
|
||||
|
||||
Reference in New Issue
Block a user