Merge branch '275-avatar-placeholder' into 'develop'
Support avatar placeholder Closes #275 See merge request pleroma/pleroma-fe!511
This commit is contained in:
commit
d6ee6e8394
13 changed files with 90 additions and 97 deletions
|
@ -1,5 +1,5 @@
|
||||||
import Status from '../status/status.vue'
|
import Status from '../status/status.vue'
|
||||||
import StillImage from '../still-image/still-image.vue'
|
import UserAvatar from '../user_avatar/user_avatar.vue'
|
||||||
import UserCardContent from '../user_card_content/user_card_content.vue'
|
import UserCardContent from '../user_card_content/user_card_content.vue'
|
||||||
import { highlightClass, highlightStyle } from '../../services/user_highlighter/user_highlighter.js'
|
import { highlightClass, highlightStyle } from '../../services/user_highlighter/user_highlighter.js'
|
||||||
import generateProfileLink from 'src/services/user_profile_link_generator/user_profile_link_generator'
|
import generateProfileLink from 'src/services/user_profile_link_generator/user_profile_link_generator'
|
||||||
|
@ -13,7 +13,7 @@ const Notification = {
|
||||||
},
|
},
|
||||||
props: [ 'notification' ],
|
props: [ 'notification' ],
|
||||||
components: {
|
components: {
|
||||||
Status, StillImage, UserCardContent
|
Status, UserAvatar, UserCardContent
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
toggleUserExpanded () {
|
toggleUserExpanded () {
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
<status v-if="notification.type === 'mention'" :compact="true" :statusoid="notification.status"></status>
|
<status v-if="notification.type === 'mention'" :compact="true" :statusoid="notification.status"></status>
|
||||||
<div class="non-mention" :class="[userClass, { highlighted: userStyle }]" :style="[ userStyle ]"v-else>
|
<div class="non-mention" :class="[userClass, { highlighted: userStyle }]" :style="[ userStyle ]"v-else>
|
||||||
<a class='avatar-container' :href="notification.action.user.statusnet_profile_url" @click.stop.prevent.capture="toggleUserExpanded">
|
<a class='avatar-container' :href="notification.action.user.statusnet_profile_url" @click.stop.prevent.capture="toggleUserExpanded">
|
||||||
<StillImage class='avatar-compact' :class="{'better-shadow': betterShadow}" :src="notification.action.user.profile_image_url_original"/>
|
<UserAvatar :compact="true" :betterShadow="betterShadow" :src="notification.action.user.profile_image_url_original"/>
|
||||||
</a>
|
</a>
|
||||||
<div class='notification-right'>
|
<div class='notification-right'>
|
||||||
<div class="usercard notification-usercard" v-if="userExpanded">
|
<div class="usercard notification-usercard" v-if="userExpanded">
|
||||||
|
|
|
@ -36,26 +36,7 @@
|
||||||
border-color: $fallback--border;
|
border-color: $fallback--border;
|
||||||
border-color: var(--border, $fallback--border);
|
border-color: var(--border, $fallback--border);
|
||||||
|
|
||||||
.avatar-compact {
|
&:hover .animated.avatar {
|
||||||
width: 32px;
|
|
||||||
height: 32px;
|
|
||||||
box-shadow: var(--avatarStatusShadow);
|
|
||||||
border-radius: $fallback--avatarAltRadius;
|
|
||||||
border-radius: var(--avatarAltRadius, $fallback--avatarAltRadius);
|
|
||||||
overflow: hidden;
|
|
||||||
line-height: 0;
|
|
||||||
|
|
||||||
&.better-shadow {
|
|
||||||
box-shadow: var(--avatarStatusShadowInset);
|
|
||||||
filter: var(--avatarStatusShadowFilter)
|
|
||||||
}
|
|
||||||
|
|
||||||
&.animated::before {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&:hover .animated.avatar-compact {
|
|
||||||
canvas {
|
canvas {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@ import RetweetButton from '../retweet_button/retweet_button.vue'
|
||||||
import DeleteButton from '../delete_button/delete_button.vue'
|
import DeleteButton from '../delete_button/delete_button.vue'
|
||||||
import PostStatusForm from '../post_status_form/post_status_form.vue'
|
import PostStatusForm from '../post_status_form/post_status_form.vue'
|
||||||
import UserCardContent from '../user_card_content/user_card_content.vue'
|
import UserCardContent from '../user_card_content/user_card_content.vue'
|
||||||
import StillImage from '../still-image/still-image.vue'
|
import UserAvatar from '../user_avatar/user_avatar.vue'
|
||||||
import Gallery from '../gallery/gallery.vue'
|
import Gallery from '../gallery/gallery.vue'
|
||||||
import LinkPreview from '../link-preview/link-preview.vue'
|
import LinkPreview from '../link-preview/link-preview.vue'
|
||||||
import generateProfileLink from 'src/services/user_profile_link_generator/user_profile_link_generator'
|
import generateProfileLink from 'src/services/user_profile_link_generator/user_profile_link_generator'
|
||||||
|
@ -244,7 +244,7 @@ const Status = {
|
||||||
DeleteButton,
|
DeleteButton,
|
||||||
PostStatusForm,
|
PostStatusForm,
|
||||||
UserCardContent,
|
UserCardContent,
|
||||||
StillImage,
|
UserAvatar,
|
||||||
Gallery,
|
Gallery,
|
||||||
LinkPreview
|
LinkPreview
|
||||||
},
|
},
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
</template>
|
</template>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<div v-if="retweet && !noHeading" :class="[repeaterClass, { highlighted: repeaterStyle }]" :style="[repeaterStyle]" class="media container retweet-info">
|
<div v-if="retweet && !noHeading" :class="[repeaterClass, { highlighted: repeaterStyle }]" :style="[repeaterStyle]" class="media container retweet-info">
|
||||||
<StillImage v-if="retweet" class='avatar' :class='{ "better-shadow": betterShadow }' :src="statusoid.user.profile_image_url_original"/>
|
<UserAvatar v-if="retweet" :betterShadow="betterShadow" :src="statusoid.user.profile_image_url_original"/>
|
||||||
<div class="media-body faint">
|
<div class="media-body faint">
|
||||||
<a v-if="retweeterHtml" :href="statusoid.user.statusnet_profile_url" class="user-name" :title="'@'+statusoid.user.screen_name" v-html="retweeterHtml"></a>
|
<a v-if="retweeterHtml" :href="statusoid.user.statusnet_profile_url" class="user-name" :title="'@'+statusoid.user.screen_name" v-html="retweeterHtml"></a>
|
||||||
<a v-else :href="statusoid.user.statusnet_profile_url" class="user-name" :title="'@'+statusoid.user.screen_name">{{retweeter}}</a>
|
<a v-else :href="statusoid.user.statusnet_profile_url" class="user-name" :title="'@'+statusoid.user.screen_name">{{retweeter}}</a>
|
||||||
|
@ -25,7 +25,7 @@
|
||||||
<div :class="[userClass, { highlighted: userStyle, 'is-retweet': retweet }]" :style="[ userStyle ]" class="media status">
|
<div :class="[userClass, { highlighted: userStyle, 'is-retweet': retweet }]" :style="[ userStyle ]" class="media status">
|
||||||
<div v-if="!noHeading" class="media-left">
|
<div v-if="!noHeading" class="media-left">
|
||||||
<router-link :to="userProfileLink" @click.stop.prevent.capture.native="toggleUserExpanded">
|
<router-link :to="userProfileLink" @click.stop.prevent.capture.native="toggleUserExpanded">
|
||||||
<StillImage class='avatar' :class="{'avatar-compact': compact, 'better-shadow': betterShadow}" :src="status.user.profile_image_url_original"/>
|
<UserAvatar :compact="compact" :betterShadow="betterShadow" :src="status.user.profile_image_url_original"/>
|
||||||
</router-link>
|
</router-link>
|
||||||
</div>
|
</div>
|
||||||
<div class="status-body">
|
<div class="status-body">
|
||||||
|
@ -413,7 +413,7 @@
|
||||||
padding: 0.4em 0.6em 0 0.6em;
|
padding: 0.4em 0.6em 0 0.6em;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
|
||||||
.avatar {
|
.avatar.still-image {
|
||||||
border-radius: $fallback--avatarAltRadius;
|
border-radius: $fallback--avatarAltRadius;
|
||||||
border-radius: var(--avatarAltRadius, $fallback--avatarAltRadius);
|
border-radius: var(--avatarAltRadius, $fallback--avatarAltRadius);
|
||||||
margin-left: 28px;
|
margin-left: 28px;
|
||||||
|
@ -497,46 +497,6 @@
|
||||||
color: var(--cBlue, $fallback--cBlue);
|
color: var(--cBlue, $fallback--cBlue);
|
||||||
}
|
}
|
||||||
|
|
||||||
.status .avatar-compact {
|
|
||||||
width: 32px;
|
|
||||||
height: 32px;
|
|
||||||
box-shadow: var(--avatarStatusShadow);
|
|
||||||
border-radius: $fallback--avatarAltRadius;
|
|
||||||
border-radius: var(--avatarAltRadius, $fallback--avatarAltRadius);
|
|
||||||
|
|
||||||
&.better-shadow {
|
|
||||||
box-shadow: var(--avatarStatusShadowInset);
|
|
||||||
filter: var(--avatarStatusShadowFilter)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.avatar.still-image {
|
|
||||||
width: 48px;
|
|
||||||
height: 48px;
|
|
||||||
box-shadow: var(--avatarStatusShadow);
|
|
||||||
border-radius: $fallback--avatarRadius;
|
|
||||||
border-radius: var(--avatarRadius, $fallback--avatarRadius);
|
|
||||||
overflow: hidden;
|
|
||||||
position: relative;
|
|
||||||
|
|
||||||
&.better-shadow {
|
|
||||||
box-shadow: var(--avatarStatusShadowInset);
|
|
||||||
filter: var(--avatarStatusShadowFilter)
|
|
||||||
}
|
|
||||||
|
|
||||||
img {
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.animated::before {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.retweeted {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.status:hover .animated.avatar {
|
.status:hover .animated.avatar {
|
||||||
canvas {
|
canvas {
|
||||||
display: none;
|
display: none;
|
||||||
|
@ -594,7 +554,7 @@ a.unmute {
|
||||||
@media all and (max-width: 800px) {
|
@media all and (max-width: 800px) {
|
||||||
.status-el {
|
.status-el {
|
||||||
.retweet-info {
|
.retweet-info {
|
||||||
.avatar {
|
.avatar.still-image {
|
||||||
margin-left: 20px;
|
margin-left: 20px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -603,14 +563,14 @@ a.unmute {
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.status .avatar {
|
.status .avatar.still-image {
|
||||||
width: 40px;
|
width: 40px;
|
||||||
height: 40px;
|
height: 40px;
|
||||||
}
|
|
||||||
|
|
||||||
.status .avatar-compact {
|
&.avatar-compact {
|
||||||
width: 32px;
|
width: 32px;
|
||||||
height: 32px;
|
height: 32px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,8 @@ const StillImage = {
|
||||||
props: [
|
props: [
|
||||||
'src',
|
'src',
|
||||||
'referrerpolicy',
|
'referrerpolicy',
|
||||||
'mimetype'
|
'mimetype',
|
||||||
|
'imageLoadError'
|
||||||
],
|
],
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<template>
|
<template>
|
||||||
<div class='still-image' :class='{ animated: animated }' >
|
<div class='still-image' :class='{ animated: animated }' >
|
||||||
<canvas ref="canvas" v-if="animated"></canvas>
|
<canvas ref="canvas" v-if="animated"></canvas>
|
||||||
<img ref="src" :src="src" :referrerpolicy="referrerpolicy" v-on:load="onLoad"/>
|
<img ref="src" :src="src" :referrerpolicy="referrerpolicy" v-on:load="onLoad" @error="imageLoadError"/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
29
src/components/user_avatar/user_avatar.js
Normal file
29
src/components/user_avatar/user_avatar.js
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
import StillImage from '../still-image/still-image.vue'
|
||||||
|
|
||||||
|
const UserAvatar = {
|
||||||
|
props: [
|
||||||
|
'src',
|
||||||
|
'betterShadow',
|
||||||
|
'compact'
|
||||||
|
],
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
showPlaceholder: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
components: {
|
||||||
|
StillImage
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
imgSrc () {
|
||||||
|
return this.showPlaceholder ? '/images/avi.png' : this.src
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
imageLoadError () {
|
||||||
|
this.showPlaceholder = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default UserAvatar
|
37
src/components/user_avatar/user_avatar.vue
Normal file
37
src/components/user_avatar/user_avatar.vue
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
<template>
|
||||||
|
<StillImage class="avatar" :class="{ 'avatar-compact': compact, 'better-shadow': betterShadow }" :src="imgSrc" :imageLoadError="imageLoadError"/>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script src="./user_avatar.js"></script>
|
||||||
|
<style lang="scss">
|
||||||
|
@import '../../_variables.scss';
|
||||||
|
|
||||||
|
.avatar.still-image {
|
||||||
|
width: 48px;
|
||||||
|
height: 48px;
|
||||||
|
box-shadow: var(--avatarStatusShadow);
|
||||||
|
border-radius: $fallback--avatarRadius;
|
||||||
|
border-radius: var(--avatarRadius, $fallback--avatarRadius);
|
||||||
|
|
||||||
|
img {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.better-shadow {
|
||||||
|
box-shadow: var(--avatarStatusShadowInset);
|
||||||
|
filter: var(--avatarStatusShadowFilter)
|
||||||
|
}
|
||||||
|
|
||||||
|
&.animated::before {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.avatar-compact {
|
||||||
|
width: 32px;
|
||||||
|
height: 32px;
|
||||||
|
border-radius: $fallback--avatarAltRadius;
|
||||||
|
border-radius: var(--avatarAltRadius, $fallback--avatarAltRadius);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -1,5 +1,5 @@
|
||||||
import UserCardContent from '../user_card_content/user_card_content.vue'
|
import UserCardContent from '../user_card_content/user_card_content.vue'
|
||||||
import StillImage from '../still-image/still-image.vue'
|
import UserAvatar from '../user_avatar/user_avatar.vue'
|
||||||
import generateProfileLink from 'src/services/user_profile_link_generator/user_profile_link_generator'
|
import generateProfileLink from 'src/services/user_profile_link_generator/user_profile_link_generator'
|
||||||
|
|
||||||
const UserCard = {
|
const UserCard = {
|
||||||
|
@ -15,7 +15,7 @@ const UserCard = {
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
UserCardContent,
|
UserCardContent,
|
||||||
StillImage
|
UserAvatar
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
currentUser () { return this.$store.state.users.currentUser }
|
currentUser () { return this.$store.state.users.currentUser }
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<a href="#">
|
<a href="#">
|
||||||
<StillImage @click.prevent="toggleUserExpanded" class="avatar" :src="user.profile_image_url"/>
|
<UserAvatar :compact="true" @click.prevent="toggleUserExpanded" :src="user.profile_image_url"/>
|
||||||
</a>
|
</a>
|
||||||
<div class="usercard" v-if="userExpanded">
|
<div class="usercard" v-if="userExpanded">
|
||||||
<user-card-content :user="user" :switcher="false"></user-card-content>
|
<user-card-content :user="user" :switcher="false"></user-card-content>
|
||||||
|
@ -70,10 +70,6 @@
|
||||||
|
|
||||||
.avatar {
|
.avatar {
|
||||||
margin-top: 0.2em;
|
margin-top: 0.2em;
|
||||||
width:32px;
|
|
||||||
height: 32px;
|
|
||||||
border-radius: $fallback--avatarAltRadius;
|
|
||||||
border-radius: var(--avatarAltRadius, $fallback--avatarAltRadius);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import StillImage from '../still-image/still-image.vue'
|
import UserAvatar from '../user_avatar/user_avatar.vue'
|
||||||
import { hex2rgb } from '../../services/color_convert/color_convert.js'
|
import { hex2rgb } from '../../services/color_convert/color_convert.js'
|
||||||
import generateProfileLink from 'src/services/user_profile_link_generator/user_profile_link_generator'
|
import generateProfileLink from 'src/services/user_profile_link_generator/user_profile_link_generator'
|
||||||
|
|
||||||
|
@ -82,7 +82,7 @@ export default {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
StillImage
|
UserAvatar
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
followUser () {
|
followUser () {
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
<div class='user-info'>
|
<div class='user-info'>
|
||||||
<div class='container'>
|
<div class='container'>
|
||||||
<router-link :to="userProfileLink(user)">
|
<router-link :to="userProfileLink(user)">
|
||||||
<StillImage class="avatar" :class='{ "better-shadow": betterShadow }' :src="user.profile_image_url_original"/>
|
<UserAvatar :betterShadow="betterShadow" :src="user.profile_image_url_original"/>
|
||||||
</router-link>
|
</router-link>
|
||||||
<div class="name-and-screen-name">
|
<div class="name-and-screen-name">
|
||||||
<div class="top-line">
|
<div class="top-line">
|
||||||
|
@ -169,23 +169,12 @@
|
||||||
max-height: 56px;
|
max-height: 56px;
|
||||||
|
|
||||||
.avatar {
|
.avatar {
|
||||||
border-radius: $fallback--avatarRadius;
|
|
||||||
border-radius: var(--avatarRadius, $fallback--avatarRadius);
|
|
||||||
flex: 1 0 100%;
|
flex: 1 0 100%;
|
||||||
width: 56px;
|
width: 56px;
|
||||||
height: 56px;
|
height: 56px;
|
||||||
box-shadow: 0px 1px 8px rgba(0,0,0,0.75);
|
box-shadow: 0px 1px 8px rgba(0,0,0,0.75);
|
||||||
box-shadow: var(--avatarShadow);
|
box-shadow: var(--avatarShadow);
|
||||||
object-fit: cover;
|
object-fit: cover;
|
||||||
|
|
||||||
&.better-shadow {
|
|
||||||
box-shadow: var(--avatarShadowInset);
|
|
||||||
filter: var(--avatarShadowFilter)
|
|
||||||
}
|
|
||||||
|
|
||||||
&.animated::before {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue