|
|
|
@ -21,28 +21,13 @@ |
|
|
|
|
|
|
|
<template> |
|
|
|
<component :is="inline ? 'div' : 'li'"> |
|
|
|
<!-- User Menu Entries --> |
|
|
|
<div v-if="!inline" class="user-status-menu-item"> |
|
|
|
<!-- Username display --> |
|
|
|
<a class="user-status-menu-item__header" |
|
|
|
:href="profilePageLink" |
|
|
|
@click.exact="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> |
|
|
|
|
|
|
|
<!-- User Status = Status modal toggle --> |
|
|
|
<button class="user-status-menu-item__toggle" @click.stop="openModal"> |
|
|
|
<span aria-hidden="true" :class="statusIcon" class="user-status-icon" /> |
|
|
|
{{ visibleMessage }} |
|
|
|
</button> |
|
|
|
</div> |
|
|
|
<!-- User Status = Status modal toggle --> |
|
|
|
<button v-if="!inline" |
|
|
|
class="user-status-menu-item" |
|
|
|
@click.stop="openModal"> |
|
|
|
<span aria-hidden="true" :class="statusIcon" class="user-status-icon" /> |
|
|
|
{{ visibleMessage }} |
|
|
|
</button> |
|
|
|
|
|
|
|
<!-- Dashboard Status --> |
|
|
|
<NcButton v-else |
|
|
|
@ -60,9 +45,6 @@ |
|
|
|
</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 NcButton from '@nextcloud/vue/dist/Components/NcButton.js' |
|
|
|
import debounce from 'debounce' |
|
|
|
@ -70,8 +52,6 @@ import debounce from 'debounce' |
|
|
|
import { sendHeartbeat } from './services/heartbeatService.js' |
|
|
|
import OnlineStatusMixin from './mixins/OnlineStatusMixin.js' |
|
|
|
|
|
|
|
const { profileEnabled } = loadState('user_status', 'profileEnabled', false) |
|
|
|
|
|
|
|
export default { |
|
|
|
name: 'UserStatus', |
|
|
|
|
|
|
|
@ -95,41 +75,19 @@ export default { |
|
|
|
|
|
|
|
data() { |
|
|
|
return { |
|
|
|
displayName: getCurrentUser().displayName, |
|
|
|
heartbeatInterval: null, |
|
|
|
isAway: false, |
|
|
|
isModalOpen: false, |
|
|
|
loadingProfilePage: false, |
|
|
|
mouseMoveListener: null, |
|
|
|
profileEnabled, |
|
|
|
setAwayTimeout: null, |
|
|
|
} |
|
|
|
}, |
|
|
|
computed: { |
|
|
|
/** |
|
|
|
* The profile page link |
|
|
|
* |
|
|
|
* @return {string | undefined} |
|
|
|
*/ |
|
|
|
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 undefined |
|
|
|
}, |
|
|
|
}, |
|
|
|
|
|
|
|
/** |
|
|
|
* 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) { |
|
|
|
@ -166,28 +124,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 |
|
|
|
*/ |
|
|
|
@ -234,75 +176,27 @@ export default { |
|
|
|
|
|
|
|
<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; |
|
|
|
|
|
|
|
&: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; |
|
|
|
} |
|
|
|
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-visible { |
|
|
|
background-color: var(--color-background-hover); |
|
|
|
} |
|
|
|
|
|
|
|
&__toggle { |
|
|
|
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-visible { |
|
|
|
box-shadow: 0 0 0 4px var(--color-main-background) !important; |
|
|
|
outline: 2px solid var(--color-main-text) !important; |
|
|
|
} |
|
|
|
&:focus-visible { |
|
|
|
box-shadow: 0 0 0 4px var(--color-main-background) !important; |
|
|
|
outline: 2px solid var(--color-main-text) !important; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|