137 lines
4.3 KiB
Swift
137 lines
4.3 KiB
Swift
//
|
||
// SettingModels.swift
|
||
// suixinkan
|
||
//
|
||
|
||
import Foundation
|
||
|
||
/// 最新版本响应实体,对齐 Android `VersionResponse`。
|
||
struct VersionResponse: Decodable, Equatable {
|
||
let id: Int
|
||
let type: Int
|
||
let version: String
|
||
let operatorName: String
|
||
let description: String
|
||
let status: Int
|
||
let createdAt: String
|
||
let updatedAt: String
|
||
let deletedAt: String?
|
||
let versionCode: Int
|
||
let apkURL: String
|
||
let isForceUpdate: Int
|
||
let approveNotes: String
|
||
|
||
enum CodingKeys: String, CodingKey {
|
||
case id
|
||
case type
|
||
case version
|
||
case operatorName = "operator"
|
||
case description
|
||
case status
|
||
case createdAt = "created_at"
|
||
case updatedAt = "updated_at"
|
||
case deletedAt = "deleted_at"
|
||
case versionCode = "version_code"
|
||
case apkURL = "apk_url"
|
||
case isForceUpdate = "is_force_update"
|
||
case approveNotes = "approve_notes"
|
||
}
|
||
|
||
init(
|
||
id: Int = 0,
|
||
type: Int = 0,
|
||
version: String = "",
|
||
operatorName: String = "",
|
||
description: String = "",
|
||
status: Int = 0,
|
||
createdAt: String = "",
|
||
updatedAt: String = "",
|
||
deletedAt: String? = nil,
|
||
versionCode: Int = 0,
|
||
apkURL: String = "",
|
||
isForceUpdate: Int = 0,
|
||
approveNotes: String = ""
|
||
) {
|
||
self.id = id
|
||
self.type = type
|
||
self.version = version
|
||
self.operatorName = operatorName
|
||
self.description = description
|
||
self.status = status
|
||
self.createdAt = createdAt
|
||
self.updatedAt = updatedAt
|
||
self.deletedAt = deletedAt
|
||
self.versionCode = versionCode
|
||
self.apkURL = apkURL
|
||
self.isForceUpdate = isForceUpdate
|
||
self.approveNotes = approveNotes
|
||
}
|
||
|
||
init(from decoder: Decoder) throws {
|
||
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||
id = try container.decodeLossyInt(forKey: .id) ?? 0
|
||
type = try container.decodeLossyInt(forKey: .type) ?? 0
|
||
version = try container.decodeLossyString(forKey: .version)
|
||
operatorName = try container.decodeLossyString(forKey: .operatorName)
|
||
description = try container.decodeLossyString(forKey: .description)
|
||
status = try container.decodeLossyInt(forKey: .status) ?? 0
|
||
createdAt = try container.decodeLossyString(forKey: .createdAt)
|
||
updatedAt = try container.decodeLossyString(forKey: .updatedAt)
|
||
deletedAt = try container.decodeIfPresent(String.self, forKey: .deletedAt)
|
||
versionCode = try container.decodeLossyInt(forKey: .versionCode) ?? 0
|
||
apkURL = try container.decodeLossyString(forKey: .apkURL)
|
||
isForceUpdate = try container.decodeLossyInt(forKey: .isForceUpdate) ?? 0
|
||
approveNotes = try container.decodeLossyString(forKey: .approveNotes)
|
||
}
|
||
}
|
||
|
||
/// 设置页协议入口实体,表示标题和对应 H5 地址。
|
||
struct SettingAgreementDestination: Equatable {
|
||
let title: String
|
||
let url: URL
|
||
}
|
||
|
||
/// 设置页协议类型。
|
||
enum SettingAgreementKind: CaseIterable {
|
||
case aboutUs
|
||
case userAgreement
|
||
case privacyPolicy
|
||
}
|
||
|
||
private extension KeyedDecodingContainer {
|
||
func decodeLossyString(forKey key: Key) throws -> String {
|
||
if let value = try? decodeIfPresent(String.self, forKey: key) {
|
||
return value
|
||
}
|
||
if let value = try? decodeIfPresent(Int.self, forKey: key) {
|
||
return String(value)
|
||
}
|
||
if let value = try? decodeIfPresent(Double.self, forKey: key) {
|
||
return String(value)
|
||
}
|
||
if let value = try? decodeIfPresent(Bool.self, forKey: key) {
|
||
return value ? "true" : "false"
|
||
}
|
||
return ""
|
||
}
|
||
|
||
func decodeLossyInt(forKey key: Key) throws -> Int? {
|
||
if let value = try? decodeIfPresent(Int.self, forKey: key) {
|
||
return value
|
||
}
|
||
if let value = try? decodeIfPresent(String.self, forKey: key) {
|
||
let text = value.trimmingCharacters(in: .whitespacesAndNewlines)
|
||
if let intValue = Int(text) {
|
||
return intValue
|
||
}
|
||
if let doubleValue = Double(text) {
|
||
return Int(doubleValue)
|
||
}
|
||
}
|
||
if let value = try? decodeIfPresent(Double.self, forKey: key) {
|
||
return Int(value)
|
||
}
|
||
return nil
|
||
}
|
||
}
|