diff --git a/package.json b/package.json
index 5fa1a20..628ff9a 100644
--- a/package.json
+++ b/package.json
@@ -57,6 +57,7 @@
"source-map-explorer": "^2.5.2",
"theme-ui": "^0.3.1",
"use-image": "^1.0.7",
+ "uuid": "^8.3.2",
"webrtc-adapter": "^7.7.1"
},
"resolutions": {
diff --git a/src/App.js b/src/App.js
index a77ae2b..7962f7b 100644
--- a/src/App.js
+++ b/src/App.js
@@ -18,7 +18,7 @@ import { TokenDataProvider } from "./contexts/TokenDataContext";
import { MapLoadingProvider } from "./contexts/MapLoadingContext";
import { SettingsProvider } from "./contexts/SettingsContext";
import { KeyboardProvider } from "./contexts/KeyboardContext";
-import { ImageSourcesProvider } from "./contexts/ImageSourceContext";
+import { AssetsProvider, AssetURLsProvider } from "./contexts/AssetsContext";
import { ToastProvider } from "./components/Toast";
@@ -30,40 +30,42 @@ function App() {
-
-
-
-
-
-
- {/* Legacy support camel case routes */}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+ {/* Legacy support camel case routes */}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/components/map/MapEditor.js b/src/components/map/MapEditor.js
index f8dbb8a..b042ab0 100644
--- a/src/components/map/MapEditor.js
+++ b/src/components/map/MapEditor.js
@@ -23,7 +23,7 @@ import MapGrid from "./MapGrid";
import MapGridEditor from "./MapGridEditor";
function MapEditor({ map, onSettingsChange }) {
- const [mapImageSource] = useMapImage(map);
+ const [mapImage] = useMapImage(map);
const [stageWidth, setStageWidth] = useState(1);
const [stageHeight, setStageHeight] = useState(1);
@@ -132,11 +132,7 @@ function MapEditor({ map, onSettingsChange }) {
)}
>
-
+
{showGridControls && canEditGrid && (
<>
diff --git a/src/components/map/MapGrid.js b/src/components/map/MapGrid.js
index 5cfbf94..6b30859 100644
--- a/src/components/map/MapGrid.js
+++ b/src/components/map/MapGrid.js
@@ -1,7 +1,7 @@
import React, { useEffect, useState } from "react";
import useImage from "use-image";
-import { useImageSource } from "../../contexts/ImageSourceContext";
+import { useDataURL } from "../../contexts/AssetsContext";
import { mapSources as defaultMapSources } from "../../maps";
@@ -13,13 +13,14 @@ function MapGrid({ map }) {
let mapSourceMap = map;
// Use lowest resolution for grid lightness
if (map && map.type === "file" && map.resolutions) {
+ // FIXME - move to resolutions array
const resolutionArray = Object.keys(map.resolutions);
if (resolutionArray.length > 0) {
- mapSourceMap = map.resolutions[resolutionArray[0]];
+ mapSourceMap.quality = resolutionArray[0];
}
}
- const mapSource = useImageSource(mapSourceMap, defaultMapSources);
- const [mapImage, mapLoadingStatus] = useImage(mapSource);
+ const mapURL = useDataURL(mapSourceMap, defaultMapSources);
+ const [mapImage, mapLoadingStatus] = useImage(mapURL);
const [isImageLight, setIsImageLight] = useState(true);
diff --git a/src/components/map/MapInteraction.js b/src/components/map/MapInteraction.js
index e1bb369..3d63a34 100644
--- a/src/components/map/MapInteraction.js
+++ b/src/components/map/MapInteraction.js
@@ -28,7 +28,7 @@ function MapInteraction({
onSelectedToolChange,
disabledControls,
}) {
- const [mapImageSource, mapImageSourceStatus] = useMapImage(map);
+ const [mapImage, mapImageStatus] = useMapImage(map);
// Map loaded taking in to account different resolutions
const [mapLoaded, setMapLoaded] = useState(false);
@@ -36,14 +36,15 @@ function MapInteraction({
if (
!map ||
!mapState ||
+ // FIXME
(map.type === "file" && !map.file && !map.resolutions) ||
mapState.mapId !== map.id
) {
setMapLoaded(false);
- } else if (mapImageSourceStatus === "loaded") {
+ } else if (mapImageStatus === "loaded") {
setMapLoaded(true);
}
- }, [mapImageSourceStatus, map, mapState]);
+ }, [mapImageStatus, map, mapState]);
const [stageWidth, setStageWidth] = useState(1);
const [stageHeight, setStageHeight] = useState(1);
@@ -211,7 +212,7 @@ function MapInteraction({
>
onMapSelect(map)}
diff --git a/src/components/map/MapToken.js b/src/components/map/MapToken.js
index 1f7258f..e866c89 100644
--- a/src/components/map/MapToken.js
+++ b/src/components/map/MapToken.js
@@ -16,7 +16,7 @@ import {
useDebouncedStageScale,
} from "../../contexts/MapInteractionContext";
import { useGridCellPixelSize } from "../../contexts/GridContext";
-import { useImageSource } from "../../contexts/ImageSourceContext";
+import { useDataURL } from "../../contexts/AssetsContext";
import TokenStatus from "../token/TokenStatus";
import TokenLabel from "../token/TokenLabel";
@@ -43,7 +43,7 @@ function MapToken({
const gridCellPixelSize = useGridCellPixelSize();
- const tokenSource = useImageSource(token, tokenSources, unknownSource);
+ const tokenSource = useDataURL(token, tokenSources, unknownSource);
const [tokenSourceImage, tokenSourceStatus] = useImage(tokenSource);
const [tokenAspectRatio, setTokenAspectRatio] = useState(1);
diff --git a/src/components/token/ListToken.js b/src/components/token/ListToken.js
index 9a094e3..7ab1720 100644
--- a/src/components/token/ListToken.js
+++ b/src/components/token/ListToken.js
@@ -3,12 +3,12 @@ import { Box, Image } from "theme-ui";
import usePreventTouch from "../../hooks/usePreventTouch";
-import { useImageSource } from "../../contexts/ImageSourceContext";
+import { useDataURL } from "../../contexts/AssetsContext";
import { tokenSources, unknownSource } from "../../tokens";
function ListToken({ token, className }) {
- const tokenSource = useImageSource(
+ const tokenURL = useDataURL(
token,
tokenSources,
unknownSource,
@@ -22,7 +22,7 @@ function ListToken({ token, className }) {
return (
onTokenSelect(token)}
diff --git a/src/contexts/AssetsContext.js b/src/contexts/AssetsContext.js
new file mode 100644
index 0000000..77b40c2
--- /dev/null
+++ b/src/contexts/AssetsContext.js
@@ -0,0 +1,273 @@
+import React, { useState, useContext, useCallback, useEffect } from "react";
+import { decode } from "@msgpack/msgpack";
+
+import { useDatabase } from "./DatabaseContext";
+
+import { omit } from "../helpers/shared";
+
+/**
+ * @typedef Asset
+ * @property {string} id
+ * @property {number} width
+ * @property {number} height
+ * @property {Uint8Array} file
+ * @property {string} mime
+ */
+
+/**
+ * @callback getAsset
+ * @param {string} assetId
+ * @returns {Promise}
+ */
+
+/**
+ * @typedef AssetsContext
+ * @property {getAsset} getAsset
+ */
+
+/**
+ * @type {React.Context}
+ */
+const AssetsContext = React.createContext();
+
+export function AssetsProvider({ children }) {
+ const { worker } = useDatabase();
+
+ const getAsset = useCallback(
+ async (assetId) => {
+ const packed = await worker.loadData("assets", assetId);
+ return decode(packed);
+ },
+ [worker]
+ );
+
+ return (
+
+ {children}
+
+ );
+}
+
+export function useAssets() {
+ const context = useContext(AssetsContext);
+ if (context === undefined) {
+ throw new Error("useAssets must be used within a AssetsProvider");
+ }
+ return context;
+}
+
+/**
+ * @typedef AssetURL
+ * @property {string} url
+ * @property {string} id
+ * @property {number} references
+ */
+
+/**
+ * @type React.Context>
+ */
+export const AssetURLsStateContext = React.createContext();
+
+/**
+ * @type React.Context>>
+ */
+export const AssetURLsUpdaterContext = React.createContext();
+
+/**
+ * Helper to manage sharing of custom image sources between uses of useAssetURL
+ */
+export function AssetURLsProvider({ children }) {
+ const [assetURLs, setAssetURLs] = useState({});
+
+ // Revoke url when no more references
+ useEffect(() => {
+ let urlsToCleanup = [];
+ for (let url of Object.values(assetURLs)) {
+ if (url.references <= 0) {
+ URL.revokeObjectURL(url.url);
+ urlsToCleanup.push(url.id);
+ }
+ }
+ if (urlsToCleanup.length > 0) {
+ setAssetURLs((prevURLs) => omit(prevURLs, urlsToCleanup));
+ }
+ }, [assetURLs]);
+
+ return (
+
+
+ {children}
+
+
+ );
+}
+
+/**
+ * Helper function to load either file or default asset into a URL
+ * @param {string} assetId
+ * @param {"file"|"default"} type
+ * @param {Object.} defaultSources
+ * @param {string} unknownSource
+ * @returns {string}
+ */
+export function useAssetURL(assetId, type, defaultSources, unknownSource = "") {
+ const assetURLs = useContext(AssetURLsStateContext);
+ if (assetURLs === undefined) {
+ throw new Error("useAssetURL must be used within a AssetURLsProvider");
+ }
+ const setAssetURLs = useContext(AssetURLsUpdaterContext);
+ if (setAssetURLs === undefined) {
+ throw new Error("useAssetURL must be used within a AssetURLsProvider");
+ }
+
+ const { getAsset } = useAssets();
+
+ useEffect(() => {
+ if (!assetId || type !== "file") {
+ return;
+ }
+
+ async function updateAssetURL() {
+ const asset = await getAsset(assetId);
+ if (asset) {
+ setAssetURLs((prevURLs) => {
+ if (assetId in prevURLs) {
+ // Check if the asset url is already added
+ return {
+ ...prevURLs,
+ [assetId]: {
+ ...prevURLs[assetId],
+ // Increase references
+ references: prevURLs[assetId].references + 1,
+ },
+ };
+ } else {
+ const url = URL.createObjectURL(
+ new Blob([asset.file], { type: asset.mime })
+ );
+ return {
+ ...prevURLs,
+ [assetId]: { url, id: assetId, references: 1 },
+ };
+ }
+ });
+ }
+ }
+
+ updateAssetURL();
+
+ return () => {
+ // Decrease references
+ setAssetURLs((prevURLs) => {
+ if (assetId in prevURLs) {
+ return {
+ ...prevURLs,
+ [assetId]: {
+ ...prevURLs[assetId],
+ references: prevURLs[assetId].references - 1,
+ },
+ };
+ } else {
+ return prevURLs;
+ }
+ });
+ };
+ }, [assetId, setAssetURLs, getAsset, type]);
+
+ if (!assetId) {
+ return unknownSource;
+ }
+
+ if (type === "default") {
+ return defaultSources[assetId];
+ }
+
+ if (type === "file") {
+ return assetURLs[assetId]?.url;
+ }
+
+ return unknownSource;
+}
+
+const dataResolutions = ["ultra", "high", "medium", "low"];
+
+/**
+ * @typedef FileData
+ * @property {string} file
+ * @property {"file"} type
+ * @property {string} thumbnail
+ * @property {string=} quality
+ * @property {Object.=} resolutions
+ */
+
+/**
+ * @typedef DefaultData
+ * @property {string} key
+ * @property {"default"} type
+ */
+
+/**
+ * Load a map or token into a URL taking into account a thumbnail and multiple resolutions
+ * @param {FileData|DefaultData} data
+ * @param {Object.} defaultSources
+ * @param {string} unknownSource
+ * @param {boolean} thumbnail
+ * @returns {string}
+ */
+export function useDataURL(
+ data,
+ defaultSources,
+ unknownSource = "",
+ thumbnail = false
+) {
+ const { database } = useDatabase();
+ const [assetId, setAssetId] = useState();
+
+ useEffect(() => {
+ if (!data) {
+ return;
+ }
+ async function loastAssetId() {
+ if (data.type === "default") {
+ setAssetId(data.key);
+ } else {
+ if (thumbnail) {
+ setAssetId(data.thumbnail);
+ } else if (data.resolutions) {
+ const fileKeys = await database
+ .table("assets")
+ .where("id")
+ .equals(data.file)
+ .primaryKeys();
+ const fileExists = fileKeys.length > 0;
+ // Check if a resolution is specified
+ if (data.quality && data.resolutions[data.quality]) {
+ setAssetId(data.resolutions[data.quality]);
+ }
+ // If no file available fallback to the highest resolution
+ else if (!fileExists) {
+ for (let res of dataResolutions) {
+ if (res in data.resolutions) {
+ setAssetId(data.resolutions[res]);
+ break;
+ }
+ }
+ } else {
+ setAssetId(data.file);
+ }
+ } else {
+ setAssetId(data.file);
+ }
+ }
+ }
+
+ loastAssetId();
+ }, [data, thumbnail, database]);
+
+ const type = data?.type || "default";
+
+ const assetURL = useAssetURL(assetId, type, defaultSources, unknownSource);
+ return assetURL;
+}
+
+export default AssetsContext;
diff --git a/src/contexts/ImageSourceContext.js b/src/contexts/ImageSourceContext.js
deleted file mode 100644
index b558383..0000000
--- a/src/contexts/ImageSourceContext.js
+++ /dev/null
@@ -1,157 +0,0 @@
-import React, { useContext, useState, useEffect } from "react";
-
-import { omit } from "../helpers/shared";
-
-export const ImageSourcesStateContext = React.createContext();
-export const ImageSourcesUpdaterContext = React.createContext(() => {});
-
-/**
- * Helper to manage sharing of custom image sources between uses of useImageSource
- */
-export function ImageSourcesProvider({ children }) {
- const [imageSources, setImageSources] = useState({});
-
- // Revoke url when no more references
- useEffect(() => {
- let sourcesToCleanup = [];
- for (let source of Object.values(imageSources)) {
- if (source.references <= 0) {
- URL.revokeObjectURL(source.url);
- sourcesToCleanup.push(source.id);
- }
- }
- if (sourcesToCleanup.length > 0) {
- setImageSources((prevSources) => omit(prevSources, sourcesToCleanup));
- }
- }, [imageSources]);
-
- return (
-
-
- {children}
-
-
- );
-}
-
-/**
- * Get id from image data
- */
-function getImageFileId(data, thumbnail) {
- if (thumbnail) {
- return `${data.id}-thumbnail`;
- }
- if (data.resolutions) {
- // Check is a resolution is specified
- if (data.quality && data.resolutions[data.quality]) {
- return `${data.id}-${data.quality}`;
- } else if (!data.file) {
- // Fallback to the highest resolution
- const resolutionArray = Object.keys(data.resolutions);
- const resolution = resolutionArray[resolutionArray.length - 1];
- return `${data.id}-${resolution.id}`;
- }
- }
- return data.id;
-}
-
-/**
- * Helper function to load either file or default image into a URL
- */
-export function useImageSource(data, defaultSources, unknownSource, thumbnail) {
- const imageSources = useContext(ImageSourcesStateContext);
- if (imageSources === undefined) {
- throw new Error(
- "useImageSource must be used within a ImageSourcesProvider"
- );
- }
- const setImageSources = useContext(ImageSourcesUpdaterContext);
- if (setImageSources === undefined) {
- throw new Error(
- "useImageSource must be used within a ImageSourcesProvider"
- );
- }
-
- useEffect(() => {
- if (!data || data.type !== "file") {
- return;
- }
- const id = getImageFileId(data, thumbnail);
-
- function updateImageSource(file) {
- if (file) {
- setImageSources((prevSources) => {
- if (id in prevSources) {
- // Check if the image source is already added
- return {
- ...prevSources,
- [id]: {
- ...prevSources[id],
- // Increase references
- references: prevSources[id].references + 1,
- },
- };
- } else {
- const url = URL.createObjectURL(new Blob([file]));
- return {
- ...prevSources,
- [id]: { url, id, references: 1 },
- };
- }
- });
- }
- }
-
- if (thumbnail) {
- updateImageSource(data.thumbnail.file);
- } else if (data.resolutions) {
- // Check is a resolution is specified
- if (data.quality && data.resolutions[data.quality]) {
- updateImageSource(data.resolutions[data.quality].file);
- }
- // If no file available fallback to the highest resolution
- else if (!data.file) {
- const resolutionArray = Object.keys(data.resolutions);
- updateImageSource(
- data.resolutions[resolutionArray[resolutionArray.length - 1]].file
- );
- } else {
- updateImageSource(data.file);
- }
- } else {
- updateImageSource(data.file);
- }
-
- return () => {
- // Decrease references
- setImageSources((prevSources) => {
- if (id in prevSources) {
- return {
- ...prevSources,
- [id]: {
- ...prevSources[id],
- references: prevSources[id].references - 1,
- },
- };
- } else {
- return prevSources;
- }
- });
- };
- }, [data, unknownSource, thumbnail, setImageSources]);
-
- if (!data) {
- return unknownSource;
- }
-
- if (data.type === "default") {
- return defaultSources[data.key];
- }
-
- if (data.type === "file") {
- const id = getImageFileId(data, thumbnail);
- return imageSources[id]?.url;
- }
-
- return unknownSource;
-}
diff --git a/src/database.js b/src/database.js
index 5ed9ed2..3257635 100644
--- a/src/database.js
+++ b/src/database.js
@@ -2,6 +2,7 @@
import Dexie, { Version, DexieOptions } from "dexie";
import "dexie-observable";
import shortid from "shortid";
+import { v4 as uuid } from "uuid";
import blobToBuffer from "./helpers/blobToBuffer";
import { getGridDefaultInset } from "./helpers/grid";
@@ -431,9 +432,139 @@ const versions = {
});
});
},
+ // v1.9.0 - Move map assets into new table
+ 23(v) {
+ v.stores({ assets: "id" }).upgrade((tx) => {
+ tx.table("maps").each((map) => {
+ let assets = [];
+ assets.push({
+ id: uuid(),
+ file: map.file,
+ width: map.width,
+ height: map.height,
+ mime: "",
+ prevId: map.id,
+ prevType: "map",
+ });
+
+ for (let resolution in map.resolutions) {
+ const mapRes = map.resolutions[resolution];
+ assets.push({
+ id: uuid(),
+ file: mapRes.file,
+ width: mapRes.width,
+ height: mapRes.height,
+ mime: "",
+ prevId: map.id,
+ prevType: "mapResolution",
+ resolution,
+ });
+ }
+
+ assets.push({
+ id: uuid(),
+ file: map.thumbnail.file,
+ width: map.thumbnail.width,
+ height: map.thumbnail.height,
+ mime: "",
+ prevId: map.id,
+ prevType: "mapThumbnail",
+ });
+
+ tx.table("assets").bulkAdd(assets);
+ });
+ });
+ },
+ // v1.9.0 - Move token assets into new table
+ 24(v) {
+ v.stores().upgrade((tx) => {
+ tx.table("tokens").each((token) => {
+ let assets = [];
+ assets.push({
+ id: uuid(),
+ file: token.file,
+ width: token.width,
+ height: token.height,
+ mime: "",
+ prevId: token.id,
+ prevType: "token",
+ });
+ assets.push({
+ id: uuid(),
+ file: token.thumbnail.file,
+ width: token.thumbnail.width,
+ height: token.thumbnail.height,
+ mime: "",
+ prevId: token.id,
+ prevType: "tokenThumbnail",
+ });
+ tx.table("assets").bulkAdd(assets);
+ });
+ });
+ },
+ // v1.9.0 - Create foreign keys for assets
+ 25(v) {
+ v.stores().upgrade((tx) => {
+ tx.table("assets").each((asset) => {
+ if (asset.prevType === "map") {
+ tx.table("maps").update(asset.prevId, {
+ file: asset.id,
+ width: undefined,
+ height: undefined,
+ });
+ } else if (asset.prevType === "token") {
+ tx.table("tokens").update(asset.prevId, {
+ file: asset.id,
+ width: undefined,
+ height: undefined,
+ });
+ } else if (asset.prevType === "mapThumbnail") {
+ tx.table("maps").update(asset.prevId, { thumbnail: asset.id });
+ } else if (asset.prevType === "tokenThumbnail") {
+ tx.table("tokens").update(asset.prevId, { thumbnail: asset.id });
+ } else if (asset.prevType === "mapResolution") {
+ tx.table("maps").update(asset.prevId, {
+ resolutions: undefined,
+ [asset.resolution]: asset.id,
+ });
+ }
+ });
+ });
+ },
+ // v1.9.0 - Remove asset migration helpers
+ 26(v) {
+ v.stores().upgrade((tx) => {
+ tx.table("assets")
+ .toCollection()
+ .modify((asset) => {
+ delete asset.prevId;
+ if (asset.prevType === "mapResolution") {
+ delete asset.resolution;
+ }
+ delete asset.prevType;
+ });
+ });
+ },
+ // v1.9.0 - Remap map resolution assets
+ 27(v) {
+ v.stores().upgrade((tx) => {
+ tx.table("maps")
+ .toCollection()
+ .modify((map) => {
+ const resolutions = ["low", "medium", "high", "ultra"];
+ map.resolutions = {};
+ for (let res of resolutions) {
+ if (res in map) {
+ map.resolutions[res] = map[res];
+ delete map[res];
+ }
+ }
+ });
+ });
+ },
};
-const latestVersion = 22;
+const latestVersion = 27;
/**
* Load versions onto a database up to a specific version number
diff --git a/src/helpers/KonvaBridge.js b/src/helpers/KonvaBridge.js
index b8fb3db..0573859 100644
--- a/src/helpers/KonvaBridge.js
+++ b/src/helpers/KonvaBridge.js
@@ -23,10 +23,10 @@ import AuthContext, { useAuth } from "../contexts/AuthContext";
import SettingsContext, { useSettings } from "../contexts/SettingsContext";
import KeyboardContext from "../contexts/KeyboardContext";
import TokenDataContext, { useTokenData } from "../contexts/TokenDataContext";
-import {
- ImageSourcesStateContext,
- ImageSourcesUpdaterContext,
-} from "../contexts/ImageSourceContext";
+import AssetsContext, {
+ AssetURLsStateContext,
+ AssetURLsUpdaterContext,
+} from "../contexts/AssetsContext";
import {
useGrid,
useGridCellPixelSize,
@@ -52,8 +52,9 @@ function KonvaBridge({ stageRender, children }) {
const auth = useAuth();
const settings = useSettings();
const tokenData = useTokenData();
- const imageSources = useContext(ImageSourcesStateContext);
- const setImageSources = useContext(ImageSourcesUpdaterContext);
+ const assets = useContext(AssetsContext);
+ const assetURLs = useContext(AssetURLsStateContext);
+ const setAssetURLs = useContext(AssetURLsUpdaterContext);
const keyboardValue = useContext(KeyboardContext);
const stageScale = useStageScale();
@@ -78,61 +79,63 @@ function KonvaBridge({ stageRender, children }) {
-
-
-
-
-
+
+
+
+
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
-
-
-
- {children}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+ {children}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/hooks/useMapImage.js b/src/hooks/useMapImage.js
index a67dc2b..02cf5b6 100644
--- a/src/hooks/useMapImage.js
+++ b/src/hooks/useMapImage.js
@@ -1,23 +1,23 @@
import { useEffect, useState } from "react";
import useImage from "use-image";
-import { useImageSource } from "../contexts/ImageSourceContext";
+import { useDataURL } from "../contexts/AssetsContext";
import { mapSources as defaultMapSources } from "../maps";
function useMapImage(map) {
- const mapSource = useImageSource(map, defaultMapSources);
- const [mapSourceImage, mapSourceImageStatus] = useImage(mapSource);
+ const mapURL = useDataURL(map, defaultMapSources);
+ const [mapImage, mapImageStatus] = useImage(mapURL);
// Create a map source that only updates when the image is fully loaded
- const [loadedMapSourceImage, setLoadedMapSourceImage] = useState();
+ const [loadedMapImage, setLoadedMapImage] = useState();
useEffect(() => {
- if (mapSourceImageStatus === "loaded") {
- setLoadedMapSourceImage(mapSourceImage);
+ if (mapImageStatus === "loaded") {
+ setLoadedMapImage(mapImage);
}
- }, [mapSourceImage, mapSourceImageStatus]);
+ }, [mapImage, mapImageStatus]);
- return [loadedMapSourceImage, mapSourceImageStatus];
+ return [loadedMapImage, mapImageStatus];
}
export default useMapImage;
diff --git a/src/workers/DatabaseWorker.js b/src/workers/DatabaseWorker.js
index 28d6c9c..8e4278f 100644
--- a/src/workers/DatabaseWorker.js
+++ b/src/workers/DatabaseWorker.js
@@ -15,26 +15,21 @@ let service = {
* Load either a whole table or individual item from the DB
* @param {string} table Table to load from
* @param {string=} key Optional database key to load, if undefined whole table will be loaded
- * @param {bool} excludeFiles Optional exclude files from loaded data when using whole table loading
*/
- async loadData(table, key, excludeFiles = true) {
+ async loadData(table, key) {
try {
let db = getDatabase({});
if (key) {
// Load specific item
const data = await db.table(table).get(key);
- return data;
+ const packed = encode(data);
+ return Comlink.transfer(packed, [packed.buffer]);
} else {
// Load entire table
let items = [];
// Use a cursor instead of toArray to prevent IPC max size error
await db.table(table).each((item) => {
- if (excludeFiles) {
- const { file, resolutions, ...rest } = item;
- items.push(rest);
- } else {
- items.push(item);
- }
+ items.push(item);
});
// Pack data with msgpack so we can use transfer to avoid memory issues
diff --git a/yarn.lock b/yarn.lock
index 439014e..9ea015e 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -13070,6 +13070,11 @@ uuid@^8.3.0:
resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.1.tgz#2ba2e6ca000da60fce5a196954ab241131e05a31"
integrity sha512-FOmRr+FmWEIG8uhZv6C2bTgEVXsHk08kE7mPlrBbEe+c3r9pjceVPgupIfNIhc4yx55H69OXANrUaSuu9eInKg==
+uuid@^8.3.2:
+ version "8.3.2"
+ resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2"
+ integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==
+
v8-compile-cache@^2.0.3:
version "2.2.0"
resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.2.0.tgz#9471efa3ef9128d2f7c6a7ca39c4dd6b5055b132"