From b97a03383990d54573bd5e68393a1ad11e33608b Mon Sep 17 00:00:00 2001 From: jared Date: Mon, 25 Mar 2019 22:38:15 -0400 Subject: [PATCH 1/4] #255 - add emoji input component --- src/components/emoji-input/emoji-input.js | 106 ++++++++++++++++++ src/components/emoji-input/emoji-input.vue | 99 ++++++++++++++++ .../post_status_form/post_status_form.js | 4 +- .../post_status_form/post_status_form.vue | 5 +- 4 files changed, 211 insertions(+), 3 deletions(-) create mode 100644 src/components/emoji-input/emoji-input.js create mode 100644 src/components/emoji-input/emoji-input.vue diff --git a/src/components/emoji-input/emoji-input.js b/src/components/emoji-input/emoji-input.js new file mode 100644 index 00000000..56414358 --- /dev/null +++ b/src/components/emoji-input/emoji-input.js @@ -0,0 +1,106 @@ +import Completion from '../../services/completion/completion.js' +import { take, filter, map } from 'lodash' + +const EmojiInput = { + props: [ + 'value', + 'placeholder', + 'type' + ], + data () { + return { + highlighted: 0, + caret: 0 + } + }, + computed: { + suggestions () { + const firstchar = this.textAtCaret.charAt(0) + if (firstchar === ':') { + if (this.textAtCaret === ':') { return } + const matchedEmoji = filter(this.emoji.concat(this.customEmoji), (emoji) => emoji.shortcode.startsWith(this.textAtCaret.slice(1))) + if (matchedEmoji.length <= 0) { + return false + } + return map(take(matchedEmoji, 5), ({shortcode, image_url, utf}, index) => ({ + shortcode: `:${shortcode}:`, + utf: utf || '', + // eslint-disable-next-line camelcase + img: utf ? '' : this.$store.state.instance.server + image_url, + highlighted: index === this.highlighted + })) + } else { + return false + } + }, + textAtCaret () { + return (this.wordAtCaret || {}).word || '' + }, + wordAtCaret () { + const word = Completion.wordAtPosition(this.value, this.caret - 1) || {} + return word + }, + emoji () { + return this.$store.state.instance.emoji || [] + }, + customEmoji () { + return this.$store.state.instance.customEmoji || [] + } + }, + methods: { + replace (replacement) { + const newValue = Completion.replaceWord(this.value, this.wordAtCaret, replacement) + this.$emit('input', newValue) + this.caret = 0 + }, + replaceEmoji (e) { + const len = this.suggestions.length || 0 + if (this.textAtCaret === ':' || e.ctrlKey) { return } + if (len > 0) { + e.preventDefault() + const emoji = this.suggestions[this.highlighted] + const replacement = emoji.utf || (emoji.shortcode + ' ') + const newValue = Completion.replaceWord(this.value, this.wordAtCaret, replacement) + this.$emit('input', newValue) + this.caret = 0 + this.highlighted = 0 + } + }, + cycleBackward (e) { + const len = this.suggestions.length || 0 + if (len > 0) { + e.preventDefault() + this.highlighted -= 1 + if (this.highlighted < 0) { + this.highlighted = this.suggestions.length - 1 + } + } else { + this.highlighted = 0 + } + }, + cycleForward (e) { + const len = this.suggestions.length || 0 + if (len > 0) { + if (e.shiftKey) { return } + e.preventDefault() + this.highlighted += 1 + if (this.highlighted >= len) { + this.highlighted = 0 + } + } else { + this.highlighted = 0 + } + }, + onKeydown (e) { + e.stopPropagation() + }, + onInput (e) { + this.$emit('input', e.target.value) + }, + setCaret ({target: {selectionStart}}) { + this.caret = selectionStart + } + } +} + +export default EmojiInput diff --git a/src/components/emoji-input/emoji-input.vue b/src/components/emoji-input/emoji-input.vue new file mode 100644 index 00000000..95606305 --- /dev/null +++ b/src/components/emoji-input/emoji-input.vue @@ -0,0 +1,99 @@ + + + + + diff --git a/src/components/post_status_form/post_status_form.js b/src/components/post_status_form/post_status_form.js index c5f30ca6..229aefb7 100644 --- a/src/components/post_status_form/post_status_form.js +++ b/src/components/post_status_form/post_status_form.js @@ -1,5 +1,6 @@ import statusPoster from '../../services/status_poster/status_poster.service.js' import MediaUpload from '../media_upload/media_upload.vue' +import EmojiInput from '../emoji-input/emoji-input.vue' import fileTypeService from '../../services/file_type/file_type.service.js' import Completion from '../../services/completion/completion.js' import { take, filter, reject, map, uniqBy } from 'lodash' @@ -28,7 +29,8 @@ const PostStatusForm = { 'subject' ], components: { - MediaUpload + MediaUpload, + EmojiInput }, mounted () { this.resize(this.$refs.textarea) diff --git a/src/components/post_status_form/post_status_form.vue b/src/components/post_status_form/post_status_form.vue index 612f87c1..9d449b74 100644 --- a/src/components/post_status_form/post_status_form.vue +++ b/src/components/post_status_form/post_status_form.vue @@ -10,12 +10,13 @@ {{ $t('post_status.account_not_locked_warning_link') }}

