Skip to content

Commit

Permalink
feat: delete file
Browse files Browse the repository at this point in the history
  • Loading branch information
drl990114 committed Aug 12, 2023
1 parent 1dca8e5 commit 844ae2a
Show file tree
Hide file tree
Showing 10 changed files with 157 additions and 37 deletions.
5 changes: 2 additions & 3 deletions apps/linebyline/src/components/Explorer/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import { useGlobalCacheData, useOpen } from '@/hooks'
import { CacheManager } from '@/helper'
import { Empty, FileTree, List, Popper } from '@/components'
import styled from 'styled-components'
import SideBarHeader from '../SideBar/SideBarHeader'

const RecentListBottom = styled.div`
padding: 8px;
Expand Down Expand Up @@ -63,8 +62,8 @@ const Explorer: FC<ExplorerProps> = (props) => {
const containerCLs = classNames(props.className)

return (
<Container className={containerCLs}>
<SideBarHeader name='EXPLORER' />
<Container className={containerCLs} onContextMenu={e => e.preventDefault()}>
{/* <SideBarHeader name='EXPLORER' /> */}
<div className='h-full w-full overflow-auto'>
{folderData && folderData.length > 0 ? (
<FileTree
Expand Down
1 change: 1 addition & 0 deletions apps/linebyline/src/components/Explorer/styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ export const Container = styled.div`
display: flex;
flex-direction: column;
min-width: calc(100% - 48px);
user-select: none;
.explorer-header {
display: flex;
Expand Down
13 changes: 11 additions & 2 deletions apps/linebyline/src/components/FileTree/FileNode.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,13 @@ import type { NewInputRef } from './NewFIleInput'
import NewFileInput from './NewFIleInput'
import bus from '@/helper/eventBus'
import useFileTreeContextMenuNode from '@/hooks/useContextMenuNode'
import { useEditorStore } from '@/stores'

const FileNode: FC<FileNodeProps> = ({ item, level = 0, activeId, onSelect, open = false }) => {
const [isOpen, setIsOpen] = useState(open)
const newInputRef = useRef<NewInputRef>(null)
const { contextMenuNode, setContextMenuNode } = useFileTreeContextMenuNode()
const { deleteFile } = useEditorStore()
const isActived = activeId === item.id
const isFolder = item.kind === 'dir'

Expand All @@ -25,12 +27,19 @@ const FileNode: FC<FileNodeProps> = ({ item, level = 0, activeId, onSelect, open
newInputRef.current?.show({ fileNode: contextMenuNode })
}

const delFileHandler = () => {
if (!contextMenuNode || contextMenuNode.id !== item.id) return
deleteFile(contextMenuNode)
}

bus.on('SIDEBAR:show-new-input', newFileHandler)
bus.on('SIDEBAR:delete-file', delFileHandler)

return () => {
bus.detach('SIDEBAR:show-new-input', newFileHandler)
bus.detach('SIDEBAR:delete-file', delFileHandler)
}
}, [contextMenuNode, item])
}, [contextMenuNode, item, deleteFile])

