Merge branch 'stillGifs' into 'develop'

Still gifs

See merge request pleroma/pleroma-fe!193
This commit is contained in:
lambda 2018-04-03 09:14:42 +00:00
commit e4b2fdf124
14 changed files with 184 additions and 17 deletions

View File

@ -1,3 +1,4 @@
import StillImage from '../still-image/still-image.vue'
import nsfwImage from '../../assets/nsfw.png' import nsfwImage from '../../assets/nsfw.png'
import fileTypeService from '../../services/file_type/file_type.service.js' import fileTypeService from '../../services/file_type/file_type.service.js'
@ -16,6 +17,9 @@ const Attachment = {
img: document.createElement('img') img: document.createElement('img')
} }
}, },
components: {
StillImage
},
computed: { computed: {
type () { type () {
return fileTypeService.fileType(this.attachment.mimetype) return fileTypeService.fileType(this.attachment.mimetype)

View File

@ -8,7 +8,7 @@
</div> </div>
<a v-if="type === 'image' && !hidden" class="image-attachment" :href="attachment.url" target="_blank"> <a v-if="type === 'image' && !hidden" class="image-attachment" :href="attachment.url" target="_blank">
<img class="base03-border" referrerpolicy="no-referrer" :src="attachment.large_thumb_url || attachment.url"/> <StillImage class="base03-border" referrerpolicy="no-referrer" :mimetype="attachment.mimetype" :src="attachment.large_thumb_url || attachment.url"/>
</a> </a>
<video class="base03" v-if="type === 'video' && !hidden" :src="attachment.url" controls loop></video> <video class="base03" v-if="type === 'video' && !hidden" :src="attachment.url" controls loop></video>
@ -126,6 +126,11 @@
display: flex; display: flex;
flex: 1; flex: 1;
.still-image {
width: 100%;
height: 100%;
}
img { img {
object-fit: contain; object-fit: contain;
width: 100%; width: 100%;

View File

@ -1,4 +1,5 @@
import Status from '../status/status.vue' import Status from '../status/status.vue'
import StillImage from '../still-image/still-image.vue'
import { sortBy, take, filter } from 'lodash' import { sortBy, take, filter } from 'lodash'
@ -31,7 +32,7 @@ const Notifications = {
} }
}, },
components: { components: {
Status Status, StillImage
}, },
watch: { watch: {
unseenCount (count) { unseenCount (count) {

View File

@ -88,10 +88,26 @@
} }
.avatar { .avatar {
padding-top: 0.3em; margin-top: 0.3em;
width: 32px; width: 32px;
height: 32px; height: 32px;
border-radius: 50%; border-radius: 50%;
overflow: hidden;
line-height: 0;
&.animated::before {
display: none;
}
}
&:hover .animated.avatar {
canvas {
display: none;
}
img {
visibility: visible;
}
} }
&:last-child { &:last-child {
@ -104,6 +120,10 @@
max-height: 12em; max-height: 12em;
overflow-y: hidden; overflow-y: hidden;
//text-overflow: ellipsis; //text-overflow: ellipsis;
img {
object-fit: contain;
}
} }
.notification-gradient { .notification-gradient {

View File

@ -10,7 +10,7 @@
<div v-for="notification in visibleNotifications" :key="notification" class="notification" :class='{"unseen": !notification.seen}'> <div v-for="notification in visibleNotifications" :key="notification" class="notification" :class='{"unseen": !notification.seen}'>
<div> <div>
<a :href="notification.action.user.statusnet_profile_url" target="_blank"> <a :href="notification.action.user.statusnet_profile_url" target="_blank">
<img class='avatar' :src="notification.action.user.profile_image_url_original"> <StillImage class='avatar' :src="notification.action.user.profile_image_url_original"/>
</a> </a>
</div> </div>
<div class='text' style="width: 100%;"> <div class='text' style="width: 100%;">

View File

@ -10,7 +10,8 @@ const settings = {
muteWordsString: this.$store.state.config.muteWords.join('\n'), muteWordsString: this.$store.state.config.muteWords.join('\n'),
autoLoadLocal: this.$store.state.config.autoLoad, autoLoadLocal: this.$store.state.config.autoLoad,
streamingLocal: this.$store.state.config.streaming, streamingLocal: this.$store.state.config.streaming,
hoverPreviewLocal: this.$store.state.config.hoverPreview hoverPreviewLocal: this.$store.state.config.hoverPreview,
stopGifs: this.$store.state.config.stopGifs
} }
}, },
components: { components: {
@ -43,6 +44,9 @@ const settings = {
muteWordsString (value) { muteWordsString (value) {
value = filter(value.split('\n'), (word) => trim(word).length > 0) value = filter(value.split('\n'), (word) => trim(word).length > 0)
this.$store.dispatch('setOption', { name: 'muteWords', value }) this.$store.dispatch('setOption', { name: 'muteWords', value })
},
stopGifs (value) {
this.$store.dispatch('setOption', { name: 'stopGifs', value })
} }
} }
} }

View File

@ -29,8 +29,8 @@
<label for="hideNsfw">{{$t('settings.nsfw_clickthrough')}}</label> <label for="hideNsfw">{{$t('settings.nsfw_clickthrough')}}</label>
</li> </li>
<li> <li>
<input type="checkbox" id="autoLoad" v-model="autoLoadLocal"> <input type="checkbox" id="autoload" v-model="autoloadlocal">
<label for="autoLoad">{{$t('settings.autoload')}}</label> <label for="autoload">{{$t('settings.autoload')}}</label>
</li> </li>
<li> <li>
<input type="checkbox" id="streaming" v-model="streamingLocal"> <input type="checkbox" id="streaming" v-model="streamingLocal">
@ -40,6 +40,10 @@
<input type="checkbox" id="hoverPreview" v-model="hoverPreviewLocal"> <input type="checkbox" id="hoverPreview" v-model="hoverPreviewLocal">
<label for="hoverPreview">{{$t('settings.reply_link_preview')}}</label> <label for="hoverPreview">{{$t('settings.reply_link_preview')}}</label>
</li> </li>
<li>
<input type="checkbox" id="stopGifs" v-model="stopGifs">
<label for="stopGifs">{{$t('settings.stop_gifs')}}</label>
</li>
</ul> </ul>
</div> </div>
</div> </div>

View File

@ -4,6 +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 { filter, find } from 'lodash' import { filter, find } from 'lodash'
const Status = { const Status = {
@ -76,7 +77,8 @@ const Status = {
RetweetButton, RetweetButton,
DeleteButton, DeleteButton,
PostStatusForm, PostStatusForm,
UserCardContent UserCardContent,
StillImage
}, },
methods: { methods: {
linkClicked ({target}) { linkClicked ({target}) {

View File

@ -34,8 +34,8 @@
<div class="media status container"> <div class="media status container">
<div class="media-left"> <div class="media-left">
<a :href="status.user.statusnet_profile_url"> <a :href="status.user.statusnet_profile_url">
<img @click.prevent="toggleUserExpanded" :class="{retweeted: retweet}" class='avatar' :src="status.user.profile_image_url_original"> <StillImage @click.native.prevent="toggleUserExpanded" :class="{retweeted: retweet}" class='avatar' :src="status.user.profile_image_url_original"/>
<img v-if="retweet" class='avatar-retweeter' :src="statusoid.user.profile_image_url_original"></img> <StillImage v-if="retweet" class='avatar avatar-retweeter' :src="statusoid.user.profile_image_url_original"/>
</a> </a>
</div> </div>
<div class="media-body"> <div class="media-body">
@ -84,7 +84,7 @@
</div> </div>
<div class="status-preview base00-background base03-border" v-if="showPreview && preview"> <div class="status-preview base00-background base03-border" v-if="showPreview && preview">
<img class="avatar" :src="preview.user.profile_image_url_original"> <StillImage class="avatar" :src="preview.user.profile_image_url_original"/>
<div class="text"> <div class="text">
<h4> <h4>
{{ preview.user.name }} {{ preview.user.name }}
@ -146,6 +146,7 @@
box-shadow: 2px 2px 3px rgba(0, 0, 0, 0.5); box-shadow: 2px 2px 3px rgba(0, 0, 0, 0.5);
margin-top: 0.5em; margin-top: 0.5em;
margin-left: 1em; margin-left: 1em;
z-index: 50;
.avatar { .avatar {
flex-shrink: 0; flex-shrink: 0;
@ -264,9 +265,8 @@
.media-left { .media-left {
margin: 0.2em 0.3em 0 0; margin: 0.2em 0.3em 0 0;
img { .avatar {
float: right; float: right;
border-radius: 5px;
} }
} }
@ -330,6 +330,17 @@
.status .avatar { .status .avatar {
width: 48px; width: 48px;
height: 48px; height: 48px;
border-radius: 5px;
overflow: hidden;
img {
width: 100%;
height: 100%;
}
&.animated::before {
display: none;
}
&.retweeted { &.retweeted {
width: 40px; width: 40px;
@ -339,7 +350,16 @@
} }
} }
.status img.avatar-retweeter { .status:hover .animated.avatar {
canvas {
display: none;
}
img {
visibility: visible;
}
}
.status .avatar-retweeter {
width: 24px; width: 24px;
height: 24px; height: 24px;
position: absolute; position: absolute;
@ -413,7 +433,7 @@
} }
} }
.status img.avatar-retweeter { .status .avatar-retweeter {
width: 22px; width: 22px;
height: 22px; height: 22px;
position: absolute; position: absolute;

View File

@ -0,0 +1,26 @@
const StillImage = {
props: [
'src',
'referrerpolicy',
'mimetype'
],
data () {
return {
stopGifs: this.$store.state.config.stopGifs
}
},
computed: {
animated () {
return this.stopGifs && (this.mimetype === 'image/gif' || this.src.endsWith('.gif'))
}
},
methods: {
onLoad () {
const canvas = this.$refs.canvas
if (!canvas) return
canvas.getContext('2d').drawImage(this.$refs.src, 1, 1, canvas.width, canvas.height)
}
}
}
export default StillImage

View File

@ -0,0 +1,62 @@
<template>
<div class='still-image' :class='{ animated: animated }' >
<canvas ref="canvas" v-if="animated"></canvas>
<img ref="src" :src="src" :referrerpolicy="referrerpolicy" v-on:load="onLoad"/>
</div>
</template>
<script src="./still-image.js"></script>
<style lang="scss">
@import '../../_variables.scss';
.still-image {
position: relative;
line-height: 0;
overflow: hidden;
&:hover canvas {
display: none;
}
img {
width: 100%;
height: 100%
}
&.animated {
&:hover::before,
img {
visibility: hidden;
}
&:hover img {
visibility: visible
}
&::before {
content: 'gif';
position: absolute;
line-height: 10px;
font-size: 10px;
top: 5px;
left: 5px;
background: rgba(127,127,127,.5);
color: #FFF;
display: block;
padding: 2px 4px;
border-radius: 3px;
z-index: 2;
}
}
canvas {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
width: 100%;
height: 100%;
}
}
</style>

View File

@ -1,3 +1,4 @@
import StillImage from '../still-image/still-image.vue'
import { hex2rgb } from '../../services/color_convert/color_convert.js' import { hex2rgb } from '../../services/color_convert/color_convert.js'
export default { export default {
@ -35,6 +36,9 @@ export default {
return Math.round(this.user.statuses_count / days) return Math.round(this.user.statuses_count / days)
} }
}, },
components: {
StillImage
},
methods: { methods: {
followUser () { followUser () {
const store = this.$store const store = this.$store

View File

@ -7,7 +7,7 @@
</router-link> </router-link>
<div class='container'> <div class='container'>
<router-link :to="{ name: 'user-profile', params: { id: user.id } }"> <router-link :to="{ name: 'user-profile', params: { id: user.id } }">
<img :src="user.profile_image_url_original"> <StillImage class="avatar" :src="user.profile_image_url_original"/>
</router-link> </router-link>
<span class="glyphicon glyphicon-user"></span> <span class="glyphicon glyphicon-user"></span>
<div class="name-and-screen-name"> <div class="name-and-screen-name">
@ -135,13 +135,26 @@
overflow: hidden; overflow: hidden;
} }
img { .avatar {
border-radius: 5px; border-radius: 5px;
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);
object-fit: cover; object-fit: cover;
&.animated::before {
display: none;
}
}
&:hover .animated.avatar {
canvas {
display: none;
}
img {
visibility: visible;
}
} }
text-shadow: 0px 1px 1.5px rgba(0, 0, 0, 1.0); text-shadow: 0px 1px 1.5px rgba(0, 0, 0, 1.0);

View File

@ -249,6 +249,7 @@ const en = {
hide_attachments_in_tl: 'Hide attachments in timeline', hide_attachments_in_tl: 'Hide attachments in timeline',
hide_attachments_in_convo: 'Hide attachments in conversations', hide_attachments_in_convo: 'Hide attachments in conversations',
nsfw_clickthrough: 'Enable clickthrough NSFW attachment hiding', nsfw_clickthrough: 'Enable clickthrough NSFW attachment hiding',
stop_gifs: 'Play-on-hover GIFs',
autoload: 'Enable automatic loading when scrolled to the bottom', autoload: 'Enable automatic loading when scrolled to the bottom',
streaming: 'Enable automatic streaming of new posts when scrolled to the top', streaming: 'Enable automatic streaming of new posts when scrolled to the top',
reply_link_preview: 'Enable reply-link preview on mouse hover', reply_link_preview: 'Enable reply-link preview on mouse hover',
@ -1103,6 +1104,7 @@ const ru = {
attachments: 'Вложения', attachments: 'Вложения',
hide_attachments_in_tl: 'Прятать вложения в ленте', hide_attachments_in_tl: 'Прятать вложения в ленте',
hide_attachments_in_convo: 'Прятать вложения в разговорах', hide_attachments_in_convo: 'Прятать вложения в разговорах',
stop_gifs: 'Проигрывать GIF анимации только при наведении',
nsfw_clickthrough: 'Включить скрытие NSFW вложений', nsfw_clickthrough: 'Включить скрытие NSFW вложений',
autoload: 'Включить автоматическую загрузку при прокрутке вниз', autoload: 'Включить автоматическую загрузку при прокрутке вниз',
streaming: 'Включить автоматическую загрузку новых сообщений при прокрутке вверх', streaming: 'Включить автоматическую загрузку новых сообщений при прокрутке вверх',