Add token edit bar back
This commit is contained in:
parent
0f2776d774
commit
1a34dc756a
147
src/components/token/TokenEditBar.js
Normal file
147
src/components/token/TokenEditBar.js
Normal file
@ -0,0 +1,147 @@
|
||||
import React, { useState, useEffect } from "react";
|
||||
import { Flex, Close, IconButton } from "theme-ui";
|
||||
|
||||
import { groupsFromIds, itemsFromGroups } from "../../helpers/group";
|
||||
|
||||
import ConfirmModal from "../../modals/ConfirmModal";
|
||||
|
||||
import TokenShowIcon from "../../icons/TokenShowIcon";
|
||||
import TokenHideIcon from "../../icons/TokenHideIcon";
|
||||
import RemoveTokenIcon from "../../icons/RemoveTokenIcon";
|
||||
|
||||
import { useGroup } from "../../contexts/GroupContext";
|
||||
import { useTokenData } from "../../contexts/TokenDataContext";
|
||||
import { useKeyboard } from "../../contexts/KeyboardContext";
|
||||
|
||||
import shortcuts from "../../shortcuts";
|
||||
|
||||
function TokenEditBar({ disabled, onLoad }) {
|
||||
const { tokens, removeTokens, updateTokens } = useTokenData();
|
||||
|
||||
const {
|
||||
groups: allGroups,
|
||||
selectedGroupIds,
|
||||
onGroupSelect,
|
||||
openGroupId,
|
||||
openGroupItems,
|
||||
} = useGroup();
|
||||
|
||||
const groups = openGroupId ? openGroupItems : allGroups;
|
||||
|
||||
const [hasSelectedDefaultToken, setHasSelectedDefaultToken] = useState(false);
|
||||
const [allTokensVisible, setAllTokensVisisble] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
const selectedGroups = groupsFromIds(selectedGroupIds, groups);
|
||||
const selectedTokens = itemsFromGroups(selectedGroups, tokens);
|
||||
|
||||
setHasSelectedDefaultToken(
|
||||
selectedTokens.some((token) => token.type === "default")
|
||||
);
|
||||
setAllTokensVisisble(selectedTokens.every((token) => !token.hideInSidebar));
|
||||
}, [selectedGroupIds, tokens, groups]);
|
||||
|
||||
function getSelectedTokens() {
|
||||
const selectedGroups = groupsFromIds(selectedGroupIds, groups);
|
||||
return itemsFromGroups(selectedGroups, tokens);
|
||||
}
|
||||
|
||||
const [isTokensRemoveModalOpen, setIsTokensRemoveModalOpen] = useState(false);
|
||||
async function handleTokensRemove() {
|
||||
onLoad(true);
|
||||
setIsTokensRemoveModalOpen(false);
|
||||
const selectedTokens = getSelectedTokens();
|
||||
const selectedTokenIds = selectedTokens.map((token) => token.id);
|
||||
await removeTokens(selectedTokenIds);
|
||||
onGroupSelect();
|
||||
onLoad(false);
|
||||
}
|
||||
|
||||
async function handleTokensHide(hideInSidebar) {
|
||||
onLoad(true);
|
||||
const selectedTokens = getSelectedTokens();
|
||||
const selectedTokenIds = selectedTokens.map((token) => token.id);
|
||||
await updateTokens(selectedTokenIds, { hideInSidebar });
|
||||
onLoad(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Shortcuts
|
||||
*/
|
||||
function handleKeyDown(event) {
|
||||
if (disabled) {
|
||||
return;
|
||||
}
|
||||
if (shortcuts.delete(event)) {
|
||||
const selectedTokens = getSelectedTokens();
|
||||
// Selected tokens and none are default
|
||||
if (
|
||||
selectedTokens.length > 0 &&
|
||||
!selectedTokens.some((token) => token.type === "default")
|
||||
) {
|
||||
// Ensure all other modals are closed
|
||||
setIsTokensRemoveModalOpen(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
useKeyboard(handleKeyDown);
|
||||
|
||||
if (selectedGroupIds.length === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
let hideTitle = "";
|
||||
if (allTokensVisible) {
|
||||
hideTitle = "Hide Selected Token(s) in Sidebar";
|
||||
} else {
|
||||
hideTitle = "Show Selected Token(s) in Sidebar";
|
||||
}
|
||||
|
||||
return (
|
||||
<Flex
|
||||
sx={{
|
||||
position: "absolute",
|
||||
bottom: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
justifyContent: "space-between",
|
||||
}}
|
||||
bg="overlay"
|
||||
>
|
||||
<Close
|
||||
title="Clear Selection"
|
||||
aria-label="Clear Selection"
|
||||
onClick={() => onGroupSelect()}
|
||||
/>
|
||||
<Flex>
|
||||
<IconButton
|
||||
aria-label={hideTitle}
|
||||
title={hideTitle}
|
||||
disabled={hasSelectedDefaultToken}
|
||||
onClick={() => handleTokensHide(allTokensVisible)}
|
||||
>
|
||||
{allTokensVisible ? <TokenShowIcon /> : <TokenHideIcon />}
|
||||
</IconButton>
|
||||
<IconButton
|
||||
aria-label="Remove Selected Token(s)"
|
||||
title="Remove Selected Token(s)"
|
||||
onClick={() => handleTokensRemove()}
|
||||
disabled={hasSelectedDefaultToken}
|
||||
>
|
||||
<RemoveTokenIcon />
|
||||
</IconButton>
|
||||
</Flex>
|
||||
<ConfirmModal
|
||||
isOpen={isTokensRemoveModalOpen}
|
||||
onRequestClose={() => setIsTokensRemoveModalOpen(false)}
|
||||
onConfirm={handleTokensRemove}
|
||||
confirmText="Remove"
|
||||
label="Remove Selected Token(s)"
|
||||
description="This operation cannot be undone."
|
||||
/>
|
||||
</Flex>
|
||||
);
|
||||
}
|
||||
|
||||
export default TokenEditBar;
|
@ -11,16 +11,13 @@ import ImageDrop from "../components/ImageDrop";
|
||||
import LoadingOverlay from "../components/LoadingOverlay";
|
||||
|
||||
import TokenTiles from "../components/token/TokenTiles";
|
||||
import TokenEditBar from "../components/token/TokenEditBar";
|
||||
|
||||
import TilesOverlay from "../components/tile/TilesOverlay";
|
||||
import TilesContainer from "../components/tile/TilesContainer";
|
||||
import TilesAddDroppable from "../components/tile/TilesAddDroppable";
|
||||
|
||||
import {
|
||||
groupsFromIds,
|
||||
itemsFromGroups,
|
||||
getGroupItems,
|
||||
} from "../helpers/group";
|
||||
import { getGroupItems } from "../helpers/group";
|
||||
import {
|
||||
createTokenFromFile,
|
||||
createTokenState,
|
||||
@ -32,14 +29,11 @@ import useResponsiveLayout from "../hooks/useResponsiveLayout";
|
||||
|
||||
import { useTokenData } from "../contexts/TokenDataContext";
|
||||
import { useAuth } from "../contexts/AuthContext";
|
||||
import { useKeyboard } from "../contexts/KeyboardContext";
|
||||
import { useAssets } from "../contexts/AssetsContext";
|
||||
import { GroupProvider } from "../contexts/GroupContext";
|
||||
import { TileDragProvider } from "../contexts/TileDragContext";
|
||||
import { useMapStage } from "../contexts/MapStageContext";
|
||||
|
||||
import shortcuts from "../shortcuts";
|
||||
|
||||
function SelectTokensModal({ isOpen, onRequestClose, onMapTokensStateCreate }) {
|
||||
const { addToast } = useToasts();
|
||||
|
||||
@ -47,8 +41,6 @@ function SelectTokensModal({ isOpen, onRequestClose, onMapTokensStateCreate }) {
|
||||
const {
|
||||
tokens,
|
||||
addToken,
|
||||
removeTokens,
|
||||
// updateTokens,
|
||||
tokensLoading,
|
||||
tokenGroups,
|
||||
updateTokenGroups,
|
||||
@ -132,32 +124,7 @@ function SelectTokensModal({ isOpen, onRequestClose, onMapTokensStateCreate }) {
|
||||
/**
|
||||
* Token controls
|
||||
*/
|
||||
const [isEditModalOpen, setIsEditModalOpen] = useState(false);
|
||||
const [selectedGroupIds, setSelectedGroupIds] = useState([]);
|
||||
|
||||
function getSelectedTokens() {
|
||||
const groups = groupsFromIds(selectedGroupIds, tokenGroups);
|
||||
return itemsFromGroups(groups, tokens);
|
||||
}
|
||||
|
||||
const [isTokensRemoveModalOpen, setIsTokensRemoveModalOpen] = useState(false);
|
||||
async function handleTokensRemove() {
|
||||
setIsLoading(true);
|
||||
setIsTokensRemoveModalOpen(false);
|
||||
const selectedTokens = getSelectedTokens();
|
||||
const selectedTokenIds = selectedTokens.map((token) => token.id);
|
||||
await removeTokens(selectedTokenIds);
|
||||
setSelectedGroupIds([]);
|
||||
setIsLoading(false);
|
||||
}
|
||||
|
||||
// async function handleTokensHide(hideInSidebar) {
|
||||
// setIsLoading(true);
|
||||
// const selectedTokens = getSelectedTokens();
|
||||
// const selectedTokenIds = selectedTokens.map((token) => token.id);
|
||||
// await updateTokens(selectedTokenIds, { hideInSidebar });
|
||||
// setIsLoading(false);
|
||||
// }
|
||||
const [editingTokenId, setEditingTokenId] = useState();
|
||||
|
||||
const mapStageRef = useMapStage();
|
||||
function handleTokensAddToMap(groupIds, rect) {
|
||||
@ -206,29 +173,6 @@ function SelectTokensModal({ isOpen, onRequestClose, onMapTokensStateCreate }) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Shortcuts
|
||||
*/
|
||||
function handleKeyDown(event) {
|
||||
if (!isOpen) {
|
||||
return;
|
||||
}
|
||||
if (shortcuts.delete(event)) {
|
||||
const selectedTokens = getSelectedTokens();
|
||||
// Selected tokens and none are default
|
||||
if (
|
||||
selectedTokens.length > 0 &&
|
||||
!selectedTokens.some((token) => token.type === "default")
|
||||
) {
|
||||
// Ensure all other modals are closed
|
||||
setIsEditModalOpen(false);
|
||||
setIsTokensRemoveModalOpen(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
useKeyboard(handleKeyDown);
|
||||
|
||||
const layout = useResponsiveLayout();
|
||||
|
||||
const [modalSize, setModalSize] = useState({ width: 0, height: 0 });
|
||||
@ -256,27 +200,26 @@ function SelectTokensModal({ isOpen, onRequestClose, onMapTokensStateCreate }) {
|
||||
handleHeight
|
||||
onResize={handleModalResize}
|
||||
>
|
||||
<Flex
|
||||
sx={{
|
||||
flexDirection: "column",
|
||||
}}
|
||||
<GroupProvider
|
||||
groups={tokenGroups}
|
||||
onGroupsChange={updateTokenGroups}
|
||||
disabled={!isOpen}
|
||||
>
|
||||
<Label pt={2} pb={1}>
|
||||
Edit or import a token
|
||||
</Label>
|
||||
<Box sx={{ position: "relative" }}>
|
||||
<GroupProvider
|
||||
groups={tokenGroups}
|
||||
onGroupsChange={updateTokenGroups}
|
||||
onGroupsSelect={setSelectedGroupIds}
|
||||
disabled={!isOpen}
|
||||
>
|
||||
<Flex
|
||||
sx={{
|
||||
flexDirection: "column",
|
||||
}}
|
||||
>
|
||||
<Label pt={2} pb={1}>
|
||||
Edit or import a token
|
||||
</Label>
|
||||
<Box sx={{ position: "relative" }}>
|
||||
<TileDragProvider onDragAdd={handleTokensAddToMap}>
|
||||
<TilesAddDroppable containerSize={modalSize} />
|
||||
<TilesContainer>
|
||||
<TokenTiles
|
||||
tokens={tokens}
|
||||
onTokenEdit={() => setIsEditModalOpen(true)}
|
||||
onTokenEdit={setEditingTokenId}
|
||||
/>
|
||||
</TilesContainer>
|
||||
</TileDragProvider>
|
||||
@ -285,42 +228,36 @@ function SelectTokensModal({ isOpen, onRequestClose, onMapTokensStateCreate }) {
|
||||
<TilesOverlay>
|
||||
<TokenTiles
|
||||
tokens={tokens}
|
||||
onTokenEdit={() => setIsEditModalOpen(true)}
|
||||
onTokenEdit={setEditingTokenId}
|
||||
subgroup
|
||||
/>
|
||||
</TilesOverlay>
|
||||
</TileDragProvider>
|
||||
</GroupProvider>
|
||||
</Box>
|
||||
|
||||
<Button
|
||||
variant="primary"
|
||||
disabled={isLoading}
|
||||
onClick={onRequestClose}
|
||||
mt={2}
|
||||
>
|
||||
Done
|
||||
</Button>
|
||||
</Flex>
|
||||
<TokenEditBar
|
||||
onLoad={setIsLoading}
|
||||
disabled={isLoading || !isOpen}
|
||||
/>
|
||||
</Box>
|
||||
<Button
|
||||
variant="primary"
|
||||
disabled={isLoading}
|
||||
onClick={onRequestClose}
|
||||
mt={2}
|
||||
>
|
||||
Done
|
||||
</Button>
|
||||
</Flex>
|
||||
</GroupProvider>
|
||||
</ReactResizeDetector>
|
||||
</ImageDrop>
|
||||
{(isLoading || tokensLoading) && <LoadingOverlay bg="overlay" />}
|
||||
<EditTokenModal
|
||||
isOpen={isEditModalOpen}
|
||||
onDone={() => setIsEditModalOpen(false)}
|
||||
isOpen={!!editingTokenId}
|
||||
onDone={() => setEditingTokenId()}
|
||||
token={
|
||||
selectedGroupIds.length === 1 &&
|
||||
tokens.find((token) => token.id === selectedGroupIds[0])
|
||||
editingTokenId && tokens.find((token) => token.id === editingTokenId)
|
||||
}
|
||||
onTokenUpdate={updateToken}
|
||||
/>
|
||||
<ConfirmModal
|
||||
isOpen={isTokensRemoveModalOpen}
|
||||
onRequestClose={() => setIsTokensRemoveModalOpen(false)}
|
||||
onConfirm={handleTokensRemove}
|
||||
confirmText="Remove"
|
||||
label="Remove Token(s)"
|
||||
description="This operation cannot be undone."
|
||||
onUpdateToken={updateToken}
|
||||
/>
|
||||
<ConfirmModal
|
||||
isOpen={isLargeImageWarningModalOpen}
|
||||
|
Loading…
Reference in New Issue
Block a user