const handleClick: MouseEventHandler = useCallback(
(e) => {
Expand All @@ -47,8 +56,8 @@ const FileNode: FC<FileNodeProps> = ({ item, level = 0, activeId, onSelect, open

const handleContextMenu = useCallback(
(e: React.MouseEvent<HTMLDivElement, MouseEvent>, fileNode?: IFile) => {
e.stopPropagation()
const node = fileNode || item
e.stopPropagation()
setContextMenuNode(node)
},
[item, setContextMenuNode],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,13 @@ export const FileNodeContextMenu = memo((props: ContextMenuProps) => {
bus.emit('SIDEBAR:show-new-input')
},
},
{
key: 'delete_file',
label: 'Delete File',
handler: () => {
bus.emit("SIDEBAR:delete-file")
}
}
]

return (
Expand Down
42 changes: 34 additions & 8 deletions apps/linebyline/src/components/FileTree/FileTree.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
import classNames from 'classnames'
import type { FC } from 'react'
import { memo, useCallback } from 'react'
import { memo, useCallback, useState } from 'react'
import FileNode from './FileNode'
import type { IFile } from '@/helper/filesys'
import { FileNodeContextMenu } from './FileNodeContextMenu'
import useFileTreeContextMenu from '@/hooks/useContextMenu'
import { RootFolderTab } from './styles'

const FileTree: FC<FileTreeProps> = (props) => {
const { data, activeId, onSelect, className } = props
const { setOpen, points, setPoints } = useFileTreeContextMenu()

const containerCls = classNames('w-full overflow-hidden', className)
const rootFolderNode = data?.[0]?.kind === 'dir' ? data[0] : null
const [folderVisible, setFolderVisible] = useState(true)

const handleContextMenu = useCallback(
(e: React.MouseEvent<HTMLDivElement, MouseEvent>) => {
Expand All @@ -24,12 +25,37 @@ const FileTree: FC<FileTreeProps> = (props) => {
[setOpen, setPoints],
)

const containerCls = classNames('w-full overflow-hidden', className)

const rootFolderTabIconCls = classNames('arrow-icon', {
'arrow-icon__down': folderVisible,
})

return (
<div className={containerCls} onContextMenuCapture={handleContextMenu}>
{/* Currently, folderData only has root file, so open it. */}
{data?.map((item) => (
<FileNode open key={item.name} item={item} level={0} activeId={activeId} onSelect={onSelect} />
))}
<div className={containerCls}>
{rootFolderNode ? (
<RootFolderTab onClick={() => setFolderVisible((prev) => !prev)}>
<div className={rootFolderTabIconCls}>
<i className='ri-arrow-drop-right-line'></i>
</div>
{rootFolderNode.name}
</RootFolderTab>
) : null}

<div onContextMenuCapture={handleContextMenu}>
{folderVisible
? (rootFolderNode?.children || data)?.map((item) => (
<FileNode
key={item.name}
item={item}
level={0}
activeId={activeId}
onSelect={onSelect}
/>
))
: null}
</div>

<FileNodeContextMenu top={points.y} left={points.x} />
</div>
)
Expand Down
23 changes: 21 additions & 2 deletions apps/linebyline/src/components/FileTree/styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,28 @@ export const FileNodeStyled = styled.div`
flex-shrink: 0;
}
.newfile-input {
margin: 0 8px;
border: 1px solid ${props => props.theme.accentColor};
border: 1px solid ${(props) => props.theme.accentColor};
}
`

export const RootFolderTab = styled.div`
padding: 4px 2px;
display: flex;
align-items: center;
cursor: pointer;
font-size: 1rem;
color: ${(props) => props.theme.tipsFontColor};
.arrow-icon {
display: inline-block;
font-size: 1.4rem;
color: ${(props) => props.theme.primaryFontColor};
transition: all 0.3s;
&__down {
transform: rotate(90deg);
}
}
`
65 changes: 56 additions & 9 deletions apps/linebyline/src/stores/useEditorStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,14 @@ const findParentNode = (fileNode: IFile, rootFile: IFile) => {
return dfs(rootFile)
}

const hasSameFile = (fileNodeList: IFile[], target: { name: string; kind: IFile['kind'] }) => {
return !!fileNodeList.find((file) => file.name === target.name && file.kind === target.kind)
type BaseIFile = { name: string; kind: IFile['kind'] }

function sameFile(current: BaseIFile, target: BaseIFile): boolean {
return current.name === target.name && current.kind === target.kind
}

const hasSameFile = (fileNodeList: IFile[], target: BaseIFile) => {
return !!fileNodeList.find((file) => sameFile(file, target))
}

const useEditorStore = create<EditorStore>((set, get) => {
Expand Down Expand Up @@ -52,14 +58,51 @@ const useEditorStore = create<EditorStore>((set, get) => {

parent.children!.push(targetFile)
addOpenedFile(targetFile.id)
set((state) => {
return {
...state,
activeId: targetFile.id,
folderData: [...(state.folderData || [])],
invoke('write_file', { filePath: targetFile.path, content: targetFile.content }).then(
() => {
set((state) => {
return {
...state,
activeId: targetFile.id,
folderData: [...(state.folderData || [])],
}
})
},
)
}
},

deleteFile: (fileNode) => {
const { folderData, activeId, delOpenedFile, opened } = get()
const parent = findParentNode(fileNode, folderData![0])
let targetFile: IFile | undefined

if (parent?.children) {
const newChildren: IFile[] = []
for (let i = 0; i < parent.children.length; i++) {
const child = parent.children[i]
if (sameFile(child, fileNode)) {
targetFile = child
} else {
newChildren.push(child)
}
}
if (!targetFile) return false

parent.children = newChildren

invoke(targetFile.kind === 'dir' ? 'delete_folder' : 'delete_file', {
filePath: targetFile.path,
}).then(() => {
delOpenedFile(targetFile!.id)
set((state) => {
return {
...state,
activeId: activeId === targetFile!.id ? opened[opened.length - 1] : activeId,
folderData: [...(state.folderData || [])],
}
})
})
invoke('write_file', { filePath: targetFile.path, content: targetFile.content })
}
},

Expand Down Expand Up @@ -119,13 +162,17 @@ const useEditorStore = create<EditorStore>((set, get) => {
}
})

interface EditorStore {
type EditorStore = {
opened: string[]
activeId?: string
/**
* folderData only has root file.
*/
folderData: null | IFile[]
editorCtxMap: Map<string, EditorDelegate<any>>
setActiveId: (id: string) => void
addFile: (file: IFile, target: { name: string; kind: IFile['kind'] }) => boolean | void
deleteFile: (file: IFile) => void
addOpenedFile: (id: string) => void
delOpenedFile: (id: string) => void
setFolderData: (folderData: IFile[]) => void
Expand Down
16 changes: 13 additions & 3 deletions src-tauri/src/cmd.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
use crate::{
fc,
};
use crate::fc;

// Learn more about Tauri commands at https://tauri.app/v1/guides/features/command
#[tauri::command]
Expand All @@ -20,3 +18,15 @@ pub fn write_file(file_path: &str, content: &str) -> String {
fc::write_file(file_path, content);
String::from("OK")
}

#[tauri::command]
pub fn delete_file(file_path: &str) -> String {
fc::remove_file(file_path);
String::from("OK")
}

#[tauri::command]
pub fn delete_folder(file_path: &str) -> String {
fc::remove_folder(file_path);
String::from("OK")
}
20 changes: 10 additions & 10 deletions src-tauri/src/fc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,14 +114,14 @@ pub fn create_file<P: AsRef<Path>>(filename: P) -> AnyResult<()> {
// Ok(())
// }

// pub fn remove_file(path: &str) -> SerdeResult<()> {
// let file_path = Path::new(path);
// fs::remove_file(file_path);
// Ok(())
// }
pub fn remove_file(path: &str) -> AnyResult<()> {
let file_path = Path::new(path);
fs::remove_file(file_path)?;
Ok(())
}

// pub fn remove_folder(path: &str) -> SerdeResult<()> {
// let folder_path = Path::new(path);
// fs::remove_dir_all(folder_path);
// Ok(())
// }
pub fn remove_folder(path: &str) -> AnyResult<()> {
let folder_path = Path::new(path);
fs::remove_dir_all(folder_path)?;
Ok(())
}
2 changes: 2 additions & 0 deletions src-tauri/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ fn main() {
cmd::open_folder,
cmd::get_file_content,
cmd::write_file,
cmd::delete_file,
cmd::delete_folder,
conf::cmd::get_app_conf_path,
conf::cmd::get_app_conf,
conf::cmd::reset_app_conf,
Expand Down

0 comments on commit 844ae2a

Please sign in to comment.