mirror of
https://github.com/nextcloud/server.git
synced 2026-02-18 18:28:50 -05:00
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>
This commit is contained in:
parent
f7ff54860b
commit
f6aa5224c4
17 changed files with 235 additions and 220 deletions
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
|
@ -1 +1 @@
|
|||
{"version":3,"sourceRoot":"","sources":["styles.scss"],"names":[],"mappings":"AAkBA,yQACC,SACA,UACA,SACA,oBACA,eACA,oBACA,wBACA,eACA,uDACA,qBAGD,6CACC,aAID,kGAEC,gDACA,aAGD,UACC,YAGD,6DACC,cAGD,KACC,gBAGD,MACC,yBACA,iBACA,mBAGD,cACC,gBACA,mBAGD,YACC,sBAGD,EACC,SACA,6BACA,qBACA,eACA,IACC,eAIF,WACC,aACA,0BAGD,MACC,eACA,QACC,eAIF,0BACC,eAGD,GACC,gBAGD,KACC,mBAEA,mCACA,uCACA,6BACA,6BAGD,mBACC,kBAGD,qBACC,kBACA,uBACA,qBACA,2BACA,2DACA,uBAGD,iBACC,qBACA,aACA,gCAGD,eACC,YACA,aAGD,cACC,eACA,MACA,SACA,OACA,YACA,WACA,aACA,kBACA,gDACA,gCACA,iBACA,eACA,kBACC,cACA,kBACA,UACA,QACA,gBAED,gBACC,gCACA,sDACA,4CACC,qCAOH,oBACC,WACA,YAGD,gCACC,+BAGD,0BACC,kCACA,yCACA,+BACA,4BAMD,YACC,8CACA,gCAMD,kBACC,sBAKD,4BAEC,oCACA,kBACA,gBACA,WACA,sDACC,gBAED,sEACC,gBAED,kCACC,mBAED,oHAEC,qBACA,YACA,WACA,mBACA,gcAEC,WAOH,sBACC,WASD,oCACC,kBACA,yBACA,sBACA,qBACA,iBAKD,kBACC,kBACA,UACA,SACA,YAGD,8BACC,WACA,oBACA,wBACA,wBAGD,2EACC,WAED,oGACC,0CACA,UACA,qBAGD,mDACC,6BACA,YACA,WACA,yCACA,4BACA,2BACA,WAOA,qEACC,UAED,qEACC,UAIF,wEACC,aAGD,2CACC,mBAGD,yBACC,kBACA,qBACA,iBAED,qBACC,cACA,QACA,iBACA,kBACA,aAKD,4CACC,eACA,YACA,mCACA,6BACA,qDAIA,2BACC,4BAKD,wBACC,sBACA,4BACA,+BACC,2CACA,qBACA,kBAGF,0BACC,qBACA,gBAIF,YACC,YACA,8BACA,oBACC,sBAIF,eACC,2CAUD,mBACC,kBACA,cACA,2BACC,kBACA,cAIF,UACC,gBAGD,8CACC,UAIA,oGAGC,WAIF,mBACC,WACA,kBACA,QAEA,kDACC,UAIF,WACC,WACA,YAGD,eACC,WAIA,8CACC,UAKD,kDACC,UAKD,0CACC,UAKD,8CACC,8CAIF,KACC,mFAGD,OACC,gBACA,YACA,eACA,qBACA,UACC,qBAIF,2FACC,gBACA,uBAGD,2BACC,yDAGD,2BACC,6DAID,yBACC,gBACA,gBACA,WACA,mCACA,YACA,wBAEA,sKAGC,+BACA,mBAED,2CACC,YACA,eACA,YACA,8CACA,6BAEA,gEACC,cACA,mBAED,oDACC,WAEA,8EACC,yEAED,8EACC,wEAGF,oEACC,UAID,oDACC,mBACA,gCACA,WACA,WACA,YAED,0DACC,yBAGA,+FACC,gDAGD,wOAGC,sCACA,gCACA,iBAGD,yNAEC,gCACA,WAMJ,wCACC,gCACA,wCAKD,yBACC,2BACA,sBACA,mCACA,wBAEA,4CACC,uBAGD,sKAGC,+BACA,mBAED,2CACC,YACA,eACA,YACA,8CACA,6BAEA,gEACC,cACA,mBAIF,qFACC,iBAGA,iDACC,mBACA,gCACA,WACA,yDACC,UACA,WACA,iBAGF,uDACC,yBAGA,0TAIC,sCACA,gCACA,iBAGD,4FACC,gCAGD,qEACC,2CASH,oGACC,aACA,iBACA,8BACA,0GACC,cACA,SACA,YACA,YACA,WACA,aACA,mBACA,uBACA,8GACC,kBACA,kBACA,mBACA,6BACA,cACA,iBACA,WACA,YACA,YACA,eAOJ,8BACC,kBACA,aACA,sBAEA,uCACC,eACA,sBACA,oBAEA,yDACC,uCACA,4BACA,gCAGA,6DACC,eAED,uDACC,iBAED,oEACC,YACA,YAKH,mDACC,kBACA,+BACA,YACA,SACA,aACA,WACA,QACA,MAEA,4KAGC,0CACA,UAIF,iDACC,eACA,YACA,sBACA,oBACA,WACA,gBACA,eACA,8CACA,0CACA,wCACA,kBACA,UACA,QACA,QAEA,gEACC,sCACA,0BACA,WACA,YACA,WACA,WAGD,mDACC,WACA,YACA,gBAGD,uDACC,SACA,gBACA,4DACC,aACA,YAMH,kDACC,sBACA,qBACA,gBACA,OAGA,WACA,kBAED,4CACC,oCACA,kBACA,gBACA,WACA,aAED,wCACC,8CACA,WAED,0DAEC,kBACA,mBAEC,mEACC,4CACA,8CACA,sEACC,UACA,YAIH,0EACC,cACA,aACA,YACA,sBACA,2BACA,sBAED,+EACC,iBACA,iBAGD,6EACC,WACA,WACA,gBACA,qBACA,2BACA,WAED,qQAGC,kBAED,oLAEC,mBAGD,6DACC,aACA,4CAED,2EACC,mBAED,oEACC,gBACA,mBACA,uBACA,qBACA,4BACA,kBACA,4BACA,eAEA,YACA,oFACC,aACA,2FACC,gBACA,gBACA,uBAED,0FACC,gBAIH,oIACC,WAED,oEACC,iBAED,oEAIC,aACA,sBAEA,0EACC,aACA,+CACA,6BACA,aACA,cAEA,6EACC,cACA,kBACA,mCACA,QAhBS,KAiBT,aACA,sBACA,YAGA,gFACC,YACA,UACA,kBACA,mCAEA,yFACC,oBACA,+BACA,wBACA,YA/BU,KAgCV,eACA,yGACC,uBAGF,yFACC,iBACA,WAED,qFACC,aAON,2DACC,gDAIF,WACC,0BAGD,aACC,WACA,sBAMA,0BACC,eACA,iCACC,0BACA,4BACA,0BACA,0BACA,aACA,YAEA,qDACA,gDAGD,iGAGC,qBAKD,mCACC,YAEA,iDACC,6DAMJ,6CAEC,2BACA,iBACA,iBACA,YAEA,2DACC,0BACA,kBACA,iJAEC,qBAIF,sDAEC,kCACA,iBACA,iBACA,gBAEA,8DACC,kBAEA,gEACC,cACA,WACA,eACA,WAKH,sDACC,aACA,kBACA,mBACA,yBAEA,8DACC,YACA,WACA,qBAGD,4DACC,YACA,iBAEA,gEACC,kBACA,WAGD,iJAEC,gBACA,gBACA,mBACA,uBAED,qJACC,oCAIF,4MACC,WACA,YACA,WACA,eAEA,gPACC,aAED,wNACC,wCAGD,6pBAGC,UAIF,2EACC,WAEA,iFACC,2BACA,4CAGD,yFACC,wCAKF,4DACC,SACA,kBAED,0EACC,UAMH,qBACC,wBACA,WACA,YAKD,YACC,6BAMA,qBACC,WACA,aAED,wBACC,cACA,gDACA,WACA,aAED,2BACC,WACA,YACA,6BACC,WAGF,wBACC,wCACA,kBACA,mBACA,gBACA,uBACA,0CACA,kCACA,6DACC,0CAGF,sBACC,UACA,WAKF,YACC,oBAED,UACC,oBACA,kDACA,4BACA,iCACA,YACA,0BACA,cACA,QACA,kBACA,oBACC,QACA,kBACA,sBACC,WAIA,0FACC,cAIF,iCACC,SACA,iBACA,oCACC,iBACA,gBACA,kBACA,kBACA,gEACC,+EAGF,gDACC,aAIH,iBACC,aACA,wBACC,QAGF,2BAEC,kBACA,aACA,WACA,uBACA,mBACA,gBACA,cAEA,gBAEA,kGAGC,oBAGF,0BACC,UACA,WAID,qBACC,iBACA,kBAEA,4BACC,eAGF,mEACC,UAEA,kKAEC,WAOH,QACC,UACA,yCACA,sCACA,qCACA,oCACA,iCACA,oBACC,UAOD,+CACC,SACA,kBAED,mDACC,gBAKF,cACC,mBAMD,mBACC,aACA,QACA,SACA","file":"styles.css"}
|
||||
{"version":3,"sourceRoot":"","sources":["styles.scss"],"names":[],"mappings":"AAkBA,yQACC,SACA,UACA,SACA,oBACA,eACA,oBACA,wBACA,eACA,uDACA,qBAGD,6CACC,aAID,kGAEC,gDACA,aAGD,UACC,YAGD,6DACC,cAGD,KACC,gBAGD,MACC,yBACA,iBACA,mBAGD,cACC,gBACA,mBAGD,YACC,sBAGD,EACC,SACA,6BACA,qBACA,eACA,IACC,eAIF,WACC,aACA,0BAGD,MACC,eACA,QACC,eAIF,0BACC,eAGD,GACC,gBAGD,KACC,mBAEA,mCACA,uCACA,6BACA,6BAGD,mBACC,kBAGD,qBACC,kBACA,uBACA,qBACA,2BACA,2DACA,uBAGD,iBACC,qBACA,aACA,gCAGD,eACC,YACA,aAGD,cACC,eACA,MACA,SACA,OACA,YACA,WACA,aACA,kBACA,gDACA,gCACA,iBACA,eACA,kBACC,cACA,kBACA,UACA,QACA,gBAED,gBACC,gCACA,sDACA,4CACC,qCAOH,oBACC,WACA,YAGD,gCACC,+BAGD,0BACC,kCACA,yCACA,+BACA,4BAMD,YACC,8CACA,gCAMD,kBACC,sBAKD,4BAEC,oCACA,kBACA,gBACA,WACA,sDACC,gBAED,sEACC,gBAED,kCACC,mBAED,oHAEC,qBACA,YACA,WACA,mBACA,gcAEC,WAOH,sBACC,WASD,oCACC,kBACA,yBACA,sBACA,qBACA,iBAKD,kBACC,kBACA,UACA,SACA,YAGD,8BACC,WACA,oBACA,wBACA,wBAGD,2EACC,WAED,oGACC,0CACA,UACA,qBAGD,mDACC,6BACA,YACA,WACA,yCACA,4BACA,2BACA,WAOA,qEACC,UAED,qEACC,UAIF,wEACC,aAGD,2CACC,mBAGD,yBACC,kBACA,qBACA,iBAED,qBACC,cACA,QACA,iBACA,kBACA,aAKD,4CACC,eACA,YACA,mCACA,6BACA,qDAIA,2BACC,4BAKD,wBACC,sBACA,4BACA,+BACC,2CACA,qBACA,kBAGF,0BACC,qBACA,gBAIF,YACC,YACA,8BACA,oBACC,sBAIF,eACC,2CAUD,mBACC,kBACA,cACA,2BACC,kBACA,cAIF,UACC,gBAGD,8CACC,UAIA,oGAGC,WAIF,mBACC,WACA,kBACA,QAEA,kDACC,UAIF,WACC,WACA,YAGD,eACC,WAIA,8CACC,UAKD,kDACC,UAKD,0CACC,UAKD,8CACC,8CAIF,KACC,mFAGD,OACC,gBACA,YACA,eACA,qBACA,UACC,qBAIF,2FACC,gBACA,uBAGD,2BACC,yDAGD,2BACC,6DAID,yBACC,gBACA,gBACA,WACA,mCACA,YACA,wBAEA,sKAGC,+BACA,mBAED,2CACC,YACA,eACA,YACA,8CACA,6BAEA,gEACC,cACA,mBAED,oDACC,WAEA,8EACC,yEAED,8EACC,wEAGF,oEACC,UAID,oDACC,mBACA,gCACA,WACA,WACA,YAED,0DACC,yBAGA,+FACC,gDAGD,wOAGC,sCACA,gCACA,iBAGD,yNAEC,gCACA,WAMJ,wCACC,gCACA,wCAKD,yBACC,2BACA,sBACA,mCACA,wBAEA,4CACC,uBAGD,sKAGC,+BACA,mBAED,2CACC,YACA,eACA,YACA,8CACA,6BAEA,gEACC,cACA,mBAIF,qFACC,iBAGA,iDACC,mBACA,gCACA,WACA,yDACC,UACA,WACA,iBAGF,uDACC,yBAGA,0TAIC,sCACA,gCACA,iBAGD,4FACC,gCAGD,qEACC,2CASH,oGACC,aACA,iBACA,8BACA,0GACC,cACA,SACA,YACA,YACA,WACA,aACA,mBACA,uBACA,8GACC,kBACA,kBACA,mBACA,6BACA,cACA,iBACA,WACA,YACA,YACA,eAOJ,8BACC,kBACA,aACA,sBAEA,uCACC,eACA,sBACA,oBAEA,yDACC,uCACA,4BACA,gCAGA,6DACC,eAED,uDACC,iBAED,oEACC,YACA,YAKH,mDACC,kBACA,+BACA,YACA,SACA,aACA,WACA,QACA,MAEA,4KAGC,0CACA,UAIF,iDACC,eACA,YACA,sBACA,oBACA,WACA,gBACA,eACA,8CACA,0CACA,wCACA,kBACA,UACA,QACA,QAEA,gEACC,sCACA,0BACA,WACA,YACA,WACA,WAGD,mDACC,WACA,YACA,gBAGD,uDACC,SACA,gBACA,4DACC,aACA,YAMH,kDACC,sBACA,qBACA,gBACA,OAGA,WACA,kBAED,4CACC,oCACA,kBACA,gBACA,WACA,aAED,wCACC,8CACA,WAED,0DAEC,kBACA,mBAEC,mEACC,4CACA,8CACA,sEACC,UACA,YAIH,0EACC,cACA,aACA,YACA,sBACA,2BACA,sBAED,+EACC,iBACA,iBAGD,6EACC,WACA,WACA,gBACA,qBACA,2BACA,WAED,qQAGC,kBAED,oLAEC,mBAGD,6DACC,aACA,4CAED,2EACC,mBAED,oEACC,gBACA,mBACA,uBACA,qBACA,4BACA,kBACA,4BACA,eAEA,YACA,oFACC,aACA,2FACC,gBACA,gBACA,uBAED,0FACC,gBAIH,oIACC,WAED,oEACC,iBAED,oEAIC,aACA,sBAEA,0EACC,aACA,+CACA,6BACA,aACA,cAEA,6EACC,cACA,kBACA,mCACA,QAhBS,KAiBT,aACA,sBACA,YAGA,gFACC,YACA,UACA,kBACA,mCAEA,yFACC,oBACA,+BACA,wBACA,YA/BU,KAgCV,eACA,yGACC,uBAGF,yFACC,iBACA,WAED,qFACC,aAON,2DACC,gDAIF,WACC,0BAGD,aACC,WACA,sBAKD,YACC,6BAMA,qBACC,WACA,aAED,wBACC,cACA,gDACA,WACA,aAED,2BACC,WACA,YACA,6BACC,WAGF,wBACC,wCACA,kBACA,mBACA,gBACA,uBACA,0CACA,kCACA,6DACC,0CAGF,sBACC,UACA,WAKF,YACC,oBAED,UACC,oBACA,kDACA,4BACA,iCACA,YACA,0BACA,cACA,QACA,kBACA,oBACC,QACA,kBACA,sBACC,WAIA,0FACC,cAIF,iCACC,SACA,iBACA,oCACC,iBACA,gBACA,kBACA,kBACA,gEACC,+EAGF,gDACC,aAIH,iBACC,aACA,wBACC,QAGF,2BAEC,kBACA,aACA,WACA,uBACA,mBACA,gBACA,cAEA,gBAEA,kGAGC,oBAGF,0BACC,UACA,WAID,qBACC,iBACA,kBAEA,4BACC,eAGF,mEACC,UAEA,kKAEC,WAOH,QACC,UACA,yCACA,sCACA,qCACA,oCACA,iCACA,oBACC,UAOD,+CACC,SACA,kBAED,mDACC,gBAKF,cACC,mBAMD,mBACC,aACA,QACA,SACA","file":"styles.css"}
|
||||
|
|
@ -893,160 +893,6 @@ span.ui-icon {
|
|||
margin: 3px 7px 30px 0;
|
||||
}
|
||||
|
||||
/* ---- CONTACTS MENU ---- */
|
||||
|
||||
#contactsmenu {
|
||||
.menutoggle {
|
||||
cursor: pointer;
|
||||
&:before {
|
||||
background-size: 20px 20px;
|
||||
background-repeat: no-repeat;
|
||||
background-position-x: 3px;
|
||||
background-position-y: 4px;
|
||||
padding: 14px;
|
||||
content: ' ';
|
||||
// Force white
|
||||
background-image: var(--original-icon-contacts-white);
|
||||
filter: var(--background-image-invert-if-bright);
|
||||
}
|
||||
|
||||
&:hover,
|
||||
&:focus,
|
||||
&:active {
|
||||
opacity: 1 !important;
|
||||
}
|
||||
}
|
||||
|
||||
#contactsmenu-menu {
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#header .header-right > div#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;
|
||||
|
||||
.emptycontent {
|
||||
margin-top: 5vh !important;
|
||||
margin-bottom: 2vh;
|
||||
.icon-loading,
|
||||
.icon-search {
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
|
||||
.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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#contactsmenu-search {
|
||||
width: calc(100% - 16px);
|
||||
margin: 8px;
|
||||
height: 34px;
|
||||
}
|
||||
|
||||
/* ---- TOOLTIPS ---- */
|
||||
|
||||
.extra-data {
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ describe('Contacts menu', function() {
|
|||
* @returns {Promise}
|
||||
*/
|
||||
function openMenu() {
|
||||
return menu._toggleVisibility(true);
|
||||
return menu.loadContacts();
|
||||
}
|
||||
|
||||
beforeEach(function(done) {
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
198
core/src/views/ContactsMenu.vue
Normal file
198
core/src/views/ContactsMenu.vue
Normal file
|
|
@ -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>
|
||||
|
|
@ -69,14 +69,7 @@ $getUserAvatar = static function (int $size) use ($_): string {
|
|||
<div class="header-right">
|
||||
<div id="unified-search"></div>
|
||||
<div id="notifications"></div>
|
||||
<div id="contactsmenu">
|
||||
<div class="menutoggle" tabindex="0" role="button"
|
||||
aria-haspopup="true" aria-controls="contactsmenu-menu" aria-expanded="false">
|
||||
<span class="hidden-visually"><?php p($l->t('Contacts'));?></span>
|
||||
</div>
|
||||
<div id="contactsmenu-menu" class="menu"
|
||||
aria-label="<?php p($l->t('Contacts menu'));?>"></div>
|
||||
</div>
|
||||
<div id="contactsmenu"></div>
|
||||
<div id="settings">
|
||||
<div id="expand" tabindex="0" role="button" class="menutoggle"
|
||||
aria-label="<?php p($l->t('Open settings menu'));?>"
|
||||
|
|
|
|||
4
dist/core-common.js
vendored
4
dist/core-common.js
vendored
File diff suppressed because one or more lines are too long
2
dist/core-common.js.map
vendored
2
dist/core-common.js.map
vendored
File diff suppressed because one or more lines are too long
4
dist/core-login.js
vendored
4
dist/core-login.js
vendored
File diff suppressed because one or more lines are too long
2
dist/core-login.js.map
vendored
2
dist/core-login.js.map
vendored
File diff suppressed because one or more lines are too long
4
dist/core-main.js
vendored
4
dist/core-main.js
vendored
File diff suppressed because one or more lines are too long
2
dist/core-main.js.map
vendored
2
dist/core-main.js.map
vendored
File diff suppressed because one or more lines are too long
|
|
@ -31,7 +31,7 @@ class ContactsMenuContext implements Context, ActorAwareInterface {
|
|||
* @return Locator
|
||||
*/
|
||||
public static function contactsMenuButton() {
|
||||
return Locator::forThe()->xpath("//*[@id = 'header']//*[@id = 'contactsmenu']")->
|
||||
return Locator::forThe()->xpath("//*[@id = 'header']//*[@id = 'contactsmenu']//*[@class = 'header-menu__trigger']")->
|
||||
describedAs("Contacts menu button");
|
||||
}
|
||||
|
||||
|
|
@ -39,8 +39,7 @@ class ContactsMenuContext implements Context, ActorAwareInterface {
|
|||
* @return Locator
|
||||
*/
|
||||
public static function contactsMenu() {
|
||||
return Locator::forThe()->css(".menu")->
|
||||
descendantOf(self::contactsMenuButton())->
|
||||
return Locator::forThe()->xpath("//*[@id = 'header']//*[@id = 'contactsmenu']//*[@id = 'contactsmenu-menu']")->
|
||||
describedAs("Contacts menu");
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue