51cf4dc298
* upstream/develop: Fix iOS Safari from making videos play fullscreen by default added PR comments resolved the lint used the deleted data param as condition in status template Switch to "timeline" when pressing user-settings Added user setting tooltip made links in user bio always open in new tabs addressed PR comments added tooltip Add userId property to timelines so that we don't overwrite user timeline meant for another user Added option to auto-hide subject field when it's empty. removes hacks from notifications storage, adds api call to let server update is_seen attribute fixes vimium not giving retweet button a hint Do not use underscore at the beginning of the method Logout user on password change Route user to the correct profile URL Typo Fix filetype detection Switch to settings when touching settings Switch to timeline on nav panel actions
362 lines
9.9 KiB
Vue
362 lines
9.9 KiB
Vue
<template>
|
|
<div id="heading" class="profile-panel-background" :style="headingStyle">
|
|
<div class="panel-heading text-center">
|
|
<div class='user-info'>
|
|
<router-link @click.native="activatePanel('timeline')" to='/user-settings' style="float: right; margin-top:16px;" v-if="!isOtherUser">
|
|
<i class="icon-cog usersettings" :title="$t('tool_tip.user_settings')"></i>
|
|
</router-link>
|
|
<a :href="user.statusnet_profile_url" target="_blank" class="floater" v-if="isOtherUser">
|
|
<i class="icon-link-ext usersettings"></i>
|
|
</a>
|
|
<div class='container'>
|
|
<router-link :to="{ name: 'user-profile', params: { id: user.id } }">
|
|
<StillImage class="avatar" :class='{ "better-shadow": betterShadow }' :src="user.profile_image_url_original"/>
|
|
</router-link>
|
|
<div class="name-and-screen-name">
|
|
<div :title="user.name" class='user-name' v-if="user.name_html" v-html="user.name_html"></div>
|
|
<div :title="user.name" class='user-name' v-else>{{user.name}}</div>
|
|
<router-link class='user-screen-name':to="{ name: 'user-profile', params: { id: user.id } }">
|
|
<span>@{{user.screen_name}}</span><span v-if="user.locked"><i class="icon icon-lock"></i></span>
|
|
<span v-if="!hideUserStatsLocal" class="dailyAvg">{{dailyAvg}} {{ $t('user_card.per_day') }}</span>
|
|
</router-link>
|
|
</div>
|
|
</div>
|
|
<div class="user-meta">
|
|
<div v-if="user.follows_you && loggedIn && isOtherUser" class="following">
|
|
{{ $t('user_card.follows_you') }}
|
|
</div>
|
|
<div class="floater" v-if="switcher || isOtherUser">
|
|
<!-- id's need to be unique, otherwise vue confuses which user-card checkbox belongs to -->
|
|
<input class="userHighlightText" type="text" :id="'userHighlightColorTx'+user.id" v-if="userHighlightType !== 'disabled'" v-model="userHighlightColor"/>
|
|
<input class="userHighlightCl" type="color" :id="'userHighlightColor'+user.id" v-if="userHighlightType !== 'disabled'" v-model="userHighlightColor"/>
|
|
<label for="style-switcher" class='userHighlightSel select'>
|
|
<select class="userHighlightSel" :id="'userHighlightSel'+user.id" v-model="userHighlightType">
|
|
<option value="disabled">No highlight</option>
|
|
<option value="solid">Solid bg</option>
|
|
<option value="striped">Striped bg</option>
|
|
<option value="side">Side stripe</option>
|
|
</select>
|
|
<i class="icon-down-open"/>
|
|
</label>
|
|
</div>
|
|
</div>
|
|
<div v-if="isOtherUser" class="user-interactions">
|
|
<div class="follow" v-if="loggedIn">
|
|
<span v-if="user.following">
|
|
<!--Following them!-->
|
|
<button @click="unfollowUser" class="pressed">
|
|
{{ $t('user_card.following') }}
|
|
</button>
|
|
</span>
|
|
<span v-if="!user.following">
|
|
<button @click="followUser">
|
|
{{ $t('user_card.follow') }}
|
|
</button>
|
|
</span>
|
|
</div>
|
|
<div class='mute' v-if='isOtherUser'>
|
|
<span v-if='user.muted'>
|
|
<button @click="toggleMute" class="pressed">
|
|
{{ $t('user_card.muted') }}
|
|
</button>
|
|
</span>
|
|
<span v-if='!user.muted'>
|
|
<button @click="toggleMute">
|
|
{{ $t('user_card.mute') }}
|
|
</button>
|
|
</span>
|
|
</div>
|
|
<div class="remote-follow" v-if='!loggedIn && user.is_local'>
|
|
<form method="POST" :action='subscribeUrl'>
|
|
<input type="hidden" name="nickname" :value="user.screen_name">
|
|
<input type="hidden" name="profile" value="">
|
|
<button click="submit" class="remote-button">
|
|
{{ $t('user_card.remote_follow') }}
|
|
</button>
|
|
</form>
|
|
</div>
|
|
<div class='block' v-if='isOtherUser && loggedIn'>
|
|
<span v-if='user.statusnet_blocking'>
|
|
<button @click="unblockUser" class="pressed">
|
|
{{ $t('user_card.blocked') }}
|
|
</button>
|
|
</span>
|
|
<span v-if='!user.statusnet_blocking'>
|
|
<button @click="blockUser">
|
|
{{ $t('user_card.block') }}
|
|
</button>
|
|
</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="panel-body profile-panel-body">
|
|
<div v-if="!hideUserStatsLocal || switcher" class="user-counts" :class="{clickable: switcher}">
|
|
<div class="user-count" v-on:click.prevent="setProfileView('statuses')" :class="{selected: selected === 'statuses'}">
|
|
<h5>{{ $t('user_card.statuses') }}</h5>
|
|
<span v-if="!hideUserStatsLocal">{{user.statuses_count}} <br></span>
|
|
</div>
|
|
<div class="user-count" v-on:click.prevent="setProfileView('friends')" :class="{selected: selected === 'friends'}">
|
|
<h5>{{ $t('user_card.followees') }}</h5>
|
|
<span v-if="!hideUserStatsLocal">{{user.friends_count}}</span>
|
|
</div>
|
|
<div class="user-count" v-on:click.prevent="setProfileView('followers')" :class="{selected: selected === 'followers'}">
|
|
<h5>{{ $t('user_card.followers') }}</h5>
|
|
<span v-if="!hideUserStatsLocal">{{user.followers_count}}</span>
|
|
</div>
|
|
</div>
|
|
<p @click.prevent="linkClicked" v-if="!hideBio && user.description_html" class="profile-bio" v-html="user.description_html"></p>
|
|
<p v-else-if="!hideBio" class="profile-bio">{{ user.description }}</p>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script src="./user_card_content.js"></script>
|
|
|
|
<style lang="scss">
|
|
@import '../../_variables.scss';
|
|
|
|
.profile-panel-background {
|
|
background-size: cover;
|
|
border-radius: $fallback--panelRadius;
|
|
border-radius: var(--panelRadius, $fallback--panelRadius);
|
|
overflow: hidden;
|
|
|
|
.panel-heading {
|
|
padding: 0.6em 0em;
|
|
text-align: center;
|
|
box-shadow: none;
|
|
}
|
|
}
|
|
|
|
.profile-panel-body {
|
|
word-wrap: break-word;
|
|
background: linear-gradient(to bottom, rgba(0, 0, 0, 0), $fallback--bg 80%);
|
|
background: linear-gradient(to bottom, rgba(0, 0, 0, 0), var(--bg, $fallback--bg) 80%);
|
|
|
|
.profile-bio {
|
|
text-align: center;
|
|
}
|
|
}
|
|
|
|
.user-info {
|
|
color: $fallback--lightText;
|
|
color: var(--lightText, $fallback--lightText);
|
|
padding: 0 16px;
|
|
|
|
.container {
|
|
padding: 16px 10px 6px 10px;
|
|
display: flex;
|
|
max-height: 56px;
|
|
|
|
.avatar {
|
|
border-radius: $fallback--avatarRadius;
|
|
border-radius: var(--avatarRadius, $fallback--avatarRadius);
|
|
flex: 1 0 100%;
|
|
width: 56px;
|
|
height: 56px;
|
|
box-shadow: 0px 1px 8px rgba(0,0,0,0.75);
|
|
box-shadow: var(--avatarShadow);
|
|
object-fit: cover;
|
|
|
|
&.better-shadow {
|
|
box-shadow: var(--avatarShadowInset);
|
|
filter: var(--avatarShadowFilter)
|
|
}
|
|
|
|
&.animated::before {
|
|
display: none;
|
|
}
|
|
}
|
|
}
|
|
|
|
&:hover .animated.avatar {
|
|
canvas {
|
|
display: none;
|
|
}
|
|
img {
|
|
visibility: visible;
|
|
}
|
|
}
|
|
|
|
.usersettings {
|
|
color: $fallback--lightText;
|
|
color: var(--lightText, $fallback--lightText);
|
|
opacity: .8;
|
|
}
|
|
|
|
.name-and-screen-name {
|
|
display: block;
|
|
margin-left: 0.6em;
|
|
text-align: left;
|
|
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
|
|
// big one
|
|
z-index: 1;
|
|
|
|
img {
|
|
width: 26px;
|
|
height: 26px;
|
|
vertical-align: middle;
|
|
object-fit: contain
|
|
}
|
|
}
|
|
|
|
.user-name{
|
|
text-overflow: ellipsis;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.user-screen-name {
|
|
color: $fallback--lightText;
|
|
color: var(--lightText, $fallback--lightText);
|
|
display: inline-block;
|
|
font-weight: light;
|
|
font-size: 15px;
|
|
padding-right: 0.1em;
|
|
}
|
|
|
|
.user-meta {
|
|
margin-bottom: .4em;
|
|
|
|
.following {
|
|
font-size: 14px;
|
|
flex: 0 0 100%;
|
|
margin: 0;
|
|
padding-left: 16px;
|
|
text-align: left;
|
|
float: left;
|
|
}
|
|
.floater {
|
|
margin: 0;
|
|
}
|
|
|
|
&::after {
|
|
display: block;
|
|
content: '';
|
|
clear: both;
|
|
}
|
|
}
|
|
.user-interactions {
|
|
display: flex;
|
|
flex-flow: row wrap;
|
|
justify-content: space-between;
|
|
|
|
div {
|
|
flex: 1;
|
|
}
|
|
|
|
.mute {
|
|
max-width: 220px;
|
|
min-height: 28px;
|
|
}
|
|
|
|
.remote-follow {
|
|
max-width: 220px;
|
|
min-height: 28px;
|
|
}
|
|
|
|
.follow {
|
|
max-width: 220px;
|
|
min-height: 28px;
|
|
}
|
|
|
|
button {
|
|
width: 92%;
|
|
height: 100%;
|
|
}
|
|
|
|
.remote-button {
|
|
height: 28px !important;
|
|
width: 92%;
|
|
}
|
|
|
|
.pressed {
|
|
border-bottom-color: rgba(255, 255, 255, 0.2);
|
|
border-top-color: rgba(0, 0, 0, 0.2);
|
|
}
|
|
}
|
|
}
|
|
|
|
.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);
|
|
|
|
&.clickable {
|
|
.user-count {
|
|
cursor: pointer;
|
|
|
|
&:hover:not(.selected) {
|
|
transition: border-bottom 100ms;
|
|
border-bottom: 3px solid $fallback--link;
|
|
border-bottom: 3px solid var(--link, $fallback--link);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
.user-count {
|
|
flex: 1;
|
|
padding: .5em 0 .5em 0;
|
|
margin: 0 .5em;
|
|
|
|
&.selected {
|
|
transition: none;
|
|
border-bottom: 5px solid $fallback--link;
|
|
border-bottom: 5px solid var(--link, $fallback--link);
|
|
border-radius: $fallback--btnRadius;
|
|
border-radius: var(--btnRadius, $fallback--btnRadius);
|
|
}
|
|
|
|
h5 {
|
|
font-size:1em;
|
|
font-weight: bolder;
|
|
margin: 0 0 0.25em;
|
|
}
|
|
a {
|
|
text-decoration: none;
|
|
}
|
|
}
|
|
|
|
.dailyAvg {
|
|
margin-left: 1em;
|
|
font-size: 0.7em;
|
|
color: #CCC;
|
|
}
|
|
.floater {
|
|
float: right;
|
|
margin-top: 16px;
|
|
|
|
.userHighlightCl {
|
|
padding: 2px 10px;
|
|
}
|
|
.userHighlightSel,
|
|
.userHighlightSel.select {
|
|
padding-top: 0;
|
|
padding-bottom: 0;
|
|
}
|
|
.userHighlightSel.select i {
|
|
line-height: 22px;
|
|
}
|
|
|
|
.userHighlightText {
|
|
width: 70px;
|
|
}
|
|
|
|
.userHighlightCl,
|
|
.userHighlightText,
|
|
.userHighlightSel,
|
|
.userHighlightSel.select {
|
|
height: 22px;
|
|
vertical-align: top;
|
|
margin-right: 0
|
|
}
|
|
}
|
|
</style>
|