@@ -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,48 +119,69 @@ 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
129+ disableTooltip
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 >
128- {{ t('profile', 'Edit Profile') }}
154+ {{ 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 "
148168 :size =" 180 "
149- : disableMenu = " true "
150- : disableTooltip = " true "
169+ disableMenu
170+ disableTooltip
151171 :isNoUser =" ! profileParameters .isUserAvatarVisible "
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 >
@@ -234,6 +269,7 @@ $content-max-width: 640px;
234269
235270:deep(#app-content-vue ) {
236271 background-color : unset ;
272+ min-width : 320px ;
237273}
238274
239275.profile {
@@ -282,6 +318,18 @@ $content-max-width: 640px;
282318 font-size : 20px ;
283319 }
284320 }
321+
322+ & __controls {
323+ display : flex ;
324+ align-items : center ;
325+ gap : 8px ;
326+ }
327+
328+ & __status-content {
329+ display : flex ;
330+ align-items : center ;
331+ gap : 8px ;
332+ }
285333 }
286334 }
287335
@@ -293,7 +341,10 @@ $content-max-width: 640px;
293341 min-width : 220px ;
294342 margin-block : -150px 0 ;
295343 margin-inline : 0 20px ;
344+ }
296345
346+ & __header ,
347+ & __sidebar {
297348 // Specificity hack is needed to override Avatar component styles
298349 :deep (.avatar.avatardiv ) {
299350 text-align : center ;
@@ -336,7 +387,7 @@ $content-max-width: 640px;
336387 }
337388
338389 & __blocks {
339- margin : 18px 0 80px 0 ;
390+ margin : 18px 0 80px 16 px ;
340391 display : grid ;
341392 gap : 16px 0 ;
342393 width : $content-max-width ;
@@ -355,7 +406,7 @@ $content-max-width: 640px;
355406 display : inline-block ;
356407 color : var (--color-text-maxcontrast );
357408
358- p .map -icon {
409+ p .detail -icon {
359410 display : inline-block ;
360411 vertical-align : middle ;
361412 }
@@ -380,7 +431,7 @@ $content-max-width: 640px;
380431
381432 & __primary {
382433 margin : 0 auto ;
383- max- width : 100 % ;
434+ width : 180 px !important ;
384435
385436 & __icon {
386437 filter : var (--primary-invert-if-dark );
@@ -406,39 +457,58 @@ $content-max-width: 640px;
406457@media only screen and (max-width : 1024px ) {
407458 .profile {
408459 & __header {
409- height : 250 px ;
460+ height : 190 px ;
410461 position : unset ;
411462
412463 & __container {
413- grid-template-columns : unset ;
414- margin-bottom : 110px ;
464+ align-self : center ;
465+ grid-template-columns : 136px minmax (0 , 1fr );
466+ grid-template-rows : max-content max-content ;
467+ max-width : 600px ;
468+ margin : 0 auto ;
469+ padding-inline : 16px ;
470+ row-gap : 0 ;
471+
472+ & __avatar {
473+ grid-column : 1 ;
474+ grid-row : 1 / 3 ;
475+ justify-self : center ;
476+ }
477+
478+ & __placeholder {
479+ display : none ;
480+ }
415481
416482 & __displayname {
417- margin : 80px 20px 0px 0px !important ;
483+ grid-column : 2 ;
484+ grid-row : 1 ;
485+ margin : 0 ;
418486 width : unset ;
419- text-align : center ;
420- padding-inline : 12px ;
487+ height : unset ;
488+ flex-direction : column ;
489+ align-items : flex-start ;
490+ gap : 2px ;
491+
492+ h2 {
493+ font-size : 24px ;
494+ overflow-wrap : anywhere;
495+ }
421496 }
422497
423- & __edit-button {
424- width : fit-content ;
425- display : block ;
426- margin : 60px auto ;
498+ & __pronoun-separator {
499+ display : none ;
427500 }
428501
429- & __status-text {
430- margin : 4px auto ;
502+ & __status {
503+ grid-column : 2 ;
504+ grid-row : 2 ;
505+ justify-self : start ;
431506 }
432507 }
433508 }
434509
435510 & __content {
436511 display : block ;
437-
438- .avatar {
439- // Overlap avatar to top header
440- margin-top : -110px !important ;
441- }
442512 }
443513
444514 & __blocks {
@@ -452,13 +522,27 @@ $content-max-width: 640px;
452522 margin : unset ;
453523 position : unset ;
454524 }
525+
526+ & __header ,
527+ & __sidebar {
528+ :deep (.avatar.avatardiv ) {
529+ .avatardiv__user- status {
530+ inset-inline-end : 0 ;
531+ bottom : 0 ;
532+ }
533+ }
534+ }
455535 }
456536
457537 .user-actions {
458538 width : unset ;
459539 max-width : 600px ;
460540 margin : 0 auto ;
461541 padding : 20px 50px 0px 50px ;
542+
543+ & __primary {
544+ width : 220px !important ;
545+ }
462546 }
463547}
464548 </style >
0 commit comments