Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
name: test

on:
pull_request:
branches: [master, main]
push:
branches: [master, main]

jobs:
vitest:
name: vitest
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- uses: pnpm/action-setup@v4
with:
version: 10.32.1

- uses: actions/setup-node@v4
with:
node-version: 20
cache: pnpm

- name: Install
run: pnpm install --frozen-lockfile

# The suite runs with the quarantine list in vitest.config.js applied —
# see tests/QUARANTINE.md for what is excluded and why.
- name: Run tests
run: pnpm test:ci
2 changes: 1 addition & 1 deletion PWA_VIDEO_PLAYBACK_GUIDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ Navigate to `chrome://flags/` and enable:

### For PWA Manifest Optimization:

Update your `static/manifest.json`:
Update your `public/manifest.json`:
```json
{
"name": "QryptChat - Quantum-Resistant Messaging",
Expand Down
3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
"build": "next build",
"start": "next start",
"test": "vitest",
"test:ci": "vitest run",
"test:quarantined": "vitest run --config vitest.quarantine.config.js",
"test:ui": "vitest --ui",
"test:coverage": "vitest --coverage",
"lint": "eslint .",
Expand All @@ -40,6 +42,7 @@
"chai": "^6.0.1",
"eslint": "^9.39.2",
"eslint-config-next": "^15.0.0",
"fake-indexeddb": "^6.2.5",
"globals": "^17.7.0",
"jsdom": "^26.1.0",
"mocha": "^11.7.5",
Expand Down
27 changes: 10 additions & 17 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion public/qryptchat.desktop
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ GenericName=Secure Messaging
Comment=Quantum-resistant encrypted messaging app
Categories=Network;Chat;InstantMessaging;
Keywords=chat;messaging;encryption;quantum;secure;
Icon=/home/ettinger/src/qrypt.chat/qryptochat-web/static/qryptchat.png
Icon=qryptchat
Exec=google-chrome --app=https://qrypt.chat
StartupNotify=true
NoDisplay=false
Expand Down
91 changes: 56 additions & 35 deletions scripts/generate-icons.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,10 @@ import sharp from 'sharp';
import { promises as fs } from 'fs';
import path from 'path';

// iOS and PWA icon sizes
// Every icon family referenced by public/manifest.json and src/app/layout.jsx.
// The `android-chrome-*` set is what the manifest actually points at, so it has
// to be regenerated here too — leaving it out meant `pnpm icons:generate`
// silently refreshed everything except the icons Chromium installs with.
const ICON_SIZES = [
{ size: 57, name: 'apple-touch-icon-57x57.png' },
{ size: 60, name: 'apple-touch-icon-60x60.png' },
Expand All @@ -20,14 +23,45 @@ const ICON_SIZES = [
{ size: 144, name: 'apple-touch-icon-144x144.png' },
{ size: 152, name: 'apple-touch-icon-152x152.png' },
{ size: 180, name: 'apple-touch-icon-180x180.png' },
{ size: 36, name: 'icon-36x36.png' },
{ size: 48, name: 'icon-48x48.png' },
{ size: 96, name: 'icon-96x96.png' },
{ size: 192, name: 'icon-192x192.png' },
{ size: 256, name: 'icon-256x256.png' },
{ size: 384, name: 'icon-384x384.png' },
{ size: 512, name: 'icon-512x512.png' }
{ size: 512, name: 'icon-512x512.png' },
{ size: 36, name: 'android-chrome-36x36.png' },
{ size: 48, name: 'android-chrome-48x48.png' },
{ size: 72, name: 'android-chrome-72x72.png' },
{ size: 96, name: 'android-chrome-96x96.png' },
{ size: 144, name: 'android-chrome-144x144.png' },
{ size: 192, name: 'android-chrome-192x192.png' },
{ size: 256, name: 'android-chrome-256x256.png' },
{ size: 384, name: 'android-chrome-384x384.png' },
{ size: 512, name: 'android-chrome-512x512.png' },
{ size: 16, name: 'favicon-16x16.png' },
{ size: 32, name: 'favicon-32x32.png' },
{ size: 48, name: 'favicon-48x48.png' },
{ size: 64, name: 'favicon-64x64.png' },
{ size: 128, name: 'favicon-128x128.png' },
{ size: 194, name: 'favicon-194x194.png' },
{ size: 256, name: 'favicon-256x256.png' },
{ size: 512, name: 'favicon-512x512.png' },
// Windows tiles, referenced from layout.jsx and public/icons/browserconfig.xml.
// These stay transparent: Windows paints msapplication-TileColor behind them.
// 310x150 is the wide tile, so these carry explicit width/height.
{ size: 70, name: 'mstile-70x70.png' },
{ size: 144, name: 'mstile-144x144.png' },
{ size: 150, name: 'mstile-150x150.png' },
{ width: 310, height: 150, name: 'mstile-310x150.png' },
{ size: 310, name: 'mstile-310x310.png' }
];

const SVG_PATH = './static/favicon.svg';
const ICONS_DIR = './static/icons';
// public/ is the only directory Next serves. The generator used to write into
// static/ (the SvelteKit holdover), so regenerated icons never reached the app
// and the two trees drifted apart.
const SVG_PATH = './public/favicon.svg';
const ICONS_DIR = './public/icons';

async function generateIcons() {
try {
Expand All @@ -42,48 +76,35 @@ async function generateIcons() {
console.log(`📖 Read ${SVG_PATH}`);

// Generate each icon size
for (const { size, name } of ICON_SIZES) {
for (const { size, width, height, name } of ICON_SIZES) {
const outputPath = path.join(ICONS_DIR, name);

// Determine if this is a PWA icon that needs solid background
const needsSolidBackground = name.includes('icon-') && (size >= 192);

const w = width ?? size;
const h = height ?? size;

// `background` only paints the letterbox `fit: 'contain'` adds, and
// favicon.svg is square, so for every square icon here it paints nothing.
// The old `needsSolidBackground` branch that set an opaque background for
// PWA icons was therefore a no-op — the committed icons have always had
// transparent pixels. Giving the manifest's maskable 192/512 icons a
// genuinely opaque background needs `.flatten()` plus safe-zone padding,
// which changes how the installed icon looks; that's a deliberate design
// change rather than something to fold into the generator silently.
await sharp(svgBuffer)
.resize(size, size, {
.resize(w, h, {
fit: 'contain',
background: needsSolidBackground
? { r: 255, g: 255, b: 255, alpha: 1 } // White background for PWA icons
: { r: 255, g: 255, b: 255, alpha: 0 } // Transparent for Apple touch icons
background: { r: 255, g: 255, b: 255, alpha: 0 }
})
.png({
quality: 95,
compressionLevel: 9
})
.toFile(outputPath);
console.log(`✅ Generated ${name} (${size}x${size})`);

console.log(`✅ Generated ${name} (${w}x${h})`);
}

// Generate favicon.ico (16x16 and 32x32 combined)
const faviconPath = './static/favicon.ico';
await sharp(svgBuffer)
.resize(32, 32, {
fit: 'contain',
background: { r: 255, g: 255, b: 255, alpha: 0 }
})
.png()
.toFile('./static/favicon-32.png');

await sharp(svgBuffer)
.resize(16, 16, {
fit: 'contain',
background: { r: 255, g: 255, b: 255, alpha: 0 }
})
.png()
.toFile('./static/favicon-16.png');

console.log('✅ Generated additional favicon sizes');

// favicon-16x16 / favicon-32x32 are part of ICON_SIZES above now; the old
// extra pass wrote them to static/favicon-{16,32}.png, a path nothing reads.
console.log('\n🎉 Icon generation complete!');
console.log(`📁 Generated ${ICON_SIZES.length} PNG icons in ${ICONS_DIR}/`);

Expand Down
22 changes: 11 additions & 11 deletions scripts/install-desktop-icons.sh
Original file line number Diff line number Diff line change
Expand Up @@ -66,21 +66,21 @@ echo "✅ Created hicolor theme index file"
echo "📁 Installing icons to $ICON_THEME_DIR..."

# Install proper icon sizes for Linux desktop environments
cp ./static/icons/icon-48x48.png "$ICON_THEME_DIR/48x48/apps/qryptchat.png" 2>/dev/null || echo "⚠️ 48x48 icon not found"
cp ./static/icons/apple-touch-icon-72x72.png "$ICON_THEME_DIR/64x64/apps/qryptchat.png" 2>/dev/null || echo "⚠️ 64x64 icon not found"
cp ./static/icons/icon-96x96.png "$ICON_THEME_DIR/96x96/apps/qryptchat.png" 2>/dev/null || echo "⚠️ 96x96 icon not found"
cp ./static/icons/apple-touch-icon-152x152.png "$ICON_THEME_DIR/128x128/apps/qryptchat.png" 2>/dev/null || echo "⚠️ 128x128 icon not found"
cp ./static/icons/icon-256x256.png "$ICON_THEME_DIR/256x256/apps/qryptchat.png" 2>/dev/null || echo "⚠️ 256x256 icon not found"
cp ./static/icons/icon-512x512.png "$ICON_THEME_DIR/512x512/apps/qryptchat.png" 2>/dev/null || echo "⚠️ 512x512 icon not found"
cp ./public/icons/icon-48x48.png "$ICON_THEME_DIR/48x48/apps/qryptchat.png" 2>/dev/null || echo "⚠️ 48x48 icon not found"
cp ./public/icons/apple-touch-icon-72x72.png "$ICON_THEME_DIR/64x64/apps/qryptchat.png" 2>/dev/null || echo "⚠️ 64x64 icon not found"
cp ./public/icons/icon-96x96.png "$ICON_THEME_DIR/96x96/apps/qryptchat.png" 2>/dev/null || echo "⚠️ 96x96 icon not found"
cp ./public/icons/apple-touch-icon-152x152.png "$ICON_THEME_DIR/128x128/apps/qryptchat.png" 2>/dev/null || echo "⚠️ 128x128 icon not found"
cp ./public/icons/icon-256x256.png "$ICON_THEME_DIR/256x256/apps/qryptchat.png" 2>/dev/null || echo "⚠️ 256x256 icon not found"
cp ./public/icons/icon-512x512.png "$ICON_THEME_DIR/512x512/apps/qryptchat.png" 2>/dev/null || echo "⚠️ 512x512 icon not found"

# Try to copy smaller sizes as fallbacks
if [ -f "./static/favicon-32.png" ]; then
cp ./static/favicon-32.png "$ICON_THEME_DIR/32x32/apps/qryptchat.png"
if [ -f "./public/icons/favicon-32x32.png" ]; then
cp ./public/icons/favicon-32x32.png "$ICON_THEME_DIR/32x32/apps/qryptchat.png"
echo "✅ Installed 32x32 icon"
fi

if [ -f "./static/favicon-16.png" ]; then
cp ./static/favicon-16.png "$ICON_THEME_DIR/16x16/apps/qryptchat.png"
if [ -f "./public/icons/favicon-16x16.png" ]; then
cp ./public/icons/favicon-16x16.png "$ICON_THEME_DIR/16x16/apps/qryptchat.png"
echo "✅ Installed 16x16 icon"
fi

Expand All @@ -89,7 +89,7 @@ echo "✅ Installed QryptChat icons to hicolor icon theme"
# Install desktop file
echo "📋 Installing desktop file to $DESKTOP_DIR..."
mkdir -p "$DESKTOP_DIR"
cp ./static/qryptchat.desktop "$DESKTOP_DIR/" 2>/dev/null || echo "⚠️ Desktop file not found"
cp ./public/qryptchat.desktop "$DESKTOP_DIR/" 2>/dev/null || echo "⚠️ Desktop file not found"

if [ -f "$DESKTOP_DIR/qryptchat.desktop" ]; then
chmod +x "$DESKTOP_DIR/qryptchat.desktop"
Expand Down
4 changes: 0 additions & 4 deletions static/.well-known/security.txt

This file was deleted.

Binary file removed static/banner.png
Binary file not shown.
Binary file removed static/favicon.ico
Binary file not shown.
1 change: 0 additions & 1 deletion static/favicon.svg

This file was deleted.

Binary file removed static/fonts/inter-var.woff2
Binary file not shown.
1 change: 0 additions & 1 deletion static/hero.svg

This file was deleted.

16 changes: 0 additions & 16 deletions static/humans.txt

This file was deleted.

Binary file removed static/icons/android-chrome-144x144.png
Binary file not shown.
Binary file removed static/icons/android-chrome-192x192.png
Binary file not shown.
Binary file removed static/icons/android-chrome-256x256.png
Binary file not shown.
Binary file removed static/icons/android-chrome-36x36.png
Binary file not shown.
Binary file removed static/icons/android-chrome-384x384.png
Binary file not shown.
Binary file removed static/icons/android-chrome-48x48.png
Binary file not shown.
Binary file removed static/icons/android-chrome-512x512.png
Binary file not shown.
Binary file removed static/icons/android-chrome-72x72.png
Binary file not shown.
Binary file removed static/icons/android-chrome-96x96.png
Binary file not shown.
Binary file removed static/icons/apple-touch-icon-114x114.png
Binary file not shown.
Binary file removed static/icons/apple-touch-icon-120x120.png
Binary file not shown.
Binary file removed static/icons/apple-touch-icon-144x144.png
Binary file not shown.
Binary file removed static/icons/apple-touch-icon-152x152.png
Binary file not shown.
Binary file removed static/icons/apple-touch-icon-180x180.png
Binary file not shown.
Binary file removed static/icons/apple-touch-icon-57x57.png
Binary file not shown.
Binary file removed static/icons/apple-touch-icon-60x60.png
Binary file not shown.
Binary file removed static/icons/apple-touch-icon-72x72.png
Binary file not shown.
Binary file removed static/icons/apple-touch-icon-76x76.png
Binary file not shown.
12 changes: 0 additions & 12 deletions static/icons/browserconfig.xml

This file was deleted.

Binary file removed static/icons/favicon-128x128.png
Binary file not shown.
Binary file removed static/icons/favicon-16x16.png
Binary file not shown.
Binary file removed static/icons/favicon-194x194.png
Binary file not shown.
Binary file removed static/icons/favicon-256x256.png
Binary file not shown.
Binary file removed static/icons/favicon-32x32.png
Diff not rendered.
Binary file removed static/icons/favicon-48x48.png
Diff not rendered.
Binary file removed static/icons/favicon-512x512.png
Diff not rendered.
Binary file removed static/icons/favicon-64x64.png
Diff not rendered.
Binary file removed static/icons/icon-192x192.png
Diff not rendered.
Binary file removed static/icons/icon-256x256.png
Diff not rendered.
Binary file removed static/icons/icon-36x36.png
Diff not rendered.
Binary file removed static/icons/icon-384x384.png
Diff not rendered.
Binary file removed static/icons/icon-48x48.png
Diff not rendered.
Binary file removed static/icons/icon-512x512.png
Diff not rendered.
Binary file removed static/icons/icon-96x96.png
Diff not rendered.
Binary file removed static/icons/mstile-144x144.png
Diff not rendered.
Binary file removed static/icons/mstile-150x150.png
Diff not rendered.
Binary file removed static/icons/mstile-310x150.png
Diff not rendered.
Binary file removed static/icons/mstile-310x310.png
Diff not rendered.
Binary file removed static/icons/mstile-70x70.png
Diff not rendered.
1 change: 0 additions & 1 deletion static/icons/safari-pinned-tab.svg
Diff not rendered.
29 changes: 0 additions & 29 deletions static/llms.txt

This file was deleted.

Loading
Loading