initial profile overhaul
This commit is contained in:
parent
38130fce90
commit
79868aeeb9
11 changed files with 470 additions and 409 deletions
|
|
@ -19,7 +19,7 @@
|
|||
/>
|
||||
<div
|
||||
class="input color-input-field"
|
||||
:class="{ disabled: !present || disabled }"
|
||||
:class="{ disabled: !present || disabled, unstyled }"
|
||||
>
|
||||
<input
|
||||
:id="name + '-t'"
|
||||
|
|
@ -92,6 +92,11 @@ export default {
|
|||
required: true,
|
||||
type: String
|
||||
},
|
||||
// use unstyled, uh, style
|
||||
unstyled: {
|
||||
required: false,
|
||||
type: Boolean
|
||||
},
|
||||
// Color value, should be required but vue cannot tell the difference
|
||||
// between "property missing" and "property set to undefined"
|
||||
modelValue: {
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
import ColorInput from 'src/components/color_input/color_input.vue'
|
||||
import UserAvatar from '../user_avatar/user_avatar.vue'
|
||||
import RemoteFollow from '../remote_follow/remote_follow.vue'
|
||||
import ProgressButton from '../progress_button/progress_button.vue'
|
||||
|
|
@ -9,6 +10,7 @@ import Select from '../select/select.vue'
|
|||
import UserLink from '../user_link/user_link.vue'
|
||||
import RichContent from 'src/components/rich_content/rich_content.jsx'
|
||||
import UserTimedFilterModal from 'src/components/user_timed_filter_modal/user_timed_filter_modal.vue'
|
||||
import localeService from 'src/services/locale/locale.service.js'
|
||||
|
||||
import generateProfileLink from 'src/services/user_profile_link_generator/user_profile_link_generator'
|
||||
import { mapGetters } from 'vuex'
|
||||
|
|
@ -21,7 +23,8 @@ import {
|
|||
faExternalLinkAlt,
|
||||
faEdit,
|
||||
faTimes,
|
||||
faExpandAlt
|
||||
faExpandAlt,
|
||||
faBirthdayCake
|
||||
} from '@fortawesome/free-solid-svg-icons'
|
||||
|
||||
import { useMediaViewerStore } from '../../stores/media_viewer'
|
||||
|
|
@ -34,7 +37,8 @@ library.add(
|
|||
faExternalLinkAlt,
|
||||
faEdit,
|
||||
faTimes,
|
||||
faExpandAlt
|
||||
faExpandAlt,
|
||||
faBirthdayCake
|
||||
)
|
||||
|
||||
export default {
|
||||
|
|
@ -60,7 +64,8 @@ export default {
|
|||
RichContent,
|
||||
UserLink,
|
||||
UserNote,
|
||||
UserTimedFilterModal
|
||||
UserTimedFilterModal,
|
||||
ColorInput
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
|
|
@ -175,6 +180,10 @@ export default {
|
|||
? this.$t('user_card.block_expires_forever')
|
||||
: this.$t('user_card.block_expires_at', [new Date(this.user.mute_expires_at).toLocaleString()])
|
||||
},
|
||||
formattedBirthday () {
|
||||
const browserLocale = localeService.internalToBrowserLocale(this.$i18n.locale)
|
||||
return this.user.birthday && new Date(Date.parse(this.user.birthday)).toLocaleDateString(browserLocale, { timeZone: 'UTC', day: 'numeric', month: 'long', year: 'numeric' })
|
||||
},
|
||||
...mapGetters(['mergedConfig'])
|
||||
},
|
||||
methods: {
|
||||
|
|
|
|||
|
|
@ -2,34 +2,67 @@
|
|||
position: relative;
|
||||
z-index: 1;
|
||||
|
||||
.user-card-inner {
|
||||
padding-bottom: 0;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
--_still-image-img-visibility: visible;
|
||||
--_still-image-canvas-visibility: hidden;
|
||||
--_still-image-label-visibility: hidden;
|
||||
}
|
||||
|
||||
.btn-mute, .btn-mention {
|
||||
display: block;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.panel-heading {
|
||||
padding: 0.5em 0;
|
||||
text-align: center;
|
||||
box-shadow: none;
|
||||
background: transparent;
|
||||
backdrop-filter: none;
|
||||
flex-direction: column;
|
||||
align-items: stretch;
|
||||
// create new stacking context
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.personal-marks {
|
||||
margin: 0.6em;
|
||||
padding: 0.6em;
|
||||
border-bottom: 1px solid var(--border);
|
||||
|
||||
.highlighter {
|
||||
h4 {
|
||||
margin-top: 0.6em;
|
||||
}
|
||||
|
||||
.userHighlightSel {
|
||||
vertical-align: bottom;
|
||||
margin-left: -0.1em;
|
||||
|
||||
&.-none {
|
||||
font-style: italic;
|
||||
color: var(--textFaint);
|
||||
}
|
||||
}
|
||||
|
||||
.highlighter-color {
|
||||
vertical-align: bottom;
|
||||
margin-left: 0.6em;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.background-image {
|
||||
position: absolute;
|
||||
width: calc(100% + 2.4em);
|
||||
margin-left: -1.2em;
|
||||
margin-right: -1.2em;
|
||||
margin-top: -1.2em;
|
||||
margin-bottom: -4.5em;
|
||||
aspect-ratio: 3;
|
||||
padding: 0;
|
||||
inset: 0;
|
||||
mask:
|
||||
linear-gradient(to top, white, transparent) bottom no-repeat,
|
||||
linear-gradient(to top, white, white);
|
||||
linear-gradient(to top, white 0%, transparent 20%) bottom no-repeat,
|
||||
linear-gradient(to top, white 0%, white 100%);
|
||||
// Autoprefixer seem to ignore this one, and also syntax is different
|
||||
/* stylelint-disable mask-composite */
|
||||
/* stylelint-disable declaration-property-value-no-unknown */
|
||||
|
|
@ -42,7 +75,7 @@
|
|||
/* stylelint-enable mask-composite */
|
||||
mask-composite: exclude;
|
||||
background-size: cover;
|
||||
mask-size: 100% 60%;
|
||||
mask-size: 100%;
|
||||
border-top-left-radius: calc(var(--__roundnessTop, --panelRadius) - 1px);
|
||||
border-top-right-radius: calc(var(--__roundnessTop, --panelRadius) - 1px);
|
||||
border-bottom-left-radius: calc(var(--__roundnessBottom, --panelRadius) - 1px);
|
||||
|
|
@ -57,10 +90,11 @@
|
|||
|
||||
&-bio {
|
||||
text-align: center;
|
||||
color: var(--lightText);
|
||||
display: block;
|
||||
line-height: 1.3;
|
||||
padding: 1em;
|
||||
margin: 0;
|
||||
padding: 0.6em;
|
||||
margin: 0 0.6em;
|
||||
|
||||
img {
|
||||
object-fit: contain;
|
||||
|
|
@ -100,14 +134,15 @@
|
|||
}
|
||||
|
||||
.user-info {
|
||||
padding: 0 26px;
|
||||
position: relative;
|
||||
margin: 0.6em;
|
||||
margin-bottom: 0;
|
||||
|
||||
.container {
|
||||
.user-identity {
|
||||
min-width: 0;
|
||||
padding: 16px 0 6px;
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
max-height: 56px;
|
||||
align-items: flex-end;
|
||||
margin-bottom: 1em;
|
||||
|
||||
> * {
|
||||
min-width: 0;
|
||||
|
|
@ -123,19 +158,42 @@
|
|||
--_avatarShadowFilter: var(--avatarShadowFilter);
|
||||
--_avatarShadowInset: var(--avatarShadowInset);
|
||||
|
||||
width: 56px;
|
||||
height: 56px;
|
||||
min-width: 6em;
|
||||
height: 6em;
|
||||
object-fit: cover;
|
||||
}
|
||||
}
|
||||
|
||||
.other-actions {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
display: grid;
|
||||
grid-auto-flow: column;
|
||||
grid-gap: 0.6em;
|
||||
|
||||
a, button {
|
||||
text-align: center;
|
||||
width: 2em;
|
||||
height: 2em;
|
||||
line-height: 2em;
|
||||
|
||||
&:not(:hover) .icon {
|
||||
color: var(--lightText);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&-avatar {
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
margin-right: 0.6em;
|
||||
|
||||
&.-overlay {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
inset: -0.6em;
|
||||
left: -0.6em;
|
||||
right: -1.2em;
|
||||
background-color: rgb(0 0 0 / 30%);
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
|
|
@ -154,22 +212,9 @@
|
|||
}
|
||||
}
|
||||
|
||||
.external-link-button,
|
||||
.edit-profile-button {
|
||||
cursor: pointer;
|
||||
width: 2.5em;
|
||||
text-align: center;
|
||||
margin: -0.5em 0;
|
||||
padding: 0.5em 0;
|
||||
|
||||
&:not(:hover) .icon {
|
||||
color: var(--lightText);
|
||||
}
|
||||
}
|
||||
|
||||
.bottom-line {
|
||||
font-weight: lighter;
|
||||
font-size: 1.1em;
|
||||
font-size: 0.9em;
|
||||
align-items: baseline;
|
||||
|
||||
.lock-icon {
|
||||
|
|
@ -184,16 +229,9 @@
|
|||
overflow: hidden;
|
||||
}
|
||||
|
||||
.dailyAvg {
|
||||
min-width: 1px;
|
||||
flex: 0 0 auto;
|
||||
margin-left: 1em;
|
||||
font-size: 0.7em;
|
||||
color: var(--text);
|
||||
}
|
||||
|
||||
.user-role {
|
||||
flex: none;
|
||||
align-self: baseline;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -216,9 +254,16 @@
|
|||
--link: var(--text) !important;
|
||||
}
|
||||
|
||||
.top-line,
|
||||
.top-line, {
|
||||
display: flex;
|
||||
line-height: 2;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.bottom-line {
|
||||
display: flex;
|
||||
font-weight: 500;
|
||||
line-height: 1.5;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -230,9 +275,8 @@
|
|||
font-size: 1.1em;
|
||||
}
|
||||
|
||||
.user-meta {
|
||||
margin-bottom: 0.15em;
|
||||
display: flex;
|
||||
.highlighter {
|
||||
margin: 5em;
|
||||
align-items: baseline;
|
||||
line-height: 22px;
|
||||
flex-wrap: wrap;
|
||||
|
|
@ -279,23 +323,17 @@
|
|||
|
||||
.user-interactions {
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-flow: row wrap;
|
||||
margin-right: -0.75em;
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(17%, 7em));
|
||||
grid-gap: 0.6em;
|
||||
|
||||
> * {
|
||||
margin: 0 0.75em 0.6em 0;
|
||||
.popover-trigger-button, .moderation-tools-button {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
> .btn-group, > button {
|
||||
white-space: nowrap;
|
||||
min-width: 95px;
|
||||
}
|
||||
|
||||
button {
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.user-note {
|
||||
margin: 0 0.75em 0.6em 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -303,24 +341,92 @@
|
|||
display: none;
|
||||
}
|
||||
|
||||
.user-counts {
|
||||
display: flex;
|
||||
line-height: 16px;
|
||||
padding: 0.5em 1.5em 0;
|
||||
text-align: center;
|
||||
.user-extras {
|
||||
display: grid;
|
||||
place-items: center baseline;
|
||||
justify-content: space-between;
|
||||
flex-wrap: wrap;
|
||||
grid-template-columns: minmax(max-content, 1fr);
|
||||
grid-auto-columns: 1fr;
|
||||
grid-auto-flow: column;
|
||||
padding: 1.2em 0.6em;
|
||||
}
|
||||
|
||||
.user-count {
|
||||
flex: 1 0 auto;
|
||||
padding: 0.5em 0;
|
||||
.birthday {
|
||||
width: 100%;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.user-birthday {
|
||||
margin: 0 0.75em 0.5em;
|
||||
}
|
||||
|
||||
.user-profile-fields {
|
||||
margin: 0 0.5em;
|
||||
|
||||
h5 {
|
||||
font-size: 1em;
|
||||
img {
|
||||
object-fit: contain;
|
||||
vertical-align: middle;
|
||||
max-width: 100%;
|
||||
max-height: 400px;
|
||||
|
||||
&.emoji {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
}
|
||||
}
|
||||
|
||||
.user-profile-field {
|
||||
display: flex;
|
||||
margin: 0.25em;
|
||||
border: 1px solid var(--border);
|
||||
border-radius: var(--roundness);
|
||||
|
||||
.user-profile-field-name,
|
||||
.user-profile-field-value {
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
box-sizing: border-box;
|
||||
line-height: 2em;
|
||||
}
|
||||
|
||||
.user-profile-field-name {
|
||||
flex: 0 1 50%;
|
||||
font-weight: 600;
|
||||
text-align: right;
|
||||
color: var(--lightText);
|
||||
min-width: 9em;
|
||||
border-right: 1px solid var(--border);
|
||||
padding-left: 1.2em;
|
||||
padding-right: 0.6em;
|
||||
}
|
||||
|
||||
.user-profile-field-value {
|
||||
flex: 1 1 55%;
|
||||
color: var(--text);
|
||||
padding-left: 0.6em;
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.user-stats {
|
||||
display: block;
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
|
||||
dl {
|
||||
display: inline;
|
||||
margin-right: 1em;
|
||||
}
|
||||
|
||||
dd {
|
||||
font-weight: bolder;
|
||||
margin: 0 0 0.25em;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
dd, dt {
|
||||
display: inline
|
||||
}
|
||||
|
||||
/* stylelint-disable-next-line no-descending-specificity */
|
||||
|
|
|
|||
|
|
@ -3,51 +3,14 @@
|
|||
class="user-card"
|
||||
:class="classes"
|
||||
>
|
||||
<div :class="onClose ? '' : 'panel-heading -flexible-height'" class="user-card-inner">
|
||||
<div class="user-info">
|
||||
<div
|
||||
:class="{ 'hide-bio': hideBio }"
|
||||
:style="style"
|
||||
class="background-image"
|
||||
/>
|
||||
<div :class="onClose ? '' : 'panel-heading -flexible-height'">
|
||||
<div class="user-info">
|
||||
<div class="container">
|
||||
<a
|
||||
v-if="avatarAction === 'zoom'"
|
||||
class="user-info-avatar -link"
|
||||
@click="zoomAvatar"
|
||||
>
|
||||
<UserAvatar :user="user" />
|
||||
<div class="user-info-avatar -link -overlay">
|
||||
<FAIcon
|
||||
class="fa-scale-110 fa-old-padding"
|
||||
icon="search-plus"
|
||||
/>
|
||||
</div>
|
||||
</a>
|
||||
<UserAvatar
|
||||
v-else-if="typeof avatarAction === 'function'"
|
||||
class="user-info-avatar"
|
||||
:user="user"
|
||||
@click="avatarAction"
|
||||
/>
|
||||
<router-link
|
||||
v-else
|
||||
:to="userProfileLink(user)"
|
||||
>
|
||||
<UserAvatar :user="user" />
|
||||
</router-link>
|
||||
<div class="user-summary">
|
||||
<div class="top-line">
|
||||
<router-link
|
||||
:to="userProfileLink(user)"
|
||||
class="user-name"
|
||||
>
|
||||
<RichContent
|
||||
:title="user.name"
|
||||
:html="user.name"
|
||||
:emoji="user.emoji"
|
||||
/>
|
||||
</router-link>
|
||||
<div class="other-actions">
|
||||
<button
|
||||
v-if="!isOtherUser && user.is_local"
|
||||
class="button-unstyled edit-profile-button"
|
||||
|
|
@ -98,6 +61,45 @@
|
|||
/>
|
||||
</button>
|
||||
</div>
|
||||
<div class="user-identity">
|
||||
<a
|
||||
v-if="avatarAction === 'zoom'"
|
||||
class="user-info-avatar -link"
|
||||
@click="zoomAvatar"
|
||||
>
|
||||
<UserAvatar :user="user" />
|
||||
<div class="user-info-avatar -link -overlay">
|
||||
<FAIcon
|
||||
class="fa-scale-110 fa-old-padding"
|
||||
icon="search-plus"
|
||||
/>
|
||||
</div>
|
||||
</a>
|
||||
<UserAvatar
|
||||
v-else-if="typeof avatarAction === 'function'"
|
||||
class="user-info-avatar"
|
||||
:user="user"
|
||||
@click="avatarAction"
|
||||
/>
|
||||
<router-link
|
||||
v-else
|
||||
:to="userProfileLink(user)"
|
||||
>
|
||||
<UserAvatar :user="user" />
|
||||
</router-link>
|
||||
<div class="user-summary">
|
||||
<div class="top-line">
|
||||
<router-link
|
||||
:to="userProfileLink(user)"
|
||||
class="user-name"
|
||||
>
|
||||
<RichContent
|
||||
:title="user.name"
|
||||
:html="user.name"
|
||||
:emoji="user.emoji"
|
||||
/>
|
||||
</router-link>
|
||||
</div>
|
||||
<div class="bottom-line">
|
||||
<user-link
|
||||
class="user-screen-name"
|
||||
|
|
@ -148,58 +150,13 @@
|
|||
>
|
||||
{{ blockExpiry }}
|
||||
</span>
|
||||
<span
|
||||
v-if="!mergedConfig.hideUserStats && !hideBio"
|
||||
class="dailyAvg"
|
||||
>{{ dailyAvg }} {{ $t('user_card.per_day') }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="user-meta">
|
||||
<div
|
||||
v-if="relationship.followed_by && loggedIn && isOtherUser"
|
||||
class="following"
|
||||
class="alert neutral user-role"
|
||||
>
|
||||
{{ $t('user_card.follows_you') }}
|
||||
</div>
|
||||
<div
|
||||
v-if="isOtherUser && (loggedIn || !switcher)"
|
||||
class="highlighter"
|
||||
>
|
||||
<!-- id's need to be unique, otherwise vue confuses which user-card checkbox belongs to -->
|
||||
<input
|
||||
v-if="userHighlightType !== 'disabled'"
|
||||
:id="'userHighlightColorTx'+user.id"
|
||||
v-model="userHighlightColor"
|
||||
class="input userHighlightText"
|
||||
type="text"
|
||||
>
|
||||
<input
|
||||
v-if="userHighlightType !== 'disabled'"
|
||||
:id="'userHighlightColor'+user.id"
|
||||
v-model="userHighlightColor"
|
||||
class="input userHighlightCl"
|
||||
type="color"
|
||||
>
|
||||
{{ ' ' }}
|
||||
<Select
|
||||
:id="'userHighlightSel'+user.id"
|
||||
v-model="userHighlightType"
|
||||
class="userHighlightSel"
|
||||
>
|
||||
<option value="disabled">
|
||||
{{ $t('user_card.highlight.disabled') }}
|
||||
</option>
|
||||
<option value="solid">
|
||||
{{ $t('user_card.highlight.solid') }}
|
||||
</option>
|
||||
<option value="striped">
|
||||
{{ $t('user_card.highlight.striped') }}
|
||||
</option>
|
||||
<option value="side">
|
||||
{{ $t('user_card.highlight.side') }}
|
||||
</option>
|
||||
</Select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
|
|
@ -241,7 +198,6 @@
|
|||
</ProgressButton>
|
||||
</template>
|
||||
</div>
|
||||
<div>
|
||||
<button
|
||||
v-if="relationship.muting"
|
||||
class="btn button-default btn-mute toggled"
|
||||
|
|
@ -258,8 +214,6 @@
|
|||
>
|
||||
{{ $t('user_card.mute') }}
|
||||
</button>
|
||||
</div>
|
||||
<div>
|
||||
<button
|
||||
class="btn button-default btn-mention"
|
||||
:disabled="user.deactivated"
|
||||
|
|
@ -267,9 +221,9 @@
|
|||
>
|
||||
{{ $t('user_card.mention') }}
|
||||
</button>
|
||||
</div>
|
||||
<ModerationTools
|
||||
v-if="showModerationMenu"
|
||||
class="moderation-menu"
|
||||
:user="user"
|
||||
/>
|
||||
</div>
|
||||
|
|
@ -279,42 +233,48 @@
|
|||
>
|
||||
<RemoteFollow :user="user" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="personal-marks" v-if="loggedIn && isOtherUser && (hasNote || !hideBio)">
|
||||
<UserNote
|
||||
v-if="loggedIn && isOtherUser && (hasNote || (hasNoteEditor && supportsNote))"
|
||||
v-if="hasNote || (hasNoteEditor && supportsNote)"
|
||||
:user="user"
|
||||
:relationship="relationship"
|
||||
:editable="hasNoteEditor"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
v-if="!hideBio"
|
||||
class="user-bio"
|
||||
class="highlighter"
|
||||
>
|
||||
<div
|
||||
v-if="!mergedConfig.hideUserStats && switcher"
|
||||
class="user-counts"
|
||||
<h4>{{ $t('user_card.highlight_header') }}</h4>
|
||||
<Select
|
||||
:id="'userHighlightSel'+user.id"
|
||||
v-model="userHighlightType"
|
||||
class="userHighlightSel unstyled"
|
||||
:class="{ '-none': userHighlightType === 'disabled' }"
|
||||
>
|
||||
<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>
|
||||
<option value="disabled">
|
||||
{{ $t('user_card.highlight_new.disabled') }}
|
||||
</option>
|
||||
<option value="solid">
|
||||
{{ $t('user_card.highlight_new.solid') }}
|
||||
</option>
|
||||
<option value="striped">
|
||||
{{ $t('user_card.highlight_new.striped') }}
|
||||
</option>
|
||||
<option value="side">
|
||||
{{ $t('user_card.highlight_new.side') }}
|
||||
</option>
|
||||
</Select>
|
||||
<!-- id's need to be unique, otherwise vue confuses which user-card checkbox belongs to -->
|
||||
<ColorInput
|
||||
v-if="userHighlightType !== 'disabled'"
|
||||
class="highlighter-color"
|
||||
v-model="userHighlightColor"
|
||||
:show-optional-checkbox="false"
|
||||
name="'userHighlightColorTx'+user.id"
|
||||
:unstyled="true"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<RichContent
|
||||
|
|
@ -324,6 +284,81 @@
|
|||
:emoji="user.emoji"
|
||||
:handle-links="true"
|
||||
/>
|
||||
<div
|
||||
v-if="!hideBio && user.fields_html && user.fields_html.length > 0"
|
||||
class="user-profile-fields"
|
||||
>
|
||||
<dl
|
||||
v-for="(field, index) in user.fields_html"
|
||||
:key="index"
|
||||
class="user-profile-field"
|
||||
>
|
||||
<dt
|
||||
:title="user.fields_text[index].name"
|
||||
class="user-profile-field-name"
|
||||
>
|
||||
<RichContent
|
||||
:html="field.name"
|
||||
:emoji="user.emoji"
|
||||
/>
|
||||
</dt>
|
||||
<dd
|
||||
:title="user.fields_text[index].value"
|
||||
class="user-profile-field-value"
|
||||
>
|
||||
<RichContent
|
||||
:html="field.value"
|
||||
:emoji="user.emoji"
|
||||
/>
|
||||
</dd>
|
||||
</dl>
|
||||
<div class="user-extras">
|
||||
<span
|
||||
v-if="!hideBio && !mergedConfig.hideUserStats"
|
||||
class="user-stats"
|
||||
>
|
||||
<dl
|
||||
class="user-count"
|
||||
@click.prevent="setProfileView('statuses')"
|
||||
v-if="!mergedConfig.hideUserStats && !hideBio"
|
||||
>
|
||||
<dd>{{ user.statuses_count }}</dd>
|
||||
{{ ' ' }}
|
||||
<dt>{{ $t('user_card.statuses') }}</dt>
|
||||
</dl>
|
||||
<dl
|
||||
class="user-count"
|
||||
@click.prevent="setProfileView('statuses')"
|
||||
>
|
||||
<dd>{{ dailyAvg }}</dd>
|
||||
{{ ' ' }}
|
||||
<dt>{{ $t('user_card.statuses_per_day') }}</dt>
|
||||
</dl>
|
||||
<dl
|
||||
class="user-count"
|
||||
@click.prevent="setProfileView('friends')"
|
||||
>
|
||||
<dd>{{ hideFollowsCount ? $t('user_card.hidden') : user.friends_count }}</dd>
|
||||
{{ ' ' }}
|
||||
<dt>{{ $t('user_card.followees') }}</dt>
|
||||
</dl>
|
||||
<dl
|
||||
class="user-count"
|
||||
@click.prevent="setProfileView('followers')"
|
||||
>
|
||||
<dd>{{ hideFollowersCount ? $t('user_card.hidden') : user.followers_count }}</dd>
|
||||
{{ ' ' }}
|
||||
<dt>{{ $t('user_card.followers') }}</dt>
|
||||
</dl>
|
||||
</span>
|
||||
<div class="birthday" v-if="!hideBio && !!user.birthday">
|
||||
<FAIcon
|
||||
class="fa-old-padding"
|
||||
icon="birthday-cake"
|
||||
/>
|
||||
{{ $t('user_card.birthday', { birthday: formattedBirthday }) }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<teleport to="#modal">
|
||||
<UserTimedFilterModal
|
||||
|
|
|
|||
|
|
@ -1,9 +1,14 @@
|
|||
import PanelLoading from 'src/components/panel_loading/panel_loading.vue'
|
||||
|
||||
const UserNote = {
|
||||
props: {
|
||||
user: Object,
|
||||
relationship: Object,
|
||||
editable: Boolean
|
||||
},
|
||||
components: {
|
||||
PanelLoading
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
localNote: '',
|
||||
|
|
@ -21,9 +26,6 @@ const UserNote = {
|
|||
this.localNote = this.relationship.note
|
||||
this.editing = true
|
||||
},
|
||||
cancelEditing () {
|
||||
this.editing = false
|
||||
},
|
||||
finalizeEditing () {
|
||||
this.frozen = true
|
||||
|
||||
|
|
|
|||
|
|
@ -1,46 +1,28 @@
|
|||
<template>
|
||||
<div
|
||||
class="user-note"
|
||||
:class="{ '-frozen': frozen }"
|
||||
>
|
||||
<div class="heading">
|
||||
<span>{{ $t('user_card.note') }}</span>
|
||||
<div class="buttons">
|
||||
<button
|
||||
v-show="!editing && editable"
|
||||
class="button-default btn"
|
||||
@click="startEditing"
|
||||
>
|
||||
{{ $t('user_card.edit_note') }}
|
||||
</button>
|
||||
<button
|
||||
v-show="editing"
|
||||
class="button-default btn"
|
||||
:disabled="frozen"
|
||||
@click="finalizeEditing"
|
||||
>
|
||||
{{ $t('user_card.edit_note_apply') }}
|
||||
</button>
|
||||
<button
|
||||
v-show="editing"
|
||||
class="button-default btn"
|
||||
:disabled="frozen"
|
||||
@click="cancelEditing"
|
||||
>
|
||||
{{ $t('user_card.edit_note_cancel') }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<h4>{{ $t('user_card.personal_note') }}</h4>
|
||||
<textarea
|
||||
v-show="editing"
|
||||
v-model="localNote"
|
||||
class="input note-text"
|
||||
@blur="finalizeEditing"
|
||||
/>
|
||||
<span
|
||||
v-show="!editing"
|
||||
class="note-text"
|
||||
:class="{ '-blank': !relationship.note }"
|
||||
@click="startEditing"
|
||||
>
|
||||
{{ relationship.note || $t('user_card.note_blank') }}
|
||||
{{ relationship.note || $t('user_card.note_blank_click') }}
|
||||
</span>
|
||||
<span
|
||||
class="overlay"
|
||||
v-if="frozen"
|
||||
>
|
||||
<PanelLoading />
|
||||
</span>
|
||||
</div>
|
||||
</template>
|
||||
|
|
@ -49,29 +31,11 @@
|
|||
|
||||
<style lang="scss">
|
||||
.user-note {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
position: relative;
|
||||
|
||||
.heading {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
h4 {
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 0.75em;
|
||||
|
||||
.btn {
|
||||
min-width: 95px;
|
||||
}
|
||||
|
||||
.buttons {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: right;
|
||||
|
||||
.btn {
|
||||
margin-left: 0.5em;
|
||||
}
|
||||
}
|
||||
margin-bottom: 0.5em;
|
||||
}
|
||||
|
||||
.note-text {
|
||||
|
|
@ -82,5 +46,15 @@
|
|||
font-style: italic;
|
||||
color: var(--textFaint);
|
||||
}
|
||||
|
||||
.overlay {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
background-color: rgb(0 0 0 / 30%);
|
||||
|
||||
.panel-loading {
|
||||
font-size: 1em;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -28,8 +28,21 @@
|
|||
backdrop-filter: var(--backdrop-filter);
|
||||
}
|
||||
|
||||
.user-info {
|
||||
margin-bottom: 0;
|
||||
|
||||
.background-image {
|
||||
max-height: 5.6em;
|
||||
margin-bottom: -4.6em;
|
||||
}
|
||||
|
||||
.Avatar {
|
||||
width: 5em;
|
||||
height: 5em;
|
||||
}
|
||||
}
|
||||
|
||||
.signed-in {
|
||||
overflow: visible;
|
||||
z-index: 10;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,7 +26,24 @@
|
|||
<style lang="scss">
|
||||
/* popover styles load on-demand, so we need to override */
|
||||
/* stylelint-disable block-no-empty */
|
||||
.user-popover.popover {
|
||||
.user-popover{
|
||||
.user-card-inner {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
&.popover {
|
||||
overflow: hidden;
|
||||
padding: 0.6em;
|
||||
|
||||
.user-info {
|
||||
width: 30em;
|
||||
}
|
||||
|
||||
.background-image {
|
||||
max-height: 6em;
|
||||
margin-bottom: -4.5em;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* stylelint-enable block-no-empty */
|
||||
|
||||
|
|
|
|||
|
|
@ -7,16 +7,13 @@ import TabSwitcher from 'src/components/tab_switcher/tab_switcher.jsx'
|
|||
import RichContent from 'src/components/rich_content/rich_content.jsx'
|
||||
import List from '../list/list.vue'
|
||||
import withLoadMore from '../../hocs/with_load_more/with_load_more'
|
||||
import localeService from 'src/services/locale/locale.service.js'
|
||||
import { library } from '@fortawesome/fontawesome-svg-core'
|
||||
import {
|
||||
faCircleNotch,
|
||||
faBirthdayCake
|
||||
faCircleNotch
|
||||
} from '@fortawesome/free-solid-svg-icons'
|
||||
|
||||
library.add(
|
||||
faCircleNotch,
|
||||
faBirthdayCake
|
||||
faCircleNotch
|
||||
)
|
||||
|
||||
const FollowerList = withLoadMore({
|
||||
|
|
@ -82,10 +79,6 @@ const UserProfile = {
|
|||
},
|
||||
favoritesTabVisible () {
|
||||
return this.isUs || (this.$store.state.instance.pleromaPublicFavouritesAvailable && !this.user.hide_favorites)
|
||||
},
|
||||
formattedBirthday () {
|
||||
const browserLocale = localeService.internalToBrowserLocale(this.$i18n.locale)
|
||||
return this.user.birthday && new Date(Date.parse(this.user.birthday)).toLocaleDateString(browserLocale, { timeZone: 'UTC', day: 'numeric', month: 'long', year: 'numeric' })
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
|
|
|||
|
|
@ -13,45 +13,6 @@
|
|||
rounded="top"
|
||||
:has-note-editor="true"
|
||||
/>
|
||||
<span
|
||||
v-if="!!user.birthday"
|
||||
class="user-birthday"
|
||||
>
|
||||
<FAIcon
|
||||
class="fa-old-padding"
|
||||
icon="birthday-cake"
|
||||
/>
|
||||
{{ $t('user_card.birthday', { birthday: formattedBirthday }) }}
|
||||
</span>
|
||||
<div
|
||||
v-if="user.fields_html && user.fields_html.length > 0"
|
||||
class="user-profile-fields"
|
||||
>
|
||||
<dl
|
||||
v-for="(field, index) in user.fields_html"
|
||||
:key="index"
|
||||
class="user-profile-field"
|
||||
>
|
||||
<dt
|
||||
:title="user.fields_text[index].name"
|
||||
class="user-profile-field-name"
|
||||
>
|
||||
<RichContent
|
||||
:html="field.name"
|
||||
:emoji="user.emoji"
|
||||
/>
|
||||
</dt>
|
||||
<dd
|
||||
:title="user.fields_text[index].value"
|
||||
class="user-profile-field-value"
|
||||
>
|
||||
<RichContent
|
||||
:html="field.value"
|
||||
:emoji="user.emoji"
|
||||
/>
|
||||
</dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
<tab-switcher
|
||||
:active-tab="tab"
|
||||
|
|
@ -173,58 +134,6 @@
|
|||
// No sticky header on user profile
|
||||
--currentPanelStack: 0;
|
||||
|
||||
.user-birthday {
|
||||
margin: 0 0.75em 0.5em;
|
||||
}
|
||||
|
||||
.user-profile-fields {
|
||||
margin: 0 0.5em;
|
||||
|
||||
img {
|
||||
object-fit: contain;
|
||||
vertical-align: middle;
|
||||
max-width: 100%;
|
||||
max-height: 400px;
|
||||
|
||||
&.emoji {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
}
|
||||
}
|
||||
|
||||
.user-profile-field {
|
||||
display: flex;
|
||||
margin: 0.25em;
|
||||
border: 1px solid var(--border);
|
||||
border-radius: var(--roundness);
|
||||
|
||||
.user-profile-field-name {
|
||||
flex: 0 1 30%;
|
||||
font-weight: 500;
|
||||
text-align: right;
|
||||
color: var(--lightText);
|
||||
min-width: 120px;
|
||||
border-right: 1px solid var(--border);
|
||||
}
|
||||
|
||||
.user-profile-field-value {
|
||||
flex: 1 1 70%;
|
||||
color: var(--text);
|
||||
margin: 0 0 0 0.25em;
|
||||
}
|
||||
|
||||
.user-profile-field-name,
|
||||
.user-profile-field-value {
|
||||
line-height: 1.3;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
padding: 0.5em 1.5em;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.userlist-placeholder {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
|
|
|
|||
|
|
@ -1423,7 +1423,7 @@
|
|||
"block_expires_forever": "Blocked forever",
|
||||
"block_expires_at": "Blocked until {0}",
|
||||
"mute_duration_prompt": "Mute this user for (0 for indefinite time):",
|
||||
"per_day": "per day",
|
||||
"statuses_per_day": "Statuses per day",
|
||||
"remote_follow": "Remote follow",
|
||||
"remove_follower": "Remove follower",
|
||||
"remove_follower_confirm_title": "Remove follower confirmation",
|
||||
|
|
@ -1464,17 +1464,15 @@
|
|||
"delete_user": "Delete user",
|
||||
"delete_user_data_and_deactivate_confirmation": "This will permanently delete the data from this account and deactivate it. Are you absolutely sure?"
|
||||
},
|
||||
"highlight": {
|
||||
"disabled": "No highlight",
|
||||
"solid": "Solid bg",
|
||||
"striped": "Striped bg",
|
||||
"highlight_new": {
|
||||
"disabled": "Don't highlight",
|
||||
"solid": "Solid background",
|
||||
"striped": "Striped background",
|
||||
"side": "Side stripe"
|
||||
},
|
||||
"note": "Note",
|
||||
"note_blank": "(None)",
|
||||
"edit_note": "Edit note",
|
||||
"edit_note_apply": "Apply",
|
||||
"edit_note_cancel": "Cancel"
|
||||
"personal_note": "Personal note",
|
||||
"note_blank_click": "Click to add note",
|
||||
"highlight_header": "Highlight user's posts and mentions"
|
||||
},
|
||||
"user_profile": {
|
||||
"timeline_title": "User timeline",
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue