From 06409b571a62909e21b9c5d39caa4647ff99ae7a Mon Sep 17 00:00:00 2001 From: Galin Iliev Date: Fri, 21 Aug 2026 16:47:34 +0300 Subject: [PATCH 1/2] G4E-10728 - Add latest io.Connect Desktop Launchpad app template exported as a new feature from @interopio/components-react. --- io-connect-desktop-launchpad/.gitignore | 23 ++ io-connect-desktop-launchpad/.prettierignore | 3 + io-connect-desktop-launchpad/.prettierrc | 6 + io-connect-desktop-launchpad/README.md | 220 ++++++++++++++++++ io-connect-desktop-launchpad/index.html | 15 ++ io-connect-desktop-launchpad/package.json | 29 +++ .../public/favicon.ico | Bin 0 -> 34494 bytes io-connect-desktop-launchpad/src/app/app.tsx | 41 ++++ .../src/components/launchpad.tsx | 37 +++ .../src/constants/constants.ts | 28 +++ io-connect-desktop-launchpad/src/main.tsx | 6 + io-connect-desktop-launchpad/src/styles.css | 2 + io-connect-desktop-launchpad/tsconfig.json | 12 + io-connect-desktop-launchpad/vite-env.d.ts | 1 + io-connect-desktop-launchpad/vite.config.ts | 16 ++ 15 files changed, 439 insertions(+) create mode 100644 io-connect-desktop-launchpad/.gitignore create mode 100644 io-connect-desktop-launchpad/.prettierignore create mode 100644 io-connect-desktop-launchpad/.prettierrc create mode 100644 io-connect-desktop-launchpad/README.md create mode 100644 io-connect-desktop-launchpad/index.html create mode 100644 io-connect-desktop-launchpad/package.json create mode 100644 io-connect-desktop-launchpad/public/favicon.ico create mode 100644 io-connect-desktop-launchpad/src/app/app.tsx create mode 100644 io-connect-desktop-launchpad/src/components/launchpad.tsx create mode 100644 io-connect-desktop-launchpad/src/constants/constants.ts create mode 100644 io-connect-desktop-launchpad/src/main.tsx create mode 100644 io-connect-desktop-launchpad/src/styles.css create mode 100644 io-connect-desktop-launchpad/tsconfig.json create mode 100644 io-connect-desktop-launchpad/vite-env.d.ts create mode 100644 io-connect-desktop-launchpad/vite.config.ts diff --git a/io-connect-desktop-launchpad/.gitignore b/io-connect-desktop-launchpad/.gitignore new file mode 100644 index 0000000..4d29575 --- /dev/null +++ b/io-connect-desktop-launchpad/.gitignore @@ -0,0 +1,23 @@ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +/node_modules +/.pnp +.pnp.js + +# testing +/coverage + +# production +/build + +# misc +.DS_Store +.env.local +.env.development.local +.env.test.local +.env.production.local + +npm-debug.log* +yarn-debug.log* +yarn-error.log* diff --git a/io-connect-desktop-launchpad/.prettierignore b/io-connect-desktop-launchpad/.prettierignore new file mode 100644 index 0000000..63520da --- /dev/null +++ b/io-connect-desktop-launchpad/.prettierignore @@ -0,0 +1,3 @@ +node_modules +dist +build diff --git a/io-connect-desktop-launchpad/.prettierrc b/io-connect-desktop-launchpad/.prettierrc new file mode 100644 index 0000000..f61d8d9 --- /dev/null +++ b/io-connect-desktop-launchpad/.prettierrc @@ -0,0 +1,6 @@ +{ + "semi": true, + "tabWidth": 2, + "trailingComma": "es5", + "printWidth": 100 +} \ No newline at end of file diff --git a/io-connect-desktop-launchpad/README.md b/io-connect-desktop-launchpad/README.md new file mode 100644 index 0000000..6b023a5 --- /dev/null +++ b/io-connect-desktop-launchpad/README.md @@ -0,0 +1,220 @@ +# Launchpad App for io.Connect Desktop + +Template for creating a custom desktop Launchpad app for **io.Connect Desktop**, built on top of the +`IOLaunchpadDesktop` feature exported by [`@interopio/components-react`](../../packages/components-react). Clone +this app and customize only the pieces you need — everything else keeps working out of the box. + +## Prerequisites + +**io.Connect Desktop** is required, since this app only configures the `desktop` factory (see +[src/constants/constants.ts](src/constants/constants.ts)). + +## Setup + +- Run `npm install` to install all dependencies. +- Run `npm run start` to start the app (dev server runs on `http://localhost:4242` by default, see + [vite.config.ts](vite.config.ts)). +- Point your io.Connect Desktop configuration's Launchpad/System application entry to this app's URL, then start + io.Connect Desktop to see your customized Launchpad. Refer to your io.Connect Desktop version's documentation for + the exact application-definition file and property to update. +- Run `npm run build` to produce a production build in `dist/`. +- Start **io.Connect Desktop** to start using and modifying your Launchpad App. + +## How it's wired + +`src/components/launchpad.tsx` wires up the required providers around a single `` component. You +don't need to pass a `components` prop at all - `` already renders a fully working default header +(`DragHandle` + `LogoButton` before search, `ExtendedArea` + `NotificationsButton` + `MainContextMenu` after +search) out of the box: + +```tsx +import { + ThemeProvider, + PlatformPrefsProvider, + IOActivePanelRenderer, + IODownloadManager, + IOLaunchpadDesktop, + IONotifications, +} from "@interopio/components-react"; + +const { LaunchpadProvider, LaunchpadBodyPopupProvider, PanelPopupProvider, Launchpad } = IOLaunchpadDesktop; +const { NotificationsProvider } = IONotifications; +const { DownloadManagerProvider } = IODownloadManager; +const { PanelManagerProvider } = IOActivePanelRenderer; + +function LaunchpadWrapper() { + return ( + + + + + + + + + + + + + + + + + + ); +} +``` + +All customization happens through the `components` prop of `` - you shouldn't need to touch the +provider chain above. + +## Customization + +### 1. Replacing the default io.Connect Desktop Launchpad with a custom implementation + +For details on how io.Connect Desktop discovers and loads a custom Launchpad app, see the +[Launchpad documentation](https://docs.interop.io/desktop/capabilities/launcher/index.html#launchpad). + + +### 2. The `components` prop + +`` forwards straight to the native `IOLaunchpad.ContentsContainer`, so it only +accepts `header` (`BeforeSearch` / `AfterSearch`) and `sections` - there's no per-piece override system. +`DragHandle`, `LogoButton`, `NotificationsButton`, `MainContextMenu`, `ExtendedArea` are exported standalone so you +compose them yourself into `header.BeforeSearch` / `AfterSearch`, as shown above. + +> **Tip:** define `BeforeSearch` / `AfterSearch` (and the `components` object) **outside** your component's render +> function (module scope), or memoize them. Passing a brand-new inline function on every render forces +> `` to remount that zone on every render - wasteful in general, and it can also break in-flight +> async work started by a piece inside it (e.g. opening the docked search popup). + +### 3. Default `BeforeSearch` / `AfterSearch` + +`` fills in `header.BeforeSearch` / `AfterSearch` with its own defaults whenever you don't specify +them, so there are 3 possible outcomes per zone: + +1. **Omitted** (key not present, or `undefined`) - the library default renders (`DragHandle` + `LogoButton` for + `BeforeSearch`; `ExtendedArea` + `NotificationsButton` + `MainContextMenu` for `AfterSearch`). +2. **Explicitly empty** (e.g. `BeforeSearch: () => null`) - the default is overridden and nothing renders in that + zone. +3. **A real custom component** - that component renders in place of the default. + +```tsx +// 1. Omitted - renders the library defaults +; + +// 2. Explicitly empty - hides the zone entirely + null } }} />; + +// 3. Custom component - fully replaces the zone +function CustomBeforeSearch() { + return ; +} + +; +``` + +### 4. Removing a piece + +Since `header.BeforeSearch` / `AfterSearch` **fully replace** the zone, just omit a piece from your composition to +hide it - e.g. hide the notifications bell: + +```tsx +function AfterSearch() { + return ( + <> + + + + ); +} +``` + +### 5. Passing your own component + +Compose your own implementation alongside (or instead of) the default pieces: + +```tsx +function MyMainContextMenu() { + return ; +} + +function AfterSearch() { + return ( + <> + + + + + ); +} +``` + +### 6. Overriding `BeforeSearch` / `AfterSearch` + +Pass `components.header` to fully replace either zone with something entirely custom: + +```tsx +function CustomBeforeSearch() { + return ; +} + +function CustomAfterSearch() { + return ; +} + +const launchpadComponents = { header: { BeforeSearch: CustomBeforeSearch, AfterSearch: CustomAfterSearch } }; + +; +``` + +Since `header.BeforeSearch` / `AfterSearch` **fully replace** the zone, if you just want to add something +alongside the defaults, import the default pieces (they're also exported standalone) and compose them yourself: + +```tsx +import { IOLaunchpadDesktop } from "@interopio/components-react"; + +const { DragHandle, LogoButton } = IOLaunchpadDesktop; + +function CustomBeforeSearch() { + return ( + <> + + + + + ); +} + +const launchpadComponents = { header: { BeforeSearch: CustomBeforeSearch } }; +``` + +### 7. Customizing the `LogoButton` + +`LogoButton` itself accepts `icon`, `iconSrc`, and `onClick` props, so you don't need to replace it entirely just +to change the logo or its click behavior: + +```tsx +import { IOLaunchpadDesktop } from "@interopio/components-react"; + +const { DragHandle, LogoButton } = IOLaunchpadDesktop; + +function BeforeSearch() { + return ( + <> + + console.log("logo clicked")} /> + + ); +} +``` + +- `icon` — an icon variant name (ignored if `iconSrc` is set); defaults to `"logo"`. +- `iconSrc` — a custom image URL/data-URI to render instead of `icon`. +- `onClick` — replaces the default collapse/popup-toggle behavior; drag-to-move still works either way. + +### 7. `ExtendedArea` visibility + +`ExtendedArea` self-guards: it renders `null` unless the Launchpad is both docked and the +`LAUNCHPAD_SHOW_EXTENDED_AREA` platform pref is enabled, so it's safe to always include it in `AfterSearch` - it +simply won't render anything otherwise. diff --git a/io-connect-desktop-launchpad/index.html b/io-connect-desktop-launchpad/index.html new file mode 100644 index 0000000..2695372 --- /dev/null +++ b/io-connect-desktop-launchpad/index.html @@ -0,0 +1,15 @@ + + + + + Launchpad + + + + + + +
+ + + diff --git a/io-connect-desktop-launchpad/package.json b/io-connect-desktop-launchpad/package.json new file mode 100644 index 0000000..9449629 --- /dev/null +++ b/io-connect-desktop-launchpad/package.json @@ -0,0 +1,29 @@ +{ + "name": "io-connect-desktop-launchpad", + "version": "4.6.0", + "homepage": "./", + "private": true, + "scripts": { + "start": "vite", + "build": "vite build" + }, + "dependencies": { + "@interopio/components-react": "~4.6.0", + "@interopio/desktop": "~6.16.0", + "@interopio/react-hooks": "~4.6.0", + "@interopio/workspaces-ui-react": "~4.6.0", + "@interopio/modals-api": "~4.6.0", + "@interopio/search-api": "^3.3.0", + "@interopio/theme": "~4.6.0", + "react": "~18.2.0", + "react-dom": "~18.2.0" + }, + "devDependencies": { + "@types/node": "~20.12.7", + "@types/react": "~18.2.79", + "@types/react-dom": "~18.2.25", + "@vitejs/plugin-react": "~3.0.0", + "typescript": "~5.8.2", + "vite": "~4.0.1" + } +} \ No newline at end of file diff --git a/io-connect-desktop-launchpad/public/favicon.ico b/io-connect-desktop-launchpad/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..1a05395ee5b1ad20d0943eaa6cbd8868de224cc8 GIT binary patch literal 34494 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 Vdg-3&pIzKJn{|_eiQt|)* literal 0 HcmV?d00001 diff --git a/io-connect-desktop-launchpad/src/app/app.tsx b/io-connect-desktop-launchpad/src/app/app.tsx new file mode 100644 index 0000000..40a53d7 --- /dev/null +++ b/io-connect-desktop-launchpad/src/app/app.tsx @@ -0,0 +1,41 @@ +import { lazy, Suspense, useContext, useEffect } from "react"; +import { IOConnectContext, IOConnectProvider } from "@interopio/react-hooks"; +import { ioConfig } from "../constants/constants"; +import "@interopio/workspaces-ui-react/dist/styles/workspaces.css"; +import "@interopio/components-react/dist/styles/components/ui/dropdown-menu.css"; +import "@interopio/components-react/dist/styles/components/ui/overlay-scrollbars-container.css"; +import "@interopio/components-react/dist/styles/features/active-panel-renderer/styles.css"; +import "@interopio/components-react/dist/styles/features/notifications/styles.css"; +import "@interopio/components-react/dist/styles/features/preferences/styles.css"; +import "@interopio/components-react/dist/styles/features/profile/styles.css"; +import "@interopio/components-react/dist/styles/features/launchpad/styles.css"; +import "@interopio/components-react/dist/styles/features/launchpad-desktop/styles.css"; + +const Launchpad = lazy(() => import("../components/launchpad")); + +// IOConnectProvider owns the only io.Connect initialization - read the resulting instance from context instead of initializing again. +function GlobalIOBinder() { + const io = useContext(IOConnectContext); + + useEffect(() => { + if (io) { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + (globalThis as any).io = io; + } + }, [io]); + + return null; +} + +export function App() { + return ( + + + + + + + ); +} + +export default App; diff --git a/io-connect-desktop-launchpad/src/components/launchpad.tsx b/io-connect-desktop-launchpad/src/components/launchpad.tsx new file mode 100644 index 0000000..115f1c4 --- /dev/null +++ b/io-connect-desktop-launchpad/src/components/launchpad.tsx @@ -0,0 +1,37 @@ +import { + ThemeProvider, + PlatformPrefsProvider, + IOActivePanelRenderer, + IODownloadManager, + IOLaunchpadDesktop, + IONotifications, +} from "@interopio/components-react"; + +const { PanelManagerProvider } = IOActivePanelRenderer; +const { DownloadManagerProvider } = IODownloadManager; +const { LaunchpadProvider, LaunchpadBodyPopupProvider, PanelPopupProvider, Launchpad } = IOLaunchpadDesktop; +const { NotificationsProvider } = IONotifications; + +function LaunchpadWrapper() { + return ( + + + + + + + + + + + + + + + + + + ); +} + +export default LaunchpadWrapper; diff --git a/io-connect-desktop-launchpad/src/constants/constants.ts b/io-connect-desktop-launchpad/src/constants/constants.ts new file mode 100644 index 0000000..8e60736 --- /dev/null +++ b/io-connect-desktop-launchpad/src/constants/constants.ts @@ -0,0 +1,28 @@ +import IODesktop from "@interopio/desktop"; +import IOSearch from "@interopio/search-api"; +import IOWorkspaces from "@interopio/workspaces-api"; +import IOModalsAPI from "@interopio/modals-api"; +import { IOConnectInitSettings } from "@interopio/react-hooks"; + +export const ioConfig = { + desktop: { + factory: IODesktop, + config: { + gateway: { + logging: { + level: "warn", + }, + }, + libraries: [IOWorkspaces, IOSearch, IOModalsAPI], + appManager: "full", + layouts: "full", + activities: "trackAll", + channels: false, + metrics: false, + contexts: true, + systemLogger: { + level: "warn", + }, + }, + }, +} as IOConnectInitSettings; diff --git a/io-connect-desktop-launchpad/src/main.tsx b/io-connect-desktop-launchpad/src/main.tsx new file mode 100644 index 0000000..784f2cf --- /dev/null +++ b/io-connect-desktop-launchpad/src/main.tsx @@ -0,0 +1,6 @@ +import * as ReactDOM from "react-dom/client"; +import App from "./app/app"; + +const root = ReactDOM.createRoot(document.getElementById("root") as HTMLElement); + +root.render(); diff --git a/io-connect-desktop-launchpad/src/styles.css b/io-connect-desktop-launchpad/src/styles.css new file mode 100644 index 0000000..fb8e8d5 --- /dev/null +++ b/io-connect-desktop-launchpad/src/styles.css @@ -0,0 +1,2 @@ +/* App-specific overrides go here. Launchpad desktop styling now ships with + @interopio/components-react/dist/styles/features/launchpad-desktop/styles.css */ diff --git a/io-connect-desktop-launchpad/tsconfig.json b/io-connect-desktop-launchpad/tsconfig.json new file mode 100644 index 0000000..7577a9f --- /dev/null +++ b/io-connect-desktop-launchpad/tsconfig.json @@ -0,0 +1,12 @@ +{ + "compilerOptions": { + "module": "esnext", + "moduleResolution": "bundler", + "jsx": "react-jsx", + "esModuleInterop": true, + "resolveJsonModule": true, + "allowJs": false, + "allowSyntheticDefaultImports": true, + "strict": true + } +} \ No newline at end of file diff --git a/io-connect-desktop-launchpad/vite-env.d.ts b/io-connect-desktop-launchpad/vite-env.d.ts new file mode 100644 index 0000000..11f02fe --- /dev/null +++ b/io-connect-desktop-launchpad/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/io-connect-desktop-launchpad/vite.config.ts b/io-connect-desktop-launchpad/vite.config.ts new file mode 100644 index 0000000..4e31992 --- /dev/null +++ b/io-connect-desktop-launchpad/vite.config.ts @@ -0,0 +1,16 @@ +import { defineConfig } from "vite"; +import react from "@vitejs/plugin-react"; + +export default defineConfig({ + plugins: [react()], + base: "./", + server: { + port: 4242, + host: "localhost", + }, + build: { + commonjsOptions: { + include: [/@interopio\/components-react/, /node_modules/], + }, + }, +}); From 7a73c4bee97f8962c4eb593c568b0c89dd5228d1 Mon Sep 17 00:00:00 2001 From: Galin Iliev Date: Fri, 21 Aug 2026 16:56:28 +0300 Subject: [PATCH 2/2] G4E-10728 - Update line endings. --- io-connect-desktop-launchpad/.prettierrc | 2 +- io-connect-desktop-launchpad/package.json | 2 +- io-connect-desktop-launchpad/tsconfig.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/io-connect-desktop-launchpad/.prettierrc b/io-connect-desktop-launchpad/.prettierrc index f61d8d9..8164313 100644 --- a/io-connect-desktop-launchpad/.prettierrc +++ b/io-connect-desktop-launchpad/.prettierrc @@ -3,4 +3,4 @@ "tabWidth": 2, "trailingComma": "es5", "printWidth": 100 -} \ No newline at end of file +} diff --git a/io-connect-desktop-launchpad/package.json b/io-connect-desktop-launchpad/package.json index 9449629..5345b4d 100644 --- a/io-connect-desktop-launchpad/package.json +++ b/io-connect-desktop-launchpad/package.json @@ -26,4 +26,4 @@ "typescript": "~5.8.2", "vite": "~4.0.1" } -} \ No newline at end of file +} diff --git a/io-connect-desktop-launchpad/tsconfig.json b/io-connect-desktop-launchpad/tsconfig.json index 7577a9f..d72ea2f 100644 --- a/io-connect-desktop-launchpad/tsconfig.json +++ b/io-connect-desktop-launchpad/tsconfig.json @@ -9,4 +9,4 @@ "allowSyntheticDefaultImports": true, "strict": true } -} \ No newline at end of file +}