768 Commits

Author SHA1 Message Date
Greg Shuflin f5267fea92 Fix cli help description
Build Debug APK / build (push) Failing after 13s
2026-05-19 03:31:07 -07:00
Greg Shuflin 7b68460061 Update test key 2026-05-19 03:31:07 -07:00
Greg Shuflin 6a3ddd58d4 GUI - music player interface improvements
Build Debug APK / build (push) Failing after 13s
2026-05-19 01:03:17 -07:00
Greg Shuflin 8feb489b29 GUI - loading screen when importing documents
Build Debug APK / build (push) Failing after 4m33s
2026-05-18 22:35:57 -07:00
Greg Shuflin 899f352ded FIx ensemble integration test
Build Debug APK / build (push) Failing after 13s
2026-05-17 02:40:21 -07:00
Greg Shuflin 329e1a7152 Fix p2p integration test 2026-05-17 01:09:35 -07:00
Greg Shuflin 83cc032f1f gui: pass Arc<Store> singleton to all setup callbacks instead of recreating stores
Build Debug APK / build (push) Failing after 13s
Replace per-callback DocumentStore::new(db_path) calls with a program-wide
Arc<Store> created once at startup. All module setup functions now accept
Arc<Store> and clone the specific sub-stores they need. Add #[derive(Clone)]
to all store types (each holds only PathBuf or Arc<RwLock<...>>). Also update
theme::spawn_system_theme_watcher to take SettingsStore directly.
2026-05-16 22:47:15 -07:00
Greg Shuflin e5e3568dc4 gui: move document and podcast list loading off the UI thread
on_load_documents, on_load_document_detail, and on_load_podcasts were
running DB queries synchronously on the Slint event loop, causing a
visible frame drop when switching to those screens.