{{ $t('post_status.direct_warning') }}

- + class="form-cw" + />
+

From 6dc2cedab07d14ef796640644c8b7ce6ec480665 Mon Sep 17 00:00:00 2001 From: jared Date: Tue, 26 Mar 2019 13:42:27 -0400 Subject: [PATCH 3/4] #255 - clean up user settings page with self-closing html tags --- src/components/user_settings/user_settings.vue | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/src/components/user_settings/user_settings.vue b/src/components/user_settings/user_settings.vue index 27c2f47d..52df143c 100644 --- a/src/components/user_settings/user_settings.vue +++ b/src/components/user_settings/user_settings.vue @@ -70,7 +70,7 @@

{{$t('settings.avatar')}}

{{$t('settings.avatar_size_instruction')}}

{{$t('settings.current_avatar')}}

- +

{{$t('settings.set_new_avatar')}}

@@ -78,12 +78,11 @@

{{$t('settings.profile_banner')}}

{{$t('settings.current_profile_banner')}}

- +

{{$t('settings.set_new_profile_banner')}}

- - +
- +
@@ -95,10 +94,9 @@

{{$t('settings.profile_background')}}

{{$t('settings.set_new_profile_background')}}

- - +
- +
@@ -174,7 +172,7 @@

{{$t('settings.follow_import')}}

{{$t('settings.import_followers_from_a_csv_file')}}

