Skip to content

Commit 36c473f

Browse files
committed
Alert user before closing tab with unsaved changes
1 parent 7cfa26f commit 36c473f

File tree

4 files changed

+63
-25
lines changed

4 files changed

+63
-25
lines changed

ui/arduino/store.js

+48-20
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,10 @@ async function store(state, emitter) {
4848
parentFolder: null, // Null parent folder means not saved?
4949
source: 'disk'
5050
})
51+
newFile.editor.onChange = function() {
52+
newFile.hasChanges = true
53+
emitter.emit('render')
54+
}
5155
state.openFiles.push(newFile)
5256
state.editingFile = newFile.id
5357

@@ -351,6 +355,7 @@ async function store(state, emitter) {
351355
log('error', e)
352356
}
353357

358+
openFile.hasChanges = false
354359
state.isSaving = false
355360
state.savingProgress = 0
356361
emitter.emit('refresh-files')
@@ -365,6 +370,11 @@ async function store(state, emitter) {
365370
})
366371
emitter.on('close-tab', (id) => {
367372
log('close-tab', id)
373+
const currentTab = state.openFiles.find(f => f.id === id)
374+
if (currentTab.hasChanges && currentTab.parentFolder !== null) {
375+
let response = confirm("Your file has unsaved changes. Are you sure you want to proceed?")
376+
if (!response) return false
377+
}
368378
state.openFiles = state.openFiles.filter(f => f.id !== id)
369379
// state.editingFile = null
370380

@@ -375,6 +385,10 @@ async function store(state, emitter) {
375385
source: 'disk',
376386
parentFolder: null
377387
})
388+
newFile.editor.onChange = function() {
389+
newFile.hasChanges = true
390+
emitter.emit('render')
391+
}
378392
state.openFiles.push(newFile)
379393
state.editingFile = newFile.id
380394
}
@@ -995,6 +1009,7 @@ async function store(state, emitter) {
9951009
}
9961010
}
9971011

1012+
openFile.hasChanges = false
9981013
state.renamingTab = null
9991014
state.isSaving = false
10001015
state.savingProgress = 0
@@ -1037,43 +1052,49 @@ async function store(state, emitter) {
10371052
let files = []
10381053
for (let i in state.selectedFiles) {
10391054
let selectedFile = state.selectedFiles[i]
1055+
let openFile = null
10401056
if (selectedFile.type == 'folder') {
10411057
// Don't open folders
10421058
continue
10431059
}
1044-
if (selectedFile.source === 'board') {
1060+
if (selectedFile.source == 'board') {
10451061
const fileContent = await serial.loadFile(
10461062
serial.getFullPath(
10471063
'/',
10481064
state.boardNavigationPath,
10491065
selectedFile.fileName
10501066
)
10511067
)
1052-
files.push(
1053-
createFile({
1054-
parentFolder: state.boardNavigationPath,
1055-
fileName: selectedFile.fileName,
1056-
source: selectedFile.source,
1057-
content: fileContent
1058-
})
1059-
)
1060-
} else {
1068+
openFile = createFile({
1069+
parentFolder: state.boardNavigationPath,
1070+
fileName: selectedFile.fileName,
1071+
source: selectedFile.source,
1072+
content: fileContent
1073+
})
1074+
openFile.editor.onChange = function() {
1075+
openFile.hasChanges = true
1076+
emitter.emit('render')
1077+
}
1078+
} else if (selectedFile.source == 'disk') {
10611079
const fileContent = await disk.loadFile(
10621080
disk.getFullPath(
10631081
state.diskNavigationRoot,
10641082
state.diskNavigationPath,
10651083
selectedFile.fileName
10661084
)
10671085
)
1068-
files.push(
1069-
createFile({
1070-
parentFolder: state.diskNavigationPath,
1071-
fileName: selectedFile.fileName,
1072-
source: selectedFile.source,
1073-
content: fileContent
1074-
})
1075-
)
1086+
openFile = createFile({
1087+
parentFolder: state.diskNavigationPath,
1088+
fileName: selectedFile.fileName,
1089+
source: selectedFile.source,
1090+
content: fileContent
1091+
})
1092+
openFile.editor.onChange = function() {
1093+
openFile.hasChanges = true
1094+
emitter.emit('render')
1095+
}
10761096
}
1097+
files.push(openFile)
10771098
}
10781099

10791100
files = files.filter((f) => { // find files to open
@@ -1280,11 +1301,17 @@ async function store(state, emitter) {
12801301
emitter.emit('render')
12811302
})
12821303

1283-
function createFile({ source, parentFolder, fileName, content = newFileContent }) {
1304+
function createFile(args) {
1305+
const {
1306+
source,
1307+
parentFolder,
1308+
fileName,
1309+
content = newFileContent,
1310+
hasChanges = false
1311+
} = args
12841312
const id = generateHash()
12851313
const editor = state.cache(CodeMirrorEditor, `editor_${id}`)
12861314
editor.content = content
1287-
const hasChanges = false
12881315
return {
12891316
id,
12901317
source,
@@ -1300,6 +1327,7 @@ async function store(state, emitter) {
13001327
fileName: generateFileName(),
13011328
parentFolder,
13021329
source,
1330+
hasChanges: true
13031331
})
13041332
}
13051333
}

ui/arduino/views/components/elements/editor.js

+6-2
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,11 @@ class CodeMirrorEditor extends Component {
77

88
load(el) {
99
const onCodeChange = (update) => {
10-
this.content = update.state.doc.toString()
1110
// console.log('code change', this.content)
11+
this.content = update.state.doc.toString()
12+
this.onChange()
1213
}
1314
this.editor = createEditor(this.content, el, onCodeChange)
14-
1515
}
1616

1717
createElement(content) {
@@ -22,4 +22,8 @@ class CodeMirrorEditor extends Component {
2222
update() {
2323
return false
2424
}
25+
26+
onChange() {
27+
return false
28+
}
2529
}

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

+8-3
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@ function Tab(args) {
88
onFinishRenaming = () => false,
99
disabled = false,
1010
active = false,
11-
renaming = false
11+
renaming = false,
12+
hasChanges = false
1213
} = args
1314

1415
if (active) {
@@ -41,7 +42,9 @@ function Tab(args) {
4142
return html`
4243
<div class="tab active" tabindex="0">
4344
<img class="icon" src="media/${icon}" />
44-
<div class="text" ondblclick=${onStartRenaming}>${text}</div>
45+
<div class="text" ondblclick=${onStartRenaming}>
46+
${hasChanges ? ' *' : ''} ${text}
47+
</div>
4548
<div class="options" >
4649
<button onclick=${onCloseTab}>
4750
<img class="icon" src="media/close.svg" />
@@ -65,7 +68,9 @@ function Tab(args) {
6568
onclick=${selectTab}
6669
>
6770
<img class="icon" src="media/${icon}" />
68-
<div class="text">${text}</div>
71+
<div class="text">
72+
${hasChanges ? '*' : ''} ${text}
73+
</div>
6974
<div class="options">
7075
<button onclick=${onCloseTab}>
7176
<img class="icon" src="media/close.svg" />

ui/arduino/views/components/tabs.js

+1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ function Tabs(state, emit) {
77
icon: file.source === 'board'? 'connect.svg': 'computer.svg',
88
active: file.id === state.editingFile,
99
renaming: file.id === state.renamingTab,
10+
hasChanges: file.hasChanges,
1011
onSelectTab: () => emit('select-tab', file.id),
1112
onCloseTab: () => emit('close-tab', file.id),
1213
onStartRenaming: () => emit('rename-tab', file.id),

0 commit comments

Comments
 (0)