Skip to content

Commit cc317fa

Browse files
committed
fix: 修复重命名可以移动文件的问题
1 parent 12384a7 commit cc317fa

5 files changed

Lines changed: 51 additions & 3 deletions

File tree

src/css/components.css

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,20 @@
120120
}
121121
}
122122

123+
& .field-error {
124+
font-size: var(--text-xs);
125+
color: var(--text-danger);
126+
margin: 0;
127+
}
128+
129+
& input:has(~ .field-error:not([hidden])) {
130+
border-color: var(--text-danger);
131+
132+
&:focus {
133+
border-color: var(--text-danger);
134+
}
135+
}
136+
123137
&:not(:last-child) {
124138
margin-bottom: var(--sp-3);
125139
}

src/index.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1145,6 +1145,7 @@ <h2 id="prompt-title">提示</h2>
11451145
<div class="field">
11461146
<label for="prompt-input" id="prompt-label"></label>
11471147
<input id="prompt-input" type="text" required autocomplete="off" />
1148+
<p id="prompt-error" class="field-error" hidden></p>
11481149
</div>
11491150
</div>
11501151
<div class="dialog-footer">

src/js/file-operations.js

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,13 @@ class FileOperations {
2727
/** @param {string} key @param {boolean} isFolder */
2828
async rename(key, isFolder) {
2929
const oldName = getFileName(key)
30-
const newName = await this.#ui.prompt(t('renameTitle'), t('renameLabel'), oldName)
30+
const newName = await this.#ui.prompt(t('renameTitle'), t('renameLabel'), oldName, {
31+
validate: v => {
32+
const illegal = v.match(/[/\\:*?"<>|\x00-\x1F]/g)
33+
if (illegal) return t('renameInvalidChars', { chars: [...new Set(illegal)].join(' ') })
34+
return null
35+
},
36+
})
3137
if (!newName || newName === oldName) return
3238

3339
try {

src/js/i18n.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ const I18N = {
5757
deleteFolderConfirmMsg: '确定要删除目录 "{name}" 及其所有内容吗?删除后无法恢复哦。',
5858
renameTitle: '重命名',
5959
renameLabel: '新名称',
60+
renameInvalidChars: '文件名包含非法字符:{chars}',
6061
copyTitle: '复制到',
6162
copyLabel: '目标路径',
6263
moveTitle: '移动到',
@@ -263,6 +264,7 @@ const I18N = {
263264
deleteFolderConfirmMsg: '确定要删除目录 "{name}" 及其所有内容吗?删除后无法恢复哦。',
264265
renameTitle: '重命名',
265266
renameLabel: '新名称',
267+
renameInvalidChars: '文件名包含非法字符:{chars}',
266268
copyTitle: '复制到',
267269
copyLabel: '目标路径',
268270
moveTitle: '移动到',
@@ -473,6 +475,7 @@ const I18N = {
473475
deleteFolderConfirmMsg: 'Delete folder "{name}" and everything inside? This can\'t be undone.',
474476
renameTitle: 'Rename',
475477
renameLabel: 'New name',
478+
renameInvalidChars: 'File name contains illegal characters: {chars}',
476479
copyTitle: 'Copy to',
477480
copyLabel: 'Destination path',
478481
moveTitle: 'Move to',
@@ -690,6 +693,7 @@ const I18N = {
690693
deleteFolderConfirmMsg: 'フォルダ "{name}" とその中身をすべて削除しますか?元に戻せません。',
691694
renameTitle: '名前変更',
692695
renameLabel: '新しい名前',
696+
renameInvalidChars: 'ファイル名に使用できない文字が含まれています:{chars}',
693697
copyTitle: 'コピー先',
694698
copyLabel: 'コピー先パス',
695699
moveTitle: '移動先',

src/js/ui-manager.js

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -205,22 +205,43 @@ class UIManager {
205205
}
206206
}
207207

208-
/** @param {string} title @param {string} label @param {string} [defaultValue] @returns {Promise<string | null>} */
209-
prompt(title, label, defaultValue = '') {
208+
/**
209+
* @param {string} title
210+
* @param {string} label
211+
* @param {string} [defaultValue]
212+
* @param {{ validate?: (v: string) => string | null }} [options]
213+
* @returns {Promise<string | null>}
214+
*/
215+
prompt(title, label, defaultValue = '', { validate } = {}) {
210216
return new Promise(resolve => {
211217
const dialog = /** @type {HTMLDialogElement} */ ($('#prompt-dialog'))
212218
const form = $('#prompt-form')
213219
const input = /** @type {HTMLInputElement} */ ($('#prompt-input'))
220+
const errorEl = $('#prompt-error')
214221
$('#prompt-title').textContent = title
215222
$('#prompt-label').textContent = label
216223
input.value = defaultValue
224+
errorEl.textContent = ''
225+
errorEl.hidden = true
217226

218227
/** @type {string | null} */
219228
let result = null
220229

230+
/** @returns {boolean} */
231+
const checkValid = () => {
232+
if (!validate) return true
233+
const err = validate(input.value)
234+
errorEl.textContent = err ?? ''
235+
errorEl.hidden = !err
236+
return !err
237+
}
238+
239+
const onInput = () => checkValid()
240+
221241
/** @param {Event} e */
222242
const onSubmit = e => {
223243
e.preventDefault()
244+
if (!checkValid()) { input.focus(); return }
224245
result = input.value.trim() || null
225246
dialog.close()
226247
}
@@ -234,12 +255,14 @@ class UIManager {
234255

235256
const onClose = () => {
236257
form.removeEventListener('submit', onSubmit)
258+
input.removeEventListener('input', onInput)
237259
$('#prompt-cancel').removeEventListener('click', onCancel)
238260
dialog.removeEventListener('click', onBackdropClick)
239261
resolve(result)
240262
}
241263

242264
form.addEventListener('submit', onSubmit)
265+
input.addEventListener('input', onInput)
243266
$('#prompt-cancel').addEventListener('click', onCancel)
244267
dialog.addEventListener('click', onBackdropClick)
245268
dialog.addEventListener('close', onClose, { once: true })

0 commit comments

Comments
 (0)