Merge branch 'develop' into feature/new-user-routes
This commit is contained in:
commit
2211c533dd
93 changed files with 5123 additions and 894 deletions
|
@ -6,21 +6,37 @@ export default {
|
|||
props: [ 'user', 'switcher', 'selected', 'hideBio', 'activatePanel' ],
|
||||
data () {
|
||||
return {
|
||||
followRequestInProgress: false,
|
||||
followRequestSent: false,
|
||||
hideUserStatsLocal: typeof this.$store.state.config.hideUserStats === 'undefined'
|
||||
? this.$store.state.instance.hideUserStats
|
||||
: this.$store.state.config.hideUserStats
|
||||
: this.$store.state.config.hideUserStats,
|
||||
betterShadow: this.$store.state.interface.browserSupport.cssFilter
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
headingStyle () {
|
||||
const color = this.$store.state.config.colors.bg
|
||||
const color = this.$store.state.config.customTheme.colors
|
||||
? this.$store.state.config.customTheme.colors.bg // v2
|
||||
: this.$store.state.config.colors.bg // v1
|
||||
|
||||
if (color) {
|
||||
const rgb = hex2rgb(color)
|
||||
const rgb = (typeof color === 'string') ? hex2rgb(color) : color
|
||||
const tintColor = `rgba(${Math.floor(rgb.r)}, ${Math.floor(rgb.g)}, ${Math.floor(rgb.b)}, .5)`
|
||||
|
||||
const gradient = [
|
||||
[tintColor, this.hideBio ? '60%' : ''],
|
||||
this.hideBio ? [
|
||||
color, '100%'
|
||||
] : [
|
||||
tintColor, ''
|
||||
]
|
||||
].map(_ => _.join(' ')).join(', ')
|
||||
|
||||
return {
|
||||
backgroundColor: `rgb(${Math.floor(rgb.r * 0.53)}, ${Math.floor(rgb.g * 0.56)}, ${Math.floor(rgb.b * 0.59)})`,
|
||||
backgroundImage: [
|
||||
`linear-gradient(to bottom, ${tintColor}, ${tintColor})`,
|
||||
`linear-gradient(to bottom, ${gradient})`,
|
||||
`url(${this.user.cover_photo})`
|
||||
].join(', ')
|
||||
}
|
||||
|
@ -71,13 +87,68 @@ export default {
|
|||
methods: {
|
||||
followUser () {
|
||||
const store = this.$store
|
||||
this.followRequestInProgress = true
|
||||
store.state.api.backendInteractor.followUser(this.user.id)
|
||||
.then((followedUser) => store.commit('addNewUsers', [followedUser]))
|
||||
.then(() => {
|
||||
// For locked users we just mark it that we sent the follow request
|
||||
if (this.user.locked) {
|
||||
this.followRequestInProgress = false
|
||||
this.followRequestSent = true
|
||||
return
|
||||
}
|
||||
|
||||
if (this.user.following) {
|
||||
// If we get result immediately, just stop.
|
||||
this.followRequestInProgress = false
|
||||
return
|
||||
}
|
||||
|
||||
// But usually we don't get result immediately, so we ask server
|
||||
// for updated user profile to confirm if we are following them
|
||||
// Sometimes it takes several tries. Sometimes we end up not following
|
||||
// user anyway, probably because they locked themselves and we
|
||||
// don't know that yet.
|
||||
// Recursive Promise, it will call itself up to 3 times.
|
||||
const fetchUser = (attempt) => new Promise((resolve, reject) => {
|
||||
setTimeout(() => {
|
||||
store.state.api.backendInteractor.fetchUser({ id: this.user.id })
|
||||
.then((user) => store.commit('addNewUsers', [user]))
|
||||
.then(() => resolve([this.user.following, attempt]))
|
||||
.catch((e) => reject(e))
|
||||
}, 500)
|
||||
}).then(([following, attempt]) => {
|
||||
if (!following && attempt <= 3) {
|
||||
// If we BE reports that we still not following that user - retry,
|
||||
// increment attempts by one
|
||||
return fetchUser(++attempt)
|
||||
} else {
|
||||
// If we run out of attempts, just return whatever status is.
|
||||
return following
|
||||
}
|
||||
})
|
||||
|
||||
return fetchUser(1)
|
||||
.then((following) => {
|
||||
if (following) {
|
||||
// We confirmed and everything its good.
|
||||
this.followRequestInProgress = false
|
||||
} else {
|
||||
// If after all the tries, just treat it as if user is locked
|
||||
this.followRequestInProgress = false
|
||||
this.followRequestSent = true
|
||||
}
|
||||
})
|
||||
})
|
||||
},
|
||||
unfollowUser () {
|
||||
const store = this.$store
|
||||
this.followRequestInProgress = true
|
||||
store.state.api.backendInteractor.unfollowUser(this.user.id)
|
||||
.then((unfollowedUser) => store.commit('addNewUsers', [unfollowedUser]))
|
||||
.then(() => {
|
||||
this.followRequestInProgress = false
|
||||
})
|
||||
},
|
||||
blockUser () {
|
||||
const store = this.$store
|
||||
|
|
|
@ -2,20 +2,20 @@
|
|||
<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="{ name: 'user-settings' }" style="float: right; margin-top:16px;" v-if="!isOtherUser">
|
||||
<router-link @click.native="activatePanel && activatePanel('timeline')" :to="{ name: '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="userProfileLink(user)">
|
||||
<StillImage class="avatar" :src="user.profile_image_url_original"/>
|
||||
<router-link @click.native="activatePanel && activatePanel('timeline')" :to="userProfileLink(user)">
|
||||
<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="userProfileLink(user)">
|
||||
<router-link @click.native="activatePanel && activatePanel('timeline')" class='user-screen-name' :to="userProfileLink(user)">
|
||||
<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>
|
||||
|
@ -41,74 +41,87 @@
|
|||
</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">
|
||||
<div class="follow" v-if="loggedIn">
|
||||
<span v-if="user.following">
|
||||
<!--Following them!-->
|
||||
<button @click="unfollowUser" class="pressed" :disabled="followRequestInProgress" :title="$t('user_card.follow_unfollow')">
|
||||
<template v-if="followRequestInProgress">
|
||||
{{ $t('user_card.follow_progress') }}
|
||||
</template>
|
||||
<template v-else>
|
||||
{{ $t('user_card.following') }}
|
||||
</button>
|
||||
</span>
|
||||
<span v-if="!user.following">
|
||||
<button @click="followUser">
|
||||
</template>
|
||||
</button>
|
||||
</span>
|
||||
<span v-if="!user.following">
|
||||
<button @click="followUser" :disabled="followRequestInProgress" :title="followRequestSent ? $t('user_card.follow_again') : ''">
|
||||
<template v-if="followRequestInProgress">
|
||||
{{ $t('user_card.follow_progress') }}
|
||||
</template>
|
||||
<template v-else-if="followRequestSent">
|
||||
{{ $t('user_card.follow_sent') }}
|
||||
</template>
|
||||
<template v-else>
|
||||
{{ $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>
|
||||
</template>
|
||||
</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 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>
|
||||
<div class="panel-body profile-panel-body" v-if="!hideBio">
|
||||
<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>
|
||||
|
@ -120,10 +133,15 @@
|
|||
background-size: cover;
|
||||
border-radius: $fallback--panelRadius;
|
||||
border-radius: var(--panelRadius, $fallback--panelRadius);
|
||||
overflow: hidden;
|
||||
|
||||
border-bottom-left-radius: 0;
|
||||
border-bottom-right-radius: 0;
|
||||
|
||||
.panel-heading {
|
||||
padding: 0.6em 0em;
|
||||
text-align: center;
|
||||
box-shadow: none;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -138,15 +156,14 @@
|
|||
}
|
||||
|
||||
.user-info {
|
||||
color: $fallback--lightFg;
|
||||
color: var(--lightFg, $fallback--lightFg);
|
||||
color: $fallback--lightText;
|
||||
color: var(--lightText, $fallback--lightText);
|
||||
padding: 0 16px;
|
||||
|
||||
.container {
|
||||
padding: 16px 10px 6px 10px;
|
||||
display: flex;
|
||||
max-height: 56px;
|
||||
overflow: hidden;
|
||||
|
||||
.avatar {
|
||||
border-radius: $fallback--avatarRadius;
|
||||
|
@ -155,8 +172,14 @@
|
|||
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;
|
||||
}
|
||||
|
@ -173,8 +196,8 @@
|
|||
}
|
||||
|
||||
.usersettings {
|
||||
color: $fallback--lightFg;
|
||||
color: var(--lightFg, $fallback--lightFg);
|
||||
color: $fallback--lightText;
|
||||
color: var(--lightText, $fallback--lightText);
|
||||
opacity: .8;
|
||||
}
|
||||
|
||||
|
@ -185,6 +208,16 @@
|
|||
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{
|
||||
|
@ -193,8 +226,8 @@
|
|||
}
|
||||
|
||||
.user-screen-name {
|
||||
color: $fallback--lightFg;
|
||||
color: var(--lightFg, $fallback--lightFg);
|
||||
color: $fallback--lightText;
|
||||
color: var(--lightText, $fallback--lightText);
|
||||
display: inline-block;
|
||||
font-weight: light;
|
||||
font-size: 15px;
|
||||
|
@ -269,8 +302,8 @@
|
|||
padding: .5em 1.5em 0em 1.5em;
|
||||
text-align: center;
|
||||
justify-content: space-between;
|
||||
color: $fallback--lightFg;
|
||||
color: var(--lightFg, $fallback--lightFg);
|
||||
color: $fallback--lightText;
|
||||
color: var(--lightText, $fallback--lightText);
|
||||
|
||||
&.clickable {
|
||||
.user-count {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue