fix conflict

multistore
Laurent 2 years ago
parent 64572ec7f3
commit cd0d5bf1ff
  1. 2
      LeStorage/Codables/Settings.swift
  2. 3
      LeStorage/MicroStorage.swift
  3. 12
      LeStorage/Services.swift
  4. 19
      LeStorage/Store.swift
  5. 14
      LeStorage/StoredCollection.swift
  6. 16
      LeStorage/Utils/Codable+Extensions.swift

@ -17,6 +17,6 @@ class Settings: MicroStorable {
// var id: String = Store.randomId() // var id: String = Store.randomId()
var userUUIDString: String? = nil var userId: String? = nil
var username: String? = nil var username: String? = nil
} }

@ -20,8 +20,7 @@ public class MicroStorage<T : MicroStorable> {
var instance: T? = nil var instance: T? = nil
do { do {
let url = try FileUtils.pathForFileInDocumentDirectory(T.fileName) let url = try FileUtils.pathForFileInDocumentDirectory(T.fileName)
let fileExists = FileManager.default.fileExists(atPath: url.path()) if FileManager.default.fileExists(atPath: url.path()) {
if fileExists {
let jsonString = try FileUtils.readDocumentFile(fileName: T.fileName) let jsonString = try FileUtils.readDocumentFile(fileName: T.fileName)
if let decoded: T = try jsonString.decode() { if let decoded: T = try jsonString.decode() {
instance = decoded instance = decoded

@ -14,7 +14,7 @@ enum Method: String {
case delete = "DELETE" case delete = "DELETE"
} }
enum ServiceError: Error { public enum ServiceError: Error {
case urlCreationError(url: String) case urlCreationError(url: String)
case cantConvertToUUID(id: String) case cantConvertToUUID(id: String)
case missingUserName case missingUserName
@ -113,7 +113,12 @@ public class Services {
try Store.main.rescheduleApiCall(id: apiCallId, type: type) try Store.main.rescheduleApiCall(id: apiCallId, type: type)
} }
Logger.log("Failed Run \(request.httpMethod ?? "") \(request.url?.absoluteString ?? "")") Logger.log("Failed Run \(request.httpMethod ?? "") \(request.url?.absoluteString ?? "")")
let dataString = String(describing: String(data: task.0, encoding: .utf8)) var dataString = String(describing: String(data: task.0, encoding: .utf8))
if let nfe: NonFieldError = try? JSONDecoder().decode(NonFieldError.self, from: task.0) {
if let reason = nfe.non_field_errors.first {
dataString = reason
}
}
throw ServiceError.responseError(response: dataString) throw ServiceError.responseError(response: dataString)
} }
} }
@ -284,6 +289,9 @@ struct Token: Codable {
struct Email: Codable { struct Email: Codable {
var email: String var email: String
} }
struct NonFieldError: Codable {
var non_field_errors: [String]
}
public protocol UserBase: Codable { public protocol UserBase: Codable {
var id: String { get } var id: String { get }

@ -72,10 +72,10 @@ public class Store {
/// Registers a collection /// Registers a collection
/// [synchronize] denotes a collection which modification will be sent to the django server /// [synchronize] denotes a collection which modification will be sent to the django server
public func registerCollection<T : Storable>(synchronized: Bool, indexed: Bool = false, inMemory: Bool = false) -> StoredCollection<T> { public func registerCollection<T : Storable>(synchronized: Bool, indexed: Bool = false, inMemory: Bool = false, sendsUpdate: Bool = true) -> StoredCollection<T> {
// register collection // register collection
let collection = StoredCollection<T>(synchronized: synchronized, store: Store.main, indexed: indexed, inMemory: inMemory, loadCompletion: nil) let collection = StoredCollection<T>(synchronized: synchronized, store: Store.main, indexed: indexed, inMemory: inMemory, sendsUpdate: sendsUpdate, loadCompletion: nil)
self._collections[T.resourceName()] = collection self._collections[T.resourceName()] = collection
// if synchronized { // register additional collection for api calls // if synchronized { // register additional collection for api calls
@ -92,18 +92,18 @@ public class Store {
func setUserUUID(uuidString: String) { func setUserUUID(uuidString: String) {
self.settingsStorage.update { settings in self.settingsStorage.update { settings in
settings.userUUIDString = uuidString settings.userId = uuidString
} }
} }
public func currentUserUUID() -> UUID { public func currentUserUUID() -> UUID {
if let uuidString = self.settingsStorage.item.userUUIDString, if let uuidString = self.settingsStorage.item.userId,
let uuid = UUID(uuidString: uuidString) { let uuid = UUID(uuidString: uuidString) {
return uuid return uuid
} else { } else {
let uuid = UIDevice.current.identifierForVendor ?? UUID() let uuid = UIDevice.current.identifierForVendor ?? UUID()
self.settingsStorage.update { settings in self.settingsStorage.update { settings in
settings.userUUIDString = uuid.uuidString settings.userId = uuid.uuidString
} }
return uuid return uuid
} }
@ -114,12 +114,17 @@ public class Store {
} }
func setUserName(_ username: String) { func setUserName(_ username: String) {
self.settingsStorage.item.username = username self.settingsStorage.update { settings in
settings.username = username
}
} }
public func disconnect() { public func disconnect() {
try? self.service().disconnect() try? self.service().disconnect()
self.settingsStorage.item.userUUIDString = nil self.settingsStorage.update { settings in
settings.username = nil
settings.userId = nil
}
} }
public func hasToken() -> Bool { public func hasToken() -> Bool {

@ -33,6 +33,9 @@ public class StoredCollection<T: Storable>: RandomAccessCollection, SomeCollecti
/// Doesn't write the collection in a file /// Doesn't write the collection in a file
fileprivate var _inMemory: Bool = false fileprivate var _inMemory: Bool = false
/// Indicates if the synchronized collection sends update to the API
fileprivate var _sendsUpdate: Bool = true
/// The list of stored items /// The list of stored items
@Published public fileprivate(set) var items: [T] = [] @Published public fileprivate(set) var items: [T] = []
@ -66,13 +69,14 @@ public class StoredCollection<T: Storable>: RandomAccessCollection, SomeCollecti
/// Denotes a collection that loads and writes asynchronousIO /// Denotes a collection that loads and writes asynchronousIO
fileprivate var asynchronousIO: Bool = true fileprivate var asynchronousIO: Bool = true
init(synchronized: Bool, store: Store, indexed: Bool = false, asynchronousIO: Bool = true, inMemory: Bool = false, loadCompletion: ((StoredCollection<T>) -> ())? = nil) { init(synchronized: Bool, store: Store, indexed: Bool = false, asynchronousIO: Bool = true, inMemory: Bool = false, sendsUpdate: Bool = true, loadCompletion: ((StoredCollection<T>) -> ())? = nil) {
self.synchronized = synchronized self.synchronized = synchronized
self.asynchronousIO = asynchronousIO self.asynchronousIO = asynchronousIO
if indexed { if indexed {
self._index = [:] self._index = [:]
} }
self._inMemory = inMemory self._inMemory = inMemory
self._sendsUpdate = sendsUpdate
self._store = store self._store = store
self.loadCompletion = loadCompletion self.loadCompletion = loadCompletion
@ -103,7 +107,7 @@ public class StoredCollection<T: Storable>: RandomAccessCollection, SomeCollecti
} }
fileprivate func _loadFromFile() throws { fileprivate func _loadFromFile() throws {
let url = try FileUtils.pathForFileInDocumentDirectory(T.fileName()) let url: URL = try FileUtils.pathForFileInDocumentDirectory(T.fileName())
if FileManager.default.fileExists(atPath: url.path()) { if FileManager.default.fileExists(atPath: url.path()) {
if self.asynchronousIO { if self.asynchronousIO {
@ -120,7 +124,7 @@ public class StoredCollection<T: Storable>: RandomAccessCollection, SomeCollecti
/// Decodes the json file into the items array /// Decodes the json file into the items array
fileprivate func _decodeJSONFile() throws { fileprivate func _decodeJSONFile() throws {
let jsonString = try FileUtils.readDocumentFile(fileName: T.fileName()) let jsonString: String = try FileUtils.readDocumentFile(fileName: T.fileName())
if let decoded: [T] = try jsonString.decodeArray() { if let decoded: [T] = try jsonString.decodeArray() {
DispatchQueue.main.async { DispatchQueue.main.async {
Logger.log("loaded \(T.fileName()) with \(decoded.count) items") Logger.log("loaded \(T.fileName()) with \(decoded.count) items")
@ -353,7 +357,7 @@ public class StoredCollection<T: Storable>: RandomAccessCollection, SomeCollecti
/// Sends an update api call for the provided [instance] /// Sends an update api call for the provided [instance]
fileprivate func _sendUpdateIfNecessary(_ instance: T) throws { fileprivate func _sendUpdateIfNecessary(_ instance: T) throws {
guard self.synchronized else { guard self.synchronized, self._sendsUpdate else {
return return
} }
@ -408,7 +412,7 @@ public class StoredCollection<T: Storable>: RandomAccessCollection, SomeCollecti
} }
fileprivate func _rescheduleApiCalls() { fileprivate func _rescheduleApiCalls() {
return // return
guard let apiCallsCollection, apiCallsCollection.isNotEmpty else { guard let apiCallsCollection, apiCallsCollection.isNotEmpty else {
return return

@ -10,7 +10,9 @@ import Foundation
fileprivate var jsonEncoder: JSONEncoder = { fileprivate var jsonEncoder: JSONEncoder = {
let encoder = JSONEncoder() let encoder = JSONEncoder()
encoder.keyEncodingStrategy = .convertToSnakeCase encoder.keyEncodingStrategy = .convertToSnakeCase
#if DEBUG
encoder.outputFormatting = .prettyPrinted encoder.outputFormatting = .prettyPrinted
#endif
encoder.dateEncodingStrategy = .iso8601 encoder.dateEncodingStrategy = .iso8601
return encoder return encoder
}() }()
@ -24,16 +26,16 @@ fileprivate var jsonDecoder: JSONDecoder = {
extension Encodable { extension Encodable {
func jsonString() throws -> String { public func jsonString() throws -> String {
let data = try self.jsonData() let data = try self.jsonData()
return String(data: data, encoding: .utf8) ?? "" return String(data: data, encoding: .utf8) ?? ""
} }
func jsonData() throws -> Data { public func jsonData() throws -> Data {
return try jsonEncoder.encode(self) return try jsonEncoder.encode(self)
} }
func prettyJSONString() throws -> String { public func prettyJSONString() throws -> String {
let data = try jsonEncoder.encode(self) let data = try jsonEncoder.encode(self)
return String(data: data, encoding: .utf8) ?? "" return String(data: data, encoding: .utf8) ?? ""
} }
@ -42,11 +44,11 @@ extension Encodable {
extension String { extension String {
func decode<T : Decodable>() throws -> T? { public func decode<T : Decodable>() throws -> T? {
return try self.data(using: .utf8)?.decode() return try self.data(using: .utf8)?.decode()
} }
func decodeArray<T : Decodable>() throws -> [T]? { public func decodeArray<T : Decodable>() throws -> [T]? {
return try self.data(using: .utf8)?.decodeArray() return try self.data(using: .utf8)?.decodeArray()
} }
@ -54,11 +56,11 @@ extension String {
extension Data { extension Data {
func decode<T : Decodable>() throws -> T { public func decode<T : Decodable>() throws -> T {
return try jsonDecoder.decode(T.self, from: self) return try jsonDecoder.decode(T.self, from: self)
} }
func decodeArray<T : Decodable>() throws -> [T] { public func decodeArray<T : Decodable>() throws -> [T] {
return try jsonDecoder.decode([T].self, from: self) return try jsonDecoder.decode([T].self, from: self)
} }

Loading…
Cancel
Save