1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
mod config;
mod client;
mod commands;
mod sys;

use std::{sync::Arc, panic::PanicInfo};

use config::Config;
use serde_json::Value;
use client::AptabaseClient;
use tauri::{
  plugin::{TauriPlugin, self},
    Runtime, Manager, App, AppHandle, Window, 
};

#[derive(Default, Debug, Clone)]
pub struct InitOptions {
  pub host: Option<String>
}


pub struct Builder {
  app_key: String,
  panic_hook: Option<PanicHook>,
  options: InitOptions
}

pub type PanicHook =
  Box<dyn Fn(&AptabaseClient, &PanicInfo<'_>) + 'static + Sync + Send>;

impl Builder {
    pub fn new(app_key: &str) -> Self {
      Builder {
        app_key: app_key.into(),
        panic_hook: None,
        options: Default::default()
      }
    }

    pub fn with_options(mut self, opts: InitOptions) -> Self {
      self.options = opts;
      self
    }

    pub fn with_panic_hook(mut self, hook: PanicHook) -> Self {
      self.panic_hook = Some(hook);
      self
    }

    pub fn build<R: Runtime>(self) -> TauriPlugin<R> {
      plugin::Builder::new("aptabase")
        .invoke_handler(tauri::generate_handler![commands::track_event])
        .setup(|app| {
          let cfg = Config::new(self.app_key, self.options.host);
          let app_version = app.package_info().version.to_string();
          let client = Arc::new(AptabaseClient::with_config(cfg, app_version));
          
          if let Some(hook) = self.panic_hook {
            let hook_client = client.clone();
            std::panic::set_hook(Box::new(move |info| {
              hook(&hook_client, info);
            }));
          }

          app.manage(client);
          Ok(())
        })
        .build()
    }
}

pub trait EventTracker {
  fn track_event(&self, name: &str, props: Option<Value>);
}

impl EventTracker for App {
    fn track_event(&self, name: &str, props: Option<Value>) {
      let client = self.state::<Arc<AptabaseClient>>();
      client.track_event(name, props);
    }
}

impl EventTracker for AppHandle {
    fn track_event(&self, name: &str, props: Option<Value>) {
      let client = self.state::<Arc<AptabaseClient>>();
      client.track_event(name, props);
    }
}

impl EventTracker for Window {
    fn track_event(&self, name: &str, props: Option<Value>) {
      let client = self.state::<Arc<AptabaseClient>>();
      client.track_event(name, props);
    }
}