auto sync, dep updates, other stuff
This commit is contained in:
391
src-tauri/Cargo.lock
generated
391
src-tauri/Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "app"
|
||||
version = "0.1.3"
|
||||
version = "0.1.4"
|
||||
description = "A Tauri App"
|
||||
authors = ["SticksDev"]
|
||||
license = "MIT"
|
||||
@ -12,26 +12,29 @@ rust-version = "1.80"
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[build-dependencies]
|
||||
tauri-build = { version = "2.0.0-rc", features = [] }
|
||||
tauri-build = { version = "2.0.0-rc.2", features = [] }
|
||||
|
||||
[dependencies]
|
||||
serde_json = "1.0"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
tauri = { version = "2.0.0-rc", features = [] }
|
||||
tauri = { version = "2.0.0-rc.2", features = [] }
|
||||
dirs = "5.0.1"
|
||||
reqwest = { version = "0.11.18", features = ["json"] }
|
||||
lazy_static = "1.5.0"
|
||||
tokio = { version = "1.29.1", features = ["full"] }
|
||||
tokio-macros = "2.3.0"
|
||||
tauri-plugin-os = "2.0.0-alpha.2"
|
||||
tauri-plugin-dialog = "2.0.0-alpha.2"
|
||||
tauri-plugin-clipboard-manager = "2.0.0-alpha.2"
|
||||
tauri-plugin-notification = "2.0.0-alpha.3"
|
||||
tauri-plugin-updater = "2.0.0-alpha.3"
|
||||
tauri-plugin-log = "2.0.0-rc.0"
|
||||
tauri-plugin-os = { version = "2.0.0-rc" }
|
||||
tauri-plugin-dialog = { version = "2.0.0-rc" }
|
||||
tauri-plugin-clipboard-manager = { version = "2.0.0-rc" }
|
||||
tauri-plugin-notification = { version = "2.0.0-rc" }
|
||||
tauri-plugin-updater = { version = "2.0.0-rc" }
|
||||
tauri-plugin-log = { version = "2.0.0-rc" }
|
||||
|
||||
[features]
|
||||
# this feature is used for production builds or when `devPath` points to the filesystem and the built-in dev server is disabled.
|
||||
# If you use cargo directly instead of tauri's cli you can use this feature flag to switch between tauri's `dev` and `build` modes.
|
||||
# DO NOT REMOVE!!
|
||||
custom-protocol = [ "tauri/custom-protocol" ]
|
||||
|
||||
[target.'cfg(not(any(target_os = "android", target_os = "ios")))'.dependencies]
|
||||
tauri-plugin-autostart = "2.0.0-rc.0"
|
||||
|
@ -1,33 +1,32 @@
|
||||
{
|
||||
"identifier": "migrated",
|
||||
"description": "permissions that were migrated from v1",
|
||||
"local": true,
|
||||
"windows": [
|
||||
"main"
|
||||
],
|
||||
"permissions": [
|
||||
"core:default",
|
||||
"dialog:allow-message",
|
||||
"dialog:allow-ask",
|
||||
"dialog:allow-confirm",
|
||||
"notification:default",
|
||||
"os:allow-platform",
|
||||
"os:allow-version",
|
||||
"os:allow-os-type",
|
||||
"os:allow-family",
|
||||
"os:allow-arch",
|
||||
"os:allow-exe-extension",
|
||||
"os:allow-locale",
|
||||
"os:allow-hostname",
|
||||
"clipboard-manager:allow-read-text",
|
||||
"clipboard-manager:allow-write-text",
|
||||
"core:app:allow-app-show",
|
||||
"core:app:allow-app-hide",
|
||||
"os:default",
|
||||
"dialog:default",
|
||||
"clipboard-manager:default",
|
||||
"notification:default",
|
||||
"updater:default",
|
||||
"log:default"
|
||||
]
|
||||
}
|
||||
"identifier": "migrated",
|
||||
"description": "permissions that were migrated from v1",
|
||||
"local": true,
|
||||
"windows": ["main"],
|
||||
"permissions": [
|
||||
"core:default",
|
||||
"dialog:allow-message",
|
||||
"dialog:allow-ask",
|
||||
"dialog:allow-confirm",
|
||||
"notification:default",
|
||||
"os:allow-platform",
|
||||
"os:allow-version",
|
||||
"os:allow-os-type",
|
||||
"os:allow-family",
|
||||
"os:allow-arch",
|
||||
"os:allow-exe-extension",
|
||||
"os:allow-locale",
|
||||
"os:allow-hostname",
|
||||
"clipboard-manager:allow-read-text",
|
||||
"clipboard-manager:allow-write-text",
|
||||
"core:app:allow-app-show",
|
||||
"core:app:allow-app-hide",
|
||||
"os:default",
|
||||
"dialog:default",
|
||||
"clipboard-manager:default",
|
||||
"notification:default",
|
||||
"updater:default",
|
||||
"log:default",
|
||||
"autostart:default"
|
||||
]
|
||||
}
|
||||
|
File diff suppressed because one or more lines are too long
@ -1 +1 @@
|
||||
{"migrated":{"identifier":"migrated","description":"permissions that were migrated from v1","local":true,"windows":["main"],"permissions":["core:default","dialog:allow-message","dialog:allow-ask","dialog:allow-confirm","notification:default","os:allow-platform","os:allow-version","os:allow-os-type","os:allow-family","os:allow-arch","os:allow-exe-extension","os:allow-locale","os:allow-hostname","clipboard-manager:allow-read-text","clipboard-manager:allow-write-text","core:app:allow-app-show","core:app:allow-app-hide","os:default","dialog:default","clipboard-manager:default","notification:default","updater:default","log:default"]}}
|
||||
{"migrated":{"identifier":"migrated","description":"permissions that were migrated from v1","local":true,"windows":["main"],"permissions":["core:default","dialog:allow-message","dialog:allow-ask","dialog:allow-confirm","notification:default","os:allow-platform","os:allow-version","os:allow-os-type","os:allow-family","os:allow-arch","os:allow-exe-extension","os:allow-locale","os:allow-hostname","clipboard-manager:allow-read-text","clipboard-manager:allow-write-text","core:app:allow-app-show","core:app:allow-app-hide","os:default","dialog:default","clipboard-manager:default","notification:default","updater:default","log:default","autostart:default"]}}
|
@ -171,6 +171,55 @@
|
||||
},
|
||||
"Identifier": {
|
||||
"oneOf": [
|
||||
{
|
||||
"description": "autostart:default -> This permission set configures if your\napplication can enable or disable auto\nstarting the application on boot.\n\n#### Granted Permissions\n\nIt allows all to check, enable and\ndisable the automatic start on boot.\n\n",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"autostart:default"
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "autostart:allow-disable -> Enables the disable command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"autostart:allow-disable"
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "autostart:allow-enable -> Enables the enable command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"autostart:allow-enable"
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "autostart:allow-is-enabled -> Enables the is_enabled command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"autostart:allow-is-enabled"
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "autostart:deny-disable -> Denies the disable command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"autostart:deny-disable"
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "autostart:deny-enable -> Denies the enable command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"autostart:deny-enable"
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "autostart:deny-is-enabled -> Denies the is_enabled command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"autostart:deny-is-enabled"
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "clipboard-manager:default -> No features are enabled by default, as we believe\nthe clipboard can be inherently dangerous and it is \napplication specific if read and/or write access is needed.\n\nClipboard interaction needs to be explicitly enabled.\n",
|
||||
"type": "string",
|
||||
|
@ -171,6 +171,55 @@
|
||||
},
|
||||
"Identifier": {
|
||||
"oneOf": [
|
||||
{
|
||||
"description": "autostart:default -> This permission set configures if your\napplication can enable or disable auto\nstarting the application on boot.\n\n#### Granted Permissions\n\nIt allows all to check, enable and\ndisable the automatic start on boot.\n\n",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"autostart:default"
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "autostart:allow-disable -> Enables the disable command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"autostart:allow-disable"
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "autostart:allow-enable -> Enables the enable command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"autostart:allow-enable"
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "autostart:allow-is-enabled -> Enables the is_enabled command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"autostart:allow-is-enabled"
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "autostart:deny-disable -> Denies the disable command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"autostart:deny-disable"
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "autostart:deny-enable -> Denies the enable command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"autostart:deny-enable"
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "autostart:deny-is-enabled -> Denies the is_enabled command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"autostart:deny-is-enabled"
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "clipboard-manager:default -> No features are enabled by default, as we believe\nthe clipboard can be inherently dangerous and it is \napplication specific if read and/or write access is needed.\n\nClipboard interaction needs to be explicitly enabled.\n",
|
||||
"type": "string",
|
||||
|
@ -3,6 +3,7 @@ use crate::{
|
||||
structs::{FanslyAccountResponse, FanslyBaseResponse, SyncDataResponse},
|
||||
};
|
||||
use lazy_static::lazy_static;
|
||||
use serde_json::Value;
|
||||
use tokio::sync::Mutex;
|
||||
|
||||
lazy_static! {
|
||||
@ -26,9 +27,34 @@ pub async fn fansly_get_me() -> Result<FanslyBaseResponse<FanslyAccountResponse>
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn fansly_sync() -> Result<SyncDataResponse, String> {
|
||||
pub async fn fansly_sync(auto: bool) -> Result<SyncDataResponse, String> {
|
||||
let fansly = FANSLY.lock().await;
|
||||
let response = fansly.sync().await;
|
||||
let response = fansly.sync(auto).await;
|
||||
|
||||
match response {
|
||||
Ok(response) => Ok(response),
|
||||
Err(e) => Err(e.to_string()),
|
||||
}
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn fansly_upload_auto_sync_data(
|
||||
data: SyncDataResponse,
|
||||
token: String,
|
||||
) -> Result<(), String> {
|
||||
let fansly: tokio::sync::MutexGuard<Fansly> = FANSLY.lock().await;
|
||||
let response = fansly.upload_auto_sync_data(data, token).await;
|
||||
|
||||
match response {
|
||||
Ok(_) => Ok(()),
|
||||
Err(e) => Err(e.to_string()),
|
||||
}
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn fansly_check_sync_token(token: String) -> Result<Value, String> {
|
||||
let fansly: tokio::sync::MutexGuard<Fansly> = FANSLY.lock().await;
|
||||
let response = fansly.check_sync_token(token).await;
|
||||
|
||||
match response {
|
||||
Ok(response) => Ok(response),
|
||||
|
@ -5,7 +5,7 @@ use std::path::{Path, PathBuf};
|
||||
|
||||
use crate::structs::{FanslyFollowersResponse, Subscription};
|
||||
|
||||
const CURRENT_VERSION: i32 = 1; // Set the current version of the config
|
||||
const CURRENT_VERSION: i32 = 2; // Set the current version of the config
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct SyncData {
|
||||
@ -18,6 +18,8 @@ pub struct Config {
|
||||
pub version: i32, // Add a version field to the config (1, 2, 3, etc.)
|
||||
pub is_first_run: bool,
|
||||
pub fansly_token: String,
|
||||
pub auto_sync_enabled: bool,
|
||||
pub sync_token: String,
|
||||
pub sync_interval: u64,
|
||||
pub last_sync: u64,
|
||||
pub last_sync_data: SyncData,
|
||||
@ -31,6 +33,8 @@ impl Default for Config {
|
||||
fansly_token: String::new(), // Fansly token is stored as a string
|
||||
sync_interval: 1, // Every hour - sync interval is interpreted as hours
|
||||
last_sync: 0, // Last sync time is stored as a UNIX timestamp
|
||||
auto_sync_enabled: false, // Auto sync is disabled by default
|
||||
sync_token: String::new(), // Sync token is stored as a string
|
||||
last_sync_data: SyncData {
|
||||
followers: Vec::new(),
|
||||
subscribers: Vec::new(),
|
||||
@ -42,17 +46,89 @@ impl Default for Config {
|
||||
impl Config {
|
||||
pub fn load_or_create(path: &Path) -> io::Result<Self> {
|
||||
if path.exists() {
|
||||
let mut config: Self = serde_json::from_str(std::fs::read_to_string(path)?.as_str())
|
||||
.map_err(|e| {
|
||||
io::Error::new(
|
||||
io::ErrorKind::InvalidData,
|
||||
format!("Could not parse config file: {}", e),
|
||||
)
|
||||
})?;
|
||||
let config_result: Result<Self, _> =
|
||||
serde_json::from_str(&std::fs::read_to_string(path)?);
|
||||
let config = match config_result {
|
||||
Ok(config) => config,
|
||||
Err(_) => {
|
||||
// Load raw JSON and attempt to parse it as a JSON object
|
||||
let config_raw = std::fs::read_to_string(path)?;
|
||||
let config_json: serde_json::Value = serde_json::from_str(&config_raw)?;
|
||||
|
||||
println!("[config::migrate] Migrating config file to latest version...");
|
||||
println!(
|
||||
"[config::migrate] [DEBUG] config is_object: {}",
|
||||
config_json.is_object()
|
||||
);
|
||||
|
||||
// Check if the JSON object is valid, if not, return an error
|
||||
if !config_json.is_object() {
|
||||
println!(
|
||||
"[config::migrate] [ERROR] Found invalid JSON object in config file"
|
||||
);
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::InvalidData,
|
||||
"Tried to migrate a config file, but found an invalid JSON object",
|
||||
));
|
||||
}
|
||||
|
||||
// Get the version field from the JSON object
|
||||
let version = config_json["version"].as_i64().unwrap_or(0) as i32;
|
||||
|
||||
// Check if the version field is a valid integer, if not, return an error
|
||||
if version == 0 {
|
||||
println!(
|
||||
"[config::migrate] [ERROR] Found invalid version field in config JSON"
|
||||
);
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::InvalidData,
|
||||
"Tried to migrate a config file, but found an invalid version field",
|
||||
));
|
||||
}
|
||||
|
||||
println!(
|
||||
"[config::migrate] Found version field in config JSON: {}",
|
||||
version
|
||||
);
|
||||
|
||||
// Now create a new Config object and set the version field to the value we found
|
||||
let mut config = Config::default();
|
||||
config.version = version;
|
||||
|
||||
// Retain important fields from the JSON object
|
||||
config.is_first_run = config_json["is_first_run"].as_bool().unwrap_or(true);
|
||||
config.fansly_token = config_json["fansly_token"]
|
||||
.as_str()
|
||||
.unwrap_or("")
|
||||
.to_string();
|
||||
config.sync_token =
|
||||
config_json["sync_token"].as_str().unwrap_or("").to_string();
|
||||
config.sync_interval =
|
||||
config_json["sync_interval"].as_i64().unwrap_or(1) as u64;
|
||||
|
||||
// Run migrations on the config object and save it
|
||||
config = config.migrate()?;
|
||||
config.save(path)?;
|
||||
|
||||
println!(
|
||||
"[config::migrate] Successfully migrated config file to latest version"
|
||||
);
|
||||
// Recursively call load_or_create to load the migrated config
|
||||
return Config::load_or_create(path);
|
||||
}
|
||||
};
|
||||
|
||||
if config.version != CURRENT_VERSION {
|
||||
config = config.migrate()?;
|
||||
config.save(path)?;
|
||||
// Should have been migrated by now, error out because it wasn't
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::InvalidData,
|
||||
format!(
|
||||
"Config version mismatch: expected {}, got {}. Please try removing the config file and restarting the application.",
|
||||
CURRENT_VERSION, config.version
|
||||
),
|
||||
));
|
||||
}
|
||||
|
||||
Ok(config)
|
||||
} else {
|
||||
let saved_config = Config::default().save(path);
|
||||
@ -66,8 +142,12 @@ impl Config {
|
||||
while self.version < CURRENT_VERSION {
|
||||
self = match self.version {
|
||||
1 => {
|
||||
// If we're on version 1, migrate to version 2 (not implemented)
|
||||
self.version += 1;
|
||||
// Migrate from version 1 to version 2
|
||||
self.version = 2;
|
||||
self.auto_sync_enabled = false;
|
||||
self.sync_token = String::new();
|
||||
self.sync_interval = 1;
|
||||
|
||||
self
|
||||
}
|
||||
_ => {
|
||||
|
@ -5,6 +5,7 @@ use crate::structs::{
|
||||
FanslySubscriptionsResponse, Subscription, SyncDataResponse,
|
||||
};
|
||||
use reqwest::header::{HeaderMap, HeaderValue, USER_AGENT};
|
||||
use serde_json::Value;
|
||||
|
||||
pub struct Fansly {
|
||||
client: reqwest::Client,
|
||||
@ -195,7 +196,73 @@ impl Fansly {
|
||||
Ok(format!("https://paste.hep.gg/{}", key))
|
||||
}
|
||||
|
||||
pub async fn sync(&self) -> Result<SyncDataResponse, String> {
|
||||
pub async fn upload_auto_sync_data(
|
||||
&self,
|
||||
data: SyncDataResponse,
|
||||
token: String,
|
||||
) -> Result<(), reqwest::Error> {
|
||||
let url = "http://localhost:5001/sync";
|
||||
|
||||
// Set our content type to application/json
|
||||
let mut headers = reqwest::header::HeaderMap::new();
|
||||
headers.insert(
|
||||
reqwest::header::CONTENT_TYPE,
|
||||
"application/json".parse().unwrap(),
|
||||
);
|
||||
|
||||
// Add our auth token to the headers
|
||||
headers.insert("Authorization", format!("{}", token).parse().unwrap());
|
||||
|
||||
let response = self
|
||||
.client
|
||||
.post(url)
|
||||
.headers(headers)
|
||||
.json(&data)
|
||||
.send()
|
||||
.await?;
|
||||
|
||||
if !response.status().is_success() {
|
||||
eprintln!("[sync::process::upload_auto_sync_data] Failed to upload sync data.");
|
||||
return Err(response.error_for_status().unwrap_err());
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn check_sync_token(&self, token: String) -> Result<Value, reqwest::Error> {
|
||||
// Check if the token is valid (GET /checkSyncToken with Authorization header)
|
||||
// If it is, return the data back from the API
|
||||
// If it isn't, return an error
|
||||
let url = "http://localhost:5001/checkSyncToken";
|
||||
|
||||
// Set our content type to application/json
|
||||
let mut headers = reqwest::header::HeaderMap::new();
|
||||
headers.insert(
|
||||
reqwest::header::CONTENT_TYPE,
|
||||
"application/json".parse().unwrap(),
|
||||
);
|
||||
|
||||
// Add our auth token to the headers
|
||||
headers.insert("Authorization", format!("{}", token).parse().unwrap());
|
||||
|
||||
let response = self.client.get(url).headers(headers).send().await;
|
||||
|
||||
// If successful, return the data, otherwise return an error
|
||||
match response {
|
||||
Ok(response) => {
|
||||
if !response.status().is_success() {
|
||||
eprintln!("[sync::process::check_sync_token] Failed to check sync token.");
|
||||
return Err(response.error_for_status().unwrap_err());
|
||||
}
|
||||
|
||||
let json: serde_json::Value = response.json().await?;
|
||||
Ok(json)
|
||||
}
|
||||
Err(e) => Err(e),
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn sync(&self, auto: bool) -> Result<SyncDataResponse, String> {
|
||||
// Fetch profile
|
||||
println!("[sync::process] Fetching profile...");
|
||||
let profile = self.get_profile().await.map_err(|e| e.to_string())?;
|
||||
@ -280,20 +347,29 @@ impl Fansly {
|
||||
println!("[sync::process] Uploading sync data to paste.hep.gg for processing...");
|
||||
|
||||
// Upload sync data to paste.hep.gg
|
||||
let paste_url = self
|
||||
.upload_sync_data(SyncDataResponse {
|
||||
followers: followers.clone(),
|
||||
subscribers: subscribers.clone(),
|
||||
if !auto {
|
||||
let paste_url = self
|
||||
.upload_sync_data(SyncDataResponse {
|
||||
followers: followers.clone(),
|
||||
subscribers: subscribers.clone(),
|
||||
sync_data_url: "".to_string(),
|
||||
})
|
||||
.await
|
||||
.map_err(|e| e.to_string())?;
|
||||
|
||||
// Return JSON of what we fetched
|
||||
Ok(SyncDataResponse {
|
||||
followers,
|
||||
subscribers,
|
||||
sync_data_url: paste_url,
|
||||
})
|
||||
} else {
|
||||
// Return JSON of what we fetched
|
||||
Ok(SyncDataResponse {
|
||||
followers,
|
||||
subscribers,
|
||||
sync_data_url: "".to_string(),
|
||||
})
|
||||
.await
|
||||
.map_err(|e| e.to_string())?;
|
||||
|
||||
// Return JSON of what we fetched
|
||||
Ok(SyncDataResponse {
|
||||
followers,
|
||||
subscribers,
|
||||
sync_data_url: paste_url,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -9,8 +9,12 @@ use std::fs;
|
||||
use std::io;
|
||||
|
||||
use commands::config::{get_config, init_config, save_config};
|
||||
use commands::fansly::{fansly_get_me, fansly_set_token, fansly_sync};
|
||||
use commands::fansly::{
|
||||
fansly_check_sync_token, fansly_get_me, fansly_set_token, fansly_sync,
|
||||
fansly_upload_auto_sync_data,
|
||||
};
|
||||
use commands::utils::quit;
|
||||
use tauri_plugin_autostart::MacosLauncher;
|
||||
use tauri_plugin_log::{Target, TargetKind};
|
||||
|
||||
fn get_log_path() -> io::Result<String> {
|
||||
@ -31,6 +35,10 @@ fn get_log_path() -> io::Result<String> {
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
tauri::Builder::default()
|
||||
.plugin(tauri_plugin_autostart::init(
|
||||
MacosLauncher::LaunchAgent,
|
||||
None,
|
||||
))
|
||||
.plugin(tauri_plugin_log::Builder::new().build())
|
||||
.plugin(tauri_plugin_notification::init())
|
||||
.plugin(tauri_plugin_clipboard_manager::init())
|
||||
@ -55,7 +63,9 @@ async fn main() {
|
||||
quit,
|
||||
fansly_set_token,
|
||||
fansly_get_me,
|
||||
fansly_sync
|
||||
fansly_sync,
|
||||
fansly_upload_auto_sync_data,
|
||||
fansly_check_sync_token
|
||||
])
|
||||
.run(tauri::generate_context!())
|
||||
.expect("error while running tauri application");
|
||||
|
Reference in New Issue
Block a user