Merge branch 'emoji-selector-update' into shigusegubu

* emoji-selector-update:
  autoscroll post form on typing + some minor improvements
  split spam mode into two separate options (one in settings page)
  Apply suggestion to src/components/emoji_input/emoji_input.js
  changelog
  Update docs/USER_GUIDE.md
  docs update
  unit test for emoji input, for now covering only insertion mechanism
This commit is contained in:
Henry Jameson 2019-09-23 22:13:39 +03:00
commit 3364c8fe01
14 changed files with 204 additions and 25 deletions

View file

@ -64,7 +64,6 @@ const EmojiInput = {
},
hideEmojiButton: {
/**
enableStickerPicker: {
* intended to use with external picker trigger, i.e. you have a button outside
* input that will open up the picker, see triggerShowPicker()
*/
@ -90,7 +89,7 @@ const EmojiInput = {
blurTimeout: null,
showPicker: false,
temporarilyHideSuggestions: false,
spamMode: false,
keepOpen: false,
disableClickOutside: false
}
},
@ -98,6 +97,9 @@ const EmojiInput = {
EmojiPicker
},
computed: {
padEmoji () {
return this.$store.state.config.padEmoji
},
suggestions () {
const firstchar = this.textAtCaret.charAt(0)
if (this.textAtCaret === firstchar) { return [] }
@ -177,7 +179,7 @@ const EmojiInput = {
this.$emit('input', newValue)
this.caret = 0
},
insert ({ insertion, spamMode }) {
insert ({ insertion, keepOpen }) {
const before = this.value.substring(0, this.caret) || ''
const after = this.value.substring(this.caret) || ''
@ -196,8 +198,8 @@ const EmojiInput = {
* them, masto seem to be rendering :emoji::emoji: correctly now so why not
*/
const isSpaceRegex = /\s/
const spaceBefore = !isSpaceRegex.exec(before.slice(-1)) && before.length && !spamMode > 0 ? ' ' : ''
const spaceAfter = !isSpaceRegex.exec(after[0]) && !spamMode ? ' ' : ''
const spaceBefore = !isSpaceRegex.exec(before.slice(-1)) && before.length && this.padEmoji > 0 ? ' ' : ''
const spaceAfter = !isSpaceRegex.exec(after[0]) && this.padEmoji ? ' ' : ''
const newValue = [
before,
@ -206,13 +208,15 @@ const EmojiInput = {
spaceAfter,
after
].join('')
this.spamMode = spamMode
this.keepOpen = keepOpen
this.$emit('input', newValue)
const position = this.caret + (insertion + spaceAfter + spaceBefore).length
if (!keepOpen) {
this.input.elm.focus()
}
this.$nextTick(function () {
// Re-focus inputbox after clicking suggestion
this.input.elm.focus()
// Set selection right after the replacement instead of the very end
this.input.elm.setSelectionRange(position, position)
this.caret = position
@ -284,7 +288,7 @@ const EmojiInput = {
this.blurTimeout = null
}
if (!this.spamMode) {
if (!this.keepOpen) {
this.showPicker = false
}
this.focused = true

View file

@ -18,7 +18,7 @@ const EmojiPicker = {
activeGroup: 'custom',
showingStickers: false,
groupsScrolledClass: 'scrolled-top',
spamMode: false
keepOpen: false
}
},
components: {
@ -27,7 +27,7 @@ const EmojiPicker = {
methods: {
onEmoji (emoji) {
const value = emoji.imageUrl ? `:${emoji.displayText}:` : emoji.replacement
this.$emit('emoji', { insertion: value, spamMode: this.spamMode })
this.$emit('emoji', { insertion: value, keepOpen: this.keepOpen })
},
highlight (key) {
const ref = this.$refs['group-' + key]

View file

@ -10,11 +10,11 @@
margin: 0 !important;
z-index: 1;
.spam-mode {
.keep-open {
padding: 7px;
line-height: normal;
}
.spam-mode-label {
.keep-open-label {
padding: 0 7px;
display: flex;
}

View file

@ -76,16 +76,16 @@
</div>
</div>
<div
class="spam-mode"
class="keep-open"
>
<input
:id="labelKey + 'spam-mode'"
v-model="spamMode"
:id="labelKey + 'keep-open'"
v-model="keepOpen"
type="checkbox"
>
<label class="spam-mode-label" :for="labelKey + 'spam-mode'">
<div class="spam-mode-label-text">
{{ $t('emoji.spam') }}
<label class="keep-open-label" :for="labelKey + 'keep-open'">
<div class="keep-open-label-text">
{{ $t('emoji.keep_open') }}
</div>
</label>
</div>

View file

@ -249,6 +249,7 @@ const PostStatusForm = {
return fileTypeService.fileType(fileInfo.mimetype)
},
paste (e) {
this.resize()
if (e.clipboardData.files.length > 0) {
// prevent pasting of file as text
e.preventDefault()
@ -267,6 +268,11 @@ const PostStatusForm = {
fileDrag (e) {
e.dataTransfer.dropEffect = 'copy'
},
onEmojiInputInput (e) {
this.$nextTick(() => {
this.resize(this.$refs['textarea'])
})
},
resize (e) {
const target = e.target || e
if (!(target instanceof window.Element)) { return }
@ -275,12 +281,25 @@ const PostStatusForm = {
// Remove "px" at the end of the values
const vertPadding = Number(topPaddingStr.substr(0, topPaddingStr.length - 2)) +
Number(bottomPaddingStr.substr(0, bottomPaddingStr.length - 2))
const oldValue = Number((/([0-9.]+)px/.exec(target.style.height || '') || [])[1])
// Auto is needed to make textbox shrink when removing lines
target.style.height = 'auto'
target.style.height = `${target.scrollHeight - vertPadding}px`
const newValue = target.scrollHeight - vertPadding
target.style.height = `${newValue}px`
const scroller = this.$el.closest('.sidebar-scroller') ||
this.$el.closest('.post-form-modal-view') ||
window
const delta = newValue - oldValue || 0
if (target.value === '') {
target.style.height = null
} else {
/* For some reason this doens't _exactly_ work on mobile post form when typing
* but it works when adding emojis. Supposedly, removing the "height = auto"
* line helps with that but it obviously breaks the autoheight.
*/
scroller.scrollBy(0, delta)
}
this.$refs['emoji-input'].resize()
},
showEmojiPicker () {
this.$refs['textarea'].focus()

View file

@ -81,6 +81,7 @@
enable-emoji-picker
hide-emoji-button
enable-sticker-picker
@input="onEmojiInputInput"
@sticker-uploaded="addMediaFile"
@sticker-upload-failed="uploadFailed"
>
@ -95,7 +96,8 @@
@keyup.ctrl.enter="postStatus(newStatus)"
@drop="fileDrop"
@dragover.prevent="fileDrag"
@input="resize"
@keydown.exact="resize"
@compositionupdate="resize"
@paste="paste"
/>
<p
@ -489,10 +491,6 @@
box-sizing: content-box;
}
.form-post-body:focus {
min-height: 48px;
}
.main-input {
position: relative;
}

View file

@ -16,6 +16,7 @@ const settings = {
return {
hideAttachmentsLocal: user.hideAttachments,
padEmojiLocal: user.padEmoji,
hideAttachmentsInConvLocal: user.hideAttachmentsInConv,
maxThumbnails: user.maxThumbnails,
hideNsfwLocal: user.hideNsfw,
@ -127,6 +128,9 @@ const settings = {
hideAttachmentsLocal (value) {
this.$store.dispatch('setOption', { name: 'hideAttachments', value })
},
padEmojiLocal (value) {
this.$store.dispatch('setOption', { name: 'padEmoji', value })
},
hideAttachmentsInConvLocal (value) {
this.$store.dispatch('setOption', { name: 'hideAttachmentsInConv', value })
},

View file

@ -198,6 +198,14 @@
>
<label for="autohideFloatingPostButton">{{ $t('settings.autohide_floating_post_button') }}</label>
</li>
<li>
<input
id="padEmoji"
v-model="padEmojiLocal"
type="checkbox"
>
<label for="padEmoji">{{ $t('settings.pad_emoji') }}</label>
</li>
</ul>
</div>