mirror of
https://github.com/infinilabs/coco-app.git
synced 2025-12-16 11:37:47 +01:00
feat: adjust oauth callback & profile info (#110)
* chore: adjust oauth callback * chore: debug profile info * chore: modify logs logic and display * chore: add logout * chore: add userinfo * chore: remove advanced settings
This commit is contained in:
4
.env
4
.env
@@ -1,3 +1,3 @@
|
|||||||
COCO_SERVER_URL=https://infini.tpddns.cn:27200 #https://coco.infini.cloud # http://localhost:2900
|
COCO_SERVER_URL=http://infini.tpddns.cn:27200 #https://coco.infini.cloud # http://localhost:9000
|
||||||
|
|
||||||
COCO_WEBSOCKET_URL=wss://infini.tpddns.cn:27200/ws #wss://coco.infini.cloud/ws # ws://localhost:2900/ws
|
COCO_WEBSOCKET_URL=ws://infini.tpddns.cn:27200/ws #wss://coco.infini.cloud/ws # ws://localhost:9000/ws
|
||||||
@@ -52,9 +52,6 @@
|
|||||||
{
|
{
|
||||||
"identifier": "http:default",
|
"identifier": "http:default",
|
||||||
"allow": [
|
"allow": [
|
||||||
{
|
|
||||||
"url": "http://localhost:2900"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"url": "http://localhost:9000"
|
"url": "http://localhost:9000"
|
||||||
},
|
},
|
||||||
@@ -62,7 +59,7 @@
|
|||||||
"url": "https://coco.infini.cloud"
|
"url": "https://coco.infini.cloud"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"url": "https://infini.tpddns.cn:27200"
|
"url": "http://infini.tpddns.cn:27200"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"deny": []
|
"deny": []
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ export const tauriFetch = async <T = any>({
|
|||||||
headers["Content-Type"] = "application/json";
|
headers["Content-Type"] = "application/json";
|
||||||
}
|
}
|
||||||
|
|
||||||
headers["X-API-TOKEN"] = auth?.token || "";
|
headers["X-API-TOKEN"] = headers["X-API-TOKEN"] || auth?.token || "";
|
||||||
|
|
||||||
// debug API
|
// debug API
|
||||||
const requestInfo = {
|
const requestInfo = {
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 753 B |
Binary file not shown.
|
Before Width: | Height: | Size: 1.0 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 621 B |
Binary file not shown.
|
Before Width: | Height: | Size: 710 B |
Binary file not shown.
|
Before Width: | Height: | Size: 439 B |
@@ -1,5 +1,5 @@
|
|||||||
import React, { useState, useEffect, useCallback } from "react";
|
import React, { useState, useEffect, useCallback } from "react";
|
||||||
import { X } from "lucide-react";
|
import { Maximize, X } from "lucide-react";
|
||||||
|
|
||||||
import { useLogStore } from "@/stores/logStore";
|
import { useLogStore } from "@/stores/logStore";
|
||||||
|
|
||||||
@@ -7,11 +7,17 @@ const ApiDetails: React.FC = () => {
|
|||||||
const logs = useLogStore((state) => state.logs);
|
const logs = useLogStore((state) => state.logs);
|
||||||
|
|
||||||
const [showAPIDetails, setShowAPIDetails] = useState(false);
|
const [showAPIDetails, setShowAPIDetails] = useState(false);
|
||||||
|
const [showFullscreen, setShowFullscreen] = useState(false);
|
||||||
|
const [showIndex, setShowIndex] = useState<number | null>(null);
|
||||||
|
|
||||||
const toggleAPIDetails = useCallback(() => {
|
const toggleAPIDetails = useCallback(() => {
|
||||||
setShowAPIDetails((prev) => !prev);
|
setShowAPIDetails((prev) => !prev);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
const toggleFullscreen = useCallback(() => {
|
||||||
|
setShowFullscreen((prev) => !prev);
|
||||||
|
}, []);
|
||||||
|
|
||||||
const handleKeyDown = useCallback(
|
const handleKeyDown = useCallback(
|
||||||
(event: KeyboardEvent) => {
|
(event: KeyboardEvent) => {
|
||||||
if (event.metaKey && event.key === "d") {
|
if (event.metaKey && event.key === "d") {
|
||||||
@@ -38,15 +44,18 @@ const ApiDetails: React.FC = () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={`fixed bottom-0 z-[2000] overflow-y-auto overflow-x-hidden transition-all duration-300 ease-in-out ${
|
className={`fixed bottom-0 z-[2000] overflow-y-auto overflow-x-hidden transition-all duration-300 ease-in-out border-t ${
|
||||||
showAPIDetails ? "h-[60vh] w-full bg-white shadow-lg rounded-t-lg" : ""
|
showAPIDetails ? "h-[60vh] w-full bg-white shadow-lg rounded-t-lg" : ""
|
||||||
}`}
|
} ${showFullscreen ? "h-[100vh]" : "h-[60vh]"}`}
|
||||||
>
|
>
|
||||||
{showAPIDetails && (
|
{showAPIDetails && (
|
||||||
<div className="p-6">
|
<div className="p-6">
|
||||||
<h3 className="text-lg font-bold text-gray-800 border-b pb-2 cursor-pointer flex justify-between" onClick={toggleAPIDetails}>
|
<h3 className="text-lg font-bold text-gray-800 border-b pb-2 cursor-pointer flex justify-between">
|
||||||
API Logs (Latest 10)
|
API Logs (Latest 10)
|
||||||
<X />
|
<div className="flex gap-4">
|
||||||
|
<Maximize onClick={toggleFullscreen} />
|
||||||
|
<X onClick={toggleAPIDetails} />
|
||||||
|
</div>
|
||||||
</h3>
|
</h3>
|
||||||
<div className="space-y-4 mt-4 ">
|
<div className="space-y-4 mt-4 ">
|
||||||
{logs.map((log, index) => (
|
{logs.map((log, index) => (
|
||||||
@@ -55,7 +64,7 @@ const ApiDetails: React.FC = () => {
|
|||||||
className="p-4 border rounded-md shadow-sm bg-gray-50"
|
className="p-4 border rounded-md shadow-sm bg-gray-50"
|
||||||
>
|
>
|
||||||
<h4 className="font-semibold text-gray-800">
|
<h4 className="font-semibold text-gray-800">
|
||||||
Request {index + 1}:
|
Latest Request {index + 1}:
|
||||||
</h4>
|
</h4>
|
||||||
<div className="text-sm text-gray-700 mt-1">
|
<div className="text-sm text-gray-700 mt-1">
|
||||||
<pre className="bg-gray-100 p-2 rounded-md whitespace-pre-wrap">
|
<pre className="bg-gray-100 p-2 rounded-md whitespace-pre-wrap">
|
||||||
@@ -65,13 +74,23 @@ const ApiDetails: React.FC = () => {
|
|||||||
{log.response && (
|
{log.response && (
|
||||||
<>
|
<>
|
||||||
<h4 className="font-semibold text-green-800 mt-4">
|
<h4 className="font-semibold text-green-800 mt-4">
|
||||||
Response:
|
Response:{" "}
|
||||||
|
<button
|
||||||
|
onClick={() =>
|
||||||
|
setShowIndex(showIndex === index ? null : index)
|
||||||
|
}
|
||||||
|
className="text-sm text-blue-600 mt-2 underline"
|
||||||
|
>
|
||||||
|
{showIndex === index ? "Collapse" : "Expand"}
|
||||||
|
</button>
|
||||||
</h4>
|
</h4>
|
||||||
<div className="text-sm text-gray-700 mt-1">
|
{showIndex === index ? (
|
||||||
<pre className="bg-green-100 p-2 rounded-md text-green-700 whitespace-pre-wrap">
|
<div className="text-sm text-gray-700 mt-1">
|
||||||
{JSON.stringify(log.response, null, 2)}
|
<pre className="bg-green-100 p-2 rounded-md text-green-700 whitespace-pre-wrap">
|
||||||
</pre>
|
{JSON.stringify(log.response, null, 2)}
|
||||||
</div>
|
</pre>
|
||||||
|
</div>
|
||||||
|
) : null}
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
{log.error && (
|
{log.error && (
|
||||||
|
|||||||
@@ -17,12 +17,7 @@ import {
|
|||||||
} from "@tauri-apps/plugin-deep-link";
|
} from "@tauri-apps/plugin-deep-link";
|
||||||
|
|
||||||
export default function CocoCloud() {
|
export default function CocoCloud() {
|
||||||
const appStore = useAppStore();
|
|
||||||
|
|
||||||
const [lastUrl, setLastUrl] = useState<string | null>(null);
|
|
||||||
const [error, setError] = useState<string | null>(null);
|
const [error, setError] = useState<string | null>(null);
|
||||||
const [info, setInfo] = useState<string | null>(null);
|
|
||||||
const [info2, setInfo2] = useState<string | null>(null);
|
|
||||||
|
|
||||||
const [isConnect] = useState(true);
|
const [isConnect] = useState(true);
|
||||||
|
|
||||||
@@ -31,19 +26,19 @@ export default function CocoCloud() {
|
|||||||
const endpoint_http = useAppStore((state) => state.endpoint_http);
|
const endpoint_http = useAppStore((state) => state.endpoint_http);
|
||||||
|
|
||||||
const { auth, setAuth } = useAuthStore();
|
const { auth, setAuth } = useAuthStore();
|
||||||
|
const userInfo = useAuthStore((state) => state.userInfo);
|
||||||
|
const setUserInfo = useAuthStore((state) => state.setUserInfo);
|
||||||
|
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
|
|
||||||
const getProfile = async () => {
|
const getProfile = async () => {
|
||||||
const response: any = await tauriFetch({
|
const response: any = await tauriFetch({
|
||||||
url: `/profile`,
|
url: `/provider/account/profile`,
|
||||||
method: "GET",
|
method: "GET",
|
||||||
baseURL: appStore.endpoint_http,
|
|
||||||
});
|
});
|
||||||
console.log("getProfile", response);
|
console.log("getProfile", response);
|
||||||
|
setUserInfo(response.data || {});
|
||||||
setInfo2(JSON.stringify(response))
|
};
|
||||||
}
|
|
||||||
|
|
||||||
const handleOAuthCallback = async (
|
const handleOAuthCallback = async (
|
||||||
code: string | null,
|
code: string | null,
|
||||||
@@ -54,37 +49,40 @@ export default function CocoCloud() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// mock
|
|
||||||
// code = "d11feeab43f6c3e48a43"
|
|
||||||
// provider = "coco-cloud"
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
console.log("Handling OAuth callback:", { code, provider });
|
console.log("Handling OAuth callback:", { code, provider });
|
||||||
const response: any = await tauriFetch({
|
const response: any = await tauriFetch({
|
||||||
url: `/auth/request_access_token?request_id=${app_uid}`,
|
url: `/auth/request_access_token?request_id=${app_uid}`,
|
||||||
method: "GET",
|
method: "GET",
|
||||||
baseURL: appStore.endpoint_http,
|
|
||||||
headers: {
|
headers: {
|
||||||
"X-API-TOKEN": code,
|
"X-API-TOKEN": code,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
// { "access_token":xxx, "expire_at": "unix_timestamp_in_s" }
|
console.log(
|
||||||
console.log("response", response);
|
"response",
|
||||||
setInfo(JSON.stringify(response))
|
`/auth/request_access_token?request_id=${app_uid}`,
|
||||||
|
code,
|
||||||
|
response
|
||||||
|
);
|
||||||
|
|
||||||
getProfile()
|
if (response.data?.access_token) {
|
||||||
|
await setAuth({
|
||||||
|
token: response.data?.access_token,
|
||||||
|
expires: response.data?.expire_at,
|
||||||
|
plan: { upgraded: false, last_checked: 0 },
|
||||||
|
});
|
||||||
|
|
||||||
await setAuth({
|
getProfile();
|
||||||
token: response.data?.access_token,
|
} else {
|
||||||
expires: response.data?.expire_at,
|
setError("Sign in failed: " + response.data?.error?.reason);
|
||||||
plan: { upgraded: false, last_checked: 0 },
|
}
|
||||||
});
|
|
||||||
|
|
||||||
getCurrentWindow()
|
getCurrentWindow()
|
||||||
.setFocus()
|
.setFocus()
|
||||||
.catch(() => {});
|
.catch(() => {});
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error("Sign in failed:", error);
|
console.error("Sign in failed:", error);
|
||||||
|
setError("Sign in failed: catch");
|
||||||
await setAuth(undefined);
|
await setAuth(undefined);
|
||||||
throw error;
|
throw error;
|
||||||
} finally {
|
} finally {
|
||||||
@@ -94,21 +92,23 @@ export default function CocoCloud() {
|
|||||||
|
|
||||||
const handleUrl = (url: string) => {
|
const handleUrl = (url: string) => {
|
||||||
try {
|
try {
|
||||||
|
// url = "coco://oauth_callback?code=cu8ag982sdb06e0j6k3g&provider=coco-cloud"
|
||||||
const urlObject = new URL(url);
|
const urlObject = new URL(url);
|
||||||
console.error("1111111:", urlObject);
|
console.log("urlObject:", urlObject);
|
||||||
|
|
||||||
switch (urlObject.pathname) {
|
const code = urlObject.searchParams.get("code");
|
||||||
case "oauth_callback":
|
const provider = urlObject.searchParams.get("provider");
|
||||||
const code = urlObject.searchParams.get("code");
|
handleOAuthCallback(code, provider);
|
||||||
const provider = urlObject.searchParams.get("provider");
|
|
||||||
handleOAuthCallback(code, provider);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
// switch (urlObject.hostname) {
|
||||||
console.log("Unhandled deep link path:", urlObject.pathname);
|
// case "/oauth_callback":
|
||||||
}
|
|
||||||
|
// break;
|
||||||
|
|
||||||
|
// default:
|
||||||
|
// console.log("Unhandled deep link path:", urlObject.pathname);
|
||||||
|
// }
|
||||||
|
|
||||||
setLastUrl(url);
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error("Failed to parse URL:", err);
|
console.error("Failed to parse URL:", err);
|
||||||
setError("Invalid URL format");
|
setError("Invalid URL format");
|
||||||
@@ -117,15 +117,12 @@ export default function CocoCloud() {
|
|||||||
|
|
||||||
// Fetch the initial deep link intent
|
// Fetch the initial deep link intent
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// coco://oauth_calback?code=&provider=
|
// handleUrl("");
|
||||||
// handleOAuthCallback("cu0bpu53q95r66at2010", "coco-cloud");
|
|
||||||
//
|
|
||||||
getCurrentDeepLinkUrls()
|
getCurrentDeepLinkUrls()
|
||||||
.then((urls) => {
|
.then((urls) => {
|
||||||
console.error("22222 URLs:", urls);
|
console.log("URLs:", urls);
|
||||||
if (urls && urls.length > 0) {
|
if (urls && urls.length > 0) {
|
||||||
handleUrl(urls[0]);
|
handleUrl(urls[0]);
|
||||||
console.error("URLs:", urls);
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
@@ -141,22 +138,11 @@ export default function CocoCloud() {
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
function LoginClick() {
|
function LoginClick() {
|
||||||
let uid = app_uid;
|
let uid = uuidv4();
|
||||||
if (!uid) {
|
setAppUid(uid);
|
||||||
uid = uuidv4();
|
|
||||||
setAppUid(uid);
|
|
||||||
}
|
|
||||||
|
|
||||||
// const response = await fetch("/api/register", {
|
|
||||||
// method: "POST",
|
|
||||||
// headers: { "Content-Type": "application/json" },
|
|
||||||
// body: JSON.stringify({ uid }),
|
|
||||||
// });
|
|
||||||
// const { token } = await response.json();
|
|
||||||
// localStorage.setItem("auth_token", token);
|
|
||||||
|
|
||||||
OpenBrowserURL(
|
OpenBrowserURL(
|
||||||
`${endpoint_http}/sso/login/github?provider=coco-cloud&product=coco&request_id=${uid}`
|
`${endpoint_http}/sso/login/?provider=coco-cloud&product=coco&request_id=${uid}`
|
||||||
);
|
);
|
||||||
|
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
@@ -169,24 +155,8 @@ export default function CocoCloud() {
|
|||||||
<main className="flex-1">
|
<main className="flex-1">
|
||||||
<div>
|
<div>
|
||||||
{error && (
|
{error && (
|
||||||
<div className="text-red-500 dark:text-red-400">Error: {error}</div>
|
<div className="text-red-500 dark:text-red-400 p-4">
|
||||||
)}
|
Error: {error}
|
||||||
|
|
||||||
{lastUrl && (
|
|
||||||
<div className="text-gray-700 dark:text-gray-300">
|
|
||||||
Last opened URL: {lastUrl}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{info && (
|
|
||||||
<div className="text-gray-700 dark:text-gray-300">
|
|
||||||
Info : {info}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{info2 && (
|
|
||||||
<div className="text-gray-700 dark:text-gray-300">
|
|
||||||
info2 : {info2}
|
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
@@ -231,7 +201,7 @@ export default function CocoCloud() {
|
|||||||
Account Information
|
Account Information
|
||||||
</h2>
|
</h2>
|
||||||
{auth ? (
|
{auth ? (
|
||||||
<UserProfile name="Rain" email="an121245@gmail.com" />
|
<UserProfile userInfo={userInfo} />
|
||||||
) : (
|
) : (
|
||||||
<button
|
<button
|
||||||
className="px-6 py-2 bg-blue-500 text-white rounded-md hover:bg-blue-600 transition-colors"
|
className="px-6 py-2 bg-blue-500 text-white rounded-md hover:bg-blue-600 transition-colors"
|
||||||
|
|||||||
@@ -1,27 +1,65 @@
|
|||||||
import { User, Edit } from 'lucide-react';
|
import { User, Edit, LogOut } from "lucide-react";
|
||||||
|
|
||||||
interface UserProfileProps {
|
import { useAuthStore } from "@/stores/authStore";
|
||||||
name: string;
|
|
||||||
|
interface UserPreferences {
|
||||||
|
theme: "dark" | "light";
|
||||||
|
language: string;
|
||||||
|
}
|
||||||
|
interface UserInfo {
|
||||||
|
username: string;
|
||||||
email: string;
|
email: string;
|
||||||
|
avatar?: string;
|
||||||
|
roles: string[]; // ["admin", "editor"]
|
||||||
|
preferences: UserPreferences;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function UserProfile({ name, email }: UserProfileProps) {
|
interface UserProfileProps {
|
||||||
|
userInfo: UserInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function UserProfile({ userInfo }: UserProfileProps) {
|
||||||
|
const setAuth = useAuthStore((state) => state.setAuth);
|
||||||
|
const setUserInfo = useAuthStore((state) => state.setUserInfo);
|
||||||
|
|
||||||
|
const handleLogout = () => {
|
||||||
|
setAuth(undefined);
|
||||||
|
setUserInfo({});
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="space-y-6">
|
<div className="space-y-6">
|
||||||
<div className="flex items-center space-x-4">
|
<div className="flex items-center space-x-4">
|
||||||
<div className="w-12 h-12 bg-gray-100 rounded-full flex items-center justify-center">
|
<div className="w-12 h-12 bg-gray-100 rounded-full flex items-center justify-center">
|
||||||
<User className="w-6 h-6 text-gray-500" />
|
{userInfo.avatar ? (
|
||||||
|
<img
|
||||||
|
src={userInfo.avatar}
|
||||||
|
alt=""
|
||||||
|
className="w-6 h-6"
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<User className="w-6 h-6 text-gray-500" />
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className="flex-1">
|
<div className="flex-1">
|
||||||
<div className="flex items-center space-x-2">
|
<div className="flex items-center space-x-2">
|
||||||
<span className="font-medium text-gray-900">{name}</span>
|
<span className="font-medium text-gray-900">
|
||||||
|
{userInfo.username || "-"}
|
||||||
|
</span>
|
||||||
<button className="text-gray-400 hover:text-gray-600">
|
<button className="text-gray-400 hover:text-gray-600">
|
||||||
<Edit className="w-4 h-4" />
|
<Edit className="w-4 h-4" />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<span className="text-sm text-gray-500">{email}</span>
|
<span className="text-sm text-gray-500">{userInfo.email || "-"}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<button
|
||||||
|
onClick={handleLogout}
|
||||||
|
className="flex items-center space-x-1 text-red-500 hover:text-red-600"
|
||||||
|
>
|
||||||
|
<LogOut className="w-4 h-4" />
|
||||||
|
<span>Logout</span>
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,9 +7,8 @@ import { AppEndpoint } from "@/utils/tauri";
|
|||||||
|
|
||||||
const ENDPOINTS = [
|
const ENDPOINTS = [
|
||||||
{ value: "https://coco.infini.cloud", label: "https://coco.infini.cloud" },
|
{ value: "https://coco.infini.cloud", label: "https://coco.infini.cloud" },
|
||||||
{ value: "http://localhost:2900", label: "http://localhost:2900" },
|
|
||||||
{ value: "http://localhost:9000", label: "http://localhost:9000" },
|
{ value: "http://localhost:9000", label: "http://localhost:9000" },
|
||||||
{ value: "https://infini.tpddns.cn:27200", label: "https://infini.tpddns.cn:27200" },
|
{ value: "http://infini.tpddns.cn:27200", label: "http://infini.tpddns.cn:27200" },
|
||||||
];
|
];
|
||||||
|
|
||||||
export default function AdvancedSettings() {
|
export default function AdvancedSettings() {
|
||||||
|
|||||||
@@ -5,12 +5,12 @@ import { useSearchParams } from "react-router-dom";
|
|||||||
|
|
||||||
import SettingsPanel from "./SettingsPanel";
|
import SettingsPanel from "./SettingsPanel";
|
||||||
import GeneralSettings from "./GeneralSettings";
|
import GeneralSettings from "./GeneralSettings";
|
||||||
import AdvancedSettings from "./AdvancedSettings";
|
|
||||||
import AboutView from "./AboutView";
|
import AboutView from "./AboutView";
|
||||||
import CocoCloud from "@/components/Auth/CocoCloud"
|
import CocoCloud from "@/components/Auth/CocoCloud"
|
||||||
import Footer from "../Footer";
|
import Footer from "../Footer";
|
||||||
import { useTheme } from "../../contexts/ThemeContext";
|
import { useTheme } from "../../contexts/ThemeContext";
|
||||||
import { AppTheme } from "../../utils/tauri";
|
import { AppTheme } from "../../utils/tauri";
|
||||||
|
import ApiDetails from "@/components/AppAI/ApiDetails";
|
||||||
|
|
||||||
function SettingsPage() {
|
function SettingsPage() {
|
||||||
const [defaultIndex, setDefaultIndex] = useState<number>(0);
|
const [defaultIndex, setDefaultIndex] = useState<number>(0);
|
||||||
@@ -82,7 +82,9 @@ function SettingsPage() {
|
|||||||
</TabPanel>
|
</TabPanel>
|
||||||
<TabPanel>
|
<TabPanel>
|
||||||
<SettingsPanel title="">
|
<SettingsPanel title="">
|
||||||
<AdvancedSettings />
|
<div className="text-gray-600 dark:text-gray-400">
|
||||||
|
Advanced Settings content
|
||||||
|
</div>
|
||||||
</SettingsPanel>
|
</SettingsPanel>
|
||||||
</TabPanel>
|
</TabPanel>
|
||||||
<TabPanel>
|
<TabPanel>
|
||||||
@@ -95,6 +97,8 @@ function SettingsPage() {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<Footer />
|
<Footer />
|
||||||
|
|
||||||
|
<ApiDetails />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -102,7 +102,7 @@ export default function LoginPage() {
|
|||||||
|
|
||||||
<button
|
<button
|
||||||
className="w-[60px] h-[60px] bg-white hover:bg-gray-100 text-black rounded-full py-3 px-4 flex items-center justify-center space-x-2 transition-colors"
|
className="w-[60px] h-[60px] bg-white hover:bg-gray-100 text-black rounded-full py-3 px-4 flex items-center justify-center space-x-2 transition-colors"
|
||||||
onClick={handleGithubSignIn}
|
onClick={handleAppleSignIn}
|
||||||
>
|
>
|
||||||
<img
|
<img
|
||||||
src={AppleImg}
|
src={AppleImg}
|
||||||
@@ -113,7 +113,7 @@ export default function LoginPage() {
|
|||||||
|
|
||||||
<button
|
<button
|
||||||
className="w-[60px] h-[60px] bg-white hover:bg-gray-100 text-black rounded-full py-3 px-4 flex items-center justify-center space-x-2 transition-colors"
|
className="w-[60px] h-[60px] bg-white hover:bg-gray-100 text-black rounded-full py-3 px-4 flex items-center justify-center space-x-2 transition-colors"
|
||||||
onClick={handleAppleSignIn}
|
onClick={handleGithubSignIn}
|
||||||
>
|
>
|
||||||
<img
|
<img
|
||||||
src={GithubImg}
|
src={GithubImg}
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ export type AuthStore = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export type IAuthStore = {
|
export type IAuthStore = {
|
||||||
|
[x: string]: any;
|
||||||
auth: AuthStore | undefined;
|
auth: AuthStore | undefined;
|
||||||
userInfo: any;
|
userInfo: any;
|
||||||
setAuth: (auth: AuthStore | undefined) => void;
|
setAuth: (auth: AuthStore | undefined) => void;
|
||||||
|
|||||||
@@ -19,9 +19,9 @@ export const useLogStore = create<ILogStore>()(
|
|||||||
logs: [],
|
logs: [],
|
||||||
addLog: (log: ApiLog) =>
|
addLog: (log: ApiLog) =>
|
||||||
set((state) => {
|
set((state) => {
|
||||||
const newLogs = [...state.logs, log];
|
const newLogs = [log, ...state.logs];
|
||||||
if (newLogs.length > 10) {
|
if (newLogs.length > 10) {
|
||||||
newLogs.shift();
|
newLogs.pop();
|
||||||
}
|
}
|
||||||
return { logs: newLogs };
|
return { logs: newLogs };
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -2,6 +2,3 @@ export const clientEnv = {
|
|||||||
COCO_SERVER_URL: import.meta.env.COCO_SERVER_URL ?? "https://coco.infini.cloud",
|
COCO_SERVER_URL: import.meta.env.COCO_SERVER_URL ?? "https://coco.infini.cloud",
|
||||||
COCO_WEBSOCKET_URL: import.meta.env.COCO_WEBSOCKET_URL ?? "wss://coco.infini.cloud/ws",
|
COCO_WEBSOCKET_URL: import.meta.env.COCO_WEBSOCKET_URL ?? "wss://coco.infini.cloud/ws",
|
||||||
};
|
};
|
||||||
|
|
||||||
// http://localhost:2900
|
|
||||||
// ws://localhost:2900/ws
|
|
||||||
|
|||||||
Reference in New Issue
Block a user