Each callback now sets a loading flag immediately on the UI thread,
spawns a worker thread to do the DB work, then pushes results back via
upgrade_in_event_loop. DocumentItemDisplay (which holds a Rc-based
ModelRc) is bridged across the thread boundary using a new RawItemDisplay
intermediate type that carries plain String + Vec fields.
2026-05-16 22:22:14 -07:00
Greg Shuflin d807e795f6 Some logging adjustments 2026-05-16 21:34:31 -07:00
Greg Shuflin bfbf470b55 gui: poll OS theme while System mode is selected
Build Debug APK / build (push) Failing after 14s
Re-apply dark/light palette when the desktop color scheme changes,
so System mode stays in sync without restarting the app.
2026-05-16 01:59:11 -07:00
Greg Shuflin 3de18d12ef gui: use muted primary fills for buttons in dark mode
Separate btn-primary-* tokens from accent md-primary so filled controls
use a darker purple (#4f378b) instead of light lavender on dark surfaces.
2026-05-16 01:57:47 -07:00
Greg Shuflin e5d21bd079 GUI - add light/dark mode 2026-05-16 01:46:47 -07:00
Greg Shuflin 2997d099d1 cli: docs show with per-node blob and artifact presence
Build Debug APK / build (push) Failing after 13s
Extract artifact_presence_for_node, blob_presence_for_node, build_peer_name_lookup,
and peer_display_name into lib::node_status so the logic is shared between GUI and CLI.

Update gui-app/src/document.rs to import from node_status instead of defining locally.

Handle docs show directly in the CLI (bypassing the daemon) to get full store access.
cmd_docs_show prints document header, node presence, properties, blobs with per-node
status rows (● Present / ◐ Ref / ○ Absent / ✗ Removed), and artifacts likewise.
2026-05-15 19:19:19 -07:00
Greg Shuflin 43593f3910 GUI document tweaks
Build Debug APK / build (push) Failing after 5m26s
2026-05-15 04:19:22 -07:00
Greg Shuflin 4bba154ffb Remove target/ files 2026-05-15 04:19:03 -07:00
Greg Shuflin 0a094572c1 gui: node status on document detail with shared presence help
Show per-document, artifact, and blob node presence in a reusable Slint
component, with document-level status under Id in the metadata card.

Add lib::help for Present/Ref/Absent tooltips (info icon on hover) and
compact rows: status dot, node name, and full node id on one line.
2026-05-15 03:15:57 -07:00
Greg Shuflin 2f8e6ea8c9 p2p: artifact and blob transfer protocols
Build Debug APK / build (push) Failing after 45s
After doc-sync populates stubs, these two protocols fetch the actual data:

- artifact_sync (/syn/artifact-sync/1): single round-trip to pull SQLite
  artifact values by (document_id, role); uses LWW merge on receipt.
- blob_sync (/syn/blob-sync/1): chunked 4 MiB streaming protocol for raw
  ciphertext files; verifies BLAKE3 hash before writing to disk.

Supporting store additions:
- ArtifactStore: list_all_artifact_stubs() across all documents
- BlobStore: read_ciphertext() / store_ciphertext() for wire transfer
- DocumentStore: list_all_blob_refs() to find locally missing blobs

fetch_missing_blobs_from_peer() auto-discovers missing blobs by diffing
all BlobRefs against what is present on disk.
2026-05-14 02:24:48 -07:00
Greg Shuflin 993ea20a60 sync: correct merge semantics for properties, artifacts, and blobs
- upsert_property now dispatches on MergeStrategy: Immutable properties
  use INSERT OR IGNORE (first-write-wins); all others apply LWW
  (only update if incoming modified_at is strictly newer)
- Add artifact_stubs table to track artifacts known to exist on remote
  nodes before their values have been fetched
- record_artifact_stub never overwrites an actual local artifact value;
  only records/updates stubs, and is LWW among stubs themselves
- upsert_artifact clears any stub for the same (document_id, role) once
  the actual value arrives
- list_artifact_stubs filters out roles where a local value is present
- apply_chunk step 4 now calls record_artifact_stub for every
  ArtifactRefRecord instead of being a no-op
- Add tests for LWW upsert, stub lifecycle, and stub/artifact interaction
2026-05-14 00:41:46 -07:00
Greg Shuflin f0b3f23c08 pictures: add rotate CW/CCW buttons to GUI ImageViewer control bar
Build Debug APK / build (push) Failing after 57s
2026-05-13 13:21:39 -07:00
Greg Shuflin 43f677ab10 pictures: tap zoom indicator to reset to 100%
Build Debug APK / build (push) Failing after 48s
2026-05-13 12:59:29 -07:00
Greg Shuflin 4e317619f4 pictures: Android Pictures agent with sidebar, zoom, and navigation
- Full PicturesScreen replacing the stub: animated left sidebar (same
  overlay pattern as Notes) listing image documents from the store,
  zoomable image viewer with pinch-to-zoom and pan, bottom bar with
  prev/next navigation and live zoom-percentage display
- ImageLoadState sealed type distinguishes None / Loaded / Error so a
  missing blob shows an error message (BrokenImage icon + message) rather
  than the generic "no image selected" placeholder
- NativeLib.getDocumentBlobBytes now returns ByteArray? — catches
  SyncException.NotFound at the FFI boundary and returns null, preventing
  crashes when a blob hasn't synced yet
- ffi.rs: add From<BlobStoreError> for SyncError with proper variant
  matching; make with_blob_store generic over E: Into<SyncError> so blob
  store callers no longer need to erase errors through Box<dyn Error>;
  strip the "not found" string-match arm from From<Box<dyn Error>> since
  BlobStoreError::NotFound is now handled correctly by the typed impl
- PdfLibraryScreen: handle null blob bytes gracefully with a toast
- MainActivity: pass nativeLib to PicturesScreen
2026-05-13 12:52:37 -07:00
Greg Shuflin 76631a84a5 todo: note Result<T> return type migration for NativeLib FFI calls 2026-05-13 12:31:49 -07:00
Greg Shuflin 5d2215f68e documents: add URL import — Android modal + GUI button
Build Debug APK / build (push) Failing after 42s
Android: Import button opens a modal with 'From local file...' and
'From URL...' options. The URL option accepts a URL in a text field
and calls the new importDocumentFromUrl native binding.

GUI: documents screen gains a URL LineEdit + 'From URL...' button
inline in the header, beside the existing 'From local file...' button.

Rust (lib): expose import_document_from_url via uniffi FFI, wrapping
documents::url_import::import_from_url from commit 86319c80.
2026-05-12 02:48:56 -07:00
Greg Shuflin e0c149a3dd Android - import document from URL 2026-05-12 01:36:09 -07:00
Greg Shuflin 3fcbd3e09a cli: add docs import <URL> command
Build Debug APK / build (push) Failing after 53s
Calls documents::url_import::import_from_url from the CLI via a small tokio
runtime. Shows a spinner while fetching. Prints the imported title and document
ID on success. Unsupported file types or HTTP errors surface as CLI errors.
2026-05-11 18:24:30 -07:00
Greg Shuflin 86319c806d lib: add url_import — fetch and import documents from URLs
- Extract shared HTTP client builder (webpki TLS) into a new crate::http module
- Update agents::podcast to use the shared http module
- Add documents::url_import::import_from_url (async): fetches a URL, detects
  the document type from Content-Type then URL extension, and stores it using
  the same blob/property/blobref path as the file-based import functions
- Supports PDF, image (JPEG/PNG/WebP/GIF/BMP/TIFF), and music (MP3)
2026-05-11 18:24:18 -07:00
Greg Shuflin b340f8010e settings: replace timezone text field with searchable picker from chrono_tz::TZ_VARIANTS
Build Debug APK / build (push) Failing after 37s
2026-05-11 02:52:47 -07:00
Greg Shuflin cce568655b settings: replace timezone text field with searchable picker from chrono_tz::TZ_VARIANTS 2026-05-11 02:29:59 -07:00
Greg Shuflin 0ff4c325e6 settings: add timezone field and CLI command
Build Debug APK / build (push) Failing after 13s
Adds a per-node timezone setting stored as chrono_tz::Tz in the Settings
struct. Serializes to/from its IANA name string (e.g. "America/New_York").

New CLI commands:
  syn settings show            - display current settings
  syn settings timezone <TZ>   - set IANA timezone (validated at parse time)
  syn settings timezone        - clear the timezone
2026-05-10 04:27:14 -07:00
Greg Shuflin 2abe9af5aa deps: add chrono-tz to workspace 2026-05-10 04:26:55 -07:00
Greg Shuflin aad9c41595 rust: separate gui-app into its own workspace to avoid multimedia deps in CLI
Build Debug APK / build (push) Failing after 13s
gui-app enables the 'multimedia' feature on synchronicity_lib, which pulls in
rodio/symphonia and their ALSA dependency. Due to Cargo workspace feature
unification, this caused ALSA to be compiled for all workspace members,
including the CLI and daemon, breaking headless builds.

Fix by removing gui-app from the main workspace so its feature requests don't
affect the CLI build. gui-app becomes a standalone workspace root with inlined
dep versions. The just 'gui' recipe now uses the gui-app manifest directly.

symphonia/rodio remain as optional deps in the lib crate (behind the
'multimedia' feature), but are no longer declared in the workspace.
2026-05-10 02:58:45 -07:00
Greg Shuflin c6594a37d3 A bunch of android podcast tweaks
Build Debug APK / build (push) Failing after 15s
2026-05-08 17:45:06 -07:00
Greg Shuflin d981dfa95a Android podcast screen changes
PodcastDetailScreen.kt — fully restructured:
  - No longer uses SubAppScreen; builds a custom Surface + Column layout with BackHandler
  - Top 1/4 (weight(1f)): podcast image (fills row height, square aspect ratio) on the left; podcast title + truncated description (maxLines = 3) on the right
  - Below the info row: an Info icon button that calls the new onInfoSelected callback
  - A HorizontalDivider separates the sections
  - Bottom 3/4 (weight(3f)): "Episodes (N)" header and episode list filling all remaining space
  - Subscribe/Unsubscribe button removed from this screen

  PodcastInfoScreen.kt — new screen:
  - Uses SubAppScreen (provides back button + title)
  - Full podcast description in a verticalScroll column
  - Subscribe/Unsubscribe button at the bottom

  PodcastScreen.kt — navigation:
  - Added PodcastDestination.Info route
  - PodcastDetailScreen receives onInfoSelected navigating to the info route
  - New composable block handles the info screen
2026-05-08 15:48:17 -07:00
Greg Shuflin 87aa85aa8c cli: add 'docs show' and 'docs delete' subcommands
Build Debug APK / build (push) Failing after 15s
2026-05-07 18:37:19 -07:00
Greg Shuflin a668ae27f2 CLI: add 'docs add' command for importing files
Build Debug APK / build (push) Failing after 27s
Adds lib/src/agents/pdf.rs and lib/src/agents/pictures.rs with
import_pdf_file and import_image_file, mirroring the existing
import_mp3_file in agents/music.rs.

The 'syn docs add FILE...' command opens the store directly (no daemon
required), detects file type by extension, calls the appropriate import
function, marks each document present on the local node, and reports
per-file success or failure. Valid files are imported even if other
files in the batch fail; exits non-zero only when no files succeed.
2026-05-07 03:30:24 -07:00
Greg Shuflin 6676224bbb cli: docs list filter/sort/limit flags with colors; daemon error improvements
Build Debug APK / build (push) Failing after 30s
docs list now accepts:
  -f/--filter TYPE   restrict to one document type (pdf, image, etc.)
  --sort CRITERIA    sort by name (default), date-created, date-modified
  -n/--number N|all  cap output at N rows (default 100) or show all

The ListDocuments daemon command gains filter/sort/limit fields.
commands.rs uses search_documents for filtering and sorts in-process.
format.rs renders document IDs in bright_black and types in cyan,
and shows 'Showing N of M' when output is truncated.

client.rs now includes the raw response body and a restart hint in
the error message when the daemon returns an unparseable response.

TODO.md: added items for CLI/daemon protocol versioning and for
generating --filter help text from DocumentType at compile time.
2026-05-07 03:11:27 -07:00
Greg Shuflin aa5c78c7e5 cli docs work
Build Debug APK / build (push) Failing after 33s
2026-05-07 02:46:45 -07:00
Greg Shuflin 2e6c9d420e cli: auto-start daemon for data commands; extract daemon file constants
Build Debug APK / build (push) Failing after 39s
Cmd::Data now calls client::ensure_daemon_running before sending the
command, so users don't need to manually start the daemon first.

client::daemon_status() encapsulates the pid-file + socket-exists +
connectivity check that was previously duplicated across
cmd_daemon_status and cmd_daemon_stop in main.rs.

DAEMON_SOCK_FILE and DAEMON_PID_FILE constants are now defined in
syn-daemon::lib and used everywhere, replacing all hard-coded
".daemon.sock" and ".daemon.pid" string literals in syn-daemon
(server, client) and cli-app (client, main, tests).
2026-05-07 02:28:48 -07:00
Greg Shuflin d226a604fd cli: reorganize cli commands 2026-05-07 02:18:34 -07:00
Greg Shuflin 84685a2b80 Fix node presence not appearing in document details screen
Build Debug APK / build (push) Failing after 31s
Two bugs prevented node_document_status from being populated correctly:

- doc_sync (apply_chunk): only the receiving node was being marked
  present; now also marks the peer sender. Peer pubkey is parsed from
  the target hex in sync_from_peer and threaded through run_client_sync
  and apply_chunk.

- ffi + gui-app: locally imported documents never called mark_present
  at all. All three Android import FFI functions now call it (via the
  new import_document_with_blob helper), and the GUI import thread does
  the same via NodeDocumentStore.
2026-05-07 01:52:50 -07:00
Greg Shuflin 7b0fc21bac Implementation of document syncing
Build Debug APK / build (push) Failing after 5m0s
Rust FFI (rust/lib/src/ffi.rs): Added sync_documents(node_id_hex) — connects to the peer, drives the sync_from_peer stream to completion, and returns the count of documents received.

  Slint UI (rust/gui-app/ui/ensemble_screen.slint): Added sync-pending, sync-ok, sync-error, last-synced fields to EnsembleMemberDisplay; added a "Sync documents" button row in NodeInfo with spinner, result/error text, and "Not synced" / "Last synced: HH:MM:SS" timestamp
  display; added sync-node(int) callback.

  Slint wiring (app_window.slint, main_screen.slint): Threaded sync-node(int) through all three layers of the component hierarchy.

  GUI backend (rust/gui-app/src/ensemble.rs): Populated the four new EnsembleMemberDisplay fields; added on_sync_node callback handler that calls sync_from_peer on a background thread and writes the result (doc count + timestamp, or error) back to the model row.

  Android (EnsembleScreen.kt): Added SyncState data class; added syncStates map; added "Sync documents" button row with spinner, result/error text, and "Not synced" / "Last synced" display — mirroring the Ping row pattern.

  Android (NativeLib.kt): Added syncDocuments(nodeIdHex) wrapper over the uniffi-generated function.
2026-05-04 02:21:18 -07:00
Greg Shuflin 0726cf8773 Android: throw on unhandled agent ID in MainActivity
Build Debug APK / build (push) Failing after 12s
2026-05-03 23:44:53 -07:00
Greg Shuflin 736d58f78d Android: add stub screens for Pictures, Video, and PomodoroTimer
These agents appear in the main screen list but had no matching case in
MainActivity's when block, leaving users on a blank unescapable screen.
Add minimal SubAppScreen stubs for each and wire them up.
2026-05-03 23:42:50 -07:00
Greg Shuflin e40ed91cbf Android: add general document import with multi-file support
Add three new FFI exports to synchronicity_lib: import_image_document,
import_music_track_document, and get_all_document_mime_types. The
MIME-type list comes from the same documents::import constants the GUI
uses, so Android and GUI share the same source of truth for which files
are supported.

On Android: add DocumentFilePicker (OpenMultipleDocuments) and an
import button to DocumentsScreen. File type is detected via
contentResolver.getType and routed to the correct importer. Add
IMPORT_ICON = Icons.Default.FileOpen as an app-wide constant; update
PdfFilePicker to use it and rename its button text to 'Import PDF'.
2026-05-03 23:36:34 -07:00
Greg Shuflin d024d82256 Remove all SQL migration code; create DB from final schema
Build Debug APK / build (push) Failing after 41s
2026-05-03 00:49:57 -07:00
Greg Shuflin 6b566a88d4 Android - document detail screen: properties/artifacts/blobs, size, copyable IDs/hashes
- Add DocumentArtifactItem and DocumentBlobRefItem FFI record types with
  list_document_artifacts and list_document_blob_refs uniffi exports
- Rework DocumentDetailScreen to show Properties, Artifacts, Blobs, and
  Node Status as separate cards with accurate counts
- Show total document size (blobs + artifacts) in the metadata card
- Wrap document ID and blob hashes in SelectionContainer so they are
  selectable/copyable; display full node ID instead of truncated form
- Fix size_bytes = 0 for documents imported before size tracking: add
  BlobStore::plaintext_size_of (ciphertext size - 16 byte AEAD tag) and
  DocumentStore::backfill_blob_ref_sizes, called from initialize_database
- Add size_bytes INTEGER NOT NULL to the blob_refs CREATE TABLE so fresh
  databases enforce the constraint without a default value
2026-05-03 00:22:52 -07:00
Greg Shuflin 1a01b0c7ab Avoid truncating the blob hash display
Build Debug APK / build (push) Failing after 13s
2026-05-02 03:49:44 -07:00
Greg Shuflin 1b38239fdb Run formatters
Build Debug APK / build (push) Failing after 13s
2026-05-02 03:23:48 -07:00
Greg Shuflin f0f508c1d6 GUI - add document size column (blobs + artifacts) 2026-05-02 03:22:36 -07:00
Greg Shuflin 619d77df3a GUI - correct properties/artifacts/blob counts 2026-05-02 03:12:40 -07:00