Compare commits
8 commits
develop
...
experiment
Author | SHA1 | Date | |
---|---|---|---|
|
3cc84a867d | ||
|
8e1182651a | ||
|
7bd18cda64 | ||
|
0ca0e642a4 | ||
|
80220c1b07 | ||
|
159bbed2f9 | ||
|
40ac9ef499 | ||
|
61dcdbf992 |
26 changed files with 362 additions and 315 deletions
|
@ -6,10 +6,7 @@
|
|||
:bound-to="{ x: 'container' }"
|
||||
remove-padding
|
||||
>
|
||||
<div
|
||||
slot="content"
|
||||
class="account-tools-popover"
|
||||
>
|
||||
<template v-slot:content>
|
||||
<div class="dropdown-menu">
|
||||
<template v-if="relationship.following">
|
||||
<button
|
||||
|
@ -59,16 +56,15 @@
|
|||
{{ $t('user_card.message') }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
slot="trigger"
|
||||
class="ellipsis-button"
|
||||
>
|
||||
<FAIcon
|
||||
class="icon"
|
||||
icon="ellipsis-v"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
<template v-slot:trigger>
|
||||
<button class="button-unstyled ellipsis-button">
|
||||
<FAIcon
|
||||
class="icon"
|
||||
icon="ellipsis-v"
|
||||
/>
|
||||
</button>
|
||||
</template>
|
||||
</Popover>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -83,7 +79,6 @@
|
|||
}
|
||||
|
||||
.ellipsis-button {
|
||||
cursor: pointer;
|
||||
width: 2.5em;
|
||||
margin: -0.5em 0;
|
||||
padding: 0.5em 0;
|
||||
|
|
|
@ -23,10 +23,7 @@
|
|||
class="timeline"
|
||||
>
|
||||
<List :items="sortedChatList">
|
||||
<template
|
||||
slot="item"
|
||||
slot-scope="{item}"
|
||||
>
|
||||
<template v-slot:item="{item}">
|
||||
<ChatListItem
|
||||
:key="item.id"
|
||||
:compact="false"
|
||||
|
|
|
@ -50,7 +50,7 @@
|
|||
@show="menuOpened = true"
|
||||
@close="menuOpened = false"
|
||||
>
|
||||
<div slot="content">
|
||||
<template v-slot:content>
|
||||
<div class="dropdown-menu">
|
||||
<button
|
||||
class="button-default dropdown-item dropdown-item-icon"
|
||||
|
@ -59,26 +59,28 @@
|
|||
<FAIcon icon="times" /> {{ $t("chats.delete") }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<button
|
||||
slot="trigger"
|
||||
class="button-default menu-icon"
|
||||
:title="$t('chats.more')"
|
||||
>
|
||||
<FAIcon icon="ellipsis-h" />
|
||||
</button>
|
||||
</template>
|
||||
<template v-slot:trigger>
|
||||
<button
|
||||
class="button-default menu-icon"
|
||||
:title="$t('chats.more')"
|
||||
>
|
||||
<FAIcon icon="ellipsis-h" />
|
||||
</button>
|
||||
</template>
|
||||
</Popover>
|
||||
</div>
|
||||
<StatusContent
|
||||
:status="messageForStatusContent"
|
||||
:full-content="true"
|
||||
>
|
||||
<span
|
||||
slot="footer"
|
||||
class="created-at"
|
||||
>
|
||||
{{ createdAt }}
|
||||
</span>
|
||||
<template v-slot:footer>
|
||||
<span
|
||||
class="created-at"
|
||||
>
|
||||
{{ createdAt }}
|
||||
</span>
|
||||
</template>
|
||||
</StatusContent>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
class="btn button-default"
|
||||
>
|
||||
{{ $t('domain_mute_card.unmute') }}
|
||||
<template slot="progress">
|
||||
<template v-slot:progress>
|
||||
{{ $t('domain_mute_card.unmute_progress') }}
|
||||
</template>
|
||||
</ProgressButton>
|
||||
|
@ -19,7 +19,7 @@
|
|||
class="btn button-default"
|
||||
>
|
||||
{{ $t('domain_mute_card.mute') }}
|
||||
<template slot="progress">
|
||||
<template v-slot:progress>
|
||||
{{ $t('domain_mute_card.mute_progress') }}
|
||||
</template>
|
||||
</ProgressButton>
|
||||
|
|
|
@ -57,6 +57,7 @@ const EmojiInput = {
|
|||
required: true,
|
||||
type: Function
|
||||
},
|
||||
// TODO VUE3: change to modelValue, change 'input' event to 'input'
|
||||
value: {
|
||||
/**
|
||||
* Used for v-model
|
||||
|
@ -143,32 +144,31 @@ const EmojiInput = {
|
|||
}
|
||||
},
|
||||
mounted () {
|
||||
const slots = this.$slots.default
|
||||
if (!slots || slots.length === 0) return
|
||||
const input = slots.find(slot => ['input', 'textarea'].includes(slot.tag))
|
||||
const { root } = this.$refs
|
||||
const input = root.querySelector('.emoji-input > input') || root.querySelector('.emoji-input > textarea')
|
||||
if (!input) return
|
||||
this.input = input
|
||||
this.resize()
|
||||
input.elm.addEventListener('blur', this.onBlur)
|
||||
input.elm.addEventListener('focus', this.onFocus)
|
||||
input.elm.addEventListener('paste', this.onPaste)
|
||||
input.elm.addEventListener('keyup', this.onKeyUp)
|
||||
input.elm.addEventListener('keydown', this.onKeyDown)
|
||||
input.elm.addEventListener('click', this.onClickInput)
|
||||
input.elm.addEventListener('transitionend', this.onTransition)
|
||||
input.elm.addEventListener('input', this.onInput)
|
||||
input.addEventListener('blur', this.onBlur)
|
||||
input.addEventListener('focus', this.onFocus)
|
||||
input.addEventListener('paste', this.onPaste)
|
||||
input.addEventListener('keyup', this.onKeyUp)
|
||||
input.addEventListener('keydown', this.onKeyDown)
|
||||
input.addEventListener('click', this.onClickInput)
|
||||
input.addEventListener('transitionend', this.onTransition)
|
||||
input.addEventListener('input', this.onInput)
|
||||
},
|
||||
unmounted () {
|
||||
const { input } = this
|
||||
if (input) {
|
||||
input.elm.removeEventListener('blur', this.onBlur)
|
||||
input.elm.removeEventListener('focus', this.onFocus)
|
||||
input.elm.removeEventListener('paste', this.onPaste)
|
||||
input.elm.removeEventListener('keyup', this.onKeyUp)
|
||||
input.elm.removeEventListener('keydown', this.onKeyDown)
|
||||
input.elm.removeEventListener('click', this.onClickInput)
|
||||
input.elm.removeEventListener('transitionend', this.onTransition)
|
||||
input.elm.removeEventListener('input', this.onInput)
|
||||
input.removeEventListener('blur', this.onBlur)
|
||||
input.removeEventListener('focus', this.onFocus)
|
||||
input.removeEventListener('paste', this.onPaste)
|
||||
input.removeEventListener('keyup', this.onKeyUp)
|
||||
input.removeEventListener('keydown', this.onKeyDown)
|
||||
input.removeEventListener('click', this.onClickInput)
|
||||
input.removeEventListener('transitionend', this.onTransition)
|
||||
input.removeEventListener('input', this.onInput)
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
|
@ -216,7 +216,7 @@ const EmojiInput = {
|
|||
}, 0)
|
||||
},
|
||||
togglePicker () {
|
||||
this.input.elm.focus()
|
||||
this.input.focus()
|
||||
this.showPicker = !this.showPicker
|
||||
if (this.showPicker) {
|
||||
this.scrollIntoView()
|
||||
|
@ -262,13 +262,13 @@ const EmojiInput = {
|
|||
this.$emit('input', newValue)
|
||||
const position = this.caret + (insertion + spaceAfter + spaceBefore).length
|
||||
if (!keepOpen) {
|
||||
this.input.elm.focus()
|
||||
this.input.focus()
|
||||
}
|
||||
|
||||
this.$nextTick(function () {
|
||||
// Re-focus inputbox after clicking suggestion
|
||||
// Set selection right after the replacement instead of the very end
|
||||
this.input.elm.setSelectionRange(position, position)
|
||||
this.input.setSelectionRange(position, position)
|
||||
this.caret = position
|
||||
})
|
||||
},
|
||||
|
@ -285,9 +285,9 @@ const EmojiInput = {
|
|||
|
||||
this.$nextTick(function () {
|
||||
// Re-focus inputbox after clicking suggestion
|
||||
this.input.elm.focus()
|
||||
this.input.focus()
|
||||
// Set selection right after the replacement instead of the very end
|
||||
this.input.elm.setSelectionRange(position, position)
|
||||
this.input.setSelectionRange(position, position)
|
||||
this.caret = position
|
||||
})
|
||||
e.preventDefault()
|
||||
|
@ -349,7 +349,7 @@ const EmojiInput = {
|
|||
}
|
||||
|
||||
this.$nextTick(() => {
|
||||
const { offsetHeight } = this.input.elm
|
||||
const { offsetHeight } = this.input
|
||||
const { picker } = this.$refs
|
||||
const pickerBottom = picker.$el.getBoundingClientRect().bottom
|
||||
if (pickerBottom > window.innerHeight) {
|
||||
|
@ -414,8 +414,8 @@ const EmojiInput = {
|
|||
|
||||
// Scroll the input element to the position of the cursor
|
||||
this.$nextTick(() => {
|
||||
this.input.elm.blur()
|
||||
this.input.elm.focus()
|
||||
this.input.blur()
|
||||
this.input.focus()
|
||||
})
|
||||
}
|
||||
// Disable suggestions hotkeys if suggestions are hidden
|
||||
|
@ -444,7 +444,7 @@ const EmojiInput = {
|
|||
// de-focuses the element (i.e. default browser behavior)
|
||||
if (key === 'Escape') {
|
||||
if (!this.temporarilyHideSuggestions) {
|
||||
this.input.elm.focus()
|
||||
this.input.focus()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -480,7 +480,7 @@ const EmojiInput = {
|
|||
if (!panel) return
|
||||
const picker = this.$refs.picker.$el
|
||||
const panelBody = this.$refs['panel-body']
|
||||
const { offsetHeight, offsetTop } = this.input.elm
|
||||
const { offsetHeight, offsetTop } = this.input
|
||||
const offsetBottom = offsetTop + offsetHeight
|
||||
|
||||
this.setPlacement(panelBody, panel, offsetBottom)
|
||||
|
@ -494,7 +494,7 @@ const EmojiInput = {
|
|||
|
||||
if (this.placement === 'top' || (this.placement === 'auto' && this.overflowsBottom(container))) {
|
||||
target.style.top = 'auto'
|
||||
target.style.bottom = this.input.elm.offsetHeight + 'px'
|
||||
target.style.bottom = this.input.offsetHeight + 'px'
|
||||
}
|
||||
},
|
||||
overflowsBottom (el) {
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
v-click-outside="onClickOutside"
|
||||
class="emoji-input"
|
||||
:class="{ 'with-picker': !hideEmojiButton }"
|
||||
ref='root'
|
||||
>
|
||||
<slot />
|
||||
<template v-if="enableEmojiPicker">
|
||||
|
|
|
@ -7,10 +7,7 @@
|
|||
:bound-to="{ x: 'container' }"
|
||||
remove-padding
|
||||
>
|
||||
<div
|
||||
slot="content"
|
||||
slot-scope="{close}"
|
||||
>
|
||||
<template v-slot:content="{close}">
|
||||
<div class="dropdown-menu">
|
||||
<button
|
||||
v-if="canMute && !status.thread_muted"
|
||||
|
@ -120,16 +117,15 @@
|
|||
/><span>{{ $t("user_card.report") }}</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<span
|
||||
slot="trigger"
|
||||
class="popover-trigger"
|
||||
>
|
||||
<FAIcon
|
||||
class="fa-scale-110 fa-old-padding"
|
||||
icon="ellipsis-h"
|
||||
/>
|
||||
</span>
|
||||
</template>
|
||||
<template v-slot:trigger>
|
||||
<button class="button-unstyled popover-trigger">
|
||||
<FAIcon
|
||||
class="fa-scale-110 fa-old-padding"
|
||||
icon="ellipsis-h"
|
||||
/>
|
||||
</button>
|
||||
</template>
|
||||
</Popover>
|
||||
</template>
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
@show="setToggled(true)"
|
||||
@close="setToggled(false)"
|
||||
>
|
||||
<div slot="content">
|
||||
<template v-slot:content>
|
||||
<div class="dropdown-menu">
|
||||
<span v-if="user.is_local">
|
||||
<button
|
||||
|
@ -121,26 +121,27 @@
|
|||
</button>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<button
|
||||
slot="trigger"
|
||||
class="btn button-default btn-block moderation-tools-button"
|
||||
:class="{ toggled }"
|
||||
>
|
||||
{{ $t('user_card.admin_menu.moderation') }}
|
||||
<FAIcon icon="chevron-down" />
|
||||
</button>
|
||||
</template>
|
||||
<template v-slot:trigger>
|
||||
<button
|
||||
class="btn button-default btn-block moderation-tools-button"
|
||||
:class="{ toggled }"
|
||||
>
|
||||
{{ $t('user_card.admin_menu.moderation') }}
|
||||
<FAIcon icon="chevron-down" />
|
||||
</button>
|
||||
</template>
|
||||
</Popover>
|
||||
<portal to="modal">
|
||||
<DialogModal
|
||||
v-if="showDeleteUserDialog"
|
||||
:on-cancel="deleteUserDialog.bind(this, false)"
|
||||
>
|
||||
<template slot="header">
|
||||
<template v-slot:header>
|
||||
{{ $t('user_card.admin_menu.delete_user') }}
|
||||
</template>
|
||||
<p>{{ $t('user_card.admin_menu.delete_user_confirmation') }}</p>
|
||||
<template slot="footer">
|
||||
<template v-slot:footer>
|
||||
<button
|
||||
class="btn button-default"
|
||||
@click="deleteUserDialog(false)"
|
||||
|
|
|
@ -2,6 +2,12 @@
|
|||
|
||||
// TODO Copypaste from Status, should unify it somehow
|
||||
.Notification {
|
||||
&:hover {
|
||||
--_still-image-img-visibility: visible;
|
||||
--_still-image-canvas-visibility: hidden;
|
||||
--_still-image-label-visibility: hidden;
|
||||
}
|
||||
|
||||
&.-muted {
|
||||
padding: 0.25em 0.6em;
|
||||
height: 1.2em;
|
||||
|
|
|
@ -5,9 +5,7 @@
|
|||
placement="bottom"
|
||||
:bound-to="{ x: 'container' }"
|
||||
>
|
||||
<template
|
||||
v-slot:content
|
||||
>
|
||||
<template v-slot:content>
|
||||
<div class="dropdown-menu">
|
||||
<button
|
||||
class="button-default dropdown-item"
|
||||
|
@ -66,7 +64,9 @@
|
|||
</div>
|
||||
</template>
|
||||
<template v-slot:trigger>
|
||||
<FAIcon icon="filter" />
|
||||
<button class="button-unstyled">
|
||||
<FAIcon icon="filter" />
|
||||
</button>
|
||||
</template>
|
||||
</Popover>
|
||||
</template>
|
||||
|
|
|
@ -54,7 +54,7 @@ const Popover = {
|
|||
}
|
||||
|
||||
// Popover will be anchored around this element, trigger ref is the container, so
|
||||
// its children are what are inside the slot. Expect only one slot="trigger".
|
||||
// its children are what are inside the slot. Expect only one v-slot:trigger.
|
||||
const anchorEl = (this.$refs.trigger && this.$refs.trigger.children[0]) || this.$el
|
||||
// SVGs don't have offsetWidth/Height, use fallback
|
||||
const anchorWidth = anchorEl.offsetWidth || anchorEl.clientWidth
|
||||
|
|
|
@ -8,10 +8,7 @@
|
|||
remove-padding
|
||||
@show="focusInput"
|
||||
>
|
||||
<div
|
||||
slot="content"
|
||||
slot-scope="{close}"
|
||||
>
|
||||
<template v-slot:content="{close}">
|
||||
<div class="reaction-picker-filter">
|
||||
<input
|
||||
v-model="filterWord"
|
||||
|
@ -41,17 +38,18 @@
|
|||
</span>
|
||||
<div class="reaction-bottom-fader" />
|
||||
</div>
|
||||
</div>
|
||||
<span
|
||||
slot="trigger"
|
||||
class="popover-trigger"
|
||||
:title="$t('tool_tip.add_reaction')"
|
||||
>
|
||||
<FAIcon
|
||||
class="fa-scale-110 fa-old-padding"
|
||||
:icon="['far', 'smile-beam']"
|
||||
/>
|
||||
</span>
|
||||
</template>
|
||||
<template v-slot:trigger>
|
||||
<button
|
||||
class="button-unstyled popover-trigger"
|
||||
:title="$t('tool_tip.add_reaction')"
|
||||
>
|
||||
<FAIcon
|
||||
class="fa-scale-110 fa-old-padding"
|
||||
:icon="['far', 'smile-beam']"
|
||||
/>
|
||||
</button>
|
||||
</template>
|
||||
</Popover>
|
||||
</template>
|
||||
|
||||
|
|
|
@ -24,10 +24,7 @@
|
|||
:items="items"
|
||||
:get-key="getKey"
|
||||
>
|
||||
<template
|
||||
slot="item"
|
||||
slot-scope="{item}"
|
||||
>
|
||||
<template v-slot:item="{item}">
|
||||
<div
|
||||
class="selectable-list-item-inner"
|
||||
:class="{ 'selectable-list-item-selected-inner': isSelected(item) }"
|
||||
|
@ -44,7 +41,7 @@
|
|||
/>
|
||||
</div>
|
||||
</template>
|
||||
<template slot="empty">
|
||||
<template v-slot:empty>
|
||||
<slot name="empty" />
|
||||
</template>
|
||||
</List>
|
||||
|
|
|
@ -6,18 +6,18 @@
|
|||
<Popover
|
||||
trigger="hover"
|
||||
>
|
||||
<span slot="trigger">
|
||||
<template v-slot:trigger>
|
||||
|
||||
<FAIcon
|
||||
icon="wrench"
|
||||
:aria-label="$t('settings.setting_changed')"
|
||||
/>
|
||||
</span>
|
||||
<div
|
||||
slot="content"
|
||||
class="modified-tooltip"
|
||||
>
|
||||
{{ $t('settings.setting_changed') }}
|
||||
</div>
|
||||
</template>
|
||||
<template v-slot:content>
|
||||
<div class="modified-tooltip">
|
||||
{{ $t('settings.setting_changed') }}
|
||||
</div>
|
||||
</template>
|
||||
</Popover>
|
||||
</span>
|
||||
</template>
|
||||
|
|
|
@ -62,20 +62,18 @@
|
|||
:bound-to="{ x: 'container' }"
|
||||
remove-padding
|
||||
>
|
||||
<button
|
||||
slot="trigger"
|
||||
class="btn button-default"
|
||||
:title="$t('general.close')"
|
||||
>
|
||||
<span>{{ $t("settings.file_export_import.backup_restore") }}</span>
|
||||
<FAIcon
|
||||
icon="chevron-down"
|
||||
/>
|
||||
</button>
|
||||
<div
|
||||
slot="content"
|
||||
slot-scope="{close}"
|
||||
>
|
||||
<template v-slot:trigger>
|
||||
<button
|
||||
class="btn button-default"
|
||||
:title="$t('general.close')"
|
||||
>
|
||||
<span>{{ $t("settings.file_export_import.backup_restore") }}</span>
|
||||
<FAIcon
|
||||
icon="chevron-down"
|
||||
/>
|
||||
</button>
|
||||
</template>
|
||||
<template v-slot:content="{close}">
|
||||
<div class="dropdown-menu">
|
||||
<button
|
||||
class="button-default dropdown-item dropdown-item-icon"
|
||||
|
@ -108,7 +106,7 @@
|
|||
/><span>{{ $t("settings.file_export_import.restore_settings") }}</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</Popover>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -10,20 +10,18 @@
|
|||
:query="queryUserIds"
|
||||
:placeholder="$t('settings.search_user_to_block')"
|
||||
>
|
||||
<BlockCard
|
||||
slot-scope="row"
|
||||
:user-id="row.item"
|
||||
/>
|
||||
<template v-slot="row">
|
||||
<BlockCard
|
||||
:user-id="row.item"
|
||||
/>
|
||||
</template>
|
||||
</Autosuggest>
|
||||
</div>
|
||||
<BlockList
|
||||
:refresh="true"
|
||||
:get-key="i => i"
|
||||
>
|
||||
<template
|
||||
slot="header"
|
||||
slot-scope="{selected}"
|
||||
>
|
||||
<template v-slot:header="{selected}">
|
||||
<div class="bulk-actions">
|
||||
<ProgressButton
|
||||
v-if="selected.length > 0"
|
||||
|
@ -31,7 +29,7 @@
|
|||
:click="() => blockUsers(selected)"
|
||||
>
|
||||
{{ $t('user_card.block') }}
|
||||
<template slot="progress">
|
||||
<template v-slot:progress>
|
||||
{{ $t('user_card.block_progress') }}
|
||||
</template>
|
||||
</ProgressButton>
|
||||
|
@ -41,19 +39,16 @@
|
|||
:click="() => unblockUsers(selected)"
|
||||
>
|
||||
{{ $t('user_card.unblock') }}
|
||||
<template slot="progress">
|
||||
<template v-slot:progress>
|
||||
{{ $t('user_card.unblock_progress') }}
|
||||
</template>
|
||||
</ProgressButton>
|
||||
</div>
|
||||
</template>
|
||||
<template
|
||||
slot="item"
|
||||
slot-scope="{item}"
|
||||
>
|
||||
<template v-slot:item="{item}">
|
||||
<BlockCard :user-id="item" />
|
||||
</template>
|
||||
<template slot="empty">
|
||||
<template v-slot:empty>
|
||||
{{ $t('settings.no_blocks') }}
|
||||
</template>
|
||||
</BlockList>
|
||||
|
@ -68,20 +63,18 @@
|
|||
:query="queryUserIds"
|
||||
:placeholder="$t('settings.search_user_to_mute')"
|
||||
>
|
||||
<MuteCard
|
||||
slot-scope="row"
|
||||
:user-id="row.item"
|
||||
/>
|
||||
<template v-slot="row">
|
||||
<MuteCard
|
||||
:user-id="row.item"
|
||||
/>
|
||||
</template>
|
||||
</Autosuggest>
|
||||
</div>
|
||||
<MuteList
|
||||
:refresh="true"
|
||||
:get-key="i => i"
|
||||
>
|
||||
<template
|
||||
slot="header"
|
||||
slot-scope="{selected}"
|
||||
>
|
||||
<template v-slot:header="{selected}">
|
||||
<div class="bulk-actions">
|
||||
<ProgressButton
|
||||
v-if="selected.length > 0"
|
||||
|
@ -89,7 +82,7 @@
|
|||
:click="() => muteUsers(selected)"
|
||||
>
|
||||
{{ $t('user_card.mute') }}
|
||||
<template slot="progress">
|
||||
<template v-slot:progress>
|
||||
{{ $t('user_card.mute_progress') }}
|
||||
</template>
|
||||
</ProgressButton>
|
||||
|
@ -99,19 +92,16 @@
|
|||
:click="() => unmuteUsers(selected)"
|
||||
>
|
||||
{{ $t('user_card.unmute') }}
|
||||
<template slot="progress">
|
||||
<template v-slot:progress>
|
||||
{{ $t('user_card.unmute_progress') }}
|
||||
</template>
|
||||
</ProgressButton>
|
||||
</div>
|
||||
</template>
|
||||
<template
|
||||
slot="item"
|
||||
slot-scope="{item}"
|
||||
>
|
||||
<template v-slot:item="{item}">
|
||||
<MuteCard :user-id="item" />
|
||||
</template>
|
||||
<template slot="empty">
|
||||
<template v-slot:empty>
|
||||
{{ $t('settings.no_mutes') }}
|
||||
</template>
|
||||
</MuteList>
|
||||
|
@ -124,20 +114,18 @@
|
|||
:query="queryKnownDomains"
|
||||
:placeholder="$t('settings.type_domains_to_mute')"
|
||||
>
|
||||
<DomainMuteCard
|
||||
slot-scope="row"
|
||||
:domain="row.item"
|
||||
/>
|
||||
<template v-slot="row">
|
||||
<DomainMuteCard
|
||||
:domain="row.item"
|
||||
/>
|
||||
</template>
|
||||
</Autosuggest>
|
||||
</div>
|
||||
<DomainMuteList
|
||||
:refresh="true"
|
||||
:get-key="i => i"
|
||||
>
|
||||
<template
|
||||
slot="header"
|
||||
slot-scope="{selected}"
|
||||
>
|
||||
<template v-slot:header="{selected}">
|
||||
<div class="bulk-actions">
|
||||
<ProgressButton
|
||||
v-if="selected.length > 0"
|
||||
|
@ -145,19 +133,16 @@
|
|||
:click="() => unmuteDomains(selected)"
|
||||
>
|
||||
{{ $t('domain_mute_card.unmute') }}
|
||||
<template slot="progress">
|
||||
<template v-slot:progress>
|
||||
{{ $t('domain_mute_card.unmute_progress') }}
|
||||
</template>
|
||||
</ProgressButton>
|
||||
</div>
|
||||
</template>
|
||||
<template
|
||||
slot="item"
|
||||
slot-scope="{item}"
|
||||
>
|
||||
<template v-slot:item="{item}">
|
||||
<DomainMuteCard :domain="item" />
|
||||
</template>
|
||||
<template slot="empty">
|
||||
<template v-slot:empty>
|
||||
{{ $t('settings.no_mutes') }}
|
||||
</template>
|
||||
</DomainMuteList>
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
import Vue from 'vue'
|
||||
import Attachment from '../attachment/attachment.vue'
|
||||
import StillImage from '../still-image/still-image.vue'
|
||||
import Poll from '../poll/poll.vue'
|
||||
import Gallery from '../gallery/gallery.vue'
|
||||
import LinkPreview from '../link-preview/link-preview.vue'
|
||||
|
@ -40,10 +42,24 @@ const StatusContent = {
|
|||
showingTall: this.fullContent || (this.inConversation && this.focused),
|
||||
showingLongSubject: false,
|
||||
// not as computed because it sets the initial state which will be changed later
|
||||
expandingSubject: !this.$store.getters.mergedConfig.collapseMessageWithSubject
|
||||
expandingSubject: !this.$store.getters.mergedConfig.collapseMessageWithSubject,
|
||||
stillImages: []
|
||||
}
|
||||
},
|
||||
|
||||
updated () {
|
||||
this.patchEmoji()
|
||||
},
|
||||
mounted () {
|
||||
this.patchEmoji()
|
||||
},
|
||||
beforeDestroy() {
|
||||
this.stillImages.forEach(vm => vm.$destroy())
|
||||
},
|
||||
computed: {
|
||||
stopGifs () {
|
||||
return this.$store.getters.mergedConfig.stopGifs
|
||||
},
|
||||
localCollapseSubjectDefault () {
|
||||
return this.mergedConfig.collapseMessageWithSubject
|
||||
},
|
||||
|
@ -167,6 +183,43 @@ const StatusContent = {
|
|||
LinkPreview
|
||||
},
|
||||
methods: {
|
||||
patchEmoji () {
|
||||
[this.$refs.subject, this.$refs.content].forEach(el => {
|
||||
if (!el) return
|
||||
const imgs = el.querySelectorAll('*:not(.still-image) > img')
|
||||
|
||||
imgs.forEach((img, i) => {
|
||||
// extract relevant info from image
|
||||
// TODO do a better job at "cloning" node and splicing it into a span
|
||||
const { src, title, className } = img
|
||||
// Outer placeholder, thing that will contain stillimage
|
||||
const placeholder = document.createElement('span')
|
||||
// Inner placeholder, this will be REPLACED by stillimage
|
||||
const placeholderInner = document.createElement('span')
|
||||
// Use special classname for emoji, just to be safe
|
||||
placeholder.className = className === 'emoji' ? '__pleromafe_emoji' : 'emoji'
|
||||
// Overall it seems to be easier to use a wrapper and add stuff to it
|
||||
// than to add stuff to component (how??)
|
||||
placeholder.title = title
|
||||
// Insert inner into outer
|
||||
placeholder.appendChild(placeholderInner)
|
||||
// put our placeholder before the image
|
||||
img.parentNode.insertBefore(placeholder, img)
|
||||
|
||||
// Render StillImage into placeholder
|
||||
const opts = {
|
||||
el: placeholder,
|
||||
props: { src }
|
||||
}
|
||||
const vm = new Vue({ el: placeholderInner, render: h => h(StillImage, opts)})
|
||||
this.stillImages.push(vm)
|
||||
|
||||
if (img.className === 'emoji') {
|
||||
img.className = img.className + ' __pleromafe_emoji_orig'
|
||||
}
|
||||
})
|
||||
})
|
||||
},
|
||||
linkClicked (event) {
|
||||
const target = event.target.closest('.status-content a')
|
||||
if (target) {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<template>
|
||||
<!-- eslint-disable vue/no-v-html -->
|
||||
<div class="StatusContent">
|
||||
<div class="StatusContent" :class="{'-stop-gifs': stopGifs}">
|
||||
<slot name="header" />
|
||||
<div
|
||||
v-if="status.summary_html"
|
||||
|
@ -10,6 +10,7 @@
|
|||
<div
|
||||
class="media-body summary"
|
||||
@click.prevent="linkClicked"
|
||||
ref="subject"
|
||||
v-html="status.summary_html"
|
||||
/>
|
||||
<button
|
||||
|
@ -45,6 +46,7 @@
|
|||
:class="{ 'single-line': singleLine }"
|
||||
class="status-content media-body"
|
||||
@click.prevent="linkClicked"
|
||||
ref="content"
|
||||
v-html="postBodyHtml"
|
||||
/>
|
||||
<button
|
||||
|
@ -140,6 +142,22 @@ $status-margin: 0.75em;
|
|||
flex: 1;
|
||||
min-width: 0;
|
||||
|
||||
&:hover {
|
||||
--_still-image-img-visibility: visible;
|
||||
--_still-image-canvas-visibility: hidden;
|
||||
--_still-image-label-visibility: hidden;
|
||||
}
|
||||
|
||||
&.-stop-gifs {
|
||||
.__pleromafe_emoji {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.__pleromafe_emoji_orig {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.status-content-wrapper {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
@ -192,11 +210,21 @@ $status-margin: 0.75em;
|
|||
object-fit: contain;
|
||||
|
||||
&.emoji {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
width: var(--big-emoji-size, 32px);
|
||||
height: var(--big-emoji-size, 32px);
|
||||
}
|
||||
}
|
||||
|
||||
.__pleromafe_emoji {
|
||||
display: none; // overriden elsewhere (in the beginning of css file)
|
||||
max-width: 100%;
|
||||
max-height: 400px;
|
||||
vertical-align: middle;
|
||||
object-fit: contain;
|
||||
width: var(--big-emoji-size, 32px);
|
||||
height: var(--big-emoji-size, 32px);
|
||||
}
|
||||
|
||||
.summary-wrapper {
|
||||
margin-bottom: 0.5em;
|
||||
border-style: solid;
|
||||
|
|
|
@ -5,12 +5,10 @@
|
|||
:bound-to="{ x: 'container' }"
|
||||
@show="enter"
|
||||
>
|
||||
<template slot="trigger">
|
||||
<template v-slot:trigger>
|
||||
<slot />
|
||||
</template>
|
||||
<div
|
||||
slot="content"
|
||||
>
|
||||
<template v-slot:content>
|
||||
<Status
|
||||
v-if="status"
|
||||
:is-preview="true"
|
||||
|
@ -33,7 +31,7 @@
|
|||
size="2x"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</Popover>
|
||||
</template>
|
||||
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
import Vue from 'vue'
|
||||
|
||||
const StillImage = {
|
||||
props: [
|
||||
'src',
|
||||
|
@ -8,8 +10,9 @@ const StillImage = {
|
|||
'alt'
|
||||
],
|
||||
data () {
|
||||
console.log('test', this.$store === undefined)
|
||||
return {
|
||||
stopGifs: this.$store.getters.mergedConfig.stopGifs
|
||||
stopGifs: this.$store === undefined ? true : this.$store.getters.mergedConfig.stopGifs
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
|
@ -36,4 +39,4 @@ const StillImage = {
|
|||
}
|
||||
}
|
||||
|
||||
export default StillImage
|
||||
export default Vue.component('still-image', StillImage)
|
||||
|
|
|
@ -4,77 +4,78 @@
|
|||
class="TimelineQuickSettings"
|
||||
:bound-to="{ x: 'container' }"
|
||||
>
|
||||
<div
|
||||
slot="content"
|
||||
class="dropdown-menu"
|
||||
>
|
||||
<div v-if="loggedIn">
|
||||
<template v-slot:content>
|
||||
<div class="dropdown-menu">
|
||||
<div v-if="loggedIn">
|
||||
<button
|
||||
class="button-default dropdown-item"
|
||||
@click="replyVisibilityAll = true"
|
||||
>
|
||||
<span
|
||||
class="menu-checkbox"
|
||||
:class="{ 'menu-checkbox-radio': replyVisibilityAll }"
|
||||
/>{{ $t('settings.reply_visibility_all') }}
|
||||
</button>
|
||||
<button
|
||||
class="button-default dropdown-item"
|
||||
@click="replyVisibilityFollowing = true"
|
||||
>
|
||||
<span
|
||||
class="menu-checkbox"
|
||||
:class="{ 'menu-checkbox-radio': replyVisibilityFollowing }"
|
||||
/>{{ $t('settings.reply_visibility_following_short') }}
|
||||
</button>
|
||||
<button
|
||||
class="button-default dropdown-item"
|
||||
@click="replyVisibilitySelf = true"
|
||||
>
|
||||
<span
|
||||
class="menu-checkbox"
|
||||
:class="{ 'menu-checkbox-radio': replyVisibilitySelf }"
|
||||
/>{{ $t('settings.reply_visibility_self_short') }}
|
||||
</button>
|
||||
<div
|
||||
role="separator"
|
||||
class="dropdown-divider"
|
||||
/>
|
||||
</div>
|
||||
<button
|
||||
class="button-default dropdown-item"
|
||||
@click="replyVisibilityAll = true"
|
||||
@click="hideMedia = !hideMedia"
|
||||
>
|
||||
<span
|
||||
class="menu-checkbox"
|
||||
:class="{ 'menu-checkbox-radio': replyVisibilityAll }"
|
||||
/>{{ $t('settings.reply_visibility_all') }}
|
||||
:class="{ 'menu-checkbox-checked': hideMedia }"
|
||||
/>{{ $t('settings.hide_media_previews') }}
|
||||
</button>
|
||||
<button
|
||||
class="button-default dropdown-item"
|
||||
@click="replyVisibilityFollowing = true"
|
||||
@click="hideMutedPosts = !hideMutedPosts"
|
||||
>
|
||||
<span
|
||||
class="menu-checkbox"
|
||||
:class="{ 'menu-checkbox-radio': replyVisibilityFollowing }"
|
||||
/>{{ $t('settings.reply_visibility_following_short') }}
|
||||
:class="{ 'menu-checkbox-checked': hideMutedPosts }"
|
||||
/>{{ $t('settings.hide_all_muted_posts') }}
|
||||
</button>
|
||||
<button
|
||||
class="button-default dropdown-item"
|
||||
@click="replyVisibilitySelf = true"
|
||||
class="button-default dropdown-item dropdown-item-icon"
|
||||
@click="openTab('filtering')"
|
||||
>
|
||||
<span
|
||||
class="menu-checkbox"
|
||||
:class="{ 'menu-checkbox-radio': replyVisibilitySelf }"
|
||||
/>{{ $t('settings.reply_visibility_self_short') }}
|
||||
<FAIcon icon="font" />{{ $t('settings.word_filter') }}
|
||||
</button>
|
||||
<button
|
||||
class="button-default dropdown-item dropdown-item-icon"
|
||||
@click="openTab('general')"
|
||||
>
|
||||
<FAIcon icon="wrench" />{{ $t('settings.more_settings') }}
|
||||
</button>
|
||||
<div
|
||||
role="separator"
|
||||
class="dropdown-divider"
|
||||
/>
|
||||
</div>
|
||||
<button
|
||||
class="button-default dropdown-item"
|
||||
@click="hideMedia = !hideMedia"
|
||||
>
|
||||
<span
|
||||
class="menu-checkbox"
|
||||
:class="{ 'menu-checkbox-checked': hideMedia }"
|
||||
/>{{ $t('settings.hide_media_previews') }}
|
||||
</template>
|
||||
<template v-slot:trigger>
|
||||
<button class="button-unstyled">
|
||||
<FAIcon icon="filter" />
|
||||
</button>
|
||||
<button
|
||||
class="button-default dropdown-item"
|
||||
@click="hideMutedPosts = !hideMutedPosts"
|
||||
>
|
||||
<span
|
||||
class="menu-checkbox"
|
||||
:class="{ 'menu-checkbox-checked': hideMutedPosts }"
|
||||
/>{{ $t('settings.hide_all_muted_posts') }}
|
||||
</button>
|
||||
<button
|
||||
class="button-default dropdown-item dropdown-item-icon"
|
||||
@click="openTab('filtering')"
|
||||
>
|
||||
<FAIcon icon="font" />{{ $t('settings.word_filter') }}
|
||||
</button>
|
||||
<button
|
||||
class="button-default dropdown-item dropdown-item-icon"
|
||||
@click="openTab('general')"
|
||||
>
|
||||
<FAIcon icon="wrench" />{{ $t('settings.more_settings') }}
|
||||
</button>
|
||||
</div>
|
||||
<div slot="trigger">
|
||||
<FAIcon icon="filter" />
|
||||
</div>
|
||||
</template>
|
||||
</Popover>
|
||||
</template>
|
||||
|
||||
|
|
|
@ -9,28 +9,26 @@
|
|||
@show="openMenu"
|
||||
@close="() => isOpen = false"
|
||||
>
|
||||
<div
|
||||
slot="content"
|
||||
class="timeline-menu-popover panel panel-default"
|
||||
>
|
||||
<TimelineMenuContent />
|
||||
</div>
|
||||
<div
|
||||
slot="trigger"
|
||||
class="title timeline-menu-title"
|
||||
>
|
||||
<span class="timeline-title">{{ timelineName() }}</span>
|
||||
<span>
|
||||
<FAIcon
|
||||
size="sm"
|
||||
icon="chevron-down"
|
||||
<template v-slot:content>
|
||||
<div class="timeline-menu-popover popover-default">
|
||||
<TimelineMenuContent />
|
||||
</div>
|
||||
</template>
|
||||
<template v-slot:trigger>
|
||||
<button class="button-unstyled title timeline-menu-title">
|
||||
<span class="timeline-title">{{ timelineName() }}</span>
|
||||
<span>
|
||||
<FAIcon
|
||||
size="sm"
|
||||
icon="chevron-down"
|
||||
/>
|
||||
</span>
|
||||
<span
|
||||
class="click-blocker"
|
||||
@click="blockOpen"
|
||||
/>
|
||||
</span>
|
||||
<span
|
||||
class="click-blocker"
|
||||
@click="blockOpen"
|
||||
/>
|
||||
</div>
|
||||
</button>
|
||||
</template>
|
||||
</Popover>
|
||||
</template>
|
||||
|
||||
|
|
|
@ -53,17 +53,17 @@
|
|||
>
|
||||
{{ user.name }}
|
||||
</div>
|
||||
<a
|
||||
<button
|
||||
v-if="isOtherUser && !user.is_local"
|
||||
:href="user.statusnet_profile_url"
|
||||
target="_blank"
|
||||
class="external-link-button"
|
||||
class="button-unstyled external-link-button"
|
||||
>
|
||||
<FAIcon
|
||||
class="icon"
|
||||
icon="external-link-alt"
|
||||
/>
|
||||
</a>
|
||||
</button>
|
||||
<AccountActions
|
||||
v-if="isOtherUser && loggedIn"
|
||||
:user="user"
|
||||
|
|
|
@ -4,40 +4,39 @@
|
|||
placement="top"
|
||||
:offset="{ y: 5 }"
|
||||
>
|
||||
<template slot="trigger">
|
||||
<template v-slot:trigger>
|
||||
<slot />
|
||||
</template>
|
||||
<div
|
||||
slot="content"
|
||||
class="user-list-popover"
|
||||
>
|
||||
<div v-if="users.length">
|
||||
<div
|
||||
v-for="(user) in usersCapped"
|
||||
:key="user.id"
|
||||
class="user-list-row"
|
||||
>
|
||||
<UserAvatar
|
||||
:user="user"
|
||||
class="avatar-small"
|
||||
:compact="true"
|
||||
/>
|
||||
<div class="user-list-names">
|
||||
<!-- eslint-disable vue/no-v-html -->
|
||||
<span v-html="user.name_html" />
|
||||
<!-- eslint-enable vue/no-v-html -->
|
||||
<span class="user-list-screen-name">{{ user.screen_name_ui }}</span>
|
||||
<template v-slot:content>
|
||||
<div class="user-list-popover">
|
||||
<template v-if="users.length">
|
||||
<div
|
||||
v-for="(user) in usersCapped"
|
||||
:key="user.id"
|
||||
class="user-list-row"
|
||||
>
|
||||
<UserAvatar
|
||||
:user="user"
|
||||
class="avatar-small"
|
||||
:compact="true"
|
||||
/>
|
||||
<div class="user-list-names">
|
||||
<!-- eslint-disable vue/no-v-html -->
|
||||
<span v-html="user.name_html" />
|
||||
<!-- eslint-enable vue/no-v-html -->
|
||||
<span class="user-list-screen-name">{{ user.screen_name_ui }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<template v-else>
|
||||
<FAIcon
|
||||
icon="circle-notch"
|
||||
spin
|
||||
size="3x"
|
||||
/>
|
||||
</template>
|
||||
</div>
|
||||
<div v-else>
|
||||
<FAIcon
|
||||
icon="circle-notch"
|
||||
spin
|
||||
size="3x"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</Popover>
|
||||
</template>
|
||||
|
||||
|
|
|
@ -60,10 +60,7 @@
|
|||
:disabled="!user.friends_count"
|
||||
>
|
||||
<FriendList :user-id="userId">
|
||||
<template
|
||||
slot="item"
|
||||
slot-scope="{item}"
|
||||
>
|
||||
<template v-slot:item="{item}">
|
||||
<FollowCard :user="item" />
|
||||
</template>
|
||||
</FriendList>
|
||||
|
@ -75,10 +72,7 @@
|
|||
:disabled="!user.followers_count"
|
||||
>
|
||||
<FollowerList :user-id="userId">
|
||||
<template
|
||||
slot="item"
|
||||
slot-scope="{item}"
|
||||
>
|
||||
<template v-slot:item="{item}">
|
||||
<FollowCard
|
||||
:user="item"
|
||||
:no-follows-you="isUs"
|
||||
|
|
|
@ -45,10 +45,7 @@
|
|||
</div>
|
||||
<div class="user-reporting-panel-right">
|
||||
<List :items="statuses">
|
||||
<template
|
||||
slot="item"
|
||||
slot-scope="{item}"
|
||||
>
|
||||
<template v-slot:item="{item}">
|
||||
<div class="status-fadein user-reporting-panel-sitem">
|
||||
<Status
|
||||
:in-conversation="false"
|
||||
|
|
Loading…
Reference in a new issue