summaryrefslogtreecommitdiffstats
path: root/core/src
diff options
context:
space:
mode:
authorChristopher Ng <chrng8@gmail.com>2023-01-12 01:35:53 +0000
committerChristopher Ng <chrng8@gmail.com>2023-01-13 23:19:28 +0000
commitf6aa5224c4c8a1e9e57f0a8069bd5f70054314e8 (patch)
treedf492c57c99bd6cfeea6d381faf1beb693cad89c /core/src
parentf7ff54860bef10c856542bb17ceb90e824c62dc8 (diff)
downloadnextcloud-server-f6aa5224c4c8a1e9e57f0a8069bd5f70054314e8.tar.gz
nextcloud-server-f6aa5224c4c8a1e9e57f0a8069bd5f70054314e8.zip
Focus trap contacts menu with NcHeaderMenu port
Signed-off-by: Christopher Ng <chrng8@gmail.com> Signed-off-by: nextcloud-command <nextcloud-command@users.noreply.github.com> Signed-off-by: Christopher Ng <chrng8@gmail.com>
Diffstat (limited to 'core/src')
-rw-r--r--core/src/OC/contactsmenu.js42
-rw-r--r--core/src/components/ContactsMenu.js19
-rw-r--r--core/src/views/ContactsMenu.vue198
3 files changed, 218 insertions, 41 deletions
diff --git a/core/src/OC/contactsmenu.js b/core/src/OC/contactsmenu.js
index 7e1586aeead..b9f4b0fc064 100644
--- a/core/src/OC/contactsmenu.js
+++ b/core/src/OC/contactsmenu.js
@@ -381,8 +381,7 @@ const ContactsMenuView = View.extend({
/**
* @param {Object} options
- * @param {jQuery} options.el
- * @param {jQuery} options.trigger
+ * @param {string} options.el
* @class ContactsMenu
* @memberOf OC
*/
@@ -391,12 +390,9 @@ const ContactsMenu = function(options) {
}
ContactsMenu.prototype = {
- /** @type {jQuery} */
+ /** @type {string} */
$el: undefined,
- /** @type {jQuery} */
- _$trigger: undefined,
-
/** @type {ContactsMenuView} */
_view: undefined,
@@ -405,41 +401,19 @@ ContactsMenu.prototype = {
/**
* @param {Object} options
- * @param {jQuery} options.el - the element to render the menu in
- * @param {jQuery} options.trigger - the element to click on to open the menu
+ * @param {string} options.el - the selector of the element to render the menu in
* @returns {undefined}
*/
initialize: function(options) {
- this.$el = options.el
- this._$trigger = options.trigger
+ this.$el = $(options.el)
this._view = new ContactsMenuView({
- el: this.$el
+ el: this.$el,
})
+
this._view.on('search', function(searchTerm) {
- this._loadContacts(searchTerm)
+ this.loadContacts(searchTerm)
}, this)
-
- OC.registerMenu(this._$trigger, this.$el, function() {
- this._toggleVisibility(true)
- }.bind(this), true)
- this.$el.on('beforeHide', function() {
- this._toggleVisibility(false)
- }.bind(this))
- },
-
- /**
- * @private
- * @param {boolean} show
- * @returns {Promise}
- */
- _toggleVisibility: function(show) {
- if (show) {
- return this._loadContacts()
- } else {
- this.$el.html('')
- return Promise.resolve()
- }
},
/**
@@ -461,7 +435,7 @@ ContactsMenu.prototype = {
* @param {string|undefined} searchTerm
* @returns {undefined}
*/
- _loadContacts: function(searchTerm) {
+ loadContacts: function(searchTerm) {
var self = this
if (!self._contactsPromise) {
diff --git a/core/src/components/ContactsMenu.js b/core/src/components/ContactsMenu.js
index cf031331a50..1b7b25873d0 100644
--- a/core/src/components/ContactsMenu.js
+++ b/core/src/components/ContactsMenu.js
@@ -2,6 +2,7 @@
* @copyright 2019 Christoph Wurst <christoph@winzerhof-wurst.at>
*
* @author Christoph Wurst <christoph@winzerhof-wurst.at>
+ * @author Christopher Ng <chrng8@gmail.com>
* @author John Molakvoæ <skjnldsv@protonmail.com>
*
* @license AGPL-3.0-or-later
@@ -21,16 +22,20 @@
*
*/
-import $ from 'jquery'
-import OC from '../OC'
+import Vue from 'vue'
+
+import ContactsMenu from '../views/ContactsMenu.vue'
/**
* @todo move to contacts menu code https://github.com/orgs/nextcloud/projects/31#card-21213129
*/
export const setUp = () => {
- // eslint-disable-next-line no-new
- new OC.ContactsMenu({
- el: $('#contactsmenu .menu'),
- trigger: $('#contactsmenu .menutoggle'),
- })
+ const mountPoint = document.getElementById('contactsmenu')
+ if (mountPoint) {
+ // eslint-disable-next-line no-new
+ new Vue({
+ el: mountPoint,
+ render: h => h(ContactsMenu),
+ })
+ }
}
diff --git a/core/src/views/ContactsMenu.vue b/core/src/views/ContactsMenu.vue
new file mode 100644
index 00000000000..f03652bb477
--- /dev/null
+++ b/core/src/views/ContactsMenu.vue
@@ -0,0 +1,198 @@
+<!--
+ - @copyright 2023 Christopher Ng <chrng8@gmail.com>
+ -
+ - @author Christopher Ng <chrng8@gmail.com>
+ -
+ - @license AGPL-3.0-or-later
+ -
+ - 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>
+ <NcHeaderMenu id="contactsmenu"
+ :aria-label="t('core', 'Search contacts')"
+ @open="handleOpen">
+ <template #trigger>
+ <Contacts :size="20" />
+ </template>
+ <div id="contactsmenu-menu" />
+ </NcHeaderMenu>
+</template>
+
+<script>
+import NcHeaderMenu from '@nextcloud/vue/dist/Components/NcHeaderMenu.js'
+
+import Contacts from 'vue-material-design-icons/Contacts.vue'
+
+import OC from '../OC/index.js'
+
+export default {
+ name: 'ContactsMenu',
+
+ components: {
+ Contacts,
+ NcHeaderMenu,
+ },
+
+ data() {
+ return {
+ contactsMenu: null,
+ }
+ },
+
+ mounted() {
+ // eslint-disable-next-line no-new
+ this.contactsMenu = new OC.ContactsMenu({
+ el: '#contactsmenu-menu',
+ })
+ },
+
+ methods: {
+ handleOpen() {
+ this.contactsMenu?.loadContacts()
+ },
+ },
+}
+</script>
+
+<style lang="scss" scoped>
+#contactsmenu-menu {
+ /* show 2.5 to 4.5 entries depending on the screen height */
+ height: calc(100vh - 50px * 3);
+ max-height: calc(50px * 6 + 2px);
+ min-height: calc(50px * 3.5);
+ width: 350px;
+
+ &:deep {
+ .emptycontent {
+ margin-top: 5vh !important;
+ margin-bottom: 1.5vh;
+ .icon-loading,
+ .icon-search {
+ display: inline-block;
+ }
+ }
+
+ #contactsmenu-search {
+ width: calc(100% - 16px);
+ margin: 8px;
+ height: 34px;
+ }
+
+ .content {
+ /* fixed max height of the parent container without the search input */
+ height: calc(100vh - 50px * 3 - 50px);
+ max-height: calc(50px * 5);
+ min-height: calc(50px * 3.5 - 50px);
+ overflow-y: auto;
+
+ .footer {
+ text-align: center;
+
+ a {
+ display: block;
+ width: 100%;
+ padding: 12px 0;
+ opacity: .5;
+ }
+ }
+ }
+
+ a {
+ padding: 2px;
+
+ &:focus-visible {
+ box-shadow: inset 0 0 0 2px var(--color-main-text) !important; // override rule in core/css/headers.scss #header a:focus-visible
+ }
+ }
+
+ .contact {
+ display: flex;
+ position: relative;
+ align-items: center;
+ padding: 3px 3px 3px 10px;
+
+ .avatar {
+ height: 32px;
+ width: 32px;
+ display: inline-block;
+ }
+
+ .body {
+ flex-grow: 1;
+ padding-left: 8px;
+
+ div {
+ position: relative;
+ width: 100%;
+ }
+
+ .full-name, .last-message {
+ /* TODO: don't use fixed width */
+ max-width: 204px;
+ overflow: hidden;
+ white-space: nowrap;
+ text-overflow: ellipsis;
+ }
+ .last-message, .email-address {
+ color: var(--color-text-maxcontrast);
+ }
+ }
+
+ .top-action, .second-action, .other-actions {
+ width: 16px;
+ height: 16px;
+ opacity: .5;
+ cursor: pointer;
+
+ &:not(button) {
+ padding: 14px;
+ }
+ img {
+ filter: var(--background-invert-if-dark);
+ }
+
+ &:hover,
+ &:active,
+ &:focus {
+ opacity: 1;
+ }
+ }
+
+ button.other-actions {
+ width: 44px;
+
+ &:focus {
+ border-color: transparent;
+ box-shadow: 0 0 0 2px var(--color-main-text);
+ }
+
+ &:focus-visible {
+ border-radius: var(--border-radius-pill);
+ }
+ }
+
+ /* actions menu */
+ .menu {
+ top: 47px;
+ margin-right: 13px;
+ }
+ .popovermenu::after {
+ right: 2px;
+ }
+ }
+ }
+}
+</style>