mirror of
https://github.com/simplex-chat/simplex-chat.git
synced 2024-12-17 17:20:21 +01:00
ios: automatic message deletion (#1160)
This commit is contained in:
@@ -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?
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>";
|
||||
|
||||
@@ -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_)))"
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user