|
1 | 1 | <script> |
2 | | - import * as fs from "@tauri-apps/plugin-fs"; |
3 | | - import { convertFileSrc } from "@tauri-apps/api/core"; |
4 | | - import { arrayBufferToBase64 } from "../lib/utils"; |
5 | | - import { onDestroy } from "svelte"; |
| 2 | + import * as fs from '@tauri-apps/plugin-fs' |
| 3 | + import { convertFileSrc } from '@tauri-apps/api/core' |
| 4 | + import { arrayBufferToBase64 } from '../lib/utils' |
| 5 | + import { onDestroy } from 'svelte' |
6 | 6 |
|
7 | | - export let onMessage; |
8 | | - export let insecureRenderHtml; |
| 7 | + const { onMessage, insecureRenderHtml } = $props() |
9 | 8 |
|
10 | | - let path = ""; |
11 | | - let img; |
| 9 | + let path = $state('') |
| 10 | + let img |
12 | 11 | /** @type {fs.FileHandle} */ |
13 | | - let file; |
14 | | - let renameTo; |
15 | | - let watchPath = ""; |
16 | | - let watchDebounceDelay = "0"; |
17 | | - let watchRecursive = false; |
18 | | - let unwatchFn; |
19 | | - let unwatchPath = ""; |
20 | | -
|
21 | | - function getDir() { |
22 | | - const dirSelect = document.getElementById("dir"); |
23 | | - return dirSelect.value ? parseInt(dir.value) : null; |
24 | | - } |
25 | | -
|
26 | | - const DirOptions = Object.keys(fs.BaseDirectory) |
27 | | - .filter((key) => isNaN(parseInt(key))) |
28 | | - .map((dir) => [dir, fs.BaseDirectory[dir]]); |
| 12 | + let file = $state() |
| 13 | + let renameTo = $state() |
| 14 | + let watchPath = $state('') |
| 15 | + let watchDebounceDelay = $state(0) |
| 16 | + let watchRecursive = $state(false) |
| 17 | + /** @type {fs.BaseDirectory | undefined} */ |
| 18 | + let baseDir = $state() |
| 19 | + let unwatchFn |
| 20 | + let unwatchPath = '' |
| 21 | +
|
| 22 | + const dirOptions = Object.keys(fs.BaseDirectory).filter((key) => |
| 23 | + isNaN(parseInt(key)) |
| 24 | + ) |
29 | 25 |
|
30 | 26 | function open() { |
31 | 27 | fs.open(path, { |
32 | | - baseDir: getDir(), |
| 28 | + baseDir, |
33 | 29 | read: true, |
34 | 30 | write: true, |
35 | | - create: true, |
| 31 | + create: true |
36 | 32 | }) |
37 | 33 | .then((f) => { |
38 | | - file = f; |
39 | | - onMessage(`Opened ${path}`); |
| 34 | + file = f |
| 35 | + onMessage(`Opened ${path}`) |
40 | 36 | }) |
41 | | - .catch(onMessage); |
| 37 | + .catch(onMessage) |
42 | 38 | } |
43 | 39 |
|
44 | 40 | function mkdir() { |
45 | | - fs.mkdir(path, { baseDir: getDir() }) |
| 41 | + fs.mkdir(path, { baseDir }) |
46 | 42 | .then(() => { |
47 | | - onMessage(`Created dir ${path}`); |
| 43 | + onMessage(`Created dir ${path}`) |
48 | 44 | }) |
49 | | - .catch(onMessage); |
| 45 | + .catch(onMessage) |
50 | 46 | } |
51 | 47 |
|
52 | 48 | function remove() { |
53 | | - fs.remove(path, { baseDir: getDir() }) |
| 49 | + fs.remove(path, { baseDir }) |
54 | 50 | .then(() => { |
55 | | - onMessage(`Removed ${path}`); |
| 51 | + onMessage(`Removed ${path}`) |
56 | 52 | }) |
57 | | - .catch(onMessage); |
| 53 | + .catch(onMessage) |
58 | 54 | } |
59 | 55 |
|
60 | 56 | function rename() { |
61 | 57 | fs.rename(path, renameTo, { |
62 | | - oldPathBaseDir: getDir(), |
63 | | - newPathBaseDir: getDir(), |
| 58 | + oldPathBaseDir, |
| 59 | + newPathBaseDir |
64 | 60 | }) |
65 | 61 | .then(() => { |
66 | | - onMessage(`Renamed ${path} to ${renameTo}`); |
| 62 | + onMessage(`Renamed ${path} to ${renameTo}`) |
67 | 63 | }) |
68 | | - .catch(onMessage); |
| 64 | + .catch(onMessage) |
69 | 65 | } |
70 | 66 |
|
71 | 67 | function truncate() { |
72 | 68 | file |
73 | 69 | .truncate(0) |
74 | 70 | .then(() => { |
75 | | - onMessage(`Truncated file`); |
| 71 | + onMessage(`Truncated file`) |
76 | 72 | }) |
77 | | - .catch(onMessage); |
| 73 | + .catch(onMessage) |
78 | 74 | } |
79 | 75 |
|
80 | 76 | function stat() { |
81 | 77 | file |
82 | 78 | .stat() |
83 | 79 | .then((stat) => { |
84 | | - onMessage(`File stat ${JSON.stringify(stat)}`); |
| 80 | + onMessage(`File stat ${JSON.stringify(stat)}`) |
85 | 81 | }) |
86 | | - .catch(onMessage); |
| 82 | + .catch(onMessage) |
87 | 83 | } |
88 | 84 |
|
89 | 85 | function read() { |
90 | 86 | const opts = { |
91 | | - baseDir: getDir(), |
92 | | - }; |
| 87 | + baseDir |
| 88 | + } |
93 | 89 | fs.stat(path, opts) |
94 | 90 | .then((stat) => { |
95 | | - const isFile = stat.isFile; |
| 91 | + const isFile = stat.isFile |
96 | 92 |
|
97 | 93 | const promise = isFile |
98 | 94 | ? fs.readFile(path, opts) |
99 | | - : fs.readDir(path, opts); |
| 95 | + : fs.readDir(path, opts) |
100 | 96 | promise |
101 | 97 | .then(function (response) { |
102 | 98 | if (isFile) { |
103 | | - if (path.includes(".png") || path.includes(".jpg")) { |
| 99 | + if (path.includes('.png') || path.includes('.jpg')) { |
104 | 100 | arrayBufferToBase64( |
105 | 101 | new Uint8Array(response), |
106 | 102 | function (base64) { |
107 | | - const src = "data:image/png;base64," + base64; |
108 | | - insecureRenderHtml('<img src="' + src + '"></img>'); |
| 103 | + const src = 'data:image/png;base64,' + base64 |
| 104 | + insecureRenderHtml('<img src="' + src + '"></img>') |
109 | 105 | } |
110 | | - ); |
| 106 | + ) |
111 | 107 | } else { |
112 | | - const value = String.fromCharCode.apply(null, response); |
| 108 | + const value = String.fromCharCode.apply(null, response) |
113 | 109 | insecureRenderHtml( |
114 | 110 | '<textarea id="file-response"></textarea><button id="file-save">Save</button>' |
115 | | - ); |
| 111 | + ) |
116 | 112 | setTimeout(() => { |
117 | | - const fileInput = document.getElementById("file-response"); |
118 | | - fileInput.value = value; |
| 113 | + const fileInput = document.getElementById('file-response') |
| 114 | + fileInput.value = value |
119 | 115 | document |
120 | | - .getElementById("file-save") |
121 | | - .addEventListener("click", function () { |
| 116 | + .getElementById('file-save') |
| 117 | + .addEventListener('click', function () { |
122 | 118 | fs.writeTextFile(path, fileInput.value, { |
123 | | - baseDir: getDir(), |
124 | | - }).catch(onMessage); |
125 | | - }); |
126 | | - }); |
| 119 | + baseDir |
| 120 | + }).catch(onMessage) |
| 121 | + }) |
| 122 | + }) |
127 | 123 | } |
128 | 124 | } else { |
129 | | - onMessage(response); |
| 125 | + onMessage(response) |
130 | 126 | } |
131 | 127 | }) |
132 | | - .catch(onMessage); |
| 128 | + .catch(onMessage) |
133 | 129 | }) |
134 | | - .catch(onMessage); |
| 130 | + .catch(onMessage) |
135 | 131 | } |
136 | 132 |
|
137 | 133 | function setSrc() { |
138 | | - img.src = convertFileSrc(path); |
| 134 | + img.src = convertFileSrc(path) |
139 | 135 | } |
140 | 136 |
|
141 | 137 | function watch() { |
142 | | - unwatch(); |
| 138 | + unwatch() |
143 | 139 | if (watchPath) { |
144 | | - onMessage(`Watching ${watchPath} for changes`); |
| 140 | + onMessage(`Watching ${watchPath} for changes`) |
145 | 141 | let options = { |
146 | 142 | recursive: watchRecursive, |
147 | | - delayMs: parseInt(watchDebounceDelay), |
148 | | - }; |
| 143 | + delayMs: watchDebounceDelay |
| 144 | + } |
149 | 145 | if (options.delayMs === 0) { |
150 | 146 | fs.watchImmediate(watchPath, onMessage, options) |
151 | 147 | .then((fn) => { |
152 | | - unwatchFn = fn; |
153 | | - unwatchPath = watchPath; |
| 148 | + unwatchFn = fn |
| 149 | + unwatchPath = watchPath |
154 | 150 | }) |
155 | | - .catch(onMessage); |
| 151 | + .catch(onMessage) |
156 | 152 | } else { |
157 | 153 | fs.watch(watchPath, onMessage, options) |
158 | 154 | .then((fn) => { |
159 | | - unwatchFn = fn; |
160 | | - unwatchPath = watchPath; |
| 155 | + unwatchFn = fn |
| 156 | + unwatchPath = watchPath |
161 | 157 | }) |
162 | | - .catch(onMessage); |
| 158 | + .catch(onMessage) |
163 | 159 | } |
164 | 160 | } |
165 | 161 | } |
166 | 162 |
|
167 | 163 | function unwatch() { |
168 | 164 | if (unwatchFn) { |
169 | | - onMessage(`Stopped watching ${unwatchPath} for changes`); |
170 | | - unwatchFn(); |
| 165 | + onMessage(`Stopped watching ${unwatchPath} for changes`) |
| 166 | + unwatchFn() |
171 | 167 | } |
172 | | - unwatchFn = undefined; |
173 | | - unwatchPath = undefined; |
| 168 | + unwatchFn = undefined |
| 169 | + unwatchPath = undefined |
174 | 170 | } |
175 | 171 |
|
176 | 172 | onDestroy(() => { |
177 | 173 | if (file) { |
178 | | - file.close(); |
| 174 | + file.close() |
179 | 175 | } |
180 | 176 | if (unwatchFn) { |
181 | | - unwatchFn(); |
| 177 | + unwatchFn() |
182 | 178 | } |
183 | 179 | }) |
184 | 180 | </script> |
185 | 181 |
|
186 | 182 | <div class="flex flex-col"> |
187 | 183 | <div class="flex gap-1"> |
188 | | - <select class="input" id="dir"> |
189 | | - <option value="">None</option> |
190 | | - {#each DirOptions as dir} |
191 | | - <option value={dir[1]}>{dir[0]}</option> |
| 184 | + <select class="input" bind:value={baseDir}> |
| 185 | + <option value={undefined} selected>None</option> |
| 186 | + {#each dirOptions as dir} |
| 187 | + <option value={fs.BaseDirectory[dir]}>{dir}</option> |
192 | 188 | {/each} |
193 | 189 | </select> |
194 | 190 | <input |
|
199 | 195 | </div> |
200 | 196 | <br /> |
201 | 197 | <div> |
202 | | - <button class="btn" on:click={open}>Open</button> |
203 | | - <button class="btn" on:click={read}>Read</button> |
204 | | - <button class="btn" on:click={mkdir}>Mkdir</button> |
205 | | - <button class="btn" on:click={remove}>Remove</button> |
| 198 | + <button class="btn" onclick={open}>Open</button> |
| 199 | + <button class="btn" onclick={read}>Read</button> |
| 200 | + <button class="btn" onclick={mkdir}>Mkdir</button> |
| 201 | + <button class="btn" onclick={remove}>Remove</button> |
206 | 202 | <div class="flex flex-row"> |
207 | | - <button class="btn" on:click={rename}>Rename</button> |
| 203 | + <button class="btn" onclick={rename}>Rename</button> |
208 | 204 | <input class="input" bind:value={renameTo} placeholder="To" /> |
209 | 205 | </div> |
210 | | - <button class="btn" type="button" on:click={setSrc}>Use as img src</button> |
| 206 | + <button class="btn" type="button" onclick={setSrc}>Use as img src</button> |
211 | 207 | </div> |
212 | 208 | {#if file} |
213 | 209 | <div> |
214 | | - <button class="btn" on:click={truncate}>Truncate</button> |
215 | | - <button class="btn" on:click={stat}>Stat</button> |
| 210 | + <button class="btn" onclick={truncate}>Truncate</button> |
| 211 | + <button class="btn" onclick={stat}>Stat</button> |
216 | 212 | </div> |
217 | 213 | {/if} |
218 | 214 |
|
|
241 | 237 | </div> |
242 | 238 | <br /> |
243 | 239 | <div> |
244 | | - <button class="btn" on:click={watch}>Watch</button> |
245 | | - <button class="btn" on:click={unwatch}>Unwatch</button> |
| 240 | + <button class="btn" onclick={watch}>Watch</button> |
| 241 | + <button class="btn" onclick={unwatch}>Unwatch</button> |
246 | 242 | </div> |
247 | 243 | </div> |
248 | 244 |
|
|
0 commit comments