Giter Club home page Giter Club logo

mcemojipicker's Introduction

MCEmojiPicker

Version License Platform

About

It is a customizable library implementing macOS style emoji picker popover.

If you are interested in how I developed it and what difficulties I encountered in the process, you can read an article on Medium, Habr about it. And if you like the project, don't forget to put star β˜….

Limitations

  • Does not support two part emojis. For example:
    • Supported: 🀝🏻 🀝🏿
    • Not supported: πŸ«±πŸΏβ€πŸ«²πŸ» πŸ«±πŸΌβ€πŸ«²πŸΏ

If you know how to fix it - welcome to the discussion.

Apps Using

If you use a MCEmojiPicker, add your application via Pull Request. Fore more information you can see contribution guide.

Navigation

Requirements

  • Swift 4.2 & 5.0
  • Ready for use on iOS 12.0+
  • SwiftUI is supported from iOS 13.0

Installation

CocoaPods

CocoaPods is a dependency manager for Cocoa projects. For usage and installation instructions, visit their website. To integrate MCEmojiPicker into your Xcode project using CocoaPods, specify it in your Podfile:

pod 'MCEmojiPicker'

Swift Package Manager

The Swift Package Manager is a tool for managing the distribution of Swift code. It’s integrated with the Swift build system to automate the process of downloading, compiling, and linking dependencies.

To integrate MCEmojiPicker into your Xcode project using Xcode 11, specify it in Project > Swift Packages:

https://github.com/izyumkin/MCEmojiPicker

Manually

If you prefer not to use any of the aforementioned dependency managers, you can integrate MCEmojiPicker into your project manually. Put Source/MCEmojiPicker folder in your Xcode project. Make sure to enable Copy items if needed and Create groups.

Quick Start

Create UIButton and add selector as action:

@objc private func selectEmojiAction(_ sender: UIButton) {
    let viewController = MCEmojiPickerViewController()
    viewController.delegate = self
    viewController.sourceView = sender
    present(viewController, animated: true)
}

And then recieve emoji in the delegate method:

extension ViewController: MCEmojiPickerDelegate {
    func didGetEmoji(emoji: String) {
        emojiButton.setTitle(emoji, for: .normal)
    }
}

Usage

sourceView is the view containing the anchor rectangle for the popover. You can create any UIView instance and set it in this property.

Selected emoji category tint color

Color for the selected emoji category. The default value of this property is .systemBlue.

viewController.selectedEmojiCategoryTintColor = .systemRed

Arrow direction

The direction of the arrow for EmojiPicker. The default value of this property is .up.

viewController.arrowDirection = .up

Horizontal inset

Inset from the sourceView border. The default value of this property is 0.

viewController.horizontalInset = 0

Is dismiss after choosing

Defines whether to dismiss emoji picker or not after choosing. The default value of this property is true.

viewController.isDismissAfterChoosing = true

Custom height

Custom height for EmojiPicker. The default value of this property is nil.

viewController.customHeight = 300

Feedback generator style

Feedback generator style. To turn off, set nil to this parameter. The default value of this property is .light.

viewController.feedBackGeneratorStyle = .soft

SwiftUI

Use like system popover. All settings are available in the method initializer.

Button(selectedEmoji) {
    isPresented.toggle()
}.emojiPicker(
    isPresented: $isPresented,
    selectedEmoji: $selectedEmoji
)

or interact directly with the SwiftUI wrapper for the MCEmojiPickerViewController:

MCEmojiPickerRepresentableController(
    isPresented: $isPresented,
    selectedEmoji: $selectedEmoji,
    arrowDirection: .up,
    customHeight: 380.0,
    horizontalInset: .zero,
    isDismissAfterChoosing: true,
    selectedEmojiCategoryTintColor: .systemBlue,
    feedBackGeneratorStyle: .light
)

Localization

🌍 This library supports all existing localizations

TODO

  • The main functionality for choosing emojis
  • Dark mode
  • Segmented control for jumping an emoji section
  • Automatic adjustment of the relevant set of emoji for the iOS version
  • Select skin tones from popup
  • Frequently used
  • Search bar and search results

mcemojipicker's People

Contributors

chrszlz avatar darvelo avatar fosterbr5 avatar htmlprogrammist avatar izyumkin avatar jfpalacios avatar luobo25 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

mcemojipicker's Issues

Presentation bug

I have a SwiftUI application where I would let the users to select the data they want (alphanumeric, emoji or numeric). Now when the selected choice in the Picker is emoji, I will show MCEmojiPicker when the gray rectangles are tapped. This works as expected. Now when I changed the choice to either alphanumeric or numeric, the emoji picker is shown unexpectedly. Please see attached video:

Simulator.Screen.Recording.-.iPhone.15.Pro.Max.-.2024-03-25.at.17.00.44.mp4

Search

Please add search field to search emoji

Emoji misclicks

When scrolling the keyboard, it is quite common to select emoji although I didn't want it. I would like the emoji to be selected only when tapping on it. Any scroll should prevent selecting.

