Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
ac90841
feat: Implement Telegram-style full emoji picker for message reactions
mx57 Jul 18, 2026
97d1d5e
Merge pull request #1 from mx57/feat/telegram-emoji-reactions-6767133…
mx57 Jul 18, 2026
c00f231
fix(android): generate test keystore in CI so release APK builds with…
Jul 19, 2026
45b1232
Merge pull request #2 from mx57/fix/android-test-keystore
mx57 Jul 19, 2026
048b6dd
feat: Telegram-style full emoji picker with toggle reactions
Jul 19, 2026
6578bcd
Merge pull request #3 from mx57/feat/telegram-emoji-reactions
mx57 Jul 19, 2026
ee5dff7
test: add comprehensive test suite for fileIcons utilities
mx57 Jul 26, 2026
33c017b
Merge pull request #4 from mx57/add-file-icons-tests-1389886814668340…
mx57 Jul 26, 2026
1976f8b
test: add tests for clipboard utility
mx57 Jul 26, 2026
7cd5cf8
Merge pull request #5 from mx57/add-clipboard-tests-8449580473609453391
mx57 Jul 26, 2026
a008b10
feat(ux): Add aria-label to image zoom buttons
mx57 Jul 26, 2026
063d4c9
Merge pull request #6 from mx57/palette-ux-image-zoom-aria-label-1059…
mx57 Jul 26, 2026
695a014
fix(ui): add type="button" and translate aria labels in context menus
mx57 Jul 27, 2026
584faa4
Merge pull request #7 from mx57/palette-context-menu-a11y-35943121949…
mx57 Jul 27, 2026
9763a30
fix(ui): use $state for pickerEl binding in ContextMenu to fix reacti…
mx57 Jul 28, 2026
1aee0b6
Merge pull request #8 from mx57/fix/svelte-5-reactive-element-binding…
mx57 Jul 29, 2026
d8c9f6e
🎨 Palette: Add ARIA roles and visible focus states to Context Menus
mx57 Jul 29, 2026
776f0a0
Merge pull request #9 from mx57/palette-a11y-context-menus-5219223638…
mx57 Jul 29, 2026
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
10 changes: 10 additions & 0 deletions .Jules/palette.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
## 2026-07-26 - Added missing ARIA label to image viewer buttons
**Learning:** Image preview buttons (cursor-zoom-in) in message bubbles wrapped images that had `alt` text, but the buttons themselves lacked accessible names, making their function (zooming/viewing full screen) unclear to screen readers.
**Action:** Add descriptive `aria-label` attributes to all interactive elements that only contain images/icons, even if the images have `alt` text.

