diff --git a/.gitignore b/.gitignore index 640e501..c32fc08 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,5 @@ local/ *.log .env *.db +*.db-shm +*.db-wal diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 48c7b01..02f8ea9 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -14,8 +14,10 @@ spring: thymeleaf: cache: false datasource: - url: jdbc:sqlite:imgfloat.db + url: jdbc:sqlite:imgfloat.db?busy_timeout=5000&journal_mode=WAL driver-class-name: org.sqlite.JDBC + hikari: + connection-init-sql: "PRAGMA journal_mode=WAL; PRAGMA busy_timeout=5000;" jpa: hibernate: ddl-auto: update diff --git a/src/main/resources/static/js/broadcast.js b/src/main/resources/static/js/broadcast.js index a75e1af..e523a2e 100644 --- a/src/main/resources/static/js/broadcast.js +++ b/src/main/resources/static/js/broadcast.js @@ -3,6 +3,7 @@ const ctx = canvas.getContext('2d'); canvas.width = window.innerWidth; canvas.height = window.innerHeight; const assets = new Map(); +const imageCache = new Map(); function connect() { const socket = new SockJS('/ws'); @@ -24,28 +25,46 @@ function renderAssets(list) { function handleEvent(event) { if (event.type === 'DELETED') { assets.delete(event.assetId); + imageCache.delete(event.assetId); } else if (event.payload && !event.payload.hidden) { assets.set(event.payload.id, event.payload); + ensureImage(event.payload); } else if (event.payload && event.payload.hidden) { assets.delete(event.payload.id); + imageCache.delete(event.payload.id); } draw(); } function draw() { ctx.clearRect(0, 0, canvas.width, canvas.height); - assets.forEach(asset => { - ctx.save(); - ctx.globalAlpha = 1; - ctx.translate(asset.x, asset.y); - ctx.rotate(asset.rotation * Math.PI / 180); - const image = new Image(); - image.src = asset.url; - image.onload = () => { - ctx.drawImage(image, 0, 0, asset.width, asset.height); - }; - ctx.restore(); - }); + assets.forEach(drawAsset); +} + +function drawAsset(asset) { + ctx.save(); + ctx.translate(asset.x, asset.y); + ctx.rotate(asset.rotation * Math.PI / 180); + + const image = ensureImage(asset); + if (image?.complete) { + ctx.drawImage(image, 0, 0, asset.width, asset.height); + } + + ctx.restore(); +} + +function ensureImage(asset) { + const cached = imageCache.get(asset.id); + if (cached && cached.src === asset.url) { + return cached; + } + + const image = new Image(); + image.onload = draw; + image.src = asset.url; + imageCache.set(asset.id, image); + return image; } window.addEventListener('resize', () => {