Add on upgrade listener for DB and overlay when upgrading
This commit is contained in:
parent
110a6bdd1f
commit
72f2c74e9d
77
src/App.js
77
src/App.js
@ -12,51 +12,54 @@ import HowTo from "./routes/HowTo";
|
|||||||
import Donate from "./routes/Donate";
|
import Donate from "./routes/Donate";
|
||||||
|
|
||||||
import { AuthProvider } from "./contexts/AuthContext";
|
import { AuthProvider } from "./contexts/AuthContext";
|
||||||
import { DatabaseProvider } from "./contexts/DatabaseContext";
|
|
||||||
import { SettingsProvider } from "./contexts/SettingsContext";
|
import { SettingsProvider } from "./contexts/SettingsContext";
|
||||||
import { KeyboardProvider } from "./contexts/KeyboardContext";
|
import { KeyboardProvider } from "./contexts/KeyboardContext";
|
||||||
|
import { DatabaseProvider } from "./contexts/DatabaseContext";
|
||||||
|
import { UserIdProvider } from "./contexts/UserIdContext";
|
||||||
|
|
||||||
import { ToastProvider } from "./components/Toast";
|
import { ToastProvider } from "./components/Toast";
|
||||||
|
|
||||||
function App() {
|
function App() {
|
||||||
return (
|
return (
|
||||||
<ThemeProvider theme={theme}>
|
<ThemeProvider theme={theme}>
|
||||||
<DatabaseProvider>
|
<SettingsProvider>
|
||||||
<SettingsProvider>
|
<AuthProvider>
|
||||||
<AuthProvider>
|
<KeyboardProvider>
|
||||||
<KeyboardProvider>
|
<ToastProvider>
|
||||||
<ToastProvider>
|
<Router>
|
||||||
<Router>
|
<Switch>
|
||||||
<Switch>
|
<Route path="/donate">
|
||||||
<Route path="/donate">
|
<Donate />
|
||||||
<Donate />
|
</Route>
|
||||||
</Route>
|
{/* Legacy support camel case routes */}
|
||||||
{/* Legacy support camel case routes */}
|
<Route path={["/howTo", "/how-to"]}>
|
||||||
<Route path={["/howTo", "/how-to"]}>
|
<HowTo />
|
||||||
<HowTo />
|
</Route>
|
||||||
</Route>
|
<Route path={["/releaseNotes", "/release-notes"]}>
|
||||||
<Route path={["/releaseNotes", "/release-notes"]}>
|
<ReleaseNotes />
|
||||||
<ReleaseNotes />
|
</Route>
|
||||||
</Route>
|
<Route path="/about">
|
||||||
<Route path="/about">
|
<About />
|
||||||
<About />
|
</Route>
|
||||||
</Route>
|
<Route path="/faq">
|
||||||
<Route path="/faq">
|
<FAQ />
|
||||||
<FAQ />
|
</Route>
|
||||||
</Route>
|
<Route path="/game/:id">
|
||||||
<Route path="/game/:id">
|
<DatabaseProvider>
|
||||||
<Game />
|
<UserIdProvider>
|
||||||
</Route>
|
<Game />
|
||||||
<Route path="/">
|
</UserIdProvider>
|
||||||
<Home />
|
</DatabaseProvider>
|
||||||
</Route>
|
</Route>
|
||||||
</Switch>
|
<Route path="/">
|
||||||
</Router>
|
<Home />
|
||||||
</ToastProvider>
|
</Route>
|
||||||
</KeyboardProvider>
|
</Switch>
|
||||||
</AuthProvider>
|
</Router>
|
||||||
</SettingsProvider>
|
</ToastProvider>
|
||||||
</DatabaseProvider>
|
</KeyboardProvider>
|
||||||
|
</AuthProvider>
|
||||||
|
</SettingsProvider>
|
||||||
</ThemeProvider>
|
</ThemeProvider>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
80
src/components/UpgradingLoadingOverlay.js
Normal file
80
src/components/UpgradingLoadingOverlay.js
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
import React, { useState, useEffect } from "react";
|
||||||
|
import { Text } from "theme-ui";
|
||||||
|
|
||||||
|
import LoadingOverlay from "./LoadingOverlay";
|
||||||
|
|
||||||
|
import { shuffle } from "../helpers/shared";
|
||||||
|
|
||||||
|
const facts = [
|
||||||
|
"Owls can rotate their necks 270 degrees",
|
||||||
|
"Not all owls hoot",
|
||||||
|
"Owl flight is almost completely silent",
|
||||||
|
"Owls are used to represent the Goddess Athena in Greek mythology",
|
||||||
|
"Owls have the best night vision of any animal",
|
||||||
|
"Bears can run up to 40 mi (~64 km) per hour ",
|
||||||
|
"A hibernating bear’s heart beats at 8 bpm",
|
||||||
|
"Bears can see in colour",
|
||||||
|
"Koala bears are not bears",
|
||||||
|
"A polar bear can swim up to 100 mi (~161 km) without resting",
|
||||||
|
"A group of bears is called a sleuth or sloth",
|
||||||
|
"Not all bears hibernate",
|
||||||
|
];
|
||||||
|
|
||||||
|
function UpgradingLoadingOverlay() {
|
||||||
|
const [subText, setSubText] = useState();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
let index = 0;
|
||||||
|
let randomFacts = shuffle(facts);
|
||||||
|
|
||||||
|
function updateFact() {
|
||||||
|
setSubText(randomFacts[index % (randomFacts.length - 1)]);
|
||||||
|
index += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Show first fact after 10 seconds then every 20 seconds after that
|
||||||
|
let interval;
|
||||||
|
let timeout = setTimeout(() => {
|
||||||
|
updateFact();
|
||||||
|
interval = setInterval(() => {
|
||||||
|
updateFact();
|
||||||
|
}, 20 * 1000);
|
||||||
|
}, 10 * 1000);
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
clearTimeout(timeout);
|
||||||
|
if (interval) {
|
||||||
|
clearInterval(interval);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<LoadingOverlay>
|
||||||
|
<Text as="p" variant="body2" m={1}>
|
||||||
|
Database upgrading, please wait...
|
||||||
|
</Text>
|
||||||
|
{subText && (
|
||||||
|
<>
|
||||||
|
<Text
|
||||||
|
sx={{ maxWidth: "200px", textAlign: "center" }}
|
||||||
|
as="p"
|
||||||
|
variant="caption"
|
||||||
|
m={1}
|
||||||
|
>
|
||||||
|
We're still working on the upgrade. In the meantime, did you know?
|
||||||
|
</Text>
|
||||||
|
<Text
|
||||||
|
sx={{ maxWidth: "200px", textAlign: "center" }}
|
||||||
|
as="p"
|
||||||
|
variant="body2"
|
||||||
|
>
|
||||||
|
{subText}
|
||||||
|
</Text>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</LoadingOverlay>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default UpgradingLoadingOverlay;
|
@ -14,7 +14,7 @@ import {
|
|||||||
} from "../../helpers/token";
|
} from "../../helpers/token";
|
||||||
import Vector2 from "../../helpers/Vector2";
|
import Vector2 from "../../helpers/Vector2";
|
||||||
|
|
||||||
import { useAuth } from "../../contexts/AuthContext";
|
import { useUserId } from "../../contexts/UserIdContext";
|
||||||
import { useMapData } from "../../contexts/MapDataContext";
|
import { useMapData } from "../../contexts/MapDataContext";
|
||||||
import { useTokenData } from "../../contexts/TokenDataContext";
|
import { useTokenData } from "../../contexts/TokenDataContext";
|
||||||
import { useAssets } from "../../contexts/AssetsContext";
|
import { useAssets } from "../../contexts/AssetsContext";
|
||||||
@ -25,7 +25,7 @@ import useImageDrop from "../../hooks/useImageDrop";
|
|||||||
function GlobalImageDrop({ children, onMapChange, onMapTokensStateCreate }) {
|
function GlobalImageDrop({ children, onMapChange, onMapTokensStateCreate }) {
|
||||||
const { addToast } = useToasts();
|
const { addToast } = useToasts();
|
||||||
|
|
||||||
const { userId } = useAuth();
|
const userId = useUserId();
|
||||||
const { addMap, getMapState } = useMapData();
|
const { addMap, getMapState } = useMapData();
|
||||||
const { addToken } = useTokenData();
|
const { addToken } = useTokenData();
|
||||||
const { addAssets } = useAssets();
|
const { addAssets } = useAssets();
|
||||||
|
@ -4,7 +4,7 @@ import { Group } from "react-konva";
|
|||||||
|
|
||||||
import { useInteractionEmitter } from "../../contexts/MapInteractionContext";
|
import { useInteractionEmitter } from "../../contexts/MapInteractionContext";
|
||||||
import { useMapStage } from "../../contexts/MapStageContext";
|
import { useMapStage } from "../../contexts/MapStageContext";
|
||||||
import { useAuth } from "../../contexts/AuthContext";
|
import { useUserId } from "../../contexts/UserIdContext";
|
||||||
|
|
||||||
import Vector2 from "../../helpers/Vector2";
|
import Vector2 from "../../helpers/Vector2";
|
||||||
import { getRelativePointerPosition } from "../../helpers/konva";
|
import { getRelativePointerPosition } from "../../helpers/konva";
|
||||||
@ -28,7 +28,7 @@ function MapNotes({
|
|||||||
fadeOnHover,
|
fadeOnHover,
|
||||||
}) {
|
}) {
|
||||||
const interactionEmitter = useInteractionEmitter();
|
const interactionEmitter = useInteractionEmitter();
|
||||||
const { userId } = useAuth();
|
const userId = useUserId();
|
||||||
const mapStageRef = useMapStage();
|
const mapStageRef = useMapStage();
|
||||||
const [isBrushDown, setIsBrushDown] = useState(false);
|
const [isBrushDown, setIsBrushDown] = useState(false);
|
||||||
const [noteData, setNoteData] = useState(null);
|
const [noteData, setNoteData] = useState(null);
|
||||||
|
@ -6,7 +6,7 @@ import useImage from "use-image";
|
|||||||
import usePrevious from "../../hooks/usePrevious";
|
import usePrevious from "../../hooks/usePrevious";
|
||||||
import useGridSnapping from "../../hooks/useGridSnapping";
|
import useGridSnapping from "../../hooks/useGridSnapping";
|
||||||
|
|
||||||
import { useAuth } from "../../contexts/AuthContext";
|
import { useUserId } from "../../contexts/UserIdContext";
|
||||||
import {
|
import {
|
||||||
useSetPreventMapInteraction,
|
useSetPreventMapInteraction,
|
||||||
useMapWidth,
|
useMapWidth,
|
||||||
@ -33,7 +33,7 @@ function MapToken({
|
|||||||
fadeOnHover,
|
fadeOnHover,
|
||||||
map,
|
map,
|
||||||
}) {
|
}) {
|
||||||
const { userId } = useAuth();
|
const userId = useUserId();
|
||||||
|
|
||||||
const mapWidth = useMapWidth();
|
const mapWidth = useMapWidth();
|
||||||
const mapHeight = useMapHeight();
|
const mapHeight = useMapHeight();
|
||||||
|
@ -5,7 +5,7 @@ import SelectMapModal from "../../modals/SelectMapModal";
|
|||||||
import SelectMapIcon from "../../icons/SelectMapIcon";
|
import SelectMapIcon from "../../icons/SelectMapIcon";
|
||||||
|
|
||||||
import { useMapData } from "../../contexts/MapDataContext";
|
import { useMapData } from "../../contexts/MapDataContext";
|
||||||
import { useAuth } from "../../contexts/AuthContext";
|
import { useUserId } from "../../contexts/UserIdContext";
|
||||||
|
|
||||||
function SelectMapButton({
|
function SelectMapButton({
|
||||||
onMapChange,
|
onMapChange,
|
||||||
@ -17,7 +17,7 @@ function SelectMapButton({
|
|||||||
const [isModalOpen, setIsModalOpen] = useState(false);
|
const [isModalOpen, setIsModalOpen] = useState(false);
|
||||||
|
|
||||||
const { updateMapState } = useMapData();
|
const { updateMapState } = useMapData();
|
||||||
const { userId } = useAuth();
|
const userId = useUserId();
|
||||||
function openModal() {
|
function openModal() {
|
||||||
if (currentMapState && currentMap && currentMap.owner === userId) {
|
if (currentMapState && currentMap && currentMap.owner === userId) {
|
||||||
updateMapState(currentMapState.mapId, currentMapState);
|
updateMapState(currentMapState.mapId, currentMapState);
|
||||||
|
@ -2,7 +2,7 @@ import React, { useEffect, useState, useRef } from "react";
|
|||||||
import { Rect, Text } from "react-konva";
|
import { Rect, Text } from "react-konva";
|
||||||
import { useSpring, animated } from "react-spring/konva";
|
import { useSpring, animated } from "react-spring/konva";
|
||||||
|
|
||||||
import { useAuth } from "../../contexts/AuthContext";
|
import { useUserId } from "../../contexts/UserIdContext";
|
||||||
import {
|
import {
|
||||||
useSetPreventMapInteraction,
|
useSetPreventMapInteraction,
|
||||||
useMapWidth,
|
useMapWidth,
|
||||||
@ -27,7 +27,7 @@ function Note({
|
|||||||
onNoteDragEnd,
|
onNoteDragEnd,
|
||||||
fadeOnHover,
|
fadeOnHover,
|
||||||
}) {
|
}) {
|
||||||
const { userId } = useAuth();
|
const userId = useUserId();
|
||||||
|
|
||||||
const mapWidth = useMapWidth();
|
const mapWidth = useMapWidth();
|
||||||
const mapHeight = useMapHeight();
|
const mapHeight = useMapHeight();
|
||||||
|
@ -17,7 +17,7 @@ import HideIcon from "../../icons/TokenHideIcon";
|
|||||||
import NoteIcon from "../../icons/NoteToolIcon";
|
import NoteIcon from "../../icons/NoteToolIcon";
|
||||||
import TextIcon from "../../icons/NoteTextIcon";
|
import TextIcon from "../../icons/NoteTextIcon";
|
||||||
|
|
||||||
import { useAuth } from "../../contexts/AuthContext";
|
import { useUserId } from "../../contexts/UserIdContext";
|
||||||
|
|
||||||
const defaultNoteMaxSize = 6;
|
const defaultNoteMaxSize = 6;
|
||||||
|
|
||||||
@ -29,7 +29,7 @@ function NoteMenu({
|
|||||||
onNoteChange,
|
onNoteChange,
|
||||||
map,
|
map,
|
||||||
}) {
|
}) {
|
||||||
const { userId } = useAuth();
|
const userId = useUserId();
|
||||||
|
|
||||||
const wasOpen = usePrevious(isOpen);
|
const wasOpen = usePrevious(isOpen);
|
||||||
|
|
||||||
|
@ -21,7 +21,7 @@ import useSetting from "../../hooks/useSetting";
|
|||||||
import usePreventSelect from "../../hooks/usePreventSelect";
|
import usePreventSelect from "../../hooks/usePreventSelect";
|
||||||
|
|
||||||
import { useTokenData } from "../../contexts/TokenDataContext";
|
import { useTokenData } from "../../contexts/TokenDataContext";
|
||||||
import { useAuth } from "../../contexts/AuthContext";
|
import { useUserId } from "../../contexts/UserIdContext";
|
||||||
import { useMapStage } from "../../contexts/MapStageContext";
|
import { useMapStage } from "../../contexts/MapStageContext";
|
||||||
import DragContext from "../../contexts/DragContext";
|
import DragContext from "../../contexts/DragContext";
|
||||||
|
|
||||||
@ -33,7 +33,7 @@ import { findGroup } from "../../helpers/group";
|
|||||||
import Vector2 from "../../helpers/Vector2";
|
import Vector2 from "../../helpers/Vector2";
|
||||||
|
|
||||||
function TokenBar({ onMapTokensStateCreate }) {
|
function TokenBar({ onMapTokensStateCreate }) {
|
||||||
const { userId } = useAuth();
|
const userId = useUserId();
|
||||||
const { tokensById, tokenGroups } = useTokenData();
|
const { tokensById, tokenGroups } = useTokenData();
|
||||||
const [fullScreen] = useSetting("map.fullScreen");
|
const [fullScreen] = useSetting("map.fullScreen");
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
|
|
||||||
import { useAuth } from "../../contexts/AuthContext";
|
import { useUserId } from "../../contexts/UserIdContext";
|
||||||
import {
|
import {
|
||||||
useMapWidth,
|
useMapWidth,
|
||||||
useMapHeight,
|
useMapHeight,
|
||||||
@ -16,7 +16,7 @@ function TokenDragOverlay({
|
|||||||
tokenGroup,
|
tokenGroup,
|
||||||
dragging,
|
dragging,
|
||||||
}) {
|
}) {
|
||||||
const { userId } = useAuth();
|
const userId = useUserId();
|
||||||
|
|
||||||
const mapWidth = useMapWidth();
|
const mapWidth = useMapWidth();
|
||||||
const mapHeight = useMapHeight();
|
const mapHeight = useMapHeight();
|
||||||
|
@ -14,7 +14,7 @@ import UnlockIcon from "../../icons/TokenUnlockIcon";
|
|||||||
import ShowIcon from "../../icons/TokenShowIcon";
|
import ShowIcon from "../../icons/TokenShowIcon";
|
||||||
import HideIcon from "../../icons/TokenHideIcon";
|
import HideIcon from "../../icons/TokenHideIcon";
|
||||||
|
|
||||||
import { useAuth } from "../../contexts/AuthContext";
|
import { useUserId } from "../../contexts/UserIdContext";
|
||||||
|
|
||||||
const defaultTokenMaxSize = 6;
|
const defaultTokenMaxSize = 6;
|
||||||
function TokenMenu({
|
function TokenMenu({
|
||||||
@ -25,7 +25,7 @@ function TokenMenu({
|
|||||||
onTokenStateChange,
|
onTokenStateChange,
|
||||||
map,
|
map,
|
||||||
}) {
|
}) {
|
||||||
const { userId } = useAuth();
|
const userId = useUserId();
|
||||||
|
|
||||||
const wasOpen = usePrevious(isOpen);
|
const wasOpen = usePrevious(isOpen);
|
||||||
|
|
||||||
|
@ -50,11 +50,13 @@ const AssetsContext = React.createContext();
|
|||||||
const maxCacheSize = 1e8;
|
const maxCacheSize = 1e8;
|
||||||
|
|
||||||
export function AssetsProvider({ children }) {
|
export function AssetsProvider({ children }) {
|
||||||
const { worker, database } = useDatabase();
|
const { worker, database, databaseStatus } = useDatabase();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
worker.cleanAssetCache(maxCacheSize);
|
if (databaseStatus === "loaded") {
|
||||||
}, [worker]);
|
worker.cleanAssetCache(maxCacheSize);
|
||||||
|
}
|
||||||
|
}, [worker, databaseStatus]);
|
||||||
|
|
||||||
const getAsset = useCallback(
|
const getAsset = useCallback(
|
||||||
async (assetId) => {
|
async (assetId) => {
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
import React, { useState, useEffect, useContext } from "react";
|
import React, { useState, useEffect, useContext } from "react";
|
||||||
|
|
||||||
import { useDatabase } from "./DatabaseContext";
|
|
||||||
|
|
||||||
import FakeStorage from "../helpers/FakeStorage";
|
import FakeStorage from "../helpers/FakeStorage";
|
||||||
|
|
||||||
const AuthContext = React.createContext();
|
const AuthContext = React.createContext();
|
||||||
@ -17,31 +15,13 @@ try {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function AuthProvider({ children }) {
|
export function AuthProvider({ children }) {
|
||||||
const { database, databaseStatus } = useDatabase();
|
|
||||||
|
|
||||||
const [password, setPassword] = useState(storage.getItem("auth") || "");
|
const [password, setPassword] = useState(storage.getItem("auth") || "");
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
storage.setItem("auth", password);
|
storage.setItem("auth", password);
|
||||||
}, [password]);
|
}, [password]);
|
||||||
|
|
||||||
const [userId, setUserId] = useState();
|
|
||||||
useEffect(() => {
|
|
||||||
if (!database || databaseStatus === "loading") {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
async function loadUserId() {
|
|
||||||
const storedUserId = await database.table("user").get("userId");
|
|
||||||
if (storedUserId) {
|
|
||||||
setUserId(storedUserId.value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
loadUserId();
|
|
||||||
}, [database, databaseStatus]);
|
|
||||||
|
|
||||||
const value = {
|
const value = {
|
||||||
userId,
|
|
||||||
password,
|
password,
|
||||||
setPassword,
|
setPassword,
|
||||||
};
|
};
|
||||||
|
@ -26,6 +26,7 @@ const worker = Comlink.wrap(new DatabaseWorker());
|
|||||||
|
|
||||||
export function DatabaseProvider({ children }) {
|
export function DatabaseProvider({ children }) {
|
||||||
const [database, setDatabase] = useState();
|
const [database, setDatabase] = useState();
|
||||||
|
// "loading" | "disabled" | "upgrading" | "loaded"
|
||||||
const [databaseStatus, setDatabaseStatus] = useState("loading");
|
const [databaseStatus, setDatabaseStatus] = useState("loading");
|
||||||
const [databaseError, setDatabaseError] = useState();
|
const [databaseError, setDatabaseError] = useState();
|
||||||
|
|
||||||
@ -34,7 +35,15 @@ export function DatabaseProvider({ children }) {
|
|||||||
let testDBRequest = window.indexedDB.open("__test");
|
let testDBRequest = window.indexedDB.open("__test");
|
||||||
testDBRequest.onsuccess = async function () {
|
testDBRequest.onsuccess = async function () {
|
||||||
testDBRequest.result.close();
|
testDBRequest.result.close();
|
||||||
let db = getDatabase({ autoOpen: false });
|
let db = getDatabase(
|
||||||
|
{ autoOpen: false },
|
||||||
|
undefined,
|
||||||
|
undefined,
|
||||||
|
true,
|
||||||
|
(v) => {
|
||||||
|
setDatabaseStatus("upgrading");
|
||||||
|
}
|
||||||
|
);
|
||||||
setDatabase(db);
|
setDatabase(db);
|
||||||
db.on("ready", () => {
|
db.on("ready", () => {
|
||||||
setDatabaseStatus("loaded");
|
setDatabaseStatus("loaded");
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import React, { useEffect, useState, useContext, useCallback } from "react";
|
import React, { useEffect, useState, useContext, useCallback } from "react";
|
||||||
|
|
||||||
import { useAuth } from "./AuthContext";
|
import { useUserId } from "./UserIdContext";
|
||||||
import { useDatabase } from "./DatabaseContext";
|
import { useDatabase } from "./DatabaseContext";
|
||||||
|
|
||||||
import { applyObservableChange } from "../helpers/dexie";
|
import { applyObservableChange } from "../helpers/dexie";
|
||||||
@ -19,7 +19,7 @@ const defaultMapState = {
|
|||||||
|
|
||||||
export function MapDataProvider({ children }) {
|
export function MapDataProvider({ children }) {
|
||||||
const { database, databaseStatus } = useDatabase();
|
const { database, databaseStatus } = useDatabase();
|
||||||
const { userId } = useAuth();
|
const userId = useUserId();
|
||||||
|
|
||||||
const [maps, setMaps] = useState([]);
|
const [maps, setMaps] = useState([]);
|
||||||
const [mapStates, setMapStates] = useState([]);
|
const [mapStates, setMapStates] = useState([]);
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import React, { useEffect, useContext } from "react";
|
import React, { useEffect, useContext } from "react";
|
||||||
|
|
||||||
import { useDatabase } from "./DatabaseContext";
|
import { useDatabase } from "./DatabaseContext";
|
||||||
import { useAuth } from "./AuthContext";
|
import { useUserId } from "./UserIdContext";
|
||||||
|
|
||||||
import { getRandomMonster } from "../helpers/monsters";
|
import { getRandomMonster } from "../helpers/monsters";
|
||||||
|
|
||||||
@ -11,7 +11,7 @@ export const PlayerStateContext = React.createContext();
|
|||||||
export const PlayerUpdaterContext = React.createContext(() => {});
|
export const PlayerUpdaterContext = React.createContext(() => {});
|
||||||
|
|
||||||
export function PlayerProvider({ session, children }) {
|
export function PlayerProvider({ session, children }) {
|
||||||
const { userId } = useAuth();
|
const userId = useUserId();
|
||||||
const { database, databaseStatus } = useDatabase();
|
const { database, databaseStatus } = useDatabase();
|
||||||
|
|
||||||
const [playerState, setPlayerState] = useNetworkedState(
|
const [playerState, setPlayerState] = useNetworkedState(
|
||||||
@ -53,7 +53,7 @@ export function PlayerProvider({ session, children }) {
|
|||||||
if (
|
if (
|
||||||
playerState.nickname &&
|
playerState.nickname &&
|
||||||
database !== undefined &&
|
database !== undefined &&
|
||||||
databaseStatus !== "loading"
|
(databaseStatus === "loaded" || databaseStatus === "disabled")
|
||||||
) {
|
) {
|
||||||
database
|
database
|
||||||
.table("user")
|
.table("user")
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import React, { useEffect, useState, useContext, useCallback } from "react";
|
import React, { useEffect, useState, useContext, useCallback } from "react";
|
||||||
|
|
||||||
import { useAuth } from "./AuthContext";
|
import { useUserId } from "./UserIdContext";
|
||||||
import { useDatabase } from "./DatabaseContext";
|
import { useDatabase } from "./DatabaseContext";
|
||||||
|
|
||||||
import { applyObservableChange } from "../helpers/dexie";
|
import { applyObservableChange } from "../helpers/dexie";
|
||||||
@ -10,7 +10,7 @@ const TokenDataContext = React.createContext();
|
|||||||
|
|
||||||
export function TokenDataProvider({ children }) {
|
export function TokenDataProvider({ children }) {
|
||||||
const { database, databaseStatus } = useDatabase();
|
const { database, databaseStatus } = useDatabase();
|
||||||
const { userId } = useAuth();
|
const userId = useUserId();
|
||||||
|
|
||||||
const [tokens, setTokens] = useState([]);
|
const [tokens, setTokens] = useState([]);
|
||||||
const [tokensLoading, setTokensLoading] = useState(true);
|
const [tokensLoading, setTokensLoading] = useState(true);
|
||||||
|
36
src/contexts/UserIdContext.js
Normal file
36
src/contexts/UserIdContext.js
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
import React, { useEffect, useState, useContext } from "react";
|
||||||
|
|
||||||
|
import { useDatabase } from "./DatabaseContext";
|
||||||
|
/**
|
||||||
|
* @type {React.Context<string|undefined>}
|
||||||
|
*/
|
||||||
|
const UserIdContext = React.createContext();
|
||||||
|
|
||||||
|
export function UserIdProvider({ children }) {
|
||||||
|
const { database, databaseStatus } = useDatabase();
|
||||||
|
|
||||||
|
const [userId, setUserId] = useState();
|
||||||
|
useEffect(() => {
|
||||||
|
if (!database || databaseStatus === "loading") {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
async function loadUserId() {
|
||||||
|
const storedUserId = await database.table("user").get("userId");
|
||||||
|
if (storedUserId) {
|
||||||
|
setUserId(storedUserId.value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
loadUserId();
|
||||||
|
}, [database, databaseStatus]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<UserIdContext.Provider value={userId}>{children}</UserIdContext.Provider>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function useUserId() {
|
||||||
|
return useContext(UserIdContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default UserIdContext;
|
@ -3,7 +3,7 @@ import Dexie, { DexieOptions } from "dexie";
|
|||||||
import { v4 as uuid } from "uuid";
|
import { v4 as uuid } from "uuid";
|
||||||
import "dexie-observable";
|
import "dexie-observable";
|
||||||
|
|
||||||
import { loadVersions, latestVersion } from "./upgrade";
|
import { loadVersions } from "./upgrade";
|
||||||
import { getDefaultMaps } from "./maps";
|
import { getDefaultMaps } from "./maps";
|
||||||
import { getDefaultTokens } from "./tokens";
|
import { getDefaultTokens } from "./tokens";
|
||||||
|
|
||||||
@ -36,16 +36,18 @@ function populate(db) {
|
|||||||
* @param {string=} name
|
* @param {string=} name
|
||||||
* @param {number=} versionNumber
|
* @param {number=} versionNumber
|
||||||
* @param {boolean=} populateData
|
* @param {boolean=} populateData
|
||||||
|
* @param {import("./upgrade").OnUpgrade=} onUpgrade
|
||||||
* @returns {Dexie}
|
* @returns {Dexie}
|
||||||
*/
|
*/
|
||||||
export function getDatabase(
|
export function getDatabase(
|
||||||
options,
|
options,
|
||||||
name = "OwlbearRodeoDB",
|
name = "OwlbearRodeoDB",
|
||||||
versionNumber = latestVersion,
|
versionNumber = undefined,
|
||||||
populateData = true
|
populateData = true,
|
||||||
|
onUpgrade = undefined
|
||||||
) {
|
) {
|
||||||
let db = new Dexie(name, options);
|
let db = new Dexie(name, options);
|
||||||
loadVersions(db, versionNumber);
|
loadVersions(db, versionNumber, onUpgrade);
|
||||||
if (populateData) {
|
if (populateData) {
|
||||||
populate(db);
|
populate(db);
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,7 @@ import {
|
|||||||
useDebouncedStageScale,
|
useDebouncedStageScale,
|
||||||
} from "../contexts/MapInteractionContext";
|
} from "../contexts/MapInteractionContext";
|
||||||
import { MapStageProvider, useMapStage } from "../contexts/MapStageContext";
|
import { MapStageProvider, useMapStage } from "../contexts/MapStageContext";
|
||||||
import AuthContext, { useAuth } from "../contexts/AuthContext";
|
import UserIdContext, { useUserId } from "../contexts/UserIdContext";
|
||||||
import SettingsContext, { useSettings } from "../contexts/SettingsContext";
|
import SettingsContext, { useSettings } from "../contexts/SettingsContext";
|
||||||
import KeyboardContext from "../contexts/KeyboardContext";
|
import KeyboardContext from "../contexts/KeyboardContext";
|
||||||
import AssetsContext, {
|
import AssetsContext, {
|
||||||
@ -50,7 +50,7 @@ import DatabaseContext, { useDatabase } from "../contexts/DatabaseContext";
|
|||||||
*/
|
*/
|
||||||
function KonvaBridge({ stageRender, children }) {
|
function KonvaBridge({ stageRender, children }) {
|
||||||
const mapStageRef = useMapStage();
|
const mapStageRef = useMapStage();
|
||||||
const auth = useAuth();
|
const userId = useUserId();
|
||||||
const settings = useSettings();
|
const settings = useSettings();
|
||||||
const assets = useAssets();
|
const assets = useAssets();
|
||||||
const assetURLs = useContext(AssetURLsStateContext);
|
const assetURLs = useContext(AssetURLsStateContext);
|
||||||
@ -78,7 +78,7 @@ function KonvaBridge({ stageRender, children }) {
|
|||||||
|
|
||||||
return stageRender(
|
return stageRender(
|
||||||
<DatabaseContext.Provider value={database}>
|
<DatabaseContext.Provider value={database}>
|
||||||
<AuthContext.Provider value={auth}>
|
<UserIdContext.Provider value={userId}>
|
||||||
<SettingsContext.Provider value={settings}>
|
<SettingsContext.Provider value={settings}>
|
||||||
<KeyboardContext.Provider value={keyboardValue}>
|
<KeyboardContext.Provider value={keyboardValue}>
|
||||||
<MapStageProvider value={mapStageRef}>
|
<MapStageProvider value={mapStageRef}>
|
||||||
@ -140,7 +140,7 @@ function KonvaBridge({ stageRender, children }) {
|
|||||||
</MapStageProvider>
|
</MapStageProvider>
|
||||||
</KeyboardContext.Provider>
|
</KeyboardContext.Provider>
|
||||||
</SettingsContext.Provider>
|
</SettingsContext.Provider>
|
||||||
</AuthContext.Provider>
|
</UserIdContext.Provider>
|
||||||
</DatabaseContext.Provider>
|
</DatabaseContext.Provider>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,7 @@ import LoadingOverlay from "../components/LoadingOverlay";
|
|||||||
import LoadingBar from "../components/LoadingBar";
|
import LoadingBar from "../components/LoadingBar";
|
||||||
import ErrorBanner from "../components/banner/ErrorBanner";
|
import ErrorBanner from "../components/banner/ErrorBanner";
|
||||||
|
|
||||||
import { useAuth } from "../contexts/AuthContext";
|
import { useUserId } from "../contexts/UserIdContext";
|
||||||
import { useDatabase } from "../contexts/DatabaseContext";
|
import { useDatabase } from "../contexts/DatabaseContext";
|
||||||
|
|
||||||
import SelectDataModal from "./SelectDataModal";
|
import SelectDataModal from "./SelectDataModal";
|
||||||
@ -22,7 +22,7 @@ const importDBName = "OwlbearRodeoImportDB";
|
|||||||
|
|
||||||
function ImportExportModal({ isOpen, onRequestClose }) {
|
function ImportExportModal({ isOpen, onRequestClose }) {
|
||||||
const { worker } = useDatabase();
|
const { worker } = useDatabase();
|
||||||
const { userId } = useAuth();
|
const userId = useUserId();
|
||||||
|
|
||||||
const [isLoading, setIsLoading] = useState(false);
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
const [error, setError] = useState();
|
const [error, setError] = useState();
|
||||||
|
@ -25,7 +25,7 @@ import { createMapFromFile } from "../helpers/map";
|
|||||||
import useResponsiveLayout from "../hooks/useResponsiveLayout";
|
import useResponsiveLayout from "../hooks/useResponsiveLayout";
|
||||||
|
|
||||||
import { useMapData } from "../contexts/MapDataContext";
|
import { useMapData } from "../contexts/MapDataContext";
|
||||||
import { useAuth } from "../contexts/AuthContext";
|
import { useUserId } from "../contexts/UserIdContext";
|
||||||
import { useAssets } from "../contexts/AssetsContext";
|
import { useAssets } from "../contexts/AssetsContext";
|
||||||
import { GroupProvider } from "../contexts/GroupContext";
|
import { GroupProvider } from "../contexts/GroupContext";
|
||||||
import { TileDragProvider } from "../contexts/TileDragContext";
|
import { TileDragProvider } from "../contexts/TileDragContext";
|
||||||
@ -40,7 +40,7 @@ function SelectMapModal({
|
|||||||
}) {
|
}) {
|
||||||
const { addToast } = useToasts();
|
const { addToast } = useToasts();
|
||||||
|
|
||||||
const { userId } = useAuth();
|
const userId = useUserId();
|
||||||
const {
|
const {
|
||||||
maps,
|
maps,
|
||||||
mapStates,
|
mapStates,
|
||||||
|
@ -29,7 +29,7 @@ import Vector2 from "../helpers/Vector2";
|
|||||||
import useResponsiveLayout from "../hooks/useResponsiveLayout";
|
import useResponsiveLayout from "../hooks/useResponsiveLayout";
|
||||||
|
|
||||||
import { useTokenData } from "../contexts/TokenDataContext";
|
import { useTokenData } from "../contexts/TokenDataContext";
|
||||||
import { useAuth } from "../contexts/AuthContext";
|
import { useUserId } from "../contexts/UserIdContext";
|
||||||
import { useAssets } from "../contexts/AssetsContext";
|
import { useAssets } from "../contexts/AssetsContext";
|
||||||
import { GroupProvider } from "../contexts/GroupContext";
|
import { GroupProvider } from "../contexts/GroupContext";
|
||||||
import { TileDragProvider } from "../contexts/TileDragContext";
|
import { TileDragProvider } from "../contexts/TileDragContext";
|
||||||
@ -38,7 +38,7 @@ import { useMapStage } from "../contexts/MapStageContext";
|
|||||||
function SelectTokensModal({ isOpen, onRequestClose, onMapTokensStateCreate }) {
|
function SelectTokensModal({ isOpen, onRequestClose, onMapTokensStateCreate }) {
|
||||||
const { addToast } = useToasts();
|
const { addToast } = useToasts();
|
||||||
|
|
||||||
const { userId } = useAuth();
|
const userId = useUserId();
|
||||||
const {
|
const {
|
||||||
tokens,
|
tokens,
|
||||||
addToken,
|
addToken,
|
||||||
|
@ -14,7 +14,7 @@ import Modal from "../components/Modal";
|
|||||||
import Slider from "../components/Slider";
|
import Slider from "../components/Slider";
|
||||||
import LoadingOverlay from "../components/LoadingOverlay";
|
import LoadingOverlay from "../components/LoadingOverlay";
|
||||||
|
|
||||||
import { useAuth } from "../contexts/AuthContext";
|
import { useUserId } from "../contexts/UserIdContext";
|
||||||
import { useDatabase } from "../contexts/DatabaseContext";
|
import { useDatabase } from "../contexts/DatabaseContext";
|
||||||
|
|
||||||
import useSetting from "../hooks/useSetting";
|
import useSetting from "../hooks/useSetting";
|
||||||
@ -24,7 +24,7 @@ import ImportExportModal from "./ImportExportModal";
|
|||||||
|
|
||||||
function SettingsModal({ isOpen, onRequestClose }) {
|
function SettingsModal({ isOpen, onRequestClose }) {
|
||||||
const { database, databaseStatus } = useDatabase();
|
const { database, databaseStatus } = useDatabase();
|
||||||
const { userId } = useAuth();
|
const userId = useUserId();
|
||||||
const [isDeleteModalOpen, setIsDeleteModalOpen] = useState(false);
|
const [isDeleteModalOpen, setIsDeleteModalOpen] = useState(false);
|
||||||
const [labelSize, setLabelSize] = useSetting("map.labelSize");
|
const [labelSize, setLabelSize] = useSetting("map.labelSize");
|
||||||
const [gridSnappingSensitivity, setGridSnappingSensitivity] = useSetting(
|
const [gridSnappingSensitivity, setGridSnappingSensitivity] = useSetting(
|
||||||
|
@ -3,7 +3,7 @@ import { useToasts } from "react-toast-notifications";
|
|||||||
|
|
||||||
import { useMapData } from "../contexts/MapDataContext";
|
import { useMapData } from "../contexts/MapDataContext";
|
||||||
import { useMapLoading } from "../contexts/MapLoadingContext";
|
import { useMapLoading } from "../contexts/MapLoadingContext";
|
||||||
import { useAuth } from "../contexts/AuthContext";
|
import { useUserId } from "../contexts/UserIdContext";
|
||||||
import { useDatabase } from "../contexts/DatabaseContext";
|
import { useDatabase } from "../contexts/DatabaseContext";
|
||||||
import { useParty } from "../contexts/PartyContext";
|
import { useParty } from "../contexts/PartyContext";
|
||||||
import { useAssets } from "../contexts/AssetsContext";
|
import { useAssets } from "../contexts/AssetsContext";
|
||||||
@ -39,7 +39,7 @@ const defaultMapActions = {
|
|||||||
*/
|
*/
|
||||||
function NetworkedMapAndTokens({ session }) {
|
function NetworkedMapAndTokens({ session }) {
|
||||||
const { addToast } = useToasts();
|
const { addToast } = useToasts();
|
||||||
const { userId } = useAuth();
|
const userId = useUserId();
|
||||||
const partyState = useParty();
|
const partyState = useParty();
|
||||||
const { assetLoadStart, assetProgressUpdate, isLoading } = useMapLoading();
|
const { assetLoadStart, assetProgressUpdate, isLoading } = useMapLoading();
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import React, { useState, useEffect, useRef } from "react";
|
import React, { useState, useEffect, useRef } from "react";
|
||||||
import { Group } from "react-konva";
|
import { Group } from "react-konva";
|
||||||
|
|
||||||
import { useAuth } from "../contexts/AuthContext";
|
import { useUserId } from "../contexts/UserIdContext";
|
||||||
|
|
||||||
import MapPointer from "../components/map/MapPointer";
|
import MapPointer from "../components/map/MapPointer";
|
||||||
import { isEmpty } from "../helpers/shared";
|
import { isEmpty } from "../helpers/shared";
|
||||||
@ -13,7 +13,7 @@ import useSetting from "../hooks/useSetting";
|
|||||||
const sendTickRate = 50;
|
const sendTickRate = 50;
|
||||||
|
|
||||||
function NetworkedMapPointer({ session, active }) {
|
function NetworkedMapPointer({ session, active }) {
|
||||||
const { userId } = useAuth();
|
const userId = useUserId();
|
||||||
const [localPointerState, setLocalPointerState] = useState({});
|
const [localPointerState, setLocalPointerState] = useState({});
|
||||||
const [pointerColor] = useSetting("pointer.color");
|
const [pointerColor] = useSetting("pointer.color");
|
||||||
|
|
||||||
|
@ -8,6 +8,7 @@ import OfflineBanner from "../components/banner/OfflineBanner";
|
|||||||
import LoadingOverlay from "../components/LoadingOverlay";
|
import LoadingOverlay from "../components/LoadingOverlay";
|
||||||
import Link from "../components/Link";
|
import Link from "../components/Link";
|
||||||
import MapLoadingOverlay from "../components/map/MapLoadingOverlay";
|
import MapLoadingOverlay from "../components/map/MapLoadingOverlay";
|
||||||
|
import UpgradingLoadingOverlay from "../components/UpgradingLoadingOverlay";
|
||||||
|
|
||||||
import AuthModal from "../modals/AuthModal";
|
import AuthModal from "../modals/AuthModal";
|
||||||
import GameExpiredModal from "../modals/GameExpiredModal";
|
import GameExpiredModal from "../modals/GameExpiredModal";
|
||||||
@ -90,13 +91,16 @@ function Game() {
|
|||||||
|
|
||||||
// Join game
|
// Join game
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (sessionStatus === "ready" && databaseStatus !== "loading") {
|
if (
|
||||||
|
sessionStatus === "ready" &&
|
||||||
|
(databaseStatus === "loaded" || databaseStatus === "disabled")
|
||||||
|
) {
|
||||||
session.joinGame(gameId, password);
|
session.joinGame(gameId, password);
|
||||||
}
|
}
|
||||||
}, [gameId, password, databaseStatus, session, sessionStatus]);
|
}, [gameId, password, databaseStatus, session, sessionStatus]);
|
||||||
|
|
||||||
function handleAuthSubmit(newPassword) {
|
function handleAuthSubmit(newPassword) {
|
||||||
if (databaseStatus !== "loading") {
|
if (databaseStatus === "loaded" || databaseStatus === "disabled") {
|
||||||
session.joinGame(gameId, newPassword);
|
session.joinGame(gameId, newPassword);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -151,6 +155,9 @@ function Game() {
|
|||||||
isOpen={sessionStatus === "needs_update"}
|
isOpen={sessionStatus === "needs_update"}
|
||||||
/>
|
/>
|
||||||
{!sessionStatus && <LoadingOverlay />}
|
{!sessionStatus && <LoadingOverlay />}
|
||||||
|
{sessionStatus && databaseStatus === "upgrading" && (
|
||||||
|
<UpgradingLoadingOverlay />
|
||||||
|
)}
|
||||||
<MapLoadingOverlay />
|
<MapLoadingOverlay />
|
||||||
</MapStageProvider>
|
</MapStageProvider>
|
||||||
</PartyProvider>
|
</PartyProvider>
|
||||||
|
110
src/upgrade.js
110
src/upgrade.js
@ -17,9 +17,15 @@ import {
|
|||||||
import { getDefaultMaps } from "./maps";
|
import { getDefaultMaps } from "./maps";
|
||||||
import { getDefaultTokens } from "./tokens";
|
import { getDefaultTokens } from "./tokens";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @callback OnUpgrade
|
||||||
|
* @param {number} versionNumber
|
||||||
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @callback VersionCallback
|
* @callback VersionCallback
|
||||||
* @param {Version} version
|
* @param {Version} version
|
||||||
|
* @param {OnUpgrade=} onUpgrade
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -37,8 +43,9 @@ export const versions = {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
// v1.2.1 - Move from blob files to array buffers
|
// v1.2.1 - Move from blob files to array buffers
|
||||||
2(v) {
|
2(v, onUpgrade) {
|
||||||
v.stores({}).upgrade(async (tx) => {
|
v.stores({}).upgrade(async (tx) => {
|
||||||
|
onUpgrade?.(2);
|
||||||
const maps = await Dexie.waitFor(tx.table("maps").toArray());
|
const maps = await Dexie.waitFor(tx.table("maps").toArray());
|
||||||
let mapBuffers = {};
|
let mapBuffers = {};
|
||||||
for (let map of maps) {
|
for (let map of maps) {
|
||||||
@ -53,8 +60,9 @@ export const versions = {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
// v1.3.0 - Added new default tokens
|
// v1.3.0 - Added new default tokens
|
||||||
3(v) {
|
3(v, onUpgrade) {
|
||||||
v.stores({}).upgrade((tx) => {
|
v.stores({}).upgrade((tx) => {
|
||||||
|
onUpgrade?.(3);
|
||||||
return tx
|
return tx
|
||||||
.table("states")
|
.table("states")
|
||||||
.toCollection()
|
.toCollection()
|
||||||
@ -116,8 +124,9 @@ export const versions = {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
// v1.3.1 - Added show grid option
|
// v1.3.1 - Added show grid option
|
||||||
4(v) {
|
4(v, onUpgrade) {
|
||||||
v.stores({}).upgrade((tx) => {
|
v.stores({}).upgrade((tx) => {
|
||||||
|
onUpgrade?.(4);
|
||||||
return tx
|
return tx
|
||||||
.table("maps")
|
.table("maps")
|
||||||
.toCollection()
|
.toCollection()
|
||||||
@ -127,8 +136,9 @@ export const versions = {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
// v1.4.0 - Added fog subtraction
|
// v1.4.0 - Added fog subtraction
|
||||||
5(v) {
|
5(v, onUpgrade) {
|
||||||
v.stores({}).upgrade((tx) => {
|
v.stores({}).upgrade((tx) => {
|
||||||
|
onUpgrade?.(5);
|
||||||
return tx
|
return tx
|
||||||
.table("states")
|
.table("states")
|
||||||
.toCollection()
|
.toCollection()
|
||||||
@ -144,8 +154,9 @@ export const versions = {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
// v1.4.2 - Added map resolutions
|
// v1.4.2 - Added map resolutions
|
||||||
6(v) {
|
6(v, onUpgrade) {
|
||||||
v.stores({}).upgrade((tx) => {
|
v.stores({}).upgrade((tx) => {
|
||||||
|
onUpgrade?.(6);
|
||||||
return tx
|
return tx
|
||||||
.table("maps")
|
.table("maps")
|
||||||
.toCollection()
|
.toCollection()
|
||||||
@ -156,8 +167,9 @@ export const versions = {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
// v1.5.0 - Fixed default token rogue spelling
|
// v1.5.0 - Fixed default token rogue spelling
|
||||||
7(v) {
|
7(v, onUpgrade) {
|
||||||
v.stores({}).upgrade((tx) => {
|
v.stores({}).upgrade((tx) => {
|
||||||
|
onUpgrade?.(7);
|
||||||
return tx
|
return tx
|
||||||
.table("states")
|
.table("states")
|
||||||
.toCollection()
|
.toCollection()
|
||||||
@ -171,8 +183,9 @@ export const versions = {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
// v1.5.0 - Added map snap to grid option
|
// v1.5.0 - Added map snap to grid option
|
||||||
8(v) {
|
8(v, onUpgrade) {
|
||||||
v.stores({}).upgrade((tx) => {
|
v.stores({}).upgrade((tx) => {
|
||||||
|
onUpgrade?.(8);
|
||||||
return tx
|
return tx
|
||||||
.table("maps")
|
.table("maps")
|
||||||
.toCollection()
|
.toCollection()
|
||||||
@ -182,8 +195,9 @@ export const versions = {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
// v1.5.1 - Added lock, visibility and modified to tokens
|
// v1.5.1 - Added lock, visibility and modified to tokens
|
||||||
9(v) {
|
9(v, onUpgrade) {
|
||||||
v.stores({}).upgrade((tx) => {
|
v.stores({}).upgrade((tx) => {
|
||||||
|
onUpgrade?.(9);
|
||||||
return tx
|
return tx
|
||||||
.table("states")
|
.table("states")
|
||||||
.toCollection()
|
.toCollection()
|
||||||
@ -199,8 +213,9 @@ export const versions = {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
// v1.5.1 - Added token prop category and remove isVehicle bool
|
// v1.5.1 - Added token prop category and remove isVehicle bool
|
||||||
10(v) {
|
10(v, onUpgrade) {
|
||||||
v.stores({}).upgrade((tx) => {
|
v.stores({}).upgrade((tx) => {
|
||||||
|
onUpgrade?.(10);
|
||||||
return tx
|
return tx
|
||||||
.table("tokens")
|
.table("tokens")
|
||||||
.toCollection()
|
.toCollection()
|
||||||
@ -211,8 +226,9 @@ export const versions = {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
// v1.5.2 - Added automatic cache invalidation to maps
|
// v1.5.2 - Added automatic cache invalidation to maps
|
||||||
11(v) {
|
11(v, onUpgrade) {
|
||||||
v.stores({}).upgrade((tx) => {
|
v.stores({}).upgrade((tx) => {
|
||||||
|
onUpgrade?.(11);
|
||||||
return tx
|
return tx
|
||||||
.table("maps")
|
.table("maps")
|
||||||
.toCollection()
|
.toCollection()
|
||||||
@ -222,8 +238,9 @@ export const versions = {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
// v1.5.2 - Added automatic cache invalidation to tokens
|
// v1.5.2 - Added automatic cache invalidation to tokens
|
||||||
12(v) {
|
12(v, onUpgrade) {
|
||||||
v.stores({}).upgrade((tx) => {
|
v.stores({}).upgrade((tx) => {
|
||||||
|
onUpgrade?.(12);
|
||||||
return tx
|
return tx
|
||||||
.table("tokens")
|
.table("tokens")
|
||||||
.toCollection()
|
.toCollection()
|
||||||
@ -233,8 +250,9 @@ export const versions = {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
// v1.6.0 - Added map grouping and grid scale and offset
|
// v1.6.0 - Added map grouping and grid scale and offset
|
||||||
13(v) {
|
13(v, onUpgrade) {
|
||||||
v.stores({}).upgrade((tx) => {
|
v.stores({}).upgrade((tx) => {
|
||||||
|
onUpgrade?.(13);
|
||||||
return tx
|
return tx
|
||||||
.table("maps")
|
.table("maps")
|
||||||
.toCollection()
|
.toCollection()
|
||||||
@ -256,8 +274,9 @@ export const versions = {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
// v1.6.0 - Added token grouping
|
// v1.6.0 - Added token grouping
|
||||||
14(v) {
|
14(v, onUpgrade) {
|
||||||
v.stores({}).upgrade((tx) => {
|
v.stores({}).upgrade((tx) => {
|
||||||
|
onUpgrade?.(14);
|
||||||
return tx
|
return tx
|
||||||
.table("tokens")
|
.table("tokens")
|
||||||
.toCollection()
|
.toCollection()
|
||||||
@ -267,8 +286,9 @@ export const versions = {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
// v1.6.1 - Added width and height to tokens
|
// v1.6.1 - Added width and height to tokens
|
||||||
15(v) {
|
15(v, onUpgrade) {
|
||||||
v.stores({}).upgrade(async (tx) => {
|
v.stores({}).upgrade(async (tx) => {
|
||||||
|
onUpgrade?.(15);
|
||||||
const tokens = await Dexie.waitFor(tx.table("tokens").toArray());
|
const tokens = await Dexie.waitFor(tx.table("tokens").toArray());
|
||||||
let tokenSizes = {};
|
let tokenSizes = {};
|
||||||
for (let token of tokens) {
|
for (let token of tokens) {
|
||||||
@ -293,8 +313,9 @@ export const versions = {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
// v1.7.0 - Added note tool
|
// v1.7.0 - Added note tool
|
||||||
16(v) {
|
16(v, onUpgrade) {
|
||||||
v.stores({}).upgrade((tx) => {
|
v.stores({}).upgrade((tx) => {
|
||||||
|
onUpgrade?.(16);
|
||||||
return tx
|
return tx
|
||||||
.table("states")
|
.table("states")
|
||||||
.toCollection()
|
.toCollection()
|
||||||
@ -305,8 +326,9 @@ export const versions = {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
// 1.7.0 (hotfix) - Optimized fog shape edits to only include needed data
|
// 1.7.0 (hotfix) - Optimized fog shape edits to only include needed data
|
||||||
17(v) {
|
17(v, onUpgrade) {
|
||||||
v.stores({}).upgrade((tx) => {
|
v.stores({}).upgrade((tx) => {
|
||||||
|
onUpgrade?.(17);
|
||||||
return tx
|
return tx
|
||||||
.table("states")
|
.table("states")
|
||||||
.toCollection()
|
.toCollection()
|
||||||
@ -328,8 +350,9 @@ export const versions = {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
// 1.8.0 - Added note text only mode, converted draw and fog representations
|
// 1.8.0 - Added note text only mode, converted draw and fog representations
|
||||||
18(v) {
|
18(v, onUpgrade) {
|
||||||
v.stores({}).upgrade((tx) => {
|
v.stores({}).upgrade((tx) => {
|
||||||
|
onUpgrade?.(18);
|
||||||
return tx
|
return tx
|
||||||
.table("states")
|
.table("states")
|
||||||
.toCollection()
|
.toCollection()
|
||||||
@ -355,8 +378,9 @@ export const versions = {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
// 1.8.0 - Add thumbnail to maps and add measurement to grid
|
// 1.8.0 - Add thumbnail to maps and add measurement to grid
|
||||||
19(v) {
|
19(v, onUpgrade) {
|
||||||
v.stores({}).upgrade(async (tx) => {
|
v.stores({}).upgrade(async (tx) => {
|
||||||
|
onUpgrade?.(19);
|
||||||
const userId = (await Dexie.waitFor(tx.table("user").get("userId")))
|
const userId = (await Dexie.waitFor(tx.table("user").get("userId")))
|
||||||
.value;
|
.value;
|
||||||
const maps = await Dexie.waitFor(tx.table("maps").toArray());
|
const maps = await Dexie.waitFor(tx.table("maps").toArray());
|
||||||
@ -378,8 +402,9 @@ export const versions = {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
// 1.8.0 - Add thumbnail to tokens
|
// 1.8.0 - Add thumbnail to tokens
|
||||||
20(v) {
|
20(v, onUpgrade) {
|
||||||
v.stores({}).upgrade(async (tx) => {
|
v.stores({}).upgrade(async (tx) => {
|
||||||
|
onUpgrade?.(20);
|
||||||
const userId = (await Dexie.waitFor(tx.table("user").get("userId")))
|
const userId = (await Dexie.waitFor(tx.table("user").get("userId")))
|
||||||
.value;
|
.value;
|
||||||
const tokens = await Dexie.waitFor(tx.table("tokens").toArray());
|
const tokens = await Dexie.waitFor(tx.table("tokens").toArray());
|
||||||
@ -404,8 +429,9 @@ export const versions = {
|
|||||||
v.stores({});
|
v.stores({});
|
||||||
},
|
},
|
||||||
// v1.8.1 - Shorten fog shape ids
|
// v1.8.1 - Shorten fog shape ids
|
||||||
22(v) {
|
22(v, onUpgrade) {
|
||||||
v.stores({}).upgrade((tx) => {
|
v.stores({}).upgrade((tx) => {
|
||||||
|
onUpgrade?.(22);
|
||||||
return tx
|
return tx
|
||||||
.table("states")
|
.table("states")
|
||||||
.toCollection()
|
.toCollection()
|
||||||
@ -420,8 +446,9 @@ export const versions = {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
// v1.9.0 - Add outlines to tokens
|
// v1.9.0 - Add outlines to tokens
|
||||||
23(v) {
|
23(v, onUpgrade) {
|
||||||
v.stores({}).upgrade(async (tx) => {
|
v.stores({}).upgrade(async (tx) => {
|
||||||
|
onUpgrade?.(23);
|
||||||
const tokens = await Dexie.waitFor(tx.table("tokens").toArray());
|
const tokens = await Dexie.waitFor(tx.table("tokens").toArray());
|
||||||
const tokenOutlines = await Dexie.waitFor(
|
const tokenOutlines = await Dexie.waitFor(
|
||||||
Promise.all(tokens.map(createDataOutline))
|
Promise.all(tokens.map(createDataOutline))
|
||||||
@ -447,8 +474,9 @@ export const versions = {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
// v1.9.0 - Move map assets into new table
|
// v1.9.0 - Move map assets into new table
|
||||||
24(v) {
|
24(v, onUpgrade) {
|
||||||
v.stores({ assets: "id, owner" }).upgrade((tx) => {
|
v.stores({ assets: "id, owner" }).upgrade((tx) => {
|
||||||
|
onUpgrade?.(24);
|
||||||
tx.table("maps").each((map) => {
|
tx.table("maps").each((map) => {
|
||||||
let assets = [];
|
let assets = [];
|
||||||
assets.push({
|
assets.push({
|
||||||
@ -493,8 +521,9 @@ export const versions = {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
// v1.9.0 - Move token assets into new table
|
// v1.9.0 - Move token assets into new table
|
||||||
25(v) {
|
25(v, onUpgrade) {
|
||||||
v.stores({}).upgrade((tx) => {
|
v.stores({}).upgrade((tx) => {
|
||||||
|
onUpgrade?.(25);
|
||||||
tx.table("tokens").each((token) => {
|
tx.table("tokens").each((token) => {
|
||||||
let assets = [];
|
let assets = [];
|
||||||
assets.push({
|
assets.push({
|
||||||
@ -522,8 +551,9 @@ export const versions = {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
// v1.9.0 - Create foreign keys for assets
|
// v1.9.0 - Create foreign keys for assets
|
||||||
26(v) {
|
26(v, onUpgrade) {
|
||||||
v.stores({}).upgrade((tx) => {
|
v.stores({}).upgrade((tx) => {
|
||||||
|
onUpgrade?.(26);
|
||||||
tx.table("assets").each((asset) => {
|
tx.table("assets").each((asset) => {
|
||||||
if (asset.prevType === "map") {
|
if (asset.prevType === "map") {
|
||||||
tx.table("maps").update(asset.prevId, {
|
tx.table("maps").update(asset.prevId, {
|
||||||
@ -547,8 +577,9 @@ export const versions = {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
// v1.9.0 - Remove asset migration helpers
|
// v1.9.0 - Remove asset migration helpers
|
||||||
27(v) {
|
27(v, onUpgrade) {
|
||||||
v.stores({}).upgrade((tx) => {
|
v.stores({}).upgrade((tx) => {
|
||||||
|
onUpgrade?.(27);
|
||||||
tx.table("assets")
|
tx.table("assets")
|
||||||
.toCollection()
|
.toCollection()
|
||||||
.modify((asset) => {
|
.modify((asset) => {
|
||||||
@ -561,8 +592,9 @@ export const versions = {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
// v1.9.0 - Remap map resolution assets
|
// v1.9.0 - Remap map resolution assets
|
||||||
28(v) {
|
28(v, onUpgrade) {
|
||||||
v.stores({}).upgrade((tx) => {
|
v.stores({}).upgrade((tx) => {
|
||||||
|
onUpgrade?.(28);
|
||||||
tx.table("maps")
|
tx.table("maps")
|
||||||
.toCollection()
|
.toCollection()
|
||||||
.modify((map) => {
|
.modify((map) => {
|
||||||
@ -579,8 +611,9 @@ export const versions = {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
// v1.9.0 - Move tokens to use more defaults
|
// v1.9.0 - Move tokens to use more defaults
|
||||||
29(v) {
|
29(v, onUpgrade) {
|
||||||
v.stores({}).upgrade((tx) => {
|
v.stores({}).upgrade((tx) => {
|
||||||
|
onUpgrade?.(29);
|
||||||
tx.table("tokens")
|
tx.table("tokens")
|
||||||
.toCollection()
|
.toCollection()
|
||||||
.modify(async (token) => {
|
.modify(async (token) => {
|
||||||
@ -592,8 +625,9 @@ export const versions = {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
// v1.9.0 - Move tokens to use more defaults and add token outline to token states
|
// v1.9.0 - Move tokens to use more defaults and add token outline to token states
|
||||||
30(v) {
|
30(v, onUpgrade) {
|
||||||
v.stores({}).upgrade(async (tx) => {
|
v.stores({}).upgrade(async (tx) => {
|
||||||
|
onUpgrade?.(30);
|
||||||
const tokens = await Dexie.waitFor(tx.table("tokens").toArray());
|
const tokens = await Dexie.waitFor(tx.table("tokens").toArray());
|
||||||
tx.table("states")
|
tx.table("states")
|
||||||
.toCollection()
|
.toCollection()
|
||||||
@ -645,8 +679,9 @@ export const versions = {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
// v1.9.0 - Remove maps not owned by user as cache is now done on the asset level
|
// v1.9.0 - Remove maps not owned by user as cache is now done on the asset level
|
||||||
31(v) {
|
31(v, onUpgrade) {
|
||||||
v.stores({}).upgrade(async (tx) => {
|
v.stores({}).upgrade(async (tx) => {
|
||||||
|
onUpgrade?.(31);
|
||||||
const userId = (await Dexie.waitFor(tx.table("user").get("userId")))
|
const userId = (await Dexie.waitFor(tx.table("user").get("userId")))
|
||||||
?.value;
|
?.value;
|
||||||
if (userId) {
|
if (userId) {
|
||||||
@ -655,8 +690,9 @@ export const versions = {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
// v1.9.0 - Remove tokens not owned by user as cache is now done on the asset level
|
// v1.9.0 - Remove tokens not owned by user as cache is now done on the asset level
|
||||||
32(v) {
|
32(v, onUpgrade) {
|
||||||
v.stores({}).upgrade(async (tx) => {
|
v.stores({}).upgrade(async (tx) => {
|
||||||
|
onUpgrade?.(32);
|
||||||
const userId = (await Dexie.waitFor(tx.table("user").get("userId")))
|
const userId = (await Dexie.waitFor(tx.table("user").get("userId")))
|
||||||
?.value;
|
?.value;
|
||||||
if (userId) {
|
if (userId) {
|
||||||
@ -665,8 +701,9 @@ export const versions = {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
// v1.9.0 - Store default maps and tokens in db
|
// v1.9.0 - Store default maps and tokens in db
|
||||||
33(v) {
|
33(v, onUpgrade) {
|
||||||
v.stores({}).upgrade(async (tx) => {
|
v.stores({}).upgrade(async (tx) => {
|
||||||
|
onUpgrade?.(33);
|
||||||
const userId = (await Dexie.waitFor(tx.table("user").get("userId")))
|
const userId = (await Dexie.waitFor(tx.table("user").get("userId")))
|
||||||
?.value;
|
?.value;
|
||||||
if (!userId) {
|
if (!userId) {
|
||||||
@ -679,8 +716,9 @@ export const versions = {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
// v1.9.0 - Add new group table
|
// v1.9.0 - Add new group table
|
||||||
34(v) {
|
34(v, onUpgrade) {
|
||||||
v.stores({ groups: "id" }).upgrade(async (tx) => {
|
v.stores({ groups: "id" }).upgrade(async (tx) => {
|
||||||
|
onUpgrade?.(34);
|
||||||
function groupItems(items) {
|
function groupItems(items) {
|
||||||
let groups = [];
|
let groups = [];
|
||||||
let subGroups = {};
|
let subGroups = {};
|
||||||
@ -714,8 +752,9 @@ export const versions = {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
// v1.9.0 - Remove map and token group in respective tables
|
// v1.9.0 - Remove map and token group in respective tables
|
||||||
35(v) {
|
35(v, onUpgrade) {
|
||||||
v.stores({}).upgrade((tx) => {
|
v.stores({}).upgrade((tx) => {
|
||||||
|
onUpgrade?.(35);
|
||||||
tx.table("maps")
|
tx.table("maps")
|
||||||
.toCollection()
|
.toCollection()
|
||||||
.modify((map) => {
|
.modify((map) => {
|
||||||
@ -736,10 +775,11 @@ export const latestVersion = 35;
|
|||||||
* Load versions onto a database up to a specific version number
|
* Load versions onto a database up to a specific version number
|
||||||
* @param {Dexie} db
|
* @param {Dexie} db
|
||||||
* @param {number=} upTo version number to load up to, latest version if undefined
|
* @param {number=} upTo version number to load up to, latest version if undefined
|
||||||
|
* @param {OnUpgrade=} onUpgrade
|
||||||
*/
|
*/
|
||||||
export function loadVersions(db, upTo = latestVersion) {
|
export function loadVersions(db, upTo = latestVersion, onUpgrade = undefined) {
|
||||||
for (let versionNumber = 1; versionNumber <= upTo; versionNumber++) {
|
for (let versionNumber = 1; versionNumber <= upTo; versionNumber++) {
|
||||||
versions[versionNumber](db.version(versionNumber));
|
versions[versionNumber](db.version(versionNumber), onUpgrade);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user