ios: automatic message deletion (#1160)

This commit is contained in:
JRoberts
2022-10-03 16:42:43 +04:00
committed by GitHub
parent 575706c7c7
commit 6e9e6057af
8 changed files with 167 additions and 30 deletions
+1
View File
@@ -32,6 +32,7 @@ final class ChatModel: ObservableObject {
@Published var terminalItems: [TerminalItem] = []
@Published var userAddress: String?
@Published var userSMPServers: [String]?
@Published var chatItemTTL: ChatItemTTL = .none
@Published var appOpenUrl: URL?
@Published var deviceToken: DeviceToken?
@Published var savedToken: DeviceToken?
+12 -1
View File
@@ -132,7 +132,7 @@ func apiCreateActiveUser(_ p: Profile) throws -> User {
}
func apiStartChat() throws -> Bool {
let r = chatSendCmdSync(.startChat(subscribe: true))
let r = chatSendCmdSync(.startChat(subscribe: true, expire: true))
switch r {
case .chatStarted: return true
case .chatRunning: return false
@@ -319,6 +319,16 @@ func setUserSMPServers(smpServers: [String]) async throws {
try await sendCommandOkResp(.setUserSMPServers(smpServers: smpServers))
}
func getChatItemTTL() throws -> ChatItemTTL {
let r = chatSendCmdSync(.apiGetChatItemTTL)
if case let .chatItemTTL(chatItemTTL) = r { return ChatItemTTL(chatItemTTL) }
throw r
}
func setChatItemTTL(_ chatItemTTL: ChatItemTTL) async throws {
try await sendCommandOkResp(.apiSetChatItemTTL(seconds: chatItemTTL.seconds))
}
func getNetworkConfig() async throws -> NetCfg? {
let r = await chatSendCmd(.apiGetNetworkConfig)
if case let .networkConfig(cfg) = r { return cfg }
@@ -757,6 +767,7 @@ func startChat() throws {
if justStarted {
m.userAddress = try apiGetUserAddress()
m.userSMPServers = try getUserSMPServers()
m.chatItemTTL = try getChatItemTTL()
let chats = try apiGetChats()
m.chats = chats.map { Chat.init($0) }
NtfManager.shared.setNtfBadgeCount(m.totalUnreadCount())
@@ -18,6 +18,7 @@ enum DatabaseAlert: Identifiable {
case chatDeleted
case deleteLegacyDatabase
case deleteFilesAndMedia
case setChatItemTTL(ttl: ChatItemTTL)
case error(title: LocalizedStringKey, error: String = "")
var id: String {
@@ -30,6 +31,7 @@ enum DatabaseAlert: Identifiable {
case .chatDeleted: return "chatDeleted"
case .deleteLegacyDatabase: return "deleteLegacyDatabase"
case .deleteFilesAndMedia: return "deleteFilesAndMedia"
case .setChatItemTTL: return "setChatItemTTL"
case let .error(title, _): return "error \(title)"
}
}
@@ -50,6 +52,9 @@ struct DatabaseView: View {
@State private var useKeychain = storeDBPassphraseGroupDefault.get()
@State private var appFilesCountAndSize: (Int, Int)?
@State var chatItemTTL: ChatItemTTL
@State private var currentChatItemTTL: ChatItemTTL = .none
var body: some View {
ZStack {
chatDatabaseView()
@@ -152,11 +157,21 @@ struct DatabaseView: View {
}
Section {
Picker("Delete messages after", selection: $chatItemTTL) {
ForEach([ChatItemTTL.none, ChatItemTTL.month, ChatItemTTL.week, ChatItemTTL.day]) { ttl in
Text(ttl.deleteAfterText).tag(ttl)
}
if case let .seconds(seconds) = chatItemTTL {
let ttl: ChatItemTTL = .seconds(seconds)
Text(ttl.deleteAfterText).tag(ttl)
}
}
Button("Delete files & media", role: .destructive) {
alert = .deleteFilesAndMedia
}
.disabled(!stopped || appFilesCountAndSize?.0 == 0)
} header: {
Text("Files")
Text("Data")
} footer: {
if let (fileCount, size) = appFilesCountAndSize {
if fileCount == 0 {
@@ -166,11 +181,18 @@ struct DatabaseView: View {
}
}
}
.disabled(!stopped || appFilesCountAndSize?.0 == 0)
}
.onAppear {
runChat = m.chatRunning ?? true
appFilesCountAndSize = directoryFileCountAndSize(getAppFilesDirectory())
currentChatItemTTL = chatItemTTL
}
.onChange(of: chatItemTTL) { ttl in
if ttl < currentChatItemTTL {
alert = .setChatItemTTL(ttl: ttl)
} else if ttl != currentChatItemTTL {
setCiTTL(ttl)
}
}
.alert(item: $alert) { item in databaseAlert(item) }
.fileImporter(
@@ -254,6 +276,17 @@ struct DatabaseView: View {
},
secondaryButton: .cancel()
)
case let .setChatItemTTL(ttl):
return Alert(
title: Text("Enable automatic message deletion?"),
message: Text("This action cannot be undone - once you confirm, messages older than specified age will start to get deleted. It may take up to several minutes to delete old messages initially after changing this setting."),
primaryButton: .destructive(Text("Delete messages")) {
setCiTTL(ttl)
},
secondaryButton: .cancel() {
chatItemTTL = currentChatItemTTL
}
)
case let .error(title, error):
return Alert(title: Text(title), message: Text("\(error)"))
}
@@ -389,6 +422,29 @@ struct DatabaseView: View {
}
}
private func setCiTTL(_ ttl: ChatItemTTL) {
logger.debug("DatabaseView setChatItemTTL \(ttl.seconds ?? -1)")
progressIndicator = true
Task {
do {
try await setChatItemTTL(ttl)
await MainActor.run {
m.chatItemTTL = ttl
currentChatItemTTL = ttl
progressIndicator = false
appFilesCountAndSize = directoryFileCountAndSize(getAppFilesDirectory())
}
} catch {
await MainActor.run {
alert = .error(title: "Error changing automatic message deletion", error: responseError(error))
chatItemTTL = currentChatItemTTL
progressIndicator = false
appFilesCountAndSize = directoryFileCountAndSize(getAppFilesDirectory())
}
}
}
}
private func deleteFiles() {
deleteAppFiles()
appFilesCountAndSize = directoryFileCountAndSize(getAppFilesDirectory())
@@ -397,6 +453,6 @@ struct DatabaseView: View {
struct DatabaseView_Previews: PreviewProvider {
static var previews: some View {
DatabaseView(showSettings: Binding.constant(false))
DatabaseView(showSettings: Binding.constant(false), chatItemTTL: .none)
}
}
@@ -101,7 +101,7 @@ struct SettingsView: View {
.disabled(chatModel.chatRunning != true)
NavigationLink {
DatabaseView(showSettings: $showSettings)
DatabaseView(showSettings: $showSettings, chatItemTTL: chatModel.chatItemTTL)
.navigationTitle("Your chat database")
} label: {
let color: Color = chatModel.chatDbEncrypted == false ? .orange : .secondary
@@ -245,7 +245,7 @@ func apiGetActiveUser() -> User? {
}
func apiStartChat() throws -> Bool {
let r = sendSimpleXCmd(.startChat(subscribe: false))
let r = sendSimpleXCmd(.startChat(subscribe: false, expire: false))
switch r {
case .chatStarted: return true
case .chatRunning: return false
+20 -20
View File
@@ -90,11 +90,6 @@
5CCD403427A5F6DF00368C90 /* AddContactView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CCD403327A5F6DF00368C90 /* AddContactView.swift */; };
5CCD403727A5F9A200368C90 /* ScanToConnectView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CCD403627A5F9A200368C90 /* ScanToConnectView.swift */; };
5CDCAD482818589900503DA2 /* NotificationService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CDCAD472818589900503DA2 /* NotificationService.swift */; };
5CE1330A28E71B8F00FFFD8C /* libHSsimplex-chat-4.0.1-6epkrQoB3nkFyTCo6XPd6m-ghc8.10.7.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5CE1330528E71B8F00FFFD8C /* libHSsimplex-chat-4.0.1-6epkrQoB3nkFyTCo6XPd6m-ghc8.10.7.a */; };
5CE1330B28E71B8F00FFFD8C /* libHSsimplex-chat-4.0.1-6epkrQoB3nkFyTCo6XPd6m.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5CE1330628E71B8F00FFFD8C /* libHSsimplex-chat-4.0.1-6epkrQoB3nkFyTCo6XPd6m.a */; };
5CE1330C28E71B8F00FFFD8C /* libgmp.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5CE1330728E71B8F00FFFD8C /* libgmp.a */; };
5CE1330D28E71B8F00FFFD8C /* libffi.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5CE1330828E71B8F00FFFD8C /* libffi.a */; };
5CE1330E28E71B8F00FFFD8C /* libgmpxx.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5CE1330928E71B8F00FFFD8C /* libgmpxx.a */; };
5CE1331028E7391000FFFD8C /* ContactConnectionInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CE1330F28E7391000FFFD8C /* ContactConnectionInfo.swift */; };
5CE2BA702845308900EC33A6 /* SimpleXChat.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5CE2BA682845308900EC33A6 /* SimpleXChat.framework */; };
5CE2BA712845308900EC33A6 /* SimpleXChat.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 5CE2BA682845308900EC33A6 /* SimpleXChat.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
@@ -127,6 +122,11 @@
6440CA03288AECA70062C672 /* AddGroupMembersView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6440CA02288AECA70062C672 /* AddGroupMembersView.swift */; };
6442E0BA287F169300CEC0F9 /* AddGroupView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6442E0B9287F169300CEC0F9 /* AddGroupView.swift */; };
6442E0BE2880182D00CEC0F9 /* GroupChatInfoView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6442E0BD2880182D00CEC0F9 /* GroupChatInfoView.swift */; };
6448BBA628EAF728000D2AB9 /* libffi.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 6448BBA128EAF728000D2AB9 /* libffi.a */; };
6448BBA728EAF728000D2AB9 /* libHSsimplex-chat-4.0.1-FvHSNBJjHeqKQoixUekUiI-ghc8.10.7.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 6448BBA228EAF728000D2AB9 /* libHSsimplex-chat-4.0.1-FvHSNBJjHeqKQoixUekUiI-ghc8.10.7.a */; };
6448BBA828EAF728000D2AB9 /* libgmpxx.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 6448BBA328EAF728000D2AB9 /* libgmpxx.a */; };
6448BBA928EAF728000D2AB9 /* libgmp.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 6448BBA428EAF728000D2AB9 /* libgmp.a */; };
6448BBAA28EAF728000D2AB9 /* libHSsimplex-chat-4.0.1-FvHSNBJjHeqKQoixUekUiI.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 6448BBA528EAF728000D2AB9 /* libHSsimplex-chat-4.0.1-FvHSNBJjHeqKQoixUekUiI.a */; };
6454036F2822A9750090DDFF /* ComposeFileView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6454036E2822A9750090DDFF /* ComposeFileView.swift */; };
646BB38C283BEEB9001CE359 /* LocalAuthentication.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 646BB38B283BEEB9001CE359 /* LocalAuthentication.framework */; };
646BB38E283FDB6D001CE359 /* LocalAuthenticationUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 646BB38D283FDB6D001CE359 /* LocalAuthenticationUtils.swift */; };
@@ -300,11 +300,6 @@
5CDCAD80281A7E2700503DA2 /* Notifications.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Notifications.swift; sourceTree = "<group>"; };
5CE1330328E118CC00FFFD8C /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = "de.lproj/SimpleX--iOS--InfoPlist.strings"; sourceTree = "<group>"; };
5CE1330428E118CC00FFFD8C /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/InfoPlist.strings; sourceTree = "<group>"; };
5CE1330528E71B8F00FFFD8C /* libHSsimplex-chat-4.0.1-6epkrQoB3nkFyTCo6XPd6m-ghc8.10.7.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-4.0.1-6epkrQoB3nkFyTCo6XPd6m-ghc8.10.7.a"; sourceTree = "<group>"; };
5CE1330628E71B8F00FFFD8C /* libHSsimplex-chat-4.0.1-6epkrQoB3nkFyTCo6XPd6m.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-4.0.1-6epkrQoB3nkFyTCo6XPd6m.a"; sourceTree = "<group>"; };
5CE1330728E71B8F00FFFD8C /* libgmp.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgmp.a; sourceTree = "<group>"; };
5CE1330828E71B8F00FFFD8C /* libffi.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libffi.a; sourceTree = "<group>"; };
5CE1330928E71B8F00FFFD8C /* libgmpxx.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgmpxx.a; sourceTree = "<group>"; };
5CE1330F28E7391000FFFD8C /* ContactConnectionInfo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContactConnectionInfo.swift; sourceTree = "<group>"; };
5CE2BA682845308900EC33A6 /* SimpleXChat.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SimpleXChat.framework; sourceTree = BUILT_PRODUCTS_DIR; };
5CE2BA76284530BF00EC33A6 /* SimpleXChat.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SimpleXChat.h; sourceTree = "<group>"; };
@@ -323,6 +318,11 @@
6440CA02288AECA70062C672 /* AddGroupMembersView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddGroupMembersView.swift; sourceTree = "<group>"; };
6442E0B9287F169300CEC0F9 /* AddGroupView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddGroupView.swift; sourceTree = "<group>"; };
6442E0BD2880182D00CEC0F9 /* GroupChatInfoView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GroupChatInfoView.swift; sourceTree = "<group>"; };
6448BBA128EAF728000D2AB9 /* libffi.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libffi.a; sourceTree = "<group>"; };
6448BBA228EAF728000D2AB9 /* libHSsimplex-chat-4.0.1-FvHSNBJjHeqKQoixUekUiI-ghc8.10.7.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-4.0.1-FvHSNBJjHeqKQoixUekUiI-ghc8.10.7.a"; sourceTree = "<group>"; };
6448BBA328EAF728000D2AB9 /* libgmpxx.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgmpxx.a; sourceTree = "<group>"; };
6448BBA428EAF728000D2AB9 /* libgmp.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgmp.a; sourceTree = "<group>"; };
6448BBA528EAF728000D2AB9 /* libHSsimplex-chat-4.0.1-FvHSNBJjHeqKQoixUekUiI.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-4.0.1-FvHSNBJjHeqKQoixUekUiI.a"; sourceTree = "<group>"; };
6454036E2822A9750090DDFF /* ComposeFileView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComposeFileView.swift; sourceTree = "<group>"; };
646BB38B283BEEB9001CE359 /* LocalAuthentication.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = LocalAuthentication.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS15.4.sdk/System/Library/Frameworks/LocalAuthentication.framework; sourceTree = DEVELOPER_DIR; };
646BB38D283FDB6D001CE359 /* LocalAuthenticationUtils.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocalAuthenticationUtils.swift; sourceTree = "<group>"; };
@@ -368,13 +368,13 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
5CE1330A28E71B8F00FFFD8C /* libHSsimplex-chat-4.0.1-6epkrQoB3nkFyTCo6XPd6m-ghc8.10.7.a in Frameworks */,
5CE1330D28E71B8F00FFFD8C /* libffi.a in Frameworks */,
5CE1330C28E71B8F00FFFD8C /* libgmp.a in Frameworks */,
6448BBAA28EAF728000D2AB9 /* libHSsimplex-chat-4.0.1-FvHSNBJjHeqKQoixUekUiI.a in Frameworks */,
5CE2BA93284534B000EC33A6 /* libiconv.tbd in Frameworks */,
6448BBA828EAF728000D2AB9 /* libgmpxx.a in Frameworks */,
6448BBA728EAF728000D2AB9 /* libHSsimplex-chat-4.0.1-FvHSNBJjHeqKQoixUekUiI-ghc8.10.7.a in Frameworks */,
6448BBA628EAF728000D2AB9 /* libffi.a in Frameworks */,
6448BBA928EAF728000D2AB9 /* libgmp.a in Frameworks */,
5CE2BA94284534BB00EC33A6 /* libz.tbd in Frameworks */,
5CE1330B28E71B8F00FFFD8C /* libHSsimplex-chat-4.0.1-6epkrQoB3nkFyTCo6XPd6m.a in Frameworks */,
5CE1330E28E71B8F00FFFD8C /* libgmpxx.a in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -429,11 +429,11 @@
5C764E5C279C70B7000C6508 /* Libraries */ = {
isa = PBXGroup;
children = (
5CE1330828E71B8F00FFFD8C /* libffi.a */,
5CE1330728E71B8F00FFFD8C /* libgmp.a */,
5CE1330928E71B8F00FFFD8C /* libgmpxx.a */,
5CE1330528E71B8F00FFFD8C /* libHSsimplex-chat-4.0.1-6epkrQoB3nkFyTCo6XPd6m-ghc8.10.7.a */,
5CE1330628E71B8F00FFFD8C /* libHSsimplex-chat-4.0.1-6epkrQoB3nkFyTCo6XPd6m.a */,
6448BBA128EAF728000D2AB9 /* libffi.a */,
6448BBA428EAF728000D2AB9 /* libgmp.a */,
6448BBA328EAF728000D2AB9 /* libgmpxx.a */,
6448BBA228EAF728000D2AB9 /* libHSsimplex-chat-4.0.1-FvHSNBJjHeqKQoixUekUiI-ghc8.10.7.a */,
6448BBA528EAF728000D2AB9 /* libHSsimplex-chat-4.0.1-FvHSNBJjHeqKQoixUekUiI.a */,
);
path = Libraries;
sourceTree = "<group>";
+25 -4
View File
@@ -15,14 +15,14 @@ let jsonEncoder = getJSONEncoder()
public enum ChatCommand {
case showActiveUser
case createActiveUser(profile: Profile)
case startChat(subscribe: Bool)
case startChat(subscribe: Bool, expire: Bool)
case apiStopChat
case apiActivateChat
case apiSuspendChat(timeoutMicroseconds: Int)
case setFilesFolder(filesFolder: String)
case setIncognito(incognito: Bool)
case apiExportArchive(config: ArchiveConfig)
case apiImportArchive(config: ArchiveConfig)
case apiImportArchive(config: ArchiveConfig)
case apiDeleteStorage
case apiStorageEncryption(config: DBEncryptionConfig)
case apiGetChats
@@ -45,6 +45,8 @@ public enum ChatCommand {
case apiUpdateGroupProfile(groupId: Int64, groupProfile: GroupProfile)
case getUserSMPServers
case setUserSMPServers(smpServers: [String])
case apiSetChatItemTTL(seconds: Int64?)
case apiGetChatItemTTL
case apiSetNetworkConfig(networkConfig: NetCfg)
case apiGetNetworkConfig
case apiSetChatSettings(type: ChatType, id: Int64, chatSettings: ChatSettings)
@@ -81,12 +83,12 @@ public enum ChatCommand {
switch self {
case .showActiveUser: return "/u"
case let .createActiveUser(profile): return "/u \(profile.displayName) \(profile.fullName)"
case let .startChat(subscribe): return "/_start subscribe=\(subscribe ? "on" : "off") expire=off"
case let .startChat(subscribe, expire): return "/_start subscribe=\(onOff(subscribe)) expire=\(onOff(expire))"
case .apiStopChat: return "/_stop"
case .apiActivateChat: return "/_app activate"
case let .apiSuspendChat(timeoutMicroseconds): return "/_app suspend \(timeoutMicroseconds)"
case let .setFilesFolder(filesFolder): return "/_files_folder \(filesFolder)"
case let .setIncognito(incognito): return "/incognito \(incognito ? "on" : "off")"
case let .setIncognito(incognito): return "/incognito \(onOff(incognito))"
case let .apiExportArchive(cfg): return "/_db export \(encodeJSON(cfg))"
case let .apiImportArchive(cfg): return "/_db import \(encodeJSON(cfg))"
case .apiDeleteStorage: return "/_db delete"
@@ -113,6 +115,8 @@ public enum ChatCommand {
case let .apiUpdateGroupProfile(groupId, groupProfile): return "/_group_profile #\(groupId) \(encodeJSON(groupProfile))"
case .getUserSMPServers: return "/smp_servers"
case let .setUserSMPServers(smpServers): return "/smp_servers \(smpServersStr(smpServers: smpServers))"
case let .apiSetChatItemTTL(seconds): return "/_ttl \(chatItemTTLStr(seconds: seconds))"
case .apiGetChatItemTTL: return "/ttl"
case let .apiSetNetworkConfig(networkConfig): return "/_network \(encodeJSON(networkConfig))"
case .apiGetNetworkConfig: return "/network"
case let .apiSetChatSettings(type, id, chatSettings): return "/_settings \(ref(type, id)) \(encodeJSON(chatSettings))"
@@ -180,6 +184,8 @@ public enum ChatCommand {
case .apiUpdateGroupProfile: return "apiUpdateGroupProfile"
case .getUserSMPServers: return "getUserSMPServers"
case .setUserSMPServers: return "setUserSMPServers"
case .apiSetChatItemTTL: return "apiSetChatItemTTL"
case .apiGetChatItemTTL: return "apiGetChatItemTTL"
case .apiSetNetworkConfig: return "apiSetNetworkConfig"
case .apiGetNetworkConfig: return "apiGetNetworkConfig"
case .apiSetChatSettings: return "apiSetChatSettings"
@@ -221,6 +227,14 @@ public enum ChatCommand {
smpServers.isEmpty ? "default" : smpServers.joined(separator: ",")
}
func chatItemTTLStr(seconds: Int64?) -> String {
if let seconds = seconds {
return String(seconds)
} else {
return "none"
}
}
public var obfuscated: ChatCommand {
switch self {
case let .apiStorageEncryption(cfg):
@@ -232,6 +246,10 @@ public enum ChatCommand {
private func obfuscate(_ s: String) -> String {
s == "" ? "" : "***"
}
private func onOff(_ b: Bool) -> String {
b ? "on" : "off"
}
}
struct APIResponse: Decodable {
@@ -248,6 +266,7 @@ public enum ChatResponse: Decodable, Error {
case apiChats(chats: [ChatData])
case apiChat(chat: ChatData)
case userSMPServers(smpServers: [String])
case chatItemTTL(chatItemTTL: Int64?)
case networkConfig(networkConfig: NetCfg)
case contactInfo(contact: Contact, connectionStats: ConnectionStats, customUserProfile: Profile?)
case groupMemberInfo(groupInfo: GroupInfo, member: GroupMember, connectionStats_: ConnectionStats?)
@@ -342,6 +361,7 @@ public enum ChatResponse: Decodable, Error {
case .apiChats: return "apiChats"
case .apiChat: return "apiChat"
case .userSMPServers: return "userSMPServers"
case .chatItemTTL: return "chatItemTTL"
case .networkConfig: return "networkConfig"
case .contactInfo: return "contactInfo"
case .groupMemberInfo: return "groupMemberInfo"
@@ -436,6 +456,7 @@ public enum ChatResponse: Decodable, Error {
case let .apiChats(chats): return String(describing: chats)
case let .apiChat(chat): return String(describing: chat)
case let .userSMPServers(smpServers): return String(describing: smpServers)
case let .chatItemTTL(chatItemTTL): return String(describing: chatItemTTL)
case let .networkConfig(networkConfig): return String(describing: networkConfig)
case let .contactInfo(contact, connectionStats, customUserProfile): return "contact: \(String(describing: contact))\nconnectionStats: \(String(describing: connectionStats))\ncustomUserProfile: \(String(describing: customUserProfile))"
case let .groupMemberInfo(groupInfo, member, connectionStats_): return "groupInfo: \(String(describing: groupInfo))\nmember: \(String(describing: member))\nconnectionStats_: \(String(describing: connectionStats_)))"
+48
View File
@@ -1464,3 +1464,51 @@ public enum SndGroupEvent: Decodable {
}
}
}
public enum ChatItemTTL: Hashable, Identifiable, Comparable {
case day
case week
case month
case seconds(_ seconds: Int64)
case none
public var id: Self { self }
public init(_ seconds: Int64?) {
switch seconds {
case 86400: self = .day
case 7 * 86400: self = .week
case 30 * 86400: self = .month
case let .some(n): self = .seconds(n)
case .none: self = .none
}
}
public var deleteAfterText: LocalizedStringKey {
switch self {
case .day: return "1 day"
case .week: return "1 week"
case .month: return "1 month"
case let .seconds(seconds): return "\(seconds) second(s)"
case .none: return "no"
}
}
public var seconds: Int64? {
switch self {
case .day: return 86400
case .week: return 7 * 86400
case .month: return 30 * 86400
case let .seconds(seconds): return seconds
case .none: return nil
}
}
private var comparisonValue: Int64 {
self.seconds ?? Int64.max
}
public static func < (lhs: Self, rhs: Self) -> Bool {
return lhs.comparisonValue < rhs.comparisonValue
}
}