refs #702 Show substitute image when can not load the image

This commit is contained in:
AkiraFukushima 2018-11-14 21:29:15 +09:00
parent b92722b979
commit 6a8585a0ec
7 changed files with 73 additions and 15 deletions

View File

@ -21,13 +21,13 @@
<span class="bold" @click="openUser(message.account)" v-html="username(message.account)"></span> favourited your status
</div>
<div class="action-icon">
<img :src="message.account.avatar" :alt="`Avatar of ${message.account.username}`" />
<FailoverImg :src="message.account.avatar" :alt="`Avatar of ${message.account.username}`" />
</div>
</div>
<div class="clearfix"></div>
<div class="target" v-on:dblclick="openDetail(message.status)">
<div class="icon" @click="openUser(message.status.account)">
<img :src="message.status.account.avatar" :alt="`Avatar of ${message.status.account.username}`" />
<FailoverImg :src="message.status.account.avatar" :alt="`Avatar of ${message.status.account.username}`" />
</div>
<div class="detail">
<div class="toot-header">
@ -60,7 +60,7 @@
<icon name="eye" class="hide"></icon>
</el-button>
<div class="media" v-for="media in mediaAttachments(message.status)">
<img :src="media.preview_url" alt="attached media" />
<FailoverImg :src="media.preview_url" alt="attached media" />
</div>
</div>
<div class="clearfix"></div>
@ -80,9 +80,13 @@ import { shell } from 'electron'
import { findAccount, findLink, findTag } from '~/src/renderer/utils/tootParser'
import emojify from '~/src/renderer/utils/emojify'
import TimeFormat from '~/src/constants/timeFormat'
import FailoverImg from '~/src/renderer/components/atoms/FailoverImg'
export default {
name: 'favourite',
components: {
FailoverImg
},
props: {
message: {
type: Object,

View File

@ -17,7 +17,7 @@
<span class="bold" @click="openUser(message.account)">{{ username(message.account) }}</span> is now following you
</div>
<div class="action-icon">
<img :src="message.account.avatar" />
<FailoverImg :src="message.account.avatar" />
</div>
</div>
<div class="clearfix"></div>
@ -26,8 +26,13 @@
</template>
<script>
import FailoverImg from '~/src/renderer/components/atoms/FailoverImg'
export default {
name: 'follow',
componengs: {
FailoverImg
},
props: {
message: {
type: Object,

View File

@ -21,13 +21,13 @@
<span class="bold" @click="openUser(message.account)" v-html="username(message.account)"></span> boosted your status
</div>
<div class="action-icon">
<img :src="message.account.avatar" :alt="`Avatar of ${message.account.username}`" />
<FailoverImg :src="message.account.avatar" :alt="`Avatar of ${message.account.username}`" />
</div>
</div>
<div class="clearfix"></div>
<div class="target" v-on:dblclick="openDetail(message.status)">
<div class="icon" @click="openUser(message.status.account)">
<img :src="message.status.account.avatar" :alt="`Avatar of ${message.status.account.username}`" />
<FailoverImg :src="message.status.account.avatar" :alt="`Avatar of ${message.status.account.username}`" />
</div>
<div class="detail">
<div class="toot-header">
@ -60,7 +60,7 @@
<icon name="eye" class="hide"></icon>
</el-button>
<div class="media" v-for="media in mediaAttachments(message.status)">
<img :src="media.preview_url" alt="attached media" />
<FailoverImg :src="media.preview_url" alt="attached media" />
</div>
</div>
<div class="clearfix"></div>
@ -80,9 +80,13 @@ import { shell } from 'electron'
import { findAccount, findLink, findTag } from '~/src/renderer/utils/tootParser'
import emojify from '~/src/renderer/utils/emojify'
import TimeFormat from '~/src/constants/timeFormat'
import FailoverImg from '~/src/renderer/components/atoms/FailoverImg'
export default {
name: 'reblog',
components: {
FailoverImg
},
props: {
message: {
type: Object,

View File

@ -14,10 +14,9 @@
</div>
<div v-show="!filtered(message)" class="toot">
<div class="icon">
<img
<FailoverImg
:src="originalMessage(message).account.avatar"
@click="openUser(originalMessage(message).account)"
role="img"
:alt="`Avatar of ${originalMessage(message).account.username}`"
/>
</div>
@ -53,7 +52,7 @@
<icon name="eye" class="hide"></icon>
</el-button>
<div class="media" v-bind:key="media.preview_url" v-for="media in mediaAttachments(message)">
<img :src="media.preview_url" @click="openImage(media.url, mediaAttachments(message))"/>
<FailoverImg :src="media.preview_url" @click="openImage(media.url, mediaAttachments(message))"/>
<span class="media-label" v-if="media.type == 'gifv'">GIF</span>
<span class="media-label" v-else-if="media.type == 'video'">VIDEO</span>
</div>
@ -63,8 +62,9 @@
<div class="reblogger" v-show="message.reblog !== null">
<icon name="retweet"></icon>
<span class="reblogger-icon" @click="openUser(message.account)">
<img :src="message.account.avatar"
:alt="`Avatar of ${message.account.username}`" />
<FailoverImg
:src="message.account.avatar"
:alt="`Avatar of ${message.account.username}`" />
</span>
<span class="reblogger-name" @click="openUser(message.account)" :title="`Reblogged by ${message.account.username}`" v-html="username(message.account)">
</span>
@ -140,9 +140,13 @@ import { findAccount, findLink, findTag } from '~/src/renderer/utils/tootParser'
import DisplayStyle from '~/src/constants/displayStyle'
import TimeFormat from '~/src/constants/timeFormat'
import emojify from '~/src/renderer/utils/emojify'
import FailoverImg from '~/src/renderer/components/atoms/FailoverImg'
export default {
name: 'toot',
components: {
FailoverImg
},
data () {
return {
showContent: false,

View File

@ -1,7 +1,7 @@
<template>
<div class="user" @click="openUser(user)" aria-label="user">
<div class="icon">
<img :src="user.avatar" :alt="`Avatar of ${user.username}`" />
<FailoverImg :src="user.avatar" :alt="`Avatar of ${user.username}`" />
</div>
<div class="name">
<div class="username">
@ -32,8 +32,13 @@
</template>
<script>
import FailoverImg from '~/src/renderer/components/atoms/FailoverImg'
export default {
name: 'user',
components: {
FailoverImg
},
props: {
user: {
type: Object,

View File

@ -46,7 +46,7 @@
</popper>
</div>
<div class="icon">
<img :src="account.avatar" :alt="`Avatar of ${account.username}`" />
<FailoverImg :src="account.avatar" :alt="`Avatar of ${account.username}`" />
</div>
<div class="follow-status" v-if="relationship !== null && relationship !== '' && account.username!==user.username">
<div v-if="relationship.following" class="unfollow" @click="unfollow(account)" :title="$t('side_bar.account_profile.unfollow')">
@ -113,13 +113,15 @@ import { findLink } from '~/src/renderer/utils/tootParser'
import Timeline from './AccountProfile/Timeline'
import Follows from './AccountProfile/Follows'
import Followers from './AccountProfile/Followers'
import FailoverImg from '~/src/renderer/components/atoms/FailoverImg'
export default {
name: 'account-profile',
components: {
Timeline,
Follows,
Followers
Followers,
FailoverImg
},
data () {
return {

View File

@ -0,0 +1,34 @@
<template>
<img :src="originalSrc" :title="title" :alt="alt" v-on:error="failover" @click="$emit('click')" />
</template>
<script>
export default {
name: 'FailoverImg',
props: {
src: {
type: String,
default: ''
},
title: {
type: String,
default: ''
},
alt: {
type: String,
default: ''
}
},
data () {
return {
originalSrc: this.src,
failoverSrc: 'data:image/png;base64,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8uyu8TbiNgXmedEw05izs7P8Fjrdad3pzMSyT9ylsyYpjwipvI2p/fBe+djEq1evGofN8qLr7PLptJane13xzkgK3Gjx2bn2BQ58QJVXf0yN6t9CeeDReNpz4Ltqy9jyucT6jwjNrtBOz5g+5rtowtnmtPB6fLPznZEU2NjhOAtMyt15/eflyw268WCm3MIG+JRA5ZbxrsPgxv9fo+/dbTnmNzY28CJaq+no3AJzh2l4mUqBafXHxppGj/r/MWM5ZWr8NG25Tf/69WuYUb180k7fp1R+bKLxCD9f7pu9jzSeMf/HOC6tP8E2/CJakwhrCpzb4cgLzCc2aq4jl1tYvjKeTqguOnsUG2L5/WLDfP9AumCdn7f86EOnYTB2LvUR5q/VmP2Yb/x7vgsi3VizaIiLRyizn+7d3nfGVmBlXjqJAlMnp6enLUebcu4693JZbJfl1c4h76jKO4X0Af8eE8vyXu1Fynlv5ZNNlVlxrP258/byK/C67i9u9UjYssDcYf3x1djEllcOIzXnP9JVmbLD/LHX9AUq5YQ2Rs4hb7OMd/Hu3buuf6v82ESbS03xZvOMIIa72H+Ve5m0iNKqj39Gh2mIjr+1tbV179696LacdMSP6vcXsVLa/H+j4zXUfEfGOkTYqcA8aZnWLu3k5KTxvHz6tXJ4j+1p0Z2NabMY/xcBl3PRljPn2LPkoSyiKitKH5nf29srK1q0d0sfEG98usFuexj1dLScPKyrll8oFNvN4eFh4zmP+LWjo6NJnPQrP8Lb8qaL8tdmT8/ETz9+/Nh4K1n8WiyiqX9b+XAj4XRvrYw1nfajbVZ27ODzd9rXZBYPFVtPuq5Y+SBf/Cjdi9z761hj281PPZtE+dOuN0zm86XlW4sXn/cU7W+hTsd+Naey0q4qLZ9Kpekt1JyzyUeenT6DsqqY/zk4OFjG41Zm4XGYMfDtRen76svD+pHfQJhe5+35OHm/RZT+RxRr9r62rNqRkN+tXUS+3gJECCIcxpAXu8zucEw4x9nZ2fn5+TDnSK+urm7JV1YiwrYGvlR694+NKV8XQYR/WZubhsAxISBCMB39W9K9V6N6q+t3pwUibNjix3yPGJiOAiIEEQIiBBGCCC0CECGIEBAhiBAQIYgQECGIEBAhiBAQIYgQECGIEBAhiBAQIYgQECGIEBAhiBAQIYgQECGIEBAhiBAQIYgQECGIEBAhiBAQIYgQECGIEBAhiBAQIYgQECGIEBAhiBAQIYgQECGIEBAhiBAQIYgQECGIEBAhiBAQIYgQECGIEBAhiBBECIgQRAiIEEQIiBBECIgQRAiIEEQIiBBECIgQRAiIEEQIiBBECIgQRAiIEEQIiBBECIgQRAiIEEQIiBBECIgQRAiIEEQIiBBECIgQRAiIEEQIiBBECIgQRAiIEEQIiBBECIgQRAiIEEQIiBDG6D8BBgBNIRvwsstoqwAAAABJRU5ErkJggg=='
}
},
methods: {
failover () {
this.originalSrc = this.failoverSrc
}
}
}
</script>