Overall this is a great framework, thanks!
P.S. Waiting for search πŸ™

`selectedEmojiCategoryTintColor` not working in SwiftUI

Thanks for this excellent library! πŸ™πŸ½ It's really impressive and saves a lot of time. πŸ™ŒπŸ½

I'm using it with SwiftUI. Unfortunately, the selectedEmojiCategoryTintColor property doesn't seem to work.

I used it as described in the documentation:

Button(selectedEmoji) {
    showEmojiSelector.toggle()
}.emojiPicker(
    isPresented: $showEmojiSelector,
    selectedEmoji: $selectedEmoji,
    selectedEmojiCategoryTintColor: .systemRed
)

But the selected category icon keeps its blue tint:

image

XCode: 14.3.1
iOS deployment target: 14.0
iOS simulator: iPhone 14 Pro, iOS 16.4

SkinTonePickerView

Hi! Thanks for creating this EmojiPicker!

I implemented it in my project. It works great, except for the SkinTonePickerView. See attached Screenshot. I checked the view hierarchy, i did see the view was added on top but it was just transparent. The pickerview is triggered from action in UIContextMenu and presented as a pageSheet. And I have the sourceView as pickerview like vc.sourceView = vc.view. Any idea what I missed?

Thanks a lot!

IMG_9498

Weird behaviour in ios 17

I have the emoji picker implemented in an ios 17 app and the emojipicker behaves weird. Sometimes it wont show up, sometimes it is just empty, sometimes it is placed random anywhere on the screen.
I can provide images later. But when you try you can see it yourself.

MCEmojiPickerRepresentableController dismisses other VCs

updateUIViewController may be called multiple times, and I find that this line is dismissing alerts that I've presented:

case false:
representableController.presentedViewController?.dismiss(animated: true)

It's reading the isPresented value and dismissing any VC on top, including alerts. When I change the line to:

        case false:
            if representableController.presentedViewController is MCEmojiPickerViewController {
                representableController.presentedViewController?.dismiss(animated: true)
            }

the bug disappears.

Custom dark mode

Hi, thanks for creating this!

It would be great if we could specify light/dark mode in addition to the current properties:

MCEmojiPickerRepresentableController(
    isPresented: $isPresented,
    selectedEmoji: $selectedEmoji,
    arrowDirection: .up,
    customHeight: 380.0,
    horizontalInset: .zero,
    isDismissAfterChoosing: true,
    selectedEmojiCategoryTintColor: .systemBlue,
    feedBackGeneratorStyle: .light
)

Memory leaks

Great library but the memory leaks makes it unusable with over 400MB memory usage sometimes that persist even after deallocating multiple parent VCs. I think displaying each emoji in a single UILabel might not be the best way to do it.

Main thread issues

