From ff281dc3e2156e242cf4cca47ca8407d158f936c Mon Sep 17 00:00:00 2001 From: Timothy Farrell Date: Fri, 1 Dec 2017 01:12:23 -0600 Subject: [PATCH] Split photos view to a separate view --- packages/gallery/src/interface/allImages.js | 67 +++++++++++++ .../src/interface/components/appbar.js | 31 +++--- .../interface/components/attachmentImage.js | 2 +- packages/gallery/src/interface/gallery.js | 94 ++++--------------- packages/gallery/src/services/router.js | 14 +-- packages/gallery/src/utils/domvm.js | 7 ++ 6 files changed, 113 insertions(+), 102 deletions(-) create mode 100644 packages/gallery/src/interface/allImages.js diff --git a/packages/gallery/src/interface/allImages.js b/packages/gallery/src/interface/allImages.js new file mode 100644 index 0000000..57068bc --- /dev/null +++ b/packages/gallery/src/interface/allImages.js @@ -0,0 +1,67 @@ +import { prop, computed } from 'frptools'; + +import { subscribeToRender, defineView, defineElement as el } from '../utils/domvm.js'; + +import { ImageType } from '../data/image.js'; +import { pouchDocArrayHash, pouchDocHash } from '../utils/conversion.js'; +import { ThumbnailTemplate } from './thumbnail.js'; +import { injectStyle, styled } from '../services/style.js'; + +export function uploadImages(evt, files) { + Array.from(files || evt.currentTarget.files).forEach(ImageType.upload); + + if (evt.currentTarget) { + evt.currentTarget.value = null; + } +} + +export function AllImagesView(vm, params, key, opts) { + const model = prop({}, pouchDocHash); + const images = prop([], pouchDocArrayHash); + + ImageType.find( + { + ['sizes.thumbnail']: { $exists: true } + }, + true + ).then(la => { + opts.appbar.renderButtons(renderAppBarButtons); + subscribeToRender(vm, [images], [la.subscribe(images)]); + }); + + function renderAppBarButtons() { + return [ + el('button', [el('label', { for: 'uploadButton' }, 'Upload')]), + el('input', { + id: 'uploadButton', + name: 'uploadButton', + type: 'file', + multiple: true, + accept: '.png,.jpg,.jpeg', // no love for gifs yet + onchange: uploadImages, + class: injectStyle({ display: 'none' }) + }) + ]; + } + + function deleteImage(i) { + ImageType.delete(i._id); + } + + function addAlbum() { + const albumName = prompt('Album Name'); + if (albumName && albumName.trim()) { + const a = new AlbumType({ + title: albumName.trim(), + count: 0 + }); + a.save(); + } + } + + return function() { + const album = model(); + + return el('div', images().map(i => ThumbnailTemplate(i, deleteImage, i._hash()))); + }; +} diff --git a/packages/gallery/src/interface/components/appbar.js b/packages/gallery/src/interface/components/appbar.js index 84fda16..be786ee 100644 --- a/packages/gallery/src/interface/components/appbar.js +++ b/packages/gallery/src/interface/components/appbar.js @@ -1,26 +1,33 @@ -import { defineElement as el } from '../../utils/domvm.js'; import { prop, computed, bundle } from 'frptools'; + +import { defineElement as el } from '../../utils/domvm.js'; import { injectStyle, styled } from '../../services/style.js'; export function AppBarView(vm, params, key, opts) { + const title = prop(params.title); + const renderButtons = prop(params.renderButtons || (() => [])); + const hasBackButton = prop(false); + const showDropShadow = prop(false); + if (opts.appbar) { throw new Error('Cannot have more than one AppBar.'); } - const title = prop(params.title); - const renderButtons = prop(params.renderButtons); + opts.appbar = { + title, + renderButtons, + hasBackButton, + showDropShadow + }; return (vm, params) => { const { title } = params; - return header([ - el('div', { style: 'font-size: 20pt' }, title), - headerRight( - { - css: { visibility: /* selectMode */ true ? 'visible' : 'hidden' } - }, - renderButtons()() - ) - ]); + return header( + { + css: { boxShadow: showDropShadow() ? '0px 0px 7px gray' : 'none' } + }, + [el('div', { style: 'font-size: 20pt' }, title), headerRight(renderButtons()())] + ); }; } diff --git a/packages/gallery/src/interface/components/attachmentImage.js b/packages/gallery/src/interface/components/attachmentImage.js index 2fc8d22..e208d7c 100644 --- a/packages/gallery/src/interface/components/attachmentImage.js +++ b/packages/gallery/src/interface/components/attachmentImage.js @@ -24,7 +24,7 @@ export function AttachmentImageView(vm, params) { }); async function loadImageFromBlob() { - const options = ['thumbnail', 'full'].filter(o => sizes().hasOwnProperty(o)); + const options = ['thumbnail', 'preview', 'full'].filter(o => sizes().hasOwnProperty(o)); for (let attempt of options) { try { diff --git a/packages/gallery/src/interface/gallery.js b/packages/gallery/src/interface/gallery.js index fe46c18..4cca059 100644 --- a/packages/gallery/src/interface/gallery.js +++ b/packages/gallery/src/interface/gallery.js @@ -1,75 +1,37 @@ import { prop } from 'frptools'; -import { defineView as vw, defineElement as el } from '../utils/domvm.js'; +import { subscribeToRender, defineView as vw, defineElement as el } from '../utils/domvm.js'; import { ImageType } from '../data/image.js'; import { AlbumType } from '../data/album.js'; import { ThumbnailTemplate } from './thumbnail.js'; -import { AlbumView } from './album.js'; +import { AllImagesView, uploadImages } from './allImages.js'; import { Dropzone } from './components/dropzone.js'; import { Overlay } from './components/overlay.js'; import { AppBarView } from './components/appbar.js'; import { Icon } from './components/icon.js'; -import { router, routeChanged } from '../services/router.js'; -import { injectStyle, styled } from '../services/style.js'; +import { routeChanged } from '../services/router.js'; +import { injectStyle } from '../services/style.js'; export function GalleryView(vm) { - const NAV_OPTIONS = { - images: { - data: ImageType.find( - { - ['sizes.thumbnail']: { $exists: true } - }, - true - ), - title: 'Images' - }, - albums: { - data: AlbumType.find({}, true), - title: 'Albums' - } - }; - let data = null; let laCleanup = null; const context = {}; const title = prop(''); + const hasData = prop(null); - function uploadImages(evt, files) { - Array.from(files || evt.currentTarget.files).forEach(ImageType.upload); + subscribeToRender(vm, [hasData]); - if (evt.currentTarget) { - evt.currentTarget.value = null; - } - } - - function deleteImage(i) { - ImageType.delete(i._id); - } - - function addAlbum() { - const albumName = prompt('Album Name'); - if (albumName && albumName.trim()) { - const a = new AlbumType({ - title: albumName.trim(), - count: 0 + routeChanged.subscribe(function onRouteChange(name, params) { + if (name == 'photos') { + title('Photos'); + ImageType.find({ + ['sizes.thumbnail']: { $exists: true } + }).then(results => { + hasData(results.length > 0); }); - a.save(); + } else { + throw new Error('Should not happen'); } - } - - routeChanged.subscribe(function onRouteChange(router, route) { - if (laCleanup) { - laCleanup(); - } - const o = NAV_OPTIONS[route.name]; - title(o.title); - - return o.data.then(la => { - data = la; - laCleanup = data.subscribe(() => { - vm.redraw(); - }); - }); }); function renderWelcomePane() { @@ -88,28 +50,12 @@ export function GalleryView(vm) { ]; } - function renderAppBarButtons() { - return [ - el('button', [el('label', { for: 'uploadButton' }, 'Upload')]), - el('input', { - id: 'uploadButton', - name: 'uploadButton', - type: 'file', - multiple: true, - accept: '.png,.jpg,.jpeg', // no love for gifs yet - onchange: uploadImages, - class: injectStyle({ display: 'none' }) - }) - ]; - } - function renderMain() { return [ vw( AppBarView, { - title: 'Photos', - renderButtons: renderAppBarButtons + title: 'Photos' }, 'appbar', context @@ -117,17 +63,13 @@ export function GalleryView(vm) { el( 'div', { class: fill }, - data().length - ? data().map(i => { - return ThumbnailTemplate(i, deleteImage, i._hash()); - }) - : [renderWelcomePane()] + hasData() ? [vw(AllImagesView, {}, 'allImages', context)] : [renderWelcomePane()] ) ]; } return function render() { - if (!data || !data.ready()) { + if (hasData() === null) { return Overlay([el('h1', 'Loading...')]); } diff --git a/packages/gallery/src/services/router.js b/packages/gallery/src/services/router.js index 65a4bba..6552d58 100644 --- a/packages/gallery/src/services/router.js +++ b/packages/gallery/src/services/router.js @@ -9,19 +9,7 @@ export const router = Router([ { name: 'home', path: '/', - enter: (r, route) => { - r.goto('images'); - } - }, - { - name: 'images', - path: '/images', - enter: fire - }, - { - name: 'albums', - path: '/albums', - enter: fire + enter: (r, route) => fire('photos', route) }, { id: '404', diff --git a/packages/gallery/src/utils/domvm.js b/packages/gallery/src/utils/domvm.js index 5f8d726..de52c59 100644 --- a/packages/gallery/src/utils/domvm.js +++ b/packages/gallery/src/utils/domvm.js @@ -1,2 +1,9 @@ // export * from 'domvm/dist/dev/domvm.dev.js'; export * from 'domvm/dist/mini/domvm.mini.js'; + +export function subscribeToRender(vm, subscribables, subscriptions) { + const redraw = () => vm.redraw(); + const subList = subscribables.map(s => s.subscribe(redraw)).concat(subscriptions); + + vm.config({ hooks: { willUnmount: () => subList.forEach(s => s()) } }); +}