commit: b831f34c06d93d714f4113b4be42efbf74c40743
parent 5a085d8e36f593fbd7ba901ed05274d749b82325
Author: Henry Jameson <me@hjkos.com>
Date: Tue, 14 Jan 2025 01:42:36 +0200
abstraction, made popover optional, initial markup for better mute options
Diffstat:
9 files changed, 248 insertions(+), 265 deletions(-)
diff --git a/src/components/status_action_buttons/action_button.js b/src/components/status_action_buttons/action_button.js
@@ -0,0 +1,83 @@
+import StatusBookmarkFolderMenu from 'src/components/status_bookmark_folder_menu/status_bookmark_folder_menu.vue'
+import Popover from 'src/components/popover/popover.vue'
+
+import { library } from '@fortawesome/fontawesome-svg-core'
+import {
+ faPlus,
+ faMinus,
+ faCheck,
+ faTimes,
+ faWrench,
+
+ faReply,
+ faRetweet,
+ faStar,
+ faSmileBeam,
+
+ faEllipsisH,
+ faBookmark,
+ faEyeSlash,
+ faThumbtack,
+ faShareAlt,
+ faExternalLinkAlt,
+ faHistory
+} from '@fortawesome/free-solid-svg-icons'
+import {
+ faStar as faStarRegular
+} from '@fortawesome/free-regular-svg-icons'
+
+library.add(
+ faPlus,
+ faMinus,
+ faCheck,
+ faTimes,
+ faWrench,
+
+ faReply,
+ faRetweet,
+ faStar,
+ faStarRegular,
+ faSmileBeam,
+
+ faEllipsisH,
+ faBookmark,
+ faEyeSlash,
+ faThumbtack,
+ faShareAlt,
+ faExternalLinkAlt,
+ faHistory
+)
+
+export default {
+ props: [
+ 'button',
+ 'extra',
+ 'status',
+ 'funcArg',
+ 'animationState',
+ 'getClass',
+ 'getComponent',
+ 'doAction',
+ 'close'
+ ],
+ components: {
+ StatusBookmarkFolderMenu,
+ Popover
+ },
+ computed: {
+ buttonClass () {
+ if (!this.extra) console.log(this.button.name)
+ return [
+ this.button.name + '-button',
+ {
+ 'main-button': this.extra,
+ 'button-unstyled': !this.extra,
+ '-extra': this.extra,
+ '-quick': !this.extra,
+ '-active': this.button.active?.(this.funcArg),
+ disabled: this.button.interactive ? !this.button.interactive(this.funcArg) : false
+ }
+ ]
+ }
+ }
+}
diff --git a/src/components/status_action_buttons/action_button.scss b/src/components/status_action_buttons/action_button.scss
@@ -2,6 +2,12 @@
/* stylelint-disable declaration-no-important */
.action-button {
+ display: grid;
+
+ &.-with-extra {
+ grid-template-columns: 1fr calc(var(--__line-height) + 2 * var(--__horizontal-gap));
+ }
+
&.-quick {
display: grid;
grid-template-columns: max-content auto;
diff --git a/src/components/status_action_buttons/action_button.vue b/src/components/status_action_buttons/action_button.vue
@@ -1,8 +1,11 @@
<template>
- <div>
+ <div
+ class="action-button"
+ :class="{ '-with-extra': button.name === 'bookmark' }"
+ >
<component
:is="getComponent(button)"
- class="main-button action-button"
+ class="action-button-inner"
:class="buttonClass"
role="menuitem"
:tabindex="0"
@@ -38,90 +41,48 @@
:icon="button.closeIndicator?.(funcArg) || 'minus'"
/>
</template>
- </FALayers><span>{{ $t(button.label(funcArg)) }}</span>
+ </FALayers>
+ <span
+ v-if="extra"
+ class="action-label"
+ >
+ {{ $t(button.label(funcArg)) }}
+ </span>
+ <span
+ v-if="!extra && button.counter?.(funcArg) > 0"
+ class="action-counter"
+ >
+ {{ button.counter?.(funcArg) }}
+ </span>
<FAIcon
- v-if="button.name === 'mute'"
+ v-if="button.dropdown?.()"
class="chevron-icon"
size="lg"
icon="chevron-right"
fixed-width
/>
</component>
+ <Popover
+ trigger="hover"
+ placement="right"
+ :trigger-attrs="{ class: 'extra-button' }"
+ v-if="button.name === 'bookmark'"
+ >
+ <template #trigger>
+ <FAIcon
+ class="chevron-icon"
+ size="lg"
+ icon="chevron-right"
+ fixed-width
+ />
+ </template>
+ <template #content>
+ <StatusBookmarkFolderMenu v-if="button.name === 'bookmark'" :status="$attrs.status" />
+ </template>
+ </Popover>
</div>
</template>
-<script>
-import { library } from '@fortawesome/fontawesome-svg-core'
-import {
- faPlus,
- faMinus,
- faCheck,
- faTimes,
- faWrench,
-
- faReply,
- faRetweet,
- faStar,
- faSmileBeam,
-
- faEllipsisH,
- faBookmark,
- faEyeSlash,
- faThumbtack,
- faShareAlt,
- faExternalLinkAlt,
- faHistory
-} from '@fortawesome/free-solid-svg-icons'
-import {
- faStar as faStarRegular
-} from '@fortawesome/free-regular-svg-icons'
-
-library.add(
- faPlus,
- faMinus,
- faCheck,
- faTimes,
- faWrench,
-
- faReply,
- faRetweet,
- faStar,
- faStarRegular,
- faSmileBeam,
-
- faEllipsisH,
- faBookmark,
- faEyeSlash,
- faThumbtack,
- faShareAlt,
- faExternalLinkAlt,
- faHistory
-)
-
-export default {
- props: [
- 'button',
- 'extra',
- 'status',
- 'funcArg',
- 'animationState',
- 'getClass',
- 'getComponent',
- 'doAction',
- 'close'
- ],
- computed: {
- buttonClass () {
- return {
- [this.button.name + '-button']: true,
- '-extra': this.extra,
- '-quick': !this.extra,
- '-active': this.button.active?.(this.funcArg),
- disabled: this.button.interactive ? !this.button.interactive(this.funcArg) : false
- }
- }
- }
-}
-</script>
+<script src="./action_button.js"/>
<style lang="scss" src="./action_button.scss"/>
diff --git a/src/components/status_action_buttons/action_button_container.js b/src/components/status_action_buttons/action_button_container.js
@@ -0,0 +1,23 @@
+import ActionButton from './action_button.vue'
+import Popover from 'src/components/popover/popover.vue'
+
+import { library } from '@fortawesome/fontawesome-svg-core'
+import {
+ faUser,
+ faGlobe,
+ faFolderTree
+} from '@fortawesome/free-solid-svg-icons'
+
+library.add(
+ faUser,
+ faGlobe,
+ faFolderTree
+)
+
+export default {
+ components: {
+ ActionButton,
+ Popover
+ },
+ props: ['button']
+}
diff --git a/src/components/status_action_buttons/action_button_container.vue b/src/components/status_action_buttons/action_button_container.vue
@@ -0,0 +1,58 @@
+<template>
+ <Popover
+ trigger="hover"
+ placement="right"
+ v-if="button.dropdown?.()"
+ >
+ <template #trigger>
+ {{ props }}
+ <ActionButton
+ :button="button"
+ v-bind="$attrs"
+ />
+ </template>
+ <template #content>
+ <div
+ v-if="button.name === 'mute'"
+ class="dropdown-menu"
+ :id="`popup-menu-${randomSeed}`"
+ role="menu"
+ >
+ <div class="menu-item dropdown-item extra-action -icon">
+ <button
+ class="main-button"
+ @click="() => {}"
+ >
+ <FAIcon icon="user" fixed-width />
+ {{ $t('status.mute_user') }}
+ </button>
+ </div>
+ <div class="menu-item dropdown-item extra-action -icon">
+ <button
+ class="main-button"
+ @click="() => {}"
+ >
+ <FAIcon icon="folder-tree" fixed-width />
+ {{ $t('status.mute_conversation') }}
+ </button>
+ </div>
+ <div class="menu-item dropdown-item extra-action -icon">
+ <button
+ class="main-button"
+ @click="() => {}"
+ >
+ <FAIcon icon="globe" fixed-width />
+ {{ $t('status.mute_domain') }}
+ </button>
+ </div>
+ </div>
+ </template>
+ </Popover>
+ <ActionButton
+ v-else
+ :button="button"
+ v-bind="$attrs"
+ />
+</template>
+
+<script src="./action_button_container.js"/>
diff --git a/src/components/status_action_buttons/status_action_buttons.js b/src/components/status_action_buttons/status_action_buttons.js
@@ -1,8 +1,7 @@
import { mapState } from 'vuex'
import ConfirmModal from 'src/components/confirm_modal/confirm_modal.vue'
-import ActionButton from './action_button.vue'
-import StatusBookmarkFolderMenu from 'src/components/status_bookmark_folder_menu/status_bookmark_folder_menu.vue'
+import ActionButtonContainer from './action_button_container.vue'
import Popover from 'src/components/popover/popover.vue'
import genRandomSeed from 'src/services/random_seed/random_seed.service.js'
@@ -136,22 +135,21 @@ const BUTTONS = [{
popover: 'emoji-picker'
}, {
// =========
- // MUTE CONVERSATION, my beloved
+ // MUTE
// =========
name: 'mute',
icon: 'eye-slash',
- label: ({ status }) => status.thread_muted
- ? 'status.unmute_conversation'
- : 'status.mute_conversation',
+ label: 'status.mute_ellipsis',
if: ({ loggedIn }) => loggedIn,
toggleable: true,
- action ({ status, dispatch, emit }) {
- if (status.thread_muted) {
- return dispatch('unmuteConversation', { id: status.id })
- } else {
- return dispatch('muteConversation', { id: status.id })
- }
- }
+ dropdown: true
+ // action ({ status, dispatch, emit }) {
+ // if (status.thread_muted) {
+ // return dispatch('unmuteConversation', { id: status.id })
+ // } else {
+ // return dispatch('muteConversation', { id: status.id })
+ // }
+ // }
}, {
// =========
// PIN STATUS
@@ -287,6 +285,7 @@ const StatusActionButtons = {
emits: ['toggleReplying'],
data () {
return {
+ Popover,
animationState: {
retweet: false,
favorite: false
@@ -303,8 +302,7 @@ const StatusActionButtons = {
components: {
Popover,
ConfirmModal,
- ActionButton,
- StatusBookmarkFolderMenu
+ ActionButtonContainer
},
computed: {
...mapState({
diff --git a/src/components/status_action_buttons/status_action_buttons.scss b/src/components/status_action_buttons/status_action_buttons.scss
@@ -8,84 +8,12 @@
grid-auto-columns: 1fr;
grid-gap: 1em;
margin-top: var(--status-margin);
-
- .quick-action {
- display: grid;
- grid-template-columns: 1fr auto;
-
- &.-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:not(.disabled) {
- &:hover,
- &.-active {
- .svg-inline--fa {
- color: var(--cBlue);
- }
- }
- }
-
- .retweet-button:not(.disabled) {
- &:hover,
- &.-active {
- .svg-inline--fa {
- color: var(--cGreen);
- }
- }
- }
-
- .favorite-button:not(.disabled) {
- &: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
/* stylelint-disable no-descending-specificity */
.extra-action-buttons {
.extra-action {
- display: grid;
- grid-template-columns: 1fr;
grid-auto-flow: column;
grid-auto-columns: auto;
grid-gap: 1em;
diff --git a/src/components/status_action_buttons/status_action_buttons.vue b/src/components/status_action_buttons/status_action_buttons.vue
@@ -7,50 +7,17 @@
v-for="button in quickButtons"
:key="button.name"
>
- <component
- :is="getComponent(button)"
- class="button-unstyled action-button"
- :class="getClass(button)"
- :disabled="getClass(button).disabled"
- role="button"
- :tabindex="0"
- :title="$t(button.label(funcArg))"
- @click.stop="getComponent(button) === 'button' && doAction(button)"
- :href="getComponent(button) == 'a' ? button.link?.(funcArg) || getRemoteInteractionLink : undefined"
- >
- <FALayers>
- <FAIcon
- class="fa-scale-110"
- :icon="button.icon(funcArg)"
- />
- <template v-if="!getClass(button).disabled && button.toggleable?.(funcArg) && button.active">
- <FAIcon
- v-if="button.active(funcArg)"
- class="active-marker"
- transform="shrink-6 up-9 right-12"
- :icon="button.activeIndicator?.(funcArg) || 'check'"
- />
- <FAIcon
- v-if="!button.active(funcArg)"
- class="focus-marker"
- transform="shrink-6 up-9 right-12"
- :icon="button.openIndicator?.(funcArg) || 'plus'"
- />
- <FAIcon
- v-else
- class="focus-marker"
- transform="shrink-6 up-9 right-12"
- :icon="button.closeIndicator?.(funcArg) || 'minus'"
- />
- </template>
- </FALayers>
- <span
- class="action-counter"
- v-if="button.counter?.(funcArg) > 0"
- >
- {{ button.counter?.(funcArg) }}
- </span>
- </component>
+ <ActionButtonContainer
+ :button="button"
+ :status="status"
+ :extra="false"
+ :funcArg="funcArg"
+ :get-class="getClass"
+ :get-component="getComponent"
+ :animation-state="animationState"
+ :close="close"
+ :do-action="doAction"
+ />
<button
v-if="showPin && currentUser"
type="button"
@@ -111,63 +78,17 @@
:disabled="getClass(button).disabled"
:class="{ disabled: getClass(button).disabled }"
>
- <Popover
- v-if="getComponent(button) === 'button'"
- trigger="hover"
- placement="right"
- >
- <template #trigger>
- <ActionButton
- :button="button"
- :status="status"
- :extra="true"
- :funcArg="funcArg"
- :get-class="getClass"
- :get-component="getComponent"
- :animation-state="animationState"
- :close="close"
- :do-action="doAction"
- />
- </template>
- <template #content>
- <template v-if="button.name === 'mute'">
- <div
- v-for="folder in folders"
- :key="folder.id"
- class="menu-item dropdown-item -icon"
- >
- <button
- class="main-button"
- @click="toggleFolder(folder.id)"
- >
- <span
- class="input menu-checkbox -radio"
- :class="{ 'menu-checkbox-checked': status.bookmark_folder_id == folder.id }"
- />
- {{ folder.name }}
- </button>
- </div>
- </template>
- </template>
- </Popover>
- <Popover
- trigger="hover"
- placement="right"
- :trigger-attrs="{ class: 'extra-button' }"
- v-if="button.name === 'bookmark'"
- >
- <template #trigger>
- <FAIcon
- class="chevron-icon"
- size="lg"
- icon="chevron-right"
- fixed-width
- />
- </template>
- <template #content>
- <StatusBookmarkFolderMenu v-if="button.name === 'bookmark'" :status="funcArg.status" />
- </template>
- </Popover>
+ <ActionButtonContainer
+ :button="button"
+ :status="status"
+ :extra="true"
+ :funcArg="funcArg"
+ :get-class="getClass"
+ :get-component="getComponent"
+ :animation-state="animationState"
+ :close="close"
+ :do-action="doAction"
+ />
<button
v-if="showPin && currentUser"
type="button"
diff --git a/src/i18n/en.json b/src/i18n/en.json
@@ -1238,6 +1238,11 @@
"mentions": "Mentions",
"replies_list": "Replies:",
"replies_list_with_others": "Replies (+{numReplies} other): | Replies (+{numReplies} others):",
+ "mute_ellipsis": "Mute…",
+ "mute_user": "Mute user",
+ "unmute_user": "Unmute user",
+ "mute_domain": "Mute domain",
+ "unmute_domain": "Unmute domain",
"mute_conversation": "Mute conversation",
"unmute_conversation": "Unmute conversation",
"status_unavailable": "Status unavailable",