aboutsummaryrefslogtreecommitdiff
path: root/src/components
diff options
context:
space:
mode:
authorShpuld Shpludson <shp@cock.li>2019-07-26 12:44:32 +0000
committerShpuld Shpludson <shp@cock.li>2019-07-26 12:44:32 +0000
commitd3f6b581d1bbe64d26fceae3f00e9d471ca44dfe (patch)
tree371e786ac95c83d914aa04f22aa9aabfb7b5dc4a /src/components
parent3370dd80dc4644f2bff053b97b18698cd2abb550 (diff)
parent4827e4d972f8ee11e606693e24ae4ca21711c6b1 (diff)
Merge branch 'develop' into 'feat/conversation-muting'
# Conflicts: # src/components/extra_buttons/extra_buttons.js # src/components/extra_buttons/extra_buttons.vue
Diffstat (limited to 'src/components')
-rw-r--r--src/components/emoji-input/suggestor.js21
-rw-r--r--src/components/extra_buttons/extra_buttons.js24
-rw-r--r--src/components/extra_buttons/extra_buttons.vue38
-rw-r--r--src/components/moderation_tools/moderation_tools.js7
-rw-r--r--src/components/moderation_tools/moderation_tools.vue28
-rw-r--r--src/components/popper/popper.scss147
-rw-r--r--src/components/post_status_form/post_status_form.js24
-rw-r--r--src/components/post_status_form/post_status_form.vue24
-rw-r--r--src/components/status/status.js15
-rw-r--r--src/components/status/status.vue5
-rw-r--r--src/components/sticker_picker/sticker_picker.js52
-rw-r--r--src/components/sticker_picker/sticker_picker.vue62
-rw-r--r--src/components/tab_switcher/tab_switcher.js14
-rw-r--r--src/components/tab_switcher/tab_switcher.scss6
-rw-r--r--src/components/user_card/user_card.vue4
-rw-r--r--src/components/user_settings/user_settings.js3
16 files changed, 327 insertions, 147 deletions
diff --git a/src/components/emoji-input/suggestor.js b/src/components/emoji-input/suggestor.js
index a7ac203e..aec5c39d 100644
--- a/src/components/emoji-input/suggestor.js
+++ b/src/components/emoji-input/suggestor.js
@@ -1,20 +1,27 @@
+import { debounce } from 'lodash'
/**
* suggest - generates a suggestor function to be used by emoji-input
* data: object providing source information for specific types of suggestions:
* data.emoji - optional, an array of all emoji available i.e.
* (state.instance.emoji + state.instance.customEmoji)
* data.users - optional, an array of all known users
+ * updateUsersList - optional, a function to search and append to users
*
* Depending on data present one or both (or none) can be present, so if field
* doesn't support user linking you can just provide only emoji.
*/
+
+const debounceUserSearch = debounce((data, input) => {
+ data.updateUsersList(input)
+}, 500, { leading: true, trailing: false })
+
export default data => input => {
const firstChar = input[0]
if (firstChar === ':' && data.emoji) {
return suggestEmoji(data.emoji)(input)
}
if (firstChar === '@' && data.users) {
- return suggestUsers(data.users)(input)
+ return suggestUsers(data)(input)
}
return []
}
@@ -38,9 +45,11 @@ export const suggestEmoji = emojis => input => {
})
}
-export const suggestUsers = users => input => {
+export const suggestUsers = data => input => {
const noPrefix = input.toLowerCase().substr(1)
- return users.filter(
+ const users = data.users
+
+ const newUsers = users.filter(
user =>
user.screen_name.toLowerCase().startsWith(noPrefix) ||
user.name.toLowerCase().startsWith(noPrefix)
@@ -75,5 +84,11 @@ export const suggestUsers = users => input => {
imageUrl: profile_image_url_original,
replacement: '@' + screen_name + ' '
}))
+
+ // BE search users if there are no matches
+ if (newUsers.length === 0 && data.updateUsersList) {
+ debounceUserSearch(data, noPrefix)
+ }
+ return newUsers
/* eslint-enable camelcase */
}
diff --git a/src/components/extra_buttons/extra_buttons.js b/src/components/extra_buttons/extra_buttons.js
index 56b2c41e..8d123293 100644
--- a/src/components/extra_buttons/extra_buttons.js
+++ b/src/components/extra_buttons/extra_buttons.js
@@ -1,35 +1,18 @@
-import Popper from 'vue-popperjs/src/component/popper.js.vue'
-
const ExtraButtons = {
props: [ 'status' ],
- components: {
- Popper
- },
- data () {
- return {
- showDropDown: false,
- showPopper: true
- }
- },
methods: {
deleteStatus () {
- this.refreshPopper()
const confirmed = window.confirm(this.$t('status.delete_confirm'))
if (confirmed) {
this.$store.dispatch('deleteStatus', { id: this.status.id })
}
},
- toggleMenu () {
- this.showDropDown = !this.showDropDown
- },
pinStatus () {
- this.refreshPopper()
this.$store.dispatch('pinStatus', this.status.id)
.then(() => this.$emit('onSuccess'))
.catch(err => this.$emit('onError', err.error.error))
},
unpinStatus () {
- this.refreshPopper()
this.$store.dispatch('unpinStatus', this.status.id)
.then(() => this.$emit('onSuccess'))
.catch(err => this.$emit('onError', err.error.error))
@@ -45,13 +28,6 @@ const ExtraButtons = {
this.$store.dispatch('unmuteConversation', this.status.id)
.then(() => this.$emit('onSuccess'))
.catch(err => this.$emit('onError', err.error.error))
- },
- refreshPopper () {
- this.showPopper = false
- this.showDropDown = false
- setTimeout(() => {
- this.showPopper = true
- })
}
},
computed: {
diff --git a/src/components/extra_buttons/extra_buttons.vue b/src/components/extra_buttons/extra_buttons.vue
index 5027be1b..fc800072 100644
--- a/src/components/extra_buttons/extra_buttons.vue
+++ b/src/components/extra_buttons/extra_buttons.vue
@@ -1,18 +1,13 @@
<template>
- <Popper
- v-if="showPopper"
+ <v-popover
+ v-if="enabled"
trigger="click"
- append-to-body
- :options="{
- placement: 'top',
- modifiers: {
- arrow: { enabled: true },
- offset: { offset: '0, 5px' },
- }
- }"
- @hide="showDropDown = false"
+ placement="top"
+ class="extra-button-popover"
+ :offset="5"
+ :container="false"
>
- <div class="popper-wrapper">
+ <div slot="popover">
<div class="dropdown-menu">
<button
v-if="!status.muted"
@@ -30,6 +25,7 @@
</button>
<button
v-if="!status.pinned && canPin"
+ v-close-popover
class="dropdown-item dropdown-item-icon"
@click.prevent="pinStatus"
>
@@ -37,6 +33,7 @@
</button>
<button
v-if="status.pinned && canPin"
+ v-close-popover
class="dropdown-item dropdown-item-icon"
@click.prevent="unpinStatus"
>
@@ -44,6 +41,7 @@
</button>
<button
v-if="canDelete"
+ v-close-popover
class="dropdown-item dropdown-item-icon"
@click.prevent="deleteStatus"
>
@@ -51,17 +49,10 @@
</button>
</div>
</div>
- <div
- slot="reference"
- class="button-icon"
- @click="toggleMenu"
- >
- <i
- class="icon-ellipsis"
- :class="{'icon-clicked': showDropDown}"
- />
+ <div class="button-icon">
+ <i class="icon-ellipsis" />
</div>
- </Popper>
+ </v-popover>
</template>
<script src="./extra_buttons.js" ></script>
@@ -73,7 +64,8 @@
.icon-ellipsis {
cursor: pointer;
- &:hover, &.icon-clicked {
+ &:hover,
+ .extra-button-popover.open & {
color: $fallback--text;
color: var(--text, $fallback--text);
}
diff --git a/src/components/moderation_tools/moderation_tools.js b/src/components/moderation_tools/moderation_tools.js
index 11de9f93..8aadc8c5 100644
--- a/src/components/moderation_tools/moderation_tools.js
+++ b/src/components/moderation_tools/moderation_tools.js
@@ -1,5 +1,4 @@
import DialogModal from '../dialog_modal/dialog_modal.vue'
-import Popper from 'vue-popperjs/src/component/popper.js.vue'
const FORCE_NSFW = 'mrf_tag:media-force-nsfw'
const STRIP_MEDIA = 'mrf_tag:media-strip'
@@ -29,8 +28,7 @@ const ModerationTools = {
}
},
components: {
- DialogModal,
- Popper
+ DialogModal
},
computed: {
tagsSet () {
@@ -41,9 +39,6 @@ const ModerationTools = {
}
},
methods: {
- toggleMenu () {
- this.showDropDown = !this.showDropDown
- },
hasTag (tagName) {
return this.tagsSet.has(tagName)
},
diff --git a/src/components/moderation_tools/moderation_tools.vue b/src/components/moderation_tools/moderation_tools.vue
index f1ab67a6..d97ca3aa 100644
--- a/src/components/moderation_tools/moderation_tools.vue
+++ b/src/components/moderation_tools/moderation_tools.vue
@@ -1,18 +1,15 @@
<template>
<div>
- <Popper
+ <v-popover
trigger="click"
- append-to-body
- :options="{
- placement: 'bottom-end',
- modifiers: {
- arrow: { enabled: true },
- offset: { offset: '0, 5px' },
- }
- }"
+ class="moderation-tools-popover"
+ :container="false"
+ placement="bottom-end"
+ :offset="5"
+ @show="showDropDown = true"
@hide="showDropDown = false"
>
- <div class="popper-wrapper">
+ <div slot="popover">
<div class="dropdown-menu">
<span v-if="user.is_local">
<button
@@ -127,14 +124,12 @@
</div>
</div>
<button
- slot="reference"
class="btn btn-default btn-block"
:class="{ pressed: showDropDown }"
- @click="toggleMenu"
>
{{ $t('user_card.admin_menu.moderation') }}
</button>
- </Popper>
+ </v-popover>
<portal to="modal">
<DialogModal
v-if="showDeleteUserDialog"
@@ -188,4 +183,11 @@
}
}
+.moderation-tools-popover {
+ height: 100%;
+ .trigger {
+ display: flex !important;
+ height: 100%;
+ }
+}
</style>
diff --git a/src/components/popper/popper.scss b/src/components/popper/popper.scss
index cfc5c8e7..279b01be 100644
--- a/src/components/popper/popper.scss
+++ b/src/components/popper/popper.scss
@@ -1,71 +1,99 @@
@import '../../_variables.scss';
-.popper-wrapper {
+.tooltip.popover {
z-index: 8;
-}
-.popper-wrapper .popper__arrow {
- width: 0;
- height: 0;
- border-style: solid;
- position: absolute;
- margin: 5px;
-}
+ .popover-inner {
+ box-shadow: 1px 1px 4px rgba(0,0,0,.6);
+ box-shadow: var(--panelShadow);
+ border-radius: $fallback--btnRadius;
+ border-radius: var(--btnRadius, $fallback--btnRadius);
+ background-color: $fallback--bg;
+ background-color: var(--bg, $fallback--bg);
+ }
-.popper-wrapper[x-placement^="top"] {
- margin-bottom: 5px;
-}
+ .popover-arrow {
+ width: 0;
+ height: 0;
+ border-style: solid;
+ position: absolute;
+ margin: 5px;
+ border-color: $fallback--bg;
+ border-color: var(--bg, $fallback--bg);
+ z-index: 1;
+ }
-.popper-wrapper[x-placement^="top"] .popper__arrow {
- border-width: 5px 5px 0 5px;
- border-color: $fallback--bg transparent transparent transparent;
- border-color: var(--bg, $fallback--bg) transparent transparent transparent;
- bottom: -5px;
- left: calc(50% - 5px);
- margin-top: 0;
- margin-bottom: 0;
-}
+ &[x-placement^="top"] {
+ margin-bottom: 5px;
+
+ .popover-arrow {
+ border-width: 5px 5px 0 5px;
+ border-left-color: transparent !important;
+ border-right-color: transparent !important;
+ border-bottom-color: transparent !important;
+ bottom: -5px;
+ left: calc(50% - 5px);
+ margin-top: 0;
+ margin-bottom: 0;
+ }
+ }
-.popper-wrapper[x-placement^="bottom"] {
- margin-top: 5px;
-}
+ &[x-placement^="bottom"] {
+ margin-top: 5px;
+
+ .popover-arrow {
+ border-width: 0 5px 5px 5px;
+ border-left-color: transparent !important;
+ border-right-color: transparent !important;
+ border-top-color: transparent !important;
+ top: -5px;
+ left: calc(50% - 5px);
+ margin-top: 0;
+ margin-bottom: 0;
+ }
+ }
-.popper-wrapper[x-placement^="bottom"] .popper__arrow {
- border-width: 0 5px 5px 5px;
- border-color: transparent transparent $fallback--bg transparent;
- border-color: transparent transparent var(--bg, $fallback--bg) transparent;
- top: -5px;
- left: calc(50% - 5px);
- margin-top: 0;
- margin-bottom: 0;
-}
+ &[x-placement^="right"] {
+ margin-left: 5px;
+
+ .popover-arrow {
+ border-width: 5px 5px 5px 0;
+ border-left-color: transparent !important;
+ border-top-color: transparent !important;
+ border-bottom-color: transparent !important;
+ left: -5px;
+ top: calc(50% - 5px);
+ margin-left: 0;
+ margin-right: 0;
+ }
+ }
-.popper-wrapper[x-placement^="right"] {
- margin-left: 5px;
-}
+ &[x-placement^="left"] {
+ margin-right: 5px;
-.popper-wrapper[x-placement^="right"] .popper__arrow {
- border-width: 5px 5px 5px 0;
- border-color: transparent $fallback--bg transparent transparent;
- border-color: transparent var(--bg, $fallback--bg) transparent transparent;
- left: -5px;
- top: calc(50% - 5px);
- margin-left: 0;
- margin-right: 0;
-}
+ .popover-arrow {
+ border-width: 5px 0 5px 5px;
+ border-top-color: transparent !important;
+ border-right-color: transparent !important;
+ border-bottom-color: transparent !important;
+ right: -5px;
+ top: calc(50% - 5px);
+ margin-left: 0;
+ margin-right: 0;
+ }
+ }
-.popper-wrapper[x-placement^="left"] {
- margin-right: 5px;
-}
+ &[aria-hidden='true'] {
+ visibility: hidden;
+ opacity: 0;
+ transition: opacity .15s, visibility .15s;
+ }
-.popper-wrapper[x-placement^="left"] .popper__arrow {
- border-width: 5px 0 5px 5px;
- border-color: transparent transparent transparent $fallback--bg;
- border-color: transparent transparent transparent var(--bg, $fallback--bg);
- right: -5px;
- top: calc(50% - 5px);
- margin-left: 0;
- margin-right: 0;
+ &[aria-hidden='false'] {
+ visibility: visible;
+ opacity: 1;
+ transition: opacity .15s;
+ }
}
.dropdown-menu {
@@ -76,13 +104,6 @@
list-style: none;
max-width: 100vw;
z-index: 10;
- box-shadow: 1px 1px 4px rgba(0,0,0,.6);
- box-shadow: var(--panelShadow);
- border: none;
- border-radius: $fallback--btnRadius;
- border-radius: var(--btnRadius, $fallback--btnRadius);
- background-color: $fallback--bg;
- background-color: var(--bg, $fallback--bg);
.dropdown-divider {
height: 0;
diff --git a/src/components/post_status_form/post_status_form.js b/src/components/post_status_form/post_status_form.js
index ef6b0fce..40bbf6d4 100644
--- a/src/components/post_status_form/post_status_form.js
+++ b/src/components/post_status_form/post_status_form.js
@@ -3,6 +3,7 @@ import MediaUpload from '../media_upload/media_upload.vue'
import ScopeSelector from '../scope_selector/scope_selector.vue'
import EmojiInput from '../emoji-input/emoji-input.vue'
import PollForm from '../poll/poll_form.vue'
+import StickerPicker from '../sticker_picker/sticker_picker.vue'
import fileTypeService from '../../services/file_type/file_type.service.js'
import { reject, map, uniqBy } from 'lodash'
import suggestor from '../emoji-input/suggestor.js'
@@ -34,6 +35,7 @@ const PostStatusForm = {
MediaUpload,
EmojiInput,
PollForm,
+ StickerPicker,
ScopeSelector
},
mounted () {
@@ -82,7 +84,8 @@ const PostStatusForm = {
contentType
},
caret: 0,
- pollFormVisible: false
+ pollFormVisible: false,
+ stickerPickerVisible: false
}
},
computed: {
@@ -104,7 +107,8 @@ const PostStatusForm = {
...this.$store.state.instance.emoji,
...this.$store.state.instance.customEmoji
],
- users: this.$store.state.users.users
+ users: this.$store.state.users.users,
+ updateUsersList: (input) => this.$store.dispatch('searchUsers', input)
})
},
emojiSuggestor () {
@@ -157,6 +161,12 @@ const PostStatusForm = {
safeDMEnabled () {
return this.$store.state.instance.safeDM
},
+ stickersAvailable () {
+ if (this.$store.state.instance.stickers) {
+ return this.$store.state.instance.stickers.length > 0
+ }
+ return 0
+ },
pollsAvailable () {
return this.$store.state.instance.pollsAvailable &&
this.$store.state.instance.pollLimits.max_options >= 2
@@ -212,6 +222,7 @@ const PostStatusForm = {
poll: {}
}
this.pollFormVisible = false
+ this.stickerPickerVisible = false
this.$refs.mediaUpload.clearFile()
this.clearPollForm()
this.$emit('posted')
@@ -228,6 +239,7 @@ const PostStatusForm = {
addMediaFile (fileInfo) {
this.newStatus.files.push(fileInfo)
this.enableSubmit()
+ this.stickerPickerVisible = false
},
removeMediaFile (fileInfo) {
let index = this.newStatus.files.indexOf(fileInfo)
@@ -287,6 +299,14 @@ const PostStatusForm = {
changeVis (visibility) {
this.newStatus.visibility = visibility
},
+ toggleStickerPicker () {
+ this.stickerPickerVisible = !this.stickerPickerVisible
+ },
+ clearStickerPicker () {
+ if (this.$refs.stickerPicker) {
+ this.$refs.stickerPicker.clear()
+ }
+ },
togglePollForm () {
this.pollFormVisible = !this.pollFormVisible
},
diff --git a/src/components/post_status_form/post_status_form.vue b/src/components/post_status_form/post_status_form.vue
index 1f389eda..d29d47e4 100644
--- a/src/components/post_status_form/post_status_form.vue
+++ b/src/components/post_status_form/post_status_form.vue
@@ -158,6 +158,17 @@
@upload-failed="uploadFailed"
/>
<div
+ v-if="stickersAvailable"
+ class="sticker-icon"
+ >
+ <i
+ :title="$t('stickers.add_sticker')"
+ class="icon-picture btn btn-default"
+ :class="{ selected: stickerPickerVisible }"
+ @click="toggleStickerPicker"
+ />
+ </div>
+ <div
v-if="pollsAvailable"
class="poll-icon"
>
@@ -169,7 +180,6 @@
/>
</div>
</div>
-
<button
v-if="posting"
disabled
@@ -248,6 +258,11 @@
<label for="filesSensitive">{{ $t('post_status.attachments_sensitive') }}</label>
</div>
</form>
+ <sticker-picker
+ v-if="stickerPickerVisible"
+ ref="stickerPicker"
+ @uploaded="addMediaFile"
+ />
</div>
</template>
@@ -310,7 +325,7 @@
}
}
- .poll-icon {
+ .poll-icon, .sticker-icon {
font-size: 26px;
flex: 1;
@@ -320,6 +335,11 @@
}
}
+ .sticker-icon {
+ flex: 0;
+ min-width: 50px;
+ }
+
.icon-chart-bar {
cursor: pointer;
}
diff --git a/src/components/status/status.js b/src/components/status/status.js
index 7911d40d..3c172e5b 100644
--- a/src/components/status/status.js
+++ b/src/components/status/status.js
@@ -110,8 +110,9 @@ const Status = {
},
muteWordHits () {
const statusText = this.status.text.toLowerCase()
+ const statusSummary = this.status.summary.toLowerCase()
const hits = filter(this.muteWords, (muteWord) => {
- return statusText.includes(muteWord.toLowerCase())
+ return statusText.includes(muteWord.toLowerCase()) || statusSummary.includes(muteWord.toLowerCase())
})
return hits
@@ -280,6 +281,11 @@ const Status = {
},
tags () {
return this.status.tags.filter(tagObj => tagObj.hasOwnProperty('name')).map(tagObj => tagObj.name).join(' ')
+ },
+ hidePostStats () {
+ return typeof this.$store.state.config.hidePostStats === 'undefined'
+ ? this.$store.state.instance.hidePostStats
+ : this.$store.state.config.hidePostStats
}
},
components: {
@@ -316,11 +322,8 @@ const Status = {
this.error = undefined
},
linkClicked (event) {
- let { target } = event
- if (target.tagName === 'SPAN') {
- target = target.parentNode
- }
- if (target.tagName === 'A') {
+ const target = event.target.closest('.status-content a')
+ if (target) {
if (target.className.match(/mention/)) {
const href = target.href
const attn = this.status.attentions.find(attn => mentionMatchesUrl(attn, href))
diff --git a/src/components/status/status.vue b/src/components/status/status.vue
index 30969256..ab506632 100644
--- a/src/components/status/status.vue
+++ b/src/components/status/status.vue
@@ -344,7 +344,7 @@
<transition name="fade">
<div
- v-if="isFocused && combinedFavsAndRepeatsUsers.length > 0"
+ v-if="!hidePostStats && isFocused && combinedFavsAndRepeatsUsers.length > 0"
class="favs-repeated-users"
>
<div class="stats">
@@ -820,11 +820,12 @@ $status-margin: 0.75em;
}
.status-actions {
+ position: relative;
width: 100%;
display: flex;
margin-top: $status-margin;
- div, favorite-button {
+ > * {
max-width: 4em;
flex: 1;
}
diff --git a/src/components/sticker_picker/sticker_picker.js b/src/components/sticker_picker/sticker_picker.js
new file mode 100644
index 00000000..a6dcded3
--- /dev/null
+++ b/src/components/sticker_picker/sticker_picker.js
@@ -0,0 +1,52 @@
+/* eslint-env browser */
+import statusPosterService from '../../services/status_poster/status_poster.service.js'
+import TabSwitcher from '../tab_switcher/tab_switcher.js'
+
+const StickerPicker = {
+ components: [
+ TabSwitcher
+ ],
+ data () {
+ return {
+ meta: {
+ stickers: []
+ },
+ path: ''
+ }
+ },
+ computed: {
+ pack () {
+ return this.$store.state.instance.stickers || []
+ }
+ },
+ methods: {
+ clear () {
+ this.meta = {
+ stickers: []
+ }
+ },
+ pick (sticker, name) {
+ const store = this.$store
+ // TODO remove this workaround by finding a way to bypass reuploads
+ fetch(sticker)
+ .then((res) => {
+ res.blob().then((blob) => {
+ var file = new File([blob], name, { mimetype: 'image/png' })
+ var formData = new FormData()
+ formData.append('file', file)
+ statusPosterService.uploadMedia({ store, formData })
+ .then((fileData) => {
+ this.$emit('uploaded', fileData)
+ this.clear()
+ }, (error) => {
+ console.warn("Can't attach sticker")
+ console.warn(error)
+ this.$emit('upload-failed', 'default')
+ })
+ })
+ })
+ }
+ }
+}
+
+export default StickerPicker
diff --git a/src/components/sticker_picker/sticker_picker.vue b/src/components/sticker_picker/sticker_picker.vue
new file mode 100644
index 00000000..938204c8
--- /dev/null
+++ b/src/components/sticker_picker/sticker_picker.vue
@@ -0,0 +1,62 @@
+<template>
+ <div
+ class="sticker-picker"
+ >
+ <div
+ class="sticker-picker-panel"
+ >
+ <tab-switcher
+ :render-only-focused="true"
+ >
+ <div
+ v-for="stickerpack in pack"
+ :key="stickerpack.path"
+ :image-tooltip="stickerpack.meta.title"
+ :image="stickerpack.path + stickerpack.meta.tabIcon"
+ class="sticker-picker-content"
+ >
+ <div
+ v-for="sticker in stickerpack.meta.stickers"
+ :key="sticker"
+ class="sticker"
+ @click="pick(stickerpack.path + sticker, stickerpack.meta.title)"
+ >
+ <img
+ :src="stickerpack.path + sticker"
+ >
+ </div>
+ </div>
+ </tab-switcher>
+ </div>
+ </div>
+</template>
+
+<script src="./sticker_picker.js"></script>
+
+<style lang="scss">
+@import '../../_variables.scss';
+
+.sticker-picker {
+ .sticker-picker-panel {
+ display: inline-block;
+ width: 100%;
+ .sticker-picker-content {
+ max-height: 300px;
+ overflow-y: scroll;
+ overflow-x: auto;
+ .sticker {
+ display: inline-block;
+ width: 20%;
+ height: 20%;
+ img {
+ width: 100%;
+ &:hover {
+ filter: drop-shadow(0 0 5px var(--link, $fallback--link));
+ }
+ }
+ }
+ }
+ }
+}
+
+</style>
diff --git a/src/components/tab_switcher/tab_switcher.js b/src/components/tab_switcher/tab_switcher.js
index 67835231..a5fe019c 100644
--- a/src/components/tab_switcher/tab_switcher.js
+++ b/src/components/tab_switcher/tab_switcher.js
@@ -45,7 +45,19 @@ export default Vue.component('tab-switcher', {
classesTab.push('active')
classesWrapper.push('active')
}
-
+ if (slot.data.attrs.image) {
+ return (
+ <div class={ classesWrapper.join(' ')}>
+ <button
+ disabled={slot.data.attrs.disabled}
+ onClick={this.activateTab(index)}
+ class={classesTab.join(' ')}>
+ <img src={slot.data.attrs.image} title={slot.data.attrs['image-tooltip']}/>
+ {slot.data.attrs.label ? '' : slot.data.attrs.label}
+ </button>
+ </div>
+ )
+ }
return (
<div class={ classesWrapper.join(' ')}>
<button
diff --git a/src/components/tab_switcher/tab_switcher.scss b/src/components/tab_switcher/tab_switcher.scss
index f7449439..4eeb42e0 100644
--- a/src/components/tab_switcher/tab_switcher.scss
+++ b/src/components/tab_switcher/tab_switcher.scss
@@ -53,6 +53,12 @@
background: transparent;
z-index: 5;
}
+
+ img {
+ max-height: 26px;
+ vertical-align: top;
+ margin-top: -5px;
+ }
}
&:not(.active) {
diff --git a/src/components/user_card/user_card.vue b/src/components/user_card/user_card.vue
index f987fbbb..9e142480 100644
--- a/src/components/user_card/user_card.vue
+++ b/src/components/user_card/user_card.vue
@@ -283,7 +283,6 @@
.user-card {
background-size: cover;
- overflow: hidden;
.panel-heading {
padding: .5em 0;
@@ -298,6 +297,8 @@
word-wrap: break-word;
background: linear-gradient(to bottom, rgba(0, 0, 0, 0), $fallback--bg 80%);
background: linear-gradient(to bottom, rgba(0, 0, 0, 0), var(--bg, $fallback--bg) 80%);
+ border-bottom-right-radius: inherit;
+ border-bottom-left-radius: inherit;
}
p {
@@ -503,6 +504,7 @@
}
}
.user-interactions {
+ position: relative;
display: flex;
flex-flow: row wrap;
justify-content: space-between;
diff --git a/src/components/user_settings/user_settings.js b/src/components/user_settings/user_settings.js
index 0c3b2aef..b5a7f0df 100644
--- a/src/components/user_settings/user_settings.js
+++ b/src/components/user_settings/user_settings.js
@@ -91,7 +91,8 @@ const UserSettings = {
...this.$store.state.instance.emoji,
...this.$store.state.instance.customEmoji
],
- users: this.$store.state.users.users
+ users: this.$store.state.users.users,
+ updateUsersList: (input) => this.$store.dispatch('searchUsers', input)
})
},
emojiSuggestor () {