add favorite/reblog animations

This commit is contained in:
Nolan Lawson 2018-03-21 09:38:20 -07:00
parent b487240343
commit 72e7e18e0b
7 changed files with 63 additions and 6 deletions

5
package-lock.json generated
View file

@ -10471,6 +10471,11 @@
} }
} }
}, },
"web-animations-js": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/web-animations-js/-/web-animations-js-2.3.1.tgz",
"integrity": "sha1-Om2bwVGWN3qQ+OKAP6UmIWWwRRA="
},
"webauth": { "webauth": {
"version": "1.1.0", "version": "1.1.0",
"resolved": "https://registry.npmjs.org/webauth/-/webauth-1.1.0.tgz", "resolved": "https://registry.npmjs.org/webauth/-/webauth-1.1.0.tgz",

View file

@ -66,6 +66,7 @@
"testcafe": "^0.19.0", "testcafe": "^0.19.0",
"timeago.js": "^3.0.2", "timeago.js": "^3.0.2",
"tiny-queue": "^0.2.1", "tiny-queue": "^0.2.1",
"web-animations-js": "^2.3.1",
"webpack": "^4.1.0", "webpack": "^4.1.0",
"webpack-bundle-analyzer": "^2.11.1", "webpack-bundle-analyzer": "^2.11.1",
"workerize-loader": "^1.0.1", "workerize-loader": "^1.0.1",
@ -100,7 +101,8 @@
"FormData", "FormData",
"atob", "atob",
"btoa", "btoa",
"Blob" "Blob",
"Element"
], ],
"ignore": [ "ignore": [
"dist", "dist",

View file

@ -6,7 +6,7 @@
:disabled :disabled
delegate-key="{{delegateKey}}" delegate-key="{{delegateKey}}"
focus-key="{{focusKey || ''}}" > focus-key="{{focusKey || ''}}" >
<svg class="icon-button-svg"> <svg class="icon-button-svg" ref:svg>
<use xlink:href="{{href}}" /> <use xlink:href="{{href}}" />
</svg> </svg>
</button> </button>
@ -18,7 +18,7 @@
focus-key="{{focusKey || ''}}" focus-key="{{focusKey || ''}}"
:disabled :disabled
on:click > on:click >
<svg class="icon-button-svg"> <svg class="icon-button-svg" ref:svg>
<use xlink:href="{{href}}" /> <use xlink:href="{{href}}" />
</svg> </svg>
</button> </button>
@ -50,7 +50,7 @@
} }
.icon-button.pressed .icon-button-svg { .icon-button.pressed .icon-button-svg {
fill: var(--action-button-fill-color-pressed) fill: var(--action-button-fill-color-pressed);
} }
.icon-button.pressed:hover .icon-button-svg { .icon-button.pressed:hover .icon-button-svg {
@ -66,6 +66,16 @@
import { classname } from '../_utils/classname' import { classname } from '../_utils/classname'
export default { export default {
oncreate() {
this.observe('animation', animation => {
if (!animation) {
return
}
let svg = this.refs.svg
let animations = animation.map(({properties, options}) => svg.animate(properties, options))
animations.forEach(anim => anim.play())
})
},
computed: { computed: {
computedClass: (pressable, pressed, big, className) => { computedClass: (pressable, pressed, big, className) => {
return classname( return classname(

View file

@ -13,6 +13,7 @@
disabled="{{reblogDisabled}}" disabled="{{reblogDisabled}}"
href="{{reblogIcon}}" href="{{reblogIcon}}"
delegateKey="{{reblogKey}}" delegateKey="{{reblogKey}}"
animation="{{animateReblog && reblogAnimation}}"
/> />
<IconButton <IconButton
label="Favorite" label="Favorite"
@ -20,6 +21,7 @@
pressed="{{favorited}}" pressed="{{favorited}}"
href="#fa-star" href="#fa-star"
delegateKey="{{favoriteKey}}" delegateKey="{{favoriteKey}}"
animation="{{animateFavorite && favoriteAnimation}}"
/> />
<IconButton <IconButton
label="Show more options" label="Show more options"
@ -46,6 +48,7 @@
import { goto } from 'sapper/runtime.js' import { goto } from 'sapper/runtime.js'
import { importDialogs } from '../../_utils/asyncModules' import { importDialogs } from '../../_utils/asyncModules'
import { updateProfileAndRelationship } from '../../_actions/accounts' import { updateProfileAndRelationship } from '../../_actions/accounts'
import { FAVORITE_ANIMATION, REBLOG_ANIMATION } from '../../_static/animations'
export default { export default {
oncreate() { oncreate() {
@ -69,11 +72,13 @@
let originalStatusId = this.get('originalStatusId') let originalStatusId = this.get('originalStatusId')
let favorited = this.get('favorited') let favorited = this.get('favorited')
/* no await */ setFavorited(originalStatusId, !favorited) /* no await */ setFavorited(originalStatusId, !favorited)
this.set({animateFavorite: !favorited})
}, },
onReblogClick() { onReblogClick() {
let originalStatusId = this.get('originalStatusId') let originalStatusId = this.get('originalStatusId')
let reblogged = this.get('reblogged') let reblogged = this.get('reblogged')
/* no await */ setReblogged(originalStatusId, !reblogged) /* no await */ setReblogged(originalStatusId, !reblogged)
this.set({animateReblog: !reblogged})
}, },
onReplyClick() { onReplyClick() {
let originalStatusId = this.get('originalStatusId') let originalStatusId = this.get('originalStatusId')
@ -88,6 +93,10 @@
dialogs.showStatusOptionsDialog(originalStatusId) dialogs.showStatusOptionsDialog(originalStatusId)
} }
}, },
data: () => ({
favoriteAnimation: FAVORITE_ANIMATION,
reblogAnimation: REBLOG_ANIMATION
}),
computed: { computed: {
reblogLabel: (visibility) => { reblogLabel: (visibility) => {
switch (visibility) { switch (visibility) {

View file

@ -0,0 +1,25 @@
export const FAVORITE_ANIMATION = [
{
properties: [
{transform: 'scale(1)'},
{transform: 'scale(2)'},
{transform: 'scale(1)'}
],
options: {
duration: 400,
easing: 'ease-in-out'
}
},
{
properties: [
{fill: 'var(--action-button-fill-color)'},
{fill: 'var(--action-button-fill-color-pressed)'}
],
options: {
duration: 400,
easing: 'linear'
}
}
]
export const REBLOG_ANIMATION = FAVORITE_ANIMATION

View file

@ -14,6 +14,10 @@ export const importIndexedDBGetAllShim = () => import(
/* webpackChunkName: 'indexeddb-getall-shim' */ 'indexeddb-getall-shim' /* webpackChunkName: 'indexeddb-getall-shim' */ 'indexeddb-getall-shim'
) )
export const importWebAnimationPolyfill = () => import(
/* webpackChunkName: 'web-animations-js' */ 'web-animations-js'
)
export const importWebSocketClient = () => import( export const importWebSocketClient = () => import(
/* webpackChunkName: '@gamestdio/websocket' */ '@gamestdio/websocket' /* webpackChunkName: '@gamestdio/websocket' */ '@gamestdio/websocket'
).then(mod => mod.default) ).then(mod => mod.default)

View file

@ -1,13 +1,15 @@
import { import {
importIntersectionObserver, importIntersectionObserver,
importRequestIdleCallback, importRequestIdleCallback,
importIndexedDBGetAllShim importIndexedDBGetAllShim,
importWebAnimationPolyfill
} from './asyncModules' } from './asyncModules'
export function loadPolyfills () { export function loadPolyfills () {
return Promise.all([ return Promise.all([
typeof IntersectionObserver === 'undefined' && importIntersectionObserver(), typeof IntersectionObserver === 'undefined' && importIntersectionObserver(),
typeof requestIdleCallback === 'undefined' && importRequestIdleCallback(), typeof requestIdleCallback === 'undefined' && importRequestIdleCallback(),
!IDBObjectStore.prototype.getAll && importIndexedDBGetAllShim() !IDBObjectStore.prototype.getAll && importIndexedDBGetAllShim(),
!Element.prototype.animate && importWebAnimationPolyfill()
]) ])
} }