Skip to content

Commit

Permalink
work in progress
Browse files Browse the repository at this point in the history
  • Loading branch information
ciur committed Aug 23, 2024
1 parent fd702f2 commit 4e07ad4
Show file tree
Hide file tree
Showing 6 changed files with 386 additions and 15 deletions.
64 changes: 59 additions & 5 deletions ui2/src/components/Viewer/Thumbnail/Thumbnail.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,19 @@ import {Stack, Checkbox} from "@mantine/core"
import PanelContext from "@/contexts/PanelContext"

import {useProtectedJpg} from "@/hooks/protected_image"
import {setCurrentPage} from "@/slices/dualPanel/dualPanel"
import {
setCurrentPage,
dropThumbnailPage,
selectionAddPage,
selectionRemovePage,
selectSelectedPageIds
} from "@/slices/dualPanel/dualPanel"
import {
dragPagesStart,
dragPagesEnd,
selectDraggedPages
} from "@/slices/dragndrop"
import type {PanelMode, PageType} from "@/types"
import type {PanelMode, PageType, DroppedThumbnailPosition} from "@/types"

import classes from "./Thumbnail.module.scss"
import {RootState} from "@/app/types"
Expand All @@ -27,6 +33,9 @@ export default function Thumbnail({page}: Args) {
const dispatch = useDispatch()
const protectedImage = useProtectedJpg(page.jpg_url)
const mode: PanelMode = useContext(PanelContext)
const selectedIds = useSelector((state: RootState) =>
selectSelectedPageIds(state, mode)
)
const ref = useRef<HTMLDivElement>(null)
const [cssClassNames, setCssClassNames] = useState<Array<string>>([])
const draggedPages = useSelector((state: RootState) =>
Expand Down Expand Up @@ -96,17 +105,58 @@ export default function Thumbnail({page}: Args) {
}

const onDragEnd = () => {
dispatch(dragPagesEnd())
//dispatch(dragPagesEnd())
}

const onLocalDrop = () => {
const onLocalDrop = (event: React.DragEvent<HTMLDivElement>) => {
let position: DroppedThumbnailPosition = "before"
const y = event.clientY

if (!draggedPages) {
console.warn("Dragged pages array is empty")
return
}

event.preventDefault()

if (ref?.current) {
const rect = ref?.current.getBoundingClientRect()
const half = (rect.bottom - rect.top) / 2

if (y >= rect.top && y < rect.top + half) {
// dropped over upper half of the page
position = "before"
} else if (y >= rect.top + half && y < rect.bottom) {
// dropped over lower half of the page
position = "after"
}

dispatch(
dropThumbnailPage({
mode: mode,
sources: draggedPages,
target: page,
position: position
})
)
dispatch(dragPagesEnd())
} // if (ref?.current)

// remove both borderline_bottom and borderline_top
const new_array = cssClassNames.filter(
i => i != BORDERLINE_BOTTOM && i != BORDERLINE_TOP
)
setCssClassNames(new_array)
}

const onCheck = (e: React.ChangeEvent<HTMLInputElement>) => {
if (e.currentTarget.checked) {
dispatch(selectionAddPage({selectionId: page.id, mode}))
} else {
dispatch(selectionRemovePage({selectionId: page.id, mode}))
}
}

return (
<Stack
ref={ref}
Expand All @@ -122,7 +172,11 @@ export default function Thumbnail({page}: Args) {
onDragEnter={onLocalDragEnter}
onDrop={onLocalDrop}
>
<Checkbox className={classes.checkbox} />
<Checkbox
onChange={onCheck}
checked={selectedIds && selectedIds.includes(page.id)}
className={classes.checkbox}
/>
<img src={protectedImage.data || ""} />
{page.number}
</Stack>
Expand Down
62 changes: 56 additions & 6 deletions ui2/src/slices/dualPanel/dualPanel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,15 @@ import {RootState} from "@/app/types"
import {
removeNodesHelper,
selectionAddNodeHelper,
selectionAddPageHelper,
selectionRemoveNodeHelper,
selectionRemovePageHelper,
clearNodesSelectionHelper,
commanderInitialState,
setCurrentNodeHelper,
nodeAddedHelper,
nodeUpdatedHelper
nodeUpdatedHelper,
dropThumbnailPageHelper
} from "./helpers"

import type {
Expand All @@ -36,15 +39,18 @@ import type {
PaginationType,
SliceStateStatus,
SearchResultNode,
PaginatedSearchResult
PaginatedSearchResult,
DroppedThumbnailPosition,
PageType
} from "@/types"
import {
DualPanelState,
SetCurrentNodeArgs,
FolderAddedArgs,
NodeUpdatedArgs,
NodeWithSpinner,
SelectionNodePayload
SelectionNodePayload,
SelectionPagePayload
} from "./types"
import {
INITIAL_PAGE_SIZE,
Expand Down Expand Up @@ -199,10 +205,41 @@ type SetCurrentPageArg = {
page: number
}

type DropThumbnailPageArgs = {
mode: PanelMode
sources: PageType[]
target: PageType
position: DroppedThumbnailPosition
}

const dualPanelSlice = createSlice({
name: "dualPanel",
initialState,
reducers: {
selectionAddPage: (state, action: PayloadAction<SelectionPagePayload>) => {
const nodeId = action.payload.selectionId
const mode = action.payload.mode
selectionAddPageHelper(state, nodeId, mode)
},
selectionRemovePage: (
state,
action: PayloadAction<SelectionPagePayload>
) => {
const nodeId = action.payload.selectionId
const mode = action.payload.mode
selectionRemovePageHelper(state, nodeId, mode)
},
dropThumbnailPage(state, action: PayloadAction<DropThumbnailPageArgs>) {
const {mode, sources, target, position} = action.payload

dropThumbnailPageHelper({
state,
mode,
sources,
target,
position
})
},
incZoomFactor(state, action: PayloadAction<PanelMode>) {
const mode = action.payload
if (mode == "main") {
Expand Down Expand Up @@ -473,7 +510,8 @@ const dualPanelSlice = createSlice({
currentVersion: Math.max(...versionNumbers),
currentPage: action.meta.arg.page || 1,
thumbnailsPanelOpen: false,
zoomFactor: 100
zoomFactor: 100,
selectedIds: []
}
return
}
Expand All @@ -489,7 +527,8 @@ const dualPanelSlice = createSlice({
currentVersion: Math.max(...versionNumbers),
currentPage: action.meta.arg.page || 1,
thumbnailsPanelOpen: false,
zoomFactor: 100
zoomFactor: 100,
selectedIds: []
}
}
return
Expand Down Expand Up @@ -530,12 +569,15 @@ export const {
closeSecondaryPanel,
selectionAddNode,
selectionRemoveNode,
selectionAddPage,
selectionRemovePage,
clearNodesSelection,
updateSearchResultItemTarget,
storeHomeNode,
storeInboxNode,
nodeAdded,
setCurrentPage
setCurrentPage,
dropThumbnailPage
} = dualPanelSlice.actions

export default dualPanelSlice.reducer
Expand Down Expand Up @@ -755,6 +797,14 @@ export const selectSelectedNodeIds = (state: RootState, mode: PanelMode) => {
return state.dualPanel.secondaryPanel?.commander?.selectedIds
}

export const selectSelectedPageIds = (state: RootState, mode: PanelMode) => {
if (mode == "main") {
return state.dualPanel.mainPanel.viewer?.selectedIds
}

return state.dualPanel.secondaryPanel?.viewer?.selectedIds
}

export const selectSelectedNodes = createSelector(
[selectSelectedNodeIds, selectNodesRaw],
(
Expand Down
121 changes: 118 additions & 3 deletions ui2/src/slices/dualPanel/helpers.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,35 @@
import type {CurrentNodeType, NodeType, PanelMode} from "@/types"
import type {
CurrentNodeType,
NodeType,
PanelMode,
PageType,
DroppedThumbnailPosition
} from "@/types"
import {DualPanelState, NodeWithSpinner, Commander} from "./types"
import {INITIAL_PAGE_SIZE} from "@/cconstants"
import {contains_every} from "@/utils"
import {reorder as reorder_pages} from "@/utils"

export function selectionAddPageHelper(
state: DualPanelState,
nodeId: string,
mode: PanelMode
) {
switch (mode) {
case "main":
if (state.mainPanel.viewer) {
state.mainPanel.viewer.selectedIds.push(nodeId)
}
break
case "secondary":
if (state.secondaryPanel?.viewer) {
state.secondaryPanel.viewer.selectedIds.push(nodeId)
}
break
default:
throw Error("Should never reach this place")
}
}

export function selectionAddNodeHelper(
state: DualPanelState,
Expand Down Expand Up @@ -47,6 +76,30 @@ export function selectionRemoveNodeHelper(
}
}

export function selectionRemovePageHelper(
state: DualPanelState,
nodeId: string,
mode: PanelMode
) {
if (mode == "main") {
if (state.mainPanel.viewer) {
const newSelectedIds = state.mainPanel.viewer.selectedIds.filter(
i => i != nodeId
)
state.mainPanel.viewer.selectedIds = newSelectedIds
}
}

if (mode == "secondary") {
if (state.secondaryPanel?.viewer) {
const newSelectedIds = state.secondaryPanel.viewer.selectedIds.filter(
i => i != nodeId
)
state.secondaryPanel.viewer.selectedIds = newSelectedIds
}
}
}

export function clearNodesSelectionHelper(
state: DualPanelState,
mode: PanelMode
Expand Down Expand Up @@ -125,7 +178,8 @@ export function setCurrentNodeHelper({
currentVersion: null,
currentPage: 1,
thumbnailsPanelOpen: false,
zoomFactor: 100
zoomFactor: 100,
selectedIds: []
}
}
}
Expand Down Expand Up @@ -165,7 +219,8 @@ export function setCurrentNodeHelper({
currentVersion: null,
currentPage: 1,
thumbnailsPanelOpen: false,
zoomFactor: 100
zoomFactor: 100,
selectedIds: []
},
searchResults: null
}
Expand Down Expand Up @@ -256,6 +311,66 @@ export function equalPanels(state: DualPanelState): boolean {
return false
}

export function dropThumbnailPageHelper({
mode,
state,
sources,
target,
position
}: {
mode: PanelMode
state: DualPanelState
sources: PageType[]
target: PageType
position: DroppedThumbnailPosition
}) {
let pages: PageType[]
let curVer
if (mode == "main") {
curVer = state.mainPanel.viewer!.currentVersion!
pages = state.mainPanel.viewer?.versions[curVer - 1].pages!
} else {
curVer = state.secondaryPanel!.viewer!.currentVersion!
pages = state.secondaryPanel!.viewer?.versions[curVer - 1].pages!
}
const page_ids = pages.map(p => p.id)
const source_ids = sources.map(p => p.id)
if (contains_every({container: page_ids, items: source_ids})) {
/* Here we deal with page transfer is within the same document
i.e we just reordering. It is so because all source pages (their IDs)
were found in the target document version.
*/
const new_pages = reorder_pages<PageType, string>({
arr: pages,
source_ids: source_ids,
target_id: target.id,
position: position,
idf: (val: PageType) => val.id
})
if (mode == "main") {
curVer = state.mainPanel.viewer!.currentVersion!
if (
state.mainPanel.viewer &&
state.mainPanel.viewer.versions.length >= curVer &&
state.mainPanel.viewer.versions[curVer - 1]
) {
state.mainPanel.viewer.versions[curVer - 1].pages = new_pages
}
} else {
curVer = state.secondaryPanel!.viewer!.currentVersion!
if (
curVer &&
state.secondaryPanel &&
state.secondaryPanel.viewer &&
state.secondaryPanel.viewer.versions.length >= curVer &&
state.secondaryPanel.viewer.versions[curVer - 1]
) {
state.secondaryPanel.viewer.versions[curVer - 1].pages = new_pages
}
}
}
}

function _removePanelNodes(
state: DualPanelState,
idsToRemove: string[],
Expand Down
Loading

0 comments on commit 4e07ad4

Please sign in to comment.