Next: Events

Creating Notes

In this video we'll use our first tauri plugin to work with the file system to create, read, and write files.

First install the plugin

npm run tauri add fs

This will add JavaScript/Rust dependencies, initialize the plugin and update our application's permissions.

package.json

+ "@tauri-apps/plugin-fs": "^2.2.0",

src-tauri/Cargo.toml

+tauri-plugin-fs = "2"

src-tauri/lib.rs

pub fn run() {
tauri::Builder::default()
+ .plugin(tauri_plugin_fs::init())
.plugin(tauri_plugin_shell::init())
.invoke_handler(tauri::generate_handler![])
.run(tauri::generate_context!())

src-tauri/capabilities/default.json

"windows": [
"main"
],
"permissions": [
"core:default",
"shell:allow-open",
+ "fs:default"
]

Open src/pages/Home.vue and make a createNote() function

--- a/src/pages/Home.vue
+++ b/src/pages/Home.vue
@@ -3,6 +3,7 @@
<h1 class="text-2xl font-bold mb-5 mt-12">Notes</h1>
<div>
<button
+ @click="createNote"
class="px-4 py-2 bg-oni-violet text-white rounded-lg"
>
Create Note
@@ -12,6 +13,14 @@
</template>
 
<script lang="ts" setup>
+import {create, BaseDirectory} from "@tauri-apps/plugin-fs";
+
+
+async function createNote() {
+ let file = await create("My Note.md", {
+ baseDir: BaseDirectory.AppData,
+ });
+ await file.close();
+}
 
</script>

Test out, and will get a permission error in console.

open console using opt+cmd+i

+ "fs:allow-app-read-recursive",
+ "fs:allow-app-write-recursive"

Checkout all the fs plugin permissions.

Let's have the console open by default only in development.
src-tauri/lib.rs

.invoke_handler(tauri::generate_handler![])
+ .setup(|app| {
+ #[cfg(debug_assertions)] // only include this code on debug builds
+ {
+ let window = app.get_webview_window("main").unwrap();
+ window.open_devtools();
+ }
+ Ok(())
+ })
.run(tauri::generate_context!())

Wait for rebuild and try again.
New error no such file or dir.
Our AppData dir doesn't exist.

So let's make sure it exists when the app launches.

src/util.ts

+async function ensureAppDirExists() {
+ if(! await exists("", {baseDir: BaseDirectory.AppData})) {
+ await mkdir("", {baseDir: BaseDirectory.AppData});
+ }
+}

Create a new page Note.vue

<template>
<div class="flex flex-col lg:flex-row justify-center">
<div class="w-full max-w-[600px] xl:max-w-[900px] mt-8 mr-4">
<EasyMde v-model="content"/>
</div>
</div>
</template>
 
<script lang="ts" setup>
import { ref } from "vue";
import EasyMde from "../components/EasyMde.vue";
 
const content = ref("");
</script>

update main.ts

+import Note from "./pages/Note.vue";
import "./styles.css";
import App from "./App.vue";
 
const routes = [
{ path: "/", component: Home },
+ { path: "/note/:file", component: Note },
];

Home.vue

+ import {useRouter} from "vue-router";
 
+ const router = useRouter();
 
async function createNote() {
await ensureAppDirExists();
 
let file = await create("My Note.md", {
baseDir: BaseDirectory.AppData,
});
 
await file.close();
 
+ await router.push("/note/My Note.md");
}

Now back to Note.vue Read/Write

import { ref, onMounted } from "vue";
import EasyMde from "../components/EasyMde.vue";
import { readTextFile, writeTextFile } from "@tauri-apps/plugin-fs";
import { BaseDirectory } from "@tauri-apps/api/path";
import { watchDebounced } from "@vueuse/core";
import { useRoute } from "vue-router";
 
const route = useRoute();
const fileName = route.params.file as string;
const content = ref("");
 
watchDebounced(content, () => {
saveNote();
});
 
async function loadNote() {
content.value = await readTextFile(fileName, {
baseDir: BaseDirectory.AppData,
});
}
 
async function saveNote() {
await writeTextFile(fileName, content.value, {
baseDir: BaseDirectory.AppData,
});
}
 
onMounted(() => {
loadNote();
});