feat: add full emoji picker using emoji-mart (#836)
* feat: add full emoji picker using emoji-mart Fixes #4 * use a sailboat as the default emoji in the emoji picker * fix tests * fix lint
This commit is contained in:
parent
943a1ed5e6
commit
098a20db49
|
@ -4,9 +4,11 @@ import sass from 'node-sass'
|
||||||
import path from 'path'
|
import path from 'path'
|
||||||
import fs from 'fs'
|
import fs from 'fs'
|
||||||
import pify from 'pify'
|
import pify from 'pify'
|
||||||
|
import CleanCSS from 'clean-css'
|
||||||
|
|
||||||
const writeFile = pify(fs.writeFile.bind(fs))
|
const writeFile = pify(fs.writeFile.bind(fs))
|
||||||
const readdir = pify(fs.readdir.bind(fs))
|
const readdir = pify(fs.readdir.bind(fs))
|
||||||
|
const readFile = pify(fs.readFile.bind(fs))
|
||||||
const render = pify(sass.render.bind(sass))
|
const render = pify(sass.render.bind(sass))
|
||||||
|
|
||||||
const globalScss = path.join(__dirname, '../scss/global.scss')
|
const globalScss = path.join(__dirname, '../scss/global.scss')
|
||||||
|
@ -39,7 +41,13 @@ async function compileThemesSass () {
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function compileThirdPartyCss () {
|
||||||
|
let css = await readFile(path.resolve(__dirname, '../node_modules/emoji-mart/css/emoji-mart.css'), 'utf8')
|
||||||
|
css = `/* compiled from emoji-mart.css */` + new CleanCSS().minify(css).styles
|
||||||
|
await writeFile(path.resolve(__dirname, '../static/emoji-mart.css'), css, 'utf8')
|
||||||
|
}
|
||||||
|
|
||||||
export async function buildSass () {
|
export async function buildSass () {
|
||||||
let [ result ] = await Promise.all([compileGlobalSass(), compileThemesSass()])
|
let [ result ] = await Promise.all([compileGlobalSass(), compileThemesSass(), compileThirdPartyCss()])
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
202
package-lock.json
generated
202
package-lock.json
generated
|
@ -1272,6 +1272,23 @@
|
||||||
"babel-types": "^6.24.1"
|
"babel-types": "^6.24.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"babel-polyfill": {
|
||||||
|
"version": "6.23.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/babel-polyfill/-/babel-polyfill-6.23.0.tgz",
|
||||||
|
"integrity": "sha1-g2TKYt+Or7gwSZ9pkXdGbDsDSZ0=",
|
||||||
|
"requires": {
|
||||||
|
"babel-runtime": "^6.22.0",
|
||||||
|
"core-js": "^2.4.0",
|
||||||
|
"regenerator-runtime": "^0.10.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"regenerator-runtime": {
|
||||||
|
"version": "0.10.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz",
|
||||||
|
"integrity": "sha1-M2w+/BIgrc7dosn6tntaeVWjNlg="
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"babel-preset-env": {
|
"babel-preset-env": {
|
||||||
"version": "1.7.0",
|
"version": "1.7.0",
|
||||||
"resolved": "https://registry.npmjs.org/babel-preset-env/-/babel-preset-env-1.7.0.tgz",
|
"resolved": "https://registry.npmjs.org/babel-preset-env/-/babel-preset-env-1.7.0.tgz",
|
||||||
|
@ -1386,7 +1403,6 @@
|
||||||
"version": "6.26.0",
|
"version": "6.26.0",
|
||||||
"resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz",
|
"resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz",
|
||||||
"integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=",
|
"integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=",
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"core-js": "^2.4.0",
|
"core-js": "^2.4.0",
|
||||||
"regenerator-runtime": "^0.11.0"
|
"regenerator-runtime": "^0.11.0"
|
||||||
|
@ -1953,8 +1969,7 @@
|
||||||
"chardet": {
|
"chardet": {
|
||||||
"version": "0.4.2",
|
"version": "0.4.2",
|
||||||
"resolved": "https://registry.npmjs.org/chardet/-/chardet-0.4.2.tgz",
|
"resolved": "https://registry.npmjs.org/chardet/-/chardet-0.4.2.tgz",
|
||||||
"integrity": "sha1-tUc7M9yXxCTl2Y3IfVXU2KKci/I=",
|
"integrity": "sha1-tUc7M9yXxCTl2Y3IfVXU2KKci/I="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"check-error": {
|
"check-error": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
|
@ -2061,14 +2076,12 @@
|
||||||
"balanced-match": {
|
"balanced-match": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
|
||||||
"integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
|
"integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c="
|
||||||
"optional": true
|
|
||||||
},
|
},
|
||||||
"brace-expansion": {
|
"brace-expansion": {
|
||||||
"version": "1.1.11",
|
"version": "1.1.11",
|
||||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
||||||
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
|
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
|
||||||
"optional": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"balanced-match": "^1.0.0",
|
"balanced-match": "^1.0.0",
|
||||||
"concat-map": "0.0.1"
|
"concat-map": "0.0.1"
|
||||||
|
@ -2088,8 +2101,7 @@
|
||||||
"concat-map": {
|
"concat-map": {
|
||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
|
||||||
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
|
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
|
||||||
"optional": true
|
|
||||||
},
|
},
|
||||||
"console-control-strings": {
|
"console-control-strings": {
|
||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
|
@ -2237,7 +2249,6 @@
|
||||||
"version": "3.0.4",
|
"version": "3.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
|
||||||
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
|
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
|
||||||
"optional": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"brace-expansion": "^1.1.7"
|
"brace-expansion": "^1.1.7"
|
||||||
}
|
}
|
||||||
|
@ -2680,7 +2691,6 @@
|
||||||
"version": "2.1.0",
|
"version": "2.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz",
|
||||||
"integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=",
|
"integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=",
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"restore-cursor": "^2.0.0"
|
"restore-cursor": "^2.0.0"
|
||||||
}
|
}
|
||||||
|
@ -2688,8 +2698,7 @@
|
||||||
"cli-width": {
|
"cli-width": {
|
||||||
"version": "2.2.0",
|
"version": "2.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz",
|
||||||
"integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=",
|
"integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"cliui": {
|
"cliui": {
|
||||||
"version": "3.2.0",
|
"version": "3.2.0",
|
||||||
|
@ -2920,8 +2929,7 @@
|
||||||
"core-js": {
|
"core-js": {
|
||||||
"version": "2.5.7",
|
"version": "2.5.7",
|
||||||
"resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.7.tgz",
|
"resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.7.tgz",
|
||||||
"integrity": "sha512-RszJCAxg/PP6uzXVXL6BsxSXx/B05oJAQ2vkJRjyjrEcNVycaqOmNb5OTxZPE3xa5gwZduqza6L9JOCenh/Ecw==",
|
"integrity": "sha512-RszJCAxg/PP6uzXVXL6BsxSXx/B05oJAQ2vkJRjyjrEcNVycaqOmNb5OTxZPE3xa5gwZduqza6L9JOCenh/Ecw=="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"core-util-is": {
|
"core-util-is": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
|
@ -3513,6 +3521,11 @@
|
||||||
"minimalistic-crypto-utils": "^1.0.0"
|
"minimalistic-crypto-utils": "^1.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"emoji-mart": {
|
||||||
|
"version": "2.9.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/emoji-mart/-/emoji-mart-2.9.2.tgz",
|
||||||
|
"integrity": "sha512-5S743OpjFb9nBbbx5F4APWgcp2IOjdT7gLLzu2OBh0k44C3ZoCm+wuIN1llOtj5eosUa3lYqrZWtU/ZiaCULrg=="
|
||||||
|
},
|
||||||
"emoji-regex": {
|
"emoji-regex": {
|
||||||
"version": "7.0.1",
|
"version": "7.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.1.tgz",
|
||||||
|
@ -4354,7 +4367,6 @@
|
||||||
"version": "2.2.0",
|
"version": "2.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.2.0.tgz",
|
||||||
"integrity": "sha512-bSn6gvGxKt+b7+6TKEv1ZycHleA7aHhRHyAqJyp5pbUFuYYNIzpZnQDk7AsYckyWdEnTeAnay0aCy2aV6iTk9A==",
|
"integrity": "sha512-bSn6gvGxKt+b7+6TKEv1ZycHleA7aHhRHyAqJyp5pbUFuYYNIzpZnQDk7AsYckyWdEnTeAnay0aCy2aV6iTk9A==",
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"chardet": "^0.4.0",
|
"chardet": "^0.4.0",
|
||||||
"iconv-lite": "^0.4.17",
|
"iconv-lite": "^0.4.17",
|
||||||
|
@ -4365,7 +4377,6 @@
|
||||||
"version": "0.0.33",
|
"version": "0.0.33",
|
||||||
"resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz",
|
"resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz",
|
||||||
"integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==",
|
"integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==",
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"os-tmpdir": "~1.0.2"
|
"os-tmpdir": "~1.0.2"
|
||||||
}
|
}
|
||||||
|
@ -4476,7 +4487,6 @@
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz",
|
||||||
"integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=",
|
"integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=",
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"escape-string-regexp": "^1.0.5"
|
"escape-string-regexp": "^1.0.5"
|
||||||
}
|
}
|
||||||
|
@ -5380,6 +5390,70 @@
|
||||||
"resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz",
|
||||||
"integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10="
|
"integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10="
|
||||||
},
|
},
|
||||||
|
"inferno": {
|
||||||
|
"version": "7.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/inferno/-/inferno-7.0.4.tgz",
|
||||||
|
"integrity": "sha512-R5lk2e7F1Jy1l9+rwz/onTyx7kqb1aikbfnMwJ1GKoKX+DJu5skha1AQvI4ran6HueXFtfoNWpylgSVx0qd9pA==",
|
||||||
|
"requires": {
|
||||||
|
"inferno-shared": "7.0.4",
|
||||||
|
"inferno-vnode-flags": "7.0.4",
|
||||||
|
"opencollective": "^1.0.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"inferno-clone-vnode": {
|
||||||
|
"version": "7.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/inferno-clone-vnode/-/inferno-clone-vnode-7.0.4.tgz",
|
||||||
|
"integrity": "sha512-Pa2TUZwHT0i28mi+blp9d/z/PAXBv9EWKjbKAcmb8wpVl/fDlk03NP0VIVRgXZvLUo973Rq90g1IQtthJCu0MA==",
|
||||||
|
"requires": {
|
||||||
|
"inferno": "7.0.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"inferno-compat": {
|
||||||
|
"version": "7.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/inferno-compat/-/inferno-compat-7.0.4.tgz",
|
||||||
|
"integrity": "sha512-SCE23uS2oryFC4cck1gR9iBN7a8quo9DwtCJ1U8fka61OC92qPOrVjteOBtYJERZr+cJlBw9vK+7uwQ6t1G8Zw==",
|
||||||
|
"requires": {
|
||||||
|
"inferno": "7.0.4",
|
||||||
|
"inferno-clone-vnode": "7.0.4",
|
||||||
|
"inferno-create-class": "7.0.4",
|
||||||
|
"inferno-create-element": "7.0.4",
|
||||||
|
"inferno-extras": "7.0.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"inferno-create-class": {
|
||||||
|
"version": "7.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/inferno-create-class/-/inferno-create-class-7.0.4.tgz",
|
||||||
|
"integrity": "sha512-l4zilxP724wwy3/2M+LlcOw2FMT7UBdAF3NXwuS39+O9xguDY6pw8EuBmBOCLc/C0felG9HOTltRQwvCFF41wA==",
|
||||||
|
"requires": {
|
||||||
|
"inferno": "7.0.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"inferno-create-element": {
|
||||||
|
"version": "7.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/inferno-create-element/-/inferno-create-element-7.0.4.tgz",
|
||||||
|
"integrity": "sha512-pT1oZOiMXVV8yZB7TQUojRulr6DW24cb9YfDZBzL1GtIMtfQkzPAYh6/IgCh6V/7acS9OHn6XOF3UK0uXyfoCA==",
|
||||||
|
"requires": {
|
||||||
|
"inferno": "7.0.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"inferno-extras": {
|
||||||
|
"version": "7.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/inferno-extras/-/inferno-extras-7.0.4.tgz",
|
||||||
|
"integrity": "sha512-R+AtXDzXTb6hGncajE17c/FBX6lT+1RJu7pEfQw9borZH4NTATHAsvgZwJJsDcfMXe6WbDoq/ioLBFZgM363Og==",
|
||||||
|
"requires": {
|
||||||
|
"inferno": "7.0.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"inferno-shared": {
|
||||||
|
"version": "7.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/inferno-shared/-/inferno-shared-7.0.4.tgz",
|
||||||
|
"integrity": "sha512-SlYO5BWsnC2S3osG5goOxxI9Hm4E7OUo3Nq976lNMaU3fWdRNeeJipTvp2s61hQznAq6r+/GY0qwrgQcC97S2Q=="
|
||||||
|
},
|
||||||
|
"inferno-vnode-flags": {
|
||||||
|
"version": "7.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/inferno-vnode-flags/-/inferno-vnode-flags-7.0.4.tgz",
|
||||||
|
"integrity": "sha512-zGGBX6a05xqle3w2dcpkyEFGu/axQfsqTsp8icX1myxhW0DFs2LikVnBtskuIegThI9mDLwvBtsf4WubDo1i1A=="
|
||||||
|
},
|
||||||
"inflight": {
|
"inflight": {
|
||||||
"version": "1.0.6",
|
"version": "1.0.6",
|
||||||
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
|
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
|
||||||
|
@ -5690,8 +5764,7 @@
|
||||||
"is-promise": {
|
"is-promise": {
|
||||||
"version": "2.1.0",
|
"version": "2.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz",
|
||||||
"integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=",
|
"integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"is-regex": {
|
"is-regex": {
|
||||||
"version": "1.0.4",
|
"version": "1.0.4",
|
||||||
|
@ -5710,8 +5783,7 @@
|
||||||
"is-stream": {
|
"is-stream": {
|
||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz",
|
||||||
"integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=",
|
"integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"is-symbol": {
|
"is-symbol": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
|
@ -6212,8 +6284,7 @@
|
||||||
"mimic-fn": {
|
"mimic-fn": {
|
||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.1.0.tgz",
|
||||||
"integrity": "sha1-5md4PZLonb00KBi1IwudYqZyrRg=",
|
"integrity": "sha1-5md4PZLonb00KBi1IwudYqZyrRg="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"minimalistic-assert": {
|
"minimalistic-assert": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
|
@ -6357,8 +6428,7 @@
|
||||||
"mute-stream": {
|
"mute-stream": {
|
||||||
"version": "0.0.7",
|
"version": "0.0.7",
|
||||||
"resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz",
|
"resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz",
|
||||||
"integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=",
|
"integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"nan": {
|
"nan": {
|
||||||
"version": "2.11.1",
|
"version": "2.11.1",
|
||||||
|
@ -6748,16 +6818,78 @@
|
||||||
"version": "2.0.1",
|
"version": "2.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz",
|
||||||
"integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=",
|
"integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=",
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"mimic-fn": "^1.0.0"
|
"mimic-fn": "^1.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"opencollective": {
|
||||||
|
"version": "1.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/opencollective/-/opencollective-1.0.3.tgz",
|
||||||
|
"integrity": "sha1-ruY3K8KBRFg2kMPKja7PwSDdDvE=",
|
||||||
|
"requires": {
|
||||||
|
"babel-polyfill": "6.23.0",
|
||||||
|
"chalk": "1.1.3",
|
||||||
|
"inquirer": "3.0.6",
|
||||||
|
"minimist": "1.2.0",
|
||||||
|
"node-fetch": "1.6.3",
|
||||||
|
"opn": "4.0.2"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"ansi-escapes": {
|
||||||
|
"version": "1.4.0",
|
||||||
|
"resolved": "http://registry.npmjs.org/ansi-escapes/-/ansi-escapes-1.4.0.tgz",
|
||||||
|
"integrity": "sha1-06ioOzGapneTZisT52HHkRQiMG4="
|
||||||
|
},
|
||||||
|
"inquirer": {
|
||||||
|
"version": "3.0.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/inquirer/-/inquirer-3.0.6.tgz",
|
||||||
|
"integrity": "sha1-4EqqnQW3o8ubD0B9BDdfBEcZA0c=",
|
||||||
|
"requires": {
|
||||||
|
"ansi-escapes": "^1.1.0",
|
||||||
|
"chalk": "^1.0.0",
|
||||||
|
"cli-cursor": "^2.1.0",
|
||||||
|
"cli-width": "^2.0.0",
|
||||||
|
"external-editor": "^2.0.1",
|
||||||
|
"figures": "^2.0.0",
|
||||||
|
"lodash": "^4.3.0",
|
||||||
|
"mute-stream": "0.0.7",
|
||||||
|
"run-async": "^2.2.0",
|
||||||
|
"rx": "^4.1.0",
|
||||||
|
"string-width": "^2.0.0",
|
||||||
|
"strip-ansi": "^3.0.0",
|
||||||
|
"through": "^2.3.6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"minimist": {
|
||||||
|
"version": "1.2.0",
|
||||||
|
"resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
|
||||||
|
"integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ="
|
||||||
|
},
|
||||||
|
"node-fetch": {
|
||||||
|
"version": "1.6.3",
|
||||||
|
"resolved": "http://registry.npmjs.org/node-fetch/-/node-fetch-1.6.3.tgz",
|
||||||
|
"integrity": "sha1-3CNO3WSJmC1Y6PDbT2lQKavNjAQ=",
|
||||||
|
"requires": {
|
||||||
|
"encoding": "^0.1.11",
|
||||||
|
"is-stream": "^1.0.1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"opener": {
|
"opener": {
|
||||||
"version": "1.5.1",
|
"version": "1.5.1",
|
||||||
"resolved": "https://registry.npmjs.org/opener/-/opener-1.5.1.tgz",
|
"resolved": "https://registry.npmjs.org/opener/-/opener-1.5.1.tgz",
|
||||||
"integrity": "sha512-goYSy5c2UXE4Ra1xixabeVh1guIX/ZV/YokJksb6q2lubWu6UbvPQ20p542/sFIll1nl8JnCyK9oBaOcCWXwvA=="
|
"integrity": "sha512-goYSy5c2UXE4Ra1xixabeVh1guIX/ZV/YokJksb6q2lubWu6UbvPQ20p542/sFIll1nl8JnCyK9oBaOcCWXwvA=="
|
||||||
},
|
},
|
||||||
|
"opn": {
|
||||||
|
"version": "4.0.2",
|
||||||
|
"resolved": "http://registry.npmjs.org/opn/-/opn-4.0.2.tgz",
|
||||||
|
"integrity": "sha1-erwi5kTf9jsKltWrfyeQwPAavJU=",
|
||||||
|
"requires": {
|
||||||
|
"object-assign": "^4.0.1",
|
||||||
|
"pinkie-promise": "^2.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"optionator": {
|
"optionator": {
|
||||||
"version": "0.8.2",
|
"version": "0.8.2",
|
||||||
"resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz",
|
"resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz",
|
||||||
|
@ -7615,8 +7747,7 @@
|
||||||
"regenerator-runtime": {
|
"regenerator-runtime": {
|
||||||
"version": "0.11.1",
|
"version": "0.11.1",
|
||||||
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz",
|
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz",
|
||||||
"integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==",
|
"integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg=="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"regenerator-transform": {
|
"regenerator-transform": {
|
||||||
"version": "0.10.1",
|
"version": "0.10.1",
|
||||||
|
@ -7685,6 +7816,11 @@
|
||||||
"resolved": "https://registry.npmjs.org/remedial/-/remedial-1.0.7.tgz",
|
"resolved": "https://registry.npmjs.org/remedial/-/remedial-1.0.7.tgz",
|
||||||
"integrity": "sha1-1mdEE6ZWdgB74A3UAJgJh7LDAME="
|
"integrity": "sha1-1mdEE6ZWdgB74A3UAJgJh7LDAME="
|
||||||
},
|
},
|
||||||
|
"remount": {
|
||||||
|
"version": "0.9.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/remount/-/remount-0.9.3.tgz",
|
||||||
|
"integrity": "sha512-U/a16ZqFadWSbjfr6k8ahEMEjFmJ3EceDFjgsbagE4tzwvcz0NQtgIKeVC4R/hF8mKhRdTyqpeFJIxQzhiP/Gw=="
|
||||||
|
},
|
||||||
"remove-trailing-separator": {
|
"remove-trailing-separator": {
|
||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz",
|
||||||
|
@ -7837,7 +7973,6 @@
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz",
|
||||||
"integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=",
|
"integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=",
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"onetime": "^2.0.0",
|
"onetime": "^2.0.0",
|
||||||
"signal-exit": "^3.0.2"
|
"signal-exit": "^3.0.2"
|
||||||
|
@ -7982,7 +8117,6 @@
|
||||||
"version": "2.3.0",
|
"version": "2.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz",
|
||||||
"integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=",
|
"integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=",
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"is-promise": "^2.1.0"
|
"is-promise": "^2.1.0"
|
||||||
}
|
}
|
||||||
|
@ -8001,6 +8135,11 @@
|
||||||
"aproba": "^1.1.1"
|
"aproba": "^1.1.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"rx": {
|
||||||
|
"version": "4.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/rx/-/rx-4.1.0.tgz",
|
||||||
|
"integrity": "sha1-pfE/957zt0D+MKqAP7CfmIBdR4I="
|
||||||
|
},
|
||||||
"rxjs": {
|
"rxjs": {
|
||||||
"version": "5.5.12",
|
"version": "5.5.12",
|
||||||
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-5.5.12.tgz",
|
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-5.5.12.tgz",
|
||||||
|
@ -9522,8 +9661,7 @@
|
||||||
"through": {
|
"through": {
|
||||||
"version": "2.3.8",
|
"version": "2.3.8",
|
||||||
"resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
|
"resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
|
||||||
"integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=",
|
"integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"through2": {
|
"through2": {
|
||||||
"version": "2.0.3",
|
"version": "2.0.3",
|
||||||
|
|
|
@ -46,9 +46,11 @@
|
||||||
"child-process-promise": "^2.2.1",
|
"child-process-promise": "^2.2.1",
|
||||||
"chokidar": "^2.0.4",
|
"chokidar": "^2.0.4",
|
||||||
"circular-dependency-plugin": "^5.0.2",
|
"circular-dependency-plugin": "^5.0.2",
|
||||||
|
"clean-css": "^4.2.1",
|
||||||
"compression": "^1.7.3",
|
"compression": "^1.7.3",
|
||||||
"cross-env": "^5.2.0",
|
"cross-env": "^5.2.0",
|
||||||
"css-loader": "^2.0.1",
|
"css-loader": "^2.0.1",
|
||||||
|
"emoji-mart": "^2.9.2",
|
||||||
"emoji-regex": "^7.0.1",
|
"emoji-regex": "^7.0.1",
|
||||||
"encoding": "^0.1.12",
|
"encoding": "^0.1.12",
|
||||||
"escape-html": "^1.0.3",
|
"escape-html": "^1.0.3",
|
||||||
|
@ -62,6 +64,7 @@
|
||||||
"helmet": "^3.15.0",
|
"helmet": "^3.15.0",
|
||||||
"idb-keyval": "^3.1.0",
|
"idb-keyval": "^3.1.0",
|
||||||
"indexeddb-getall-shim": "^1.3.5",
|
"indexeddb-getall-shim": "^1.3.5",
|
||||||
|
"inferno-compat": "^7.0.4",
|
||||||
"intersection-observer": "^0.5.1",
|
"intersection-observer": "^0.5.1",
|
||||||
"localstorage-memory": "^1.0.3",
|
"localstorage-memory": "^1.0.3",
|
||||||
"lodash-es": "^4.17.11",
|
"lodash-es": "^4.17.11",
|
||||||
|
@ -75,6 +78,7 @@
|
||||||
"performance-now": "^2.1.0",
|
"performance-now": "^2.1.0",
|
||||||
"pify": "^4.0.1",
|
"pify": "^4.0.1",
|
||||||
"quick-lru": "^2.0.0",
|
"quick-lru": "^2.0.0",
|
||||||
|
"remount": "^0.9.3",
|
||||||
"requestidlecallback": "^0.3.0",
|
"requestidlecallback": "^0.3.0",
|
||||||
"rollup": "^0.68.0",
|
"rollup": "^0.68.0",
|
||||||
"rollup-plugin-replace": "^2.1.0",
|
"rollup-plugin-replace": "^2.1.0",
|
||||||
|
@ -137,7 +141,8 @@
|
||||||
"NotificationEvent",
|
"NotificationEvent",
|
||||||
"NodeList",
|
"NodeList",
|
||||||
"DOMParser",
|
"DOMParser",
|
||||||
"CSS"
|
"CSS",
|
||||||
|
"customElements"
|
||||||
],
|
],
|
||||||
"ignore": [
|
"ignore": [
|
||||||
"dist",
|
"dist",
|
||||||
|
|
|
@ -17,11 +17,12 @@ export async function updateCustomEmojiForInstance (instanceName) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function insertEmoji (realm, emoji) {
|
export function insertEmoji (realm, emoji) {
|
||||||
|
let emojiText = emoji.custom ? emoji.colons : emoji.native
|
||||||
let { composeSelectionStart } = store.get()
|
let { composeSelectionStart } = store.get()
|
||||||
let idx = composeSelectionStart || 0
|
let idx = composeSelectionStart || 0
|
||||||
let oldText = store.getComposeData(realm, 'text') || ''
|
let oldText = store.getComposeData(realm, 'text') || ''
|
||||||
let pre = oldText.substring(0, idx)
|
let pre = oldText.substring(0, idx)
|
||||||
let post = oldText.substring(idx)
|
let post = oldText.substring(idx)
|
||||||
let newText = `${pre}:${emoji.shortcode}: ${post}`
|
let newText = `${pre}${emojiText} ${post}`
|
||||||
store.setComposeData(realm, { text: newText })
|
store.setComposeData(realm, { text: newText })
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,57 +4,39 @@
|
||||||
{title}
|
{title}
|
||||||
background="var(--main-bg)"
|
background="var(--main-bg)"
|
||||||
>
|
>
|
||||||
<div class="custom-emoji-container">
|
<div class="emoji-container" {style} >
|
||||||
{#if emojis.length}
|
{#if loaded}
|
||||||
<ul class="custom-emoji-list">
|
<emoji-mart props-json={emojiMartPropsJson} ></emoji-mart>
|
||||||
{#each emojis as emoji}
|
{:elseif error}
|
||||||
<li class="custom-emoji">
|
<div>Failed to load emoji picker: {error}</div>
|
||||||
<button type="button" on:click="onClickEmoji(emoji)">
|
|
||||||
<img src={$autoplayGifs ? emoji.url : emoji.static_url}
|
|
||||||
alt=":{emoji.shortcode}:"
|
|
||||||
title=":{emoji.shortcode}:"
|
|
||||||
/>
|
|
||||||
</button>
|
|
||||||
</li>
|
|
||||||
{/each}
|
|
||||||
</ul>
|
|
||||||
{:else}
|
{:else}
|
||||||
<div class="custom-emoji-no-emoji">No custom emoji found for this instance.</div>
|
<div class="emoji-container-loading" >
|
||||||
|
<LoadingSpinner />
|
||||||
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
</ModalDialog>
|
</ModalDialog>
|
||||||
<style>
|
<style>
|
||||||
.custom-emoji-container {
|
.emoji-container {
|
||||||
max-width: 100%;
|
max-width: calc(100vw - 20px);
|
||||||
width: 400px;
|
position: relative;
|
||||||
height: 300px;
|
|
||||||
overflow: auto;
|
|
||||||
}
|
}
|
||||||
.custom-emoji-no-emoji {
|
.emoji-container-loading {
|
||||||
font-size: 1.3em;
|
position: absolute;
|
||||||
padding: 20px;
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
top: 0;
|
||||||
|
bottom: 0;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
}
|
}
|
||||||
.custom-emoji-list {
|
:global(.emoji-mart-category .emoji-mart-emoji-custom span,
|
||||||
list-style: none;
|
.emoji-mart-preview-emoji .emoji-mart-emoji-custom span) {
|
||||||
display: grid;
|
/* some custom emoji look repeated because they aren't tall enough */
|
||||||
grid-template-columns: repeat(auto-fill, minmax(48px, 1fr));
|
background-repeat: no-repeat;
|
||||||
grid-gap: 5px;
|
background-position: center center;
|
||||||
padding: 20px 10px;
|
|
||||||
}
|
}
|
||||||
.custom-emoji button {
|
|
||||||
padding: 0;
|
|
||||||
margin: 0;
|
|
||||||
border: none;
|
|
||||||
cursor: pointer;
|
|
||||||
box-shadow: none;
|
|
||||||
background: none;
|
|
||||||
}
|
|
||||||
.custom-emoji img {
|
|
||||||
width: 48px;
|
|
||||||
height: 48px;
|
|
||||||
object-fit: contain;
|
|
||||||
}
|
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
<script>
|
<script>
|
||||||
import ModalDialog from './ModalDialog.html'
|
import ModalDialog from './ModalDialog.html'
|
||||||
|
@ -62,30 +44,77 @@
|
||||||
import { insertEmoji } from '../../../_actions/emoji'
|
import { insertEmoji } from '../../../_actions/emoji'
|
||||||
import { show } from '../helpers/showDialog'
|
import { show } from '../helpers/showDialog'
|
||||||
import { close } from '../helpers/closeDialog'
|
import { close } from '../helpers/closeDialog'
|
||||||
import { oncreate } from '../helpers/onCreateDialog'
|
import { oncreate as onCreateDialog } from '../helpers/onCreateDialog'
|
||||||
|
import { define } from 'remount/es6'
|
||||||
|
import { loadCSS } from '../../../_utils/loadCSS'
|
||||||
|
import LoadingSpinner from '../../../_components/LoadingSpinner.html'
|
||||||
|
import { importEmojiMart } from '../../../_utils/asyncModules'
|
||||||
|
import { on } from '../../../_utils/eventBus'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
oncreate,
|
async oncreate () {
|
||||||
|
onCreateDialog.call(this)
|
||||||
|
on('emoji-selected', this, emoji => this.onEmojiSelected(emoji))
|
||||||
|
try {
|
||||||
|
loadCSS('/emoji-mart.css')
|
||||||
|
let Picker = await importEmojiMart()
|
||||||
|
if (!customElements.get('emoji-mart')) {
|
||||||
|
define({ 'emoji-mart': Picker })
|
||||||
|
}
|
||||||
|
this.set({ loaded: true })
|
||||||
|
} catch (error) {
|
||||||
|
this.set({ error }) // should never happen, but you never know
|
||||||
|
}
|
||||||
|
},
|
||||||
components: {
|
components: {
|
||||||
ModalDialog
|
ModalDialog,
|
||||||
|
LoadingSpinner
|
||||||
},
|
},
|
||||||
store: () => store,
|
store: () => store,
|
||||||
|
data: () => ({
|
||||||
|
loading: true,
|
||||||
|
loaded: false,
|
||||||
|
error: void 0
|
||||||
|
}),
|
||||||
computed: {
|
computed: {
|
||||||
emojis: ({ $currentCustomEmoji }) => {
|
// try to estimate size of emoji-mart based on mobile vs desktop
|
||||||
|
style: ({ $isSmallMobileSize }) => (`
|
||||||
|
min-width: ${$isSmallMobileSize ? 250 : 300}px;
|
||||||
|
min-height: ${$isSmallMobileSize ? 300 : 400}px;
|
||||||
|
`),
|
||||||
|
emojiMartPropsJson: ({ emojiMartProps }) => JSON.stringify(emojiMartProps),
|
||||||
|
emojiMartProps: ({ perLine, custom, showPreview }) => ({
|
||||||
|
perLine,
|
||||||
|
custom,
|
||||||
|
showPreview,
|
||||||
|
color: 'var(--nav-bg)',
|
||||||
|
emoji: 'sailboat',
|
||||||
|
title: 'Emoji'
|
||||||
|
}),
|
||||||
|
showPreview: ({ $isSmallMobileSize }) => !$isSmallMobileSize,
|
||||||
|
perLine: ({ $isSmallMobileSize }) => $isSmallMobileSize ? 7 : 9,
|
||||||
|
custom: ({ $currentCustomEmoji, $autoplayGifs }) => {
|
||||||
if (!$currentCustomEmoji) {
|
if (!$currentCustomEmoji) {
|
||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
return $currentCustomEmoji.filter(emoji => emoji.visible_in_picker)
|
return $currentCustomEmoji.filter(emoji => emoji.visible_in_picker).map(emoji => ({
|
||||||
|
name: emoji.shortcode,
|
||||||
|
short_names: [emoji.shortcode],
|
||||||
|
text: `:${emoji.shortcode}:`,
|
||||||
|
emoticons: [],
|
||||||
|
keywords: [emoji.shortcode],
|
||||||
|
imageUrl: $autoplayGifs ? emoji.url : emoji.static_url
|
||||||
|
}))
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
show,
|
show,
|
||||||
close,
|
close,
|
||||||
onClickEmoji (emoji) {
|
onEmojiSelected (emoji) {
|
||||||
let { realm } = this.get()
|
let { realm } = this.get()
|
||||||
insertEmoji(realm, emoji)
|
insertEmoji(realm, emoji)
|
||||||
this.close()
|
this.close()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -8,7 +8,7 @@ export default function showEmojiDialog (realm) {
|
||||||
data: {
|
data: {
|
||||||
id: createDialogId(),
|
id: createDialogId(),
|
||||||
label: 'Emoji dialog',
|
label: 'Emoji dialog',
|
||||||
title: 'Custom emoji',
|
title: 'Emoji',
|
||||||
realm
|
realm
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
20
src/routes/_react/emoji-mart.js
Normal file
20
src/routes/_react/emoji-mart.js
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
// I wrap the emoji-mart React code itself here, so that we don't need to pass in a huge "data"
|
||||||
|
// object via a JSON-stringified custom element attribute. Also, AFAICT there is no way when
|
||||||
|
// using `remount` to pass in functions as attributes, since everything is stringified. So
|
||||||
|
// I just fire a global event here when an emoji is clicked.
|
||||||
|
|
||||||
|
import data from 'emoji-mart/data/messenger.json'
|
||||||
|
import NimblePicker from 'emoji-mart/dist-es/components/picker/nimble-picker'
|
||||||
|
import React from 'react'
|
||||||
|
import { emit } from '../_utils/eventBus'
|
||||||
|
|
||||||
|
function onEmojiSelected (emoji) {
|
||||||
|
emit('emoji-selected', emoji)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default props => React.createElement(NimblePicker, Object.assign({
|
||||||
|
set: 'messenger',
|
||||||
|
data,
|
||||||
|
native: true,
|
||||||
|
onSelect: onEmojiSelected
|
||||||
|
}, props))
|
|
@ -6,7 +6,10 @@ export function resizeObservers (store) {
|
||||||
}
|
}
|
||||||
|
|
||||||
const recalculateIsMobileSize = () => {
|
const recalculateIsMobileSize = () => {
|
||||||
store.set({ isMobileSize: window.matchMedia('(max-width: 767px)').matches })
|
store.set({
|
||||||
|
isMobileSize: window.matchMedia('(max-width: 767px)').matches,
|
||||||
|
isSmallMobileSize: window.matchMedia('(max-width: 479px)').matches
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
registerResizeListener(recalculateIsMobileSize)
|
registerResizeListener(recalculateIsMobileSize)
|
||||||
|
|
|
@ -35,3 +35,7 @@ export const importDatabase = () => import(
|
||||||
export const importLoggedInObservers = () => import(
|
export const importLoggedInObservers = () => import(
|
||||||
/* webpackChunkName: 'loggedInObservers.js' */ '../_store/observers/loggedInObservers.js'
|
/* webpackChunkName: 'loggedInObservers.js' */ '../_store/observers/loggedInObservers.js'
|
||||||
).then(getDefault)
|
).then(getDefault)
|
||||||
|
|
||||||
|
export const importEmojiMart = () => import(
|
||||||
|
/* webpackChunkName: 'emoji-mart.js' */ '../_react/emoji-mart.js'
|
||||||
|
).then(getDefault)
|
||||||
|
|
12
src/routes/_utils/loadCSS.js
Normal file
12
src/routes/_utils/loadCSS.js
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
export function loadCSS (href) {
|
||||||
|
let existingLink = document.querySelector(`link[href="${href}"]`)
|
||||||
|
|
||||||
|
if (existingLink) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
let link = document.createElement('link')
|
||||||
|
link.rel = 'stylesheet'
|
||||||
|
link.href = href
|
||||||
|
|
||||||
|
document.head.appendChild(link)
|
||||||
|
}
|
|
@ -1,6 +1,5 @@
|
||||||
import { Selector as $ } from 'testcafe'
|
|
||||||
import {
|
import {
|
||||||
composeButton, composeInput, composeLengthIndicator, emojiButton, getComposeSelectionStart,
|
composeButton, composeInput, composeLengthIndicator, emojiButton, emojiSearchInput, getComposeSelectionStart,
|
||||||
getNthStatusContent, getUrl,
|
getNthStatusContent, getUrl,
|
||||||
homeNavButton,
|
homeNavButton,
|
||||||
notificationsNavButton, sleep,
|
notificationsNavButton, sleep,
|
||||||
|
@ -63,7 +62,8 @@ test('shows compose limits for custom emoji', async t => {
|
||||||
await t
|
await t
|
||||||
.typeText(composeInput, 'hello world ')
|
.typeText(composeInput, 'hello world ')
|
||||||
.click(emojiButton)
|
.click(emojiButton)
|
||||||
.click($('button img[title=":blobnom:"]'))
|
.typeText(emojiSearchInput, 'blobnom')
|
||||||
|
.pressKey('enter')
|
||||||
.expect(composeInput.value).eql('hello world :blobnom: ')
|
.expect(composeInput.value).eql('hello world :blobnom: ')
|
||||||
.expect(composeLengthIndicator.innerText).eql('478')
|
.expect(composeLengthIndicator.innerText).eql('478')
|
||||||
})
|
})
|
||||||
|
@ -75,16 +75,19 @@ test('inserts custom emoji correctly', async t => {
|
||||||
.selectText(composeInput, 6, 6)
|
.selectText(composeInput, 6, 6)
|
||||||
.expect(getComposeSelectionStart()).eql(6)
|
.expect(getComposeSelectionStart()).eql(6)
|
||||||
.click(emojiButton)
|
.click(emojiButton)
|
||||||
.click($('button img[title=":blobpats:"]'))
|
.typeText(emojiSearchInput, 'blobpats')
|
||||||
|
.pressKey('enter')
|
||||||
.expect(composeInput.value).eql('hello :blobpats: world')
|
.expect(composeInput.value).eql('hello :blobpats: world')
|
||||||
.selectText(composeInput, 0, 0)
|
.selectText(composeInput, 0, 0)
|
||||||
.expect(getComposeSelectionStart()).eql(0)
|
.expect(getComposeSelectionStart()).eql(0)
|
||||||
.click(emojiButton)
|
.click(emojiButton)
|
||||||
.click($('button img[title=":blobnom:"]'))
|
.typeText(emojiSearchInput, 'blobnom')
|
||||||
|
.pressKey('enter')
|
||||||
.expect(composeInput.value).eql(':blobnom: hello :blobpats: world')
|
.expect(composeInput.value).eql(':blobnom: hello :blobpats: world')
|
||||||
.typeText(composeInput, ' foobar ')
|
.typeText(composeInput, ' foobar ')
|
||||||
.click(emojiButton)
|
.click(emojiButton)
|
||||||
.click($('button img[title=":blobpeek:"]'))
|
.typeText(emojiSearchInput, 'blobpeek')
|
||||||
|
.pressKey('enter')
|
||||||
.expect(composeInput.value).eql(':blobnom: hello :blobpats: world foobar :blobpeek: ')
|
.expect(composeInput.value).eql(':blobnom: hello :blobpats: world foobar :blobpeek: ')
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -92,13 +95,28 @@ test('inserts emoji without typing anything', async t => {
|
||||||
await loginAsFoobar(t)
|
await loginAsFoobar(t)
|
||||||
await t
|
await t
|
||||||
.click(emojiButton)
|
.click(emojiButton)
|
||||||
.click($('button img[title=":blobpats:"]'))
|
.typeText(emojiSearchInput, 'blobpats')
|
||||||
|
.pressKey('enter')
|
||||||
.expect(composeInput.value).eql(':blobpats: ')
|
.expect(composeInput.value).eql(':blobpats: ')
|
||||||
.click(emojiButton)
|
.click(emojiButton)
|
||||||
.click($('button img[title=":blobpeek:"]'))
|
.typeText(emojiSearchInput, 'blobpeek')
|
||||||
|
.pressKey('enter')
|
||||||
.expect(composeInput.value).eql(':blobpeek: :blobpats: ')
|
.expect(composeInput.value).eql(':blobpeek: :blobpats: ')
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test('inserts native emoji without typing anything', async t => {
|
||||||
|
await loginAsFoobar(t)
|
||||||
|
await t
|
||||||
|
.click(emojiButton)
|
||||||
|
.typeText(emojiSearchInput, 'pineapple')
|
||||||
|
.pressKey('enter')
|
||||||
|
.expect(composeInput.value).eql('\ud83c\udf4d ')
|
||||||
|
.click(emojiButton)
|
||||||
|
.typeText(emojiSearchInput, 'elephant')
|
||||||
|
.pressKey('enter')
|
||||||
|
.expect(composeInput.value).eql('\ud83d\udc18 \ud83c\udf4d ')
|
||||||
|
})
|
||||||
|
|
||||||
test('cannot post an empty status', async t => {
|
test('cannot post an empty status', async t => {
|
||||||
await loginAsFoobar(t)
|
await loginAsFoobar(t)
|
||||||
await t
|
await t
|
||||||
|
|
|
@ -9,7 +9,7 @@ import {
|
||||||
getNthStatusSelector,
|
getNthStatusSelector,
|
||||||
composeModalEmojiButton,
|
composeModalEmojiButton,
|
||||||
composeModalInput,
|
composeModalInput,
|
||||||
composeModalComposeButton
|
composeModalComposeButton, emojiSearchInput
|
||||||
} from '../utils'
|
} from '../utils'
|
||||||
import { loginAsFoobar } from '../roles'
|
import { loginAsFoobar } from '../roles'
|
||||||
import { Selector as $ } from 'testcafe'
|
import { Selector as $ } from 'testcafe'
|
||||||
|
@ -42,7 +42,8 @@ test('can use emoji dialog within compose dialog', async t => {
|
||||||
await sleep(2000)
|
await sleep(2000)
|
||||||
await t.click(composeButton)
|
await t.click(composeButton)
|
||||||
.click(composeModalEmojiButton)
|
.click(composeModalEmojiButton)
|
||||||
.click($('button img[title=":blobpats:"]'))
|
.typeText(emojiSearchInput, 'blobpats')
|
||||||
|
.pressKey('enter')
|
||||||
.expect(composeModalInput.value).eql(':blobpats: ')
|
.expect(composeModalInput.value).eql(':blobpats: ')
|
||||||
.click(composeModalComposeButton)
|
.click(composeModalComposeButton)
|
||||||
.expect(modalDialog.exists).notOk()
|
.expect(modalDialog.exists).notOk()
|
||||||
|
|
|
@ -46,6 +46,7 @@ export const markMediaSensitiveInput = $('#choice-mark-media-sensitive')
|
||||||
export const neverMarkMediaSensitiveInput = $('#choice-never-mark-media-sensitive')
|
export const neverMarkMediaSensitiveInput = $('#choice-never-mark-media-sensitive')
|
||||||
export const removeEmojiFromDisplayNamesInput = $('#choice-omit-emoji-in-display-names')
|
export const removeEmojiFromDisplayNamesInput = $('#choice-omit-emoji-in-display-names')
|
||||||
export const dialogOptionsOption = $(`.modal-dialog button`)
|
export const dialogOptionsOption = $(`.modal-dialog button`)
|
||||||
|
export const emojiSearchInput = $('.emoji-mart-search input')
|
||||||
|
|
||||||
export const composeModalInput = $('.modal-dialog .compose-box-input')
|
export const composeModalInput = $('.modal-dialog .compose-box-input')
|
||||||
export const composeModalComposeButton = $('.modal-dialog .compose-box-button')
|
export const composeModalComposeButton = $('.modal-dialog .compose-box-button')
|
||||||
|
|
|
@ -4,15 +4,12 @@ const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPl
|
||||||
const LodashModuleReplacementPlugin = require('lodash-webpack-plugin')
|
const LodashModuleReplacementPlugin = require('lodash-webpack-plugin')
|
||||||
const terser = require('./terser.config')
|
const terser = require('./terser.config')
|
||||||
const CircularDependencyPlugin = require('circular-dependency-plugin')
|
const CircularDependencyPlugin = require('circular-dependency-plugin')
|
||||||
const { mode, dev } = require('./shared.config')
|
const { mode, dev, resolve } = require('./shared.config')
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
entry: config.client.entry(),
|
entry: config.client.entry(),
|
||||||
output: Object.assign(config.client.output(), { globalObject: 'this' }), // enables HMR in workers
|
output: Object.assign(config.client.output(), { globalObject: 'this' }), // enables HMR in workers
|
||||||
resolve: {
|
resolve,
|
||||||
extensions: ['.js', '.json', '.html'],
|
|
||||||
mainFields: ['svelte', 'module', 'browser', 'main']
|
|
||||||
},
|
|
||||||
mode,
|
mode,
|
||||||
module: {
|
module: {
|
||||||
rules: [
|
rules: [
|
||||||
|
|
|
@ -1,15 +1,12 @@
|
||||||
const config = require('sapper/config/webpack.js')
|
const config = require('sapper/config/webpack.js')
|
||||||
const pkg = require('../package.json')
|
const pkg = require('../package.json')
|
||||||
const { mode, dev } = require('./shared.config')
|
const { mode, dev, resolve } = require('./shared.config')
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
entry: config.server.entry(),
|
entry: config.server.entry(),
|
||||||
output: config.server.output(),
|
output: config.server.output(),
|
||||||
target: 'node',
|
target: 'node',
|
||||||
resolve: {
|
resolve,
|
||||||
extensions: ['.js', '.json', '.html'],
|
|
||||||
mainFields: ['svelte', 'module', 'browser', 'main']
|
|
||||||
},
|
|
||||||
externals: Object.keys(pkg.dependencies),
|
externals: Object.keys(pkg.dependencies),
|
||||||
module: {
|
module: {
|
||||||
rules: [
|
rules: [
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
const config = require('sapper/config/webpack.js')
|
const config = require('sapper/config/webpack.js')
|
||||||
const terser = require('./terser.config')
|
const terser = require('./terser.config')
|
||||||
const webpack = require('webpack')
|
const webpack = require('webpack')
|
||||||
const { mode, dev } = require('./shared.config')
|
const { mode, dev, resolve } = require('./shared.config')
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
entry: config.serviceworker.entry(),
|
entry: config.serviceworker.entry(),
|
||||||
output: config.serviceworker.output(),
|
output: config.serviceworker.output(),
|
||||||
|
resolve,
|
||||||
mode,
|
mode,
|
||||||
devtool: dev ? 'inline-source-map' : 'source-map',
|
devtool: dev ? 'inline-source-map' : 'source-map',
|
||||||
plugins: [
|
plugins: [
|
||||||
|
|
|
@ -1,7 +1,18 @@
|
||||||
const mode = process.env.NODE_ENV
|
const mode = process.env.NODE_ENV
|
||||||
const dev = mode === 'development'
|
const dev = mode === 'development'
|
||||||
|
|
||||||
|
const resolve = {
|
||||||
|
extensions: ['.js', '.json', '.html'],
|
||||||
|
mainFields: ['svelte', 'module', 'browser', 'main'],
|
||||||
|
alias: {
|
||||||
|
'react': 'inferno-compat',
|
||||||
|
'react-dom': 'inferno-compat',
|
||||||
|
'inferno': dev ? 'inferno/dist/index.dev.esm.js' : 'inferno'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
mode,
|
mode,
|
||||||
dev
|
dev,
|
||||||
|
resolve
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue