mirror of
https://github.com/infinilabs/coco-app.git
synced 2025-12-16 11:37:47 +01:00
refactor: calling service related interfaces (#831)
* chore: server * chore: add * refactor: calling service related interfaces * chore: server list * chore: add * chore: add * update * chore: remove logs * focs: update notes * docs: remove server doc --------- Co-authored-by: ayang <473033518@qq.com>
This commit is contained in:
@@ -23,6 +23,7 @@ Information about release notes of Coco App is provided here.
|
||||
|
||||
### ✈️ Improvements
|
||||
|
||||
- refactor: calling service related interfaces #831
|
||||
- refactor: split query_coco_fusion() #836
|
||||
- chore: web component loading font icon #838
|
||||
- chore: delete unused code files and dependencies #841
|
||||
|
||||
@@ -86,6 +86,12 @@ export const Get = <T>(
|
||||
} else {
|
||||
res = result?.data as FcResponse<T>;
|
||||
}
|
||||
// web component log
|
||||
infoLog({
|
||||
username: "@/api/axiosRequest.ts",
|
||||
logName: url,
|
||||
})(res);
|
||||
|
||||
resolve([null, res as FcResponse<T>]);
|
||||
})
|
||||
.catch((err) => {
|
||||
@@ -103,7 +109,7 @@ export const Post = <T>(
|
||||
return new Promise((resolve) => {
|
||||
const appStore = JSON.parse(localStorage.getItem("app-store") || "{}");
|
||||
|
||||
let baseURL = appStore.state?.endpoint_http
|
||||
let baseURL = appStore.state?.endpoint_http;
|
||||
if (!baseURL || baseURL === "undefined") {
|
||||
baseURL = "";
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { invoke } from "@tauri-apps/api/core";
|
||||
import { emit } from "@tauri-apps/api/event";
|
||||
|
||||
import {
|
||||
Server,
|
||||
@@ -18,17 +17,42 @@ import {
|
||||
import { useAppStore } from "@/stores/appStore";
|
||||
import { useAuthStore } from "@/stores/authStore";
|
||||
import { useConnectStore } from "@/stores/connectStore";
|
||||
import { SETTINGS_WINDOW_LABEL } from "@/constants";
|
||||
import platformAdapter from "@/utils/platformAdapter";
|
||||
|
||||
export function handleLogout(serverId?: string) {
|
||||
const setIsCurrentLogin = useAuthStore.getState().setIsCurrentLogin;
|
||||
const { currentService, setCurrentService, serverList, setServerList } =
|
||||
export async function getCurrentWindowService() {
|
||||
const currentService = useConnectStore.getState().currentService;
|
||||
const cloudSelectService = useConnectStore.getState().cloudSelectService;
|
||||
const windowLabel = await platformAdapter.getCurrentWindowLabel();
|
||||
|
||||
return windowLabel === SETTINGS_WINDOW_LABEL
|
||||
? cloudSelectService
|
||||
: currentService;
|
||||
}
|
||||
|
||||
export async function setCurrentWindowService(service: any) {
|
||||
const windowLabel = await platformAdapter.getCurrentWindowLabel();
|
||||
const { setCurrentService, setCloudSelectService } =
|
||||
useConnectStore.getState();
|
||||
const id = serverId || currentService?.id;
|
||||
|
||||
return windowLabel === SETTINGS_WINDOW_LABEL
|
||||
? setCloudSelectService(service)
|
||||
: setCurrentService(service);
|
||||
}
|
||||
|
||||
export async function handleLogout(serverId?: string) {
|
||||
const setIsCurrentLogin = useAuthStore.getState().setIsCurrentLogin;
|
||||
const { serverList, setServerList } = useConnectStore.getState();
|
||||
|
||||
const service = await getCurrentWindowService();
|
||||
|
||||
const id = serverId || service?.id;
|
||||
if (!id) return;
|
||||
|
||||
// Update the status first
|
||||
setIsCurrentLogin(false);
|
||||
emit("login_or_logout", false);
|
||||
if (currentService?.id === id) {
|
||||
setCurrentService({ ...currentService, profile: null });
|
||||
if (service?.id === id) {
|
||||
await setCurrentWindowService({ ...service, profile: null });
|
||||
}
|
||||
const updatedServerList = serverList.map((server) =>
|
||||
server.id === id ? { ...server, profile: null } : server
|
||||
@@ -55,13 +79,14 @@ async function invokeWithErrorHandler<T>(
|
||||
args?: Record<string, any>
|
||||
): Promise<T> {
|
||||
const isCurrentLogin = useAuthStore.getState().isCurrentLogin;
|
||||
const currentService = useConnectStore.getState().currentService;
|
||||
|
||||
const service = await getCurrentWindowService();
|
||||
|
||||
// Not logged in
|
||||
console.log(command, isCurrentLogin, currentService?.profile);
|
||||
// console.log("isCurrentLogin", command, isCurrentLogin);
|
||||
if (
|
||||
!WHITELIST_SERVERS.includes(command) &&
|
||||
(!isCurrentLogin || !currentService?.profile)
|
||||
(!isCurrentLogin || !service?.profile)
|
||||
) {
|
||||
console.error("This command requires authentication");
|
||||
throw new Error("This command requires authentication");
|
||||
@@ -89,6 +114,18 @@ async function invokeWithErrorHandler<T>(
|
||||
}
|
||||
}
|
||||
|
||||
// Server Data log
|
||||
let parsedResult = result;
|
||||
let logData = result;
|
||||
if (typeof result === "string") {
|
||||
parsedResult = JSON.parse(result);
|
||||
logData = parsedResult;
|
||||
}
|
||||
infoLog({
|
||||
username: "@/commands/servers.ts",
|
||||
logName: command,
|
||||
})(logData);
|
||||
|
||||
return result;
|
||||
} catch (error: any) {
|
||||
const errorMessage = error || "Command execution failed";
|
||||
@@ -380,4 +417,4 @@ export const query_coco_fusion = (payload: {
|
||||
|
||||
export const get_app_search_source = () => {
|
||||
return invokeWithErrorHandler<void>("get_app_search_source");
|
||||
};
|
||||
};
|
||||
|
||||
@@ -57,8 +57,6 @@ export const AssistantFetcher = ({
|
||||
|
||||
let assistantList = response?.hits?.hits ?? [];
|
||||
|
||||
console.log("assistantList", assistantList);
|
||||
|
||||
if (
|
||||
!currentAssistant?._id ||
|
||||
currentService?.id !== lastServerId.current
|
||||
|
||||
@@ -17,6 +17,8 @@ import { Server as IServer } from "@/types/server";
|
||||
import StatusIndicator from "@/components/Cloud/StatusIndicator";
|
||||
import { useAuthStore } from "@/stores/authStore";
|
||||
import { useSearchStore } from "@/stores/searchStore";
|
||||
import { useServers } from "@/hooks/useServers";
|
||||
import { getCurrentWindowService, setCurrentWindowService } from "@/commands";
|
||||
|
||||
interface ServerListProps {
|
||||
clearChat: () => void;
|
||||
@@ -25,17 +27,20 @@ interface ServerListProps {
|
||||
export function ServerList({ clearChat }: ServerListProps) {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const isCurrentLogin = useAuthStore((state) => state.isCurrentLogin);
|
||||
const setIsCurrentLogin = useAuthStore((state) => state.setIsCurrentLogin);
|
||||
const serviceList = useShortcutsStore((state) => state.serviceList);
|
||||
const serviceListShortcut = useShortcutsStore(
|
||||
(state) => state.serviceListShortcut
|
||||
);
|
||||
const setEndpoint = useAppStore((state) => state.setEndpoint);
|
||||
const setCurrentService = useConnectStore((state) => state.setCurrentService);
|
||||
const isTauri = useAppStore((state) => state.isTauri);
|
||||
const currentService = useConnectStore((state) => state.currentService);
|
||||
const cloudSelectService = useConnectStore((state) => {
|
||||
return state.cloudSelectService;
|
||||
});
|
||||
|
||||
const { setMessages } = useChatStore();
|
||||
|
||||
const [serverList, setServerList] = useState<IServer[]>([]);
|
||||
const [list, setList] = useState<IServer[]>([]);
|
||||
const [isRefreshing, setIsRefreshing] = useState(false);
|
||||
const [highlightId, setHighlightId] = useState<string>("");
|
||||
|
||||
@@ -49,44 +54,49 @@ export function ServerList({ clearChat }: ServerListProps) {
|
||||
const popoverRef = useRef<HTMLDivElement>(null);
|
||||
const serverListButtonRef = useRef<HTMLButtonElement>(null);
|
||||
|
||||
const fetchServers = useCallback(
|
||||
async (resetSelection: boolean) => {
|
||||
platformAdapter.commands("list_coco_servers").then((res: any) => {
|
||||
console.log("list_coco_servers", res);
|
||||
if (!Array.isArray(res)) {
|
||||
// If res is not an array, it might be an error message or something else.
|
||||
// Log it and don't proceed.
|
||||
// console.log("list_coco_servers did not return an array:", res);
|
||||
setServerList([]); // Clear the list or handle as appropriate
|
||||
return;
|
||||
}
|
||||
const enabledServers = (res as IServer[])?.filter(
|
||||
(server) => server.enabled && server.available
|
||||
);
|
||||
const { refreshServerList } = useServers();
|
||||
const serverList = useConnectStore((state) => state.serverList);
|
||||
|
||||
setServerList(enabledServers);
|
||||
const switchServer = async (server: IServer) => {
|
||||
if (!server) return;
|
||||
try {
|
||||
// Switch UI first, then switch server connection
|
||||
await setCurrentWindowService(server);
|
||||
setEndpoint(server.endpoint);
|
||||
setMessages(""); // Clear previous messages
|
||||
clearChat();
|
||||
//
|
||||
if (!server.public && !server.profile) {
|
||||
setIsCurrentLogin(false);
|
||||
return;
|
||||
}
|
||||
//
|
||||
setIsCurrentLogin(true);
|
||||
} catch (error) {
|
||||
console.error("switchServer:", error);
|
||||
}
|
||||
};
|
||||
|
||||
if (resetSelection && enabledServers.length > 0) {
|
||||
const currentServiceExists = enabledServers.find(
|
||||
(server) => server.id === currentService?.id
|
||||
);
|
||||
const fetchServers = useCallback(async () => {
|
||||
const service = await getCurrentWindowService();
|
||||
|
||||
if (currentServiceExists) {
|
||||
switchServer(currentServiceExists);
|
||||
} else {
|
||||
switchServer(enabledServers[enabledServers.length - 1]);
|
||||
}
|
||||
}
|
||||
const enabledServers = serverList.filter(
|
||||
(server) => server.enabled && server.available
|
||||
);
|
||||
setList(enabledServers);
|
||||
|
||||
if (enabledServers.length > 0) {
|
||||
const serviceExists = enabledServers.find((server) => {
|
||||
return server.id === service?.id;
|
||||
});
|
||||
},
|
||||
[currentService?.id]
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
if (!isTauri) return;
|
||||
|
||||
fetchServers(true);
|
||||
}, [currentService?.enabled]);
|
||||
if (serviceExists) {
|
||||
switchServer(serviceExists);
|
||||
} else {
|
||||
switchServer(enabledServers[enabledServers.length - 1]);
|
||||
}
|
||||
}
|
||||
}, [currentService?.id, cloudSelectService?.id, serverList]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!askAiServerId || serverList.length === 0) return;
|
||||
@@ -104,25 +114,12 @@ export function ServerList({ clearChat }: ServerListProps) {
|
||||
useEffect(() => {
|
||||
if (!isTauri) return;
|
||||
|
||||
fetchServers(true);
|
||||
|
||||
const unlisten = platformAdapter.listenEvent("login_or_logout", (event) => {
|
||||
//console.log("Login or Logout:", currentService, event.payload);
|
||||
if (event.payload !== isCurrentLogin) {
|
||||
setIsCurrentLogin(!!event.payload);
|
||||
}
|
||||
fetchServers(true);
|
||||
});
|
||||
|
||||
return () => {
|
||||
// Cleanup logic if needed
|
||||
unlisten.then((fn) => fn());
|
||||
};
|
||||
}, []);
|
||||
fetchServers();
|
||||
}, [serverList]);
|
||||
|
||||
const handleRefresh = async () => {
|
||||
setIsRefreshing(true);
|
||||
await fetchServers(false);
|
||||
await refreshServerList();
|
||||
setTimeout(() => setIsRefreshing(false), 1000);
|
||||
};
|
||||
|
||||
@@ -130,29 +127,10 @@ export function ServerList({ clearChat }: ServerListProps) {
|
||||
platformAdapter.emitEvent("open_settings", "connect");
|
||||
};
|
||||
|
||||
const switchServer = async (server: IServer) => {
|
||||
if (!server) return;
|
||||
try {
|
||||
// Switch UI first, then switch server connection
|
||||
setCurrentService(server);
|
||||
setEndpoint(server.endpoint);
|
||||
setMessages(""); // Clear previous messages
|
||||
clearChat();
|
||||
//
|
||||
if (!server.public && !server.profile) {
|
||||
setIsCurrentLogin(false);
|
||||
return;
|
||||
}
|
||||
//
|
||||
setIsCurrentLogin(true);
|
||||
} catch (error) {
|
||||
console.error("switchServer:", error);
|
||||
}
|
||||
};
|
||||
|
||||
useKeyPress(
|
||||
["uparrow", "downarrow", "enter"],
|
||||
(event, key) => {
|
||||
async (event, key) => {
|
||||
const service = await getCurrentWindowService();
|
||||
const isClose = isNil(serverListButtonRef.current?.dataset["open"]);
|
||||
const length = serverList.length;
|
||||
|
||||
@@ -162,9 +140,7 @@ export function ServerList({ clearChat }: ServerListProps) {
|
||||
event.preventDefault();
|
||||
|
||||
const currentIndex = serverList.findIndex((server) => {
|
||||
return (
|
||||
server.id === (highlightId === "" ? currentService?.id : highlightId)
|
||||
);
|
||||
return server.id === (highlightId === "" ? service?.id : highlightId);
|
||||
});
|
||||
|
||||
let nextIndex = currentIndex;
|
||||
@@ -197,7 +173,7 @@ export function ServerList({ clearChat }: ServerListProps) {
|
||||
<Popover ref={popoverRef} className="relative">
|
||||
<PopoverButton ref={serverListButtonRef} className="flex items-center">
|
||||
<VisibleKey
|
||||
shortcut={serviceList}
|
||||
shortcut={serviceListShortcut}
|
||||
onKeyPress={() => {
|
||||
serverListButtonRef.current?.click();
|
||||
}}
|
||||
@@ -240,8 +216,8 @@ export function ServerList({ clearChat }: ServerListProps) {
|
||||
</div>
|
||||
</div>
|
||||
<div className="space-y-1">
|
||||
{serverList.length > 0 ? (
|
||||
serverList.map((server) => (
|
||||
{list.length > 0 ? (
|
||||
list.map((server) => (
|
||||
<div
|
||||
key={server.id}
|
||||
onClick={() => switchServer(server)}
|
||||
|
||||
@@ -82,8 +82,6 @@ const AudioRecording: FC<AudioRecordingProps> = (props) => {
|
||||
}
|
||||
);
|
||||
|
||||
console.log("response", response);
|
||||
|
||||
const text = response?.results
|
||||
.flatMap((item: any) => item?.transcription?.transcripts)
|
||||
.map((item: any) => item?.text?.replace(/<\|[\/\w]+\|>/g, ""))
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { useEffect, useRef, useState, useCallback } from "react";
|
||||
import { emit } from "@tauri-apps/api/event";
|
||||
|
||||
import { DataSourcesList } from "./DataSourcesList";
|
||||
import { Sidebar } from "./Sidebar";
|
||||
@@ -9,6 +8,8 @@ import { useConnectStore } from "@/stores/connectStore";
|
||||
import ServiceInfo from "./ServiceInfo";
|
||||
import ServiceAuth from "./ServiceAuth";
|
||||
import platformAdapter from "@/utils/platformAdapter";
|
||||
import type { Server } from "@/types/server";
|
||||
import { useServers } from "@/hooks/useServers";
|
||||
|
||||
export default function Cloud() {
|
||||
const SidebarRef = useRef<{ refreshData: () => void }>(null);
|
||||
@@ -17,100 +18,63 @@ export default function Cloud() {
|
||||
|
||||
const [isConnect, setIsConnect] = useState(true);
|
||||
|
||||
const { currentService, setCurrentService, serverList, setServerList } =
|
||||
useConnectStore();
|
||||
const {
|
||||
cloudSelectService,
|
||||
setCloudSelectService,
|
||||
serverList,
|
||||
setServerList,
|
||||
} = useConnectStore();
|
||||
|
||||
const [refreshLoading, setRefreshLoading] = useState(false);
|
||||
|
||||
const { addServer, refreshServerList } = useServers();
|
||||
|
||||
// fetch the servers
|
||||
useEffect(() => {
|
||||
fetchServers(true);
|
||||
}, []);
|
||||
fetchServers();
|
||||
}, [serverList]);
|
||||
|
||||
useEffect(() => {
|
||||
// console.log("currentService", currentService);
|
||||
setRefreshLoading(false);
|
||||
setIsConnect(true);
|
||||
}, [JSON.stringify(currentService)]);
|
||||
}, [cloudSelectService?.id]);
|
||||
|
||||
const fetchServers = async (resetSelection: boolean) => {
|
||||
platformAdapter
|
||||
.commands("list_coco_servers")
|
||||
.then((res: any) => {
|
||||
if (errors.length > 0) {
|
||||
res = (res || []).map((item: any) => {
|
||||
if (item.id === currentService?.id) {
|
||||
item.health = {
|
||||
services: null,
|
||||
status: null,
|
||||
};
|
||||
}
|
||||
return item;
|
||||
});
|
||||
const fetchServers = useCallback(async () => {
|
||||
let res = serverList;
|
||||
if (errors.length > 0) {
|
||||
res = res.map((item: Server) => {
|
||||
if (item.id === cloudSelectService?.id) {
|
||||
item.health = {
|
||||
services: item.health?.services || {},
|
||||
status: item.health?.status || "red",
|
||||
};
|
||||
}
|
||||
console.log("list_coco_servers", res);
|
||||
setServerList(res);
|
||||
|
||||
if (resetSelection && res.length > 0) {
|
||||
const matched = res.find((server: any) => {
|
||||
return server.id === currentService?.id;
|
||||
});
|
||||
|
||||
if (matched) {
|
||||
setCurrentService(matched);
|
||||
} else {
|
||||
setCurrentService(res[res.length - 1]);
|
||||
}
|
||||
}
|
||||
})
|
||||
};
|
||||
|
||||
const addServer = (endpointLink: string) => {
|
||||
if (!endpointLink) {
|
||||
throw new Error("Endpoint is required");
|
||||
}
|
||||
if (
|
||||
!endpointLink.startsWith("http://") &&
|
||||
!endpointLink.startsWith("https://")
|
||||
) {
|
||||
throw new Error("Invalid Endpoint");
|
||||
}
|
||||
|
||||
setRefreshLoading(true);
|
||||
|
||||
return platformAdapter
|
||||
.commands("add_coco_server", endpointLink)
|
||||
.then((res: any) => {
|
||||
// console.log("add_coco_server", res);
|
||||
fetchServers(false).then((r) => {
|
||||
console.log("fetchServers", r);
|
||||
setCurrentService(res);
|
||||
});
|
||||
})
|
||||
.finally(() => {
|
||||
setRefreshLoading(false);
|
||||
return item;
|
||||
});
|
||||
};
|
||||
}
|
||||
setServerList(res);
|
||||
|
||||
if (res.length > 0) {
|
||||
const matched = res.find((server: any) => {
|
||||
return server.id === cloudSelectService?.id;
|
||||
});
|
||||
|
||||
if (matched) {
|
||||
setCloudSelectService(matched);
|
||||
} else {
|
||||
setCloudSelectService(res[res.length - 1]);
|
||||
}
|
||||
}
|
||||
}, [serverList, errors, cloudSelectService]);
|
||||
|
||||
const refreshClick = useCallback(
|
||||
(id: string) => {
|
||||
async (id: string) => {
|
||||
setRefreshLoading(true);
|
||||
platformAdapter
|
||||
.commands("refresh_coco_server_info", id)
|
||||
.then((res: any) => {
|
||||
console.log("refresh_coco_server_info", id, res);
|
||||
fetchServers(false).then((r) => {
|
||||
console.log("fetchServers", r);
|
||||
});
|
||||
// update currentService
|
||||
setCurrentService(res);
|
||||
emit("login_or_logout", true);
|
||||
})
|
||||
.finally(() => {
|
||||
setRefreshLoading(false);
|
||||
});
|
||||
await platformAdapter.commands("refresh_coco_server_info", id);
|
||||
await refreshServerList();
|
||||
setRefreshLoading(false);
|
||||
},
|
||||
[fetchServers]
|
||||
[refreshServerList]
|
||||
);
|
||||
|
||||
return (
|
||||
@@ -127,7 +91,6 @@ export default function Cloud() {
|
||||
<ServiceInfo
|
||||
refreshLoading={refreshLoading}
|
||||
refreshClick={refreshClick}
|
||||
fetchServers={fetchServers}
|
||||
/>
|
||||
|
||||
<ServiceAuth
|
||||
@@ -135,8 +98,8 @@ export default function Cloud() {
|
||||
refreshClick={refreshClick}
|
||||
/>
|
||||
|
||||
{currentService?.profile && currentService?.available ? (
|
||||
<DataSourcesList server={currentService?.id} />
|
||||
{cloudSelectService?.profile && cloudSelectService?.available ? (
|
||||
<DataSourcesList server={cloudSelectService?.id} />
|
||||
) : null}
|
||||
</div>
|
||||
) : (
|
||||
|
||||
@@ -21,7 +21,7 @@ export function Connect({ setIsConnect, onAddServer }: ConnectServiceProps) {
|
||||
};
|
||||
|
||||
const onAddServerClick = async (endpoint: string) => {
|
||||
console.log("onAddServer", endpoint);
|
||||
//console.log("onAddServer", endpoint);
|
||||
await onAddServer(endpoint);
|
||||
setIsConnect(true);
|
||||
};
|
||||
|
||||
@@ -20,7 +20,6 @@ export function DataSourcesList({ server }: { server: string }) {
|
||||
platformAdapter
|
||||
.commands("get_connectors_by_server", server)
|
||||
.then((res: any) => {
|
||||
// console.log("get_connectors_by_server", res);
|
||||
setConnectorData(res, server);
|
||||
})
|
||||
.finally(() => {});
|
||||
@@ -29,7 +28,6 @@ export function DataSourcesList({ server }: { server: string }) {
|
||||
platformAdapter
|
||||
.commands("datasource_search", { id: server })
|
||||
.then((res: any) => {
|
||||
// console.log("datasource_search", res);
|
||||
setDatasourceData(res, server);
|
||||
})
|
||||
.finally(() => {
|
||||
|
||||
@@ -14,7 +14,7 @@ import { useConnectStore } from "@/stores/connectStore";
|
||||
import { useAppStore } from "@/stores/appStore";
|
||||
import { copyToClipboard } from "@/utils";
|
||||
import platformAdapter from "@/utils/platformAdapter";
|
||||
import { handleLogout } from "@/commands/servers";
|
||||
import { useServers } from "@/hooks/useServers";
|
||||
|
||||
interface ServiceAuthProps {
|
||||
setRefreshLoading: (loading: boolean) => void;
|
||||
@@ -30,7 +30,9 @@ const ServiceAuth = memo(
|
||||
|
||||
const addError = useAppStore((state) => state.addError);
|
||||
|
||||
const currentService = useConnectStore((state) => state.currentService);
|
||||
const cloudSelectService = useConnectStore((state) => state.cloudSelectService);
|
||||
|
||||
const { logoutServer } = useServers();
|
||||
|
||||
const [loading, setLoading] = useState(false);
|
||||
|
||||
@@ -41,7 +43,7 @@ const ServiceAuth = memo(
|
||||
setSSORequestID(requestID);
|
||||
|
||||
// Generate the login URL with the current appUid
|
||||
const url = `${currentService?.auth_provider?.sso?.url}/?provider=${currentService?.id}&product=coco&request_id=${requestID}`;
|
||||
const url = `${cloudSelectService?.auth_provider?.sso?.url}/?provider=${cloudSelectService?.id}&product=coco&request_id=${requestID}`;
|
||||
|
||||
console.log("Open SSO link, requestID:", ssoRequestID, url);
|
||||
|
||||
@@ -50,20 +52,17 @@ const ServiceAuth = memo(
|
||||
|
||||
// Start loading state
|
||||
setLoading(true);
|
||||
}, [ssoRequestID, loading, currentService]);
|
||||
}, [ssoRequestID, loading, cloudSelectService]);
|
||||
|
||||
const onLogout = useCallback((id: string) => {
|
||||
setRefreshLoading(true);
|
||||
platformAdapter
|
||||
.commands("logout_coco_server", id)
|
||||
.then((res: any) => {
|
||||
console.log("logout_coco_server", id, JSON.stringify(res));
|
||||
handleLogout(id);
|
||||
})
|
||||
.finally(() => {
|
||||
const onLogout = useCallback(
|
||||
(id: string) => {
|
||||
setRefreshLoading(true);
|
||||
logoutServer(id).finally(() => {
|
||||
setRefreshLoading(false);
|
||||
});
|
||||
}, []);
|
||||
},
|
||||
[logoutServer]
|
||||
);
|
||||
|
||||
const handleOAuthCallback = useCallback(
|
||||
async (code: string | null, serverId: string | null) => {
|
||||
@@ -109,7 +108,7 @@ const ServiceAuth = memo(
|
||||
return;
|
||||
}
|
||||
|
||||
const serverId = currentService?.id;
|
||||
const serverId = cloudSelectService?.id;
|
||||
handleOAuthCallback(code, serverId);
|
||||
} catch (err) {
|
||||
console.error("Failed to parse URL:", err);
|
||||
@@ -162,9 +161,9 @@ const ServiceAuth = memo(
|
||||
|
||||
useEffect(() => {
|
||||
setLoading(false);
|
||||
}, [currentService]);
|
||||
}, [cloudSelectService]);
|
||||
|
||||
if (!currentService?.auth_provider?.sso?.url) {
|
||||
if (!cloudSelectService?.auth_provider?.sso?.url) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -173,10 +172,10 @@ const ServiceAuth = memo(
|
||||
<h2 className="text-lg font-medium text-gray-900 dark:text-white mb-4">
|
||||
{t("cloud.accountInfo")}
|
||||
</h2>
|
||||
{currentService?.profile ? (
|
||||
{cloudSelectService?.profile ? (
|
||||
<UserProfile
|
||||
server={currentService?.id}
|
||||
userInfo={currentService?.profile}
|
||||
server={cloudSelectService?.id}
|
||||
userInfo={cloudSelectService?.profile}
|
||||
onLogout={onLogout}
|
||||
/>
|
||||
) : (
|
||||
@@ -190,7 +189,7 @@ const ServiceAuth = memo(
|
||||
onCancel={() => setLoading(false)}
|
||||
onCopy={() => {
|
||||
copyToClipboard(
|
||||
`${currentService?.auth_provider?.sso?.url}/?provider=${currentService?.id}&product=coco&request_id=${ssoRequestID}`
|
||||
`${cloudSelectService?.auth_provider?.sso?.url}/?provider=${cloudSelectService?.id}&product=coco&request_id=${ssoRequestID}`
|
||||
);
|
||||
}}
|
||||
/>
|
||||
@@ -201,7 +200,7 @@ const ServiceAuth = memo(
|
||||
<button
|
||||
className="text-xs text-[#0096FB] dark:text-blue-400 block"
|
||||
onClick={() =>
|
||||
OpenURLWithBrowser(currentService?.provider?.eula)
|
||||
OpenURLWithBrowser(cloudSelectService?.provider?.eula)
|
||||
}
|
||||
>
|
||||
{t("cloud.eula")}
|
||||
@@ -215,7 +214,7 @@ const ServiceAuth = memo(
|
||||
<button
|
||||
className="text-xs text-[#0096FB] dark:text-blue-400 block"
|
||||
onClick={() =>
|
||||
OpenURLWithBrowser(currentService?.provider?.privacy_policy)
|
||||
OpenURLWithBrowser(cloudSelectService?.provider?.privacy_policy)
|
||||
}
|
||||
>
|
||||
{t("cloud.privacyPolicy")}
|
||||
|
||||
@@ -6,13 +6,13 @@ import { useConnectStore } from "@/stores/connectStore";
|
||||
interface ServiceBannerProps {}
|
||||
|
||||
const ServiceBanner = memo(({}: ServiceBannerProps) => {
|
||||
const currentService = useConnectStore((state) => state.currentService);
|
||||
const cloudSelectService = useConnectStore((state) => state.cloudSelectService);
|
||||
|
||||
return (
|
||||
<div className="w-full rounded-[4px] bg-[rgba(229,229,229,1)] dark:bg-gray-800 mb-6">
|
||||
<img
|
||||
width="100%"
|
||||
src={currentService?.provider?.banner || bannerImg}
|
||||
src={cloudSelectService?.provider?.banner || bannerImg}
|
||||
alt="banner"
|
||||
onError={(e) => {
|
||||
const target = e.target as HTMLImageElement;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { memo, useCallback } from "react";
|
||||
import { memo } from "react";
|
||||
import { Globe, RefreshCcw, Trash2 } from "lucide-react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import clsx from "clsx";
|
||||
@@ -7,90 +7,64 @@ import Tooltip from "@/components/Common/Tooltip";
|
||||
import SettingsToggle from "@/components/Settings/SettingsToggle";
|
||||
import { OpenURLWithBrowser } from "@/utils";
|
||||
import { useConnectStore } from "@/stores/connectStore";
|
||||
import platformAdapter from "@/utils/platformAdapter";
|
||||
import { useServers } from "@/hooks/useServers";
|
||||
|
||||
interface ServiceHeaderProps {
|
||||
refreshLoading?: boolean;
|
||||
refreshClick: (id: string) => void;
|
||||
fetchServers: (force: boolean) => Promise<void>;
|
||||
}
|
||||
|
||||
const ServiceHeader = memo(
|
||||
({ refreshLoading, refreshClick, fetchServers }: ServiceHeaderProps) => {
|
||||
({ refreshLoading, refreshClick }: ServiceHeaderProps) => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const currentService = useConnectStore((state) => state.currentService);
|
||||
const setCurrentService = useConnectStore(
|
||||
(state) => state.setCurrentService
|
||||
);
|
||||
const cloudSelectService = useConnectStore((state) => state.cloudSelectService);
|
||||
|
||||
const enable_coco_server = useCallback(
|
||||
async (enabled: boolean) => {
|
||||
if (enabled) {
|
||||
await platformAdapter.commands("enable_server", currentService?.id);
|
||||
} else {
|
||||
await platformAdapter.commands("disable_server", currentService?.id);
|
||||
}
|
||||
|
||||
setCurrentService({ ...currentService, enabled });
|
||||
|
||||
await fetchServers(false);
|
||||
},
|
||||
[currentService?.id]
|
||||
);
|
||||
|
||||
const removeServer = (id: string) => {
|
||||
platformAdapter.commands("remove_coco_server", id).then((res: any) => {
|
||||
console.log("remove_coco_server", id, JSON.stringify(res));
|
||||
fetchServers(true).then((r) => {
|
||||
console.log("fetchServers", r);
|
||||
});
|
||||
});
|
||||
};
|
||||
const { enableServer, removeServer } = useServers();
|
||||
|
||||
return (
|
||||
<div className="flex items-center justify-between mb-4">
|
||||
<div className="flex items-center space-x-3">
|
||||
<Tooltip content={currentService?.endpoint}>
|
||||
<Tooltip content={cloudSelectService?.endpoint}>
|
||||
<div className="flex items-center text-gray-900 dark:text-white font-medium cursor-pointer">
|
||||
{currentService?.name}
|
||||
{cloudSelectService?.name}
|
||||
</div>
|
||||
</Tooltip>
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
<SettingsToggle
|
||||
checked={currentService?.enabled}
|
||||
checked={cloudSelectService?.enabled}
|
||||
className={clsx({
|
||||
"bg-red-600 focus:ring-red-500": !currentService?.enabled,
|
||||
"bg-red-600 focus:ring-red-500": !cloudSelectService?.enabled,
|
||||
})}
|
||||
label={
|
||||
currentService?.enabled
|
||||
cloudSelectService?.enabled
|
||||
? t("cloud.enable_server")
|
||||
: t("cloud.disable_server")
|
||||
}
|
||||
onChange={enable_coco_server}
|
||||
onChange={enableServer}
|
||||
/>
|
||||
|
||||
<button
|
||||
className="p-2 text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-300 rounded-[6px] bg-white dark:bg-gray-800 border border-[rgba(228,229,239,1)] dark:border-gray-700"
|
||||
onClick={() =>
|
||||
OpenURLWithBrowser(currentService?.provider?.website)
|
||||
OpenURLWithBrowser(cloudSelectService?.provider?.website)
|
||||
}
|
||||
>
|
||||
<Globe className="w-3.5 h-3.5" />
|
||||
</button>
|
||||
<button
|
||||
className="p-2 text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-300 rounded-[6px] bg-white dark:bg-gray-800 border border-[rgba(228,229,239,1)] dark:border-gray-700"
|
||||
onClick={() => refreshClick(currentService?.id)}
|
||||
onClick={() => refreshClick(cloudSelectService?.id)}
|
||||
>
|
||||
<RefreshCcw
|
||||
className={`w-3.5 h-3.5 ${refreshLoading ? "animate-spin" : ""}`}
|
||||
/>
|
||||
</button>
|
||||
{!currentService?.builtin && (
|
||||
{!cloudSelectService?.builtin && (
|
||||
<button
|
||||
className="p-2 text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-300 rounded-[6px] bg-white dark:bg-gray-800 border border-[rgba(228,229,239,1)] dark:border-gray-700"
|
||||
onClick={() => removeServer(currentService?.id)}
|
||||
onClick={() => removeServer(cloudSelectService?.id)}
|
||||
>
|
||||
<Trash2 className="w-3.5 h-3.5 text-[#ff4747]" />
|
||||
</button>
|
||||
|
||||
@@ -7,11 +7,10 @@ import ServiceMetadata from "./ServiceMetadata";
|
||||
interface ServiceInfoProps {
|
||||
refreshLoading?: boolean;
|
||||
refreshClick: (id: string) => void;
|
||||
fetchServers: (force: boolean) => Promise<void>;
|
||||
}
|
||||
|
||||
const ServiceInfo = memo(
|
||||
({ refreshLoading, refreshClick, fetchServers }: ServiceInfoProps) => {
|
||||
({ refreshLoading, refreshClick }: ServiceInfoProps) => {
|
||||
return (
|
||||
<>
|
||||
<ServiceBanner />
|
||||
@@ -19,7 +18,6 @@ const ServiceInfo = memo(
|
||||
<ServiceHeader
|
||||
refreshLoading={refreshLoading}
|
||||
refreshClick={refreshClick}
|
||||
fetchServers={fetchServers}
|
||||
/>
|
||||
|
||||
<ServiceMetadata />
|
||||
|
||||
@@ -6,25 +6,25 @@ import { useConnectStore } from "@/stores/connectStore";
|
||||
interface ServiceMetadataProps {}
|
||||
|
||||
const ServiceMetadata = memo(({}: ServiceMetadataProps) => {
|
||||
const currentService = useConnectStore((state) => state.currentService);
|
||||
const cloudSelectService = useConnectStore((state) => state.cloudSelectService);
|
||||
|
||||
return (
|
||||
<div className="mb-8">
|
||||
<div className="text-sm text-gray-500 dark:text-gray-400 mb-2 flex">
|
||||
<span className="flex items-center gap-1">
|
||||
<PackageOpen className="w-4 h-4" /> {currentService?.provider?.name}
|
||||
<PackageOpen className="w-4 h-4" /> {cloudSelectService?.provider?.name}
|
||||
</span>
|
||||
<span className="mx-4">|</span>
|
||||
<span className="flex items-center gap-1">
|
||||
<GitFork className="w-4 h-4" /> {currentService?.version?.number}
|
||||
<GitFork className="w-4 h-4" /> {cloudSelectService?.version?.number}
|
||||
</span>
|
||||
<span className="mx-4">|</span>
|
||||
<span className="flex items-center gap-1">
|
||||
<CalendarSync className="w-4 h-4" /> {currentService?.updated}
|
||||
<CalendarSync className="w-4 h-4" /> {cloudSelectService?.updated}
|
||||
</span>
|
||||
</div>
|
||||
<p className="text-gray-600 dark:text-gray-300 leading-relaxed">
|
||||
{currentService?.provider?.description}
|
||||
{cloudSelectService?.provider?.description}
|
||||
</p>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -20,13 +20,15 @@ interface ServerGroups {
|
||||
export const Sidebar = forwardRef<{ refreshData: () => void }, SidebarProps>(
|
||||
({ setIsConnect, serverList }, _ref) => {
|
||||
const { t } = useTranslation();
|
||||
const currentService = useConnectStore((state) => state.currentService);
|
||||
const setCurrentService = useConnectStore(
|
||||
(state) => state.setCurrentService
|
||||
);
|
||||
const cloudSelectService = useConnectStore((state) => {
|
||||
return state.cloudSelectService;
|
||||
});
|
||||
const setCloudSelectService = useConnectStore((state) => {
|
||||
return state.setCloudSelectService;
|
||||
});
|
||||
|
||||
const selectService = (item: Server) => {
|
||||
setCurrentService(item);
|
||||
setCloudSelectService(item);
|
||||
setIsConnect(true);
|
||||
};
|
||||
|
||||
@@ -41,7 +43,7 @@ export const Sidebar = forwardRef<{ refreshData: () => void }, SidebarProps>(
|
||||
// Extracted server item rendering
|
||||
const renderServerItem = useCallback(
|
||||
(item: Server) => {
|
||||
const isSelected = currentService?.id === item.id;
|
||||
const isSelected = cloudSelectService?.id === item.id;
|
||||
return (
|
||||
<div
|
||||
key={item.id}
|
||||
@@ -72,7 +74,7 @@ export const Sidebar = forwardRef<{ refreshData: () => void }, SidebarProps>(
|
||||
</div>
|
||||
);
|
||||
},
|
||||
[currentService]
|
||||
[cloudSelectService]
|
||||
);
|
||||
|
||||
const { builtinServers, customServers } = useMemo(() => {
|
||||
|
||||
@@ -12,7 +12,6 @@ interface UserProfileProps {
|
||||
export function UserProfile({ server, userInfo, onLogout }: UserProfileProps) {
|
||||
const handleLogout = () => {
|
||||
onLogout(server);
|
||||
console.log("Logout", server);
|
||||
};
|
||||
|
||||
const [imageLoadError, setImageLoadError] = useState(false);
|
||||
|
||||
@@ -124,7 +124,6 @@ export const DocumentList: React.FC<DocumentListProps> = ({
|
||||
}
|
||||
}
|
||||
|
||||
console.log("_docs", from, queryStrings, response);
|
||||
const list = response?.hits ?? [];
|
||||
const allTotal = response?.total_hits ?? 0;
|
||||
// set first select hover
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Command, RotateCcw } from "lucide-react";
|
||||
import { useEffect } from "react";
|
||||
import { Button } from "@headlessui/react";
|
||||
import clsx from "clsx";
|
||||
|
||||
import { formatKey } from "@/utils/keyboardUtils";
|
||||
import SettingsItem from "@/components/Settings/SettingsItem";
|
||||
@@ -28,8 +30,6 @@ import { ModifierKey } from "@/types/index";
|
||||
import platformAdapter from "@/utils/platformAdapter";
|
||||
import { useAppStore } from "@/stores/appStore";
|
||||
import SettingsInput from "@/components/Settings/SettingsInput";
|
||||
import { Button } from "@headlessui/react";
|
||||
import clsx from "clsx";
|
||||
|
||||
export const modifierKeys: ModifierKey[] = isMac
|
||||
? ["meta", "ctrl"]
|
||||
@@ -66,8 +66,8 @@ const Shortcuts = () => {
|
||||
setNewSession,
|
||||
fixedWindow,
|
||||
setFixedWindow,
|
||||
serviceList,
|
||||
setServiceList,
|
||||
serviceListShortcut,
|
||||
setServiceListShortcut,
|
||||
external,
|
||||
setExternal,
|
||||
aiOverview,
|
||||
@@ -181,8 +181,8 @@ const Shortcuts = () => {
|
||||
title: "settings.advanced.shortcuts.serviceList.title",
|
||||
description: "settings.advanced.shortcuts.serviceList.description",
|
||||
initialValue: INITIAL_SERVICE_LIST,
|
||||
value: serviceList,
|
||||
setValue: setServiceList,
|
||||
value: serviceListShortcut,
|
||||
setValue: setServiceListShortcut,
|
||||
},
|
||||
{
|
||||
title: "settings.advanced.shortcuts.external.title",
|
||||
|
||||
@@ -1,137 +1,164 @@
|
||||
import { FC, useMemo, useState, useCallback } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { isArray } from "lodash-es";
|
||||
import { useAsyncEffect, useMount } from "ahooks";
|
||||
|
||||
import { AssistantFetcher } from "@/components/Assistant/AssistantFetcher";
|
||||
import SettingsSelectPro from "@/components/Settings/SettingsSelectPro";
|
||||
import { useAppStore } from "@/stores/appStore";
|
||||
import platformAdapter from "@/utils/platformAdapter";
|
||||
import { useAsyncEffect, useMount } from "ahooks";
|
||||
import { FC, useMemo, useState } from "react";
|
||||
import { ExtensionId } from "../../..";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { isArray } from "lodash-es";
|
||||
import { ExtensionId } from "@/components/Settings/Extensions/index";
|
||||
import { useConnectStore } from "@/stores/connectStore";
|
||||
import type { Server } from "@/types/server";
|
||||
|
||||
interface Assistant {
|
||||
id: string;
|
||||
name?: string;
|
||||
icon?: string;
|
||||
description?: string;
|
||||
}
|
||||
|
||||
interface SharedAiProps {
|
||||
id: ExtensionId;
|
||||
server?: any;
|
||||
setServer: (server: any) => void;
|
||||
assistant?: any;
|
||||
setAssistant: (assistant: any) => void;
|
||||
server?: Server;
|
||||
setServer: (server: Server | undefined) => void;
|
||||
assistant?: Assistant;
|
||||
setAssistant: (assistant: Assistant | undefined) => void;
|
||||
}
|
||||
|
||||
const SharedAi: FC<SharedAiProps> = (props) => {
|
||||
const { id, server, setServer, assistant, setAssistant } = props;
|
||||
|
||||
const [serverList, setServerList] = useState<any[]>([server]);
|
||||
const [assistantList, setAssistantList] = useState<any[]>([assistant]);
|
||||
const serverList = useConnectStore((state) => state.serverList);
|
||||
|
||||
const [list, setList] = useState<Server[]>([]);
|
||||
const [assistantList, setAssistantList] = useState<Assistant[]>([]);
|
||||
const addError = useAppStore((state) => state.addError);
|
||||
const { fetchAssistant } = AssistantFetcher({});
|
||||
const { t } = useTranslation();
|
||||
const [assistantSearchValue, setAssistantSearchValue] = useState("");
|
||||
const [isLoadingAssistants, setIsLoadingAssistants] = useState(false);
|
||||
|
||||
const getEnabledServers = useCallback((servers: Server[]): Server[] => {
|
||||
if (!isArray(servers)) return [];
|
||||
return servers.filter(
|
||||
(s) => s.enabled && s.available && (s.public || s.profile)
|
||||
);
|
||||
}, []);
|
||||
|
||||
useMount(async () => {
|
||||
try {
|
||||
const data = await platformAdapter.invokeBackend<any[]>(
|
||||
"list_coco_servers"
|
||||
);
|
||||
const enabledServers = getEnabledServers(serverList);
|
||||
setList(enabledServers);
|
||||
|
||||
if (isArray(data)) {
|
||||
const enabledServers = data.filter(
|
||||
(s) => s.enabled && s.available && (s.public || s.profile)
|
||||
);
|
||||
|
||||
setServerList(enabledServers);
|
||||
|
||||
if (server) {
|
||||
const matchServer = enabledServers.find((item) => {
|
||||
return item.id === server.id;
|
||||
});
|
||||
|
||||
if (matchServer) {
|
||||
return setServer(matchServer);
|
||||
}
|
||||
}
|
||||
|
||||
setServer(enabledServers[0]);
|
||||
if (enabledServers.length === 0) {
|
||||
setServer(undefined);
|
||||
return;
|
||||
}
|
||||
|
||||
if (server) {
|
||||
const matchServer = enabledServers.find((item) => item.id === server.id);
|
||||
if (matchServer) {
|
||||
setServer(matchServer);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
setServer(enabledServers[0]);
|
||||
} catch (error) {
|
||||
addError(String(error));
|
||||
console.error('Failed to load servers:', error);
|
||||
addError(`Failed to load servers: ${String(error)}`);
|
||||
}
|
||||
});
|
||||
|
||||
useAsyncEffect(async () => {
|
||||
try {
|
||||
if (!server) return;
|
||||
if (!server) {
|
||||
setAssistantList([]);
|
||||
setAssistant(undefined);
|
||||
return;
|
||||
}
|
||||
|
||||
setIsLoadingAssistants(true);
|
||||
try {
|
||||
const data = await fetchAssistant({
|
||||
current: 1,
|
||||
pageSize: 1000,
|
||||
pageSize: 100,
|
||||
serverId: server.id,
|
||||
query: assistantSearchValue,
|
||||
});
|
||||
|
||||
const list = data.list.map((item: any) => item._source);
|
||||
const assistants: Assistant[] = data.list.map((item: any) => item._source);
|
||||
setAssistantList(assistants);
|
||||
|
||||
setAssistantList(list);
|
||||
if (assistants.length === 0) {
|
||||
setAssistant(undefined);
|
||||
return;
|
||||
}
|
||||
|
||||
if (assistant) {
|
||||
const matched = list.find((item: any) => {
|
||||
return item.id === assistant.id;
|
||||
});
|
||||
|
||||
const matched = assistants.find((item) => item.id === assistant.id);
|
||||
if (matched) {
|
||||
return setAssistant(matched);
|
||||
setAssistant(matched);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
setAssistant(list[0]);
|
||||
setAssistant(assistants[0]);
|
||||
} catch (error) {
|
||||
addError(String(error));
|
||||
console.error('Failed to fetch assistants:', error);
|
||||
addError(`Failed to fetch assistants: ${String(error)}`);
|
||||
setAssistantList([]);
|
||||
setAssistant(undefined);
|
||||
} finally {
|
||||
setIsLoadingAssistants(false);
|
||||
}
|
||||
}, [server, assistantSearchValue]);
|
||||
}, [server?.id, assistantSearchValue]);
|
||||
|
||||
const selectList = useMemo(() => {
|
||||
return [
|
||||
{
|
||||
label: t(
|
||||
"settings.extensions.shardAi.details.linkedAssistant.label.cocoServer"
|
||||
),
|
||||
value: server?.id,
|
||||
icon: server?.provider?.icon,
|
||||
data: serverList,
|
||||
searchable: false,
|
||||
onChange: (value: string) => {
|
||||
const matched = serverList.find((item) => item.id === value);
|
||||
|
||||
setServer(matched);
|
||||
},
|
||||
const serverSelectConfig = {
|
||||
label: t(
|
||||
"settings.extensions.shardAi.details.linkedAssistant.label.cocoServer"
|
||||
),
|
||||
value: server?.id,
|
||||
icon: server?.provider?.icon,
|
||||
data: list,
|
||||
searchable: false,
|
||||
onChange: (value: string) => {
|
||||
const matched = list.find((item) => item.id === value);
|
||||
setServer(matched);
|
||||
},
|
||||
{
|
||||
label: t(
|
||||
"settings.extensions.shardAi.details.linkedAssistant.label.aiAssistant"
|
||||
),
|
||||
value: assistant?.id,
|
||||
icon: assistant?.icon,
|
||||
data: assistantList,
|
||||
searchable: true,
|
||||
onChange: (value: string) => {
|
||||
const matched = assistantList.find((item) => item.id === value);
|
||||
onSearch: undefined,
|
||||
};
|
||||
|
||||
setAssistant(matched);
|
||||
},
|
||||
onSearch: (value: string) => {
|
||||
setAssistantSearchValue(value);
|
||||
},
|
||||
const assistantSelectConfig = {
|
||||
label: t(
|
||||
"settings.extensions.shardAi.details.linkedAssistant.label.aiAssistant"
|
||||
),
|
||||
value: assistant?.id,
|
||||
icon: assistant?.icon,
|
||||
data: assistantList,
|
||||
searchable: true,
|
||||
onChange: (value: string) => {
|
||||
const matched = assistantList.find((item) => item.id === value);
|
||||
setAssistant(matched);
|
||||
},
|
||||
];
|
||||
}, [serverList, assistantList, server, assistant]);
|
||||
onSearch: (value: string) => {
|
||||
setAssistantSearchValue(value);
|
||||
},
|
||||
};
|
||||
|
||||
const renderDescription = () => {
|
||||
if (id === "QuickAIAccess") {
|
||||
return t("settings.extensions.quickAiAccess.description");
|
||||
}
|
||||
return [serverSelectConfig, assistantSelectConfig];
|
||||
}, [list, assistantList, server?.id, assistant?.id, t]);
|
||||
|
||||
if (id === "AIOverview") {
|
||||
return t("settings.extensions.aiOverview.description");
|
||||
const renderDescription = useCallback(() => {
|
||||
switch (id) {
|
||||
case "QuickAIAccess":
|
||||
return t("settings.extensions.quickAiAccess.description");
|
||||
case "AIOverview":
|
||||
return t("settings.extensions.aiOverview.description");
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
};
|
||||
}, [id, t]);
|
||||
|
||||
return (
|
||||
<>
|
||||
@@ -154,6 +181,7 @@ const SharedAi: FC<SharedAiProps> = (props) => {
|
||||
searchable={searchable}
|
||||
onChange={onChange}
|
||||
onSearch={onSearch}
|
||||
placeholder={isLoadingAssistants && searchable ? "Loading..." : undefined}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -5,3 +5,7 @@ export const HISTORY_PANEL_ID = "headlessui-popover-panel:history-panel";
|
||||
export const CONTEXT_MENU_PANEL_ID = "headlessui-popover-panel:context-menu";
|
||||
|
||||
export const DEFAULT_COCO_SERVER_ID = "default_coco_server";
|
||||
|
||||
export const MAIN_WINDOW_LABEL = "main";
|
||||
|
||||
export const SETTINGS_WINDOW_LABEL = "settings";
|
||||
|
||||
@@ -82,7 +82,6 @@ export function useChatActions(
|
||||
const [_error, res] = await Post(`/chat/${activeChat?._id}/_close`, {});
|
||||
response = res;
|
||||
}
|
||||
console.log("_close", response);
|
||||
},
|
||||
[currentService?.id, isTauri]
|
||||
);
|
||||
@@ -130,7 +129,6 @@ export function useChatActions(
|
||||
);
|
||||
response = res;
|
||||
}
|
||||
console.log("_cancel", response);
|
||||
},
|
||||
[currentService?.id, isTauri]
|
||||
);
|
||||
@@ -176,7 +174,6 @@ export function useChatActions(
|
||||
...chat,
|
||||
messages: hits,
|
||||
};
|
||||
console.log("id_history", updatedChat);
|
||||
updatedChatRef.current = updatedChat;
|
||||
setActiveChat(updatedChat);
|
||||
callback && callback(updatedChat);
|
||||
@@ -260,20 +257,6 @@ export function useChatActions(
|
||||
`chat-stream-${clientId}-${timestamp}`,
|
||||
(event) => {
|
||||
const msg = event.payload as string;
|
||||
try {
|
||||
// console.log("msg:", JSON.parse(msg));
|
||||
// console.log("user:", msg.includes(`"user"`));
|
||||
// console.log("_source:", msg.includes("_source"));
|
||||
// console.log("result:", msg.includes("result"));
|
||||
// console.log("");
|
||||
// console.log("");
|
||||
// console.log("");
|
||||
// console.log("");
|
||||
// console.log("");
|
||||
} catch (error) {
|
||||
console.error("Failed to parse JSON in listener:", error);
|
||||
}
|
||||
|
||||
handleChatCreateStreamMessage(msg);
|
||||
}
|
||||
);
|
||||
@@ -480,7 +463,6 @@ export function useChatActions(
|
||||
response = res;
|
||||
}
|
||||
|
||||
console.log("_open", response);
|
||||
return response;
|
||||
},
|
||||
[currentService?.id, isTauri]
|
||||
@@ -509,7 +491,6 @@ export function useChatActions(
|
||||
response = res;
|
||||
}
|
||||
|
||||
console.log("_history", response);
|
||||
const hits = response?.hits?.hits || [];
|
||||
setChats(hits);
|
||||
}, [
|
||||
|
||||
105
src/hooks/useServers.ts
Normal file
105
src/hooks/useServers.ts
Normal file
@@ -0,0 +1,105 @@
|
||||
import { useEffect, useCallback } from "react";
|
||||
|
||||
import { useConnectStore } from "@/stores/connectStore";
|
||||
import platformAdapter from "@/utils/platformAdapter";
|
||||
import type { Server } from "@/types/server";
|
||||
import {
|
||||
getCurrentWindowService,
|
||||
setCurrentWindowService,
|
||||
handleLogout,
|
||||
} from "@/commands/servers";
|
||||
|
||||
export const useServers = () => {
|
||||
const setServerList = useConnectStore((state) => state.setServerList);
|
||||
const currentService = useConnectStore((state) => state.currentService);
|
||||
const cloudSelectService = useConnectStore((state) => {
|
||||
return state.cloudSelectService;
|
||||
});
|
||||
|
||||
const getAllServerList = async () => {
|
||||
try {
|
||||
const res = await platformAdapter.commands("list_coco_servers");
|
||||
if (!Array.isArray(res)) {
|
||||
// If res is not an array, it might be an error message or something else.
|
||||
// Log it and don't proceed.
|
||||
console.warn("Invalid server list response:", res);
|
||||
setServerList([]); // Clear the list or handle as appropriate
|
||||
return;
|
||||
}
|
||||
setServerList(res);
|
||||
} catch (error) {
|
||||
console.error("Failed to fetch server list:", error);
|
||||
setServerList([]);
|
||||
}
|
||||
};
|
||||
|
||||
const addServer = useCallback(
|
||||
async (endpointLink: string): Promise<Server> => {
|
||||
if (!endpointLink) {
|
||||
throw new Error("Endpoint is required");
|
||||
}
|
||||
if (
|
||||
!endpointLink.startsWith("http://") &&
|
||||
!endpointLink.startsWith("https://")
|
||||
) {
|
||||
throw new Error("Invalid Endpoint");
|
||||
}
|
||||
|
||||
const res: Server = await platformAdapter.commands(
|
||||
"add_coco_server",
|
||||
endpointLink
|
||||
);
|
||||
await getAllServerList();
|
||||
await setCurrentWindowService(res);
|
||||
return res;
|
||||
},
|
||||
[]
|
||||
);
|
||||
|
||||
const enableServer = useCallback(
|
||||
async (enabled: boolean) => {
|
||||
const service = await getCurrentWindowService();
|
||||
|
||||
if (!service?.id) {
|
||||
throw new Error("No current service selected");
|
||||
}
|
||||
|
||||
if (enabled) {
|
||||
await platformAdapter.commands("enable_server", service.id);
|
||||
} else {
|
||||
await platformAdapter.commands("disable_server", service.id);
|
||||
}
|
||||
|
||||
await setCurrentWindowService({ ...service, enabled });
|
||||
await getAllServerList();
|
||||
},
|
||||
[currentService, cloudSelectService]
|
||||
);
|
||||
|
||||
const removeServer = useCallback(
|
||||
async (id: string) => {
|
||||
await platformAdapter.commands("remove_coco_server", id);
|
||||
await getAllServerList();
|
||||
},
|
||||
[currentService?.id, cloudSelectService?.id]
|
||||
);
|
||||
|
||||
const logoutServer = useCallback(async (id: string) => {
|
||||
await platformAdapter.commands("logout_coco_server", id);
|
||||
handleLogout(id);
|
||||
await getAllServerList();
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
getAllServerList();
|
||||
}, [currentService?.enabled, cloudSelectService?.enabled]);
|
||||
|
||||
return {
|
||||
getAllServerList,
|
||||
refreshServerList: getAllServerList,
|
||||
addServer,
|
||||
enableServer,
|
||||
removeServer,
|
||||
logoutServer,
|
||||
};
|
||||
};
|
||||
@@ -1,3 +1,6 @@
|
||||
import { isNumber } from "lodash-es";
|
||||
import { useEffect } from "react";
|
||||
|
||||
import { useAppearanceStore } from "@/stores/appearanceStore";
|
||||
import { useAppStore } from "@/stores/appStore";
|
||||
import { useConnectStore } from "@/stores/connectStore";
|
||||
@@ -5,8 +8,6 @@ import { useExtensionsStore } from "@/stores/extensionsStore";
|
||||
import { useShortcutsStore } from "@/stores/shortcutsStore";
|
||||
import { useStartupStore } from "@/stores/startupStore";
|
||||
import platformAdapter from "@/utils/platformAdapter";
|
||||
import { isNumber } from "lodash-es";
|
||||
import { useEffect } from "react";
|
||||
|
||||
export const useSyncStore = () => {
|
||||
const setModifierKey = useShortcutsStore((state) => {
|
||||
@@ -60,8 +61,8 @@ export const useSyncStore = () => {
|
||||
const setFixedWindow = useShortcutsStore((state) => {
|
||||
return state.setFixedWindow;
|
||||
});
|
||||
const setServiceList = useShortcutsStore((state) => {
|
||||
return state.setServiceList;
|
||||
const setServiceListShortcut = useShortcutsStore((state) => {
|
||||
return state.setServiceListShortcut;
|
||||
});
|
||||
const setExternal = useShortcutsStore((state) => {
|
||||
return state.setExternal;
|
||||
@@ -143,7 +144,7 @@ export const useSyncStore = () => {
|
||||
aiAssistant,
|
||||
newSession,
|
||||
fixedWindow,
|
||||
serviceList,
|
||||
serviceListShortcut,
|
||||
external,
|
||||
aiOverview,
|
||||
} = payload;
|
||||
@@ -162,7 +163,7 @@ export const useSyncStore = () => {
|
||||
setAiAssistant(aiAssistant);
|
||||
setNewSession(newSession);
|
||||
setFixedWindow(fixedWindow);
|
||||
setServiceList(serviceList);
|
||||
setServiceListShortcut(serviceListShortcut);
|
||||
setExternal(external);
|
||||
setAiOverview(aiOverview);
|
||||
}),
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import type { I } from '../index.d';
|
||||
import SVGWrap from "./SVGWrap";
|
||||
|
||||
export default function History(props: I.SVG) {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import type { I } from '../index.d';
|
||||
import SVGWrap from "./SVGWrap";
|
||||
|
||||
export default function Pin(props: I.SVG) {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import type { I } from '../index.d';
|
||||
import SVGWrap from "./SVGWrap";
|
||||
|
||||
export default function PinOff(props: I.SVG) {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import type { I } from '../index.d';
|
||||
import SVGWrap from "./SVGWrap";
|
||||
|
||||
export default function Reading(props: I.SVG) {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import type { I } from '../index.d';
|
||||
import SVGWrap from "./SVGWrap";
|
||||
|
||||
export default function Retrieve(props: I.SVG) {
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import React from "react";
|
||||
import clsx from "clsx";
|
||||
|
||||
import type { I } from '../index.d';
|
||||
|
||||
export default function SVGWrap({
|
||||
size = 18,
|
||||
children,
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import type { I } from '../index.d';
|
||||
import SVGWrap from "./SVGWrap";
|
||||
|
||||
export default function Selection(props: I.SVG) {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import type { I } from '../index.d';
|
||||
import SVGWrap from "./SVGWrap";
|
||||
|
||||
export default function Server(props: I.SVG) {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import type { I } from '../index.d';
|
||||
import SVGWrap from "./SVGWrap";
|
||||
|
||||
export default function Stop(props: I.SVG) {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import type { I } from '../index.d';
|
||||
import SVGWrap from "./SVGWrap";
|
||||
|
||||
export default function Understand(props: I.SVG) {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import type { I } from '../index.d';
|
||||
import SVGWrap from "./SVGWrap";
|
||||
|
||||
export default function WindowsFull(props: I.SVG) {
|
||||
|
||||
77
src/index.d.ts
vendored
77
src/index.d.ts
vendored
@@ -1,3 +1,5 @@
|
||||
import type { IConfig } from "@/utils/console-custom";
|
||||
|
||||
declare namespace I {
|
||||
export type AppConf = {
|
||||
theme: "light" | "dark" | "auto";
|
||||
@@ -17,40 +19,49 @@ declare namespace I {
|
||||
|
||||
declare global {
|
||||
interface Window {
|
||||
__TAURI__: Record<string, unknown>;
|
||||
__TAURI__?: {
|
||||
writeText(text: string): Promise<void>;
|
||||
invoke(command: string, payload?: Record<string, unknown>): Promise<any>;
|
||||
dialog: {
|
||||
save(options?: Record<string, unknown>): Promise<string | null>;
|
||||
};
|
||||
fs: {
|
||||
writeBinaryFile(path: string, data: Uint8Array): Promise<void>;
|
||||
writeTextFile(path: string, data: string): Promise<void>;
|
||||
};
|
||||
notification: {
|
||||
requestPermission(): Promise<Permission>;
|
||||
isPermissionGranted(): Promise<boolean>;
|
||||
sendNotification(options: string | Options): void;
|
||||
};
|
||||
updater: {
|
||||
checkUpdate(): Promise<UpdateResult>;
|
||||
installUpdate(): Promise<void>;
|
||||
onUpdaterEvent(
|
||||
handler: (status: UpdateStatusResult) => void
|
||||
): Promise<UnlistenFn>;
|
||||
};
|
||||
http: {
|
||||
fetch<T>(
|
||||
url: string,
|
||||
options?: Record<string, unknown>
|
||||
): Promise<Response<T>>;
|
||||
};
|
||||
};
|
||||
__TAURI_INTERNALS__?: any;
|
||||
__TAURI_OS_PLUGIN_INTERNALS__?: any;
|
||||
}
|
||||
}
|
||||
|
||||
declare interface Window {
|
||||
__TAURI__?: {
|
||||
writeText(text: string): Promise<void>;
|
||||
invoke(command: string, payload?: Record<string, unknown>): Promise<any>;
|
||||
dialog: {
|
||||
save(options?: Record<string, unknown>): Promise<string | null>;
|
||||
};
|
||||
fs: {
|
||||
writeBinaryFile(path: string, data: Uint8Array): Promise<void>;
|
||||
writeTextFile(path: string, data: string): Promise<void>;
|
||||
};
|
||||
notification: {
|
||||
requestPermission(): Promise<Permission>;
|
||||
isPermissionGranted(): Promise<boolean>;
|
||||
sendNotification(options: string | Options): void;
|
||||
};
|
||||
updater: {
|
||||
checkUpdate(): Promise<UpdateResult>;
|
||||
installUpdate(): Promise<void>;
|
||||
onUpdaterEvent(
|
||||
handler: (status: UpdateStatusResult) => void,
|
||||
): Promise<UnlistenFn>;
|
||||
};
|
||||
http: {
|
||||
fetch<T>(
|
||||
url: string,
|
||||
options?: Record<string, unknown>,
|
||||
): Promise<Response<T>>;
|
||||
};
|
||||
};
|
||||
bLog: (...data: any[]) => void;
|
||||
infoLog: (
|
||||
config?: Partial<import("./utils/console-custom").IConfig>
|
||||
) => (...data: any[]) => void;
|
||||
createLogger: typeof import("./utils/console-custom").default;
|
||||
}
|
||||
|
||||
// global variable declarations
|
||||
var bLog: (...data: any[]) => void;
|
||||
var infoLog: (
|
||||
config?: Partial<import("./utils/console-custom").IConfig>
|
||||
) => (...data: any[]) => void;
|
||||
var createLogger: typeof import("./utils/console-custom").default;
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ import { RouterProvider } from "react-router-dom";
|
||||
|
||||
import { router } from "./routes/index";
|
||||
import "./i18n";
|
||||
import '@/utils/global-logger';
|
||||
|
||||
import "./main.css";
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ import { useModifierKeyPress } from "@/hooks/useModifierKeyPress";
|
||||
import { useIconfontScript } from "@/hooks/useScript";
|
||||
import { Extension } from "@/components/Settings/Extensions";
|
||||
import { useExtensionsStore } from "@/stores/extensionsStore";
|
||||
import { useServers } from "@/hooks/useServers";
|
||||
|
||||
export default function Layout() {
|
||||
const location = useLocation();
|
||||
@@ -27,6 +28,10 @@ export default function Layout() {
|
||||
const { language } = useAppStore();
|
||||
const { i18n } = useTranslation();
|
||||
const { activeTheme, isDark, setIsDark, setTheme } = useThemeStore();
|
||||
|
||||
// init servers isTauri
|
||||
useServers();
|
||||
|
||||
const [langUpdated, setLangUpdated] = useState(false);
|
||||
|
||||
useAsyncEffect(async () => {
|
||||
|
||||
@@ -3,7 +3,7 @@ import { persist, subscribeWithSelector } from "zustand/middleware";
|
||||
import { produce } from "immer";
|
||||
|
||||
import platformAdapter from "@/utils/platformAdapter";
|
||||
import { Server } from "@/types/server";
|
||||
import type { Server } from "@/types/server";
|
||||
|
||||
const CONNECTOR_CHANGE_EVENT = "connector_data_change";
|
||||
const DATASOURCE_CHANGE_EVENT = "datasourceData_change";
|
||||
@@ -17,6 +17,8 @@ export type IConnectStore = {
|
||||
setServerList: (servers: Server[]) => void;
|
||||
currentService: Server;
|
||||
setCurrentService: (service: Server) => void;
|
||||
cloudSelectService: Server;
|
||||
setCloudSelectService: (service: Server) => void;
|
||||
connector_data: keyArrayObject;
|
||||
setConnectorData: (connector_data: any[], key: string) => void;
|
||||
datasourceData: keyArrayObject;
|
||||
@@ -43,7 +45,6 @@ export const useConnectStore = create<IConnectStore>()(
|
||||
(set) => ({
|
||||
serverList: [],
|
||||
setServerList: (serverList: Server[]) => {
|
||||
console.log("set serverList:", serverList);
|
||||
set(
|
||||
produce((draft) => {
|
||||
draft.serverList = serverList;
|
||||
@@ -52,13 +53,20 @@ export const useConnectStore = create<IConnectStore>()(
|
||||
},
|
||||
currentService: {} as Server,
|
||||
setCurrentService: (server: any) => {
|
||||
console.log("set default server:", server);
|
||||
set(
|
||||
produce((draft) => {
|
||||
draft.currentService = server;
|
||||
})
|
||||
);
|
||||
},
|
||||
cloudSelectService: {} as Server,
|
||||
setCloudSelectService: (server: any) => {
|
||||
set(
|
||||
produce((draft) => {
|
||||
draft.cloudSelectService = server;
|
||||
})
|
||||
);
|
||||
},
|
||||
connector_data: {},
|
||||
setConnectorData: async (connector_data: any[], key: string) => {
|
||||
set(
|
||||
@@ -130,7 +138,9 @@ export const useConnectStore = create<IConnectStore>()(
|
||||
{
|
||||
name: "connect-store",
|
||||
partialize: (state) => ({
|
||||
serverList: state.serverList,
|
||||
currentService: state.currentService,
|
||||
cloudSelectService: state.cloudSelectService,
|
||||
connector_data: state.connector_data,
|
||||
datasourceData: state.datasourceData,
|
||||
connectionTimeout: state.connectionTimeout,
|
||||
|
||||
@@ -37,8 +37,8 @@ export type IShortcutsStore = {
|
||||
setNewSession: (newSession: string) => void;
|
||||
fixedWindow: string;
|
||||
setFixedWindow: (fixedWindow: string) => void;
|
||||
serviceList: string;
|
||||
setServiceList: (serviceList: string) => void;
|
||||
serviceListShortcut: string;
|
||||
setServiceListShortcut: (serviceListShortcut: string) => void;
|
||||
external: string;
|
||||
setExternal: (external: string) => void;
|
||||
resetFixedWindow: boolean;
|
||||
@@ -109,8 +109,8 @@ export const useShortcutsStore = create<IShortcutsStore>()(
|
||||
setNewSession: (newSession) => set({ newSession }),
|
||||
fixedWindow: INITIAL_FIXED_WINDOW,
|
||||
setFixedWindow: (fixedWindow) => set({ fixedWindow }),
|
||||
serviceList: INITIAL_SERVICE_LIST,
|
||||
setServiceList: (serviceList) => set({ serviceList }),
|
||||
serviceListShortcut: INITIAL_SERVICE_LIST,
|
||||
setServiceListShortcut: (serviceListShortcut) => set({ serviceListShortcut }),
|
||||
external: INITIAL_EXTERNAL,
|
||||
setExternal: (external) => set({ external }),
|
||||
resetFixedWindow: false,
|
||||
@@ -137,7 +137,7 @@ export const useShortcutsStore = create<IShortcutsStore>()(
|
||||
aiAssistant: state.aiAssistant,
|
||||
newSession: state.newSession,
|
||||
fixedWindow: state.fixedWindow,
|
||||
serviceList: state.serviceList,
|
||||
serviceListShortcut: state.serviceListShortcut,
|
||||
external: state.external,
|
||||
resetFixedWindow: state.resetFixedWindow,
|
||||
}),
|
||||
|
||||
@@ -24,7 +24,7 @@ interface MinimalClientVersion {
|
||||
export type Status = 'green' | 'yellow' | 'red';
|
||||
|
||||
interface Health {
|
||||
services?: Record<string, Status>;
|
||||
services?: Record<string, any>;
|
||||
status: Status;
|
||||
}
|
||||
|
||||
|
||||
145
src/utils/console-custom.ts
Normal file
145
src/utils/console-custom.ts
Normal file
@@ -0,0 +1,145 @@
|
||||
export interface IConfig {
|
||||
logType?: string;
|
||||
username?: string;
|
||||
logName?: string;
|
||||
usernameColor?: string;
|
||||
logNameColor?: string;
|
||||
padding?: number;
|
||||
borderRadius?: number;
|
||||
fontColor?: string;
|
||||
usernameStyle?: string;
|
||||
logNameStyle?: string;
|
||||
}
|
||||
|
||||
const GourdBabyColorMap = new Map([
|
||||
["1", "#FF0000"],
|
||||
["2", "#FFA500"],
|
||||
["3", "#FFFF00"],
|
||||
["4", "#008000"],
|
||||
["5", "#00FFFF"],
|
||||
["6", "#0000FF"],
|
||||
["7", "#800080"],
|
||||
]);
|
||||
|
||||
const createBLog = (config: IConfig) => {
|
||||
const logType = config.logType || "default";
|
||||
const username = config.username || "";
|
||||
const logName = config.logName || "";
|
||||
const usernameColor = config.usernameColor || "#41b883";
|
||||
const logNameColor = config.logNameColor || "#35495e";
|
||||
const padding = config.padding || 6;
|
||||
const borderRadius = config.borderRadius || 6;
|
||||
const fontColor = config.fontColor || "#FFFFFF";
|
||||
const usernameStyle = config.usernameStyle || "";
|
||||
const logNameStyle = config.logNameStyle || "";
|
||||
|
||||
const logTemplate = (username = "myLog", logName = "") =>
|
||||
`${username ? "%c" + username : ""} ${logName ? "%c" + logName : ""} `;
|
||||
|
||||
const customLog = (...data: any[]) => {
|
||||
console.log(
|
||||
logTemplate(username, logName),
|
||||
usernameStyle
|
||||
? usernameStyle
|
||||
: `background: ${usernameColor}; padding: 6px; border-radius: 6px 0 0 6px; color: #fff`,
|
||||
logNameStyle
|
||||
? logNameStyle
|
||||
: `background: ${logNameColor}; padding: 6px; border-radius: 0 6px 6px 0; color: #fff`,
|
||||
...data
|
||||
);
|
||||
};
|
||||
|
||||
const defaultLog = (...data: any[]) => {
|
||||
const len = data.length;
|
||||
if (len > 1) {
|
||||
data.map((item, index) => {
|
||||
let firstStyle = `
|
||||
background: ${GourdBabyColorMap.get((index % 7) + 1 + "")};
|
||||
padding: ${padding}px;
|
||||
border-radius: 0 0;
|
||||
color: ${fontColor}
|
||||
`;
|
||||
let secondStyle = `
|
||||
background: ${logNameColor};
|
||||
padding: ${padding}px;
|
||||
border-radius: 0 0;
|
||||
color: ${fontColor}
|
||||
`;
|
||||
if (index === 0) {
|
||||
firstStyle = `
|
||||
background: ${GourdBabyColorMap.get((index % 7) + 1 + "")};
|
||||
padding: ${padding}px;
|
||||
margin-top: ${padding * 2}px;
|
||||
border-radius: ${borderRadius}px 0 0 0;
|
||||
color: ${fontColor}
|
||||
`;
|
||||
secondStyle = `
|
||||
background: ${logNameColor};
|
||||
padding: ${padding}px;
|
||||
margin-top: ${padding * 2}px;
|
||||
border-radius: 0 ${borderRadius}px 0 0;
|
||||
color: ${fontColor}
|
||||
`;
|
||||
} else if (index === len - 1) {
|
||||
firstStyle = `
|
||||
background: ${GourdBabyColorMap.get((index % 7) + 1 + "")};
|
||||
padding: ${padding}px;
|
||||
margin-bottom: ${padding * 2}px;
|
||||
border-radius: 0 0 0 ${borderRadius}px;
|
||||
color: ${fontColor}
|
||||
`;
|
||||
secondStyle = `
|
||||
background: ${logNameColor};
|
||||
padding: ${padding}px;
|
||||
margin-bottom: ${padding * 2}px;
|
||||
border-radius: 0 0 ${borderRadius}px 0;
|
||||
color: ${fontColor}
|
||||
`;
|
||||
}
|
||||
console.log(
|
||||
logTemplate(username, `data${index + 1}`),
|
||||
firstStyle,
|
||||
secondStyle,
|
||||
item
|
||||
);
|
||||
});
|
||||
} else {
|
||||
const firstStyle = `
|
||||
background: ${usernameColor};
|
||||
padding: ${padding}px;
|
||||
border-radius: ${borderRadius}px 0 0 ${borderRadius}px;
|
||||
color: ${fontColor}
|
||||
`;
|
||||
|
||||
const secondStyle = `
|
||||
background: ${logNameColor};
|
||||
padding: ${padding}px;
|
||||
border-radius: 0 ${borderRadius}px ${borderRadius}px 0;
|
||||
color: ${fontColor}
|
||||
`;
|
||||
|
||||
console.log(
|
||||
logTemplate(username, logName),
|
||||
firstStyle,
|
||||
secondStyle,
|
||||
...data
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
const log = (...data: any[]) => {
|
||||
switch (logType) {
|
||||
case "custom":
|
||||
customLog(...data);
|
||||
break;
|
||||
default:
|
||||
defaultLog(...data);
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
log,
|
||||
};
|
||||
};
|
||||
|
||||
export default createBLog;
|
||||
37
src/utils/global-logger.ts
Normal file
37
src/utils/global-logger.ts
Normal file
@@ -0,0 +1,37 @@
|
||||
import createBLog, { IConfig } from './console-custom';
|
||||
|
||||
// default config
|
||||
const defaultConfig: IConfig = {
|
||||
logType: 'custom',
|
||||
usernameColor: '#41b883',
|
||||
logNameColor: '#35495e'
|
||||
};
|
||||
|
||||
// create a flexible logger function
|
||||
const createLogFunction = (defaultLogConfig: Partial<IConfig> = {}) => {
|
||||
return (config: Partial<IConfig> = {}) => {
|
||||
const finalConfig = {
|
||||
...defaultConfig,
|
||||
...defaultLogConfig,
|
||||
...config
|
||||
};
|
||||
return createBLog(finalConfig).log;
|
||||
};
|
||||
};
|
||||
|
||||
// export convenient methods
|
||||
export const bLog = createBLog(defaultConfig).log;
|
||||
export const createLogger = createBLog;
|
||||
|
||||
// create a flexible logger function
|
||||
export const infoLog = createLogFunction({
|
||||
logName: 'Info',
|
||||
logNameColor: '#28a745'
|
||||
});
|
||||
|
||||
// register global logger
|
||||
if (typeof window !== 'undefined') {
|
||||
(window as any).bLog = bLog;
|
||||
(window as any).infoLog = infoLog;
|
||||
(window as any).createLogger = createLogger;
|
||||
}
|
||||
@@ -25,6 +25,7 @@ export interface TauriPlatformAdapter extends BasePlatformAdapter {
|
||||
) => Promise<string | string[] | null>;
|
||||
metadata: typeof metadata;
|
||||
error: typeof error;
|
||||
getCurrentWindowLabel: () => Promise<string>;
|
||||
}
|
||||
|
||||
// Create Tauri adapter functions
|
||||
@@ -79,8 +80,8 @@ export const createTauriAdapter = (): TauriPlatformAdapter => {
|
||||
const { getCurrentWindow } = await import("@tauri-apps/api/window");
|
||||
const window = getCurrentWindow();
|
||||
return window.setAlwaysOnTop(isPinned);
|
||||
},
|
||||
|
||||
},
|
||||
|
||||
async toggleMoveToActiveSpaceAttribute() {
|
||||
if (isMac) {
|
||||
return toggle_move_to_active_space_attribute();
|
||||
@@ -340,5 +341,10 @@ export const createTauriAdapter = (): TauriPlatformAdapter => {
|
||||
queryParams,
|
||||
});
|
||||
},
|
||||
|
||||
async getCurrentWindowLabel() {
|
||||
const window = await windowWrapper.getWebviewWindow();
|
||||
return window.label;
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user