├── src ├── devtools │ ├── README.md │ ├── api │ │ ├── path.ts │ │ ├── indicators.ts │ │ ├── database.ts │ │ ├── music.ts │ │ ├── app.ts │ │ ├── network.ts │ │ ├── system.ts │ │ ├── clipboard.ts │ │ ├── files.ts │ │ ├── shell.ts │ │ └── notifications.ts │ ├── hooks │ │ ├── localStorage.ts │ │ ├── router.ts │ │ └── context.tsx │ ├── types │ │ ├── events.ts │ │ ├── models.ts │ │ └── index.ts │ ├── lib │ │ ├── custom-events.ts │ │ └── utils.ts │ ├── register.ts │ ├── tsconfig.json │ ├── components │ │ ├── skeletons.tsx │ │ ├── fieldset.tsx │ │ ├── input.tsx │ │ ├── textarea.tsx │ │ ├── badge.tsx │ │ ├── slider.tsx │ │ ├── switch.tsx │ │ ├── layout.tsx │ │ ├── checkbox.tsx │ │ ├── radio.tsx │ │ ├── button.tsx │ │ ├── table.tsx │ │ ├── dialog.tsx │ │ └── select.tsx │ ├── build.js │ ├── index.ts │ └── package.json ├── config │ └── index.ts ├── types │ ├── extension.ts │ └── typings.d.ts ├── ui │ ├── Kbd.tsx │ ├── Command.tsx │ ├── MainActivity.tsx │ ├── shadcn │ │ └── command.tsx │ └── Footer.tsx ├── extensions │ ├── todoist │ │ ├── const.tsx │ │ ├── page.tsx │ │ ├── mapper.tsx │ │ ├── create.tsx │ │ └── use-todoist.tsx │ ├── music │ │ └── items.tsx │ ├── extension-viewer │ │ └── pages.tsx │ ├── navigation │ │ ├── context.tsx │ │ └── no-results.tsx │ ├── extension-assembly.ts │ ├── low-level-interaction │ │ └── items.tsx │ ├── ui-example │ │ └── pages.tsx │ ├── store │ │ └── page.tsx │ └── find-files │ │ └── page.tsx ├── main.tsx ├── services │ └── music.ts ├── init.ts ├── styles.css └── App.tsx ├── src-tauri ├── build.rs ├── .gitignore ├── icons │ ├── 32x32.png │ ├── icon.icns │ ├── icon.ico │ ├── icon.png │ ├── input.png │ ├── 128x128.png │ ├── 128x128@2x.png │ ├── StoreLogo.png │ ├── Square30x30Logo.png │ ├── Square44x44Logo.png │ ├── Square71x71Logo.png │ ├── Square89x89Logo.png │ ├── Square107x107Logo.png │ ├── Square142x142Logo.png │ ├── Square150x150Logo.png │ ├── Square284x284Logo.png │ └── Square310x310Logo.png ├── src │ ├── events │ │ ├── mod.rs │ │ ├── cmd.rs │ │ ├── app.rs │ │ ├── music.rs │ │ ├── clipboard.rs │ │ └── files.rs │ ├── constants.rs │ ├── database │ │ └── mod.rs │ └── main.rs ├── Cargo.toml └── tauri.conf.json ├── .vscode └── extensions.json ├── postcss.config.js ├── .gitignore ├── components.json ├── tsconfig.json ├── vite.config.ts ├── README.md ├── index.html ├── package.json └── tailwind.config.js /src/devtools/README.md: -------------------------------------------------------------------------------- 1 | # Sittly devtools 2 | -------------------------------------------------------------------------------- /src-tauri/build.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | tauri_build::build() 3 | } 4 | -------------------------------------------------------------------------------- /src/devtools/api/path.ts: -------------------------------------------------------------------------------- 1 | export * from "@tauri-apps/api/path"; 2 | -------------------------------------------------------------------------------- /src/config/index.ts: -------------------------------------------------------------------------------- 1 | export const DATABASE_TABLE_NAME = "extensions-store"; 2 | -------------------------------------------------------------------------------- /src-tauri/.gitignore: -------------------------------------------------------------------------------- 1 | # Generated by Cargo 2 | # will have compiled files and executables 3 | /target/ 4 | 5 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": ["tauri-apps.tauri-vscode", "rust-lang.rust-analyzer"] 3 | } 4 | -------------------------------------------------------------------------------- /src-tauri/icons/32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JulianKominovic/sittly-launcher/HEAD/src-tauri/icons/32x32.png -------------------------------------------------------------------------------- /src-tauri/icons/icon.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JulianKominovic/sittly-launcher/HEAD/src-tauri/icons/icon.icns -------------------------------------------------------------------------------- /src-tauri/icons/icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JulianKominovic/sittly-launcher/HEAD/src-tauri/icons/icon.ico -------------------------------------------------------------------------------- /src-tauri/icons/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JulianKominovic/sittly-launcher/HEAD/src-tauri/icons/icon.png -------------------------------------------------------------------------------- /src-tauri/icons/input.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JulianKominovic/sittly-launcher/HEAD/src-tauri/icons/input.png -------------------------------------------------------------------------------- /src/devtools/hooks/localStorage.ts: -------------------------------------------------------------------------------- 1 | import { useLocalStorage } from "usehooks-ts"; 2 | export { useLocalStorage }; 3 | -------------------------------------------------------------------------------- /postcss.config.js: -------------------------------------------------------------------------------- 1 | export default { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | }, 6 | } 7 | -------------------------------------------------------------------------------- /src-tauri/icons/128x128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JulianKominovic/sittly-launcher/HEAD/src-tauri/icons/128x128.png -------------------------------------------------------------------------------- /src-tauri/src/events/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod app; 2 | pub mod clipboard; 3 | pub mod cmd; 4 | pub mod files; 5 | pub mod music; 6 | -------------------------------------------------------------------------------- /src-tauri/icons/128x128@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JulianKominovic/sittly-launcher/HEAD/src-tauri/icons/128x128@2x.png -------------------------------------------------------------------------------- /src-tauri/icons/StoreLogo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JulianKominovic/sittly-launcher/HEAD/src-tauri/icons/StoreLogo.png -------------------------------------------------------------------------------- /src-tauri/icons/Square30x30Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JulianKominovic/sittly-launcher/HEAD/src-tauri/icons/Square30x30Logo.png -------------------------------------------------------------------------------- /src-tauri/icons/Square44x44Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JulianKominovic/sittly-launcher/HEAD/src-tauri/icons/Square44x44Logo.png -------------------------------------------------------------------------------- /src-tauri/icons/Square71x71Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JulianKominovic/sittly-launcher/HEAD/src-tauri/icons/Square71x71Logo.png -------------------------------------------------------------------------------- /src-tauri/icons/Square89x89Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JulianKominovic/sittly-launcher/HEAD/src-tauri/icons/Square89x89Logo.png -------------------------------------------------------------------------------- /src-tauri/icons/Square107x107Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JulianKominovic/sittly-launcher/HEAD/src-tauri/icons/Square107x107Logo.png -------------------------------------------------------------------------------- /src-tauri/icons/Square142x142Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JulianKominovic/sittly-launcher/HEAD/src-tauri/icons/Square142x142Logo.png -------------------------------------------------------------------------------- /src-tauri/icons/Square150x150Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JulianKominovic/sittly-launcher/HEAD/src-tauri/icons/Square150x150Logo.png -------------------------------------------------------------------------------- /src-tauri/icons/Square284x284Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JulianKominovic/sittly-launcher/HEAD/src-tauri/icons/Square284x284Logo.png -------------------------------------------------------------------------------- /src-tauri/icons/Square310x310Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JulianKominovic/sittly-launcher/HEAD/src-tauri/icons/Square310x310Logo.png -------------------------------------------------------------------------------- /src/devtools/types/events.ts: -------------------------------------------------------------------------------- 1 | export enum SittlyCustomEvents { 2 | ASYNC_STATUS = "async-status", 3 | } 4 | 5 | export type AsyncStatusEvent = { 6 | title: string; 7 | description: string; 8 | status: "IN_PROGRESS" | "SUCCESS" | "ERROR" | "IDLE"; 9 | }; 10 | -------------------------------------------------------------------------------- /src/devtools/api/indicators.ts: -------------------------------------------------------------------------------- 1 | import { dispatchAsyncStatusEvent } from "../lib/custom-events"; 2 | import { AsyncStatusEvent } from "../types/events"; 3 | 4 | export function notifyAsyncOperationStatus(asyncOpDetails: AsyncStatusEvent) { 5 | dispatchAsyncStatusEvent(asyncOpDetails); 6 | } 7 | -------------------------------------------------------------------------------- /src-tauri/src/constants.rs: -------------------------------------------------------------------------------- 1 | use std::path; 2 | 3 | pub fn get_sittly_path() -> String { 4 | let home_dir = std::env::home_dir().unwrap(); 5 | let home_dir_str = home_dir.to_str().unwrap(); 6 | let sittly_path = path::Path::new(home_dir_str).join(".sittly"); 7 | 8 | sittly_path.to_str().unwrap().to_string() 9 | } 10 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | 15 | # Editor directories and files 16 | .vscode/* 17 | !.vscode/extensions.json 18 | .idea 19 | .DS_Store 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | .env 26 | -------------------------------------------------------------------------------- /src/devtools/lib/custom-events.ts: -------------------------------------------------------------------------------- 1 | import { AsyncStatusEvent, SittlyCustomEvents } from "../types/events"; 2 | 3 | export function dispatchAsyncStatusEvent(asyncStatus: AsyncStatusEvent) { 4 | const asyncStatusEvent = new CustomEvent( 5 | SittlyCustomEvents.ASYNC_STATUS, 6 | { 7 | detail: asyncStatus, 8 | } 9 | ); 10 | window.dispatchEvent(asyncStatusEvent); 11 | } 12 | -------------------------------------------------------------------------------- /components.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://ui.shadcn.com/schema.json", 3 | "style": "default", 4 | "rsc": false, 5 | "tsx": true, 6 | "tailwind": { 7 | "config": "tailwind.config.js", 8 | "css": "./src/styles.css", 9 | "baseColor": "slate", 10 | "cssVariables": true 11 | }, 12 | "aliases": { 13 | "components": "./src/ui/shadcn", 14 | "utils": "./src/lib/utils" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/types/extension.ts: -------------------------------------------------------------------------------- 1 | export type ExtensionDatabaseModel = { 2 | url: string; 3 | author: string; 4 | name: string; 5 | body: string; 6 | user_id: string; 7 | icon_url: string; 8 | id: string; 9 | }; 10 | 11 | export type TodoistItem = { 12 | id: string; 13 | title: string; 14 | description: string; 15 | status: "TODO" | "DONE" | "IN_PROGRESS"; 16 | priority: "HIGH" | "MEDIUM" | "LOW"; 17 | due_date: number; 18 | category?: string; 19 | }; 20 | -------------------------------------------------------------------------------- /src/devtools/register.ts: -------------------------------------------------------------------------------- 1 | import { 2 | ExtensionPages, 3 | ExtensionContextMenuItems, 4 | ExtensionItems, 5 | ExtensionMetadata, 6 | ExtensionNoResultItems, 7 | } from "./types"; 8 | 9 | export default (extension: { 10 | pages?: ExtensionPages; 11 | items?: ExtensionItems; 12 | context?: ExtensionContextMenuItems; 13 | noResults?: ExtensionNoResultItems; 14 | metadata: ExtensionMetadata; 15 | }) => { 16 | (window as any).__SITTLY_EXTENSIONS__.push(extension); 17 | }; 18 | -------------------------------------------------------------------------------- /src/devtools/api/database.ts: -------------------------------------------------------------------------------- 1 | import { invoke } from "@tauri-apps/api"; 2 | 3 | export const write = ( 4 | key: string, 5 | value: Record | any[] 6 | ): Promise => { 7 | return invoke("write_database", { 8 | key, 9 | value: JSON.stringify(value), 10 | }); 11 | }; 12 | 13 | export const read = | any[] | void>( 14 | key: string 15 | ): Promise => { 16 | return invoke("read_database", { 17 | key, 18 | }).then((value) => (value ? JSON.parse(value) : value)); 19 | }; 20 | -------------------------------------------------------------------------------- /src/devtools/api/music.ts: -------------------------------------------------------------------------------- 1 | import { invoke } from "@tauri-apps/api"; 2 | 3 | export const playPause = () => invoke("play_pause_music"); 4 | export const prevMedia = () => invoke("previous_media"); 5 | export const nextMedia = () => invoke("next_media"); 6 | /** 7 | * Set the volume of the player 8 | * @example 9 | * setVolume("50%") // 50% 10 | * 11 | * @example 12 | * setVolume("10%-") // -10% based on current volume 13 | * 14 | * @example 15 | * setVolume("10%+") // +10% based on current volume 16 | */ 17 | export const setVolume = (volume: string) => { 18 | invoke("set_volume", { volume }); 19 | }; 20 | -------------------------------------------------------------------------------- /src/ui/Kbd.tsx: -------------------------------------------------------------------------------- 1 | import React, { useId } from "react"; 2 | 3 | export default function ({ keys }: { keys: string[] }) { 4 | const id = useId(); 5 | return ( 6 |
7 | {keys.map((key) => ( 8 | 12 | {key} 13 | 14 | ))} 15 |
16 | ); 17 | } 18 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ESNext", 4 | "module": "ESNext", 5 | "lib": ["ESNext", "DOM"], 6 | "moduleResolution": "Node", 7 | "strict": true, 8 | "sourceMap": true, 9 | "resolveJsonModule": true, 10 | "skipLibCheck": true, 11 | "esModuleInterop": true, 12 | "types": ["vite/client"], 13 | "noEmit": true, 14 | "noUnusedLocals": true, 15 | "noUnusedParameters": true, 16 | "noImplicitReturns": true, 17 | "jsx": "react", 18 | "baseUrl": ".", 19 | "paths": { 20 | "@/*": ["./src/*"] 21 | } 22 | }, 23 | "include": ["./src"], 24 | "exclude": ["node_modules", "dist"] 25 | } 26 | -------------------------------------------------------------------------------- /src-tauri/src/events/cmd.rs: -------------------------------------------------------------------------------- 1 | use std::process::Command; 2 | 3 | #[tauri::command] 4 | // cmd must return stdout, stderr, status 5 | pub async fn cmd(command: String, args: Vec) -> Result { 6 | println!("{} {:?}", command, args); 7 | let output = Command::new(command) 8 | .args(args) 9 | .output() 10 | .unwrap_or_else(|_| panic!("Failed to execute command")); 11 | let stdout = String::from_utf8(output.stdout).unwrap(); 12 | let stderr = String::from_utf8(output.stderr).unwrap(); 13 | let status = output.status; 14 | if status.success() { 15 | Ok(stdout) 16 | } else { 17 | Err(stderr) 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/devtools/api/app.ts: -------------------------------------------------------------------------------- 1 | import { invoke } from "@tauri-apps/api"; 2 | import { appWindow } from "@tauri-apps/api/window"; 3 | 4 | /** 5 | * Quit the app. Kill the process. 6 | */ 7 | export function quitApp() { 8 | return appWindow.close(); 9 | } 10 | /** 11 | * Hide the app. Keep the process running in background. User can open it again by pressing `Ctrl+Alt+K` 12 | */ 13 | export function hideApp() { 14 | return appWindow.minimize(); 15 | } 16 | /** 17 | * Show the app. 18 | */ 19 | export async function showApp() { 20 | await centerApp(); 21 | await invoke("show_app"); 22 | } 23 | 24 | /** 25 | * Center the app. 26 | */ 27 | export function centerApp() { 28 | return appWindow.center(); 29 | } 30 | -------------------------------------------------------------------------------- /src/extensions/todoist/const.tsx: -------------------------------------------------------------------------------- 1 | export const TODOIST_DATABASE = "todoist-db"; 2 | export const TODOIST_DATABASE_TASKS = "todoist-db-tasks"; 3 | export const TODOIST_DATABASE_GROUPING = "todoist-db-grouping"; 4 | export const TASK_STATUSES = ["TODO", "IN_PROGRESS", "DONE"]; 5 | export const TASK_VISUAL_STATUSES = { 6 | TODO: "⌛ todo", 7 | IN_PROGRESS: "🟡 in progress", 8 | DONE: "🟢 done", 9 | }; 10 | export const TASK_VISUAL_STATUSES_ICONS = { 11 | TODO: "⌛", 12 | IN_PROGRESS: "🟡", 13 | DONE: "🟢", 14 | }; 15 | export const PRIORITIES = ["LOW", "MEDIUM", "HIGH"]; 16 | export const PRIORITY_VISUAL: Record = { 17 | LOW: "🏖️ Low", 18 | MEDIUM: "🚧 Medium", 19 | HIGH: "🚨 High", 20 | }; 21 | -------------------------------------------------------------------------------- /src/devtools/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "esModuleInterop": true, 4 | "strict": true, 5 | "skipLibCheck": true, 6 | "jsx": "preserve", 7 | "module": "ESNext", 8 | "declaration": true, 9 | "sourceMap": true, 10 | "target": "ESNext", 11 | "outDir": "dist", 12 | "moduleResolution": "node", 13 | "emitDeclarationOnly": true, 14 | "allowSyntheticDefaultImports": true, 15 | "forceConsistentCasingInFileNames": true, 16 | "experimentalDecorators": true, 17 | "declarationDir": "dist" 18 | }, 19 | "include": ["./index.ts"], 20 | "exclude": [ 21 | "dist", 22 | "node_modules", 23 | "src/**/*.test.tsx", 24 | "src/**/*.stories.tsx" 25 | ] 26 | } 27 | -------------------------------------------------------------------------------- /src/devtools/hooks/router.ts: -------------------------------------------------------------------------------- 1 | import { useLocation, useNavigate } from "react-router"; 2 | 3 | export function useRouter() { 4 | const navigate = useNavigate(); 5 | const location = useLocation(); 6 | function goBack() { 7 | return navigate(-1); 8 | } 9 | function goForward() { 10 | return navigate(1); 11 | } 12 | function goTo(path: string) { 13 | if (location.pathname === path) return; 14 | return navigate(path); 15 | } 16 | function goToHome() { 17 | return navigate("/"); 18 | } 19 | function reload() { 20 | return window.location.reload(); 21 | } 22 | 23 | return { 24 | goBack, 25 | goForward, 26 | goTo, 27 | goToHome, 28 | location, 29 | reload, 30 | }; 31 | } 32 | -------------------------------------------------------------------------------- /src/devtools/components/skeletons.tsx: -------------------------------------------------------------------------------- 1 | import clsx from "clsx"; 2 | import React from "react"; 3 | 4 | export function Skeleton({ 5 | className, 6 | ...rest 7 | }: { className?: string } & React.HTMLAttributes) { 8 | return ( 9 |
16 | ); 17 | } 18 | export function ListSkeleton() { 19 | return ( 20 |
21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | ); 30 | } 31 | -------------------------------------------------------------------------------- /src/types/typings.d.ts: -------------------------------------------------------------------------------- 1 | import { 2 | ExtensionContextMenuItems, 3 | ExtensionItems, 4 | ExtensionMetadata, 5 | ExtensionNoResultItems, 6 | ExtensionPages, 7 | } from "../devtools/types"; 8 | import sittlyDevtools from "../devtools"; 9 | import { SystemApp } from "@/devtools/types/models"; 10 | 11 | declare global { 12 | interface Window { 13 | __SITTLY_EXTENSIONS__: { 14 | pages?: ExtensionPages; 15 | items?: ExtensionItems; 16 | context?: ExtensionContextMenuItems; 17 | noResults?: ExtensionNoResultItems; 18 | metadata: ExtensionMetadata; 19 | }[]; 20 | extensionsLoaded: Promise; 21 | React: any; 22 | SittlyDevtools: typeof sittlyDevtools; 23 | systemApps: SystemApp[]; 24 | } 25 | } 26 | 27 | export {}; 28 | -------------------------------------------------------------------------------- /src/devtools/components/fieldset.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { cn } from "../lib/utils"; 3 | 4 | const Fieldset = { 5 | Label: ( 6 | props: { children: React.ReactNode } & React.HTMLProps 7 | ) => ( 8 |