izyumkin / MCEmojiPicker

๐Ÿ‘ป EmojiPicker. Emoji picker for iOS like on macOS. With SwiftUI support.
MIT License
235 stars 27 forks source link

macOS Support #23

Open ygee07 opened 9 months ago

ygee07 commented 9 months ago

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

izyumkin commented 9 months ago

This is the second issue about macOS support I think I will add support after all.

If you can, please share the emoji picker you are using now. It would definitely make my work easier.

ygee07 commented 9 months ago

This is where I got it from https://github.com/Remotionco/Emoji-Library-and-Utilities

I just extracted the getAllEmojis() and its dependencies, then just quickly made my own, though not as elegant as your library.

struct MacEmojiPicker: View {
    @Binding var selection: String
    @State private var showPicker: Bool = false

    var body: some View {
        YVButtonIcon(selection, emoji: true) {
            showPicker.toggle()
        }
        .sheet(isPresented: $showPicker) {
            pickerView
                .padding()
        }
    }

    var pickerView: some View {
        ScrollView {
            let items = getAllEmojis()
            let columns: [GridItem] = Array(repeating: GridItem(.flexible(minimum: 50, maximum: 240), spacing: 10), count: 8)

            LazyVGrid(columns: columns, spacing: 10) {
                ForEach(0 ..< items.count, id: \.self) { index in
                    Text(items[index].emoji)
                        .font(.largeTitle)
                        .contentShape(.circle)
                        .onTapGesture {
                            selection = items[index].emoji
                            showPicker.toggle()
                        }
                }
            }
        }
        .scrollIndicators(.hidden)
    }

    func getAllEmojis() -> [Emoji] {
        let emojiData = (try? Data(contentsOf: Bundle.main.url(forResource: "Emoji Unicode 15.0", withExtension: "json")!))!
        let data = try! JSONDecoder().decode([Emoji].self, from: emojiData)
        return data

    }
}

public struct Emoji: Decodable, Equatable {
    public let emoji: String
    public let description: String
    public let category: EmojiCategory
    public let aliases: [String]
    public let tags: [String]
    public let supportsSkinTones: Bool
    public let iOSVersion: String

    /// Get a string representation of this emoji with another skin tone
    /// - Parameter withSkinTone: new skin tone to use
    /// - Returns: a string of the new emoji with the applied skin tone
//    public func emoji (_ withSkinTone: EmojiSkinTone?) -> String? {
//        // Applying skin tones with Dan Wood's code: https://github.com/Remotionco/Emoji-Library-and-Utilities
//        
//        if !supportsSkinTones { return nil }
//        // If skin tone is nil, return the default yellow emoji
//        guard let withSkinTone = withSkinTone else {
//            if let unicode = emoji.unicodeScalars.first { return String(unicode) }
//            else { return emoji }
//        }
//        
//        var wasToneInserted = false
//        guard let toneScalar = Unicode.Scalar(withSkinTone.rawValue) else { return nil }
//
//        var scalars = [UnicodeScalar]()
//        // Either replace first found Fully Qualified 0xFE0F, or add to the end or before the first ZWJ, 0x200D.
//        for scalar in emoji.unicodeScalars {
//            if !wasToneInserted {
//                switch scalar.value {
//                case 0xFE0F:
//                    scalars.append(toneScalar) // tone scalar goes in place of the FE0F.
//                    wasToneInserted = true
//                case 0x200D:
//                    scalars.append(toneScalar) // Insert the tone selector
//                    scalars.append(scalar) // and then the ZWJ afterwards.
//                    wasToneInserted = true
//                default:
//                    scalars.append(scalar)
//                }
//            } else { // already handled tone, just append the other selectors it finds.
//                scalars.append(scalar)
//            }
//        }
//
//        if !wasToneInserted {
//            scalars.append(toneScalar) // Append at the end if needed.
//        }
//        
//        var string = ""
//        scalars.forEach({ string.append($0.description) })
//        return string
//    }

    enum CodingKeys: CodingKey {
        case emoji
        case description
        case category
        case aliases
        case tags
        case skin_tones
        case ios_version
    }

    public init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        self.emoji = try container.decode(String.self, forKey: .emoji)
        self.description = try container.decode(String.self, forKey: .description)
        self.category = try container.decode(EmojiCategory.self, forKey: .category)
        self.aliases = try container.decode([String].self, forKey: .aliases)
        self.tags = try container.decode([String].self, forKey: .tags)
        self.supportsSkinTones = try container.decodeIfPresent(Bool.self, forKey: .skin_tones) ?? false
        self.iOSVersion = try container.decode(String.self, forKey: .ios_version)
    }

    /// Create an instance of an emoji
    /// - Parameters:
    ///    - emoji: string representation of this emoji
    ///    - description: unicode textual description
    ///    - category: unicode category of this emoji
    ///    - aliases: similar names for this emoji
    ///    - tags: this emojis tags used for search
    ///    - supportsSkinTones: weather this emoji supports skin tones
    ///    - iOSVersion: the earliest iOS which supports this emoji
    public init (emoji: String, description: String, category: EmojiCategory, aliases: [String], tags: [String], supportsSkinTones: Bool, iOSVersion: String) {
        self.emoji = emoji
        self.description = description
        self.category = category
        self.aliases = aliases
        self.tags = tags
        self.supportsSkinTones = supportsSkinTones
        self.iOSVersion = iOSVersion
    }
}

public enum EmojiSkinTone: String, CaseIterable {
    case Light = "๐Ÿป"
    case MediumLight = "๐Ÿผ"
    case Medium = "๐Ÿฝ"
    case MediumDark = "๐Ÿพ"
    case Dark = "๐Ÿฟ"
}

public enum EmojiCategory: String, CaseIterable, Decodable {
    case SmileysAndEmotion = "Smileys & Emotion"
    case PeopleAndBody = "People & Body"
    case AnimalsAndNature = "Animals & Nature"
    case FoodAndDrink = "Food & Drink"
    case TravelAndPlaces = "Travel & Places"
    case Activities = "Activities"
    case Objects = "Objects"
    case Symbols = "Symbols"
    case Flags = "Flags"
}
izyumkin commented 9 months ago

Thanks a lot! I'll add macOS support soon๐Ÿ™

naingminoo99 commented 9 months ago

Thank you I am also waiting for MacOS support

MagicFlow29 commented 2 months ago

Hey any updates on this? Happy to help

chansencc commented 2 months ago

Any update on this?