// Gemeinsame Viewport-Pagination für Upload-Grids (Mainseite, Profilseite). // Der Client schickt cells (Zeilen x Spalten, die ohne Scrollen passen), cols // und den Modus — der Server simuliert grid-auto-flow: dense exakt nach. export function getGridPageParams(q: Record) { const page = Math.max(1, Math.floor(Number(q.page)) || 1) const cells = Math.min(400, Math.max(1, Math.floor(Number(q.cells)) || 48)) const cols = Math.min(12, Math.max(1, Math.floor(Number(q.cols)) || 12)) const uniform = q.mode === 'uniform' return { page, cells, cols, uniform } } // Gleiche Maße wie UploadTile: uniform = 1x1, >=7 Kommentare = 3x3 // (ab sm/cols>=6) bzw. 2x2, >=1 Kommentar = 2x2, sonst 1x1 export function gridTileDims(commentCount: number, uniform: boolean, cols: number): [h: number, w: number] { return uniform ? [1, 1] : commentCount >= 7 ? (cols >= 6 ? [3, 3] : [2, 2]) : commentCount >= 1 ? [2, 2] : [1, 1] } // Simuliert grid-auto-flow: dense — jedes Tile geht in die erste freie // Rechteck-Position (zeilenweise von oben links). Passt es nirgends in die // maxRows-Zeilen, wird es auf die nächste Seite verschoben (Reihenfolge der // übrigen Items bleibt erhalten). Kleinere Tiles danach füllen noch Lücken. export function paginateGrid(items: T[], dims: (item: T) => [h: number, w: number], cells: number, cols: number): T[][] { const maxRows = Math.max(1, Math.floor(cells / cols)) const pack = (input: T[]) => { const occupied: boolean[][] = [] const placed: T[] = [] const deferred: T[] = [] const fits = (r: number, c: number, h: number, w: number) => { if (r + h > maxRows || c + w > cols) return false for (let dr = 0; dr < h; dr++) for (let dc = 0; dc < w; dc++) if (occupied[r + dr]?.[c + dc]) return false return true } for (const item of input) { const [h, w] = dims(item) let done = false for (let r = 0; r + h <= maxRows && !done; r++) { for (let c = 0; c + w <= cols; c++) { if (fits(r, c, h, w)) { for (let dr = 0; dr < h; dr++) { const line = (occupied[r + dr] ??= new Array(cols).fill(false)) for (let dc = 0; dc < w; dc++) line[c + dc] = true } placed.push(item) done = true break } } } if (!done) deferred.push(item) } return { placed, deferred } } const pages: T[][] = [] let rest = items while (rest.length) { const { placed, deferred } = pack(rest) if (!placed.length) { // Sicherheitsnetz: kann bei cols>=1 nie leer sein (1x1 passt immer) pages.push(rest) break } pages.push(placed) rest = deferred } return pages }