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 c918a26282
commit a53c984acf
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,27 +26,28 @@ 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(','));
function calculateSections(photos) { const sections = computed(
const { width: vw } = availableViewportSize(); (pArr, { width: vw }) => {
const availableWidth = vw - CONTENT_MARGIN_WIDTH; const availableWidth = vw - CONTENT_MARGIN_WIDTH;
const totalImageRatio = photos.reduce((acc, img) => acc + aspectRatio(img), 0); const aspectRatios = pArr.map(aspectRatio);
const totalImageRatio = sum(aspectRatios);
const rowCount = Math.ceil(totalImageRatio * OPTIMAL_IMAGE_HEIGHT / availableWidth); const rowCount = Math.ceil(totalImageRatio * OPTIMAL_IMAGE_HEIGHT / availableWidth);
const rowRatios = partition(photos.map(aspectRatio), rowCount); const rowRatios = partition(aspectRatios, rowCount);
let index = 0; let index = 0;
const result = rowRatios.map(row => { const result = rowRatios.map(row => {
const rowTotal = row.reduce((acc, r) => acc + r, 0); const rowTotal = sum(row);
const imageRatio = row[0]; const imageRatio = row[0];
const portion = imageRatio / rowTotal; const portion = imageRatio / rowTotal;
let rowHeight = availableWidth * portion / aspectRatio(photos[index]); let rowHeight = availableWidth * portion / aspectRatio(pArr[index]);
if (rowHeight > OPTIMAL_IMAGE_HEIGHT * ROW_HEIGHT_CUTOFF_MODIFIER) { if (rowHeight > OPTIMAL_IMAGE_HEIGHT * ROW_HEIGHT_CUTOFF_MODIFIER) {
rowHeight = OPTIMAL_IMAGE_HEIGHT * ROW_HEIGHT_CUTOFF_MODIFIER; rowHeight = OPTIMAL_IMAGE_HEIGHT * ROW_HEIGHT_CUTOFF_MODIFIER;
} }
const rowResult = row.map((imageRatio, imgIndex) => ({ const rowResult = row.map((imageRatio, imgIndex) => ({
photo: photos[imgIndex + index], photo: pArr[imgIndex + index],
width: imageRatio * rowHeight - IMAGE_MARGIN_WIDTH, width: imageRatio * rowHeight - IMAGE_MARGIN_WIDTH,
height: rowHeight height: rowHeight
})); }));
@ -54,29 +56,27 @@ export function SectionView(vm, params, key) {
return rowResult; return rowResult;
}); });
return result; return result;
} },
[photoArray, availableViewportSize]
);
subscribeToRender(vm, [availableViewportSize]); subscribeToRender(vm, [sections]);
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, doc: photo,
isSelected: selectedIds.has(photo._id), isSelected: selectedIds.has(photo._id),
selectMode, selectMode,
width, width,
height 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');