Files
simplex-chat/apps/ios/Shared/Views/Chat/ComposeMessage/ContextItemView.swift
T
Evgeny @ SimpleX Chat cfb9b7c656 ios: snapshot tests render all app previews (#7912)
* ios: snapshot tests render all previews at fixed dates

* ios: previews of your servers and terminal render without errors

* ios: snapshots fill the screen height for lists, skip device migration

* ios: snapshots show the sample user, secondary chat preview has items

* ios: snapshots skip previews of live prices, profiles and console

* ci: references of all iOS previews

* ci: snapshot docs state window height, exclusions and timing

* ios: snapshots skip previews with a blinking caret or a spinner

* ios: snapshots end editing and stop animations, restoring 8 previews

* ci: references of the restored cursor and spinner previews

* ios: chat item previews clip items to bubbles as the chat view does

* ci: references of chat item previews with bubbles
2026-10-28 05:18:10 +00:00

105 lines
4.1 KiB
Swift

//
// ContextItemView.swift
// SimpleX
//
// Created by JRoberts on 13/03/2022.
// Copyright © 2022 SimpleX Chat. All rights reserved.
//
import SwiftUI
import SimpleXChat
struct ContextItemView: View {
@EnvironmentObject var theme: AppTheme
@ObservedObject var chat: Chat
let contextItems: [ChatItem]
let contextIcon: String
let cancelContextItem: () -> Void
var contextIconForeground: Color? = nil
var showSender: Bool = true
var body: some View {
HStack {
Image(systemName: contextIcon)
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: 16, height: 16)
.foregroundColor(contextIconForeground ?? theme.colors.secondary)
if let singleItem = contextItems.first, contextItems.count == 1 {
if showSender, let sender = singleItem.memberDisplayName {
VStack(alignment: .leading, spacing: 4) {
Text(sender).font(.caption).foregroundColor(theme.colors.secondary)
msgContentView(lines: 2, contextItem: singleItem)
}
} else {
msgContentView(lines: 3, contextItem: singleItem)
}
} else {
Text(
chat.chatInfo.chatType == .local
? "Saving \(contextItems.count) messages"
: "Forwarding \(contextItems.count) messages"
)
.italic()
}
Spacer()
Button {
withAnimation {
cancelContextItem()
}
} label: {
Image(systemName: "multiply")
}
.tint(theme.colors.primary)
}
.padding(12)
.frame(minHeight: 54)
.frame(maxWidth: .infinity)
.background(background)
}
private var background: Color {
contextItems.first
.map { chatItemFrameColor($0, theme) }
?? Color(uiColor: .tertiarySystemBackground)
}
private func msgContentView(lines: Int, contextItem: ChatItem) -> some View {
contextMsgPreview(contextItem)
.multilineTextAlignment(isRightToLeft(contextItem.text) ? .trailing : .leading)
.lineLimit(lines)
}
private func contextMsgPreview(_ contextItem: ChatItem) -> some View {
let r = messageText(contextItem.text, contextItem.formattedText, markdownBlocks: contextItem.markdownBlocks, sender: nil, preview: true, mentions: contextItem.mentions, userMemberId: nil, showSecrets: nil, backgroundColor: UIColor(background), stripLink: contextItem.content.msgContent?.chatLinkStr)
let t = attachment() + Text(AttributedString(r.string))
return t.if(r.hasSecrets, transform: hiddenSecretsView)
func attachment() -> Text {
let isFileLoaded = if let fileSource = getLoadedFileSource(contextItem.file) {
FileManager.default.fileExists(atPath: getAppFilePath(fileSource.filePath).path)
} else { false }
switch contextItem.content.msgContent {
case .file: return isFileLoaded ? image("doc.fill") : Text("")
case .image: return image("photo")
case .voice: return isFileLoaded ? image("play.fill") : Text("")
case let .chat(_, chatLink, _):
let hasText = contextItem.text != chatLink.connLinkStr
return image(chatLink.smallIconName) + Text(chatLink.displayName) + Text(verbatim: hasText ? " - " : "")
default: return Text("")
}
}
func image(_ s: String) -> Text {
Text(Image(systemName: s)).foregroundColor(Color(uiColor: .tertiaryLabel)) + textSpace
}
}
}
struct ContextItemView_Previews: PreviewProvider {
static var previews: some View {
let contextItem: ChatItem = ChatItem.getSample(1, .directSnd, previewDate, "hello")
return ContextItemView(chat: Chat.sampleData, contextItems: [contextItem], contextIcon: "pencil.circle", cancelContextItem: {}, contextIconForeground: Color.red)
}
}