Initial FocusView

This commit is contained in:
Timothy Farrell 2017-12-28 22:14:46 -06:00
parent 83b458bb41
commit c0c0898d8c
6 changed files with 173 additions and 35 deletions

View File

@ -2,6 +2,7 @@ import { prop, computed, container } from 'frptools';
import { Icon } from './icon.js';
import { defineElement as el, subscribeToRender } from '../../utils/domvm.js';
import { pick } from '../../utils/conversion.js';
import { injectStyle, styled } from '../../services/style.js';
import { CLICKABLE } from '../styles.js';
@ -13,8 +14,9 @@ export function AppBarView(vm, params, key, opts) {
const companionScrollTop = prop(0);
const currentState = computed(stack => stack[0] || {}, [stateStack]);
const title = computed(state => state.title || '', [currentState]);
const renderButtons = computed(state => state.buttons, [currentState]);
const title = computed(pick('title', ''), [currentState]);
const renderButtons = computed(pick('buttons'), [currentState]);
const stateStyle = computed(pick('style', {}), [currentState]);
const backButton = computed(
(state, stack) =>
stack.length > 1 ? (state.backButton !== undefined ? state.backButton : 'arrow_left') : null,
@ -27,6 +29,13 @@ export function AppBarView(vm, params, key, opts) {
[companionScrollTop]
);
const containerStyle = computed(
(boxShadow, style) => ({
css: Object.assign({ boxShadow }, style)
}),
[boxShadowStyle, stateStyle]
);
if (opts.appbar) {
throw new Error('Cannot have more than one AppBar.');
}
@ -48,16 +57,12 @@ export function AppBarView(vm, params, key, opts) {
subscribe: stateChange.subscribe
};
subscribeToRender(vm, [boxShadowStyle, renderButtons, backButton, title]);
subscribeToRender(vm, [containerStyle, renderButtons, backButton, title]);
return (vm, params) => {
const _buttons = renderButtons() || (() => {});
return header(
{
css: { boxShadow: boxShadowStyle() }
},
[
return appBarContainer(containerStyle(), [
backButton() !== null
? backButtonContainer(
{
@ -73,17 +78,17 @@ export function AppBarView(vm, params, key, opts) {
: null,
titleContainer(title()),
headerRight(_buttons())
]
);
]);
};
}
const header = styled({
const appBarContainer = styled({
justifyContent: 'space-between',
padding: '1em',
zIndex: 1000,
display: 'flex',
alignItems: 'center'
alignItems: 'center',
width: '100%'
});
const backButtonContainer = styled(

View File

@ -0,0 +1,132 @@
import { prop, computed, container } from 'frptools';
import {
subscribeToRender,
defineView,
nodeParentWithType,
defineElement as el
} from '../utils/domvm.js';
import { ImageType } from '../data/image.js';
import { pouchDocHash, pick } from '../utils/conversion.js';
import { AttachmentImageView } from './components/attachmentImage.js';
import { Overlay } from './components/overlay.js';
import { Icon } from './components/icon.js';
import { styled, injectStyle } from '../services/style.js';
import { error } from '../services/console.js';
import { CLICKABLE } from './styles.js';
export function FocusView(vm, params, key, { appbar }) {
const id = params.vars.id;
const { body } = document;
const windowSize = prop({}, o => (o ? `${o.width}x${o.height}` : ''));
const extractWindowSize = () =>
windowSize({ width: window.innerWidth, height: window.innerHeight });
const doc = container({}, pouchDocHash);
const imageStyle = computed(
({ width: iw, height: ih }, { width: vw, height: vh }) => {
const imageRatio = iw / ih;
const windowRatio = vw / vh;
if (windowRatio > imageRatio) {
return {
height: vw / windowRatio,
width: vw / windowRatio * imageRatio
};
} else {
return {
height: vh * windowRatio / imageRatio,
width: vh * windowRatio
};
}
},
[doc, windowSize]
);
async function goBack() {
history.go(-1);
}
function navBack() {
// appbar.popState();
goBack();
}
async function clickTrash() {
await ImageType.delete(id);
navBack();
}
function renderAppBarButtons() {
return [
trashButtonContainer(
{
onclick: clickTrash
},
[
Icon({
name: 'trash',
size: 0.75
})
]
)
];
}
// Prime our window size
extractWindowSize();
window.addEventListener('resize', extractWindowSize);
// Set the appbar title.
appbar.pushState({ title: '', buttons: renderAppBarButtons, style: { position: 'fixed' } });
// Look for our image and set it.
ImageType.find(id)
.then(d => {
doc.src = d.sizes.full || d.sizes.preview || d.sizes.thumbnail;
doc.width = d.width;
doc.height = d.height;
doc._id = d._id;
})
.catch(error);
// Subscribe to our changables.
subscribeToRender(
vm,
[doc, imageStyle],
[appbar.subscribe(goBack), () => window.removeEventListener('resize', extractWindowSize)]
);
return function() {
if (!doc._id) {
return Overlay('Loading...');
}
return focusContainer([
AttachmentImageView({
src: doc._id ? doc.src : null,
style: imageStyle()
})
]);
};
}
const trashButtonContainer = styled(
{
marginRight: '1em'
},
CLICKABLE
);
const focusContainer = styled({
display: 'flex',
flex: 1,
justifyContent: 'center',
alignItems: 'center',
overflow: 'hidden'
});
const WIDE = injectStyle({ width: '100%' });
const TALL = injectStyle({ height: '100%' });

View File

@ -12,6 +12,7 @@ import { ImageType } from '../data/image.js';
import { AlbumType } from '../data/album.js';
import { ThumbnailTemplate } from './components/thumbnail.js';
import { AllImagesView, uploadImages } from './allImages.js';
import { FocusView } from './focus.js';
import { Dropzone } from './components/dropzone.js';
import { Overlay } from './components/overlay.js';
import { AppBarView } from './components/appbar.js';
@ -28,6 +29,7 @@ export function GalleryView(vm) {
routeChanged.subscribe(function onRouteChange(name, params) {
routeName(name);
routeParams(params);
vm.redraw();
});
function handleContentScroll(evt) {
@ -41,8 +43,8 @@ export function GalleryView(vm) {
{ onscroll: handleContentScroll },
renderSwitch(
{
photos: [AllImagesView, {}, 'allImages', context]
// focus: renderFocus
photos: [AllImagesView, {}, 'allImages', context],
focus: [FocusView, routeParams(), 'focus', context]
},
routeName()
)
@ -88,7 +90,6 @@ const fill = injectStyle(FILL_STYLE);
const content = styled(
{
overflow: 'scroll',
['-webkit-transform']: 'translate3d(0,0,0);' // http://blog.getpostman.com/2015/01/23/ui-repaint-issue-on-chrome/
},
FILL_STYLE

View File

@ -15,9 +15,9 @@ export const router = Router([
name: 'focus',
path: '/focus/:id',
vars: {
id: /^[_A-Za-z0-9]+$/
id: /[_A-Za-z0-9]+/
},
enter: (r, route) => fire('image', route)
enter: (r, route) => fire('focus', route)
},
{
id: '404',

View File

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

View File

@ -6,7 +6,7 @@ import { deepAssign } from './conversion.js';
import { error } from '../services/console.js';
export function subscribeToRender(vm, subscribables, subscriptions) {
const redraw = (...args) => vm.redraw();
const redraw = () => vm.redraw();
const subList = subscribables.map(s => s.subscribe(redraw));
vm.config({
@ -48,5 +48,5 @@ export function nodeParentWithType(node, type) {
export function renderSwitch(renderMap, switchValue) {
const params = renderMap[switchValue];
return params ? defineView.apply(null, params) : 'NOT FOUND';
return params ? defineView.apply(null, params) : `VIEW ${switchValue} NOT FOUND`;
}