From a6fcbc626228405f29f794021e4fc94b2b176756 Mon Sep 17 00:00:00 2001 From: Murilo Polese Date: Tue, 26 Mar 2024 15:07:03 +0100 Subject: [PATCH 1/8] Improved alerts to remove and overwrite --- ui/arduino2/store.js | 70 +++++++++++++++++++++++++++++++++++++++----- 1 file changed, 62 insertions(+), 8 deletions(-) diff --git a/ui/arduino2/store.js b/ui/arduino2/store.js index c7fb442..9244fb9 100644 --- a/ui/arduino2/store.js +++ b/ui/arduino2/store.js @@ -421,12 +421,34 @@ async function store(state, emitter) { state.isRemoving = true emitter.emit('render') + let boardNames = state.selectedFiles + .filter(file => file.source === 'board') + .map(file => file.fileName) + + let diskNames = state.selectedFiles + .filter(file => file.source === 'disk') + .map(file => file.fileName) + + let message = `You are about to delete the following files:\n\n` + if (boardNames.length) { + message += `From your board:\n` + boardNames.forEach(name => message += `${name}\n`) + message += `\n` + } + if (diskNames.length) { + message += `From your disk:\n` + diskNames.forEach(name => message += `${name}\n`) + message += `\n` + } + + message += `Are you sure you want to proceed?` + const confirmAction = confirm(message, 'Cancel', 'Yes') + state.isRemoving = false + emitter.emit('render') + if (!confirmAction) return + for (let i in state.selectedFiles) { const file = state.selectedFiles[i] - const confirmAction = confirm(`You are about to delete ${file.fileName} from your ${file.source}.\nAre you sure you want to proceed?`, 'Cancel', 'Yes') - if (!confirmAction) { - continue - } if (file.type == 'folder') { if (file.source === 'board') { await removeBoardFolder( @@ -587,6 +609,23 @@ async function store(state, emitter) { log('upload-files') state.isTransferring = true emitter.emit('render') + // Check if it will overwrite something + const willOverwrite = await checkOverwrite({ + fileNames: state.selectedFiles.map(f => f.fileName), + parentFolder: serial.getFullPath(state.boardNavigationRoot, state.boardNavigationPath, ''), + source: 'board' + }) + if (willOverwrite.length > 0) { + let message = `You are about to overwrite the following files/folders on your board:\n\n` + willOverwrite.forEach(f => message += `${f.fileName}\n`) + message += `\n` + message += `Are you sure you want to proceed?` + const confirmAction = confirm(message, 'Cancel', 'Yes') + state.isTransferring = false + emitter.emit('render') + if (!confirmAction) return + } + // Upload files for (let i in state.selectedFiles) { const file = state.selectedFiles[i] const srcPath = disk.getFullPath( @@ -627,7 +666,23 @@ async function store(state, emitter) { log('download-files') state.isTransferring = true emitter.emit('render') - + // Check if it will overwrite something + const willOverwrite = await checkOverwrite({ + fileNames: state.selectedFiles.map(f => f.fileName), + parentFolder: disk.getFullPath(state.diskNavigationRoot, state.diskNavigationPath, ''), + source: 'disk' + }) + if (willOverwrite.length > 0) { + let message = `You are about to overwrite the following files/folders on your disk:\n\n` + willOverwrite.forEach(f => message += `${f.fileName}\n`) + message += `\n` + message += `Are you sure you want to proceed?` + const confirmAction = confirm(message, 'Cancel', 'Yes') + state.isTransferring = false + emitter.emit('render') + if (!confirmAction) return + } + // Download files for (let i in state.selectedFiles) { const file = state.selectedFiles[i] const srcPath = serial.getFullPath( @@ -807,13 +862,12 @@ async function checkBoardFile({ parentFolder, fileName }) { async function checkOverwrite({ fileNames = [], parentFolder, source }) { let files = [] - let overwrite = [] if (source === 'board') { - files = getBoardFiles(parentFolder) + files = await getBoardFiles(parentFolder) } else { files = await getDiskFiles(parentFolder) } - return files.filter((f) => filenames.indexOf(f.fileName) !== -1) + return files.filter((f) => fileNames.indexOf(f.fileName) !== -1) } function generateFileName(filename) { From 748a1f4a34ea722904523e463ae1b32617b39c11 Mon Sep 17 00:00:00 2001 From: Murilo Polese Date: Wed, 27 Mar 2024 11:56:42 +0100 Subject: [PATCH 2/8] Renaming files With temporary cursor icon --- ui/arduino2/main.css | 5 ++ ui/arduino2/media/cursor.svg | 9 +++ ui/arduino2/store.js | 49 ++++++++++++++- ui/arduino2/views/components/file-list.js | 76 ++++++++++++++++------- 4 files changed, 114 insertions(+), 25 deletions(-) create mode 100644 ui/arduino2/media/cursor.svg diff --git a/ui/arduino2/main.css b/ui/arduino2/main.css index da59b1a..18d8acc 100644 --- a/ui/arduino2/main.css +++ b/ui/arduino2/main.css @@ -548,8 +548,13 @@ button.small .icon { } .file-list .item input { + box-sizing: border-box; border: none; border-radius: none; height: 100%; + width: 100%; background: rgba(255, 255, 255, 0.5); + font-family: inherit; + font-size: inherit; + outline-color: #F4BA00; } diff --git a/ui/arduino2/media/cursor.svg b/ui/arduino2/media/cursor.svg new file mode 100644 index 0000000..84e3019 --- /dev/null +++ b/ui/arduino2/media/cursor.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/ui/arduino2/store.js b/ui/arduino2/store.js index 9244fb9..33c592f 100644 --- a/ui/arduino2/store.js +++ b/ui/arduino2/store.js @@ -494,8 +494,53 @@ async function store(state, emitter) { emitter.emit('render') }) - emitter.on('rename-file', () => { /* TODO */ }) - emitter.on('finish-renaming', () => { /* TODO */ }) + emitter.on('rename-file', (source, item) => { + log('rename-file', source, item) + state.renamingFile = source + emitter.emit('render') + }) + emitter.on('finish-renaming', async (value) => { + log('finish-renaming', value) + if (!value) return + state.isSaving = true + emitter.emit('render') + + // You can only rename one file, the selected one + const fileName = state.selectedFiles[0].fileName + + if (state.renamingFile == 'board') { + await serial.renameFile( + serial.getFullPath( + state.boardNavigationRoot, + state.boardNavigationPath, + fileName + ), + serial.getFullPath( + state.boardNavigationRoot, + state.boardNavigationPath, + value + ) + ) + } else { + await disk.renameFile( + disk.getFullPath( + state.diskNavigationRoot, + state.diskNavigationPath, + fileName + ), + disk.getFullPath( + state.diskNavigationRoot, + state.diskNavigationPath, + value + ) + ) + } + + state.isSaving = false + state.renamingFile = null + emitter.emit('refresh-files') + emitter.emit('render') + }) emitter.on('toggle-file-selection', (file, source, event) => { log('toggle-file-selection', file, source, event) diff --git a/ui/arduino2/views/components/file-list.js b/ui/arduino2/views/components/file-list.js index 477bb76..50b4163 100644 --- a/ui/arduino2/views/components/file-list.js +++ b/ui/arduino2/views/components/file-list.js @@ -2,7 +2,7 @@ const DiskFileList = generateFileList('disk') const BoardFileList = generateFileList('board') function generateFileList(source) { - return function(state, emit) { + return function FileList(state, emit) { function onKeyEvent(e) { if(e.key.toLowerCase() === 'enter') { e.target.blur() @@ -13,19 +13,65 @@ function generateFileList(source) { } } + const newFileItem = html` +
+ +
+ emit('finish-creating-file', e.target.value)}/> +
+
+ ` + const newFolderItem = html` +
+ +
+ emit('finish-creating-folder', e.target.value)}/> +
+
+ ` + function FileItem(item, i) { + const renamingFileItem = html` + emit('finish-renaming', e.target.value)} + onclick=${(e) => false} + ondblclick=${(e) => false} + /> + ` const isChecked = state.selectedFiles.find( f => f.fileName === item.fileName && f.source === source ) + function renameItem(e) { + e.preventDefault() + emit('rename-file', source, item) + return false + } + function navigateToFolder() { + if (!state.renamingFile) emit(`navigate-${source}-folder`, item.fileName) + } + function openFile() { + if (!state.renamingFile) emit(`open-file`, source, item) + } + let fileName = item.fileName + const isSelected = state.selectedFiles.find(f => f.fileName === fileName) + + if (state.renamingFile == source && isSelected) { + fileName = renamingFileItem + } if (item.type === 'folder') { return html`
emit(`navigate-${source}-folder`, item.fileName)} onclick=${(e) => emit('toggle-file-selection', item, source, e)} + ondblclick=${navigateToFolder} > -
${item.fileName}
+
${fileName}
+
+ +
` } else { @@ -33,34 +79,18 @@ function generateFileList(source) {
emit('toggle-file-selection', item, source, e)} - ondblclick=${() => emit(`open-file`, source, item)} + ondblclick=${openFile} > -
${item.fileName}
-
console.log('options', item)}> - +
${fileName}
+
+
` } } - const newFileItem = html` -
- -
- emit('finish-creating-file', e.target.value)}/> -
-
- ` - const newFolderItem = html` -
- -
- emit('finish-creating-folder', e.target.value)}/> -
-
- ` // XXX: Use `source` to filter an array of files with a `source` as proprety const list = html`
From 4d80af50145556bd5581113cc911fb188f348e50 Mon Sep 17 00:00:00 2001 From: Murilo Polese Date: Wed, 27 Mar 2024 13:45:28 +0100 Subject: [PATCH 3/8] Fix timing of waiting state --- ui/arduino2/store.js | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/ui/arduino2/store.js b/ui/arduino2/store.js index 33c592f..8be7939 100644 --- a/ui/arduino2/store.js +++ b/ui/arduino2/store.js @@ -666,9 +666,11 @@ async function store(state, emitter) { message += `\n` message += `Are you sure you want to proceed?` const confirmAction = confirm(message, 'Cancel', 'Yes') - state.isTransferring = false - emitter.emit('render') - if (!confirmAction) return + if (!confirmAction) { + state.isTransferring = false + emitter.emit('render') + return + } } // Upload files for (let i in state.selectedFiles) { @@ -723,9 +725,11 @@ async function store(state, emitter) { message += `\n` message += `Are you sure you want to proceed?` const confirmAction = confirm(message, 'Cancel', 'Yes') - state.isTransferring = false - emitter.emit('render') - if (!confirmAction) return + if (!confirmAction) { + state.isTransferring = false + emitter.emit('render') + return + } } // Download files for (let i in state.selectedFiles) { From ef1c588178fa817e094dca39394ce10baad0c9dd Mon Sep 17 00:00:00 2001 From: Murilo Polese Date: Wed, 27 Mar 2024 14:33:22 +0100 Subject: [PATCH 4/8] Cursor SVG icon --- ui/arduino2/main.css | 2 +- ui/arduino2/media/cursor.svg | 10 ++-------- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/ui/arduino2/main.css b/ui/arduino2/main.css index 18d8acc..86079c4 100644 --- a/ui/arduino2/main.css +++ b/ui/arduino2/main.css @@ -501,9 +501,9 @@ button.small .icon { .file-list .item .options { display: none; - padding: 5px; align-items: center; align-self: stretch; + cursor: pointer; } .file-list .item:hover .options { diff --git a/ui/arduino2/media/cursor.svg b/ui/arduino2/media/cursor.svg index 84e3019..34a5608 100644 --- a/ui/arduino2/media/cursor.svg +++ b/ui/arduino2/media/cursor.svg @@ -1,9 +1,3 @@ - - - - - - - - + + From 4556f2dacba0e8d87d2e22357ddebf718a1fa9f3 Mon Sep 17 00:00:00 2001 From: Murilo Polese Date: Wed, 27 Mar 2024 14:33:48 +0100 Subject: [PATCH 5/8] Check overwrites on rename operation --- ui/arduino2/store.js | 103 ++++++++++++++++++++++++++++++++----------- 1 file changed, 77 insertions(+), 26 deletions(-) diff --git a/ui/arduino2/store.js b/ui/arduino2/store.js index 8be7939..f4ed624 100644 --- a/ui/arduino2/store.js +++ b/ui/arduino2/store.js @@ -501,39 +501,90 @@ async function store(state, emitter) { }) emitter.on('finish-renaming', async (value) => { log('finish-renaming', value) - if (!value) return - state.isSaving = true - emitter.emit('render') // You can only rename one file, the selected one const fileName = state.selectedFiles[0].fileName + if (!value || fileName == value) { + state.renamingFile = null + emitter.emit('render') + return + } + + state.isSaving = true + emitter.emit('render') + + // Check if new name overwrites something if (state.renamingFile == 'board') { - await serial.renameFile( - serial.getFullPath( - state.boardNavigationRoot, - state.boardNavigationPath, - fileName - ), - serial.getFullPath( - state.boardNavigationRoot, - state.boardNavigationPath, - value - ) - ) + // Check if it will overwrite something + const willOverwrite = await checkOverwrite({ + fileNames: [ value ], + parentFolder: disk.getFullPath(state.boardNavigationRoot, state.boardNavigationPath, ''), + source: 'board' + }) + if (willOverwrite.length > 0) { + let message = `You are about to overwrite the following files/folders on your board:\n\n` + willOverwrite.forEach(f => message += `${f.fileName}\n`) + message += `\n` + message += `Are you sure you want to proceed?` + const confirmAction = confirm(message, 'Cancel', 'Yes') + if (!confirmAction) { + state.isSaving = false + emitter.emit('render') + return + } + } } else { - await disk.renameFile( - disk.getFullPath( - state.diskNavigationRoot, - state.diskNavigationPath, - fileName - ), - disk.getFullPath( - state.diskNavigationRoot, - state.diskNavigationPath, - value + // Check if it will overwrite something + const willOverwrite = await checkOverwrite({ + fileNames: [ value ], + parentFolder: disk.getFullPath(state.diskNavigationRoot, state.diskNavigationPath, ''), + source: 'disk' + }) + if (willOverwrite.length > 0) { + let message = `You are about to overwrite the following files/folders on your disk:\n\n` + willOverwrite.forEach(f => message += `${f.fileName}\n`) + message += `\n` + message += `Are you sure you want to proceed?` + const confirmAction = confirm(message, 'Cancel', 'Yes') + if (!confirmAction) { + state.isSaving = false + emitter.emit('render') + return + } + } + } + + try { + if (state.renamingFile == 'board') { + await serial.renameFile( + serial.getFullPath( + state.boardNavigationRoot, + state.boardNavigationPath, + fileName + ), + serial.getFullPath( + state.boardNavigationRoot, + state.boardNavigationPath, + value + ) ) - ) + } else { + await disk.renameFile( + disk.getFullPath( + state.diskNavigationRoot, + state.diskNavigationPath, + fileName + ), + disk.getFullPath( + state.diskNavigationRoot, + state.diskNavigationPath, + value + ) + ) + } + } catch (e) { + alert(`The file ${fileName} could not be renamed to ${value}`) } state.isSaving = false From 88ca1fbb8d256e6fdd1a5be1723f6eeb63c1332e Mon Sep 17 00:00:00 2001 From: Murilo Polese Date: Wed, 27 Mar 2024 15:48:45 +0100 Subject: [PATCH 6/8] Fix imperceptible bug on file removal alert --- ui/arduino2/store.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/ui/arduino2/store.js b/ui/arduino2/store.js index f4ed624..b3fa798 100644 --- a/ui/arduino2/store.js +++ b/ui/arduino2/store.js @@ -443,9 +443,11 @@ async function store(state, emitter) { message += `Are you sure you want to proceed?` const confirmAction = confirm(message, 'Cancel', 'Yes') - state.isRemoving = false - emitter.emit('render') - if (!confirmAction) return + if (!confirmAction) { + state.isRemoving = false + emitter.emit('render') + return + } for (let i in state.selectedFiles) { const file = state.selectedFiles[i] From fe9ad321f2e3c71e9bf2a458c787a4ca7f2f4e3c Mon Sep 17 00:00:00 2001 From: Murilo Polese Date: Tue, 2 Apr 2024 14:59:28 +0200 Subject: [PATCH 7/8] Fix merge issues --- ui/arduino2/store.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ui/arduino2/store.js b/ui/arduino2/store.js index f54264e..5ed5cdb 100644 --- a/ui/arduino2/store.js +++ b/ui/arduino2/store.js @@ -850,7 +850,7 @@ async function store(state, emitter) { // Check if it will overwrite something const willOverwrite = await checkOverwrite({ fileNames: state.selectedFiles.map(f => f.fileName), - parentFolder: serial.getFullPath(state.boardNavigationRoot, state.boardNavigationPath, ''), + parentPath: serial.getFullPath(state.boardNavigationRoot, state.boardNavigationPath, ''), source: 'board' }) if (willOverwrite.length > 0) { @@ -909,7 +909,7 @@ async function store(state, emitter) { // Check if it will overwrite something const willOverwrite = await checkOverwrite({ fileNames: state.selectedFiles.map(f => f.fileName), - parentFolder: disk.getFullPath(state.diskNavigationRoot, state.diskNavigationPath, ''), + parentPath: disk.getFullPath(state.diskNavigationRoot, state.diskNavigationPath, ''), source: 'disk' }) if (willOverwrite.length > 0) { @@ -1102,7 +1102,7 @@ async function checkBoardFile({ root, parentFolder, fileName }) { async function checkOverwrite({ fileNames = [], parentPath, source }) { let files = [] if (source === 'board') { - files = await getBoardFiles(parentFolder) + files = await getBoardFiles(parentPath) } else { files = await getDiskFiles(parentPath) } From 71285cb89a1e778f4a972f89003126fd0ee7654d Mon Sep 17 00:00:00 2001 From: Murilo Polese Date: Tue, 2 Apr 2024 15:34:56 +0200 Subject: [PATCH 8/8] Fix renaming alerts --- ui/arduino2/store.js | 71 ++++++++++++++++++++++++++++++++++---------- 1 file changed, 56 insertions(+), 15 deletions(-) diff --git a/ui/arduino2/store.js b/ui/arduino2/store.js index 5ed5cdb..e4d989e 100644 --- a/ui/arduino2/store.js +++ b/ui/arduino2/store.js @@ -645,9 +645,9 @@ async function store(state, emitter) { log('finish-renaming', value) // You can only rename one file, the selected one - const fileName = state.selectedFiles[0].fileName + const file = state.selectedFiles[0] - if (!value || fileName == value) { + if (!value || file.fileName == value) { state.renamingFile = null emitter.emit('render') return @@ -657,43 +657,84 @@ async function store(state, emitter) { emitter.emit('render') // Check if new name overwrites something - if (state.renamingFile == 'board') { + if (state.renamingFile == 'board' && state.isConnected) { // Check if it will overwrite something const willOverwrite = await checkOverwrite({ fileNames: [ value ], - parentFolder: disk.getFullPath(state.boardNavigationRoot, state.boardNavigationPath, ''), + parentPath: disk.getFullPath( + state.boardNavigationRoot, state.boardNavigationPath, '' + ), source: 'board' }) if (willOverwrite.length > 0) { - let message = `You are about to overwrite the following files/folders on your board:\n\n` - willOverwrite.forEach(f => message += `${f.fileName}\n`) - message += `\n` + let message = `You are about to overwrite the following file/folder on your board:\n\n` + message += `${value}\n\n` message += `Are you sure you want to proceed?` const confirmAction = confirm(message, 'Cancel', 'Yes') if (!confirmAction) { state.isSaving = false + state.renamingFile = null emitter.emit('render') return } + + if (file.type == 'folder') { + await removeBoardFolder( + serial.getFullPath( + state.boardNavigationRoot, + state.boardNavigationPath, + value + ) + ) + } else if (file.type == 'file') { + await serial.removeFile( + serial.getFullPath( + state.boardNavigationRoot, + state.boardNavigationPath, + value + ) + ) + } } - } else { + } else if (state.renamingFile == 'disk') { // Check if it will overwrite something const willOverwrite = await checkOverwrite({ fileNames: [ value ], - parentFolder: disk.getFullPath(state.diskNavigationRoot, state.diskNavigationPath, ''), + parentPath: disk.getFullPath( + state.diskNavigationRoot, state.diskNavigationPath, '' + ), source: 'disk' }) if (willOverwrite.length > 0) { - let message = `You are about to overwrite the following files/folders on your disk:\n\n` - willOverwrite.forEach(f => message += `${f.fileName}\n`) - message += `\n` + let message = `You are about to overwrite the following file/folder on your disk:\n\n` + message += `${value}\n\n` message += `Are you sure you want to proceed?` const confirmAction = confirm(message, 'Cancel', 'Yes') if (!confirmAction) { state.isSaving = false + state.renamingFile = null emitter.emit('render') return } + + if (file.type == 'folder') { + await disk.removeFolder( + disk.getFullPath( + state.diskNavigationRoot, + state.diskNavigationPath, + value + ) + ) + } else if (file.type == 'file') { + await disk.removeFile( + disk.getFullPath( + state.diskNavigationRoot, + state.diskNavigationPath, + value + ) + ) + } + } } @@ -703,7 +744,7 @@ async function store(state, emitter) { serial.getFullPath( state.boardNavigationRoot, state.boardNavigationPath, - fileName + file.fileName ), serial.getFullPath( state.boardNavigationRoot, @@ -716,7 +757,7 @@ async function store(state, emitter) { disk.getFullPath( state.diskNavigationRoot, state.diskNavigationPath, - fileName + file.fileName ), disk.getFullPath( state.diskNavigationRoot, @@ -726,7 +767,7 @@ async function store(state, emitter) { ) } } catch (e) { - alert(`The file ${fileName} could not be renamed to ${value}`) + alert(`The file ${file.fileName} could not be renamed to ${value}`) } state.isSaving = false