Complete(?) AppBar state management

This commit is contained in:
Timothy Farrell 2017-12-16 03:58:42 -06:00
parent d83b397b89
commit 8006e98dbc
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 { 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
});

View File

@ -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

View File

@ -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');