Compare commits
2 Commits
dc7678d184
...
v0.0.1
| Author | SHA1 | Date | |
|---|---|---|---|
| b93ca7dcb6 | |||
| fb3bc6e93a |
83
.gitea/workflows/release.yml
Normal file
83
.gitea/workflows/release.yml
Normal file
@@ -0,0 +1,83 @@
|
||||
name: release
|
||||
|
||||
on:
|
||||
push:
|
||||
tags: ["v*"]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-22.04
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20
|
||||
|
||||
- uses: dtolnay/rust-toolchain@stable
|
||||
with:
|
||||
targets: aarch64-linux-android,armv7-linux-androideabi,i686-linux-android,x86_64-linux-android
|
||||
|
||||
- uses: actions/setup-java@v4
|
||||
with:
|
||||
distribution: temurin
|
||||
java-version: 17
|
||||
|
||||
- uses: android-actions/setup-android@v3
|
||||
|
||||
- uses: nttld/setup-ndk@v1
|
||||
id: ndk
|
||||
with:
|
||||
ndk-version: r26d
|
||||
|
||||
- name: System dependencies
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y jq libgtk-3-dev libwebkit2gtk-4.1-dev \
|
||||
libsoup-3.0-dev libayatana-appindicator3-dev librsvg2-dev
|
||||
|
||||
- run: npm ci
|
||||
|
||||
# Desktop: deb + rpm + AppImage (bundle.targets = "all")
|
||||
- name: Build Linux desktop
|
||||
run: npm run tauri build
|
||||
|
||||
- name: Build Android APK
|
||||
env:
|
||||
NDK_HOME: ${{ steps.ndk.outputs.ndk-path }}
|
||||
run: |
|
||||
npm run tauri android init
|
||||
npm run tauri android build -- --apk
|
||||
|
||||
# ponytail: sign the finished APK with apksigner instead of patching
|
||||
# gen/android/app/build.gradle.kts — keeps gen/ throwaway, no committed generated code.
|
||||
- name: Sign APK
|
||||
env:
|
||||
KEYSTORE_B64: ${{ secrets.ANDROID_KEYSTORE }}
|
||||
KS_PASS: ${{ secrets.ANDROID_KEYSTORE_PASSWORD }}
|
||||
run: |
|
||||
echo "$KEYSTORE_B64" | base64 -d > /tmp/ks.jks
|
||||
BT="$ANDROID_HOME/build-tools/$(ls "$ANDROID_HOME/build-tools" | sort -V | tail -1)"
|
||||
IN=src-tauri/gen/android/app/build/outputs/apk/universal/release/app-universal-release-unsigned.apk
|
||||
"$BT/zipalign" -p -f 4 "$IN" /tmp/aligned.apk
|
||||
"$BT/apksigner" sign --ks /tmp/ks.jks --ks-pass "env:KS_PASS" \
|
||||
--out "rustification-${GITHUB_REF_NAME}.apk" /tmp/aligned.apk
|
||||
|
||||
- name: Publish release
|
||||
env:
|
||||
TOKEN: ${{ secrets.GITEA_TOKEN }}
|
||||
API: ${{ github.server_url }}/api/v1/repos/${{ github.repository }}
|
||||
run: |
|
||||
set -eu
|
||||
ID=$(curl -sSf -X POST "$API/releases" \
|
||||
-H "Authorization: token $TOKEN" -H "Content-Type: application/json" \
|
||||
-d "{\"tag_name\":\"${GITHUB_REF_NAME}\",\"name\":\"${GITHUB_REF_NAME}\"}" | jq -r .id)
|
||||
for f in src-tauri/target/release/bundle/deb/*.deb \
|
||||
src-tauri/target/release/bundle/rpm/*.rpm \
|
||||
src-tauri/target/release/bundle/appimage/*.AppImage \
|
||||
rustification-${GITHUB_REF_NAME}.apk; do
|
||||
[ -f "$f" ] || continue
|
||||
curl -sSf -X POST "$API/releases/$ID/assets?name=$(basename "$f")" \
|
||||
-H "Authorization: token $TOKEN" -F "attachment=@$f"
|
||||
done
|
||||
123
README.md
Normal file
123
README.md
Normal file
@@ -0,0 +1,123 @@
|
||||
# rustification-client
|
||||
|
||||
Desktop chat client for Rustification. Built with Tauri v2 (Rust backend) and React + TypeScript (frontend).
|
||||
|
||||
## Tech stack
|
||||
|
||||
| Layer | Technology |
|
||||
|-------|-----------|
|
||||
| Desktop shell | [Tauri](https://tauri.app) v2 |
|
||||
| Frontend | React 18 + TypeScript, Vite |
|
||||
| HTTP | reqwest (Rust) via Tauri commands |
|
||||
| Persistence | tauri-plugin-store (JWT token, user ID) |
|
||||
| Build (Linux) | nix-shell |
|
||||
|
||||
## Features
|
||||
|
||||
- **Login / Register** — authenticates against the rustification-server, stores JWT via tauri-plugin-store
|
||||
- **Workspace list** — browse workspaces the current user belongs to
|
||||
- **Chat page** — conversation list, message history, and real-time polling for new messages
|
||||
- **Message input** — send messages to any conversation
|
||||
- **Member panel** — view conversation members
|
||||
- **Settings page** — user preferences
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- [Rust](https://rustup.rs/) + Cargo
|
||||
- [Node.js](https://nodejs.org/) 18+ and npm
|
||||
- Tauri v2 system dependencies (see below)
|
||||
- A running [rustification-server](../rustification-server)
|
||||
|
||||
### System dependencies (Linux)
|
||||
|
||||
The project ships a `shell.nix`. If you use Nix, enter the dev shell first:
|
||||
|
||||
```bash
|
||||
nix-shell
|
||||
```
|
||||
|
||||
This provides: `cargo`, `rustc`, `pkg-config`, `glib`, `gtk3`, `webkitgtk_4_1`, `libsoup_3`, `openssl`, `librsvg`.
|
||||
|
||||
Without Nix, install the equivalent packages via your system package manager. On Debian/Ubuntu:
|
||||
|
||||
```bash
|
||||
sudo apt install libgtk-3-dev libwebkit2gtk-4.1-dev libsoup-3.0-dev \
|
||||
libayatana-appindicator3-dev librsvg2-dev
|
||||
```
|
||||
|
||||
## Getting started
|
||||
|
||||
```bash
|
||||
# Install frontend dependencies
|
||||
npm install
|
||||
|
||||
# Start in development mode (hot-reload frontend + Tauri window)
|
||||
# Must be run inside nix-shell on NixOS / Nix systems
|
||||
npm run tauri dev
|
||||
```
|
||||
|
||||
The client defaults to `http://localhost:3000/api/v1` as the server base URL (configurable at runtime via Settings).
|
||||
|
||||
## Build
|
||||
|
||||
```bash
|
||||
# Must be run inside nix-shell on NixOS / Nix systems
|
||||
npm run tauri build
|
||||
```
|
||||
|
||||
Output bundles (`.deb`, `.AppImage`, etc.) are written to `src-tauri/target/release/bundle/`.
|
||||
|
||||
## Project structure
|
||||
|
||||
```
|
||||
src/ # React frontend
|
||||
├── main.tsx # Entry point
|
||||
├── App.tsx # Router + AuthContext provider
|
||||
├── theme.ts # MUI / global theme
|
||||
├── styles.css
|
||||
├── contexts/
|
||||
│ └── AuthContext.tsx # Auth state (token, user ID, login/logout)
|
||||
├── pages/
|
||||
│ ├── LoginPage.tsx
|
||||
│ ├── WorkspacePage.tsx
|
||||
│ ├── ChatPage.tsx
|
||||
│ └── SettingsPage.tsx
|
||||
└── components/
|
||||
├── ConversationList.tsx
|
||||
├── MessageList.tsx
|
||||
├── MessageInput.tsx
|
||||
├── MemberPanel.tsx
|
||||
└── Toast.tsx
|
||||
|
||||
src-tauri/ # Tauri Rust backend
|
||||
├── Cargo.toml
|
||||
└── src/
|
||||
├── lib.rs # Tauri builder, plugin + command registration
|
||||
├── main.rs
|
||||
├── state.rs # AppState: reqwest client, token, base URL
|
||||
├── models.rs # Shared response types
|
||||
└── commands/
|
||||
├── user.rs # login, register, refresh_session, logout
|
||||
├── workspace.rs # list_workspaces
|
||||
├── conversation.rs # list_conversations
|
||||
└── message.rs # list_messages, send_message
|
||||
```
|
||||
|
||||
## Tauri commands
|
||||
|
||||
The frontend calls these via `invoke()`:
|
||||
|
||||
| Command | Description |
|
||||
|---------|-------------|
|
||||
| `login` | Authenticates and stores JWT + user ID |
|
||||
| `register` | Registers a new account |
|
||||
| `refresh_session` | Refreshes the JWT using the stored refresh token |
|
||||
| `logout` | Clears stored credentials |
|
||||
| `list_workspaces` | Returns workspaces for the current user |
|
||||
| `list_conversations` | Returns conversations for a workspace |
|
||||
| `list_messages` | Returns messages for a conversation |
|
||||
| `send_message` | Posts a new message |
|
||||
|
||||
## Server connection
|
||||
|
||||
The default base URL is `http://localhost:3000/api/v1`. To point the client at a different server, update the URL in Settings — it is persisted in the Tauri store across sessions.
|
||||
Reference in New Issue
Block a user