From cb95e027c4cb4d626cfae159502cc4e418ddfcbb Mon Sep 17 00:00:00 2001 From: Devin Howard Date: Mon, 9 Jan 2017 13:14:20 -0500 Subject: [PATCH 01/57] Add emoji to chat (#1013) * add emoji picker unstyled * rename junto.css.erb => junto.scss.erb * junto scss-ified * add emoji mart css * emoji are replaced in the text area * remove unicode emoji from messages before sending to db * add emoji back into messages on display * bigger font size on chat messages * tweak styling * codeclimate (eslint) --- app/assets/stylesheets/emoji-mart-0.3.5.css | 263 +++++++++++++ app/assets/stylesheets/junto.css.erb | 328 ---------------- app/assets/stylesheets/junto.scss.erb | 370 ++++++++++++++++++ frontend/src/Metamaps/Util.js | 31 ++ frontend/src/components/MapChat/Message.js | 4 +- frontend/src/components/MapChat/NewMessage.js | 68 ++++ frontend/src/components/MapChat/index.js | 42 +- package.json | 1 + 8 files changed, 759 insertions(+), 348 deletions(-) create mode 100644 app/assets/stylesheets/emoji-mart-0.3.5.css delete mode 100644 app/assets/stylesheets/junto.css.erb create mode 100644 app/assets/stylesheets/junto.scss.erb create mode 100644 frontend/src/components/MapChat/NewMessage.js diff --git a/app/assets/stylesheets/emoji-mart-0.3.5.css b/app/assets/stylesheets/emoji-mart-0.3.5.css new file mode 100644 index 00000000..3672320f --- /dev/null +++ b/app/assets/stylesheets/emoji-mart-0.3.5.css @@ -0,0 +1,263 @@ +.emoji-mart, +.emoji-mart * { + box-sizing: border-box; + line-height: 1.15; +} + +.emoji-mart { + font-family: -apple-system, BlinkMacSystemFont, "Helvetica Neue", sans-serif; + font-size: 16px; + display: inline-block; + color: #222427; + border: 1px solid #d9d9d9; + border-radius: 5px; + background: #fff; +} + +.emoji-mart .emoji-mart-emoji { + padding: 6px; +} + +.emoji-mart-bar:first-child { + border-top-left-radius: 5px; + border-top-right-radius: 5px; +} +.emoji-mart-bar:last-child { + border-bottom-left-radius: 5px; + border-bottom-right-radius: 5px; +} + +.emoji-mart-anchors { + display: flex; + justify-content: space-between; + padding: 0 6px; + color: #858585; + line-height: 0; +} + +.emoji-mart-anchor { + position: relative; + flex: 1; + text-align: center; + padding: 12px 4px; + overflow: hidden; + transition: color .1s ease-out; +} +.emoji-mart-anchor:hover, +.emoji-mart-anchor-selected { + color: #464646; +} + +.emoji-mart-anchor-selected .emoji-mart-anchor-bar { + bottom: 0; +} + +.emoji-mart-anchor-bar { + position: absolute; + bottom: -3px; left: 0; + width: 100%; height: 3px; + background-color: #464646; +} + +.emoji-mart-anchors i { + display: inline-block; + width: 100%; + max-width: 22px; +} + +.emoji-mart-anchors svg { + fill: currentColor; +} + +.emoji-mart-scroll { + overflow-y: scroll; + height: 270px; + padding: 0 6px 6px 6px; + border: solid #d9d9d9; + border-width: 1px 0; +} + +.emoji-mart-search { + font-size: 16px; + display: block; + width: 100%; + padding: .2em .6em; + margin-top: 6px; + border-radius: 25px; + border: 1px solid #d9d9d9; + outline: 0; +} + +.emoji-mart-category .emoji-mart-emoji span { + z-index: 1; + position: relative; +} + +.emoji-mart-category .emoji-mart-emoji:hover:before { + z-index: 0; + content: ""; + position: absolute; + top: 0; left: 0; + width: 100%; height: 100%; + background-color: #f4f4f4; + border-radius: 100%; +} + +.emoji-mart-category-label { + z-index: 2; + position: relative; + position: -webkit-sticky; + top: 0; +} + +.emoji-mart-category-label span { + display: block; + width: 100%; + font-weight: 500; + padding: 5px 6px; + background-color: #fff; + background-color: rgba(255, 255, 255, .95); +} + +.emoji-mart-emoji { + position: relative; + display: inline-block; + font-size: 0; +} + +.emoji-mart-no-results { + font-size: 14px; + text-align: center; + padding-top: 70px; + color: #858585; +} +.emoji-mart-no-results span { + display: inline-block; + vertical-align: middle; +} + +.emoji-mart-preview { + position: relative; + height: 70px; +} + +.emoji-mart-preview-emoji, +.emoji-mart-preview-data, +.emoji-mart-preview-skins { + position: absolute; + top: 50%; + transform: translateY(-50%); +} + +.emoji-mart-preview-emoji { + left: 12px; +} + +.emoji-mart-preview-data { + left: 68px; right: 12px; + word-break: break-word; +} + +.emoji-mart-preview-skins { + right: 30px; + text-align: right; +} + +.emoji-mart-preview-name { + font-size: 14px; +} + +.emoji-mart-preview-shortname { + font-size: 12px; + color: #888; +} +.emoji-mart-preview-shortname + .emoji-mart-preview-shortname, +.emoji-mart-preview-shortname + .emoji-mart-preview-emoticon, +.emoji-mart-preview-emoticon + .emoji-mart-preview-emoticon { + margin-left: .5em; +} + +.emoji-mart-preview-emoticon { + font-size: 11px; + color: #bbb; +} + +.emoji-mart-title span { + display: inline-block; + vertical-align: middle; +} + +.emoji-mart-title .emoji-mart-emoji { + padding: 0; +} + +.emoji-mart-title-label { + color: #999A9C; + font-size: 26px; + font-weight: 300; +} + +.emoji-mart-skin-swatches { + font-size: 0; + padding: 2px 0; + border: 1px solid #d9d9d9; + border-radius: 12px; + background-color: #fff; +} + +.emoji-mart-skin-swatches-opened .emoji-mart-skin-swatch { + width: 16px; + padding: 0 2px; +} + +.emoji-mart-skin-swatches-opened .emoji-mart-skin-swatch-selected:after { + opacity: .75; +} + +.emoji-mart-skin-swatch { + display: inline-block; + width: 0; + vertical-align: middle; + transition-property: width, padding; + transition-duration: .125s; + transition-timing-function: ease-out; +} + +.emoji-mart-skin-swatch:nth-child(1) { transition-delay: 0 } +.emoji-mart-skin-swatch:nth-child(2) { transition-delay: .03s } +.emoji-mart-skin-swatch:nth-child(3) { transition-delay: .06s } +.emoji-mart-skin-swatch:nth-child(4) { transition-delay: .09s } +.emoji-mart-skin-swatch:nth-child(5) { transition-delay: .12s } +.emoji-mart-skin-swatch:nth-child(6) { transition-delay: .15s } + +.emoji-mart-skin-swatch-selected { + position: relative; + width: 16px; + padding: 0 2px; +} +.emoji-mart-skin-swatch-selected:after { + content: ""; + position: absolute; + top: 50%; left: 50%; + width: 4px; height: 4px; + margin: -2px 0 0 -2px; + background-color: #fff; + border-radius: 100%; + pointer-events: none; + opacity: 0; + transition: opacity .2s ease-out; +} + +.emoji-mart-skin { + display: inline-block; + width: 100%; padding-top: 100%; + max-width: 12px; + border-radius: 100%; +} + +.emoji-mart-skin-tone-1 { background-color: #ffc93a } +.emoji-mart-skin-tone-2 { background-color: #fadcbc } +.emoji-mart-skin-tone-3 { background-color: #e0bb95 } +.emoji-mart-skin-tone-4 { background-color: #bf8f68 } +.emoji-mart-skin-tone-5 { background-color: #9b643d } +.emoji-mart-skin-tone-6 { background-color: #594539 } diff --git a/app/assets/stylesheets/junto.css.erb b/app/assets/stylesheets/junto.css.erb deleted file mode 100644 index 9dd94a91..00000000 --- a/app/assets/stylesheets/junto.css.erb +++ /dev/null @@ -1,328 +0,0 @@ -.collaborator-video { - z-index: 1; - position: absolute; - width: 150px; - height: 150px; - cursor: default; - color: #FFF; -} -.collaborator-video .video-receive { - position: absolute; - width: 160px; - padding: 20px 20px 20px 170px; - background: #424242; - height: 110px; - border-top-left-radius: 75px; - border-bottom-left-radius: 75px; - border-top-right-radius: 2px; - border-bottom-right-radius: 2px; -} -.collaborator-video .video-receive .video-statement { - margin-bottom: 10px; -} -.collaborator-video .video-receive .btn-group .btn-yes { - margin-right: 10px; -} -.collaborator-video .video-receive .btn-group .btn-no { - background-color: #c04f4f; -} -.collaborator-video .video-receive .btn-group .btn-no:hover { - background-color: #A54242; -} -.collaborator-video .video-cutoff { - width: 150px; - height: 150px; - overflow: hidden; - border-radius: 75px; - z-index: 0; - position: relative; - -webkit-box-shadow: 0px 6px 3px rgba(0, 0, 0, 0.23), 10px 10px 10px rgba(0, 0, 0, 0.19); - -moz-box-shadow: 0px 6px 3px rgba(0, 0, 0, 0.23), 10px 10px 10px rgba(0, 0, 0, 0.19); - box-shadow: 0px 6px 3px rgba(0, 0, 0, 0.23), 10px 10px 10px rgba(0, 0, 0, 0.19); -} -.collaborator-video .video-cutoff video { - height: 150px; - margin-left: -25px; -} -.collaborator-video .video-cutoff .collaborator-video-avatar { - position: absolute; - top: 0; - left: 0; - -webkit-user-select: none; - -khtml-user-select: none; - -moz-user-select: none; - -o-user-select: none; - user-select: none; - -webkit-user-drag: none; - display: none; -} -.collaborator-video .video-audio { - position: absolute; - width: 24px; - height: 24px; - top: 85%; - right: 0px; - cursor: pointer; - background: url(<%= asset_path 'audio_sprite.png' %>) no-repeat; -} -.collaborator-video .video-audio:hover { - background-position-x: -24px; -} -.collaborator-video .video-audio.active { - background-position-y: -24px; -} -.collaborator-video .video-video { - position: absolute; - width: 24px; - height: 24px; - top: 85%; - left: 0px; - cursor: pointer; - background: url(<%= asset_path 'camera_sprite.png' %>) no-repeat; -} -.collaborator-video .video-video:hover { - background-position-x: -24px; -} -.collaborator-video .video-video.active { - background-position-y: -24px; -} -.collaborator-video.my-video { - left: 30px; - top: 72px; -} -#chat-box-wrapper { - height: 100%; - float: right; -} -.chat-box { - position: relative; - display: flex; - flex-direction: column; - z-index: 1; - width: 300px; - height: 100%; - background: #424242; - box-shadow: -8px 0px 16px 2px rgba(0, 0, 0, 0.23); -} -.chat-box .chat-button { - position: absolute; - top: 50%; - left: -36px; - width: 36px; - height: 49px; - background: url(<%= asset_path 'junto.png' %>) no-repeat 2px 9px, url(<%= asset_path 'tray_tab.png' %>) no-repeat; - cursor: pointer; -} -.chat-box .chat-button.active { - background: url(<%= asset_path 'junto_spinner_dark.gif' %>) no-repeat 2px 8px, url(<%= asset_path 'tray_tab.png' %>) no-repeat !important; -} -.chat-box .chat-button .chat-unread { - background: #DAB539; - position: absolute; - top: -3px; - left: -11px; - width: 20px; - height: 20px; - border-radius: 11px; - border: 2px solid #424242; - color: #424242; - text-align: center; - font-size: 12px; - font-weight: bold; - line-height: 20px; -} -.chat-box .junto-header { - width: 276px; - padding: 16px 8px 16px 16px; - font-size: 16px; - text-align: left; - font-weight: bold; - background-color: #000000; - color: #f5f5f5; - box-shadow: 0px 6px 3px rgba(0, 0, 0, 0.23); -} -.chat-box .junto-header .cursor-toggle { - width: 32px; - height: 32px; - margin-right: 8px; - margin-top: -8px; - float: right; - background: url(<%= asset_path 'cursor_sprite.png' %>) no-repeat; -} -.chat-box .junto-header .cursor-toggle:hover { - background-position-x: -32px; -} -.chat-box .junto-header .cursor-toggle.active { - background-position-y: -32px; -} -.chat-box .junto-header .video-toggle { - width: 32px; - height: 32px; - margin-right: 10px; - margin-top: -8px; - float: right; - background: url(<%= asset_path 'video_sprite.png' %>) no-repeat; -} -.chat-box .junto-header .video-toggle:hover { - background-position-x: -32px; -} -.chat-box .junto-header .video-toggle.active { - background-position-y: -32px; -} -.chat-box .participants { - width: 100%; - min-height: 150px; - padding: 16px 0px 16px 0px; - text-align: left; - color: #f5f5f5; - overflow-y: auto; -} -.chat-box .participants .conversation-live { - padding: 5px 10px 5px 10px; - background: #c04f4f; - margin: 5px 10px; - border-radius: 2px; -} -.chat-box .participants .conversation-live .call-action { - float: right; - cursor: pointer; - color: #EBFF00; -} -.chat-box .participants .participant { - width: 89%; - padding: 8px 8px 2px 8px; - color: #f5f5f5; - font-family: arial, sans-serif; - font-size: 13px; - line-height: 14px; -} -.chat-box .participants .participant .chat-participant-image { - width: 15%; - float: left; - overflow: hidden; - color: #BBB; - padding-top: 2px; -} -.chat-box .participants .participant .chat-participant-image img { - width: 32px; - height: 32px; - border-radius: 18px; -} -.chat-box .participants .participant .chat-participant-name { - width: 53%; - float: left; - font-size: 13px; - font-weight: bold; - margin-top: 12px; - padding: 2px 8px 0; - text-align: left; -} -.chat-box .participants .participant .chat-participant-invite-call, -.chat-box .participants .participant .chat-participant-invite-join - { - float: right; - background: #4FC059 url(<%= asset_path 'invitepeer16.png' %>) no-repeat center center; -} -.chat-box .participants .participant .chat-participant-invite-call.pending, -.chat-box .participants .participant .chat-participant-invite-join.pending { - background: #dab539 url(<%= asset_path 'ellipsis.gif' %>) no-repeat center center; -} -.chat-box .participants .participant .chat-participant-participating { - float: right; - margin-top: 14px; -} -.chat-box .participants .participant .chat-participant-participating .green-dot { - background: #4fc059; - width: 12px; - height: 12px; - border-radius: 6px; -} -.chat-box .chat-header { - width: 276px; - padding: 16px 8px 16px 16px; - font-size: 16px; - text-align: left; - font-weight: bold; - background-color: #000000; - color: #f5f5f5; - box-shadow: 0px 6px 3px rgba(0, 0, 0, 0.23); -} -.chat-box .chat-header .sound-toggle { - width: 24px; - height: 24px; - margin-right: 10px; - margin-top: -2px; - float: right; - background: url(<%= asset_path 'sound_sprite.png' %>) no-repeat; -} -.chat-box .chat-header .sound-toggle:hover { - background-position-x: -24px; -} -.chat-box .chat-header .sound-toggle.active { - background-position-y: -24px; -} -.chat-box .chat-input { - min-height: 80px; - width: 94%; - padding: 8px 3% 8px 3%; - font-size: 13px; - outline: none; - resize: none; -} -.chat-box .chat-messages { - width: 100%; - padding: 16px 0px; - overflow-y: auto; - flex-grow: 1; -} -.chat-box .chat-messages .chat-message { - width: 89%; - padding: 8px 8px 2px 8px; - color: #f5f5f5; - font-family: arial, sans-serif; - font-size: 13px; - line-height: 14px; -} -.chat-box .chat-messages .chat-message a:link { - color: #4fb5c0; - text-decoration: underline; -} -.chat-box .chat-messages .chat-message a:visited { - color: #aea9fd; - text-decoration: underline; -} -.chat-box .chat-messages .chat-message a:hover { - color: #dab539; - text-decoration: underline; -} -.chat-box .chat-messages .chat-message .chat-message-user { - width: 12%; - float: left; - overflow: hidden; - color: #BBB; - padding-top: 2px; -} -.chat-box .chat-messages .chat-message .chat-message-user img { - border: 2px solid #424242; - width: 26px; - height: 26px; - border-radius: 14px; -} -.chat-box .chat-messages .chat-message .chat-message-meta { - padding: 0 8px; - float: left; -} -.chat-box .chat-messages .chat-message .chat-message-username { - color: #4fc059; -} -.chat-box .chat-messages .chat-message .chat-message-text { - width: 80%; - float: left; - padding: 2px 8px 0; - text-align: left; - word-wrap: break-word; -} -.chat-box .chat-messages .chat-message .chat-message-time { - font-size: 10px; - color: #757575; -} diff --git a/app/assets/stylesheets/junto.scss.erb b/app/assets/stylesheets/junto.scss.erb new file mode 100644 index 00000000..19588341 --- /dev/null +++ b/app/assets/stylesheets/junto.scss.erb @@ -0,0 +1,370 @@ +.collaborator-video { + z-index: 1; + position: absolute; + width: 150px; + height: 150px; + cursor: default; + color: #FFF; + + .video-receive { + position: absolute; + width: 160px; + padding: 20px 20px 20px 170px; + background: #424242; + height: 110px; + border-top-left-radius: 75px; + border-bottom-left-radius: 75px; + border-top-right-radius: 2px; + border-bottom-right-radius: 2px; + + .video-statement { + margin-bottom: 10px; + } + .btn-group { + .btn-yes { + margin-right: 10px; + } + .btn-no { + background-color: #c04f4f; + &:hover { + background-color: #A54242; + } + } + } + } + + .video-cutoff { + width: 150px; + height: 150px; + overflow: hidden; + border-radius: 75px; + z-index: 0; + position: relative; + -webkit-box-shadow: 0px 6px 3px rgba(0, 0, 0, 0.23), 10px 10px 10px rgba(0, 0, 0, 0.19); + -moz-box-shadow: 0px 6px 3px rgba(0, 0, 0, 0.23), 10px 10px 10px rgba(0, 0, 0, 0.19); + box-shadow: 0px 6px 3px rgba(0, 0, 0, 0.23), 10px 10px 10px rgba(0, 0, 0, 0.19); + + video { + height: 150px; + margin-left: -25px; + } + .collaborator-video-avatar { + position: absolute; + top: 0; + left: 0; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -o-user-select: none; + user-select: none; + -webkit-user-drag: none; + display: none; + } + } + .video-audio { + position: absolute; + width: 24px; + height: 24px; + top: 85%; + right: 0px; + cursor: pointer; + background: url(<%= asset_path 'audio_sprite.png' %>) no-repeat; + } + .video-audio:hover { + background-position-x: -24px; + } + .video-audio.active { + background-position-y: -24px; + } + .video-video { + position: absolute; + width: 24px; + height: 24px; + top: 85%; + left: 0px; + cursor: pointer; + background: url(<%= asset_path 'camera_sprite.png' %>) no-repeat; + } + .video-video:hover { + background-position-x: -24px; + } + .video-video.active { + background-position-y: -24px; + } +} + +.collaborator-video.my-video { + left: 30px; + top: 72px; +} + +#chat-box-wrapper { + height: 100%; + float: right; +} + +.chat-box { + position: relative; + display: flex; + flex-direction: column; + z-index: 1; + width: 300px; + height: 100%; + background: #424242; + box-shadow: -8px 0px 16px 2px rgba(0, 0, 0, 0.23); + + .chat-button { + position: absolute; + top: 50%; + left: -36px; + width: 36px; + height: 49px; + background: url(<%= asset_path 'junto.png' %>) no-repeat 2px 9px, url(<%= asset_path 'tray_tab.png' %>) no-repeat; + cursor: pointer; + + &.active { + background: url(<%= asset_path 'junto_spinner_dark.gif' %>) no-repeat 2px 8px, url(<%= asset_path 'tray_tab.png' %>) no-repeat !important; + } + .chat-unread { + background: #DAB539; + position: absolute; + top: -3px; + left: -11px; + width: 20px; + height: 20px; + border-radius: 11px; + border: 2px solid #424242; + color: #424242; + text-align: center; + font-size: 12px; + font-weight: bold; + line-height: 20px; + } + } + + .junto-header { + width: 276px; + padding: 16px 8px 16px 16px; + font-size: 16px; + text-align: left; + font-weight: bold; + background-color: #000000; + color: #f5f5f5; + box-shadow: 0px 6px 3px rgba(0, 0, 0, 0.23); + + .cursor-toggle { + width: 32px; + height: 32px; + margin-right: 8px; + margin-top: -8px; + float: right; + background: url(<%= asset_path 'cursor_sprite.png' %>) no-repeat; + } + .cursor-toggle:hover { + background-position-x: -32px; + } + .cursor-toggle.active { + background-position-y: -32px; + } + .video-toggle { + width: 32px; + height: 32px; + margin-right: 10px; + margin-top: -8px; + float: right; + background: url(<%= asset_path 'video_sprite.png' %>) no-repeat; + } + .video-toggle:hover { + background-position-x: -32px; + } + .video-toggle.active { + background-position-y: -32px; + } + } + + .participants { + width: 100%; + min-height: 150px; + padding: 16px 0px 16px 0px; + text-align: left; + color: #f5f5f5; + overflow-y: auto; + + .conversation-live { + padding: 5px 10px 5px 10px; + background: #c04f4f; + margin: 5px 10px; + border-radius: 2px; + } + .conversation-live .call-action { + float: right; + cursor: pointer; + color: #EBFF00; + } + .participant { + width: 89%; + padding: 8px 8px 2px 8px; + color: #f5f5f5; + font-family: arial, sans-serif; + font-size: 13px; + line-height: 14px; + + .chat-participant-image { + width: 15%; + float: left; + overflow: hidden; + color: #BBB; + padding-top: 2px; + } + .chat-participant-image img { + width: 32px; + height: 32px; + border-radius: 18px; + } + .chat-participant-name { + width: 53%; + float: left; + font-size: 13px; + font-weight: bold; + margin-top: 12px; + padding: 2px 8px 0; + text-align: left; + } + .chat-participant-invite-call, + .chat-participant-invite-join + { + float: right; + background: #4FC059 url(<%= asset_path 'invitepeer16.png' %>) no-repeat center center; + } + .chat-participant-invite-call.pending, + .chat-participant-invite-join.pending { + background: #dab539 url(<%= asset_path 'ellipsis.gif' %>) no-repeat center center; + } + .chat-participant-participating { + float: right; + margin-top: 14px; + } + .chat-participant-participating .green-dot { + background: #4fc059; + width: 12px; + height: 12px; + border-radius: 6px; + } + } + } + + .chat-header { + width: 276px; + padding: 16px 8px 16px 16px; + font-size: 16px; + text-align: left; + font-weight: bold; + background-color: #000000; + color: #f5f5f5; + box-shadow: 0px 6px 3px rgba(0, 0, 0, 0.23); + + .sound-toggle { + width: 24px; + height: 24px; + margin-right: 10px; + margin-top: -2px; + float: right; + background: url(<%= asset_path 'sound_sprite.png' %>) no-repeat; + } + .sound-toggle:hover { + background-position-x: -24px; + } + .sound-toggle.active { + background-position-y: -24px; + } + } + + $chat_font_size: 16px; + + .chat-input { + min-height: 80px; + width: 88%; + padding: 8px 9% 8px 3%; + font-size: $chat_font_size; + outline: none; + resize: none; + } + + .chat-messages { + width: 100%; + padding: 16px 0px; + overflow-y: auto; + flex-grow: 1; + + .chat-message { + width: 89%; + padding: 8px 8px 2px 8px; + color: #f5f5f5; + font-family: arial, sans-serif; + font-size: $chat_font_size; + line-height: $chat_font_size + 1px; + + a:link { + color: #4fb5c0; + text-decoration: underline; + } + a:visited { + color: #aea9fd; + text-decoration: underline; + } + a:hover { + color: #dab539; + text-decoration: underline; + } + .chat-message-user { + width: 12%; + float: left; + overflow: hidden; + color: #BBB; + padding-top: 2px; + } + .chat-message-user img { + border: 2px solid #424242; + width: 26px; + height: 26px; + border-radius: 14px; + } + .chat-message-meta { + padding: 0 px; + float: left; + } + .chat-message-username { + color: #4fc059; + } + .chat-message-text { + width: 80%; + float: left; + padding: 2px 8px 0; + text-align: left; + word-wrap: break-word; + } + .chat-message-time { + font-size: 10px; + color: #757575; + } + } + } + + .new-message-area { + position: relative; + + .extra-message-options { + height: 20px; + position: absolute; + right: 2px; + bottom: 74px; + + .emoji-picker-button { + font-size: 16px; + line-height: 20px; + cursor: pointer; + padding: 4px; + } + } + } +} diff --git a/frontend/src/Metamaps/Util.js b/frontend/src/Metamaps/Util.js index 1e5c3b66..f35970da 100644 --- a/frontend/src/Metamaps/Util.js +++ b/frontend/src/Metamaps/Util.js @@ -1,6 +1,14 @@ /* global $ */ import { Parser, HtmlRenderer } from 'commonmark' +import { emojiIndex } from 'emoji-mart' +import { escapeRegExp } from 'lodash' + +const emojiToShortcodes = {} +Object.keys(emojiIndex.emojis).forEach(key => { + const emoji = emojiIndex.emojis[key] + emojiToShortcodes[emoji.native] = emoji.colons +}) const Util = { // helper function to determine how many lines are needed @@ -150,6 +158,29 @@ const Util = { canvas.scale(oldAttr.scaleX, oldAttr.scaleY) const newAttr = Util.logCanvasAttributes(canvas) canvas.translate(newAttr.centreCoords.x - oldAttr.centreCoords.x, newAttr.centreCoords.y - oldAttr.centreCoords.y) + }, + removeEmoji: function(withEmoji) { + let text = withEmoji + Object.keys(emojiIndex.emojis).forEach(key => { + const emoji = emojiIndex.emojis[key] + text = text.replace(new RegExp(escapeRegExp(emoji.native), 'g'), emoji.colons) + }) + return text + }, + addEmoji: function(withoutEmoji, opts = { emoticons: false }) { + let text = withoutEmoji + Object.keys(emojiIndex.emojis).forEach(key => { + const emoji = emojiIndex.emojis[key] + text = text.replace(new RegExp(escapeRegExp(emoji.colons), 'g'), emoji.native) + }) + if (opts.emoticons) { + Object.keys(emojiIndex.emoticons).forEach(emoticon => { + const key = emojiIndex.emoticons[emoticon] + const emoji = emojiIndex.emojis[key] + text = text.replace(new RegExp(escapeRegExp(emoticon), 'g'), emoji.native) + }) + } + return text } } diff --git a/frontend/src/components/MapChat/Message.js b/frontend/src/components/MapChat/Message.js index a13bbf3b..ae3507ce 100644 --- a/frontend/src/components/MapChat/Message.js +++ b/frontend/src/components/MapChat/Message.js @@ -1,5 +1,6 @@ import React from 'react' import Autolinker from 'autolinker' +import Util from '../../Metamaps/Util' const linker = new Autolinker({ newWindow: true, truncate: 50, email: false, phone: false }) @@ -19,7 +20,8 @@ function formatDate(created_at) { const Message = props => { const { user_image, user_name, message, created_at, heading } = props - const messageHtml = {__html: linker.link(message)} + const messageHtml = {__html: linker.link(Util.addEmoji(message, { emoticons: false }))} + return (
diff --git a/frontend/src/components/MapChat/NewMessage.js b/frontend/src/components/MapChat/NewMessage.js new file mode 100644 index 00000000..947ec6c6 --- /dev/null +++ b/frontend/src/components/MapChat/NewMessage.js @@ -0,0 +1,68 @@ +import React, { PropTypes, Component } from 'react' +import { Picker } from 'emoji-mart' +import Util from '../../Metamaps/Util' + +class NewMessage extends Component { + constructor(props) { + super(props) + + this.state = { + showEmojiPicker: false + } + } + + toggleEmojiPicker = () => { + this.setState({ showEmojiPicker: !this.state.showEmojiPicker }) + } + + textAreaValue = () => { + return Util.addEmoji(this.props.messageText) + } + + handleClick = (emoji, event) => { + const { messageText } = this.props + this.props.handleChange({ target: { + value: messageText + emoji.colons + }}) + + this.setState({ showEmojiPicker: false }) + } + + render = () => { + return ( +
+ +
+ 🙃 +
+