Typescript
This commit is contained in:
parent
49b8caa2d7
commit
569ed696fc
@ -100,6 +100,7 @@
|
||||
"@types/jest": "^26.0.23",
|
||||
"@types/lodash.clonedeep": "^4.5.6",
|
||||
"@types/lodash.get": "^4.4.6",
|
||||
"@types/lodash.set": "^4.3.6",
|
||||
"@types/node": "^15.6.0",
|
||||
"@types/react": "^17.0.6",
|
||||
"@types/react-dom": "^17.0.5",
|
||||
|
@ -5,12 +5,13 @@ import DiceTile from "./DiceTile";
|
||||
|
||||
import useResponsiveLayout from "../../hooks/useResponsiveLayout";
|
||||
import { DefaultDice } from "../../types/Dice";
|
||||
import { DiceSelectEventHandler } from "../../types/Events";
|
||||
|
||||
type DiceTileProps = {
|
||||
dice: DefaultDice[];
|
||||
onDiceSelect: (dice: DefaultDice) => void;
|
||||
onDiceSelect: DiceSelectEventHandler;
|
||||
selectedDice: DefaultDice;
|
||||
onDone: (dice: DefaultDice) => void;
|
||||
onDone: DiceSelectEventHandler;
|
||||
};
|
||||
|
||||
function DiceTiles({
|
||||
|
@ -1,26 +1,38 @@
|
||||
import React, { useEffect, useRef, useState } from "react";
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
import { Box, IconButton } from "theme-ui";
|
||||
import { Node } from "konva/types/Node";
|
||||
|
||||
import RemoveTokenIcon from "../../icons/RemoveTokenIcon";
|
||||
|
||||
function DragOverlay({ dragging, node, onRemove }) {
|
||||
type DragOverlayProps = {
|
||||
dragging: boolean;
|
||||
node: Node;
|
||||
onRemove: () => void;
|
||||
};
|
||||
|
||||
function DragOverlay({ dragging, node, onRemove }: DragOverlayProps) {
|
||||
const [isRemoveHovered, setIsRemoveHovered] = useState(false);
|
||||
const removeTokenRef = useRef();
|
||||
const removeTokenRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
// Detect token hover on remove icon manually to support touch devices
|
||||
useEffect(() => {
|
||||
const map = document.querySelector(".map");
|
||||
const mapRect = map.getBoundingClientRect();
|
||||
|
||||
function detectRemoveHover() {
|
||||
if (!node || !dragging || !removeTokenRef.current) {
|
||||
return;
|
||||
}
|
||||
const map = document.querySelector(".map");
|
||||
if (!map) {
|
||||
return;
|
||||
}
|
||||
const mapRect = map.getBoundingClientRect();
|
||||
const stage = node.getStage();
|
||||
if (!stage) {
|
||||
return;
|
||||
}
|
||||
const pointerPosition = stage.getPointerPosition();
|
||||
if (!pointerPosition) {
|
||||
return;
|
||||
}
|
||||
const screenSpacePointerPosition = {
|
||||
x: pointerPosition.x + mapRect.left,
|
||||
y: pointerPosition.y + mapRect.top,
|
||||
@ -41,7 +53,7 @@ function DragOverlay({ dragging, node, onRemove }) {
|
||||
}
|
||||
}
|
||||
|
||||
let handler;
|
||||
let handler: NodeJS.Timeout;
|
||||
if (node && dragging) {
|
||||
handler = setInterval(detectRemoveHover, 100);
|
||||
}
|
@ -21,6 +21,22 @@ import FullScreenExitIcon from "../../icons/FullScreenExitIcon";
|
||||
import NoteToolIcon from "../../icons/NoteToolIcon";
|
||||
|
||||
import useSetting from "../../hooks/useSetting";
|
||||
import { Map } from "../../types/Map";
|
||||
import { MapState } from "../../types/MapState";
|
||||
|
||||
type MapControlsProps = {
|
||||
onMapChange: () => void;
|
||||
onMapReset: () => void;
|
||||
currentMap?: Map;
|
||||
currentMapState?: MapState;
|
||||
selectedToolId: string;
|
||||
onSelectedToolChange: () => void;
|
||||
toolSettings: any;
|
||||
onToolSettingChange: () => void;
|
||||
onToolAction: () => void;
|
||||
disabledControls: string[];
|
||||
disabledSettings: string[];
|
||||
};
|
||||
|
||||
function MapContols({
|
||||
onMapChange,
|
||||
@ -34,7 +50,7 @@ function MapContols({
|
||||
onToolAction,
|
||||
disabledControls,
|
||||
disabledSettings,
|
||||
}) {
|
||||
}: MapControlsProps) {
|
||||
const [isExpanded, setIsExpanded] = useState(true);
|
||||
const [fullScreen, setFullScreen] = useSetting("map.fullScreen");
|
||||
|
@ -1,4 +1,4 @@
|
||||
import React, { useState, useEffect } from "react";
|
||||
import { useState, useEffect } from "react";
|
||||
import { Flex, Close, IconButton } from "theme-ui";
|
||||
|
||||
import { groupsFromIds, itemsFromGroups } from "../../helpers/group";
|
||||
@ -13,8 +13,27 @@ import { useMapData } from "../../contexts/MapDataContext";
|
||||
import { useKeyboard } from "../../contexts/KeyboardContext";
|
||||
|
||||
import shortcuts from "../../shortcuts";
|
||||
import { Map } from "../../types/Map";
|
||||
import {
|
||||
MapChangeEventHandler,
|
||||
MapResetEventHandler,
|
||||
} from "../../types/Events";
|
||||
|
||||
function MapEditBar({ currentMap, disabled, onMapChange, onMapReset, onLoad }) {
|
||||
type MapEditBarProps = {
|
||||
currentMap?: Map;
|
||||
disabled: boolean;
|
||||
onMapChange: MapChangeEventHandler;
|
||||
onMapReset: MapResetEventHandler;
|
||||
onLoad: (loading: boolean) => void;
|
||||
};
|
||||
|
||||
function MapEditBar({
|
||||
currentMap,
|
||||
disabled,
|
||||
onMapChange,
|
||||
onMapReset,
|
||||
onLoad,
|
||||
}: MapEditBarProps) {
|
||||
const [hasMapState, setHasMapState] = useState(false);
|
||||
|
||||
const { maps, mapStates, removeMaps, resetMap } = useMapData();
|
||||
@ -56,11 +75,11 @@ function MapEditBar({ currentMap, disabled, onMapChange, onMapReset, onLoad }) {
|
||||
setIsMapsRemoveModalOpen(false);
|
||||
const selectedMaps = getSelectedMaps();
|
||||
const selectedMapIds = selectedMaps.map((map) => map.id);
|
||||
onGroupSelect();
|
||||
onGroupSelect(undefined);
|
||||
await removeMaps(selectedMapIds);
|
||||
// Removed the map from the map screen if needed
|
||||
if (currentMap && selectedMapIds.includes(currentMap.id)) {
|
||||
onMapChange(null, null);
|
||||
onMapChange(undefined, undefined);
|
||||
}
|
||||
onLoad(false);
|
||||
}
|
||||
@ -84,7 +103,7 @@ function MapEditBar({ currentMap, disabled, onMapChange, onMapReset, onLoad }) {
|
||||
/**
|
||||
* Shortcuts
|
||||
*/
|
||||
function handleKeyDown(event) {
|
||||
function handleKeyDown(event: KeyboardEvent) {
|
||||
if (disabled) {
|
||||
return;
|
||||
}
|
||||
@ -117,7 +136,7 @@ function MapEditBar({ currentMap, disabled, onMapChange, onMapReset, onLoad }) {
|
||||
<Close
|
||||
title="Clear Selection"
|
||||
aria-label="Clear Selection"
|
||||
onClick={() => onGroupSelect()}
|
||||
onClick={() => onGroupSelect(undefined)}
|
||||
/>
|
||||
<Flex>
|
||||
<IconButton
|
@ -11,37 +11,58 @@ import { useDatabase } from "./DatabaseContext";
|
||||
|
||||
import { Map } from "../types/Map";
|
||||
import { MapState } from "../types/MapState";
|
||||
import { Note } from "../types/Note";
|
||||
|
||||
import { removeGroupsItems } from "../helpers/group";
|
||||
|
||||
// TODO: fix differences in types between default maps and imported maps
|
||||
import { Group } from "../types/Group";
|
||||
|
||||
export type AddMapEventHandler = (map: Map) => Promise<void>;
|
||||
export type RemoveMapsEventHandler = (ids: string[]) => Promise<void>;
|
||||
export type ResetMapEventHandler = (id: string) => Promise<MapState>;
|
||||
export type UpdateMapEventHanlder = (
|
||||
id: string,
|
||||
update: Partial<Map>
|
||||
) => Promise<void>;
|
||||
export type UpdateMapStateEventHandler = (
|
||||
id: string,
|
||||
update: Partial<MapState>
|
||||
) => Promise<void>;
|
||||
export type GetMapStateEventHandler = (
|
||||
id: string
|
||||
) => Promise<MapState | undefined>;
|
||||
export type GetMapEventHandler = (id: string) => Promise<Map | undefined>;
|
||||
export type UpdateMapGroupsEventHandler = (groups: Group[]) => Promise<void>;
|
||||
|
||||
type MapDataContext = {
|
||||
maps: Array<Map>;
|
||||
mapStates: MapState[];
|
||||
addMap: (map: Map) => void;
|
||||
removeMaps: (ids: string[]) => void;
|
||||
resetMap: (id: string) => void;
|
||||
updateMap: (id: string, update: Partial<Map>) => void;
|
||||
updateMapState: (id: string, update: Partial<MapState>) => void;
|
||||
getMapState: (id: string) => Promise<MapState>;
|
||||
getMap: (id: string) => Promise<Map | undefined>;
|
||||
/** Adds a map to the database, also adds an assosiated state and group for that map */
|
||||
addMap: AddMapEventHandler;
|
||||
removeMaps: RemoveMapsEventHandler;
|
||||
resetMap: ResetMapEventHandler;
|
||||
updateMap: UpdateMapEventHanlder;
|
||||
updateMapState: UpdateMapStateEventHandler;
|
||||
getMapState: GetMapStateEventHandler;
|
||||
getMap: GetMapEventHandler;
|
||||
mapsLoading: boolean;
|
||||
updateMapGroups: (groups: any) => void;
|
||||
updateMapGroups: UpdateMapGroupsEventHandler;
|
||||
mapsById: Record<string, Map>;
|
||||
mapGroups: any[];
|
||||
mapGroups: Group[];
|
||||
};
|
||||
|
||||
const MapDataContext =
|
||||
React.createContext<MapDataContext | undefined>(undefined);
|
||||
|
||||
const defaultMapState = {
|
||||
const defaultMapState: Pick<
|
||||
MapState,
|
||||
"tokens" | "drawShapes" | "fogShapes" | "editFlags" | "notes"
|
||||
> = {
|
||||
tokens: {},
|
||||
drawShapes: {},
|
||||
fogShapes: {},
|
||||
// Flags to determine what other people can edit
|
||||
editFlags: ["drawing", "tokens", "notes", "fog"],
|
||||
notes: {} as Note[],
|
||||
notes: {},
|
||||
};
|
||||
|
||||
export function MapDataProvider({ children }: { children: React.ReactNode }) {
|
||||
@ -68,7 +89,7 @@ export function MapDataProvider({ children }: { children: React.ReactNode }) {
|
||||
[database]
|
||||
);
|
||||
|
||||
const [mapGroups, setMapGroups] = useState([]);
|
||||
const [mapGroups, setMapGroups] = useState<Group[]>([]);
|
||||
useEffect(() => {
|
||||
async function updateMapGroups() {
|
||||
const group = await database?.table("groups").get("maps");
|
||||
@ -79,27 +100,23 @@ export function MapDataProvider({ children }: { children: React.ReactNode }) {
|
||||
}
|
||||
}, [mapGroupQuery, database]);
|
||||
|
||||
const getMap = useCallback(
|
||||
async (mapId: string) => {
|
||||
let map = (await database?.table("maps").get(mapId)) as Map;
|
||||
const getMap = useCallback<GetMapEventHandler>(
|
||||
async (mapId) => {
|
||||
let map = await database?.table("maps").get(mapId);
|
||||
return map;
|
||||
},
|
||||
[database]
|
||||
);
|
||||
|
||||
const getMapState = useCallback(
|
||||
const getMapState = useCallback<GetMapStateEventHandler>(
|
||||
async (mapId) => {
|
||||
let mapState = (await database?.table("states").get(mapId)) as MapState;
|
||||
let mapState = await database?.table("states").get(mapId);
|
||||
return mapState;
|
||||
},
|
||||
[database]
|
||||
);
|
||||
|
||||
/**
|
||||
* Adds a map to the database, also adds an assosiated state and group for that map
|
||||
* @param {Object} map map to add
|
||||
*/
|
||||
const addMap = useCallback(
|
||||
const addMap = useCallback<AddMapEventHandler>(
|
||||
async (map) => {
|
||||
if (database) {
|
||||
// Just update map database as react state will be updated with an Observable
|
||||
@ -115,7 +132,7 @@ export function MapDataProvider({ children }: { children: React.ReactNode }) {
|
||||
[database]
|
||||
);
|
||||
|
||||
const removeMaps = useCallback(
|
||||
const removeMaps = useCallback<RemoveMapsEventHandler>(
|
||||
async (ids) => {
|
||||
if (database) {
|
||||
const maps = await database.table("maps").bulkGet(ids);
|
||||
@ -143,30 +160,30 @@ export function MapDataProvider({ children }: { children: React.ReactNode }) {
|
||||
[database]
|
||||
);
|
||||
|
||||
const resetMap = useCallback(
|
||||
const resetMap = useCallback<ResetMapEventHandler>(
|
||||
async (id) => {
|
||||
const state = { ...defaultMapState, mapId: id };
|
||||
const state: MapState = { ...defaultMapState, mapId: id };
|
||||
await database?.table("states").put(state);
|
||||
return state;
|
||||
},
|
||||
[database]
|
||||
);
|
||||
|
||||
const updateMap = useCallback(
|
||||
const updateMap = useCallback<UpdateMapEventHanlder>(
|
||||
async (id, update) => {
|
||||
await database?.table("maps").update(id, update);
|
||||
},
|
||||
[database]
|
||||
);
|
||||
|
||||
const updateMapState = useCallback(
|
||||
const updateMapState = useCallback<UpdateMapStateEventHandler>(
|
||||
async (id, update) => {
|
||||
await database?.table("states").update(id, update);
|
||||
},
|
||||
[database]
|
||||
);
|
||||
|
||||
const updateMapGroups = useCallback(
|
||||
const updateMapGroups = useCallback<UpdateMapGroupsEventHandler>(
|
||||
async (groups) => {
|
||||
// Update group state immediately to avoid animation delay
|
||||
setMapGroups(groups);
|
||||
|
@ -2,21 +2,26 @@ import React, { useState, useEffect, useContext } from "react";
|
||||
|
||||
import { getSettings } from "../settings";
|
||||
|
||||
const SettingsContext = React.createContext({
|
||||
settings: {},
|
||||
setSettings: () => {},
|
||||
});
|
||||
import { Settings } from "../types/Settings";
|
||||
|
||||
type SettingsContext = {
|
||||
settings: Settings;
|
||||
setSettings: React.Dispatch<React.SetStateAction<Settings>>;
|
||||
};
|
||||
|
||||
const SettingsContext =
|
||||
React.createContext<SettingsContext | undefined>(undefined);
|
||||
|
||||
const settingsProvider = getSettings();
|
||||
|
||||
export function SettingsProvider({ children }: { children: any }) {
|
||||
const [settings, setSettings] = useState(settingsProvider.getAll());
|
||||
const [settings, setSettings] = useState<Settings>(settingsProvider.getAll());
|
||||
|
||||
useEffect(() => {
|
||||
settingsProvider.setAll(settings);
|
||||
}, [settings]);
|
||||
|
||||
const value: { settings: any, setSettings: any} = {
|
||||
const value = {
|
||||
settings,
|
||||
setSettings,
|
||||
};
|
||||
|
@ -9,20 +9,37 @@ import { useLiveQuery } from "dexie-react-hooks";
|
||||
|
||||
import { useDatabase } from "./DatabaseContext";
|
||||
|
||||
import { Token } from "../tokens";
|
||||
import { removeGroupsItems } from "../helpers/group";
|
||||
|
||||
import { Token } from "../types/Token";
|
||||
import { Group } from "../types/Group";
|
||||
|
||||
export type AddTokenEventHandler = (token: Token) => Promise<void>;
|
||||
export type RemoveTokensEventHandler = (ids: string[]) => Promise<void>;
|
||||
export type UpdateTokenEventHandler = (
|
||||
id: string,
|
||||
update: Partial<Token>
|
||||
) => Promise<void>;
|
||||
export type GetTokenEventHandler = (
|
||||
tokenId: string
|
||||
) => Promise<Token | undefined>;
|
||||
export type UpdateTokenGroupsEventHandler = (groups: any[]) => Promise<void>;
|
||||
export type UpdateTokensHiddenEventHandler = (
|
||||
ids: string[],
|
||||
hideInSidebar: boolean
|
||||
) => Promise<void>;
|
||||
|
||||
type TokenDataContext = {
|
||||
tokens: Token[];
|
||||
addToken: (token: Token) => Promise<void>;
|
||||
tokenGroups: any[];
|
||||
removeTokens: (ids: string[]) => Promise<void>;
|
||||
updateToken: (id: string, update: Partial<Token>) => Promise<void>;
|
||||
getToken: (tokenId: string) => Promise<Token | undefined>;
|
||||
addToken: AddTokenEventHandler;
|
||||
tokenGroups: Group[];
|
||||
removeTokens: RemoveTokensEventHandler;
|
||||
updateToken: UpdateTokenEventHandler;
|
||||
getToken: GetTokenEventHandler;
|
||||
tokensById: Record<string, Token>;
|
||||
tokensLoading: boolean;
|
||||
updateTokenGroups: (groups: any[]) => void;
|
||||
updateTokensHidden: (ids: string[], hideInSidebar: boolean) => void;
|
||||
updateTokenGroups: UpdateTokenGroupsEventHandler;
|
||||
updateTokensHidden: UpdateTokensHiddenEventHandler;
|
||||
};
|
||||
|
||||
const TokenDataContext =
|
||||
@ -44,7 +61,7 @@ export function TokenDataProvider({ children }: { children: React.ReactNode }) {
|
||||
[database]
|
||||
);
|
||||
|
||||
const [tokenGroups, setTokenGroups] = useState([]);
|
||||
const [tokenGroups, setTokenGroups] = useState<Group[]>([]);
|
||||
useEffect(() => {
|
||||
async function updateTokenGroups() {
|
||||
const group = await database?.table("groups").get("tokens");
|
||||
@ -55,7 +72,7 @@ export function TokenDataProvider({ children }: { children: React.ReactNode }) {
|
||||
}
|
||||
}, [tokenGroupQuery, database]);
|
||||
|
||||
const getToken = useCallback(
|
||||
const getToken = useCallback<GetTokenEventHandler>(
|
||||
async (tokenId) => {
|
||||
let token = await database?.table("tokens").get(tokenId);
|
||||
return token;
|
||||
@ -64,7 +81,7 @@ export function TokenDataProvider({ children }: { children: React.ReactNode }) {
|
||||
);
|
||||
|
||||
// Add token and add it to the token group
|
||||
const addToken = useCallback(
|
||||
const addToken = useCallback<AddTokenEventHandler>(
|
||||
async (token) => {
|
||||
if (database) {
|
||||
await database.table("tokens").add(token);
|
||||
@ -77,7 +94,7 @@ export function TokenDataProvider({ children }: { children: React.ReactNode }) {
|
||||
[database]
|
||||
);
|
||||
|
||||
const removeTokens = useCallback(
|
||||
const removeTokens = useCallback<RemoveTokensEventHandler>(
|
||||
async (ids) => {
|
||||
if (database) {
|
||||
const tokens = await database.table("tokens").bulkGet(ids);
|
||||
@ -100,14 +117,14 @@ export function TokenDataProvider({ children }: { children: React.ReactNode }) {
|
||||
[database]
|
||||
);
|
||||
|
||||
const updateToken = useCallback(
|
||||
const updateToken = useCallback<UpdateTokenEventHandler>(
|
||||
async (id, update) => {
|
||||
await database?.table("tokens").update(id, update);
|
||||
},
|
||||
[database]
|
||||
);
|
||||
|
||||
const updateTokensHidden = useCallback(
|
||||
const updateTokensHidden = useCallback<UpdateTokensHiddenEventHandler>(
|
||||
async (ids: string[], hideInSidebar: boolean) => {
|
||||
await Promise.all(
|
||||
ids.map((id) => database?.table("tokens").update(id, { hideInSidebar }))
|
||||
@ -116,8 +133,8 @@ export function TokenDataProvider({ children }: { children: React.ReactNode }) {
|
||||
[database]
|
||||
);
|
||||
|
||||
const updateTokenGroups = useCallback(
|
||||
async (groups) => {
|
||||
const updateTokenGroups = useCallback<UpdateTokenGroupsEventHandler>(
|
||||
async (groups: Group[]) => {
|
||||
// Update group state immediately to avoid animation delay
|
||||
setTokenGroups(groups);
|
||||
await database?.table("groups").update("tokens", { items: groups });
|
||||
|
@ -5,14 +5,14 @@ import { useSettings } from "../contexts/SettingsContext";
|
||||
|
||||
/**
|
||||
* Helper to get and set nested settings that are saved in local storage
|
||||
* @param {String} path The path to the setting within the Settings object provided by the SettingsContext
|
||||
* @param {string} path The path to the setting within the Settings object provided by the SettingsContext
|
||||
*/
|
||||
function useSetting(path) {
|
||||
function useSetting<Type>(path: string): [Type, (value: Type) => void] {
|
||||
const { settings, setSettings } = useSettings();
|
||||
|
||||
const setting = get(settings, path);
|
||||
const setting = get(settings, path) as Type;
|
||||
|
||||
const setSetting = (value) =>
|
||||
const setSetting = (value: Type) =>
|
||||
setSettings((prev) => {
|
||||
const updated = set({ ...prev }, path, value);
|
||||
return updated;
|
@ -9,13 +9,16 @@ import TokenPreview from "../components/token/TokenPreview";
|
||||
import { isEmpty } from "../helpers/shared";
|
||||
|
||||
import useResponsiveLayout from "../hooks/useResponsiveLayout";
|
||||
|
||||
import { Token } from "../types/Token";
|
||||
|
||||
import { UpdateTokenEventHandler } from "../contexts/TokenDataContext";
|
||||
|
||||
type EditModalProps = {
|
||||
isOpen: boolean;
|
||||
onDone: () => void;
|
||||
token: Token;
|
||||
onUpdateToken: (id: string, update: Partial<Token>) => void;
|
||||
onUpdateToken: UpdateTokenEventHandler;
|
||||
};
|
||||
|
||||
function EditTokenModal({
|
||||
|
@ -2,9 +2,11 @@ import { Box, Label, Flex, Button, Text } from "theme-ui";
|
||||
|
||||
import Modal from "../components/Modal";
|
||||
|
||||
import { RequestCloseEventHandler } from "../types/Events";
|
||||
|
||||
type GameExpiredModalProps = {
|
||||
isOpen: boolean;
|
||||
onRequestClose: () => void;
|
||||
onRequestClose: RequestCloseEventHandler;
|
||||
};
|
||||
|
||||
function GameExpiredModal({ isOpen, onRequestClose }: GameExpiredModalProps) {
|
||||
|
@ -5,11 +5,13 @@ import Modal from "../components/Modal";
|
||||
import Markdown from "../components/Markdown";
|
||||
import Link from "../components/Link";
|
||||
|
||||
import { RequestCloseEventHandler } from "../types/Events";
|
||||
|
||||
const gettingStarted = raw("../docs/howTo/gettingStarted.md");
|
||||
|
||||
type GettingStartedModalProps = {
|
||||
isOpen: boolean;
|
||||
onRequestClose: () => void;
|
||||
onRequestClose: RequestCloseEventHandler;
|
||||
};
|
||||
|
||||
function GettingStartedModal({
|
||||
|
@ -3,11 +3,15 @@ import { Box, Input, Button, Label, Flex } from "theme-ui";
|
||||
|
||||
import Modal from "../components/Modal";
|
||||
|
||||
import { RequestCloseEventHandler } from "../types/Events";
|
||||
|
||||
export type GroupNameEventHandler = (name: string) => void;
|
||||
|
||||
type GroupNameModalProps = {
|
||||
isOpen: boolean;
|
||||
onRequestClose: () => void;
|
||||
onRequestClose: RequestCloseEventHandler;
|
||||
name: string;
|
||||
onSubmit: (name: string) => void;
|
||||
onSubmit: GroupNameEventHandler;
|
||||
};
|
||||
|
||||
function GroupNameModal({
|
||||
|
@ -21,6 +21,7 @@ import { Map } from "../types/Map";
|
||||
import { MapState } from "../types/MapState";
|
||||
import { Token } from "../types/Token";
|
||||
import { Group } from "../types/Group";
|
||||
import { RequestCloseEventHandler } from "../types/Events";
|
||||
|
||||
const importDBName = "OwlbearRodeoImportDB";
|
||||
|
||||
@ -36,7 +37,7 @@ function ImportExportModal({
|
||||
onRequestClose,
|
||||
}: {
|
||||
isOpen: boolean;
|
||||
onRequestClose: () => void;
|
||||
onRequestClose: RequestCloseEventHandler;
|
||||
}) {
|
||||
const { worker } = useDatabase();
|
||||
const userId = useUserId();
|
||||
|
@ -4,9 +4,11 @@ import { useHistory } from "react-router-dom";
|
||||
|
||||
import Modal from "../components/Modal";
|
||||
|
||||
import { RequestCloseEventHandler } from "../types/Events";
|
||||
|
||||
type JoinModalProps = {
|
||||
isOpen: boolean;
|
||||
onRequestClose: () => void;
|
||||
onRequestClose: RequestCloseEventHandler;
|
||||
};
|
||||
|
||||
function JoinModal({ isOpen, onRequestClose }: JoinModalProps) {
|
||||
|
@ -12,21 +12,7 @@ import { Map } from "../types/Map";
|
||||
import { Group, GroupContainer } from "../types/Group";
|
||||
import { MapState } from "../types/MapState";
|
||||
import { Token } from "../types/Token";
|
||||
|
||||
type SelectDataProps = {
|
||||
isOpen: boolean;
|
||||
onRequestClose: () => void;
|
||||
onConfirm: (
|
||||
checkedMaps: SelectData[],
|
||||
checkedTokens: SelectData[],
|
||||
checkedMapGroups: Group[],
|
||||
checkedTokenGroups: Group[]
|
||||
) => void;
|
||||
confirmText: string;
|
||||
label: string;
|
||||
databaseName: string;
|
||||
filter: (table: string, data: Map | MapState | Token, id: string) => boolean;
|
||||
};
|
||||
import { RequestCloseEventHandler } from "../types/Events";
|
||||
|
||||
export type SelectData = {
|
||||
name: string;
|
||||
@ -35,6 +21,23 @@ export type SelectData = {
|
||||
checked: boolean;
|
||||
};
|
||||
|
||||
export type ConfirmDataEventHandler = (
|
||||
checkedMaps: SelectData[],
|
||||
checkedTokens: SelectData[],
|
||||
checkedMapGroups: Group[],
|
||||
checkedTokenGroups: Group[]
|
||||
) => void;
|
||||
|
||||
type SelectDataProps = {
|
||||
isOpen: boolean;
|
||||
onRequestClose: RequestCloseEventHandler;
|
||||
onConfirm: ConfirmDataEventHandler;
|
||||
confirmText: string;
|
||||
label: string;
|
||||
databaseName: string;
|
||||
filter: (table: string, data: Map | MapState | Token, id: string) => boolean;
|
||||
};
|
||||
|
||||
type DataRecord = Record<string, SelectData>;
|
||||
|
||||
function SelectDataModal({
|
||||
|
@ -8,12 +8,16 @@ import { dice } from "../dice";
|
||||
|
||||
import useResponsiveLayout from "../hooks/useResponsiveLayout";
|
||||
|
||||
import {
|
||||
DiceSelectEventHandler,
|
||||
RequestCloseEventHandler,
|
||||
} from "../types/Events";
|
||||
import { DefaultDice } from "../types/Dice";
|
||||
|
||||
type SelectDiceProps = {
|
||||
isOpen: boolean;
|
||||
onRequestClose: () => void;
|
||||
onDone: (dice: DefaultDice) => void;
|
||||
onRequestClose: RequestCloseEventHandler;
|
||||
onDone: DiceSelectEventHandler;
|
||||
defaultDice: DefaultDice;
|
||||
};
|
||||
|
||||
|
@ -31,13 +31,17 @@ import { GroupProvider } from "../contexts/GroupContext";
|
||||
import { TileDragProvider } from "../contexts/TileDragContext";
|
||||
|
||||
import { Map } from "../types/Map";
|
||||
import { MapState } from "../types/MapState";
|
||||
import {
|
||||
MapChangeEventHandler,
|
||||
MapResetEventHandler,
|
||||
RequestCloseEventHandler,
|
||||
} from "../types/Events";
|
||||
|
||||
type SelectMapProps = {
|
||||
isOpen: boolean;
|
||||
onDone: () => void;
|
||||
onMapChange: (map?: Map, mapState?: MapState) => void;
|
||||
onMapReset: (newState: MapState) => void;
|
||||
onDone: RequestCloseEventHandler;
|
||||
onMapChange: MapChangeEventHandler;
|
||||
onMapReset: MapResetEventHandler;
|
||||
currentMap?: Map;
|
||||
};
|
||||
|
||||
@ -294,7 +298,7 @@ function SelectMapModal({
|
||||
</TileDragProvider>
|
||||
<MapEditBar
|
||||
currentMap={currentMap}
|
||||
disabled={isLoading || editingMapId}
|
||||
disabled={isLoading || !!editingMapId}
|
||||
onMapChange={onMapChange}
|
||||
onMapReset={onMapReset}
|
||||
onLoad={setIsLoading}
|
||||
|
@ -36,11 +36,15 @@ import { TileDragProvider } from "../contexts/TileDragContext";
|
||||
import { useMapStage } from "../contexts/MapStageContext";
|
||||
|
||||
import { TokenState } from "../types/TokenState";
|
||||
import {
|
||||
MapTokensStateCreateHandler,
|
||||
RequestCloseEventHandler,
|
||||
} from "../types/Events";
|
||||
|
||||
type SelectTokensModalProps = {
|
||||
isOpen: boolean;
|
||||
onRequestClose: () => void;
|
||||
onMapTokensStateCreate: (states: TokenState[]) => void;
|
||||
onRequestClose: RequestCloseEventHandler;
|
||||
onMapTokensStateCreate: MapTokensStateCreateHandler;
|
||||
};
|
||||
|
||||
function SelectTokensModal({
|
||||
|
@ -21,24 +21,27 @@ import useSetting from "../hooks/useSetting";
|
||||
|
||||
import ConfirmModal from "./ConfirmModal";
|
||||
import ImportExportModal from "./ImportExportModal";
|
||||
import { MapState } from "../components/map/Map";
|
||||
|
||||
import { MapState } from "../types/MapState";
|
||||
import { RequestCloseEventHandler } from "../types/Events";
|
||||
|
||||
function SettingsModal({
|
||||
isOpen,
|
||||
onRequestClose,
|
||||
}: {
|
||||
isOpen: boolean;
|
||||
onRequestClose: () => void;
|
||||
onRequestClose: RequestCloseEventHandler;
|
||||
}) {
|
||||
const { database, databaseStatus } = useDatabase();
|
||||
const userId = useUserId();
|
||||
const [isDeleteModalOpen, setIsDeleteModalOpen] = useState(false);
|
||||
const [labelSize, setLabelSize] = useSetting("map.labelSize");
|
||||
const [gridSnappingSensitivity, setGridSnappingSensitivity] = useSetting(
|
||||
"map.gridSnappingSensitivity"
|
||||
);
|
||||
const [showFogGuides, setShowFogGuides] = useSetting("fog.showGuides");
|
||||
const [fogEditOpacity, setFogEditOpacity] = useSetting("fog.editOpacity");
|
||||
const [labelSize, setLabelSize] = useSetting<number>("map.labelSize");
|
||||
const [gridSnappingSensitivity, setGridSnappingSensitivity] =
|
||||
useSetting<number>("map.gridSnappingSensitivity");
|
||||
const [showFogGuides, setShowFogGuides] =
|
||||
useSetting<boolean>("fog.showGuides");
|
||||
const [fogEditOpacity, setFogEditOpacity] =
|
||||
useSetting<number>("fog.editOpacity");
|
||||
const [storageEstimate, setStorageEstimate] = useState<StorageEstimate>();
|
||||
const [isImportExportModalOpen, setIsImportExportModalOpen] = useState(false);
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
|
@ -9,7 +9,15 @@ import useSetting from "../hooks/useSetting";
|
||||
|
||||
import Modal from "../components/Modal";
|
||||
|
||||
function StartModal({ isOpen, onRequestClose }: { isOpen: boolean, onRequestClose: () => void}) {
|
||||
import { RequestCloseEventHandler } from "../types/Events";
|
||||
|
||||
function StartModal({
|
||||
isOpen,
|
||||
onRequestClose,
|
||||
}: {
|
||||
isOpen: boolean;
|
||||
onRequestClose: RequestCloseEventHandler;
|
||||
}) {
|
||||
let history = useHistory();
|
||||
const { password, setPassword } = useAuth();
|
||||
|
||||
@ -17,7 +25,7 @@ function StartModal({ isOpen, onRequestClose }: { isOpen: boolean, onRequestClos
|
||||
setPassword(event.target.value);
|
||||
}
|
||||
|
||||
const [usePassword, setUsePassword] = useSetting("game.usePassword");
|
||||
const [usePassword, setUsePassword] = useSetting<boolean>("game.usePassword");
|
||||
function handleUsePasswordChange(event: ChangeEvent<HTMLInputElement>) {
|
||||
setUsePassword(event.target.checked);
|
||||
}
|
||||
|
@ -2,17 +2,22 @@ import { Box, Text, Button, Label, Flex } from "theme-ui";
|
||||
|
||||
import Modal from "../components/Modal";
|
||||
|
||||
import { RequestCloseEventHandler } from "../types/Events";
|
||||
|
||||
export type StreamStartEventHandler = () => void;
|
||||
export type StreamEndEventHandler = (stream: MediaStream) => void;
|
||||
|
||||
type StartStreamProps = {
|
||||
isOpen: boolean,
|
||||
onRequestClose: () => void,
|
||||
isSupported: boolean,
|
||||
unavailableMessage: JSX.Element,
|
||||
stream: MediaStream,
|
||||
noAudioTrack: boolean,
|
||||
noAudioMessage: JSX.Element,
|
||||
onStreamStart: any,
|
||||
onStreamEnd: any,
|
||||
}
|
||||
isOpen: boolean;
|
||||
onRequestClose: RequestCloseEventHandler;
|
||||
isSupported: boolean;
|
||||
unavailableMessage: JSX.Element;
|
||||
stream: MediaStream;
|
||||
noAudioTrack: boolean;
|
||||
noAudioMessage: JSX.Element;
|
||||
onStreamStart: StreamStartEventHandler;
|
||||
onStreamEnd: StreamEndEventHandler;
|
||||
};
|
||||
|
||||
function StartStreamModal({
|
||||
isOpen,
|
||||
|
@ -7,13 +7,19 @@ import { getHMSDuration, getDurationHMS } from "../helpers/timer";
|
||||
|
||||
import useSetting from "../hooks/useSetting";
|
||||
|
||||
import { RequestCloseEventHandler } from "../types/Events";
|
||||
import { Timer } from "../types/Timer";
|
||||
|
||||
export type TimerStartEventHandler = (event: Timer) => void;
|
||||
export type TimerStopEventHandler = () => void;
|
||||
|
||||
type StartTimerProps = {
|
||||
isOpen: boolean,
|
||||
onRequestClose: () => void,
|
||||
onTimerStart: any,
|
||||
onTimerStop: any,
|
||||
timer: any,
|
||||
}
|
||||
isOpen: boolean;
|
||||
onRequestClose: RequestCloseEventHandler;
|
||||
onTimerStart: TimerStartEventHandler;
|
||||
onTimerStop: TimerStopEventHandler;
|
||||
timer?: Timer;
|
||||
};
|
||||
|
||||
function StartTimerModal({
|
||||
isOpen,
|
||||
@ -27,9 +33,9 @@ function StartTimerModal({
|
||||
inputRef.current && inputRef.current.focus();
|
||||
}
|
||||
|
||||
const [hour, setHour] = useSetting("timer.hour");
|
||||
const [minute, setMinute] = useSetting("timer.minute");
|
||||
const [second, setSecond] = useSetting("timer.second");
|
||||
const [hour, setHour] = useSetting<number>("timer.hour");
|
||||
const [minute, setMinute] = useSetting<number>("timer.minute");
|
||||
const [second, setSecond] = useSetting<number>("timer.second");
|
||||
|
||||
function handleSubmit(event: ChangeEvent<HTMLInputElement>) {
|
||||
event.preventDefault();
|
||||
@ -85,10 +91,10 @@ function StartTimerModal({
|
||||
</Text>
|
||||
<Input
|
||||
sx={inputStyle}
|
||||
value={`${timer ? timerHMS.hour : hour}`}
|
||||
value={`${timerHMS ? timerHMS.hour : hour}`}
|
||||
onChange={(e) => setHour(parseValue(e.target.value, 24))}
|
||||
type="number"
|
||||
disabled={timer}
|
||||
disabled={!!timer}
|
||||
min={0}
|
||||
max={24}
|
||||
/>
|
||||
@ -97,11 +103,11 @@ function StartTimerModal({
|
||||
</Text>
|
||||
<Input
|
||||
sx={inputStyle}
|
||||
value={`${timer ? timerHMS.minute : minute}`}
|
||||
value={`${timerHMS ? timerHMS.minute : minute}`}
|
||||
onChange={(e) => setMinute(parseValue(e.target.value, 59))}
|
||||
type="number"
|
||||
ref={inputRef}
|
||||
disabled={timer}
|
||||
disabled={!!timer}
|
||||
min={0}
|
||||
max={59}
|
||||
/>
|
||||
@ -110,10 +116,10 @@ function StartTimerModal({
|
||||
</Text>
|
||||
<Input
|
||||
sx={inputStyle}
|
||||
value={`${timer ? timerHMS.second : second}`}
|
||||
value={`${timerHMS ? timerHMS.second : second}`}
|
||||
onChange={(e) => setSecond(parseValue(e.target.value, 59))}
|
||||
type="number"
|
||||
disabled={timer}
|
||||
disabled={!!timer}
|
||||
min={0}
|
||||
max={59}
|
||||
/>
|
||||
|
14
src/types/Events.ts
Normal file
14
src/types/Events.ts
Normal file
@ -0,0 +1,14 @@
|
||||
import { DefaultDice } from "./Dice";
|
||||
import { Map } from "./Map";
|
||||
import { MapState } from "./MapState";
|
||||
import { TokenState } from "./TokenState";
|
||||
|
||||
export type MapChangeEventHandler = (map?: Map, mapState?: MapState) => void;
|
||||
|
||||
export type MapResetEventHandler = (newState: MapState) => void;
|
||||
|
||||
export type DiceSelectEventHandler = (dice: DefaultDice) => void;
|
||||
|
||||
export type RequestCloseEventHandler = () => void;
|
||||
|
||||
export type MapTokensStateCreateHandler = (states: TokenState[]) => void;
|
@ -2998,6 +2998,13 @@
|
||||
dependencies:
|
||||
"@types/lodash" "*"
|
||||
|
||||
"@types/lodash.set@^4.3.6":
|
||||
version "4.3.6"
|
||||
resolved "https://registry.yarnpkg.com/@types/lodash.set/-/lodash.set-4.3.6.tgz#33e635c2323f855359225df6a5c8c6f1f1908264"
|
||||
integrity sha512-ZeGDDlnRYTvS31Laij0RsSaguIUSBTYIlJFKL3vm3T2OAZAQj2YpSvVWJc0WiG4jqg9fGX6PAPGvDqBcHfSgFg==
|
||||
dependencies:
|
||||
"@types/lodash" "*"
|
||||
|
||||
"@types/lodash@*":
|
||||
version "4.14.170"
|
||||
resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.170.tgz#0d67711d4bf7f4ca5147e9091b847479b87925d6"
|
||||
|
Loading…
Reference in New Issue
Block a user