Compare commits

..

No commits in common. "main" and "v1.2.0" have entirely different histories.
main ... v1.2.0

22 changed files with 122 additions and 420 deletions

View File

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

View File

@ -1,19 +0,0 @@
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,6 +1,3 @@
# DO NOT EDIT DIRECTLY IN REPOSITORY
# Managed in Terraform templates
name: Release Webhook
on:
@ -15,12 +12,8 @@ jobs:
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" \
RELEASE_URL="https://github.com/${{ github.repository }}/releases/tag/${{ github.event.release.tag_name }}"
curl -X POST "${{ secrets.STOAT_WEBHOOK_UPDATES_URL }}" \
-H "Content-Type: application/json" \
-d "{\"content\": \"$RELEASE_URL\"}"
-d "{\"content\": \"$RELEASE_URL\"}"

View File

@ -1,6 +1,3 @@
# DO NOT EDIT DIRECTLY IN REPOSITORY
# Managed in Terraform templates
name: "Lint PR"
on:
@ -18,6 +15,6 @@ jobs:
permissions:
pull-requests: read
steps:
- uses: amannn/action-semantic-pull-request@48f256284bd46cdaab1048c3721360e808335d50 # v6.1.1
- uses: amannn/action-semantic-pull-request@v6
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

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

View File

@ -1,27 +1,5 @@
# 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)

View File

@ -13,14 +13,6 @@ 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!_

2
assets

@ -1 +1 @@
Subproject commit bd432f2298901a8566a092636eef0c35a3a80fbc
Subproject commit f106946659af67ad4f008588ac51570029b2fd47

View File

