//! GoingsOn - Tauri application library. //! //! This library exposes the core modules for testing purposes. //! The main application entry point is in `main.rs` (desktop) //! or via `mobile_entry_point` (iOS/Android). pub mod backup_scheduler; pub mod blob_gc; pub mod commands; pub mod email; pub mod email_sync_scheduler; pub mod export; pub mod external_sync; pub mod jmap; pub mod oauth; pub mod state; pub mod sync_scheduler; pub mod sync_service; pub mod tz; // Desktop-only: file watching for external DB changes #[cfg(not(any(target_os = "ios", target_os = "android")))] pub mod db_watcher; // Desktop-only: OS notifications for snooze expiry #[cfg(not(any(target_os = "ios", target_os = "android")))] pub mod notifications; #[cfg(test)] pub mod test_utils; /// The single source of truth for the Tauri command registration list. /// /// Both the desktop entry point (`main.rs`) and the mobile entry point /// (`build_mobile_app` below) expand this macro, so the desktop and mobile /// handler lists cannot drift: adding a `#[tauri::command]` and forgetting to /// register it here is a build error, and omitting a command from one platform /// is impossible because there is only one list. Paths are written as /// `$crate::commands::*` so the macro resolves correctly whether it is invoked /// from inside this crate (mobile) or from the `goingson_desktop` consumer crate /// (the desktop binary). #[macro_export] macro_rules! all_commands { () => { ::tauri::generate_handler![ // Attachments $crate::commands::add_attachment, $crate::commands::list_attachments, $crate::commands::delete_attachment, $crate::commands::open_attachment, $crate::commands::save_attachment, $crate::commands::convert_email_attachments, $crate::commands::open_email_blob, $crate::commands::save_email_blob, $crate::commands::get_file_size, // Projects $crate::commands::list_projects, $crate::commands::get_project, $crate::commands::create_project, $crate::commands::update_project, $crate::commands::delete_project, // Tasks $crate::commands::list_tasks, $crate::commands::list_tasks_filtered, $crate::commands::get_task, $crate::commands::create_task, $crate::commands::quick_add_task, $crate::commands::update_task, $crate::commands::delete_task, $crate::commands::bulk_set_task_project, $crate::commands::bulk_set_task_priority, $crate::commands::start_task, $crate::commands::complete_task, $crate::commands::list_snoozed_tasks, $crate::commands::snooze_task, $crate::commands::unsnooze_task, $crate::commands::list_waiting_tasks, $crate::commands::mark_task_waiting, $crate::commands::clear_task_waiting, // Task Overview $crate::commands::get_task_overview, // Annotations $crate::commands::list_annotations, $crate::commands::add_annotation, $crate::commands::delete_annotation, // Subtasks $crate::commands::list_subtasks, $crate::commands::add_subtask, $crate::commands::add_subtask_link, $crate::commands::toggle_subtask, $crate::commands::update_subtask, $crate::commands::delete_subtask, // Status tokens (e.g. linked commits) $crate::commands::list_task_status_tokens, $crate::commands::record_task_status_token, $crate::commands::delete_task_status_token, // Milestones $crate::commands::list_milestones, $crate::commands::create_milestone, $crate::commands::update_milestone, $crate::commands::delete_milestone, $crate::commands::reorder_milestones, // Events $crate::commands::list_events, $crate::commands::get_event, $crate::commands::create_event, $crate::commands::update_event, $crate::commands::delete_event, $crate::commands::bulk_delete_events, $crate::commands::list_events_between, $crate::commands::list_upcoming_events, $crate::commands::get_event_status_indicator, $crate::commands::list_snoozed_events, $crate::commands::snooze_event, $crate::commands::unsnooze_event, // Emails $crate::commands::list_emails, $crate::commands::list_emails_threaded, $crate::commands::get_email, $crate::commands::build_reply_prefill, $crate::commands::build_forward_prefill, $crate::commands::fetch_email_full_body, $crate::commands::open_email_in_browser, $crate::commands::create_email, $crate::commands::send_email, $crate::commands::save_email_draft, $crate::commands::list_email_drafts, $crate::commands::send_email_draft, $crate::commands::set_email_labels, $crate::commands::list_email_folders, $crate::commands::list_email_labels, $crate::commands::move_email_to_folder, $crate::commands::delete_email, $crate::commands::mark_email_read, $crate::commands::mark_email_unread, $crate::commands::archive_email, $crate::commands::unarchive_email, $crate::commands::mark_all_emails_read, $crate::commands::link_email_to_project, $crate::commands::get_unread_email_count, $crate::commands::list_snoozed_emails, $crate::commands::snooze_email, $crate::commands::unsnooze_email, $crate::commands::list_waiting_emails, $crate::commands::mark_email_waiting, $crate::commands::clear_email_waiting, // Contacts $crate::commands::list_contacts, $crate::commands::get_contact, $crate::commands::create_contact, $crate::commands::update_contact, $crate::commands::delete_contact, $crate::commands::add_contact_email, $crate::commands::remove_contact_email, $crate::commands::add_contact_phone, $crate::commands::remove_contact_phone, $crate::commands::add_contact_social_handle, $crate::commands::remove_contact_social_handle, $crate::commands::add_contact_custom_field, $crate::commands::remove_contact_custom_field, $crate::commands::update_contact_email, $crate::commands::update_contact_phone, $crate::commands::update_contact_social_handle, $crate::commands::update_contact_custom_field, $crate::commands::find_contact_by_email, $crate::commands::validate_email_addresses, $crate::commands::promote_contact, $crate::commands::list_tasks_for_contact, $crate::commands::list_events_for_contact, $crate::commands::list_emails_for_contact, $crate::commands::get_contact_activity, $crate::commands::list_contacts_filtered, $crate::commands::list_contact_email_directory, $crate::commands::bulk_delete_contacts, $crate::commands::bulk_tag_contacts, // Snooze Options $crate::commands::get_snooze_options, // Email Accounts $crate::commands::list_email_accounts, $crate::commands::get_email_account, $crate::commands::create_email_account, $crate::commands::update_email_account, $crate::commands::update_email_sync_interval, $crate::commands::update_email_signature, $crate::commands::update_email_notify, $crate::commands::delete_email_account, $crate::commands::test_email_account, $crate::commands::sync_email_account, // Project Dashboard $crate::commands::list_tasks_for_project, $crate::commands::list_events_for_project, $crate::commands::list_emails_for_project, $crate::commands::list_unlinked_emails, // Email Threading $crate::commands::list_emails_by_thread, // Stats $crate::commands::get_dashboard_stats, // App info $crate::commands::get_changelog, $crate::commands::parse_natural_date, // Window $crate::commands::open_compose_window, $crate::commands::set_window_title, $crate::commands::open_external_url, // Search $crate::commands::search, // Daily Notes $crate::commands::get_daily_note, $crate::commands::upsert_daily_note, // Day Planning $crate::commands::get_day_planning, $crate::commands::schedule_task, $crate::commands::unschedule_task, // Saved Views $crate::commands::list_saved_views, $crate::commands::list_pinned_views, $crate::commands::get_saved_view, $crate::commands::create_saved_view, $crate::commands::update_saved_view, $crate::commands::delete_saved_view, $crate::commands::toggle_view_pinned, // OAuth $crate::commands::list_oauth_providers, $crate::commands::start_oauth, $crate::commands::poll_oauth_result, $crate::commands::complete_oauth, $crate::commands::refresh_oauth_tokens, $crate::commands::disconnect_oauth, $crate::commands::reconnect_oauth, // Export/Backup $crate::commands::get_export_summary, $crate::commands::export_json, $crate::commands::export_tasks_csv, $crate::commands::export_events_ics, $crate::commands::create_backup, $crate::commands::list_backups, $crate::commands::restore_backup, $crate::commands::delete_backup, $crate::commands::get_backup_settings, $crate::commands::save_backup_settings, // Monthly Review $crate::commands::get_monthly_review, $crate::commands::upsert_monthly_goal, $crate::commands::update_monthly_goal_status, $crate::commands::delete_monthly_goal, $crate::commands::save_monthly_reflection, // Weekly Review $crate::commands::get_weekly_review, $crate::commands::complete_weekly_review, $crate::commands::set_task_focus, $crate::commands::clear_all_focus, $crate::commands::set_vacation_days, $crate::commands::check_weekly_review_nudge, // Sync $crate::commands::sync_get_tiers, $crate::commands::sync_status, $crate::commands::sync_start_auth, $crate::commands::sync_complete_auth, $crate::commands::sync_disconnect, $crate::commands::sync_now, $crate::commands::sync_setup_encryption_new, $crate::commands::sync_setup_encryption_existing, $crate::commands::sync_update_settings, $crate::commands::sync_account_info, $crate::commands::sync_subscription_status, $crate::commands::sync_subscribe, // Themes $crate::commands::list_themes, $crate::commands::get_theme, $crate::commands::get_custom_themes_dir, $crate::commands::import_theme, $crate::commands::export_theme, // Import (CSV/TSV) $crate::commands::preview_import, $crate::commands::execute_import, // Import (VCF/ICS) $crate::commands::preview_vcf, $crate::commands::import_vcf, $crate::commands::preview_ics, $crate::commands::import_ics, // Time Tracking $crate::commands::start_timer, $crate::commands::stop_timer, $crate::commands::discard_timer, $crate::commands::get_active_timer, $crate::commands::list_time_sessions, $crate::commands::log_manual_time, $crate::commands::get_time_summary_panel, // Preferences $crate::commands::get_preferences, $crate::commands::set_update_check_on_launch, ] }; } /// Build the Tauri app with all commands registered. /// Shared between desktop `main()` and mobile entry point. pub fn build_mobile_app() -> tauri::Builder { use state::AppState; use std::sync::Arc; use tauri::Manager; use tokio_util::sync::CancellationToken; let mut builder = tauri::Builder::default(); // Desktop-only plugins #[cfg(not(any(target_os = "ios", target_os = "android")))] { builder = builder .plugin(tauri_plugin_shell::init()) .plugin(tauri_plugin_notification::init()) .plugin(tauri_plugin_window_state::Builder::new().build()); } builder .plugin(tauri_plugin_dialog::init()) .setup(|app| { // Initialize database let app_handle = app.handle().clone(); tauri::async_runtime::block_on(async move { let state = AppState::new(&app_handle).await .expect("Failed to initialize app state"); // Reclaim orphaned attachment blobs before the schedulers spawn // and before the UI can create attachments — race-free here. blob_gc::reconcile(&state.pool, &state.data_dir).await; app_handle.manage(Arc::new(state)); }); // Background services that work on all platforms let cancel_token = CancellationToken::new(); app.manage(cancel_token.clone()); let backup_handle = app.handle().clone(); let backup_cancel = cancel_token.clone(); tauri::async_runtime::spawn(async move { backup_scheduler::start_backup_scheduler(backup_handle, backup_cancel).await; }); let sync_handle = app.handle().clone(); let email_cancel = cancel_token.clone(); tauri::async_runtime::spawn(async move { email_sync_scheduler::start_email_sync_scheduler(sync_handle, email_cancel).await; }); let cloud_sync_handle = app.handle().clone(); let cloud_cancel = cancel_token; tauri::async_runtime::spawn(async move { sync_scheduler::start_sync_scheduler(cloud_sync_handle, cloud_cancel).await; }); // Clean up stale email preview + attachment temp files from previous sessions tauri::async_runtime::spawn(async { commands::email::cleanup_stale_temp_files().await; commands::attachment::cleanup_stale_attachment_temp().await; }); Ok(()) }) .invoke_handler(crate::all_commands!()) } /// Mobile entry point for iOS/Android. #[cfg(mobile)] #[tauri::mobile_entry_point] fn main() { tracing_subscriber::fmt::init(); build_mobile_app() .run(tauri::generate_context!()) .expect("error while running tauri application"); }