App architecture modifications.
Now GUI and the app itself is divided into two different binaries. The app also provides system tray icon. Whereas the GUI can be used to configure the app.
This commit is contained in:
parent
4f3d572b26
commit
4e860d63c3
91 changed files with 5818 additions and 0 deletions
19
gui/src/App.svelte
Normal file
19
gui/src/App.svelte
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
<!-- src/App.svelte -->
|
||||
<script>
|
||||
import { Router } from "@roxi/routify";
|
||||
import { routes } from "../.routify/routes";
|
||||
|
||||
import { SvelteUIProvider } from '@svelteuidev/core';
|
||||
|
||||
import Events from "./Events.svelte";
|
||||
|
||||
/** START LISTENING **/
|
||||
import { startListening } from "./functions";
|
||||
startListening();
|
||||
</script>
|
||||
|
||||
<SvelteUIProvider themeObserver='dark' withNormalizeCSS withGlobalStyles>
|
||||
<Router {routes} />
|
||||
</SvelteUIProvider>
|
||||
|
||||
<Events />
|
||||
44
gui/src/Events.svelte
Normal file
44
gui/src/Events.svelte
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
<script>
|
||||
import { onMount, onDestroy } from 'svelte'
|
||||
import { emit, listen } from '@tauri-apps/api/event'
|
||||
|
||||
import { resolveResource } from '@tauri-apps/api/path'
|
||||
|
||||
import {Howl, Howler} from 'howler';
|
||||
|
||||
let assistant_voice_val = "jarvis-og";
|
||||
import { assistant_voice } from "@/stores"
|
||||
import { invoke } from '@tauri-apps/api/tauri';
|
||||
assistant_voice.subscribe(value => {
|
||||
assistant_voice_val = value;
|
||||
});
|
||||
|
||||
onMount(async () => {
|
||||
await listen('audio-play', async (event) => {
|
||||
// event.event is the event name (useful if you want to use a single callback fn for multiple event types)
|
||||
// event.payload is the payload object
|
||||
// let path = await resolveResource('sound/' + (assistant_voice_val == "" ? "jarvis-remake":assistant_voice_val) + '/' + event.payload['data'] + '.wav');
|
||||
// console.log(path);
|
||||
// let sound = new Howl({
|
||||
// src: [path],
|
||||
// html5: true
|
||||
// });
|
||||
|
||||
// sound.play();
|
||||
|
||||
let filename = 'sound/' + (assistant_voice_val == "" ? "jarvis-remake":assistant_voice_val) + '/' + event.payload['data'] + '.wav';
|
||||
await invoke("play_sound", {
|
||||
filename: filename,
|
||||
sleep: true
|
||||
});
|
||||
});
|
||||
|
||||
await listen('assistant-greet', (event) => {
|
||||
document.getElementById("arc-reactor").classList.add("active");
|
||||
});
|
||||
|
||||
await listen('assistant-waiting', (event) => {
|
||||
document.getElementById("arc-reactor").classList.remove("active");
|
||||
});
|
||||
});
|
||||
</script>
|
||||
73
gui/src/components/Footer.svelte
Normal file
73
gui/src/components/Footer.svelte
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
<script>
|
||||
import { invoke } from "@tauri-apps/api/tauri"
|
||||
|
||||
import { tg_official_link, github_repository_link } from "@/stores";
|
||||
|
||||
let current_year = new Date().getFullYear();
|
||||
let author_name = "";
|
||||
|
||||
(async () => {
|
||||
author_name = await invoke("get_author_name")
|
||||
|
||||
})().catch(err => {
|
||||
console.error(err);
|
||||
});
|
||||
</script>
|
||||
|
||||
<footer id="footer">
|
||||
<p>© {current_year}. Автор проекта: {author_name}</p>
|
||||
<p style="margin-top: 5px;margin-bottom: 15px;">
|
||||
<a href="{tg_official_link}" target="_blank" class="special-link"><img src="/media/icons/howdy-logo.png" alt="" width="20px"> Наш телеграм</a> канал.
|
||||
|
||||
<a href="{github_repository_link}" target="_blank"><img src="/media/icons/github-logo.png" alt="" width="18px"> Github репозиторий</a> проекта.</p>
|
||||
</footer>
|
||||
|
||||
<style lang="scss">
|
||||
#footer {
|
||||
text-align: center;
|
||||
color: #565759;
|
||||
font-size: 12px;
|
||||
font-weight: bold;
|
||||
line-height: 1.7em;
|
||||
margin-top: 15px;
|
||||
|
||||
p {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #185876;
|
||||
text-decoration: none;
|
||||
transition: opacity .5s;
|
||||
|
||||
img {
|
||||
opacity: .5;
|
||||
transition: opacity .5s;
|
||||
margin-top: -4px;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
color: #2A9CD0;
|
||||
|
||||
img {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
&.special-link {
|
||||
color: #941d92;
|
||||
display: inline-block;
|
||||
|
||||
&:hover {
|
||||
color: #FF07FC;
|
||||
|
||||
background: url(/media/images/bg/bg24.gif);
|
||||
background-repeat: no-repeat;
|
||||
background-size: contain;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
28
gui/src/components/Header.svelte
Normal file
28
gui/src/components/Header.svelte
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
<script lang="ts">
|
||||
import { invoke } from "@tauri-apps/api/tauri"
|
||||
import { Dashboard, Gear } from 'radix-icons-svelte'
|
||||
import {isActive} from '@roxi/routify'
|
||||
|
||||
let app_version = "";
|
||||
|
||||
(async () => {
|
||||
app_version = await invoke("get_app_version")
|
||||
})().catch(err => {
|
||||
console.error(err);
|
||||
});
|
||||
</script>
|
||||
<header id="header">
|
||||
<div class="logo">
|
||||
<a href="/" title="Проект канала Хауди Хо!"><img src="/media/header-logo.png" alt=""></a>
|
||||
<div>
|
||||
<h1><a href="/">JARVIS</a></h1>
|
||||
<h2>v{app_version} <small style="color: #8AC832;opacity: .9;font-size: 13px;">BETA</small></h2>
|
||||
</div>
|
||||
</div>
|
||||
<nav class="top-menu">
|
||||
<ul>
|
||||
<li><a href="/commands" class:active={$isActive('/commands')}><Dashboard /> Команды</a></li>
|
||||
<li><a href="/settings" class:active={$isActive('/settings')}><Gear /> Настройки</a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
</header>
|
||||
5
gui/src/components/Nav.svelte
Normal file
5
gui/src/components/Nav.svelte
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
|
||||
<nav>
|
||||
<a href="/index">Main Page</a>
|
||||
<a href="/settings">Настройки</a>
|
||||
</nav>
|
||||
647
gui/src/components/elements/ArcReactor.svelte
Normal file
647
gui/src/components/elements/ArcReactor.svelte
Normal file
|
|
@ -0,0 +1,647 @@
|
|||
<!-- Based on: https://github.com/rembertdesigns/Iron-Man-Arc-Reactor-Pure-CSS and https://codepen.io/FlyingEmu/pen/DZNqEj -->
|
||||
<div id="arc-reactor" class="reactor-container">
|
||||
<div class="reactor-container-inner circle abs-center">
|
||||
<ul class="marks"><li></li><li></li><li></li><li></li><li></li><li></li>
|
||||
<li></li><li></li><li></li><li></li><li></li><li></li>
|
||||
<li></li><li></li><li></li><li></li><li></li><li></li>
|
||||
<li></li><li></li><li></li><li></li><li></li><li></li>
|
||||
<li></li><li></li><li></li><li></li><li></li><li></li>
|
||||
<li></li><li></li><li></li><li></li><li></li><li></li>
|
||||
<li></li><li></li><li></li><li></li><li></li><li></li>
|
||||
<li></li><li></li><li></li><li></li><li></li><li></li>
|
||||
<li></li><li></li><li></li><li></li><li></li><li></li>
|
||||
<li></li><li></li><li></li><li></li><li></li><li></li></ul>
|
||||
<div class="e7">
|
||||
<div class="semi_arc_3 e5_1">
|
||||
<div class="semi_arc_3 e5_2">
|
||||
<div class="semi_arc_3 e5_3">
|
||||
<div class="semi_arc_3 e5_4" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tunnel circle abs-center" />
|
||||
<div class="core-wrapper circle abs-center" />
|
||||
<div class="core-outer circle abs-center" />
|
||||
<div class="core-inner circle abs-center" />
|
||||
<div class="coil-container">
|
||||
<div class="coil coil-1" />
|
||||
<div class="coil coil-2" />
|
||||
<div class="coil coil-3" />
|
||||
<div class="coil coil-4" />
|
||||
<div class="coil coil-5" />
|
||||
<div class="coil coil-6" />
|
||||
<div class="coil coil-7" />
|
||||
<div class="coil coil-8" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style lang="scss" global>
|
||||
$arc_radius: 130px;
|
||||
$size3: 6px;
|
||||
$cshadow: rgba(2, 254, 255, 0.8);
|
||||
$marks_color_1: rgba(2, 254, 255, 1);
|
||||
$marks_color_2: rgba(2, 254, 255, 0.3);
|
||||
$colour1: rgba(2, 255, 255, 0.15);
|
||||
$colour3: rgba(2, 255, 255, 0.3);
|
||||
$cshadow: rgba(2, 254, 255, 0.8);
|
||||
|
||||
.reactor-container {
|
||||
width: 300px;
|
||||
height: 320px;
|
||||
margin: auto;
|
||||
// border: 1px dashed #888;
|
||||
position: relative;
|
||||
border-radius: 50%;
|
||||
transition: scale 1s ease, opacity .5s ease;
|
||||
scale: 0.9;
|
||||
opacity: .9;
|
||||
// background-color: #384c50;
|
||||
// border: 1px solid #121414;
|
||||
// box-shadow: 0px 0px 32px 8px #121414, 0px 0px 4px 1px #121414 inset;
|
||||
|
||||
ul {
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
.reactor-container-inner {
|
||||
height: 238px;
|
||||
width: 238px;
|
||||
background-color: #161a1b;
|
||||
box-shadow: 0px 0px 50px 15px $colour3, inset 0px 0px 50px 15px $colour3;
|
||||
// box-shadow: 0px 0px 4px 1px #52fefe;
|
||||
}
|
||||
.circle {
|
||||
border-radius: 50%;
|
||||
}
|
||||
.abs-center {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
margin: auto;
|
||||
}
|
||||
.core-inner {
|
||||
width: 70px;
|
||||
height: 70px;
|
||||
border: 5px solid #1b4e5f;
|
||||
background-color: #ffffff;
|
||||
box-shadow: 0px 0px 7px 5px #52fefe, 0px 0px 10px 10px #52fefe inset;
|
||||
}
|
||||
.core-outer {
|
||||
width: 120px;
|
||||
height: 120px;
|
||||
border: 1px solid #52fefe;
|
||||
background-color: #ffffff;
|
||||
box-shadow: 0px 0px 2px 1px #52fefe, 0px 0px 10px 5px #52fefe inset;
|
||||
}
|
||||
.core-wrapper {
|
||||
width: 180px;
|
||||
height: 180px;
|
||||
background-color: #073c4b;
|
||||
box-shadow: 0px 0px 5px 4px #52fefe, 0px 0px 6px 2px #52fefe inset;
|
||||
}
|
||||
.tunnel {
|
||||
width: 220px;
|
||||
height: 220px;
|
||||
background-color: #ffffff;
|
||||
box-shadow: 0px 0px 5px 1px #52fefe, 0px 0px 5px 4px #52fefe inset;
|
||||
}
|
||||
.coil-container {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
animation: 10s infinite linear reactor-anim;
|
||||
transition: animation 1s;
|
||||
}
|
||||
.coil {
|
||||
position: absolute;
|
||||
width: 30px;
|
||||
height: 20px;
|
||||
top: calc(50% - 110px);
|
||||
left: calc(50% - 15px);
|
||||
transform-origin: 15px 110px;
|
||||
background-color: #073c4b;
|
||||
box-shadow: 0px 0px 5px #52fefe inset;
|
||||
}
|
||||
.coil-1 {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
.coil-2 {
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
.coil-3 {
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
.coil-4 {
|
||||
transform: rotate(135deg);
|
||||
}
|
||||
.coil-5 {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
.coil-6 {
|
||||
transform: rotate(225deg);
|
||||
}
|
||||
.coil-7 {
|
||||
transform: rotate(270deg);
|
||||
}
|
||||
.coil-8 {
|
||||
transform: rotate(315deg);
|
||||
}
|
||||
@keyframes reactor-anim {
|
||||
from {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
to {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
@mixin border-radius($pixel...) {
|
||||
border-radius: $pixel;
|
||||
}
|
||||
|
||||
.e7 {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
width: 160%;
|
||||
height: 160%;
|
||||
left: -32.5%;
|
||||
top: -32.5%;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
margin: auto;
|
||||
border: $size3 solid transparent;
|
||||
background: transparent;
|
||||
@include border-radius(50%);
|
||||
transform: rotateZ(0deg);
|
||||
transition: box-shadow 3s ease;
|
||||
text-align: center;
|
||||
opacity: .3;
|
||||
}
|
||||
|
||||
.semi_arc {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
border: 6px solid #02feff;
|
||||
background: rgba(2, 254, 255, 0.2);
|
||||
-moz-border-radius: 50%;
|
||||
-webkit-border-radius: 50%;
|
||||
border-radius: 50%;
|
||||
transform: rotateZ(0deg);
|
||||
transition: box-shadow 3s ease;
|
||||
text-align: center;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.semi_arc:hover {
|
||||
box-shadow: 0px 0px 30px $cshadow;
|
||||
transition: 0.3s;
|
||||
}
|
||||
|
||||
.semi_arc_2 {
|
||||
content: "";
|
||||
position: absolute;
|
||||
width: 94%;
|
||||
height: 94%;
|
||||
left: 3%;
|
||||
top: 3%;
|
||||
border: 5px solid #02feff;
|
||||
-moz-border-radius: 50%;
|
||||
-webkit-border-radius: 50%;
|
||||
border-radius: 50%;
|
||||
-moz-box-sizing: border-box;
|
||||
-webkit-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
animation: rotate 4s linear infinite;
|
||||
text-align: center;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.semi_arc_2:after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
width: 94%;
|
||||
height: 94%;
|
||||
left: 3%;
|
||||
top: 3%;
|
||||
border: 4px solid #02feff;
|
||||
-moz-border-radius: 50%;
|
||||
-webkit-border-radius: 50%;
|
||||
border-radius: 50%;
|
||||
-moz-box-sizing: border-box;
|
||||
-webkit-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
animation: rotate_anti 2s linear infinite;
|
||||
}
|
||||
|
||||
.semi_arc_3 {
|
||||
content: "";
|
||||
position: absolute;
|
||||
width: 94%;
|
||||
height: 94%;
|
||||
left: 3%;
|
||||
top: 3%;
|
||||
border: 5px solid #02feff;
|
||||
-moz-border-radius: 50%;
|
||||
-webkit-border-radius: 50%;
|
||||
border-radius: 50%;
|
||||
-moz-box-sizing: border-box;
|
||||
-webkit-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
animation: rotate 4s linear infinite;
|
||||
text-align: center;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.e1:after {
|
||||
border-color: rgba(2, 255, 255, 0.6);
|
||||
border-left: 5px solid transparent;
|
||||
border-right: 5px solid transparent;
|
||||
}
|
||||
|
||||
.e2:after {
|
||||
border-color: rgba(2, 255, 255, 0.6);
|
||||
border-left: 5px solid transparent;
|
||||
border-right: 5px solid transparent;
|
||||
border-bottom: 5px solid transparent;
|
||||
}
|
||||
|
||||
.e3 {
|
||||
border-left: 6px solid transparent;
|
||||
border-right: 6px solid transparent;
|
||||
animation: rotate 5s linear infinite;
|
||||
}
|
||||
|
||||
.e3:after {
|
||||
border-color: rgba(2, 255, 255, 0.6);
|
||||
border-top: 5px solid transparent;
|
||||
border-bottom: 5px solid transparent;
|
||||
}
|
||||
|
||||
.e4 {
|
||||
width: 150px;
|
||||
height: 150px;
|
||||
}
|
||||
|
||||
.e4_1 {
|
||||
border-color: rgba(2, 255, 255, 0.3);
|
||||
border-left: 5px solid transparent;
|
||||
border-right: 5px solid transparent;
|
||||
}
|
||||
|
||||
.e4_1:after {
|
||||
border-color: rgba(2, 255, 255, 0.6);
|
||||
border-top: 4px solid transparent;
|
||||
border-bottom: 4px solid transparent;
|
||||
}
|
||||
|
||||
.e5 {
|
||||
width: 200px;
|
||||
height: 200px;
|
||||
}
|
||||
|
||||
.e5_1 {
|
||||
color: rgba(2, 255, 255, 0.15);
|
||||
border: 2px solid;
|
||||
border-left: 2px solid transparent;
|
||||
animation: rotate 5s linear infinite;
|
||||
}
|
||||
|
||||
.e5_2 {
|
||||
color: rgba(2, 255, 255, 0.7);
|
||||
border: 4px solid;
|
||||
border-left: 4px solid transparent;
|
||||
border-right: 4px solid transparent;
|
||||
animation: rotate_anti 4s linear infinite;
|
||||
}
|
||||
|
||||
.e5_3 {
|
||||
color: rgba(2, 255, 255, 0.5);
|
||||
border: 2px solid;
|
||||
border-left: 2px solid transparent;
|
||||
border-right: 2px solid transparent;
|
||||
animation: rotate 3s linear infinite;
|
||||
}
|
||||
|
||||
.e5_4 {
|
||||
color: rgba(2, 255, 255, 0.15);
|
||||
border: 4px solid;
|
||||
border-left: 4px solid transparent;
|
||||
border-right: 4px solid transparent;
|
||||
border-bottom: 4px solid transparent;
|
||||
animation: rotate_anti 2s linear infinite;
|
||||
}
|
||||
|
||||
.e6 {
|
||||
border-color: transparent;
|
||||
background: rgba(255, 255, 255, 0);
|
||||
width: 200px;
|
||||
height: 200px;
|
||||
}
|
||||
|
||||
@keyframes rotate_anti {
|
||||
0% {
|
||||
transform: rotateZ(360deg);
|
||||
}
|
||||
100% {
|
||||
transform: rotateZ(0deg);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes rotate {
|
||||
0% {
|
||||
transform: rotateZ(0deg);
|
||||
}
|
||||
100% {
|
||||
transform: rotateZ(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
.marks {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
margin: auto;
|
||||
|
||||
li {
|
||||
display: block;
|
||||
width: 3px;
|
||||
height: 11px;
|
||||
background: $cshadow;
|
||||
position: absolute;
|
||||
margin-left: 117.5px;
|
||||
margin-top: 113.5px;
|
||||
animation: colour_ease2 3s infinite ease-in-out;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes colour_ease2 {
|
||||
0% {
|
||||
background: $marks_color_1;
|
||||
}
|
||||
50% {
|
||||
background: $marks_color_2;
|
||||
}
|
||||
100% {
|
||||
background: $marks_color_1;
|
||||
}
|
||||
}
|
||||
|
||||
.marks li:first-child {
|
||||
transform: rotate(6deg) translateY($arc_radius);
|
||||
}
|
||||
.marks li:nth-child(2) {
|
||||
transform: rotate(12deg) translateY($arc_radius);
|
||||
}
|
||||
.marks li:nth-child(3) {
|
||||
transform: rotate(18deg) translateY($arc_radius);
|
||||
}
|
||||
.marks li:nth-child(4) {
|
||||
transform: rotate(24deg) translateY($arc_radius);
|
||||
}
|
||||
.marks li:nth-child(5) {
|
||||
transform: rotate(30deg) translateY($arc_radius);
|
||||
}
|
||||
.marks li:nth-child(6) {
|
||||
transform: rotate(36deg) translateY($arc_radius);
|
||||
}
|
||||
.marks li:nth-child(7) {
|
||||
transform: rotate(42deg) translateY($arc_radius);
|
||||
}
|
||||
.marks li:nth-child(8) {
|
||||
transform: rotate(48deg) translateY($arc_radius);
|
||||
}
|
||||
.marks li:nth-child(9) {
|
||||
transform: rotate(54deg) translateY($arc_radius);
|
||||
}
|
||||
.marks li:nth-child(10) {
|
||||
transform: rotate(60deg) translateY($arc_radius);
|
||||
}
|
||||
.marks li:nth-child(11) {
|
||||
transform: rotate(66deg) translateY($arc_radius);
|
||||
}
|
||||
.marks li:nth-child(12) {
|
||||
transform: rotate(72deg) translateY($arc_radius);
|
||||
}
|
||||
.marks li:nth-child(13) {
|
||||
transform: rotate(78deg) translateY($arc_radius);
|
||||
}
|
||||
.marks li:nth-child(14) {
|
||||
transform: rotate(84deg) translateY($arc_radius);
|
||||
}
|
||||
.marks li:nth-child(15) {
|
||||
transform: rotate(90deg) translateY($arc_radius);
|
||||
}
|
||||
.marks li:nth-child(16) {
|
||||
transform: rotate(96deg) translateY($arc_radius);
|
||||
}
|
||||
.marks li:nth-child(17) {
|
||||
transform: rotate(102deg) translateY($arc_radius);
|
||||
}
|
||||
.marks li:nth-child(18) {
|
||||
transform: rotate(108deg) translateY($arc_radius);
|
||||
}
|
||||
.marks li:nth-child(19) {
|
||||
transform: rotate(114deg) translateY($arc_radius);
|
||||
}
|
||||
.marks li:nth-child(20) {
|
||||
transform: rotate(120deg) translateY($arc_radius);
|
||||
}
|
||||
.marks li:nth-child(21) {
|
||||
transform: rotate(126deg) translateY($arc_radius);
|
||||
}
|
||||
.marks li:nth-child(22) {
|
||||
transform: rotate(132deg) translateY($arc_radius);
|
||||
}
|
||||
.marks li:nth-child(23) {
|
||||
transform: rotate(138deg) translateY($arc_radius);
|
||||
}
|
||||
.marks li:nth-child(24) {
|
||||
transform: rotate(144deg) translateY($arc_radius);
|
||||
}
|
||||
.marks li:nth-child(25) {
|
||||
transform: rotate(150deg) translateY($arc_radius);
|
||||
}
|
||||
.marks li:nth-child(26) {
|
||||
transform: rotate(156deg) translateY($arc_radius);
|
||||
}
|
||||
.marks li:nth-child(27) {
|
||||
transform: rotate(162deg) translateY($arc_radius);
|
||||
}
|
||||
.marks li:nth-child(28) {
|
||||
transform: rotate(168deg) translateY($arc_radius);
|
||||
}
|
||||
.marks li:nth-child(29) {
|
||||
transform: rotate(174deg) translateY($arc_radius);
|
||||
}
|
||||
.marks li:nth-child(30) {
|
||||
transform: rotate(180deg) translateY($arc_radius);
|
||||
}
|
||||
.marks li:nth-child(31) {
|
||||
transform: rotate(186deg) translateY($arc_radius);
|
||||
}
|
||||
.marks li:nth-child(32) {
|
||||
transform: rotate(192deg) translateY($arc_radius);
|
||||
}
|
||||
.marks li:nth-child(33) {
|
||||
transform: rotate(198deg) translateY($arc_radius);
|
||||
}
|
||||
.marks li:nth-child(34) {
|
||||
transform: rotate(204deg) translateY($arc_radius);
|
||||
}
|
||||
.marks li:nth-child(35) {
|
||||
transform: rotate(210deg) translateY($arc_radius);
|
||||
}
|
||||
.marks li:nth-child(36) {
|
||||
transform: rotate(216deg) translateY($arc_radius);
|
||||
}
|
||||
.marks li:nth-child(37) {
|
||||
transform: rotate(222deg) translateY($arc_radius);
|
||||
}
|
||||
.marks li:nth-child(38) {
|
||||
transform: rotate(228deg) translateY($arc_radius);
|
||||
}
|
||||
.marks li:nth-child(39) {
|
||||
transform: rotate(234deg) translateY($arc_radius);
|
||||
}
|
||||
.marks li:nth-child(40) {
|
||||
transform: rotate(240deg) translateY($arc_radius);
|
||||
}
|
||||
.marks li:nth-child(41) {
|
||||
transform: rotate(246deg) translateY($arc_radius);
|
||||
}
|
||||
.marks li:nth-child(42) {
|
||||
transform: rotate(252deg) translateY($arc_radius);
|
||||
}
|
||||
.marks li:nth-child(43) {
|
||||
transform: rotate(258deg) translateY($arc_radius);
|
||||
}
|
||||
.marks li:nth-child(44) {
|
||||
transform: rotate(264deg) translateY($arc_radius);
|
||||
}
|
||||
.marks li:nth-child(45) {
|
||||
transform: rotate(270deg) translateY($arc_radius);
|
||||
}
|
||||
.marks li:nth-child(46) {
|
||||
transform: rotate(276deg) translateY($arc_radius);
|
||||
}
|
||||
.marks li:nth-child(47) {
|
||||
transform: rotate(282deg) translateY($arc_radius);
|
||||
}
|
||||
.marks li:nth-child(48) {
|
||||
transform: rotate(288deg) translateY($arc_radius);
|
||||
}
|
||||
.marks li:nth-child(49) {
|
||||
transform: rotate(294deg) translateY($arc_radius);
|
||||
}
|
||||
.marks li:nth-child(50) {
|
||||
transform: rotate(300deg) translateY($arc_radius);
|
||||
}
|
||||
.marks li:nth-child(51) {
|
||||
transform: rotate(306deg) translateY($arc_radius);
|
||||
}
|
||||
.marks li:nth-child(52) {
|
||||
transform: rotate(312deg) translateY($arc_radius);
|
||||
}
|
||||
.marks li:nth-child(53) {
|
||||
transform: rotate(318deg) translateY($arc_radius);
|
||||
}
|
||||
.marks li:nth-child(54) {
|
||||
transform: rotate(324deg) translateY($arc_radius);
|
||||
}
|
||||
.marks li:nth-child(55) {
|
||||
transform: rotate(330deg) translateY($arc_radius);
|
||||
}
|
||||
.marks li:nth-child(56) {
|
||||
transform: rotate(336deg) translateY($arc_radius);
|
||||
}
|
||||
.marks li:nth-child(57) {
|
||||
transform: rotate(342deg) translateY($arc_radius);
|
||||
}
|
||||
.marks li:nth-child(58) {
|
||||
transform: rotate(348deg) translateY($arc_radius);
|
||||
}
|
||||
.marks li:nth-child(59) {
|
||||
transform: rotate(354deg) translateY($arc_radius);
|
||||
}
|
||||
.marks li:nth-child(60) {
|
||||
transform: rotate(360deg) translateY($arc_radius);
|
||||
}
|
||||
|
||||
/*
|
||||
Some overrides.
|
||||
*/
|
||||
.reactor-container.active {
|
||||
$arc_radius: 130px;
|
||||
$size3: 6px;
|
||||
$cshadow: rgba(2, 254, 255, 0.8);
|
||||
$marks_color_1: rgba(2, 254, 255, 1);
|
||||
$marks_color_2: rgba(2, 254, 255, 0.3);
|
||||
$colour1: rgba(2, 255, 255, 0.15);
|
||||
$colour3: rgba(2, 255, 255, 0.3);
|
||||
$cshadow: rgba(2, 254, 255, 0.8);
|
||||
|
||||
scale: 1.1;
|
||||
opacity: 1;
|
||||
.coil-container {
|
||||
animation: 3s infinite linear reactor-anim;
|
||||
}
|
||||
|
||||
.reactor-container-inner {
|
||||
box-shadow: 0px 0px 50px 15px $colour3, inset 0px 0px 50px 15px $colour3;
|
||||
}
|
||||
|
||||
.core-inner {
|
||||
border: 5px solid #1b4e5f;
|
||||
background-color: #ffffff;
|
||||
box-shadow: 0px 0px 7px 5px #52fefe, 0px 0px 10px 10px #52fefe inset;
|
||||
}
|
||||
|
||||
.core-outer {
|
||||
border: 1px solid #52fefe;
|
||||
background-color: #ffffff;
|
||||
box-shadow: 0px 0px 2px 1px #52fefe, 0px 0px 10px 5px #52fefe inset;
|
||||
}
|
||||
.core-wrapper {
|
||||
background-color: #073c4b;
|
||||
box-shadow: 0px 0px 5px 4px #52fefe, 0px 0px 6px 2px #52fefe inset;
|
||||
}
|
||||
.tunnel {
|
||||
background-color: #ffffff;
|
||||
box-shadow: 0px 0px 5px 1px #52fefe, 0px 0px 5px 4px #52fefe inset;
|
||||
}
|
||||
.coil {
|
||||
background-color: #073c4b;
|
||||
box-shadow: 0px 0px 5px #52fefe inset;
|
||||
}
|
||||
|
||||
.semi_arc {
|
||||
border: 6px solid #02feff;
|
||||
background: rgba(2, 254, 255, 0.2);
|
||||
}
|
||||
|
||||
|
||||
.e5_1 {
|
||||
animation: rotate 3s linear infinite;
|
||||
}
|
||||
|
||||
.e5_2 {
|
||||
animation: rotate_anti 2s linear infinite;
|
||||
}
|
||||
|
||||
.e5_3 {
|
||||
animation: rotate 2s linear infinite;
|
||||
}
|
||||
|
||||
.e5_4 {
|
||||
animation: rotate_anti 2s linear infinite;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
18
gui/src/components/elements/HDivider.svelte
Normal file
18
gui/src/components/elements/HDivider.svelte
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
<script>
|
||||
export let no_margin = false;
|
||||
</script>
|
||||
|
||||
<div class="h-divider" class:no-margin="{no_margin}"></div>
|
||||
|
||||
<style lang="scss">
|
||||
.h-divider {
|
||||
margin: 20px 0;
|
||||
height: 40px;
|
||||
background-image: url(media/images/decor.png);
|
||||
background-position: center;
|
||||
|
||||
&.no-margin {
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
11
gui/src/components/elements/SearchBar.svelte
Normal file
11
gui/src/components/elements/SearchBar.svelte
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
<script>
|
||||
let search_q = "";
|
||||
</script>
|
||||
|
||||
<div id="search-form" class="search" class:active={search_q != ""}>
|
||||
<form action="#" method="GET">
|
||||
<input bind:value={search_q} type="text" name="q" placeholder="Введите команду или скажите «Джарвис» ..." autocomplete="off" minlength="3" maxlength="30">
|
||||
<button type="submit"></button>
|
||||
<small>Enter</small>
|
||||
</form>
|
||||
</div>
|
||||
377
gui/src/components/elements/Stats.svelte
Normal file
377
gui/src/components/elements/Stats.svelte
Normal file
|
|
@ -0,0 +1,377 @@
|
|||
<script>
|
||||
// IMPORTS
|
||||
import { invoke } from "@tauri-apps/api/tauri"
|
||||
import { onMount } from 'svelte'
|
||||
import { capitalizeFirstLetter } from "@/functions";
|
||||
|
||||
// VARIABLES
|
||||
let selected_microphone = 0;
|
||||
let microphone_label = "";
|
||||
|
||||
let nn_details = {
|
||||
"ww_engine": "",
|
||||
"stt_engine": "Vosk"
|
||||
}
|
||||
|
||||
// let resources_cpu_temp = 0;
|
||||
// let resources_cpu_usage = 0;
|
||||
let resources_ram_usage = "-";
|
||||
|
||||
// CODE
|
||||
setInterval(() => {
|
||||
(async () => {
|
||||
resources_ram_usage = Number(await invoke("get_current_ram_usage")).toFixed(2);
|
||||
// resources_cpu_temp = await invoke("get_cpu_temp");
|
||||
// resources_cpu_usage = +Number(await invoke("get_cpu_usage")).toFixed(2);
|
||||
})().catch(err => {
|
||||
console.error(err);
|
||||
});
|
||||
}, 1000);
|
||||
|
||||
onMount(async () => {
|
||||
(async () => {
|
||||
selected_microphone = +Number(await invoke("db_read", {key: "selected_microphone"}));
|
||||
microphone_label = await invoke("pv_get_audio_device_name", {idx: selected_microphone});
|
||||
|
||||
nn_details["ww_engine"] = capitalizeFirstLetter(await invoke("db_read", {key: "selected_wake_word_engine"}));
|
||||
|
||||
// resources_cpu_temp = await invoke("get_cpu_temp");
|
||||
// resources_cpu_usage = +Number(await invoke("get_cpu_usage")).toFixed(2);
|
||||
})().catch(err => {
|
||||
console.error(err);
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<div class="statistics">
|
||||
<div class="online">
|
||||
<div class="pulse"><div class="wave"></div></div>
|
||||
<div class="info">
|
||||
<span class="num">Микрофон</span>
|
||||
<small title="{microphone_label}">{microphone_label}</small>
|
||||
</div>
|
||||
</div>
|
||||
<div class="files">
|
||||
<div class="pulse"><div class="wave"></div></div>
|
||||
<div class="info">
|
||||
<span class="num">Нейросети</span>
|
||||
<small>{nn_details["ww_engine"]} + {nn_details["stt_engine"]}</small>
|
||||
</div>
|
||||
</div>
|
||||
<div class="downloads hint--bottom" aria-label="Общее количество скачиваний по всему проекту">
|
||||
<div class="pulse"><div class="wave"></div></div>
|
||||
<div class="info">
|
||||
<span class="num">Ресурсы</span>
|
||||
<small><!-- CPU {resources_cpu_usage}%<br /> -->RAM {resources_ram_usage}mb</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style lang="scss">
|
||||
.statistics {
|
||||
position: relative;
|
||||
z-index: 3;
|
||||
padding: 0 10px;
|
||||
height: 100px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
|
||||
& > div {
|
||||
height: 70px;
|
||||
}
|
||||
|
||||
.info {
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
& > .online {
|
||||
position: relative;
|
||||
width: 40%;
|
||||
|
||||
$base-color: rgba(0, 191, 8, 1);
|
||||
$mid-color: rgba(0, 191, 8, 0.4);
|
||||
$end-color: rgba(0, 191, 8, 0);
|
||||
|
||||
& > .pulse::before {
|
||||
background-color: rgba(0, 191, 8, 1);
|
||||
}
|
||||
& > .pulse::after {
|
||||
background-color: rgba(0, 191, 8, 1);
|
||||
animation: online-cdot linear 3s;
|
||||
animation-iteration-count: infinite;
|
||||
animation-fill-mode: forwards;
|
||||
}
|
||||
& > .pulse .wave {
|
||||
background-color: rgba(0, 191, 8, 0.4);
|
||||
animation: online-radarWave cubic-bezier(0, 0.54, 0.53, 1) 3s 0s;
|
||||
animation-iteration-count: infinite;
|
||||
}
|
||||
& > .pulse .wave::after {
|
||||
background-color: rgba(0, 191, 8, 0.4);
|
||||
animation: online-radarWave cubic-bezier(0, 0.54, 0.53, 1) 3s
|
||||
0.1s;
|
||||
animation-iteration-count: infinite;
|
||||
}
|
||||
|
||||
& > .info {
|
||||
position: absolute;
|
||||
top: 26px;
|
||||
left: 26px;
|
||||
|
||||
& > span.num {
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
color: #00bf08;
|
||||
}
|
||||
& > small {
|
||||
display: block;
|
||||
color: #535a60;
|
||||
font-size: 12px;
|
||||
position: relative;
|
||||
top: 0;
|
||||
width: 130px;
|
||||
max-height: 40px;
|
||||
overflow: hidden;
|
||||
line-height: 1.5em;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes online-cdot {
|
||||
0% {
|
||||
opacity: 0.3;
|
||||
background: $base-color;
|
||||
}
|
||||
50% {
|
||||
opacity: 0.5;
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
background: $end-color;
|
||||
}
|
||||
}
|
||||
@keyframes online-radarWave {
|
||||
0% {
|
||||
opacity: 0.1;
|
||||
transform: scale(0);
|
||||
}
|
||||
5% {
|
||||
background: $mid-color;
|
||||
opacity: 1;
|
||||
}
|
||||
100% {
|
||||
transform: scale(1.2);
|
||||
background: $end-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
& > .files {
|
||||
position: relative;
|
||||
width: 35%;
|
||||
|
||||
$base-color: rgba(255, 129, 48, 1);
|
||||
$mid-color: rgba(255, 129, 48, 0.4);
|
||||
$end-color: rgba(255, 129, 48, 0);
|
||||
|
||||
& > .pulse::before {
|
||||
background-color: $base-color;
|
||||
}
|
||||
& > .pulse::after {
|
||||
background-color: $base-color;
|
||||
animation: files-cdot linear 5s;
|
||||
animation-iteration-count: infinite;
|
||||
animation-fill-mode: forwards;
|
||||
}
|
||||
& > .pulse .wave {
|
||||
background-color: $mid-color;
|
||||
animation: files-radarWave cubic-bezier(0, 0.54, 0.53, 1) 5s 0s;
|
||||
animation-iteration-count: infinite;
|
||||
}
|
||||
& > .pulse .wave::after {
|
||||
background-color: $mid-color;
|
||||
animation: files-radarWave cubic-bezier(0, 0.54, 0.53, 1) 5s
|
||||
0.1s;
|
||||
animation-iteration-count: infinite;
|
||||
}
|
||||
|
||||
& > .info {
|
||||
position: absolute;
|
||||
top: 26px;
|
||||
left: 26px;
|
||||
|
||||
& > span.num {
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
color: #ff8130;
|
||||
}
|
||||
& > small {
|
||||
display: block;
|
||||
color: #535a60;
|
||||
font-size: 12px;
|
||||
position: relative;
|
||||
top: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes files-cdot {
|
||||
0% {
|
||||
opacity: 0.3;
|
||||
background: $base-color;
|
||||
}
|
||||
50% {
|
||||
opacity: 0.5;
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
background: $end-color;
|
||||
}
|
||||
}
|
||||
@keyframes files-radarWave {
|
||||
0% {
|
||||
opacity: 0.1;
|
||||
transform: scale(0);
|
||||
}
|
||||
5% {
|
||||
background: $mid-color;
|
||||
transform: scale(0.2);
|
||||
opacity: 1;
|
||||
}
|
||||
100% {
|
||||
transform: scale(0.8);
|
||||
background: $end-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
& > .downloads {
|
||||
position: relative;
|
||||
|
||||
$base-color: rgba(11,66,166, 1);
|
||||
$mid-color: rgba(32, 150, 243, 0.4);
|
||||
$end-color: rgba(32, 150, 243, 0);
|
||||
|
||||
& > .pulse::before {
|
||||
background: rgba(32, 150, 243, 1);
|
||||
}
|
||||
& > .pulse::after {
|
||||
background: rgba(32, 150, 243, 1);
|
||||
animation: downloads-cdot linear 7s;
|
||||
animation-iteration-count: infinite;
|
||||
animation-fill-mode: forwards;
|
||||
animation-delay: 1s;
|
||||
}
|
||||
& > .pulse .wave {
|
||||
background-color: $mid-color;
|
||||
animation: downloads-radarWave cubic-bezier(0, 0.54, 0.53, 1) 7s
|
||||
0s;
|
||||
animation-iteration-count: infinite;
|
||||
animation-delay: 1s;
|
||||
}
|
||||
& > .pulse .wave::after {
|
||||
background-color: $mid-color;
|
||||
animation: downloads-radarWave cubic-bezier(0, 0.54, 0.53, 1) 7s
|
||||
0.1s;
|
||||
animation-iteration-count: infinite;
|
||||
animation-delay: 1s;
|
||||
}
|
||||
|
||||
& > .info {
|
||||
position: absolute;
|
||||
top: 26px;
|
||||
left: 26px;
|
||||
|
||||
& > span.num {
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
color: #1b78a6;
|
||||
}
|
||||
|
||||
& > small {
|
||||
display: block;
|
||||
color: #535a60;
|
||||
font-size: 12px;
|
||||
position: relative;
|
||||
top: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes downloads-cdot {
|
||||
0% {
|
||||
opacity: 0.3;
|
||||
background: $base-color;
|
||||
}
|
||||
50% {
|
||||
opacity: 0.5;
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
background: $end-color;
|
||||
}
|
||||
}
|
||||
@keyframes downloads-radarWave {
|
||||
0% {
|
||||
opacity: 0.1;
|
||||
transform: scale(0);
|
||||
}
|
||||
5% {
|
||||
background: $mid-color;
|
||||
opacity: 1;
|
||||
}
|
||||
100% {
|
||||
transform: scale(0.7);
|
||||
background: $end-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.pulse {
|
||||
position: relative;
|
||||
height: 100px;
|
||||
width: 100px;
|
||||
margin: 0;
|
||||
left: -43px;
|
||||
top: 0px;
|
||||
z-index: 5;
|
||||
}
|
||||
.pulse::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
width: 11px;
|
||||
height: 11px;
|
||||
border-radius: 50%;
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
opacity: .5;
|
||||
}
|
||||
.pulse::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
border-radius: 50%;
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
.pulse .wave {
|
||||
position: absolute;
|
||||
left: 7%;
|
||||
top: 7%;
|
||||
width: 86%;
|
||||
height: 86%;
|
||||
border-radius: 50%;
|
||||
opacity: 0;
|
||||
}
|
||||
.pulse .wave::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: 7%;
|
||||
top: 7%;
|
||||
width: 86%;
|
||||
height: 86%;
|
||||
border-radius: 50%;
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
308
gui/src/css/main.scss
Normal file
308
gui/src/css/main.scss
Normal file
|
|
@ -0,0 +1,308 @@
|
|||
$prim-font: "Roboto", sans-serif;
|
||||
$sec-font: "Roboto Condensed", sans-serif;
|
||||
|
||||
html, body {
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar {
|
||||
width: 15px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-track {
|
||||
-webkit-box-shadow: inset 0 0 6px rgba(0,0,0,0.3);
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb {
|
||||
background: -webkit-gradient(linear,left top,left bottom,from(#999),to(#27292F));
|
||||
background: linear-gradient(to bottom,#999,#27292F);
|
||||
}
|
||||
|
||||
::selection {
|
||||
background: #FF8901!important; /* WebKit/Blink Browsers */
|
||||
color: white!important;
|
||||
text-shadow: 1px 1px 1px rgba(0, 0, 0, .5)!important;
|
||||
}
|
||||
::-moz-selection {
|
||||
background: #FF8901!important; /* WebKit/Blink Browsers */
|
||||
color: white!important;
|
||||
text-shadow: 1px 1px 1px rgba(0, 0, 0, .5)!important;
|
||||
}
|
||||
|
||||
/*
|
||||
* HEADER
|
||||
*/
|
||||
|
||||
#header {
|
||||
height: 80px;
|
||||
background-color: #0c1013;
|
||||
box-shadow: 0 0 19px 2px rgba(0, 0, 0, 0.91);
|
||||
position: relative;
|
||||
z-index: 100;
|
||||
text-align: justify;
|
||||
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
|
||||
.logo {
|
||||
margin-top: 12px;
|
||||
|
||||
& > a > img {
|
||||
width: 57px;
|
||||
display: inline-block;
|
||||
transition: .5s opacity ease-in;
|
||||
|
||||
&:hover {
|
||||
opacity: .8;
|
||||
}
|
||||
}
|
||||
|
||||
& > div {
|
||||
display: inline-block;
|
||||
margin-left: 13px;
|
||||
margin-top: 8px;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
h1 {
|
||||
color: #ffffff;
|
||||
font-family: $sec-font;
|
||||
font-size: 20px;
|
||||
font-weight: bold;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.1px;
|
||||
margin: 0;
|
||||
|
||||
& > a {
|
||||
color: white;
|
||||
text-shadow: 1px 1px 1px rgba(0, 0, 0, .5);
|
||||
text-decoration: none;
|
||||
|
||||
&:hover {
|
||||
color: #8AC832;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
h2 {
|
||||
color: #888;
|
||||
font-family: $sec-font;
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
letter-spacing: 0.1px;
|
||||
margin-top: 2px;
|
||||
letter-spacing: -0.01px;
|
||||
}
|
||||
}
|
||||
|
||||
.top-menu {
|
||||
vertical-align: top;
|
||||
margin-top: 18px;
|
||||
margin-left: 50px;
|
||||
|
||||
& > ul {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
|
||||
& > li {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
|
||||
&:not(:first-child) {
|
||||
margin-left: 20px;
|
||||
}
|
||||
|
||||
& > a {
|
||||
display: inline-block;
|
||||
text-decoration: none;
|
||||
color: #c6c6c6;
|
||||
font-family: $sec-font;
|
||||
font-size: 16px;
|
||||
text-transform: uppercase;
|
||||
font-weight: bold;
|
||||
transition: .2s color;
|
||||
padding: 10px 0;
|
||||
|
||||
& > svg {
|
||||
height: 20px;
|
||||
width: 20px;
|
||||
vertical-align: middle;
|
||||
margin-bottom: 4px;
|
||||
margin-right: 3px;
|
||||
margin-left: 3px;
|
||||
}
|
||||
|
||||
&:hover, &.active {
|
||||
color: #8AC832;
|
||||
|
||||
&:after {
|
||||
-webkit-transform: scaleX(1);
|
||||
-ms-transform: scaleX(1);
|
||||
transform: scaleX(1);
|
||||
-webkit-transform-origin: left;
|
||||
-ms-transform-origin: left;
|
||||
transform-origin: left;
|
||||
}
|
||||
}
|
||||
|
||||
&:after {
|
||||
content: "";
|
||||
display: block;
|
||||
height: 3px;
|
||||
border-radius: 10px;
|
||||
-webkit-transform: scaleX(0);
|
||||
-ms-transform: scaleX(0);
|
||||
transform: scaleX(0);
|
||||
transition: .4s -webkit-transform;
|
||||
transition: .4s transform;
|
||||
-webkit-transform-origin: 100% 0;
|
||||
-ms-transform-origin: 100% 0;
|
||||
transform-origin: 100% 0;
|
||||
background: #8AC832;
|
||||
opacity: 0.90;
|
||||
position: absolute;
|
||||
bottom: 5px;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
z-index: 333;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.search {
|
||||
display: block;
|
||||
margin: 20px 0;
|
||||
text-align: center;
|
||||
|
||||
& > form {
|
||||
position: relative;
|
||||
|
||||
& > input {
|
||||
width: 380px;
|
||||
height: 38px;
|
||||
box-shadow: inset 0 0 5px 1px rgba(0, 0, 0, 0.6);
|
||||
border: 1px solid rgba(6, 6, 6, 0.99);
|
||||
background-color: #0f1012;
|
||||
outline: none;
|
||||
|
||||
color: #D1D1D1;
|
||||
font-family: $sec-font;
|
||||
font-size: 17px;
|
||||
font-weight: 600;
|
||||
line-height: 70.58px;
|
||||
padding-left: 20px;
|
||||
padding-right: 45px;
|
||||
padding-right: 45px;
|
||||
|
||||
&::placeholder {
|
||||
color: #676767;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
&:focus + button + small {
|
||||
opacity: .3;
|
||||
}
|
||||
}
|
||||
|
||||
& > button {
|
||||
position: absolute;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
background: none;
|
||||
border: none;
|
||||
right: 35px;
|
||||
top: 4px;
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
opacity: 1;
|
||||
transition: .3s opacity;
|
||||
|
||||
&::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 110%;
|
||||
height: 110%;
|
||||
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABwAAAAbCAYAAABvCO8sAAAC4ElEQVRIiaXWX4hXRRTA8c/etkwy+gNBEVRCmxFl1ouZGlEWFUQZPfVQRLAjKvSylEFBf16EiChJOxhLQY8RtA+lRZtpRv8ohUJQNMiHooKyojZNtoeZy95+/fZ3r+uBy5xz5pzznYGZc2dodHRUB1lVviUYwXkYwk84iK8wGRHb2goNtQDXYxRXdVkV9mFrRDx/osCl2IxrG75PsAv75Z1NyzsdwQosb8R+jXURsbML8AG82rDH8TI+77eyiAAppSVYg9SYXhsRW5rxVU/+Qw3Yd7ip+PrCesB7ImKNvNMDxb05pbR+NuBSvFL0L7EYH7SB+oA/Lrm7i2tTSmlVL3AYbxf9eyzDkROFNaBTWCmfYJhIKc1rAh/DuUW/HUfnCmtAp3FrMefjmRp4Kh4tE+PYO6DO6fKp7Ao9hJeKOZZSWlBhNc4ozidbaqyUr8W4/x+42aSuOYT7KtxZHF/gcEvyvDI+KF/yFW20iPgZk8W8o8KVxZjsn/IfOdbQL8OulNLTHfJ2lHFRhYuKcbB/bKs8kVLanVK6ZkBMfS8vqLCgGL/NEQjX48MB8/UVm1/hz2KceRLAfbh3wHxde2pYbmFnY+EcYVsiYm1LzKVl/KHCN8W4sUPxUxr6j7i7AwxuKOP+ykxLW4bzWxKnyziBRXirjZRSOstMx9lW4Q38XRyPt+R/hOtwF35tgzVqDhX99QpTeK441pWVzya/49OOICmlCzFWzE0RcaRuT0/hj6Jv71qwg7xbxuNKv66BR820uIuxE6edDCmltB1XFPOeiPiL/B+sZQcexgtyk96L+3X42/eAFuM1+YUHGyJiop4f7ol/Ef/Iv5TL8VlZQMiXexBoRH7hjTXcj0TEs8242V5tNxdo8wC9J5/Sfq+25bitEfut/Gp7p7dw7w5reV/e4Yay6oW4pXyD5DC2YmNEHOsXMBuwlo3lWy3v+mpcgnPku/WL3Br3yA+uNyPi+KCC/wJQGMGINsMjCwAAAABJRU5ErkJggg==");
|
||||
background-repeat: no-repeat;
|
||||
background-size: 75%;
|
||||
background-position: center center;
|
||||
transition: all .3s;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
&::before {
|
||||
cursor: pointer;
|
||||
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABwAAAAbCAYAAABvCO8sAAABN2lDQ1BBZG9iZSBSR0IgKDE5OTgpAAAokZWPv0rDUBSHvxtFxaFWCOLgcCdRUGzVwYxJW4ogWKtDkq1JQ5ViEm6uf/oQjm4dXNx9AidHwUHxCXwDxamDQ4QMBYvf9J3fORzOAaNi152GUYbzWKt205Gu58vZF2aYAoBOmKV2q3UAECdxxBjf7wiA10277jTG+38yH6ZKAyNguxtlIYgK0L/SqQYxBMygn2oQD4CpTto1EE9AqZf7G1AKcv8ASsr1fBBfgNlzPR+MOcAMcl8BTB1da4Bakg7UWe9Uy6plWdLuJkEkjweZjs4zuR+HiUoT1dFRF8jvA2AxH2w3HblWtay99X/+PRHX82Vun0cIQCw9F1lBeKEuf1UYO5PrYsdwGQ7vYXpUZLs3cLcBC7dFtlqF8hY8Dn8AwMZP/fNTP8gAAAAJcEhZcwAACxMAAAsTAQCanBgAAAXRaVRYdFhNTDpjb20uYWRvYmUueG1wAAAAAAA8P3hwYWNrZXQgYmVnaW49Iu+7vyIgaWQ9Ilc1TTBNcENlaGlIenJlU3pOVGN6a2M5ZCI/PiA8eDp4bXBtZXRhIHhtbG5zOng9ImFkb2JlOm5zOm1ldGEvIiB4OnhtcHRrPSJBZG9iZSBYTVAgQ29yZSA1LjYtYzE0MiA3OS4xNjA5MjQsIDIwMTcvMDcvMTMtMDE6MDY6MzkgICAgICAgICI+IDxyZGY6UkRGIHhtbG5zOnJkZj0iaHR0cDovL3d3dy53My5vcmcvMTk5OS8wMi8yMi1yZGYtc3ludGF4LW5zIyI+IDxyZGY6RGVzY3JpcHRpb24gcmRmOmFib3V0PSIiIHhtbG5zOnhtcD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLyIgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIiB4bWxuczpwaG90b3Nob3A9Imh0dHA6Ly9ucy5hZG9iZS5jb20vcGhvdG9zaG9wLzEuMC8iIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIiB4bWxuczpzdEV2dD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlRXZlbnQjIiB4bXA6Q3JlYXRvclRvb2w9IkFkb2JlIFBob3Rvc2hvcCBDQyAyMDE4IChXaW5kb3dzKSIgeG1wOkNyZWF0ZURhdGU9IjIwMjMtMDQtMjNUMDQ6MzE6NTgrMDU6MDAiIHhtcDpNb2RpZnlEYXRlPSIyMDIzLTA0LTIzVDA0OjM0OjI3KzA1OjAwIiB4bXA6TWV0YWRhdGFEYXRlPSIyMDIzLTA0LTIzVDA0OjM0OjI3KzA1OjAwIiBkYzpmb3JtYXQ9ImltYWdlL3BuZyIgcGhvdG9zaG9wOkNvbG9yTW9kZT0iMyIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDowZDA5NTdiMi0zYmM3LTcxNDItODcyNS01ODA3MjA2NTFlYTIiIHhtcE1NOkRvY3VtZW50SUQ9ImFkb2JlOmRvY2lkOnBob3Rvc2hvcDoxM2UwZWYxNi03OGM0LTE2NGMtODc1Mi0xYjY5OTQ1OTczMGMiIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDo5YjNkZTI4Yy1iOTBmLTNjNDUtYjAwNS1kNTExOTE3ZDhkNzIiPiA8eG1wTU06SGlzdG9yeT4gPHJkZjpTZXE+IDxyZGY6bGkgc3RFdnQ6YWN0aW9uPSJjcmVhdGVkIiBzdEV2dDppbnN0YW5jZUlEPSJ4bXAuaWlkOjliM2RlMjhjLWI5MGYtM2M0NS1iMDA1LWQ1MTE5MTdkOGQ3MiIgc3RFdnQ6d2hlbj0iMjAyMy0wNC0yM1QwNDozMTo1OCswNTowMCIgc3RFdnQ6c29mdHdhcmVBZ2VudD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTggKFdpbmRvd3MpIi8+IDxyZGY6bGkgc3RFdnQ6YWN0aW9uPSJzYXZlZCIgc3RFdnQ6aW5zdGFuY2VJRD0ieG1wLmlpZDowZDA5NTdiMi0zYmM3LTcxNDItODcyNS01ODA3MjA2NTFlYTIiIHN0RXZ0OndoZW49IjIwMjMtMDQtMjNUMDQ6MzQ6MjcrMDU6MDAiIHN0RXZ0OnNvZnR3YXJlQWdlbnQ9IkFkb2JlIFBob3Rvc2hvcCBDQyAyMDE4IChXaW5kb3dzKSIgc3RFdnQ6Y2hhbmdlZD0iLyIvPiA8L3JkZjpTZXE+IDwveG1wTU06SGlzdG9yeT4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz4Wh528AAAC7UlEQVRIiaXWX4gXVRTA8c9v2jLJ6A8ERVAJbUakTr2YqRFl0QRRRk89FBGYqNDLUgY51PQiRERJWhhLQY8RtA+OFm2mGf2RGqEQDAvyoaigrKhNk+3h3mGnX7/9zbgeGO45555zvvfCvWdub/POpTrI6vilGMVF6OEnHMEXmCyyaldboV4LcCPWYnGXVeEQdhRZ9fypApdhG65v+D7GPhwWdjYt7HQUK7GiEfslNhRZtbcL8EG81rDH8TI+G7SyIqtAXqYp1uGRxvT6Iqu2N+OTvvyHG7DvcEv0DYT1gasiq9YJO/06urflZbpxNuAyvBr1z7EE77eBBoA/irn7o2trXqar+4Ej2Bn177Ecx04V1oBOYZVwgmEiL9N5TeATuDDqGY7PFdaATuP2aM7HMzXwTDweJ8ZxcEids4VT2RX6DV6K5lhepgsSrME50flUS41VwrUY9/8DN5vUNXu4P8Fd0XEAR1uS58XxIeGSr2yjFVn1MyajeWeCa6MxOTjlP3KioV+FfXmZFh3y9sRxUYLLonFkcGyrbM7LdH9eptcNianv5SUJFkTjtzkC4UZ8MGS+vmLzE/wZjXNPA3gI9w2Zr2tPjQgt7HwsnCNse5FV61tirozjDwm+isbNHYqf0dB/xD0dYHBTHA8nZlraclzckjgdxwkswtttpLxMzzPTcXYleBN/R8eTLfkf4gbcjV/bYI2avai/kWAKz0XHhrjy2eR3fNIRJC/TSzEWza1FVh2r29PT+CPqu7sW7CDvxPGk2K9r4HEzLe5y7MVZp0PKy3Q3ronmvUVW/UX4D9ayB4/iBaFJH8QDOvzt+0BL8LrwwoNNRVZN1PMjffEv4h/hl3I1Po0LeEW43MNAo8ILb6zhfqzIqmebcbO92m6N0OYBelc4pYNebStwRyP2W+HVVvYX7t9hLe8JO9wUV70Qt8VvmBzFDmwpsurEoIDZgLVsid8aYddLcQUuEO7WL0JrrIQH11tFVp0cVvBfVZDA+HDoxOQAAAAASUVORK5CYII=");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
& > small {
|
||||
position: absolute;
|
||||
font-family: $sec-font;
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
line-height: 1.7em;
|
||||
top: 8px;
|
||||
right: 75px;
|
||||
background-color: #D1D1D1;
|
||||
color: #080C0F;
|
||||
padding: 0 7px;
|
||||
padding-top: 2px;
|
||||
border-radius: 4px;
|
||||
opacity: 0;
|
||||
transition: opacity .3s;
|
||||
cursor: default;
|
||||
}
|
||||
}
|
||||
|
||||
&.active {
|
||||
small {
|
||||
opacity: .3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 1364px) {
|
||||
#content>.inner>section.materials>header>h1 {
|
||||
font-size: 26px;
|
||||
}
|
||||
|
||||
#content>.inner>section.materials>article>.details>h1 {
|
||||
font-size: 25px;
|
||||
}
|
||||
|
||||
#content>.inner>section.materials>article>.details>blockquote {
|
||||
font-size: 17px;
|
||||
line-height: 24px;
|
||||
-webkit-line-clamp: 4;
|
||||
}
|
||||
|
||||
.btn {
|
||||
font-size: 16px!important;
|
||||
}
|
||||
|
||||
#paginator>header>h1 {
|
||||
font-size: 30px!important;
|
||||
}
|
||||
|
||||
#paginator>.paginator-wrapper>.paginator-box {
|
||||
transform: scale(1.5);
|
||||
margin-top: 15px;
|
||||
}
|
||||
|
||||
#paginator>.paginator-wrapper>small:first-child {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#paginator>.paginator-wrapper>small:last-child {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
92
gui/src/css/styles.scss
Normal file
92
gui/src/css/styles.scss
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
/*
|
||||
SOME DEFAULT CSS.
|
||||
*/
|
||||
html, body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
min-height: 100vh;
|
||||
min-width: 100vw;
|
||||
|
||||
background-color: #4C5062;
|
||||
color: white;
|
||||
|
||||
|
||||
&.assist-page {
|
||||
background: rgb(24,123,123);
|
||||
background: -moz-radial-gradient(circle, rgba(24,123,123,0.4906337535014006) 0%, rgba(13,15,19,1) 64%);
|
||||
background: -webkit-radial-gradient(circle, rgba(24,123,123,0.4906337535014006) 0%, rgba(13,15,19,1) 64%);
|
||||
background: radial-gradient(circle, rgba(24,123,123,0.4906337535014006) 0%, rgba(13,15,19,1) 64%);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr="#187b7b",endColorstr="#0d0f13",GradientType=1);
|
||||
|
||||
&.assist-active {
|
||||
background: rgb(24,81,123);
|
||||
background: -moz-radial-gradient(circle, rgba(24,81,123,0.6418942577030813) 0%, rgba(13,15,19,1) 64%);
|
||||
background: -webkit-radial-gradient(circle, rgba(24,81,123,0.6418942577030813) 0%, rgba(13,15,19,1) 64%);
|
||||
background: radial-gradient(circle, rgba(24,81,123,0.6418942577030813) 0%, rgba(13,15,19,1) 64%);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr="#18517b",endColorstr="#0d0f13",GradientType=1);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
:root {
|
||||
font-family: Inter, Avenir, Helvetica, Arial, sans-serif;
|
||||
font-size: 16px;
|
||||
line-height: 24px;
|
||||
font-weight: 400;
|
||||
|
||||
color: #0f0f0f;
|
||||
background-color: #f6f6f6;
|
||||
|
||||
font-synthesis: none;
|
||||
text-rendering: optimizeLegibility;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
-webkit-text-size-adjust: 100%;
|
||||
}
|
||||
|
||||
|
||||
a {
|
||||
color: #2A9CD0;
|
||||
text-decoration: none;
|
||||
font-weight: bold;
|
||||
|
||||
&:hover {
|
||||
color: #1dabed;
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
OVERRIDES.
|
||||
*/
|
||||
#wrapper {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
#header, main {
|
||||
padding: 0 30px;
|
||||
}
|
||||
|
||||
select, input {
|
||||
color: #ccc!important;
|
||||
}
|
||||
|
||||
.form {
|
||||
label {
|
||||
font-weight: bold!important;
|
||||
color: #8AC832!important;
|
||||
font-size: 15px!important;
|
||||
border-bottom: 1px dotted gray;
|
||||
margin-bottom: 10px!important;
|
||||
|
||||
& + div {
|
||||
line-height: 1.2em;
|
||||
}
|
||||
}
|
||||
|
||||
.svelteui-Tab-label {
|
||||
font-size: 18px!important;
|
||||
}
|
||||
}
|
||||
61
gui/src/functions.ts
Normal file
61
gui/src/functions.ts
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
import { invoke } from "@tauri-apps/api/tauri"
|
||||
import { is_listening, isListening } from "@/stores"
|
||||
import { clearInterval, clearTimeout, setInterval, setTimeout } from 'worker-timers';
|
||||
|
||||
setInterval(() => {
|
||||
(async () => {
|
||||
is_listening.set(await invoke("is_listening"));
|
||||
})().catch(err => {
|
||||
console.error(err);
|
||||
});
|
||||
}, 1000);
|
||||
|
||||
export function startListening() {
|
||||
(async () => {
|
||||
invoke('start_listening')
|
||||
.then((message) => {
|
||||
is_listening.set(true);
|
||||
})
|
||||
.catch((error) => {
|
||||
is_listening.set(false);
|
||||
console.error(error);
|
||||
// alert("Ошибка: " + error);
|
||||
})
|
||||
})().catch(err => {
|
||||
console.error(err);
|
||||
});
|
||||
}
|
||||
|
||||
export function stopListening(callback) {
|
||||
(async () => {
|
||||
invoke('stop_listening')
|
||||
.then((message) => {
|
||||
is_listening.set(false);
|
||||
if(callback) {
|
||||
callback();
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error(error);
|
||||
})
|
||||
})().catch(err => {
|
||||
console.error(err);
|
||||
});
|
||||
}
|
||||
|
||||
export function capitalizeFirstLetter(string) {
|
||||
return string.charAt(0).toUpperCase() + string.slice(1);
|
||||
}
|
||||
|
||||
export function showInExplorer(path) {
|
||||
(async () => {
|
||||
invoke('show_in_folder', {path: path})
|
||||
.then((message) => {})
|
||||
.catch((error) => {
|
||||
console.error(error);
|
||||
// alert("Ошибка: " + error);
|
||||
})
|
||||
})().catch(err => {
|
||||
console.error(err);
|
||||
});
|
||||
}
|
||||
13
gui/src/main.ts
Normal file
13
gui/src/main.ts
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
// Klondike project old CSS file
|
||||
import "./css/main.scss";
|
||||
|
||||
// App current CSS file
|
||||
import "./css/styles.scss";
|
||||
|
||||
// deploy app
|
||||
import App from "./App.svelte";
|
||||
const app = new App({
|
||||
target: document.getElementById("app"),
|
||||
});
|
||||
|
||||
export default app;
|
||||
12
gui/src/pages/_layout.svelte
Normal file
12
gui/src/pages/_layout.svelte
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
<!-- _layout.svelte -->
|
||||
<script>
|
||||
import { Container } from '@svelteuidev/core'
|
||||
import Header from '@/components/Header.svelte'
|
||||
</script>
|
||||
|
||||
<Container fluid id="wrapper">
|
||||
<Header />
|
||||
<main>
|
||||
<slot></slot>
|
||||
</main>
|
||||
</Container>
|
||||
23
gui/src/pages/commands.svelte
Normal file
23
gui/src/pages/commands.svelte
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
<script lang="ts">
|
||||
import HDivider from "@/components/elements/HDivider.svelte"
|
||||
import Footer from "@/components/Footer.svelte"
|
||||
|
||||
import { Notification, Space } from '@svelteuidev/core';
|
||||
import { InfoCircled } from 'radix-icons-svelte';
|
||||
|
||||
import { tg_official_link } from "@/stores";
|
||||
</script>
|
||||
|
||||
<Space h="xl" />
|
||||
|
||||
<Notification title='[404] Этот раздел еще находится в разработке!' icon={InfoCircled} color='blue' withCloseButton={false}>
|
||||
Тут будет список команд + полноценный редактор команд.<br>
|
||||
Следите за обновлениями в <a href="{tg_official_link}" target="_blank">нашем телеграм канале</a>!
|
||||
</Notification>
|
||||
|
||||
<div style="text-align: center;margin-top: 25px;">
|
||||
<img src="/media/images/tenor.gif" alt="bruh" width="320px">
|
||||
</div>
|
||||
|
||||
<HDivider />
|
||||
<Footer />
|
||||
71
gui/src/pages/index.svelte
Normal file
71
gui/src/pages/index.svelte
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
<script lang="ts">
|
||||
import SearchBar from "@/components/elements/SearchBar.svelte"
|
||||
import ArcReactor from "@/components/elements/ArcReactor.svelte"
|
||||
import HDivider from "@/components/elements/HDivider.svelte"
|
||||
import Stats from "@/components/elements/Stats.svelte"
|
||||
import Footer from "@/components/Footer.svelte"
|
||||
|
||||
import { Notification, Space } from '@svelteuidev/core'
|
||||
import { InfoCircled } from 'radix-icons-svelte'
|
||||
import { onMount, onDestroy } from 'svelte'
|
||||
|
||||
onMount(async () => {
|
||||
document.body.classList.add('assist-page');
|
||||
});
|
||||
|
||||
onDestroy(async () => {
|
||||
document.body.classList.remove('assist-page');
|
||||
});
|
||||
|
||||
import { is_listening } from "@/stores"
|
||||
let is_listening__val: boolean;
|
||||
is_listening.subscribe(value => {
|
||||
is_listening__val = value;
|
||||
});
|
||||
</script>
|
||||
|
||||
<HDivider />
|
||||
{#if !is_listening__val}
|
||||
<Notification title='Внимание!' icon={InfoCircled} color='cyan' withCloseButton={false}>
|
||||
В данный момент ассистент не прослушивает команды.<br />
|
||||
Пожалуйста, <a href="/settings">перейдите в настройки</a> и введите ключ Picovoice.
|
||||
</Notification>
|
||||
<!-- <SearchBar /> -->
|
||||
{:else}
|
||||
<!-- <SearchBar /> -->
|
||||
<ArcReactor />
|
||||
{/if}
|
||||
<HDivider no_margin />
|
||||
<Stats />
|
||||
<Footer />
|
||||
|
||||
|
||||
<!--
|
||||
<Title order={1}>This is h1 title</Title>
|
||||
<Title order={1} variant='gradient' gradient={{from: 'blue', to: 'red', deg: 45}}>This is h1 title with a twist</Title>
|
||||
|
||||
<Menu>
|
||||
<Button slot="control" variant="gradient" gradient={{ from: 'blue', to: 'teal', deg: 50 }} radius="md" size="md">Toggle Menu</Button>
|
||||
<Menu.Label>Application</Menu.Label>
|
||||
<Menu.Item icon={Gear}>Settings</Menu.Item>
|
||||
<Menu.Item icon={ChatBubble}>Messages</Menu.Item>
|
||||
<Menu.Item icon={Camera}>Gallery</Menu.Item>
|
||||
<Menu.Item icon={MagnifyingGlass}>
|
||||
<svelte:fragment slot='rightSection'>
|
||||
<Text size="xs" color="dimmed">⌘K</Text>
|
||||
</svelte:fragment>
|
||||
Search
|
||||
</Menu.Item>
|
||||
|
||||
<Divider />
|
||||
|
||||
<Menu.Label>Danger zone</Menu.Label>
|
||||
<Menu.Item icon={Width}>Transfer my data</Menu.Item>
|
||||
<Menu.Item color="red" icon={Trash}>Delete my account</Menu.Item>
|
||||
</Menu>
|
||||
|
||||
<Checkbox bind:checked={checked} label="I agree to sell my privacy" />
|
||||
{checked}
|
||||
{#if checked}
|
||||
YEP!
|
||||
{/if} -->
|
||||
188
gui/src/pages/settings.svelte
Normal file
188
gui/src/pages/settings.svelte
Normal file
|
|
@ -0,0 +1,188 @@
|
|||
<script lang="ts">
|
||||
// IMPORTS
|
||||
import { invoke } from "@tauri-apps/api/tauri"
|
||||
import { goto } from '@roxi/routify'
|
||||
import { onMount } from 'svelte'
|
||||
import { startListening, stopListening, showInExplorer } from "@/functions";
|
||||
import { setTimeout } from 'worker-timers';
|
||||
|
||||
import { feedback_link, log_file_path } from "@/stores";
|
||||
|
||||
// COMPONENTS & STUFF
|
||||
import HDivider from "@/components/elements/HDivider.svelte"
|
||||
import Footer from "@/components/Footer.svelte"
|
||||
|
||||
import { Notification, Button, Text, Tabs, Space, Alert, Input, InputWrapper, NativeSelect } from '@svelteuidev/core';
|
||||
import { Check, Mix, Cube, Code, Gear, QuestionMarkCircled, CrossCircled } from 'radix-icons-svelte';
|
||||
|
||||
// VARIABLES
|
||||
|
||||
let available_microphones = [];
|
||||
let settings_saved = false;
|
||||
let save_button_disabled = false;
|
||||
|
||||
let assistant_voice_val = ""; // shared
|
||||
let selected_microphone = "";
|
||||
|
||||
let selected_wake_word_engine = "";
|
||||
let api_key__picovoice = "";
|
||||
let api_key__openai = "";
|
||||
|
||||
// SHARED VALUES
|
||||
import { assistant_voice } from "@/stores"
|
||||
assistant_voice.subscribe(value => {
|
||||
assistant_voice_val = value;
|
||||
});
|
||||
|
||||
// FUNCTIONS
|
||||
async function save_settings() {
|
||||
save_button_disabled = true; // disable save button for a while
|
||||
settings_saved = false; // hide alert
|
||||
|
||||
await invoke("db_write", {key: "assistant_voice", val: assistant_voice_val});
|
||||
await invoke("db_write", {key: "selected_microphone", val: selected_microphone});
|
||||
|
||||
await invoke("db_write", {key: "selected_wake_word_engine", val: selected_wake_word_engine});
|
||||
await invoke("db_write", {key: "api_key__picovoice", val: api_key__picovoice});
|
||||
await invoke("db_write", {key: "api_key__openai", val: api_key__openai});
|
||||
|
||||
// update shared
|
||||
assistant_voice.set(assistant_voice_val);
|
||||
|
||||
settings_saved = true; // show alert
|
||||
setTimeout(() => {
|
||||
settings_saved = false; // hide alert again after N seconds
|
||||
}, 5000);
|
||||
|
||||
setTimeout(() => {
|
||||
save_button_disabled = false; // enable save button again
|
||||
}, 1000);
|
||||
|
||||
// restart listening everytime new settings is saved
|
||||
stopListening(() => {
|
||||
startListening();
|
||||
});
|
||||
}
|
||||
|
||||
// CODE
|
||||
onMount(async () => {
|
||||
// preload some vars
|
||||
let _available_microphones: Array<Number> = await invoke("pv_get_audio_devices");
|
||||
Object.entries(_available_microphones).forEach(entry => {
|
||||
const [k, v] = entry;
|
||||
|
||||
available_microphones.push({
|
||||
label: v,
|
||||
value: k
|
||||
});
|
||||
});
|
||||
|
||||
available_microphones = available_microphones; // update component options
|
||||
|
||||
// load values from db
|
||||
// assistant_voice.set(await invoke("db_read", {key: "assistant_voice"}));
|
||||
selected_microphone = await invoke("db_read", {key: "selected_microphone"});
|
||||
|
||||
selected_wake_word_engine = await invoke("db_read", {key: "selected_wake_word_engine"});
|
||||
api_key__picovoice = await invoke("db_read", {key: "api_key__picovoice"});
|
||||
api_key__openai = await invoke("db_read", {key: "api_key__openai"});
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
<Space h="xl" />
|
||||
|
||||
<Notification title='БЕТА версия!' icon={QuestionMarkCircled} color='blue' withCloseButton={false}>
|
||||
Часть функций может работать некорректно.<br />
|
||||
Сообщайте обо всех найденных багах в <a href="{feedback_link}" target="_blank">наш телеграм бот</a>.
|
||||
<Space h="sm" />
|
||||
<Button color="gray" radius="md" size="xs" uppercase on:click={() => {showInExplorer(log_file_path)}}>Открыть папку с логами</Button>
|
||||
</Notification>
|
||||
|
||||
<Space h="xl" />
|
||||
|
||||
{#if settings_saved }
|
||||
<Notification title='Настройки сохранены!' icon={Check} color='teal' on:close="{() => {settings_saved = false}}"></Notification>
|
||||
<Space h="xl" />
|
||||
{/if}
|
||||
|
||||
<Tabs class="form" color='#8AC832' position="left">
|
||||
<Tabs.Tab label='Общее' icon={Gear}>
|
||||
<Space h="sm" />
|
||||
|
||||
<NativeSelect data={[
|
||||
{ label: 'Jarvis ремейк (от Хауди)', value: 'jarvis-remake' },
|
||||
{ label: 'Jarvis OG (из фильмов)', value: 'jarvis-og' }
|
||||
]}
|
||||
label="Голос ассистента"
|
||||
description="Не все команды работают со всеми звуковыми пакетами."
|
||||
variant="filled"
|
||||
bind:value={assistant_voice_val}
|
||||
/>
|
||||
</Tabs.Tab>
|
||||
<Tabs.Tab label='Устройства' icon={Mix}>
|
||||
<Space h="sm" />
|
||||
|
||||
<NativeSelect data={available_microphones}
|
||||
label="Выберите микрофон"
|
||||
description="Его будет слушать ассистент."
|
||||
variant="filled"
|
||||
bind:value={selected_microphone}
|
||||
/>
|
||||
</Tabs.Tab>
|
||||
<Tabs.Tab label='Нейросети' icon={Cube}>
|
||||
<Space h="sm" />
|
||||
|
||||
<NativeSelect data={[
|
||||
{ label: 'Rustpotter', value: 'rustpotter' },
|
||||
{ label: 'Vosk (медленный)', value: 'vosk' },
|
||||
{ label: 'Picovoice Porcupine (требует API ключ)', value: 'picovoice' }
|
||||
]}
|
||||
label="Распознавание активационной фразы (Wake Word)"
|
||||
description="Выберите, какая нейросеть будет отвечать за распознавание активационной фразы."
|
||||
variant="filled"
|
||||
bind:value={selected_wake_word_engine}
|
||||
/>
|
||||
|
||||
{#if selected_wake_word_engine == "picovoice"}
|
||||
<Space h="sm" />
|
||||
<Alert title="Внимание!" color="#868E96" variant="outline">
|
||||
|
||||
<Notification title='Эта нейросеть работает не у всех!' icon={CrossCircled} color='orange' withCloseButton={false}>
|
||||
Мы ждем официального патча от разработчиков.
|
||||
</Notification>
|
||||
<Space h="sm" />
|
||||
|
||||
<Text size='sm' color="gray">
|
||||
Введите сюда свой ключ Picovoice.<br />
|
||||
Он выдается бесплатно при регистрации в <a href='https://console.picovoice.ai/' target="_blank">Picovoice Console</a>.<br>
|
||||
</Text>
|
||||
<Space h="sm" />
|
||||
<Input icon={Code} placeholder='Ключ Picovoice' variant='filled' autocomplete="off" bind:value={api_key__picovoice}/>
|
||||
|
||||
</Alert>
|
||||
{/if}
|
||||
|
||||
<Space h="xl" />
|
||||
|
||||
<InputWrapper label="Ключ OpenAI">
|
||||
<!-- <Text size='sm' color="gray">Введите сюда свой ключ OpenAI, он требуется для работы ChatGPT.<br />Получить его можно <a href="https://chat.openai.com/auth/login" target="_blank">на официальном сайте OpenAI</a>.</Text> -->
|
||||
<Text size='sm' color="gray">В данный момент ChatGPT <u>не поддерживается</u>. Он будет добавлен в ближайших обновлениях.</Text>
|
||||
<Space h="sm" />
|
||||
<Input icon={Code} placeholder='Ключ OpenAI' variant='filled' autocomplete="off" bind:value={api_key__openai} disabled/>
|
||||
</InputWrapper>
|
||||
</Tabs.Tab>
|
||||
</Tabs>
|
||||
|
||||
<Space h="xl" />
|
||||
|
||||
<Button color="lime" radius="md" size="sm" uppercase ripple fullSize on:click={save_settings} disabled={save_button_disabled}>
|
||||
Сохранить
|
||||
</Button>
|
||||
<Space h="sm" />
|
||||
<Button color="gray" radius="md" size="sm" uppercase fullSize on:click={() => {$goto('/')}}>
|
||||
Назад
|
||||
</Button>
|
||||
|
||||
<HDivider />
|
||||
<Footer />
|
||||
34
gui/src/stores.ts
Normal file
34
gui/src/stores.ts
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
import { invoke } from "@tauri-apps/api/tauri"
|
||||
import { writable } from 'svelte/store'
|
||||
|
||||
// listen state
|
||||
export const is_listening = writable(true);
|
||||
let is_listening__val: boolean;
|
||||
is_listening.subscribe(value => {
|
||||
is_listening__val = value;
|
||||
});
|
||||
export function isListening() {return is_listening__val}
|
||||
|
||||
// assistant voice
|
||||
export const assistant_voice = writable("");
|
||||
|
||||
(async () => {
|
||||
assistant_voice.set(await invoke("db_read", {key: "assistant_voice"}));
|
||||
})().catch(err => {
|
||||
console.error(err);
|
||||
});
|
||||
|
||||
// etc
|
||||
export let tg_official_link = "";
|
||||
export let feedback_link = "";
|
||||
export let github_repository_link = "";
|
||||
export let log_file_path = "";
|
||||
|
||||
(async () => {
|
||||
tg_official_link = await invoke("get_tg_official_link")
|
||||
feedback_link = await invoke("get_feedback_link")
|
||||
github_repository_link = await invoke("get_repository_link")
|
||||
log_file_path = await invoke("get_log_file_path")
|
||||
})().catch(err => {
|
||||
console.error(err);
|
||||
});
|
||||
2
gui/src/vite-env.d.ts
vendored
Normal file
2
gui/src/vite-env.d.ts
vendored
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
/// <reference types="svelte" />
|
||||
/// <reference types="vite/client" />
|
||||
Loading…
Add table
Add a link
Reference in a new issue