diff --git a/apps/dashboard/js/dashboard.js b/apps/dashboard/js/dashboard.js index 5e046c7924c30510ad9f66216a93245677e7ca66..ddc28fcdd9bd55f3907832b11661b6eb19baf207 100644 Binary files a/apps/dashboard/js/dashboard.js and b/apps/dashboard/js/dashboard.js differ diff --git a/apps/dashboard/js/dashboard.js.map b/apps/dashboard/js/dashboard.js.map index 15797b4628160710cb816e754aa7b4d03fd06996..342df6e3bcb24d3397e18b181db74de15cf69572 100644 Binary files a/apps/dashboard/js/dashboard.js.map and b/apps/dashboard/js/dashboard.js.map differ diff --git a/apps/files/js/dist/personal-settings.js b/apps/files/js/dist/personal-settings.js index c7b5ef759faeef87182b48e8a70c1b9e5de61526..be56fe43a4069ecaab54e29236cc509bf4499d87 100644 Binary files a/apps/files/js/dist/personal-settings.js and b/apps/files/js/dist/personal-settings.js differ diff --git a/apps/files/js/dist/personal-settings.js.map b/apps/files/js/dist/personal-settings.js.map index a2d787a264072286d150e289c1e6bb01b14acee9..4e08921d8dc8cb7734f31687bd5d68afd909afee 100644 Binary files a/apps/files/js/dist/personal-settings.js.map and b/apps/files/js/dist/personal-settings.js.map differ diff --git a/apps/files/js/dist/sidebar.js b/apps/files/js/dist/sidebar.js index 6136fe1958a42914fb36dd8dd7ca84293d18e622..ddcff7405072220524bd7a944858a042ad446b58 100644 Binary files a/apps/files/js/dist/sidebar.js and b/apps/files/js/dist/sidebar.js differ diff --git a/apps/files/js/dist/sidebar.js.map b/apps/files/js/dist/sidebar.js.map index 09fb8f25b149f32e3a08eee281a0ce5e64b1a6ab..14dfff7bb316d140e3dd7d356df34e711b1cf236 100644 Binary files a/apps/files/js/dist/sidebar.js.map and b/apps/files/js/dist/sidebar.js.map differ diff --git a/apps/files_sharing/js/dist/files_sharing_tab.js b/apps/files_sharing/js/dist/files_sharing_tab.js index b50abdbd779b2122dff2e9797654a5b2e7827397..5ce0c586009a77235d6075b2aa532116ba0f8394 100644 Binary files a/apps/files_sharing/js/dist/files_sharing_tab.js and b/apps/files_sharing/js/dist/files_sharing_tab.js differ diff --git a/apps/files_sharing/js/dist/files_sharing_tab.js.map b/apps/files_sharing/js/dist/files_sharing_tab.js.map index 69ba9ec688730fe13ef9bb41df0cf8085df8adbd..fa6243aff70c95b68f441966f1b0d13d6e3e0635 100644 Binary files a/apps/files_sharing/js/dist/files_sharing_tab.js.map and b/apps/files_sharing/js/dist/files_sharing_tab.js.map differ diff --git a/apps/settings/js/vue-settings-admin-security.js b/apps/settings/js/vue-settings-admin-security.js index b389530e0e8c6247aad99e2c868325af328d7683..ff5039b3974eab928f272edaad72e1432f37fc92 100644 Binary files a/apps/settings/js/vue-settings-admin-security.js and b/apps/settings/js/vue-settings-admin-security.js differ diff --git a/apps/settings/js/vue-settings-admin-security.js.map b/apps/settings/js/vue-settings-admin-security.js.map index ff94b2915b40a4c01a0c9fed2c484b955525f7b6..865b5417905efa55e564b54845c137181a22dbc4 100644 Binary files a/apps/settings/js/vue-settings-admin-security.js.map and b/apps/settings/js/vue-settings-admin-security.js.map differ diff --git a/apps/settings/js/vue-settings-apps-users-management.js b/apps/settings/js/vue-settings-apps-users-management.js index e019f4950dcb27de743166de9934e4ee0fe47529..0b59b9f7344045b1e2d8b065f7d3302e4113f837 100644 Binary files a/apps/settings/js/vue-settings-apps-users-management.js and b/apps/settings/js/vue-settings-apps-users-management.js differ diff --git a/apps/settings/js/vue-settings-apps-users-management.js.map b/apps/settings/js/vue-settings-apps-users-management.js.map index 285e335dbac5ffb2e00f244f0999638c399b86e0..bbf376e22f8094636caf94ded68bcaadcf4040dc 100644 Binary files a/apps/settings/js/vue-settings-apps-users-management.js.map and b/apps/settings/js/vue-settings-apps-users-management.js.map differ diff --git a/apps/settings/js/vue-settings-personal-security.js b/apps/settings/js/vue-settings-personal-security.js index 59efe314dace5bd1ebdf9e6ae76692a6d234498f..fa2630d1450b1a77129f91f3a9d67c522df9affa 100644 Binary files a/apps/settings/js/vue-settings-personal-security.js and b/apps/settings/js/vue-settings-personal-security.js differ diff --git a/apps/settings/js/vue-settings-personal-security.js.map b/apps/settings/js/vue-settings-personal-security.js.map index 7d3f4c87386dea542c6094676e7302ec9c20f7ee..2dfa970b22b2434a9a944850a0b3df479de43abb 100644 Binary files a/apps/settings/js/vue-settings-personal-security.js.map and b/apps/settings/js/vue-settings-personal-security.js.map differ diff --git a/apps/settings/js/vue-settings-personal-webauthn.js b/apps/settings/js/vue-settings-personal-webauthn.js index 78dbaa73703b721336a21aacaa473d44dc8e9f7b..f9c11c69f5b8098d011b3cf42cd78011e5b67af9 100644 Binary files a/apps/settings/js/vue-settings-personal-webauthn.js and b/apps/settings/js/vue-settings-personal-webauthn.js differ diff --git a/apps/settings/js/vue-settings-personal-webauthn.js.map b/apps/settings/js/vue-settings-personal-webauthn.js.map index 789082827deb1fd8a7d074eb95d6c7257fecbbb2..94cadd41f8a481e96300aecbf74707f7a0b333d7 100644 Binary files a/apps/settings/js/vue-settings-personal-webauthn.js.map and b/apps/settings/js/vue-settings-personal-webauthn.js.map differ diff --git a/apps/settings/js/vue-vendors-settings-apps-316e23ec36a476148305.js b/apps/settings/js/vue-vendors-settings-apps-316e23ec36a476148305.js new file mode 100644 index 0000000000000000000000000000000000000000..7305c753f3f8bfe1d019b80bfdd46c5b12a38dc1 Binary files /dev/null and b/apps/settings/js/vue-vendors-settings-apps-316e23ec36a476148305.js differ diff --git a/apps/settings/js/vue-vendors-settings-apps-316e23ec36a476148305.js.map b/apps/settings/js/vue-vendors-settings-apps-316e23ec36a476148305.js.map new file mode 100644 index 0000000000000000000000000000000000000000..55b5ba548e7ea86e63c1ef72230adc722022ffc2 Binary files /dev/null and b/apps/settings/js/vue-vendors-settings-apps-316e23ec36a476148305.js.map differ diff --git a/apps/settings/js/vue-vendors-settings-apps-settings-users-0451d2c076dc79ae5d94.js b/apps/settings/js/vue-vendors-settings-apps-settings-users-0451d2c076dc79ae5d94.js new file mode 100644 index 0000000000000000000000000000000000000000..f0e1c1d2c2012c509fa1cc8c7a25b98f17a75298 Binary files /dev/null and b/apps/settings/js/vue-vendors-settings-apps-settings-users-0451d2c076dc79ae5d94.js differ diff --git a/apps/settings/js/vue-vendors-settings-apps-settings-users-0451d2c076dc79ae5d94.js.map b/apps/settings/js/vue-vendors-settings-apps-settings-users-0451d2c076dc79ae5d94.js.map new file mode 100644 index 0000000000000000000000000000000000000000..08f81bf5abc86b10b547f716cc0ecc4979801cff Binary files /dev/null and b/apps/settings/js/vue-vendors-settings-apps-settings-users-0451d2c076dc79ae5d94.js.map differ diff --git a/apps/settings/js/vue-vendors-settings-users-32c87e3bed5cc0363135.js b/apps/settings/js/vue-vendors-settings-users-32c87e3bed5cc0363135.js new file mode 100644 index 0000000000000000000000000000000000000000..d92450f77b2fe885385bf114d3de75c853e66ae1 Binary files /dev/null and b/apps/settings/js/vue-vendors-settings-users-32c87e3bed5cc0363135.js differ diff --git a/apps/settings/js/vue-vendors-settings-users-32c87e3bed5cc0363135.js.map b/apps/settings/js/vue-vendors-settings-users-32c87e3bed5cc0363135.js.map new file mode 100644 index 0000000000000000000000000000000000000000..7a04c3d6a956fdb933d450cc7302330c458da425 Binary files /dev/null and b/apps/settings/js/vue-vendors-settings-users-32c87e3bed5cc0363135.js.map differ diff --git a/apps/updatenotification/js/updatenotification.js b/apps/updatenotification/js/updatenotification.js index 0a5a0e159010c17be569b92ed69ba9440849e0bf..3619bf9165f6667905721bb62ec9162b2aca7227 100644 Binary files a/apps/updatenotification/js/updatenotification.js and b/apps/updatenotification/js/updatenotification.js differ diff --git a/apps/updatenotification/js/updatenotification.js.map b/apps/updatenotification/js/updatenotification.js.map index 05e55db672dff2ecb80235c37088dd30bbfaf3c4..832b0b5ce53cfb674a3fc91180ef7d59dd90490d 100644 Binary files a/apps/updatenotification/js/updatenotification.js.map and b/apps/updatenotification/js/updatenotification.js.map differ diff --git a/apps/user_status/js/dashboard.js b/apps/user_status/js/dashboard.js index 7d5329b46cace3b1bd42da3f37f1ddbde2a41106..f0ecdf7c439d9edcc82803f28baa0f47d96f06a7 100644 Binary files a/apps/user_status/js/dashboard.js and b/apps/user_status/js/dashboard.js differ diff --git a/apps/user_status/js/dashboard.js.map b/apps/user_status/js/dashboard.js.map index 66a62e017ba2a27a46fc770dcc535a628d8188b5..33dcd6872b3f6def445a07f8506f963feabe8670 100644 Binary files a/apps/user_status/js/dashboard.js.map and b/apps/user_status/js/dashboard.js.map differ diff --git a/apps/user_status/js/user-status-menu.js b/apps/user_status/js/user-status-menu.js index ba402ebac9b11815c32f8eb1ec95e08646654ad7..988b4931baa1b5ed0637f221a478205896f7927b 100644 Binary files a/apps/user_status/js/user-status-menu.js and b/apps/user_status/js/user-status-menu.js differ diff --git a/apps/user_status/js/user-status-menu.js.map b/apps/user_status/js/user-status-menu.js.map index 3593802a1769279b66c2a23223fd4b7231951524..659c0667d1afa4d37b0e890c876a1ce2aea693a3 100644 Binary files a/apps/user_status/js/user-status-menu.js.map and b/apps/user_status/js/user-status-menu.js.map differ diff --git a/apps/user_status/js/user-status-modal.js b/apps/user_status/js/user-status-modal.js new file mode 100644 index 0000000000000000000000000000000000000000..c55e254481b977a42f96dc85f3d7d4da0e71742c Binary files /dev/null and b/apps/user_status/js/user-status-modal.js differ diff --git a/apps/user_status/js/user-status-modal.js.map b/apps/user_status/js/user-status-modal.js.map new file mode 100644 index 0000000000000000000000000000000000000000..5a8841c0b0b3f7614ece326d6d784c30f2f87e6c Binary files /dev/null and b/apps/user_status/js/user-status-modal.js.map differ diff --git a/apps/user_status/js/vendors-user-status-modal.js b/apps/user_status/js/vendors-user-status-modal.js new file mode 100644 index 0000000000000000000000000000000000000000..cbe81fef86bcec2c358516625f732e19c50a6e6e Binary files /dev/null and b/apps/user_status/js/vendors-user-status-modal.js differ diff --git a/apps/user_status/js/vendors-user-status-modal.js.map b/apps/user_status/js/vendors-user-status-modal.js.map new file mode 100644 index 0000000000000000000000000000000000000000..1f48916798c7c26d097a100603b8b3284f9b11e8 Binary files /dev/null and b/apps/user_status/js/vendors-user-status-modal.js.map differ diff --git a/apps/user_status/src/App.vue b/apps/user_status/src/UserStatus.vue similarity index 50% rename from apps/user_status/src/App.vue rename to apps/user_status/src/UserStatus.vue index ff927505baeeaa21773881e9be8a51a2b32c1e26..517615825955e8c3226b971b8a0f9804e3e1ba66 100644 --- a/apps/user_status/src/App.vue +++ b/apps/user_status/src/UserStatus.vue @@ -20,70 +20,59 @@ --> <template> - <li :class="{ inline }"> - <div id="user-status-menu-item"> + <li> + <div class="user-status-menu-item"> + <!-- Username display --> <span v-if="!inline" - id="user-status-menu-item__header" + class="user-status-menu-item__header" :title="displayName"> {{ displayName }} </span> - <Actions - id="user-status-menu-item__subheader" - :default-icon="statusIcon" - container="header" - :menu-title="visibleMessage" - :title="visibleMessage"> - <ActionButton - v-for="status in statuses" - :key="status.type" - :icon="status.icon" - :close-after-click="true" - :title="status.label" - @click.prevent.stop="changeStatus(status.type)"> - {{ status.subline }} - </ActionButton> - <ActionButton - icon="icon-rename" - :close-after-click="true" - :title="$t('user_status', 'Set status message')" - @click.prevent.stop="openModal" /> - </Actions> - <SetStatusModal - v-if="isModalOpen" - @close="closeModal" /> + + <!-- 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" /> + {{ visibleMessage }} + </toggle> </div> + + <!-- Status management modal --> + <SetStatusModal + v-if="isModalOpen" + @close="closeModal" /> </li> </template> <script> import { getCurrentUser } from '@nextcloud/auth' -import SetStatusModal from './components/SetStatusModal' -import Actions from '@nextcloud/vue/dist/Components/Actions' -import ActionButton from '@nextcloud/vue/dist/Components/ActionButton' -import { mapState } from 'vuex' -import { showError } from '@nextcloud/dialogs' -import { getAllStatusOptions } from './services/statusOptionsService' -import { sendHeartbeat } from './services/heartbeatService' import debounce from 'debounce' +import { sendHeartbeat } from './services/heartbeatService' +import OnlineStatusMixin from './mixins/OnlineStatusMixin' + export default { - name: 'App', + name: 'UserStatus', + components: { - Actions, - ActionButton, - SetStatusModal, + SetStatusModal: () => import(/* webpackChunkName: 'user-status-modal' */'./components/SetStatusModal'), }, + mixins: [OnlineStatusMixin], + props: { inline: { type: Boolean, default: false, }, }, + data() { return { isModalOpen: false, - statuses: getAllStatusOptions(), heartbeatInterval: null, setAwayTimeout: null, mouseMoveListener: null, @@ -91,12 +80,6 @@ export default { } }, computed: { - ...mapState({ - statusType: state => state.userStatus.status, - statusIsUserDefined: state => state.userStatus.statusIsUserDefined, - customIcon: state => state.userStatus.icon, - customMessage: state => state.userStatus.message, - }), /** * The display-name of the current user * @@ -105,64 +88,8 @@ export default { displayName() { return getCurrentUser().displayName }, - /** - * The message displayed in the top right corner - * - * @returns {String} - */ - visibleMessage() { - if (this.customIcon && this.customMessage) { - return `${this.customIcon} ${this.customMessage}` - } - if (this.customMessage) { - return this.customMessage - } - - if (this.statusIsUserDefined) { - switch (this.statusType) { - case 'online': - return this.$t('user_status', 'Online') - - case 'away': - return this.$t('user_status', 'Away') - - case 'dnd': - return this.$t('user_status', 'Do not disturb') - - case 'invisible': - return this.$t('user_status', 'Invisible') - - case 'offline': - return this.$t('user_status', 'Offline') - } - } - - return this.$t('user_status', 'Set status') - }, - /** - * The status indicator icon - * - * @returns {String|null} - */ - statusIcon() { - switch (this.statusType) { - case 'online': - return 'icon-user-status-online' - - case 'away': - return 'icon-user-status-away' - - case 'dnd': - return 'icon-user-status-dnd' - - case 'invisible': - case 'offline': - return 'icon-user-status-invisible' - } - - return '' - }, }, + /** * Loads the current user's status from initial state * and stores it in Vuex @@ -198,6 +125,7 @@ export default { this._backgroundHeartbeat() } }, + /** * Some housekeeping before destroying the component */ @@ -205,6 +133,7 @@ export default { window.removeEventListener('mouseMove', this.mouseMoveListener) clearInterval(this.heartbeatInterval) }, + methods: { /** * Opens the modal to set a custom status @@ -218,19 +147,7 @@ export default { closeModal() { this.isModalOpen = false }, - /** - * Changes the user-status - * - * @param {String} statusType (online / away / dnd / invisible) - */ - async changeStatus(statusType) { - try { - await this.$store.dispatch('setStatus', { statusType }) - } catch (err) { - showError(this.$t('user_status', 'There was an error saving the new status')) - console.debug(err) - } - }, + /** * Sends the status heartbeat to the server * @@ -248,65 +165,55 @@ export default { <style lang="scss"> $max-width-user-status: 200px; -li:not(.inline) #user-status-menu-item { +.user-status-menu-item { &__header { display: block; + overflow: hidden; box-sizing: border-box; - color: var(--color-text-maxcontrast); + max-width: $max-width-user-status; padding: 10px 12px 5px 38px; - opacity: 1; - white-space: nowrap; text-align: left; - max-width: $max-width-user-status; - overflow: hidden; + white-space: nowrap; text-overflow: ellipsis; + opacity: 1; + color: var(--color-text-maxcontrast); } - &__subheader { - width: 100%; - - button.action-item__menutoggle { - display: block; - box-sizing: border-box; - background-color: var(--color-main-background); - background-position: 12px center; + &__toggle { + &-icon { + width: 16px; + height: 16px; + margin-right: 10px; + opacity: 1 !important; background-size: 16px; + } + + // In dashboard + &--inline { + width: auto; + min-width: 44px; + height: 44px; + margin: 0; border: 0; - border-radius: 0; + border-radius: var(--border-radius-pill); + background-color: var(--color-background-translucent); + font-size: inherit; font-weight: normal; - padding-left: 38px; - opacity: 1; - max-width: $max-width-user-status; - overflow: hidden; - text-overflow: ellipsis; + -webkit-backdrop-filter: var(--background-blur); + backdrop-filter: var(--background-blur); + + &:active, &:hover, &:focus { - box-shadow: inset 4px 0 var(--color-primary-element); + background-color: var(--color-background-hover); } } } } -.inline #user-status-menu-item__subheader { - width: 100%; - - button.action-item__menutoggle { - background-size: 16px; - border: 0; - border-radius: var(--border-radius-pill); - font-weight: normal; - padding-left: 40px; - - &.icon-loading-small { - &::after { - left: 21px; - } - } - } +li { + list-style-type: none; } - li { - list-style-type: none; - } </style> diff --git a/apps/user_status/src/components/OnlineStatusSelect.vue b/apps/user_status/src/components/OnlineStatusSelect.vue new file mode 100644 index 0000000000000000000000000000000000000000..b03af75681eba5512e49d76a255b526b7edfe5e2 --- /dev/null +++ b/apps/user_status/src/components/OnlineStatusSelect.vue @@ -0,0 +1,103 @@ +<!-- + - @copyright Copyright (c) 2020 John Molakvoæ <skjnldsv@protonmail.com> + - + - @author John Molakvoæ <skjnldsv@protonmail.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/>. + - + --> +<template> + <div class="user-status-online-select"> + <input :id="id" + :checked="checked" + class="user-status-online-select__input" + type="radio" + name="user-status-online" + @change="onChange"> + <label :for="id" :class="icon" class="user-status-online-select__label"> + <slot /> + </label> + </div> +</template> + +<script> +export default { + name: 'OnlineStatusSelect', + + props: { + checked: { + type: Boolean, + default: false, + }, + icon: { + type: String, + required: true, + }, + type: { + type: String, + required: true, + }, + }, + + computed: { + id() { + return `user-status-online-status-${this.type}` + }, + }, + + methods: { + onChange() { + this.$emit('select', this.type) + }, + }, +} +</script> + +<style lang="scss" scoped> +$icon-size: 24px; +$label-padding: 8px; + +.user-status-online-select { + // Inputs are here for keyboard navigation, they are not visually visible + &__input { + position: absolute; + top: auto; + left: -10000px; + overflow: hidden; + width: 1px; + height: 1px; + } + + &__label { + display: block; + margin: $label-padding; + padding: $label-padding; + padding-left: $icon-size + $label-padding * 2; + border: 2px solid var(--color-main-background); + border-radius: var(--border-radius-large); + background-color: var(--color-background-hover); + background-position: $label-padding center; + background-size: $icon-size; + } + + &__input:checked + &__label, + &__input:focus + &__label, + &__label:hover { + border-color: var(--color-primary); + } +} + +</style> diff --git a/apps/user_status/src/components/SetStatusModal.vue b/apps/user_status/src/components/SetStatusModal.vue index c0652ce990b43e6078afbb279324d0f2970f8b31..c6d48d493cea877f20011eea08dfe02981c9bc60 100644 --- a/apps/user_status/src/components/SetStatusModal.vue +++ b/apps/user_status/src/components/SetStatusModal.vue @@ -22,11 +22,27 @@ <template> <Modal size="normal" - :title="$t('user_status', 'Set status message')" + :title="$t('user_status', 'Set status')" @close="closeModal"> <div class="set-status-modal"> + <!-- Status selector --> <div class="set-status-modal__header"> - <h3>{{ $t('user_status', 'Set status message') }}</h3> + <h3>{{ $t('user_status', 'Online status') }}</h3> + </div> + <div class="set-status-modal__online-status"> + <OnlineStatusSelect v-for="status in statuses" + :key="status.type" + v-bind="status" + :checked="status.type === statusType" + @select="changeStatus"> + {{ status.label }} + <em class="subline">{{ status.subline }}</em> + </OnlineStatusSelect> + </div> + + <!-- Status message --> + <div class="set-status-modal__header"> + <h3>{{ $t('user_status', 'Status message') }}</h3> </div> <div class="set-status-modal__custom-input"> <EmojiPicker @select="setIcon"> @@ -57,27 +73,36 @@ </template> <script> +import { showError } from '@nextcloud/dialogs' import EmojiPicker from '@nextcloud/vue/dist/Components/EmojiPicker' import Modal from '@nextcloud/vue/dist/Components/Modal' + +import { getAllStatusOptions } from '../services/statusOptionsService' +import OnlineStatusMixin from '../mixins/OnlineStatusMixin' import PredefinedStatusesList from './PredefinedStatusesList' import CustomMessageInput from './CustomMessageInput' import ClearAtSelect from './ClearAtSelect' -import { showError } from '@nextcloud/dialogs' +import OnlineStatusSelect from './OnlineStatusSelect' export default { name: 'SetStatusModal', + components: { + ClearAtSelect, + CustomMessageInput, EmojiPicker, Modal, - CustomMessageInput, + OnlineStatusSelect, PredefinedStatusesList, - ClearAtSelect, }, + mixins: [OnlineStatusMixin], + data() { return { + clearAt: null, icon: null, message: null, - clearAt: null, + statuses: getAllStatusOptions(), } }, computed: { @@ -90,6 +115,7 @@ export default { return this.icon || '😀' }, }, + /** * Loads the current status when a user opens dialog */ @@ -208,6 +234,25 @@ export default { min-width: 500px; min-height: 200px; padding: 8px 20px 20px 20px; + // Enable scrollbar for too long content, same way as in Dashboard customize + max-height: 70vh; + overflow: auto; + + &__header { + text-align: center; + font-weight: bold; + } + + &__online-status { + display: grid; + // Space between the two sections + margin-bottom: 40px; + grid-template-columns: 1fr 1fr; + + .subline { + display: block; + } + } &__custom-input { display: flex; @@ -216,12 +261,12 @@ export default { .custom-input__emoji-button { flex-basis: 40px; - width: 40px; flex-grow: 0; - border-radius: var(--border-radius) 0 0 var(--border-radius); + width: 40px; height: 34px; margin-right: 0; border-right: none; + border-radius: var(--border-radius) 0 0 var(--border-radius); } } @@ -233,4 +278,5 @@ export default { } } } + </style> diff --git a/apps/user_status/src/main-user-status-menu.js b/apps/user_status/src/main-user-status-menu.js index 322585c3f0c57a198e05a58f4f5c61597ccc28ef..12fda36e85b8baff995fd31e916a42f6ab9e69b2 100644 --- a/apps/user_status/src/main-user-status-menu.js +++ b/apps/user_status/src/main-user-status-menu.js @@ -21,7 +21,7 @@ */ import Vue from 'vue' import { getRequestToken } from '@nextcloud/auth' -import App from './App' +import UserStatus from './UserStatus' import store from './store' // eslint-disable-next-line camelcase @@ -36,18 +36,23 @@ __webpack_public_path__ = OC.linkTo('user_status', 'js/') Vue.prototype.t = t Vue.prototype.$t = t -const app = new Vue({ - render: h => h(App), +// Register settings menu entry +export default new Vue({ + el: 'li[data-id="user_status-menuitem"]', + // eslint-disable-next-line vue/match-component-file-name + name: 'UserStatusRoot', + render: h => h(UserStatus), store, -}).$mount('li[data-id="user_status-menuitem"]') +}) +// Register dashboard status document.addEventListener('DOMContentLoaded', function() { if (!OCA.Dashboard) { return } OCA.Dashboard.registerStatus('status', (el) => { - const Dashboard = Vue.extend(App) + const Dashboard = Vue.extend(UserStatus) return new Dashboard({ propsData: { inline: true, @@ -56,5 +61,3 @@ document.addEventListener('DOMContentLoaded', function() { }).$mount(el) }) }) - -export { app } diff --git a/apps/user_status/src/mixins/OnlineStatusMixin.js b/apps/user_status/src/mixins/OnlineStatusMixin.js new file mode 100644 index 0000000000000000000000000000000000000000..ceba40f05e7179c63fa492283b30b69fe1cea40d --- /dev/null +++ b/apps/user_status/src/mixins/OnlineStatusMixin.js @@ -0,0 +1,110 @@ +/** + * @copyright Copyright (c) 2020 John Molakvoæ <skjnldsv@protonmail.com> + * + * @author John Molakvoæ <skjnldsv@protonmail.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/>. + * + */ +import { mapState } from 'vuex' +import { showError } from '@nextcloud/dialogs' + +export default { + computed: { + ...mapState({ + statusType: state => state.userStatus.status, + statusIsUserDefined: state => state.userStatus.statusIsUserDefined, + customIcon: state => state.userStatus.icon, + customMessage: state => state.userStatus.message, + }), + + /** + * The message displayed in the top right corner + * + * @returns {String} + */ + visibleMessage() { + if (this.customIcon && this.customMessage) { + return `${this.customIcon} ${this.customMessage}` + } + + if (this.customMessage) { + return this.customMessage + } + + if (this.statusIsUserDefined) { + switch (this.statusType) { + case 'online': + return this.$t('user_status', 'Online') + + case 'away': + return this.$t('user_status', 'Away') + + case 'dnd': + return this.$t('user_status', 'Do not disturb') + + case 'invisible': + return this.$t('user_status', 'Invisible') + + case 'offline': + return this.$t('user_status', 'Offline') + } + } + + return this.$t('user_status', 'Set status') + }, + + /** + * The status indicator icon + * + * @returns {String|null} + */ + statusIcon() { + switch (this.statusType) { + case 'online': + return 'icon-user-status-online' + + case 'away': + return 'icon-user-status-away' + + case 'dnd': + return 'icon-user-status-dnd' + + case 'invisible': + case 'offline': + return 'icon-user-status-invisible' + } + + return '' + }, + }, + + methods: { + /** + * Changes the user-status + * + * @param {String} statusType (online / away / dnd / invisible) + */ + async changeStatus(statusType) { + try { + await this.$store.dispatch('setStatus', { statusType }) + } catch (err) { + showError(this.$t('user_status', 'There was an error saving the new status')) + console.debug(err) + } + }, + }, +} diff --git a/apps/user_status/src/services/statusOptionsService.js b/apps/user_status/src/services/statusOptionsService.js index 9c646915a651bd06cbf1c1f6fbcc3eb9713f872a..266f33230cd7d6817dd251838c143039a4ff1f8f 100644 --- a/apps/user_status/src/services/statusOptionsService.js +++ b/apps/user_status/src/services/statusOptionsService.js @@ -44,6 +44,7 @@ const getAllStatusOptions = () => { }, { type: 'invisible', label: t('user_status', 'Invisible'), + subline: t('user_status', 'Appear offline'), icon: 'icon-user-status-invisible', }] } diff --git a/apps/user_status/webpack.js b/apps/user_status/webpack.js index 4b3372b25c737f915c500b7e4e851bb5e7faf771..178bd28e7a5e5206a4c88ae3d6ce386646b17010 100644 --- a/apps/user_status/webpack.js +++ b/apps/user_status/webpack.js @@ -2,18 +2,18 @@ const path = require('path') module.exports = { entry: { - 'dashboard': path.join(__dirname, 'src', 'dashboard'), - 'user-status-menu': path.join(__dirname, 'src', 'main-user-status-menu') + dashboard: path.join(__dirname, 'src', 'dashboard'), + 'user-status-menu': path.join(__dirname, 'src', 'main-user-status-menu'), }, output: { path: path.resolve(__dirname, './js'), publicPath: '/js/', filename: '[name].js?v=[chunkhash]', - jsonpFunction: 'webpackJsonpUserStatus' + jsonpFunction: 'webpackJsonpUserStatus', }, optimization: { splitChunks: { automaticNameDelimiter: '-', - } - } + }, + }, } diff --git a/apps/weather_status/js/weather-status.js b/apps/weather_status/js/weather-status.js index 3561299491bc08de97fcb76abda8cd0dc5dab9f4..3999da95ad1aae6e99dcf9be7e87534d6607b29d 100644 Binary files a/apps/weather_status/js/weather-status.js and b/apps/weather_status/js/weather-status.js differ diff --git a/apps/weather_status/js/weather-status.js.map b/apps/weather_status/js/weather-status.js.map index 61d31ae91edb46d33951626988a12846030cb885..6597b4b158cf79e552aaa5216ab0a09604652810 100644 Binary files a/apps/weather_status/js/weather-status.js.map and b/apps/weather_status/js/weather-status.js.map differ diff --git a/apps/workflowengine/js/workflowengine.js b/apps/workflowengine/js/workflowengine.js index 6a66ee01c897cbb369bbc7bd2c88c0aae560d0c4..42d57d5ea5801b1eb294c647ea7279540704d4d1 100644 Binary files a/apps/workflowengine/js/workflowengine.js and b/apps/workflowengine/js/workflowengine.js differ diff --git a/apps/workflowengine/js/workflowengine.js.map b/apps/workflowengine/js/workflowengine.js.map index ee6783c472442548034bd2ba9d53cba5084f3839..4d8e5b5626d7750ec7b2bf086a8540a729e1b329 100644 Binary files a/apps/workflowengine/js/workflowengine.js.map and b/apps/workflowengine/js/workflowengine.js.map differ diff --git a/core/js/dist/unified-search.js b/core/js/dist/unified-search.js index 5e6068c585e480645d5a7bfff31ec5f24a686a86..9558f11c55206df9f24a4128c2a25f050b5568d9 100644 Binary files a/core/js/dist/unified-search.js and b/core/js/dist/unified-search.js differ diff --git a/core/js/dist/unified-search.js.map b/core/js/dist/unified-search.js.map index 227dcc73656c618989d60229f5b15fedef31e6f5..bfa696930a780d627917c60864dbfb38619a1f84 100644 Binary files a/core/js/dist/unified-search.js.map and b/core/js/dist/unified-search.js.map differ diff --git a/package-lock.json b/package-lock.json index 0ac83eb145fdbe04eba2bd343852adffa32f6ec5..5343f8fc8ce680fc1aabf8024380bbf065d6f4b4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1272,9 +1272,9 @@ } }, "@nextcloud/vue": { - "version": "2.6.6", - "resolved": "https://registry.npmjs.org/@nextcloud/vue/-/vue-2.6.6.tgz", - "integrity": "sha512-amlFNT5uDnz8ryFeD4birEXXx2K0KyV5nthYoIuz6A7liOxFwOF7BX7jNwhYkM21JvSloMCfm76BcK+DxtShOw==", + "version": "2.6.7", + "resolved": "https://registry.npmjs.org/@nextcloud/vue/-/vue-2.6.7.tgz", + "integrity": "sha512-ISu1ceEifRpQ7TiXykCnr/mPPtmlmGLW2hOOq3DBbpxueiEk8w6JCBB7SCwNbSg01T/vm01dlnT1ibHm1HjAIg==", "requires": { "@nextcloud/auth": "^1.2.3", "@nextcloud/axios": "^1.3.2", diff --git a/package.json b/package.json index b542abb479a9b1c71b3999c268b20dc7da0fb76f..9e10317ddb1431235e2d5fb4d0b5c5c34a008104 100644 --- a/package.json +++ b/package.json @@ -39,7 +39,7 @@ "@nextcloud/password-confirmation": "^1.0.1", "@nextcloud/paths": "^1.1.2", "@nextcloud/router": "^1.1.0", - "@nextcloud/vue": "^2.6.6", + "@nextcloud/vue": "^2.6.7", "@nextcloud/vue-dashboard": "^1.0.1", "autosize": "^4.0.2", "backbone": "^1.4.0", diff --git a/tests/acceptance/features/header.feature b/tests/acceptance/features/header.feature index 94b08e8f6d94bfd9d1ac8d3396636b5142762124..df9d8045b8b36eb49a5371f743c5ce61dab20b6c 100644 --- a/tests/acceptance/features/header.feature +++ b/tests/acceptance/features/header.feature @@ -5,7 +5,8 @@ Feature: header Given I am logged in as the admin When I open the Settings menu Then I see that the Settings menu is shown - And I see that the Settings menu has only 5 items + And I see that the Settings menu has only 6 items + And I see that the "Set status" item in the Settings menu is shown And I see that the "Settings" item in the Settings menu is shown And I see that the "Apps" item in the Settings menu is shown And I see that the "Users" item in the Settings menu is shown @@ -16,7 +17,8 @@ Feature: header Given I am logged in When I open the Settings menu Then I see that the Settings menu is shown - And I see that the Settings menu has only 3 items + And I see that the Settings menu has only 4 items + And I see that the "Set status" item in the Settings menu is shown And I see that the "Settings" item in the Settings menu is shown And I see that the "Help" item in the Settings menu is shown And I see that the "Log out" item in the Settings menu is shown