Implementing SwiftData storage service
This commit is contained in:
parent
df15a154be
commit
e91fd89eff
@ -28,6 +28,10 @@
|
|||||||
7A1441662C297EDE00E79018 /* NotesScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A1441652C297EDE00E79018 /* NotesScreen.swift */; };
|
7A1441662C297EDE00E79018 /* NotesScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A1441652C297EDE00E79018 /* NotesScreen.swift */; };
|
||||||
7A1441682C297EFD00E79018 /* NotesViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A1441672C297EFD00E79018 /* NotesViewModel.swift */; };
|
7A1441682C297EFD00E79018 /* NotesViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A1441672C297EFD00E79018 /* NotesViewModel.swift */; };
|
||||||
7A17ADA02DC9F4A5002BA02A /* ScreenInput.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A17AD9F2DC9F4A5002BA02A /* ScreenInput.swift */; };
|
7A17ADA02DC9F4A5002BA02A /* ScreenInput.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A17AD9F2DC9F4A5002BA02A /* ScreenInput.swift */; };
|
||||||
|
7A1AE64F2DFB22EC00ECFC4D /* SwiftDataStorageService+Utils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A1AE64E2DFB22EC00ECFC4D /* SwiftDataStorageService+Utils.swift */; };
|
||||||
|
7A1AE6512DFB235300ECFC4D /* SwiftDataStorageService+Notes.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A1AE6502DFB235300ECFC4D /* SwiftDataStorageService+Notes.swift */; };
|
||||||
|
7A1AE6532DFB2AD900ECFC4D /* SwiftDataStorageService+Events.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A1AE6522DFB2AD900ECFC4D /* SwiftDataStorageService+Events.swift */; };
|
||||||
|
7A1AE6552DFB2E9D00ECFC4D /* SwiftDataStorageService+AudioRecords.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A1AE6542DFB2E9D00ECFC4D /* SwiftDataStorageService+AudioRecords.swift */; };
|
||||||
7A1CF81629A42117007962DA /* Realm.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A1CF81529A42117007962DA /* Realm.swift */; };
|
7A1CF81629A42117007962DA /* Realm.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A1CF81529A42117007962DA /* Realm.swift */; };
|
||||||
7A1E78F62CE900330004B740 /* ReportScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A1E78F52CE900330004B740 /* ReportScreen.swift */; };
|
7A1E78F62CE900330004B740 /* ReportScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A1E78F52CE900330004B740 /* ReportScreen.swift */; };
|
||||||
7A1E78F82CE900440004B740 /* ReportViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A1E78F72CE900440004B740 /* ReportViewModel.swift */; };
|
7A1E78F82CE900440004B740 /* ReportViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A1E78F72CE900440004B740 /* ReportViewModel.swift */; };
|
||||||
@ -167,6 +171,7 @@
|
|||||||
7AD857262DF876C9009E4B72 /* SDVehicleNote.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AD857252DF876C9009E4B72 /* SDVehicleNote.swift */; };
|
7AD857262DF876C9009E4B72 /* SDVehicleNote.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AD857252DF876C9009E4B72 /* SDVehicleNote.swift */; };
|
||||||
7AD857282DF87733009E4B72 /* SDDebugInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AD857272DF87733009E4B72 /* SDDebugInfo.swift */; };
|
7AD857282DF87733009E4B72 /* SDDebugInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AD857272DF87733009E4B72 /* SDDebugInfo.swift */; };
|
||||||
7AD8572A2DF87928009E4B72 /* SDAudioRecord.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AD857292DF87928009E4B72 /* SDAudioRecord.swift */; };
|
7AD8572A2DF87928009E4B72 /* SDAudioRecord.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AD857292DF87928009E4B72 /* SDAudioRecord.swift */; };
|
||||||
|
7AD8572D2DF95F72009E4B72 /* SwiftDataStorageService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AD8572C2DF95F72009E4B72 /* SwiftDataStorageService.swift */; };
|
||||||
7ADCBC572DB51739002522C0 /* AutoCatApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7ADCBC562DB51739002522C0 /* AutoCatApp.swift */; };
|
7ADCBC572DB51739002522C0 /* AutoCatApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7ADCBC562DB51739002522C0 /* AutoCatApp.swift */; };
|
||||||
7ADF6C99250F872C00F237B2 /* RoadNumbers.otf in Resources */ = {isa = PBXBuildFile; fileRef = 7ADF6C98250F872C00F237B2 /* RoadNumbers.otf */; };
|
7ADF6C99250F872C00F237B2 /* RoadNumbers.otf in Resources */ = {isa = PBXBuildFile; fileRef = 7ADF6C98250F872C00F237B2 /* RoadNumbers.otf */; };
|
||||||
7ADF6CA12512244400F237B2 /* MapExt.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7ADF6CA02512244400F237B2 /* MapExt.swift */; };
|
7ADF6CA12512244400F237B2 /* MapExt.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7ADF6CA02512244400F237B2 /* MapExt.swift */; };
|
||||||
@ -289,6 +294,10 @@
|
|||||||
7A1441672C297EFD00E79018 /* NotesViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotesViewModel.swift; sourceTree = "<group>"; };
|
7A1441672C297EFD00E79018 /* NotesViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotesViewModel.swift; sourceTree = "<group>"; };
|
||||||
7A15051124DB3E3000F39631 /* AnyEncodable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnyEncodable.swift; sourceTree = "<group>"; };
|
7A15051124DB3E3000F39631 /* AnyEncodable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnyEncodable.swift; sourceTree = "<group>"; };
|
||||||
7A17AD9F2DC9F4A5002BA02A /* ScreenInput.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScreenInput.swift; sourceTree = "<group>"; };
|
7A17AD9F2DC9F4A5002BA02A /* ScreenInput.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScreenInput.swift; sourceTree = "<group>"; };
|
||||||
|
7A1AE64E2DFB22EC00ECFC4D /* SwiftDataStorageService+Utils.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SwiftDataStorageService+Utils.swift"; sourceTree = "<group>"; };
|
||||||
|
7A1AE6502DFB235300ECFC4D /* SwiftDataStorageService+Notes.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SwiftDataStorageService+Notes.swift"; sourceTree = "<group>"; };
|
||||||
|
7A1AE6522DFB2AD900ECFC4D /* SwiftDataStorageService+Events.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SwiftDataStorageService+Events.swift"; sourceTree = "<group>"; };
|
||||||
|
7A1AE6542DFB2E9D00ECFC4D /* SwiftDataStorageService+AudioRecords.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SwiftDataStorageService+AudioRecords.swift"; sourceTree = "<group>"; };
|
||||||
7A1CF81529A42117007962DA /* Realm.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Realm.swift; sourceTree = "<group>"; };
|
7A1CF81529A42117007962DA /* Realm.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Realm.swift; sourceTree = "<group>"; };
|
||||||
7A1E78F52CE900330004B740 /* ReportScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReportScreen.swift; sourceTree = "<group>"; };
|
7A1E78F52CE900330004B740 /* ReportScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReportScreen.swift; sourceTree = "<group>"; };
|
||||||
7A1E78F72CE900440004B740 /* ReportViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReportViewModel.swift; sourceTree = "<group>"; };
|
7A1E78F72CE900440004B740 /* ReportViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReportViewModel.swift; sourceTree = "<group>"; };
|
||||||
@ -432,6 +441,7 @@
|
|||||||
7AD857252DF876C9009E4B72 /* SDVehicleNote.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SDVehicleNote.swift; sourceTree = "<group>"; };
|
7AD857252DF876C9009E4B72 /* SDVehicleNote.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SDVehicleNote.swift; sourceTree = "<group>"; };
|
||||||
7AD857272DF87733009E4B72 /* SDDebugInfo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SDDebugInfo.swift; sourceTree = "<group>"; };
|
7AD857272DF87733009E4B72 /* SDDebugInfo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SDDebugInfo.swift; sourceTree = "<group>"; };
|
||||||
7AD857292DF87928009E4B72 /* SDAudioRecord.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SDAudioRecord.swift; sourceTree = "<group>"; };
|
7AD857292DF87928009E4B72 /* SDAudioRecord.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SDAudioRecord.swift; sourceTree = "<group>"; };
|
||||||
|
7AD8572C2DF95F72009E4B72 /* SwiftDataStorageService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwiftDataStorageService.swift; sourceTree = "<group>"; };
|
||||||
7ADCBC562DB51739002522C0 /* AutoCatApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AutoCatApp.swift; sourceTree = "<group>"; };
|
7ADCBC562DB51739002522C0 /* AutoCatApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AutoCatApp.swift; sourceTree = "<group>"; };
|
||||||
7ADF6C98250F872C00F237B2 /* RoadNumbers.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = RoadNumbers.otf; sourceTree = "<group>"; };
|
7ADF6C98250F872C00F237B2 /* RoadNumbers.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = RoadNumbers.otf; sourceTree = "<group>"; };
|
||||||
7ADF6CA02512244400F237B2 /* MapExt.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MapExt.swift; sourceTree = "<group>"; };
|
7ADF6CA02512244400F237B2 /* MapExt.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MapExt.swift; sourceTree = "<group>"; };
|
||||||
@ -766,6 +776,7 @@
|
|||||||
7A60D24B2C5A9D2700D13F7B /* LocationService */,
|
7A60D24B2C5A9D2700D13F7B /* LocationService */,
|
||||||
7AB5873D2C42FF4000FA7B66 /* ApiService */,
|
7AB5873D2C42FF4000FA7B66 /* ApiService */,
|
||||||
7AB587302C42D35900FA7B66 /* StorageService */,
|
7AB587302C42D35900FA7B66 /* StorageService */,
|
||||||
|
7AD8572B2DF95F1E009E4B72 /* SwiftDataStorageService */,
|
||||||
);
|
);
|
||||||
path = Services;
|
path = Services;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@ -1053,6 +1064,18 @@
|
|||||||
path = NumberEditView;
|
path = NumberEditView;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
|
7AD8572B2DF95F1E009E4B72 /* SwiftDataStorageService */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
7AD8572C2DF95F72009E4B72 /* SwiftDataStorageService.swift */,
|
||||||
|
7A1AE64E2DFB22EC00ECFC4D /* SwiftDataStorageService+Utils.swift */,
|
||||||
|
7A1AE6502DFB235300ECFC4D /* SwiftDataStorageService+Notes.swift */,
|
||||||
|
7A1AE6522DFB2AD900ECFC4D /* SwiftDataStorageService+Events.swift */,
|
||||||
|
7A1AE6542DFB2E9D00ECFC4D /* SwiftDataStorageService+AudioRecords.swift */,
|
||||||
|
);
|
||||||
|
path = SwiftDataStorageService;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
7ADFC9552DAD026C001A43E3 /* GoogleAuthScreen */ = {
|
7ADFC9552DAD026C001A43E3 /* GoogleAuthScreen */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
@ -1490,7 +1513,9 @@
|
|||||||
7A64A21E2C19E8D500284124 /* VehicleAdDto.swift in Sources */,
|
7A64A21E2C19E8D500284124 /* VehicleAdDto.swift in Sources */,
|
||||||
7AD857202DF874F8009E4B72 /* SDVehicleEvent.swift in Sources */,
|
7AD857202DF874F8009E4B72 /* SDVehicleEvent.swift in Sources */,
|
||||||
7AF6D2202677C1680086EA64 /* Filter.swift in Sources */,
|
7AF6D2202677C1680086EA64 /* Filter.swift in Sources */,
|
||||||
|
7A1AE6552DFB2E9D00ECFC4D /* SwiftDataStorageService+AudioRecords.swift in Sources */,
|
||||||
7A761C042677F18E0005F28F /* ApiService.swift in Sources */,
|
7A761C042677F18E0005F28F /* ApiService.swift in Sources */,
|
||||||
|
7A1AE6532DFB2AD900ECFC4D /* SwiftDataStorageService+Events.swift in Sources */,
|
||||||
7A95197B2D80B41600E69883 /* AudioRecordServiceProtocol.swift in Sources */,
|
7A95197B2D80B41600E69883 /* AudioRecordServiceProtocol.swift in Sources */,
|
||||||
7AF6D21C2677C1680086EA64 /* DebugInfo.swift in Sources */,
|
7AF6D21C2677C1680086EA64 /* DebugInfo.swift in Sources */,
|
||||||
7A0818762DF83DB4000219FE /* SDVehicleName.swift in Sources */,
|
7A0818762DF83DB4000219FE /* SDVehicleName.swift in Sources */,
|
||||||
@ -1502,6 +1527,7 @@
|
|||||||
7A599C392C18B22900D47C18 /* FbRefreshTokenModel.swift in Sources */,
|
7A599C392C18B22900D47C18 /* FbRefreshTokenModel.swift in Sources */,
|
||||||
7AF6D2172677C1680086EA64 /* VehicleRegion.swift in Sources */,
|
7AF6D2172677C1680086EA64 /* VehicleRegion.swift in Sources */,
|
||||||
7A6F096026DBF588003A965D /* VehicleNote.swift in Sources */,
|
7A6F096026DBF588003A965D /* VehicleNote.swift in Sources */,
|
||||||
|
7AD8572D2DF95F72009E4B72 /* SwiftDataStorageService.swift in Sources */,
|
||||||
7AF6D21E2677C1680086EA64 /* PlateNumber.swift in Sources */,
|
7AF6D21E2677C1680086EA64 /* PlateNumber.swift in Sources */,
|
||||||
7A5D84C62C1AE72E00C2209B /* VehicleName.swift in Sources */,
|
7A5D84C62C1AE72E00C2209B /* VehicleName.swift in Sources */,
|
||||||
7AD8572A2DF87928009E4B72 /* SDAudioRecord.swift in Sources */,
|
7AD8572A2DF87928009E4B72 /* SDAudioRecord.swift in Sources */,
|
||||||
@ -1542,12 +1568,14 @@
|
|||||||
7AD857222DF875B2009E4B72 /* SDOsago.swift in Sources */,
|
7AD857222DF875B2009E4B72 /* SDOsago.swift in Sources */,
|
||||||
7ABDA80F2D8723F90083C715 /* StorageService+AudioRecords.swift in Sources */,
|
7ABDA80F2D8723F90083C715 /* StorageService+AudioRecords.swift in Sources */,
|
||||||
7A64A2142C19E3B700284124 /* VehicleEngineDto.swift in Sources */,
|
7A64A2142C19E3B700284124 /* VehicleEngineDto.swift in Sources */,
|
||||||
|
7A1AE64F2DFB22EC00ECFC4D /* SwiftDataStorageService+Utils.swift in Sources */,
|
||||||
7A761C052677F1BC0005F28F /* CocoaError.swift in Sources */,
|
7A761C052677F1BC0005F28F /* CocoaError.swift in Sources */,
|
||||||
7AF6D2132677C15A0086EA64 /* AudioRecord.swift in Sources */,
|
7AF6D2132677C15A0086EA64 /* AudioRecord.swift in Sources */,
|
||||||
7A64A21A2C19E6B300284124 /* VehicleEventDto.swift in Sources */,
|
7A64A21A2C19E6B300284124 /* VehicleEventDto.swift in Sources */,
|
||||||
7AB587342C42D3FA00FA7B66 /* StorageService+Notes.swift in Sources */,
|
7AB587342C42D3FA00FA7B66 /* StorageService+Notes.swift in Sources */,
|
||||||
7AF6D21B2677C1680086EA64 /* Vehicle.swift in Sources */,
|
7AF6D21B2677C1680086EA64 /* Vehicle.swift in Sources */,
|
||||||
7AB587412C42FFE200FA7B66 /* ApiServiceProtocol.swift in Sources */,
|
7AB587412C42FFE200FA7B66 /* ApiServiceProtocol.swift in Sources */,
|
||||||
|
7A1AE6512DFB235300ECFC4D /* SwiftDataStorageService+Notes.swift in Sources */,
|
||||||
7A5D84C42C1AE65C00C2209B /* VehicleBrand.swift in Sources */,
|
7A5D84C42C1AE65C00C2209B /* VehicleBrand.swift in Sources */,
|
||||||
7A599C362C18AC7F00D47C18 /* ApiError.swift in Sources */,
|
7A599C362C18AC7F00D47C18 /* ApiError.swift in Sources */,
|
||||||
7A45FB382C27073700618694 /* StorageService.swift in Sources */,
|
7A45FB382C27073700618694 /* StorageService.swift in Sources */,
|
||||||
|
|||||||
@ -30,6 +30,16 @@ final class SDVehicleNote {
|
|||||||
self.date = date
|
self.date = date
|
||||||
self.text = text
|
self.text = text
|
||||||
}
|
}
|
||||||
|
|
||||||
|
convenience init(text: String, user: String) {
|
||||||
|
|
||||||
|
self.init(
|
||||||
|
id: UUID().uuidString,
|
||||||
|
user: user,
|
||||||
|
date: Date().timeIntervalSince1970,
|
||||||
|
text: text
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension SDVehicleNote: DtoConvertible {
|
extension SDVehicleNote: DtoConvertible {
|
||||||
|
|||||||
@ -0,0 +1,53 @@
|
|||||||
|
//
|
||||||
|
// SwiftDataStorageService+AudioRecords.swift
|
||||||
|
// AutoCatCore
|
||||||
|
//
|
||||||
|
// Created by Selim Mustafaev on 12.06.2025.
|
||||||
|
// Copyright © 2025 Selim Mustafaev. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import SwiftData
|
||||||
|
|
||||||
|
extension SwiftDataStorageService {
|
||||||
|
|
||||||
|
public func add(record: AudioRecordDto) async throws {
|
||||||
|
|
||||||
|
context.insert(SDAudioRecord(dto: record))
|
||||||
|
try context.save()
|
||||||
|
}
|
||||||
|
|
||||||
|
public func loadRecords() async throws -> [AudioRecordDto] {
|
||||||
|
|
||||||
|
do {
|
||||||
|
return try context.fetch(
|
||||||
|
FetchDescriptor<SDAudioRecord>(
|
||||||
|
sortBy: [SortDescriptor(\.addedDate, order: .reverse)]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.map(\.dto)
|
||||||
|
} catch {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public func deleteRecord(id: String) async throws {
|
||||||
|
guard let record = try? fetchAudioRecord(id: id) else {
|
||||||
|
throw StorageError.recordNotFound
|
||||||
|
}
|
||||||
|
|
||||||
|
context.delete(record)
|
||||||
|
try context.save()
|
||||||
|
}
|
||||||
|
|
||||||
|
public func updateRecord(id: String, number: String) async throws -> AudioRecordDto {
|
||||||
|
guard let record = try? fetchAudioRecord(id: id) else {
|
||||||
|
throw StorageError.recordNotFound
|
||||||
|
}
|
||||||
|
|
||||||
|
record.number = number
|
||||||
|
try context.save()
|
||||||
|
|
||||||
|
return record.dto
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,57 @@
|
|||||||
|
//
|
||||||
|
// SwiftDataStorageService+Events.swift
|
||||||
|
// AutoCatCore
|
||||||
|
//
|
||||||
|
// Created by Selim Mustafaev on 12.06.2025.
|
||||||
|
// Copyright © 2025 Selim Mustafaev. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import SwiftData
|
||||||
|
|
||||||
|
extension SwiftDataStorageService {
|
||||||
|
|
||||||
|
public func add(event: VehicleEventDto, to number: String) async throws -> VehicleDto {
|
||||||
|
guard let vehicle = try? fetchVehicle(number: number) else {
|
||||||
|
throw StorageError.vehicleNotFound
|
||||||
|
}
|
||||||
|
|
||||||
|
vehicle.events.append(SDVehicleEvent(dto: event))
|
||||||
|
vehicle.updatedDate = Date().timeIntervalSince1970
|
||||||
|
try context.save()
|
||||||
|
|
||||||
|
return vehicle.dto
|
||||||
|
}
|
||||||
|
|
||||||
|
public func remove(event id: String, from number: String) async throws -> VehicleDto {
|
||||||
|
guard let vehicle = try? fetchVehicle(number: number) else {
|
||||||
|
throw StorageError.vehicleNotFound
|
||||||
|
}
|
||||||
|
|
||||||
|
if let index = vehicle.events.firstIndex(where: { $0.id == id }) {
|
||||||
|
vehicle.events.remove(at: index)
|
||||||
|
vehicle.updatedDate = Date().timeIntervalSince1970
|
||||||
|
} else {
|
||||||
|
throw StorageError.eventNotFound
|
||||||
|
}
|
||||||
|
|
||||||
|
try context.save()
|
||||||
|
return vehicle.dto
|
||||||
|
}
|
||||||
|
|
||||||
|
public func edit(event: VehicleEventDto, for number: String) async throws -> VehicleDto {
|
||||||
|
guard let vehicle = try? fetchVehicle(number: number) else {
|
||||||
|
throw StorageError.vehicleNotFound
|
||||||
|
}
|
||||||
|
|
||||||
|
if let index = vehicle.events.firstIndex(where: { $0.id == event.id }) {
|
||||||
|
vehicle.events[index] = SDVehicleEvent(dto: event)
|
||||||
|
vehicle.updatedDate = Date().timeIntervalSince1970
|
||||||
|
try context.save()
|
||||||
|
} else {
|
||||||
|
throw StorageError.eventNotFound
|
||||||
|
}
|
||||||
|
|
||||||
|
return vehicle.dto
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,59 @@
|
|||||||
|
//
|
||||||
|
// SwiftDataStorageService+Notes.swift
|
||||||
|
// AutoCatCore
|
||||||
|
//
|
||||||
|
// Created by Selim Mustafaev on 12.06.2025.
|
||||||
|
// Copyright © 2025 Selim Mustafaev. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import SwiftData
|
||||||
|
|
||||||
|
extension SwiftDataStorageService {
|
||||||
|
|
||||||
|
public func addNote(text: String, to number: String) async throws -> VehicleDto {
|
||||||
|
guard let vehicle = try? fetchVehicle(number: number) else {
|
||||||
|
throw StorageError.vehicleNotFound
|
||||||
|
}
|
||||||
|
|
||||||
|
let note = SDVehicleNote(text: text, user: settingsService.user.email)
|
||||||
|
|
||||||
|
vehicle.notes.append(note)
|
||||||
|
vehicle.updatedDate = Date().timeIntervalSince1970
|
||||||
|
try context.save()
|
||||||
|
|
||||||
|
return vehicle.dto
|
||||||
|
}
|
||||||
|
|
||||||
|
public func deleteNote(id: String, for number: String) async throws -> VehicleDto {
|
||||||
|
guard let vehicle = try? fetchVehicle(number: number) else {
|
||||||
|
throw StorageError.vehicleNotFound
|
||||||
|
}
|
||||||
|
|
||||||
|
guard let note = try? fetchNote(id: id) else {
|
||||||
|
throw StorageError.noteNotFound
|
||||||
|
}
|
||||||
|
|
||||||
|
vehicle.updatedDate = Date().timeIntervalSince1970
|
||||||
|
context.delete(note)
|
||||||
|
try context.save()
|
||||||
|
|
||||||
|
return vehicle.dto
|
||||||
|
}
|
||||||
|
|
||||||
|
public func editNote(id: String, text: String, for number: String) async throws -> VehicleDto {
|
||||||
|
guard let vehicle = try? fetchVehicle(number: number) else {
|
||||||
|
throw StorageError.vehicleNotFound
|
||||||
|
}
|
||||||
|
|
||||||
|
guard let note = try? fetchNote(id: id) else {
|
||||||
|
throw StorageError.noteNotFound
|
||||||
|
}
|
||||||
|
|
||||||
|
note.text = text
|
||||||
|
vehicle.updatedDate = Date().timeIntervalSince1970
|
||||||
|
try context.save()
|
||||||
|
|
||||||
|
return vehicle.dto
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,49 @@
|
|||||||
|
//
|
||||||
|
// SwiftDataStorageService+Utils.swift
|
||||||
|
// AutoCatCore
|
||||||
|
//
|
||||||
|
// Created by Selim Mustafaev on 12.06.2025.
|
||||||
|
// Copyright © 2025 Selim Mustafaev. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import SwiftData
|
||||||
|
|
||||||
|
extension SwiftDataStorageService {
|
||||||
|
|
||||||
|
func vehicleExists(number: String) throws -> Bool {
|
||||||
|
|
||||||
|
let count = try context.fetchCount(
|
||||||
|
FetchDescriptor<SDVehicle>(predicate: #Predicate { $0.number == number })
|
||||||
|
)
|
||||||
|
|
||||||
|
return count > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func fetchVehicle(number: String) throws -> SDVehicle? {
|
||||||
|
|
||||||
|
let vehicles = try context.fetch(
|
||||||
|
FetchDescriptor<SDVehicle>(predicate: #Predicate { $0.number == number })
|
||||||
|
)
|
||||||
|
|
||||||
|
return vehicles.first
|
||||||
|
}
|
||||||
|
|
||||||
|
func fetchNote(id: String) throws -> SDVehicleNote? {
|
||||||
|
|
||||||
|
let notes = try context.fetch(
|
||||||
|
FetchDescriptor<SDVehicleNote>(predicate: #Predicate { $0.id == id })
|
||||||
|
)
|
||||||
|
|
||||||
|
return notes.first
|
||||||
|
}
|
||||||
|
|
||||||
|
func fetchAudioRecord(id: String) throws -> SDAudioRecord? {
|
||||||
|
|
||||||
|
let records = try context.fetch(
|
||||||
|
FetchDescriptor<SDAudioRecord>(predicate: #Predicate { $0.path == id })
|
||||||
|
)
|
||||||
|
|
||||||
|
return records.first
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,93 @@
|
|||||||
|
//
|
||||||
|
// SwiftDataStorageService.swift
|
||||||
|
// AutoCatCore
|
||||||
|
//
|
||||||
|
// Created by Selim Mustafaev on 11.06.2025.
|
||||||
|
// Copyright © 2025 Selim Mustafaev. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import SwiftData
|
||||||
|
|
||||||
|
@MainActor
|
||||||
|
public final class SwiftDataStorageService: StorageServiceProtocol {
|
||||||
|
|
||||||
|
let settingsService: SettingsServiceProtocol
|
||||||
|
let container: ModelContainer
|
||||||
|
let context: ModelContext
|
||||||
|
|
||||||
|
public init(settingsService: SettingsServiceProtocol, isTest: Bool = false) throws {
|
||||||
|
|
||||||
|
self.settingsService = settingsService
|
||||||
|
|
||||||
|
self.container = try ModelContainer(
|
||||||
|
for: SDVehicle.self, SDVehicleNote.self, SDAudioRecord.self,
|
||||||
|
configurations: .init(isStoredInMemoryOnly: isTest)
|
||||||
|
)
|
||||||
|
|
||||||
|
self.context = container.mainContext
|
||||||
|
}
|
||||||
|
|
||||||
|
public var dbFileURL: URL? {
|
||||||
|
|
||||||
|
// TODO: Set specific URL in ModelConfiguration
|
||||||
|
get async { nil }
|
||||||
|
}
|
||||||
|
|
||||||
|
public func deleteAll() async throws {
|
||||||
|
|
||||||
|
container.deleteAllData()
|
||||||
|
}
|
||||||
|
|
||||||
|
@discardableResult
|
||||||
|
public func updateVehicle(dto: VehicleDto, policy: DbUpdatePolicy) async throws -> Bool {
|
||||||
|
|
||||||
|
let shouldUpdate = switch policy {
|
||||||
|
case .always:
|
||||||
|
true
|
||||||
|
case .ifExists:
|
||||||
|
try vehicleExists(number: dto.number)
|
||||||
|
}
|
||||||
|
|
||||||
|
guard shouldUpdate else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
context.insert(SDVehicle(dto: dto))
|
||||||
|
try context.save()
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
public func loadVehicle(number: String) async throws -> VehicleDto {
|
||||||
|
|
||||||
|
if let vehicle = try fetchVehicle(number: number) {
|
||||||
|
return vehicle.dto
|
||||||
|
} else {
|
||||||
|
throw StorageError.vehicleNotFound
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public func loadVehicles() async -> [VehicleDto] {
|
||||||
|
|
||||||
|
do {
|
||||||
|
return try context.fetch(
|
||||||
|
FetchDescriptor<SDVehicle>(
|
||||||
|
sortBy: [SortDescriptor(\.updatedDate, order: .reverse)]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.map(\.shallowDto)
|
||||||
|
} catch {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public func deleteVehicle(number: String) async throws {
|
||||||
|
guard let vehicle = try? fetchVehicle(number: number) else {
|
||||||
|
throw StorageError.vehicleNotFound
|
||||||
|
}
|
||||||
|
|
||||||
|
context.delete(vehicle)
|
||||||
|
try context.save()
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user