Files
coco-app/src/utils/webAdapter.ts

280 lines
7.1 KiB
TypeScript
Raw Normal View History

import type { BasePlatformAdapter } from "@/types/platform";
import { copyToClipboard, OpenURLWithBrowser } from ".";
import { Post } from "@/api/axiosRequest";
export interface WebPlatformAdapter extends BasePlatformAdapter {
// Add web-specific methods here
openFileDialog: (options: any) => Promise<string | string[] | null>;
metadata: (path: string, options: any) => Promise<Record<string, any>>;
error: (message: string) => void;
2025-10-13 16:43:29 +08:00
openLogDir: () => Promise<void>;
getCurrentWebviewWindow: () => Promise<any>;
getWindowTheme: () => Promise<string>;
setWindowTheme: (theme: string | null) => Promise<void>;
getAllWindows: () => Promise<any[]>;
}
// Create Web adapter functions
export const createWebAdapter = (): WebPlatformAdapter => {
return {
async commands(commandName, ...args) {
console.warn(
`Command "${commandName}" is not supported in web environment`,
args
);
return Promise.reject(new Error("Not supported in web environment"));
},
async invokeBackend(command, args) {
console.log(`Web mode simulated backend call: ${command}`, args);
// Implement web environment simulation logic or API calls here
return null as any;
},
async setWindowSize(width, height) {
console.log(`Web mode simulated window resize: ${width}x${height}`);
// No actual operation needed in web environment
},
async hideWindow() {
console.log("Web mode simulated window hide");
// No actual operation needed in web environment
},
async showWindow() {
console.log("Web mode simulated window show");
// No actual operation needed in web environment
},
convertFileSrc(path) {
return path;
},
async emitEvent(event, payload) {
console.log("Web mode simulated event emit", event, payload);
},
async listenEvent(event, _callback) {
console.log("Web mode simulated event listen", event);
return () => {};
},
async setAlwaysOnTop(isPinned) {
console.log("Web mode simulated set always on top", isPinned);
},
async checkScreenRecordingPermission() {
console.log("Web mode simulated check screen recording permission");
return false;
},
async checkMicrophonePermission() {
return false;
},
async requestMicrophonePermission() {
return false;
},
requestScreenRecordingPermission() {
console.log("Web mode simulated request screen recording permission");
},
async getScreenshotableMonitors() {
console.log("Web mode simulated get screenshotable monitors");
return [];
},
async getScreenshotableWindows() {
console.log("Web mode simulated get screenshotable windows");
return [];
},
async captureMonitorScreenshot(id) {
console.log("Web mode simulated capture monitor screenshot", id);
return "";
},
async captureWindowScreenshot(id) {
console.log("Web mode simulated capture window screenshot", id);
return "";
},
async openFileDialog(options) {
console.log("Web mode simulated open file dialog", options);
return null;
},
async getFileMetadata(path) {
console.log("Web mode simulated get file metadata", path);
return null;
},
async getFileIcon(path, size) {
console.log("Web mode simulated get file icon", path, size);
return "";
},
async checkUpdate() {
return null;
},
async relaunchApp() {
console.log("Web mode simulated relaunch app");
},
async listenThemeChanged() {
console.log("Web mode simulated theme change listener");
return () => {};
},
async setWindowTheme(theme) {
console.log("Web mode simulated set window theme:", theme);
},
async getWindowTheme() {
console.log("Web mode simulated get window theme");
return "light";
},
async onThemeChanged(callback) {
console.log("Web mode simulated on theme changed", callback);
},
async getWindowByLabel(label) {
console.log("Web mode simulated get window by label:", label);
return null;
},
async createWindow(label, options) {
console.log("Web mode simulated create window:", label, options);
},
async getAllWindows() {
console.log("Web mode simulated get all windows");
return [];
},
async getCurrentWebviewWindow() {
console.log("Web mode simulated get current window");
return null;
},
async createWebviewWindow(label, options) {
console.log("Web mode simulated create webview window:", label, options);
return null;
},
async listenWindowEvent(event, _callback) {
console.log("Web mode simulated listen window event:", event);
return () => {};
},
isTauri() {
return false;
},
async openUrl(url) {
console.log(`Web mode opening URL: ${url}`);
window.open(url, "_blank");
},
isWindows10: async () => false,
async setShadow(enable) {
console.log("setShadow is not supported in web environment", enable);
return Promise.resolve();
},
async metadata(path, options = {}) {
console.log(
"metadata is not supported in web environment",
path,
options
);
2025-06-03 19:28:26 +08:00
return Promise.resolve({ isAbsolute: false });
},
async revealItemInDir(path) {
console.log("revealItemInDir is not supported in web environment", path);
},
async openSearchItem(data, formatUrl) {
if (data.type === "AI Assistant") {
return;
}
const url = (formatUrl && formatUrl(data)) || data.url;
if (url) {
return OpenURLWithBrowser(url);
}
if (data?.payload?.result?.value) {
return copyToClipboard(data.payload.result.value);
}
},
error: console.error,
async searchMCPServers(_serverId, queryParams) {
const [error, res]: any = await Post(
`/mcp_server/_search?${queryParams?.join("&")}`,
undefined
);
if (error) {
console.error("_search", error);
return [];
}
return (
res?.hits?.hits?.map((item: any) => ({
...item,
id: item._source.id,
name: item._source.name,
})) || []
);
},
async searchDataSources(_serverId, queryParams) {
const [error, res]: any = await Post(
`/datasource/_search?${queryParams?.join("&")}`,
undefined
);
if (error) {
console.error("_search", error);
return [];
}
return (
res?.hits?.hits?.map((item: any) => ({
...item,
id: item._source.id,
name: item._source.name,
})) || []
);
},
async fetchAssistant(_serverId, queryParams) {
const [error, res]: any = await Post(
`/assistant/_search?${queryParams?.join("&")}`,
undefined
);
if (error) {
console.error("_search", error);
return {};
}
return res;
},
async getCurrentWindowLabel() {
return "web";
},
2025-10-13 16:43:29 +08:00
async openLogDir() {
console.log("openLogDir is not supported in web environment");
return Promise.resolve();
},
};
feat: selection settings add & delete (#992) * feat: add selection window page * fix: chat input * feat: add selection page * chore: add * chore: test * feat: add * feat: add store * feat: add selection settings * chore: remove unused code * docs: add release note * docs: add release note * chore: format code * chore: format code * fix: copy error * disable hashbrown default feature * Enable unstable feature allocator_api To make coco-app compile in CI: ``` --> /home/runner/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/hashbrown-0.15.5/src/raw/mod.rs:3856:12 | 3856 | impl<T, A: Allocator> RawIntoIter<T, A> { | ^^^^^^^^^ | = note: see issue #32838 <https://github.com/rust-lang/rust/issues/32838> for more information = help: add `#![feature(allocator_api)]` to the crate attributes to enable = note: this compiler was built on 2025-06-25; consider upgrading it if it is out of date ``` I don't know why it does not compile, feature `allocator-api2` is enabled for `hashbrown 0.15.5`, so technically [1] it should not use the allocator APIs from the std. According to [2], enabling the `nightly` feature of `allocator-api2` may cause this issue as well, but it is not enabled in our case either. Anyway, enabling `#![feature(allocator_api)]` should make it work. [1]: https://github.com/rust-lang/hashbrown/blob/b751eef8e99ccf3652046ef4a9e1ec47c1bfb78d/src/raw/alloc.rs#L26-L47 [2]: https://github.com/rust-lang/hashbrown/issues/564 * put it in main.rs * format main.rs * Enable default-features for hashbrown 0.15.5 * format main.rs * enable feature allocator-api2 * feat: add selection set config * fix: selection setting * fix: ci error * fix: ci error * fix: ci error * fix: ci error * merge: merge main * fix: rust code warn * fix: rust code error * fix: rust code error * fix: selection settings * style: selection styles * style: selection styles * feat: selection settings add & delete * feat: selection settings add & delete * feat: selection settings add & delete * style: selection styles * chore: add @tauri-store/zustand plugin * refactor: the selection store using @tauri-store/zustand * fix: data error * fix: data error * chore: remove config * chore: selection * chore: selection * chore: width * chore: ignore selection in the app itself * style: selection styles * style: remove * docs: add notes * chore: add permission check * chore: selection * chore: style & store --------- Co-authored-by: Steve Lau <stevelauc@outlook.com>
2025-12-05 15:32:57 +08:00
};