-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathuseFile.tsx
More file actions
125 lines (112 loc) · 3.36 KB
/
Copy pathuseFile.tsx
File metadata and controls
125 lines (112 loc) · 3.36 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
import { useDispatch, useSelector } from "react-redux";
import {
fileChanged,
refreshFile as refreshFileAction,
selectFile,
fileComparator
} from "../../redux/slices/fileCacheSlice";
import { MacroMap } from "../../types/macros";
import { errorWidget, WidgetDescription } from "../widgets/createComponent";
import { useEffect } from "react";
import { httpRequest } from "../../misc";
import log from "loglevel";
import { parseBob } from "../widgets/EmbeddedDisplay/bobParser";
import { parseJson } from "../widgets/EmbeddedDisplay/jsonParser";
import { parseOpi } from "../widgets/EmbeddedDisplay/opiParser";
import { Store } from "redux";
import { newAbsolutePosition } from "../../types/position";
import { parseBcf } from "../widgets/EmbeddedDisplay/bcfParser";
const EMPTY_WIDGET: WidgetDescription = {
type: "shape",
id: "123",
fileId: "AShapeFilePath",
position: newAbsolutePosition("0", "0", "0", "0")
};
export interface File {
path: string;
macros: MacroMap;
defaultProtocol: string;
}
export async function fetchAndConvert(
filepath: string,
protocol: string,
macros?: MacroMap
): Promise<WidgetDescription> {
try {
const parentDir = filepath.slice(0, filepath.lastIndexOf("/"));
const fileResponse = await httpRequest(filepath);
const fileExt = filepath.split(".").pop() || "json";
const contents = await fileResponse.text();
let description = EMPTY_WIDGET;
// Hack!
if (contents.startsWith("<!DOCTYPE html>")) {
throw new Error("File not found");
}
if (contents !== "") {
// Convert the contents to widget description style object
switch (fileExt) {
case "bob":
description = await parseBob(
contents,
protocol,
parentDir,
macros,
filepath
);
break;
case "bcf":
description = await parseBcf(contents, protocol, parentDir, filepath);
break;
case "json":
description = await parseJson(
contents,
protocol,
parentDir,
filepath
);
break;
case "opi":
description = await parseOpi(contents, protocol, parentDir, filepath);
break;
}
}
return description;
} catch (error) {
const message = `Error parsing ${filepath}: ${error}.`;
log.warn(message);
log.warn(error);
return errorWidget(message);
}
}
export function useFile(file: File, macros?: MacroMap): WidgetDescription {
const dispatch = useDispatch();
const contents = useSelector(
(state): any => selectFile(state, file.path),
fileComparator
);
useEffect(() => {
const fetchData = async (): Promise<void> => {
const widgetDescription = await fetchAndConvert(
file.path,
file.defaultProtocol,
macros
);
// Populate the file cache.
if (isMounted) {
dispatch(fileChanged({ file: file.path, contents: widgetDescription }));
}
};
if (contents == null) {
fetchData();
}
let isMounted = true;
// Tidy up in case component is unmounted
return () => {
isMounted = false;
};
}, [file.path, file.defaultProtocol, contents, dispatch, macros]);
return contents || EMPTY_WIDGET;
}
export function refreshFile(store: Store, file: string): void {
store.dispatch(refreshFileAction({ file: file }));
}