Skip to content

Commit 2376e00

Browse files
committed
many desktop fixes and filesystem refactoring
1 parent c6bccf1 commit 2376e00

File tree

6 files changed

+205
-178
lines changed

6 files changed

+205
-178
lines changed

desktop/menu-template.js

Lines changed: 15 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,21 @@ module.exports = [
8484
currentWindow.webContents.send("save-file")
8585
}
8686
},
87+
{
88+
role: "save",
89+
accelerator: "CommandOrControl+Shift+S",
90+
label: "Save As",
91+
click: (menuItem, currentWindow) => {
92+
currentWindow.webContents.send("save-file-as")
93+
}
94+
},
95+
{
96+
role: "export",
97+
label: "Export CSV",
98+
click: (menuItem, currentWindow) => {
99+
currentWindow.webContents.send("export-to-csv")
100+
}
101+
},
87102
{ type: "separator" },
88103
{
89104
role: "quit"
@@ -98,24 +113,6 @@ module.exports = [
98113
click: (menuItem, currentWindow) => {
99114
currentWindow.webContents.send("open-welcome-page")
100115
}
101-
},
102-
{
103-
label: "Settings",
104-
click: (menuItem, currentWindow) => {
105-
currentWindow.webContents.send("open-settings-page")
106-
}
107-
},
108-
{
109-
label: "Samples",
110-
click: (menuItem, currentWindow) => {
111-
currentWindow.webContents.send("open-samples-page")
112-
}
113-
},
114-
{
115-
label: "Label",
116-
click: (menuItem, currentWindow) => {
117-
currentWindow.webContents.send("open-label-page")
118-
}
119116
}
120117
]
121118
},

src/components/DesktopApp/index.js

Lines changed: 72 additions & 128 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,11 @@ import useErrors from "../../utils/use-errors.js"
1010
import useLocalStorage from "../../utils/use-local-storage.js"
1111
import useElectron from "../../utils/use-electron.js"
1212
import templates from "../StartingPage/templates"
13+
import useEventCallback from "use-event-callback"
14+
import { setIn } from "seamless-immutable"
15+
import toUDTCSV from "../../utils/to-udt-csv.js"
16+
17+
import useFileHandler from "../../utils/file-handlers"
1318

