@@ -4,7 +4,7 @@ export default defineConfig({
|
||||
e2e: {
|
||||
baseUrl: 'http://localhost:5173',
|
||||
supportFile: 'tests/e2e/support/e2e.js',
|
||||
specPattern: 'tests/e2e/specs/**/*.cy.{js,jsx}',
|
||||
specPattern: 'tests/e2e/specs/**/*.cy.{js,jsx,ts,tsx}',
|
||||
videosFolder: 'tests/e2e/videos',
|
||||
screenshotsFolder: 'tests/e2e/screenshots',
|
||||
setupNodeEvents(on, config) {
|
||||
@@ -24,7 +24,7 @@
|
||||
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
<script type="module" src="/src/main.js"></script>
|
||||
<script type="module" src="/src/main.ts"></script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
|
||||
@@ -5,5 +5,5 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { IonApp, IonRouterOutlet } from '@ionic/vue'
|
||||
import { IonApp, IonRouterOutlet } from '@ionic/vue'
|
||||
</script>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { appLocalDataDir } from '@tauri-apps/api/path';
|
||||
|
||||
export async function getDB_URL() {
|
||||
// Функция верёнт путь до бд
|
||||
/** Возвращает URL подключения к SQLite */
|
||||
export async function getDB_URL(): Promise<string> {
|
||||
|
||||
const appDir = await appLocalDataDir();
|
||||
return `sqlite:${appDir}/timer.db`;
|
||||
@@ -1,10 +0,0 @@
|
||||
import { getDb } from "../initDb";
|
||||
import { SELECT_TIMERS } from "../dml/timerDML";
|
||||
|
||||
|
||||
export async function getTimers() {
|
||||
// Функция для получения списка таймеров
|
||||
|
||||
const db = await getDb();
|
||||
return await db.select(SELECT_TIMERS);
|
||||
}
|
||||
10
client/src/db/crud/timerCrud.ts
Normal file
10
client/src/db/crud/timerCrud.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import { getDb } from "@/db/initDb";
|
||||
import { SELECT_TIMERS } from "@/db/dml/timerDML";
|
||||
import { TimersRow } from "@/types/timerType"
|
||||
|
||||
|
||||
/** Получает список таймеров */
|
||||
export async function getTimers(): Promise<TimersRow[]> {
|
||||
const db = await getDb();
|
||||
return await db.select<TimersRow[]>(SELECT_TIMERS);
|
||||
}
|
||||
@@ -1,13 +1,12 @@
|
||||
import Database from '@tauri-apps/plugin-sql';
|
||||
import { CREATE_TIMER } from './ddl/timerDDL';
|
||||
import { getDB_URL } from '../config';
|
||||
import { seedDb } from './seed';
|
||||
import { CREATE_TIMER } from '@/db/ddl/timerDDL';
|
||||
import { getDB_URL } from '@/config';
|
||||
import { seedDb } from '@/db/seed';
|
||||
|
||||
let dbPromise = null;
|
||||
|
||||
export async function getDb() {
|
||||
// Функция для получения подключения к базе данных
|
||||
let dbPromise: Promise<Database> | null = null;
|
||||
|
||||
/** Получает подключение к бд */
|
||||
export async function getDb(): Promise<Database> {
|
||||
if (!dbPromise) {
|
||||
dbPromise = (async () => {
|
||||
try {
|
||||
@@ -22,5 +21,5 @@ export async function getDb() {
|
||||
}
|
||||
})();
|
||||
}
|
||||
return await dbPromise; // await для консистентности
|
||||
return await dbPromise;
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
import { INSERT_SEED_DB, COUNT_TIMERS } from './dml/timerDML'
|
||||
|
||||
|
||||
export async function seedDb(db) {
|
||||
// Функция для заполнения бд данными
|
||||
|
||||
const count = await db.select(COUNT_TIMERS);
|
||||
if (count[0].cnt === 0) {
|
||||
await db.execute(INSERT_SEED_DB);
|
||||
}
|
||||
}
|
||||
14
client/src/db/seed.ts
Normal file
14
client/src/db/seed.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
import Database from '@tauri-apps/plugin-sql';
|
||||
import { INSERT_SEED_DB, COUNT_TIMERS } from '@/db/dml/timerDML'
|
||||
import { CountRow } from '@/types/timerType'
|
||||
|
||||
|
||||
/** Заполняет бд данными (демо таймерами) */
|
||||
export async function seedDb(db: Database) {
|
||||
|
||||
const count = await db.select<CountRow[]>(COUNT_TIMERS);
|
||||
const cnt = count[0]?.cnt ?? 0;
|
||||
if (cnt === 0) {
|
||||
await db.execute(INSERT_SEED_DB);
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
import { createApp } from 'vue'
|
||||
import App from './App.vue'
|
||||
import router from './router';
|
||||
import App from '@/App.vue'
|
||||
import router from '@/router';
|
||||
|
||||
import { IonicVue } from '@ionic/vue';
|
||||
|
||||
@@ -21,7 +21,7 @@ import '@ionic/vue/css/flex-utils.css';
|
||||
import '@ionic/vue/css/display.css';
|
||||
|
||||
/* Theme variables */
|
||||
import './theme/variables.css';
|
||||
import '@/theme/variables.css';
|
||||
|
||||
const app = createApp(App)
|
||||
.use(IonicVue)
|
||||
@@ -1,7 +1,8 @@
|
||||
import { createRouter, createWebHistory } from '@ionic/vue-router';
|
||||
import TimersList from '../views/TimersList/TimersList.vue';
|
||||
import type { RouteRecordRaw } from 'vue-router';
|
||||
import TimersList from '@/views/TimersList/TimersList.vue';
|
||||
|
||||
const routes = [
|
||||
const routes: RouteRecordRaw[] = [
|
||||
{
|
||||
path: '/',
|
||||
redirect: '/timers'
|
||||
8
client/src/types/timerType.ts
Normal file
8
client/src/types/timerType.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
export type TimersRow = {
|
||||
id: number;
|
||||
title: string;
|
||||
pomodoro_time: number;
|
||||
count_pomodoro: number;
|
||||
};
|
||||
|
||||
export type CountRow = { cnt: number };
|
||||
@@ -1,66 +0,0 @@
|
||||
import { IonIcon } from '@ionic/vue';
|
||||
import {
|
||||
timerOutline,
|
||||
chevronUp,
|
||||
chevronDown,
|
||||
playCircleOutline,
|
||||
pencilOutline,
|
||||
trashOutline
|
||||
} from 'ionicons/icons';
|
||||
|
||||
import { ref, onMounted } from 'vue';
|
||||
import { getTimers } from '../../db/crud/timerCrud';
|
||||
|
||||
export default {
|
||||
name: 'TimersList',
|
||||
components: {
|
||||
IonIcon,
|
||||
},
|
||||
setup() {
|
||||
const timers = ref([]);
|
||||
const loading = ref(true);
|
||||
const error = ref(null);
|
||||
const expandedId = ref(null);
|
||||
|
||||
const loadTimers = async () => {
|
||||
loading.value = true;
|
||||
error.value = null;
|
||||
|
||||
try {
|
||||
const result = await getTimers();
|
||||
timers.value = result;
|
||||
} catch (err) {
|
||||
error.value = err.message || 'Ошибка загрузки таймеров';
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
const toggleExpand = (id) => {
|
||||
expandedId.value = expandedId.value === id ? null : id;
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
loadTimers();
|
||||
});
|
||||
|
||||
return {
|
||||
// состояние
|
||||
timers,
|
||||
loading,
|
||||
error,
|
||||
expandedId,
|
||||
|
||||
// методы
|
||||
toggleExpand,
|
||||
|
||||
// иконки
|
||||
timerOutline,
|
||||
chevronUp,
|
||||
chevronDown,
|
||||
playCircleOutline,
|
||||
pencilOutline,
|
||||
trashOutline,
|
||||
};
|
||||
},
|
||||
};
|
||||
60
client/src/views/TimersList/TimersList.ts
Normal file
60
client/src/views/TimersList/TimersList.ts
Normal file
@@ -0,0 +1,60 @@
|
||||
import { defineComponent, onMounted, ref } from 'vue'
|
||||
import { IonIcon } from '@ionic/vue'
|
||||
import {
|
||||
timerOutline,
|
||||
chevronUp,
|
||||
chevronDown,
|
||||
playCircleOutline,
|
||||
pencilOutline,
|
||||
trashOutline,
|
||||
} from 'ionicons/icons'
|
||||
|
||||
import { getTimers } from '@/db/crud/timerCrud'
|
||||
import type { TimersRow } from '@/types/timerType'
|
||||
|
||||
export default defineComponent({
|
||||
name: 'TimersList',
|
||||
components: { IonIcon },
|
||||
setup() {
|
||||
const timers = ref<TimersRow[]>([])
|
||||
const loading = ref<boolean>(true)
|
||||
const error = ref<string | null>(null)
|
||||
const expandedId = ref<number | null>(null)
|
||||
|
||||
const loadTimers = async (): Promise<void> => {
|
||||
loading.value = true
|
||||
error.value = null
|
||||
|
||||
try {
|
||||
const result = await getTimers()
|
||||
timers.value = result
|
||||
} catch (e: unknown) {
|
||||
error.value = e instanceof Error ? e.message : 'Ошибка загрузки таймеров'
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
const toggleExpand = (id: number): void => {
|
||||
expandedId.value = expandedId.value === id ? null : id
|
||||
}
|
||||
|
||||
onMounted(loadTimers)
|
||||
|
||||
return {
|
||||
timers,
|
||||
loading,
|
||||
error,
|
||||
expandedId,
|
||||
|
||||
toggleExpand,
|
||||
|
||||
timerOutline,
|
||||
chevronUp,
|
||||
chevronDown,
|
||||
playCircleOutline,
|
||||
pencilOutline,
|
||||
trashOutline,
|
||||
}
|
||||
},
|
||||
})
|
||||
@@ -1,4 +1,4 @@
|
||||
<!-- TimersList.vue -->
|
||||
<template src="./TimersList.html"></template>
|
||||
<script src="./TimersList.js"></script>
|
||||
<style src="./TimersList.css" scoped></style>
|
||||
<template src="@/views/TimersList/TimersList.html"></template>
|
||||
<script lang="ts" src="@/views/TimersList/TimersList.ts"></script>
|
||||
<style src="@/views/TimersList/TimersList.css" scoped></style>
|
||||
|
||||
1
client/src/vite-env.d.ts
vendored
Normal file
1
client/src/vite-env.d.ts
vendored
Normal file
@@ -0,0 +1 @@
|
||||
/// <reference types="vite/client" />
|
||||
11
client/tsconfig.json
Normal file
11
client/tsconfig.json
Normal file
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"@/*": ["src/*"]
|
||||
},
|
||||
"module": "ESNext",
|
||||
"target": "ES2020",
|
||||
"moduleResolution": "Bundler"
|
||||
}
|
||||
}
|
||||
26
desktop/src-tauri/Cargo.lock
generated
26
desktop/src-tauri/Cargo.lock
generated
@@ -81,19 +81,6 @@ version = "1.0.100"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61"
|
||||
|
||||
[[package]]
|
||||
name = "app"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"log",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"tauri",
|
||||
"tauri-build",
|
||||
"tauri-plugin-log",
|
||||
"tauri-plugin-sql",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "arrayvec"
|
||||
version = "0.7.6"
|
||||
@@ -1849,6 +1836,19 @@ dependencies = [
|
||||
"serde_json",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "kawai-focus"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"log",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"tauri",
|
||||
"tauri-build",
|
||||
"tauri-plugin-log",
|
||||
"tauri-plugin-sql",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "keyboard-types"
|
||||
version = "0.7.0"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
[package]
|
||||
name = "app"
|
||||
name = "kawai-focus"
|
||||
version = "0.1.0"
|
||||
description = "Kawai-Focus - приложение для фокусировки внимания на основе таймера Pomodoro."
|
||||
authors = ["Arduinum"]
|
||||
@@ -11,7 +11,7 @@ rust-version = "1.77.2"
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[lib]
|
||||
name = "app_lib"
|
||||
name = "kawai_focus"
|
||||
crate-type = ["staticlib", "cdylib", "rlib"]
|
||||
|
||||
[build-dependencies]
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<component type="desktop-application">
|
||||
<id>io.github.arduinum.KawaiFocus</id>
|
||||
|
||||
<name>Kawai-Focus</name>
|
||||
<summary>Focus timer for working sessions</summary>
|
||||
|
||||
<description>
|
||||
<p>Kawai-Focus is a focus-training app based on the Pomodoro timer.</p>
|
||||
</description>
|
||||
|
||||
<developer id="io.github.arduinum">
|
||||
<name>Kaddo Eugene</name>
|
||||
</developer>
|
||||
|
||||
<metadata_license>FSFAP</metadata_license>
|
||||
<project_license>MIT</project_license>
|
||||
|
||||
<launchable type="desktop-id">io.github.arduinum.KawaiFocus.desktop</launchable>
|
||||
|
||||
<url type="homepage">https://github.com/Arduinum/kawai-focus-v2</url>
|
||||
</component>
|
||||
44
desktop/src-tauri/src/flags.rs
Normal file
44
desktop/src-tauri/src/flags.rs
Normal file
@@ -0,0 +1,44 @@
|
||||
#[cfg(target_os = "linux")]
|
||||
pub fn apply_linux_cli_flags() {
|
||||
let disable_webkit_compositing_mode = std::env::args().any(|a| a == "--webkit-disable-compositing-mode");
|
||||
if disable_webkit_compositing_mode {
|
||||
unsafe { std::env::set_var("WEBKIT_DISABLE_COMPOSITING_MODE", "1"); }
|
||||
}
|
||||
|
||||
let webkit_disable_dmabuf_renderer = std::env::args().any(|a| a == "--webkit-disable-dmabuf-renderer");
|
||||
if webkit_disable_dmabuf_renderer {
|
||||
unsafe { std::env::set_var("WEBKIT_DISABLE_DMABUF_RENDERER", "1"); }
|
||||
}
|
||||
|
||||
let nv_disable_explicit_sync = std::env::args().any(|a| a == "--nv-disable-explicit-sync");
|
||||
if nv_disable_explicit_sync {
|
||||
unsafe { std::env::set_var("__NV_DISABLE_EXPLICIT_SYNC", "1"); }
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
pub fn print_help() {
|
||||
println!(
|
||||
r#"Kawai Focus — Pomodoro таймер
|
||||
|
||||
Использование:
|
||||
kawai-focus [FLAGS]
|
||||
|
||||
Флаги (Linux):
|
||||
|
||||
--webkit-disable-compositing-mode
|
||||
Отключает WebKit compositing mode.
|
||||
Помогает при графических артефактах на некоторых GPU.
|
||||
|
||||
--webkit-disable-dmabuf-renderer
|
||||
Отключает DMA-BUF renderer WebKit.
|
||||
Полезно при проблемах с Wayland и с отсутствием GBM.
|
||||
|
||||
--nv-disable-explicit-sync
|
||||
Отключает explicit sync драйвера NVIDIA.
|
||||
Иногда исправляет: зависания интерфейса, проблемы с отсутствием GBM.
|
||||
|
||||
--help
|
||||
Показать эту справку и выйти.
|
||||
"#);
|
||||
}
|
||||
@@ -1,5 +1,16 @@
|
||||
mod flags;
|
||||
|
||||
#[cfg_attr(mobile, tauri::mobile_entry_point)]
|
||||
pub fn run() {
|
||||
#[cfg(target_os = "linux")]
|
||||
if std::env::args().any(|a| a == "--help" || a == "-h") {
|
||||
flags::print_help();
|
||||
std::process::exit(0);
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
flags::apply_linux_cli_flags();
|
||||
|
||||
tauri::Builder::default()
|
||||
.plugin(tauri_plugin_sql::Builder::default().build())
|
||||
.run(tauri::generate_context!())
|
||||
|
||||
@@ -3,5 +3,5 @@
|
||||
|
||||
fn main() {
|
||||
println!("Запуск приложения Tauri...");
|
||||
app_lib::run();
|
||||
kawai_focus::run();
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"$schema": "https://schema.tauri.app/config/2",
|
||||
"productName": "Kawai-Focus",
|
||||
"version": "0.1.0",
|
||||
"identifier": "com.kawai.focus",
|
||||
"identifier": "io.github.arduinum.KawaiFocus",
|
||||
"build": {
|
||||
"frontendDist": "../../client/dist",
|
||||
"devUrl": "http://localhost:8100",
|
||||
@@ -29,7 +29,15 @@
|
||||
},
|
||||
"bundle": {
|
||||
"active": true,
|
||||
"targets": "all",
|
||||
"targets": ["deb", "rpm"],
|
||||
"linux": {
|
||||
"deb": {
|
||||
"files": {
|
||||
"/usr/share/metainfo/io.github.arduinum.KawaiFocus.metainfo.xml": "assets/io.github.arduinum.KawaiFocus.metainfo.xml"
|
||||
}
|
||||
}
|
||||
},
|
||||
"shortDescription": "Kawai-Focus - приложение для фокусировки внимания на основе таймера Pomodoro.",
|
||||
"icon": [
|
||||
"icons/32x32.png",
|
||||
"icons/128x128.png",
|
||||
|
||||
Reference in New Issue
Block a user