From cfdf84522b1944afba4eed34a58c9d9de62aeb59 Mon Sep 17 00:00:00 2001 From: Timothy Farrell Date: Sat, 16 Dec 2017 03:58:42 -0600 Subject: [PATCH] Complete(?) AppBar state management --- .../src/interface/components/appbar.js | 70 +++++++++++++++---- packages/gallery/src/interface/gallery.js | 11 +-- packages/gallery/src/utils/conversion.js | 2 +- 3 files changed, 60 insertions(+), 23 deletions(-) diff --git a/packages/gallery/src/interface/components/appbar.js b/packages/gallery/src/interface/components/appbar.js index 92ecbff..cc8f15a 100644 --- a/packages/gallery/src/interface/components/appbar.js +++ b/packages/gallery/src/interface/components/appbar.js @@ -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 { 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) { - const title = prop(params.title); - const renderButtons = prop(params.renderButtons || (() => [])); - const hasBackButton = prop(false); + const stateStack = container([], arr => arr.length); 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( t => (t === 0 ? 'none' : `0px ${Math.min(t / 10, 3)}px 3px rgba(0, 0, 0, .2)`), [companionScrollTop] @@ -17,22 +31,49 @@ export function AppBarView(vm, params, key, opts) { 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 = { - title, - renderButtons, - hasBackButton, - companionScrollTop + pushState, + popState, + companionScrollTop, + subscribe: stateChange.subscribe }; - subscribeToRender(vm, [boxShadowStyle, renderButtons]); + subscribeToRender(vm, [boxShadowStyle, renderButtons, hasBackButton, title]); return (vm, params) => { - const { title } = params; + const _buttons = renderButtons() || (() => {}); + return header( { 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' }); +const backButtonContainer = styled({ + marginRight: '1em' +}); + const headerRight = styled({ display: 'flex', alignItems: 'center' }); const titleContainer = styled({ - fontSize: '20pt' + fontSize: '20pt', + flex: 1 }); diff --git a/packages/gallery/src/interface/gallery.js b/packages/gallery/src/interface/gallery.js index f4bf2dd..9274250 100644 --- a/packages/gallery/src/interface/gallery.js +++ b/packages/gallery/src/interface/gallery.js @@ -16,14 +16,12 @@ export function GalleryView(vm) { let data = null; let laCleanup = null; const context = {}; - const title = prop(''); const hasData = prop(null); subscribeToRender(vm, [hasData]); routeChanged.subscribe(function onRouteChange(name, params) { if (name == 'photos') { - title('Photos'); ImageType.find({ ['sizes.thumbnail']: { $exists: true } }).then(results => { @@ -56,14 +54,7 @@ export function GalleryView(vm) { function renderMain() { return [ - vw( - AppBarView, - { - title: 'Photos' - }, - 'appbar', - context - ), + vw(AppBarView, {}, 'appbar', context), content( { onscroll: handleContentScroll diff --git a/packages/gallery/src/utils/conversion.js b/packages/gallery/src/utils/conversion.js index 4a5f65c..98fd776 100644 --- a/packages/gallery/src/utils/conversion.js +++ b/packages/gallery/src/utils/conversion.js @@ -45,7 +45,7 @@ export function deepAssign(to, ...rest) { return to; } -export const pick = id => doc => doc[id]; +export const pick = id => doc => doc && doc[id]; export const extractID = pick('_id'); export const extractREV = pick('_rev');