From 98e53fb35b5371dcea0d59febb2bd215771bf9c7 Mon Sep 17 00:00:00 2001 From: spaced4ndy <8711996+spaced4ndy@users.noreply.github.com> Date: Mon, 31 Jul 2023 11:54:39 +0400 Subject: [PATCH] core: read unparsable item status as unknown (#2805) --- .../Shared/Views/Chat/ChatItem/CIFileView.swift | 2 ++ .../Shared/Views/Chat/ChatItem/CIImageView.swift | 1 + .../Shared/Views/Chat/ChatItem/CIVideoView.swift | 1 + .../Shared/Views/Chat/ChatItem/CIVoiceView.swift | 1 + apps/ios/SimpleXChat/ChatTypes.swift | 7 +++++++ .../main/java/chat/simplex/app/model/ChatModel.kt | 5 +++++ .../chat/simplex/app/views/chat/item/CIFileView.kt | 1 + .../simplex/app/views/chat/item/CIImageView.kt | 1 + .../simplex/app/views/chat/item/CIVideoView.kt | 1 + .../resources/MR/images/ic_question_mark.svg | 1 + src/Simplex/Chat/Messages.hs | 14 ++++++++++++-- src/Simplex/Chat/View.hs | 1 + 12 files changed, 34 insertions(+), 2 deletions(-) create mode 100644 apps/multiplatform/common/src/commonMain/resources/MR/images/ic_question_mark.svg diff --git a/apps/ios/Shared/Views/Chat/ChatItem/CIFileView.swift b/apps/ios/Shared/Views/Chat/ChatItem/CIFileView.swift index 134c9679d9..6e792e825d 100644 --- a/apps/ios/Shared/Views/Chat/ChatItem/CIFileView.swift +++ b/apps/ios/Shared/Views/Chat/ChatItem/CIFileView.swift @@ -62,6 +62,7 @@ struct CIFileView: View { case .rcvComplete: return true case .rcvCancelled: return false case .rcvError: return false + case .invalid: return false } } return false @@ -149,6 +150,7 @@ struct CIFileView: View { case .rcvComplete: fileIcon("doc.fill") case .rcvCancelled: fileIcon("doc.fill", innerIcon: "xmark", innerIconSize: 10) case .rcvError: fileIcon("doc.fill", innerIcon: "xmark", innerIconSize: 10) + case .invalid: fileIcon("doc.fill", innerIcon: "questionmark", innerIconSize: 10) } } else { fileIcon("doc.fill") diff --git a/apps/ios/Shared/Views/Chat/ChatItem/CIImageView.swift b/apps/ios/Shared/Views/Chat/ChatItem/CIImageView.swift index a9eadc5aa2..b13ee52829 100644 --- a/apps/ios/Shared/Views/Chat/ChatItem/CIImageView.swift +++ b/apps/ios/Shared/Views/Chat/ChatItem/CIImageView.swift @@ -99,6 +99,7 @@ struct CIImageView: View { case .rcvTransfer: progressView() case .rcvCancelled: fileIcon("xmark", 10, 13) case .rcvError: fileIcon("xmark", 10, 13) + case .invalid: fileIcon("questionmark", 10, 13) default: EmptyView() } } diff --git a/apps/ios/Shared/Views/Chat/ChatItem/CIVideoView.swift b/apps/ios/Shared/Views/Chat/ChatItem/CIVideoView.swift index 0232be700b..4387614918 100644 --- a/apps/ios/Shared/Views/Chat/ChatItem/CIVideoView.swift +++ b/apps/ios/Shared/Views/Chat/ChatItem/CIVideoView.swift @@ -212,6 +212,7 @@ struct CIVideoView: View { } case .rcvCancelled: fileIcon("xmark", 10, 13) case .rcvError: fileIcon("xmark", 10, 13) + case .invalid: fileIcon("questionmark", 10, 13) default: EmptyView() } } diff --git a/apps/ios/Shared/Views/Chat/ChatItem/CIVoiceView.swift b/apps/ios/Shared/Views/Chat/ChatItem/CIVoiceView.swift index e6ce74953b..9541ac9483 100644 --- a/apps/ios/Shared/Views/Chat/ChatItem/CIVoiceView.swift +++ b/apps/ios/Shared/Views/Chat/ChatItem/CIVoiceView.swift @@ -144,6 +144,7 @@ struct VoiceMessagePlayer: View { case .rcvComplete: playbackButton() case .rcvCancelled: playPauseIcon("play.fill", Color(uiColor: .tertiaryLabel)) case .rcvError: playPauseIcon("play.fill", Color(uiColor: .tertiaryLabel)) + case .invalid: playPauseIcon("play.fill", Color(uiColor: .tertiaryLabel)) } } else { playPauseIcon("play.fill", Color(uiColor: .tertiaryLabel)) diff --git a/apps/ios/SimpleXChat/ChatTypes.swift b/apps/ios/SimpleXChat/ChatTypes.swift index 31930fd31c..cfad3cc691 100644 --- a/apps/ios/SimpleXChat/ChatTypes.swift +++ b/apps/ios/SimpleXChat/ChatTypes.swift @@ -2273,6 +2273,7 @@ public struct CIMeta: Decodable { case .sndErrorAuth: return ("multiply", .red) case .sndError: return ("exclamationmark.triangle.fill", .yellow) case .rcvNew: return ("circlebadge.fill", Color.accentColor) + case .invalid: return ("questionmark", metaColor) default: return nil } } @@ -2343,6 +2344,7 @@ public enum CIStatus: Decodable { case sndError(agentError: String) case rcvNew case rcvRead + case invalid(text: String) var id: String { switch self { @@ -2353,6 +2355,7 @@ public enum CIStatus: Decodable { case .sndError: return "sndError" case .rcvNew: return "rcvNew" case .rcvRead: return "rcvRead" + case .invalid: return "invalid" } } } @@ -2615,6 +2618,7 @@ public struct CIFile: Decodable { case .rcvCancelled: return false case .rcvComplete: return true case .rcvError: return false + case .invalid: return false } } } @@ -2638,6 +2642,7 @@ public struct CIFile: Decodable { case .rcvCancelled: return nil case .rcvComplete: return nil case .rcvError: return nil + case .invalid: return nil } } } @@ -2698,6 +2703,7 @@ public enum CIFileStatus: Decodable, Equatable { case rcvComplete case rcvCancelled case rcvError + case invalid(text: String) var id: String { switch self { @@ -2712,6 +2718,7 @@ public enum CIFileStatus: Decodable, Equatable { case .rcvComplete: return "rcvComplete" case .rcvCancelled: return "rcvCancelled" case .rcvError: return "rcvError" + case .invalid: return "invalid" } } } diff --git a/apps/multiplatform/android/src/main/java/chat/simplex/app/model/ChatModel.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/model/ChatModel.kt index 1a76510a0b..5adc17fc61 100644 --- a/apps/multiplatform/android/src/main/java/chat/simplex/app/model/ChatModel.kt +++ b/apps/multiplatform/android/src/main/java/chat/simplex/app/model/ChatModel.kt @@ -1626,6 +1626,7 @@ data class CIMeta ( is CIStatus.SndErrorAuth -> MR.images.ic_close to Color.Red is CIStatus.SndError -> MR.images.ic_warning_filled to WarningYellow is CIStatus.RcvNew -> MR.images.ic_circle_filled to primaryColor + is CIStatus.Invalid -> MR.images.ic_question_mark to metaColor else -> null } @@ -1712,6 +1713,7 @@ sealed class CIStatus { @Serializable @SerialName("sndError") class SndError(val agentError: String): CIStatus() @Serializable @SerialName("rcvNew") class RcvNew: CIStatus() @Serializable @SerialName("rcvRead") class RcvRead: CIStatus() + @Serializable @SerialName("invalid") class Invalid(val text: String): CIStatus() } @Serializable @@ -1949,6 +1951,7 @@ class CIFile( is CIFileStatus.RcvCancelled -> false is CIFileStatus.RcvComplete -> true is CIFileStatus.RcvError -> false + is CIFileStatus.Invalid -> false } @Transient @@ -1969,6 +1972,7 @@ class CIFile( is CIFileStatus.RcvCancelled -> null is CIFileStatus.RcvComplete -> null is CIFileStatus.RcvError -> null + is CIFileStatus.Invalid -> null } companion object { @@ -2038,6 +2042,7 @@ sealed class CIFileStatus { @Serializable @SerialName("rcvComplete") object RcvComplete: CIFileStatus() @Serializable @SerialName("rcvCancelled") object RcvCancelled: CIFileStatus() @Serializable @SerialName("rcvError") object RcvError: CIFileStatus() + @Serializable @SerialName("invalid") class Invalid(val text: String): CIFileStatus() } @Suppress("SERIALIZER_TYPE_INCOMPATIBLE") diff --git a/apps/multiplatform/android/src/main/java/chat/simplex/app/views/chat/item/CIFileView.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/chat/item/CIFileView.kt index 7c9e49766b..82ecefaf20 100644 --- a/apps/multiplatform/android/src/main/java/chat/simplex/app/views/chat/item/CIFileView.kt +++ b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/chat/item/CIFileView.kt @@ -170,6 +170,7 @@ fun CIFileView( is CIFileStatus.RcvComplete -> fileIcon() is CIFileStatus.RcvCancelled -> fileIcon(innerIcon = painterResource(MR.images.ic_close)) is CIFileStatus.RcvError -> fileIcon(innerIcon = painterResource(MR.images.ic_close)) + is CIFileStatus.Invalid -> fileIcon(innerIcon = painterResource(MR.images.ic_question_mark)) } } else { fileIcon() diff --git a/apps/multiplatform/android/src/main/java/chat/simplex/app/views/chat/item/CIImageView.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/chat/item/CIImageView.kt index 642757f271..f5ebf4753b 100644 --- a/apps/multiplatform/android/src/main/java/chat/simplex/app/views/chat/item/CIImageView.kt +++ b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/chat/item/CIImageView.kt @@ -86,6 +86,7 @@ fun CIImageView( is CIFileStatus.RcvTransfer -> progressIndicator() is CIFileStatus.RcvCancelled -> fileIcon(painterResource(MR.images.ic_close), MR.strings.icon_descr_file) is CIFileStatus.RcvError -> fileIcon(painterResource(MR.images.ic_close), MR.strings.icon_descr_file) + is CIFileStatus.Invalid -> fileIcon(painterResource(MR.images.ic_question_mark), MR.strings.icon_descr_file) else -> {} } } diff --git a/apps/multiplatform/android/src/main/java/chat/simplex/app/views/chat/item/CIVideoView.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/chat/item/CIVideoView.kt index f6123e7bed..ee8422d46d 100644 --- a/apps/multiplatform/android/src/main/java/chat/simplex/app/views/chat/item/CIVideoView.kt +++ b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/chat/item/CIVideoView.kt @@ -309,6 +309,7 @@ private fun loadingIndicator(file: CIFile?) { } is CIFileStatus.RcvCancelled -> fileIcon(painterResource(MR.images.ic_close), MR.strings.icon_descr_file) is CIFileStatus.RcvError -> fileIcon(painterResource(MR.images.ic_close), MR.strings.icon_descr_file) + is CIFileStatus.Invalid -> fileIcon(painterResource(MR.images.ic_question_mark), MR.strings.icon_descr_file) else -> {} } } diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/images/ic_question_mark.svg b/apps/multiplatform/common/src/commonMain/resources/MR/images/ic_question_mark.svg new file mode 100644 index 0000000000..9c2e7e110b --- /dev/null +++ b/apps/multiplatform/common/src/commonMain/resources/MR/images/ic_question_mark.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Simplex/Chat/Messages.hs b/src/Simplex/Chat/Messages.hs index f2d6553a5a..7e8331b202 100644 --- a/src/Simplex/Chat/Messages.hs +++ b/src/Simplex/Chat/Messages.hs @@ -501,6 +501,7 @@ data CIFileStatus (d :: MsgDirection) where CIFSRcvComplete :: CIFileStatus 'MDRcv CIFSRcvCancelled :: CIFileStatus 'MDRcv CIFSRcvError :: CIFileStatus 'MDRcv + CIFSInvalid :: {text :: Text} -> CIFileStatus 'MDSnd deriving instance Eq (CIFileStatus d) @@ -519,6 +520,7 @@ ciFileEnded = \case CIFSRcvCancelled -> True CIFSRcvComplete -> True CIFSRcvError -> True + CIFSInvalid {} -> True instance ToJSON (CIFileStatus d) where toJSON = J.toJSON . jsonCIFileStatus @@ -545,6 +547,7 @@ instance MsgDirectionI d => StrEncoding (CIFileStatus d) where CIFSRcvComplete -> "rcv_complete" CIFSRcvCancelled -> "rcv_cancelled" CIFSRcvError -> "rcv_error" + CIFSInvalid {} -> "invalid" strP = (\(AFS _ st) -> checkDirection st) <$?> strP instance StrEncoding ACIFileStatus where @@ -562,7 +565,7 @@ instance StrEncoding ACIFileStatus where "rcv_complete" -> pure $ AFS SMDRcv CIFSRcvComplete "rcv_cancelled" -> pure $ AFS SMDRcv CIFSRcvCancelled "rcv_error" -> pure $ AFS SMDRcv CIFSRcvError - _ -> fail "bad file status" + text -> pure $ AFS SMDSnd (CIFSInvalid $ safeDecodeUtf8 text) where progress :: (Int64 -> Int64 -> a) -> A.Parser a progress f = f <$> num <*> num <|> pure (f 0 1) @@ -580,6 +583,7 @@ data JSONCIFileStatus | JCIFSRcvComplete | JCIFSRcvCancelled | JCIFSRcvError + | JCIFSInvalid {text :: Text} deriving (Generic) instance ToJSON JSONCIFileStatus where @@ -599,6 +603,7 @@ jsonCIFileStatus = \case CIFSRcvComplete -> JCIFSRcvComplete CIFSRcvCancelled -> JCIFSRcvCancelled CIFSRcvError -> JCIFSRcvError + CIFSInvalid text -> JCIFSInvalid text aciFileStatusJSON :: JSONCIFileStatus -> ACIFileStatus aciFileStatusJSON = \case @@ -613,6 +618,7 @@ aciFileStatusJSON = \case JCIFSRcvComplete -> AFS SMDRcv CIFSRcvComplete JCIFSRcvCancelled -> AFS SMDRcv CIFSRcvCancelled JCIFSRcvError -> AFS SMDRcv CIFSRcvError + JCIFSInvalid text -> AFS SMDSnd $ CIFSInvalid text -- to conveniently read file data from db data CIFileInfo = CIFileInfo @@ -630,6 +636,7 @@ data CIStatus (d :: MsgDirection) where CISSndError :: String -> CIStatus 'MDSnd CISRcvNew :: CIStatus 'MDRcv CISRcvRead :: CIStatus 'MDRcv + CISInvalid :: Text -> CIStatus 'MDSnd deriving instance Show (CIStatus d) @@ -654,6 +661,7 @@ instance MsgDirectionI d => StrEncoding (CIStatus d) where CISSndError e -> "snd_error " <> encodeUtf8 (T.pack e) CISRcvNew -> "rcv_new" CISRcvRead -> "rcv_read" + CISInvalid {} -> "invalid" strP = (\(ACIStatus _ st) -> checkDirection st) <$?> strP instance StrEncoding ACIStatus where @@ -667,7 +675,7 @@ instance StrEncoding ACIStatus where "snd_error" -> ACIStatus SMDSnd . CISSndError . T.unpack . safeDecodeUtf8 <$> (A.space *> A.takeByteString) "rcv_new" -> pure $ ACIStatus SMDRcv CISRcvNew "rcv_read" -> pure $ ACIStatus SMDRcv CISRcvRead - _ -> fail "bad status" + text -> pure $ ACIStatus SMDSnd (CISInvalid $ safeDecodeUtf8 text) data JSONCIStatus = JCISSndNew @@ -677,6 +685,7 @@ data JSONCIStatus | JCISSndError {agentError :: String} | JCISRcvNew | JCISRcvRead + | JCISInvalid {text :: Text} deriving (Show, Generic) instance ToJSON JSONCIStatus where @@ -692,6 +701,7 @@ jsonCIStatus = \case CISSndError e -> JCISSndError e CISRcvNew -> JCISRcvNew CISRcvRead -> JCISRcvRead + CISInvalid text -> JCISInvalid text ciStatusNew :: forall d. MsgDirectionI d => CIStatus d ciStatusNew = case msgDirection @d of diff --git a/src/Simplex/Chat/View.hs b/src/Simplex/Chat/View.hs index 0b7db12f94..d079e1fccb 100644 --- a/src/Simplex/Chat/View.hs +++ b/src/Simplex/Chat/View.hs @@ -1360,6 +1360,7 @@ viewFileTransferStatusXFTP (AChatItem _ _ _ ChatItem {file = Just CIFile {fileId CIFSRcvComplete -> ["receiving " <> fstr <> " complete" <> maybe "" (\fp -> ", path: " <> plain fp) filePath] CIFSRcvCancelled -> ["receiving " <> fstr <> " cancelled"] CIFSRcvError -> ["receiving " <> fstr <> " error"] + CIFSInvalid text -> [fstr <> " invalid status: " <> plain text] where fstr = fileTransferStr fileId fileName viewFileTransferStatusXFTP _ = ["no file status"]