Compare commits

...

43 Commits

Author SHA1 Message Date
Jacob Schlecht c9d59ee044
feat: enable screen sharing and integrate screen picker (#207)
Signed-off-by: Jacob Schlecht <dadadah@echoha.us>
2026-05-30 18:52:35 +01:00
Jacob Schlecht 3ff2cd0e5a
chore: Update electron to version 40 (#193)
* chore: Update to electron 39 and include some fixes

This commit was made without the use of generative AI.

Signed-off-by: Jacob Schlecht <dadadah@echoha.us>

* chore: Upgrade to electron 40

This commit was made without the use of generative AI.

Signed-off-by: Jacob Schlecht <dadadah@echoha.us>

---------

Signed-off-by: Jacob Schlecht <dadadah@echoha.us>
2026-05-27 19:44:56 -06:00
Christoffer 74c941e5b8
fix(flatpak): change screenshot path into an url in the metainfo file (#195) 2026-04-06 17:35:02 +01:00
Taureon 00c7572cd0
chore: update hardcoded domain to be stoat.chat instead of beta.revolt.chat (#196)
Co-authored-by: stoat-tofu[bot] <242700035+stoat-tofu[bot]@users.noreply.github.com>
2026-04-06 17:30:46 +01:00
stoat-tofu[bot] d1bf862a6c
chore: modify .github/workflows/validate-pr-title.yml 2026-03-24 19:04:04 +00:00
stoat-tofu[bot] 9a5ecbb22c
chore: modify .github/workflows/release-webhook.yml 2026-03-24 19:03:41 +00:00
stoat-tofu[bot] b57faa2c59
chore: modify .github/workflows/release-webhook.yml 2026-02-18 20:28:00 +00:00
stoat-release[bot] c1e4d4ee91
chore(main): release 1.3.0 (#128)
Co-authored-by: stoat-release[bot] <245062572+stoat-release[bot]@users.noreply.github.com>
2026-02-18 09:09:14 +00:00
Jacob Schlecht ffe17ec2c5
fix: flatpak icons not building correctly and wayland support (#132)
This commit was made without the use of generative AI.

Signed-off-by: Jacob Schlecht <dadadah@echoha.us>
2026-02-18 09:05:56 +00:00
Mihai 63b9ea818a
fix: firstLaunch = false after initial setup (#131)
fix: don't re-enable abutostart

Signed-off-by: Mihai <cristian@mihaimuresan.com>
Co-authored-by: Mihai <cristian@mihaimuresan.com>
2026-02-17 22:33:46 -05:00
Paul Makles 58ccb63d23
fix: use template icon for macOS tray, use higher res icons for other platforms (#130) 2026-02-17 20:36:25 +00:00
Mihai 8284117e76
feat: minimise-to-tray-on-startup (#126)
* feat: minimise-to-tray-on-startup

Signed-off-by: Mihai <cristian@mihaimuresan.com>

* feat: minimise-to-tray-on-startup

Signed-off-by: Mihai <cristian@mihaimuresan.com>

* fix: redundant call

Signed-off-by: Mihai <cristian@mihaimuresan.com>

* fix: redundant call

Signed-off-by: Mihai <cristian@mihaimuresan.com>

---------

Signed-off-by: Mihai <cristian@mihaimuresan.com>
Co-authored-by: Mihai <cristian@mihaimuresan.com>
2026-02-17 20:28:29 +00:00
Mihai 897d706983
fix: try to restore maximised windows to correct display (#92)
fix: App-maximized-2nd-monitor

Signed-off-by: Mihai <cristian@mihaimuresan.com>
Signed-off-by: Mihai <45673304+mihaicm93@users.noreply.github.com>
Co-authored-by: Mihai <cristian@mihaimuresan.com>
2026-02-17 20:27:01 +00:00
dxty522 7d2f296ca7
fix: replace default dialog with notification (#98)
Signed-off-by: dxty522 <261609953+dxty522@users.noreply.github.com>
2026-02-17 20:05:26 +00:00
Abel Ortolan 17d6d174ae
chore: changing flatpak runtime version to newest stable release (#120)
Update forge.config.ts

Changing Flatpak runtime version from 21.08 (EOL) to 25.08 (newest stable version)

Signed-off-by: Abel Ortolan <70042422+TrojanHorse-bot@users.noreply.github.com>
2026-02-17 20:02:46 +00:00
trendwhore 742a95f3cb
fix: toggle window visibility on tray click instead of always showing (#103) 2026-02-17 20:02:17 +00:00
a distraction 2b962c5d06
fix: allow CTRL+"+" to also zoom in. (#108)
Allow "+" to also zoom in.

Signed-off-by: a distraction <106486896+dresklaw@users.noreply.github.com>
Co-authored-by: Paul Makles <me@insrt.uk>
2026-02-17 19:59:18 +00:00
a distraction def29f9b3c
fix: Add common zoom-reset shortcut. (#112)
Add common zoom reset shortcut.

Signed-off-by: a distraction <106486896+dresklaw@users.noreply.github.com>
Signed-off-by: marcy <69540471+reeesespuffs@users.noreply.github.com>
Co-authored-by: marcy <69540471+reeesespuffs@users.noreply.github.com>
2026-02-17 14:35:57 -05:00
Paul Makles e2dc20b755
chore: Nix, mise, CI configuration (#129)
* chore: update Nix flake and setup mise for toolchains

* ci: use workflows
2026-02-17 19:29:43 +00:00
Mihai 2e99b19353
feat: Reload/Refresh shortcut (#119)
Signed-off-by: Mihai <cristian@mihaimuresan.com>
Co-authored-by: Mihai <cristian@mihaimuresan.com>
2026-02-17 14:21:57 -05:00
sfalken 1243f88b21
chore: add files to manage flathub details upstream (#104)
* Add files for flathub compliance

Please see: https://github.com/flathub/flathub/pull/7783

This adds the requested files to the upstream git repo, and adds the
screenshot.png so it may be sourced from Stoat, rather than from a user
repository.

* chore: update product screenshot

* chore: update desktop entry comment

* chore: update icon

* chore: update summary to current github tag

---------

Co-authored-by: Shawn W Dunn <sfalken@opensuse.org>
Co-authored-by: izzy <me@insrt.uk>
2026-02-17 19:04:04 +00:00
V3RM1N 7d3d80ae6e
docs: add installation section to README (#81)
Add Installation section with Repology badge and links to download page and GitHub releases

Signed-off-by: V3RM1N <mail@v3rm1n.dev>
2026-02-17 18:59:29 +00:00
stoat-release[bot] b765e84151
chore(main): release 1.2.0 (#79)
Co-authored-by: stoat-release[bot] <245062572+stoat-release[bot]@users.noreply.github.com>
2026-02-14 00:51:45 +00:00
Paul Makles 8910dcba92
feat: new branding (#87)
Signed-off-by: izzy <me@insrt.uk>
2026-02-14 00:41:34 +00:00
Mihai 127d1430a9
fix: App Autostart (#68)
Signed-off-by: Mihai <cristian@mihaimuresan.com>
Co-authored-by: Mihai <cristian@mihaimuresan.com>
2026-02-13 00:25:05 -05:00
Jespercal 3bf697d1a9
feat: persist and restore window size and position (#74)
Finished up saving and restoring of window position and size

Signed-off-by: Jespercal <chap600@hotmail.com>
2026-02-13 00:16:53 -05:00
Paul Makles a162219668
Revert "fix: add NixOS compatibility for electron startup (#23)" (#42)
This reverts commit 3eb9b8e84b.

Signed-off-by: izzy <me@insrt.uk>
2026-02-09 19:38:58 +00:00
stoat-tofu[bot] dad885aa1d
chore: modify .github/workflows/release-webhook.yml 2026-01-10 16:33:15 +00:00
stoat-tofu[bot] 7b9918f43b
chore: modify .github/workflows/release-webhook.yml 2026-01-10 13:19:22 +00:00
stoat-release[bot] 6ca1143c22
chore(main): release 1.1.12 (#28)
Co-authored-by: stoat-release[bot] <245062572+stoat-release[bot]@users.noreply.github.com>
2025-12-29 18:06:33 +00:00
Paul Makles e431f205c2
refactor: move publish.yml workflow into release please workflow (#29) 2025-12-29 18:05:26 +00:00
Paul Makles eac8195f68
chore: configure release please (#27) 2025-12-29 17:55:58 +00:00
Paul Makles ea7c57962b
chore: use Stoat name for auto launch entry (#24) 2025-12-29 17:55:55 +00:00
Paul Makles 96fa8cc647
fix: event listener accumulation from rpc client (#26) 2025-12-29 17:47:33 +00:00
Paul Makles 6817b554e5
fix: correctly load badge count; expose to renderer (#25) 2025-12-29 17:47:24 +00:00
Paul Makles cb373b6dc6
fix: rpc should define largeImageText (#21) 2025-12-29 17:00:09 +00:00
Paul Makles 532af4a680
fix: use the correct argument for auto start (#22)
fixes #20
2025-12-29 16:59:49 +00:00
Paul Makles 3eb9b8e84b
fix: add NixOS compatibility for electron startup (#23)
- Add start.sh script that auto-detects NixOS and configures electron path
- Script dynamically finds the correct electron version from nix store
- Keeps original electron-forge start available as start:forge
- Fixes electron launch issues on NixOS systems

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-authored-by: Claude <noreply@anthropic.com>
2025-12-29 16:59:31 +00:00
stoat-tofu[bot] 6907a33dc7
chore: modify .github/workflows/validate-pr-title.yml 2025-11-14 20:24:54 +00:00
izzy 1aa5f7e1c3
chore: update assets submodule [skip ci]
docs: remove pub. notes
2025-10-20 15:04:24 +01:00
Paul Makles e11c0490fc
merge: pull request #4 from e1berd/fix/macos-tray-icon 2025-10-14 17:33:56 +01:00
l 61ffe199ee chore(macos): remove useless comment 2025-10-10 19:29:43 +03:00
l 5eecab5943 fix(macos): tray icon size 2025-10-10 19:24:53 +03:00
29 changed files with 586 additions and 138 deletions

View File

@ -1,7 +1,8 @@
on:
push:
branches:
- "**"
- main
pull_request:
jobs:
build:
@ -15,16 +16,10 @@ jobs:
- name: Checkout assets
run: git -c submodule."assets".update=checkout submodule update --init assets
- name: Install pnpm
uses: pnpm/action-setup@v4
- name: Setup Mise
uses: immich-app/devtools/actions/use-mise@cd24790a7f5f6439ac32cc94f5523cb2de8bfa8c # use-mise-action-v1.1.0
with:
run_install: false
- name: Install Node.js
uses: actions/setup-node@v4
with:
node-version: 22
cache: "pnpm"
github-token: ${{ secrets.GITHUB_TOKEN }}
- name: Install dependencies
run: pnpm install

19
.github/workflows/git-town.yml vendored Normal file
View File

@ -0,0 +1,19 @@
name: Git Town
on:
pull_request:
jobs:
git-town:
name: Display the branch stack
runs-on: ubuntu-slim
if: ${{ !startsWith(github.head_ref, 'release-please--') }}
permissions:
contents: read
pull-requests: write
steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- uses: stoatchat/action-git-town@4bc5c942e4603bffa0806b51d5fe5f0bc5deb0ac

View File

@ -1,11 +1,41 @@
name: Release Please
on:
push:
tags:
- v*
branches: [main] # updates/opens the release PR when commits land on main
workflow_dispatch:
permissions:
contents: write
pull-requests: write
id-token: write
concurrency:
group: release-please
cancel-in-progress: true
jobs:
release:
release-please:
name: Release Please
runs-on: ubuntu-latest
outputs:
release_created: ${{ steps.rp.outputs.release_created }}
steps:
- id: app-token
uses: actions/create-github-app-token@v2
with:
app-id: ${{ secrets.GH_STOAT_RELEASE_APP_ID }}
private-key: ${{ secrets.GH_STOAT_RELEASE_APP_PRIVATE_KEY }}
- id: rp
uses: googleapis/release-please-action@v4
with:
token: ${{ steps.app-token.outputs.token }}
config-file: release-please-config.json
publish-release:
name: Publish App
needs: release-please
if: needs.release-please.outputs.release_created == 'true'
runs-on: ${{ matrix.os }}
permissions:
@ -14,7 +44,7 @@ jobs:
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
steps:
- name: Checkout
uses: actions/checkout@v4

26
.github/workflows/release-webhook.yml vendored Normal file
View File

@ -0,0 +1,26 @@
# DO NOT EDIT DIRECTLY IN REPOSITORY
# Managed in Terraform templates
name: Release Webhook
on:
workflow_dispatch:
release:
types: [published]
jobs:
release-webhook:
name: Send Release Webhook
runs-on: ubuntu-latest
steps:
- name: Send release notification webhook
env:
TAG_NAME: ${{ github.event.release.tag_name }}
REPOSITORY: ${{ github.repository }}
WEBHOOK_URL: ${{ secrets.STOAT_WEBHOOK_UPDATES_URL }}
run: |
RELEASE_URL="https://github.com/${REPOSITORY}/releases/tag/${TAG_NAME}"
curl -X POST "$WEBHOOK_URL" \
-H "Content-Type: application/json" \
-d "{\"content\": \"$RELEASE_URL\"}"

23
.github/workflows/validate-pr-title.yml vendored Normal file
View File

@ -0,0 +1,23 @@
# DO NOT EDIT DIRECTLY IN REPOSITORY
# Managed in Terraform templates
name: "Lint PR"
on:
pull_request_target:
types:
- opened
- reopened
- edited
- synchronize
jobs:
main:
name: Validate PR title
runs-on: ubuntu-latest
permissions:
pull-requests: read
steps:
- uses: amannn/action-semantic-pull-request@48f256284bd46cdaab1048c3721360e808335d50 # v6.1.1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

@ -0,0 +1,3 @@
{
".": "1.3.0"
}

48
CHANGELOG.md Normal file
View File

@ -0,0 +1,48 @@
# Changelog
## [1.3.0](https://github.com/stoatchat/for-desktop/compare/v1.2.0...v1.3.0) (2026-02-18)
### Features
* minimise-to-tray-on-startup ([#126](https://github.com/stoatchat/for-desktop/issues/126)) ([8284117](https://github.com/stoatchat/for-desktop/commit/8284117e76c0fcff4091de3ef623014e4594a593))
* Reload/Refresh shortcut ([#119](https://github.com/stoatchat/for-desktop/issues/119)) ([2e99b19](https://github.com/stoatchat/for-desktop/commit/2e99b19353fbd45d9fdf1d148bae3a8a19c788ed))
### Bug Fixes
* Add common zoom-reset shortcut. ([#112](https://github.com/stoatchat/for-desktop/issues/112)) ([def29f9](https://github.com/stoatchat/for-desktop/commit/def29f9b3c1205944aab58beb8000815d41633b5))
* allow CTRL+"+" to also zoom in. ([#108](https://github.com/stoatchat/for-desktop/issues/108)) ([2b962c5](https://github.com/stoatchat/for-desktop/commit/2b962c5d066787601223368ee7dcc1e46a345b8a))
* App-maximized-2nd-monitor ([897d706](https://github.com/stoatchat/for-desktop/commit/897d706983a347938a2fb42ba8e58e40794bba13))
* don't re-enable abutostart ([63b9ea8](https://github.com/stoatchat/for-desktop/commit/63b9ea818a9f32ca8535948e18752726c0f50a12))
* firstLaunch = false after initial setup ([#131](https://github.com/stoatchat/for-desktop/issues/131)) ([63b9ea8](https://github.com/stoatchat/for-desktop/commit/63b9ea818a9f32ca8535948e18752726c0f50a12))
* flatpak icons not building correctly and wayland support ([#132](https://github.com/stoatchat/for-desktop/issues/132)) ([ffe17ec](https://github.com/stoatchat/for-desktop/commit/ffe17ec2c54fca6967435b8a4ada7fa8d4da7b33))
* replace default dialog with notification ([#98](https://github.com/stoatchat/for-desktop/issues/98)) ([7d2f296](https://github.com/stoatchat/for-desktop/commit/7d2f296ca72bbd7ad694c66a917d47067f883fc5))
* toggle window visibility on tray click instead of always showing ([#103](https://github.com/stoatchat/for-desktop/issues/103)) ([742a95f](https://github.com/stoatchat/for-desktop/commit/742a95f3cb820c5b5398c815b7b45017b6b06053))
* try to restore maximised windows to correct display ([#92](https://github.com/stoatchat/for-desktop/issues/92)) ([897d706](https://github.com/stoatchat/for-desktop/commit/897d706983a347938a2fb42ba8e58e40794bba13))
* use template icon for macOS tray, use higher res icons for other platforms ([#130](https://github.com/stoatchat/for-desktop/issues/130)) ([58ccb63](https://github.com/stoatchat/for-desktop/commit/58ccb63d23541a03e05a48a37a98f883a2ba0d3f))
## [1.2.0](https://github.com/stoatchat/for-desktop/compare/v1.1.12...v1.2.0) (2026-02-14)
### Features
* new branding ([#87](https://github.com/stoatchat/for-desktop/issues/87)) ([8910dcb](https://github.com/stoatchat/for-desktop/commit/8910dcba923b55df789c0541b59a6a6321a28768))
* persist and restore window size and position ([#74](https://github.com/stoatchat/for-desktop/issues/74)) ([3bf697d](https://github.com/stoatchat/for-desktop/commit/3bf697d1a9aba739b6954c8469223f51093497cc))
### Bug Fixes
* App Autostart ([#68](https://github.com/stoatchat/for-desktop/issues/68)) ([127d143](https://github.com/stoatchat/for-desktop/commit/127d1430a9c630e0429c9cc50d57ee316a63ebe5))
## [1.1.12](https://github.com/stoatchat/for-desktop/compare/v1.1.11...v1.1.12) (2025-12-29)
### Bug Fixes
* add NixOS compatibility for electron startup ([#23](https://github.com/stoatchat/for-desktop/issues/23)) ([3eb9b8e](https://github.com/stoatchat/for-desktop/commit/3eb9b8e84bf05debf9843b80c468911fd095f4a0))
* correctly load badge count; expose to renderer ([#25](https://github.com/stoatchat/for-desktop/issues/25)) ([6817b55](https://github.com/stoatchat/for-desktop/commit/6817b554e57c5a65b7b4aca7d1cc4e05cd6f01b7))
* event listener accumulation from rpc client ([#26](https://github.com/stoatchat/for-desktop/issues/26)) ([96fa8cc](https://github.com/stoatchat/for-desktop/commit/96fa8cc647029cb53e5d619b94debc6cdfdf32f6))
* **macos:** tray icon size ([5eecab5](https://github.com/stoatchat/for-desktop/commit/5eecab59431cb4966eaa1fc907a8e5c16c813230))
* rpc should define largeImageText ([#21](https://github.com/stoatchat/for-desktop/issues/21)) ([cb373b6](https://github.com/stoatchat/for-desktop/commit/cb373b6dc62630147151039c3711aef74c8c2d88))
* use the correct argument for auto start ([#22](https://github.com/stoatchat/for-desktop/issues/22)) ([532af4a](https://github.com/stoatchat/for-desktop/commit/532af4a680069f72734148b0ccdacec6c435e640)), closes [#20](https://github.com/stoatchat/for-desktop/issues/20)

View File

@ -13,6 +13,14 @@ Application for Windows, macOS, and Linux.
</div>
<br/>
## Installation
<a href="https://repology.org/project/stoat-desktop/versions">
<img src="https://repology.org/badge/vertical-allrepos/stoat-desktop.svg" alt="Packaging status" align="right">
</a>
- All downloads and instructions for Stoat can be found on our [Website](https://stoat.chat/download).
## Development Guide
_Contribution guidelines for Desktop app TBA!_
@ -74,11 +82,3 @@ git -c submodule."assets".update=checkout submodule update --init assets
```
Currently, this is required to build, any forks are expected to provide their own assets.
## Publishing Guide
To publish a new version, simply tag a new release by:
1. Edit `package.json` with the new version
2. Create a new tag from latest commit by `git tag v1.0.0`
3. Push the tag and commit by `git push --atomic origin main v1.0.0`

2
assets

@ -1 +1 @@
Subproject commit 628eb2f8255c215148007f4227d2e0d5d1a67582
Subproject commit bd432f2298901a8566a092636eef0c35a3a80fbc

View File

@ -0,0 +1,11 @@
[Desktop Entry]
Name=Stoat
Comment=Open source, user-first chat platform
Exec=stoat-desktop
Terminal=false
Type=Application
Icon=chat.stoat.StoatDesktop
Categories=Network;InstantMessaging
StartupWMClass=stoat-desktop
X-Desktop-File-Install-Version=0.26
X-Flatpak=chat.stoat.StoatDesktop

View File

@ -0,0 +1,70 @@
<?xml version="1.0" encoding="UTF-8"?>
<component type="desktop">
<id>chat.stoat.StoatDesktop</id>
<launchable type="desktop-id">chat.stoat.StoatDesktop.desktop</launchable>
<name>Stoat</name>
<developer id="chat.stoat">
<name>Revolt Platforms Ltd</name>
</developer>
<summary>Open source, user-first chat platform</summary>
<metadata_license>CC0-1.0</metadata_license>
<project_license>AGPL-3.0</project_license>
<icon type="remote" height="256" width="256">
https://raw.githubusercontent.com/stoatchat/assets/f106946659af67ad4f008588ac51570029b2fd47/desktop/icon.png</icon>
<description>
<p>Stoat is an open source, user-first chat platform. Send messages, share
images, mention users, and join voice channels — all from a native desktop
application.</p>
</description>
<screenshots>
<screenshot type="default">
<caption>Main window</caption>
<image>https://raw.githubusercontent.com/stoatchat/for-desktop/b57faa2c59865fea15a879c9a9304271067d0020/screenshot.png</image>
</screenshot>
</screenshots>
<releases>
<release date="2026-02-14" version="1.2.0">
<description>
<p>Features:</p>
<ul>
<li>New Branding</li>
<li>Persist and restore window size and position</li>
</ul>
<p>Bug Fixes:</p>
<ul>
<li>App Autostart</li>
</ul>
</description>
</release>
<release date="2025-12-29" version="1.1.12">
<description>
<p>Bug fixes:</p>
<ul>
<li>Add NixOS compatibility for electron startup</li>
<li>Correctly load badge count; expose to renderer</li>
<li>Fix event listener accumulation from rpc client</li>
<li>Fix macOS tray icon size</li>
<li>Fix RPC largeImageText</li>
<li>Use the correct argument for auto start</li>
</ul>
</description>
</release>
</releases>
<url type="bugtracker">https://github.com/stoatchat/for-desktop/issues</url>
<url type="homepage">https://stoat.chat</url>
<url type="vcs-browser">https://github.com/stoatchat/for-desktop</url>
<content_rating type="oars-1.1">
<content_attribute id="social-chat">intense</content_attribute>
<content_attribute id="social-info">intense</content_attribute>
<content_attribute id="social-audio">intense</content_attribute>
<content_attribute id="social-contacts">intense</content_attribute>
</content_rating>
<requires>
<display_length compare="ge">940</display_length>
<internet>always</internet>
</requires>
<supports>
<control>keyboard</control>
<control>pointing</control>
</supports>
</component>

View File

@ -1,16 +1,13 @@
{
pkgs ? import <nixpkgs> { },
{ pkgs ? import (fetchTarball {
url = "https://github.com/NixOS/nixpkgs/archive/77ef7a29d276c6d8303aece3444d61118ef71ac2.tar.gz";
sha256 = "0pm4l48jq8plzrrrisimahxqlcpx7qqq9c99hylmf7p3zlc3phsy";
}) {},
}:
pkgs.mkShell rec {
buildInputs = [
buildInputs = with pkgs; [
# Tools
pkgs.git
pkgs.gh
# Node
pkgs.nodejs
pkgs.nodejs.pkgs.pnpm
pkgs.mise
# Electron
(pkgs.writeShellScriptBin "electron-nix" ''
@ -29,5 +26,15 @@ pkgs.mkShell rec {
pkgs.flatpak-builder
pkgs.elfutils
# flatpak remote-add --if-not-exists --user flathub https://dl.flathub.org/repo/flathub.flatpakrepo
(writeShellScriptBin "fish" ''
exec ${pkgs.fish}/bin/fish -C 'mise activate fish | source' "$@"
'')
];
shellHook = ''
export ELECTRON_OVERRIDE_DIST_PATH="${pkgs.electron}/bin"
export MISE_NODE_COMPILE=false
eval "$(mise activate bash)"
'';
}

View File

@ -58,8 +58,15 @@ if (!process.env.PLATFORM) {
description: STRINGS.description,
productName: STRINGS.name,
productDescription: STRINGS.description,
runtimeVersion: "21.08",
icon: `${ASSET_DIR}/icon.png`,
runtimeVersion: "25.08",
icon: {
"16x16": `${ASSET_DIR}/hicolor/16x16.png`,
"32x32": `${ASSET_DIR}/hicolor/32x32.png`,
"64x64": `${ASSET_DIR}/hicolor/64x64.png`,
"128x128": `${ASSET_DIR}/hicolor/128x128.png`,
"256x256": `${ASSET_DIR}/hicolor/256x256.png`,
"512x512": `${ASSET_DIR}/hicolor/512x512.png`,
} as unknown,
categories: ["Network"],
modules: [
// use the latest zypak -- Electron sandboxing for Flatpak
@ -77,38 +84,30 @@ if (!process.env.PLATFORM) {
finishArgs: [
// default arguments found by running
// DEBUG=electron-installer-flatpak* pnpm make
"--socket=x11",
"--socket=fallback-x11",
"--socket=wayland",
"--share=ipc",
"--share=network",
"--device=dri",
"--device=all",
"--socket=pulseaudio",
"--filesystem=home",
"--env=TMPDIR=/var/tmp",
"--share=network",
"--filesystem=xdg-run/pipewire-0",
"--filesystem=xdg-videos:ro",
"--filesystem=xdg-pictures:ro",
"--filesystem=xdg-run/speech-dispatcher",
"--talk-name=org.freedesktop.ScreenSaver",
"--talk-name=org.freedesktop.Notifications",
// add Unity talk name for badges
"--talk-name=org.kde.StatusNotifierWatcher",
"--talk-name=com.canonical.AppMenu.Registrar",
"--talk-name=com.canonical.indicator.application",
"--talk-name=com.canonical.Unity",
"--env=XCURSOR_PATH=/run/host/user-share/icons:/run/host/share/icons",
"--env=ELECTRON_TRASH=gio",
"--env=TMPDIR=xdg-run/app/chat.stoat.stoat-desktop",
],
// files: [
// // is this necessary?
// // https://stackoverflow.com/q/79745700
// ...[16, 32, 64, 128, 256, 512].map(
// (size) =>
// [
// `assets/desktop/hicolor/${size}x${size}.png`,
// `/app/share/icons/hicolor/${size}x${size}/apps/chat.stoat.stoat-desktop.png`,
// ] as [string, string],
// ),
// [
// `assets/desktop/icon.svg`,
// `/app/share/icons/hicolor/scalable/apps/chat.stoat.stoat-desktop.svg`,
// ] as [string, string],
// ],
files: [],
} as MakerFlatpakOptionsConfig,
/* as Omit<
MakerFlatpakOptionsConfig,
"files"
> */
}),
// testing purposes
new MakerDeb({

5
mise.toml Normal file
View File

@ -0,0 +1,5 @@
[tools]
node = "25.4.0"
pnpm = "10.28.1"
gh = "2.25.0"
"github:git-town/git-town" = "22.4.0"

View File

@ -1,11 +1,11 @@
{
"name": "stoat-desktop",
"productName": "stoat-desktop",
"version": "1.1.11",
"version": "1.3.0",
"main": ".vite/build/main.js",
"repository": "stoatchat/desktop",
"scripts": {
"start": "electron-forge start",
"start": "electron-forge start -- --no-sandbox",
"package": "electron-forge package",
"make": "electron-forge make",
"publish": "electron-forge publish",
@ -36,7 +36,7 @@
"@types/electron-squirrel-startup": "^1.0.2",
"@typescript-eslint/eslint-plugin": "^5.62.0",
"@typescript-eslint/parser": "^5.62.0",
"electron": "38.1.2",
"electron": "^40.8.3",
"eslint": "^8.57.1",
"eslint-plugin-import": "^2.32.0",
"json-schema-typed": "^8.0.1",

View File

@ -85,8 +85,8 @@ importers:
specifier: ^5.62.0
version: 5.62.0(eslint@8.57.1)(typescript@4.5.5)
electron:
specifier: 38.1.2
version: 38.1.2
specifier: ^40.8.3
version: 40.8.3
eslint:
specifier: ^8.57.1
version: 8.57.1
@ -104,7 +104,7 @@ importers:
version: 4.5.5
vite:
specifier: ^5.4.20
version: 5.4.20(@types/node@24.5.2)
version: 5.4.20(@types/node@24.10.13)
packages:
@ -825,6 +825,9 @@ packages:
'@types/node@22.18.6':
resolution: {integrity: sha512-r8uszLPpeIWbNKtvWRt/DbVi5zbqZyj1PTmhRMqBMvDnaz1QpmSKujUtJLrqGZeoM8v72MfYggDceY4K1itzWQ==}
'@types/node@24.10.13':
resolution: {integrity: sha512-oH72nZRfDv9lADUBSo104Aq7gPHpQZc4BTx38r9xf9pg5LfP6EzSyH2n7qFmmxRQXh7YlUXODcYsg6PuTDSxGg==}
'@types/node@24.5.2':
resolution: {integrity: sha512-FYxk1I7wPv3K2XBaoyH2cTnocQEu8AOZ60hPbsyukMPLv5/5qr7V1i8PLHdl6Zf87I+xZXFvPCXYjiTFq+YSDQ==}
@ -907,6 +910,7 @@ packages:
'@xmldom/xmldom@0.8.11':
resolution: {integrity: sha512-cQzWCtO6C8TQiYl1ruKNn2U6Ao4o4WBBcbL61yJl84x+j5sOWWFU9X7DpND8XZG3daDppSsigMdfAIl2upQBRw==}
engines: {node: '>=10.0.0'}
deprecated: this version has critical issues, please update to the latest version
abbrev@1.1.1:
resolution: {integrity: sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==}
@ -1075,6 +1079,9 @@ packages:
brace-expansion@2.0.2:
resolution: {integrity: sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==}
brace-expansion@2.1.0:
resolution: {integrity: sha512-TN1kCZAgdgweJhWWpgKYrQaMNHcDULHkWwQIspdtjV4Y5aurRdZpjAqn6yX3FPqTA9ngHCc4hJxMAMgGfve85w==}
braces@3.0.3:
resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==}
engines: {node: '>=8'}
@ -1372,8 +1379,8 @@ packages:
resolution: {integrity: sha512-bO3y10YikuUwUuDUQRM4KfwNkKhnpVO7IPdbsrejwN9/AABJzzTQ4GeHwyzNSrVO+tEH3/Np255a3sVZpZDjvg==}
engines: {node: '>=8.0.0'}
electron@38.1.2:
resolution: {integrity: sha512-WXUcN3W8h8NTTZViA3KNX0rV2YBU0X0mEUM3ubupXTDY4QtIN7tmiqYVOKSKpR2LckTmBWGuEeY4D6xVoffwKQ==}
electron@40.8.3:
resolution: {integrity: sha512-MH6LK4xM6VVmmtz0nRE0Fe8l2jTKSYTvH1t0ZfbNLw3o6dlBCVTRqQha6uL8ZQVoMy74JyLguGwK7dU7rCKIhw==}
engines: {node: '>= 12.20.55'}
hasBin: true
@ -1537,8 +1544,8 @@ packages:
resolution: {integrity: sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==}
engines: {node: '>=6'}
exponential-backoff@3.1.2:
resolution: {integrity: sha512-8QxYTVXUkuy7fIIoitQkPwGonB8F3Zj8eEO8Sqg9Zv/bkI7RJAzowee4gr81Hak/dUTpA2Z7VfQgoijjPNlUZA==}
exponential-backoff@3.1.3:
resolution: {integrity: sha512-ZgEeZXj30q+I0EN+CbSSpIyPaJ5HVQD18Z1m+u1FXbAeT94mr1zw50q4q6jiiC447Nl/YTcIYSAftiGqetwXCA==}
external-editor@3.1.0:
resolution: {integrity: sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==}
@ -1715,12 +1722,12 @@ packages:
glob@7.2.3:
resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==}
deprecated: Glob versions prior to v9 are no longer supported
deprecated: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me
glob@8.1.0:
resolution: {integrity: sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==}
engines: {node: '>=12'}
deprecated: Glob versions prior to v9 are no longer supported
deprecated: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me
global-agent@3.0.0:
resolution: {integrity: sha512-PT6XReJ+D07JvGoxQMkT6qji/jVNfX/h364XHZOWeRzy64sSFr+xJ5OX7LI3b4MPQzdL4H8Y8M0xzPpsVMwA8Q==}
@ -1866,8 +1873,8 @@ packages:
resolution: {integrity: sha512-6xwYfHbajpoF0xLW+iwLkhwgvLoZDfjYfoFNu8ftMoXINzwuymNLd9u/KmwtdT2GbR+/Cz66otEGEVVUHX9QLQ==}
engines: {node: '>=10.13.0'}
ip-address@10.0.1:
resolution: {integrity: sha512-NWv9YLW4PoW2B7xtzaS3NCot75m6nK7Icdv0o3lfMceJVRfSoQwqD4wEH5rLwoKJwUiZ/rfpiVBhnaF0FK4HoA==}
ip-address@10.1.0:
resolution: {integrity: sha512-XXADHxXmvT9+CRxhXg56LJovE+bmWnEWB78LB83VZTprKTmaC5QfruXocxzTZ2Kl0DNwKuBdlIhjL8LeY8Sf8Q==}
engines: {node: '>= 12'}
is-array-buffer@3.0.5:
@ -2185,8 +2192,8 @@ packages:
minimatch@3.1.2:
resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==}
minimatch@5.1.6:
resolution: {integrity: sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==}
minimatch@5.1.9:
resolution: {integrity: sha512-7o1wEA2RyMP7Iu7GNba9vc0RWWGACJOCZBJX2GJWip0ikV+wcOsgVuY9uE8CPiyQhkGFSlhuSkZPavN7u1c2Fw==}
engines: {node: '>=10'}
minimatch@9.0.5:
@ -2204,8 +2211,8 @@ packages:
resolution: {integrity: sha512-LT49Zi2/WMROHYoqGgdlQIZh8mLPZmOrN2NdJjMXxYe4nkN6FUyuPuOAOedNJDrx0IRGg9+4guZewtp8hE6TxA==}
engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0}
minipass-flush@1.0.5:
resolution: {integrity: sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==}
minipass-flush@1.0.7:
resolution: {integrity: sha512-TbqTz9cUwWyHS2Dy89P3ocAGUGxKjjLuR9z8w4WUTGAVgEj17/4nhgo2Du56i0Fm3Pm30g4iA8Lcqctc76jCzA==}
engines: {node: '>= 8'}
minipass-pipeline@1.2.4:
@ -2273,8 +2280,8 @@ packages:
nice-try@1.0.5:
resolution: {integrity: sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==}
node-abi@3.77.0:
resolution: {integrity: sha512-DSmt0OEcLoK4i3NuscSbGjOf3bqiDEutejqENSplMSFA/gmB8mkED9G4pKWnPl7MDU4rSHebKPHeitpDfyH0cQ==}
node-abi@3.89.0:
resolution: {integrity: sha512-6u9UwL0HlAl21+agMN3YAMXcKByMqwGx+pq+P76vii5f7hTPtKDp08/H9py6DY+cfDw7kQNTGEj/rly3IgbNQA==}
engines: {node: '>=10'}
node-addon-api@1.7.2:
@ -2876,6 +2883,7 @@ packages:
tar@6.2.1:
resolution: {integrity: sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==}
engines: {node: '>=10'}
deprecated: Old versions of tar are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me
temp@0.9.4:
resolution: {integrity: sha512-yYrrsWnrXMcdsnu/7YMYAofM1ktpL5By7vZhf15CrXijWWrEYZks5AXBudalfSWJLlnen/QUJUB5aoB0kqZUGA==}
@ -2983,6 +2991,9 @@ packages:
undici-types@7.12.0:
resolution: {integrity: sha512-goOacqME2GYyOZZfb5Lgtu+1IDmAlAEu5xnD3+xTzS10hT0vzpf0SPjkXwAw9Jm+4n/mQGDP3LO8CPbYROeBfQ==}
undici-types@7.16.0:
resolution: {integrity: sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==}
unique-filename@2.0.1:
resolution: {integrity: sha512-ODWHtkkdx3IAR+veKxFV+VBkUMcN+FaqzUUd7IZzt+0zhDZFPFxhlqwPF3YQvMHx1TD0tdgYl+kuPnJ8E6ql7A==}
engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0}
@ -3531,7 +3542,7 @@ snapshots:
'@electron/node-gyp@https://codeload.github.com/electron/node-gyp/tar.gz/06b29aafb7708acef8b3669835c8a7857ebc92d2':
dependencies:
env-paths: 2.2.1
exponential-backoff: 3.1.2
exponential-backoff: 3.1.3
glob: 8.1.0
graceful-fs: 4.2.11
make-fetch-happen: 10.2.1
@ -3598,7 +3609,7 @@ snapshots:
detect-libc: 2.1.1
fs-extra: 10.1.0
got: 11.8.6
node-abi: 3.77.0
node-abi: 3.89.0
node-api-version: 0.2.1
ora: 5.4.1
read-binary-file-arch: 1.0.6
@ -4103,7 +4114,7 @@ snapshots:
'@types/fs-extra@9.0.13':
dependencies:
'@types/node': 24.5.2
'@types/node': 24.10.13
optional: true
'@types/http-cache-semantics@4.0.4': {}
@ -4114,16 +4125,20 @@ snapshots:
'@types/keyv@3.1.4':
dependencies:
'@types/node': 24.5.2
'@types/node': 24.10.13
'@types/mute-stream@0.0.4':
dependencies:
'@types/node': 22.18.6
'@types/node': 24.10.13
'@types/node@22.18.6':
dependencies:
undici-types: 6.21.0
'@types/node@24.10.13':
dependencies:
undici-types: 7.16.0
'@types/node@24.5.2':
dependencies:
undici-types: 7.12.0
@ -4138,7 +4153,7 @@ snapshots:
'@types/yauzl@2.10.3':
dependencies:
'@types/node': 22.18.6
'@types/node': 24.10.13
optional: true
'@typescript-eslint/eslint-plugin@5.62.0(@typescript-eslint/parser@5.62.0(eslint@8.57.1)(typescript@4.5.5))(eslint@8.57.1)(typescript@4.5.5)':
@ -4416,6 +4431,10 @@ snapshots:
dependencies:
balanced-match: 1.0.2
brace-expansion@2.1.0:
dependencies:
balanced-match: 1.0.2
braces@3.0.3:
dependencies:
fill-range: 7.1.1
@ -4444,7 +4463,7 @@ snapshots:
lru-cache: 7.18.3
minipass: 3.3.6
minipass-collect: 1.0.2
minipass-flush: 1.0.5
minipass-flush: 1.0.7
minipass-pipeline: 1.2.4
mkdirp: 1.0.4
p-map: 4.0.0
@ -4787,10 +4806,10 @@ snapshots:
- supports-color
optional: true
electron@38.1.2:
electron@40.8.3:
dependencies:
'@electron/get': 2.0.3
'@types/node': 22.18.6
'@types/node': 24.10.13
extract-zip: 2.0.1
transitivePeerDependencies:
- supports-color
@ -5079,7 +5098,7 @@ snapshots:
signal-exit: 3.0.7
strip-eof: 1.0.0
exponential-backoff@3.1.2: {}
exponential-backoff@3.1.3: {}
external-editor@3.1.0:
dependencies:
@ -5315,7 +5334,7 @@ snapshots:
fs.realpath: 1.0.0
inflight: 1.0.6
inherits: 2.0.4
minimatch: 5.1.6
minimatch: 5.1.9
once: 1.4.0
global-agent@3.0.0:
@ -5483,7 +5502,7 @@ snapshots:
interpret@3.1.1: {}
ip-address@10.0.1: {}
ip-address@10.1.0: {}
is-array-buffer@3.0.5:
dependencies:
@ -5734,7 +5753,7 @@ snapshots:
minipass: 3.3.6
minipass-collect: 1.0.2
minipass-fetch: 2.1.2
minipass-flush: 1.0.5
minipass-flush: 1.0.7
minipass-pipeline: 1.2.4
negotiator: 0.6.4
promise-retry: 2.0.1
@ -5791,9 +5810,9 @@ snapshots:
dependencies:
brace-expansion: 1.1.12
minimatch@5.1.6:
minimatch@5.1.9:
dependencies:
brace-expansion: 2.0.2
brace-expansion: 2.1.0
minimatch@9.0.5:
dependencies:
@ -5813,7 +5832,7 @@ snapshots:
optionalDependencies:
encoding: 0.1.13
minipass-flush@1.0.5:
minipass-flush@1.0.7:
dependencies:
minipass: 3.3.6
@ -5866,7 +5885,7 @@ snapshots:
nice-try@1.0.5: {}
node-abi@3.77.0:
node-abi@3.89.0:
dependencies:
semver: 7.7.2
@ -6375,7 +6394,7 @@ snapshots:
socks@2.8.7:
dependencies:
ip-address: 10.0.1
ip-address: 10.1.0
smart-buffer: 4.2.0
source-map-js@1.2.1: {}
@ -6638,6 +6657,8 @@ snapshots:
undici-types@7.12.0: {}
undici-types@7.16.0: {}
unique-filename@2.0.1:
dependencies:
unique-slug: 3.0.0
@ -6679,13 +6700,13 @@ snapshots:
spdx-correct: 3.2.0
spdx-expression-parse: 3.0.1
vite@5.4.20(@types/node@24.5.2):
vite@5.4.20(@types/node@24.10.13):
dependencies:
esbuild: 0.21.5
postcss: 8.5.6
rollup: 4.52.2
optionalDependencies:
'@types/node': 24.5.2
'@types/node': 24.10.13
fsevents: 2.3.3
wcwidth@1.0.1:

View File

@ -1,7 +1,9 @@
nodeLinker: hoisted
onlyBuiltDependencies:
- bufferutil
- electron
- electron-winstaller
- esbuild
- register-scheme
- utf-8-validate

View File

@ -0,0 +1,14 @@
{
"packages": {
".": {
"changelog-path": "CHANGELOG.md",
"release-type": "node",
"bump-minor-pre-major": false,
"bump-patch-for-minor-pre-major": false,
"draft": false,
"prerelease": false,
"include-component-in-tag": false
}
},
"$schema": "https://raw.githubusercontent.com/googleapis/release-please/main/schemas/config.json"
}

BIN
screenshot.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 702 KiB

4
src/config.d.ts vendored
View File

@ -6,6 +6,10 @@ declare type DesktopConfig = {
hardwareAcceleration: boolean;
discordRpc: boolean;
windowState: {
x: number;
y: number;
width: number;
height: number;
isMaximised: boolean;
};
};

View File

@ -1,6 +1,6 @@
import { updateElectronApp } from "update-electron-app";
import { IUpdateInfo, updateElectronApp } from "update-electron-app";
import { BrowserWindow, app, shell } from "electron";
import { BrowserWindow, Notification, app, shell } from "electron";
import started from "electron-squirrel-startup";
import { autoLaunch } from "./native/autoLaunch";
@ -24,21 +24,33 @@ if (!config.hardwareAcceleration) {
// ensure only one copy of the application can run
const acquiredLock = app.requestSingleInstanceLock();
const onNotifyUser = (_info: IUpdateInfo) => {
const notification = new Notification({
title: "Update Available",
body: "Restart the app to install the update.",
silent: true,
});
notification.show();
};
if (acquiredLock) {
// start auto update logic
updateElectronApp();
updateElectronApp({ onNotifyUser });
// create and configure the app when electron is ready
app.on("ready", () => {
// create window and application contexts
createMainWindow();
// enable auto start on Windows and MacOS
if (config.firstLaunch) {
if (process.platform === "win32" || process.platform === "darwin") {
autoLaunch.enable();
}
config.firstLaunch = false;
}
// create window and application contexts
createMainWindow();
initTray();
initDiscordRpc();

View File

@ -5,15 +5,23 @@ import { ipcMain } from "electron";
import { mainWindow } from "./window";
export const autoLaunch = new AutoLaunch({
name: "Revolt",
name: "Stoat",
});
ipcMain.on("isAutostart?", () =>
autoLaunch
.isEnabled()
.then((enabled) => mainWindow.webContents.send("isAutostart", enabled)),
);
ipcMain.handle("getAutostart", async () => {
const enabled = await autoLaunch.isEnabled();
return enabled;
});
ipcMain.on("setAutostart", (state) =>
state ? autoLaunch.enable() : autoLaunch.disable(),
);
ipcMain.handle("setAutostart", async (_event, state: boolean) => {
if (state) {
await autoLaunch.enable();
console.log("Received new configuration autoStart: true");
} else {
await autoLaunch.disable();
console.log("Received new configuration autoStart: false");
}
const enabled = await autoLaunch.isEnabled();
return enabled;
});

View File

@ -1,6 +1,6 @@
import dbus from "@homebridge/dbus-native";
import { NativeImage, app, nativeImage } from "electron";
import { NativeImage, app, ipcMain, nativeImage } from "electron";
import { mainWindow } from "./window";
@ -21,7 +21,7 @@ export async function setBadgeCount(count: number) {
nativeIcons[count] = nativeImage.createFromDataURL(
await import(
`../../assets/desktop/badges/${Math.min(count, 10)}.ico?asset`
),
).then((asset) => asset.default),
);
mainWindow.setOverlayIcon(
@ -65,3 +65,5 @@ export async function setBadgeCount(count: number) {
break;
}
}
ipcMain.on("setBadgeCount", (_event, count: number) => setBadgeCount(count));

View File

@ -16,6 +16,9 @@ const schema = {
minimiseToTray: {
type: "boolean",
} as JSONSchema.Boolean,
startMinimisedToTray: {
type: "boolean",
} as JSONSchema.Boolean,
spellchecker: {
type: "boolean",
} as JSONSchema.Boolean,
@ -28,18 +31,18 @@ const schema = {
windowState: {
type: "object",
properties: {
// x: {
// type: 'number'
// } as JSONSchema.Number,
// y: {
// type: 'number'
// } as JSONSchema.Number,
// width: {
// type: 'number'
// } as JSONSchema.Number,
// height: {
// type: 'number'
// } as JSONSchema.Number,
x: {
type: "number",
} as JSONSchema.Number,
y: {
type: "number",
} as JSONSchema.Number,
width: {
type: "number",
} as JSONSchema.Number,
height: {
type: "number",
} as JSONSchema.Number,
isMaximised: {
type: "boolean",
} as JSONSchema.Boolean,
@ -53,10 +56,15 @@ const store = new Store({
firstLaunch: true,
customFrame: true,
minimiseToTray: true,
startMinimisedToTray: false,
spellchecker: true,
hardwareAcceleration: true,
discordRpc: true,
windowState: {
x: 0,
y: 0,
width: 0,
height: 0,
isMaximised: false,
},
} as DesktopConfig,
@ -71,6 +79,7 @@ class Config {
firstLaunch: this.firstLaunch,
customFrame: this.customFrame,
minimiseToTray: this.minimiseToTray,
startMinimisedToTray: this.startMinimisedToTray,
spellchecker: this.spellchecker,
hardwareAcceleration: this.hardwareAcceleration,
discordRpc: this.discordRpc,
@ -119,6 +128,21 @@ class Config {
this.sync();
}
get startMinimisedToTray() {
return (store as never as { get(k: string): boolean }).get(
"startMinimisedToTray",
);
}
set startMinimisedToTray(value: boolean) {
(store as never as { set(k: string, value: boolean): void }).set(
"startMinimisedToTray",
value,
);
this.sync();
}
get spellchecker() {
return (store as never as { get(k: string): boolean }).get("spellchecker");
}

View File

@ -8,6 +8,9 @@ let rpc: Client;
export async function initDiscordRpc() {
if (!config.discordRpc) return;
// clean up existing client if one exists
rpc?.removeAllListeners();
try {
rpc = new Client({ transport: "ipc" });
@ -16,8 +19,7 @@ export async function initDiscordRpc() {
state: "stoat.chat",
details: "Chatting with others",
largeImageKey: "qr",
// largeImageText: "Communication is critical use Revolt.",
largeImageText: "",
largeImageText: "Join Stoat!",
buttons: [
{
label: "Join Stoat",

View File

@ -1,6 +1,7 @@
import { Menu, Tray, nativeImage } from "electron";
import trayIconAsset from "../../assets/desktop/icon.png?asset";
import macOsTrayIconAsset from "../../assets/desktop/iconTemplate.png?asset";
import { version } from "../../package.json";
import { mainWindow, quitApp } from "./window";
@ -8,19 +9,31 @@ import { mainWindow, quitApp } from "./window";
// internal tray state
let tray: Tray = null;
// load the tray icon
const trayIcon = nativeImage.createFromDataURL(trayIconAsset);
// trayIcon.setTemplateImage(true);
// Create and resize tray icon for macOS
function createTrayIcon() {
if (process.platform === "darwin") {
const image = nativeImage.createFromDataURL(macOsTrayIconAsset);
const resized = image.resize({ width: 20, height: 20 });
resized.setTemplateImage(true);
return resized;
} else {
return nativeImage.createFromDataURL(trayIconAsset);
}
}
export function initTray() {
const trayIcon = createTrayIcon();
tray = new Tray(trayIcon);
updateTrayMenu();
tray.setToolTip("Stoat for Desktop");
tray.setImage(trayIcon);
tray.on("click", () => {
mainWindow.show();
mainWindow.focus();
if (mainWindow.isVisible()) {
mainWindow.hide();
} else {
mainWindow.show();
mainWindow.focus();
}
});
}

View File

@ -5,8 +5,10 @@ import {
Menu,
MenuItem,
app,
desktopCapturer,
ipcMain,
nativeImage,
session,
} from "electron";
import windowIconAsset from "../../assets/desktop/icon.png?asset";
@ -21,7 +23,7 @@ export let mainWindow: BrowserWindow;
export const BUILD_URL = new URL(
app.commandLine.hasSwitch("force-server")
? app.commandLine.getSwitchValue("force-server")
: /*MAIN_WINDOW_VITE_DEV_SERVER_URL ??*/ "https://beta.revolt.chat",
: /*MAIN_WINDOW_VITE_DEV_SERVER_URL ??*/ "https://stoat.chat/app",
);
// internal window state
@ -36,6 +38,10 @@ const windowIcon = nativeImage.createFromDataURL(windowIconAsset);
* Create the main application window
*/
export function createMainWindow() {
// (CLI arg --hidden or config)
const startHidden =
app.commandLine.hasSwitch("hidden") || config.startMinimisedToTray;
// create the window
mainWindow = new BrowserWindow({
minWidth: 300,
@ -45,6 +51,7 @@ export function createMainWindow() {
backgroundColor: "#191919",
frame: !config.customFrame,
icon: windowIcon,
show: !startHidden,
webPreferences: {
// relative to `.vite/build`
preload: join(__dirname, "preload.js"),
@ -57,6 +64,22 @@ export function createMainWindow() {
// hide the options
mainWindow.setMenu(null);
// restore last position if it was moved previously
if (config.windowState.x > 0 || config.windowState.y > 0) {
mainWindow.setPosition(
config.windowState.x ?? 0,
config.windowState.y ?? 0,
);
}
// restore last size if it was resized previously
if (config.windowState.width > 0 && config.windowState.height > 0) {
mainWindow.setSize(
config.windowState.width ?? 1280,
config.windowState.height ?? 720,
);
}
// maximise the window if it was maximised before
if (config.windowState.isMaximised) {
mainWindow.maximize();
@ -80,16 +103,22 @@ export function createMainWindow() {
// keep track of window state
function generateState() {
config.windowState = {
x: mainWindow.getPosition()[0],
y: mainWindow.getPosition()[1],
width: mainWindow.getSize()[0],
height: mainWindow.getSize()[1],
isMaximised: mainWindow.isMaximized(),
};
}
mainWindow.on("maximize", generateState);
mainWindow.on("unmaximize", generateState);
mainWindow.on("moved", generateState);
mainWindow.on("resized", generateState);
// rebind zoom controls to be more sensible
mainWindow.webContents.on("before-input-event", (event, input) => {
if (input.control && input.key === "=") {
if (input.control && (input.key === "=" || input.key === "+")) {
// zoom in (+)
event.preventDefault();
mainWindow.webContents.setZoomLevel(
@ -101,6 +130,16 @@ export function createMainWindow() {
mainWindow.webContents.setZoomLevel(
mainWindow.webContents.getZoomLevel() - 1,
);
} else if (input.control && input.key === "0") {
// reset zoom to default.
event.preventDefault();
mainWindow.webContents.setZoomLevel(0);
} else if (
input.key === "F5" ||
((input.control || input.meta) && input.key.toLowerCase() === "r")
) {
event.preventDefault();
mainWindow.webContents.reload();
}
});
@ -150,6 +189,59 @@ export function createMainWindow() {
}
});
// Create display media request handler
session.defaultSession.setDisplayMediaRequestHandler(
(request, callback) => {
desktopCapturer
.getSources({ types: ["screen", "window"], fetchWindowIcons: true })
.then((sources) => {
// Shortcut for linux wayland.
if (sources.length == 1) {
// TODO: Get audio to work with wayland
// See vencord for an implementation using a virtual microphone.
callback({
video: sources[0],
audio: request.audioRequested ? "loopbackWithMute" : undefined,
});
return;
}
ipcMain.once(
"screenPickerCallback",
(_, idx: number, audio: boolean) => {
if (idx < 0 || idx > sources.length) {
callback({});
} else {
callback({
video: sources[idx],
audio: audio ? "loopbackWithMute" : undefined,
});
}
},
);
mainWindow.webContents.send(
"screenPicker",
sources.map((source, idx) => {
const image = source.appIcon;
if (image) {
if (image.getAspectRatio() > 1) {
image.resize({ width: 256 });
} else {
image.resize({ height: 256 });
}
}
return {
idx: idx,
name: source.name,
isFullScreen: source.id.startsWith("screen"),
image: image?.toDataURL(),
};
}),
);
});
},
{ useSystemPicker: true },
);
// push world events to the window
ipcMain.on("minimise", () => mainWindow.minimize());
ipcMain.on("maximise", () =>

View File

@ -8,10 +8,9 @@ contextBridge.exposeInMainWorld("desktopConfig", {
get: () => config,
set: (config: DesktopConfig) => ipcRenderer.send("config", config),
getAutostart() {
ipcRenderer.send("isAutostart?");
return new Promise((resolve) => ipcRenderer.once("isAutostart", resolve));
return ipcRenderer.invoke("getAutostart") as Promise<boolean>;
},
setAutostart(value: boolean) {
ipcRenderer.send("setAutostart", value);
return ipcRenderer.invoke("setAutostart", value) as Promise<boolean>;
},
});

View File

@ -13,4 +13,23 @@ contextBridge.exposeInMainWorld("native", {
minimise: () => ipcRenderer.send("minimise"),
maximise: () => ipcRenderer.send("maximise"),
close: () => ipcRenderer.send("close"),
setBadgeCount: (count: number) => ipcRenderer.send("setBadgeCount", count),
onceScreenPicker: (
onScreenPick: (
sources: {
idx: number;
name: string;
isFullScreen: boolean;
image?: string;
}[],
) => void,
) => {
const eventName = "screenPicker";
ipcRenderer.removeAllListeners(eventName);
ipcRenderer.once(eventName, (_, sources) => onScreenPick(sources));
},
screenPickerCallback: (idx: number, audio: boolean) =>
ipcRenderer.send("screenPickerCallback", idx, audio),
});