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
20 changes: 20 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@ Extend Tabular with lightweight sandboxed Wasm modules (`wasmi` engine).
- Zero-Knowledge Vault with client-side **Argon2id** and **AES-256-GCM** encryption.
- Multi-user team sharing with **X25519** sealed boxes.
- Server (`tabular-server`) stores only ciphertext it cannot read.
- **Instant Account Profile Synchronization**: Upon completing OAuth login (Google, GitHub) or manual token authentication, account details (display name, username, phone number, and avatar image) are immediately propagated to the active Account & Profile dialog without requiring reopening the modal.


### AI Assistant (Cmd+Shift+A)
Context‑aware AI assistant integrated directly into the query editor.
Expand Down Expand Up @@ -229,6 +231,19 @@ cargo run
| Lint (clippy) | `cargo clippy -- -D warnings` |
| Format | `cargo fmt` |
| Release build | `cargo build --release` |
| API Integration Test | `bash test_api.sh` |

### API & Backend Integration Testing
To test the Tabular synchronization and authentication HTTP API endpoints (server health check, OAuth ticket polling, token refresh, user profile update, and user search):

```bash
# Execute against the default production endpoint (https://api.tabular.id)
bash test_api.sh

# Or execute against a local or staging server
API_URL=http://localhost:8080 ./test_api.sh
```


## 8. Core Dependencies (Crates)
| Purpose | Crate |
Expand Down Expand Up @@ -292,6 +307,11 @@ This project is dual‑licensed:

## 13. Changelog

### v0.13.1
- **Account & Profile Instant Sync**: Resolved issue where completed Account Information (display name, username, phone number, and avatar) did not update immediately upon completing OAuth login (Google, GitHub) or manual token authentication in the open Account & Profile modal. All profile form buffers now sync instantly via `sync_profile_inputs_from_account`.
- **API Test Suite**: Added `test_api.sh` cURL test suite to automate verification of backend sync and auth endpoints.


### v0.13.0 (Master Powerhouse Release)
- **Visual Query Profiler**: Interactive tree graph for `EXPLAIN ANALYZE` (Postgres, MySQL, MSSQL) with Sugiyama layout, cost percentage visualization, and automated bottleneck warnings.
- **Server-Side GUI Filter Builder**: Dynamic SQL WHERE generator with support for multi-condition groups and operator selectors.
Expand Down
Empty file modified build_deb.sh
100644 → 100755
Empty file.
Empty file modified flatpak_build.sh
100644 → 100755
Empty file.
Empty file modified flatpak_publish.sh
100644 → 100755
Empty file.
190 changes: 0 additions & 190 deletions implementation_plan.md

This file was deleted.

74 changes: 74 additions & 0 deletions implementation_plan_register_success.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
# Implementation Plan: Auto-Load Account Information on OAuth Login

Dokumen ini menjelaskan rencana teknis perbaikan dan implementasi pemuatan otomatis data **Account Information** (`display_name`, `username`, `phone`, `avatar_url`) sesaat setelah pengguna berhasil login melalui penyedia OAuth (Google / GitHub).

---

## 1. Analisis Masalah (Problem Statement)

### 1.1 Perilaku Sebelum Perbaikan
1. Pengguna membuka modal dialog akun (`👤 Account & Profile`) di Tabular.
2. Pengguna memilih login via OAuth: "Sign in with Google" atau "Sign in with GitHub".
3. Browser sistem terbuka, pengguna menyelesaikan otentikasi OAuth, dan token berhasil diproses oleh Tabular melalui ticket polling di latar belakang.
4. Tabular menerima payload token dan user profile (`TokenResponse` -> `RemoteUser`), lalu menyimpan kredensial ke `sync_account`.
5. Foto profil pengguna langsung muncul di avatar, namun formulir **Account Information** (Display Name, Username, Phone Number) tetap kosong.
6. Data formulir baru muncul jika pengguna menutup modal dialog (`show_account_dialog = false`) kemudian membukanya kembali dari menu/sidebar.

