Skip to content

feat: add Electron desktop client#184

Merged
mahata merged 4 commits intomainfrom
feat/electron-desktop-client
Apr 7, 2026
Merged

feat: add Electron desktop client#184
mahata merged 4 commits intomainfrom
feat/electron-desktop-client

Conversation

@mahata
Copy link
Copy Markdown
Owner

@mahata mahata commented Apr 7, 2026

Summary

  • Adds an Electron desktop client (electron/ workspace package) that wraps the existing mlack web app in a native desktop window
  • Includes system tray icon with context menu, native OS notifications for new messages when the window is unfocused, and persistent login sessions
  • Integrates into the monorepo with root-level electron:dev, electron:build, and electron:package scripts

Details

Architecture

The Electron app is a thin wrapper — it loads the mlack web app (localhost:8787 in dev, mlack.uk in prod) in a BrowserWindow. No server changes required.

Features

  • Native notifications: WebSocket messages are intercepted via an injected script that monkey-patches WebSocket in the renderer. When the window is unfocused and a new message arrives, a native OS notification is shown. Clicking it focuses the window.
  • System tray: Tray icon with "Open MLack" and "Quit" options. Clicking the icon shows/focuses the window.
  • Persistent sessions: Electron's default session persists cookies, so login state survives app restarts.
  • External links: Links that open new windows are opened in the system browser.
  • Packaging: electron-builder configured for macOS (.dmg), Windows (.exe), and Linux (.AppImage).

Usage

pnpm dev                    # Terminal 1: start web server
pnpm electron:dev           # Terminal 2: launch desktop app (localhost)
pnpm electron:package       # Build distributable

New files

File Purpose
electron/package.json Package config with Electron deps and scripts
electron/tsconfig.json TypeScript config for main process
electron/src/main.ts Main process (BrowserWindow, lifecycle)
electron/src/preload.ts Context bridge for notification API
electron/src/tray.ts System tray icon and menu
electron/src/notifications.ts Desktop notification logic
electron/assets/icon.png Placeholder icon (replace later)

Add an Electron wrapper that loads the existing mlack web app in a
native desktop window. Includes:
- System tray icon with show/quit context menu
- Native OS notifications for new messages when window is unfocused
- WebSocket message interception via injected script
- Persistent cookie sessions across app restarts
- electron-builder config for macOS, Windows, and Linux packaging
- Workspace integration with root-level electron:dev/build/package scripts
Copilot AI review requested due to automatic review settings April 7, 2026 15:05
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new electron/ workspace package that wraps the existing MLack web app in an Electron BrowserWindow, with a tray icon and native notifications, and wires it into the monorepo via root electron:* scripts.

Changes:

  • Add electron/ workspace package (main process, preload, tray, notifications) plus packaging config.
  • Update monorepo scripts/workspace config to support pnpm electron:dev|build|package.
  • Update pnpm configuration/lockfile to include Electron + electron-builder dependencies.
Show a summary per file
File Description
pnpm-workspace.yaml Adds electron as a workspace package.
package.json Adds root scripts for Electron workflows and pnpm.onlyBuiltDependencies config.
pnpm-lock.yaml Locks Electron/electron-builder dependency graph and related transitive deps.
electron/package.json Defines mlack-desktop package scripts and electron-builder packaging targets.
electron/tsconfig.json TypeScript config for the Electron main/preload build output.
electron/src/main.ts Creates the BrowserWindow, handles external links, bootstraps tray + notifications.
electron/src/tray.ts Implements tray icon + context menu actions.
electron/src/notifications.ts Implements IPC-driven notifications and injects WS interception script.
electron/src/preload.ts Exposes mlackDesktop bridge for renderer → main IPC interactions.
electron/assets/icon.png Adds placeholder tray/app icon asset.
electron/.gitignore Ignores build artifacts for the Electron package.

Copilot's findings

  • Files reviewed: 9/11 changed files
  • Comments generated: 7

