diff options
Diffstat (limited to 'apps/user_status/src/UserStatus.vue')
-rw-r--r-- | apps/user_status/src/UserStatus.vue | 238 |
1 files changed, 51 insertions, 187 deletions
diff --git a/apps/user_status/src/UserStatus.vue b/apps/user_status/src/UserStatus.vue index a4b7b9552f3..07d81aad95c 100644 --- a/apps/user_status/src/UserStatus.vue +++ b/apps/user_status/src/UserStatus.vue @@ -1,80 +1,70 @@ <!-- - - @copyright Copyright (c) 2020 Georg Ehrke <oc.list@georgehrke.com> - - @author Georg Ehrke <oc.list@georgehrke.com> - - - - @license GNU AGPL version 3 or any later version - - - - This program is free software: you can redistribute it and/or modify - - it under the terms of the GNU Affero General Public License as - - published by the Free Software Foundation, either version 3 of the - - License, or (at your option) any later version. - - - - This program is distributed in the hope that it will be useful, - - but WITHOUT ANY WARRANTY; without even the implied warranty of - - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - - GNU Affero General Public License for more details. - - - - You should have received a copy of the GNU Affero General Public License - - along with this program. If not, see <http://www.gnu.org/licenses/>. - - - --> + - SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors + - SPDX-License-Identifier: AGPL-3.0-or-later +--> <template> - <component :is="elementTag"> - <div class="user-status-menu-item"> - <!-- Username display --> - <a v-if="!inline" - class="user-status-menu-item__header" - :href="profilePageLink" - @click="loadProfilePage"> - <div class="user-status-menu-item__header-content"> - <div class="user-status-menu-item__header-content-displayname">{{ displayName }}</div> - <div v-if="!loadingProfilePage" class="user-status-menu-item__header-content-placeholder" /> - <div v-else class="icon-loading-small" /> - </div> - <div v-if="profileEnabled"> - {{ t('user_status', 'View profile') }} - </div> - </a> - - <!-- Status modal toggle --> - <toggle :is="inline ? 'button' : 'a'" - :class="{'user-status-menu-item__toggle--inline': inline}" - class="user-status-menu-item__toggle" - href="#" - @click.prevent.stop="openModal"> - <span :class="statusIcon" class="user-status-menu-item__toggle-icon" /> + <Fragment> + <NcListItem v-if="!inline" + class="user-status-menu-item" + compact + :name="visibleMessage" + @click.stop="openModal"> + <template #icon> + <NcUserStatusIcon class="user-status-icon" + :status="statusType" + aria-hidden="true" /> + </template> + </NcListItem> + + <div v-else> + <!-- Dashboard Status --> + <NcButton @click.stop="openModal"> + <template #icon> + <NcUserStatusIcon class="user-status-icon" + :status="statusType" + aria-hidden="true" /> + </template> {{ visibleMessage }} - </toggle> + </NcButton> </div> - <!-- Status management modal --> <SetStatusModal v-if="isModalOpen" + :inline="inline" @close="closeModal" /> - </component> + </Fragment> </template> <script> -import { generateUrl } from '@nextcloud/router' import { getCurrentUser } from '@nextcloud/auth' -import { loadState } from '@nextcloud/initial-state' import { subscribe, unsubscribe } from '@nextcloud/event-bus' +import { Fragment } from 'vue-frag' +import NcButton from '@nextcloud/vue/components/NcButton' +import NcListItem from '@nextcloud/vue/components/NcListItem' +import NcUserStatusIcon from '@nextcloud/vue/components/NcUserStatusIcon' import debounce from 'debounce' -import { sendHeartbeat } from './services/heartbeatService' -import OnlineStatusMixin from './mixins/OnlineStatusMixin' - -const { profileEnabled } = loadState('user_status', 'profileEnabled', false) +import { sendHeartbeat } from './services/heartbeatService.js' +import OnlineStatusMixin from './mixins/OnlineStatusMixin.js' export default { name: 'UserStatus', components: { - SetStatusModal: () => import(/* webpackChunkName: 'user-status-modal' */'./components/SetStatusModal'), + Fragment, + NcButton, + NcListItem, + NcUserStatusIcon, + SetStatusModal: () => import(/* webpackChunkName: 'user-status-modal' */'./components/SetStatusModal.vue'), }, mixins: [OnlineStatusMixin], props: { + /** + * Whether the component should be rendered as a Dashboard Status or a User Menu Entries + * true = Dashboard Status + * false = User Menu Entries + */ inline: { type: Boolean, default: false, @@ -83,44 +73,19 @@ export default { data() { return { - displayName: getCurrentUser().displayName, heartbeatInterval: null, isAway: false, isModalOpen: false, - loadingProfilePage: false, mouseMoveListener: null, - profileEnabled, setAwayTimeout: null, } }, - computed: { - elementTag() { - return this.inline ? 'div' : 'li' - }, - /** - * The profile page link - * - * @return {string | null} - */ - profilePageLink() { - if (this.profileEnabled) { - return generateUrl('/u/{userId}', { userId: getCurrentUser().uid }) - } - // Since an anchor element is used rather than a button, - // this hack removes href if the profile is disabled so that disabling pointer-events is not needed to prevent a click from opening a page - // and to allow the hover event for styling - return null - }, - }, /** * Loads the current user's status from initial state * and stores it in Vuex */ mounted() { - subscribe('settings:display-name:updated', this.handleDisplayNameUpdate) - subscribe('settings:profile-enabled:updated', this.handleProfileEnabledUpdate) - this.$store.dispatch('loadStatusFromInitialState') if (OC.config.session_keepalive) { @@ -157,28 +122,12 @@ export default { * Some housekeeping before destroying the component */ beforeDestroy() { - unsubscribe('settings:display-name:updated', this.handleDisplayNameUpdate) - unsubscribe('settings:profile-enabled:updated', this.handleProfileEnabledUpdate) window.removeEventListener('mouseMove', this.mouseMoveListener) clearInterval(this.heartbeatInterval) unsubscribe('user_status:status.updated', this.handleUserStatusUpdated) }, methods: { - handleDisplayNameUpdate(displayName) { - this.displayName = displayName - }, - - handleProfileEnabledUpdate(profileEnabled) { - this.profileEnabled = profileEnabled - }, - - loadProfilePage() { - if (this.profileEnabled) { - this.loadingProfilePage = true - } - }, - /** * Opens the modal to set a custom status */ @@ -211,7 +160,7 @@ export default { } }, handleUserStatusUpdated(state) { - if (OC.getCurrentUser().uid === state.userId) { + if (getCurrentUser()?.uid === state.userId) { this.$store.dispatch('setStatusFromObject', { status: state.status, icon: state.icon, @@ -224,97 +173,12 @@ export default { </script> <style lang="scss" scoped> -.user-status-menu-item { - &__header { - display: flex !important; - flex-direction: column !important; - width: auto !important; - height: 44px * 1.5 !important; - padding: 10px 12px 5px 12px !important; - align-items: flex-start !important; - color: var(--color-main-text) !important; - - &:focus-visible { - padding: 6px 8px 1px 8px !important; - margin: 2px !important; - } - - &:not([href]) { - height: var(--header-menu-item-height) !important; - color: var(--color-text-maxcontrast) !important; - cursor: default !important; - - & * { - cursor: default !important; - } - - &:hover { - background-color: transparent !important; - } - } - - &-content { - display: inline-flex !important; - font-weight: bold !important; - gap: 0 10px !important; - width: auto; - - &-displayname { - width: auto; - } - - &-placeholder { - width: 16px !important; - height: 24px !important; - margin-right: 10px !important; - visibility: hidden !important; - } - } - - span { - color: var(--color-text-maxcontrast) !important; - } - } - - &__toggle { - &-icon { - width: 16px; - height: 16px; - margin-right: 10px; - opacity: 1 !important; - background-size: 16px; - vertical-align: middle !important; - } - - // In dashboard - &--inline { - width: auto; - min-width: 44px; - height: 44px; - margin: 0; - border: 0; - border-radius: var(--border-radius-pill); - background-color: var(--color-main-background-blur); - font-size: inherit; - font-weight: normal; - - -webkit-backdrop-filter: var(--background-blur); - backdrop-filter: var(--background-blur); - - &:active, - &:hover, - &:focus { - background-color: var(--color-background-hover); - } - &:focus { - box-shadow: 0 0 0 2px var(--color-main-text) !important; - } - } - } +.user-status-icon { + width: 20px; + height: 20px; + margin: calc((var(--default-clickable-area) - 20px) / 2); // 20px icon size + opacity: 1 !important; + background-size: 20px; + vertical-align: middle !important; } - -li { - list-style-type: none; -} - </style> |