pull/2410/merge
Fabian-Lars 5 months ago committed by GitHub
commit e6cd5412e7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -4,7 +4,7 @@
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<meta <meta
name="viewport" name="viewport"
content="width=device-width, initial-scale=1.0, viewport-fit=cover" content="width=device-width, initial-scale=1.0, viewport-fit=cover, user-scalable=0"
/> />
<title>Svelte + Vite App</title> <title>Svelte + Vite App</title>
</head> </head>

@ -68,12 +68,18 @@
"fs:allow-rename", "fs:allow-rename",
"fs:allow-mkdir", "fs:allow-mkdir",
"fs:allow-remove", "fs:allow-remove",
"fs:allow-stat",
"fs:allow-fstat",
"fs:allow-lstat",
"fs:allow-write-text-file", "fs:allow-write-text-file",
"fs:scope-download-recursive", "fs:scope-download-recursive",
"fs:scope-resource-recursive", "fs:scope-resource-recursive",
{ {
"identifier": "fs:scope-appdata-recursive", "identifier": "fs:scope-appdata-recursive",
"allow": [ "allow": [
{
"path": "$APPDATA/db/"
},
{ {
"path": "$APPDATA/db/**" "path": "$APPDATA/db/**"
} }

@ -1,178 +1,203 @@
<script> <script>
import * as fs from "@tauri-apps/plugin-fs"; import * as fs from '@tauri-apps/plugin-fs'
import { convertFileSrc } from "@tauri-apps/api/core"; import * as os from '@tauri-apps/plugin-os'
import { arrayBufferToBase64 } from "../lib/utils"; import { convertFileSrc } from '@tauri-apps/api/core'
import { arrayBufferToBase64 } from '../lib/utils'
export let onMessage; import { onMount } from 'svelte'
export let insecureRenderHtml;
export let onMessage
let path = ""; export let insecureRenderHtml
let img;
let file; let path = ''
let renameTo; let img
let watchPath = ""; let file
let watchDebounceDelay = 0; let renameTo
let watchRecursive = false; let watchPath = ''
let unwatchFn; let watchDebounceDelay = 0
let unwatchPath = ""; let watchRecursive = false
let unwatchFn
let unwatchPath = ''
let isMobile
onMount(async () => {
let platform = await os.platform()
isMobile = platform === 'android' || platform === 'ios'
})
function getDir() { function getDir() {
const dirSelect = document.getElementById("dir"); const dirSelect = document.getElementById('dir')
return dirSelect.value ? parseInt(dir.value) : null; return dirSelect.value ? parseInt(dir.value) : null
} }
const DirOptions = Object.keys(fs.BaseDirectory) const DirOptions = Object.keys(fs.BaseDirectory)
.filter((key) => isNaN(parseInt(key))) .filter((key) => isNaN(parseInt(key)))
.map((dir) => [dir, fs.BaseDirectory[dir]]); .map((dir) => [dir, fs.BaseDirectory[dir]])
function open() { function open() {
fs.open(path, { fs.open(path, {
baseDir: getDir(), baseDir: getDir(),
read: true, read: true,
write: true, write: true,
create: true, create: true
}) })
.then((f) => { .then((f) => {
file = f; file = f
onMessage(`Opened ${path}`); onMessage(`Opened ${path}`)
}) })
.catch(onMessage); .catch(onMessage)
} }
function mkdir() { function mkdir() {
fs.mkdir(path, { baseDir: getDir() }) fs.mkdir(path, { baseDir: getDir(), recursive: true })
.then(() => { .then(() => {
onMessage(`Created dir ${path}`); onMessage(`Created dir ${path}`)
}) })
.catch(onMessage); .catch(onMessage)
} }
function remove() { function remove() {
fs.remove(path, { baseDir: getDir() }) fs.remove(path, { baseDir: getDir() })
.then(() => { .then(() => {
onMessage(`Removed ${path}`); onMessage(`Removed ${path}`)
}) })
.catch(onMessage); .catch(onMessage)
} }
function rename() { function rename() {
fs.rename(path, renameTo, { fs.rename(path, renameTo, {
oldPathBaseDir: getDir(), oldPathBaseDir: getDir(),
newPathBaseDir: getDir(), newPathBaseDir: getDir()
}) })
.then(() => { .then(() => {
onMessage(`Renamed ${path} to ${renameTo}`); onMessage(`Renamed ${path} to ${renameTo}`)
}) })
.catch(onMessage); .catch(onMessage)
} }
function truncate() { function truncate() {
file file
.truncate(0) .truncate(0)
.then(() => { .then(() => {
onMessage(`Truncated file`); onMessage(`Truncated file`)
})
.catch(onMessage)
}
function write() {
const encoder = new TextEncoder()
file
.write(encoder.encode('Hello from Tauri :)'))
.then(() => {
onMessage(`wrote to file`)
}) })
.catch(onMessage); .catch(onMessage)
} }
function stat() { function stat() {
file file
.stat() .stat()
.then((stat) => { .then((stat) => {
onMessage(`File stat ${JSON.stringify(stat)}`); onMessage(`File stat ${JSON.stringify(stat)}`)
}) })
.catch(onMessage); .catch(onMessage)
} }
function read() { function read() {
const opts = { const opts = {
baseDir: getDir(), baseDir: getDir()
}; }
fs.stat(path, opts) fs.stat(path, opts)
.then((stat) => { .then((stat) => {
const isFile = stat.isFile; const isFile = stat.isFile
const promise = isFile const promise = isFile
? fs.readFile(path, opts) ? fs.readFile(path, opts)
: fs.readDir(path, opts); : fs.readDir(path, opts)
promise promise
.then(function (response) { .then(function (response) {
if (isFile) { if (isFile) {
if (path.includes(".png") || path.includes(".jpg")) { if (path.includes('.png') || path.includes('.jpg')) {
arrayBufferToBase64( arrayBufferToBase64(
new Uint8Array(response), new Uint8Array(response),
function (base64) { function (base64) {
const src = "data:image/png;base64," + base64; const src = 'data:image/png;base64,' + base64
insecureRenderHtml('<img src="' + src + '"></img>'); insecureRenderHtml('<img src="' + src + '"></img>')
} }
); )
} else { } else {
const value = String.fromCharCode.apply(null, response); const value = String.fromCharCode.apply(null, response)
insecureRenderHtml( insecureRenderHtml(
'<textarea id="file-response"></textarea><button id="file-save">Save</button>' '<textarea id="file-response"></textarea><button id="file-save">Save</button>'
); )
setTimeout(() => { setTimeout(() => {
const fileInput = document.getElementById("file-response"); const fileInput = document.getElementById('file-response')
fileInput.value = value; fileInput.value = value
document document
.getElementById("file-save") .getElementById('file-save')
.addEventListener("click", function () { .addEventListener('click', function () {
fs.writeTextFile(path, fileInput.value, { fs.writeTextFile(path, fileInput.value, {
dir: getDir(), dir: getDir()
}).catch(onMessage); }).catch(onMessage)
}); })
}); })
} }
} else { } else {
onMessage(response); onMessage(response)
} }
}) })
.catch(onMessage); .catch(onMessage)
}) })
.catch(onMessage); .catch(onMessage)
} }
function setSrc() { function setSrc() {
img.src = convertFileSrc(path); img.src = convertFileSrc(path)
} }
function watch() { function watch() {
unwatch(); unwatch()
if (watchPath) { if (watchPath) {
onMessage(`Watching ${watchPath} for changes`); onMessage(`Watching ${watchPath} for changes`)
let options = { let options = {
recursive: watchRecursive, recursive: watchRecursive,
delayMs: parseInt(watchDebounceDelay), delayMs: parseInt(watchDebounceDelay)
}; }
if (options.delayMs === 0) { if (options.delayMs === 0) {
fs.watchImmediate(watchPath, onMessage, options) fs.watchImmediate(watchPath, onMessage, options)
.then((fn) => { .then((fn) => {
unwatchFn = fn; unwatchFn = fn
unwatchPath = watchPath; unwatchPath = watchPath
}) })
.catch(onMessage); .catch(onMessage)
} else { } else {
fs.watch(watchPath, onMessage, options) fs.watch(watchPath, onMessage, options)
.then((fn) => { .then((fn) => {
unwatchFn = fn; unwatchFn = fn
unwatchPath = watchPath; unwatchPath = watchPath
}) })
.catch(onMessage); .catch(onMessage)
} }
} }
} }
function unwatch() { function unwatch() {
if (unwatchFn) { if (unwatchFn) {
onMessage(`Stopped watching ${unwatchPath} for changes`); onMessage(`Stopped watching ${unwatchPath} for changes`)
unwatchFn(); unwatchFn()
} }
unwatchFn = undefined; unwatchFn = undefined
unwatchPath = undefined; unwatchPath = undefined
} }
</script> </script>
<div class="flex flex-col"> <div class="flex flex-col">
{#if isMobile}
<div>
On mobile, paths outside of App* paths require the use of dialogs
regardless of Tauri's scope mechanism.
</div>
<br />
{/if}
<div class="flex gap-1"> <div class="flex gap-1">
<select class="input" id="dir"> <select class="input" id="dir">
<option value="">None</option> <option value="">None</option>
@ -200,6 +225,7 @@
</div> </div>
{#if file} {#if file}
<div> <div>
<button class="btn" on:click={write}>Write</button>
<button class="btn" on:click={truncate}>Truncate</button> <button class="btn" on:click={truncate}>Truncate</button>
<button class="btn" on:click={stat}>Stat</button> <button class="btn" on:click={stat}>Stat</button>
</div> </div>

Loading…
Cancel
Save