mobile: support images (#536)
* ios api
* ios wip
* android wip
* ios files folder
* ios get address on start
* android app files folder
* ios more backend
* android more backend
* translation
* ios image without text, remove preview
* android image without text, remove preview
* fix translation
* file name in previews and w/t text
* Revert "file name in previews and w/t text"
This reverts commit 0110570e55.
* ios filename in preview
* android filename in preview
* android wider images
* ios determine width on image for correct quote width
* ios images in previews wip
* ios square image in quote
* ios: update image layout
* android images in quotes
* android remove redundant modifier
* android clip to bounds
* android - image in right side of quote
* android refactor image view
* android - refactor, align quote text top
* android fix emoji view
* fix image layout
* full screen image view, fix quote layout
* android various size
* android fixed image width
* android meta on image
* ios: add drag gesture to hide full-screen image
* android: make image-only meta white
* refactor file.stored
* android: meta icon color
* android: open chat scrolled to last unread item
* copy/share image messages
* android: full screen image
* check file is loaded
* terminal: refactor view for messages with files
* android: change to onClick, only show stored file
* android: remove close sheet bar
* android: close image view on click
* translation
* android: pass showMenu to CIImageView to show menu on long click
* increase DropDown width
Co-authored-by: Evgeny Poberezkin <2769109+epoberezkin@users.noreply.github.com>
This commit is contained in:
@@ -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?
|
||||
@@ -26,15 +44,23 @@ struct ComposeView: View {
|
||||
var inProgress: Bool = false
|
||||
@FocusState.Binding var keyboardVisible: Bool
|
||||
@State var editing: Bool = false
|
||||
@State var sendEnabled: Bool = false
|
||||
@State var linkUrl: URL? = nil
|
||||
@State var prevLinkUrl: URL? = nil
|
||||
@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 +68,31 @@ 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,
|
||||
sendEnabled: $sendEnabled
|
||||
)
|
||||
.padding(.trailing, 12)
|
||||
.background(.background)
|
||||
}
|
||||
}
|
||||
.onChange(of: message) { _ in
|
||||
if message.count > 0 {
|
||||
@@ -60,10 +100,41 @@ struct ComposeView: View {
|
||||
} else {
|
||||
resetLinkPreview()
|
||||
}
|
||||
sendEnabled = (imagePreview != nil || !message.isEmpty)
|
||||
}
|
||||
.onChange(of: editingItem == nil) { _ in
|
||||
editing = (editingItem != nil)
|
||||
}
|
||||
.confirmationDialog("Attach", 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(image, maxDataSize: 12500)
|
||||
} else {
|
||||
imagePreview = nil
|
||||
}
|
||||
}
|
||||
.onChange(of: imagePreview) { _ in
|
||||
sendEnabled = (imagePreview != nil || !message.isEmpty)
|
||||
}
|
||||
}
|
||||
|
||||
private func showLinkPreview(_ s: String) {
|
||||
@@ -136,6 +207,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 +218,9 @@ struct ComposeView_Previews: PreviewProvider {
|
||||
linkPreview: $linkPreview,
|
||||
sendMessage: { print ($0) },
|
||||
resetMessage: {},
|
||||
keyboardVisible: $keyboardVisible
|
||||
keyboardVisible: $keyboardVisible,
|
||||
chosenImage: $chosenImage,
|
||||
imagePreview: $imagePreview
|
||||
)
|
||||
ComposeView(
|
||||
message: $message,
|
||||
@@ -154,7 +229,9 @@ struct ComposeView_Previews: PreviewProvider {
|
||||
linkPreview: $linkPreview,
|
||||
sendMessage: { print ($0) },
|
||||
resetMessage: {},
|
||||
keyboardVisible: $keyboardVisible
|
||||
keyboardVisible: $keyboardVisible,
|
||||
chosenImage: $chosenImage,
|
||||
imagePreview: $imagePreview
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ struct SendMessageView: View {
|
||||
@Namespace var namespace
|
||||
@FocusState.Binding var keyboardVisible: Bool
|
||||
@Binding var editing: Bool
|
||||
@Binding var sendEnabled: Bool
|
||||
@State private var teHeight: CGFloat = 42
|
||||
@State private var teFont: Font = .body
|
||||
var maxHeight: CGFloat = 360
|
||||
@@ -52,7 +53,7 @@ struct SendMessageView: View {
|
||||
.resizable()
|
||||
.foregroundColor(.accentColor)
|
||||
}
|
||||
.disabled(message.isEmpty)
|
||||
.disabled(!sendEnabled)
|
||||
.frame(width: 29, height: 29)
|
||||
.padding([.bottom, .trailing], 4)
|
||||
}
|
||||
@@ -62,7 +63,6 @@ struct SendMessageView: View {
|
||||
.strokeBorder(.secondary, lineWidth: 0.3, antialiased: true)
|
||||
.frame(height: teHeight)
|
||||
}
|
||||
.padding(.horizontal, 12)
|
||||
.padding(.vertical, 8)
|
||||
}
|
||||
|
||||
@@ -90,6 +90,7 @@ struct SendMessageView_Previews: PreviewProvider {
|
||||
@FocusState var keyboardVisible: Bool
|
||||
@State var editingOff: Bool = false
|
||||
@State var editingOn: Bool = true
|
||||
@State var sendEnabled: Bool = true
|
||||
@State var item: ChatItem? = ChatItem.getSample(1, .directSnd, .now, "hello")
|
||||
|
||||
return Group {
|
||||
@@ -100,7 +101,8 @@ struct SendMessageView_Previews: PreviewProvider {
|
||||
sendMessage: { print ($0) },
|
||||
message: $message,
|
||||
keyboardVisible: $keyboardVisible,
|
||||
editing: $editingOff
|
||||
editing: $editingOff,
|
||||
sendEnabled: $sendEnabled
|
||||
)
|
||||
}
|
||||
VStack {
|
||||
@@ -110,7 +112,8 @@ struct SendMessageView_Previews: PreviewProvider {
|
||||
sendMessage: { print ($0) },
|
||||
message: $message,
|
||||
keyboardVisible: $keyboardVisible,
|
||||
editing: $editingOn
|
||||
editing: $editingOn,
|
||||
sendEnabled: $sendEnabled
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user