From fc62b3e4efcd8ed2fd4fe1c0b1a19caccff5f03e Mon Sep 17 00:00:00 2001 From: Nayan Lakhwani Date: Tue, 3 Dec 2024 18:26:06 +0530 Subject: [PATCH 01/56] feat: added support for app-based simple login[] --- apps/@sparrow-desktop/src/components/App.svelte | 3 ++- apps/@sparrow-desktop/src/constants/constants.ts | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/apps/@sparrow-desktop/src/components/App.svelte b/apps/@sparrow-desktop/src/components/App.svelte index 482071798..c0be43207 100644 --- a/apps/@sparrow-desktop/src/components/App.svelte +++ b/apps/@sparrow-desktop/src/components/App.svelte @@ -15,6 +15,7 @@ import LoginPage from "@app/pages/auth-page/sub-pages/login-page/LoginPage.svelte"; import { singleInstanceHandler } from "@app/utils/singleinstance/app.singleinstance"; import { AppViewModel } from "./app.ViewModel"; + import constants from "@app/constants/constants"; const _viewModel = new AppViewModel(); @@ -76,7 +77,7 @@
- {#if 1} + {#if constants.SIMPLIFIED_LOGIN != "true"} diff --git a/apps/@sparrow-desktop/src/constants/constants.ts b/apps/@sparrow-desktop/src/constants/constants.ts index d23cccb91..ff8f29eb8 100644 --- a/apps/@sparrow-desktop/src/constants/constants.ts +++ b/apps/@sparrow-desktop/src/constants/constants.ts @@ -22,6 +22,7 @@ const constants = { AZURE_INSIGHTS_CONNECTION_STRING: import.meta.env .VITE_AZURE_INSIGHTS_CONNECTION_STRING, BASE_URL: import.meta.env.VITE_BASE_URL, + SIMPLIFIED_LOGIN: import.meta.env.VITE_SIMPLIFIED_LOGIN, }; export default constants; From 8a750774d73afda70d881b22303259f73a7ce156 Mon Sep 17 00:00:00 2001 From: Harsh Date: Mon, 16 Dec 2024 15:27:59 +0530 Subject: [PATCH 02/56] feat: websocket functionality in browser agent --- .../src/containers/api/api.common.ts | 331 ++++++++++++------ .../WebSocketExplorerPage.ViewModel.ts | 54 +-- .../src/services/collection.service.ts | 17 + 3 files changed, 275 insertions(+), 127 deletions(-) diff --git a/apps/@sparrow-web/src/containers/api/api.common.ts b/apps/@sparrow-web/src/containers/api/api.common.ts index ba4b4cde1..fd271a0a7 100644 --- a/apps/@sparrow-web/src/containers/api/api.common.ts +++ b/apps/@sparrow-web/src/containers/api/api.common.ts @@ -245,41 +245,66 @@ function formatTime(date) { * */ const sendMessage = async (tab_id: string, message: string) => { - // debugger; - await invoke("send_websocket_message", { tabid: tab_id, message: message }) - .then(async (data: string) => { - try { - // Logic to handle response + const selectedAgent = localStorage.getItem("selectedAgent"); - webSocketDataStore.update((webSocketDataMap) => { - const wsData = webSocketDataMap.get(tab_id); - if (wsData) { - wsData.messages.unshift({ - data: message, - transmitter: "sender", - timestamp: formatTime(new Date()), - uuid: uuidv4(), - }); - webSocketDataMap.set(tab_id, wsData); - } - return webSocketDataMap; - }); - } catch (e) { - console.error(e); - return error("error"); + if (typeof window !== "undefined" && selectedAgent === "Browser Agent") { + try { + const ws = (window as any).webSocketInstances?.[tab_id]; + if (!ws) { + throw new Error("WebSocket not connected"); } - }) - .catch((e) => { + + ws.send(message); + webSocketDataStore.update((webSocketDataMap) => { + const wsData = webSocketDataMap.get(tab_id); + if (wsData) { + wsData.messages.unshift({ + data: message, + transmitter: "sender", + timestamp: formatTime(new Date()), + uuid: uuidv4(), + }); + webSocketDataMap.set(tab_id, wsData); + } + return webSocketDataMap; + }); + } catch (e) { console.error(e); + notifications.error("Failed to send message"); return error("error"); - }); + } + } else { + // Existing Tauri implementation + await invoke("send_websocket_message", { tabid: tab_id, message: message }) + .then(async (data: string) => { + try { + webSocketDataStore.update((webSocketDataMap) => { + const wsData = webSocketDataMap.get(tab_id); + if (wsData) { + wsData.messages.unshift({ + data: message, + transmitter: "sender", + timestamp: formatTime(new Date()), + uuid: uuidv4(), + }); + webSocketDataMap.set(tab_id, wsData); + } + return webSocketDataMap; + }); + } catch (e) { + console.error(e); + return error("error"); + } + }) + .catch((e) => { + console.error(e); + return error("error"); + }); + } }; /** * Disconnects a WebSocket connection for a specific tab and handles the response. - * - * @param tab_id - The ID of the tab for which the WebSocket connection should be disconnected. - * */ const disconnectWebSocket = async (tab_id: string) => { let url = ""; @@ -293,10 +318,16 @@ const disconnectWebSocket = async (tab_id: string) => { } return webSocketDataMap; }); - await invoke("disconnect_websocket", { tabid: tab_id }) - .then(async (data: string) => { - try { - // Logic to handle response + + const selectedAgent = localStorage.getItem("selectedAgent"); + + if (typeof window !== "undefined" && selectedAgent === "Browser Agent") { + try { + const ws = (window as any).webSocketInstances?.[tab_id]; + if (ws) { + ws.close(); + delete (window as any).webSocketInstances[tab_id]; + webSocketDataStore.update((webSocketDataMap) => { const wsData = webSocketDataMap.get(tab_id); if (wsData) { @@ -312,21 +343,57 @@ const disconnectWebSocket = async (tab_id: string) => { return webSocketDataMap; }); notifications.success("WebSocket disconnected successfully."); - } catch (e) { + } + } catch (e) { + console.error(e); + notifications.error("Failed to disconnect WebSocket. Please try again."); + return error("error"); + } + } else { + // Existing Tauri implementation + await invoke("disconnect_websocket", { tabid: tab_id }) + .then(async (data: string) => { + try { + webSocketDataStore.update((webSocketDataMap) => { + const wsData = webSocketDataMap.get(tab_id); + if (wsData) { + wsData.messages.unshift({ + data: `Disconnected from ${url}`, + transmitter: "disconnector", + timestamp: formatTime(new Date()), + uuid: uuidv4(), + }); + wsData.status = "disconnected"; + webSocketDataMap.set(tab_id, wsData); + } + return webSocketDataMap; + }); + notifications.success("WebSocket disconnected successfully."); + } catch (e) { + console.error(e); + notifications.error( + "Failed to disconnect WebSocket. Please try again.", + ); + return error("error"); + } + }) + .catch((e) => { console.error(e); notifications.error( "Failed to disconnect WebSocket. Please try again.", ); return error("error"); - } - }) - .catch((e) => { - console.error(e); - notifications.error("Failed to disconnect WebSocket. Please try again."); - return error("error"); - }); + }); + } }; +/** + * Disconnects a WebSocket connection for a specific tab and handles the response. + * + * @param tab_id - The ID of the tab for which the WebSocket connection should be disconnected. + * + */ + const convertWebSocketUrl = (url: string) => { // Check if the URL starts with 'wss://' if (url.startsWith("wss://")) { @@ -357,58 +424,63 @@ const connectWebSocket = async ( tabId: string, requestHeaders: string, ) => { - // debugger; - const httpurl = convertWebSocketUrl(url); - console.table({ url, httpurl, tabId, requestHeaders }); - webSocketDataStore.update((webSocketDataMap) => { - webSocketDataMap.set(tabId, { - messages: [], - status: "connecting", - search: "", - contentType: RequestDataTypeEnum.TEXT, - body: "", - filter: "All Messages", - url: url, - }); + const selectedAgent = localStorage.getItem("selectedAgent"); - return webSocketDataMap; - }); - await invoke("connect_websocket", { - url: url, - httpurl: httpurl, - tabid: tabId, - headers: requestHeaders, - }) - .then(async (data: string) => { - try { - // Logic to handle response - if (data) { - const dt = JSON.parse(data); - } - // Store the WebSocket and initialize data - webSocketDataStore.update((webSocketDataMap) => { - const wsData = webSocketDataMap.get(tabId); - if (wsData) { - wsData.messages.unshift({ - data: `Connected from ${url}`, - transmitter: "connecter", - timestamp: formatTime(new Date()), - uuid: uuidv4(), - }); - wsData.status = "connected"; - webSocketDataMap.set(tabId, wsData); - } - return webSocketDataMap; + if (selectedAgent === "Browser Agent") { + try { + // Parse headers + const headers = JSON.parse(requestHeaders); + + // Initialize webSocket data + webSocketDataStore.update((webSocketDataMap) => { + webSocketDataMap.set(tabId, { + messages: [], + status: "connecting", + search: "", + contentType: RequestDataTypeEnum.TEXT, + body: "", + filter: "All Messages", + url: url, }); - notifications.success("WebSocket connected successfully"); + return webSocketDataMap; + }); + + // Create WebSocket instance + const ws = new WebSocket(url); + + // Store WS instance + if (typeof window !== "undefined") { + (window as any).webSocketInstances = + (window as any).webSocketInstances || {}; + (window as any).webSocketInstances[tabId] = ws; + } - // All the response of particular web socket can be listened here. (Can be shifted to another place) - listen(`ws_message_${tabId}`, (event) => { + return new Promise((resolve, reject) => { + ws.onopen = () => { webSocketDataStore.update((webSocketDataMap) => { const wsData = webSocketDataMap.get(tabId); if (wsData) { wsData.messages.unshift({ - data: event.payload, + data: `Connected to ${url}`, + transmitter: "connecter", + timestamp: formatTime(new Date()), + uuid: uuidv4(), + }); + wsData.status = "connected"; + webSocketDataMap.set(tabId, wsData); + } + return webSocketDataMap; + }); + notifications.success("WebSocket connected successfully"); + resolve(); + }; + + ws.onmessage = (event) => { + webSocketDataStore.update((webSocketDataMap) => { + const wsData = webSocketDataMap.get(tabId); + if (wsData) { + wsData.messages.unshift({ + data: event.data, transmitter: "receiver", timestamp: formatTime(new Date()), uuid: uuidv4(), @@ -417,26 +489,85 @@ const connectWebSocket = async ( } return webSocketDataMap; }); - }); - } catch (e) { + }; + + ws.onerror = (error) => { + console.error("WebSocket error:", error); + webSocketDataStore.update((webSocketDataMap) => { + webSocketDataMap.delete(tabId); + return webSocketDataMap; + }); + reject(new Error("Failed to connect to WebSocket")); + }; + }); + } catch (error) { + console.error(error); + notifications.error("Failed to connect WebSocket"); + throw error; + } + } else { + // Existing Tauri implementation + await invoke("connect_websocket", { + url: url, + httpurl: convertWebSocketUrl(url), + tabid: tabId, + headers: requestHeaders, + }) + .then(async (data: string) => { + try { + if (data) { + const dt = JSON.parse(data); + } + webSocketDataStore.update((webSocketDataMap) => { + const wsData = webSocketDataMap.get(tabId); + if (wsData) { + wsData.messages.unshift({ + data: `Connected from ${url}`, + transmitter: "connecter", + timestamp: formatTime(new Date()), + uuid: uuidv4(), + }); + wsData.status = "connected"; + webSocketDataMap.set(tabId, wsData); + } + return webSocketDataMap; + }); + notifications.success("WebSocket connected successfully"); + + listen(`ws_message_${tabId}`, (event) => { + webSocketDataStore.update((webSocketDataMap) => { + const wsData = webSocketDataMap.get(tabId); + if (wsData) { + wsData.messages.unshift({ + data: event.payload, + transmitter: "receiver", + timestamp: formatTime(new Date()), + uuid: uuidv4(), + }); + webSocketDataMap.set(tabId, wsData); + } + return webSocketDataMap; + }); + }); + } catch (e) { + console.error(e); + notifications.error( + "Failed to fetch WebSocket response. Please try again.", + ); + return error("error"); + } + }) + .catch((e) => { console.error(e); - notifications.error( - "Failed to fetch WebSocket response. Please try again.", - ); + webSocketDataStore.update((webSocketDataMap) => { + webSocketDataMap.delete(tabId); + return webSocketDataMap; + }); + notifications.error("Failed to connect WebSocket. Please try again."); return error("error"); - } - }) - .catch((e) => { - console.error(e); - webSocketDataStore.update((webSocketDataMap) => { - webSocketDataMap.delete(tabId); - return webSocketDataMap; }); - notifications.error("Failed to connect WebSocket. Please try again."); - return error("error"); - }); + } }; - /** * Invoke RPC Communication * @param url - Request URL diff --git a/apps/@sparrow-web/src/pages/workspace-page/sub-pages/WebSocketExplorerPage/WebSocketExplorerPage.ViewModel.ts b/apps/@sparrow-web/src/pages/workspace-page/sub-pages/WebSocketExplorerPage/WebSocketExplorerPage.ViewModel.ts index 8a5067e68..ca50aede1 100644 --- a/apps/@sparrow-web/src/pages/workspace-page/sub-pages/WebSocketExplorerPage/WebSocketExplorerPage.ViewModel.ts +++ b/apps/@sparrow-web/src/pages/workspace-page/sub-pages/WebSocketExplorerPage/WebSocketExplorerPage.ViewModel.ts @@ -1447,33 +1447,33 @@ class RestExplorerViewModel { return await this.workspaceRepository.readWorkspace(workspaceId); }; - // public connectWebsocket = async (environmentVariables) => { - // const websocketData = this._tab.getValue(); - - // const decodeData = new DecodeWebsocket().init( - // this._tab.getValue().property.websocket, - // environmentVariables?.filtered || [], - // ); - - // return await this.webSocketService.connectWebsocket( - // decodeData[0] as string, - // websocketData.tabId, - // decodeData[1], - // ); - // }; - // public disconnectWebsocket = async () => { - // const websocketData = this._tab.getValue(); - // return await this.webSocketService.disconnectWebsocket( - // websocketData?.tabId, - // ); - // }; - // public sendMessageWebsocket = async () => { - // const websocketData = this._tab.getValue(); - // return await this.webSocketService.sendMessageWebsocket( - // websocketData.tabId, - // websocketData.property.websocket?.message as string, - // ); - // }; + public connectWebsocket = async (environmentVariables) => { + const websocketData = this._tab.getValue(); + + const decodeData = new DecodeWebsocket().init( + this._tab.getValue().property.websocket, + environmentVariables?.filtered || [], + ); + + return await this.collectionService.connectWebsocket( + decodeData[0] as string, + websocketData.tabId, + decodeData[1], + ); + }; + public disconnectWebsocket = async () => { + const websocketData = this._tab.getValue(); + return await this.collectionService.disconnectWebsocket( + websocketData?.tabId, + ); + }; + public sendMessageWebsocket = async () => { + const websocketData = this._tab.getValue(); + return await this.collectionService.sendMessageWebsocket( + websocketData.tabId, + websocketData.property.websocket?.message as string, + ); + }; public searchMessages = async (_search: string) => { const websocketData = this._tab.getValue(); diff --git a/apps/@sparrow-web/src/services/collection.service.ts b/apps/@sparrow-web/src/services/collection.service.ts index 70974c563..64d839c5f 100644 --- a/apps/@sparrow-web/src/services/collection.service.ts +++ b/apps/@sparrow-web/src/services/collection.service.ts @@ -1,8 +1,11 @@ import { + connectWebSocket, + disconnectWebSocket, // connectSocketIo, // disconnectSocketIo, getAuthHeaders, makeRequest, + sendMessage, // sendSocketIoMessage, } from "@app/containers/api/api.common"; import { CollectionRepository } from "../repositories/collection.repository"; @@ -562,6 +565,20 @@ export class CollectionService { return response; }; + public connectWebsocket = async ( + _url: string, + _tabId: string, + _headers: string, + ) => { + return connectWebSocket(_url, _tabId, _headers); + }; + public disconnectWebsocket = async (_tabId: string) => { + return disconnectWebSocket(_tabId); + }; + public sendMessageWebsocket = async (_tabId: string, _message: string) => { + return sendMessage(_tabId, _message); + }; + public deleteGraphqlInCollection = async ( _graphqlId: string, _graphql: GraphqlRequestDeletePayloadDtoInterface, From 315249980368faf2eeb80bf1dad9a4561e9dc8af Mon Sep 17 00:00:00 2001 From: Nayan lakhwani Date: Tue, 17 Dec 2024 16:39:13 +0530 Subject: [PATCH 03/56] feat: merge with dev[] --- .github/workflows/development.yaml | 1 + .github/workflows/feat-sparrow-refactoring.yaml | 1 + .github/workflows/release.yaml | 1 + .github/workflows/staging.yaml | 1 + .github/workflows/testflow.yml | 1 + 5 files changed, 5 insertions(+) diff --git a/.github/workflows/development.yaml b/.github/workflows/development.yaml index 5fb1ab85d..4ee525ded 100644 --- a/.github/workflows/development.yaml +++ b/.github/workflows/development.yaml @@ -24,6 +24,7 @@ env: VITE_BASE_URL: ${{ vars.VITE_BASE_URL }} VITE_SPARROW_LINKEDIN: ${{ vars.VITE_SPARROW_LINKEDIN }} ACTIONS_ALLOW_UNSECURE_COMMANDS: true + VITE_SIMPLIFIED_LOGIN: ${{ vars.VITE_SIMPLIFIED_LOGIN }} jobs: release_win: diff --git a/.github/workflows/feat-sparrow-refactoring.yaml b/.github/workflows/feat-sparrow-refactoring.yaml index eb415d01c..927ac3a18 100644 --- a/.github/workflows/feat-sparrow-refactoring.yaml +++ b/.github/workflows/feat-sparrow-refactoring.yaml @@ -24,6 +24,7 @@ env: VITE_BASE_URL: ${{ vars.VITE_BASE_URL }} VITE_SPARROW_LINKEDIN: ${{ vars.VITE_SPARROW_LINKEDIN }} ACTIONS_ALLOW_UNSECURE_COMMANDS: true + VITE_SIMPLIFIED_LOGIN: ${{ vars.VITE_SIMPLIFIED_LOGIN }} jobs: release_win: diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 18125ac29..6b54b8bb6 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -24,6 +24,7 @@ env: VITE_BASE_URL: ${{ vars.VITE_BASE_URL }} VITE_SPARROW_LINKEDIN: ${{ vars.VITE_SPARROW_LINKEDIN }} ACTIONS_ALLOW_UNSECURE_COMMANDS: true + VITE_SIMPLIFIED_LOGIN: ${{ vars.VITE_SIMPLIFIED_LOGIN }} jobs: release_win: diff --git a/.github/workflows/staging.yaml b/.github/workflows/staging.yaml index 71c5ea3e4..3f8209147 100644 --- a/.github/workflows/staging.yaml +++ b/.github/workflows/staging.yaml @@ -16,6 +16,7 @@ env: VITE_SPARROW_GITHUB: ${{ secrets.VITE_SPARROW_GITHUB }} VITE_SPARROW_DOWNLOAD_LINK: ${{ secrets.VITE_SPARROW_DOWNLOAD_LINK }} ACTIONS_ALLOW_UNSECURE_COMMANDS: true + VITE_SIMPLIFIED_LOGIN: ${{ vars.VITE_SIMPLIFIED_LOGIN }} jobs: release_win: diff --git a/.github/workflows/testflow.yml b/.github/workflows/testflow.yml index 8e504ab5d..f7826be87 100644 --- a/.github/workflows/testflow.yml +++ b/.github/workflows/testflow.yml @@ -22,6 +22,7 @@ env: VITE_CANNY_API: ${{ vars.VITE_CANNY_API }} VITE_CANNY_URL: ${{ vars.VITE_CANNY_URL }} ACTIONS_ALLOW_UNSECURE_COMMANDS: true + VITE_SIMPLIFIED_LOGIN: ${{ vars.VITE_SIMPLIFIED_LOGIN }} jobs: release_win: From 680f20a4d8be8d500c937971ceeece44b88ae28e Mon Sep 17 00:00:00 2001 From: Nayan lakhwani Date: Tue, 17 Dec 2024 17:19:21 +0530 Subject: [PATCH 04/56] feat: merge with dev[] --- README.md | 3 +++ apps/@sparrow-desktop/.env.example | 3 ++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 3ee655961..03788a64e 100644 --- a/README.md +++ b/README.md @@ -66,6 +66,9 @@ cp apps/@sparrow-desktop/.env.example apps/@sparrow-desktop/.env # Copy web app .env.example to .env cp apps/@sparrow-web/.env.example apps/@sparrow-web/.env +# [OPTIONAL] Simplified Login (Bypassing Standard Authentication) +SET VITE_SIMPLIFIED_LOGIN=true in .env file + # Run the desktop app in dev mode yarn desktop-start diff --git a/apps/@sparrow-desktop/.env.example b/apps/@sparrow-desktop/.env.example index 6dcb9b3b6..988b58341 100644 --- a/apps/@sparrow-desktop/.env.example +++ b/apps/@sparrow-desktop/.env.example @@ -15,4 +15,5 @@ VITE_BASE_URL= VITE_SPARROW_LINKEDIN= VITE_CANNY_API="" VITE_CANNY_URL="https://canny.io/api/v1" -VITE_MARKETING_URL="http://localhost:1429" \ No newline at end of file +VITE_MARKETING_URL="http://localhost:1429" +VITE_SIMPLIFIED_LOGIN=true \ No newline at end of file From 94c541175f29ab02c37038dbbbc4fff5e11aa732 Mon Sep 17 00:00:00 2001 From: Harsh Date: Tue, 17 Dec 2024 17:58:51 +0530 Subject: [PATCH 05/56] working on browser agent workflow --- .../src/containers/api/api.common.ts | 287 +++++++++--------- 1 file changed, 147 insertions(+), 140 deletions(-) diff --git a/apps/@sparrow-web/src/containers/api/api.common.ts b/apps/@sparrow-web/src/containers/api/api.common.ts index fd271a0a7..91973da3d 100644 --- a/apps/@sparrow-web/src/containers/api/api.common.ts +++ b/apps/@sparrow-web/src/containers/api/api.common.ts @@ -247,23 +247,20 @@ function formatTime(date) { const sendMessage = async (tab_id: string, message: string) => { const selectedAgent = localStorage.getItem("selectedAgent"); - if (typeof window !== "undefined" && selectedAgent === "Browser Agent") { + if (selectedAgent === "Browser Agent") { try { - const ws = (window as any).webSocketInstances?.[tab_id]; - if (!ws) { - throw new Error("WebSocket not connected"); - } - - ws.send(message); + let listener; webSocketDataStore.update((webSocketDataMap) => { const wsData = webSocketDataMap.get(tab_id); if (wsData) { + listener = wsData.listener; wsData.messages.unshift({ data: message, transmitter: "sender", timestamp: formatTime(new Date()), uuid: uuidv4(), }); + listener.send(message); webSocketDataMap.set(tab_id, wsData); } return webSocketDataMap; @@ -273,33 +270,32 @@ const sendMessage = async (tab_id: string, message: string) => { notifications.error("Failed to send message"); return error("error"); } - } else { - // Existing Tauri implementation - await invoke("send_websocket_message", { tabid: tab_id, message: message }) - .then(async (data: string) => { - try { - webSocketDataStore.update((webSocketDataMap) => { - const wsData = webSocketDataMap.get(tab_id); - if (wsData) { - wsData.messages.unshift({ - data: message, - transmitter: "sender", - timestamp: formatTime(new Date()), - uuid: uuidv4(), - }); - webSocketDataMap.set(tab_id, wsData); - } - return webSocketDataMap; + } else if (selectedAgent === "Cloud Agent") { + try { + const proxyUrl = "http://localhost:3000/proxy/ws-message"; + await axios.post(proxyUrl, { + tabId: tab_id, + message: message, + }); + + webSocketDataStore.update((webSocketDataMap) => { + const wsData = webSocketDataMap.get(tab_id); + if (wsData) { + wsData.messages.unshift({ + data: message, + transmitter: "sender", + timestamp: formatTime(new Date()), + uuid: uuidv4(), }); - } catch (e) { - console.error(e); - return error("error"); + webSocketDataMap.set(tab_id, wsData); } - }) - .catch((e) => { - console.error(e); - return error("error"); + return webSocketDataMap; }); + } catch (e) { + console.error(e); + notifications.error("Failed to send message"); + return error("error"); + } } }; @@ -321,69 +317,58 @@ const disconnectWebSocket = async (tab_id: string) => { const selectedAgent = localStorage.getItem("selectedAgent"); - if (typeof window !== "undefined" && selectedAgent === "Browser Agent") { + if (selectedAgent === "Browser Agent") { try { - const ws = (window as any).webSocketInstances?.[tab_id]; - if (ws) { - ws.close(); - delete (window as any).webSocketInstances[tab_id]; - - webSocketDataStore.update((webSocketDataMap) => { - const wsData = webSocketDataMap.get(tab_id); - if (wsData) { - wsData.messages.unshift({ - data: `Disconnected from ${url}`, - transmitter: "disconnector", - timestamp: formatTime(new Date()), - uuid: uuidv4(), - }); - wsData.status = "disconnected"; - webSocketDataMap.set(tab_id, wsData); + let listener; + webSocketDataStore.update((webSocketDataMap) => { + const wsData = webSocketDataMap.get(tab_id); + if (wsData) { + listener = wsData.listener; + wsData.messages.unshift({ + data: `Disconnected from ${url}`, + transmitter: "disconnector", + timestamp: formatTime(new Date()), + uuid: uuidv4(), + }); + wsData.status = "disconnected"; + webSocketDataMap.set(tab_id, wsData); + if (listener) { + listener.close(); } - return webSocketDataMap; - }); - notifications.success("WebSocket disconnected successfully."); - } + } + return webSocketDataMap; + }); + notifications.success("WebSocket disconnected successfully."); } catch (e) { console.error(e); notifications.error("Failed to disconnect WebSocket. Please try again."); return error("error"); } - } else { - // Existing Tauri implementation - await invoke("disconnect_websocket", { tabid: tab_id }) - .then(async (data: string) => { - try { - webSocketDataStore.update((webSocketDataMap) => { - const wsData = webSocketDataMap.get(tab_id); - if (wsData) { - wsData.messages.unshift({ - data: `Disconnected from ${url}`, - transmitter: "disconnector", - timestamp: formatTime(new Date()), - uuid: uuidv4(), - }); - wsData.status = "disconnected"; - webSocketDataMap.set(tab_id, wsData); - } - return webSocketDataMap; + } else if (selectedAgent === "Cloud Agent") { + try { + const proxyUrl = "http://localhost:3000/proxy/ws-disconnect"; + await axios.post(proxyUrl, { tabId: tab_id }); + + webSocketDataStore.update((webSocketDataMap) => { + const wsData = webSocketDataMap.get(tab_id); + if (wsData) { + wsData.messages.unshift({ + data: `Disconnected from ${url}`, + transmitter: "disconnector", + timestamp: formatTime(new Date()), + uuid: uuidv4(), }); - notifications.success("WebSocket disconnected successfully."); - } catch (e) { - console.error(e); - notifications.error( - "Failed to disconnect WebSocket. Please try again.", - ); - return error("error"); + wsData.status = "disconnected"; + webSocketDataMap.set(tab_id, wsData); } - }) - .catch((e) => { - console.error(e); - notifications.error( - "Failed to disconnect WebSocket. Please try again.", - ); - return error("error"); + return webSocketDataMap; }); + notifications.success("WebSocket disconnected successfully."); + } catch (e) { + console.error(e); + notifications.error("Failed to disconnect WebSocket. Please try again."); + return error("error"); + } } }; @@ -428,10 +413,8 @@ const connectWebSocket = async ( if (selectedAgent === "Browser Agent") { try { - // Parse headers const headers = JSON.parse(requestHeaders); - // Initialize webSocket data webSocketDataStore.update((webSocketDataMap) => { webSocketDataMap.set(tabId, { messages: [], @@ -445,15 +428,16 @@ const connectWebSocket = async ( return webSocketDataMap; }); - // Create WebSocket instance const ws = new WebSocket(url); - // Store WS instance - if (typeof window !== "undefined") { - (window as any).webSocketInstances = - (window as any).webSocketInstances || {}; - (window as any).webSocketInstances[tabId] = ws; - } + webSocketDataStore.update((webSocketDataMap) => { + const wsData = webSocketDataMap.get(tabId); + if (wsData) { + wsData.listener = ws; + webSocketDataMap.set(tabId, wsData); + } + return webSocketDataMap; + }); return new Promise((resolve, reject) => { ws.onopen = () => { @@ -505,69 +489,91 @@ const connectWebSocket = async ( notifications.error("Failed to connect WebSocket"); throw error; } - } else { - // Existing Tauri implementation - await invoke("connect_websocket", { - url: url, - httpurl: convertWebSocketUrl(url), - tabid: tabId, - headers: requestHeaders, - }) - .then(async (data: string) => { - try { - if (data) { - const dt = JSON.parse(data); + } else if (selectedAgent === "Cloud Agent") { + try { + webSocketDataStore.update((webSocketDataMap) => { + webSocketDataMap.set(tabId, { + messages: [], + status: "connecting", + search: "", + contentType: RequestDataTypeEnum.TEXT, + body: "", + filter: "All Messages", + url: url, + }); + return webSocketDataMap; + }); + + const proxyUrl = "http://localhost:9000/proxy/ws-connect"; + const response = await axios.post(proxyUrl, { + tabId, + targetUrl: url, + headers: requestHeaders, + }); + + if (response.data.success) { + webSocketDataStore.update((webSocketDataMap) => { + const wsData = webSocketDataMap.get(tabId); + if (wsData) { + wsData.messages.unshift({ + data: `Connected to ${url}`, + transmitter: "connecter", + timestamp: formatTime(new Date()), + uuid: uuidv4(), + }); + wsData.status = "connected"; + webSocketDataMap.set(tabId, wsData); } + return webSocketDataMap; + }); + notifications.success("WebSocket connected successfully"); + + // Set up event source for receiving messages + const eventSource = new EventSource( + `http://localhost:3000/proxy/ws-events/${tabId}`, + ); + + eventSource.onmessage = (event) => { + const data = JSON.parse(event.data); webSocketDataStore.update((webSocketDataMap) => { const wsData = webSocketDataMap.get(tabId); if (wsData) { wsData.messages.unshift({ - data: `Connected from ${url}`, - transmitter: "connecter", + data: data.message, + transmitter: "receiver", timestamp: formatTime(new Date()), uuid: uuidv4(), }); - wsData.status = "connected"; webSocketDataMap.set(tabId, wsData); } return webSocketDataMap; }); - notifications.success("WebSocket connected successfully"); + }; - listen(`ws_message_${tabId}`, (event) => { - webSocketDataStore.update((webSocketDataMap) => { - const wsData = webSocketDataMap.get(tabId); - if (wsData) { - wsData.messages.unshift({ - data: event.payload, - transmitter: "receiver", - timestamp: formatTime(new Date()), - uuid: uuidv4(), - }); - webSocketDataMap.set(tabId, wsData); - } - return webSocketDataMap; - }); + eventSource.onerror = () => { + eventSource.close(); + webSocketDataStore.update((webSocketDataMap) => { + const wsData = webSocketDataMap.get(tabId); + if (wsData) { + wsData.status = "disconnected"; + webSocketDataMap.set(tabId, wsData); + } + return webSocketDataMap; }); - } catch (e) { - console.error(e); - notifications.error( - "Failed to fetch WebSocket response. Please try again.", - ); - return error("error"); - } - }) - .catch((e) => { - console.error(e); - webSocketDataStore.update((webSocketDataMap) => { - webSocketDataMap.delete(tabId); - return webSocketDataMap; - }); - notifications.error("Failed to connect WebSocket. Please try again."); - return error("error"); + }; + } + } catch (error) { + console.error(error); + notifications.error("Failed to connect WebSocket"); + webSocketDataStore.update((webSocketDataMap) => { + webSocketDataMap.delete(tabId); + return webSocketDataMap; }); + throw error; + } } }; + /** * Invoke RPC Communication * @param url - Request URL @@ -591,7 +597,8 @@ const makeHttpRequestV2 = async ( try { let response; if (selectedAgent === "Cloud Agent") { - const proxyUrl = constants.PROXY_SERVICE + "/proxy/http-request"; + // const proxyUrl = constants.PROXY_SERVICE + "/proxy/http-request"; + const proxyUrl = "http://localhost:3000/proxy/http-request"; response = await axios({ data: { url, method, headers, body, contentType }, url: proxyUrl, From 6f2ebbcd9e88ac8aaa61b5052820228dea833056 Mon Sep 17 00:00:00 2001 From: Harsh Date: Tue, 17 Dec 2024 19:39:16 +0530 Subject: [PATCH 06/56] fix : completed browser agent workflow --- .../src/containers/api/api.common.ts | 128 ++++++++---------- 1 file changed, 56 insertions(+), 72 deletions(-) diff --git a/apps/@sparrow-web/src/containers/api/api.common.ts b/apps/@sparrow-web/src/containers/api/api.common.ts index bf6d85394..f64ad47ba 100644 --- a/apps/@sparrow-web/src/containers/api/api.common.ts +++ b/apps/@sparrow-web/src/containers/api/api.common.ts @@ -258,13 +258,14 @@ function formatTime(date) { const sendMessage = async (tab_id: string, message: string) => { const selectedAgent = localStorage.getItem("selectedAgent"); - if (selectedAgent === "Browser Agent") { - try { - let listener; - webSocketDataStore.update((webSocketDataMap) => { - const wsData = webSocketDataMap.get(tab_id); - if (wsData) { - listener = wsData.listener; + try { + let listener; + webSocketDataStore.update((webSocketDataMap) => { + const wsData = webSocketDataMap.get(tab_id); + if (wsData) { + listener = wsData.listener; + // Check for the original agent type from the store, not the currently selected agent + if (wsData.agent === WorkspaceUserAgentBaseEnum.BROWSER_AGENT) { wsData.messages.unshift({ data: message, transmitter: "sender", @@ -274,40 +275,41 @@ const sendMessage = async (tab_id: string, message: string) => { listener.send(message); webSocketDataMap.set(tab_id, wsData); } - return webSocketDataMap; - }); - } catch (e) { - console.error(e); - notifications.error("Failed to send message"); - return error("error"); - } - } else if (selectedAgent === "Cloud Agent") { - try { - const proxyUrl = "http://localhost:3000/proxy/ws-message"; - await axios.post(proxyUrl, { - tabId: tab_id, - message: message, - }); - - webSocketDataStore.update((webSocketDataMap) => { - const wsData = webSocketDataMap.get(tab_id); - if (wsData) { - wsData.messages.unshift({ - data: message, - transmitter: "sender", - timestamp: formatTime(new Date()), - uuid: uuidv4(), - }); - webSocketDataMap.set(tab_id, wsData); - } - return webSocketDataMap; - }); - } catch (e) { - console.error(e); - notifications.error("Failed to send message"); - return error("error"); - } + } + return webSocketDataMap; + }); + } catch (e) { + console.error(e); + notifications.error("Failed to send message"); + return error("error"); } + + // else if (selectedAgent === "Cloud Agent") { + // try { + // const proxyUrl = "http://localhost:3000/proxy/ws-message"; + // await axios.post(proxyUrl, { + // tabId: tab_id, + // message: message, + // }); + // webSocketDataStore.update((webSocketDataMap) => { + // const wsData = webSocketDataMap.get(tab_id); + // if (wsData) { + // wsData.messages.unshift({ + // data: message, + // transmitter: "sender", + // timestamp: formatTime(new Date()), + // uuid: uuidv4(), + // }); + // webSocketDataMap.set(tab_id, wsData); + // } + // return webSocketDataMap; + // }); + // } catch (e) { + // console.error(e); + // notifications.error("Failed to send message"); + // return error("error"); + // } + // } }; /** @@ -332,7 +334,6 @@ const disconnectWebSocket = async (tab_id: string) => { if (wsData) { const socketInsta = wsData.listener; if (wsData.agent === WorkspaceUserAgentBaseEnum.BROWSER_AGENT) { - debugger; wsData.messages.unshift({ data: `Disconnected from ${url}`, transmitter: "disconnector", @@ -347,37 +348,6 @@ const disconnectWebSocket = async (tab_id: string) => { return webSocketDataMap; }); - const selectedAgent = localStorage.getItem("selectedAgent"); - - if (selectedAgent === "Browser Agent") { - try { - let listener; - webSocketDataStore.update((webSocketDataMap) => { - const wsData = webSocketDataMap.get(tab_id); - if (wsData) { - listener = wsData.listener; - wsData.messages.unshift({ - data: `Disconnected from ${url}`, - transmitter: "disconnector", - timestamp: formatTime(new Date()), - uuid: uuidv4(), - }); - wsData.status = "disconnected"; - webSocketDataMap.set(tab_id, wsData); - if (listener) { - listener.close(); - } - } - return webSocketDataMap; - }); - notifications.success("WebSocket disconnected successfully."); - } catch (e) { - console.error(e); - notifications.error("Failed to disconnect WebSocket. Please try again."); - return error("error"); - } - } - // else if (selectedAgent === "Cloud Agent") { // try { // const proxyUrl = "http://localhost:3000/proxy/ws-disconnect"; @@ -467,6 +437,13 @@ const connectWebSocket = async ( const ws = new WebSocket(url); + ws.addEventListener("close", (event) => { + console.log("WebSocket closed", event); + }); + ws.addEventListener("error", (event) => { + debugger; + console.log("WebSocket errorred", event); + }); webSocketDataStore.update((webSocketDataMap) => { const wsData = webSocketDataMap.get(tabId); if (wsData) { @@ -520,9 +497,16 @@ const connectWebSocket = async ( }); reject(new Error("Failed to connect to WebSocket")); }; + ws.onclose = () => { + disconnectWebSocket(tabId); + }; }); } catch (error) { console.error(error); + webSocketDataStore.update((webSocketDataMap) => { + webSocketDataMap.delete(tabId); + return webSocketDataMap; + }); notifications.error("Failed to connect WebSocket"); throw error; } From d8f83dd7cb27197ba2a478996061fc79ef25084d Mon Sep 17 00:00:00 2001 From: Harsh Date: Wed, 18 Dec 2024 11:44:16 +0530 Subject: [PATCH 07/56] fix: completed browser agent functionality in webapp with all bug fixes --- .../src/containers/api/api.common.ts | 31 +++++++++---------- 1 file changed, 14 insertions(+), 17 deletions(-) diff --git a/apps/@sparrow-web/src/containers/api/api.common.ts b/apps/@sparrow-web/src/containers/api/api.common.ts index f64ad47ba..764097bc2 100644 --- a/apps/@sparrow-web/src/containers/api/api.common.ts +++ b/apps/@sparrow-web/src/containers/api/api.common.ts @@ -334,14 +334,6 @@ const disconnectWebSocket = async (tab_id: string) => { if (wsData) { const socketInsta = wsData.listener; if (wsData.agent === WorkspaceUserAgentBaseEnum.BROWSER_AGENT) { - wsData.messages.unshift({ - data: `Disconnected from ${url}`, - transmitter: "disconnector", - timestamp: formatTime(new Date()), - uuid: uuidv4(), - }); - wsData.status = "disconnected"; - webSocketDataMap.set(tab_id, wsData); socketInsta.close(); } } @@ -437,13 +429,6 @@ const connectWebSocket = async ( const ws = new WebSocket(url); - ws.addEventListener("close", (event) => { - console.log("WebSocket closed", event); - }); - ws.addEventListener("error", (event) => { - debugger; - console.log("WebSocket errorred", event); - }); webSocketDataStore.update((webSocketDataMap) => { const wsData = webSocketDataMap.get(tabId); if (wsData) { @@ -495,10 +480,22 @@ const connectWebSocket = async ( webSocketDataMap.delete(tabId); return webSocketDataMap; }); - reject(new Error("Failed to connect to WebSocket")); }; ws.onclose = () => { - disconnectWebSocket(tabId); + webSocketDataStore.update((webSocketDataMap) => { + const wsData = webSocketDataMap.get(tabId); + if (wsData) { + wsData.messages.unshift({ + data: `Disconnected from ${url}`, + transmitter: "disconnector", + timestamp: formatTime(new Date()), + uuid: uuidv4(), + }); + wsData.status = "disconnected"; + webSocketDataMap.set(tabId, wsData); + } + return webSocketDataMap; + }); }; }); } catch (error) { From 077cfa7e542029ea12f345d912275230a80c0803 Mon Sep 17 00:00:00 2001 From: pratikshinde590 Date: Wed, 18 Dec 2024 12:18:57 +0530 Subject: [PATCH 08/56] build: Added Docker-compose file [] --- docker-compose.yml | 156 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 156 insertions(+) create mode 100644 docker-compose.yml diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 000000000..4916fca7f --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,156 @@ +version: "3.8" + +services: + # MongoDB + mongo: + image: mongo:7.0 + ports: + - "27017:27017" + environment: + MONGO_INITDB_ROOT_USERNAME: sparowapp + MONGO_INITDB_ROOT_PASSWORD: sparrow123 + networks: + - localnet + + # Kafka + kafka: + image: bitnami/kafka:3.4.1 + hostname: kafka + ports: + - "9092:9092" + volumes: + - "kafka_data:/bitnami" + environment: + - KAFKA_ENABLE_KRAFT=yes + - KAFKA_CFG_PROCESS_ROLES=broker,controller + - KAFKA_CFG_CONTROLLER_LISTENER_NAMES=CONTROLLER + - KAFKA_CFG_LISTENERS=PLAINTEXT://:9092,CONTROLLER://:9093,EXTERNAL://:9094 + - KAFKA_CFG_LISTENER_SECURITY_PROTOCOL_MAP=CONTROLLER:PLAINTEXT,PLAINTEXT:PLAINTEXT,EXTERNAL:PLAINTEXT + - KAFKA_CFG_ADVERTISED_LISTENERS=PLAINTEXT://127.0.0.1:9092,EXTERNAL://kafka:9094 + - KAFKA_BROKER_ID=1 + - KAFKA_CFG_CONTROLLER_QUORUM_VOTERS=1@localhost:9093 + - ALLOW_PLAINTEXT_LISTENER=yes + - KAFKA_CFG_NODE_ID=1 + - KAFKA_AUTO_CREATE_TOPICS_ENABLE=true + - KAFKA_CFG_NUM_PARTITIONS=2 + - KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR=1 + - KAFKA_TRANSACTION_STATE_LOG_MIN_ISR=1 + - KAFKA_TRANSACTION_STATE_LOG_REPLICATION_FACTOR=1 + - KAFKA_GROUP_INITIAL_REBALANCE_DELAY_MS=0 + - KAFKA_MESSAGE_MAX_BYTES=1000000 + networks: + - localnet + + # App + app: + image: sparrowapi/sparrow-api:v2 + ports: + - "9000:9000" + volumes: + - ./:/src + networks: + - localnet + depends_on: + - mongo + - kafka + environment: + # APP + PORT: 9000 + APP_ENV: DEV + APP_URL: http://localhost + + # AUTH + JWT_SECRET_KEY: webtoken-secret-key + JWT_EXPIRATION_TIME: 2400 + + # DATABASE + DB_URL: mongodb://sparowapp:sparrow123@mongo:27017 + + # Google OAuth + GOOGLE_CLIENT_ID: google-client-id + GOOGLE_CLIENT_SECRET: google-client-secret + GOOGLE_APP_URL: google-app-url + LOGIN_REDIRECT_URL: login-redirect-url + GOOGLE_ACCESS_TYPE: google-access-type + + # EXPIRY TIME FOR EMAIL VALIDATION CODE/LINK + EMAIL_VALIDATION_CODE_EXPIRY_TIME: "" + + # KAFKA + KAFKA_BROKER: kafka:9094 + + # EMAIL + SMTP_SENDER_EMAIL: "" + SMTP_SENDER_PASSWORD: "" + SMTP_MAIL_HOST: "" + SMTP_MAIL_PORT: "" + SMTP_MAIL_SECURE: "" + SMTP_USER_NAME: "" + + # REFRESH TOKEN + REFRESH_TOKEN_SECRET_KEY: refresh-token-secret + REFRESH_TOKEN_EXPIRATION_TIME: 604800 + REFRESH_TOKEN_MAX_LIMIT: 50 + + # APP UPDATER + APP_UPDATE_AVAILABLE: false + APP_VERSION: "" + WINDOWS_APP_SIGNATURE: "" + WINDOWS_APP_URL: "" + MAC_APPLE_SILICON_APP_SIGNATURE: "" + MAC_APPLE_SILICON_APP_URL: "" + MAC_INTEL_APP_SIGNATURE: "" + MAC_INTEL_APP_URL: "" + + # SUPPORT + SPARROW_EMAIL: contactus@sparrowapp.dev + + # AZURE SERVICES + AZURE_CONNECTION_STRING: "" + AZURE_INSIGHTS_CONNECTION_STRING: "" + FEEDBACK_BLOB_CONTAINER: "" + + # AI SUPPORT + AZURE_OPENAI_ENDPOINT: "" + AZURE_OPENAI_API_KEY: "" + AZURE_OPENAI_DEPLOYMENT: "" + AZURE_OPENAI_API_VERSION: "" + AZURE_OPENAI_MAX_TOKENS: "" + AZURE_OPENAI_MONTHLY_TOKEN_LIMIT: "" + + # Hubspot + HUBSPOT_BASEURL: "" + HUBSPOT_INTEGRATION_ENABLED: "" + HUBSPOT_PORTALID: "" + HUBSPOT_FORMID: "" + + # Sparrow Auth + auth: + image: sparrowapi/sparrow-auth:v1 + ports: + - "80:80" + networks: + - localnet + depends_on: + - mongo + - kafka + environment: + AUTH_SERVICE_PORT: 80 + JWT_SECRET: auth-jwt-secret + DB_URL: mongodb://sparowapp:sparrow123@mongo:27017 + VITE_API_URL: "http://localhost:9000" + VITE_SPARROW_SUPPORT_EMAIL: "support@example.dev" + VITE_SPARROW_OAUTH: "http://localhost:9000/api/auth/google/callback" + VITE_ENABLE_MIX_PANEL: "false" + VITE_MIX_PANEL_TOKEN: "" + VITE_TERMS_OF_SERVICE: "https://example.dev/termsandconditions" + VITE_SPARROW_WEB_URL: "http://localhost:1422" + VITE_SPARROW_PRIVACY_POLICY: "https://example.com/privacy-policy" + +volumes: + kafka_data: + driver: local + +networks: + localnet: + driver: bridge From 616cebc94d69b30b7611d91bff72fbbf613c2b55 Mon Sep 17 00:00:00 2001 From: Harsh Date: Wed, 18 Dec 2024 12:55:02 +0530 Subject: [PATCH 09/56] fix: ui bugs --- .../components/collection/Collection.svelte | 45 +++++++++---------- .../components/folder/Folder.svelte | 2 +- .../components/socket-io/SocketIo.svelte | 5 +-- .../components/web-socket/WebSocket.svelte | 2 +- .../ResponseNavigator.svelte | 1 + .../ResponsePreviewNavigator.svelte | 20 +++++---- .../layout/SocketExplorer.svelte | 7 +-- 7 files changed, 41 insertions(+), 41 deletions(-) diff --git a/packages/@sparrow-workspaces/src/features/collection-list/components/collection/Collection.svelte b/packages/@sparrow-workspaces/src/features/collection-list/components/collection/Collection.svelte index 4b3c61417..2af56be41 100644 --- a/packages/@sparrow-workspaces/src/features/collection-list/components/collection/Collection.svelte +++ b/packages/@sparrow-workspaces/src/features/collection-list/components/collection/Collection.svelte @@ -664,32 +664,27 @@ /> - {#if !isWebApp} - +
{ + onItemCreated("websocketCollection", { + workspaceId: collection.workspaceId, + collection, + }); + MixpanelEvent(Events.Collection_WebSocket); + }} > -
{ - onItemCreated("websocketCollection", { - workspaceId: collection.workspaceId, - collection, - }); - MixpanelEvent(Events.Collection_WebSocket); - }} - > - -
- - + +
+
+ {#if !isWebApp} {:else}
{socketIo.name} @@ -298,7 +297,7 @@ >
diff --git a/packages/@sparrow-workspaces/src/features/socket-explorer/layout/SocketExplorer.svelte b/packages/@sparrow-workspaces/src/features/socket-explorer/layout/SocketExplorer.svelte index c1ca88338..890b7e68f 100644 --- a/packages/@sparrow-workspaces/src/features/socket-explorer/layout/SocketExplorer.svelte +++ b/packages/@sparrow-workspaces/src/features/socket-explorer/layout/SocketExplorer.svelte @@ -195,6 +195,7 @@
@@ -270,9 +271,9 @@ border-right: 0 !important; } :global( - .rest-splitter .splitpanes__splitter:active, - .rest-splitter .splitpanes__splitter:hover - ) { + .rest-splitter .splitpanes__splitter:active, + .rest-splitter .splitpanes__splitter:hover + ) { background-color: var(--bg-primary-200) !important; } From 7f587540d635f06664de9c195f8613b0b1a01841 Mon Sep 17 00:00:00 2001 From: Harsh Date: Wed, 18 Dec 2024 16:13:51 +0530 Subject: [PATCH 10/56] fix: iswebapp import --- .../WebSocketExplorerPage/WebSocketExplorerPage.svelte | 1 + .../src/features/socket-explorer/layout/SocketExplorer.svelte | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/apps/@sparrow-desktop/src/pages/workspace-page/sub-pages/WebSocketExplorerPage/WebSocketExplorerPage.svelte b/apps/@sparrow-desktop/src/pages/workspace-page/sub-pages/WebSocketExplorerPage/WebSocketExplorerPage.svelte index 4c9a2bf69..4255eba3d 100644 --- a/apps/@sparrow-desktop/src/pages/workspace-page/sub-pages/WebSocketExplorerPage/WebSocketExplorerPage.svelte +++ b/apps/@sparrow-desktop/src/pages/workspace-page/sub-pages/WebSocketExplorerPage/WebSocketExplorerPage.svelte @@ -145,6 +145,7 @@ webSocket={webSocketData} {environmentVariables} {isGuestUser} + isWebApp={true} {isLoginBannerActive} onUpdateRequestUrl={_viewModel.updateRequestUrl} onUpdateRequestParams={_viewModel.updateParams} diff --git a/packages/@sparrow-workspaces/src/features/socket-explorer/layout/SocketExplorer.svelte b/packages/@sparrow-workspaces/src/features/socket-explorer/layout/SocketExplorer.svelte index 890b7e68f..eee04aa1b 100644 --- a/packages/@sparrow-workspaces/src/features/socket-explorer/layout/SocketExplorer.svelte +++ b/packages/@sparrow-workspaces/src/features/socket-explorer/layout/SocketExplorer.svelte @@ -67,7 +67,7 @@ export let onUpdateContentType; export let onClearInput; export let onUpdateFilterType; - + export let isWebApp = false; let isExposeSaveAsSocket = false; const toggleSaveRequest = (flag: boolean): void => { isExposeSaveAsSocket = flag; @@ -195,7 +195,7 @@
From 34e020d627192e7dd2f2f621b5d8798188f8bfcc Mon Sep 17 00:00:00 2001 From: Nayan lakhwani Date: Wed, 18 Dec 2024 17:19:04 +0530 Subject: [PATCH 11/56] fix: mac rounded corners --- apps/@sparrow-desktop/src-tauri/Cargo.lock | 1 + apps/@sparrow-desktop/src-tauri/Cargo.toml | 1 + apps/@sparrow-desktop/src-tauri/src/main.rs | 123 +++++++++++++++++- .../src-tauri/tauri.conf.json | 18 ++- .../src/components/App.svelte | 14 ++ .../default-header/DefaultHeader.svelte | 1 + .../header/window-action/WindowAction.svelte | 6 + 7 files changed, 158 insertions(+), 6 deletions(-) diff --git a/apps/@sparrow-desktop/src-tauri/Cargo.lock b/apps/@sparrow-desktop/src-tauri/Cargo.lock index b60fd5caa..242069da6 100644 --- a/apps/@sparrow-desktop/src-tauri/Cargo.lock +++ b/apps/@sparrow-desktop/src-tauri/Cargo.lock @@ -4246,6 +4246,7 @@ version = "0.0.0" dependencies = [ "anyhow", "brotli 3.5.0", + "cocoa", "dotenv", "flate2", "futures", diff --git a/apps/@sparrow-desktop/src-tauri/Cargo.toml b/apps/@sparrow-desktop/src-tauri/Cargo.toml index 646de3ccf..26fba7b29 100644 --- a/apps/@sparrow-desktop/src-tauri/Cargo.toml +++ b/apps/@sparrow-desktop/src-tauri/Cargo.toml @@ -50,3 +50,4 @@ tauri-plugin-fs = "2.2.0" tauri-plugin-deep-link = "2.2.0" [target.'cfg(target_os = "macos")'.dependencies] objc = "0.2" +cocoa = "0.26.0" diff --git a/apps/@sparrow-desktop/src-tauri/src/main.rs b/apps/@sparrow-desktop/src-tauri/src/main.rs index 51975de03..376374093 100644 --- a/apps/@sparrow-desktop/src-tauri/src/main.rs +++ b/apps/@sparrow-desktop/src-tauri/src/main.rs @@ -80,19 +80,113 @@ use tokio_tungstenite::connect_async; use tokio_tungstenite::tungstenite::protocol::Message; // Socket.IO imports +use futures_util::FutureExt; use rust_socketio::{ asynchronous::{Client as SocketClient, ClientBuilder}, Event as SocketIoEvent, Payload as SocketIoPayload, TransportType, }; - use tokio::sync::Mutex as SocketMutex; -use futures_util::FutureExt; - +// MacOs Window Titlebar Config Imports +#[cfg(target_os = "macos")] +use cocoa::appkit::{NSWindow, NSWindowButton, NSWindowStyleMask, NSWindowTitleVisibility}; +use objc::runtime::NO; #[cfg(target_os = "macos")] +use objc::runtime::YES; +use tauri::{Runtime, WebviewWindow}; +use tauri_plugin_os::platform; +#[cfg(target_os = "macos")] +#[macro_use] extern crate objc; +pub trait WindowExt { + #[cfg(target_os = "macos")] + fn set_transparent_titlebar(&self, title_transparent: bool, remove_toolbar: bool); + fn show_toolbar(&self); + fn hide_toolbar(&self); +} + +// Funtion to hide default titlebar in macos +impl WindowExt for WebviewWindow { + #[cfg(target_os = "macos")] + fn set_transparent_titlebar(&self, title_transparent: bool, remove_tool_bar: bool) { + unsafe { + let id = self.ns_window().unwrap() as cocoa::base::id; + NSWindow::setTitlebarAppearsTransparent_(id, cocoa::base::YES); + let mut style_mask = id.styleMask(); + style_mask.set( + NSWindowStyleMask::NSFullSizeContentViewWindowMask, + title_transparent, + ); + + id.setStyleMask_(style_mask); + + if remove_tool_bar { + let close_button = id.standardWindowButton_(NSWindowButton::NSWindowCloseButton); + let _: () = msg_send![close_button, setHidden: YES]; + let min_button = + id.standardWindowButton_(NSWindowButton::NSWindowMiniaturizeButton); + let _: () = msg_send![min_button, setHidden: YES]; + let zoom_button = id.standardWindowButton_(NSWindowButton::NSWindowZoomButton); + let _: () = msg_send![zoom_button, setHidden: YES]; + } + + id.setTitleVisibility_(if title_transparent { + NSWindowTitleVisibility::NSWindowTitleHidden + } else { + NSWindowTitleVisibility::NSWindowTitleVisible + }); + + id.setTitlebarAppearsTransparent_(if title_transparent { + cocoa::base::YES + } else { + cocoa::base::NO + }); + } + } + + #[cfg(target_os = "macos")] + fn show_toolbar(&self) { + unsafe { + let id = self.ns_window().unwrap() as cocoa::base::id; + + let close_button = id.standardWindowButton_(NSWindowButton::NSWindowCloseButton); + let _: () = msg_send![close_button, setHidden: NO]; + let min_button = id.standardWindowButton_(NSWindowButton::NSWindowMiniaturizeButton); + let _: () = msg_send![min_button, setHidden: NO]; + let zoom_button = id.standardWindowButton_(NSWindowButton::NSWindowZoomButton); + let _: () = msg_send![zoom_button, setHidden: NO]; + } + } + + #[cfg(target_os = "macos")] + fn hide_toolbar(&self) { + unsafe { + let id = self.ns_window().unwrap() as cocoa::base::id; + + let close_button = id.standardWindowButton_(NSWindowButton::NSWindowCloseButton); + let _: () = msg_send![close_button, setHidden: YES]; + let min_button = id.standardWindowButton_(NSWindowButton::NSWindowMiniaturizeButton); + let _: () = msg_send![min_button, setHidden: YES]; + let zoom_button = id.standardWindowButton_(NSWindowButton::NSWindowZoomButton); + let _: () = msg_send![zoom_button, setHidden: YES]; + } + } +} + // Commands +#[cfg(target_os = "macos")] +#[tauri::command] +fn hide_toolbar(window: tauri::WebviewWindow) { + window.hide_toolbar(); +} + +#[cfg(target_os = "macos")] +#[tauri::command] +fn show_toolbar(window: tauri::WebviewWindow) { + window.show_toolbar(); +} + #[tauri::command] fn fetch_swagger_url_command(url: &str, headers: &str, workspaceid: &str) -> Value { let response = import_swagger_url(url, headers, workspaceid); @@ -1139,6 +1233,25 @@ fn main() { app.manage(Arc::new(SocketIoAppState { connections: Mutex::new(std::collections::HashMap::new()), })); + + // Hide Titlebar for MacOS and close the additional window + let platform_name = platform(); + if platform_name == "macos" { + // Fetch tauri windows + let macos_window = app.get_webview_window("main").unwrap(); + let windows_window: WebviewWindow = app.get_webview_window("windows").unwrap(); + + // Close Windows window which has decoration set to false + let _ = windows_window.close(); + + // Hide Titlebar + macos_window.set_transparent_titlebar(true, true); + } else { + // Close Mac window which has decoration set to true + let macos_window = app.get_webview_window("main").unwrap(); + let _ = macos_window.close(); + } + Ok(()) }) .invoke_handler(tauri::generate_handler![ @@ -1156,7 +1269,9 @@ fn main() { connect_socket_io, disconnect_socket_io, send_socket_io_message, - send_graphql_request + send_graphql_request, + show_toolbar, + hide_toolbar ]) .on_page_load(|wry_window, _payload| { if let Ok(url) = wry_window.url() { diff --git a/apps/@sparrow-desktop/src-tauri/tauri.conf.json b/apps/@sparrow-desktop/src-tauri/tauri.conf.json index 0cb49d351..9bb4c0bb8 100644 --- a/apps/@sparrow-desktop/src-tauri/tauri.conf.json +++ b/apps/@sparrow-desktop/src-tauri/tauri.conf.json @@ -6,7 +6,7 @@ "windows": [ { "center": true, - "decorations": false, + "decorations": true, "fullscreen": false, "label": "main", "minHeight": 700, @@ -17,9 +17,23 @@ "focus": true, "dragDropEnabled": false, "maximized": true + }, + { + "center": true, + "decorations": false, + "fullscreen": false, + "label": "windows", + "minHeight": 700, + "minWidth": 1200, + "resizable": true, + "title": "Sparrow", + "shadow": true, + "focus": true, + "dragDropEnabled": false, + "maximized": true } ], - "withGlobalTauri": false + "withGlobalTauri": true }, "build": { "beforeBuildCommand": "yarn build", diff --git a/apps/@sparrow-desktop/src/components/App.svelte b/apps/@sparrow-desktop/src/components/App.svelte index f114b2634..509ead5ad 100644 --- a/apps/@sparrow-desktop/src/components/App.svelte +++ b/apps/@sparrow-desktop/src/components/App.svelte @@ -16,6 +16,9 @@ import { singleInstanceHandler } from "@app/utils/singleinstance/app.singleinstance"; import { AppViewModel } from "./app.ViewModel"; import { getScaleFactor, setScaleFactorToDb } from "@app/utils/zoom"; + import { listen } from "@tauri-apps/api/event"; + import { getCurrentWindow } from "@tauri-apps/api/window"; + import { invoke } from "@tauri-apps/api/core"; const _viewModel = new AppViewModel(); @@ -29,7 +32,18 @@ } else isActiveInternet = true; }; + // Hide Toolbar when window is restored from maximized state + async function setupMaximizeToggleListener() { + listen("tauri://resize", async () => { + const isMaximized = await getCurrentWindow().isFullscreen(); + if (!isMaximized) { + await invoke("hide_toolbar"); + } + }); + } + onMount(async () => { + setupMaximizeToggleListener(); await _viewModel.registerDeepLinkHandler(); await singleInstanceHandler(); await setScaleFactorToDb(await getScaleFactor()); diff --git a/packages/@sparrow-common/src/components/default-header/DefaultHeader.svelte b/packages/@sparrow-common/src/components/default-header/DefaultHeader.svelte index e5cb9eb48..b9f5cd4bb 100644 --- a/packages/@sparrow-common/src/components/default-header/DefaultHeader.svelte +++ b/packages/@sparrow-common/src/components/default-header/DefaultHeader.svelte @@ -35,6 +35,7 @@
Date: Wed, 18 Dec 2024 17:27:14 +0530 Subject: [PATCH 12/56] fix: mac rounded corners --- apps/@sparrow-desktop/src-tauri/src/main.rs | 61 ++++++++----------- .../src/components/App.svelte | 1 - 2 files changed, 25 insertions(+), 37 deletions(-) diff --git a/apps/@sparrow-desktop/src-tauri/src/main.rs b/apps/@sparrow-desktop/src-tauri/src/main.rs index 376374093..b5b22ed5c 100644 --- a/apps/@sparrow-desktop/src-tauri/src/main.rs +++ b/apps/@sparrow-desktop/src-tauri/src/main.rs @@ -102,33 +102,28 @@ extern crate objc; pub trait WindowExt { #[cfg(target_os = "macos")] fn set_transparent_titlebar(&self, title_transparent: bool, remove_toolbar: bool); - fn show_toolbar(&self); - fn hide_toolbar(&self); + fn set_toolbar_visibility(&self, visible: bool); } -// Funtion to hide default titlebar in macos +// Implementation for WebviewWindow impl WindowExt for WebviewWindow { #[cfg(target_os = "macos")] - fn set_transparent_titlebar(&self, title_transparent: bool, remove_tool_bar: bool) { + fn set_transparent_titlebar(&self, title_transparent: bool, remove_toolbar: bool) { unsafe { let id = self.ns_window().unwrap() as cocoa::base::id; + + // Set titlebar transparency NSWindow::setTitlebarAppearsTransparent_(id, cocoa::base::YES); let mut style_mask = id.styleMask(); style_mask.set( NSWindowStyleMask::NSFullSizeContentViewWindowMask, title_transparent, ); - id.setStyleMask_(style_mask); - if remove_tool_bar { - let close_button = id.standardWindowButton_(NSWindowButton::NSWindowCloseButton); - let _: () = msg_send![close_button, setHidden: YES]; - let min_button = - id.standardWindowButton_(NSWindowButton::NSWindowMiniaturizeButton); - let _: () = msg_send![min_button, setHidden: YES]; - let zoom_button = id.standardWindowButton_(NSWindowButton::NSWindowZoomButton); - let _: () = msg_send![zoom_button, setHidden: YES]; + // Adjust toolbar visibility + if remove_toolbar { + self.set_toolbar_visibility(false); } id.setTitleVisibility_(if title_transparent { @@ -146,30 +141,24 @@ impl WindowExt for WebviewWindow { } #[cfg(target_os = "macos")] - fn show_toolbar(&self) { - unsafe { - let id = self.ns_window().unwrap() as cocoa::base::id; - - let close_button = id.standardWindowButton_(NSWindowButton::NSWindowCloseButton); - let _: () = msg_send![close_button, setHidden: NO]; - let min_button = id.standardWindowButton_(NSWindowButton::NSWindowMiniaturizeButton); - let _: () = msg_send![min_button, setHidden: NO]; - let zoom_button = id.standardWindowButton_(NSWindowButton::NSWindowZoomButton); - let _: () = msg_send![zoom_button, setHidden: NO]; - } - } - - #[cfg(target_os = "macos")] - fn hide_toolbar(&self) { + fn set_toolbar_visibility(&self, visible: bool) { unsafe { let id = self.ns_window().unwrap() as cocoa::base::id; - let close_button = id.standardWindowButton_(NSWindowButton::NSWindowCloseButton); - let _: () = msg_send![close_button, setHidden: YES]; - let min_button = id.standardWindowButton_(NSWindowButton::NSWindowMiniaturizeButton); - let _: () = msg_send![min_button, setHidden: YES]; - let zoom_button = id.standardWindowButton_(NSWindowButton::NSWindowZoomButton); - let _: () = msg_send![zoom_button, setHidden: YES]; + let visibility = if visible { + cocoa::base::NO + } else { + cocoa::base::YES + }; + let buttons = [ + id.standardWindowButton_(NSWindowButton::NSWindowCloseButton), + id.standardWindowButton_(NSWindowButton::NSWindowMiniaturizeButton), + id.standardWindowButton_(NSWindowButton::NSWindowZoomButton), + ]; + + for button in buttons { + let _: () = msg_send![button, setHidden: visibility]; + } } } } @@ -178,13 +167,13 @@ impl WindowExt for WebviewWindow { #[cfg(target_os = "macos")] #[tauri::command] fn hide_toolbar(window: tauri::WebviewWindow) { - window.hide_toolbar(); + window.set_toolbar_visibility(false); } #[cfg(target_os = "macos")] #[tauri::command] fn show_toolbar(window: tauri::WebviewWindow) { - window.show_toolbar(); + window.set_toolbar_visibility(true); } #[tauri::command] diff --git a/apps/@sparrow-desktop/src/components/App.svelte b/apps/@sparrow-desktop/src/components/App.svelte index 509ead5ad..5449d82f3 100644 --- a/apps/@sparrow-desktop/src/components/App.svelte +++ b/apps/@sparrow-desktop/src/components/App.svelte @@ -17,7 +17,6 @@ import { AppViewModel } from "./app.ViewModel"; import { getScaleFactor, setScaleFactorToDb } from "@app/utils/zoom"; import { listen } from "@tauri-apps/api/event"; - import { getCurrentWindow } from "@tauri-apps/api/window"; import { invoke } from "@tauri-apps/api/core"; const _viewModel = new AppViewModel(); From 58d78619d50c35d2d1307cfdf452a6dc6a9aa16d Mon Sep 17 00:00:00 2001 From: Nayan lakhwani Date: Wed, 18 Dec 2024 17:42:25 +0530 Subject: [PATCH 13/56] fix: mac rounded corners --- .../src/components/App.svelte | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/apps/@sparrow-desktop/src/components/App.svelte b/apps/@sparrow-desktop/src/components/App.svelte index 5449d82f3..5b9ea1a3e 100644 --- a/apps/@sparrow-desktop/src/components/App.svelte +++ b/apps/@sparrow-desktop/src/components/App.svelte @@ -18,6 +18,7 @@ import { getScaleFactor, setScaleFactorToDb } from "@app/utils/zoom"; import { listen } from "@tauri-apps/api/event"; import { invoke } from "@tauri-apps/api/core"; + import { platform } from "@tauri-apps/plugin-os"; const _viewModel = new AppViewModel(); @@ -32,17 +33,19 @@ }; // Hide Toolbar when window is restored from maximized state - async function setupMaximizeToggleListener() { - listen("tauri://resize", async () => { - const isMaximized = await getCurrentWindow().isFullscreen(); - if (!isMaximized) { - await invoke("hide_toolbar"); - } - }); + async function setupMaximizeToggleListenerForMac() { + if (platform() === "macos") { + listen("tauri://resize", async () => { + const isMaximized = await getCurrentWindow().isFullscreen(); + if (!isMaximized) { + await invoke("hide_toolbar"); + } + }); + } } onMount(async () => { - setupMaximizeToggleListener(); + setupMaximizeToggleListenerForMac(); await _viewModel.registerDeepLinkHandler(); await singleInstanceHandler(); await setScaleFactorToDb(await getScaleFactor()); From 66dfa40324457a076a03f48731d51763392f5a2e Mon Sep 17 00:00:00 2001 From: Nayan lakhwani Date: Wed, 18 Dec 2024 17:56:30 +0530 Subject: [PATCH 14/56] fix: mac rounded corners --- apps/@sparrow-desktop/src-tauri/src/main.rs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/apps/@sparrow-desktop/src-tauri/src/main.rs b/apps/@sparrow-desktop/src-tauri/src/main.rs index b5b22ed5c..fef534869 100644 --- a/apps/@sparrow-desktop/src-tauri/src/main.rs +++ b/apps/@sparrow-desktop/src-tauri/src/main.rs @@ -100,14 +100,12 @@ use tauri_plugin_os::platform; extern crate objc; pub trait WindowExt { - #[cfg(target_os = "macos")] fn set_transparent_titlebar(&self, title_transparent: bool, remove_toolbar: bool); fn set_toolbar_visibility(&self, visible: bool); } // Implementation for WebviewWindow impl WindowExt for WebviewWindow { - #[cfg(target_os = "macos")] fn set_transparent_titlebar(&self, title_transparent: bool, remove_toolbar: bool) { unsafe { let id = self.ns_window().unwrap() as cocoa::base::id; @@ -140,7 +138,6 @@ impl WindowExt for WebviewWindow { } } - #[cfg(target_os = "macos")] fn set_toolbar_visibility(&self, visible: bool) { unsafe { let id = self.ns_window().unwrap() as cocoa::base::id; @@ -164,13 +161,11 @@ impl WindowExt for WebviewWindow { } // Commands -#[cfg(target_os = "macos")] #[tauri::command] fn hide_toolbar(window: tauri::WebviewWindow) { window.set_toolbar_visibility(false); } -#[cfg(target_os = "macos")] #[tauri::command] fn show_toolbar(window: tauri::WebviewWindow) { window.set_toolbar_visibility(true); From 37e3bb861be80646ceb2c70726f2193fad02dbb4 Mon Sep 17 00:00:00 2001 From: Nayan lakhwani Date: Wed, 18 Dec 2024 17:59:04 +0530 Subject: [PATCH 15/56] fix: mac rounded corners --- apps/@sparrow-desktop/src-tauri/src/main.rs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/apps/@sparrow-desktop/src-tauri/src/main.rs b/apps/@sparrow-desktop/src-tauri/src/main.rs index fef534869..f6916e2b8 100644 --- a/apps/@sparrow-desktop/src-tauri/src/main.rs +++ b/apps/@sparrow-desktop/src-tauri/src/main.rs @@ -88,14 +88,9 @@ use rust_socketio::{ use tokio::sync::Mutex as SocketMutex; // MacOs Window Titlebar Config Imports -#[cfg(target_os = "macos")] use cocoa::appkit::{NSWindow, NSWindowButton, NSWindowStyleMask, NSWindowTitleVisibility}; -use objc::runtime::NO; -#[cfg(target_os = "macos")] -use objc::runtime::YES; use tauri::{Runtime, WebviewWindow}; use tauri_plugin_os::platform; -#[cfg(target_os = "macos")] #[macro_use] extern crate objc; From f2aa0573697c10096b069b9ef911af6cb145fa23 Mon Sep 17 00:00:00 2001 From: Astitva Patle Date: Wed, 18 Dec 2024 18:47:51 +0530 Subject: [PATCH 16/56] fix: removed [target.'cfg(target_os = macos)'.dependencies] --- apps/@sparrow-desktop/src-tauri/Cargo.toml | 1 - .../src-tauri/gen/schemas/windows-schema.json | 34 +++++++++++++++---- 2 files changed, 27 insertions(+), 8 deletions(-) diff --git a/apps/@sparrow-desktop/src-tauri/Cargo.toml b/apps/@sparrow-desktop/src-tauri/Cargo.toml index 646de3ccf..79e7be43a 100644 --- a/apps/@sparrow-desktop/src-tauri/Cargo.toml +++ b/apps/@sparrow-desktop/src-tauri/Cargo.toml @@ -48,5 +48,4 @@ tauri-plugin-shell = "2.2.0" tauri-plugin-dialog = "2.2.0" tauri-plugin-fs = "2.2.0" tauri-plugin-deep-link = "2.2.0" -[target.'cfg(target_os = "macos")'.dependencies] objc = "0.2" diff --git a/apps/@sparrow-desktop/src-tauri/gen/schemas/windows-schema.json b/apps/@sparrow-desktop/src-tauri/gen/schemas/windows-schema.json index a46a74266..7355bdc2f 100644 --- a/apps/@sparrow-desktop/src-tauri/gen/schemas/windows-schema.json +++ b/apps/@sparrow-desktop/src-tauri/gen/schemas/windows-schema.json @@ -84,7 +84,7 @@ } }, "permissions": { - "description": "List of permissions attached to this capability.\n\nMust include the plugin name as prefix in the form of `${plugin-name}:${permission-name}`. For commands directly implemented in the application itself only `${permission-name}` is required.\n\n## Example\n\n```json [ \"core:default\", \"shell:allow-open\", \"dialog:open\", { \"identifier\": \"fs:allow-write-text-file\", \"allow\": [{ \"path\": \"$HOME/test.txt\" }] } ```", + "description": "List of permissions attached to this capability.\n\nMust include the plugin name as prefix in the form of `${plugin-name}:${permission-name}`. For commands directly implemented in the application itself only `${permission-name}` is required.\n\n## Example\n\n```json [ \"core:default\", \"shell:allow-open\", \"dialog:open\", { \"identifier\": \"fs:allow-write-text-file\", \"allow\": [{ \"path\": \"$HOME/test.txt\" }] } ] ```", "type": "array", "items": { "$ref": "#/definitions/PermissionEntry" @@ -140,7 +140,7 @@ "identifier": { "anyOf": [ { - "description": "This set of permissions describes the what kind of\nfile system access the `fs` plugin has enabled or denied by default.\n\n#### Granted Permissions\n\nThis default permission set enables read access to the\napplication specific directories (AppConfig, AppData, AppLocalData, AppCache,\nAppLog) and all files and sub directories created in it.\nThe location of these directories depends on the operating system,\nwhere the application is run.\n\nIn general these directories need to be manually created\nby the application at runtime, before accessing files or folders\nin it is possible.\n\nTherefore, it is also allowed to create all of these folders via\nthe `mkdir` command.\n\n#### Denied Permissions\n\nThis default permission set prevents access to critical components\nof the Tauri application by default.\nOn Windows the webview data folder access is denied.\n\n", + "description": "This set of permissions describes the what kind of\nfile system access the `fs` plugin has enabled or denied by default.\n\n#### Granted Permissions\n\nThis default permission set enables read access to the\napplication specific directories (AppConfig, AppData, AppLocalData, AppCache,\nAppLog) and all files and sub directories created in it.\nThe location of these directories depends on the operating system,\nwhere the application is run.\n\nIn general these directories need to be manually created\nby the application at runtime, before accessing files or folders\nin it is possible.\n\nTherefore, it is also allowed to create all of these folders via\nthe `mkdir` command.\n\n#### Denied Permissions\n\nThis default permission set prevents access to critical components\nof the Tauri application by default.\nOn Windows the webview data folder access is denied.\n\n#### Included permissions within this default permission set:\n", "type": "string", "const": "fs:default" }, @@ -984,6 +984,11 @@ "type": "string", "const": "fs:allow-seek" }, + { + "description": "Enables the size command without any pre-configured scope.", + "type": "string", + "const": "fs:allow-size" + }, { "description": "Enables the stat command without any pre-configured scope.", "type": "string", @@ -1109,6 +1114,11 @@ "type": "string", "const": "fs:deny-seek" }, + { + "description": "Denies the size command without any pre-configured scope.", + "type": "string", + "const": "fs:deny-size" + }, { "description": "Denies the stat command without any pre-configured scope.", "type": "string", @@ -1581,7 +1591,7 @@ "description": "FS scope entry.", "anyOf": [ { - "description": "FS scope path.", + "description": "A path that can be accessed by the webview when using the fs APIs. FS scope path pattern.\n\nThe pattern can start with a variable that resolves to a system base directory. The variables are: `$AUDIO`, `$CACHE`, `$CONFIG`, `$DATA`, `$LOCALDATA`, `$DESKTOP`, `$DOCUMENT`, `$DOWNLOAD`, `$EXE`, `$FONT`, `$HOME`, `$PICTURE`, `$PUBLIC`, `$RUNTIME`, `$TEMPLATE`, `$VIDEO`, `$RESOURCE`, `$APP`, `$LOG`, `$TEMP`, `$APPCONFIG`, `$APPDATA`, `$APPLOCALDATA`, `$APPCACHE`, `$APPLOG`.", "type": "string" }, { @@ -1591,7 +1601,7 @@ ], "properties": { "path": { - "description": "FS scope path.", + "description": "A path that can be accessed by the webview when using the fs APIs.\n\nThe pattern can start with a variable that resolves to a system base directory. The variables are: `$AUDIO`, `$CACHE`, `$CONFIG`, `$DATA`, `$LOCALDATA`, `$DESKTOP`, `$DOCUMENT`, `$DOWNLOAD`, `$EXE`, `$FONT`, `$HOME`, `$PICTURE`, `$PUBLIC`, `$RUNTIME`, `$TEMPLATE`, `$VIDEO`, `$RESOURCE`, `$APP`, `$LOG`, `$TEMP`, `$APPCONFIG`, `$APPDATA`, `$APPLOCALDATA`, `$APPCACHE`, `$APPLOG`.", "type": "string" } } @@ -1605,7 +1615,7 @@ "description": "FS scope entry.", "anyOf": [ { - "description": "FS scope path.", + "description": "A path that can be accessed by the webview when using the fs APIs. FS scope path pattern.\n\nThe pattern can start with a variable that resolves to a system base directory. The variables are: `$AUDIO`, `$CACHE`, `$CONFIG`, `$DATA`, `$LOCALDATA`, `$DESKTOP`, `$DOCUMENT`, `$DOWNLOAD`, `$EXE`, `$FONT`, `$HOME`, `$PICTURE`, `$PUBLIC`, `$RUNTIME`, `$TEMPLATE`, `$VIDEO`, `$RESOURCE`, `$APP`, `$LOG`, `$TEMP`, `$APPCONFIG`, `$APPDATA`, `$APPLOCALDATA`, `$APPCACHE`, `$APPLOG`.", "type": "string" }, { @@ -1615,7 +1625,7 @@ ], "properties": { "path": { - "description": "FS scope path.", + "description": "A path that can be accessed by the webview when using the fs APIs.\n\nThe pattern can start with a variable that resolves to a system base directory. The variables are: `$AUDIO`, `$CACHE`, `$CONFIG`, `$DATA`, `$LOCALDATA`, `$DESKTOP`, `$DOCUMENT`, `$DOWNLOAD`, `$EXE`, `$FONT`, `$HOME`, `$PICTURE`, `$PUBLIC`, `$RUNTIME`, `$TEMPLATE`, `$VIDEO`, `$RESOURCE`, `$APP`, `$LOG`, `$TEMP`, `$APPCONFIG`, `$APPDATA`, `$APPLOCALDATA`, `$APPCACHE`, `$APPLOG`.", "type": "string" } } @@ -3458,7 +3468,7 @@ "const": "dialog:deny-save" }, { - "description": "This set of permissions describes the what kind of\nfile system access the `fs` plugin has enabled or denied by default.\n\n#### Granted Permissions\n\nThis default permission set enables read access to the\napplication specific directories (AppConfig, AppData, AppLocalData, AppCache,\nAppLog) and all files and sub directories created in it.\nThe location of these directories depends on the operating system,\nwhere the application is run.\n\nIn general these directories need to be manually created\nby the application at runtime, before accessing files or folders\nin it is possible.\n\nTherefore, it is also allowed to create all of these folders via\nthe `mkdir` command.\n\n#### Denied Permissions\n\nThis default permission set prevents access to critical components\nof the Tauri application by default.\nOn Windows the webview data folder access is denied.\n\n", + "description": "This set of permissions describes the what kind of\nfile system access the `fs` plugin has enabled or denied by default.\n\n#### Granted Permissions\n\nThis default permission set enables read access to the\napplication specific directories (AppConfig, AppData, AppLocalData, AppCache,\nAppLog) and all files and sub directories created in it.\nThe location of these directories depends on the operating system,\nwhere the application is run.\n\nIn general these directories need to be manually created\nby the application at runtime, before accessing files or folders\nin it is possible.\n\nTherefore, it is also allowed to create all of these folders via\nthe `mkdir` command.\n\n#### Denied Permissions\n\nThis default permission set prevents access to critical components\nof the Tauri application by default.\nOn Windows the webview data folder access is denied.\n\n#### Included permissions within this default permission set:\n", "type": "string", "const": "fs:default" }, @@ -4302,6 +4312,11 @@ "type": "string", "const": "fs:allow-seek" }, + { + "description": "Enables the size command without any pre-configured scope.", + "type": "string", + "const": "fs:allow-size" + }, { "description": "Enables the stat command without any pre-configured scope.", "type": "string", @@ -4427,6 +4442,11 @@ "type": "string", "const": "fs:deny-seek" }, + { + "description": "Denies the size command without any pre-configured scope.", + "type": "string", + "const": "fs:deny-size" + }, { "description": "Denies the stat command without any pre-configured scope.", "type": "string", From 89507f8734f64fbaaadc4492c85faea92702ee51 Mon Sep 17 00:00:00 2001 From: Nayan Lakhwani Date: Wed, 18 Dec 2024 08:56:39 -0500 Subject: [PATCH 17/56] feat: add cocoa as a extern crate[] --- apps/@sparrow-desktop/src-tauri/Cargo.toml | 2 ++ apps/@sparrow-desktop/src-tauri/src/main.rs | 7 +++++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/apps/@sparrow-desktop/src-tauri/Cargo.toml b/apps/@sparrow-desktop/src-tauri/Cargo.toml index b461003f8..d53a34ae8 100644 --- a/apps/@sparrow-desktop/src-tauri/Cargo.toml +++ b/apps/@sparrow-desktop/src-tauri/Cargo.toml @@ -48,5 +48,7 @@ tauri-plugin-shell = "2.2.0" tauri-plugin-dialog = "2.2.0" tauri-plugin-fs = "2.2.0" tauri-plugin-deep-link = "2.2.0" + +[target.'cfg(target_os = "macos")'.dependencies] objc = "0.2" cocoa = "0.26.0" diff --git a/apps/@sparrow-desktop/src-tauri/src/main.rs b/apps/@sparrow-desktop/src-tauri/src/main.rs index f6916e2b8..698f07f1a 100644 --- a/apps/@sparrow-desktop/src-tauri/src/main.rs +++ b/apps/@sparrow-desktop/src-tauri/src/main.rs @@ -88,11 +88,14 @@ use rust_socketio::{ use tokio::sync::Mutex as SocketMutex; // MacOs Window Titlebar Config Imports +#[macro_use] +extern crate objc; +extern crate cocoa; + use cocoa::appkit::{NSWindow, NSWindowButton, NSWindowStyleMask, NSWindowTitleVisibility}; use tauri::{Runtime, WebviewWindow}; use tauri_plugin_os::platform; -#[macro_use] -extern crate objc; + pub trait WindowExt { fn set_transparent_titlebar(&self, title_transparent: bool, remove_toolbar: bool); From 21e028257cfd51a27394c61cfc7b9fa187a66fa2 Mon Sep 17 00:00:00 2001 From: Nayan Lakhwani Date: Wed, 18 Dec 2024 09:01:12 -0500 Subject: [PATCH 18/56] feat: add cocoa as a extern crate[] --- apps/@sparrow-desktop/src-tauri/src/main.rs | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/apps/@sparrow-desktop/src-tauri/src/main.rs b/apps/@sparrow-desktop/src-tauri/src/main.rs index 698f07f1a..897ebdfaa 100644 --- a/apps/@sparrow-desktop/src-tauri/src/main.rs +++ b/apps/@sparrow-desktop/src-tauri/src/main.rs @@ -86,15 +86,18 @@ use rust_socketio::{ Event as SocketIoEvent, Payload as SocketIoPayload, TransportType, }; use tokio::sync::Mutex as SocketMutex; +use tauri_plugin_os::platform; + // MacOs Window Titlebar Config Imports +#[cfg(target_os = "macos")] #[macro_use] extern crate objc; extern crate cocoa; +#[cfg(target_os = "macos")] use cocoa::appkit::{NSWindow, NSWindowButton, NSWindowStyleMask, NSWindowTitleVisibility}; use tauri::{Runtime, WebviewWindow}; -use tauri_plugin_os::platform; pub trait WindowExt { @@ -103,6 +106,7 @@ pub trait WindowExt { } // Implementation for WebviewWindow +#[cfg(target_os = "macos")] impl WindowExt for WebviewWindow { fn set_transparent_titlebar(&self, title_transparent: bool, remove_toolbar: bool) { unsafe { @@ -158,6 +162,18 @@ impl WindowExt for WebviewWindow { } } +// Windows/Linux placeholder implementation (no-op) +#[cfg(not(target_os = "macos"))] +impl WindowExt for WebviewWindow { + fn set_transparent_titlebar(&self, _title_transparent: bool, _remove_toolbar: bool) { + // No-op: Not supported on Windows or Linux + } + + fn set_toolbar_visibility(&self, _visible: bool) { + // No-op: Not supported on Windows or Linux + } +} + // Commands #[tauri::command] fn hide_toolbar(window: tauri::WebviewWindow) { From ef0432ba003be2e9974b074225a613df4add36b4 Mon Sep 17 00:00:00 2001 From: Nayan Lakhwani Date: Wed, 18 Dec 2024 11:14:07 -0500 Subject: [PATCH 19/56] feat: add cocoa as a extern crate[] --- apps/@sparrow-desktop/src-tauri/src/main.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/apps/@sparrow-desktop/src-tauri/src/main.rs b/apps/@sparrow-desktop/src-tauri/src/main.rs index 897ebdfaa..94f1ae061 100644 --- a/apps/@sparrow-desktop/src-tauri/src/main.rs +++ b/apps/@sparrow-desktop/src-tauri/src/main.rs @@ -93,6 +93,9 @@ use tauri_plugin_os::platform; #[cfg(target_os = "macos")] #[macro_use] extern crate objc; + +#[cfg(target_os = "macos")] +#[macro_use] extern crate cocoa; #[cfg(target_os = "macos")] From b553de50ce9713079e97f6b22b99b029436d4bea Mon Sep 17 00:00:00 2001 From: Nayan Lakhwani Date: Wed, 18 Dec 2024 11:14:47 -0500 Subject: [PATCH 20/56] feat: add cocoa as a extern crate[] --- apps/@sparrow-desktop/src-tauri/src/main.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/apps/@sparrow-desktop/src-tauri/src/main.rs b/apps/@sparrow-desktop/src-tauri/src/main.rs index 94f1ae061..94ce7e037 100644 --- a/apps/@sparrow-desktop/src-tauri/src/main.rs +++ b/apps/@sparrow-desktop/src-tauri/src/main.rs @@ -95,7 +95,6 @@ use tauri_plugin_os::platform; extern crate objc; #[cfg(target_os = "macos")] -#[macro_use] extern crate cocoa; #[cfg(target_os = "macos")] From 0324c1f8d53e17c04de8692d978aba8299be0822 Mon Sep 17 00:00:00 2001 From: pratikshinde590 Date: Wed, 18 Dec 2024 22:51:09 +0530 Subject: [PATCH 21/56] build: Added new ENV in workflows dev, prod [] --- .github/workflows/development.yaml | 1 + .github/workflows/release.yaml | 1 + .github/workflows/sparrow-web-dev.yml | 2 ++ .github/workflows/sparrow-web-prod.yml | 1 + 4 files changed, 5 insertions(+) diff --git a/.github/workflows/development.yaml b/.github/workflows/development.yaml index 5fb1ab85d..070285c0e 100644 --- a/.github/workflows/development.yaml +++ b/.github/workflows/development.yaml @@ -23,6 +23,7 @@ env: VITE_CANNY_URL: ${{ vars.VITE_CANNY_URL }} VITE_BASE_URL: ${{ vars.VITE_BASE_URL }} VITE_SPARROW_LINKEDIN: ${{ vars.VITE_SPARROW_LINKEDIN }} + VITE_WEB_SOCKET_IO_API_URL: ${{ vars.VITE_WEB_SOCKET_IO_API_URL }} ACTIONS_ALLOW_UNSECURE_COMMANDS: true jobs: diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 18125ac29..91985746c 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -23,6 +23,7 @@ env: VITE_CANNY_URL: ${{ vars.VITE_CANNY_URL }} VITE_BASE_URL: ${{ vars.VITE_BASE_URL }} VITE_SPARROW_LINKEDIN: ${{ vars.VITE_SPARROW_LINKEDIN }} + VITE_WEB_SOCKET_IO_API_URL: ${{ vars.VITE_WEB_SOCKET_IO_API_URL }} ACTIONS_ALLOW_UNSECURE_COMMANDS: true jobs: diff --git a/.github/workflows/sparrow-web-dev.yml b/.github/workflows/sparrow-web-dev.yml index 52588be0c..6c2366a79 100644 --- a/.github/workflows/sparrow-web-dev.yml +++ b/.github/workflows/sparrow-web-dev.yml @@ -36,6 +36,8 @@ jobs: --build-arg VITE_WEB_MARKETING_URL=${{ vars.VITE_WEB_MARKETING_URL }} \ --build-arg VITE_WEB_SPARROW_DOCS=${{ vars.VITE_WEB_SPARROW_DOCS }} \ --build-arg VITE_WEB_PROXY_SERVICE=${{ vars.VITE_WEB_PROXY_SERVICE }} \ + --build-arg VITE_WEB_SOCKET_IO_API_URL=${{ vars.VITE_WEB_SOCKET_IO_API_URL }} \ + -t sparrowprod.azurecr.io/sparrow-web:${{ github.run_number }} . docker push sparrowprod.azurecr.io/sparrow-web:${{ github.run_number }} diff --git a/.github/workflows/sparrow-web-prod.yml b/.github/workflows/sparrow-web-prod.yml index c54c63c41..d60a1baf3 100644 --- a/.github/workflows/sparrow-web-prod.yml +++ b/.github/workflows/sparrow-web-prod.yml @@ -36,6 +36,7 @@ jobs: --build-arg VITE_WEB_MARKETING_URL=${{ vars.VITE_WEB_MARKETING_URL }} \ --build-arg VITE_WEB_SPARROW_DOCS=${{ vars.VITE_WEB_SPARROW_DOCS }} \ --build-arg VITE_WEB_PROXY_SERVICE=${{ vars.VITE_WEB_PROXY_SERVICE }} \ + --build-arg VITE_WEB_SOCKET_IO_API_URL=${{ vars.VITE_WEB_SOCKET_IO_API_URL }} \ -t sparrowprod.azurecr.io/sparrow-web:${{ github.run_number }} . docker push sparrowprod.azurecr.io/sparrow-web:${{ github.run_number }} From eab01dfeb8328f0ee60ceb4b69873356576dd400 Mon Sep 17 00:00:00 2001 From: pratikshinde590 Date: Wed, 18 Dec 2024 22:57:47 +0530 Subject: [PATCH 22/56] build: Added new ENV in workflows dev, prod [] --- docker-compose.yml | 156 --------------------------------------------- 1 file changed, 156 deletions(-) delete mode 100644 docker-compose.yml diff --git a/docker-compose.yml b/docker-compose.yml deleted file mode 100644 index 4916fca7f..000000000 --- a/docker-compose.yml +++ /dev/null @@ -1,156 +0,0 @@ -version: "3.8" - -services: - # MongoDB - mongo: - image: mongo:7.0 - ports: - - "27017:27017" - environment: - MONGO_INITDB_ROOT_USERNAME: sparowapp - MONGO_INITDB_ROOT_PASSWORD: sparrow123 - networks: - - localnet - - # Kafka - kafka: - image: bitnami/kafka:3.4.1 - hostname: kafka - ports: - - "9092:9092" - volumes: - - "kafka_data:/bitnami" - environment: - - KAFKA_ENABLE_KRAFT=yes - - KAFKA_CFG_PROCESS_ROLES=broker,controller - - KAFKA_CFG_CONTROLLER_LISTENER_NAMES=CONTROLLER - - KAFKA_CFG_LISTENERS=PLAINTEXT://:9092,CONTROLLER://:9093,EXTERNAL://:9094 - - KAFKA_CFG_LISTENER_SECURITY_PROTOCOL_MAP=CONTROLLER:PLAINTEXT,PLAINTEXT:PLAINTEXT,EXTERNAL:PLAINTEXT - - KAFKA_CFG_ADVERTISED_LISTENERS=PLAINTEXT://127.0.0.1:9092,EXTERNAL://kafka:9094 - - KAFKA_BROKER_ID=1 - - KAFKA_CFG_CONTROLLER_QUORUM_VOTERS=1@localhost:9093 - - ALLOW_PLAINTEXT_LISTENER=yes - - KAFKA_CFG_NODE_ID=1 - - KAFKA_AUTO_CREATE_TOPICS_ENABLE=true - - KAFKA_CFG_NUM_PARTITIONS=2 - - KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR=1 - - KAFKA_TRANSACTION_STATE_LOG_MIN_ISR=1 - - KAFKA_TRANSACTION_STATE_LOG_REPLICATION_FACTOR=1 - - KAFKA_GROUP_INITIAL_REBALANCE_DELAY_MS=0 - - KAFKA_MESSAGE_MAX_BYTES=1000000 - networks: - - localnet - - # App - app: - image: sparrowapi/sparrow-api:v2 - ports: - - "9000:9000" - volumes: - - ./:/src - networks: - - localnet - depends_on: - - mongo - - kafka - environment: - # APP - PORT: 9000 - APP_ENV: DEV - APP_URL: http://localhost - - # AUTH - JWT_SECRET_KEY: webtoken-secret-key - JWT_EXPIRATION_TIME: 2400 - - # DATABASE - DB_URL: mongodb://sparowapp:sparrow123@mongo:27017 - - # Google OAuth - GOOGLE_CLIENT_ID: google-client-id - GOOGLE_CLIENT_SECRET: google-client-secret - GOOGLE_APP_URL: google-app-url - LOGIN_REDIRECT_URL: login-redirect-url - GOOGLE_ACCESS_TYPE: google-access-type - - # EXPIRY TIME FOR EMAIL VALIDATION CODE/LINK - EMAIL_VALIDATION_CODE_EXPIRY_TIME: "" - - # KAFKA - KAFKA_BROKER: kafka:9094 - - # EMAIL - SMTP_SENDER_EMAIL: "" - SMTP_SENDER_PASSWORD: "" - SMTP_MAIL_HOST: "" - SMTP_MAIL_PORT: "" - SMTP_MAIL_SECURE: "" - SMTP_USER_NAME: "" - - # REFRESH TOKEN - REFRESH_TOKEN_SECRET_KEY: refresh-token-secret - REFRESH_TOKEN_EXPIRATION_TIME: 604800 - REFRESH_TOKEN_MAX_LIMIT: 50 - - # APP UPDATER - APP_UPDATE_AVAILABLE: false - APP_VERSION: "" - WINDOWS_APP_SIGNATURE: "" - WINDOWS_APP_URL: "" - MAC_APPLE_SILICON_APP_SIGNATURE: "" - MAC_APPLE_SILICON_APP_URL: "" - MAC_INTEL_APP_SIGNATURE: "" - MAC_INTEL_APP_URL: "" - - # SUPPORT - SPARROW_EMAIL: contactus@sparrowapp.dev - - # AZURE SERVICES - AZURE_CONNECTION_STRING: "" - AZURE_INSIGHTS_CONNECTION_STRING: "" - FEEDBACK_BLOB_CONTAINER: "" - - # AI SUPPORT - AZURE_OPENAI_ENDPOINT: "" - AZURE_OPENAI_API_KEY: "" - AZURE_OPENAI_DEPLOYMENT: "" - AZURE_OPENAI_API_VERSION: "" - AZURE_OPENAI_MAX_TOKENS: "" - AZURE_OPENAI_MONTHLY_TOKEN_LIMIT: "" - - # Hubspot - HUBSPOT_BASEURL: "" - HUBSPOT_INTEGRATION_ENABLED: "" - HUBSPOT_PORTALID: "" - HUBSPOT_FORMID: "" - - # Sparrow Auth - auth: - image: sparrowapi/sparrow-auth:v1 - ports: - - "80:80" - networks: - - localnet - depends_on: - - mongo - - kafka - environment: - AUTH_SERVICE_PORT: 80 - JWT_SECRET: auth-jwt-secret - DB_URL: mongodb://sparowapp:sparrow123@mongo:27017 - VITE_API_URL: "http://localhost:9000" - VITE_SPARROW_SUPPORT_EMAIL: "support@example.dev" - VITE_SPARROW_OAUTH: "http://localhost:9000/api/auth/google/callback" - VITE_ENABLE_MIX_PANEL: "false" - VITE_MIX_PANEL_TOKEN: "" - VITE_TERMS_OF_SERVICE: "https://example.dev/termsandconditions" - VITE_SPARROW_WEB_URL: "http://localhost:1422" - VITE_SPARROW_PRIVACY_POLICY: "https://example.com/privacy-policy" - -volumes: - kafka_data: - driver: local - -networks: - localnet: - driver: bridge From 7967c29053a103ba7e9a71e4ff468a63820c69d6 Mon Sep 17 00:00:00 2001 From: pratikshinde590 Date: Wed, 18 Dec 2024 23:30:34 +0530 Subject: [PATCH 23/56] build: fix docker build issue [] --- .github/workflows/sparrow-web-dev.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/sparrow-web-dev.yml b/.github/workflows/sparrow-web-dev.yml index 6c2366a79..19788d86a 100644 --- a/.github/workflows/sparrow-web-dev.yml +++ b/.github/workflows/sparrow-web-dev.yml @@ -37,7 +37,6 @@ jobs: --build-arg VITE_WEB_SPARROW_DOCS=${{ vars.VITE_WEB_SPARROW_DOCS }} \ --build-arg VITE_WEB_PROXY_SERVICE=${{ vars.VITE_WEB_PROXY_SERVICE }} \ --build-arg VITE_WEB_SOCKET_IO_API_URL=${{ vars.VITE_WEB_SOCKET_IO_API_URL }} \ - -t sparrowprod.azurecr.io/sparrow-web:${{ github.run_number }} . docker push sparrowprod.azurecr.io/sparrow-web:${{ github.run_number }} From cfa7b890e5c559ae6b35a187c68f232bc420d247 Mon Sep 17 00:00:00 2001 From: Nayan Lakhwani Date: Wed, 18 Dec 2024 22:32:28 -0500 Subject: [PATCH 24/56] feat: added windows as a valid webview[] --- apps/@sparrow-desktop/src-tauri/capabilities/migrated.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/@sparrow-desktop/src-tauri/capabilities/migrated.json b/apps/@sparrow-desktop/src-tauri/capabilities/migrated.json index 7b39dbb3f..9ee8acb0b 100644 --- a/apps/@sparrow-desktop/src-tauri/capabilities/migrated.json +++ b/apps/@sparrow-desktop/src-tauri/capabilities/migrated.json @@ -2,7 +2,7 @@ "identifier": "migrated", "description": "permissions that were migrated from v1", "context": "local", - "windows": ["main"], + "windows": ["main", "windows"], "permissions": [ "core:path:default", "core:event:default", From ba9a25cba714229d5771ed34e482933484a5dc7d Mon Sep 17 00:00:00 2001 From: Aakash Reddy Date: Thu, 19 Dec 2024 10:43:08 +0530 Subject: [PATCH 25/56] Fix: resolved collection placeholder message/[#2217] --- .../features/import-collection/layout/ImportCollection.svelte | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/packages/@sparrow-workspaces/src/features/import-collection/layout/ImportCollection.svelte b/packages/@sparrow-workspaces/src/features/import-collection/layout/ImportCollection.svelte index 6b4ccd58c..2adb926f8 100644 --- a/packages/@sparrow-workspaces/src/features/import-collection/layout/ImportCollection.svelte +++ b/packages/@sparrow-workspaces/src/features/import-collection/layout/ImportCollection.svelte @@ -547,9 +547,7 @@ on:blur={() => { isInputDataTouched = true; }} - placeholder={isWebApp - ? "Example - OpenAPI JSON text" - : "Example - OpenAPI JSON text or http://localhost:8080/api-docs"} + placeholder={"Example - OpenAPI JSON text or http://localhost:8080/api-docs"} bind:value={importData} class="text-area mb-0 border-0 text-fs-12 rounded bg-tertiary-300 pe-4 ps-2 pb-2 pt-2" style={!isValidServerDeployedURL && From 5ce987ae8263b62a12526ba14411f826dfda401a Mon Sep 17 00:00:00 2001 From: pratikshinde590 Date: Thu, 19 Dec 2024 13:24:55 +0530 Subject: [PATCH 26/56] build: test run for mac build[] --- .github/workflows/development.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/development.yaml b/.github/workflows/development.yaml index 070285c0e..9b598b74f 100644 --- a/.github/workflows/development.yaml +++ b/.github/workflows/development.yaml @@ -3,7 +3,7 @@ name: Development release on: push: branches: - - development + - pratik/dev workflow_dispatch: env: @@ -25,6 +25,7 @@ env: VITE_SPARROW_LINKEDIN: ${{ vars.VITE_SPARROW_LINKEDIN }} VITE_WEB_SOCKET_IO_API_URL: ${{ vars.VITE_WEB_SOCKET_IO_API_URL }} ACTIONS_ALLOW_UNSECURE_COMMANDS: true + CI: true jobs: release_win: From 62543f1f5dda02e43427f11fa4a8a266c51f1ba5 Mon Sep 17 00:00:00 2001 From: pratikshinde590 Date: Thu, 19 Dec 2024 13:26:40 +0530 Subject: [PATCH 27/56] build: test run for mac build[] --- .github/workflows/development.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/development.yaml b/.github/workflows/development.yaml index 9b598b74f..08153765a 100644 --- a/.github/workflows/development.yaml +++ b/.github/workflows/development.yaml @@ -147,6 +147,7 @@ jobs: APPLE_ID: ${{ secrets.APPLE_ID }} APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }} APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }} + CI: true - name: file content run: | From c369f3e22e775811d2254ad2fbbf5b021275a90f Mon Sep 17 00:00:00 2001 From: pratikshinde590 Date: Thu, 19 Dec 2024 14:12:29 +0530 Subject: [PATCH 28/56] build: test run for mac build[] --- .github/workflows/development.yaml | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/.github/workflows/development.yaml b/.github/workflows/development.yaml index 08153765a..8c0f5c089 100644 --- a/.github/workflows/development.yaml +++ b/.github/workflows/development.yaml @@ -25,7 +25,7 @@ env: VITE_SPARROW_LINKEDIN: ${{ vars.VITE_SPARROW_LINKEDIN }} VITE_WEB_SOCKET_IO_API_URL: ${{ vars.VITE_WEB_SOCKET_IO_API_URL }} ACTIONS_ALLOW_UNSECURE_COMMANDS: true - CI: true + CI: false jobs: release_win: @@ -64,6 +64,9 @@ jobs: Set-Content -Path apps/@sparrow-desktop/src-tauri/tauri.conf.json -Value $newContent shell: pwsh + - name: Increase Yarn network timeout + run: yarn config set network-timeout 600000 + - name: Build Tauri App run: | yarn cache clean @@ -132,6 +135,9 @@ jobs: echo "$newContent" > apps/@sparrow-desktop/src-tauri/tauri.conf.json shell: bash + - name: Increase Yarn network timeout + run: yarn config set network-timeout 600000 + - name: Build Tauri App run: | yarn cache clean @@ -147,7 +153,7 @@ jobs: APPLE_ID: ${{ secrets.APPLE_ID }} APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }} APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }} - CI: true + CI: false - name: file content run: | From f191e6b90eb34eea94b161766d84ceba6b6c0bf5 Mon Sep 17 00:00:00 2001 From: pratikshinde590 Date: Thu, 19 Dec 2024 14:41:40 +0530 Subject: [PATCH 29/56] build: Added CI: false ENV in dev & prod workflow [] --- .github/workflows/development.yaml | 2 +- .github/workflows/release.yaml | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/.github/workflows/development.yaml b/.github/workflows/development.yaml index 8c0f5c089..25b0592c7 100644 --- a/.github/workflows/development.yaml +++ b/.github/workflows/development.yaml @@ -3,7 +3,7 @@ name: Development release on: push: branches: - - pratik/dev + - development workflow_dispatch: env: diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 91985746c..81c4d79b8 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -25,6 +25,7 @@ env: VITE_SPARROW_LINKEDIN: ${{ vars.VITE_SPARROW_LINKEDIN }} VITE_WEB_SOCKET_IO_API_URL: ${{ vars.VITE_WEB_SOCKET_IO_API_URL }} ACTIONS_ALLOW_UNSECURE_COMMANDS: true + CI: false jobs: release_win: @@ -63,6 +64,9 @@ jobs: Set-Content -Path apps/@sparrow-desktop/src-tauri/tauri.conf.json -Value $newContent shell: pwsh + - name: Increase Yarn network timeout + run: yarn config set network-timeout 600000 + - name: Build Tauri App run: | yarn cache clean @@ -131,6 +135,9 @@ jobs: echo "$newContent" > apps/@sparrow-desktop/src-tauri/tauri.conf.json shell: bash + - name: Increase Yarn network timeout + run: yarn config set network-timeout 600000 + - name: Build Tauri App run: | yarn cache clean @@ -147,6 +154,7 @@ jobs: APPLE_ID: ${{ secrets.APPLE_ID }} APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }} APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }} + CI: false - name: dmg sig run: cat /Users/runner/work/sparrow-app/sparrow-app/apps/@sparrow-desktop/src-tauri/target/debug/bundle/macos/*.sig From 9dc68e7818087c6c56f06a1d20bc0be11be31e67 Mon Sep 17 00:00:00 2001 From: Nayan lakhwani Date: Thu, 19 Dec 2024 14:42:51 +0530 Subject: [PATCH 30/56] fix: mac dmg installer alignment --- apps/@sparrow-desktop/src-tauri/tauri.conf.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/@sparrow-desktop/src-tauri/tauri.conf.json b/apps/@sparrow-desktop/src-tauri/tauri.conf.json index 9bb4c0bb8..68d4ae762 100644 --- a/apps/@sparrow-desktop/src-tauri/tauri.conf.json +++ b/apps/@sparrow-desktop/src-tauri/tauri.conf.json @@ -71,7 +71,7 @@ }, "windowSize": { "height": 500, - "width": 700 + "width": 770 }, "windowPosition": { "x": 400, From bfabe90e5881db946686d5cac8a24cb660656e0e Mon Sep 17 00:00:00 2001 From: Astitva Patle Date: Thu, 19 Dec 2024 15:11:38 +0530 Subject: [PATCH 31/56] fix: modified mixpanel event property [] --- apps/@sparrow-desktop/src/components/app.ViewModel.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/@sparrow-desktop/src/components/app.ViewModel.ts b/apps/@sparrow-desktop/src/components/app.ViewModel.ts index e04360b76..482b5f34d 100644 --- a/apps/@sparrow-desktop/src/components/app.ViewModel.ts +++ b/apps/@sparrow-desktop/src/components/app.ViewModel.ts @@ -212,7 +212,7 @@ export class AppViewModel { isGuestUserActive.set(true); navigate("/guest/collections"); MixpanelEvent(Events.CONTINUE_WITHOUT_SIGNUP, { - source: "Entry Page", + source: "Sparrow Auth", }); } }; From 7b61a2f5d7521e81338fdc21f91b67cb72b667e7 Mon Sep 17 00:00:00 2001 From: Aakash Reddy Date: Thu, 19 Dec 2024 15:50:57 +0530 Subject: [PATCH 32/56] fix: corrected message name for add collection [#2217] --- .../import-collection/layout/ImportCollection.svelte | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/packages/@sparrow-workspaces/src/features/import-collection/layout/ImportCollection.svelte b/packages/@sparrow-workspaces/src/features/import-collection/layout/ImportCollection.svelte index 2adb926f8..70a1c0dd2 100644 --- a/packages/@sparrow-workspaces/src/features/import-collection/layout/ImportCollection.svelte +++ b/packages/@sparrow-workspaces/src/features/import-collection/layout/ImportCollection.svelte @@ -547,7 +547,9 @@ on:blur={() => { isInputDataTouched = true; }} - placeholder={"Example - OpenAPI JSON text or http://localhost:8080/api-docs"} + placeholder={isWebApp + ? "Example - OpenAPI JSON text" + : "Example - OpenAPI JSON text or http://localhost:8080/api-docs"} bind:value={importData} class="text-area mb-0 border-0 text-fs-12 rounded bg-tertiary-300 pe-4 ps-2 pb-2 pt-2" style={!isValidServerDeployedURL && @@ -571,7 +573,9 @@
{#if !importData && isInputDataTouched && !isimportDataLoading}

- Please paste your OpenAPI specification text or Swagger/localhost link. + {isWebApp + ? "Please paste your OpenAPI specification text." + : "Please paste your OpenAPI specification text or Swagger/localhost link."}

{:else if (!isimportDataLoading && isValidClientDeployedURL && !isValidServerDeployedURL && isInputDataTouched) || (!isimportDataLoading && isValidClientURL && !isValidServerURL && isInputDataTouched) || (!isTextEmpty && !isimportDataLoading && isValidClientXML && !isValidServerXML && isInputDataTouched) || (!isTextEmpty && !isimportDataLoading && isValidClientJSON && !isValidServerJSON && isInputDataTouched) || (!isTextEmpty && !isimportDataLoading && !isValidClientJSON && !isValidClientURL && !isValidClientXML && !isValidServerJSON && !isValidServerURL && !isValidServerXML && !isValidClientDeployedURL && !isValidServerDeployedURL && isInputDataTouched)}

From 4ab6f626d956482ecac2468947685d3d62245013 Mon Sep 17 00:00:00 2001 From: Md Asif Raza Date: Thu, 19 Dec 2024 15:54:14 +0530 Subject: [PATCH 33/56] feat: login desktop with token feature [#2192] --- .../src-tauri/gen/schemas/windows-schema.json | 34 +- .../src/components/App.svelte | 1 + .../src/components/app.ViewModel.ts | 2 +- .../src/pages/auth-page/Auth.svelte | 305 +++++++++++------- 4 files changed, 220 insertions(+), 122 deletions(-) diff --git a/apps/@sparrow-desktop/src-tauri/gen/schemas/windows-schema.json b/apps/@sparrow-desktop/src-tauri/gen/schemas/windows-schema.json index a46a74266..7355bdc2f 100644 --- a/apps/@sparrow-desktop/src-tauri/gen/schemas/windows-schema.json +++ b/apps/@sparrow-desktop/src-tauri/gen/schemas/windows-schema.json @@ -84,7 +84,7 @@ } }, "permissions": { - "description": "List of permissions attached to this capability.\n\nMust include the plugin name as prefix in the form of `${plugin-name}:${permission-name}`. For commands directly implemented in the application itself only `${permission-name}` is required.\n\n## Example\n\n```json [ \"core:default\", \"shell:allow-open\", \"dialog:open\", { \"identifier\": \"fs:allow-write-text-file\", \"allow\": [{ \"path\": \"$HOME/test.txt\" }] } ```", + "description": "List of permissions attached to this capability.\n\nMust include the plugin name as prefix in the form of `${plugin-name}:${permission-name}`. For commands directly implemented in the application itself only `${permission-name}` is required.\n\n## Example\n\n```json [ \"core:default\", \"shell:allow-open\", \"dialog:open\", { \"identifier\": \"fs:allow-write-text-file\", \"allow\": [{ \"path\": \"$HOME/test.txt\" }] } ] ```", "type": "array", "items": { "$ref": "#/definitions/PermissionEntry" @@ -140,7 +140,7 @@ "identifier": { "anyOf": [ { - "description": "This set of permissions describes the what kind of\nfile system access the `fs` plugin has enabled or denied by default.\n\n#### Granted Permissions\n\nThis default permission set enables read access to the\napplication specific directories (AppConfig, AppData, AppLocalData, AppCache,\nAppLog) and all files and sub directories created in it.\nThe location of these directories depends on the operating system,\nwhere the application is run.\n\nIn general these directories need to be manually created\nby the application at runtime, before accessing files or folders\nin it is possible.\n\nTherefore, it is also allowed to create all of these folders via\nthe `mkdir` command.\n\n#### Denied Permissions\n\nThis default permission set prevents access to critical components\nof the Tauri application by default.\nOn Windows the webview data folder access is denied.\n\n", + "description": "This set of permissions describes the what kind of\nfile system access the `fs` plugin has enabled or denied by default.\n\n#### Granted Permissions\n\nThis default permission set enables read access to the\napplication specific directories (AppConfig, AppData, AppLocalData, AppCache,\nAppLog) and all files and sub directories created in it.\nThe location of these directories depends on the operating system,\nwhere the application is run.\n\nIn general these directories need to be manually created\nby the application at runtime, before accessing files or folders\nin it is possible.\n\nTherefore, it is also allowed to create all of these folders via\nthe `mkdir` command.\n\n#### Denied Permissions\n\nThis default permission set prevents access to critical components\nof the Tauri application by default.\nOn Windows the webview data folder access is denied.\n\n#### Included permissions within this default permission set:\n", "type": "string", "const": "fs:default" }, @@ -984,6 +984,11 @@ "type": "string", "const": "fs:allow-seek" }, + { + "description": "Enables the size command without any pre-configured scope.", + "type": "string", + "const": "fs:allow-size" + }, { "description": "Enables the stat command without any pre-configured scope.", "type": "string", @@ -1109,6 +1114,11 @@ "type": "string", "const": "fs:deny-seek" }, + { + "description": "Denies the size command without any pre-configured scope.", + "type": "string", + "const": "fs:deny-size" + }, { "description": "Denies the stat command without any pre-configured scope.", "type": "string", @@ -1581,7 +1591,7 @@ "description": "FS scope entry.", "anyOf": [ { - "description": "FS scope path.", + "description": "A path that can be accessed by the webview when using the fs APIs. FS scope path pattern.\n\nThe pattern can start with a variable that resolves to a system base directory. The variables are: `$AUDIO`, `$CACHE`, `$CONFIG`, `$DATA`, `$LOCALDATA`, `$DESKTOP`, `$DOCUMENT`, `$DOWNLOAD`, `$EXE`, `$FONT`, `$HOME`, `$PICTURE`, `$PUBLIC`, `$RUNTIME`, `$TEMPLATE`, `$VIDEO`, `$RESOURCE`, `$APP`, `$LOG`, `$TEMP`, `$APPCONFIG`, `$APPDATA`, `$APPLOCALDATA`, `$APPCACHE`, `$APPLOG`.", "type": "string" }, { @@ -1591,7 +1601,7 @@ ], "properties": { "path": { - "description": "FS scope path.", + "description": "A path that can be accessed by the webview when using the fs APIs.\n\nThe pattern can start with a variable that resolves to a system base directory. The variables are: `$AUDIO`, `$CACHE`, `$CONFIG`, `$DATA`, `$LOCALDATA`, `$DESKTOP`, `$DOCUMENT`, `$DOWNLOAD`, `$EXE`, `$FONT`, `$HOME`, `$PICTURE`, `$PUBLIC`, `$RUNTIME`, `$TEMPLATE`, `$VIDEO`, `$RESOURCE`, `$APP`, `$LOG`, `$TEMP`, `$APPCONFIG`, `$APPDATA`, `$APPLOCALDATA`, `$APPCACHE`, `$APPLOG`.", "type": "string" } } @@ -1605,7 +1615,7 @@ "description": "FS scope entry.", "anyOf": [ { - "description": "FS scope path.", + "description": "A path that can be accessed by the webview when using the fs APIs. FS scope path pattern.\n\nThe pattern can start with a variable that resolves to a system base directory. The variables are: `$AUDIO`, `$CACHE`, `$CONFIG`, `$DATA`, `$LOCALDATA`, `$DESKTOP`, `$DOCUMENT`, `$DOWNLOAD`, `$EXE`, `$FONT`, `$HOME`, `$PICTURE`, `$PUBLIC`, `$RUNTIME`, `$TEMPLATE`, `$VIDEO`, `$RESOURCE`, `$APP`, `$LOG`, `$TEMP`, `$APPCONFIG`, `$APPDATA`, `$APPLOCALDATA`, `$APPCACHE`, `$APPLOG`.", "type": "string" }, { @@ -1615,7 +1625,7 @@ ], "properties": { "path": { - "description": "FS scope path.", + "description": "A path that can be accessed by the webview when using the fs APIs.\n\nThe pattern can start with a variable that resolves to a system base directory. The variables are: `$AUDIO`, `$CACHE`, `$CONFIG`, `$DATA`, `$LOCALDATA`, `$DESKTOP`, `$DOCUMENT`, `$DOWNLOAD`, `$EXE`, `$FONT`, `$HOME`, `$PICTURE`, `$PUBLIC`, `$RUNTIME`, `$TEMPLATE`, `$VIDEO`, `$RESOURCE`, `$APP`, `$LOG`, `$TEMP`, `$APPCONFIG`, `$APPDATA`, `$APPLOCALDATA`, `$APPCACHE`, `$APPLOG`.", "type": "string" } } @@ -3458,7 +3468,7 @@ "const": "dialog:deny-save" }, { - "description": "This set of permissions describes the what kind of\nfile system access the `fs` plugin has enabled or denied by default.\n\n#### Granted Permissions\n\nThis default permission set enables read access to the\napplication specific directories (AppConfig, AppData, AppLocalData, AppCache,\nAppLog) and all files and sub directories created in it.\nThe location of these directories depends on the operating system,\nwhere the application is run.\n\nIn general these directories need to be manually created\nby the application at runtime, before accessing files or folders\nin it is possible.\n\nTherefore, it is also allowed to create all of these folders via\nthe `mkdir` command.\n\n#### Denied Permissions\n\nThis default permission set prevents access to critical components\nof the Tauri application by default.\nOn Windows the webview data folder access is denied.\n\n", + "description": "This set of permissions describes the what kind of\nfile system access the `fs` plugin has enabled or denied by default.\n\n#### Granted Permissions\n\nThis default permission set enables read access to the\napplication specific directories (AppConfig, AppData, AppLocalData, AppCache,\nAppLog) and all files and sub directories created in it.\nThe location of these directories depends on the operating system,\nwhere the application is run.\n\nIn general these directories need to be manually created\nby the application at runtime, before accessing files or folders\nin it is possible.\n\nTherefore, it is also allowed to create all of these folders via\nthe `mkdir` command.\n\n#### Denied Permissions\n\nThis default permission set prevents access to critical components\nof the Tauri application by default.\nOn Windows the webview data folder access is denied.\n\n#### Included permissions within this default permission set:\n", "type": "string", "const": "fs:default" }, @@ -4302,6 +4312,11 @@ "type": "string", "const": "fs:allow-seek" }, + { + "description": "Enables the size command without any pre-configured scope.", + "type": "string", + "const": "fs:allow-size" + }, { "description": "Enables the stat command without any pre-configured scope.", "type": "string", @@ -4427,6 +4442,11 @@ "type": "string", "const": "fs:deny-seek" }, + { + "description": "Denies the size command without any pre-configured scope.", + "type": "string", + "const": "fs:deny-size" + }, { "description": "Denies the stat command without any pre-configured scope.", "type": "string", diff --git a/apps/@sparrow-desktop/src/components/App.svelte b/apps/@sparrow-desktop/src/components/App.svelte index f114b2634..378fe29ba 100644 --- a/apps/@sparrow-desktop/src/components/App.svelte +++ b/apps/@sparrow-desktop/src/components/App.svelte @@ -31,6 +31,7 @@ onMount(async () => { await _viewModel.registerDeepLinkHandler(); + const loginWithToken = _viewModel.processDeepLink; await singleInstanceHandler(); await setScaleFactorToDb(await getScaleFactor()); let isloggedIn; diff --git a/apps/@sparrow-desktop/src/components/app.ViewModel.ts b/apps/@sparrow-desktop/src/components/app.ViewModel.ts index e04360b76..f8e360e72 100644 --- a/apps/@sparrow-desktop/src/components/app.ViewModel.ts +++ b/apps/@sparrow-desktop/src/components/app.ViewModel.ts @@ -218,7 +218,7 @@ export class AppViewModel { }; // Private method to process deep link - private async processDeepLink(url: string): Promise { + public async processDeepLink(url: string): Promise { try { await getCurrentWindow().setFocus(); const params = new URLSearchParams(url.split("?")[1]); diff --git a/apps/@sparrow-desktop/src/pages/auth-page/Auth.svelte b/apps/@sparrow-desktop/src/pages/auth-page/Auth.svelte index fb3d3a8a7..505593621 100644 --- a/apps/@sparrow-desktop/src/pages/auth-page/Auth.svelte +++ b/apps/@sparrow-desktop/src/pages/auth-page/Auth.svelte @@ -1,5 +1,6 @@ -{#if isEntry} - -

- If your browser doesn’t open automatically, please visit - Sparrow website - - - - - to sign In or copy URL - { - await copyToClipBoard(externalSparrowLink); - notifications.success("Link copied to clipboard."); + + {#if isTokenFormEnabled} +

+
- -
-

- Welcome to Sparrow! -

-

- The only API Sidekick you need -

+ {/if} +
+
+
+

Sparrow

+
+ +
+

+ Welcome to Sparrow! +

+

+ The only API Sidekick you need +

+
+ {#if !isTokenFormEnabled}
{ handleRedirect(true); openDefaultBrowser(); + isTokenFormEnabled = true; }} id="create_account_or_sign_in" > @@ -192,45 +159,147 @@ font-size: 12px; font-weight:400; " > - Instantly test - APIs without signing up-just the essentials to get started fast. + Instantly test APIs without + signing up-just the essentials to get started fast.
- + {:else} - -{/if} + {/if} + + +
{ setupMaximizeToggleListenerForMac(); await _viewModel.registerDeepLinkHandler(); - const loginWithToken = _viewModel.processDeepLink; await singleInstanceHandler(); await setScaleFactorToDb(await getScaleFactor()); let isloggedIn; From 3962e07322632cbb0f6ef799df9bb0f2087b614d Mon Sep 17 00:00:00 2001 From: Md Asif Raza Date: Thu, 19 Dec 2024 16:10:39 +0530 Subject: [PATCH 35/56] feat/2192/login-desktop-with-token-feature --- apps/@sparrow-desktop/src-tauri/tauri.conf.json | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/@sparrow-desktop/src-tauri/tauri.conf.json b/apps/@sparrow-desktop/src-tauri/tauri.conf.json index f7e41ad16..9bb4c0bb8 100644 --- a/apps/@sparrow-desktop/src-tauri/tauri.conf.json +++ b/apps/@sparrow-desktop/src-tauri/tauri.conf.json @@ -15,6 +15,7 @@ "title": "Sparrow", "shadow": true, "focus": true, + "dragDropEnabled": false, "maximized": true }, { From d2ff90f9dfb78423b2a3f4fb28319bd05f88e91b Mon Sep 17 00:00:00 2001 From: Md Asif Raza Date: Thu, 19 Dec 2024 16:13:09 +0530 Subject: [PATCH 36/56] feat/2192/login-desktop-with-token-feature --- apps/@sparrow-desktop/src/components/app.ViewModel.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/@sparrow-desktop/src/components/app.ViewModel.ts b/apps/@sparrow-desktop/src/components/app.ViewModel.ts index f8e360e72..e04360b76 100644 --- a/apps/@sparrow-desktop/src/components/app.ViewModel.ts +++ b/apps/@sparrow-desktop/src/components/app.ViewModel.ts @@ -218,7 +218,7 @@ export class AppViewModel { }; // Private method to process deep link - public async processDeepLink(url: string): Promise { + private async processDeepLink(url: string): Promise { try { await getCurrentWindow().setFocus(); const params = new URLSearchParams(url.split("?")[1]); From ea38e2b98d72ada3ce8b2acf3e6dbe07331df1f3 Mon Sep 17 00:00:00 2001 From: pratikshinde590 Date: Thu, 19 Dec 2024 16:38:36 +0530 Subject: [PATCH 37/56] build: added new env in dockerfile for sparrow-web [] --- apps/@sparrow-web/Dockerfile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/apps/@sparrow-web/Dockerfile b/apps/@sparrow-web/Dockerfile index b742197d1..6e72fbe91 100644 --- a/apps/@sparrow-web/Dockerfile +++ b/apps/@sparrow-web/Dockerfile @@ -20,6 +20,7 @@ ARG VITE_WEB_AZURE_INSIGHTS_CONNECTION_STRING ARG VITE_WEB_MARKETING_URL ARG VITE_WEB_SPARROW_DOCS ARG VITE_WEB_PROXY_SERVICE +ARG VITE_WEB_SOCKET_IO_API_URL ENV PORT=$PORT ENV VITE_WEB_API_URL=$VITE_WEB_API_URL @@ -38,6 +39,7 @@ ENV VITE_WEB_AZURE_INSIGHTS_CONNECTION_STRING=$VITE_WEB_AZURE_INSIGHTS_CONNECTIO ENV VITE_WEB_MARKETING_URL=$VITE_WEB_MARKETING_URL ENV VITE_WEB_SPARROW_DOCS=$VITE_WEB_SPARROW_DOCS ENV VITE_WEB_PROXY_SERVICE=$VITE_WEB_PROXY_SERVICE +ENV VITE_WEB_SOCKET_IO_API_URL=$VITE_WEB_SOCKET_IO_API_URL EXPOSE 1422 From cea00a3620a62f27b0b842bdcd2bf85f2c06d569 Mon Sep 17 00:00:00 2001 From: Harsh Date: Thu, 19 Dec 2024 18:13:15 +0530 Subject: [PATCH 38/56] fix : ui bugs --- .../src/features/socket-explorer/layout/SocketExplorer.svelte | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/@sparrow-workspaces/src/features/socket-explorer/layout/SocketExplorer.svelte b/packages/@sparrow-workspaces/src/features/socket-explorer/layout/SocketExplorer.svelte index eee04aa1b..ff8e4f163 100644 --- a/packages/@sparrow-workspaces/src/features/socket-explorer/layout/SocketExplorer.svelte +++ b/packages/@sparrow-workspaces/src/features/socket-explorer/layout/SocketExplorer.svelte @@ -67,7 +67,6 @@ export let onUpdateContentType; export let onClearInput; export let onUpdateFilterType; - export let isWebApp = false; let isExposeSaveAsSocket = false; const toggleSaveRequest = (flag: boolean): void => { isExposeSaveAsSocket = flag; From 5f7580d461bf3a77199159180885dc2a172fb649 Mon Sep 17 00:00:00 2001 From: Harsh Date: Thu, 19 Dec 2024 18:24:34 +0530 Subject: [PATCH 39/56] fix : resolved conflicts --- .../src/containers/api/api.common.ts | 6 +- .../src/containers/api/api.common.ts | 86 +------------------ 2 files changed, 5 insertions(+), 87 deletions(-) diff --git a/apps/@sparrow-desktop/src/containers/api/api.common.ts b/apps/@sparrow-desktop/src/containers/api/api.common.ts index 0c469f00d..633d01c49 100644 --- a/apps/@sparrow-desktop/src/containers/api/api.common.ts +++ b/apps/@sparrow-desktop/src/containers/api/api.common.ts @@ -400,7 +400,7 @@ const addSocketDataToMap = (tabId, url) => { try { updateSocketDataStore( tabId, - `Connected from ${url}`, + `Connected to ${url}`, "connecter", "connected", ); @@ -456,7 +456,7 @@ async function processMessageEvent(tabId, event) { // Retrieve tab data and check event inclusion const tabData = await tabRepository.getTabByTabId(tabId); const tabDataJSON = tabData?.toMutableJSON(); - console.log(event,"event"); + console.log(event, "event"); const socketIOresponse = event.payload; const eventName = socketIOresponse.event; const message = socketIOresponse.message; @@ -631,7 +631,7 @@ const connectWebSocket = async ( const wsData = webSocketDataMap.get(tabId); if (wsData) { wsData.messages.unshift({ - data: `Connected from ${url}`, + data: `Connected to ${url}`, transmitter: "connecter", timestamp: formatTime(new Date()), uuid: uuidv4(), diff --git a/apps/@sparrow-web/src/containers/api/api.common.ts b/apps/@sparrow-web/src/containers/api/api.common.ts index de43e1c86..2264110e9 100644 --- a/apps/@sparrow-web/src/containers/api/api.common.ts +++ b/apps/@sparrow-web/src/containers/api/api.common.ts @@ -454,87 +454,6 @@ const connectWebSocket = async ( throw error; } } else if (selectedAgent === "Cloud Agent") { - try { - webSocketDataStore.update((webSocketDataMap) => { - webSocketDataMap.set(tabId, { - messages: [], - status: "connecting", - search: "", - contentType: RequestDataTypeEnum.TEXT, - body: "", - filter: "All Messages", - url: url, - }); - return webSocketDataMap; - }); - - const proxyUrl = "http://localhost:9000/proxy/ws-connect"; - const response = await axios.post(proxyUrl, { - tabId, - targetUrl: url, - headers: requestHeaders, - }); - - if (response.data.success) { - webSocketDataStore.update((webSocketDataMap) => { - const wsData = webSocketDataMap.get(tabId); - if (wsData) { - wsData.messages.unshift({ - data: `Connected to ${url}`, - transmitter: "connecter", - timestamp: formatTime(new Date()), - uuid: uuidv4(), - }); - wsData.status = "connected"; - webSocketDataMap.set(tabId, wsData); - } - return webSocketDataMap; - }); - notifications.success("WebSocket connected successfully"); - - // Set up event source for receiving messages - const eventSource = new EventSource( - `http://localhost:3000/proxy/ws-events/${tabId}`, - ); - - eventSource.onmessage = (event) => { - const data = JSON.parse(event.data); - webSocketDataStore.update((webSocketDataMap) => { - const wsData = webSocketDataMap.get(tabId); - if (wsData) { - wsData.messages.unshift({ - data: data.message, - transmitter: "receiver", - timestamp: formatTime(new Date()), - uuid: uuidv4(), - }); - webSocketDataMap.set(tabId, wsData); - } - return webSocketDataMap; - }); - }; - - eventSource.onerror = () => { - eventSource.close(); - webSocketDataStore.update((webSocketDataMap) => { - const wsData = webSocketDataMap.get(tabId); - if (wsData) { - wsData.status = "disconnected"; - webSocketDataMap.set(tabId, wsData); - } - return webSocketDataMap; - }); - }; - } - } catch (error) { - console.error(error); - notifications.error("Failed to connect WebSocket"); - webSocketDataStore.update((webSocketDataMap) => { - webSocketDataMap.delete(tabId); - return webSocketDataMap; - }); - throw error; - } } }; @@ -561,8 +480,7 @@ const makeHttpRequestV2 = async ( try { let response; if (selectedAgent === "Cloud Agent") { - // const proxyUrl = constants.PROXY_SERVICE + "/proxy/http-request"; - const proxyUrl = "http://localhost:3000/proxy/http-request"; + const proxyUrl = constants.PROXY_SERVICE + "/proxy/http-request"; response = await axios({ data: { url, method, headers, body, contentType }, url: proxyUrl, @@ -746,7 +664,7 @@ const processMessageEvent = async ( * @returns A message indicating the connection was established. */ const processConnectEvent = (_url: string): string => { - return `Connected from ${_url}`; + return `Connected to ${_url}`; }; /** From beeb0d7c8e529596464838b78029f3f6b96051e3 Mon Sep 17 00:00:00 2001 From: Harsh Date: Thu, 19 Dec 2024 19:20:08 +0530 Subject: [PATCH 40/56] fix : resolved conflicts --- .../src/containers/api/api.common.ts | 51 +++++++++++++++++-- .../layout/SocketExplorer.svelte | 1 + .../layout/WorkspaceActions.svelte | 10 ++++ 3 files changed, 58 insertions(+), 4 deletions(-) diff --git a/apps/@sparrow-web/src/containers/api/api.common.ts b/apps/@sparrow-web/src/containers/api/api.common.ts index 2264110e9..be0d92ee5 100644 --- a/apps/@sparrow-web/src/containers/api/api.common.ts +++ b/apps/@sparrow-web/src/containers/api/api.common.ts @@ -357,8 +357,34 @@ const connectWebSocket = async ( if (selectedAgent === "Browser Agent") { try { + // Parse the headers string to array of header objects const headers = JSON.parse(requestHeaders); + // Filter and process headers that are supported by WebSocket + const protocols: string[] = []; + const validHeaders = new Set([ + "Sec-WebSocket-Protocol", + "Sec-WebSocket-Version", + "Sec-WebSocket-Key", + "Sec-WebSocket-Accept", + ]); + + // Extract WebSocket protocols from headers + headers.forEach( + (header: { key: string; value: string; checked: boolean }) => { + if (header.checked !== false) { + if (header.key === "Sec-WebSocket-Protocol") { + // Split protocol string and add to protocols array + const protocolValues = header.value + .split(",") + .map((p) => p.trim()); + protocols.push(...protocolValues); + } + } + }, + ); + + // Initialize WebSocket store webSocketDataStore.update((webSocketDataMap) => { webSocketDataMap.set(tabId, { messages: [], @@ -373,8 +399,13 @@ const connectWebSocket = async ( return webSocketDataMap; }); - const ws = new WebSocket(url); + // Create WebSocket with protocols if specified + const ws = + protocols.length > 0 + ? new WebSocket(url, protocols) + : new WebSocket(url); + // Update store with WebSocket instance webSocketDataStore.update((webSocketDataMap) => { const wsData = webSocketDataMap.get(tabId); if (wsData) { @@ -396,6 +427,15 @@ const connectWebSocket = async ( uuid: uuidv4(), }); wsData.status = "connected"; + // Add information about used protocols if any + if (ws.protocol) { + wsData.messages.unshift({ + data: `Using protocol: ${ws.protocol}`, + transmitter: "info", + timestamp: formatTime(new Date()), + uuid: uuidv4(), + }); + } webSocketDataMap.set(tabId, wsData); } return webSocketDataMap; @@ -426,13 +466,16 @@ const connectWebSocket = async ( webSocketDataMap.delete(tabId); return webSocketDataMap; }); + notifications.error("WebSocket connection failed"); + reject(error); }; - ws.onclose = () => { + + ws.onclose = (event) => { webSocketDataStore.update((webSocketDataMap) => { const wsData = webSocketDataMap.get(tabId); if (wsData) { wsData.messages.unshift({ - data: `Disconnected from ${url}`, + data: `Disconnected from ${url} (Code: ${event.code})`, transmitter: "disconnector", timestamp: formatTime(new Date()), uuid: uuidv4(), @@ -445,7 +488,7 @@ const connectWebSocket = async ( }; }); } catch (error) { - console.error(error); + console.error("WebSocket connection error:", error); webSocketDataStore.update((webSocketDataMap) => { webSocketDataMap.delete(tabId); return webSocketDataMap; diff --git a/packages/@sparrow-workspaces/src/features/socket-explorer/layout/SocketExplorer.svelte b/packages/@sparrow-workspaces/src/features/socket-explorer/layout/SocketExplorer.svelte index ff8e4f163..9f75f5669 100644 --- a/packages/@sparrow-workspaces/src/features/socket-explorer/layout/SocketExplorer.svelte +++ b/packages/@sparrow-workspaces/src/features/socket-explorer/layout/SocketExplorer.svelte @@ -51,6 +51,7 @@ export let onUpdateEnvironment; export let environmentVariables; export let isGuestUser = false; + export let isWebApp; /** * Role of user in active workspace */ diff --git a/packages/@sparrow-workspaces/src/features/workspace-actions/layout/WorkspaceActions.svelte b/packages/@sparrow-workspaces/src/features/workspace-actions/layout/WorkspaceActions.svelte index 2dd32774b..18e0ef37e 100644 --- a/packages/@sparrow-workspaces/src/features/workspace-actions/layout/WorkspaceActions.svelte +++ b/packages/@sparrow-workspaces/src/features/workspace-actions/layout/WorkspaceActions.svelte @@ -262,6 +262,16 @@ showImportCurlPopup(); }, }, + { + name: "Add WebSocket", + icon: SocketIcon, + iconColor: "var(--icon-secondary-130)", + iconSize: "15px", + onclick: () => { + onItemCreated("web-socket", {}); + MixpanelEvent(Events.Add_WebSocket); + }, + }, { name: "Add Environment", icon: StackIcon, From 5b454ee7bb9d865b11cd069a4253a45a28f67f8e Mon Sep 17 00:00:00 2001 From: Harsh Date: Thu, 19 Dec 2024 19:34:15 +0530 Subject: [PATCH 41/56] fix : resolved conflicts --- apps/@sparrow-web/src/containers/api/api.common.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/@sparrow-web/src/containers/api/api.common.ts b/apps/@sparrow-web/src/containers/api/api.common.ts index be0d92ee5..85d235b55 100644 --- a/apps/@sparrow-web/src/containers/api/api.common.ts +++ b/apps/@sparrow-web/src/containers/api/api.common.ts @@ -470,12 +470,12 @@ const connectWebSocket = async ( reject(error); }; - ws.onclose = (event) => { + ws.onclose = () => { webSocketDataStore.update((webSocketDataMap) => { const wsData = webSocketDataMap.get(tabId); if (wsData) { wsData.messages.unshift({ - data: `Disconnected from ${url} (Code: ${event.code})`, + data: `Disconnected from ${url}`, transmitter: "disconnector", timestamp: formatTime(new Date()), uuid: uuidv4(), From 27e45899c30f6ade78809e0272dd65a902b34c0f Mon Sep 17 00:00:00 2001 From: Harsh Date: Thu, 19 Dec 2024 19:36:44 +0530 Subject: [PATCH 42/56] fix : resolved conflicts --- .../src/containers/api/api.common.ts | 24 ------------------- 1 file changed, 24 deletions(-) diff --git a/apps/@sparrow-web/src/containers/api/api.common.ts b/apps/@sparrow-web/src/containers/api/api.common.ts index 85d235b55..790be309a 100644 --- a/apps/@sparrow-web/src/containers/api/api.common.ts +++ b/apps/@sparrow-web/src/containers/api/api.common.ts @@ -360,30 +360,6 @@ const connectWebSocket = async ( // Parse the headers string to array of header objects const headers = JSON.parse(requestHeaders); - // Filter and process headers that are supported by WebSocket - const protocols: string[] = []; - const validHeaders = new Set([ - "Sec-WebSocket-Protocol", - "Sec-WebSocket-Version", - "Sec-WebSocket-Key", - "Sec-WebSocket-Accept", - ]); - - // Extract WebSocket protocols from headers - headers.forEach( - (header: { key: string; value: string; checked: boolean }) => { - if (header.checked !== false) { - if (header.key === "Sec-WebSocket-Protocol") { - // Split protocol string and add to protocols array - const protocolValues = header.value - .split(",") - .map((p) => p.trim()); - protocols.push(...protocolValues); - } - } - }, - ); - // Initialize WebSocket store webSocketDataStore.update((webSocketDataMap) => { webSocketDataMap.set(tabId, { From 31e7ae9b1e8342c4df24f0aadd5fa1729004f562 Mon Sep 17 00:00:00 2001 From: Harsh Date: Thu, 19 Dec 2024 19:40:59 +0530 Subject: [PATCH 43/56] fix : resolved conflicts --- .../src/containers/api/api.common.ts | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) diff --git a/apps/@sparrow-web/src/containers/api/api.common.ts b/apps/@sparrow-web/src/containers/api/api.common.ts index 790be309a..c56da19aa 100644 --- a/apps/@sparrow-web/src/containers/api/api.common.ts +++ b/apps/@sparrow-web/src/containers/api/api.common.ts @@ -375,12 +375,6 @@ const connectWebSocket = async ( return webSocketDataMap; }); - // Create WebSocket with protocols if specified - const ws = - protocols.length > 0 - ? new WebSocket(url, protocols) - : new WebSocket(url); - // Update store with WebSocket instance webSocketDataStore.update((webSocketDataMap) => { const wsData = webSocketDataMap.get(tabId); @@ -403,15 +397,7 @@ const connectWebSocket = async ( uuid: uuidv4(), }); wsData.status = "connected"; - // Add information about used protocols if any - if (ws.protocol) { - wsData.messages.unshift({ - data: `Using protocol: ${ws.protocol}`, - transmitter: "info", - timestamp: formatTime(new Date()), - uuid: uuidv4(), - }); - } + webSocketDataMap.set(tabId, wsData); } return webSocketDataMap; @@ -442,8 +428,6 @@ const connectWebSocket = async ( webSocketDataMap.delete(tabId); return webSocketDataMap; }); - notifications.error("WebSocket connection failed"); - reject(error); }; ws.onclose = () => { From 2694e5bf149ad118f3c939a78bc996d20f6ed871 Mon Sep 17 00:00:00 2001 From: Harsh Date: Fri, 20 Dec 2024 11:35:17 +0530 Subject: [PATCH 44/56] fix : browser agent bug --- apps/@sparrow-web/src/containers/api/api.common.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/@sparrow-web/src/containers/api/api.common.ts b/apps/@sparrow-web/src/containers/api/api.common.ts index c56da19aa..7f6464e89 100644 --- a/apps/@sparrow-web/src/containers/api/api.common.ts +++ b/apps/@sparrow-web/src/containers/api/api.common.ts @@ -375,6 +375,7 @@ const connectWebSocket = async ( return webSocketDataMap; }); + const ws = new WebSocket(url); // Update store with WebSocket instance webSocketDataStore.update((webSocketDataMap) => { const wsData = webSocketDataMap.get(tabId); From 0ecf8ca6c791602b9fde2add18ebfa6db6fc31a2 Mon Sep 17 00:00:00 2001 From: Harsh Date: Fri, 20 Dec 2024 13:01:47 +0530 Subject: [PATCH 45/56] fix : crate team modal --- .../@sparrow-web/src/pages/Teams/Teams.svelte | 27 ++++++++++++++++--- .../features/team-list/layout/TeamList.svelte | 2 +- 2 files changed, 24 insertions(+), 5 deletions(-) diff --git a/apps/@sparrow-web/src/pages/Teams/Teams.svelte b/apps/@sparrow-web/src/pages/Teams/Teams.svelte index c8e9dfde0..e90ebbb25 100644 --- a/apps/@sparrow-web/src/pages/Teams/Teams.svelte +++ b/apps/@sparrow-web/src/pages/Teams/Teams.svelte @@ -24,6 +24,7 @@ import { Modal, Tooltip, Dropdown } from "@sparrow/library/ui"; import { pagesMotion } from "../../constants"; import { version } from "../../../package.json"; + import { CreateTeam } from "@sparrow/common/features"; const _viewModel = new TeamsViewModel(); const teamList: Observable = _viewModel.teams; @@ -108,7 +109,7 @@ }); let isGithubStarHover = false; - let activeIndex; + let activeIndex = ""; $: { if ($openTeam) { @@ -380,6 +381,24 @@ + { + isCreateTeamModalOpen = flag; + }} +> + { + isCreateTeamModalOpen = flag; + }} + onCreateTeam={_viewModel.createTeam} + /> + +