Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F85650126
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Award Token
Flag For Later
Size
36 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/src/components/notification/notification.vue b/src/components/notification/notification.vue
index 118c1ba0e1..7165289dca 100644
--- a/src/components/notification/notification.vue
+++ b/src/components/notification/notification.vue
@@ -1,293 +1,293 @@
<template>
<article
v-if="notification.type === 'mention' || notification.type === 'status'"
ref="root"
>
<Status
class="Notification"
:compact="true"
:statusoid="notification.status"
@interacted="interacted"
/>
</article>
<article
+ v-else
+ ref="root"
class="NotificationParent"
:class="{ '-expandable': expandable }"
- ref="root"
- v-else
>
<div
v-if="needMute && !unmuted"
:id="'notif-' +notification.id"
:aria-expanded="statusExpanded"
:aria-controls="'notif-' +notification.id"
class="Notification container -muted"
>
<small>
<user-link
:user="notification.from_profile"
:at="false"
/>
</small>
<button
class="button-unstyled unmute"
@click.prevent="toggleMute"
>
<FAIcon
class="fa-scale-110 fa-old-padding"
icon="eye-slash"
/>
</button>
</div>
<div
v-else
class="Notification non-mention"
:class="[userClass, { highlighted: userStyle }, '-type--' + notification.type]"
:style="[ userStyle ]"
>
<a
class="avatar-container"
:href="$router.resolve(userProfileLink).href"
@click.prevent
>
<UserPopover
:user-id="notification.from_profile.id"
:overlay-centers="true"
>
<UserAvatar
class="post-avatar"
:compact="true"
:user="notification.from_profile"
/>
</UserPopover>
</a>
<div class="notification-right">
<span class="notification-details">
<div class="name-and-action">
<!-- eslint-disable vue/no-v-html -->
<bdi v-if="!!notification.from_profile.name_html">
<RichContent
class="username"
:title="'@'+notification.from_profile.screen_name_ui"
:html="notification.from_profile.name_html"
:emoji="notification.from_profile.emoji"
:is-local="notification.from_profile.is_local"
/>
</bdi>
<!-- eslint-enable vue/no-v-html -->
<span
v-else
class="username"
:title="'@'+notification.from_profile.screen_name_ui"
>
{{ notification.from_profile.name }}
</span>
{{ ' ' }}
<span v-if="notification.type === 'like'">
<FAIcon
class="type-icon"
icon="star"
/>
{{ ' ' }}
<small>{{ $t('notifications.favorited_you') }}</small>
</span>
<span v-if="notification.type === 'repeat'">
<FAIcon
class="type-icon"
icon="retweet"
:title="$t('tool_tip.repeat')"
/>
{{ ' ' }}
<small>{{ $t('notifications.repeated_you') }}</small>
</span>
<span v-if="notification.type === 'follow'">
<FAIcon
class="type-icon"
icon="user-plus"
/>
{{ ' ' }}
<small>{{ $t('notifications.followed_you') }}</small>
</span>
<span v-if="notification.type === 'follow_request'">
<FAIcon
class="type-icon"
icon="user"
/>
{{ ' ' }}
<small>{{ $t('notifications.follow_request') }}</small>
</span>
<span v-if="notification.type === 'move'">
<FAIcon
class="type-icon"
icon="suitcase-rolling"
/>
{{ ' ' }}
<small>{{ $t('notifications.migrated_to') }}</small>
</span>
<span v-if="notification.type === 'pleroma:emoji_reaction'">
<small>
<i18n-t
scope="global"
keypath="notifications.reacted_with"
>
<img
v-if="notification.emoji_url"
class="emoji-reaction-emoji emoji-reaction-emoji-image"
:src="notification.emoji_url"
:alt="notification.emoji"
:title="notification.emoji"
>
<span
v-else
class="emoji-reaction-emoji"
>{{ notification.emoji }}</span>
</i18n-t>
</small>
</span>
<span v-if="notification.type === 'pleroma:report'">
<small>{{ $t('notifications.submitted_report') }}</small>
</span>
<span v-if="notification.type === 'poll'">
<FAIcon
class="type-icon"
icon="poll-h"
/>
{{ ' ' }}
<small>{{ $t('notifications.poll_ended') }}</small>
</span>
</div>
<div
v-if="isStatusNotification"
class="timeago"
>
<router-link
v-if="notification.status"
:to="{ name: 'conversation', params: { id: notification.status.id } }"
class="timeago-link faint"
>
<Timeago
:time="notification.created_at"
:auto-update="240"
/>
</router-link>
<button
class="button-unstyled expand-icon"
:title="$t('tool_tip.toggle_expand')"
:aria-expanded="statusExpanded"
@click.prevent="toggleStatusExpanded"
>
<FAIcon
class="fa-scale-110"
fixed-width
:icon="statusExpanded ? 'compress-alt' : 'expand-alt'"
/>
</button>
</div>
<div
v-else
class="timeago"
>
<span class="faint">
<Timeago
:time="notification.created_at"
:auto-update="240"
/>
</span>
</div>
<button
v-if="needMute"
class="button-unstyled"
:title="$t('tool_tip.toggle_mute')"
:aria-expanded="!unmuted"
@click.prevent="toggleMute"
>
<FAIcon
class="fa-scale-110 fa-old-padding"
icon="eye-slash"
/>
</button>
</span>
<div
v-if="notification.type === 'follow' || notification.type === 'follow_request'"
class="follow-text"
>
<user-link
class="follow-name"
:user="notification.from_profile"
/>
<div
v-if="notification.type === 'follow_request'"
style="white-space: nowrap;"
>
<button
class="button-unstyled"
:title="$t('tool_tip.accept_follow_request')"
@click="approveUser()"
>
<FAIcon
icon="check"
class="fa-scale-110 fa-old-padding follow-request-accept"
/>
</button>
<button
class="button-unstyled"
:title="$t('tool_tip.reject_follow_request')"
@click="denyUser()"
>
<FAIcon
icon="times"
class="fa-scale-110 fa-old-padding follow-request-reject"
/>
</button>
</div>
</div>
<div
v-else-if="notification.type === 'move'"
class="move-text"
>
<user-link
:user="notification.target"
/>
</div>
<Report
v-else-if="notification.type === 'pleroma:report'"
:report-id="notification.report.id"
/>
<template v-else>
<StatusContent
class="status-content"
:compact="!statusExpanded"
:status="notification.status"
:collapse="!statusExpanded"
@click="onContentClick"
/>
</template>
</div>
</div>
<teleport to="#modal">
<confirm-modal
v-if="showingApproveConfirmDialog"
:title="$t('user_card.approve_confirm_title')"
:confirm-text="$t('user_card.approve_confirm_accept_button')"
:cancel-text="$t('user_card.approve_confirm_cancel_button')"
@accepted="doApprove"
@cancelled="hideApproveConfirmDialog"
>
{{ $t('user_card.approve_confirm', { user: user.screen_name_ui }) }}
</confirm-modal>
<confirm-modal
v-if="showingDenyConfirmDialog"
:title="$t('user_card.deny_confirm_title')"
:confirm-text="$t('user_card.deny_confirm_accept_button')"
:cancel-text="$t('user_card.deny_confirm_cancel_button')"
@accepted="doDeny"
@cancelled="hideDenyConfirmDialog"
>
{{ $t('user_card.deny_confirm', { user: user.screen_name_ui }) }}
</confirm-modal>
</teleport>
</article>
</template>
<script src="./notification.js"></script>
<style src="./notification.scss" lang="scss"></style>
diff --git a/src/components/settings_modal/helpers/emoji_editing_popover.vue b/src/components/settings_modal/helpers/emoji_editing_popover.vue
index e466822b33..d25b02da20 100644
--- a/src/components/settings_modal/helpers/emoji_editing_popover.vue
+++ b/src/components/settings_modal/helpers/emoji_editing_popover.vue
@@ -1,311 +1,314 @@
<template>
<Popover
ref="emojiPopover"
trigger="click"
:placement="placement"
bound-to-selector=".emoji-list"
popover-class="emoji-tab-edit-popover popover-default"
:bound-to="{ x: 'container' }"
:offset="{ y: 5 }"
:class="{'emoji-unsaved': isEdited}"
>
<template #trigger>
<slot name="trigger" />
</template>
<template #content>
<h3>
{{ title }}
</h3>
<StillImage
v-if="emojiPreview"
class="emoji"
:src="emojiPreview"
/>
<div
v-else
class="emoji"
/>
- <div v-if="newUpload" class="emoji-tab-popover-new-upload">
+ <div
+ v-if="newUpload"
+ class="emoji-tab-popover-new-upload"
+ >
<h4>{{ $t('admin_dash.emoji.emoji_source') }}</h4>
<div class="emoji-tab-popover-input">
<input
type="file"
accept="image/*"
class="emoji-tab-popover-file input"
@change="uploadFile = $event.target.files"
>
</div>
<div class="emoji-tab-popover-input ">
<input
v-model="uploadURL"
:placeholder="$t('admin_dash.emoji.upload_url')"
class="emoji-data-input input"
>
</div>
</div>
<div>
<div class="emoji-tab-popover-input">
<label>
{{ $t('admin_dash.emoji.shortcode') }}
<input
v-model="editedShortcode"
class="emoji-data-input input"
:placeholder="$t('admin_dash.emoji.new_shortcode')"
>
</label>
</div>
<div class="emoji-tab-popover-input">
<label>
{{ $t('admin_dash.emoji.filename') }}
<input
v-model="editedFile"
class="emoji-data-input input"
:placeholder="$t('admin_dash.emoji.new_filename')"
>
</label>
</div>
<div
v-if="remote !== undefined"
class="emoji-tab-popover-input"
>
<label>
{{ $t('admin_dash.emoji.copy_to') }}
<SelectComponent
v-model="copyToPack"
class="form-control"
>
<option
value=""
disabled
hidden
>
{{ $t('admin_dash.emoji.emoji_pack') }}
</option>
<option
v-for="(pack, listPackName) in knownLocalPacks"
:key="listPackName"
:label="listPackName"
>
{{ listPackName }}
</option>
</SelectComponent>
</label>
</div>
<!--
For local emojis, disable the button if nothing was edited.
For remote emojis, also disable it if a local pack is not selected.
Remote emojis are processed by the same function that uploads new ones, as that is effectively what it does
-->
<button
class="button button-default btn"
type="button"
:disabled="saveButtonDisabled"
@click="(newUpload || remote !== undefined) ? uploadEmoji() : saveEditedEmoji()"
>
{{ $t('admin_dash.emoji.save') }}
</button>
<template v-if="!newUpload && remote === undefined">
<button
class="button button-default btn emoji-tab-popover-button"
type="button"
@click="deleteModalVisible = true"
>
{{ $t('admin_dash.emoji.delete') }}
</button>
<button
class="button button-default btn emoji-tab-popover-button"
type="button"
@click="revertEmoji"
>
{{ $t('admin_dash.emoji.revert') }}
</button>
<ConfirmModal
v-if="deleteModalVisible"
:title="$t('admin_dash.emoji.delete_title')"
:cancel-text="$t('status.delete_confirm_cancel_button')"
:confirm-text="$t('status.delete_confirm_accept_button')"
@cancelled="deleteModalVisible = false"
@accepted="deleteEmoji"
>
{{ $t('admin_dash.emoji.delete_confirm', [shortcode]) }}
</ConfirmModal>
</template>
</div>
</template>
</Popover>
</template>
<script>
import Popover from 'components/popover/popover.vue'
import ConfirmModal from 'components/confirm_modal/confirm_modal.vue'
import StillImage from 'components/still-image/still-image.vue'
import SelectComponent from 'components/select/select.vue'
export default {
components: { Popover, ConfirmModal, StillImage, SelectComponent },
inject: ['emojiAddr'],
props: {
placement: {
type: String,
required: true
},
newUpload: Boolean,
title: {
type: String,
required: true
},
packName: {
type: String,
required: true
},
shortcode: {
type: String,
// Only exists when this is not a new upload
default: ''
},
file: {
type: String,
// Only exists when this is not a new upload
default: ''
},
// Only exists for emojis from remote packs
remote: {
type: Object,
default: undefined
},
knownLocalPacks: {
type: Object,
default: undefined
}
},
emits: ['updatePackFiles', 'displayError'],
data () {
return {
uploadFile: [],
uploadURL: '',
editedShortcode: this.shortcode,
editedFile: this.file,
deleteModalVisible: false,
copyToPack: ''
}
},
computed: {
emojiPreview () {
if (this.newUpload && this.uploadFile.length > 0) {
return URL.createObjectURL(this.uploadFile[0])
} else if (this.newUpload && this.uploadURL !== '') {
return this.uploadURL
} else if (!this.newUpload) {
return this.emojiAddr(this.file)
}
return null
},
isEdited () {
return !this.newUpload && (this.editedShortcode !== this.shortcode || this.editedFile !== this.file)
},
saveButtonDisabled() {
if (this.remote === undefined)
return this.newUpload ? (this.uploadURL === "" && this.uploadFile.length == 0) : !this.isEdited
else
return this.copyToPack === ""
}
},
methods: {
saveEditedEmoji () {
if (!this.isEdited) return
this.$store.state.api.backendInteractor.updateEmojiFile(
{ packName: this.packName, shortcode: this.shortcode, newShortcode: this.editedShortcode, newFilename: this.editedFile, force: false }
).then(resp => {
if (resp.error !== undefined) {
this.$emit('displayError', resp.error)
return Promise.reject(resp.error)
}
return resp.json()
}).then(resp => this.$emit('updatePackFiles', resp))
},
uploadEmoji () {
let packName = this.remote === undefined ? this.packName : this.copyToPack
this.$store.state.api.backendInteractor.addNewEmojiFile({
packName: packName,
file: this.remote === undefined
? (this.uploadURL !== "" ? this.uploadURL : this.uploadFile[0])
: this.emojiAddr(this.file),
shortcode: this.editedShortcode,
filename: this.editedFile
}).then(resp => resp.json()).then(resp => {
if (resp.error !== undefined) {
this.$emit('displayError', resp.error)
return
}
this.$emit('updatePackFiles', resp, packName)
this.$refs.emojiPopover.hidePopover()
this.editedFile = ''
this.editedShortcode = ''
this.uploadFile = []
})
},
revertEmoji () {
this.editedFile = this.file
this.editedShortcode = this.shortcode
},
deleteEmoji () {
this.deleteModalVisible = false
this.$store.state.api.backendInteractor.deleteEmojiFile(
{ packName: this.packName, shortcode: this.shortcode }
).then(resp => resp.json()).then(resp => {
if (resp.error !== undefined) {
this.$emit('displayError', resp.error)
return
}
this.$emit('updatePackFiles', resp, this.packName)
})
}
}
}
</script>
<style lang="scss">
.emoji-tab-edit-popover {
padding-left: 0.5em;
padding-right: 0.5em;
padding-bottom: 0.5em;
.emoji-tab-popover-new-upload {
margin-bottom: 2em;
}
.emoji {
width: 2.3em;
height: 2.3em;
}
.Select {
display: inline-block;
}
h4 {
margin-bottom: 1em;
margin-top: 1em;
}
}
</style>
diff --git a/src/components/settings_modal/tabs/theme_tab/theme_preview.vue b/src/components/settings_modal/tabs/theme_tab/theme_preview.vue
index 016d84c49a..df2d9f9e9a 100644
--- a/src/components/settings_modal/tabs/theme_tab/theme_preview.vue
+++ b/src/components/settings_modal/tabs/theme_tab/theme_preview.vue
@@ -1,249 +1,255 @@
<template>
<div class="theme-preview-container">
<div class="underlay underlay-preview" />
<div class="panel dummy">
<div class="panel-heading">
<h1 class="title">
{{ $t('settings.style.preview.header') }}
<span class="badge -notification">
99
</span>
</h1>
<span class="faint">
{{ $t('settings.style.preview.header_faint') }}
</span>
<span class="alert error">
{{ $t('settings.style.preview.error') }}
</span>
<button class="btn button-default">
{{ $t('settings.style.preview.button') }}
</button>
</div>
<div class="panel-body theme-preview-content">
<div class="post">
- <div class="avatar still-image" aria-hidden="true">
+ <div
+ class="avatar still-image"
+ aria-hidden="true"
+ >
( ͡° ͜ʖ ͡°)
</div>
<div class="content">
<h4>
{{ $t('settings.style.preview.content') }}
</h4>
<i18n-t
scope="global"
keypath="settings.style.preview.text"
>
<code style="font-family: var(--postCodeFont);">
{{ $t('settings.style.preview.mono') }}
</code>
<a style="color: var(--link);">
{{ $t('settings.style.preview.link') }}
</a>
</i18n-t>
<div class="icons">
<FAIcon
fixed-width
style="color: var(--cBlue);"
class="fa-scale-110 fa-old-padding"
icon="reply"
/>
<FAIcon
fixed-width
style="color: var(--cGreen);"
class="fa-scale-110 fa-old-padding"
icon="retweet"
/>
<FAIcon
fixed-width
style="color: var(--cOrange);"
class="fa-scale-110 fa-old-padding"
icon="star"
/>
<FAIcon
fixed-width
style="color: var(--cRed);"
class="fa-scale-110 fa-old-padding"
icon="times"
/>
</div>
</div>
</div>
<div class="after-post">
- <div class="avatar-alt" aria-hidden="true">
+ <div
+ class="avatar-alt"
+ aria-hidden="true"
+ >
:^)
</div>
<div class="content">
<i18n-t
keypath="settings.style.preview.fine_print"
tag="span"
class="faint"
scope="global"
>
<a style="color: var(--linkFaint);">
{{ $t('settings.style.preview.faint_link') }}
</a>
</i18n-t>
</div>
</div>
<div class="separator" />
<span class="alert error">
{{ $t('settings.style.preview.error') }}
</span>
<input
:value="$t('settings.style.preview.input')"
type="text"
class="input"
>
<div class="actions">
<Checkbox>
{{ $t('settings.style.preview.checkbox') }}
</Checkbox>
<button class="btn button-default">
{{ $t('settings.style.preview.button') }}
</button>
</div>
</div>
</div>
</div>
</template>
<script>
import Checkbox from 'src/components/checkbox/checkbox.vue'
import { library } from '@fortawesome/fontawesome-svg-core'
import {
faTimes,
faStar,
faRetweet,
faReply
} from '@fortawesome/free-solid-svg-icons'
library.add(
faTimes,
faStar,
faRetweet,
faReply
)
export default {
components: {
Checkbox
}
}
</script>
<style lang="scss">
.theme-preview-container {
position: relative;
border-top: 1px dashed;
border-bottom: 1px dashed;
border-color: var(--border);
margin: 1em 0;
padding: 1em;
background-color: var(--wallpaper);
background-image: var(--body-background-image);
background-size: cover;
background-position: 50% 50%;
.theme-preview-content {
padding: 1.5em;
}
.dummy {
.post {
font-family: var(--postFont);
display: flex;
.content {
flex: 1;
h4 {
margin-bottom: 0.25em;
}
.icons {
margin-top: 0.5em;
display: flex;
i {
margin-right: 1em;
}
}
}
}
.after-post {
margin-top: 1em;
display: flex;
align-items: center;
}
.avatar,
.avatar-alt {
background:
linear-gradient(
135deg,
#b8e1fc 0%,
#a9d2f3 10%,
#90bae4 25%,
#90bcea 37%,
#90bff0 50%,
#6ba8e5 51%,
#a2daf5 83%,
#bdf3fd 100%
);
color: black;
font-family: sans-serif;
text-align: center;
margin-right: 1em;
}
.avatar-alt {
flex: 0 auto;
margin-left: 2em;
font-size: 0.85em;
min-width: 2.2rem;
min-height: 2.2rem;
line-height: 1.5em;
align-content: center;
}
.avatar {
flex: 0 auto;
width: 3.5em;
height: 3.5em;
font-size: 1rem;
line-height: 3.5em;
justify-content: center;
}
.actions {
display: flex;
align-items: baseline;
.checkbox {
margin-right: 1em;
flex: 1;
}
}
.separator {
margin: 1em;
border-bottom: 1px solid;
border-color: var(--border);
}
.btn {
min-width: 3em;
}
}
.underlay-preview {
position: absolute;
inset: 0 0.9em;
}
}
</style>
diff --git a/src/components/status_content/status_content.vue b/src/components/status_content/status_content.vue
index bab4f70a5c..460a0714b6 100644
--- a/src/components/status_content/status_content.vue
+++ b/src/components/status_content/status_content.vue
@@ -1,71 +1,74 @@
<template>
<div
class="StatusContent"
:class="{ '-compact': compact }"
>
<slot name="header" />
<StatusBody
:status="status"
:compact="compact"
:single-line="singleLine"
:showing-tall="showingTall"
:expanding-subject="expandingSubject"
:showing-long-subject="showingLongSubject"
:toggle-showing-tall="toggleShowingTall"
:toggle-expanding-subject="toggleExpandingSubject"
:toggle-showing-long-subject="toggleShowingLongSubject"
:collapse="collapse"
@parse-ready="$emit('parseReady', $event)"
>
<div v-if="status.poll && status.poll.options && !compact">
<Poll
:base-poll="status.poll"
:emoji="status.emojis"
/>
</div>
- <div class="poll-icon" v-else-if="status.poll && status.poll.options && compact">
+ <div
+ v-else-if="status.poll && status.poll.options && compact"
+ class="poll-icon"
+ >
<FAIcon
icon="poll-h"
size="2x"
/>
</div>
<gallery
v-if="status.attachments.length !== 0"
class="attachments media-body"
:compact="compact"
:nsfw="nsfwClickthrough"
:attachments="status.attachments"
:limit="compact ? 1 : 0"
:size="attachmentSize"
@play="$emit('mediaplay', attachment.id)"
@pause="$emit('mediapause', attachment.id)"
/>
<div
v-if="statusCard && !noHeading && !compact"
class="link-preview media-body"
>
<link-preview
:card="status.card"
:size="attachmentSize"
:nsfw="nsfwClickthrough"
/>
</div>
</StatusBody>
<slot name="footer" />
</div>
</template>
<script src="./status_content.js"></script>
<style lang="scss">
.StatusContent {
flex: 1;
min-width: 0;
.poll-icon {
margin: 0.5em;
}
}
</style>
diff --git a/src/components/still-image/still-image-emoji-popover.vue b/src/components/still-image/still-image-emoji-popover.vue
index 8588d5165d..8317c6a0c3 100644
--- a/src/components/still-image/still-image-emoji-popover.vue
+++ b/src/components/still-image/still-image-emoji-popover.vue
@@ -1,189 +1,189 @@
<template>
<Popover
ref="emojiPopover"
trigger="click"
placement="top"
:bound-to="{ x: 'container' }"
:offset="{ y: 10 }"
@show="fetchEmojiPacksIfAdmin"
>
<template #trigger>
<StillImage v-bind="$attrs" />
</template>
<template #content>
<div class="emoji-popover">
<h3>{{ $attrs.title }}</h3>
<div class="emoji-popover-centered">
<StillImage
class="emoji"
v-bind="$attrs"
/>
</div>
<div v-if="isUserAdmin && !isLocal">
<button
class="button button-default btn emoji-popover-button"
type="button"
- @click="copyToLocalPack"
:disabled="packName == ''"
+ @click="copyToLocalPack"
>
{{ $t('admin_dash.emoji.copy_to_pack') }}
</button>
<SelectComponent
v-model="packName"
>
<option
value=""
disabled
hidden
>
{{ $t('admin_dash.emoji.emoji_pack') }}
</option>
<option
v-for="(pack, listPackName) in knownLocalPacks"
:key="listPackName"
:label="listPackName"
>
{{ listPackName }}
</option>
</SelectComponent>
</div>
</div>
</template>
</Popover>
</template>
<script>
import { assign } from 'lodash'
import StillImage from './still-image.vue'
import Popover from 'components/popover/popover.vue'
import SelectComponent from 'components/select/select.vue'
import { useInterfaceStore } from 'src/stores/interface'
export default {
components: { StillImage, Popover, SelectComponent },
props: {
shortcode: {
type: String,
required: true
},
isLocal: {
type: Boolean,
required: true
}
},
data() {
return {
knownLocalPacks: { },
packName: ""
}
},
computed: {
isUserAdmin () {
return this.$store.state.users.currentUser.rights.admin
}
},
methods: {
displayError (msg) {
useInterfaceStore().pushGlobalNotice({
messageKey: 'admin_dash.emoji.error',
messageArgs: [msg],
level: 'error'
})
},
copyToLocalPack() {
this.$store.state.api.backendInteractor.addNewEmojiFile({
packName: this.packName,
file: this.$attrs.src,
shortcode: this.shortcode,
filename: ""
}).then(resp => resp.json()).then(resp => {
if (resp.error !== undefined) {
this.displayError(resp.error)
return
}
useInterfaceStore().pushGlobalNotice({
messageKey: 'admin_dash.emoji.copied_successfully',
messageArgs: [this.shortcode, this.packName],
level: 'success'
})
this.$refs.emojiPopover.hidePopover()
this.packName = ''
})
},
// Copied from emoji_tab.js
loadPacksPaginated (listFunction) {
const pageSize = 25
const allPacks = {}
return listFunction({ instance: this.$store.state.instance.server, page: 1, pageSize: 0 })
.then(data => data.json())
.then(data => {
if (data.error !== undefined) { return Promise.reject(data.error) }
let resultingPromise = Promise.resolve({})
for (let i = 0; i < Math.ceil(data.count / pageSize); i++) {
resultingPromise = resultingPromise.then(() => listFunction({ instance: this.$store.state.instance.server, page: i, pageSize })
).then(data => data.json()).then(pageData => {
if (pageData.error !== undefined) { return Promise.reject(pageData.error) }
assign(allPacks, pageData.packs)
})
}
return resultingPromise
})
.then(() => allPacks)
.catch(data => {
this.displayError(data)
})
},
fetchEmojiPacksIfAdmin() {
if (!this.isUserAdmin) return
this.loadPacksPaginated(this.$store.state.api.backendInteractor.listEmojiPacks)
.then(allPacks => {
// Sort by key
const sorted = Object.keys(allPacks).sort().reduce((acc, key) => {
if (key.length === 0) return acc
acc[key] = allPacks[key]
return acc
}, {})
this.knownLocalPacks = sorted
})
}
}
}
</script>
<style>
.emoji-popover {
margin: 0 0.5em 0.5em;
text-align: center;
.emoji {
width: 4.6em;
height: 4.6em;
}
.emoji-popover-centered {
display: flex;
align-items: center;
justify-content: center;
}
.emoji-popover-button {
width: 100%;
margin-top: 0.5em;
}
.Select {
width: 100%;
}
}
</style>
diff --git a/src/components/user_reporting_modal/user_reporting_modal.vue b/src/components/user_reporting_modal/user_reporting_modal.vue
index dbd7e7e564..aa5704a975 100644
--- a/src/components/user_reporting_modal/user_reporting_modal.vue
+++ b/src/components/user_reporting_modal/user_reporting_modal.vue
@@ -1,174 +1,177 @@
<template>
<Modal
v-if="isOpen"
@backdrop-clicked="closeModal"
>
<div class="user-reporting-panel panel">
<div class="panel-heading">
<i18n-t
tag="h1"
keypath="user_reporting.title"
class="title"
>
- <UserLink class="user-link" :user="user" />
+ <UserLink
+ class="user-link"
+ :user="user"
+ />
</i18n-t>
</div>
<div class="panel-body">
<div class="user-reporting-panel-left">
<div>
<p>{{ $t('user_reporting.add_comment_description') }}</p>
<textarea
v-model="comment"
class="input form-control"
:placeholder="$t('user_reporting.additional_comments')"
rows="1"
@input="resize"
/>
</div>
<div v-if="!user.is_local">
<p>{{ $t('user_reporting.forward_description') }}</p>
<Checkbox v-model="forward">
{{ $t('user_reporting.forward_to', [remoteInstance]) }}
</Checkbox>
</div>
<div>
<button
class="btn button-default"
:disabled="processing"
@click="reportUser"
>
{{ $t('user_reporting.submit') }}
</button>
<div
v-if="error"
class="alert error"
>
{{ $t('user_reporting.generic_error') }}
</div>
</div>
</div>
<div class="user-reporting-panel-right">
<List :items="statuses">
<template #item="{item}">
<div class="status-fadein user-reporting-panel-sitem">
<Status
:in-conversation="false"
:focused="false"
:statusoid="item"
/>
<Checkbox
:model-value="isChecked(item.id)"
@update:model-value="checked => toggleStatus(checked, item.id)"
/>
</div>
</template>
</List>
</div>
</div>
</div>
</Modal>
</template>
<script src="./user_reporting_modal.js"></script>
<style lang="scss">
.user-reporting-panel {
width: 90vw;
max-width: 50rem;
min-height: 20vh;
max-height: 80vh;
.user-link {
display: inline
}
.panel-body {
display: flex;
flex-direction: column-reverse;
border-top: 1px solid;
border-color: var(--border);
overflow: hidden;
}
&-left {
padding: 1.1em 0.7em 0.7em;
line-height: var(--post-line-height);
box-sizing: border-box;
> div {
margin-bottom: 1em;
&:last-child {
margin-bottom: 0;
}
}
p {
margin-top: 0;
}
textarea.form-control {
line-height: 1.1;
resize: none;
overflow: hidden;
transition: min-height 200ms 100ms;
min-height: 44px;
width: 100%;
}
.btn {
min-width: 10em;
padding: 0 2em;
}
.alert {
margin: 1em 0 0;
line-height: 1.3em;
}
}
&-right {
display: flex;
flex-direction: column;
overflow-y: auto;
}
&-sitem {
display: flex;
justify-content: space-between;
/* TODO cleanup this */
> .Status {
flex: 1;
}
> .checkbox {
margin: 0.75em;
}
}
@media all and (width >= 801px) {
.panel-body {
flex-direction: row;
}
&-left {
width: 50%;
max-width: 320px;
border-right: 1px solid;
border-color: var(--border);
padding: 1.1em;
> div {
margin-bottom: 2em;
}
}
&-right {
width: 50%;
flex: 1 1 auto;
margin-bottom: 12px;
}
}
}
</style>
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Sat, Aug 29, 9:36 PM (1 d, 15 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1737496
Default Alt Text
(36 KB)
Attached To
Mode
rPUFE pleroma-fe-upstream
Attached
Detach File
Event Timeline
Log In to Comment