feat: add window controls & screen creation util
This commit is contained in:
parent
96c43fba05
commit
a4822948d1
20 changed files with 149 additions and 61 deletions
|
|
@ -4,24 +4,25 @@
|
|||
"version": "0.0.0",
|
||||
"type": "module",
|
||||
"exports": {
|
||||
"./context": "./src/context.tsx"
|
||||
"./context": "./src/context.tsx",
|
||||
"./controls": "./src/windowControls.tsx"
|
||||
},
|
||||
"scripts": {
|
||||
"dev:mobile:raw": "tauri android dev",
|
||||
"build:mobile:raw": "tauri android build",
|
||||
"dev:mobile": "if command -v nix >/dev/null 2>&1; then nix develop --command bun dev:mobile:raw; else bun dev:mobile:raw; fi",
|
||||
"build:mobile": "if command -v nix >/dev/null 2>&1; then nix develop --command bun build:mobile:raw; else bun build:mobile:raw; fi",
|
||||
|
||||
"dev:desktop:raw": "tauri dev",
|
||||
"build:desktop:raw": "tauri build",
|
||||
"dev:desktop": "if command -v nix >/dev/null 2>&1; then nix develop --command bun dev:desktop:raw; else bun dev:desktop:raw; fi",
|
||||
"build:desktop": "if command -v nix >/dev/null 2>&1; then nix develop --command bun build:desktop:raw; else bun build:desktop:raw; fi",
|
||||
|
||||
"gen-icons": "tauri icon ./logo.png"
|
||||
},
|
||||
"dependencies": {
|
||||
"@tauri-apps/api": "^2",
|
||||
"@tauri-apps/plugin-opener": "^2",
|
||||
"@tensamin/ui": "workspace:*",
|
||||
"lucide-react": "^1.7.0",
|
||||
"react": "^19.2.0",
|
||||
"react-dom": "^19.2.0"
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
# Outputs
|
||||
|
||||
- ./src-tauri/gen/android/app/build/outputs/apk/universal/release/app-universal-release.apk
|
||||
- ./src-tauri/target/release/bundle/deb/Tensamin_{version}_{arch}.deb
|
||||
- ./src-tauri/target/release/bundle/deb/Tensamin*{version}*{arch}.deb
|
||||
- ./src-tauri/target/release/bundle/rpm/Tensamin-{version}-1.{arch}.rpm
|
||||
|
|
|
|||
|
|
@ -2,6 +2,16 @@
|
|||
"$schema": "../gen/schemas/desktop-schema.json",
|
||||
"identifier": "default",
|
||||
"description": "Capability for the main window",
|
||||
"windows": ["main"],
|
||||
"permissions": ["core:default", "opener:default"]
|
||||
}
|
||||
"windows": [
|
||||
"main"
|
||||
],
|
||||
"permissions": [
|
||||
"core:default",
|
||||
"opener:default",
|
||||
"core:window:default",
|
||||
"core:window:allow-start-dragging",
|
||||
"core:window:allow-close",
|
||||
"core:window:allow-toggle-maximize",
|
||||
"core:window:allow-minimize"
|
||||
]
|
||||
}
|
||||
53
apps/tauri/src/windowControls.tsx
Normal file
53
apps/tauri/src/windowControls.tsx
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
import { Maximize, Minus, X } from "lucide-react";
|
||||
import { Button, buttonVariants } from "@tensamin/ui/cmp/button";
|
||||
|
||||
import { isTauri } from "@tauri-apps/api/core";
|
||||
import { getCurrentWindow } from "@tauri-apps/api/window";
|
||||
import { cn, useIsMobile } from "@tensamin/ui/utils";
|
||||
import { Card } from "@tensamin/ui/cmp/card";
|
||||
|
||||
export default function Controls({
|
||||
className,
|
||||
notPresentClassName,
|
||||
}: {
|
||||
className?: string;
|
||||
notPresentClassName?: string;
|
||||
}) {
|
||||
const isMobile = useIsMobile();
|
||||
if (!isTauri() || isMobile) return <div className={notPresentClassName} />;
|
||||
|
||||
const currentWindow = getCurrentWindow();
|
||||
|
||||
return (
|
||||
<Card
|
||||
className={cn(
|
||||
"flex flex-row py-0 px-0 p-0.5 gap-0 rounded-lg",
|
||||
className,
|
||||
)}
|
||||
>
|
||||
<>
|
||||
<Button
|
||||
variant="ghost"
|
||||
className="w-9 h-9 aspect-square rounded-lg"
|
||||
onClick={() => currentWindow.minimize()}
|
||||
>
|
||||
<Minus />
|
||||
</Button>
|
||||
<Button
|
||||
variant="ghost"
|
||||
className="w-9 h-9 aspect-square rounded-lg"
|
||||
onClick={() => currentWindow.toggleMaximize()}
|
||||
>
|
||||
<Maximize />
|
||||
</Button>
|
||||
<Button
|
||||
variant="ghost"
|
||||
className="w-9 h-9 aspect-square rounded-lg"
|
||||
onClick={() => currentWindow.close()}
|
||||
>
|
||||
<X />
|
||||
</Button>
|
||||
</>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
|
|
@ -14,6 +14,7 @@ import { displayCallId } from "@tensamin/call/utils";
|
|||
import { useState } from "react";
|
||||
import { SidebarTrigger, useSidebar } from "@tensamin/ui/cmp/sidebar";
|
||||
import { useTTP } from "@tensamin/ttp/context";
|
||||
import Controls from "@tensamin/tauri/controls";
|
||||
|
||||
export default function Navbar({ forMobile }: { forMobile: boolean }) {
|
||||
const navigate = useNavigate();
|
||||
|
|
@ -30,7 +31,8 @@ export default function Navbar({ forMobile }: { forMobile: boolean }) {
|
|||
|
||||
return (
|
||||
<div
|
||||
className={`${forMobile && "border-b"} w-full gap-2 h-13.5 flex items-center justify-center`}
|
||||
data-tauri-drag-region
|
||||
className={`${forMobile && "border-b"} w-full gap-2 h-13.5 flex items-center justify-between`}
|
||||
>
|
||||
{forMobile ? (
|
||||
<SidebarTrigger
|
||||
|
|
@ -57,7 +59,7 @@ export default function Navbar({ forMobile }: { forMobile: boolean }) {
|
|||
loading={<Skeleton className="ml-3 w-40 h-5" />}
|
||||
/>
|
||||
)}
|
||||
<div className="w-full" />
|
||||
{/* Empty space */}
|
||||
{pathname === "/chat" && id && (
|
||||
<>
|
||||
{currentCalls.length === 0 ? (
|
||||
|
|
@ -77,7 +79,7 @@ export default function Navbar({ forMobile }: { forMobile: boolean }) {
|
|||
onClick={() => {
|
||||
joinCall(id, currentCalls[0]);
|
||||
}}
|
||||
className="w-9 h-9 aspect-square rounded-lg mr-2"
|
||||
className="w-9 h-9 aspect-square rounded-lg"
|
||||
>
|
||||
<Phone />
|
||||
</Button>
|
||||
|
|
@ -85,7 +87,7 @@ export default function Navbar({ forMobile }: { forMobile: boolean }) {
|
|||
<>
|
||||
<Button
|
||||
onClick={() => setSelectOpen((prev) => !prev)}
|
||||
className="w-9! h-9! aspect-square rounded-lg mr-2"
|
||||
className="w-9! h-9! aspect-square rounded-lg"
|
||||
>
|
||||
<Phone />
|
||||
</Button>
|
||||
|
|
@ -109,6 +111,7 @@ export default function Navbar({ forMobile }: { forMobile: boolean }) {
|
|||
)}
|
||||
</>
|
||||
)}
|
||||
<Controls className="mr-2 ring-border" notPresentClassName="mr-2" />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,7 +23,9 @@ export default function Sidebar() {
|
|||
return (
|
||||
<SidebarRoot>
|
||||
<SidebarContent
|
||||
className={isTauri() && isMobile ? "pt-[env(safe-area-inset-top)]" : "pt-2"}
|
||||
className={
|
||||
isTauri() && isMobile ? "pt-[env(safe-area-inset-top)]" : "pt-2"
|
||||
}
|
||||
>
|
||||
<div className="h-full w-full flex flex-col gap-3 p-2 pt-0!">
|
||||
<div>
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import { legalDocsSchema } from "@tensamin/shared/features/legal/schema";
|
|||
import { log } from "@tensamin/shared/log";
|
||||
import Link from "@tensamin/ui/link";
|
||||
import { Label } from "@tensamin/ui/cmp/label";
|
||||
import CreateScreen from "@tensamin/ui/screens/util";
|
||||
|
||||
// Prevents the user from using Tensamin without accepting the privacy policy and terms of service.
|
||||
export default function Screen(props: { children: React.ReactNode }) {
|
||||
|
|
@ -160,7 +161,7 @@ export default function Screen(props: { children: React.ReactNode }) {
|
|||
}
|
||||
|
||||
return (
|
||||
<div className="w-full h-full flex items-center justify-center py-15">
|
||||
<CreateScreen>
|
||||
<div className="h-full flex flex-col gap-15 p-10 md:p-40 w-full lg:w-2/3">
|
||||
<h1 className="text-3xl md:text-4xl font-bold">
|
||||
Privacy Policy & ToS
|
||||
|
|
@ -198,7 +199,7 @@ export default function Screen(props: { children: React.ReactNode }) {
|
|||
onClick={handleContinueLegal}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</CreateScreen>
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -17,7 +17,6 @@ import Home from "@/routes/app/home";
|
|||
import ChatScreen from "@tensamin/chat/screen";
|
||||
import CallScreen from "@tensamin/call/screen";
|
||||
import Login from "@/routes/screens/login";
|
||||
import Signup from "@/routes/screens/signup";
|
||||
|
||||
import ChatContext from "@tensamin/chat/context";
|
||||
import CallContext from "@tensamin/call/context";
|
||||
|
|
@ -117,16 +116,9 @@ const loginRoute = createRoute({
|
|||
component: Login,
|
||||
});
|
||||
|
||||
const signupRoute = createRoute({
|
||||
getParentRoute: () => rootRoute,
|
||||
path: "signup",
|
||||
component: Signup,
|
||||
});
|
||||
|
||||
const routeTree = rootRoute.addChildren([
|
||||
appRoute.addChildren([homeRoute, chatRoute, callRoute]),
|
||||
loginRoute,
|
||||
signupRoute,
|
||||
]);
|
||||
|
||||
const router = createRouter({
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import Form from "@/components/screens/login/form";
|
||||
import CreateScreen from "@tensamin/ui/screens/util";
|
||||
|
||||
/**
|
||||
* Executes Page.
|
||||
|
|
@ -7,7 +8,7 @@ import Form from "@/components/screens/login/form";
|
|||
*/
|
||||
export default function Page() {
|
||||
return (
|
||||
<div className="w-full h-full flex flex-col gap-10 items-center justify-center">
|
||||
<CreateScreen>
|
||||
<Form />
|
||||
<div className="flex">
|
||||
<a target="_blank" href="https://docs.tensamin.net/installation/#iota">
|
||||
|
|
@ -17,6 +18,6 @@ export default function Page() {
|
|||
</p>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</CreateScreen>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +0,0 @@
|
|||
/**
|
||||
* Executes Page.
|
||||
* @param none This function has no parameters.
|
||||
* @returns unknown.
|
||||
*/
|
||||
export default function Page() {
|
||||
return <div>Signup Page</div>;
|
||||
}
|
||||
Loading…
Reference in a new issue