Hey, I'm using the picker from a SwiftUI view with the .emojiPicker modifier And I'm often getting these warnings (and even sometimes crashes I believe - I don't have a consistent way of repro this though) in MCEmojiPickerRepresentableController:

Screenshot 2024-06-07 at 09 44 02

Log output:

Main Thread Checker: UI API called on a background thread: -[UIViewController presentedViewController]
PID: 34514, TID: 393139, Thread name: (none), Queue name: com.apple.root.user-initiated-qos.cooperative, QoS: 25
Backtrace:
4   TestApp                               0x000000010127f9fc $s13MCEmojiPicker0aB23RepresentableControllerV012updateUIViewD0_7contextySo0fD0C_7SwiftUI0fdC7ContextVyACGtF + 1756
5   TestApp                               0x000000010127fe50 $s13MCEmojiPicker0aB23RepresentableControllerV7SwiftUI06UIViewdC0AadEP06updategD0_7contexty0gD4TypeQz_AD0gdC7ContextVyxGtFTW + 60
6   SwiftUI                             0x00000001cce102a8 OUTLINED_FUNCTION_70 + 3324
7   SwiftUI                             0x00000001cd4f8254 OUTLINED_FUNCTION_73 + 15220
8   SwiftUI                             0x00000001cd4f818c OUTLINED_FUNCTION_73 + 15020
9   SwiftUI                             0x00000001cd4dac3c OUTLINED_FUNCTION_16 + 18920
10  SwiftUI                             0x00000001cd4f802c OUTLINED_FUNCTION_73 + 14668
11  SwiftUI                             0x00000001cd4f7e44 OUTLINED_FUNCTION_73 + 14180
12  SwiftUI                             0x00000001cd4f7084 OUTLINED_FUNCTION_73 + 10660
13  SwiftUI                             0x00000001cc2697f4 __swift_memcpy128_8 + 1020
14  AttributeGraph                      0x00000001b9d4f5c4 _ZN2AG5Graph11UpdateStack6updateEv + 504
15  AttributeGraph                      0x00000001b9d4fd54 _ZN2AG5Graph16update_attributeENS_4data3ptrINS_4NodeEEEj + 432
16  AttributeGraph                      0x00000001b9d5d8d0 _ZN2AG8Subgraph6updateEj + 828
17  SwiftUI                             0x00000001cd42b714 OUTLINED_FUNCTION_0 + 10564
18  SwiftUI                             0x00000001cd52e2f0 OUTLINED_FUNCTION_20 + 12920
19  SwiftUI                             0x00000001cc9bd640 OUTLINED_FUNCTION_76 + 964
20  libswiftObservation.dylib           0x000000020a7b8cc8 $s11Observation0A8TrackingV08_installB0_7willSet03didE0yAC_yACYbcSgAGtFZAC2IdOAC5EntryVXEfU_yyYbcfU2_TATm + 40
21  libswiftObservation.dylib           0x000000020a7b8d6c $sIegh_ytIeghr_TRTA + 20
22  libswiftObservation.dylib           0x000000020a7b7730 $s11Observation0A9RegistrarV7ContextV7willSet_7keyPathyx_s03KeyG0Cyxq_GtAA10ObservableRzr0_lFTf4dnn_n + 636
23  libswiftObservation.dylib           0x000000020a7b7c38 $s11Observation0A9RegistrarV7willSet_7keyPathyx_s03KeyF0Cyxq_GtAA10ObservableRzr0_lFTf4dnn_n + 56
24  libswiftObservation.dylib           0x000000020a7b274c $s11Observation0A9RegistrarV12withMutation2of7keyPath_q0_x_s03KeyG0Cyxq_Gq0_yKXEtKAA10ObservableRzr1_lF + 76
25  TestApp                               0x00000001017e70a8 $s8UserFeed0aB5ModelC12withMutation7keyPath_q_s03KeyG0CyACxG_q_yKXEtKr0_lF + 268
26  TestApp                               0x00000001017e2750 $s8UserFeed0aB5ModelC10activities18OrderedCollections0E10DictionaryVySS12CommonModels8ActivityVGvs + 200
27  TestApp                               0x00000001017e2964 $s8UserFeed0aB5ModelC10activities18OrderedCollections0E10DictionaryVySS12CommonModels8ActivityVGvM.resume.0 + 52
28  TestApp                               0x00000001017e6ce4 $s8UserFeed0aB5ModelC19loadActivityDetails3for12CommonModels0E0VSS_tYaKFTY2_ + 308
29  libswift_Concurrency.dylib          0x000000020a8b410c _ZN5swift34runJobInEstablishedExecutorContextEPNS_3JobE + 324
30  libswift_Concurrency.dylib          0x000000020a8b4fd4 _ZL17swift_job_runImplPN5swift3JobENS_11ExecutorRefE + 80
31  libdispatch.dylib                   0x000000010347536c _dispatch_root_queue_drain + 372
32  libdispatch.dylib                   0x0000000103475f18 _dispatch_worker_thread2 + 256
33  libsystem_pthread.dylib             0x00000001033937d8 _pthread_wqthread + 224
34  libsystem_pthread.dylib             0x00000001033925d4 start_wqthread + 8

Any idea where this could come from? Or what I could do to investigate this further?

Automatic arrow direction

There should be an automatic arrow direction option, because we might not know where the popover fits best.
If you try to display it too close to the edge of the screen the popover renders truncated:

image

visionOS support

Hi,

First of all, amazing package!

I've managed to make some clumsy changes so it can be used in visionOS, such as removing feedback generator, reseting UIScreen sizes, etc. However, it's not perfect, as you can see in the photo.

Could I have an updated version so that:

  1. It supports visionOS.
  2. Fully glass effect, as you can see, the banner is currently black.
  3. Adjustable emoji sizes. Currently the emojis are too small.
  4. When long tap, show skin tones. I know in iOS it's supported, but visionOS doesn't work.

Thank you so much!

Screenshot 2023-07-25 at 15 18 10

macOS Support

Currently using a different emoji picker for macOS, but would love to have this library have Mac Support.

Categories items multiply on colorScheme change in SwiftUI.

I noticed an unusual behavior where category items multiply when the colorScheme changes while the emojiPicker is open in SwiftUI using the .emojiPicker modifier. It appears that these categories multiply each time the colorScheme changes.
image

Minimal Reproducible Example:
XCode Version 14.2 (14C18), iOS 16.2

struct EmojiPickerTest: View {
    
    @State private var isEmojiPickerShown: Bool = false
    @State private var emoji: String = "πŸ˜€"
    
    var body: some View {
        Button(emoji, action: { isEmojiPickerShown = true })
            .emojiPicker(isPresented: $isEmojiPickerShown,
                         selectedEmoji: $emoji)
    }
}

struct EmojiPickerTest_Previews: PreviewProvider {
    static var previews: some View {
        EmojiPickerTest()
    }
}

There is a workaround for the problem: manually dismiss the emojiPicker when colorScheme is changed using the onChange() modifier like this:

        .onChange(of: colorScheme, perform: { _ in
            isEmojiPickerShown = false
        })

However, I believe the issue is still worth mentioning.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.