Skip to content

Commit

Permalink
Merge pull request #20 from ilittlebig/develop
Browse files Browse the repository at this point in the history
Add settings for the integration functionality
  • Loading branch information
ilittlebig authored Nov 29, 2024
2 parents 94d14d5 + fdd17b1 commit f3bf279
Show file tree
Hide file tree
Showing 51 changed files with 959 additions and 43 deletions.
10 changes: 10 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
"@ilittlebig/easy-auth": "^0.0.9",
"@tauri-apps/api": "^2",
"@tauri-apps/plugin-dialog": "^2.0.1",
"@tauri-apps/plugin-fs": "^2.0.2",
"@tauri-apps/plugin-process": "^2.0.0",
"@tauri-apps/plugin-shell": "^2",
"@tauri-apps/plugin-updater": "^2.0.0",
Expand Down
3 changes: 2 additions & 1 deletion src-tauri/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion src-tauri/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "Jaafar"
version = "0.0.4"
version = "0.0.5"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
Expand All @@ -20,6 +20,7 @@ serde_json = "1"
rand = "0.8.5"
tauri-plugin-dialog = "2"
tauri-plugin-process = "2"
tauri-plugin-fs = "2"

[target.'cfg(target_os = "macos")'.dependencies]
cocoa = "0.25.0"
Expand Down
7 changes: 5 additions & 2 deletions src-tauri/capabilities/default.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@
"core:window:default",
"core:window:allow-start-dragging",
"dialog:default",
"process:default"
"process:default",
"fs:default",
"fs:allow-appdata-write",
"fs:allow-appdata-read"
]
}
}
1 change: 1 addition & 0 deletions src-tauri/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ use plugins::tauri_traffic_light_positioner_plugin;
#[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run() {
tauri::Builder::default()
.plugin(tauri_plugin_fs::init())
.plugin(tauri_plugin_process::init())
.plugin(tauri_plugin_dialog::init())
.plugin(tauri_plugin_updater::Builder::new().build())
Expand Down
2 changes: 1 addition & 1 deletion src-tauri/tauri.conf.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"$schema": "https://schema.tauri.app/config/2",
"identifier": "com.jaafar.app",
"identifier": "com.jaafar.application",
"build": {
"beforeDevCommand": "npm run dev",
"devUrl": "http://localhost:1420",
Expand Down
2 changes: 1 addition & 1 deletion src/lib/components/dialogs/auth/sign-out-dialog.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
<Dialog.Root bind:open={signOutDialog.open}>
<Dialog.Content class="max-w-[425px]">
<Dialog.Header>
<Dialog.Title>Confirm Sign-Out</Dialog.Title>
<Dialog.Title>Confirm Sign Out</Dialog.Title>
<Dialog.Description>
Please confirm if you would like to sign out of your account.
</Dialog.Description>
Expand Down
110 changes: 110 additions & 0 deletions src/lib/components/dialogs/settings-dialog.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
<script module>
export let settingsDialog = $state({ open: false });
</script>

<script lang="ts">
import { onMount, onDestroy, type Component } from "svelte";
import { superForm } from "sveltekit-superforms";
import { zodClient } from "sveltekit-superforms/adapters";
import { addHotkey, removeHotkey } from "$lib/services/hotkeys-service";
import { settingsSchema } from "$lib/schemas/settings";
import { settingsLoaded, settingsStore } from "$lib/stores/settings-store.svelte";
import { loadSettings, saveSettings } from "$lib/services/settings-service.svelte";
import { Separator } from "$lib/components/ui/separator";
import { ScrollArea } from "$lib/components/ui/scroll-area";
import * as Dialog from "$lib/components/ui/dialog";
import * as Tabs from "$lib/components/ui/tabs";
import Sidebar from "$lib/components/settings/sidebar.svelte";
import AccountSettingsPage from "$lib/components/settings/account-settings-page.svelte";
import NotificationsPage from "$lib/components/settings/notifications-page.svelte";
import PrivacyPage from "$lib/components/settings/privacy-page.svelte";
import PreferencesPage from "$lib/components/settings/preferences-page.svelte";
import IntegrationPage from "$lib/components/settings/integration-page.svelte";
import SecurityPage from "$lib/components/settings/security-page.svelte";
import BillingPage from "$lib/components/settings/billing-page.svelte";
interface Page {
name: string;
label: string;
icon: string;
page: Component<any, {}, any>;
}
let currentTab: string | undefined = $state(undefined);
const form = superForm(settingsStore, {
dataType: "json",
SPA: true,
resetForm: false,
validators: zodClient(settingsSchema),
});
const {
form: formData,
enhance,
allErrors,
submit
} = form;
const pages: Page[] = [
{ name: "account-settings", label: "Account Settings", icon: "fa-user", page: AccountSettingsPage },
{ name: "notifications", label: "Notifications", icon: "fa-bell", page: NotificationsPage },
{ name: "privacy", label: "Privacy", icon: "fa-lock", page: PrivacyPage },
{ name: "preferences", label: "Preferences", icon: "fa-cog", page: PreferencesPage },
{ name: "integration", label: "Integration", icon: "fa-link", page: IntegrationPage },
{ name: "security", label: "Security", icon: "fa-shield", page: SecurityPage },
{ name: "billing", label: "Billing", icon: "fa-money-bill", page: BillingPage },
];
const onValueChange = async (value: string) => {
submit();
if ($allErrors.length > 0) return;
currentTab = value;
}
const onOpenChange = async (value: boolean) => {
submit();
if ($allErrors.length > 0) return;
settingsDialog.open = value;
await saveSettings($formData);
}
onMount(async () => {
addHotkey("meta+,", () => settingsDialog.open = true);
if (settingsLoaded.value) return;
await loadSettings();
formData.set(settingsStore);
});
onDestroy(() => removeHotkey("meta+,"));
</script>

<Dialog.Root controlledOpen bind:open={settingsDialog.open} {onOpenChange}>
<Dialog.Content class="max-w-[800px] max-h-[650px] h-full flex flex-col px-0 pt-6 pb-0 gap-0">
<Dialog.Header class="h-fit px-6">
<Dialog.Title>Settings</Dialog.Title>
<div class="-mx-6">
<Separator class="mt-4" />
</div>
</Dialog.Header>
<ScrollArea class="h-full" scrollHideDelay={0}>
<form method="POST" use:enhance>
<Tabs.Root
controlledValue
{onValueChange}
value={currentTab ?? pages[0].name}
class="flex gap-x-4 h-full pb-6 px-6 pt-4"
>
<Sidebar {pages} />
<div class="ml-52 w-full">
{#each pages as { name, page: Page }}
<Tabs.Content value={name} class="w-full">
<Page {form} {formData} />
</Tabs.Content>
{/each}
</div>
</Tabs.Root>
</form>
</ScrollArea>
</Dialog.Content>
</Dialog.Root>
8 changes: 0 additions & 8 deletions src/lib/components/header.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,4 @@
>
<i class="fa-regular fa-bell text-lg"></i>
</Button>
<Button
variant="ghost"
size="icon"
class="rounded-lg z-20"
aria-label="Help"
>
<i class="fa-regular fa-circle-question text-lg"></i>
</Button>
</header>
15 changes: 0 additions & 15 deletions src/lib/components/navbar.svelte

This file was deleted.

File renamed without changes.
3 changes: 3 additions & 0 deletions src/lib/components/settings/account-settings-page.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<div class="flex h-full">
account settings
</div>
3 changes: 3 additions & 0 deletions src/lib/components/settings/billing-page.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<div class="flex h-full">
billing
</div>
135 changes: 135 additions & 0 deletions src/lib/components/settings/integration-page.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
<script lang="ts">
import type { SuperForm } from "sveltekit-superforms";
import type { SettingsSchema } from "$lib/schemas/settings";
import { Input } from "$lib/components/ui/input";
import { Label } from "$lib/components/ui/label";
import { Separator } from "$lib/components/ui/separator";
import * as Select from "$lib/components/ui/select";
import * as Form from "$lib/components/ui/form";
interface SelectType {
value: string;
label: string;
}
interface Props {
form: SuperForm<SettingsSchema>;
formData: SvelteStore<SettingsSchema>;
}
const captchaSolvers = [
{ value: "cap-solver", label: "CapSolver" },
{ value: "anti-captcha", label: "Anti-Captcha" },
{ value: "2-captcha", label: "2Captcha" },
{ value: "death-by-captcha", label: "Death by Captcha" },
{ value: "zennolab-captcha", label: "ZennoLab Captcha" },
{ value: "image-typerz", label: "ImageTyperz" },
{ value: "az-captcha", label: "AZcaptcha" },
{ value: "best-captcha-solver", label: "Best Captcha Solver" },
{ value: "resolve-captcha", label: "ResolveCaptcha" },
{ value: "captcha-solutions", label: "CaptchaSolutions" },
];
let { form, formData }: Props = $props();
const selectedCaptcha = $derived(
$formData.integration.captcha_solver
? captchaSolvers.find((captcha: SelectType) => captcha.value === $formData.integration.captcha_solver)?.label
: "Select a captcha solver"
);
</script>

<div class="flex flex-col gap-y-6 h-full">
<Form.Field name="integration.captcha_solver" {form}>
<Form.Control>
{#snippet children({ props })}
<div class="flex w-full flex-col gap-1.5">
<Form.Label>Captcha Solver</Form.Label>
<Select.Root type="single" bind:value={$formData.integration.captcha_solver}>
<Select.Trigger {...props}>{selectedCaptcha}</Select.Trigger>
<Select.Content>
{#each captchaSolvers as captchaSolver}
<Select.Item value={captchaSolver.value}>{captchaSolver.label}</Select.Item>
{/each}
</Select.Content>
</Select.Root>
<p class="text-muted-foreground text-sm">Required for solving captchas on supported websites.</p>
</div>
{/snippet}
</Form.Control>
<Form.FieldErrors />
</Form.Field>
{#if !!$formData.integration.captcha_solver}
<Form.Field name="integration.captcha_solver_api_key" {form}>
<Form.Control>
{#snippet children({ props })}
<div class="flex w-full flex-col gap-1.5">
<Form.Label>Captcha API Key</Form.Label>
<Input {...props} bind:value={$formData.integration.captcha_solver_api_key} />
</div>
{/snippet}
</Form.Control>
<Form.FieldErrors />
</Form.Field>
{/if}
<Separator />
<Form.Field name="integration.request_delay" {form}>
<Form.Control>
{#snippet children({ props })}
<div class="flex w-full flex-col gap-1.5">
<Form.Label>Request Delay</Form.Label>
<Input {...props} placeholder="3000" bind:value={$formData.integration.request_delay} />
<p class="text-muted-foreground text-sm">Configure the delay (in milliseconds) between automated actions.</p>
</div>
{/snippet}
</Form.Control>
<Form.FieldErrors />
</Form.Field>
<Form.Field name="integration.entry_limit" {form}>
<Form.Control>
{#snippet children({ props })}
<div class="flex w-full flex-col gap-1.5">
<Form.Label>Entry Limit</Form.Label>
<Input {...props} placeholder="10" bind:value={$formData.integration.entry_limit} />
<p class="text-muted-foreground text-sm">Sets the maximum number of entries/tasks to process per request.</p>
</div>
{/snippet}
</Form.Control>
<Form.FieldErrors />
</Form.Field>
<Separator />
<Form.Field name="integration.imap_email" {form}>
<Form.Control>
{#snippet children({ props })}
<div class="flex w-full flex-col gap-1.5">
<Form.Label>IMAP Email</Form.Label>
<Input {...props} type="email" bind:value={$formData.integration.imap_email} />
</div>
{/snippet}
</Form.Control>
<Form.FieldErrors />
</Form.Field>
<Form.Field name="integration.imap_password" {form}>
<Form.Control>
{#snippet children({ props })}
<div class="flex w-full flex-col gap-1.5">
<Form.Label>IMAP Password</Form.Label>
<Input {...props} type="password" bind:value={$formData.integration.imap_password} />
</div>
{/snippet}
</Form.Control>
<Form.FieldErrors />
</Form.Field>
<Separator />
<Form.Field name="integration.webhook" {form}>
<Form.Control>
{#snippet children({ props })}
<div class="flex w-full flex-col gap-1.5">
<Form.Label>Webhook</Form.Label>
<Input {...props} bind:value={$formData.integration.webhook} />
<p class="text-muted-foreground text-sm">Configure a URL for handling webhook events.</p>
</div>
{/snippet}
</Form.Control>
<Form.FieldErrors />
</Form.Field>
</div>
3 changes: 3 additions & 0 deletions src/lib/components/settings/notifications-page.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<div class="flex h-full">
notifications
</div>
3 changes: 3 additions & 0 deletions src/lib/components/settings/preferences-page.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<div class="flex h-full">
preferences
</div>
3 changes: 3 additions & 0 deletions src/lib/components/settings/privacy-page.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<div class="flex h-full">
privacy
</div>
Loading

0 comments on commit f3bf279

Please sign in to comment.