@ -1,11 +0,0 @@
[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

@ -1,70 +0,0 @@
<?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,13 +1,16 @@
{ pkgs ? import (fetchTarball {
url = "https://github.com/NixOS/nixpkgs/archive/77ef7a29d276c6d8303aece3444d61118ef71ac2.tar.gz";
sha256 = "0pm4l48jq8plzrrrisimahxqlcpx7qqq9c99hylmf7p3zlc3phsy";
}) {},
{
pkgs ? import <nixpkgs> { },
}:
pkgs.mkShell rec {
buildInputs = with pkgs; [
buildInputs = [
# Tools
pkgs.mise
pkgs.git
pkgs.gh
# Node
pkgs.nodejs
pkgs.nodejs.pkgs.pnpm
# Electron
(pkgs.writeShellScriptBin "electron-nix" ''
@ -26,15 +29,5 @@ 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,15 +58,8 @@ if (!process.env.PLATFORM) {
description: STRINGS.description,
productName: STRINGS.name,
productDescription: STRINGS.description,
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,
runtimeVersion: "21.08",
icon: `${ASSET_DIR}/icon.png`,
categories: ["Network"],
modules: [
// use the latest zypak -- Electron sandboxing for Flatpak
@ -84,30 +77,38 @@ if (!process.env.PLATFORM) {
finishArgs: [
// default arguments found by running
// DEBUG=electron-installer-flatpak* pnpm make
"--socket=fallback-x11",
"--socket=wayland",
"--socket=x11",
"--share=ipc",
"--share=network",
"--device=dri",
"--device=all",
"--socket=pulseaudio",
"--filesystem=home",
"--filesystem=xdg-run/pipewire-0",
"--filesystem=xdg-videos:ro",
"--filesystem=xdg-pictures:ro",
"--filesystem=xdg-run/speech-dispatcher",
"--talk-name=org.freedesktop.ScreenSaver",
"--env=TMPDIR=/var/tmp",
"--share=network",
"--talk-name=org.freedesktop.Notifications",
"--talk-name=org.kde.StatusNotifierWatcher",
"--talk-name=com.canonical.AppMenu.Registrar",
"--talk-name=com.canonical.indicator.application",
// add Unity talk name for badges
"--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({

View File

@ -1,5 +0,0 @@
[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.3.0",
"version": "1.2.0",
"main": ".vite/build/main.js",
"repository": "stoatchat/desktop",
"scripts": {
"start": "electron-forge start -- --no-sandbox",
"start": "electron-forge start",
"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": "^40.8.3",
"electron": "38.1.2",
"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: ^40.8.3
version: 40.8.3
specifier: 38.1.2
version: 38.1.2
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.10.13)
version: 5.4.20(@types/node@24.5.2)
packages:
@ -825,9 +825,6 @@ 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==}
@ -910,7 +907,6 @@ 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==}
@ -1079,9 +1075,6 @@ 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'}
@ -1379,8 +1372,8 @@ packages:
resolution: {integrity: sha512-bO3y10YikuUwUuDUQRM4KfwNkKhnpVO7IPdbsrejwN9/AABJzzTQ4GeHwyzNSrVO+tEH3/Np255a3sVZpZDjvg==}
engines: {node: '>=8.0.0'}
electron@40.8.3:
resolution: {integrity: sha512-MH6LK4xM6VVmmtz0nRE0Fe8l2jTKSYTvH1t0ZfbNLw3o6dlBCVTRqQha6uL8ZQVoMy74JyLguGwK7dU7rCKIhw==}
electron@38.1.2:
resolution: {integrity: sha512-WXUcN3W8h8NTTZViA3KNX0rV2YBU0X0mEUM3ubupXTDY4QtIN7tmiqYVOKSKpR2LckTmBWGuEeY4D6xVoffwKQ==}
engines: {node: '>= 12.20.55'}
hasBin: true
@ -1544,8 +1537,8 @@ packages:
resolution: {integrity: sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==}
engines: {node: '>=6'}
exponential-backoff@3.1.3:
resolution: {integrity: sha512-ZgEeZXj30q+I0EN+CbSSpIyPaJ5HVQD18Z1m+u1FXbAeT94mr1zw50q4q6jiiC447Nl/YTcIYSAftiGqetwXCA==}
exponential-backoff@3.1.2:
resolution: {integrity: sha512-8QxYTVXUkuy7fIIoitQkPwGonB8F3Zj8eEO8Sqg9Zv/bkI7RJAzowee4gr81Hak/dUTpA2Z7VfQgoijjPNlUZA==}
external-editor@3.1.0:
resolution: {integrity: sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==}
@ -1722,12 +1715,12 @@ packages:
glob@7.2.3:
resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==}
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
deprecated: Glob versions prior to v9 are no longer supported
glob@8.1.0:
resolution: {integrity: sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==}
engines: {node: '>=12'}
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
deprecated: Glob versions prior to v9 are no longer supported
global-agent@3.0.0:
resolution: {integrity: sha512-PT6XReJ+D07JvGoxQMkT6qji/jVNfX/h364XHZOWeRzy64sSFr+xJ5OX7LI3b4MPQzdL4H8Y8M0xzPpsVMwA8Q==}
@ -1873,8 +1866,8 @@ packages:
resolution: {integrity: sha512-6xwYfHbajpoF0xLW+iwLkhwgvLoZDfjYfoFNu8ftMoXINzwuymNLd9u/KmwtdT2GbR+/Cz66otEGEVVUHX9QLQ==}
engines: {node: '>=10.13.0'}
ip-address@10.1.0:
resolution: {integrity: sha512-XXADHxXmvT9+CRxhXg56LJovE+bmWnEWB78LB83VZTprKTmaC5QfruXocxzTZ2Kl0DNwKuBdlIhjL8LeY8Sf8Q==}
ip-address@10.0.1:
resolution: {integrity: sha512-NWv9YLW4PoW2B7xtzaS3NCot75m6nK7Icdv0o3lfMceJVRfSoQwqD4wEH5rLwoKJwUiZ/rfpiVBhnaF0FK4HoA==}
engines: {node: '>= 12'}
is-array-buffer@3.0.5:
@ -2192,8 +2185,8 @@ packages:
minimatch@3.1.2:
resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==}
minimatch@5.1.9:
resolution: {integrity: sha512-7o1wEA2RyMP7Iu7GNba9vc0RWWGACJOCZBJX2GJWip0ikV+wcOsgVuY9uE8CPiyQhkGFSlhuSkZPavN7u1c2Fw==}
minimatch@5.1.6:
resolution: {integrity: sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==}
engines: {node: '>=10'}
minimatch@9.0.5:
@ -2211,8 +2204,8 @@ packages:
resolution: {integrity: sha512-LT49Zi2/WMROHYoqGgdlQIZh8mLPZmOrN2NdJjMXxYe4nkN6FUyuPuOAOedNJDrx0IRGg9+4guZewtp8hE6TxA==}
engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0}
minipass-flush@1.0.7:
resolution: {integrity: sha512-TbqTz9cUwWyHS2Dy89P3ocAGUGxKjjLuR9z8w4WUTGAVgEj17/4nhgo2Du56i0Fm3Pm30g4iA8Lcqctc76jCzA==}
minipass-flush@1.0.5:
resolution: {integrity: sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==}
engines: {node: '>= 8'}
minipass-pipeline@1.2.4:
@ -2280,8 +2273,8 @@ packages:
nice-try@1.0.5:
resolution: {integrity: sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==}
node-abi@3.89.0:
resolution: {integrity: sha512-6u9UwL0HlAl21+agMN3YAMXcKByMqwGx+pq+P76vii5f7hTPtKDp08/H9py6DY+cfDw7kQNTGEj/rly3IgbNQA==}
node-abi@3.77.0:
resolution: {integrity: sha512-DSmt0OEcLoK4i3NuscSbGjOf3bqiDEutejqENSplMSFA/gmB8mkED9G4pKWnPl7MDU4rSHebKPHeitpDfyH0cQ==}
engines: {node: '>=10'}
node-addon-api@1.7.2:
@ -2883,7 +2876,6 @@ 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==}
@ -2991,9 +2983,6 @@ 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}
@ -3542,7 +3531,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.3
exponential-backoff: 3.1.2
glob: 8.1.0
graceful-fs: 4.2.11
make-fetch-happen: 10.2.1
@ -3609,7 +3598,7 @@ snapshots:
detect-libc: 2.1.1
fs-extra: 10.1.0
got: 11.8.6
node-abi: 3.89.0
node-abi: 3.77.0
node-api-version: 0.2.1
ora: 5.4.1
read-binary-file-arch: 1.0.6
@ -4114,7 +4103,7 @@ snapshots:
'@types/fs-extra@9.0.13':
dependencies:
'@types/node': 24.10.13
'@types/node': 24.5.2
optional: true
'@types/http-cache-semantics@4.0.4': {}
@ -4125,20 +4114,16 @@ snapshots:
'@types/keyv@3.1.4':
dependencies:
'@types/node': 24.10.13
'@types/node': 24.5.2
'@types/mute-stream@0.0.4':
dependencies:
'@types/node': 24.10.13
'@types/node': 22.18.6
'@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
@ -4153,7 +4138,7 @@ snapshots:
'@types/yauzl@2.10.3':
dependencies:
'@types/node': 24.10.13
'@types/node': 22.18.6
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)':
@ -4431,10 +4416,6 @@ 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
@ -4463,7 +4444,7 @@ snapshots:
lru-cache: 7.18.3
minipass: 3.3.6
minipass-collect: 1.0.2
minipass-flush: 1.0.7
minipass-flush: 1.0.5
minipass-pipeline: 1.2.4
mkdirp: 1.0.4
p-map: 4.0.0
@ -4806,10 +4787,10 @@ snapshots:
- supports-color
optional: true
electron@40.8.3:
electron@38.1.2:
dependencies:
'@electron/get': 2.0.3
'@types/node': 24.10.13
'@types/node': 22.18.6
extract-zip: 2.0.1
transitivePeerDependencies:
- supports-color
@ -5098,7 +5079,7 @@ snapshots:
signal-exit: 3.0.7
strip-eof: 1.0.0
exponential-backoff@3.1.3: {}
exponential-backoff@3.1.2: {}
external-editor@3.1.0:
dependencies:
@ -5334,7 +5315,7 @@ snapshots:
fs.realpath: 1.0.0
inflight: 1.0.6
inherits: 2.0.4
minimatch: 5.1.9
minimatch: 5.1.6
once: 1.4.0
global-agent@3.0.0:
@ -5502,7 +5483,7 @@ snapshots:
interpret@3.1.1: {}
ip-address@10.1.0: {}
ip-address@10.0.1: {}
is-array-buffer@3.0.5:
dependencies:
@ -5753,7 +5734,7 @@ snapshots:
minipass: 3.3.6
minipass-collect: 1.0.2
minipass-fetch: 2.1.2
minipass-flush: 1.0.7
minipass-flush: 1.0.5
minipass-pipeline: 1.2.4
negotiator: 0.6.4
promise-retry: 2.0.1
@ -5810,9 +5791,9 @@ snapshots:
dependencies:
brace-expansion: 1.1.12
minimatch@5.1.9:
minimatch@5.1.6:
dependencies:
brace-expansion: 2.1.0
brace-expansion: 2.0.2
minimatch@9.0.5:
dependencies:
@ -5832,7 +5813,7 @@ snapshots:
optionalDependencies:
encoding: 0.1.13
minipass-flush@1.0.7:
minipass-flush@1.0.5:
dependencies:
minipass: 3.3.6
@ -5885,7 +5866,7 @@ snapshots:
nice-try@1.0.5: {}
node-abi@3.89.0:
node-abi@3.77.0:
dependencies:
semver: 7.7.2
@ -6394,7 +6375,7 @@ snapshots:
socks@2.8.7:
dependencies:
ip-address: 10.1.0
ip-address: 10.0.1
smart-buffer: 4.2.0
source-map-js@1.2.1: {}
@ -6657,8 +6638,6 @@ snapshots:
undici-types@7.12.0: {}
undici-types@7.16.0: {}
unique-filename@2.0.1:
dependencies:
unique-slug: 3.0.0
@ -6700,13 +6679,13 @@ snapshots:
spdx-correct: 3.2.0
spdx-expression-parse: 3.0.1
vite@5.4.20(@types/node@24.10.13):
vite@5.4.20(@types/node@24.5.2):
dependencies:
esbuild: 0.21.5
postcss: 8.5.6
rollup: 4.52.2
optionalDependencies:
'@types/node': 24.10.13
'@types/node': 24.5.2
fsevents: 2.3.3
wcwidth@1.0.1:

View File

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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 702 KiB

View File

@ -1,6 +1,6 @@
import { IUpdateInfo, updateElectronApp } from "update-electron-app";
import { updateElectronApp } from "update-electron-app";
import { BrowserWindow, Notification, app, shell } from "electron";
import { BrowserWindow, app, shell } from "electron";
import started from "electron-squirrel-startup";
import { autoLaunch } from "./native/autoLaunch";
@ -24,33 +24,21 @@ 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({ onNotifyUser });
updateElectronApp();
// 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

@ -16,9 +16,6 @@ const schema = {
minimiseToTray: {
type: "boolean",
} as JSONSchema.Boolean,
startMinimisedToTray: {
type: "boolean",
} as JSONSchema.Boolean,
spellchecker: {
type: "boolean",
} as JSONSchema.Boolean,
@ -32,16 +29,16 @@ const schema = {
type: "object",
properties: {
x: {
type: "number",
type: 'number'
} as JSONSchema.Number,
y: {
type: "number",
type: 'number'
} as JSONSchema.Number,
width: {
type: "number",
type: 'number'
} as JSONSchema.Number,
height: {
type: "number",
type: 'number'
} as JSONSchema.Number,
isMaximised: {
type: "boolean",
@ -56,7 +53,6 @@ const store = new Store({
firstLaunch: true,
customFrame: true,
minimiseToTray: true,
startMinimisedToTray: false,
spellchecker: true,
hardwareAcceleration: true,
discordRpc: true,
@ -79,7 +75,6 @@ class Config {
firstLaunch: this.firstLaunch,
customFrame: this.customFrame,
minimiseToTray: this.minimiseToTray,
startMinimisedToTray: this.startMinimisedToTray,
spellchecker: this.spellchecker,
hardwareAcceleration: this.hardwareAcceleration,
discordRpc: this.discordRpc,
@ -128,21 +123,6 @@ 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

@ -1,7 +1,6 @@
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";
@ -11,16 +10,17 @@ let tray: Tray = null;
// 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);
}
const image = nativeImage.createFromDataURL(trayIconAsset);
const resized = image.resize({ width: 20, height: 20 });
// Mark as template image so it adapts to dark/light mode
resized.setTemplateImage(true);
return resized;
}
// trayIcon.setTemplateImage(true);
export function initTray() {
const trayIcon = createTrayIcon();
tray = new Tray(trayIcon);
@ -28,12 +28,8 @@ export function initTray() {
tray.setToolTip("Stoat for Desktop");
tray.setImage(trayIcon);
tray.on("click", () => {
if (mainWindow.isVisible()) {
mainWindow.hide();
} else {
mainWindow.show();
mainWindow.focus();
}
mainWindow.show();
mainWindow.focus();
});
}

View File

@ -5,10 +5,8 @@ import {
Menu,
MenuItem,
app,
desktopCapturer,
ipcMain,
nativeImage,
session,
} from "electron";
import windowIconAsset from "../../assets/desktop/icon.png?asset";
@ -23,7 +21,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://stoat.chat/app",
: /*MAIN_WINDOW_VITE_DEV_SERVER_URL ??*/ "https://beta.revolt.chat",
);
// internal window state
@ -38,10 +36,6 @@ 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,
@ -51,7 +45,6 @@ export function createMainWindow() {
backgroundColor: "#191919",
frame: !config.customFrame,
icon: windowIcon,
show: !startHidden,
webPreferences: {
// relative to `.vite/build`
preload: join(__dirname, "preload.js"),
@ -64,27 +57,21 @@ 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();
}
// 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);
}
// load the entrypoint
mainWindow.loadURL(BUILD_URL.toString());
@ -118,7 +105,7 @@ export function createMainWindow() {
// rebind zoom controls to be more sensible
mainWindow.webContents.on("before-input-event", (event, input) => {
if (input.control && (input.key === "=" || input.key === "+")) {
if (input.control && input.key === "=") {
// zoom in (+)
event.preventDefault();
mainWindow.webContents.setZoomLevel(
@ -130,16 +117,6 @@ 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();
}
});
@ -189,59 +166,6 @@ 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

@ -15,21 +15,4 @@ contextBridge.exposeInMainWorld("native", {
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),
});