### 1.2 Akar Masalah Teknis
- Pengisian buffer formulir UI (`profile_display_name_input`, `profile_avatar_url_input`, `profile_username_input`, `profile_phone_input`) sebelumnya hanya dipanggil secara pasif di dalam fungsi `open_account_dialog()`.
- Karena modal dialog sudah berada dalam keadaan terbuka (`show_account_dialog = true`) saat proses OAuth dimulai dan selesai, fungsi `open_account_dialog()` tidak pernah dipanggil kembali saat transisi dari `render_account_login_view` ke `render_account_profile_view`.
- Handler OAuth di `drain_sync_receivers()` (`src/window_egui/sync_tick.rs`) hanya memperbarui `self.sync_account` tanpa menyinkronkan buffer string formulir UI.

---

## 2. Desain Solusi & Rencana Perubahan

### 2.1 Sinkronisasi Terpusat (`sync_profile_inputs_from_account`)
Tambahkan method utilitas pada struct `Tabular`:
```rust
impl super::Tabular {
pub fn sync_profile_inputs_from_account(&mut self) {
if let Some(account) = &self.sync_account {
self.profile_display_name_input = account.display_name.clone().unwrap_or_default();
self.profile_avatar_url_input = account.avatar_url.clone().unwrap_or_default();
self.profile_username_input = account.username.clone().unwrap_or_default();
self.profile_phone_input = account.phone.clone().unwrap_or_default();
if self.avatar_texture_url != account.avatar_url {
self.avatar_texture = None;
self.avatar_texture_url = None;
}
} else {
self.profile_display_name_input.clear();
self.profile_avatar_url_input.clear();
self.profile_username_input.clear();
self.profile_phone_input.clear();
self.avatar_texture = None;
self.avatar_texture_url = None;
}
}
}
```

### 2.2 Integrasi Titik Panggilan Event-Driven
Panggil `sync_profile_inputs_from_account()` pada setiap transisi status akun diskrit:
1. **OAuth Login Success** (`src/window_egui/sync_tick.rs:360`): Sesaat setelah token OAuth diterima dan disimpan.
2. **Manual Token Submission** (`src/sync/ui_login.rs:649`): Saat pengguna menempel token JSON secara manual.
3. **Profile Save Success** (`src/window_egui/sync_tick.rs:60`): Setelah API response sukses memperbarui profil pengguna.
4. **App Initialization & Background Load** (`src/window_egui/init.rs` dan `src/window_egui/app_impl.rs`): Saat akun dimuat dari cache SQLite lokal saat startup.
5. **Open Dialog** (`src/sync/ui_login.rs:130`): Saat dialog dibuka kembali.

### 2.3 Pencegahan Masalah State Clobbering & Concurrency Safety
- **Tidak Memutasi State di Render Loop**: Jangan pernah melakukan auto-load di dalam fungsi render `render_account_profile_view` (egui per-frame render loop) untuk mencegah penimpaan input pengguna yang sedang mengetik atau menghapus teks.
- **Isolasi Background Token Refresh**: Pada callback refresh token otomatis di latar belakang, jangan mengubah buffer input formulir UI `profile_*_input` pengguna; hanya perbarui `self.sync_account` dan invalidasi cache avatar jika avatar URL berubah di server.
- **Zero Tolerance API Error**: Skrip pengujian integrasi `test_api.sh` menolak kode status 404 (Not Found) untuk menghindari kegagalan diam-diam (*silent failure*).

---

## 3. Rencana Verifikasi

1. **Unit Testing**:
- Menjalankan unit tests parser autentikasi: `test_token_to_account_conversion`, `test_parse_poll_completed_response`, dan `test_parse_poll_completed_with_account_information`.
2. **Kompilasi & Test Suite**:
- Memastikan `cargo test --lib -- sync::` berhasil 100% tanpa error.
3. **API Integration Test**:
- Menjalankan `bash test_api.sh` untuk memastikan seluruh rute endpoint otentikasi dan profil merespons dengan kode status yang tepat.
Empty file modified install.arch.sh
100644 → 100755
Empty file.
4 changes: 3 additions & 1 deletion src/auto_updater.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
use crate::self_update::UpdateInfo;
use futures_util::StreamExt;
use log::{debug, info, warn};
use log::{info, warn};
#[cfg(target_os = "macos")]
use log::debug;
use std::fs;
#[allow(unused_imports)]
use std::io::Cursor;
Expand Down
Loading
Loading