Comment thread electron/src/notifications.ts Outdated
Comment thread electron/src/main.ts
Comment on lines +55 to +62
app.on("activate", () => {
if (BrowserWindow.getAllWindows().length === 0) {
mainWindow = createWindow();
createTray(mainWindow);
setupNotifications(mainWindow);
} else {
mainWindow?.show();
}
Copy link

Copilot AI Apr 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The app calls createTray() and setupNotifications() again inside the activate handler when creating a new window. On macOS, this path can be hit multiple times during the app lifetime, which can lead to multiple tray icons (since the old tray isn’t destroyed) and duplicate IPC notification listeners. Consider ensuring any existing tray/listeners are torn down before recreating them, or structure initialization so tray + IPC are set up exactly once per app lifecycle.

Copilot uses AI. Check for mistakes.
Comment thread electron/src/tray.ts
Comment thread electron/src/tray.ts
Comment on lines +34 to +40
label: "Quit",
click: () => {
tray?.destroy();
tray = null;
mainWindow.destroy();
process.exit(0);
},
Copy link

Copilot AI Apr 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The tray "Quit" action calls process.exit(0) after destroying the window. For Electron apps this bypasses normal shutdown/cleanup (and can skip async teardown), which can lead to corrupted state or incomplete telemetry/log flushing. Prefer app.quit() (and optionally app.exit(0) only after before-quit completes) instead of process.exit.

Copilot uses AI. Check for mistakes.
Comment thread electron/src/preload.ts Outdated
Comment thread electron/src/notifications.ts Outdated
Comment on lines +2 to +20
import type { BrowserWindow } from "electron";

export function setupNotifications(mainWindow: BrowserWindow): void {
ipcMain.on("show-notification", (_event, data: { title: string; body: string; channelId?: number }) => {
if (mainWindow.isFocused()) {
return;
}

const notification = new Notification({
title: data.title,
body: data.body,
silent: false,
});

notification.on("click", () => {
mainWindow.show();
mainWindow.focus();
if (data.channelId !== undefined) {
mainWindow.webContents.send("notification-clicked", data.channelId);
Copy link

Copilot AI Apr 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The show-notification IPC channel is accepted from any renderer without validating the sender’s origin. Since this app loads a remote URL in production, a compromised/modified page could spam OS notifications with arbitrary content. Consider checking event.senderFrame.url (or event.sender.getURL()) against an allowlist (dev localhost + prod domain) and applying basic validation/truncation to title/body before showing notifications.

Suggested change
import type { BrowserWindow } from "electron";
export function setupNotifications(mainWindow: BrowserWindow): void {
ipcMain.on("show-notification", (_event, data: { title: string; body: string; channelId?: number }) => {
if (mainWindow.isFocused()) {
return;
}
const notification = new Notification({
title: data.title,
body: data.body,
silent: false,
});
notification.on("click", () => {
mainWindow.show();
mainWindow.focus();
if (data.channelId !== undefined) {
mainWindow.webContents.send("notification-clicked", data.channelId);
import type { BrowserWindow, IpcMainEvent } from "electron";
const localDevelopmentOrigins = new Set([
"http://localhost:3000",
"http://localhost:5173",
"http://127.0.0.1:3000",
"http://127.0.0.1:5173",
]);
const notificationTitleLimit = 120;
const notificationBodyLimit = 500;
function getOrigin(value: string): string | null {
try {
return new URL(value).origin;
} catch {
return null;
}
}
function isAllowedNotificationSender(event: IpcMainEvent, mainWindow: BrowserWindow): boolean {
const senderUrl = event.senderFrame?.url || event.sender.getURL();
const senderOrigin = getOrigin(senderUrl);
if (!senderOrigin) {
return false;
}
if (localDevelopmentOrigins.has(senderOrigin)) {
return true;
}
const mainWindowOrigin = getOrigin(mainWindow.webContents.getURL());
return mainWindowOrigin !== null && senderOrigin === mainWindowOrigin;
}
function normalizeNotificationText(value: unknown, maxLength: number): string | null {
if (typeof value !== "string") {
return null;
}
const normalizedValue = value.replace(/\s+/g, " ").trim();
if (!normalizedValue) {
return null;
}
return normalizedValue.slice(0, maxLength);
}
export function setupNotifications(mainWindow: BrowserWindow): void {
ipcMain.on("show-notification", (event, data: unknown) => {
if (!isAllowedNotificationSender(event, mainWindow)) {
return;
}
if (mainWindow.isFocused()) {
return;
}
if (!data || typeof data !== "object") {
return;
}
const payload = data as { title?: unknown; body?: unknown; channelId?: unknown };
const title = normalizeNotificationText(payload.title, notificationTitleLimit);
const body = normalizeNotificationText(payload.body, notificationBodyLimit);
const channelId = Number.isInteger(payload.channelId) ? payload.channelId : undefined;
if (!title || !body) {
return;
}
const notification = new Notification({
title,
body,
silent: false,
});
notification.on("click", () => {
mainWindow.show();
mainWindow.focus();
if (channelId !== undefined) {
mainWindow.webContents.send("notification-clicked", channelId);

Copilot uses AI. Check for mistakes.
Comment thread electron/package.json
Comment on lines +27 to +31
"icon": "assets/icon.icns",
"target": ["dmg"]
},
"win": {
"icon": "assets/icon.ico",
Copy link

Copilot AI Apr 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

electron-builder is configured to use assets/icon.icns (mac) and assets/icon.ico (win), but this PR only adds assets/icon.png. As-is, packaging for macOS/Windows will likely fail due to missing icon files. Either add the .icns/.ico assets or update the config to use files that exist.

Suggested change
"icon": "assets/icon.icns",
"target": ["dmg"]
},
"win": {
"icon": "assets/icon.ico",
"icon": "assets/icon.png",
"target": ["dmg"]
},
"win": {
"icon": "assets/icon.png",

Copilot uses AI. Check for mistakes.
mahata and others added 3 commits April 8, 2026 00:15
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@mahata mahata merged commit 383e689 into main Apr 7, 2026
3 checks passed
@mahata mahata deleted the feat/electron-desktop-client branch April 7, 2026 22:03
mahata added a commit that referenced this pull request Apr 8, 2026
…194)

* feat: add deployment tagging, GitHub Releases, and PR template

Add a post-deploy step to deploy.yml that creates a git tag
(deploy-YYYY-MM-DD-SHA) and a GitHub Release with auto-generated
notes after each successful production deployment. This provides
a clear history of which commits were deployed and when.

Add a default PR template with a pre-deploy checklist covering
CI status, migration review, secrets, and Durable Objects state.

* Update .github/workflows/deploy.yml

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* fix: scope contents:write permission to deploy job only

Agent-Logs-Url: https://github.com/mahata/mlack/sessions/b28d6893-dc36-48da-a24d-589cb4ad8e05

Co-authored-by: mahata <23497+mahata@users.noreply.github.com>

* deps-dev(deps-dev): bump @cloudflare/workers-types (#164)

Bumps [@cloudflare/workers-types](https://github.com/cloudflare/workerd) from 4.20260317.1 to 4.20260329.1.
- [Release notes](https://github.com/cloudflare/workerd/releases)
- [Changelog](https://github.com/cloudflare/workerd/blob/main/RELEASE.md)
- [Commits](https://github.com/cloudflare/workerd/commits)

---
updated-dependencies:
- dependency-name: "@cloudflare/workers-types"
  dependency-version: 4.20260329.1
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* chore: add conventional-commit skill for Copilot

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* deps(deps): bump hono in the production-dependencies group (#168)

Bumps the production-dependencies group with 1 update: [hono](https://github.com/honojs/hono).


Updates `hono` from 4.12.9 to 4.12.11
- [Release notes](https://github.com/honojs/hono/releases)
- [Commits](honojs/hono@v4.12.9...v4.12.11)

---
updated-dependencies:
- dependency-name: hono
  dependency-version: 4.12.11
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: production-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* deps(deps): bump the development-dependencies group with 11 updates (#169)

Bumps the development-dependencies group with 11 updates:

| Package | From | To |
| --- | --- | --- |
| [@biomejs/biome](https://github.com/biomejs/biome/tree/HEAD/packages/@biomejs/biome) | `2.4.9` | `2.4.10` |
| [@playwright/test](https://github.com/microsoft/playwright) | `1.58.2` | `1.59.1` |
| [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) | `24.12.0` | `24.12.2` |
| [@biomejs/cli-darwin-arm64](https://github.com/biomejs/biome/tree/HEAD/packages/@biomejs/biome) | `2.4.9` | `2.4.10` |
| [@biomejs/cli-darwin-x64](https://github.com/biomejs/biome/tree/HEAD/packages/@biomejs/biome) | `2.4.9` | `2.4.10` |
| [@biomejs/cli-linux-arm64-musl](https://github.com/biomejs/biome/tree/HEAD/packages/@biomejs/biome) | `2.4.9` | `2.4.10` |
| [@biomejs/cli-linux-arm64](https://github.com/biomejs/biome/tree/HEAD/packages/@biomejs/biome) | `2.4.9` | `2.4.10` |
| [@biomejs/cli-linux-x64-musl](https://github.com/biomejs/biome/tree/HEAD/packages/@biomejs/biome) | `2.4.9` | `2.4.10` |
| [@biomejs/cli-linux-x64](https://github.com/biomejs/biome/tree/HEAD/packages/@biomejs/biome) | `2.4.9` | `2.4.10` |
| [@biomejs/cli-win32-arm64](https://github.com/biomejs/biome/tree/HEAD/packages/@biomejs/biome) | `2.4.9` | `2.4.10` |
| [@biomejs/cli-win32-x64](https://github.com/biomejs/biome/tree/HEAD/packages/@biomejs/biome) | `2.4.9` | `2.4.10` |


Updates `@biomejs/biome` from 2.4.9 to 2.4.10
- [Release notes](https://github.com/biomejs/biome/releases)
- [Changelog](https://github.com/biomejs/biome/blob/main/packages/@biomejs/biome/CHANGELOG.md)
- [Commits](https://github.com/biomejs/biome/commits/@biomejs/biome@2.4.10/packages/@biomejs/biome)

Updates `@playwright/test` from 1.58.2 to 1.59.1
- [Release notes](https://github.com/microsoft/playwright/releases)
- [Commits](microsoft/playwright@v1.58.2...v1.59.1)

Updates `@types/node` from 24.12.0 to 24.12.2
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

Updates `@biomejs/cli-darwin-arm64` from 2.4.9 to 2.4.10
- [Release notes](https://github.com/biomejs/biome/releases)
- [Changelog](https://github.com/biomejs/biome/blob/main/packages/@biomejs/biome/CHANGELOG.md)
- [Commits](https://github.com/biomejs/biome/commits/@biomejs/biome@2.4.10/packages/@biomejs/biome)

Updates `@biomejs/cli-darwin-x64` from 2.4.9 to 2.4.10
- [Release notes](https://github.com/biomejs/biome/releases)
- [Changelog](https://github.com/biomejs/biome/blob/main/packages/@biomejs/biome/CHANGELOG.md)
- [Commits](https://github.com/biomejs/biome/commits/@biomejs/biome@2.4.10/packages/@biomejs/biome)

Updates `@biomejs/cli-linux-arm64-musl` from 2.4.9 to 2.4.10
- [Release notes](https://github.com/biomejs/biome/releases)
- [Changelog](https://github.com/biomejs/biome/blob/main/packages/@biomejs/biome/CHANGELOG.md)
- [Commits](https://github.com/biomejs/biome/commits/@biomejs/biome@2.4.10/packages/@biomejs/biome)

Updates `@biomejs/cli-linux-arm64` from 2.4.9 to 2.4.10
- [Release notes](https://github.com/biomejs/biome/releases)
- [Changelog](https://github.com/biomejs/biome/blob/main/packages/@biomejs/biome/CHANGELOG.md)
- [Commits](https://github.com/biomejs/biome/commits/@biomejs/biome@2.4.10/packages/@biomejs/biome)

Updates `@biomejs/cli-linux-x64-musl` from 2.4.9 to 2.4.10
- [Release notes](https://github.com/biomejs/biome/releases)
- [Changelog](https://github.com/biomejs/biome/blob/main/packages/@biomejs/biome/CHANGELOG.md)
- [Commits](https://github.com/biomejs/biome/commits/@biomejs/biome@2.4.10/packages/@biomejs/biome)

Updates `@biomejs/cli-linux-x64` from 2.4.9 to 2.4.10
- [Release notes](https://github.com/biomejs/biome/releases)
- [Changelog](https://github.com/biomejs/biome/blob/main/packages/@biomejs/biome/CHANGELOG.md)
- [Commits](https://github.com/biomejs/biome/commits/@biomejs/biome@2.4.10/packages/@biomejs/biome)

Updates `@biomejs/cli-win32-arm64` from 2.4.9 to 2.4.10
- [Release notes](https://github.com/biomejs/biome/releases)
- [Changelog](https://github.com/biomejs/biome/blob/main/packages/@biomejs/biome/CHANGELOG.md)
- [Commits](https://github.com/biomejs/biome/commits/@biomejs/biome@2.4.10/packages/@biomejs/biome)

Updates `@biomejs/cli-win32-x64` from 2.4.9 to 2.4.10
- [Release notes](https://github.com/biomejs/biome/releases)
- [Changelog](https://github.com/biomejs/biome/blob/main/packages/@biomejs/biome/CHANGELOG.md)
- [Commits](https://github.com/biomejs/biome/commits/@biomejs/biome@2.4.10/packages/@biomejs/biome)

---
updated-dependencies:
- dependency-name: "@biomejs/biome"
  dependency-version: 2.4.10
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: development-dependencies
- dependency-name: "@playwright/test"
  dependency-version: 1.59.1
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: development-dependencies
- dependency-name: "@types/node"
  dependency-version: 24.12.2
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: development-dependencies
- dependency-name: "@biomejs/cli-darwin-arm64"
  dependency-version: 2.4.10
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: development-dependencies
- dependency-name: "@biomejs/cli-darwin-x64"
  dependency-version: 2.4.10
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: development-dependencies
- dependency-name: "@biomejs/cli-linux-arm64-musl"
  dependency-version: 2.4.10
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: development-dependencies
- dependency-name: "@biomejs/cli-linux-arm64"
  dependency-version: 2.4.10
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: development-dependencies
- dependency-name: "@biomejs/cli-linux-x64-musl"
  dependency-version: 2.4.10
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: development-dependencies
- dependency-name: "@biomejs/cli-linux-x64"
  dependency-version: 2.4.10
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: development-dependencies
- dependency-name: "@biomejs/cli-win32-arm64"
  dependency-version: 2.4.10
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: development-dependencies
- dependency-name: "@biomejs/cli-win32-x64"
  dependency-version: 2.4.10
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: development-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* deps(deps): bump tinyglobby from 0.2.14 to 0.2.15 (#170)

Bumps [tinyglobby](https://github.com/SuperchupuDev/tinyglobby) from 0.2.14 to 0.2.15.
- [Release notes](https://github.com/SuperchupuDev/tinyglobby/releases)
- [Changelog](https://github.com/SuperchupuDev/tinyglobby/blob/main/CHANGELOG.md)
- [Commits](SuperchupuDev/tinyglobby@0.2.14...0.2.15)

---
updated-dependencies:
- dependency-name: tinyglobby
  dependency-version: 0.2.15
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* deps(deps): bump @emnapi/runtime from 1.9.1 to 1.9.2 (#172)

Bumps [@emnapi/runtime](https://github.com/toyobayashi/emnapi) from 1.9.1 to 1.9.2.
- [Release notes](https://github.com/toyobayashi/emnapi/releases)
- [Commits](toyobayashi/emnapi@v1.9.1...v1.9.2)

---
updated-dependencies:
- dependency-name: "@emnapi/runtime"
  dependency-version: 1.9.2
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* deps(deps): bump vite from 7.0.5 to 7.3.1 (#171)

Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 7.0.5 to 7.3.1.
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/main/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v7.3.1/packages/vite)

---
updated-dependencies:
- dependency-name: vite
  dependency-version: 7.3.1
  dependency-type: indirect
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* deps(deps): bump tinyspy from 4.0.3 to 4.0.4 (#173)

Bumps [tinyspy](https://github.com/tinylibs/tinyspy) from 4.0.3 to 4.0.4.
- [Release notes](https://github.com/tinylibs/tinyspy/releases)
- [Commits](tinylibs/tinyspy@v4.0.3...v4.0.4)

---
updated-dependencies:
- dependency-name: tinyspy
  dependency-version: 4.0.4
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: mahata <23497+mahata@users.noreply.github.com>

* deps-dev(deps-dev): bump @cloudflare/workers-types (#174)

Bumps [@cloudflare/workers-types](https://github.com/cloudflare/workerd) from 4.20260329.1 to 4.20260405.1.
- [Release notes](https://github.com/cloudflare/workerd/releases)
- [Changelog](https://github.com/cloudflare/workerd/blob/main/RELEASE.md)
- [Commits](https://github.com/cloudflare/workerd/commits)

---
updated-dependencies:
- dependency-name: "@cloudflare/workers-types"
  dependency-version: 4.20260405.1
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* deps-dev(deps-dev): bump wrangler from 4.77.0 to 4.79.0 (#178)

Bumps [wrangler](https://github.com/cloudflare/workers-sdk/tree/HEAD/packages/wrangler) from 4.77.0 to 4.79.0.
- [Release notes](https://github.com/cloudflare/workers-sdk/releases)
- [Commits](https://github.com/cloudflare/workers-sdk/commits/wrangler@4.79.0/packages/wrangler)

---
updated-dependencies:
- dependency-name: wrangler
  dependency-version: 4.79.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* deps(deps): bump drizzle-orm from 0.45.1 to 0.45.2 (#165)

Bumps [drizzle-orm](https://github.com/drizzle-team/drizzle-orm) from 0.45.1 to 0.45.2.
- [Release notes](https://github.com/drizzle-team/drizzle-orm/releases)
- [Commits](drizzle-team/drizzle-orm@0.45.1...0.45.2)

---
updated-dependencies:
- dependency-name: drizzle-orm
  dependency-version: 0.45.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* fix: resolve duplicate @types/node@24.12.2 in pnpm-lock.yaml (#175)

* deps(deps): bump expect-type from 1.2.2 to 1.3.0

Bumps [expect-type](https://github.com/mmkal/expect-type) from 1.2.2 to 1.3.0.
- [Release notes](https://github.com/mmkal/expect-type/releases)
- [Commits](mmkal/expect-type@v1.2.2...v1.3.0)

---
updated-dependencies:
- dependency-name: expect-type
  dependency-version: 1.3.0
  dependency-type: indirect
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

* fix: resolve duplicate @types/node@24.12.2 in pnpm-lock.yaml by updating @types/node to ^24.12.2

Agent-Logs-Url: https://github.com/mahata/mlack/sessions/75387082-98f8-4f32-a101-e17460603972

Co-authored-by: mahata <23497+mahata@users.noreply.github.com>

* chore: merge main into branch, resolve @playwright/test version conflict

Agent-Logs-Url: https://github.com/mahata/mlack/sessions/93366234-814a-46ee-b2fd-3d5296eeaa11

Co-authored-by: mahata <23497+mahata@users.noreply.github.com>

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: mahata <23497+mahata@users.noreply.github.com>

* feat: add mlack.uk custom domain route to production

* fix: resolve duplicate @types/node@24.12.2 in pnpm-lock.yaml (#176)

* deps(deps): bump postcss from 8.5.6 to 8.5.8

Bumps [postcss](https://github.com/postcss/postcss) from 8.5.6 to 8.5.8.
- [Release notes](https://github.com/postcss/postcss/releases)
- [Changelog](https://github.com/postcss/postcss/blob/main/CHANGELOG.md)
- [Commits](postcss/postcss@8.5.6...8.5.8)

---
updated-dependencies:
- dependency-name: postcss
  dependency-version: 8.5.8
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

* fix: resolve duplicate @types/node@24.12.2 in pnpm-lock.yaml after merging main

Agent-Logs-Url: https://github.com/mahata/mlack/sessions/ee849a11-8ea0-46b7-8001-8e30404fc116

Co-authored-by: mahata <23497+mahata@users.noreply.github.com>

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: mahata <23497+mahata@users.noreply.github.com>

* deps(deps): bump vite from 7.0.5 to 7.3.2 (#183)

Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 7.0.5 to 7.3.2.
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/v7.3.2/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v7.3.2/packages/vite)

---
updated-dependencies:
- dependency-name: vite
  dependency-version: 7.3.2
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* feat: add Electron desktop client (#184)

* feat: add Electron desktop client with notifications and system tray

Add an Electron wrapper that loads the existing mlack web app in a
native desktop window. Includes:
- System tray icon with show/quit context menu
- Native OS notifications for new messages when window is unfocused
- WebSocket message interception via injected script
- Persistent cookie sessions across app restarts
- electron-builder config for macOS, Windows, and Linux packaging
- Workspace integration with root-level electron:dev/build/package scripts

* Update electron/src/notifications.ts

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update electron/src/tray.ts

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update electron/src/preload.ts

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* fix: disable electron-builder publish to prevent channel crash (#186)

* deps-dev(deps-dev): bump electron from 35.7.5 to 39.8.5 (#185)

Bumps [electron](https://github.com/electron/electron) from 35.7.5 to 39.8.5.
- [Release notes](https://github.com/electron/electron/releases)
- [Commits](electron/electron@v35.7.5...v39.8.5)

---
updated-dependencies:
- dependency-name: electron
  dependency-version: 39.8.5
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* docs: clarify Copilot CLI review command path usage (#187)

* chore: replace security-auditor agent with Copilot CLI reviews

Remove the dedicated security-auditor OpenCode agent and add a Copilot CLI
review step to AGENTS.md instead. This gives multi-model review coverage
(Opus 4.6 writes, GPT-5.4 reviews) and runs per-task rather than per-file
to keep the workflow efficient.

* docs: clarify copilot CLI file path placeholder

Agent-Logs-Url: https://github.com/mahata/mlack/sessions/8cef0ef9-23e7-4daf-9bc5-6af13accf40c

Co-authored-by: mahata <23497+mahata@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: mahata <23497+mahata@users.noreply.github.com>

* deps(deps): bump hono from 4.12.11 to 4.12.12 (#189)

Bumps [hono](https://github.com/honojs/hono) from 4.12.11 to 4.12.12.
- [Release notes](https://github.com/honojs/hono/releases)
- [Commits](honojs/hono@v4.12.11...v4.12.12)

---
updated-dependencies:
- dependency-name: hono
  dependency-version: 4.12.12
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* fix: enforce existing Git tag guard in electron release workflow (#188)

* feat: add GitHub Actions workflow for Electron desktop releases

Add a manual-dispatch workflow that builds MLack Desktop binaries for
macOS (.dmg), Windows (.nsis), and Linux (.AppImage) in parallel, then
creates a GitHub Release with all artifacts attached.

Includes version validation, duplicate release check, branch guard
(main only), scoped permissions, and concurrency protection.

* fix: validate existing git tags in electron release workflow

Agent-Logs-Url: https://github.com/mahata/mlack/sessions/9f1592bd-764d-4005-8c02-81a5c88659a2

Co-authored-by: mahata <23497+mahata@users.noreply.github.com>

* fix: check existing release tags with git ls-remote

Agent-Logs-Url: https://github.com/mahata/mlack/sessions/9f1592bd-764d-4005-8c02-81a5c88659a2

Co-authored-by: mahata <23497+mahata@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: mahata <23497+mahata@users.noreply.github.com>

* fix: resolve Electron release build failures (#190)

* fix: resolve Electron release build failures

- Replace 16x16 placeholder icon with 512x512 PNG and generate .icns
  (macOS) and .ico (Windows) files to meet electron-builder requirements
- Move version update step after dependency install so npm is available
  from the project's Node.js version rather than the runner default

* Update .github/workflows/electron-release.yml

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* fix: write explicit newline when updating Electron package version in release workflow (#191)

* fix: avoid lifecycle scripts when updating electron package version

Replace pnpm version with a direct JSON file write to prevent Electron
from launching during the version update step, which fails on Linux CI
due to SUID sandbox configuration.

* fix: use explicit newline char when writing electron package version

Agent-Logs-Url: https://github.com/mahata/mlack/sessions/b04db865-e846-4b04-8b58-959693015c66

Co-authored-by: mahata <23497+mahata@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: mahata <23497+mahata@users.noreply.github.com>

* docs: align README Node.js prerequisite with Node 24 upgrade (#192)

* chore: upgrade Node.js to 24 and remove corepack

Node.js 24 no longer bundles corepack, so remove the corepack enable
steps from all CI workflows and drop the packageManager field from
package.json. Update .node-version and AGENTS.md to reflect Node 24.

* fix: install pnpm via pnpm/action-setup in CI workflows

Node.js 24 no longer bundles corepack, so pnpm must be installed
explicitly. Add pnpm/action-setup@v4 before actions/setup-node in
every CI job.

* docs: update README Node.js prerequisite to v24

Agent-Logs-Url: https://github.com/mahata/mlack/sessions/21f73092-2de8-4e30-b7eb-4dd8f51484dc

Co-authored-by: mahata <23497+mahata@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: mahata <23497+mahata@users.noreply.github.com>

* feat: add workspaces with isolated channels, members, and invite system (#193)

* feat: add workspaces with isolated channels, members, and invite system

Introduce workspace support with path-based routing (/w/:slug/...), per-workspace
admin roles, invite links with 1-hour expiration, and one Durable Object per
workspace for WebSocket connections. Existing data auto-migrates into a seeded
'default' workspace. Migration uses PRAGMA defer_foreign_keys to handle the
channels table rebuild safely on D1.

* fix: address PR review feedback — type safety, SQL efficiency, and invite security

- Make workspace/workspaceMember optional in Variables type to match runtime
- First user auto-joining default workspace now becomes admin (bootstrap fix)
- Remove unreachable auth check in /w/:slug (middleware already handles it)
- Replace select-all-then-filter with SQL inner join for workspace queries
- Use subquery in seed.sql instead of hardcoded workspace_id=1
- Convert invite acceptance from mutating GET to GET confirmation + POST

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: mahata <23497+mahata@users.noreply.github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants