[Feature] Rename (#10)

diff --git a/studio/components/files/index.tsx b/studio/components/files/index.tsx
index 27c306f..fa54b5b 100644
--- a/studio/components/files/index.tsx
+++ b/studio/components/files/index.tsx
@@ -43,7 +43,7 @@
 export const Files = defineComponent({
   name: 'files',
   props,
-  emits: ['select', 'inputBlur', 'delete'],
+  emits: ['select', 'inputBlur', 'delete', 'rename'],
   setup(props, { emit, expose }) {
     const keyRef = ref()
     const treeRef = ref()
@@ -99,11 +99,9 @@
       }
     }
 
-    const onContextMenuSelect = (key: string) => {
+    const onContextMenuSelect = (key: 'delete' | 'rename') => {
       showDropdownRef.value = false
-      if (key === 'delete') {
-        emit('delete', Number(id))
-      }
+      emit(key, Number(id))
     }
 
     const onClickoutside = () => {
@@ -135,7 +133,10 @@
           trigger='manual'
           x={xRef.value}
           y={yRef.value}
-          options={[{ key: 'delete', label: t('delete') }]}
+          options={[
+            { key: 'delete', label: t('delete') },
+            { key: 'rename', label: t('rename') }
+          ]}
           show={showDropdownRef.value}
           onClickoutside={onClickoutside}
           onSelect={onContextMenuSelect}
diff --git a/studio/components/studio-sider/index.tsx b/studio/components/studio-sider/index.tsx
index 43b0284..b1b725e 100644
--- a/studio/components/studio-sider/index.tsx
+++ b/studio/components/studio-sider/index.tsx
@@ -33,7 +33,8 @@
       onCreateFolder,
       onSelectFile,
       onInputBlur,
-      onDelete
+      onDelete,
+      onRename
     } = useFile(inputRef, fileRef)
 
     return () => (
@@ -52,6 +53,7 @@
             onSelect={onSelectFile}
             onInputBlur={onInputBlur}
             onDelete={onDelete}
+            onRename={onRename}
             inputRef={inputRef}
             selected-keys={[state.currentKey]}
             ref={fileRef}
diff --git a/studio/components/studio-sider/use-file.ts b/studio/components/studio-sider/use-file.ts
index cf88ede..c61215b 100644
--- a/studio/components/studio-sider/use-file.ts
+++ b/studio/components/studio-sider/use-file.ts
@@ -16,16 +16,16 @@
  */
 import { reactive, Ref, nextTick } from 'vue'
 import { useMessage } from 'naive-ui'
-import { remove } from 'lodash'
 import { addFile, deleteFile } from '@/service/modules/file'
 import { useLocale } from '@/hooks'
+import { remove } from 'lodash'
 import { sameNameValidator } from './helper'
 import type { IFileState, FileType, IFileRecord } from './types'
 
 export const useFile = (inputRef: Ref, fileRef: Ref) => {
   const state = reactive({
     currentKey: 0,
-    files: [{ type: '', id: 1, name: '123', pid: 0, children: [] }],
+    files: [],
     isCreating: false
   } as IFileState)
 
@@ -36,7 +36,7 @@
     1: { type: '', id: 1, name: '123', pid: 0, children: [] }
   } as { [key: number]: IFileRecord }
 
-  const freshFiles = () => {
+  const refreshFiles = () => {
     fileRef.value.refresh()
   }
 
@@ -70,7 +70,7 @@
 
     state.currentKey = record.id
 
-    freshFiles()
+    refreshFiles()
     await nextTick()
     inputRef.value?.focus()
   }
@@ -90,16 +90,7 @@
     }
   }
 
-  const onCreateFile = (type: FileType) => void create(true, type)
-
-  const onCreateFolder = () => void create(false, '')
-
-  const onSelectFile = (key: number) => {
-    state.currentKey = key
-  }
-
-  const onInputBlur = async (value: string) => {
-    state.isCreating = false
+  const add = async (value: string) => {
     if (!value) {
       const currentFolderKey = getCurrentFolderKey()
 
@@ -111,7 +102,7 @@
 
       state.currentKey = currentFolderKey
 
-      freshFiles()
+      refreshFiles()
       return
     }
 
@@ -129,10 +120,37 @@
     if (result) {
       filesCached[state.currentKey].isEditing = false
       filesCached[state.currentKey].name = value
-      freshFiles()
+      refreshFiles()
     }
   }
 
+  const rename = async (value: string) => {
+    if (!value) {
+      message.error(t('empty_name_tips'))
+      return
+    }
+    filesCached[state.currentKey].isEditing = false
+    filesCached[state.currentKey].name = value
+    refreshFiles()
+  }
+
+  const onCreateFile = (type: FileType) => void create(true, type)
+
+  const onCreateFolder = () => void create(false, '')
+
+  const onSelectFile = (key: number) => {
+    state.currentKey = key
+  }
+
+  const onInputBlur = async (value: string) => {
+    if (state.isCreating) {
+      state.isCreating = false
+      add(value)
+      return
+    }
+    rename(value)
+  }
+
   const onDelete = async (id: number) => {
     const deletedRecord = filesCached[id]
     if (!deletedRecord.type && deletedRecord.children?.length) {
@@ -151,12 +169,20 @@
     delete filesCached[id]
   }
 
+  const onRename = (id: number) => {
+    const currentRecord = filesCached[id]
+    currentRecord.isEditing = true
+    state.currentKey = id
+    refreshFiles()
+  }
+
   return {
     state,
     onCreateFile,
     onCreateFolder,
     onSelectFile,
     onInputBlur,
-    onDelete
+    onDelete,
+    onRename
   }
 }
diff --git a/studio/locales/en_US.ts b/studio/locales/en_US.ts
index 81ab60d..551972a 100644
--- a/studio/locales/en_US.ts
+++ b/studio/locales/en_US.ts
@@ -20,7 +20,9 @@
   saved_successfully: 'Saved successfully',
   same_name_tips: 'Same name exits for files at the same level.',
   delete: 'Delete',
-  delete_tips: 'Please delete the files in this folder first.'
+  delete_tips: 'Please delete the files in this folder first.',
+  empty_name_tips: 'Please input the name.',
+  rename: 'Rename'
 }
 
 export type Locale = typeof enUS
diff --git a/studio/locales/zh_CN.ts b/studio/locales/zh_CN.ts
index e8d1367..fcd14a7 100644
--- a/studio/locales/zh_CN.ts
+++ b/studio/locales/zh_CN.ts
@@ -20,5 +20,7 @@
   saved_successfully: '保存成功',
   same_name_tips: '同级文件存在相同名字',
   delete: '删除',
-  delete_tips: '请先删除文件夹下的文件'
+  delete_tips: '请先删除文件夹下的文件',
+  empty_name_tips: '请输入名字',
+  rename: '重命名'
 }