more work + dropdown items overhaul

This commit is contained in:
Henry Jameson 2025-01-12 01:46:10 +02:00
commit 96fd7f91c4
9 changed files with 340 additions and 227 deletions

View file

@ -113,11 +113,11 @@ const BUTTONS = [{
counter: ({ status }) => status.fave_num,
anonLink: true,
toggleable: true,
action ({ status, store }) {
action ({ status, dispatch }) {
if (!status.favorited) {
return store.dispatch('favorite', { id: status.id })
return dispatch('favorite', { id: status.id })
} else {
return store.dispatch('unfavorite', { id: status.id })
return dispatch('unfavorite', { id: status.id })
}
}
}, {
@ -125,7 +125,7 @@ const BUTTONS = [{
// EMOJI REACTIONS
// =========
name: 'emoji',
label: 'tool_lip.add_reaction',
label: 'tool_tip.add_reaction',
icon: ['far', 'smile-beam'],
anonLink: true,
popover: 'emoji-picker'
@ -279,6 +279,7 @@ const StatusActionButtons = {
emits: ['toggleReplying'],
data () {
return {
showPin: true,
showingConfirmDialog: false,
currentConfirmTitle: '',
currentConfirmOkText: '',
@ -304,6 +305,9 @@ const StatusActionButtons = {
extraButtons () {
return this.buttons.filter(x => !this.pinnedItems.has(x.name))
},
currentUser () {
return this.$store.state.users.currentUser
},
funcArg () {
return {
status: this.status,
@ -313,8 +317,8 @@ const StatusActionButtons = {
state: this.$store.state,
getters: this.$store.getters,
router: this.$router,
currentUser: this.$store.state.users.currentUser,
loggedIn: !!this.$store.state.users.currentUser
currentUser: this.currentUser,
loggedIn: !!this.currentUser
}
},
triggerAttrs () {
@ -336,6 +340,18 @@ const StatusActionButtons = {
.then(() => this.$emit('onSuccess'))
.catch(err => this.$emit('onError', err.error.error))
},
isPinned (button) {
console.log(this.pinnedItems, button.name)
return this.pinnedItems.has(button.name)
},
unpin (button) {
this.$store.commit('removeCollectionPreference', { path: 'collections.pinnedStatusActions', value: button.name })
this.$store.dispatch('pushServerSideStorage')
},
pin (button) {
this.$store.commit('addCollectionPreference', { path: 'collections.pinnedStatusActions', value: button.name })
this.$store.dispatch('pushServerSideStorage')
},
component (button) {
if (!this.$store.state.users.currentUser && button.anonLink) {
return 'a'
@ -348,6 +364,8 @@ const StatusActionButtons = {
getClass (button) {
return {
[button.name + '-button']: true,
'-pin-edit': this.showPin,
'-dropdown': button.dropdown?.(),
'-active': button.active?.(this.funcArg),
'-interactive': !!this.$store.state.users.currentUser
}

View file

@ -0,0 +1,112 @@
@import "../../mixins";
.StatusActionButtons {
.quick-action-buttons {
display: grid;
grid-template-columns: 1fr;
grid-auto-flow: column;
grid-auto-columns: 1fr;
grid-gap: 1em;
margin-top: var(--status-margin);
.quick-action {
display: grid;
grid-template-columns: 1fr auto;
.action-button {
display: grid;
grid-template-columns: max-content auto;
grid-gap: 1em;
align-items: center;
}
&.-pin {
margin: calc(-2px - 0.25em);
padding: 0.25em;
border: 2px dashed var(--icon);
border-radius: var(--roundness);
}
&.-pin,
&.-dropdown {
grid-template-columns: 1fr max-content;
}
.reply-button {
&:hover,
&.-active {
.svg-inline--fa {
color: var(--cBlue);
}
}
}
.retweet-button {
&:hover,
&.-active {
.svg-inline--fa {
color: var(--cGreen);
}
}
}
.favorite-button {
&:hover,
&.-active {
.svg-inline--fa {
color: var(--cOrange);
}
}
}
> button,
> a {
padding: 0.5em;
margin: -0.5em;
@include unfocused-style {
.focus-marker {
visibility: hidden;
}
.active-marker {
visibility: visible;
}
}
@include focused-style {
.focus-marker {
visibility: visible;
}
.active-marker {
visibility: hidden;
}
}
}
}
}
}
// popover
.extra-action-buttons {
.extra-action {
display: grid;
grid-template-columns: 1fr;
grid-auto-flow: column;
grid-auto-columns: auto;
grid-gap: 1em;
.pin-action-button {
margin: 0;
padding: var(--__horizontal-gap) var(--__horizontal-gap);
&::before {
content: "";
height: 1em;
width: 1px;
border-left: 1px solid var(--icon);
margin-right: 0.5em;
}
}
}
}

View file

@ -3,12 +3,13 @@
<span class="quick-action-buttons">
<span
class="quick-action"
:class="{ '-pin': showPin, '-toggle': button.dropdown?.() }"
v-for="button in quickButtons"
:key="button.name"
>
<component
:is="component(button)"
class="button-unstyled"
class="button-unstyled action-button"
:class="getClass(button)"
role="button"
:tabindex="0"
@ -16,7 +17,7 @@
@click.stop="component(button) === 'button' && doAction(button)"
:href="component(button) == 'a' ? button.link?.(funcArg) || getRemoteInteractionLink : undefined"
>
<FALayers class="fa-old-padding">
<FALayers>
<FAIcon
class="fa-scale-110"
:icon="button.icon(funcArg)"
@ -42,13 +43,28 @@
/>
</template>
</FALayers>
<span
class="action-counter"
v-if="button.counter?.(funcArg) > 0"
>
{{ button.counter?.(funcArg) }}
</span>
</component>
<span
class="action-counter"
v-if="button.counter?.(funcArg) > 0"
<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)"
>
{{ button.counter?.(funcArg) }}
</span>
<FAIcon
v-if="showPin && currentUser"
fixed-width
class="fa-scale-110"
icon="thumbtack"
/>
</button>
</span>
<Popover
trigger="click"
@ -56,44 +72,61 @@
:tabindex="0"
placement="top"
:offset="{ y: 5 }"
:bound-to="{ x: 'container2' }"
:bound-to="{ x: 'container' }"
remove-padding
@show="onShow"
@close="onClose"
>
<template #trigger>
<span class="popover-trigger">
<FALayers class="fa-old-padding-layer">
<FAIcon
class="fa-scale-110 "
icon="ellipsis-h"
/>
</FALayers>
</span>
<FAIcon
class="fa-scale-110 "
icon="ellipsis-h"
/>
</template>
<template #content="{close}">
<div
:id="`popup-menu-${randomSeed}`"
class="dropdown-menu"
class="dropdown-menu extra-action-buttons"
role="menu"
>
<component
<div
v-for="button in extraButtons"
:key="button.name"
:is="component(button)"
class="menu-item dropdown-item dropdown-item-icon"
role="menuitem"
:class="getClass(button)"
:tabindex="0"
@click.stop="component(button) === 'button' && doAction(button)"
@click="close"
:href="component(button) == 'a' ? button.link?.(funcArg) || getRemoteInteractionLink : undefined"
class="menu-item dropdown-item extra-action dropdown-item-icon"
>
<FAIcon
class="fa-scale-110"
:icon="button.icon(funcArg)"
/><span>{{ $t(button.label(funcArg)) }}</span>
</component>
<component
:is="component(button)"
class="main-button"
role="menuitem"
:class="getClass(button)"
:tabindex="0"
@click.stop="component(button) === 'button' && doAction(button)"
@click="close"
:href="component(button) == 'a' ? button.link?.(funcArg) || getRemoteInteractionLink : undefined"
>
<FAIcon
class="fa-scale-110"
fixed-width
:icon="button.icon(funcArg)"
/><span>{{ $t(button.label(funcArg)) }}</span>
</component>
<button
v-if="showPin && currentUser"
type="button"
class="button-unstyled pin-action-button"
:title="$t('general.pin' )"
:aria-pressed="false"
@click.stop.prevent="pin(button)"
>
<FAIcon
v-if="showPin && currentUser"
fixed-width
class="fa-scale-110 veryfaint"
transform="rotate-45"
icon="thumbtack"
/>
</button>
</div>
</div>
</template>
</Popover>
@ -116,78 +149,4 @@
<script src="./status_action_buttons.js"></script>
<style lang="scss">
@import "../../mixins";
.StatusActionButtons {
.quick-action-buttons {
display: grid;
grid-template-columns: 1fr;
grid-auto-flow: column;
grid-auto-columns: 1fr;
grid-gap: 1em;
margin-top: var(--status-margin);
.quick-action {
display: grid;
grid-template-columns: auto 1fr;
grid-gap: 0.5em;
max-width: 4em;
.reply-button {
&:hover,
&.-active {
.svg-inline--fa {
color: var(--cBlue);
}
}
}
.retweet-button {
&:hover,
&.-active {
.svg-inline--fa {
color: var(--cGreen);
}
}
}
.favorite-button {
&:hover,
&.-active {
.svg-inline--fa {
color: var(--cOrange);
}
}
}
> button,
> a {
padding: 0.5em;
margin: -0.5em;
}
@include unfocused-style {
.focus-marker {
visibility: hidden;
}
.active-marker {
visibility: visible;
}
}
@include focused-style {
.focus-marker {
visibility: visible;
}
.active-marker {
visibility: hidden;
}
}
}
}
}
</style>
<style lang="scss" src="./status_action_buttons.scss"></style>