Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F85823530
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Authored By
Unknown
Size
14 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/src/components/status_action_buttons/action_button.scss b/src/components/status_action_buttons/action_button.scss
index 25d7b71d46..e1e5ef3a69 100644
--- a/src/components/status_action_buttons/action_button.scss
+++ b/src/components/status_action_buttons/action_button.scss
@@ -1,132 +1,140 @@
@use "../../mixins";
/* stylelint-disable declaration-no-important */
.quick-action {
justify-content: space-between;
display: flex;
align-items: baseline;
align-items: center;
border: 2px solid transparent;
.action-counter {
overflow-x: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
+ &.-counter {
+ justify-self: start;
+ }
+
+ &.-more-actions {
+ justify-self: end;
+ }
+
.action-button-inner,
.extra-button {
padding: 0.5em;
z-index: 1;
}
.separator {
display: block;
align-self: stretch;
width: 1px;
background-color: var(--icon);
opacity: 0.75;
margin: 0.5em 0;
}
.action-button-inner {
display: grid;
gap: 0.125em;
grid-template-columns: max-content;
grid-auto-flow: column;
grid-auto-columns: max-content;
align-items: center;
@include mixins.unfocused-style {
.focus-marker {
visibility: hidden;
}
.active-marker {
visibility: visible;
}
}
@include mixins.focused-style {
.focus-marker {
visibility: visible;
}
.active-marker {
visibility: hidden;
}
}
}
&.-pin {
border: 2px dashed var(--icon);
border-radius: var(--roundness);
grid-template-columns: minmax(max-content, 1fr) auto;
.action-button-inner {
opacity: 0.8;
padding-right: 0;
pointer-events: none;
}
.chevron-icon,
.extra-button,
.separator {
display: none;
}
}
&.-with-extra {
.action-button-inner,
.extra-button {
padding-left: 0.25em;
padding-right: 0.25em;
}
}
}
.action-button {
display: grid;
grid-auto-flow: column;
align-items: center;
padding: 0;
.action-button-inner {
&:hover,
&.-active {
&.reply-button:not(.disabled) {
.svg-inline--fa {
color: var(--cBlue);
}
}
&.retweet-button:not(.disabled) {
.svg-inline--fa {
color: var(--cGreen);
}
}
&.favorite-button:not(.disabled) {
.svg-inline--fa {
color: var(--cOrange);
}
}
}
}
&.-extra {
.action-counter {
justify-self: end;
margin-left: 1em;
}
.chevron-icon {
justify-self: end;
}
.extra-button {
justify-self: end;
justify-content: end;
}
}
}
diff --git a/src/components/status_action_buttons/status_action_buttons.js b/src/components/status_action_buttons/status_action_buttons.js
index ffa9936758..34ff211cb5 100644
--- a/src/components/status_action_buttons/status_action_buttons.js
+++ b/src/components/status_action_buttons/status_action_buttons.js
@@ -1,184 +1,192 @@
import { mapState } from 'pinia'
import { defineAsyncComponent } from 'vue'
import Popover from 'src/components/popover/popover.vue'
import ActionButtonContainer from './action_button_container.vue'
import { BUTTONS } from './buttons_definitions.js'
import { useSyncConfigStore } from 'src/stores/sync_config.js'
import { useUsersStore } from 'src/stores/users.js'
import genRandomSeed from 'src/services/random_seed/random_seed.service.js'
import { library } from '@fortawesome/fontawesome-svg-core'
import { faEllipsisH } from '@fortawesome/free-solid-svg-icons'
library.add(faEllipsisH)
const StatusActionButtons = {
props: {
status: {
type: Object,
required: true,
},
replying: {
type: Boolean,
default: false,
},
fixedPinned: {
type: Boolean,
default: false,
},
pinned: {
type: Set,
},
useDefaultButtons: {
type: Boolean,
default: false,
},
hideLabels: {
type: Boolean,
default: false,
},
inChatView: {
type: Boolean,
default: false,
},
},
emits: ['toggleReplying', 'onSuccess', 'onError'],
data() {
return {
showPin: false,
showingConfirmDialog: false,
currentConfirmTitle: '',
currentConfirmOkText: '',
currentConfirmCancelText: '',
currentConfirmAction: () => {
/* no-op */
},
randomSeed: genRandomSeed(),
emojiPickerShown: false,
}
},
components: {
Popover,
ConfirmModal: defineAsyncComponent(
() => import('src/components/confirm_modal/confirm_modal.vue'),
),
ActionButtonContainer,
},
computed: {
...mapState(useSyncConfigStore, {
userPinnedItems: (store) =>
new Set(store.prefsStorage.collections.pinnedStatusActions),
}),
pinnedItems() {
if (this.fixedPinned) {
return this.pinned
} else {
return this.userPinnedItems
}
},
buttons() {
return BUTTONS.filter((x) => (x.if ? x.if(this.funcArg) : true))
},
quickButtons() {
return this.buttons.filter((x) => this.pinnedItems.has(x.name))
},
extraButtons() {
return this.buttons.filter((x) => !this.pinnedItems.has(x.name))
},
currentUser() {
return useUsersStore().currentUser
},
funcArg() {
return {
status: this.status,
replying: this.replying,
emojiPickerShown: this.emojiPickerShown,
emit: this.$emit,
router: this.$router,
currentUser: this.currentUser,
loggedIn: !!this.currentUser,
chatView: !!this.inChatView,
}
},
},
methods: {
doAction(button) {
if (button.confirm?.(this.funcArg)) {
// TODO move to action_button
this.currentConfirmTitle = this.$t(
button.confirmStrings(this.funcArg).title,
)
this.currentConfirmOkText = this.$t(
button.confirmStrings(this.funcArg).confirm,
)
this.currentConfirmCancelText = this.$t(
button.confirmStrings(this.funcArg).cancel,
)
this.currentConfirmBody = this.$t(
button.confirmStrings(this.funcArg).body,
)
this.currentConfirmAction = () => {
this.showingConfirmDialog = false
this.doActionReal(button)
}
this.showingConfirmDialog = true
} else {
this.doActionReal(button)
}
},
+ quickButtonClass(button) {
+ return {
+ '-pin': this.showPin,
+ '-toggle': button.dropdown?.(),
+ '-with-extra': button.name === 'bookmark',
+ '-counter': button.counter,
+ }
+ },
doActionReal(button) {
const promise = button.action?.(this.funcArg) ?? Promise.resolve()
promise
.then(() => this.$emit('onSuccess'))
.catch((err) => this.$emit('onError', err))
},
onExtraClose() {
this.showPin = false
},
onEmojiPickerShown(state) {
this.emojiPickerShown = state
},
isPinned(button) {
return this.pinnedItems.has(button.name)
},
unpin(button) {
useSyncConfigStore().removeCollectionPreference({
path: 'collections.pinnedStatusActions',
value: button.name,
})
useSyncConfigStore().pushSyncConfig()
},
pin(button) {
useSyncConfigStore().addCollectionPreference({
path: 'collections.pinnedStatusActions',
value: button.name,
})
useSyncConfigStore().pushSyncConfig()
},
getComponent(button) {
if (!useUsersStore().currentUser && button.anonLink) {
return 'a'
} else if (button.action == null && button.link != null) {
return 'a'
} else {
return 'button'
}
},
getClass(button) {
return {
[button.name + '-button']: true,
disabled: button.interactive
? !button.interactive(this.funcArg)
: false,
'-pin-edit': this.showPin,
'-dropdown': button.dropdown?.(),
'-active': button.active?.(this.funcArg),
}
},
},
}
export default StatusActionButtons
diff --git a/src/components/status_action_buttons/status_action_buttons.scss b/src/components/status_action_buttons/status_action_buttons.scss
index 756f640001..7ed4a42fe4 100644
--- a/src/components/status_action_buttons/status_action_buttons.scss
+++ b/src/components/status_action_buttons/status_action_buttons.scss
@@ -1,28 +1,30 @@
@use "../../mixins";
.StatusActionButtons {
.quick-action-buttons {
display: grid;
margin-left: -0.5em;
- grid-template-columns: repeat(auto-fill, minmax(3.75em, 10%));
+ grid-template-columns: repeat(auto-fit, minmax(3.75em, 10%));
grid-auto-flow: row dense;
grid-auto-rows: 1fr;
+ justify-content: space-between;
+ justify-items: center;
gap: 0.5em 0.1em;
}
.pin-action-button {
display: flex;
z-index: 1;
padding: 0.5em;
margin: 0;
}
}
// popover
.extra-action-buttons {
.extra-action {
margin: 0;
padding-top: 0;
padding-bottom: 0;
padding-right: 0;
}
}
diff --git a/src/components/status_action_buttons/status_action_buttons.vue b/src/components/status_action_buttons/status_action_buttons.vue
index 2426b200d5..4cf996ce2c 100644
--- a/src/components/status_action_buttons/status_action_buttons.vue
+++ b/src/components/status_action_buttons/status_action_buttons.vue
@@ -1,141 +1,141 @@
<template>
<div class="StatusActionButtons">
<span
class="quick-action-buttons"
:class="{ '-pin': showPin }"
role="toolbar"
:aria-label="$t('status.status_actions')"
>
<span
v-for="button in quickButtons"
:key="button.name"
class="quick-action"
role="presentation"
- :class="{ '-pin': showPin, '-toggle': button.dropdown?.(), '-with-extra': button.name === 'bookmark' }"
+ :class="quickButtonClass(button)"
>
<ActionButtonContainer
:class="{ '-pin': showPin }"
:button="button"
:status="status"
:extra="false"
:func-arg="funcArg"
:get-class="getClass"
:get-component="getComponent"
:close="() => { /* no-op */ }"
:do-action="doAction"
:default-button-style="useDefaultButtons"
:hide-label="hideLabels"
@emoji-picker-shown="onEmojiPickerShown"
/>
<button
v-if="showPin && currentUser"
type="button"
class="button-unstyled pin-action-button"
:title="$t('general.unpin')"
:aria-pressed="true"
@click.stop.prevent="unpin(button)"
>
<FAIcon
v-if="showPin && currentUser"
fixed-width
icon="thumbtack"
/>
</button>
</span>
<Popover
trigger="click"
:title="$t('status.more_actions')"
:normal-button="useDefaultButtons"
- class="quick-action"
+ class="quick-action -more-actions"
placement="bottom"
:offset="{ y: 5 }"
remove-padding
@close="onExtraClose"
>
<template #trigger>
<FAIcon
class="action-button-inner"
icon="ellipsis-h"
/>
</template>
<template #content="{close, resize}">
<div
:id="`popup-menu-${randomSeed}`"
class="dropdown-menu extra-action-buttons"
role="menu"
>
<div
v-for="button in extraButtons"
:key="button.name"
class="menu-item dropdown-item extra-action -icon"
:disabled="getClass(button).disabled"
:class="{ disabled: getClass(button).disabled }"
>
<ActionButtonContainer
:button="button"
:status="status"
:extra="true"
:func-arg="funcArg"
:get-class="getClass"
:get-component="getComponent"
:outer-close="close"
:do-action="doAction"
:default-button-style="useDefaultButtons"
:hide-label="hideLabels"
/>
<button
v-if="showPin && currentUser"
type="button"
class="button-unstyled pin-action-button extra-button"
:title="$t('general.pin')"
:aria-pressed="false"
@click.stop.prevent="pin(button)"
>
<FAIcon
v-if="showPin && currentUser"
fixed-width
class="fa-scale-110"
transform="rotate-45"
icon="thumbtack"
/>
</button>
</div>
<div
v-if="currentUser"
class="menu-item dropdown-item extra-action -icon"
>
<button
class="main-button"
:tabindex="0"
@click.stop="() => { resize(); showPin = !showPin }"
>
<FAIcon
class="fa-scale-110"
fixed-width
icon="wrench"
/><span>{{ $t('nav.edit_pinned') }}</span>
</button>
</div>
</div>
</template>
</Popover>
</span>
<teleport to="#modal">
<ConfirmModal
v-if="showingConfirmDialog"
:title="currentConfirmTitle"
:confirm-text="currentConfirmOkText"
:cancel-text="currentConfirmCancelText"
@accepted="currentConfirmAction"
@cancelled="showingConfirmDialog = false"
>
{{ currentConfirmBody }}
</ConfirmModal>
</teleport>
</div>
</template>
<script src="./status_action_buttons.js"></script>
<style lang="scss" src="./status_action_buttons.scss"></style>
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Thu, Oct 29, 6:48 AM (14 h, 19 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1797663
Default Alt Text
(14 KB)
Attached To
Mode
rPUFE pleroma-fe-upstream
Attached
Detach File
Event Timeline