Skip to content

Commit da22e5d

Browse files
committed
Verbose attempt to implement renaming tabs
1 parent 1e43d2d commit da22e5d

File tree

5 files changed

+234
-21
lines changed

5 files changed

+234
-21
lines changed

ui/arduino2/main.css

+12
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,18 @@ button.small .icon {
186186
background: rgba(255, 255, 255, 0.5);
187187
}
188188

189+
.tab .text input {
190+
box-sizing: border-box;
191+
border: none;
192+
border-radius: none;
193+
height: 100%;
194+
width: 100%;
195+
background: rgba(255, 255, 255, 0.5);
196+
font-family: inherit;
197+
font-size: inherit;
198+
outline-color: #F4BA00;
199+
}
200+
189201
#code-editor {
190202
flex: 1 0 0;
191203
align-self: stretch;

ui/arduino2/store.js

+162-2
Original file line numberDiff line numberDiff line change
@@ -641,8 +641,8 @@ async function store(state, emitter) {
641641
state.renamingFile = source
642642
emitter.emit('render')
643643
})
644-
emitter.on('finish-renaming', async (value) => {
645-
log('finish-renaming', value)
644+
emitter.on('finish-renaming-file', async (value) => {
645+
log('finish-renaming-file', value)
646646

647647
// You can only rename one file, the selected one
648648
const file = state.selectedFiles[0]
@@ -776,6 +776,166 @@ async function store(state, emitter) {
776776
emitter.emit('render')
777777
})
778778

779+
emitter.on('rename-tab', (id) => {
780+
log('rename-tab', id)
781+
state.renamingTab = id
782+
emitter.emit('render')
783+
})
784+
emitter.on('finish-renaming-tab', async (value) => {
785+
log('finish-renaming-tab', value)
786+
let response = canSave({
787+
view: state.view,
788+
isConnected: state.isConnected,
789+
openFiles: state.openFiles,
790+
editingFile: state.editingFile
791+
})
792+
if (response == false) {
793+
log("can't save")
794+
return
795+
}
796+
797+
state.isSaving = true
798+
emitter.emit('render')
799+
800+
// Rename the open file object
801+
let openFile = state.openFiles.find(f => f.id === state.renamingTab)
802+
if (value == openFile.fileName) {
803+
state.renamingTab = null
804+
state.isSaving = false
805+
emitter.emit('render')
806+
return
807+
}
808+
809+
const oldName = openFile.fileName
810+
openFile.fileName = value
811+
812+
let willOverwrite = false
813+
if (openFile.parentFolder === null) { // it's a new file
814+
// Define parent folder
815+
if (openFile.source == 'board') {
816+
openFile.parentFolder = state.boardNavigationPath
817+
// Check for overwrite
818+
willOverwrite = await serial.fileExists(
819+
serial.getFullPath(
820+
state.boardNavigationRoot,
821+
openFile.parentFolder,
822+
openFile.fileName
823+
)
824+
)
825+
} else if (openFile.source == 'disk') {
826+
openFile.parentFolder = state.diskNavigationPath
827+
// Check for overwrite
828+
willOverwrite = await disk.fileExists(
829+
disk.getFullPath(
830+
state.diskNavigationRoot,
831+
openFile.parentFolder,
832+
openFile.fileName
833+
)
834+
)
835+
}
836+
} else if (openFile.parentFolder !== null) {
837+
if (openFile.source == 'board') {
838+
// Check for overwrite
839+
willOverwrite = await serial.fileExists(
840+
serial.getFullPath(
841+
state.boardNavigationRoot,
842+
openFile.parentFolder,
843+
openFile.fileName
844+
)
845+
)
846+
} else if (openFile.source == 'disk') {
847+
// Check for overwrite
848+
willOverwrite = await disk.fileExists(
849+
disk.getFullPath(
850+
state.diskNavigationRoot,
851+
openFile.parentFolder,
852+
openFile.fileName
853+
)
854+
)
855+
}
856+
}
857+
858+
// SAVE FILE CONTENTS
859+
const contents = openFile.editor.editor.state.doc.toString()
860+
try {
861+
if (openFile.source == 'board') {
862+
await serial.get_prompt()
863+
await serial.saveFileContent(
864+
serial.getFullPath(
865+
state.boardNavigationRoot,
866+
openFile.parentFolder,
867+
oldName
868+
),
869+
contents,
870+
(e) => {
871+
state.savingProgress = e
872+
emitter.emit('render')
873+
}
874+
)
875+
} else if (openFile.source == 'disk') {
876+
await disk.saveFileContent(
877+
disk.getFullPath(
878+
state.diskNavigationRoot,
879+
openFile.parentFolder,
880+
oldName
881+
),
882+
contents
883+
)
884+
}
885+
} catch (e) {
886+
log('error', e)
887+
}
888+
889+
if (willOverwrite) {
890+
const confirmation = confirm(`You are about to overwrite the file ${openFile.fileName} on your ${openFile.source}.\n\n Are you sure you want to proceed?`, 'Cancel', 'Yes')
891+
if (!confirmation) {
892+
state.renamingTab = null
893+
state.isSaving = false
894+
openFile.fileName = oldName
895+
emitter.emit('render')
896+
return
897+
}
898+
}
899+
900+
try {
901+
if (openFile.source == 'board') {
902+
await serial.renameFile(
903+
serial.getFullPath(
904+
state.boardNavigationRoot,
905+
openFile.parentFolder,
906+
oldName
907+
),
908+
serial.getFullPath(
909+
state.boardNavigationRoot,
910+
openFile.parentFolder,
911+
openFile.fileName
912+
)
913+
)
914+
} else if (openFile.source == 'disk') {
915+
await disk.renameFile(
916+
disk.getFullPath(
917+
state.diskNavigationRoot,
918+
openFile.parentFolder,
919+
oldName
920+
),
921+
disk.getFullPath(
922+
state.diskNavigationRoot,
923+
openFile.parentFolder,
924+
openFile.fileName
925+
)
926+
)
927+
}
928+
} catch(e) {
929+
log('error', e)
930+
}
931+
932+
state.renamingTab = null
933+
state.isSaving = false
934+
state.savingProgress = 0
935+
emitter.emit('refresh-files')
936+
emitter.emit('render')
937+
})
938+
779939
emitter.on('toggle-file-selection', (file, source, event) => {
780940
log('toggle-file-selection', file, source, event)
781941
// Single file selection unless holding keyboard key

ui/arduino2/views/components/elements/tab.js

+44-16
Original file line numberDiff line numberDiff line change
@@ -4,25 +4,53 @@ function Tab(args) {
44
icon = 'computer.svg',
55
onSelectTab = () => false,
66
onCloseTab = () => false,
7+
onStartRenaming = () => false,
8+
onFinishRenaming = () => false,
79
disabled = false,
8-
active = false
10+
active = false,
11+
renaming = false
912
} = args
1013

11-
let activeClass = active ? 'active' : ''
12-
let disabledClass = disabled ? 'disabled' : ''
13-
1414
if (active) {
15-
return html`
16-
<div class="tab active" tabindex="0">
17-
<img class="icon" src="media/${icon}" />
18-
<div class="text">${text}</div>
19-
<div class="options" >
20-
<button onclick=${onCloseTab}>
21-
<img class="icon" src="media/close.svg" />
22-
</button>
15+
if (renaming) {
16+
function onBlur(e) {
17+
onFinishRenaming(e.target.value)
18+
}
19+
function onKeyDown(e) {
20+
if(e.key.toLowerCase() === 'enter') {
21+
e.target.blur()
22+
}
23+
if(e.key.toLowerCase() === 'escape') {
24+
e.target.value = null
25+
e.target.blur()
26+
}
27+
}
28+
return html`
29+
<div class="tab active" tabindex="0">
30+
<img class="icon" src="media/${icon}" />
31+
<div class="text">
32+
<input type="text"
33+
value=${text}
34+
onblur=${onBlur}
35+
onkeydown=${onKeyDown}
36+
/>
37+
</div>
2338
</div>
24-
</div>
25-
`
39+
`
40+
} else {
41+
return html`
42+
<div class="tab active" tabindex="0">
43+
<img class="icon" src="media/${icon}" />
44+
<div class="text" ondblclick=${onStartRenaming}>${text}</div>
45+
<div class="options" >
46+
<button onclick=${onCloseTab}>
47+
<img class="icon" src="media/close.svg" />
48+
</button>
49+
</div>
50+
</div>
51+
`
52+
}
53+
2654
}
2755

2856
function selectTab(e) {
@@ -32,8 +60,8 @@ function Tab(args) {
3260

3361
return html`
3462
<div
35-
class="tab ${activeClass} ${disabledClass}"
36-
tabindex=${active ? 0 : null}
63+
class="tab"
64+
tabindex="1"
3765
onclick=${selectTab}
3866
>
3967
<img class="icon" src="media/${icon}" />

ui/arduino2/views/components/file-list.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ function generateFileList(source) {
3535
<input type="text"
3636
value=${item.fileName}
3737
onkeydown=${onKeyEvent}
38-
onblur=${(e) => emit('finish-renaming', e.target.value)}
38+
onblur=${(e) => emit('finish-renaming-file', e.target.value)}
3939
onclick=${(e) => false}
4040
ondblclick=${(e) => false}
4141
/>

ui/arduino2/views/components/tabs.js

+15-2
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,28 @@
11
function Tabs(state, emit) {
2-
return html`
2+
const tabs = html`
33
<div id="tabs">
44
${state.openFiles.map((file) => {
55
return Tab({
66
text: file.fileName,
77
icon: file.source === 'board'? 'connect.svg': 'computer.svg',
88
active: file.id === state.editingFile,
9+
renaming: file.id === state.renamingTab,
910
onSelectTab: () => emit('select-tab', file.id),
10-
onCloseTab: () => emit('close-tab', file.id)
11+
onCloseTab: () => emit('close-tab', file.id),
12+
onStartRenaming: () => emit('rename-tab', file.id),
13+
onFinishRenaming: (value) => emit('finish-renaming-tab', value)
1114
})
1215
})}
1316
</div>
1417
`
18+
// Mutation observer
19+
const observer = new MutationObserver((mutations) => {
20+
const el = tabs.querySelector('input')
21+
if (el) {
22+
el.focus()
23+
}
24+
})
25+
observer.observe(tabs, { childList: true, subtree:true })
26+
27+
return tabs
1528
}

0 commit comments

Comments
 (0)