Added deeplinks, added qr code login, added settings, other stuff
This commit is contained in:
parent
462fc19591
commit
8ff8bd9528
32 changed files with 917 additions and 78 deletions
|
|
@ -10,6 +10,7 @@ import { useTTP } from "@tensamin/ttp/context";
|
|||
import { useCrypto } from "@tensamin/crypto/context";
|
||||
import { log, toast } from "@tensamin/shared/log";
|
||||
import Message from "./message";
|
||||
import { cn, useIsMobile } from "@tensamin/ui/utils";
|
||||
|
||||
export default function InputComponent({
|
||||
value,
|
||||
|
|
@ -27,7 +28,7 @@ export default function InputComponent({
|
|||
const { load } = useStorage();
|
||||
|
||||
React.useEffect(() => {
|
||||
void load("chat_invert_enter_behaviour").then((shouldInvert) => {
|
||||
void load("settings.reverse_enter_behavior").then((shouldInvert) => {
|
||||
setInvertEnterBehavior(shouldInvert);
|
||||
});
|
||||
}, [load]);
|
||||
|
|
@ -100,8 +101,17 @@ export default function InputComponent({
|
|||
setValue("");
|
||||
}
|
||||
|
||||
const isMobile = useIsMobile();
|
||||
|
||||
return (
|
||||
<Card className="rounded-none rounded-t-xl border-b-0 pt-0 pb-[env(safe-area-inset-bottom)]">
|
||||
<Card
|
||||
className={cn(
|
||||
"rounded-none border-b-0 pt-0 pb-[env(safe-area-inset-bottom)]",
|
||||
isMobile
|
||||
? "border-0 border-t-1 fixed w-full bottom-0 left-0 px-2"
|
||||
: "rounded-t-xl",
|
||||
)}
|
||||
>
|
||||
<CardHeader className="relative p-0 flex flex-col">
|
||||
<div
|
||||
aria-hidden="true"
|
||||
|
|
|
|||
|
|
@ -258,7 +258,13 @@ export default function Screen() {
|
|||
})}
|
||||
</div>
|
||||
</div>
|
||||
<div ref={inputBoxRef}>
|
||||
<div
|
||||
ref={inputBoxRef}
|
||||
className="fixed -bottom-15 pb-15"
|
||||
style={{
|
||||
width: "calc(100vw - 277px)",
|
||||
}}
|
||||
>
|
||||
<InputComponent setValue={setValue} value={value} />
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
"exports": {
|
||||
"./data": "./src/data.ts",
|
||||
"./log": "./src/log.tsx",
|
||||
"./settings": "./src/settings.ts",
|
||||
"./features/legal/schema": "./src/features/legal/schema.ts",
|
||||
"./features/conversation/schema": "./src/features/conversation/schema.ts"
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import { z } from "zod";
|
||||
|
||||
import { legalDocsSchema } from "./features/legal/schema";
|
||||
import { settingsStorageDefaults, type SettingsStorageDefaults } from "./settings";
|
||||
|
||||
const fileFromMessage = z.object({
|
||||
name: z.string(),
|
||||
|
|
@ -168,7 +169,7 @@ export const ttp = {
|
|||
export type TTP = typeof ttp;
|
||||
|
||||
// Storage
|
||||
export interface Storage {
|
||||
export interface Storage extends SettingsStorageDefaults {
|
||||
session_id: number;
|
||||
user_id: number;
|
||||
private_key: string;
|
||||
|
|
@ -179,7 +180,6 @@ export interface Storage {
|
|||
analytics_usage_data: boolean;
|
||||
analytics_done: boolean;
|
||||
legal_docs: z.infer<typeof legalDocsSchema>;
|
||||
chat_invert_enter_behaviour: boolean;
|
||||
}
|
||||
|
||||
export const storageDefaults: Storage = {
|
||||
|
|
@ -192,6 +192,7 @@ export const storageDefaults: Storage = {
|
|||
analytics_crash_reports: true,
|
||||
analytics_usage_data: true,
|
||||
analytics_done: false,
|
||||
...settingsStorageDefaults,
|
||||
legal_docs: {
|
||||
eula: {
|
||||
version: "0.0",
|
||||
|
|
@ -209,5 +210,4 @@ export const storageDefaults: Storage = {
|
|||
unix: 0,
|
||||
},
|
||||
},
|
||||
chat_invert_enter_behaviour: false,
|
||||
};
|
||||
|
|
|
|||
76
packages/shared/src/settings.ts
Normal file
76
packages/shared/src/settings.ts
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
type StringKeyOf<T> = Extract<keyof T, string>;
|
||||
|
||||
type SettingDefinition = {
|
||||
display: string;
|
||||
type: string;
|
||||
default?: unknown;
|
||||
};
|
||||
|
||||
export type SettingsSchema = Record<
|
||||
string,
|
||||
Record<string, Record<string, SettingDefinition>>
|
||||
>;
|
||||
|
||||
const settings = {
|
||||
account: {
|
||||
security: {
|
||||
login_qr_code: {
|
||||
display: "Login QR Code",
|
||||
type: "custom",
|
||||
},
|
||||
},
|
||||
},
|
||||
accessability: {
|
||||
chat: {
|
||||
reverse_enter_behavior: {
|
||||
display: "Reverse Enter Behavior",
|
||||
type: "boolean",
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
} as const satisfies SettingsSchema;
|
||||
|
||||
export default settings;
|
||||
|
||||
type BooleanSettingNames<T extends SettingsSchema> = {
|
||||
[C in StringKeyOf<T>]: {
|
||||
[P in StringKeyOf<T[C]>]: {
|
||||
[S in StringKeyOf<T[C][P]>]: T[C][P][S] extends {
|
||||
type: "boolean";
|
||||
default: boolean;
|
||||
}
|
||||
? S
|
||||
: never;
|
||||
}[StringKeyOf<T[C][P]>];
|
||||
}[StringKeyOf<T[C]>];
|
||||
}[StringKeyOf<T>];
|
||||
|
||||
export type SettingsStorageKey<T extends SettingsSchema = typeof settings> =
|
||||
`settings.${BooleanSettingNames<T>}`;
|
||||
|
||||
export type SettingsStorageDefaults<T extends SettingsSchema = typeof settings> =
|
||||
{
|
||||
[K in SettingsStorageKey<T>]: boolean;
|
||||
};
|
||||
|
||||
function buildSettingsStorageDefaults<T extends SettingsSchema>(
|
||||
schema: T,
|
||||
): SettingsStorageDefaults<T> {
|
||||
const defaults: Partial<SettingsStorageDefaults<T>> = {};
|
||||
|
||||
for (const category of Object.values(schema)) {
|
||||
for (const page of Object.values(category)) {
|
||||
for (const [settingName, setting] of Object.entries(page)) {
|
||||
if (setting.type === "boolean" && typeof setting.default === "boolean") {
|
||||
const key = `settings.${settingName}` as SettingsStorageKey<T>;
|
||||
defaults[key] = setting.default;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return defaults as SettingsStorageDefaults<T>;
|
||||
}
|
||||
|
||||
export const settingsStorageDefaults = buildSettingsStorageDefaults(settings);
|
||||
|
|
@ -11,12 +11,12 @@
|
|||
"./utils": "./src/lib/utils.ts"
|
||||
},
|
||||
"scripts": {
|
||||
"patch": "find src -type f \\( -name \"*.ts\" -o -name \"*.tsx\" \\) -print0 | xargs -0 sed -i 's|@/lib/utils|../lib/utils|g; s|@/cmp/|./|g' && bunx prettier --write .",
|
||||
"format": "bunx prettier --write .",
|
||||
"lint": "eslint src",
|
||||
"build": "tsc -p tsconfig.json --noEmit"
|
||||
},
|
||||
"dependencies": {
|
||||
"@tauri-apps/api": "^2",
|
||||
"@tensamin/tauri": "workspace:*",
|
||||
"@base-ui/react": "^1.3.0",
|
||||
"class-variance-authority": "^0.7.1",
|
||||
|
|
|
|||
30
packages/ui/src/cmp/switch.tsx
Normal file
30
packages/ui/src/cmp/switch.tsx
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
import { Switch as SwitchPrimitive } from "@base-ui/react/switch"
|
||||
|
||||
import { cn } from "../lib/utils"
|
||||
|
||||
function Switch({
|
||||
className,
|
||||
size = "default",
|
||||
...props
|
||||
}: SwitchPrimitive.Root.Props & {
|
||||
size?: "sm" | "default"
|
||||
}) {
|
||||
return (
|
||||
<SwitchPrimitive.Root
|
||||
data-slot="switch"
|
||||
data-size={size}
|
||||
className={cn(
|
||||
"peer group/switch relative inline-flex shrink-0 items-center rounded-full border border-transparent transition-all outline-none after:absolute after:-inset-x-3 after:-inset-y-2 focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 data-[size=default]:h-[18.4px] data-[size=default]:w-[32px] data-[size=sm]:h-[14px] data-[size=sm]:w-[24px] dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 data-checked:bg-primary data-unchecked:bg-input dark:data-unchecked:bg-input/80 data-disabled:cursor-not-allowed data-disabled:opacity-50",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
<SwitchPrimitive.Thumb
|
||||
data-slot="switch-thumb"
|
||||
className="pointer-events-none block rounded-full bg-background ring-0 transition-transform group-data-[size=default]/switch:size-4 group-data-[size=sm]/switch:size-3 group-data-[size=default]/switch:data-checked:translate-x-[calc(100%-2px)] group-data-[size=sm]/switch:data-checked:translate-x-[calc(100%-2px)] dark:data-checked:bg-primary-foreground group-data-[size=default]/switch:data-unchecked:translate-x-0 group-data-[size=sm]/switch:data-unchecked:translate-x-0 dark:data-unchecked:bg-foreground"
|
||||
/>
|
||||
</SwitchPrimitive.Root>
|
||||
)
|
||||
}
|
||||
|
||||
export { Switch }
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
import { cn } from "../lib/utils";
|
||||
import Controls from "@tensamin/tauri/controls";
|
||||
import { isTauri } from "@tauri-apps/api/core";
|
||||
|
||||
export default function CreateScreen({
|
||||
children,
|
||||
|
|
@ -41,7 +42,13 @@ import { useIsMobile } from "../lib/utils";
|
|||
export function StorageDestoryer() {
|
||||
const isMobile = useIsMobile();
|
||||
return (
|
||||
<div className={cn("fixed p-5 bottom-0", isMobile ? "w-full" : "right-0")}>
|
||||
<div
|
||||
className={cn(
|
||||
"fixed p-5 bottom-0",
|
||||
isMobile ? "w-full" : "right-0",
|
||||
isTauri() ? "py-10" : "",
|
||||
)}
|
||||
>
|
||||
<AlertDialog>
|
||||
<AlertDialogTrigger
|
||||
render={
|
||||
|
|
|
|||
Loading…
Reference in a new issue