Merge branch 'master' into directory-service

This commit is contained in:
Evgeny Poberezkin
2023-08-02 16:25:56 +01:00
17 changed files with 461 additions and 85 deletions
+22 -14
View File
@@ -802,33 +802,41 @@ func apiChatUnread(type: ChatType, id: Int64, unreadChat: Bool) async throws {
try await sendCommandOkResp(.apiChatUnread(type: type, id: id, unreadChat: unreadChat))
}
func receiveFile(user: User, fileId: Int64) async {
if let chatItem = await apiReceiveFile(fileId: fileId) {
func receiveFile(user: User, fileId: Int64, auto: Bool = false) async {
if let chatItem = await apiReceiveFile(fileId: fileId, auto: auto) {
DispatchQueue.main.async { chatItemSimpleUpdate(user, chatItem) }
}
}
func apiReceiveFile(fileId: Int64, inline: Bool? = nil) async -> AChatItem? {
func apiReceiveFile(fileId: Int64, inline: Bool? = nil, auto: Bool = false) async -> AChatItem? {
let r = await chatSendCmd(.receiveFile(fileId: fileId, inline: inline))
let am = AlertManager.shared
if case let .rcvFileAccepted(_, chatItem) = r { return chatItem }
if case .rcvFileAcceptedSndCancelled = r {
am.showAlertMsg(
title: "Cannot receive file",
message: "Sender cancelled file transfer."
)
logger.debug("apiReceiveFile error: sender cancelled file transfer")
if !auto {
am.showAlertMsg(
title: "Cannot receive file",
message: "Sender cancelled file transfer."
)
}
} else if let networkErrorAlert = networkErrorAlert(r) {
am.showAlert(networkErrorAlert)
logger.error("apiReceiveFile network error: \(String(describing: r))")
if !auto {
am.showAlert(networkErrorAlert)
}
} else {
logger.error("apiReceiveFile error: \(String(describing: r))")
switch r {
case .chatCmdError(_, .error(.fileAlreadyReceiving)):
logger.debug("apiReceiveFile ignoring fileAlreadyReceiving error")
default:
am.showAlertMsg(
title: "Error receiving file",
message: "Error: \(String(describing: r))"
)
logger.error("apiReceiveFile error: \(String(describing: r))")
if !auto {
am.showAlertMsg(
title: "Error receiving file",
message: "Error: \(String(describing: r))"
)
}
}
}
return nil
@@ -1323,7 +1331,7 @@ func processReceivedMsg(_ res: ChatResponse) async {
}
if let file = cItem.autoReceiveFile() {
Task {
await receiveFile(user: user, fileId: file.fileId)
await receiveFile(user: user, fileId: file.fileId, auto: true)
}
}
if cItem.showNotification {
@@ -247,10 +247,10 @@ struct CIVideoView: View {
.padding([.trailing, .top], 11)
}
private func receiveFileIfValidSize(file: CIFile, receiveFile: @escaping (User, Int64) async -> Void) {
private func receiveFileIfValidSize(file: CIFile, receiveFile: @escaping (User, Int64, Bool) async -> Void) {
Task {
if let user = ChatModel.shared.currentUser {
await receiveFile(user, file.fileId)
await receiveFile(user, file.fileId, false)
}
}
}
@@ -87,7 +87,7 @@ struct MsgContentView: View {
func messageText(_ text: String, _ formattedText: [FormattedText]?, _ sender: String?, icon: String? = nil, preview: Bool = false) -> Text {
let s = text
var res: Text
if let ft = formattedText, ft.count > 0 {
if let ft = formattedText, ft.count > 0 && ft.count <= 200 {
res = formatText(ft[0], preview)
var i = 1
while i < ft.count {
@@ -28,6 +28,7 @@ struct GroupMemberInfoView: View {
case switchAddressAlert
case abortSwitchAddressAlert
case syncConnectionForceAlert
case connectViaMemberAddressAlert(contactLink: String)
case connRequestSentAlert(type: ConnReqType)
case error(title: LocalizedStringKey, error: LocalizedStringKey)
case other(alert: Alert)
@@ -38,8 +39,9 @@ struct GroupMemberInfoView: View {
case let .changeMemberRoleAlert(_, role): return "changeMemberRoleAlert \(role.rawValue)"
case .switchAddressAlert: return "switchAddressAlert"
case .abortSwitchAddressAlert: return "abortSwitchAddressAlert"
case .connRequestSentAlert: return "connRequestSentAlert"
case .syncConnectionForceAlert: return "syncConnectionForceAlert"
case .connectViaMemberAddressAlert: return "connectViaMemberAddressAlert"
case .connRequestSentAlert: return "connRequestSentAlert"
case let .error(title, _): return "error \(title)"
case let .other(alert): return "other \(alert)"
}
@@ -201,6 +203,7 @@ struct GroupMemberInfoView: View {
case .switchAddressAlert: return switchAddressAlert(switchMemberAddress)
case .abortSwitchAddressAlert: return abortSwitchAddressAlert(abortSwitchMemberAddress)
case .syncConnectionForceAlert: return syncConnectionForceAlert({ syncMemberConnection(force: true) })
case let .connectViaMemberAddressAlert(contactLink): return connectViaMemberAddressAlert(contactLink)
case let .connRequestSentAlert(type): return connReqSentAlert(type)
case let .error(title, error): return Alert(title: Text(title), message: Text(error))
case let .other(alert): return alert
@@ -210,12 +213,23 @@ struct GroupMemberInfoView: View {
func connectViaAddressButton(_ contactLink: String) -> some View {
Button {
connectViaAddress(contactLink)
alert = .connectViaMemberAddressAlert(contactLink: contactLink)
} label: {
Label("Connect", systemImage: "link")
}
}
func connectViaMemberAddressAlert(_ contactLink: String) -> Alert {
return Alert(
title: Text("Connect directly?"),
message: Text("Сonnection request will be sent to this group member."),
primaryButton: .default(Text("Connect")) {
connectViaAddress(contactLink)
},
secondaryButton: .cancel()
)
}
func connectViaAddress(_ contactLink: String) {
Task {
let (connReqType, connectAlert) = await apiConnect_(connReq: contactLink)
+1 -1
View File
@@ -206,7 +206,7 @@ public func responseError(_ err: Error) -> String {
switch r {
case let .chatCmdError(_, chatError): return chatErrorString(chatError)
case let .chatError(_, chatError): return chatErrorString(chatError)
default: return String(describing: r)
default: return "\(String(describing: r.responseType)), details: \(String(describing: r.details))"
}
} else {
return String(describing: err)
+77 -7
View File
@@ -452,6 +452,7 @@ public enum ChatResponse: Decodable, Error {
case sentConfirmation(user: User)
case sentInvitation(user: User)
case contactAlreadyExists(user: User, contact: Contact)
case contactRequestAlreadyAccepted(user: User, contact: Contact)
case contactDeleted(user: User, contact: Contact)
case chatCleared(user: User, chatInfo: ChatInfo)
case userProfileNoChange(user: User)
@@ -481,6 +482,7 @@ public enum ChatResponse: Decodable, Error {
case newChatItem(user: User, chatItem: AChatItem)
case chatItemStatusUpdated(user: User, chatItem: AChatItem)
case chatItemUpdated(user: User, chatItem: AChatItem)
case chatItemNotChanged(user: User, chatItem: AChatItem)
case chatItemReaction(user: User, added: Bool, reaction: ACIReaction)
case chatItemDeleted(user: User, deletedChatItem: AChatItem, toChatItem: AChatItem?, byUser: Bool)
case contactsList(user: User, contacts: [Contact])
@@ -583,6 +585,7 @@ public enum ChatResponse: Decodable, Error {
case .sentConfirmation: return "sentConfirmation"
case .sentInvitation: return "sentInvitation"
case .contactAlreadyExists: return "contactAlreadyExists"
case .contactRequestAlreadyAccepted: return "contactRequestAlreadyAccepted"
case .contactDeleted: return "contactDeleted"
case .chatCleared: return "chatCleared"
case .userProfileNoChange: return "userProfileNoChange"
@@ -612,6 +615,7 @@ public enum ChatResponse: Decodable, Error {
case .newChatItem: return "newChatItem"
case .chatItemStatusUpdated: return "chatItemStatusUpdated"
case .chatItemUpdated: return "chatItemUpdated"
case .chatItemNotChanged: return "chatItemNotChanged"
case .chatItemReaction: return "chatItemReaction"
case .chatItemDeleted: return "chatItemDeleted"
case .contactsList: return "contactsList"
@@ -713,6 +717,7 @@ public enum ChatResponse: Decodable, Error {
case .sentConfirmation: return noDetails
case .sentInvitation: return noDetails
case let .contactAlreadyExists(u, contact): return withUser(u, String(describing: contact))
case let .contactRequestAlreadyAccepted(u, contact): return withUser(u, String(describing: contact))
case let .contactDeleted(u, contact): return withUser(u, String(describing: contact))
case let .chatCleared(u, chatInfo): return withUser(u, String(describing: chatInfo))
case .userProfileNoChange: return noDetails
@@ -742,6 +747,7 @@ public enum ChatResponse: Decodable, Error {
case let .newChatItem(u, chatItem): return withUser(u, String(describing: chatItem))
case let .chatItemStatusUpdated(u, chatItem): return withUser(u, String(describing: chatItem))
case let .chatItemUpdated(u, chatItem): return withUser(u, String(describing: chatItem))
case let .chatItemNotChanged(u, chatItem): return withUser(u, String(describing: chatItem))
case let .chatItemReaction(u, added, reaction): return withUser(u, "added: \(added)\n\(String(describing: reaction))")
case let .chatItemDeleted(u, deletedChatItem, toChatItem, byUser): return withUser(u, "deletedChatItem:\n\(String(describing: deletedChatItem))\ntoChatItem:\n\(String(describing: toChatItem))\nbyUser: \(byUser)")
case let .contactsList(u, contacts): return withUser(u, String(describing: contacts))
@@ -1367,14 +1373,32 @@ public enum ChatError: Decodable {
public enum ChatErrorType: Decodable {
case noActiveUser
case noConnectionUser(agentConnId: String)
case noSndFileUser(agentSndFileId: String)
case noRcvFileUser(agentRcvFileId: String)
case userUnknown
case activeUserExists
case userExists
case differentActiveUser
case differentActiveUser(commandUserId: Int64, activeUserId: Int64)
case cantDeleteActiveUser(userId: Int64)
case cantDeleteLastUser(userId: Int64)
case cantHideLastUser(userId: Int64)
case hiddenUserAlwaysMuted(userId: Int64)
case emptyUserPassword(userId: Int64)
case userAlreadyHidden(userId: Int64)
case userNotHidden(userId: Int64)
case chatNotStarted
case chatNotStopped
case chatStoreChanged
case invalidConnReq
case invalidChatMessage(message: String)
case invalidChatMessage(connection: Connection, message: String)
case contactNotReady(contact: Contact)
case groupUserRole
case contactDisabled(contact: Contact)
case connectionDisabled(connection: Connection)
case groupUserRole(groupInfo: GroupInfo, requiredRole: GroupMemberRole)
case groupMemberInitialRole(groupInfo: GroupInfo, initialRole: GroupMemberRole)
case contactIncognitoCantInvite
case groupIncognitoCantInvite
case groupContactRole(contactName: ContactName)
case groupDuplicateMember(contactName: ContactName)
case groupDuplicateMemberId
@@ -1386,23 +1410,49 @@ public enum ChatErrorType: Decodable {
case groupCantResendInvitation(groupInfo: GroupInfo, contactName: ContactName)
case groupInternal(message: String)
case fileNotFound(message: String)
case fileSize(filePath: String)
case fileAlreadyReceiving(message: String)
case fileCancelled(message: String)
case fileCancel(fileId: Int64, message: String)
case fileAlreadyExists(filePath: String)
case fileRead(filePath: String, message: String)
case fileWrite(filePath: String, message: String)
case fileSend(fileId: Int64, agentError: String)
case fileRcvChunk(message: String)
case fileInternal(message: String)
case fileImageType(filePath: String)
case fileImageSize(filePath: String)
case fileNotReceived(fileId: Int64)
// case xFTPRcvFile
// case xFTPSndFile
case fallbackToSMPProhibited(fileId: Int64)
case inlineFileProhibited(fileId: Int64)
case invalidQuote
case invalidChatItemUpdate
case invalidChatItemDelete
case hasCurrentCall
case noCurrentCall
case callContact(contactId: Int64)
case callState
case directMessagesProhibited(contact: Contact)
case agentVersion
case agentNoSubResult(agentConnId: String)
case commandError(message: String)
case serverProtocol
case agentCommandError(message: String)
case invalidFileDescription(message: String)
case internalError(message: String)
case exception(message: String)
}
public enum StoreError: Decodable {
case duplicateName
case userNotFound(userId: Int64)
case userNotFoundByName(contactName: ContactName)
case userNotFoundByContactId(contactId: Int64)
case userNotFoundByGroupId(groupId: Int64)
case userNotFoundByFileId(fileId: Int64)
case userNotFoundByContactRequestId(contactRequestId: Int64)
case contactNotFound(contactId: Int64)
case contactNotFoundByName(contactName: ContactName)
case contactNotReady(contactName: ContactName)
@@ -1412,6 +1462,9 @@ public enum StoreError: Decodable {
case contactRequestNotFoundByName(contactName: ContactName)
case groupNotFound(groupId: Int64)
case groupNotFoundByName(groupName: GroupName)
case groupMemberNameNotFound(groupId: Int64, groupMemberName: ContactName)
case groupMemberNotFound(groupMemberId: Int64)
case groupMemberNotFoundByMemberId(memberId: String)
case groupWithoutUser
case duplicateGroupMember
case groupAlreadyJoined
@@ -1419,9 +1472,16 @@ public enum StoreError: Decodable {
case sndFileNotFound(fileId: Int64)
case sndFileInvalid(fileId: Int64)
case rcvFileNotFound(fileId: Int64)
case rcvFileDescrNotFound(fileId: Int64)
case fileNotFound(fileId: Int64)
case rcvFileInvalid(fileId: Int64)
case rcvFileInvalidDescrPart
case sharedMsgIdNotFoundByFileId(fileId: Int64)
case fileIdNotFoundBySharedMsgId(sharedMsgId: String)
case sndFileNotFoundXFTP(agentSndFileId: String)
case rcvFileNotFoundXFTP(agentRcvFileId: String)
case connectionNotFound(agentConnId: String)
case connectionNotFoundById(connId: Int64)
case pendingConnectionNotFound(connId: Int64)
case introNotFound
case uniqueID
@@ -1429,11 +1489,16 @@ public enum StoreError: Decodable {
case noMsgDelivery(connId: Int64, agentMsgId: String)
case badChatItem(itemId: Int64)
case chatItemNotFound(itemId: Int64)
case quotedChatItemNotFound
case chatItemNotFoundByText(text: String)
case chatItemSharedMsgIdNotFound(sharedMsgId: String)
case chatItemNotFoundByFileId(fileId: Int64)
case chatItemNotFoundByGroupId(groupId: Int64)
case profileNotFound(profileId: Int64)
case duplicateGroupLink(groupInfo: GroupInfo)
case groupLinkNotFound(groupInfo: GroupInfo)
case hostMemberIdNotFound(groupId: Int64)
case contactNotFoundByFileId(fileId: Int64)
case noGroupSndStatus(itemId: Int64, groupMemberId: Int64)
}
public enum DatabaseError: Decodable {
@@ -1453,11 +1518,12 @@ public enum AgentErrorType: Decodable {
case CMD(cmdErr: CommandErrorType)
case CONN(connErr: ConnectionErrorType)
case SMP(smpErr: ProtocolErrorType)
case XFTP(xftpErr: XFTPErrorType)
case NTF(ntfErr: ProtocolErrorType)
case XFTP(xftpErr: XFTPErrorType)
case BROKER(brokerAddress: String, brokerErr: BrokerErrorType)
case AGENT(agentErr: SMPAgentError)
case INTERNAL(internalErr: String)
case INACTIVE
}
public enum CommandErrorType: Decodable {
@@ -1477,9 +1543,10 @@ public enum ConnectionErrorType: Decodable {
}
public enum BrokerErrorType: Decodable {
case RESPONSE(smpErr: ProtocolErrorType)
case RESPONSE(smpErr: String)
case UNEXPECTED
case NETWORK
case HOST
case TRANSPORT(transportErr: ProtocolTransportError)
case TIMEOUT
}
@@ -1513,6 +1580,7 @@ public enum XFTPErrorType: Decodable {
public enum ProtocolCommandError: Decodable {
case UNKNOWN
case SYNTAX
case PROHIBITED
case NO_AUTH
case HAS_AUTH
case NO_ENTITY
@@ -1535,7 +1603,9 @@ public enum SMPAgentError: Decodable {
case A_MESSAGE
case A_PROHIBITED
case A_VERSION
case A_ENCRYPTION
case A_CRYPTO
case A_DUPLICATE
case A_QUEUE(queueErr: String)
}
public enum ArchiveError: Decodable {
+1 -1
View File
@@ -11,7 +11,7 @@
local.properties
common/src/commonMain/cpp/android/libs/
common/src/commonMain/cpp/desktop/libs/
common/src/commonMain/resources/libs/
desktop/src/jvmMain/resources/libs/
android/build
android/release
common/build
@@ -49,7 +49,7 @@ object ChatModel {
val chatDbStatus = mutableStateOf<DBMigrationResult?>(null)
val chats = mutableStateListOf<Chat>()
// map of connections network statuses, key is agent connection id
val networkStatuses = mutableStateMapOf<String, NetworkStatus>()
val networkStatuses = mutableStateOf<Map<String, NetworkStatus>>(mapOf())
// current chat
val chatId = mutableStateOf<String?>(null)
@@ -477,11 +477,13 @@ object ChatModel {
}
fun setContactNetworkStatus(contact: Contact, status: NetworkStatus) {
networkStatuses[contact.activeConn.agentConnId] = status
val statuses = networkStatuses.value.toMutableMap()
statuses[contact.activeConn.agentConnId] = status
networkStatuses.value = statuses
}
fun contactNetworkStatus(contact: Contact): NetworkStatus =
networkStatuses[contact.activeConn.agentConnId] ?: NetworkStatus.Unknown()
networkStatuses.value[contact.activeConn.agentConnId] ?: NetworkStatus.Unknown()
fun addTerminalItem(item: TerminalItem) {
if (terminalItems.value.size >= 500) {
@@ -1678,9 +1678,11 @@ object ChatController {
}
private fun updateContactsStatus(contactRefs: List<ContactRef>, status: NetworkStatus) {
val statuses = chatModel.networkStatuses.value.toMutableMap()
for (c in contactRefs) {
chatModel.networkStatuses[c.agentConnId] = status
statuses[c.agentConnId] = status
}
chatModel.networkStatuses.value = statuses
}
private fun processContactSubError(contact: Contact, chatError: ChatError) {
@@ -3250,6 +3252,7 @@ sealed class CR {
@Serializable @SerialName("sentConfirmation") class SentConfirmation(val user: User): CR()
@Serializable @SerialName("sentInvitation") class SentInvitation(val user: User): CR()
@Serializable @SerialName("contactAlreadyExists") class ContactAlreadyExists(val user: User, val contact: Contact): CR()
@Serializable @SerialName("contactRequestAlreadyAccepted") class ContactRequestAlreadyAccepted(val user: User, val contact: Contact): CR()
@Serializable @SerialName("contactDeleted") class ContactDeleted(val user: User, val contact: Contact): CR()
@Serializable @SerialName("chatCleared") class ChatCleared(val user: User, val chatInfo: ChatInfo): CR()
@Serializable @SerialName("userProfileNoChange") class UserProfileNoChange(val user: User): CR()
@@ -3279,6 +3282,7 @@ sealed class CR {
@Serializable @SerialName("newChatItem") class NewChatItem(val user: User, val chatItem: AChatItem): CR()
@Serializable @SerialName("chatItemStatusUpdated") class ChatItemStatusUpdated(val user: User, val chatItem: AChatItem): CR()
@Serializable @SerialName("chatItemUpdated") class ChatItemUpdated(val user: User, val chatItem: AChatItem): CR()
@Serializable @SerialName("chatItemNotChanged") class ChatItemNotChanged(val user: User, val chatItem: AChatItem): CR()
@Serializable @SerialName("chatItemReaction") class ChatItemReaction(val user: User, val added: Boolean, val reaction: ACIReaction): CR()
@Serializable @SerialName("chatItemDeleted") class ChatItemDeleted(val user: User, val deletedChatItem: AChatItem, val toChatItem: AChatItem? = null, val byUser: Boolean): CR()
@Serializable @SerialName("contactsList") class ContactsList(val user: User, val contacts: List<Contact>): CR()
@@ -3376,6 +3380,7 @@ sealed class CR {
is SentConfirmation -> "sentConfirmation"
is SentInvitation -> "sentInvitation"
is ContactAlreadyExists -> "contactAlreadyExists"
is ContactRequestAlreadyAccepted -> "contactRequestAlreadyAccepted"
is ContactDeleted -> "contactDeleted"
is ChatCleared -> "chatCleared"
is UserProfileNoChange -> "userProfileNoChange"
@@ -3405,6 +3410,7 @@ sealed class CR {
is NewChatItem -> "newChatItem"
is ChatItemStatusUpdated -> "chatItemStatusUpdated"
is ChatItemUpdated -> "chatItemUpdated"
is ChatItemNotChanged -> "chatItemNotChanged"
is ChatItemReaction -> "chatItemReaction"
is ChatItemDeleted -> "chatItemDeleted"
is ContactsList -> "contactsList"
@@ -3499,6 +3505,7 @@ sealed class CR {
is SentConfirmation -> withUser(user, noDetails())
is SentInvitation -> withUser(user, noDetails())
is ContactAlreadyExists -> withUser(user, json.encodeToString(contact))
is ContactRequestAlreadyAccepted -> withUser(user, json.encodeToString(contact))
is ContactDeleted -> withUser(user, json.encodeToString(contact))
is ChatCleared -> withUser(user, json.encodeToString(chatInfo))
is UserProfileNoChange -> withUser(user, noDetails())
@@ -3529,6 +3536,7 @@ sealed class CR {
is NewChatItem -> withUser(user, json.encodeToString(chatItem))
is ChatItemStatusUpdated -> withUser(user, json.encodeToString(chatItem))
is ChatItemUpdated -> withUser(user, json.encodeToString(chatItem))
is ChatItemNotChanged -> withUser(user, json.encodeToString(chatItem))
is ChatItemReaction -> withUser(user, "added: $added\n${json.encodeToString(reaction)}")
is ChatItemDeleted -> withUser(user, "deletedChatItem:\n${json.encodeToString(deletedChatItem)}\ntoChatItem:\n${json.encodeToString(toChatItem)}\nbyUser: $byUser")
is ContactsList -> withUser(user, json.encodeToString(contacts))
@@ -3734,34 +3742,266 @@ sealed class ChatError {
@Serializable
sealed class ChatErrorType {
val string: String get() = when (this) {
is NoActiveUser -> "noActiveUser"
is DifferentActiveUser -> "differentActiveUser"
is UserExists -> "userExists"
is InvalidConnReq -> "invalidConnReq"
is FileAlreadyReceiving -> "fileAlreadyReceiving"
is СommandError -> "commandError $message"
is CEException -> "exception $message"
}
@Serializable @SerialName("noActiveUser") class NoActiveUser: ChatErrorType()
@Serializable @SerialName("differentActiveUser") class DifferentActiveUser: ChatErrorType()
val string: String
get() = when (this) {
is NoActiveUser -> "noActiveUser"
is NoConnectionUser -> "noConnectionUser"
is NoSndFileUser -> "noSndFileUser"
is NoRcvFileUser -> "noRcvFileUser"
is UserUnknown -> "userUnknown"
is ActiveUserExists -> "activeUserExists"
is UserExists -> "userExists"
is DifferentActiveUser -> "differentActiveUser"
is CantDeleteActiveUser -> "cantDeleteActiveUser"
is CantDeleteLastUser -> "cantDeleteLastUser"
is CantHideLastUser -> "cantHideLastUser"
is HiddenUserAlwaysMuted -> "hiddenUserAlwaysMuted"
is EmptyUserPassword -> "emptyUserPassword"
is UserAlreadyHidden -> "userAlreadyHidden"
is UserNotHidden -> "userNotHidden"
is ChatNotStarted -> "chatNotStarted"
is ChatNotStopped -> "chatNotStopped"
is ChatStoreChanged -> "chatStoreChanged"
is InvalidConnReq -> "invalidConnReq"
is InvalidChatMessage -> "invalidChatMessage"
is ContactNotReady -> "contactNotReady"
is ContactDisabled -> "contactDisabled"
is ConnectionDisabled -> "connectionDisabled"
is GroupUserRole -> "groupUserRole"
is GroupMemberInitialRole -> "groupMemberInitialRole"
is ContactIncognitoCantInvite -> "contactIncognitoCantInvite"
is GroupIncognitoCantInvite -> "groupIncognitoCantInvite"
is GroupContactRole -> "groupContactRole"
is GroupDuplicateMember -> "groupDuplicateMember"
is GroupDuplicateMemberId -> "groupDuplicateMemberId"
is GroupNotJoined -> "groupNotJoined"
is GroupMemberNotActive -> "groupMemberNotActive"
is GroupMemberUserRemoved -> "groupMemberUserRemoved"
is GroupMemberNotFound -> "groupMemberNotFound"
is GroupMemberIntroNotFound -> "groupMemberIntroNotFound"
is GroupCantResendInvitation -> "groupCantResendInvitation"
is GroupInternal -> "groupInternal"
is FileNotFound -> "fileNotFound"
is FileSize -> "fileSize"
is FileAlreadyReceiving -> "fileAlreadyReceiving"
is FileCancelled -> "fileCancelled"
is FileCancel -> "fileCancel"
is FileAlreadyExists -> "fileAlreadyExists"
is FileRead -> "fileRead"
is FileWrite -> "fileWrite"
is FileSend -> "fileSend"
is FileRcvChunk -> "fileRcvChunk"
is FileInternal -> "fileInternal"
is FileImageType -> "fileImageType"
is FileImageSize -> "fileImageSize"
is FileNotReceived -> "fileNotReceived"
// is XFTPRcvFile -> "xftpRcvFile"
// is XFTPSndFile -> "xftpSndFile"
is FallbackToSMPProhibited -> "fallbackToSMPProhibited"
is InlineFileProhibited -> "inlineFileProhibited"
is InvalidQuote -> "invalidQuote"
is InvalidChatItemUpdate -> "invalidChatItemUpdate"
is InvalidChatItemDelete -> "invalidChatItemDelete"
is HasCurrentCall -> "hasCurrentCall"
is NoCurrentCall -> "noCurrentCall"
is CallContact -> "callContact"
is CallState -> "callState"
is DirectMessagesProhibited -> "directMessagesProhibited"
is AgentVersion -> "agentVersion"
is AgentNoSubResult -> "agentNoSubResult"
is CommandError -> "commandError $message"
is ServerProtocol -> "serverProtocol"
is AgentCommandError -> "agentCommandError"
is InvalidFileDescription -> "invalidFileDescription"
is InternalError -> "internalError"
is CEException -> "exception $message"
}
@Serializable @SerialName("noActiveUser") object NoActiveUser: ChatErrorType()
@Serializable @SerialName("noConnectionUser") class NoConnectionUser(val agentConnId: String): ChatErrorType()
@Serializable @SerialName("noSndFileUser") class NoSndFileUser(val agentSndFileId: String): ChatErrorType()
@Serializable @SerialName("noRcvFileUser") class NoRcvFileUser(val agentRcvFileId: String): ChatErrorType()
@Serializable @SerialName("userUnknown") object UserUnknown: ChatErrorType()
@Serializable @SerialName("activeUserExists") object ActiveUserExists: ChatErrorType()
@Serializable @SerialName("userExists") class UserExists(val contactName: String): ChatErrorType()
@Serializable @SerialName("invalidConnReq") class InvalidConnReq: ChatErrorType()
@Serializable @SerialName("fileAlreadyReceiving") class FileAlreadyReceiving: ChatErrorType()
@Serializable @SerialName("commandError") class СommandError(val message: String): ChatErrorType()
@Serializable @SerialName("differentActiveUser") class DifferentActiveUser(val commandUserId: Long, val activeUserId: Long): ChatErrorType()
@Serializable @SerialName("cantDeleteActiveUser") class CantDeleteActiveUser(val userId: Long): ChatErrorType()
@Serializable @SerialName("cantDeleteLastUser") class CantDeleteLastUser(val userId: Long): ChatErrorType()
@Serializable @SerialName("cantHideLastUser") class CantHideLastUser(val userId: Long): ChatErrorType()
@Serializable @SerialName("hiddenUserAlwaysMuted") class HiddenUserAlwaysMuted(val userId: Long): ChatErrorType()
@Serializable @SerialName("emptyUserPassword") class EmptyUserPassword(val userId: Long): ChatErrorType()
@Serializable @SerialName("userAlreadyHidden") class UserAlreadyHidden(val userId: Long): ChatErrorType()
@Serializable @SerialName("userNotHidden") class UserNotHidden(val userId: Long): ChatErrorType()
@Serializable @SerialName("chatNotStarted") object ChatNotStarted: ChatErrorType()
@Serializable @SerialName("chatNotStopped") object ChatNotStopped: ChatErrorType()
@Serializable @SerialName("chatStoreChanged") object ChatStoreChanged: ChatErrorType()
@Serializable @SerialName("invalidConnReq") object InvalidConnReq: ChatErrorType()
@Serializable @SerialName("invalidChatMessage") class InvalidChatMessage(val connection: Connection, val message: String): ChatErrorType()
@Serializable @SerialName("contactNotReady") class ContactNotReady(val contact: Contact): ChatErrorType()
@Serializable @SerialName("contactDisabled") class ContactDisabled(val contact: Contact): ChatErrorType()
@Serializable @SerialName("connectionDisabled") class ConnectionDisabled(val connection: Connection): ChatErrorType()
@Serializable @SerialName("groupUserRole") class GroupUserRole(val groupInfo: GroupInfo, val requiredRole: GroupMemberRole): ChatErrorType()
@Serializable @SerialName("groupMemberInitialRole") class GroupMemberInitialRole(val groupInfo: GroupInfo, val initialRole: GroupMemberRole): ChatErrorType()
@Serializable @SerialName("contactIncognitoCantInvite") object ContactIncognitoCantInvite: ChatErrorType()
@Serializable @SerialName("groupIncognitoCantInvite") object GroupIncognitoCantInvite: ChatErrorType()
@Serializable @SerialName("groupContactRole") class GroupContactRole(val contactName: String): ChatErrorType()
@Serializable @SerialName("groupDuplicateMember") class GroupDuplicateMember(val contactName: String): ChatErrorType()
@Serializable @SerialName("groupDuplicateMemberId") object GroupDuplicateMemberId: ChatErrorType()
@Serializable @SerialName("groupNotJoined") class GroupNotJoined(val groupInfo: GroupInfo): ChatErrorType()
@Serializable @SerialName("groupMemberNotActive") object GroupMemberNotActive: ChatErrorType()
@Serializable @SerialName("groupMemberUserRemoved") object GroupMemberUserRemoved: ChatErrorType()
@Serializable @SerialName("groupMemberNotFound") object GroupMemberNotFound: ChatErrorType()
@Serializable @SerialName("groupMemberIntroNotFound") class GroupMemberIntroNotFound(val contactName: String): ChatErrorType()
@Serializable @SerialName("groupCantResendInvitation") class GroupCantResendInvitation(val groupInfo: GroupInfo, val contactName: String): ChatErrorType()
@Serializable @SerialName("groupInternal") class GroupInternal(val message: String): ChatErrorType()
@Serializable @SerialName("fileNotFound") class FileNotFound(val message: String): ChatErrorType()
@Serializable @SerialName("fileSize") class FileSize(val filePath: String): ChatErrorType()
@Serializable @SerialName("fileAlreadyReceiving") class FileAlreadyReceiving(val message: String): ChatErrorType()
@Serializable @SerialName("fileCancelled") class FileCancelled(val message: String): ChatErrorType()
@Serializable @SerialName("fileCancel") class FileCancel(val fileId: Long, val message: String): ChatErrorType()
@Serializable @SerialName("fileAlreadyExists") class FileAlreadyExists(val filePath: String): ChatErrorType()
@Serializable @SerialName("fileRead") class FileRead(val filePath: String, val message: String): ChatErrorType()
@Serializable @SerialName("fileWrite") class FileWrite(val filePath: String, val message: String): ChatErrorType()
@Serializable @SerialName("fileSend") class FileSend(val fileId: Long, val agentError: String): ChatErrorType()
@Serializable @SerialName("fileRcvChunk") class FileRcvChunk(val message: String): ChatErrorType()
@Serializable @SerialName("fileInternal") class FileInternal(val message: String): ChatErrorType()
@Serializable @SerialName("fileImageType") class FileImageType(val filePath: String): ChatErrorType()
@Serializable @SerialName("fileImageSize") class FileImageSize(val filePath: String): ChatErrorType()
@Serializable @SerialName("fileNotReceived") class FileNotReceived(val fileId: Long): ChatErrorType()
// @Serializable @SerialName("xFTPRcvFile") object XFTPRcvFile: ChatErrorType()
// @Serializable @SerialName("xFTPSndFile") object XFTPSndFile: ChatErrorType()
@Serializable @SerialName("fallbackToSMPProhibited") class FallbackToSMPProhibited(val fileId: Long): ChatErrorType()
@Serializable @SerialName("inlineFileProhibited") class InlineFileProhibited(val fileId: Long): ChatErrorType()
@Serializable @SerialName("invalidQuote") object InvalidQuote: ChatErrorType()
@Serializable @SerialName("invalidChatItemUpdate") object InvalidChatItemUpdate: ChatErrorType()
@Serializable @SerialName("invalidChatItemDelete") object InvalidChatItemDelete: ChatErrorType()
@Serializable @SerialName("hasCurrentCall") object HasCurrentCall: ChatErrorType()
@Serializable @SerialName("noCurrentCall") object NoCurrentCall: ChatErrorType()
@Serializable @SerialName("callContact") class CallContact(val contactId: Long): ChatErrorType()
@Serializable @SerialName("callState") object CallState: ChatErrorType()
@Serializable @SerialName("directMessagesProhibited") class DirectMessagesProhibited(val contact: Contact): ChatErrorType()
@Serializable @SerialName("agentVersion") object AgentVersion: ChatErrorType()
@Serializable @SerialName("agentNoSubResult") class AgentNoSubResult(val agentConnId: String): ChatErrorType()
@Serializable @SerialName("commandError") class CommandError(val message: String): ChatErrorType()
@Serializable @SerialName("serverProtocol") object ServerProtocol: ChatErrorType()
@Serializable @SerialName("agentCommandError") class AgentCommandError(val message: String): ChatErrorType()
@Serializable @SerialName("invalidFileDescription") class InvalidFileDescription(val message: String): ChatErrorType()
@Serializable @SerialName("internalError") class InternalError(val message: String): ChatErrorType()
@Serializable @SerialName("exception") class CEException(val message: String): ChatErrorType()
}
@Serializable
sealed class StoreError {
val string: String get() = when (this) {
is UserContactLinkNotFound -> "userContactLinkNotFound"
is GroupNotFound -> "groupNotFound"
is DuplicateName -> "duplicateName"
}
@Serializable @SerialName("userContactLinkNotFound") class UserContactLinkNotFound: StoreError()
@Serializable @SerialName("groupNotFound") class GroupNotFound: StoreError()
@Serializable @SerialName("duplicateName") class DuplicateName: StoreError()
val string: String
get() = when (this) {
is DuplicateName -> "duplicateName"
is UserNotFound -> "userNotFound"
is UserNotFoundByName -> "userNotFoundByName"
is UserNotFoundByContactId -> "userNotFoundByContactId"
is UserNotFoundByGroupId -> "userNotFoundByGroupId"
is UserNotFoundByFileId -> "userNotFoundByFileId"
is UserNotFoundByContactRequestId -> "userNotFoundByContactRequestId"
is ContactNotFound -> "contactNotFound"
is ContactNotFoundByName -> "contactNotFoundByName"
is ContactNotReady -> "contactNotReady"
is DuplicateContactLink -> "duplicateContactLink"
is UserContactLinkNotFound -> "userContactLinkNotFound"
is ContactRequestNotFound -> "contactRequestNotFound"
is ContactRequestNotFoundByName -> "contactRequestNotFoundByName"
is GroupNotFound -> "groupNotFound"
is GroupNotFoundByName -> "groupNotFoundByName"
is GroupMemberNameNotFound -> "groupMemberNameNotFound"
is GroupMemberNotFound -> "groupMemberNotFound"
is GroupMemberNotFoundByMemberId -> "groupMemberNotFoundByMemberId"
is GroupWithoutUser -> "groupWithoutUser"
is DuplicateGroupMember -> "duplicateGroupMember"
is GroupAlreadyJoined -> "groupAlreadyJoined"
is GroupInvitationNotFound -> "groupInvitationNotFound"
is SndFileNotFound -> "sndFileNotFound"
is SndFileInvalid -> "sndFileInvalid"
is RcvFileNotFound -> "rcvFileNotFound"
is RcvFileDescrNotFound -> "rcvFileDescrNotFound"
is FileNotFound -> "fileNotFound"
is RcvFileInvalid -> "rcvFileInvalid"
is RcvFileInvalidDescrPart -> "rcvFileInvalidDescrPart"
is SharedMsgIdNotFoundByFileId -> "sharedMsgIdNotFoundByFileId"
is FileIdNotFoundBySharedMsgId -> "fileIdNotFoundBySharedMsgId"
is SndFileNotFoundXFTP -> "sndFileNotFoundXFTP"
is RcvFileNotFoundXFTP -> "rcvFileNotFoundXFTP"
is ConnectionNotFound -> "connectionNotFound"
is ConnectionNotFoundById -> "connectionNotFoundById"
is PendingConnectionNotFound -> "pendingConnectionNotFound"
is IntroNotFound -> "introNotFound"
is UniqueID -> "uniqueID"
is InternalError -> "internalError"
is NoMsgDelivery -> "noMsgDelivery"
is BadChatItem -> "badChatItem"
is ChatItemNotFound -> "chatItemNotFound"
is ChatItemNotFoundByText -> "chatItemNotFoundByText"
is ChatItemSharedMsgIdNotFound -> "chatItemSharedMsgIdNotFound"
is ChatItemNotFoundByFileId -> "chatItemNotFoundByFileId"
is ChatItemNotFoundByGroupId -> "chatItemNotFoundByGroupId"
is ProfileNotFound -> "profileNotFound"
is DuplicateGroupLink -> "duplicateGroupLink"
is GroupLinkNotFound -> "groupLinkNotFound"
is HostMemberIdNotFound -> "hostMemberIdNotFound"
is ContactNotFoundByFileId -> "contactNotFoundByFileId"
is NoGroupSndStatus -> "noGroupSndStatus"
}
@Serializable @SerialName("duplicateName") object DuplicateName: StoreError()
@Serializable @SerialName("userNotFound") class UserNotFound(val userId: Long): StoreError()
@Serializable @SerialName("userNotFoundByName") class UserNotFoundByName(val contactName: String): StoreError()
@Serializable @SerialName("userNotFoundByContactId") class UserNotFoundByContactId(val contactId: Long): StoreError()
@Serializable @SerialName("userNotFoundByGroupId") class UserNotFoundByGroupId(val groupId: Long): StoreError()
@Serializable @SerialName("userNotFoundByFileId") class UserNotFoundByFileId(val fileId: Long): StoreError()
@Serializable @SerialName("userNotFoundByContactRequestId") class UserNotFoundByContactRequestId(val contactRequestId: Long): StoreError()
@Serializable @SerialName("contactNotFound") class ContactNotFound(val contactId: Long): StoreError()
@Serializable @SerialName("contactNotFoundByName") class ContactNotFoundByName(val contactName: String): StoreError()
@Serializable @SerialName("contactNotReady") class ContactNotReady(val contactName: String): StoreError()
@Serializable @SerialName("duplicateContactLink") object DuplicateContactLink: StoreError()
@Serializable @SerialName("userContactLinkNotFound") object UserContactLinkNotFound: StoreError()
@Serializable @SerialName("contactRequestNotFound") class ContactRequestNotFound(val contactRequestId: Long): StoreError()
@Serializable @SerialName("contactRequestNotFoundByName") class ContactRequestNotFoundByName(val contactName: String): StoreError()
@Serializable @SerialName("groupNotFound") class GroupNotFound(val groupId: Long): StoreError()
@Serializable @SerialName("groupNotFoundByName") class GroupNotFoundByName(val groupName: String): StoreError()
@Serializable @SerialName("groupMemberNameNotFound") class GroupMemberNameNotFound(val groupId: Long, val groupMemberName: String): StoreError()
@Serializable @SerialName("groupMemberNotFound") class GroupMemberNotFound(val groupMemberId: Long): StoreError()
@Serializable @SerialName("groupMemberNotFoundByMemberId") class GroupMemberNotFoundByMemberId(val memberId: String): StoreError()
@Serializable @SerialName("groupWithoutUser") object GroupWithoutUser: StoreError()
@Serializable @SerialName("duplicateGroupMember") object DuplicateGroupMember: StoreError()
@Serializable @SerialName("groupAlreadyJoined") object GroupAlreadyJoined: StoreError()
@Serializable @SerialName("groupInvitationNotFound") object GroupInvitationNotFound: StoreError()
@Serializable @SerialName("sndFileNotFound") class SndFileNotFound(val fileId: Long): StoreError()
@Serializable @SerialName("sndFileInvalid") class SndFileInvalid(val fileId: Long): StoreError()
@Serializable @SerialName("rcvFileNotFound") class RcvFileNotFound(val fileId: Long): StoreError()
@Serializable @SerialName("rcvFileDescrNotFound") class RcvFileDescrNotFound(val fileId: Long): StoreError()
@Serializable @SerialName("fileNotFound") class FileNotFound(val fileId: Long): StoreError()
@Serializable @SerialName("rcvFileInvalid") class RcvFileInvalid(val fileId: Long): StoreError()
@Serializable @SerialName("rcvFileInvalidDescrPart") object RcvFileInvalidDescrPart: StoreError()
@Serializable @SerialName("sharedMsgIdNotFoundByFileId") class SharedMsgIdNotFoundByFileId(val fileId: Long): StoreError()
@Serializable @SerialName("fileIdNotFoundBySharedMsgId") class FileIdNotFoundBySharedMsgId(val sharedMsgId: String): StoreError()
@Serializable @SerialName("sndFileNotFoundXFTP") class SndFileNotFoundXFTP(val agentSndFileId: String): StoreError()
@Serializable @SerialName("rcvFileNotFoundXFTP") class RcvFileNotFoundXFTP(val agentRcvFileId: String): StoreError()
@Serializable @SerialName("connectionNotFound") class ConnectionNotFound(val agentConnId: String): StoreError()
@Serializable @SerialName("connectionNotFoundById") class ConnectionNotFoundById(val connId: Long): StoreError()
@Serializable @SerialName("pendingConnectionNotFound") class PendingConnectionNotFound(val connId: Long): StoreError()
@Serializable @SerialName("introNotFound") object IntroNotFound: StoreError()
@Serializable @SerialName("uniqueID") object UniqueID: StoreError()
@Serializable @SerialName("internalError") class InternalError(val message: String): StoreError()
@Serializable @SerialName("noMsgDelivery") class NoMsgDelivery(val connId: Long, val agentMsgId: String): StoreError()
@Serializable @SerialName("badChatItem") class BadChatItem(val itemId: Long): StoreError()
@Serializable @SerialName("chatItemNotFound") class ChatItemNotFound(val itemId: Long): StoreError()
@Serializable @SerialName("chatItemNotFoundByText") class ChatItemNotFoundByText(val text: String): StoreError()
@Serializable @SerialName("chatItemSharedMsgIdNotFound") class ChatItemSharedMsgIdNotFound(val sharedMsgId: String): StoreError()
@Serializable @SerialName("chatItemNotFoundByFileId") class ChatItemNotFoundByFileId(val fileId: Long): StoreError()
@Serializable @SerialName("chatItemNotFoundByGroupId") class ChatItemNotFoundByGroupId(val groupId: Long): StoreError()
@Serializable @SerialName("profileNotFound") class ProfileNotFound(val profileId: Long): StoreError()
@Serializable @SerialName("duplicateGroupLink") class DuplicateGroupLink(val groupInfo: GroupInfo): StoreError()
@Serializable @SerialName("groupLinkNotFound") class GroupLinkNotFound(val groupInfo: GroupInfo): StoreError()
@Serializable @SerialName("hostMemberIdNotFound") class HostMemberIdNotFound(val groupId: Long): StoreError()
@Serializable @SerialName("contactNotFoundByFileId") class ContactNotFoundByFileId(val fileId: Long): StoreError()
@Serializable @SerialName("noGroupSndStatus") class NoGroupSndStatus(val itemId: Long, val groupMemberId: Long): StoreError()
}
@Serializable
@@ -3792,18 +4032,22 @@ sealed class AgentErrorType {
is CMD -> "CMD ${cmdErr.string}"
is CONN -> "CONN ${connErr.string}"
is SMP -> "SMP ${smpErr.string}"
// is NTF -> "NTF ${ntfErr.string}"
is XFTP -> "XFTP ${xftpErr.string}"
is BROKER -> "BROKER ${brokerErr.string}"
is AGENT -> "AGENT ${agentErr.string}"
is INTERNAL -> "INTERNAL $internalErr"
is INACTIVE -> "INACTIVE"
}
@Serializable @SerialName("CMD") class CMD(val cmdErr: CommandErrorType): AgentErrorType()
@Serializable @SerialName("CONN") class CONN(val connErr: ConnectionErrorType): AgentErrorType()
@Serializable @SerialName("SMP") class SMP(val smpErr: SMPErrorType): AgentErrorType()
// @Serializable @SerialName("NTF") class NTF(val ntfErr: SMPErrorType): AgentErrorType()
@Serializable @SerialName("XFTP") class XFTP(val xftpErr: XFTPErrorType): AgentErrorType()
@Serializable @SerialName("BROKER") class BROKER(val brokerAddress: String, val brokerErr: BrokerErrorType): AgentErrorType()
@Serializable @SerialName("AGENT") class AGENT(val agentErr: SMPAgentError): AgentErrorType()
@Serializable @SerialName("INTERNAL") class INTERNAL(val internalErr: String): AgentErrorType()
@Serializable @SerialName("INACTIVE") object INACTIVE: AgentErrorType()
}
@Serializable
@@ -3841,17 +4085,19 @@ sealed class ConnectionErrorType {
@Serializable
sealed class BrokerErrorType {
val string: String get() = when (this) {
is RESPONSE -> "RESPONSE ${smpErr.string}"
is RESPONSE -> "RESPONSE ${smpErr}"
is UNEXPECTED -> "UNEXPECTED"
is NETWORK -> "NETWORK"
is HOST -> "HOST"
is TRANSPORT -> "TRANSPORT ${transportErr.string}"
is TIMEOUT -> "TIMEOUT"
}
@Serializable @SerialName("RESPONSE") class RESPONSE(val smpErr: SMPErrorType): BrokerErrorType()
@Serializable @SerialName("UNEXPECTED") class UNEXPECTED: BrokerErrorType()
@Serializable @SerialName("NETWORK") class NETWORK: BrokerErrorType()
@Serializable @SerialName("RESPONSE") class RESPONSE(val smpErr: String): BrokerErrorType()
@Serializable @SerialName("UNEXPECTED") object UNEXPECTED: BrokerErrorType()
@Serializable @SerialName("NETWORK") object NETWORK: BrokerErrorType()
@Serializable @SerialName("HOST") object HOST: BrokerErrorType()
@Serializable @SerialName("TRANSPORT") class TRANSPORT(val transportErr: SMPTransportError): BrokerErrorType()
@Serializable @SerialName("TIMEOUT") class TIMEOUT: BrokerErrorType()
@Serializable @SerialName("TIMEOUT") object TIMEOUT: BrokerErrorType()
}
@Serializable
@@ -3881,15 +4127,17 @@ sealed class ProtocolCommandError {
val string: String get() = when (this) {
is UNKNOWN -> "UNKNOWN"
is SYNTAX -> "SYNTAX"
is PROHIBITED -> "PROHIBITED"
is NO_AUTH -> "NO_AUTH"
is HAS_AUTH -> "HAS_AUTH"
is NO_QUEUE -> "NO_QUEUE"
}
@Serializable @SerialName("UNKNOWN") class UNKNOWN: ProtocolCommandError()
@Serializable @SerialName("SYNTAX") class SYNTAX: ProtocolCommandError()
@Serializable @SerialName("NO_AUTH") class NO_AUTH: ProtocolCommandError()
@Serializable @SerialName("HAS_AUTH") class HAS_AUTH: ProtocolCommandError()
@Serializable @SerialName("NO_QUEUE") class NO_QUEUE: ProtocolCommandError()
@Serializable @SerialName("UNKNOWN") object UNKNOWN: ProtocolCommandError()
@Serializable @SerialName("SYNTAX") object SYNTAX: ProtocolCommandError()
@Serializable @SerialName("PROHIBITED") object PROHIBITED: ProtocolCommandError()
@Serializable @SerialName("NO_AUTH") object NO_AUTH: ProtocolCommandError()
@Serializable @SerialName("HAS_AUTH") object HAS_AUTH: ProtocolCommandError()
@Serializable @SerialName("NO_QUEUE") object NO_QUEUE: ProtocolCommandError()
}
@Serializable
@@ -3924,12 +4172,16 @@ sealed class SMPAgentError {
is A_MESSAGE -> "A_MESSAGE"
is A_PROHIBITED -> "A_PROHIBITED"
is A_VERSION -> "A_VERSION"
is A_ENCRYPTION -> "A_ENCRYPTION"
is A_CRYPTO -> "A_CRYPTO"
is A_DUPLICATE -> "A_DUPLICATE"
is A_QUEUE -> "A_QUEUE"
}
@Serializable @SerialName("A_MESSAGE") class A_MESSAGE: SMPAgentError()
@Serializable @SerialName("A_PROHIBITED") class A_PROHIBITED: SMPAgentError()
@Serializable @SerialName("A_VERSION") class A_VERSION: SMPAgentError()
@Serializable @SerialName("A_ENCRYPTION") class A_ENCRYPTION: SMPAgentError()
@Serializable @SerialName("A_MESSAGE") object A_MESSAGE: SMPAgentError()
@Serializable @SerialName("A_PROHIBITED") object A_PROHIBITED: SMPAgentError()
@Serializable @SerialName("A_VERSION") object A_VERSION: SMPAgentError()
@Serializable @SerialName("A_CRYPTO") object A_CRYPTO: SMPAgentError()
@Serializable @SerialName("A_DUPLICATE") object A_DUPLICATE: SMPAgentError()
@Serializable @SerialName("A_QUEUE") class A_QUEUE(val queueErr: String): SMPAgentError()
}
@Serializable
@@ -46,7 +46,7 @@ private fun sendCommand(chatModel: ChatModel, composeState: MutableState<Compose
val prefPerformLA = chatModel.controller.appPrefs.performLA.get()
val s = composeState.value.message
if (s.startsWith("/sql") && (!prefPerformLA || !developerTools)) {
val resp = CR.ChatCmdError(null, ChatError.ChatErrorChat(ChatErrorType.СommandError("Failed reading: empty")))
val resp = CR.ChatCmdError(null, ChatError.ChatErrorChat(ChatErrorType.CommandError("Failed reading: empty")))
chatModel.addTerminalItem(TerminalItem.cmd(CC.Console(s)))
chatModel.addTerminalItem(TerminalItem.resp(resp))
composeState.value = ComposeState(useLinkPreviews = false)
@@ -55,7 +55,7 @@ fun ChatInfoView(
val connStats = remember { mutableStateOf(connectionStats) }
val developerTools = chatModel.controller.appPrefs.developerTools.get()
if (chat != null && currentUser != null) {
val contactNetworkStatus = remember(chatModel.networkStatuses.toMap()) {
val contactNetworkStatus = remember(chatModel.networkStatuses.value) {
mutableStateOf(chatModel.contactNetworkStatus(contact))
}
val sendReceipts = remember { mutableStateOf(SendReceipts.fromBool(contact.chatSettings.sendRcpts, currentUser.sendRcptsContacts)) }
@@ -76,13 +76,7 @@ fun GroupMemberInfoView(
}
},
connectViaAddress = { connReqUri ->
val uri = URI(connReqUri)
withUriAction(uri) { linkType ->
withApi {
Log.d(TAG, "connectViaUri: connecting")
connectViaUri(chatModel, linkType, uri)
}
}
connectViaMemberAddressAlert(connReqUri)
},
removeMember = { removeMemberDialog(groupInfo, member, chatModel, close) },
onRoleSelected = {
@@ -450,6 +444,23 @@ private fun updateMemberRoleDialog(
)
}
fun connectViaMemberAddressAlert(connReqUri: String) {
AlertManager.shared.showAlertDialog(
title = generalGetString(MR.strings.connect_via_member_address_alert_title),
text = generalGetString(MR.strings.connect_via_member_address_alert_desc),
confirmText = generalGetString(MR.strings.connect_via_link_verb),
onConfirm = {
val uri = URI(connReqUri)
withUriAction(uri) { linkType ->
withApi {
Log.d(TAG, "connectViaUri: connecting")
connectViaUri(chatModel, linkType, uri)
}
}
},
)
}
@Preview
@Composable
fun PreviewGroupMemberInfoLayout() {
@@ -1212,6 +1212,8 @@
<string name="change_member_role_question">Change group role?</string>
<string name="member_role_will_be_changed_with_notification">The role will be changed to \"%s\". Everyone in the group will be notified.</string>
<string name="member_role_will_be_changed_with_invitation">The role will be changed to \"%s\". The member will receive a new invitation.</string>
<string name="connect_via_member_address_alert_title">Connect directly?</string>
<string name="connect_via_member_address_alert_desc">Сonnection request will be sent to this group member.</string>
<string name="error_removing_member">Error removing member</string>
<string name="error_changing_role">Error changing role</string>
<string name="info_row_group">Group</string>
@@ -1,5 +1,7 @@
package chat.simplex.common.ui.theme
import chat.simplex.common.platform.Log
import chat.simplex.common.platform.TAG
import com.jthemedetecor.OsThemeDetector
private val detector: OsThemeDetector = OsThemeDetector.getDetector()
@@ -7,4 +9,11 @@ private val detector: OsThemeDetector = OsThemeDetector.getDetector()
registerListener(::reactOnDarkThemeChanges)
}
actual fun isSystemInDarkTheme(): Boolean = detector.isDark
actual fun isSystemInDarkTheme(): Boolean = try {
detector.isDark
}
catch (e: Exception) {
Log.e(TAG, e.stackTraceToString())
/* On Mac this code can produce exception */
false
}
+2 -2
View File
@@ -125,7 +125,7 @@ afterEvaluate {
copy {
from("${project(":desktop").buildDir}/cmake/main/linux-amd64", "$cppPath/desktop/libs/linux-x86_64", "$cppPath/desktop/libs/linux-x86_64/deps")
into("src/jvmMain/resources/libs/linux-x86_64")
include("*.so")
include("*.so*")
eachFile {
path = name
}
@@ -135,7 +135,7 @@ afterEvaluate {
copy {
from("${project(":desktop").buildDir}/cmake/main/linux-aarch64", "$cppPath/desktop/libs/linux-aarch64", "$cppPath/desktop/libs/linux-aarch64/deps")
into("src/jvmMain/resources/libs/linux-aarch64")
include("*.so")
include("*.so*")
eachFile {
path = name
}
+10 -4
View File
@@ -17,7 +17,7 @@ import qualified Data.Attoparsec.Text as A
import Data.Char (isDigit)
import Data.Either (fromRight)
import Data.Functor (($>))
import Data.List (intercalate)
import Data.List (intercalate, foldl')
import Data.List.NonEmpty (NonEmpty)
import qualified Data.List.NonEmpty as L
import Data.Maybe (fromMaybe, isNothing)
@@ -124,9 +124,15 @@ unmarked :: Text -> Markdown
unmarked = Markdown Nothing
parseMaybeMarkdownList :: Text -> Maybe MarkdownList
parseMaybeMarkdownList s =
let m = intercalate ["\n"] . map (markdownToList . parseMarkdown) $ T.lines s
in if all (isNothing . format) m then Nothing else Just m
parseMaybeMarkdownList s
| all (isNothing . format) ml = Nothing
| otherwise = Just . reverse $ foldl' acc [] ml
where
ml = intercalate ["\n"] . map (markdownToList . parseMarkdown) $ T.lines s
acc [] m = [m]
acc ms@(FormattedText f t : ms') ft@(FormattedText f' t')
| f == f' = FormattedText f (t <> t') : ms'
| otherwise = ft : ms
parseMarkdownList :: Text -> MarkdownList
parseMarkdownList = markdownToList . parseMarkdown
+2
View File
@@ -204,5 +204,7 @@ multilineMarkdownList :: Spec
multilineMarkdownList = describe "multiline markdown" do
it "correct markdown" do
parseMaybeMarkdownList "http://simplex.chat\nhttp://app.simplex.chat" `shouldBe` Just [uri' "http://simplex.chat", "\n", uri' "http://app.simplex.chat"]
it "combines the same formats" do
parseMaybeMarkdownList "http://simplex.chat\ntext 1\ntext 2\nhttp://app.simplex.chat" `shouldBe` Just [uri' "http://simplex.chat", "\ntext 1\ntext 2\n", uri' "http://app.simplex.chat"]
it "no markdown" do
parseMaybeMarkdownList "not a\nmarkdown" `shouldBe` Nothing