1419
const useStyles = makeStyles({
1520
empty: {
@@ -20,142 +25,78 @@ const useStyles = makeStyles({
2025
}
2126
})
2227

28+
const randomId = () =>
29+
Math.random()
30+
.toString()
31+
.split(".")[1]
32+
2333
export default () => {
2434
const c = useStyles()
25-
const [pageName, changePageName] = useState("welcome")
26-
const [currentFile, changeCurrentFile] = useState()
35+
const {
36+
file,
37+
changeFile,
38+
openFile,
39+
openUrl,
40+
makeSession,
41+
saveFile,
42+
recentItems
43+
} = useFileHandler()
44+
2745
const [oha, changeOHA] = useState()
2846
const [errors, addError] = useErrors()
29-
let [recentItems, changeRecentItems] = [[], () => null] // useLocalStorage("recentItems", [])
3047
const { addToast } = useToasts()
31-
if (!recentItems) recentItems = []
48+
3249
const { remote, ipcRenderer } = useElectron()
3350

34-
const onCreateTemplate = useMemo(
35-
() => template => {
36-
changeCurrentFile({
37-
fileName: "unnamed",
38-
content: template.oha,
39-
id: Math.random()
40-
.toString()
41-
.split(".")[1]
42-
})
43-
changeOHA(template.oha)
44-
changePageName("edit")
45-
},
46-
[]
47-
)
51+
const onCreateTemplate = useEventCallback(template => {
52+
changeFile({
53+
fileName: "unnamed",
54+
content: template.oha,
55+
id: randomId(),
56+
mode: "filesystem"
57+
})
58+
})
59+
60+
const openRecentItem = useEventCallback(item => changeFile(item))
61+
const onClickHome = useEventCallback(() => changeFile(null))
4862

4963
useEffect(() => {
50-
const onOpenWelcomePage = () => changePageName("welcome")
51-
const onOpenSettingsPage = () => changePageName("edit")
52-
const onOpenSamplesPage = () => changePageName("edit")
53-
const onOpenLabelPage = () => changePageName("edit")
54-
const onNewFile = (e, data) => {
55-
if (data.templateName) {
56-
onCreateTemplate(
57-
templates.find(template => template.name === data.templateName)
58-
)
59-
} else {
60-
changeCurrentFile({
61-
fileName: "unnamed",
62-
content: {},
63-
id: Math.random()
64-
.toString()
65-
.split(".")[1]
66-
})
67-
changeOHA({})
68-
changePageName("edit")
69-
}
64+
const onOpenWelcomePage = () => changeFile(null)
65+
const onNewFile = (arg0, { templateName } = {}) => {
66+
onCreateTemplate(
67+
templates.find(t => t.name === templateName) || templates[0]
68+
)
7069
}
71-
const onOpenFile = (e, data) => {
72-
try {
73-
const oha = JSON.parse(data.content)
74-
changeCurrentFile({
75-
...data,
76-
content: oha
77-
})
78-
changeOHA(oha)
79-
changePageName("edit")
80-
} catch (e) {
81-
addError(e.toString())
82-
}
83-
}
84-
const onSaveFile = async (e, data) => {
85-
let filePath = currentFile.filePath
86-
if (!currentFile.filePath) {
87-
const {
88-
cancelled,
89-
filePath: newFilePath
90-
} = await remote.dialog.showSaveDialog()
91-
filePath = newFilePath
92-
if (cancelled || !filePath) {
93-
addError("Could not save")
94-
return
95-
}
96-
changeCurrentFile({ ...currentFile, filePath })
97-
}
70+
const saveFileAs = () => saveFile({ saveAs: true })
71+
const exportToCSV = async () => {
72+
if (!file) return
73+
let { cancelled, filePath } = await remote.dialog.showSaveDialog({
74+
filters: [{ name: ".udt.csv", extensions: ["udt.csv"] }]
75+
})
76+
filePath =
77+
!filePath || filePath.endsWith(".json")
78+
? filePath
79+
: `${filePath}.udt.json`
80+
9881
await remote
9982
.require("fs")
100-
.promises.writeFile(filePath, JSON.stringify(oha, null, " "))
101-
addToast("File Saved!")
83+
.promises.writeFile(filePath, toUDTCSV(file.content))
10284
}
10385
ipcRenderer.on("open-welcome-page", onOpenWelcomePage)
104-
ipcRenderer.on("open-settings-page", onOpenSettingsPage)
105-
ipcRenderer.on("open-samples-page", onOpenSamplesPage)
106-
ipcRenderer.on("open-label-page", onOpenLabelPage)
10786
ipcRenderer.on("new-file", onNewFile)
108-
ipcRenderer.on("open-file", onOpenFile)
109-
ipcRenderer.on("save-file", onSaveFile)
87+
ipcRenderer.on("open-file", openFile)
88+
ipcRenderer.on("save-file", saveFile)
89+
ipcRenderer.on("save-file-as", saveFileAs)
90+
ipcRenderer.on("export-to-csv", exportToCSV)
11091
return () => {
11192
ipcRenderer.removeListener("open-welcome-page", onOpenWelcomePage)
112-
ipcRenderer.removeListener("open-settings-page", onOpenWelcomePage)
113-
ipcRenderer.removeListener("open-samples-page", onOpenWelcomePage)
114-
ipcRenderer.removeListener("open-label-page", onOpenWelcomePage)
11593
ipcRenderer.removeListener("new-file", onNewFile)
116-
ipcRenderer.removeListener("open-file", onOpenFile)
117-
ipcRenderer.removeListener("save-file", onSaveFile)
118-
}
119-
}, [currentFile])
120-
121-
const openRecentItem = useMemo(() => item => {
122-
changeCurrentFile(item)
123-
try {
124-
changeOHA(JSON.parse(item.content))
125-
} catch (e) {
126-
addError("Couldn't parse content into JSON")
94+
ipcRenderer.removeListener("open-file", openFile)
95+
ipcRenderer.removeListener("save-file", saveFile)
96+
ipcRenderer.removeListener("save-file-as", saveFileAs)
97+
ipcRenderer.removeListener("export-to-csv", exportToCSV)
12798
}
128-
changePageName("edit")
129-
})
130-
131-
const onClickHome = useMemo(() => () => changePageName("welcome"), [])
132-
133-
const handleOpenFile = useMemo(
134-
() => file => {
135-
const { name: fileName, path: filePath } = file
136-
const reader = new FileReader()
137-
reader.onload = e => {
138-
const content = e.target.result
139-
try {
140-
const oha = JSON.parse(content)
141-
// TODO validate OHA and prompt to open anyway if invalid
142-
changeCurrentFile({
143-
fileName,
144-
filePath,
145-
content: oha,
146-
id: filePath
147-
})
148-
changeOHA(oha)
149-
changePageName("edit")
150-
} catch (e) {
151-
console.log(e.toString())
152-
addError(`Could not read file "${file.name}"`)
153-
}
154-
}
155-
reader.readAsText(file)
156-
},
157-
[]
158-
)
99+
}, [file])
159100

160101
return (
161102
<>
@@ -164,30 +105,33 @@ export default () => {
164105
recentItems,
165106
onClickTemplate: onCreateTemplate,
166107
onClickHome,
108+
title: file ? file.fileName : null,
109+
fileOpen: Boolean(file),
167110
onOpenRecentItem: openRecentItem,
168-
isDesktop: true
111+
isDesktop: true,
112+
onOpenFile: openFile
169113
}}
170114
>
171-
{pageName === "welcome" ? (
115+
{!file ? (
172116
<StartingPage
173117
showDownloadLink={false}
174-
onFileDrop={handleOpenFile}
118+
onFileDrop={openFile}
175119
onOpenTemplate={onCreateTemplate}
176120
recentItems={recentItems}
177121
onOpenRecentItem={openRecentItem}
178122
/>
179-
) : pageName === "edit" && currentFile ? (
123+
) : (
180124
<OHAEditor
181-
key={currentFile.id}
182-
{...currentFile}
183-
oha={oha}
125+
key={file.id}
126+
{...file}
127+
oha={file.content}
184128
onChangeFileName={newName => {
185-
changeCurrentFile({ ...currentFile, fileName: newName })
129+
changeFile(setIn(file, ["fileName"], newName))
130+
}}
131+
onChangeOHA={newOHA => {
132+
changeFile(setIn(file, ["content"], newOHA))
186133
}}
187-
onChangeOHA={changeOHA}
188134
/>
189-
) : (
190-
<div className={c.empty}>Unknown Page "{pageName}"</div>
191135
)}
192136
</HeaderContext.Provider>
193137
<ErrorToasts errors={errors} />

src/components/LocalStorageApp/index.js

Lines changed: 15 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -22,26 +22,31 @@ const useStyles = makeStyles({
2222
}
2323
})
2424

25+
const randomId = () =>
26+
Math.random()
27+
.toString()
28+
.split(".")[1]
29+
2530
export default () => {
2631
const c = useStyles()
27-
const { file, changeFile, openFile, openUrl, makeSession } = useFileHandler()
32+
const {
33+
file,
34+
changeFile,
35+
openFile,
36+
openUrl,
37+
makeSession,
38+
recentItems
39+
} = useFileHandler()
2840
const [errors, addError] = useErrors()
29-
let [recentItems, changeRecentItems] = useLocalStorage("recentItems", [])
30-
if (!recentItems) recentItems = []
31-
32-
const randomId = () =>
33-
Math.random()
34-
.toString()
35-
.split(".")[1]
3641

37-
const onCreateTemplate = useCallback(template => {
42+
const onCreateTemplate = useEventCallback(template => {
3843
changeFile({
3944
fileName: "unnamed",
4045
content: template.oha,
4146
id: randomId(),
4247
mode: "local-storage"
4348
})
44-
}, [])
49+
})
4550

4651
const openRecentItem = useEventCallback(item => changeFile(item))
4752
const onClickHome = useEventCallback(() => changeFile(null))
@@ -55,17 +60,6 @@ export default () => {
5560
}
5661
})
5762

58-
useEffect(() => {
59-
if (!file) return
60-
if (!file.fileName || file.fileName === "unnamed") return
61-
if (file.mode !== "local-storage") return
62-
if (recentItems.map(item => item.id).includes(file.id)) {
63-
changeRecentItems(recentItems.map(ri => (ri.id === file.id ? file : ri)))
64-
} else {
65-
changeRecentItems([file].concat(recentItems).slice(0, 3))
66-
}
67-
}, [file])
68-
6963
const inSession = file && file.mode === "server"
7064
const [sessionBoxOpen, changeSessionBoxOpen] = useState(false)
7165

src/utils/file-handlers/index.js

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@ export default () => {
1818
const [file, changeFile] = useState()
1919
const { addToast } = useToasts()
2020

21-
useFilesystem(file, changeFile)
22-
useLocalStorage(file, changeFile)
21+
const { saveFile } = useFilesystem(file, changeFile)
22+
const { recentItems } = useLocalStorage(file, changeFile)
2323
useServer(file, changeFile)
2424

2525
// Telemetry
@@ -97,10 +97,16 @@ export default () => {
9797
)
9898
})
9999

100-
return useMemo(() => ({ file, changeFile, openFile, openUrl, makeSession }), [
101-
file,
102-
changeFile,
103-
openFile,
104-
makeSession
105-
])
100+
return useMemo(
101+
() => ({
102+
file,
103+
changeFile,
104+
openFile,
105+
openUrl,
106+
makeSession,
107+
saveFile,
108+
recentItems
109+
}),
110+
[file, changeFile, openFile, makeSession, recentItems]
111+
)
106112
}

0 commit comments

Comments
 (0)