Skip to content

Commit

Permalink
fix: fix current tab when closing
Browse files Browse the repository at this point in the history
  • Loading branch information
moonayyur committed Mar 24, 2024
1 parent 164a1e0 commit 410af6b
Show file tree
Hide file tree
Showing 5 changed files with 56 additions and 87 deletions.
33 changes: 27 additions & 6 deletions src/components/images/ImagesPanel.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import styled from '@emotion/styled';
import { useCallback, useMemo } from 'react';
import { Toolbar } from 'react-science/ui';
import { Button } from 'react-science/ui';

import useCurrentTab from '../../hooks/useCurrentTab';
import useData from '../../hooks/useData';
import useDataDispatch from '../../hooks/useDataDispatch';
import useViewDispatch from '../../hooks/useViewDispatch';
import { OPEN_TAB } from '../../state/view/ViewActionTypes';
import CloseTool from '../tool/CloseTool';
import { CLOSE_IMAGE } from '../../state/data/DataActionTypes';
import { CLOSE_TAB, OPEN_TAB } from '../../state/view/ViewActionTypes';

const TabTitle = styled.div`
display: flex;
Expand All @@ -30,6 +31,7 @@ const TabItem = styled.div<{ current: boolean }>`
export default function ImagesPanel() {
const { images } = useData();
const viewDispatch = useViewDispatch();
const dataDispatch = useDataDispatch();

const tabsItems = useMemo(
() =>
Expand All @@ -49,6 +51,20 @@ export default function ImagesPanel() {
[viewDispatch],
);

const closeImage = useCallback(
(closeId: string) => {
dataDispatch({ type: CLOSE_IMAGE, payload: closeId });
if (tabsItems.length === 1) {
viewDispatch({ type: CLOSE_TAB });
} else if (currentTab === closeId) {
const lastTab = tabsItems.at(-1)?.id;
const id = lastTab === currentTab ? tabsItems.at(-2)?.id : lastTab;
if (id) viewDispatch({ type: OPEN_TAB, payload: id });
}
},
[dataDispatch, tabsItems, currentTab, viewDispatch],
);

return (
<>
{tabsItems.length > 0 ? (
Expand All @@ -60,9 +76,14 @@ export default function ImagesPanel() {
onClick={() => openTab(item.id)}
>
{item.title}
<Toolbar>
<CloseTool closeId={item.id} />
</Toolbar>
<Button
minimal
icon="cross"
onClick={(e) => {
e.stopPropagation();
closeImage(item.id);
}}
/>
</TabItem>
))}
</div>
Expand Down
53 changes: 3 additions & 50 deletions src/components/layout/CenterPanel.tsx
Original file line number Diff line number Diff line change
@@ -1,52 +1,19 @@
/** @jsxImportSource @emotion/react */
import { Tabs, Tab } from '@blueprintjs/core';
import { css } from '@emotion/react';
import styled from '@emotion/styled';
import { memo, useCallback, useEffect, useMemo } from 'react';
import { memo } from 'react';
import { DropZoneContainer } from 'react-science/ui';

import useCurrentTab from '../../hooks/useCurrentTab';
import useData from '../../hooks/useData';
import useFileLoader from '../../hooks/useFileLoader';
import useViewDispatch from '../../hooks/useViewDispatch';
import { OPEN_TAB } from '../../state/view/ViewActionTypes';
import ImageViewer from '../ImageViewer';

const StyledCenterPanel = styled.div`
width: 100%;
`;

function CenterPanel() {
const { images } = useData();
const viewDispatch = useViewDispatch();

const tabsItems = useMemo(
() =>
Object.keys(images).map((identifier) => ({
id: identifier,
content: (
<ImageViewer key={identifier} identifier={identifier} annotable />
),
})),
[images],
);

const currentTab = useCurrentTab();

const openTab = useCallback(
(identifier: string) => {
viewDispatch({ type: OPEN_TAB, payload: identifier });
},
[viewDispatch],
);

useEffect(() => {
if (tabsItems.length > 0) {
const defaultTab = tabsItems.at(-1);
if (defaultTab) openTab(defaultTab.id);
}
}, [openTab, tabsItems]);

const { handleFileLoad: handleOnDrop } = useFileLoader();

return (
Expand All @@ -55,22 +22,8 @@ function CenterPanel() {
emptyDescription="Drag and drop here either an image or a Pixelium file."
onDrop={handleOnDrop}
>
{tabsItems.length > 0 ? (
<Tabs
selectedTabId={currentTab}
onChange={openTab}
css={css`
height: 100%;
div[role='tabpanel'] {
height: 100%;
margin-top: 0;
}
`}
>
{tabsItems.map((item) => (
<Tab id={item.id} key={item.id} panel={item.content} />
))}
</Tabs>
{currentTab ? (
<ImageViewer key={currentTab} identifier={currentTab} annotable />
) : null}
</DropZoneContainer>
</StyledCenterPanel>
Expand Down
24 changes: 0 additions & 24 deletions src/components/tool/CloseTool.tsx

This file was deleted.

18 changes: 16 additions & 2 deletions src/hooks/useFileLoader.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { v4 as uuid } from '@lukeed/uuid';
import {
fileCollectionFromFiles,
FileCollection,
Expand All @@ -14,7 +15,7 @@ import {
} from '../state/data/DataActionTypes';
import { DataFile } from '../state/data/DataReducer';
import { INITIALIZE_PREFERENCES } from '../state/preferences/PreferenceActionTypes';
import { LOAD_VIEW_STATE } from '../state/view/ViewActionTypes';
import { LOAD_VIEW_STATE, OPEN_TAB } from '../state/view/ViewActionTypes';
import { loadPixeliumBundle } from '../utils/export';

import useDataDispatch from './useDataDispatch';
Expand Down Expand Up @@ -77,7 +78,20 @@ export default function useFileLoader() {
}
}
}
dataDispatch({ type: LOAD_DROP, payload: dataFiles });

const ids = dataFiles.map(() => uuid());
if (dataFiles.length !== ids.length) {
logger.error('The number of files and ids must be the same');
return 0;
}
const files = Object.fromEntries(
ids.map((id, index) => [id, dataFiles[index]]),
);

dataDispatch({ type: LOAD_DROP, payload: files });

const newId = ids.at(-1);
if (newId) viewDispatch({ type: OPEN_TAB, payload: newId });
return dataFiles.length;
},
[dataDispatch, logger, preferencesDispatch, viewDispatch],
Expand Down
15 changes: 10 additions & 5 deletions src/state/data/actions/LoadActions.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { v4 as uuid } from '@lukeed/uuid';
import { Draft } from 'immer';

import {
Expand All @@ -11,7 +10,10 @@ import {
import { DataState, DataFile } from '../DataReducer';

export type SetLoadingAction = DataActionType<typeof SET_LOADING, boolean>;
export type LoadDropAction = DataActionType<typeof LOAD_DROP, DataFile[]>;
export type LoadDropAction = DataActionType<
typeof LOAD_DROP,
Record<string, DataFile>
>;
export type LoadPixeliumAction = DataActionType<
typeof LOAD_PIXELIUM,
DataState
Expand All @@ -25,9 +27,12 @@ export function setLoading(
draft.isLoading = payload;
}

export function loadDrop(draft: Draft<DataState>, payload: DataFile[]) {
for (const file of payload) {
draft.images[uuid()] = file;
export function loadDrop(
draft: Draft<DataState>,
payload: Record<string, DataFile>,
) {
for (const id in payload) {
draft.images[id] = payload[id];
}
}

Expand Down

0 comments on commit 410af6b

Please sign in to comment.