|
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