diff --git a/Resources/Plugins/emoji-keyboard/browser.js b/Resources/Plugins/emoji-keyboard/browser.js index 04b270a9..34112f21 100644 --- a/Resources/Plugins/emoji-keyboard/browser.js +++ b/Resources/Plugins/emoji-keyboard/browser.js @@ -1,14 +1,40 @@ -enabled(){ - this.emojiHTML = ""; +enabled(){ + this.selectedSkinTone = ""; + + this.skinToneList = [ + "", "1F3FB", "1F3FC", "1F3FD", "1F3FE", "1F3FF" + ]; + + this.skinToneNonDefaultList = [ + "1F3FB", "1F3FC", "1F3FD", "1F3FE", "1F3FF" + ]; + + this.skinToneData = [ + [ "", "#FFDD67" ], + [ "1F3FB", "#FFE1BD" ], + [ "1F3FC", "#FED0AC" ], + [ "1F3FD", "#D6A57C" ], + [ "1F3FE", "#B47D56" ], + [ "1F3FF", "#8A6859" ], + ]; + + this.emojiHTML1 = ""; // no skin tones, prepended + this.emojiHTML2 = {}; // contains emojis with skin tones + this.emojiHTML3 = ""; // no skin tones, appended var me = this; // styles this.css = window.TDPF_createCustomStyle(this); - this.css.insert(".emoji-keyboard { position: absolute; width: 15.35em; height: 11.2em; background-color: white; overflow-y: auto; padding: 0.1em; box-sizing: border-box; border-radius: 2px; font-size: 24px; z-index: 9999 }"); - this.css.insert(".emoji-keyboard .separator { height: 26px; }"); - this.css.insert(".emoji-keyboard .emoji { padding: 0.1em !important; cursor: pointer }"); + this.css.insert(".emoji-keyboard { position: absolute; width: 15.35em; background-color: white; border-radius: 2px 2px 3px 3px; font-size: 24px; z-index: 9999 }"); + this.css.insert(".emoji-keyboard-list { height: 10.14em; padding: 0.1em; box-sizing: border-box; overflow-y: auto }"); + this.css.insert(".emoji-keyboard-list .separator { height: 26px }"); + this.css.insert(".emoji-keyboard-list .emoji { padding: 0.1em !important; cursor: pointer }"); + this.css.insert(".emoji-keyboard-skintones { height: 1.3em; text-align: center; background-color: #292f33; border-radius: 0 0 2px 2px }"); + this.css.insert(".emoji-keyboard-skintones div { width: 0.8em; height: 0.8em; margin: 0.25em 0.1em; border-radius: 50%; display: inline-block; box-sizing: border-box; cursor: pointer }"); + this.css.insert(".emoji-keyboard-skintones .sel { border: 2px solid rgba(0, 0, 0, 0.35); box-shadow: 0 0 2px 0 rgba(255, 255, 255, 0.65), 0 0 1px 0 rgba(255, 255, 255, 0.4) inset }"); + this.css.insert(".emoji-keyboard-skintones :hover { border: 2px solid rgba(0, 0, 0, 0.25); box-shadow: 0 0 1px 0 rgba(255, 255, 255, 0.65), 0 0 1px 0 rgba(255, 255, 255, 0.25) inset }"); // layout @@ -34,16 +60,29 @@ enabled(){ $(".emoji-keyboard-popup-btn").removeClass("is-selected"); }; - this.generateKeyboardFor = (input, left, top) => { - var created = document.createElement("div"); - document.body.appendChild(created); + var generateEmojiHTML = skinTone => { + return this.emojiHTML1+this.emojiHTML2[skinTone]+this.emojiHTML3; + }; + + var selectSkinTone = skinTone => { + let selectedEle = this.currentKeyboard.children[1].querySelector("[data-tone='"+this.selectedSkinTone+"']"); + selectedEle && selectedEle.classList.remove("sel"); - created.classList.add("emoji-keyboard"); - created.style.left = left+"px"; - created.style.top = top+"px"; - created.innerHTML = this.emojiHTML; + this.selectedSkinTone = skinTone; + this.currentKeyboard.children[0].innerHTML = generateEmojiHTML(skinTone); + this.currentKeyboard.children[1].querySelector("[data-tone='"+this.selectedSkinTone+"']").classList.add("sel"); + }; + + this.generateKeyboard = (input, left, top) => { + var outer = document.createElement("div"); + outer.classList.add("emoji-keyboard"); + outer.style.left = left+"px"; + outer.style.top = top+"px"; - created.addEventListener("click", function(e){ + var keyboard = document.createElement("div"); + keyboard.classList.add("emoji-keyboard-list"); + + keyboard.addEventListener("click", function(e){ if (e.target.tagName === "IMG"){ input.val(input.val()+e.target.getAttribute("alt")); input.trigger("change"); @@ -53,7 +92,24 @@ enabled(){ e.stopPropagation(); }); - return created; + var skintones = document.createElement("div"); + skintones.innerHTML = me.skinToneData.map(entry => "<div data-tone='"+entry[0]+"' style='background-color:"+entry[1]+"'></div>").join(""); + skintones.classList.add("emoji-keyboard-skintones"); + + skintones.addEventListener("click", function(e){ + if (e.target.hasAttribute("data-tone")){ + selectSkinTone(e.target.getAttribute("data-tone") || ""); + } + + e.stopPropagation(); + }); + + outer.appendChild(keyboard); + outer.appendChild(skintones); + document.body.appendChild(outer); + + this.currentKeyboard = outer; + selectSkinTone(this.selectedSkinTone); }; this.prevTryPasteImage = window.TDGF_tryPasteImage; @@ -75,7 +131,7 @@ enabled(){ } else{ var pos = $(this).offset(); - me.currentKeyboard = me.generateKeyboardFor($(".js-compose-text").first(), pos.left, pos.top+$(this).outerHeight()+8); + me.generateKeyboard($(".js-compose-text").first(), pos.left, pos.top+$(this).outerHeight()+8); $(this).addClass("is-selected"); } @@ -123,38 +179,93 @@ ready(){ }; $TDP.readFileRoot(this.$token, "emoji-ordering.txt").then(contents => { - let generated = []; + let generated1 = []; + let generated2 = {}; + let generated3 = []; - let addDeclaration = decl => { - generated.push(decl.split(" ").map(pt => convUnicode(parseInt(pt, 16))).join("")); + for(let skinTone of this.skinToneList){ + generated2[skinTone] = []; + } + + // declaration inserters + + let addDeclaration1 = decl => { + generated1.push(decl.split(" ").map(pt => convUnicode(parseInt(pt, 16))).join("")); }; - let skinTones = [ - "1F3FB", "1F3FC", "1F3FD", "1F3FE", "1F3FF" - ]; + let addDeclaration2 = (tone, decl) => { + let gen = decl.split(" ").map(pt => convUnicode(parseInt(pt, 16))).join(""); + + if (tone === null){ + for(let skinTone of this.skinToneList){ + generated2[skinTone].push(gen); + } + } + else{ + generated2[tone].push(gen); + } + }; + + let addDeclaration3 = decl => { + generated3.push(decl.split(" ").map(pt => convUnicode(parseInt(pt, 16))).join("")); + }; + + // line reading + + let skinToneState = 0; for(let line of contents.split("\n")){ if (line[0] === '@'){ - generated.push("___"); + switch(skinToneState){ + case 0: generated1.push("___"); break; + case 1: this.skinToneList.forEach(skinTone => generated2[skinTone].push("___")); break; + case 2: generated3.push("___"); break; + } + + if (line[1] === '1'){ + skinToneState = 1; + } + else if (line[1] === '2'){ + skinToneState = 2; + } } - else{ - let decl = line.slice(0, line.indexOf(";")); + else if (skinToneState === 1){ + let decl = line.slice(0, line.indexOf(';')); let skinIndex = decl.indexOf('$'); if (skinIndex !== -1){ let declPre = decl.slice(0, skinIndex); let declPost = decl.slice(skinIndex+1); - - skinTones.map(skinTone => declPre+skinTone+declPost).forEach(addDeclaration); + + for(let skinTone of this.skinToneNonDefaultList){ + generated2[skinTone].pop(); + addDeclaration2(skinTone, declPre+skinTone+declPost); + } } else{ - addDeclaration(decl); + addDeclaration2(null, decl); } } + else if (skinToneState === 2){ + addDeclaration3(line.slice(0, line.indexOf(';'))); + } + else if (skinToneState === 0){ + addDeclaration1(line.slice(0, line.indexOf(';'))); + } } + // final processing + + let replaceSeparators = str => str.replace(/___/g, "<div class='separator'></div>"); + let start = "<p style='font-size:13px;color:#444;margin:4px;text-align:center'>Please, note that most emoji will not show up properly in the text box above, but they will display in the tweet.</p>"; - this.emojiHTML = start+TD.util.cleanWithEmoji(generated.join("")).replace(/___/g, "<div class='separator'></div>"); + this.emojiHTML1 = start+replaceSeparators(TD.util.cleanWithEmoji(generated1.join(""))); + + for(let skinTone of this.skinToneList){ + this.emojiHTML2[skinTone] = replaceSeparators(TD.util.cleanWithEmoji(generated2[skinTone].join(""))); + } + + this.emojiHTML3 = replaceSeparators(TD.util.cleanWithEmoji(generated3.join(""))); }).catch(err => { $TD.alert("error", "Problem loading emoji keyboard: "+err.message); }); diff --git a/Resources/Plugins/emoji-keyboard/emoji-ordering.txt b/Resources/Plugins/emoji-keyboard/emoji-ordering.txt index 8da966aa..f9891e78 100644 --- a/Resources/Plugins/emoji-keyboard/emoji-ordering.txt +++ b/Resources/Plugins/emoji-keyboard/emoji-ordering.txt @@ -96,7 +96,7 @@ 1F648; ๐ see-no-evil monkey 1F649; ๐ hear-no-evil monkey 1F64A; ๐ speak-no-evil monkey -@ +@1 enable skin tones 1F466; ๐ฆ boy 1F466 $; ๐ฆ๐ป boy 1F467; ๐ง girl @@ -402,6 +402,10 @@ 1F939 $ 200D 2642 FE0F; ๐คน๐ปโโ๏ธ man juggling 1F939 200D 2640 FE0F; ๐คนโโ๏ธ woman juggling 1F939 $ 200D 2640 FE0F; ๐คน๐ปโโ๏ธ woman juggling +1F6CC; ๐ person in bed !! moved +1F6CC $; ๐๐ป person in beh !! moved +1F6C0; ๐ person taking bath !! moved +1F6C0 $; ๐๐ป person taking bath !! moved 1F46B; ๐ซ man and woman holding hands 1F46C; ๐ฌ two men holding hands 1F46D; ๐ญ two women holding hands @@ -439,7 +443,7 @@ 1F469 200D 1F467; ๐ฉโ๐ง family 1F469 200D 1F467 200D 1F466; ๐ฉโ๐งโ๐ฆ family 1F469 200D 1F467 200D 1F467; ๐ฉโ๐งโ๐ง family -@ !! removed skin tone modifiers +@ 1F4AA; ๐ช flexed biceps 1F4AA $; ๐ช๐ป flexed biceps 1F933; ๐คณ selfie @@ -505,7 +509,6 @@ 1F443; ๐ nose 1F443 $; ๐๐ป nose 1F91D; ๐ค handshake !! moved -@ 1F463; ๐ฃ footprints 1F440; ๐ eyes 1F441; ๐ eye @@ -570,7 +573,7 @@ 1F484; ๐ lipstick 1F48D; ๐ ring 1F48E; ๐ gem stone -@ +@2 no more skin tones beyond this point 1F435; ๐ต monkey face 1F412; ๐ monkey 1F98D; ๐ฆ gorilla @@ -895,14 +898,10 @@ 1F6F0; ๐ฐ satellite 1F6CE; ๐ bellhop bell 1F6AA; ๐ช door -1F6CC; ๐ person in bed -1F6CC $; ๐๐ป person in bed 1F6CF; ๐ bed 1F6CB; ๐ couch and lamp 1F6BD; ๐ฝ toilet 1F6BF; ๐ฟ shower -1F6C0; ๐ person taking bath -1F6C0 $; ๐๐ป person taking bath 1F6C1; ๐ bathtub @ 231B; โ hourglass