- +
From 8fe9101f0b134978212bf05ed6e73894f47c617e Mon Sep 17 00:00:00 2001 From: jared Date: Tue, 26 Mar 2019 14:53:27 -0400 Subject: [PATCH 4/4] #255 - clean up autocomplete form --- src/App.scss | 51 +++++++++++++++ src/components/emoji-input/emoji-input.vue | 51 --------------- .../post_status_form/post_status_form.vue | 65 ++++--------------- 3 files changed, 63 insertions(+), 104 deletions(-) diff --git a/src/App.scss b/src/App.scss index 244b3474..ae068e4f 100644 --- a/src/App.scss +++ b/src/App.scss @@ -767,3 +767,54 @@ nav { .btn.btn-default { min-height: 28px; } + +.autocomplete { + &-panel { + position: relative; + + &-body { + margin: 0 0.5em 0 0.5em; + border-radius: $fallback--tooltipRadius; + border-radius: var(--tooltipRadius, $fallback--tooltipRadius); + position: absolute; + z-index: 1; + box-shadow: 1px 2px 4px rgba(0, 0, 0, 0.5); + // this doesn't match original but i don't care, making it uniform. + box-shadow: var(--popupShadow); + min-width: 75%; + background: $fallback--bg; + background: var(--bg, $fallback--bg); + color: $fallback--lightText; + color: var(--lightText, $fallback--lightText); + } + } + + &-item { + cursor: pointer; + padding: 0.2em 0.4em 0.2em 0.4em; + border-bottom: 1px solid rgba(0, 0, 0, 0.4); + display: flex; + + img { + width: 24px; + height: 24px; + object-fit: contain; + } + + span { + line-height: 24px; + margin: 0 0.1em 0 0.2em; + } + + small { + margin-left: .5em; + color: $fallback--faint; + color: var(--faint, $fallback--faint); + } + + &.highlighted { + background-color: $fallback--fg; + background-color: var(--lightBg, $fallback--fg); + } + } +} \ No newline at end of file diff --git a/src/components/emoji-input/emoji-input.vue b/src/components/emoji-input/emoji-input.vue index 568bd080..338b77cd 100644 --- a/src/components/emoji-input/emoji-input.vue +++ b/src/components/emoji-input/emoji-input.vue @@ -61,55 +61,4 @@ width: 100%; } } - -.autocomplete { - &-panel { - position: relative; - - &-body { - margin: 0 0.5em 0 0.5em; - border-radius: $fallback--tooltipRadius; - border-radius: var(--tooltipRadius, $fallback--tooltipRadius); - position: absolute; - z-index: 1; - box-shadow: 1px 2px 4px rgba(0, 0, 0, 0.5); - // this doesn't match original but i don't care, making it uniform. - box-shadow: var(--popupShadow); - min-width: 75%; - background: $fallback--bg; - background: var(--bg, $fallback--bg); - color: $fallback--lightText; - color: var(--lightText, $fallback--lightText); - } - } - - &-item { - cursor: pointer; - padding: 0.2em 0.4em 0.2em 0.4em; - border-bottom: 1px solid rgba(0, 0, 0, 0.4); - display: flex; - - img { - width: 24px; - height: 24px; - object-fit: contain; - } - - span { - line-height: 24px; - margin: 0 0.1em 0 0.2em; - } - - small { - margin-left: .5em; - color: $fallback--faint; - color: var(--faint, $fallback--faint); - } - - &.highlighted { - background-color: $fallback--fg; - background-color: var(--lightBg, $fallback--fg); - } - } -} diff --git a/src/components/post_status_form/post_status_form.vue b/src/components/post_status_form/post_status_form.vue index b2a1dc58..9f9f16ba 100644 --- a/src/components/post_status_form/post_status_form.vue +++ b/src/components/post_status_form/post_status_form.vue @@ -56,14 +56,18 @@
-
-
-
-
- - {{candidate.utf}} - {{candidate.screen_name}}{{candidate.name}} -
+
+
+
+ + {{candidate.utf}} + {{candidate.screen_name}}{{candidate.name}}
@@ -262,50 +266,5 @@ cursor: pointer; z-index: 4; } - - .autocomplete-panel { - margin: 0 0.5em 0 0.5em; - border-radius: $fallback--tooltipRadius; - border-radius: var(--tooltipRadius, $fallback--tooltipRadius); - position: absolute; - z-index: 1; - box-shadow: 1px 2px 4px rgba(0, 0, 0, 0.5); - // this doesn't match original but i don't care, making it uniform. - box-shadow: var(--popupShadow); - min-width: 75%; - background: $fallback--bg; - background: var(--bg, $fallback--bg); - color: $fallback--lightText; - color: var(--lightText, $fallback--lightText); - } - - .autocomplete { - cursor: pointer; - padding: 0.2em 0.4em 0.2em 0.4em; - border-bottom: 1px solid rgba(0, 0, 0, 0.4); - display: flex; - - img { - width: 24px; - height: 24px; - object-fit: contain; - } - - span { - line-height: 24px; - margin: 0 0.1em 0 0.2em; - } - - small { - margin-left: .5em; - color: $fallback--faint; - color: var(--faint, $fallback--faint); - } - - &.highlighted { - background-color: $fallback--fg; - background-color: var(--lightBg, $fallback--fg); - } - } }