From 3fd2938a5fe7486c277bcd3bf331bdefa541b29c Mon Sep 17 00:00:00 2001 From: Diogo Date: Fri, 13 Dec 2024 21:58:15 +0000 Subject: [PATCH] nice emoji picker --- .../Views/ChatList/ChatListNavLink.swift | 99 ++++++++++++------- apps/ios/SimpleX.xcodeproj/project.pbxproj | 17 ++++ .../xcshareddata/swiftpm/Package.resolved | 11 ++- 3 files changed, 93 insertions(+), 34 deletions(-) diff --git a/apps/ios/Shared/Views/ChatList/ChatListNavLink.swift b/apps/ios/Shared/Views/ChatList/ChatListNavLink.swift index 7bc78eafaa..100a3ee7c0 100644 --- a/apps/ios/Shared/Views/ChatList/ChatListNavLink.swift +++ b/apps/ios/Shared/Views/ChatList/ChatListNavLink.swift @@ -8,6 +8,7 @@ import SwiftUI import SimpleXChat +import ElegantEmojiPicker typealias DynamicSizes = ( rowHeight: CGFloat, @@ -674,36 +675,52 @@ struct ChatListTag: View { } } -struct SingleEmojiTextField: View { - @Binding var emoji: String - @State var lastEmoji: Character? = nil - var placeholder: String +struct EmojiPickerView: UIViewControllerRepresentable { + @Binding var selectedEmoji: Emoji? + @Binding var showingPicker: Bool + @Environment(\.presentationMode) var presentationMode - var body: some View { - TextField(placeholder, text: $emoji) - .keyboardType(.default) - .multilineTextAlignment(.center) - .frame(width: 40) - .onChange(of: emoji) { _ in - print("changes: \(emoji) \(String(describing: lastEmoji))") - var newEmoji = "" - - if emoji.count > 1 { - let uniqueChars = Set(emoji) - - if uniqueChars.count == 1, let firstChar = emoji.first, isEmoji(firstChar) { - newEmoji = String(firstChar) - } else if let firstValidEmoji = emoji.first(where: { isEmoji($0) && $0 != lastEmoji }) { - newEmoji = String(firstValidEmoji) - } - } else if let firstChar = emoji.first, isEmoji(firstChar) { - newEmoji = String(firstChar) - } - - emoji = newEmoji - lastEmoji = newEmoji.first + class Coordinator: NSObject, ElegantEmojiPickerDelegate, UIAdaptivePresentationControllerDelegate { + var parent: EmojiPickerView + + init(parent: EmojiPickerView) { + self.parent = parent + } + + func emojiPicker(_ picker: ElegantEmojiPicker, didSelectEmoji emoji: Emoji?) { + parent.selectedEmoji = emoji + parent.showingPicker = false + picker.dismiss(animated: true) + } + + // Called when the picker is dismissed manually (without selection) + func presentationControllerWillDismiss(_ presentationController: UIPresentationController) { + parent.showingPicker = false + } + } + + func makeCoordinator() -> Coordinator { + return Coordinator(parent: self) + } + + func makeUIViewController(context: Context) -> UIViewController { + let config = ElegantConfiguration(showRandom: false, showReset: false, defaultSkinTone: .Light) + let picker = ElegantEmojiPicker(delegate: context.coordinator, configuration: config) + + picker.presentationController?.delegate = context.coordinator + + let viewController = UIViewController() + DispatchQueue.main.async { + if let topVC = getTopViewController() { + topVC.present(picker, animated: true) } - .opacity(emoji.isEmpty ? 0.4 : 1) + } + + return viewController + } + + func updateUIViewController(_ uiViewController: UIViewController, context: Context) { + // No need to update the controller after creation } } @@ -712,13 +729,26 @@ struct CreateChatListTag: View { @Environment(\.presentationMode) var presentationMode @EnvironmentObject var chatTagsModel: ChatTagsModel @EnvironmentObject var m: ChatModel - @State private var emoji: String = "" + @State private var emoji: Emoji? = nil @State private var name: String = "" - + @State private var isPickerPresented = false // Boolean to show picker sheet + var body: some View { List { HStack { - SingleEmojiTextField(emoji: $emoji, placeholder: "🙂") + Button { + isPickerPresented.toggle() + } label: { + if let emoji { + Text(emoji.emoji) + } else { + Image(systemName: "face.smiling") + .resizable() + .scaledToFit() + .frame(width: 18, height: 18) + .foregroundColor(.secondary) + } + } TextField("List name...", text: $name) } @@ -727,7 +757,10 @@ struct CreateChatListTag: View { } label: { Text("Create list") } - .disabled(emoji.isEmpty || name.isEmpty) + .disabled(name.isEmpty) + } + if isPickerPresented { + EmojiPickerView(selectedEmoji: $emoji, showingPicker: $isPickerPresented) } } @@ -737,7 +770,7 @@ struct CreateChatListTag: View { let (userTags, chatTags) = try await apiCreateChatTag( type: chat.chatInfo.chatType, id: chat.chatInfo.apiId, - tag: ChatTagData(emoji: emoji, text: name) + tag: ChatTagData(emoji: emoji?.emoji ?? "😂", text: name) ) await MainActor.run { diff --git a/apps/ios/SimpleX.xcodeproj/project.pbxproj b/apps/ios/SimpleX.xcodeproj/project.pbxproj index 759b16b196..bc4030fd61 100644 --- a/apps/ios/SimpleX.xcodeproj/project.pbxproj +++ b/apps/ios/SimpleX.xcodeproj/project.pbxproj @@ -203,6 +203,7 @@ 8CC4ED902BD7B8530078AEE8 /* CallAudioDeviceManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8CC4ED8F2BD7B8530078AEE8 /* CallAudioDeviceManager.swift */; }; 8CC956EE2BC0041000412A11 /* NetworkObserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8CC956ED2BC0041000412A11 /* NetworkObserver.swift */; }; 8CE848A32C5A0FA000D5C7C8 /* SelectableChatItemToolbars.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8CE848A22C5A0FA000D5C7C8 /* SelectableChatItemToolbars.swift */; }; + B728945B2D0C62BF00F7A19A /* ElegantEmojiPicker in Frameworks */ = {isa = PBXBuildFile; productRef = B728945A2D0C62BF00F7A19A /* ElegantEmojiPicker */; }; B73EFE532CE5FA3500C778EA /* CreateSimpleXAddress.swift in Sources */ = {isa = PBXBuildFile; fileRef = B73EFE522CE5FA3500C778EA /* CreateSimpleXAddress.swift */; }; B76E6C312C5C41D900EC11AA /* ContactListNavLink.swift in Sources */ = {isa = PBXBuildFile; fileRef = B76E6C302C5C41D900EC11AA /* ContactListNavLink.swift */; }; B79ADAFF2CE4EF930083DFFD /* AddressCreationCard.swift in Sources */ = {isa = PBXBuildFile; fileRef = B79ADAFE2CE4EF930083DFFD /* AddressCreationCard.swift */; }; @@ -636,6 +637,7 @@ buildActionMask = 2147483647; files = ( 5CE2BA702845308900EC33A6 /* SimpleXChat.framework in Frameworks */, + B728945B2D0C62BF00F7A19A /* ElegantEmojiPicker in Frameworks */, 8C8118722C220B5B00E6FC94 /* Yams in Frameworks */, 8CB3476C2CF5CFFA006787A5 /* Ink in Frameworks */, D741547829AF89AF0022400A /* StoreKit.framework in Frameworks */, @@ -1186,6 +1188,7 @@ D7197A1729AE89660055C05A /* WebRTC */, 8C8118712C220B5B00E6FC94 /* Yams */, 8CB3476B2CF5CFFA006787A5 /* Ink */, + B728945A2D0C62BF00F7A19A /* ElegantEmojiPicker */, ); productName = "SimpleX (iOS)"; productReference = 5CA059CA279559F40002BEB4 /* SimpleX.app */; @@ -1330,6 +1333,7 @@ D7197A1629AE89660055C05A /* XCRemoteSwiftPackageReference "WebRTC" */, 8C73C1162C21E17B00892670 /* XCRemoteSwiftPackageReference "Yams" */, 8CB3476A2CF5CFFA006787A5 /* XCRemoteSwiftPackageReference "ink" */, + B72894592D0C62BF00F7A19A /* XCRemoteSwiftPackageReference "Elegant-Emoji-Picker" */, ); productRefGroup = 5CA059CB279559F40002BEB4 /* Products */; projectDirPath = ""; @@ -2387,6 +2391,14 @@ version = 0.6.0; }; }; + B72894592D0C62BF00F7A19A /* XCRemoteSwiftPackageReference "Elegant-Emoji-Picker" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/Finalet/Elegant-Emoji-Picker"; + requirement = { + branch = main; + kind = branch; + }; + }; D7197A1629AE89660055C05A /* XCRemoteSwiftPackageReference "WebRTC" */ = { isa = XCRemoteSwiftPackageReference; repositoryURL = "https://github.com/simplex-chat/WebRTC.git"; @@ -2429,6 +2441,11 @@ package = 8CB3476A2CF5CFFA006787A5 /* XCRemoteSwiftPackageReference "ink" */; productName = Ink; }; + B728945A2D0C62BF00F7A19A /* ElegantEmojiPicker */ = { + isa = XCSwiftPackageProductDependency; + package = B72894592D0C62BF00F7A19A /* XCRemoteSwiftPackageReference "Elegant-Emoji-Picker" */; + productName = ElegantEmojiPicker; + }; CE38A29B2C3FCD72005ED185 /* SwiftyGif */ = { isa = XCSwiftPackageProductDependency; package = D77B92DA2952372200A5A1CC /* XCRemoteSwiftPackageReference "SwiftyGif" */; diff --git a/apps/ios/SimpleX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/apps/ios/SimpleX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 7fdbff38af..2bddf5b5b8 100644 --- a/apps/ios/SimpleX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/apps/ios/SimpleX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -1,5 +1,5 @@ { - "originHash" : "33afc44be5f4225325b3cb940ed71b6cbf3ef97290d348d7b6803697bcd0637d", + "originHash" : "07434ae88cbf078ce3d27c91c1f605836aaebff0e0cef5f25317795151c77db1", "pins" : [ { "identity" : "codescanner", @@ -10,6 +10,15 @@ "version" : "2.5.0" } }, + { + "identity" : "elegant-emoji-picker", + "kind" : "remoteSourceControl", + "location" : "https://github.com/Finalet/Elegant-Emoji-Picker", + "state" : { + "branch" : "main", + "revision" : "71d2d46092b4d550cc593614efc06438f845f6e6" + } + }, { "identity" : "ink", "kind" : "remoteSourceControl",