implement autoplay gif feature for avatars
This commit is contained in:
parent
545d2a9d92
commit
f1eaee4674
|
@ -1,9 +1,10 @@
|
|||
<div class="account-profile {{headerIsMissing ? 'header-is-missing' : ''}}" style="background-image: url({{profile.header}});">
|
||||
<div class="account-profile {{headerIsMissing ? 'header-is-missing' : ''}}"
|
||||
style="background-image: url({{$autoplayGifs ? profile.header : profile.header_static}});">
|
||||
<div class="account-profile-grid-wrapper">
|
||||
<div class="account-profile-backdrop"></div>
|
||||
<div class="account-profile-grid">
|
||||
<div class="account-profile-avatar">
|
||||
<img src="{{profile.avatar}}" aria-hidden="true">
|
||||
<Avatar account="{{profile}}" size="big" />
|
||||
</div>
|
||||
<div class="account-profile-name">
|
||||
<ExternalLink href="{{profile.url}}">
|
||||
|
@ -101,11 +102,6 @@
|
|||
.account-profile-avatar {
|
||||
grid-area: avatar;
|
||||
}
|
||||
.account-profile-avatar img {
|
||||
border-radius: 4px;
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
}
|
||||
|
||||
.account-profile-username {
|
||||
grid-area: username;
|
||||
|
@ -159,10 +155,6 @@
|
|||
}
|
||||
|
||||
@media (max-width: 767px) {
|
||||
.account-profile-avatar img {
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
}
|
||||
.account-profile-name {
|
||||
font-size: 1.3em;
|
||||
}
|
||||
|
@ -190,14 +182,18 @@
|
|||
<script>
|
||||
import IconButton from './IconButton.html'
|
||||
import ExternalLink from './ExternalLink.html'
|
||||
import Avatar from './Status/Avatar.html'
|
||||
import { store } from '../_store/store'
|
||||
|
||||
export default {
|
||||
computed: {
|
||||
headerIsMissing: (profile) => profile.header.endsWith('missing.png')
|
||||
},
|
||||
store: () => store,
|
||||
components: {
|
||||
IconButton,
|
||||
ExternalLink
|
||||
ExternalLink,
|
||||
Avatar
|
||||
}
|
||||
}
|
||||
</script>
|
38
routes/_components/NonAutoplayImg.html
Normal file
38
routes/_components/NonAutoplayImg.html
Normal file
|
@ -0,0 +1,38 @@
|
|||
{{#if staticSrc === src}}
|
||||
<img class="{{className || ''}}"
|
||||
aria-hidden="{{ariaHidden}}"
|
||||
alt="{{alt}}"
|
||||
src="{{src}}"
|
||||
on:imgLoadError />
|
||||
{{else}}
|
||||
<img class="{{className || ''}} non-autoplay-zoom-in"
|
||||
aria-hidden="{{ariaHidden}}"
|
||||
alt="{{alt}}"
|
||||
src="{{staticSrc}}"
|
||||
on:imgLoadError
|
||||
on:mouseover="onMouseOver(event)"
|
||||
ref:node />
|
||||
{{/if}}
|
||||
<style>
|
||||
.non-autoplay-zoom-in {
|
||||
cursor: zoom-in;
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
import { imgLoadError, mouseover } from '../_utils/events'
|
||||
export default {
|
||||
methods: {
|
||||
onMouseOver(mouseOver) {
|
||||
if (mouseOver) {
|
||||
this.refs.node.src = this.get('src')
|
||||
} else {
|
||||
this.refs.node.src = this.get('staticSrc')
|
||||
}
|
||||
}
|
||||
},
|
||||
events: {
|
||||
imgLoadError,
|
||||
mouseover
|
||||
}
|
||||
}
|
||||
</script>
|
|
@ -1,16 +1,33 @@
|
|||
{{#if error}}
|
||||
<svg class="{{className}} avatar" aria-hidden="true">
|
||||
<svg class="{{className}} avatar size-{{size}}" aria-hidden="true">
|
||||
<use xlink:href="#fa-user" />
|
||||
</svg>
|
||||
{{else}}
|
||||
<img class="{{className}} avatar" aria-hidden="true" alt=""
|
||||
{{elseif $autoplayGifs}}
|
||||
<img class="{{className}} avatar size-{{size}}" aria-hidden="true" alt=""
|
||||
src="{{account.avatar}}" on:imgLoadError="set({error: true})" />
|
||||
{{else}}
|
||||
<NonAutoplayImg className="{{className}} avatar size-{{size}}" ariaHidden="true" alt=""
|
||||
src="{{account.avatar}}" staticSrc="{{account.avatar_static}}" on:imgLoadError="set({error: true})" />
|
||||
{{/if}}
|
||||
<style>
|
||||
.avatar {
|
||||
:global(.avatar) {
|
||||
border-radius: 4px;
|
||||
}
|
||||
:global(.avatar.size-small) {
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
:global(.avatar.size-big) {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
}
|
||||
|
||||
@media (max-width: 767px) {
|
||||
:global(.avatar.size-big) {
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
}
|
||||
}
|
||||
|
||||
svg.avatar {
|
||||
|
@ -19,10 +36,16 @@
|
|||
</style>
|
||||
<script>
|
||||
import { imgLoadError } from '../../_utils/events'
|
||||
import { store } from '../../_store/store'
|
||||
import NonAutoplayImg from '../NonAutoplayImg.html'
|
||||
|
||||
export default {
|
||||
events: {
|
||||
imgLoadError
|
||||
},
|
||||
store: () => store,
|
||||
components: {
|
||||
NonAutoplayImg
|
||||
}
|
||||
}
|
||||
</script>
|
|
@ -30,7 +30,7 @@
|
|||
</a>
|
||||
{{/if}}
|
||||
</div>
|
||||
<Avatar account={{originalAccount}} className="status-sidebar"/>
|
||||
<Avatar account={{originalAccount}} className="status-sidebar" size="small" />
|
||||
{{#if originalStatus.spoiler_text}}
|
||||
<div class="status-spoiler">{{originalStatus.spoiler_text}}</div>
|
||||
{{/if}}
|
||||
|
|
|
@ -10,7 +10,8 @@ const KEYS_TO_STORE_IN_LOCAL_STORAGE = new Set([
|
|||
"instanceNameInSearch",
|
||||
"instanceThemes",
|
||||
"loggedInInstances",
|
||||
"loggedInInstancesInOrder"
|
||||
"loggedInInstancesInOrder",
|
||||
"autoplayGifs"
|
||||
])
|
||||
|
||||
class PinaforeStore extends LocalStorageStore {
|
||||
|
@ -24,7 +25,8 @@ const store = new PinaforeStore({
|
|||
currentInstance: null,
|
||||
loggedInInstances: {},
|
||||
loggedInInstancesInOrder: [],
|
||||
instanceThemes: {}
|
||||
instanceThemes: {},
|
||||
autoplayGifs: false
|
||||
})
|
||||
|
||||
mixins(PinaforeStore)
|
||||
|
|
|
@ -16,4 +16,21 @@ export function imgLoad (node, callback) {
|
|||
node.removeEventListener('load', callback)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function mouseover(node, callback) {
|
||||
function onMouseEnter() {
|
||||
callback(true)
|
||||
}
|
||||
function onMouseLeave() {
|
||||
callback(false)
|
||||
}
|
||||
node.addEventListener('mouseenter', onMouseEnter)
|
||||
node.addEventListener('mouseleave', onMouseLeave)
|
||||
return {
|
||||
teardown () {
|
||||
node.removeEventListener('mouseenter', onMouseEnter)
|
||||
node.removeEventListener('mouseleave', onMouseLeave)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -43,6 +43,7 @@
|
|||
const NAV_ITEMS = {
|
||||
'settings': 'Settings',
|
||||
'settings/about': 'About Pinafore',
|
||||
'settings/general': 'General',
|
||||
'settings/instances': 'Instances',
|
||||
'settings/instances/add': 'Add an instance',
|
||||
}
|
||||
|
|
44
routes/settings/general.html
Normal file
44
routes/settings/general.html
Normal file
|
@ -0,0 +1,44 @@
|
|||
<:Head>
|
||||
<title>General Settings</title>
|
||||
</:Head>
|
||||
|
||||
<Layout page='settings'>
|
||||
<SettingsLayout page='settings/general' label="General">
|
||||
<h1>General Settings</h1>
|
||||
|
||||
<h2>UI</h2>
|
||||
<form class="ui-settings" aria-label="UI settings">
|
||||
<div class="setting-group">
|
||||
<input type="checkbox" id="choice-autoplay-gif"
|
||||
bind:checked="$autoplayGifs" on:change="store.save()">
|
||||
<label for="choice-autoplay-gif">Autoplay GIFs</label>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
</SettingsLayout>
|
||||
</Layout>
|
||||
|
||||
<style>
|
||||
.ui-settings {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
background: var(--form-bg);
|
||||
border: 1px solid var(--main-border);
|
||||
border-radius: 4px;
|
||||
padding: 20px;
|
||||
line-height: 2em;
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
import Layout from '../_components/Layout.html';
|
||||
import SettingsLayout from './_components/SettingsLayout.html'
|
||||
import { store } from '../_store/store'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
Layout,
|
||||
SettingsLayout
|
||||
},
|
||||
store: () => store
|
||||
};
|
||||
</script>
|
|
@ -7,6 +7,7 @@
|
|||
<h1>Settings</h1>
|
||||
|
||||
<SettingsList>
|
||||
<SettingsListItem href="/settings/general" label="General"/>
|
||||
<SettingsListItem href="/settings/instances" label="Instances"/>
|
||||
<SettingsListItem href="/settings/about" label="About Pinafore"/>
|
||||
</SettingsList>
|
||||
|
|
Loading…
Reference in a new issue