diff --git a/theatre/studio/src/panels/DetailPanel/DetailPanel.tsx b/theatre/studio/src/panels/DetailPanel/DetailPanel.tsx index 0025fff..f64eddc 100644 --- a/theatre/studio/src/panels/DetailPanel/DetailPanel.tsx +++ b/theatre/studio/src/panels/DetailPanel/DetailPanel.tsx @@ -10,7 +10,7 @@ import { } from '@theatre/studio/panels/BasePanel/common' import {pointerEventsAutoInNormalMode} from '@theatre/studio/css' import ObjectDetails from './ObjectDetails' -import ProjectDetails from './ProjectDetails' +import ProjectDetails from './ProjectDetails/ProjectDetails' const Container = styled.div` background-color: transparent; diff --git a/theatre/studio/src/panels/DetailPanel/ProjectDetails.tsx b/theatre/studio/src/panels/DetailPanel/ProjectDetails/ProjectDetails.tsx similarity index 51% rename from theatre/studio/src/panels/DetailPanel/ProjectDetails.tsx rename to theatre/studio/src/panels/DetailPanel/ProjectDetails/ProjectDetails.tsx index 093cada..4746d74 100644 --- a/theatre/studio/src/panels/DetailPanel/ProjectDetails.tsx +++ b/theatre/studio/src/panels/DetailPanel/ProjectDetails/ProjectDetails.tsx @@ -1,13 +1,12 @@ import type Project from '@theatre/core/projects/Project' -import {val} from '@theatre/dataverse' -import {usePrism} from '@theatre/dataverse-react' import getStudio from '@theatre/studio/getStudio' -import {generateDiskStateRevision} from '@theatre/studio/StudioStore/generateDiskStateRevision' import BasicPopover from '@theatre/studio/uiComponents/Popover/BasicPopover' import usePopover from '@theatre/studio/uiComponents/Popover/usePopover' import React, {useCallback, useState} from 'react' import styled from 'styled-components' -import {rowBgColor} from './propEditors/utils/SingleRowPropEditor' +import {rowBgColor} from '@theatre/studio/panels/DetailPanel/propEditors/utils/SingleRowPropEditor' +import StateConflictRow from './StateConflictRow' +import DetailPanelButton from '@theatre/studio/uiComponents/DetailPanelButton' const Container = styled.div` background-color: ${rowBgColor}; @@ -20,26 +19,6 @@ const TheExportRow = styled.div` align-items: stretch; ` -const Button = styled.button<{disabled?: boolean}>` - text-align: center; - padding: 8px; - border-radius: 2px; - border: 1px solid #627b7b87; - background-color: #4b787d3d; - color: #eaeaea; - font-weight: 400; - display: block; - appearance: none; - flex-grow: 1; - cursor: ${(props) => (props.disabled ? 'none' : 'pointer')}; - opacity: ${(props) => (props.disabled ? 0.4 : 1)}; - - &:hover { - background-color: #7dc1c878; - border-color: #9ebcbf; - } -` - const ExportTooltip = styled(BasicPopover)` width: 280px; padding: 1em; @@ -51,51 +30,6 @@ const ProjectDetails: React.FC<{ const project = projects[0] const projectId = project.address.projectId - const nn = usePrism(() => { - const loadingState = val( - getStudio().atomP.ephemeral.coreByProject[projectId].loadingState, - ) - if (!loadingState) return - if (loadingState.type === 'browserStateIsNotBasedOnDiskState') { - /** - * This stuff is not undo-safe, but once we switch to the new persistence - * scheme, these will be unnecessary anyway. - */ - const useBrowserState = () => { - getStudio().transaction(({drafts, stateEditors}) => { - stateEditors.coreByProject.historic.revisionHistory.add({ - projectId, - revision: loadingState.onDiskState.revisionHistory[0], - }) - - stateEditors.coreByProject.historic.revisionHistory.add({ - projectId, - revision: generateDiskStateRevision(), - }) - - drafts.ephemeral.coreByProject[projectId].loadingState = { - type: 'loaded', - } - }) - } - - const useOnDiskState = () => { - getStudio().transaction(({drafts}) => { - drafts.historic.coreByProject[projectId] = loadingState.onDiskState - drafts.ephemeral.coreByProject[projectId].loadingState = { - type: 'loaded', - } - }) - } - return ( -
- Browser state is not based on disk state. - - -
- ) - } - }, [project]) const [downloaded, setDownloaded] = useState(false) @@ -140,11 +74,11 @@ const ProjectDetails: React.FC<{ return ( <> - {nn} {tooltip} + - + diff --git a/theatre/studio/src/panels/DetailPanel/ProjectDetails/StateConflictRow.tsx b/theatre/studio/src/panels/DetailPanel/ProjectDetails/StateConflictRow.tsx new file mode 100644 index 0000000..5fcfba5 --- /dev/null +++ b/theatre/studio/src/panels/DetailPanel/ProjectDetails/StateConflictRow.tsx @@ -0,0 +1,124 @@ +import {useVal} from '@theatre/dataverse-react' +import getStudio from '@theatre/studio/getStudio' +import React from 'react' +import styled from 'styled-components' +import {generateDiskStateRevision} from '@theatre/studio/StudioStore/generateDiskStateRevision' +import type {ProjectEphemeralState} from '@theatre/core/projects/store/storeTypes' +import useTooltip from '@theatre/studio/uiComponents/Popover/useTooltip' +import BasicTooltip from '@theatre/studio/uiComponents/Popover/BasicTooltip' +import type {$FixMe} from '@theatre/shared/utils/types' +import DetailPanelButton from '@theatre/studio/uiComponents/DetailPanelButton' + +const Container = styled.div` + padding: 8px 10px; + position: relative; + background-color: #6d232352; + &:before { + position: absolute; + content: ' '; + display: block; + left: 0; + top: 0; + bottom: 0; + width: 2px; + background-color: #ff000070; + } +` + +const Message = styled.div` + margin-bottom: 1em; +` + +const ChooseStateRow = styled.div` + display: flex; + gap: 8px; +` + +const StateConflictRow: React.FC<{projectId: string}> = ({projectId}) => { + const loadingState = useVal( + getStudio().atomP.ephemeral.coreByProject[projectId].loadingState, + ) + + if (!loadingState) return null + + if (loadingState.type === 'browserStateIsNotBasedOnDiskState') { + return + } else { + return null + } +} + +const InConflict: React.FC<{ + projectId: string + loadingState: Extract< + ProjectEphemeralState['loadingState'], + {type: 'browserStateIsNotBasedOnDiskState'} + > +}> = ({projectId, loadingState}) => { + /** + * This stuff is not undo-safe, but once we switch to the new persistence + * scheme, these will be unnecessary anyway. + */ + const useBrowserState = () => { + getStudio().transaction(({drafts, stateEditors}) => { + stateEditors.coreByProject.historic.revisionHistory.add({ + projectId, + revision: loadingState.onDiskState.revisionHistory[0], + }) + + stateEditors.coreByProject.historic.revisionHistory.add({ + projectId, + revision: generateDiskStateRevision(), + }) + + drafts.ephemeral.coreByProject[projectId]!.loadingState = { + type: 'loaded', + } + }) + } + + const useOnDiskState = () => { + getStudio().transaction(({drafts}) => { + drafts.historic.coreByProject[projectId] = loadingState.onDiskState + drafts.ephemeral.coreByProject[projectId]!.loadingState = { + type: 'loaded', + } + }) + } + + const [browserStateNode, browserStateRef] = useTooltip({}, () => ( + + The browser's state will override the disk state. + + )) + + const [diskStateNode, diskStateRef] = useTooltip({}, () => ( + + The disk's state will override the browser's state. + + )) + + return ( + + Browser state is not based on disk state. + + {browserStateNode} + + Use browser's state + + {diskStateNode} + + Use disk state + + + + ) +} + +export default StateConflictRow diff --git a/theatre/studio/src/uiComponents/DetailPanelButton.tsx b/theatre/studio/src/uiComponents/DetailPanelButton.tsx new file mode 100644 index 0000000..3a1d29c --- /dev/null +++ b/theatre/studio/src/uiComponents/DetailPanelButton.tsx @@ -0,0 +1,23 @@ +import styled from 'styled-components' + +const DetailPanelButton = styled.button<{disabled?: boolean}>` + text-align: center; + padding: 8px; + border-radius: 2px; + border: 1px solid #627b7b87; + background-color: #4b787d3d; + color: #eaeaea; + font-weight: 400; + display: block; + appearance: none; + flex-grow: 1; + cursor: ${(props) => (props.disabled ? 'none' : 'pointer')}; + opacity: ${(props) => (props.disabled ? 0.4 : 1)}; + + &:hover { + background-color: #7dc1c878; + border-color: #9ebcbf; + } +` + +export default DetailPanelButton