|
1 | | -import { DecodeBase64ToBinary } from "@dev/core"; |
| 1 | +import { DecodeBase64ToBinary, Logger } from "@dev/core"; |
2 | 2 | import type { GlobalState } from "../globalState"; |
3 | 3 | import { Utilities } from "./utilities"; |
4 | 4 |
|
@@ -38,6 +38,48 @@ export class LoadManager { |
38 | 38 | this._loadPlayground(id); |
39 | 39 | } |
40 | 40 | }); |
| 41 | + |
| 42 | + globalState.onLocalLoadRequiredObservable.add(async () => { |
| 43 | + globalState.onDisplayWaitRingObservable.notifyObservers(true); |
| 44 | + const json = await this._pickJsonFileAsync(); |
| 45 | + if (json) { |
| 46 | + location.hash = ""; |
| 47 | + this._processJsonPayload(json); |
| 48 | + } else { |
| 49 | + globalState.onDisplayWaitRingObservable.notifyObservers(false); |
| 50 | + } |
| 51 | + }); |
| 52 | + } |
| 53 | + |
| 54 | + private async _pickJsonFileAsync() { |
| 55 | + try { |
| 56 | + // Show native file picker |
| 57 | + const [handle] = await (window as any).showOpenFilePicker({ |
| 58 | + types: [ |
| 59 | + { |
| 60 | + description: "Playground JSON Files", |
| 61 | + // eslint-disable-next-line @typescript-eslint/naming-convention |
| 62 | + accept: { "application/json": [".json"] }, |
| 63 | + }, |
| 64 | + ], |
| 65 | + multiple: false, |
| 66 | + }); |
| 67 | + |
| 68 | + // Get the file from the handle |
| 69 | + const file = await handle.getFile(); |
| 70 | + |
| 71 | + // Read the file as text |
| 72 | + const text = await file.text(); |
| 73 | + |
| 74 | + return text; // This is the raw JSON string |
| 75 | + } catch (err) { |
| 76 | + if (err.name === "AbortError") { |
| 77 | + Logger.Warn("User canceled file selection"); |
| 78 | + } else { |
| 79 | + Logger.Error("Error reading file:", err); |
| 80 | + } |
| 81 | + return null; |
| 82 | + } |
41 | 83 | } |
42 | 84 |
|
43 | 85 | private _cleanHash() { |
@@ -92,81 +134,85 @@ export class LoadManager { |
92 | 134 | } |
93 | 135 | } |
94 | 136 |
|
| 137 | + private _processJsonPayload(data: string) { |
| 138 | + if (data.indexOf("class Playground") !== -1) { |
| 139 | + if (this.globalState.language === "JS") { |
| 140 | + Utilities.SwitchLanguage("TS", this.globalState, true); |
| 141 | + } |
| 142 | + } else { |
| 143 | + // If we're loading JS content and it's TS page |
| 144 | + if (this.globalState.language === "TS") { |
| 145 | + Utilities.SwitchLanguage("JS", this.globalState, true); |
| 146 | + } |
| 147 | + } |
| 148 | + |
| 149 | + const snippet = JSON.parse(data); |
| 150 | + |
| 151 | + // Check if title / descr / tags are already set |
| 152 | + if (snippet.name != null && snippet.name != "") { |
| 153 | + this.globalState.currentSnippetTitle = snippet.name; |
| 154 | + } else { |
| 155 | + this.globalState.currentSnippetTitle = ""; |
| 156 | + } |
| 157 | + |
| 158 | + if (snippet.description != null && snippet.description != "") { |
| 159 | + this.globalState.currentSnippetDescription = snippet.description; |
| 160 | + } else { |
| 161 | + this.globalState.currentSnippetDescription = ""; |
| 162 | + } |
| 163 | + |
| 164 | + if (snippet.tags != null && snippet.tags != "") { |
| 165 | + this.globalState.currentSnippetTags = snippet.tags; |
| 166 | + } else { |
| 167 | + this.globalState.currentSnippetTags = ""; |
| 168 | + } |
| 169 | + |
| 170 | + // Extract code |
| 171 | + const payload = JSON.parse(snippet.jsonPayload || snippet.payload); |
| 172 | + let code: string = payload.code.toString(); |
| 173 | + |
| 174 | + if (payload.unicode) { |
| 175 | + // Need to decode |
| 176 | + const encodedData = payload.unicode; |
| 177 | + const decoder = new TextDecoder("utf8"); |
| 178 | + |
| 179 | + code = decoder.decode((DecodeBase64ToBinary || DecodeBase64ToBinaryReproduced)(encodedData)); |
| 180 | + } |
| 181 | + |
| 182 | + // check the engine |
| 183 | + if (payload.engine && ["WebGL1", "WebGL2", "WebGPU"].includes(payload.engine)) { |
| 184 | + // check if an engine is forced in the URL |
| 185 | + const url = new URL(window.location.href); |
| 186 | + const engineInURL = url.searchParams.get("engine") || url.search.includes("webgpu"); |
| 187 | + // get the current engine |
| 188 | + const currentEngine = Utilities.ReadStringFromStore("engineVersion", "WebGL2", true); |
| 189 | + if (!engineInURL && currentEngine !== payload.engine) { |
| 190 | + if ( |
| 191 | + window.confirm( |
| 192 | + `The engine version in this playground (${payload.engine}) is different from the one you are currently using (${currentEngine}). |
| 193 | +Confirm to switch to ${payload.engine}, cancel to keep ${currentEngine}` |
| 194 | + ) |
| 195 | + ) { |
| 196 | + // we need to change the engine |
| 197 | + Utilities.StoreStringToStore("engineVersion", payload.engine, true); |
| 198 | + window.location.reload(); |
| 199 | + } |
| 200 | + } |
| 201 | + } |
| 202 | + |
| 203 | + this.globalState.onCodeLoaded.notifyObservers(code); |
| 204 | + |
| 205 | + this.globalState.onMetadataUpdatedObservable.notifyObservers(); |
| 206 | + } |
| 207 | + |
95 | 208 | private _loadPlayground(id: string) { |
96 | 209 | this.globalState.loadingCodeInProgress = true; |
97 | 210 | try { |
98 | 211 | const xmlHttp = new XMLHttpRequest(); |
99 | 212 | xmlHttp.onreadystatechange = () => { |
100 | 213 | if (xmlHttp.readyState === 4) { |
101 | 214 | if (xmlHttp.status === 200) { |
102 | | - if (xmlHttp.responseText.indexOf("class Playground") !== -1) { |
103 | | - if (this.globalState.language === "JS") { |
104 | | - Utilities.SwitchLanguage("TS", this.globalState, true); |
105 | | - } |
106 | | - } else { |
107 | | - // If we're loading JS content and it's TS page |
108 | | - if (this.globalState.language === "TS") { |
109 | | - Utilities.SwitchLanguage("JS", this.globalState, true); |
110 | | - } |
111 | | - } |
112 | | - |
113 | | - const snippet = JSON.parse(xmlHttp.responseText); |
114 | | - |
115 | | - // Check if title / descr / tags are already set |
116 | | - if (snippet.name != null && snippet.name != "") { |
117 | | - this.globalState.currentSnippetTitle = snippet.name; |
118 | | - } else { |
119 | | - this.globalState.currentSnippetTitle = ""; |
120 | | - } |
121 | | - |
122 | | - if (snippet.description != null && snippet.description != "") { |
123 | | - this.globalState.currentSnippetDescription = snippet.description; |
124 | | - } else { |
125 | | - this.globalState.currentSnippetDescription = ""; |
126 | | - } |
127 | | - |
128 | | - if (snippet.tags != null && snippet.tags != "") { |
129 | | - this.globalState.currentSnippetTags = snippet.tags; |
130 | | - } else { |
131 | | - this.globalState.currentSnippetTags = ""; |
132 | | - } |
133 | | - |
134 | | - // Extract code |
135 | | - const payload = JSON.parse(snippet.jsonPayload); |
136 | | - let code: string = payload.code.toString(); |
137 | | - |
138 | | - if (payload.unicode) { |
139 | | - // Need to decode |
140 | | - const encodedData = payload.unicode; |
141 | | - const decoder = new TextDecoder("utf8"); |
142 | | - |
143 | | - code = decoder.decode((DecodeBase64ToBinary || DecodeBase64ToBinaryReproduced)(encodedData)); |
144 | | - } |
145 | | - |
146 | | - // check the engine |
147 | | - if (payload.engine && ["WebGL1", "WebGL2", "WebGPU"].includes(payload.engine)) { |
148 | | - // check if an engine is forced in the URL |
149 | | - const url = new URL(window.location.href); |
150 | | - const engineInURL = url.searchParams.get("engine") || url.search.includes("webgpu"); |
151 | | - // get the current engine |
152 | | - const currentEngine = Utilities.ReadStringFromStore("engineVersion", "WebGL2", true); |
153 | | - if (!engineInURL && currentEngine !== payload.engine) { |
154 | | - if ( |
155 | | - window.confirm( |
156 | | - `The engine version in this playground (${payload.engine}) is different from the one you are currently using (${currentEngine}). |
157 | | -Confirm to switch to ${payload.engine}, cancel to keep ${currentEngine}` |
158 | | - ) |
159 | | - ) { |
160 | | - // we need to change the engine |
161 | | - Utilities.StoreStringToStore("engineVersion", payload.engine, true); |
162 | | - window.location.reload(); |
163 | | - } |
164 | | - } |
165 | | - } |
166 | | - |
167 | | - this.globalState.onCodeLoaded.notifyObservers(code); |
168 | | - |
169 | | - this.globalState.onMetadataUpdatedObservable.notifyObservers(); |
| 215 | + this._processJsonPayload(xmlHttp.responseText); |
170 | 216 | } |
171 | 217 | } |
172 | 218 | }; |
|
0 commit comments