Make sections a computed so it recomputes less often

This commit is contained in:
Timothy Farrell 2018-01-05 21:13:53 -06:00
parent 25fe9dd71f
commit 72126d4960
2 changed files with 44 additions and 42 deletions

View File

@ -1,4 +1,5 @@
import partition from 'linear-partitioning'; import partition from 'linear-partitioning';
import { prop, computed, container } from 'frptools';
import { import {
defineView as vw, defineView as vw,
@ -12,7 +13,7 @@ import { injectStyle, styled } from '../services/style.js';
import { DEFAULT_TRANSITION, CLICKABLE, IMAGE_MARGIN, CONTENT_MARGIN } from './styles.js'; import { DEFAULT_TRANSITION, CLICKABLE, IMAGE_MARGIN, CONTENT_MARGIN } from './styles.js';
import { Icon } from './components/icon.js'; import { Icon } from './components/icon.js';
import { SectionPhoto } from './sectionPhoto.js'; import { SectionPhoto } from './sectionPhoto.js';
import { extractID } from '../utils/conversion.js'; import { extractID, sum } from '../utils/conversion.js';
const OPTIMAL_IMAGE_HEIGHT = 140; const OPTIMAL_IMAGE_HEIGHT = 140;
const ROW_HEIGHT_CUTOFF_MODIFIER = 2; const ROW_HEIGHT_CUTOFF_MODIFIER = 2;
@ -25,58 +26,57 @@ const aspectRatio = img => img.width / img.height;
export function SectionView(vm, params, key) { export function SectionView(vm, params, key) {
const { title, photos } = params; const { title, photos } = params;
const sectionSelectButtonRef = `secSel${key}`; const sectionSelectButtonRef = `secSel${key}`;
const photoArray = container(photos || [], pArr => pArr.map(extractID).join(','));
const sections = computed(
(pArr, { width: vw }) => {
const availableWidth = vw - CONTENT_MARGIN_WIDTH;
const aspectRatios = pArr.map(aspectRatio);
const totalImageRatio = sum(aspectRatios);
const rowCount = Math.ceil(totalImageRatio * OPTIMAL_IMAGE_HEIGHT / availableWidth);
const rowRatios = partition(aspectRatios, rowCount);
function calculateSections(photos) { let index = 0;
const { width: vw } = availableViewportSize();
const availableWidth = vw - CONTENT_MARGIN_WIDTH;
const totalImageRatio = photos.reduce((acc, img) => acc + aspectRatio(img), 0);
const rowCount = Math.ceil(totalImageRatio * OPTIMAL_IMAGE_HEIGHT / availableWidth);
const rowRatios = partition(photos.map(aspectRatio), rowCount);
let index = 0; const result = rowRatios.map(row => {
const rowTotal = sum(row);
const imageRatio = row[0];
const portion = imageRatio / rowTotal;
let rowHeight = availableWidth * portion / aspectRatio(pArr[index]);
if (rowHeight > OPTIMAL_IMAGE_HEIGHT * ROW_HEIGHT_CUTOFF_MODIFIER) {
rowHeight = OPTIMAL_IMAGE_HEIGHT * ROW_HEIGHT_CUTOFF_MODIFIER;
}
const result = rowRatios.map(row => { const rowResult = row.map((imageRatio, imgIndex) => ({
const rowTotal = row.reduce((acc, r) => acc + r, 0); photo: pArr[imgIndex + index],
const imageRatio = row[0]; width: imageRatio * rowHeight - IMAGE_MARGIN_WIDTH,
const portion = imageRatio / rowTotal; height: rowHeight
let rowHeight = availableWidth * portion / aspectRatio(photos[index]); }));
if (rowHeight > OPTIMAL_IMAGE_HEIGHT * ROW_HEIGHT_CUTOFF_MODIFIER) {
rowHeight = OPTIMAL_IMAGE_HEIGHT * ROW_HEIGHT_CUTOFF_MODIFIER;
}
const rowResult = row.map((imageRatio, imgIndex) => ({ index += row.length;
photo: photos[imgIndex + index], return rowResult;
width: imageRatio * rowHeight - IMAGE_MARGIN_WIDTH, });
height: rowHeight return result;
})); },
[photoArray, availableViewportSize]
);
index += row.length; subscribeToRender(vm, [sections]);
return rowResult;
});
return result;
}
subscribeToRender(vm, [availableViewportSize]);
return function render(vm, params) { return function render(vm, params) {
const { selectedIds, selectMode } = params; const { selectedIds, selectMode } = params;
function photoTemplate({ photo, width, height }) { function photoTemplate({ photo, width, height }) {
return vw( return vw(SectionPhoto, {
SectionPhoto, doc: photo,
{ isSelected: selectedIds.has(photo._id),
doc: photo, selectMode,
isSelected: selectedIds.has(photo._id), width,
selectMode, height
width, });
height
},
photo._hash()
);
} }
function sectionRowTemplate(photos) { function sectionRowTemplate(pArr) {
return sectionRow(photos.map(photoTemplate)); return sectionRow(pArr.map(photoTemplate));
} }
return sectionContainer( return sectionContainer(
@ -105,7 +105,7 @@ export function SectionView(vm, params, key) {
[Icon({ name: 'check_circle', size: 0.25 })] [Icon({ name: 'check_circle', size: 0.25 })]
) )
]), ]),
sectionContent(calculateSections(photos).map(sectionRowTemplate)) sectionContent(sections().map(sectionRowTemplate))
] ]
); );
}; };

View File

@ -47,6 +47,8 @@ export function deepAssign(to, ...rest) {
return to; return to;
} }
export const sum = arr => arr.reduce((acc, i) => acc + i, 0);
export const extractID = pick('_id'); export const extractID = pick('_id');
export const extractREV = pick('_rev'); export const extractREV = pick('_rev');