Skip to content

Commit

Permalink
Improve logic for determining which are of the board to show for a ne…
Browse files Browse the repository at this point in the history
…w user
  • Loading branch information
raimohanska committed Feb 3, 2024
1 parent 6239384 commit 7cb61ea
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 29 deletions.
33 changes: 4 additions & 29 deletions frontend/src/board/board-scroll-and-zoom.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { Board } from "../../../common/src/domain"
import * as G from "../../../common/src/geometry"
import { BoardCoordinateHelper } from "./board-coordinates"
import { ToolController } from "./tool-selection"
import { boardContentArea } from "./boardContentArea"

export type BoardZoom = { zoom: number; quickZoom: number }
export type ZoomAdjustMode = "preserveCursor" | "preserveCenter"
Expand Down Expand Up @@ -42,14 +43,15 @@ export function boardScrollAndZoomHandler(
(id) => "scrollAndZoom." + id,
)

L.view(scrollElement, boardElement, localStorageKey, (el, be, key) => ({ el, be, key }))
const boardIsNonEmpty = board.pipe(L.map((b) => Object.keys(b.items).length > 0))
L.view(scrollElement, boardElement, localStorageKey, boardIsNonEmpty, (el, be, key, neb) => ({ el, be, key, neb }))
.pipe(L.applyScope(componentScope()))
.forEach(({ el, be, key }) => {
if (el && be) {
const storedScrollAndZoom = localStorage[key]
setTimeout(() => {
if (storedScrollAndZoom) {
//console.log("Init position for board", key)
console.log("Restoring scroll and zoom for board from localStorage")
const parsed = JSON.parse(storedScrollAndZoom)
el.scrollTop = parsed.y
el.scrollLeft = parsed.x
Expand All @@ -61,33 +63,6 @@ export function boardScrollAndZoomHandler(
}
})

function boardContentArea(b: Board) {
const width = b.width / 10
const height = b.height / 10
let left = b.width / 2 - width / 2
let top = b.height / 2 - height / 2
let right = left + width
let bottom = top + height

Object.values(b.items).forEach((item) => {
const { x, y, width, height } = item
left = Math.min(left, x)
top = Math.min(top, y)
right = Math.max(right, x + width)
bottom = Math.max(bottom, y + height)
})

const marginTop = height * 0.1
const marginLeft = height * 0.1

return {
x: left - marginLeft,
y: top - marginTop,
width: right - left + 2 * marginLeft,
height: bottom - top + marginTop,
}
}

scrollAndZoom.pipe(L.changes, L.debounce(100), L.applyScope(componentScope())).forEach((s) => {
//console.log("Store position for board", localStorageKey.get())
localStorage[localStorageKey.get()] = JSON.stringify({ ...s, zoom: s.zoom.zoom * s.zoom.quickZoom })
Expand Down
74 changes: 74 additions & 0 deletions frontend/src/board/boardContentArea.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import _ from "lodash"
import { Board } from "../../../common/src/domain"
import { Rect } from "../../../common/src/geometry"

function combineRects(r1: Rect, r2: Rect): Rect {
const left = Math.min(r1.x, r2.x)
const top = Math.min(r1.y, r2.y)
const right = Math.max(r1.x + r1.width, r2.x + r2.width)
const bottom = Math.max(r1.y + r1.height, r2.y + r2.height)
return { x: left, y: top, width: right - left, height: bottom - top }
}

function itemToRect(item: Rect): Rect {
return { x: item.x, y: item.y, width: item.width, height: item.height }
}

function addMargin(rect: Rect, margin: number): Rect {
return {
x: rect.x - margin,
y: rect.y - margin,
width: rect.width + 2 * margin,
height: rect.height + 2 * margin,
}
}

function setMinimumSizeKeepingCenter(rect: Rect, minimumSize: { width: number; height: number }) {
const center = { x: rect.x + rect.width / 2, y: rect.y + rect.height / 2 }
const width = Math.max(rect.width, minimumSize.width)
const height = Math.max(rect.height, minimumSize.height)
return {
x: center.x - width / 2,
y: center.y - height / 2,
width,
height,
}
}

function clampIntoKeepingSize(rect: Rect, bounds: Rect) {
const minLeft = bounds.x
const minTop = bounds.y
const maxLeft = bounds.x + bounds.width - rect.width
const maxTop = bounds.y + bounds.height - rect.height
const x = _.clamp(rect.x, minLeft, maxLeft)
const y = _.clamp(rect.y, minTop, maxTop)
return { x, y, width: rect.width, height: rect.height }
}

export function boardContentArea(b: Board) {
// Default / minimum size for initial view
const width = b.width / 10
const height = b.height / 10

const items = Object.values(b.items)

if (!items.length) {
console.log("No items in board, centering view")
return { x: b.width / 2 - width / 2, y: b.height / 2 - height / 2, width, height }
}

let itemsArea = itemToRect(items[0])
items.forEach((item) => {
itemsArea = combineRects(itemsArea, itemToRect(item))
})

// Now we have the area of all items, let's add some margin
itemsArea = addMargin(itemsArea, width * 0.2)

// Grow to at least the default size keeping center point
itemsArea = setMinimumSizeKeepingCenter(itemsArea, { width, height })

// Clamp to board limits
itemsArea = clampIntoKeepingSize(itemsArea, { x: 0, y: 0, width: b.width, height: b.height })
return itemsArea
}

0 comments on commit 7cb61ea

Please sign in to comment.