mirror of
https://github.com/simplex-chat/simplex-chat.git
synced 2026-10-23 04:22:13 +00:00
ios wip
This commit is contained in:
1 parent
9d84ddc214
commit
1a869460b8
9 files changed
+238
-26
No files matched your search
@@ -775,13 +775,13 @@ struct CIFile: Decodable {
|
||||
}
|
||||
}
|
||||
|
||||
enum CIFileStatus: Decodable {
|
||||
case sndStored
|
||||
case sndCancelled
|
||||
case rcvInvitation
|
||||
case rcvTransfer
|
||||
case rcvComplete
|
||||
case rcvCancelled
|
||||
enum CIFileStatus: String, Decodable {
|
||||
case sndStored = "snd_stored"
|
||||
case sndCancelled = "snd_cancelled"
|
||||
case rcvInvitation = "rcv_invitation"
|
||||
case rcvTransfer = "rcv_transfer"
|
||||
case rcvComplete = "rcv_complete"
|
||||
case rcvCancelled = "rcv_cancelled"
|
||||
}
|
||||
|
||||
enum MsgContent {
|
||||
@@ -819,6 +819,7 @@ enum MsgContent {
|
||||
case type
|
||||
case text
|
||||
case preview
|
||||
case image
|
||||
}
|
||||
}
|
||||
|
||||
@@ -836,6 +837,10 @@ extension MsgContent: Decodable {
|
||||
let text = try container.decode(String.self, forKey: CodingKeys.text)
|
||||
let preview = try container.decode(LinkPreview.self, forKey: CodingKeys.preview)
|
||||
self = .link(text: text, preview: preview)
|
||||
case "image":
|
||||
let text = try container.decode(String.self, forKey: CodingKeys.text)
|
||||
let image = try container.decode(String.self, forKey: CodingKeys.image)
|
||||
self = .image(text: text, image: image)
|
||||
default:
|
||||
let text = try? container.decode(String.self, forKey: CodingKeys.text)
|
||||
self = .unknown(type: type, text: text ?? "unknown message format")
|
||||
|
||||
@@ -51,7 +51,9 @@ struct FramedItemView: View {
|
||||
.frame(minWidth: msgWidth, alignment: .center)
|
||||
.padding(.bottom, 2)
|
||||
} else {
|
||||
if case let .link(_, preview) = chatItem.content.msgContent {
|
||||
if case let .image(_, image) = chatItem.content.msgContent {
|
||||
ChatItemImageView(image: image, file: chatItem.file?.filePath)
|
||||
} else if case let .link(_, preview) = chatItem.content.msgContent {
|
||||
ChatItemLinkView(linkPreview: preview)
|
||||
}
|
||||
MsgContentView(
|
||||
|
||||
@@ -24,6 +24,9 @@ struct ChatView: View {
|
||||
@State private var showChatInfo = false
|
||||
@State private var showDeleteMessage = false
|
||||
|
||||
@State private var chosenImage: UIImage? = nil
|
||||
@State private var imagePreview: String? = nil
|
||||
|
||||
var body: some View {
|
||||
let cInfo = chat.chatInfo
|
||||
|
||||
@@ -90,7 +93,9 @@ struct ChatView: View {
|
||||
sendMessage: sendMessage,
|
||||
resetMessage: { message = "" },
|
||||
inProgress: inProgress,
|
||||
keyboardVisible: $keyboardVisible
|
||||
keyboardVisible: $keyboardVisible,
|
||||
chosenImage: $chosenImage,
|
||||
imagePreview: $imagePreview
|
||||
)
|
||||
}
|
||||
.navigationTitle(cInfo.chatViewName)
|
||||
@@ -221,7 +226,13 @@ struct ChatView: View {
|
||||
}
|
||||
} else {
|
||||
let mc: MsgContent
|
||||
if let preview = linkPreview {
|
||||
var file: String? = nil
|
||||
if let preview = imagePreview,
|
||||
let uiImage = chosenImage,
|
||||
let savedFile = saveImage(uiImage) {
|
||||
mc = .image(text: text, image: preview)
|
||||
file = savedFile
|
||||
} else if let preview = linkPreview {
|
||||
mc = .link(text: text, preview: preview)
|
||||
} else {
|
||||
mc = .text(text)
|
||||
@@ -229,7 +240,7 @@ struct ChatView: View {
|
||||
let chatItem = try await apiSendMessage(
|
||||
type: chat.chatInfo.chatType,
|
||||
id: chat.chatInfo.apiId,
|
||||
file: nil,
|
||||
file: file,
|
||||
quotedItemId: quotedItem?.meta.itemId,
|
||||
msg: mc
|
||||
)
|
||||
@@ -244,6 +255,30 @@ struct ChatView: View {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func saveImage(_ uiImage: UIImage) -> String? {
|
||||
if let imageResized = resizeImageToDataSize(uiImage, maxDataSize: 160000),
|
||||
let dataResized = Data(base64Encoded: dropImagePrefix(imageResized)),
|
||||
let jpegData = UIImage(data: dataResized)?.jpegData(compressionQuality: 1) {
|
||||
let imgName = "IMG_\(Date().timeIntervalSince1970).jpg"
|
||||
let filename = getDocumentsDirectory().appendingPathComponent(imgName)
|
||||
do {
|
||||
try jpegData.write(to: filename)
|
||||
return filename.path
|
||||
} catch {
|
||||
logger.error("ChatView.saveImage error: \(error.localizedDescription)")
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func getDocumentsDirectory() -> URL {
|
||||
let path = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
|
||||
return path
|
||||
// let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
|
||||
// return paths[0]
|
||||
}
|
||||
|
||||
func deleteMessage(_ mode: CIDeleteMode) {
|
||||
logger.debug("ChatView deleteMessage")
|
||||
|
||||
@@ -15,6 +15,24 @@ import SwiftUI
|
||||
// case editing(editingItem: ChatItem)
|
||||
//}
|
||||
|
||||
//enum ReferencedItem {
|
||||
// case none
|
||||
// case quoted(quotedItem: ChatItem)
|
||||
// case editing(editingItem: ChatItem)
|
||||
//}
|
||||
//
|
||||
//enum Preview {
|
||||
// case none
|
||||
// case link(linkPreview: LinkPreview)
|
||||
// case image(image: UIImage)
|
||||
//}
|
||||
//
|
||||
//struct ComposeState {
|
||||
// var quotedItem: ChatItem? = nil
|
||||
// var editingItem: ChatItem? = nil
|
||||
// var linkPreview: LinkPreview? = nil
|
||||
//}
|
||||
|
||||
struct ComposeView: View {
|
||||
@Binding var message: String
|
||||
@Binding var quotedItem: ChatItem?
|
||||
@@ -31,10 +49,17 @@ struct ComposeView: View {
|
||||
@State var pendingLinkUrl: URL? = nil
|
||||
@State var cancelledLinks: Set<String> = []
|
||||
|
||||
@State private var showChooseSource = false
|
||||
@State private var showImagePicker = false
|
||||
@State private var imageSource: ImageSource = .imageLibrary
|
||||
@Binding var chosenImage: UIImage?
|
||||
@Binding var imagePreview: String?
|
||||
|
||||
var body: some View {
|
||||
VStack(spacing: 0) {
|
||||
if let metadata = linkPreview {
|
||||
if let metadata = imagePreview {
|
||||
ComposeImageView(image: metadata, cancelImage: nil)
|
||||
} else if let metadata = linkPreview {
|
||||
ComposeLinkView(linkPreview: metadata, cancelPreview: cancelPreview)
|
||||
}
|
||||
if (quotedItem != nil) {
|
||||
@@ -42,17 +67,30 @@ struct ComposeView: View {
|
||||
} else if (editingItem != nil) {
|
||||
ContextItemView(contextItem: $editingItem, editing: $editing, resetMessage: resetMessage)
|
||||
}
|
||||
SendMessageView(
|
||||
sendMessage: { text in
|
||||
sendMessage(text)
|
||||
resetLinkPreview()
|
||||
},
|
||||
inProgress: inProgress,
|
||||
message: $message,
|
||||
keyboardVisible: $keyboardVisible,
|
||||
editing: $editing
|
||||
)
|
||||
.background(.background)
|
||||
HStack{
|
||||
Button {
|
||||
showChooseSource = true
|
||||
} label: {
|
||||
Image(systemName: "paperclip")
|
||||
.resizable()
|
||||
}
|
||||
.disabled(editingItem != nil)
|
||||
.frame(width: 25, height: 25)
|
||||
.padding(.vertical, 4)
|
||||
.padding(.leading, 12)
|
||||
SendMessageView(
|
||||
sendMessage: { text in
|
||||
sendMessage(text)
|
||||
resetLinkPreview()
|
||||
},
|
||||
inProgress: inProgress,
|
||||
message: $message,
|
||||
keyboardVisible: $keyboardVisible,
|
||||
editing: $editing
|
||||
)
|
||||
.padding(.trailing, 12)
|
||||
.background(.background)
|
||||
}
|
||||
}
|
||||
.onChange(of: message) { _ in
|
||||
if message.count > 0 {
|
||||
@@ -64,6 +102,33 @@ struct ComposeView: View {
|
||||
.onChange(of: editingItem == nil) { _ in
|
||||
editing = (editingItem != nil)
|
||||
}
|
||||
.confirmationDialog("Add image", isPresented: $showChooseSource, titleVisibility: .visible) {
|
||||
Button("Take picture") {
|
||||
imageSource = .camera
|
||||
showImagePicker = true
|
||||
}
|
||||
Button("Choose from library") {
|
||||
imageSource = .imageLibrary
|
||||
showImagePicker = true
|
||||
}
|
||||
}
|
||||
.sheet(isPresented: $showImagePicker) {
|
||||
switch imageSource {
|
||||
case .imageLibrary:
|
||||
LibraryImagePicker(image: $chosenImage) {
|
||||
didSelectItem in showImagePicker = false
|
||||
}
|
||||
case .camera:
|
||||
CameraImagePicker(image: $chosenImage)
|
||||
}
|
||||
}
|
||||
.onChange(of: chosenImage) { image in
|
||||
if let image = image {
|
||||
imagePreview = resizeImageToDataSize(cropToSquare(image), maxDataSize: 12500)
|
||||
} else {
|
||||
imagePreview = nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func showLinkPreview(_ s: String) {
|
||||
@@ -136,6 +201,8 @@ struct ComposeView_Previews: PreviewProvider {
|
||||
@State var item: ChatItem? = ChatItem.getSample(1, .directSnd, .now, "hello")
|
||||
@State var nilItem: ChatItem? = nil
|
||||
@State var linkPreview: LinkPreview? = nil
|
||||
@State var chosenImage: UIImage? = nil
|
||||
@State var imagePreview: String? = nil
|
||||
|
||||
return Group {
|
||||
ComposeView(
|
||||
@@ -145,7 +212,9 @@ struct ComposeView_Previews: PreviewProvider {
|
||||
linkPreview: $linkPreview,
|
||||
sendMessage: { print ($0) },
|
||||
resetMessage: {},
|
||||
keyboardVisible: $keyboardVisible
|
||||
keyboardVisible: $keyboardVisible,
|
||||
chosenImage: $chosenImage,
|
||||
imagePreview: $imagePreview
|
||||
)
|
||||
ComposeView(
|
||||
message: $message,
|
||||
@@ -154,7 +223,9 @@ struct ComposeView_Previews: PreviewProvider {
|
||||
linkPreview: $linkPreview,
|
||||
sendMessage: { print ($0) },
|
||||
resetMessage: {},
|
||||
keyboardVisible: $keyboardVisible
|
||||
keyboardVisible: $keyboardVisible,
|
||||
chosenImage: $chosenImage,
|
||||
imagePreview: $imagePreview
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,7 +62,6 @@ struct SendMessageView: View {
|
||||
.strokeBorder(.secondary, lineWidth: 0.3, antialiased: true)
|
||||
.frame(height: teHeight)
|
||||
}
|
||||
.padding(.horizontal, 12)
|
||||
.padding(.vertical, 8)
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
//
|
||||
// ChatItemImageView.swift
|
||||
// SimpleX
|
||||
//
|
||||
// Created by JRoberts on 12/04/2022.
|
||||
// Copyright © 2022 SimpleX Chat. All rights reserved.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
struct ChatItemImageView: View {
|
||||
@Environment(\.colorScheme) var colorScheme
|
||||
let image: String
|
||||
let file: String?
|
||||
|
||||
var body: some View {
|
||||
VStack(alignment: .center, spacing: 6) {
|
||||
if let file = file,
|
||||
let uiImage = UIImage(contentsOfFile: file) {
|
||||
Image(uiImage: uiImage)
|
||||
.resizable()
|
||||
.scaledToFit()
|
||||
} else if let data = Data(base64Encoded: dropImagePrefix(image)),
|
||||
let uiImage = UIImage(data: data) {
|
||||
Image(uiImage: uiImage)
|
||||
.resizable()
|
||||
.scaledToFit()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func loadImage(file: String?) -> UIImage? {
|
||||
if let file = file {
|
||||
return UIImage(contentsOfFile: file)
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//struct ChatItemImageView_Previews: PreviewProvider {
|
||||
// static var previews: some View {
|
||||
// let preview = LinkPreview(
|
||||
// uri: URL(string: "http://DuckDuckGo.com")!,
|
||||
// title: "Privacy, simplified.",
|
||||
// description: "",
|
||||
// image: "data:image/jpg;base64,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 truncated
|
||||
// )
|
||||
// ChatItemLinkView(linkPreview: preview)
|
||||
// .previewLayout(.fixed(width: 360, height: 200))
|
||||
// }
|
||||
//}
|
||||
@@ -0,0 +1,37 @@
|
||||
//
|
||||
// ComposeImageView.swift
|
||||
// SimpleX
|
||||
//
|
||||
// Created by JRoberts on 11/04/2022.
|
||||
// Copyright © 2022 SimpleX Chat. All rights reserved.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
struct ComposeImageView: View {
|
||||
@Environment(\.colorScheme) var colorScheme
|
||||
let image: String
|
||||
var cancelImage: (() -> Void)? = nil
|
||||
|
||||
var body: some View {
|
||||
HStack(alignment: .center, spacing: 8) {
|
||||
if let data = Data(base64Encoded: dropImagePrefix(image)),
|
||||
let uiImage = UIImage(data: data) {
|
||||
Image(uiImage: uiImage)
|
||||
.resizable()
|
||||
.aspectRatio(contentMode: .fit)
|
||||
.frame(maxWidth: 80, maxHeight: 60)
|
||||
}
|
||||
if let cancelImage = cancelImage {
|
||||
Button { cancelImage() } label: {
|
||||
Image(systemName: "multiply")
|
||||
}
|
||||
}
|
||||
}
|
||||
.padding(.vertical, 1)
|
||||
.padding(.trailing, 12)
|
||||
.background(colorScheme == .light ? sentColorLight : sentColorDark)
|
||||
.frame(maxWidth: .infinity)
|
||||
.padding(.top, 8)
|
||||
}
|
||||
}
|
||||
@@ -69,6 +69,7 @@ struct TerminalView: View {
|
||||
keyboardVisible: $keyboardVisible,
|
||||
editing: $editing
|
||||
)
|
||||
.padding(.horizontal, 12)
|
||||
}
|
||||
}
|
||||
.navigationViewStyle(.stack)
|
||||
|
||||
@@ -113,6 +113,8 @@
|
||||
649BCD9C280430D100C3A862 /* libHSsimplex-chat-1.5.0-3uBn0HoMpg08OGLfasXsOx.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 649BCD97280430D100C3A862 /* libHSsimplex-chat-1.5.0-3uBn0HoMpg08OGLfasXsOx.a */; };
|
||||
649BCD9D280430D100C3A862 /* libgmp.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 649BCD98280430D100C3A862 /* libgmp.a */; };
|
||||
649BCD9E280430D100C3A862 /* libgmpxx.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 649BCD99280430D100C3A862 /* libgmpxx.a */; };
|
||||
649BCDA0280460FD00C3A862 /* ComposeImageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 649BCD9F280460FD00C3A862 /* ComposeImageView.swift */; };
|
||||
649BCDA22805D6EF00C3A862 /* ChatItemImageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 649BCDA12805D6EF00C3A862 /* ChatItemImageView.swift */; };
|
||||
64AA1C6927EE10C800AC7277 /* ContextItemView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64AA1C6827EE10C800AC7277 /* ContextItemView.swift */; };
|
||||
64AA1C6A27EE10C800AC7277 /* ContextItemView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64AA1C6827EE10C800AC7277 /* ContextItemView.swift */; };
|
||||
64AA1C6C27F3537400AC7277 /* DeletedItemView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64AA1C6B27F3537400AC7277 /* DeletedItemView.swift */; };
|
||||
@@ -201,6 +203,8 @@
|
||||
649BCD97280430D100C3A862 /* libHSsimplex-chat-1.5.0-3uBn0HoMpg08OGLfasXsOx.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-1.5.0-3uBn0HoMpg08OGLfasXsOx.a"; sourceTree = "<group>"; };
|
||||
649BCD98280430D100C3A862 /* libgmp.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgmp.a; sourceTree = "<group>"; };
|
||||
649BCD99280430D100C3A862 /* libgmpxx.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgmpxx.a; sourceTree = "<group>"; };
|
||||
649BCD9F280460FD00C3A862 /* ComposeImageView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComposeImageView.swift; sourceTree = "<group>"; };
|
||||
649BCDA12805D6EF00C3A862 /* ChatItemImageView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatItemImageView.swift; sourceTree = "<group>"; };
|
||||
64AA1C6827EE10C800AC7277 /* ContextItemView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContextItemView.swift; sourceTree = "<group>"; };
|
||||
64AA1C6B27F3537400AC7277 /* DeletedItemView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeletedItemView.swift; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
@@ -319,6 +323,8 @@
|
||||
5C5F2B6F27EBC704006A9D5F /* ProfileImage.swift */,
|
||||
3CDBCF4127FAE51000354CDD /* ComposeLinkView.swift */,
|
||||
3CDBCF4727FF621E00354CDD /* ChatItemLinkView.swift */,
|
||||
649BCD9F280460FD00C3A862 /* ComposeImageView.swift */,
|
||||
649BCDA12805D6EF00C3A862 /* ChatItemImageView.swift */,
|
||||
);
|
||||
path = Helpers;
|
||||
sourceTree = "<group>";
|
||||
@@ -635,6 +641,7 @@
|
||||
5CC1C99227A6C7F5000D9FF6 /* QRCode.swift in Sources */,
|
||||
5C116CDC27AABE0400E66D01 /* ContactRequestView.swift in Sources */,
|
||||
5CB9250D27A9432000ACCCDD /* ChatListNavLink.swift in Sources */,
|
||||
649BCDA0280460FD00C3A862 /* ComposeImageView.swift in Sources */,
|
||||
5CA059ED279559F40002BEB4 /* ContentView.swift in Sources */,
|
||||
5CCD403427A5F6DF00368C90 /* AddContactView.swift in Sources */,
|
||||
5C3A88CE27DF50170060F1C2 /* DetermineWidth.swift in Sources */,
|
||||
@@ -649,6 +656,7 @@
|
||||
5C577F7D27C83AA10006112D /* MarkdownHelp.swift in Sources */,
|
||||
5CA059EB279559F40002BEB4 /* SimpleXApp.swift in Sources */,
|
||||
5CCD403727A5F9A200368C90 /* ConnectContactView.swift in Sources */,
|
||||
649BCDA22805D6EF00C3A862 /* ChatItemImageView.swift in Sources */,
|
||||
5CCD403A27A5F9BE00368C90 /* CreateGroupView.swift in Sources */,
|
||||
5CEACCED27DEA495000BD591 /* MsgContentView.swift in Sources */,
|
||||
5C764E89279CBCB3000C6508 /* ChatModel.swift in Sources */,
|
||||
|
||||
Reference in new issue
Block a user