aboutsummaryrefslogtreecommitdiffstats
path: root/apps/user_status/src/UserStatus.vue
diff options
context:
space:
mode:
Diffstat (limited to 'apps/user_status/src/UserStatus.vue')
-rw-r--r--apps/user_status/src/UserStatus.vue238
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>