## 2026-07-28 - Reactive DOM Bindings in Svelte 5
**Learning:** In Svelte 5, variables bound to DOM elements via `bind:this` must be explicitly declared as reactive using the `$state` rune (e.g., `let el = $state<HTMLElement | null>(null)`) if they are read inside `$effect` blocks. Otherwise, Svelte will not correctly trigger updates when the DOM element is attached, leading to silent failures in event listeners and broken interactions.
**Action:** Always use `$state` for `bind:this` references in Svelte 5 when the component logic relies on tracking the element's lifecycle or properties reactively.
## 2024-05-18 - Semantic Roles & Focus States in Dynamically Rendered Context Menus
**Learning:** Dynamically portaled, absolute-positioned context menus often lack essential ARIA roles (e.g., `role="menu"` on the container and `role="menuitem"` on the buttons). Furthermore, keyboard users lose track of focus without explicitly defined `focus-visible` styling (typically mirroring hover states) and removing the default outline using `focus-visible:outline-none` can provide a much cleaner UX for those using keyboard navigation compared to standard browser outlines.
**Action:** When creating or editing context menus, dropdowns, or popovers, ensure the container has `role="menu"` and items have `role="menuitem"`. Always add explicit `focus-visible` classes matching the `hover` states to guarantee visibility and polish for keyboard users.
28 changes: 20 additions & 8 deletions .github/workflows/android-apk.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,14 @@ jobs:
permissions:
contents: write # needed to upload assets to the release
env:
# Gradle signing config expects these
# Gradle signing config expects these.
# TEST build: a self-signed keystore is generated on the fly below,
# so no repository secrets are required to produce a signed APK.
# Replace this block with real secrets for a production release.
RELEASE_STORE_FILE: ../release.keystore
RELEASE_STORE_PASSWORD: ${{ secrets.RELEASE_STORE_PASSWORD }}
RELEASE_KEY_ALIAS: ${{ secrets.RELEASE_KEY_ALIAS }}
RELEASE_KEY_PASSWORD: ${{ secrets.RELEASE_KEY_PASSWORD }}
RELEASE_STORE_PASSWORD: androidtest
RELEASE_KEY_ALIAS: nospeaktest
RELEASE_KEY_PASSWORD: androidtest
steps:
- name: Checkout repository
uses: actions/checkout@v4
Expand Down Expand Up @@ -64,12 +67,21 @@ jobs:
echo "buildscript { repositories { google(); mavenCentral() } dependencies { classpath 'com.android.tools.build:gradle:8.13.0' } } apply plugin: 'com.android.library' android { namespace \"capacitor.android.plugins\" compileSdk 36 defaultConfig { minSdkVersion 24 targetSdkVersion 36 } }" > android/capacitor-cordova-android-plugins/build.gradle
echo '<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="capacitor.android.plugins"/>' > android/capacitor-cordova-android-plugins/src/main/AndroidManifest.xml
fi
- name: Restore release keystore from secret
- name: Generate test (self-signed) release keystore
working-directory: android/app
run: |
echo "$ANDROID_KEYSTORE_BASE64" | base64 -d > "$RELEASE_STORE_FILE"
env:
ANDROID_KEYSTORE_BASE64: ${{ secrets.ANDROID_KEYSTORE_BASE64 }}
# TEST build only: generate a throwaway self-signed keystore so the
# release APK can be signed without any repository secrets.
# For a real release, delete this step and restore the
# ANDROID_KEYSTORE_BASE64 secret + RELEASE_* secrets instead.
keytool -genkeypair -v \
-keystore "$RELEASE_STORE_FILE" \
-keyalg RSA -keysize 2048 -validity 10000 \
-alias "$RELEASE_KEY_ALIAS" \
-storepass "$RELEASE_STORE_PASSWORD" \
-keypass "$RELEASE_KEY_PASSWORD" \
-dname "CN=nospeak-test, OU=test, O=nospeak, L=test, ST=test, C=US"
ls -la "$RELEASE_STORE_FILE"
- name: Make Gradle wrapper executable
run: chmod +x android/gradlew
- name: Build signed release APK
Expand Down
31 changes: 31 additions & 0 deletions _push_dispatch.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import os, urllib.request, json, subprocess

with open("/root/workspace/nospeak/.ghtoken") as f:
tok = f.read().strip()

req = urllib.request.Request("https://api.github.com/user",
headers={"Authorization": f"Bearer {tok}", "Accept": "application/vnd.github+json"})
with urllib.request.urlopen(req) as r:
print("login:", json.load(r).get("login"))

user = "x-access-token"
host = "github.com"
owner = "mx57"
repo = "nospeak"
remote = f"https://{user}:{tok}@{host}/{owner}/{repo}.git"

res = subprocess.run(["git", "-c", "credential.helper=", "push", remote, "fix/android-test-keystore"],
capture_output=True, text=True, cwd="/root/workspace/nospeak")
print("push RC:", res.returncode)
print("OUT:", res.stdout[-400:], "ERR:", res.stderr[-400:])

url = f"https://api.github.com/repos/{owner}/{repo}/actions/workflows/android-apk.yaml/dispatches"
payload = {"ref": "fix/android-test-keystore", "inputs": {}}
dreq = urllib.request.Request(url, data=json.dumps(payload).encode(),
headers={"Authorization": f"Bearer {tok}", "Accept": "application/vnd.github+json",
"Content-Type": "application/json"}, method="POST")
try:
with urllib.request.urlopen(dreq) as r:
print("dispatch status:", r.status)
except urllib.error.HTTPError as e:
print("dispatch HTTP", e.code, e.read().decode()[:200])
11 changes: 9 additions & 2 deletions package-lock.json

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

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "web",
"private": true,
"version": "1.1.3",
"version": "1.1.4",
"versionCode": 1010030,
"type": "module",
"scripts": {
Expand Down Expand Up @@ -54,6 +54,7 @@
"blurhash": "^2.0.5",
"cropperjs": "^2.1.0",
"dexie": "^4.2.1",
"emoji-picker-element": "^1.29.1",
"jsqr": "^1.4.0",
"leaflet": "^1.9.4",
"minidenticons": "^4.2.1",
Expand Down
Loading