(arguably) improved layouting of user profile page #403

Open
Riedler wants to merge 14 commits from Riedler/akkoma-fe:user-profile-changes into develop
7 changed files with 191 additions and 144 deletions

View file

@ -159,6 +159,16 @@
{{ $t('settings.show_page_backgrounds') }} {{ $t('settings.show_page_backgrounds') }}
</BooleanSetting> </BooleanSetting>
</li> </li>
<li>
<BooleanSetting path="centerAlignBio">
{{ $t('settings.center_align_bio') }}
</BooleanSetting>
</li>
<li>
<BooleanSetting path="compactUserInfo">
{{ $t('settings.compact_user_info') }}
</BooleanSetting>
</li>
<li> <li>
<BooleanSetting path="stopGifs"> <BooleanSetting path="stopGifs">
{{ $t('settings.stop_gifs') }} {{ $t('settings.stop_gifs') }}

View file

@ -117,6 +117,11 @@ export default {
shouldConfirmMute () { shouldConfirmMute () {
return this.mergedConfig.modalOnMute return this.mergedConfig.modalOnMute
}, },
compactUserInfo () {
return this.$store.getters.mergedConfig.compactUserInfo
&& (this.$store.state.interface.layoutType !== 'mobile')
&& this.switcher
},
...mapGetters(['mergedConfig']) ...mapGetters(['mergedConfig'])
}, },
components: { components: {

View file

@ -21,6 +21,13 @@
position: relative; position: relative;
} }
.user-buttons {
grid-area: edit;
display: flex;
padding: .5em 0 .5em 0;
justify-self: end;
}
.panel-body { .panel-body {
word-wrap: break-word; word-wrap: break-word;
border-bottom-right-radius: inherit; border-bottom-right-radius: inherit;
@ -53,7 +60,6 @@
} }
&-bio { &-bio {
text-align: center;
display: block; display: block;
line-height: 1.3; line-height: 1.3;
padding: 1em; padding: 1em;
@ -100,15 +106,14 @@
padding: 0 26px; padding: 0 26px;
.container { .container {
min-width: 0;
padding: 16px 0 6px; padding: 16px 0 6px;
display: flex; display: grid;
align-items: flex-start; grid-template-areas:
max-height: 56px; "pfp name edit"
"pfp summary summary"
> * { "stats stats stats";
min-width: 0; grid-template-columns: auto 1fr auto;
} align-items: start;
.Avatar { .Avatar {
--_avatarShadowBox: var(--avatarShadow); --_avatarShadowBox: var(--avatarShadow);
@ -123,6 +128,7 @@
} }
&-avatar-link { &-avatar-link {
grid-area: pfp;
position: relative; position: relative;
cursor: pointer; cursor: pointer;
@ -153,8 +159,8 @@
.external-link-button, .edit-profile-button { .external-link-button, .edit-profile-button {
cursor: pointer; cursor: pointer;
width: 2.5em; width: 2.3em;
text-align: center; text-align: right;
margin: -0.5em 0; margin: -0.5em 0;
padding: 0.5em 0; padding: 0.5em 0;
@ -165,12 +171,16 @@
} }
.user-summary { .user-summary {
display: block; grid-area: summary;
display: grid;
grid-template-areas:
"name name name name name"
"hand role lock avg _";
grid-template-columns:
auto auto auto auto 1fr;
justify-items: start;
margin-left: 0.6em; margin-left: 0.6em;
text-align: left;
text-overflow: ellipsis; text-overflow: ellipsis;
white-space: nowrap;
flex: 1 1 0;
// This is so that text doesn't get overlapped by avatar's shadow if it has // This is so that text doesn't get overlapped by avatar's shadow if it has
// big one // big one
z-index: 1; z-index: 1;
@ -178,56 +188,82 @@
--emoji-size: 1.7em; --emoji-size: 1.7em;
.top-line, .user-locked {
.bottom-line {
display: flex;
}
}
.user-name {
text-overflow: ellipsis;
overflow: hidden;
flex: 1 1 auto;
margin-right: 1em;
font-size: 1.1em;
}
.bottom-line {
font-weight: light;
font-size: 1.1em;
align-items: baseline;
.lock-icon {
margin-left: 0.5em; margin-left: 0.5em;
grid-area: lock;
} }
.user-screen-name { .user-screen-name {
min-width: 1px; min-width: 1px;
flex: 0 1 auto; max-width: 100%;
text-overflow: ellipsis; text-overflow: ellipsis;
overflow: hidden; overflow: hidden;
color: $fallback--lightText; color: $fallback--lightText;
color: var(--lightText, $fallback--lightText); color: var(--lightText, $fallback--lightText);
grid-area: hand;
} }
.dailyAvg { .dailyAvg {
min-width: 1px; min-width: 1px;
flex: 0 0 auto;
margin-left: 1em; margin-left: 1em;
font-size: 0.7em; font-size: 0.7em;
color: $fallback--text; color: $fallback--text;
color: var(--text, $fallback--text); color: var(--text, $fallback--text);
grid-area: avg;
} }
.user-role { .user-roles {
flex: none; display: flex;
color: $fallback--text; grid-area: role;
color: var(--alertNeutralText, $fallback--text);
background-color: $fallback--fg; .user-role {
background-color: var(--alertNeutral, $fallback--fg); color: $fallback--text;
color: var(--alertNeutralText, $fallback--text);
background-color: $fallback--fg;
background-color: var(--alertNeutral, $fallback--fg);
}
} }
} }
.user-counts {
grid-area: stats;
display: flex;
line-height:16px;
padding-top: 0.5em;
text-align: center;
justify-content: space-around;
color: $fallback--lightText;
color: var(--lightText, $fallback--lightText);
align-self: center;
.user-count {
padding: .5em 0 .5em 0;
margin: 0 .5em;
h5 {
font-size:1em;
font-weight: bolder;
margin: 0 0 0.25em;
}
a {
text-decoration: none;
}
}
}
.user-name {
text-align: start;
text-overflow: ellipsis;
overflow: hidden;
margin-left: 0.6em;
font-size: 1.1em;
grid-area: name;
align-self: center;
white-space: nowrap;
max-width: 100%;
z-index: 1; // so shadow from user avatar doesn't overlap it
}
.user-meta { .user-meta {
margin-bottom: .15em; margin-bottom: .15em;
display: flex; display: flex;
@ -290,34 +326,21 @@
margin: 0; margin: 0;
} }
} }
&.-compact {
.container {
grid-template-areas:
"pfp name stats edit"
"pfp summary stats edit";
grid-template-columns: auto auto 1fr auto;
}
.user-counts {
padding-top: 0;
justify-content: space-evenly;
}
}
} }
.sidebar .edit-profile-button { .sidebar .edit-profile-button {
display: none; display: none;
} }
.user-counts {
display: flex;
line-height:16px;
padding: .5em 1.5em 0em 1.5em;
text-align: center;
justify-content: space-between;
color: $fallback--lightText;
color: var(--lightText, $fallback--lightText);
flex-wrap: wrap;
}
.user-count {
flex: 1 0 auto;
padding: .5em 0 .5em 0;
margin: 0 .5em;
h5 {
font-size:1em;
font-weight: bolder;
margin: 0 0 0.25em;
}
a {
text-decoration: none;
}
}

View file

@ -9,7 +9,10 @@
class="background-image" class="background-image"
/> />
<div class="panel-heading -flexible-height"> <div class="panel-heading -flexible-height">
<div class="user-info"> <div
class="user-info"
:class="{ '-compact': this.compactUserInfo }"
>
<div class="container"> <div class="container">
<a <a
v-if="allowZoomingAvatar" v-if="allowZoomingAvatar"
@ -29,6 +32,7 @@
</a> </a>
<router-link <router-link
v-else v-else
class="user-info-avatar-link"
:to="userProfileLink(user)" :to="userProfileLink(user)"
> >
<UserAvatar <UserAvatar
@ -36,15 +40,80 @@
:user="user" :user="user"
/> />
</router-link> </router-link>
<RichContent
:title="user.name"
class="user-name"
:html="user.name"
:emoji="user.emoji"
/>
<div class="user-summary"> <div class="user-summary">
<div class="top-line"> <router-link
<RichContent class="user-screen-name"
:title="user.name" :title="user.screen_name_ui"
class="user-name" :to="userProfileLink(user)"
:html="user.name" >
:emoji="user.emoji" @{{ user.screen_name_ui }}
</router-link>
<span class="user-roles" v-if="!hideBio && (user.deactivated || !!visibleRole || user.bot)">
<span
v-if="user.deactivated"
class="alert user-role"
>
{{ $t('user_card.deactivated') }}
</span>
<span
v-if="!!visibleRole"
class="alert user-role"
>
{{ $t(`general.role.${visibleRole}`) }}
</span>
<span
v-if="user.bot"
class="alert user-role"
>
{{ $t('user_card.bot') }}
</span>
</span>
<span class="user-locked" v-if="user.locked">
<FAIcon
class="lock-icon"
icon="lock"
size="sm"
/> />
<button </span>
<span
v-if="!mergedConfig.hideUserStats && !hideBio"
class="dailyAvg"
>{{ dailyAvg }} {{ $t('user_card.per_day') }}</span>
</div>
<div
v-if="!mergedConfig.hideUserStats && switcher"
class="user-counts"
>
<div
class="user-count"
@click.prevent="setProfileView('statuses')"
>
<h5>{{ $t('user_card.statuses') }}</h5>
<span>{{ user.statuses_count }} <br></span>
</div>
<div
class="user-count"
@click.prevent="setProfileView('friends')"
>
<h5>{{ $t('user_card.followees') }}</h5>
<span>{{ hideFollowsCount ? $t('user_card.hidden') : user.friends_count }}</span>
</div>
<div
class="user-count"
@click.prevent="setProfileView('followers')"
>
<h5>{{ $t('user_card.followers') }}</h5>
<span>{{ hideFollowersCount ? $t('user_card.hidden') : user.followers_count }}</span>
</div>
</div>
<div class="user-buttons">
<button
v-if="!isOtherUser && user.is_local" v-if="!isOtherUser && user.is_local"
class="button-unstyled edit-profile-button" class="button-unstyled edit-profile-button"
@click.stop="openProfileTab" @click.stop="openProfileTab"
@ -83,47 +152,6 @@
:user="user" :user="user"
:relationship="relationship" :relationship="relationship"
/> />
</div>
<div class="bottom-line">
<router-link
class="user-screen-name"
:title="user.screen_name_ui"
:to="userProfileLink(user)"
>
@{{ user.screen_name_ui }}
</router-link>
<template v-if="!hideBio">
<span
v-if="user.deactivated"
class="alert user-role"
>
{{ $t('user_card.deactivated') }}
</span>
<span
v-if="!!visibleRole"
class="alert user-role"
>
{{ $t(`general.role.${visibleRole}`) }}
</span>
<span
v-if="user.bot"
class="alert user-role"
>
{{ $t('user_card.bot') }}
</span>
</template>
<span v-if="user.locked">
<FAIcon
class="lock-icon"
icon="lock"
size="sm"
/>
</span>
<span
v-if="!mergedConfig.hideUserStats && !hideBio"
class="dailyAvg"
>{{ dailyAvg }} {{ $t('user_card.per_day') }}</span>
</div>
</div> </div>
</div> </div>
<div class="user-meta"> <div class="user-meta">
@ -269,38 +297,13 @@
v-if="!hideBio" v-if="!hideBio"
class="panel-body" class="panel-body"
> >
<div
v-if="!mergedConfig.hideUserStats && switcher"
class="user-counts"
>
<div
class="user-count"
@click.prevent="setProfileView('statuses')"
>
<h5>{{ $t('user_card.statuses') }}</h5>
<span>{{ user.statuses_count }} <br></span>
</div>
<div
class="user-count"
@click.prevent="setProfileView('friends')"
>
<h5>{{ $t('user_card.followees') }}</h5>
<span>{{ hideFollowsCount ? $t('user_card.hidden') : user.friends_count }}</span>
</div>
<div
class="user-count"
@click.prevent="setProfileView('followers')"
>
<h5>{{ $t('user_card.followers') }}</h5>
<span>{{ hideFollowersCount ? $t('user_card.hidden') : user.followers_count }}</span>
</div>
</div>
<RichContent <RichContent
v-if="!hideBio" v-if="!hideBio"
class="user-card-bio" class="user-card-bio"
:html="user.description_html" :html="user.description_html"
:emoji="user.emoji" :emoji="user.emoji"
:handle-links="true" :handle-links="true"
:style='{"text-align": this.$store.getters.mergedConfig.centerAlignBio ? "center" : "start"}'
/> />
</div> </div>
<teleport to="#modal"> <teleport to="#modal">

View file

@ -482,6 +482,7 @@
"blocks_tab": "Blocks", "blocks_tab": "Blocks",
"bot": "Dies ist ein Bot Account", "bot": "Dies ist ein Bot Account",
"btnRadius": "Knöpfe", "btnRadius": "Knöpfe",
"center_align_bio": "Zentrale Textausrichtung in der Bio",
"cBlue": "Blau (Antworten, folgt dir)", "cBlue": "Blau (Antworten, folgt dir)",
"cGreen": "Grün (Retweet)", "cGreen": "Grün (Retweet)",
"cOrange": "Orange (Favorisieren)", "cOrange": "Orange (Favorisieren)",
@ -496,6 +497,7 @@
"checkboxRadius": "Auswahlfelder", "checkboxRadius": "Auswahlfelder",
"collapse_subject": "Beiträge mit Inhaltswarnungen einklappen", "collapse_subject": "Beiträge mit Inhaltswarnungen einklappen",
"columns": "Spalten", "columns": "Spalten",
"compact_user_info": "Kompakte Benutzerinfos wenn genug Platz",
"composing": "Verfassen", "composing": "Verfassen",
"confirm_dialogs": "Bestätigung erforderlich für:", "confirm_dialogs": "Bestätigung erforderlich für:",
"confirm_dialogs_approve_follow": "Annehmen einer Followanfrage", "confirm_dialogs_approve_follow": "Annehmen einer Followanfrage",

View file

@ -488,6 +488,7 @@
"blocks_tab": "Blocks", "blocks_tab": "Blocks",
"bot": "This is a bot account", "bot": "This is a bot account",
"btnRadius": "Buttons", "btnRadius": "Buttons",
"center_align_bio": "Center text in user bio",
"cBlue": "Blue (Reply, follow)", "cBlue": "Blue (Reply, follow)",
"cGreen": "Green (Retweet)", "cGreen": "Green (Retweet)",
"cOrange": "Orange (Favorite)", "cOrange": "Orange (Favorite)",
@ -502,6 +503,7 @@
"checkboxRadius": "Checkboxes", "checkboxRadius": "Checkboxes",
"collapse_subject": "Collapse posts with content warnings", "collapse_subject": "Collapse posts with content warnings",
"columns": "Columns", "columns": "Columns",
"compact_user_info": "Compact user info when enough space",
"composing": "Composing", "composing": "Composing",
"confirm_dialogs": "Require confirmation for:", "confirm_dialogs": "Require confirmation for:",
"confirm_dialogs_approve_follow": "Accepting a follow request", "confirm_dialogs_approve_follow": "Accepting a follow request",

View file

@ -56,6 +56,8 @@ export const defaultState = {
autohideFloatingPostButton: false, autohideFloatingPostButton: false,
pauseOnUnfocused: true, pauseOnUnfocused: true,
displayPageBackgrounds: true, displayPageBackgrounds: true,
centerAlignBio: false,
compactUserInfo: true,
stopGifs: undefined, stopGifs: undefined,
replyVisibility: 'all', replyVisibility: 'all',
thirdColumnMode: 'notifications', thirdColumnMode: 'notifications',