mirror of
https://github.com/simplex-chat/simplex-chat.git
synced 2026-10-22 17:31:55 +00:00
core: add peer type "agent" (#7738)
* add agent peer type * bot types * agent app icons * refactor * smaller image --------- Co-authored-by: Evgeny @ SimpleX Chat <259188159+evgeny-simplex@users.noreply.github.com>
This commit is contained in:
1 parent
9a90d8e230
commit
77f9f4a464
29 files changed
+101
-45
No files matched your search
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "agent.svg",
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
},
|
||||
"properties" : {
|
||||
"preserves-vector-representation" : true,
|
||||
"template-rendering-intent" : "template"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="124.5 -878.5 711 797" width="21.41px" fill="#000000"><path d="M564.12,-698.86 C564.12,-652.47 526.51,-614.86 480.12,-614.86 C433.73,-614.86 396.12,-652.47 396.12,-698.86 C396.12,-745.25 433.73,-782.86 480.12,-782.86 C526.51,-782.86 564.12,-745.25 564.12,-698.86 Z M373.01,-371.05 C373.01,-324.66 335.4,-287.05 289.01,-287.05 C242.62,-287.05 205.01,-324.66 205.01,-371.05 C205.01,-417.44 242.62,-455.05 289.01,-455.05 C335.4,-455.05 373.01,-417.44 373.01,-371.05 Z M755.03,-371.07 C755.03,-324.68 717.42,-287.07 671.03,-287.07 C624.63,-287.07 587.03,-324.68 587.03,-371.07 C587.03,-417.46 624.63,-455.07 671.03,-455.07 C717.42,-455.07 755.03,-417.46 755.03,-371.07 Z"/></svg>
|
||||
|
After Width: | Height: | Size: 737 B |
@@ -50,7 +50,7 @@ struct CIChatLinkHeader: View {
|
||||
HStack(alignment: .top) {
|
||||
ProfileImage(
|
||||
imageStr: chatLink.image,
|
||||
iconName: chatLink.iconName,
|
||||
icon: Image(systemName: chatLink.iconName),
|
||||
size: 44,
|
||||
color: Color(uiColor: .tertiaryLabel)
|
||||
)
|
||||
|
||||
@@ -115,7 +115,7 @@ struct CIGroupInvitationView: View {
|
||||
return HStack(alignment: .top) {
|
||||
ProfileImage(
|
||||
imageStr: groupInvitation.groupProfile.image,
|
||||
iconName: "person.2.circle.fill",
|
||||
icon: Image(systemName: "person.2.circle.fill"),
|
||||
size: 44,
|
||||
color: color
|
||||
)
|
||||
|
||||
@@ -1968,7 +1968,7 @@ struct ChatView: View {
|
||||
.padding(.trailing, 12)
|
||||
}
|
||||
HStack(alignment: .top, spacing: 10) {
|
||||
ProfileImage(imageStr: groupInfo.image, iconName: groupInfo.chatIconName, size: memberImageSize, backgroundColor: theme.colors.background)
|
||||
ProfileImage(imageStr: groupInfo.image, icon: Image(systemName: groupInfo.chatIconName), size: memberImageSize, backgroundColor: theme.colors.background)
|
||||
.simultaneousGesture(TapGesture().onEnded {
|
||||
showChatInfoSheet = true
|
||||
})
|
||||
@@ -2052,7 +2052,7 @@ struct ChatView: View {
|
||||
}
|
||||
HStack(alignment: .top, spacing: 10) {
|
||||
if ci.meta.showGroupAsSender {
|
||||
ProfileImage(imageStr: groupInfo.image, iconName: groupInfo.chatIconName, size: memberImageSize, backgroundColor: theme.colors.background)
|
||||
ProfileImage(imageStr: groupInfo.image, icon: Image(systemName: groupInfo.chatIconName), size: memberImageSize, backgroundColor: theme.colors.background)
|
||||
.simultaneousGesture(TapGesture().onEnded {
|
||||
showChatInfoSheet = true
|
||||
})
|
||||
|
||||
@@ -11,7 +11,7 @@ struct ComposeChatLinkView: View {
|
||||
HStack(alignment: .center, spacing: 8) {
|
||||
ProfileImage(
|
||||
imageStr: chatLink.image,
|
||||
iconName: chatLink.iconName,
|
||||
icon: Image(systemName: chatLink.iconName),
|
||||
size: 44
|
||||
)
|
||||
.padding(.leading, 12)
|
||||
|
||||
@@ -37,7 +37,7 @@ struct GroupProfileView: View {
|
||||
|
||||
var body: some View {
|
||||
List {
|
||||
EditProfileImage(profileImage: $groupProfile.image, iconName: groupInfo.chatIconName, showChooseSource: $showChooseSource)
|
||||
EditProfileImage(profileImage: $groupProfile.image, icon: Image(systemName: groupInfo.chatIconName), showChooseSource: $showChooseSource)
|
||||
.if(!focusDisplayName) { $0.padding(.top) }
|
||||
|
||||
Section {
|
||||
|
||||
@@ -444,7 +444,7 @@ struct ChatPreviewView: View {
|
||||
smallContentPreview(size: dynamicMediaSize, borderColor: chatLink.image != nil ? .secondary : .clear) {
|
||||
ProfileImage(
|
||||
imageStr: chatLink.image,
|
||||
iconName: chatLink.iconName,
|
||||
icon: Image(systemName: chatLink.iconName),
|
||||
size: dynamicMediaSize,
|
||||
color: Color(uiColor: .tertiaryLabel)
|
||||
)
|
||||
|
||||
@@ -19,7 +19,7 @@ struct ChatInfoImage: View {
|
||||
let iconColor = if case .local = chat.chatInfo { theme.appColors.primaryVariant2 } else { color }
|
||||
return ProfileImage(
|
||||
imageStr: chat.chatInfo.image,
|
||||
iconName: chatIconName(chat.chatInfo),
|
||||
icon: chatIcon(chat.chatInfo),
|
||||
size: size,
|
||||
color: iconColor
|
||||
)
|
||||
|
||||
@@ -12,7 +12,7 @@ import SimpleXChat
|
||||
struct ProfileImage: View {
|
||||
@EnvironmentObject var theme: AppTheme
|
||||
var imageStr: String? = nil
|
||||
var iconName: String = "person.crop.circle.fill"
|
||||
var icon: Image = Image(systemName: "person.crop.circle.fill")
|
||||
var size: CGFloat
|
||||
var color = Color(uiColor: .tertiarySystemGroupedBackground)
|
||||
var backgroundColor: Color? = nil
|
||||
@@ -24,7 +24,7 @@ struct ProfileImage: View {
|
||||
clipProfileImage(Image(uiImage: uiImage), size: size, radius: radius, blurred: blurred)
|
||||
} else {
|
||||
let c = color.asAnotherColorFromSecondaryVariant(theme)
|
||||
Image(systemName: iconName)
|
||||
icon
|
||||
.resizable()
|
||||
.foregroundColor(c)
|
||||
.scaledToFit()
|
||||
|
||||
@@ -50,7 +50,7 @@ struct AddChannelView: View {
|
||||
Spacer(minLength: 0)
|
||||
ZStack(alignment: .center) {
|
||||
ZStack(alignment: .topTrailing) {
|
||||
ProfileImage(imageStr: profile.image, iconName: "antenna.radiowaves.left.and.right.circle.fill", size: 128)
|
||||
ProfileImage(imageStr: profile.image, icon: Image(systemName: "antenna.radiowaves.left.and.right.circle.fill"), size: 128)
|
||||
if profile.image != nil {
|
||||
Button {
|
||||
profile.image = nil
|
||||
@@ -285,7 +285,7 @@ struct AddChannelView: View {
|
||||
let total = groupRelays.count
|
||||
return List {
|
||||
Group {
|
||||
ProfileImage(imageStr: gInfo.groupProfile.image, iconName: "antenna.radiowaves.left.and.right.circle.fill", size: 128)
|
||||
ProfileImage(imageStr: gInfo.groupProfile.image, icon: Image(systemName: "antenna.radiowaves.left.and.right.circle.fill"), size: 128)
|
||||
.frame(maxWidth: .infinity, alignment: .center)
|
||||
|
||||
Text(gInfo.groupProfile.displayName)
|
||||
|
||||
@@ -71,7 +71,7 @@ struct AddGroupView: View {
|
||||
Spacer(minLength: 0)
|
||||
ZStack(alignment: .center) {
|
||||
ZStack(alignment: .topTrailing) {
|
||||
ProfileImage(imageStr: profile.image, iconName: "person.2.circle.fill", size: 128)
|
||||
ProfileImage(imageStr: profile.image, icon: Image(systemName: "person.2.circle.fill"), size: 128)
|
||||
if profile.image != nil {
|
||||
Button {
|
||||
profile.image = nil
|
||||
|
||||
@@ -1129,11 +1129,9 @@ private func showPrepareContactAlert(
|
||||
profileImage:
|
||||
ProfileImage(
|
||||
imageStr: contactShortLinkData.profile.image,
|
||||
iconName: contactShortLinkData.business
|
||||
? "briefcase.circle.fill"
|
||||
: contactShortLinkData.profile.peerType == .bot
|
||||
? "cube.fill"
|
||||
: "person.crop.circle.fill",
|
||||
icon: contactShortLinkData.business
|
||||
? Image(systemName: "briefcase.circle.fill")
|
||||
: peerTypeIcon(contactShortLinkData.profile.peerType),
|
||||
size: alertProfileImageSize
|
||||
),
|
||||
profileBadge: contactShortLinkData.localBadge,
|
||||
@@ -1186,9 +1184,9 @@ private func showPrepareGroupAlert(
|
||||
profileImage:
|
||||
ProfileImage(
|
||||
imageStr: groupShortLinkData.groupProfile.image,
|
||||
iconName: isChannel
|
||||
icon: Image(systemName: isChannel
|
||||
? "antenna.radiowaves.left.and.right.circle.fill"
|
||||
: "person.2.circle.fill",
|
||||
: "person.2.circle.fill"),
|
||||
size: alertProfileImageSize
|
||||
),
|
||||
theme: theme,
|
||||
@@ -1240,7 +1238,7 @@ private func showOpenKnownContactAlert(
|
||||
profileImage:
|
||||
ProfileImage(
|
||||
imageStr: contact.profile.image,
|
||||
iconName: contact.chatIconName,
|
||||
icon: contact.chatIcon,
|
||||
size: alertProfileImageSize
|
||||
),
|
||||
profileBadge: contact.active ? contact.profile.localBadge : nil,
|
||||
@@ -1288,7 +1286,7 @@ private func showOpenKnownGroupAlert(
|
||||
profileImage:
|
||||
ProfileImage(
|
||||
imageStr: groupInfo.groupProfile.image,
|
||||
iconName: groupInfo.chatIconName,
|
||||
icon: Image(systemName: groupInfo.chatIconName),
|
||||
size: alertProfileImageSize
|
||||
),
|
||||
theme: theme,
|
||||
@@ -1605,7 +1603,7 @@ func planAndConnect(
|
||||
profileImage:
|
||||
ProfileImage(
|
||||
imageStr: groupSLinkData.groupProfile.image,
|
||||
iconName: "antenna.radiowaves.left.and.right.circle.fill",
|
||||
icon: Image(systemName: "antenna.radiowaves.left.and.right.circle.fill"),
|
||||
size: alertProfileImageSize
|
||||
),
|
||||
theme: theme,
|
||||
@@ -1632,7 +1630,7 @@ func planAndConnect(
|
||||
profileImage:
|
||||
ProfileImage(
|
||||
imageStr: groupSLinkData.groupProfile.image,
|
||||
iconName: "person.2.circle.fill",
|
||||
icon: Image(systemName: "person.2.circle.fill"),
|
||||
size: alertProfileImageSize
|
||||
),
|
||||
theme: theme,
|
||||
|
||||
@@ -29,7 +29,7 @@ struct UserProfile: View {
|
||||
|
||||
var body: some View {
|
||||
List {
|
||||
EditProfileImage(profileImage: $profile.image, iconName: "person.crop.circle.fill", showChooseSource: $showChooseSource)
|
||||
EditProfileImage(profileImage: $profile.image, icon: Image(systemName: "person.crop.circle.fill"), showChooseSource: $showChooseSource)
|
||||
.padding(.top)
|
||||
|
||||
Section {
|
||||
@@ -221,7 +221,7 @@ struct EditProfileImage: View {
|
||||
@EnvironmentObject var theme: AppTheme
|
||||
@AppStorage(DEFAULT_PROFILE_IMAGE_CORNER_RADIUS) private var radius = defaultProfileImageCorner
|
||||
@Binding var profileImage: String?
|
||||
var iconName: String
|
||||
var icon: Image
|
||||
@Binding var showChooseSource: Bool
|
||||
|
||||
var body: some View {
|
||||
@@ -237,7 +237,7 @@ struct EditProfileImage: View {
|
||||
}
|
||||
} else {
|
||||
ZStack(alignment: .center) {
|
||||
ProfileImage(imageStr: profileImage, iconName: iconName, size: 160)
|
||||
ProfileImage(imageStr: profileImage, icon: icon, size: 160)
|
||||
editImageButton { showChooseSource = true }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ struct ShareView: View {
|
||||
HStack {
|
||||
profileImage(
|
||||
chatInfoId: chat.chatInfo.id,
|
||||
iconName: chatIconName(chat.chatInfo),
|
||||
icon: chatIcon(chat.chatInfo),
|
||||
size: 30
|
||||
)
|
||||
Text(chat.chatInfo.displayName).foregroundStyle(
|
||||
@@ -209,11 +209,11 @@ struct ShareView: View {
|
||||
.background(Material.ultraThin)
|
||||
}
|
||||
|
||||
@ViewBuilder private func profileImage(chatInfoId: ChatInfo.ID, iconName: String, size: Double) -> some View {
|
||||
@ViewBuilder private func profileImage(chatInfoId: ChatInfo.ID, icon: Image, size: Double) -> some View {
|
||||
if let uiImage = model.profileImages[chatInfoId] {
|
||||
clipProfileImage(Image(uiImage: uiImage), size: size, radius: radius)
|
||||
} else {
|
||||
Image(systemName: iconName)
|
||||
icon
|
||||
.resizable()
|
||||
.foregroundColor(Color(uiColor: .tertiaryLabel))
|
||||
.frame(width: size, height: size)
|
||||
|
||||
@@ -271,6 +271,8 @@
|
||||
E5AEC0AF2F91A73500270665 /* ComposeChatLinkView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E5AEC0AE2F91A73500270665 /* ComposeChatLinkView.swift */; };
|
||||
E5C0BBE82F82B45500EA7527 /* SimpleXAssets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = E5C0BBE72F82B45500EA7527 /* SimpleXAssets.xcassets */; };
|
||||
E5C0BBE92F82B45500EA7527 /* SimpleXAssets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = E5C0BBE72F82B45500EA7527 /* SimpleXAssets.xcassets */; };
|
||||
E5C0BBEB2F82B45500EA7527 /* SharedAssets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = E5C0BBEA2F82B45500EA7527 /* SharedAssets.xcassets */; };
|
||||
E5C0BBEC2F82B45500EA7527 /* SharedAssets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = E5C0BBEA2F82B45500EA7527 /* SharedAssets.xcassets */; };
|
||||
E5DBF1932F88169800E1D7FD /* ConnectBannerCard.swift in Sources */ = {isa = PBXBuildFile; fileRef = E5DBF1922F88169800E1D7FD /* ConnectBannerCard.swift */; };
|
||||
E5DCF8DB2C56FAC1007928CC /* SimpleXChat.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5CE2BA682845308900EC33A6 /* SimpleXChat.framework */; };
|
||||
E5DCF9712C590272007928CC /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = E5DCF96F2C590272007928CC /* Localizable.strings */; };
|
||||
@@ -662,6 +664,7 @@
|
||||
E5AEC0AA2F91A6EA00270665 /* CIChatLinkHeader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CIChatLinkHeader.swift; sourceTree = "<group>"; };
|
||||
E5AEC0AE2F91A73500270665 /* ComposeChatLinkView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComposeChatLinkView.swift; sourceTree = "<group>"; };
|
||||
E5C0BBE72F82B45500EA7527 /* SimpleXAssets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = SimpleXAssets.xcassets; sourceTree = "<group>"; };
|
||||
E5C0BBEA2F82B45500EA7527 /* SharedAssets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = SharedAssets.xcassets; sourceTree = "<group>"; };
|
||||
E5C0BBFD2F82BBC000EA7527 /* Debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = "<group>"; };
|
||||
E5C0BBFE2F82BBC900EA7527 /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = "<group>"; };
|
||||
E5DBF1922F88169800E1D7FD /* ConnectBannerCard.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConnectBannerCard.swift; sourceTree = "<group>"; };
|
||||
@@ -953,6 +956,7 @@
|
||||
5C2E260D27A30E2400F70299 /* Views */,
|
||||
5CA059C5279559F40002BEB4 /* Assets.xcassets */,
|
||||
E5C0BBE72F82B45500EA7527 /* SimpleXAssets.xcassets */,
|
||||
E5C0BBEA2F82B45500EA7527 /* SharedAssets.xcassets */,
|
||||
D7AA2C3429A936B400737B40 /* MediaEncryption.playground */,
|
||||
5C13730C2815740A00F43030 /* DebugJSON.playground */,
|
||||
);
|
||||
@@ -1506,6 +1510,7 @@
|
||||
5CC2C0FC2809BF11000C35E3 /* Localizable.strings in Resources */,
|
||||
5CC2C0FF2809BF11000C35E3 /* SimpleX--iOS--InfoPlist.strings in Resources */,
|
||||
E5C0BBE82F82B45500EA7527 /* SimpleXAssets.xcassets in Resources */,
|
||||
E5C0BBEB2F82B45500EA7527 /* SharedAssets.xcassets in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@@ -1538,6 +1543,7 @@
|
||||
files = (
|
||||
E5DCF9712C590272007928CC /* Localizable.strings in Resources */,
|
||||
E5C0BBE92F82B45500EA7527 /* SimpleXAssets.xcassets in Resources */,
|
||||
E5C0BBEC2F82B45500EA7527 /* SharedAssets.xcassets in Resources */,
|
||||
E5DCF9982C5906FF007928CC /* InfoPlist.strings in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
|
||||
@@ -228,6 +228,7 @@ public enum ChatPeerType: Hashable {
|
||||
case human
|
||||
case bot
|
||||
case business
|
||||
case agent
|
||||
case unknown(String)
|
||||
|
||||
public var text: String {
|
||||
@@ -235,6 +236,7 @@ public enum ChatPeerType: Hashable {
|
||||
case .human: "human"
|
||||
case .bot: "bot"
|
||||
case .business: "business"
|
||||
case .agent: "agent"
|
||||
case let .unknown(s): s
|
||||
}
|
||||
}
|
||||
@@ -246,6 +248,7 @@ extension ChatPeerType: Codable {
|
||||
case "human": self = .human
|
||||
case "bot": self = .bot
|
||||
case "business": self = .business
|
||||
case "agent": self = .agent
|
||||
case let s: self = .unknown(s)
|
||||
}
|
||||
}
|
||||
@@ -256,6 +259,14 @@ extension ChatPeerType: Codable {
|
||||
}
|
||||
}
|
||||
|
||||
public func peerTypeIcon(_ peerType: ChatPeerType?) -> Image {
|
||||
switch peerType {
|
||||
case .bot: Image(systemName: "cube.fill")
|
||||
case .agent: Image("agent")
|
||||
default: Image(systemName: "person.crop.circle.fill")
|
||||
}
|
||||
}
|
||||
|
||||
// Supporter badge. The credential/proof bytes stay core-side; the UI only sees the disclosed type + status.
|
||||
// Unknown types keep their string so a verified badge's real name can be shown, while the icon falls back to supporter.
|
||||
public enum BadgeType: Hashable {
|
||||
@@ -2532,8 +2543,8 @@ public struct Contact: Identifiable, Decodable, NamedChat, Hashable {
|
||||
activeConn?.customUserProfileId != nil
|
||||
}
|
||||
|
||||
public var chatIconName: String {
|
||||
isBot ? "cube.fill" : "person.crop.circle.fill"
|
||||
public var chatIcon: Image {
|
||||
peerTypeIcon(profile.peerType)
|
||||
}
|
||||
|
||||
public func allowsFeature(_ feature: ChatFeature) -> Bool {
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import SwiftUI
|
||||
|
||||
public protocol ChatLike {
|
||||
var chatInfo: ChatInfo { get }
|
||||
@@ -91,13 +92,13 @@ private func canForwardToChat(_ cInfo: ChatInfo) -> Bool {
|
||||
}
|
||||
}
|
||||
|
||||
public func chatIconName(_ cInfo: ChatInfo) -> String {
|
||||
public func chatIcon(_ cInfo: ChatInfo) -> Image {
|
||||
switch cInfo {
|
||||
case let .direct(contact): contact.chatIconName
|
||||
case let .group(groupInfo, _): groupInfo.chatIconName
|
||||
case .local: "folder.circle.fill"
|
||||
case .contactRequest: "person.crop.circle.fill"
|
||||
default: "circle.fill"
|
||||
case let .direct(contact): contact.chatIcon
|
||||
case let .group(groupInfo, _): Image(systemName: groupInfo.chatIconName)
|
||||
case .local: Image(systemName: "folder.circle.fill")
|
||||
case .contactRequest: Image(systemName: "person.crop.circle.fill")
|
||||
default: Image(systemName: "circle.fill")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+11
-1
@@ -1954,7 +1954,7 @@ data class Contact(
|
||||
activeConn?.customUserProfileId != null
|
||||
|
||||
val chatIconName: ImageResource get() =
|
||||
if (isBot) MR.images.ic_cube else MR.images.ic_account_circle_filled
|
||||
peerTypeIcon(profile.peerType)
|
||||
|
||||
fun allowsFeature(feature: ChatFeature): Boolean = when (feature) {
|
||||
ChatFeature.TimedMessages -> mergedPreferences.timedMessages.contactPreference.allow != FeatureAllowed.NO
|
||||
@@ -2165,6 +2165,7 @@ sealed class ChatPeerType {
|
||||
@Serializable @SerialName("human") object Human: ChatPeerType()
|
||||
@Serializable @SerialName("bot") object Bot: ChatPeerType()
|
||||
@Serializable @SerialName("business") object Business: ChatPeerType()
|
||||
@Serializable @SerialName("agent") object Agent: ChatPeerType()
|
||||
@Serializable @SerialName("unknown") data class Unknown(val type: String): ChatPeerType()
|
||||
|
||||
val text: String
|
||||
@@ -2172,6 +2173,7 @@ sealed class ChatPeerType {
|
||||
is Human -> "human"
|
||||
is Bot -> "bot"
|
||||
is Business -> "business"
|
||||
is Agent -> "agent"
|
||||
is Unknown -> type
|
||||
}
|
||||
}
|
||||
@@ -2183,11 +2185,19 @@ object ChatPeerTypeSerializer : KSerializer<ChatPeerType> {
|
||||
"human" -> ChatPeerType.Human
|
||||
"bot" -> ChatPeerType.Bot
|
||||
"business" -> ChatPeerType.Business
|
||||
"agent" -> ChatPeerType.Agent
|
||||
else -> ChatPeerType.Unknown(v)
|
||||
}
|
||||
override fun serialize(encoder: Encoder, value: ChatPeerType) = encoder.encodeString(value.text)
|
||||
}
|
||||
|
||||
fun peerTypeIcon(peerType: ChatPeerType?): ImageResource =
|
||||
when (peerType) {
|
||||
ChatPeerType.Bot -> MR.images.ic_cube
|
||||
ChatPeerType.Agent -> MR.images.ic_agent
|
||||
else -> MR.images.ic_account_circle_filled
|
||||
}
|
||||
|
||||
// Supporter badge. The credential/proof bytes stay core-side; the UI only sees the disclosed type + status.
|
||||
// Unknown types keep their string so a verified badge's real name can be shown, while the icon falls back to supporter.
|
||||
@Serializable(with = BadgeTypeSerializer::class)
|
||||
|
||||
+1
-1
@@ -8139,7 +8139,7 @@ sealed class StoreError {
|
||||
is UserChatRelayNotFound -> "userChatRelayNotFound $chatRelayId"
|
||||
is GroupRelayNotFound -> "groupRelayNotFound $groupRelayId"
|
||||
is GroupRelayNotFoundByMemberId -> "groupRelayNotFoundByMemberId $groupMemberId"
|
||||
is DuplicateGroupMessage -> "duplicateGroupMessage $groupId $sharedMsgId $authorGroupMemberId $authorGroupMemberId"
|
||||
is DuplicateGroupMessage -> "duplicateGroupMessage $groupId $sharedMsgId $authorGroupMemberId $forwardedByGroupMemberId"
|
||||
is RemoteHostNotFound -> "remoteHostNotFound $remoteHostId"
|
||||
is RemoteHostUnknown -> "remoteHostUnknown"
|
||||
is RemoteHostDuplicateCA -> "remoteHostDuplicateCA"
|
||||
|
||||
+1
-2
@@ -717,8 +717,7 @@ fun showPrepareContactAlert(
|
||||
image = contactShortLinkData.profile.image,
|
||||
icon =
|
||||
if (contactShortLinkData.business) MR.images.ic_work_filled_padded
|
||||
else if (contactShortLinkData.profile.peerType == ChatPeerType.Bot) MR.images.ic_cube
|
||||
else MR.images.ic_account_circle_filled
|
||||
else peerTypeIcon(contactShortLinkData.profile.peerType)
|
||||
)
|
||||
},
|
||||
profileBadge = if (contactShortLinkData.localBadge?.status == BadgeStatus.ExpiredOld) null else contactShortLinkData.localBadge,
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" height="22px" viewBox="0 -960 960 960" width="22px" fill="#000000"><path d="M564.12,-698.86 C564.12,-652.47 526.51,-614.86 480.12,-614.86 C433.73,-614.86 396.12,-652.47 396.12,-698.86 C396.12,-745.25 433.73,-782.86 480.12,-782.86 C526.51,-782.86 564.12,-745.25 564.12,-698.86 Z M373.01,-371.05 C373.01,-324.66 335.4,-287.05 289.01,-287.05 C242.62,-287.05 205.01,-324.66 205.01,-371.05 C205.01,-417.44 242.62,-455.05 289.01,-455.05 C335.4,-455.05 373.01,-417.44 373.01,-371.05 Z M755.03,-371.07 C755.03,-324.68 717.42,-287.07 671.03,-287.07 C624.63,-287.07 587.03,-324.68 587.03,-371.07 C587.03,-417.46 624.63,-455.07 671.03,-455.07 C717.42,-455.07 755.03,-417.46 755.03,-371.07 Z"/></svg>
|
||||
|
After Width: | Height: | Size: 728 B |
@@ -1545,6 +1545,7 @@ Search:
|
||||
- "human"
|
||||
- "bot"
|
||||
- "business"
|
||||
- "agent"
|
||||
|
||||
|
||||
---
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
"metadata": {"comment": "profile bio (160 characters)"}
|
||||
},
|
||||
"contactLink": {"ref": "connReqUri"},
|
||||
"peerType": {"enum": ["human", "bot"]},
|
||||
"peerType": {"enum": ["human", "bot", "agent"]},
|
||||
"preferences": {
|
||||
"optionalProperties": {
|
||||
"commands": {
|
||||
|
||||
@@ -1796,6 +1796,7 @@ export enum ChatPeerType {
|
||||
Human = "human",
|
||||
Bot = "bot",
|
||||
Business = "business",
|
||||
Agent = "agent",
|
||||
}
|
||||
// Used in API commands. Chat scope can only be passed with groups.
|
||||
|
||||
|
||||
@@ -1247,7 +1247,7 @@ ChatListQuery = ChatListQuery_filters | ChatListQuery_search
|
||||
|
||||
ChatListQuery_Tag = Literal["filters", "search"]
|
||||
|
||||
ChatPeerType = Literal["human", "bot", "business"]
|
||||
ChatPeerType = Literal["human", "bot", "business", "agent"]
|
||||
|
||||
# Used in API commands. Chat scope can only be passed with groups.
|
||||
|
||||
|
||||
@@ -749,7 +749,7 @@ data Profile = Profile
|
||||
}
|
||||
deriving (Eq, Show)
|
||||
|
||||
data ChatPeerType = CPTHuman | CPTBot | CPTBusiness | CPTUnknown Text
|
||||
data ChatPeerType = CPTHuman | CPTBot | CPTBusiness | CPTAgent | CPTUnknown Text
|
||||
deriving (Eq, Show)
|
||||
|
||||
instance FromJSON ChatPeerType where
|
||||
@@ -768,11 +768,13 @@ instance TextEncoding ChatPeerType where
|
||||
"human" -> CPTHuman
|
||||
"bot" -> CPTBot
|
||||
"business" -> CPTBusiness
|
||||
"agent" -> CPTAgent
|
||||
tag -> CPTUnknown tag
|
||||
textEncode = \case
|
||||
CPTHuman -> "human"
|
||||
CPTBot -> "bot"
|
||||
CPTBusiness -> "business"
|
||||
CPTAgent -> "agent"
|
||||
CPTUnknown tag -> tag
|
||||
|
||||
profileFromName :: ContactName -> Profile
|
||||
|
||||
@@ -332,6 +332,9 @@ decodeChatMessageTest = describe "Chat message encoding/decoding" $ do
|
||||
it "x.info with empty full name" $
|
||||
"{\"v\":\"9\",\"event\":\"x.info\",\"params\":{\"profile\":{\"fullName\":\"\",\"displayName\":\"alice\",\"preferences\":{\"reactions\":{\"allow\":\"yes\"},\"voice\":{\"allow\":\"yes\"}}}}}"
|
||||
#==# XInfo Profile {displayName = "alice", fullName = "", shortDescr = Nothing, description = Nothing, image = Nothing, contactLink = Nothing, peerType = Nothing, preferences = testChatPreferences, badge = Nothing, contactDomain = Nothing} Nothing
|
||||
it "x.info with agent peer type" $
|
||||
"{\"v\":\"9\",\"event\":\"x.info\",\"params\":{\"profile\":{\"fullName\":\"\",\"displayName\":\"alice\",\"peerType\":\"agent\",\"preferences\":{\"reactions\":{\"allow\":\"yes\"},\"voice\":{\"allow\":\"yes\"}}}}}"
|
||||
#==# XInfo Profile {displayName = "alice", fullName = "", shortDescr = Nothing, description = Nothing, image = Nothing, contactLink = Nothing, peerType = Just CPTAgent, preferences = testChatPreferences, badge = Nothing, contactDomain = Nothing} Nothing
|
||||
it "x.contact with xContactId" $
|
||||
"{\"v\":\"9\",\"event\":\"x.contact\",\"params\":{\"contactReqId\":\"AQIDBA==\",\"profile\":{\"fullName\":\"Alice\",\"displayName\":\"alice\",\"image\":\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAIAQMAAAD+wSzIAAAABlBMVEX///+/v7+jQ3Y5AAAADklEQVQI12P4AIX8EAgALgAD/aNpbtEAAAAASUVORK5CYII=\",\"preferences\":{\"reactions\":{\"allow\":\"yes\"},\"voice\":{\"allow\":\"yes\"}}}}}"
|
||||
#==# XContact testProfile Nothing (Just $ XContactId "\1\2\3\4") Nothing Nothing
|
||||
|
||||
Reference in new issue
Block a user