Complete(?) AppBar state management

This commit is contained in:
Timothy Farrell 2017-12-16 03:58:42 -06:00
parent 779d08ae84
commit cfdf84522b
3 changed files with 60 additions and 23 deletions

View File

@ -1,13 +1,27 @@
import { prop, computed, bundle } from 'frptools'; import { prop, computed, container } from 'frptools';
import { Icon } from './icon.js';
import { defineElement as el, subscribeToRender } from '../../utils/domvm.js'; import { defineElement as el, subscribeToRender } from '../../utils/domvm.js';
import { injectStyle, styled } from '../../services/style.js'; import { injectStyle, styled } from '../../services/style.js';
import { pick } from '../../utils/conversion.js';
let seq = 0;
const getSeq = pick('_seq');
export function AppBarView(vm, params, key, opts) { export function AppBarView(vm, params, key, opts) {
const title = prop(params.title); const stateStack = container([], arr => arr.length);
const renderButtons = prop(params.renderButtons || (() => []));
const hasBackButton = prop(false);
const companionScrollTop = prop(0); const companionScrollTop = prop(0);
const previousState = prop({ _seq: seq }, getSeq);
const currentState = computed(stack => stack[0] || {}, [stateStack]);
const title = computed(state => state.title || '', [currentState]);
const renderButtons = computed(state => state.buttons, [currentState]);
const hasBackButton = computed(stack => stack.length > 1, [stateStack]);
const stateChange = computed((c, p) => ({ newState: c, oldState: p }), [
currentState,
previousState
]);
const boxShadowStyle = computed( const boxShadowStyle = computed(
t => (t === 0 ? 'none' : `0px ${Math.min(t / 10, 3)}px 3px rgba(0, 0, 0, .2)`), t => (t === 0 ? 'none' : `0px ${Math.min(t / 10, 3)}px 3px rgba(0, 0, 0, .2)`),
[companionScrollTop] [companionScrollTop]
@ -17,22 +31,49 @@ export function AppBarView(vm, params, key, opts) {
throw new Error('Cannot have more than one AppBar.'); throw new Error('Cannot have more than one AppBar.');
} }
function pushState(newState) {
const oldState = currentState() || {};
stateStack.unshift(Object.assign({ _seq: seq++ }, newState));
previousState(oldState);
}
function popState() {
const oldState = currentState();
stateStack.shift();
previousState(oldState);
}
opts.appbar = { opts.appbar = {
title, pushState,
renderButtons, popState,
hasBackButton, companionScrollTop,
companionScrollTop subscribe: stateChange.subscribe
}; };
subscribeToRender(vm, [boxShadowStyle, renderButtons]); subscribeToRender(vm, [boxShadowStyle, renderButtons, hasBackButton, title]);
return (vm, params) => { return (vm, params) => {
const { title } = params; const _buttons = renderButtons() || (() => {});
return header( return header(
{ {
css: { boxShadow: boxShadowStyle() } css: { boxShadow: boxShadowStyle() }
}, },
[titleContainer(title), headerRight(renderButtons()())] [
hasBackButton()
? backButtonContainer([
Icon({
name: 'arrow_left',
size: 0.75,
attrs: {
onclick: popState
}
})
])
: null,
titleContainer(title()),
headerRight(_buttons())
]
); );
}; };
} }
@ -45,11 +86,16 @@ const header = styled({
alignItems: 'center' alignItems: 'center'
}); });
const backButtonContainer = styled({
marginRight: '1em'
});
const headerRight = styled({ const headerRight = styled({
display: 'flex', display: 'flex',
alignItems: 'center' alignItems: 'center'
}); });
const titleContainer = styled({ const titleContainer = styled({
fontSize: '20pt' fontSize: '20pt',
flex: 1
}); });

View File

@ -16,14 +16,12 @@ export function GalleryView(vm) {
let data = null; let data = null;
let laCleanup = null; let laCleanup = null;
const context = {}; const context = {};
const title = prop('');
const hasData = prop(null); const hasData = prop(null);
subscribeToRender(vm, [hasData]); subscribeToRender(vm, [hasData]);
routeChanged.subscribe(function onRouteChange(name, params) { routeChanged.subscribe(function onRouteChange(name, params) {
if (name == 'photos') { if (name == 'photos') {
title('Photos');
ImageType.find({ ImageType.find({
['sizes.thumbnail']: { $exists: true } ['sizes.thumbnail']: { $exists: true }
}).then(results => { }).then(results => {
@ -56,14 +54,7 @@ export function GalleryView(vm) {
function renderMain() { function renderMain() {
return [ return [
vw( vw(AppBarView, {}, 'appbar', context),
AppBarView,
{
title: 'Photos'
},
'appbar',
context
),
content( content(
{ {
onscroll: handleContentScroll onscroll: handleContentScroll

View File

@ -45,7 +45,7 @@ export function deepAssign(to, ...rest) {
return to; return to;
} }
export const pick = id => doc => doc[id]; export const pick = id => doc => doc && doc[id];
export const extractID = pick('_id'); export const extractID = pick('_id');
export const extractREV = pick('_rev'); export const extractREV = pick('_rev');