Files
simplex-chat/apps/ios/Shared/Views/Chat/ChatInfoToolbar.swift
T
ad23da63d0 core: supporter badges using anonymous BBS credentials (#7040)
* core: supporter badges using anonymous BBS credentials

* badges in profiles

* badge in profiles

* process badges

* update simplexmq

* update simplexmq

* change types

* fix migration

* migration

* update simplexmq

* fix bot API, schema

* fix postgresql build

* refactor

* postgresql schema

* correctly set badges in all cases

* badges ffi

* plan, bot types

* FFI

* FFI: export badge symbols

* add extra field

* refactor badge types to GADT

* configurable badge key

* add badge to profile, test

* ui: badge images

* generate badge key and sign badge

* badge sign in CLI

* fix commands, ui

* rename badges

* Binary

* image size, migration

* update badge images, add public key

* send badges in more cases

* update UI, tests

* bot types, schema

* postgres schema

* tone down badges

* revert formula

* refactor badges

* smaller badges

* badge position

* better badge position

* simpler

* position

* move position

* update simplexmq

* show badge after name

* badge layout

* fix badge

* debug badge height

* shift badge

* fix badge in member name

* bigger badge

* badge layout

* differentiate badge colors

* more avatars for the user's profiles

* refactor

* remove color filter

* alerts

* multiple keys, old expired

* use new BBS api

* update badge keys, bot api

* presentation header

* simplify

* parser

* update iOS images

* update public keys

* query plans

* update simplexmq

* refactor badge types

* simplexmq

* bot api types

* update simplexmq - commoncrypto flag

* update simplexmq

* pass commoncrypto flag to simplexmq in nix iOS build

* ios ui

* update core library, fixes

* badge layout

* badge size

* badge gap

* remove extensions

* simplify

* share badge in more events, reverify badge if verification failed

* larger files with badges

* allow sending larger files

* simpler

* update simplexmq

* better decoder for badge keys

* update simplexmq

---------

Co-authored-by: Evgeny @ SimpleX Chat <259188159+evgeny-simplex@users.noreply.github.com>
Co-authored-by: shum <github.shum@liber.li>
2026-06-15 22:25:08 +01:00

140 lines
5.1 KiB
Swift

//
// ChatInfoToolbar.swift
// SimpleX
//
// Created by Evgeny Poberezkin on 11/02/2022.
// Copyright © 2022 SimpleX Chat. All rights reserved.
//
import SwiftUI
import SimpleXChat
struct ChatInfoToolbar: View {
@Environment(\.colorScheme) var colorScheme
@EnvironmentObject var theme: AppTheme
@EnvironmentObject var m: ChatModel
@ObservedObject var chat: Chat
var imageSize: CGFloat = 32
var body: some View {
let cInfo = chat.chatInfo
return HStack {
if (cInfo.incognito) {
Image(systemName: "theatermasks").frame(maxWidth: 24, maxHeight: 24, alignment: .center).foregroundColor(.indigo)
Spacer().frame(width: 16)
}
ZStack(alignment: .bottomTrailing) {
ChatInfoImage(
chat: chat,
size: imageSize,
color: Color(uiColor: .tertiaryLabel)
)
if chat.chatStats.reportsCount > 0 {
Image(systemName: "flag.circle.fill")
.resizable()
.scaledToFit()
.frame(width: 14, height: 14)
.symbolRenderingMode(.palette)
.foregroundStyle(.white, .red)
} else if chat.supportUnreadCount > 0 {
Image(systemName: "flag.circle.fill")
.resizable()
.scaledToFit()
.frame(width: 14, height: 14)
.symbolRenderingMode(.palette)
.foregroundStyle(.white, theme.colors.primary)
}
}
.padding(.trailing, 4)
let t = Text(cInfo.displayName).font(.headline)
NameWithBadge((cInfo.contact?.verified == true ? contactVerifiedShield + t : t), cInfo.nameBadge, .headline)
.lineLimit(1)
.if (cInfo.fullName != "" && cInfo.displayName != cInfo.fullName) { v in
VStack(spacing: 0) {
v
Text(cInfo.fullName).font(.subheadline)
.lineLimit(1)
.padding(.top, -2)
}
}
.if (channelSubscriberCount != nil) { v in
VStack(spacing: 0) {
v
if let count = channelSubscriberCount {
Text(subscriberCountStr(count))
.font(.caption)
.foregroundColor(theme.colors.secondary)
.lineLimit(1)
.padding(.top, -2)
}
}
}
if let contact = chat.chatInfo.contact,
contact.ready && contact.active,
let chatSubStatus = m.chatSubStatus,
chatSubStatus != .active {
SubStatusView(status: chatSubStatus)
.padding(.leading, 4)
}
}
.foregroundColor(theme.colors.onBackground)
.frame(width: 220)
}
private var channelSubscriberCount: Int64? {
if case let .group(groupInfo, _) = chat.chatInfo,
groupInfo.useRelays,
let count = groupInfo.groupSummary.publicMemberCount,
count > 0 {
count
} else {
nil
}
}
private var contactVerifiedShield: Text {
(Text(Image(systemName: "checkmark.shield")) + textSpace)
.font(.caption)
.foregroundColor(theme.colors.secondary)
.baselineOffset(1)
.kerning(-2)
}
struct SubStatusView: View {
@Environment(\.dynamicTypeSize) private var userFont: DynamicTypeSize
@EnvironmentObject var theme: AppTheme
var status: SubscriptionStatus
var body: some View {
switch status {
case .active: EmptyView()
case .pending: ProgressView()
case .removed: subStatusError()
case .noSub: subStatusError()
}
}
@ViewBuilder private func subStatusError() -> some View {
let dynamicChatInfoSize = dynamicSize(userFont).chatInfoSize
Image(systemName: "exclamationmark.circle")
.resizable()
.scaledToFit()
.frame(width: dynamicChatInfoSize, height: dynamicChatInfoSize)
.foregroundColor(theme.colors.secondary)
}
}
}
public func subscriberCountStr(_ count: Int64) -> String {
count == 1
? String.localizedStringWithFormat(NSLocalizedString("%d subscriber", comment: "channel subscriber count"), count)
: String.localizedStringWithFormat(NSLocalizedString("%d subscribers", comment: "channel subscriber count"), count)
}
struct ChatInfoToolbar_Previews: PreviewProvider {
static var previews: some View {
ChatInfoToolbar(chat: Chat(chatInfo: ChatInfo.sampleData.direct, chatItems: []))
.environmentObject(CurrentColors.toAppTheme())
}
}