Make sections a computed so it recomputes less often
This commit is contained in:
parent
c918a26282
commit
a53c984acf
@ -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))
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -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');
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user