Разрабатываем десктопное приложение для заметок с помощью Tauri (React + Rust)
Привет, друзья!
В данном туториале мы разработаем десктопное приложение с помощью Tauri. Tauri
— это фреймворк для создания десктопных приложений, похожий на Electron, но позволяющий использовать Rust вместо Node.js, например, для взаимодействия с файловой системой.
В качестве фреймворка для разработки пользовательского интерфейса я буду использовать React и TypeScript, а для работы с зависимостями для JavaScript
— Yarn.
Источником вдохновения для меня послужила эта замечательная статья.
Обратите внимание: я буду разрабатывать приложение под Windows x64
, в других операционных системах (и архитектурах) детали реализации будут немного отличаться.
Приложение будет представлять собой своего рода однострочный терминал для записи заметок в файл tasks.txt
, находящийся в домашней директории (для Windows
— это C:\Users\[User]
). Приложение будет запускаться с помощью сочетания клавиш Ctrl + Shift + Q
и завершаться при нажатии Esc
.
Вот как это будет выглядеть:
Репозиторий с кодом проекта.
Если вам это интересно, прошу под кат.
Подготовка и настройка проекта
Обратите внимание: на вашей машине должны быть установлены Node.js и Rust
. Про установку Rust
можно почитать здесь и здесь.
Если в качестве редактора кода вы используете VSCode, рекомендую установить этот набор расширений для работы с Rust
.
Windows
- При установке Build Tools for Visual Studio 2022 выбираем полезную нагрузку
Разработка классических приложений на C++
.
- После установки
Rust
выполняем командуrustup default stable-msvc
в терминале для переключения на набор инструментовMSVC
.
Создаем новый проект Tauri
:
yarn create tauri-app
- Вводим название приложения, например,
Tauri Focus
; - выбираем инструмент для создания шаблона фронтенда create-vite;
- добавляем пакет @tauri-apps/api;
- выбираем шаблон react-ts.
Обратите внимание: в Windows
командная строка должна быть запущена от имени администратора.
Переходим в созданную директорию tauri-focus
и приводим ее к следующему виду:
Пока не обращайте внимание на файлы postcss.config.js
и tailwind.config.js
, скоро они у вас появятся.
Выполняем команду yarn tauri dev
для запуска приложения в режиме для разработки. Обратите внимание: при первом запуске Rust
потребуется скомпилировать файлы приложения, поэтому придется немного подождать (при последующих запусках будет использоваться кеш).
На этом подготовка и настройка проекта завершены. Переходим к разработке пользовательского интерфейса.
Пользовательский интерфейс
Для стилизации приложения будем использовать TailwindCSS. Устанавливаем необходимые пакеты, находясь в корневой директории проекта:
yarn add -D tailwindcss postcss autoprefixer
Инициализируем Tailwind
:
yarn tailwindcss init -p
Добавляем в tailwind.config.js
следующую строку:
module.exports = {
// если хотите, можете оставить здесь только `tsx`
content: ['./index.html', './src/**/*.{vue,js,ts,jsx,tsx}'],
// ...
}
Импортируем стили в src/index.css
:
@tailwind base;
@tailwind components;
@tailwind utilities;
Редактируем файл src/App.tsx
:
import React, { useState } from 'react'
function App() {
const [text, setText] = useState('')
const addTask = (e: React.KeyboardEvent) => {
if (e.key === 'Enter') {
console.log(text)
}
}
return (
setText(e.target.value)}
onKeyDown={addTask}
/>
)
}
export default App
У нас имеется (темное) поле размером 600x60px
для ввода (зеленого) текста заметки. При нажатии Enter
значение данного поля выводится в консоль.
Далее нам нужна функция для записи заметки в файл.
Взаимодействие с файловой системой
Определяем команду Tauri
/функцию для записи заметки в файле src-tauri/src/main.rs
:
// импорт зависимостей
use std::fs::OpenOptions;
use std::io::Write;
#[tauri::command]
fn add_task(text: String) {
let mut file = OpenOptions::new()
.create(true)
.append(true)
.open("../tasks.txt")
.expect("Ошибка при открытии файла");
writeln!(file, "{}", text).expect("Ошибка при записи файла");
}
Добавляем эту функцию в список команд:
fn main() {
let context = tauri::generate_context!();
tauri::Builder::default()
// !
.invoke_handler(tauri::generate_handler![add_task])
.menu(tauri::Menu::os_default(&context.package_info().name))
.run(context)
.expect("Ошибка при запуске приложения");
}
Редактируем обработчик addTask
в src/App.tsx
(вызов Rust
из фронтенда):
import { invoke, process } from '@tauri-apps/api'
// ...
const addTask = async (e: React.KeyboardEvent) => {
switch (e.key) {
// при нажатии `Enter` вызываем `add_task` с текстом заметки
case 'Enter':
try {
await invoke('add_task', { text })
setText('')
} catch (e) {
console.error(e)
}
break
// при нажатии `Esc` завершаем процесс
case 'Escape':
return process.exit()
default:
return
}
}
// ...
Проверка работоспобности приложения и последние штрихи
Перед запуском приложения необходимо немного отредактировать файл tauri.conf.json
:
"tauri": {
"bundle": {
"identifier": "app.tauri.focus",
},
"windows": [
{
"fullscreen": false,
"resizable": false,
"center": true,
"width": 600,
"height": 60,
"title": "Tauri Focus App",
"decorations": false
}
]
}
decorations: false
означает скрытие заголовка, остальное, думаю, понятно.
- Выполняем команду
yarn tauri dev
(обратите внимание, что фронтенд можно отлаживать отдельно по адресуhttp://localhost:3000
); - вводим несколько тестовых значений, например,
test
,test2
,test3
; - видим, что в корне проекта появился файл
tasks.txt
с нашими заметками.
Если вас смущает ошибка на этой строке:
let context = tauri::generate_context!();
Просто создайте сборку фронтенда с помощью команды yarn build
.
Отлично. Приложение работает, как ожидается. Однако корень проекта не слишком удачное место для хранения файла tasks.txt
. Кроме того, мы еще не сгенерировали установочный файл.
Для универсального доступа к домашней директории потребуется пакет home («крейт» в терминологии Rust
). Добавляем в файл src-tauri/src/Cargo.toml
такую строку:
[dependencies]
# ...
home = "0.5.3"
Импортируем пакет в main.rs
и определяем переменную для пути к домашней директории:
// ...
use home::home_dir;
fn add_task(text: String) {
// !
let mut path = home_dir()
.expect("Ошибка доступа к домашней директории");
// добавляем в путь название файла для заметок
path.push("tasks.txt");
let mut file = OpenOptions::new()
.create(true)
.append(true)
// !
.open(path)
.expect("Ошибка при открытии файла");
writeln!(file, "{text}").expect("Ошибка при записи файла");
}
Выполняем команду yarn tauri build
:
Это приводит к генерации установочного файла src-tauri/target/release/bundle/msi/tauri-focus_0.1.0_x64_en-US.msi
.
Также в директории src-tauri/target/release
генерируется исполняемый файл tauri-focus.exe
.
- Создаем ярлык этого файла на рабочем столе;
- открываем свойства ярлыка;
- в поле «Быстрый вызов» вводим сочетание клавиш для запуска приложения, например,
Ctrl + Shift + Q
; - применяем изменения.
Нажимаем Ctrl + Shift + Q
и вводим парочку заметок:
Нажатие Esc
завершает работу приложения.
Пожалуй, это все, чем я хотел поделиться с вами в данной статье. Надеюсь, вы нашли для себя что-то интересное и не зря потратили время.
Благодарю за внимание и happy coding!