@@ -12,6 +12,7 @@ import { subscribe, unsubscribe } from '@nextcloud/event-bus'
1212import { loadState } from ' @nextcloud/initial-state'
1313import { translate as t } from ' @nextcloud/l10n'
1414import { generateUrl } from ' @nextcloud/router'
15+ import { useIsMobile } from ' @nextcloud/vue/composables/useIsMobile'
1516import { computed , onBeforeMount , onBeforeUnmount , onMounted , ref } from ' vue'
1617import NcActionLink from ' @nextcloud/vue/components/NcActionLink'
1718import NcActions from ' @nextcloud/vue/components/NcActions'
@@ -22,7 +23,8 @@ import NcContent from '@nextcloud/vue/components/NcContent'
2223import NcEmptyContent from ' @nextcloud/vue/components/NcEmptyContent'
2324import NcRichText from ' @nextcloud/vue/components/NcRichText'
2425import AccountIcon from ' vue-material-design-icons/AccountOutline.vue'
25- import MapMarkerIcon from ' vue-material-design-icons/MapMarker.vue'
26+ import BriefcaseIcon from ' vue-material-design-icons/BriefcaseOutline.vue'
27+ import MapMarkerIcon from ' vue-material-design-icons/MapMarkerOutline.vue'
2628import PencilIcon from ' vue-material-design-icons/PencilOutline.vue'
2729import ProfileSection from ' ../components/ProfileSection.vue'
2830
@@ -60,9 +62,13 @@ onBeforeMount(() => {
6062})
6163
6264const isCurrentUser = getCurrentUser ()?.uid === profileParameters .userId
65+ const isMobile = useIsMobile ()
6366
6467const primaryAction = profileParameters .actions [0 ]
65- const otherActions = profileParameters .actions .slice (1 )
68+ const showEditAsPrimaryAction = computed (() => isMobile .value && isCurrentUser )
69+ const otherActions = computed (() => showEditAsPrimaryAction .value
70+ ? profileParameters .actions
71+ : profileParameters .actions .slice (1 ))
6672
6773const settingsUrl = generateUrl (' /settings/user' )
6874const emptyProfileMessage = isCurrentUser
@@ -113,35 +119,49 @@ function openStatusModal() {
113119 <NcAppContent >
114120 <div class =" profile__header" >
115121 <div class =" profile__header__container" >
122+ <NcAvatar
123+ v-if =" isMobile "
124+ class="avatar profile__header__container__avatar"
125+ :class =" { interactive: isCurrentUser } "
126+ :user =" profileParameters .userId "
127+ :size =" 120 "
128+ :disableMenu =" true "
129+ :disableTooltip =" true "
130+ :isNoUser =" ! profileParameters .isUserAvatarVisible "
131+ @click .prevent .stop =" openStatusModal " />
116132 <div class =" profile__header__container__placeholder" />
117133 <div class =" profile__header__container__displayname" >
118134 <h2 >{{ profileParameters.displayname || profileParameters.userId }}</h2 >
119- <span v-if =" profileParameters.pronouns" >·</span >
135+ <span v-if =" profileParameters.pronouns" class = " profile__header__container__pronoun-separator " >·</span >
120136 <span v-if =" profileParameters.pronouns" class =" profile__header__container__pronouns" >{{ profileParameters.pronouns }}</span >
137+ </div >
138+ <div class =" profile__header__container__controls" >
139+ <NcButton
140+ v-if =" userStatus .icon || userStatus .message "
141+ class="profile__header__container__status"
142+ :disabled =" ! isCurrentUser "
143+ :variant =" isCurrentUser ? ' tertiary' : ' tertiary-no-background' "
144+ @click =" openStatusModal " >
145+ <span class =" profile__header__container__status-content" >
146+ <span >{{ userStatus.icon }} {{ userStatus.message }}</span >
147+ <PencilIcon v-if =" isCurrentUser " :size =" 20 " />
148+ </span >
149+ </NcButton >
121150 <NcButton
122- v-if =" isCurrentUser "
151+ v-if =" isCurrentUser && ! isMobile "
123152 variant="primary"
124153 :href =" settingsUrl " >
125- <template #icon >
126- <PencilIcon :size =" 20 " />
127- </template >
128154 {{ t('profile', 'Edit Profile') }}
129155 </NcButton >
130156 </div >
131- <NcButton
132- v-if =" userStatus .icon || userStatus .message "
133- :disabled =" ! isCurrentUser "
134- :variant =" isCurrentUser ? ' tertiary' : ' tertiary-no-background' "
135- @click =" openStatusModal " >
136- {{ userStatus.icon }} {{ userStatus.message }}
137- </NcButton >
138157 </div >
139158 </div >
140159
141160 <div class =" profile__wrapper" >
142161 <div class =" profile__content" >
143162 <div class =" profile__sidebar" >
144163 <NcAvatar
164+ v-if =" ! isMobile "
145165 class="avatar"
146166 :class =" { interactive: isCurrentUser } "
147167 :user =" profileParameters .userId "
@@ -152,9 +172,16 @@ function openStatusModal() {
152172 @click .prevent .stop =" openStatusModal " />
153173
154174 <div class =" user-actions" >
175+ <NcButton
176+ v-if =" showEditAsPrimaryAction "
177+ variant="primary"
178+ class="user-actions__primary"
179+ :href =" settingsUrl " >
180+ {{ t('profile', 'Edit Profile') }}
181+ </NcButton >
155182 <!-- When a tel: URL is opened with target="_blank", a blank new tab is opened which is inconsistent with the handling of other URLs so we set target="_self" for the phone action -->
156183 <NcButton
157- v-if =" primaryAction "
184+ v-if =" primaryAction && ! showEditAsPrimaryAction "
158185 variant="primary"
159186 class="user-actions__primary"
160187 :href =" primaryAction .target "
@@ -167,7 +194,10 @@ function openStatusModal() {
167194 </template >
168195 {{ primaryAction.title }}
169196 </NcButton >
170- <NcActions class="user-actions__other" :inline =" 4 " >
197+ <NcActions
198+ v-if =" otherActions .length > 0 "
199+ class="user-actions__other"
200+ :inline =" isMobile ? 5 : 4 " >
171201 <NcActionLink
172202 v-for =" action in otherActions "
173203 :key =" action .id "
@@ -188,12 +218,17 @@ function openStatusModal() {
188218 <div class =" profile__blocks" >
189219 <div v-if =" profileParameters.organisation || profileParameters.role || profileParameters.address" class =" profile__blocks-details" >
190220 <div v-if =" profileParameters.organisation || profileParameters.role" class =" detail" >
191- <p >{{ profileParameters.organisation }} <span v-if =" profileParameters.organisation && profileParameters.role" >•</span > {{ profileParameters.role }}</p >
221+ <p >
222+ <BriefcaseIcon
223+ class="detail-icon"
224+ :size =" 16 " />
225+ {{ profileParameters.organisation }} <span v-if =" profileParameters.organisation && profileParameters.role" >•</span > {{ profileParameters.role }}
226+ </p >
192227 </div >
193228 <div v-if =" profileParameters.address" class =" detail" >
194229 <p >
195230 <MapMarkerIcon
196- class="map -icon"
231+ class="detail -icon"
197232 :size =" 16 " />
198233 {{ profileParameters.address }}
199234 </p >
@@ -233,7 +268,7 @@ $profile-max-width: 1024px;
233268$content-max-width : 640px ;
234269
235270:deep(#app-content-vue ) {
236- background-color : unset ;
271+ min-width : 320 px ;
237272}
238273
239274.profile {
@@ -282,6 +317,18 @@ $content-max-width: 640px;
282317 font-size : 20px ;
283318 }
284319 }
320+
321+ & __controls {
322+ display : flex ;
323+ align-items : center ;
324+ gap : 8px ;
325+ }
326+
327+ & __status-content {
328+ display : flex ;
329+ align-items : center ;
330+ gap : 8px ;
331+ }
285332 }
286333 }
287334
@@ -293,7 +340,10 @@ $content-max-width: 640px;
293340 min-width : 220px ;
294341 margin-block : -150px 0 ;
295342 margin-inline : 0 20px ;
343+ }
296344
345+ & __header ,
346+ & __sidebar {
297347 // Specificity hack is needed to override Avatar component styles
298348 :deep (.avatar.avatardiv ) {
299349 text-align : center ;
@@ -336,7 +386,7 @@ $content-max-width: 640px;
336386 }
337387
338388 & __blocks {
339- margin : 18px 0 80px 0 ;
389+ margin : 18px 0 80px 16 px ;
340390 display : grid ;
341391 gap : 16px 0 ;
342392 width : $content-max-width ;
@@ -355,7 +405,7 @@ $content-max-width: 640px;
355405 display : inline-block ;
356406 color : var (--color-text-maxcontrast );
357407
358- p .map -icon {
408+ p .detail -icon {
359409 display : inline-block ;
360410 vertical-align : middle ;
361411 }
@@ -380,7 +430,7 @@ $content-max-width: 640px;
380430
381431 & __primary {
382432 margin : 0 auto ;
383- max- width : 100 % ;
433+ width : 180 px !important ;
384434
385435 & __icon {
386436 filter : var (--primary-invert-if-dark );
@@ -406,39 +456,58 @@ $content-max-width: 640px;
406456@media only screen and (max-width : 1024px ) {
407457 .profile {
408458 & __header {
409- height : 250 px ;
459+ height : 190 px ;
410460 position : unset ;
411461
412462 & __container {
413- grid-template-columns : unset ;
414- margin-bottom : 110px ;
463+ align-self : center ;
464+ grid-template-columns : 136px minmax (0 , 1fr );
465+ grid-template-rows : max-content max-content ;
466+ max-width : 600px ;
467+ margin : 0 auto ;
468+ padding-inline : 16px ;
469+ row-gap : 0 ;
470+
471+ & __avatar {
472+ grid-column : 1 ;
473+ grid-row : 1 / 3 ;
474+ justify-self : center ;
475+ }
476+
477+ & __placeholder {
478+ display : none ;
479+ }
415480
416481 & __displayname {
417- margin : 80px 20px 0px 0px !important ;
482+ grid-column : 2 ;
483+ grid-row : 1 ;
484+ margin : 0 ;
418485 width : unset ;
419- text-align : center ;
420- padding-inline : 12px ;
486+ height : unset ;
487+ flex-direction : column ;
488+ align-items : flex-start ;
489+ gap : 2px ;
490+
491+ h2 {
492+ font-size : 24px ;
493+ overflow-wrap : anywhere;
494+ }
421495 }
422496
423- & __edit-button {
424- width : fit-content ;
425- display : block ;
426- margin : 60px auto ;
497+ & __pronoun-separator {
498+ display : none ;
427499 }
428500
429- & __status-text {
430- margin : 4px auto ;
501+ & __status {
502+ grid-column : 2 ;
503+ grid-row : 2 ;
504+ justify-self : start ;
431505 }
432506 }
433507 }
434508
435509 & __content {
436510 display : block ;
437-
438- .avatar {
439- // Overlap avatar to top header
440- margin-top : -110px !important ;
441- }
442511 }
443512
444513 & __blocks {
@@ -452,13 +521,27 @@ $content-max-width: 640px;
452521 margin : unset ;
453522 position : unset ;
454523 }
524+
525+ & __header ,
526+ & __sidebar {
527+ :deep (.avatar.avatardiv ) {
528+ .avatardiv__user- status {
529+ inset-inline-end : 0 ;
530+ bottom : 0 ;
531+ }
532+ }
533+ }
455534 }
456535
457536 .user-actions {
458537 width : unset ;
459538 max-width : 600px ;
460539 margin : 0 auto ;
461540 padding : 20px 50px 0px 50px ;
541+
542+ & __primary {
543+ width : 220px !important ;
544+ }
462545 }
463546}
464547 </style >
0 commit comments