feat: add sync progress, break loops once we get 0 users back
This commit is contained in:
parent
ba25e5d485
commit
5a7c3155ac
8
.idea/.gitignore
generated
vendored
Normal file
8
.idea/.gitignore
generated
vendored
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
# Default ignored files
|
||||||
|
/shelf/
|
||||||
|
/workspace.xml
|
||||||
|
# Editor-based HTTP Client requests
|
||||||
|
/httpRequests/
|
||||||
|
# Datasource local storage ignored files
|
||||||
|
/dataSources/
|
||||||
|
/dataSources.local.xml
|
12
.idea/FanslySync.iml
generated
Normal file
12
.idea/FanslySync.iml
generated
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<module type="JAVA_MODULE" version="4">
|
||||||
|
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||||
|
<exclude-output />
|
||||||
|
<content url="file://$MODULE_DIR$">
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/src-tauri/src" isTestSource="false" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/src-tauri/target" />
|
||||||
|
</content>
|
||||||
|
<orderEntry type="inheritedJdk" />
|
||||||
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
|
</component>
|
||||||
|
</module>
|
63
.idea/codeStyles/Project.xml
generated
Normal file
63
.idea/codeStyles/Project.xml
generated
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
<component name="ProjectCodeStyleConfiguration">
|
||||||
|
<code_scheme name="Project" version="173">
|
||||||
|
<HTMLCodeStyleSettings>
|
||||||
|
<option name="HTML_SPACE_INSIDE_EMPTY_TAG" value="true" />
|
||||||
|
</HTMLCodeStyleSettings>
|
||||||
|
<JSCodeStyleSettings version="0">
|
||||||
|
<option name="FORCE_SEMICOLON_STYLE" value="true" />
|
||||||
|
<option name="SPACE_BEFORE_FUNCTION_LEFT_PARENTH" value="false" />
|
||||||
|
<option name="USE_DOUBLE_QUOTES" value="false" />
|
||||||
|
<option name="FORCE_QUOTE_STYlE" value="true" />
|
||||||
|
<option name="ENFORCE_TRAILING_COMMA" value="Remove" />
|
||||||
|
<option name="SPACES_WITHIN_OBJECT_LITERAL_BRACES" value="true" />
|
||||||
|
<option name="SPACES_WITHIN_IMPORTS" value="true" />
|
||||||
|
</JSCodeStyleSettings>
|
||||||
|
<TypeScriptCodeStyleSettings version="0">
|
||||||
|
<option name="FORCE_SEMICOLON_STYLE" value="true" />
|
||||||
|
<option name="SPACE_BEFORE_FUNCTION_LEFT_PARENTH" value="false" />
|
||||||
|
<option name="USE_DOUBLE_QUOTES" value="false" />
|
||||||
|
<option name="FORCE_QUOTE_STYlE" value="true" />
|
||||||
|
<option name="ENFORCE_TRAILING_COMMA" value="Remove" />
|
||||||
|
<option name="SPACES_WITHIN_OBJECT_LITERAL_BRACES" value="true" />
|
||||||
|
<option name="SPACES_WITHIN_IMPORTS" value="true" />
|
||||||
|
</TypeScriptCodeStyleSettings>
|
||||||
|
<VueCodeStyleSettings>
|
||||||
|
<option name="INTERPOLATION_NEW_LINE_AFTER_START_DELIMITER" value="false" />
|
||||||
|
<option name="INTERPOLATION_NEW_LINE_BEFORE_END_DELIMITER" value="false" />
|
||||||
|
</VueCodeStyleSettings>
|
||||||
|
<codeStyleSettings language="HTML">
|
||||||
|
<option name="SOFT_MARGINS" value="100" />
|
||||||
|
<indentOptions>
|
||||||
|
<option name="INDENT_SIZE" value="2" />
|
||||||
|
<option name="CONTINUATION_INDENT_SIZE" value="2" />
|
||||||
|
<option name="TAB_SIZE" value="2" />
|
||||||
|
<option name="USE_TAB_CHARACTER" value="true" />
|
||||||
|
</indentOptions>
|
||||||
|
</codeStyleSettings>
|
||||||
|
<codeStyleSettings language="JavaScript">
|
||||||
|
<option name="SOFT_MARGINS" value="100" />
|
||||||
|
<indentOptions>
|
||||||
|
<option name="INDENT_SIZE" value="2" />
|
||||||
|
<option name="CONTINUATION_INDENT_SIZE" value="2" />
|
||||||
|
<option name="TAB_SIZE" value="2" />
|
||||||
|
<option name="USE_TAB_CHARACTER" value="true" />
|
||||||
|
</indentOptions>
|
||||||
|
</codeStyleSettings>
|
||||||
|
<codeStyleSettings language="TypeScript">
|
||||||
|
<option name="SOFT_MARGINS" value="100" />
|
||||||
|
<indentOptions>
|
||||||
|
<option name="INDENT_SIZE" value="2" />
|
||||||
|
<option name="CONTINUATION_INDENT_SIZE" value="2" />
|
||||||
|
<option name="TAB_SIZE" value="2" />
|
||||||
|
<option name="USE_TAB_CHARACTER" value="true" />
|
||||||
|
</indentOptions>
|
||||||
|
</codeStyleSettings>
|
||||||
|
<codeStyleSettings language="Vue">
|
||||||
|
<option name="SOFT_MARGINS" value="100" />
|
||||||
|
<indentOptions>
|
||||||
|
<option name="CONTINUATION_INDENT_SIZE" value="2" />
|
||||||
|
<option name="USE_TAB_CHARACTER" value="true" />
|
||||||
|
</indentOptions>
|
||||||
|
</codeStyleSettings>
|
||||||
|
</code_scheme>
|
||||||
|
</component>
|
5
.idea/codeStyles/codeStyleConfig.xml
generated
Normal file
5
.idea/codeStyles/codeStyleConfig.xml
generated
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
<component name="ProjectCodeStyleConfiguration">
|
||||||
|
<state>
|
||||||
|
<option name="USE_PER_PROJECT_SETTINGS" value="true" />
|
||||||
|
</state>
|
||||||
|
</component>
|
6
.idea/inspectionProfiles/Project_Default.xml
generated
Normal file
6
.idea/inspectionProfiles/Project_Default.xml
generated
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
<component name="InspectionProjectProfileManager">
|
||||||
|
<profile version="1.0">
|
||||||
|
<option name="myName" value="Project Default" />
|
||||||
|
<inspection_tool class="Eslint" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||||
|
</profile>
|
||||||
|
</component>
|
5
.idea/misc.xml
generated
Normal file
5
.idea/misc.xml
generated
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
<project version="4">
|
||||||
|
<component name="ProjectRootManager">
|
||||||
|
<output url="file://$PROJECT_DIR$/out" />
|
||||||
|
</component>
|
||||||
|
</project>
|
8
.idea/modules.xml
generated
Normal file
8
.idea/modules.xml
generated
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="ProjectModuleManager">
|
||||||
|
<modules>
|
||||||
|
<module fileurl="file://$PROJECT_DIR$/.idea/FanslySync.iml" filepath="$PROJECT_DIR$/.idea/FanslySync.iml" />
|
||||||
|
</modules>
|
||||||
|
</component>
|
||||||
|
</project>
|
6
.idea/prettier.xml
generated
Normal file
6
.idea/prettier.xml
generated
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="PrettierConfiguration">
|
||||||
|
<option name="myConfigurationMode" value="AUTOMATIC" />
|
||||||
|
</component>
|
||||||
|
</project>
|
6
.idea/vcs.xml
generated
Normal file
6
.idea/vcs.xml
generated
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="VcsDirectoryMappings">
|
||||||
|
<mapping directory="" vcs="Git" />
|
||||||
|
</component>
|
||||||
|
</project>
|
@ -5,6 +5,7 @@ use crate::{
|
|||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
use tokio::sync::Mutex;
|
use tokio::sync::Mutex;
|
||||||
|
use crate::handlers::fansly::{SyncProgress, PROGRESS};
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
static ref FANSLY: Mutex<Fansly> = Mutex::new(Fansly::new(None));
|
static ref FANSLY: Mutex<Fansly> = Mutex::new(Fansly::new(None));
|
||||||
@ -28,7 +29,7 @@ pub async fn fansly_get_me() -> Result<FanslyBaseResponse<FanslyAccountResponse>
|
|||||||
|
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
pub async fn fansly_sync(auto: bool) -> Result<SyncDataResponse, String> {
|
pub async fn fansly_sync(auto: bool) -> Result<SyncDataResponse, String> {
|
||||||
let fansly = FANSLY.lock().await;
|
let mut fansly = FANSLY.lock().await;
|
||||||
let response = fansly.sync(auto).await;
|
let response = fansly.sync(auto).await;
|
||||||
|
|
||||||
match response {
|
match response {
|
||||||
@ -37,6 +38,11 @@ pub async fn fansly_sync(auto: bool) -> Result<SyncDataResponse, String> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tauri::command]
|
||||||
|
pub async fn fansly_get_sync_status() -> SyncProgress {
|
||||||
|
PROGRESS.lock().await.clone()
|
||||||
|
}
|
||||||
|
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
pub async fn fansly_upload_auto_sync_data(
|
pub async fn fansly_upload_auto_sync_data(
|
||||||
data: SyncDataResponse,
|
data: SyncDataResponse,
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
use lazy_static::lazy::Lazy;
|
||||||
|
use lazy_static::lazy_static;
|
||||||
// Create a simple module for handling the Fansly API, using reqwest to make requests to the API.
|
// Create a simple module for handling the Fansly API, using reqwest to make requests to the API.
|
||||||
// This module will contain a struct Fansly, which will have a method to get the user's profile information.
|
// This module will contain a struct Fansly, which will have a method to get the user's profile information.
|
||||||
use crate::structs::{
|
use crate::structs::{
|
||||||
@ -5,7 +7,24 @@ use crate::structs::{
|
|||||||
FanslySubscriptionsResponse, Subscription, SyncDataResponse,
|
FanslySubscriptionsResponse, Subscription, SyncDataResponse,
|
||||||
};
|
};
|
||||||
use reqwest::header::{HeaderMap, HeaderValue, USER_AGENT};
|
use reqwest::header::{HeaderMap, HeaderValue, USER_AGENT};
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
|
use tokio::sync::Mutex;
|
||||||
|
|
||||||
|
// Create a PROGRESS mutex to hold the current sync progress, lazy initialized
|
||||||
|
lazy_static! {
|
||||||
|
pub static ref PROGRESS: Mutex<SyncProgress> = Mutex::new(SyncProgress::default());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||||
|
pub struct SyncProgress {
|
||||||
|
// Should contain the current progress of the sync operation
|
||||||
|
pub current_step: String,
|
||||||
|
pub percentage_done: u32,
|
||||||
|
pub current_count: u32,
|
||||||
|
pub total_count: u32,
|
||||||
|
pub complete: bool,
|
||||||
|
}
|
||||||
|
|
||||||
pub struct Fansly {
|
pub struct Fansly {
|
||||||
client: reqwest::Client,
|
client: reqwest::Client,
|
||||||
@ -170,6 +189,26 @@ impl Fansly {
|
|||||||
Ok(subscriptions.response.subscriptions)
|
Ok(subscriptions.response.subscriptions)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn update_progress(
|
||||||
|
&self,
|
||||||
|
current_step: impl Into<String>,
|
||||||
|
curr_count: u32,
|
||||||
|
total_count: u32,
|
||||||
|
complete: bool,
|
||||||
|
) {
|
||||||
|
let mut p = PROGRESS.lock().await;
|
||||||
|
p.current_step = current_step.into();
|
||||||
|
p.current_count = curr_count;
|
||||||
|
p.total_count = total_count;
|
||||||
|
p.percentage_done = if total_count > 0 {
|
||||||
|
curr_count * 100 / total_count
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
};
|
||||||
|
p.complete = complete;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
async fn upload_sync_data(&self, data: SyncDataResponse) -> Result<String, reqwest::Error> {
|
async fn upload_sync_data(&self, data: SyncDataResponse) -> Result<String, reqwest::Error> {
|
||||||
let url = "https://paste.fanslycreatorbot.com";
|
let url = "https://paste.fanslycreatorbot.com";
|
||||||
|
|
||||||
@ -273,7 +312,10 @@ impl Fansly {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn sync(&self, auto: bool) -> Result<SyncDataResponse, String> {
|
pub async fn sync(&mut self, auto: bool) -> Result<SyncDataResponse, String> {
|
||||||
|
// Reset progress
|
||||||
|
self.update_progress("Starting Sync".to_string(), 0, 100, false).await;
|
||||||
|
|
||||||
// Fetch profile
|
// Fetch profile
|
||||||
log::info!("[sync::process] Fetching profile...");
|
log::info!("[sync::process] Fetching profile...");
|
||||||
let profile = self.get_profile().await.map_err(|e| e.to_string())?;
|
let profile = self.get_profile().await.map_err(|e| e.to_string())?;
|
||||||
@ -313,14 +355,28 @@ impl Fansly {
|
|||||||
"[sync::process] Got {} followers from API.",
|
"[sync::process] Got {} followers from API.",
|
||||||
response.response.len()
|
response.response.len()
|
||||||
);
|
);
|
||||||
followers.extend(response.response);
|
followers.extend(response.response.clone());
|
||||||
offset += 100;
|
offset += 100;
|
||||||
total_requests += 1;
|
total_requests += 1;
|
||||||
|
|
||||||
|
// Update progress
|
||||||
|
self.update_progress(
|
||||||
|
"Fetching Followers".to_string(),
|
||||||
|
followers.len() as u32,
|
||||||
|
total_followers as u32,
|
||||||
|
false
|
||||||
|
).await;
|
||||||
|
|
||||||
// Every 10 requests, sleep for a bit to avoid rate limiting
|
// Every 10 requests, sleep for a bit to avoid rate limiting
|
||||||
if total_requests % 10 == 0 {
|
if total_requests % 10 == 0 {
|
||||||
tokio::time::sleep(tokio::time::Duration::from_secs(5)).await;
|
tokio::time::sleep(tokio::time::Duration::from_secs(5)).await;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If we've received no followers, break the loop
|
||||||
|
if response.response.is_empty() {
|
||||||
|
log::info!("[sync::process] No more followers found, breaking the loop.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fetch subscribers until we have all of them
|
// Fetch subscribers until we have all of them
|
||||||
@ -336,14 +392,28 @@ impl Fansly {
|
|||||||
.await
|
.await
|
||||||
.map_err(|e| e.to_string())?;
|
.map_err(|e| e.to_string())?;
|
||||||
|
|
||||||
subscribers.extend(response);
|
subscribers.extend(response.clone());
|
||||||
offset += 100;
|
offset += 100;
|
||||||
total_requests += 1;
|
total_requests += 1;
|
||||||
|
|
||||||
|
// Update progress
|
||||||
|
self.update_progress(
|
||||||
|
"Fetching Subscribers".to_string(),
|
||||||
|
subscribers.len() as u32,
|
||||||
|
total_subscribers as u32,
|
||||||
|
false
|
||||||
|
).await;
|
||||||
|
|
||||||
// Every 10 requests, sleep for a bit to avoid rate limiting
|
// Every 10 requests, sleep for a bit to avoid rate limiting
|
||||||
if total_requests % 10 == 0 {
|
if total_requests % 10 == 0 {
|
||||||
tokio::time::sleep(tokio::time::Duration::from_secs(5)).await;
|
tokio::time::sleep(tokio::time::Duration::from_secs(5)).await;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If we've received no subscribers, break the loop
|
||||||
|
if response.is_empty() {
|
||||||
|
log::info!("[sync::process] No more subscribers found, breaking the loop.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
log::info!(
|
log::info!(
|
||||||
@ -353,6 +423,10 @@ impl Fansly {
|
|||||||
);
|
);
|
||||||
|
|
||||||
log::info!("[sync::process] Sync complete.");
|
log::info!("[sync::process] Sync complete.");
|
||||||
|
|
||||||
|
// Reset progress
|
||||||
|
self.update_progress("Sync Complete".to_string(), 100, 100, true).await;
|
||||||
|
|
||||||
log::info!("[sync::process] Uploading sync data to paste.hep.gg for processing...");
|
log::info!("[sync::process] Uploading sync data to paste.hep.gg for processing...");
|
||||||
|
|
||||||
// Upload sync data to paste.hep.gg
|
// Upload sync data to paste.hep.gg
|
||||||
|
@ -11,7 +11,7 @@ use std::io;
|
|||||||
use commands::config::{get_config, init_config, save_config};
|
use commands::config::{get_config, init_config, save_config};
|
||||||
use commands::fansly::{
|
use commands::fansly::{
|
||||||
fansly_check_sync_token, fansly_get_me, fansly_set_token, fansly_sync,
|
fansly_check_sync_token, fansly_get_me, fansly_set_token, fansly_sync,
|
||||||
fansly_upload_auto_sync_data,
|
fansly_upload_auto_sync_data, fansly_get_sync_status
|
||||||
};
|
};
|
||||||
use commands::utils::quit;
|
use commands::utils::quit;
|
||||||
use tauri_plugin_autostart::MacosLauncher;
|
use tauri_plugin_autostart::MacosLauncher;
|
||||||
@ -66,7 +66,8 @@ async fn main() {
|
|||||||
fansly_get_me,
|
fansly_get_me,
|
||||||
fansly_sync,
|
fansly_sync,
|
||||||
fansly_upload_auto_sync_data,
|
fansly_upload_auto_sync_data,
|
||||||
fansly_check_sync_token
|
fansly_check_sync_token,
|
||||||
|
fansly_get_sync_status
|
||||||
])
|
])
|
||||||
.run(tauri::generate_context!())
|
.run(tauri::generate_context!())
|
||||||
.expect("error while running tauri application");
|
.expect("error while running tauri application");
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
|
/* eslint-disable @typescript-eslint/no-unused-vars */
|
||||||
import { info, error } from '@tauri-apps/plugin-log';
|
import { info, error } from '@tauri-apps/plugin-log';
|
||||||
import { awaiter } from '$lib/utils';
|
import { awaiter } from '$lib/utils';
|
||||||
import { onDestroy, onMount } from 'svelte';
|
import { onDestroy, onMount } from 'svelte';
|
||||||
@ -21,6 +22,7 @@
|
|||||||
appVersion: 'Loading...',
|
appVersion: 'Loading...',
|
||||||
tauriVersion: 'Loading...'
|
tauriVersion: 'Loading...'
|
||||||
};
|
};
|
||||||
|
|
||||||
let syncState = {
|
let syncState = {
|
||||||
show: false,
|
show: false,
|
||||||
syncing: false,
|
syncing: false,
|
||||||
@ -30,6 +32,14 @@
|
|||||||
message: ''
|
message: ''
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let syncProgress = {
|
||||||
|
currentStep: '',
|
||||||
|
percentage: 0,
|
||||||
|
current_count: 0,
|
||||||
|
total_count: 0,
|
||||||
|
complete: false
|
||||||
|
}
|
||||||
|
|
||||||
let isAutoSyncConfigModalOpen = false;
|
let isAutoSyncConfigModalOpen = false;
|
||||||
let canSave = false;
|
let canSave = false;
|
||||||
let config: Config | null = null;
|
let config: Config | null = null;
|
||||||
@ -47,14 +57,14 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
onMount(async () => {
|
onMount(async () => {
|
||||||
info(`[FanslySync::page_init:home] onMount() called. Starting page initialization...`);
|
await info(`[FanslySync::page_init:home] onMount() called. Starting page initialization...`);
|
||||||
const [configData, configError] = await awaiter(invoke('get_config') as Promise<Config>);
|
const [configData, configError] = await awaiter(invoke('get_config') as Promise<Config>);
|
||||||
|
|
||||||
if (configError || !configData) {
|
if (configError || !configData) {
|
||||||
error(
|
await error(
|
||||||
`[FanslySync::page_init:home] Failed to get configuration. Error: ${configError ?? 'Config was null'}`
|
`[FanslySync::page_init:home] Failed to get configuration. Error: ${configError ?? 'Config was null'}`
|
||||||
);
|
);
|
||||||
info(
|
await info(
|
||||||
`[FanslySync::page_init:home] Page Initialization failed due to configuration error. Exiting...`
|
`[FanslySync::page_init:home] Page Initialization failed due to configuration error. Exiting...`
|
||||||
);
|
);
|
||||||
await message(
|
await message(
|
||||||
@ -76,43 +86,48 @@
|
|||||||
loadingSync = false;
|
loadingSync = false;
|
||||||
|
|
||||||
const updateStatus = await check();
|
const updateStatus = await check();
|
||||||
upToDate = !updateStatus?.available ?? false;
|
|
||||||
|
// We are up to date if the update status is null
|
||||||
|
upToDate = updateStatus === null;
|
||||||
updateData = updateStatus;
|
updateData = updateStatus;
|
||||||
info(
|
|
||||||
|
await info(
|
||||||
`[FanslySync::page_init:home] Update check completed. Up to date: ${upToDate}, Update data: ${updateData}`
|
`[FanslySync::page_init:home] Update check completed. Up to date: ${upToDate}, Update data: ${updateData}`
|
||||||
);
|
);
|
||||||
info(`[FanslySync::page_init:home] Getting app and Tauri versions...`);
|
|
||||||
|
await info(`[FanslySync::page_init:home] Getting app and Tauri versions...`);
|
||||||
|
|
||||||
versionData.appVersion = await getVersion();
|
versionData.appVersion = await getVersion();
|
||||||
versionData.tauriVersion = await getTauriVersion();
|
versionData.tauriVersion = await getTauriVersion();
|
||||||
|
|
||||||
info(
|
await info(
|
||||||
`[FanslySync::page_init:home] App and Tauri versions fetched. We are running App version: ${versionData.appVersion}, atop Tauri version: ${versionData.tauriVersion}`
|
`[FanslySync::page_init:home] App and Tauri versions fetched. We are running App version: ${versionData.appVersion}, atop Tauri version: ${versionData.tauriVersion}`
|
||||||
);
|
);
|
||||||
|
|
||||||
info(`[FanslySync::page_init:home] Setting up autosync interval...`);
|
await info(`[FanslySync::page_init:home] Setting up autosync interval...`);
|
||||||
syncInterval = setInterval(
|
syncInterval = setInterval(
|
||||||
async () => {
|
async () => {
|
||||||
if (config?.auto_sync_enabled) {
|
if (config?.auto_sync_enabled) {
|
||||||
info(`[FanslySync::autoSyncProcess] Auto Sync enabled - syncing data automatically.`);
|
await info(`[FanslySync::autoSyncProcess] Auto Sync enabled - syncing data automatically.`);
|
||||||
const nextIntervalTime = new Date(
|
const nextIntervalTime = new Date(
|
||||||
Date.now() + (config?.sync_interval ?? 1) * 60 * 60 * 1000
|
Date.now() + (config?.sync_interval ?? 1) * 60 * 60 * 1000
|
||||||
);
|
);
|
||||||
const nextIntervalTimeString = nextIntervalTime.toLocaleTimeString();
|
const nextIntervalTimeString = nextIntervalTime.toLocaleTimeString();
|
||||||
const returnedData = await syncNow(true);
|
const returnedData = await syncNow(true);
|
||||||
if (!returnedData || returnedData === null) {
|
if (!returnedData || returnedData === null) {
|
||||||
error(`[FanslySync::autoSyncProcess] Failed to sync data automatically.`);
|
await error(`[FanslySync::autoSyncProcess] Failed to sync data automatically.`);
|
||||||
|
|
||||||
// Send error notification
|
// Send error notification
|
||||||
await sendNotification({
|
sendNotification({
|
||||||
title: 'FanslySync: Auto Sync Failed!',
|
title: 'FanslySync: Auto Sync Failed!',
|
||||||
body: `An error occurred while syncing data automatically. We will automatically retry at ${nextIntervalTimeString}.`
|
body: `An error occurred while syncing data automatically. We will automatically retry at ${nextIntervalTimeString}.`
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
info(
|
await info(
|
||||||
`[FanslySync::autoSyncProcess] Synced data automatically - preparing to send to server.`
|
`[FanslySync::autoSyncProcess] Synced data automatically - preparing to send to server.`
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
const [_, uploadErr] = await awaiter(
|
const [_, uploadErr] = await awaiter(
|
||||||
invoke('fansly_upload_auto_sync_data', {
|
invoke('fansly_upload_auto_sync_data', {
|
||||||
token: config?.sync_token,
|
token: config?.sync_token,
|
||||||
@ -121,12 +136,12 @@
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (uploadErr) {
|
if (uploadErr) {
|
||||||
error(
|
await error(
|
||||||
`[FanslySync::autoSyncProcess] Failed to upload data to server. Error: ${uploadErr}`
|
`[FanslySync::autoSyncProcess] Failed to upload data to server. Error: ${uploadErr}`
|
||||||
);
|
);
|
||||||
|
|
||||||
// Send error notification
|
// Send error notification
|
||||||
await sendNotification({
|
sendNotification({
|
||||||
title: 'FanslySync: Auto Sync Failed!',
|
title: 'FanslySync: Auto Sync Failed!',
|
||||||
body: `An error occurred while uploading data to the server. We will automatically retry at ${nextIntervalTimeString}.`
|
body: `An error occurred while uploading data to the server. We will automatically retry at ${nextIntervalTimeString}.`
|
||||||
});
|
});
|
||||||
@ -135,29 +150,53 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Send success notification
|
// Send success notification
|
||||||
await sendNotification({
|
sendNotification({
|
||||||
title: 'FanslySync: Auto Sync Successful!',
|
title: 'FanslySync: Auto Sync Successful!',
|
||||||
body: `Data synced and uploaded successfully. Next sync will occur at ${nextIntervalTimeString}.`
|
body: `Data synced and uploaded successfully. Next sync will occur at ${nextIntervalTimeString}.`
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
info(`[FanslySync::autoSyncProcess] Auto Sync disabled - skipping this sync.`);
|
await info(`[FanslySync::autoSyncProcess] Auto Sync disabled - skipping this sync.`);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
(config?.sync_interval ?? 1) * 60 * 60 * 1000
|
(config?.sync_interval ?? 1) * 60 * 60 * 1000
|
||||||
);
|
);
|
||||||
|
|
||||||
info(`[FanslySync::page_init:home] Autosync interval set successfully.`);
|
await info(`[FanslySync::page_init:home] Autosync interval set successfully.`);
|
||||||
info(`[FanslySync::page_init:home] Page initialization completed successfully.`);
|
await info(`[FanslySync::page_init:home] Page initialization completed successfully.`);
|
||||||
});
|
});
|
||||||
|
|
||||||
async function syncNow(auto: boolean = false) {
|
async function syncNow(auto: boolean = false) {
|
||||||
info(`[FanslySync::syncNow] Starting manual sync...`);
|
await info(`[FanslySync::syncNow] Starting manual sync...`);
|
||||||
|
|
||||||
syncState.error = false;
|
syncState.error = false;
|
||||||
syncState.success = false;
|
syncState.success = false;
|
||||||
syncState.syncing = true;
|
syncState.syncing = true;
|
||||||
syncState.show = !auto;
|
syncState.show = true;
|
||||||
|
|
||||||
|
const updateThread = setInterval(async () => {
|
||||||
|
const [progress, progressErr] = await awaiter<{
|
||||||
|
current_step: string;
|
||||||
|
percentage_done: number;
|
||||||
|
current_count: number;
|
||||||
|
total_count: number;
|
||||||
|
complete: boolean;
|
||||||
|
}>(invoke('fansly_get_sync_status'))
|
||||||
|
|
||||||
|
if (progressErr || !progress) {
|
||||||
|
await error(`[FanslySync::syncNow] Failed to get sync status. Error: ${progressErr} or progress was null.`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
syncProgress.currentStep = progress.current_step;
|
||||||
|
syncProgress.percentage = progress.percentage_done;
|
||||||
|
syncProgress.current_count = progress.current_count;
|
||||||
|
syncProgress.total_count = progress.total_count;
|
||||||
|
|
||||||
|
await info(`[FanslySync::syncNow] Sync progress updated: ${JSON.stringify(syncProgress)}`);
|
||||||
|
console.log(`[FanslySync::syncNow] Sync progress updated: ${JSON.stringify(syncProgress)}`);
|
||||||
|
}, 1000);
|
||||||
|
|
||||||
|
|
||||||
const [syncData, syncError] = await awaiter(
|
const [syncData, syncError] = await awaiter(
|
||||||
invoke('fansly_sync', {
|
invoke('fansly_sync', {
|
||||||
@ -165,8 +204,10 @@
|
|||||||
}) as Promise<SyncData>
|
}) as Promise<SyncData>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
clearInterval(updateThread);
|
||||||
|
|
||||||
if (syncError || syncData === null) {
|
if (syncError || syncData === null) {
|
||||||
error(
|
await error(
|
||||||
`[FanslySync::syncNow] Failed to sync data. Error: ${syncError ?? 'Sync data was null'}`
|
`[FanslySync::syncNow] Failed to sync data. Error: ${syncError ?? 'Sync data was null'}`
|
||||||
);
|
);
|
||||||
syncState.syncing = false;
|
syncState.syncing = false;
|
||||||
@ -174,7 +215,7 @@
|
|||||||
syncState.message = syncError ?? 'Sync data was null';
|
syncState.message = syncError ?? 'Sync data was null';
|
||||||
|
|
||||||
// Send failure notification
|
// Send failure notification
|
||||||
await sendNotification({
|
sendNotification({
|
||||||
title: 'FanslySync: Sync Failed!',
|
title: 'FanslySync: Sync Failed!',
|
||||||
body: 'An error occurred while syncing data. Please check the app for more details.'
|
body: 'An error occurred while syncing data. Please check the app for more details.'
|
||||||
});
|
});
|
||||||
@ -188,17 +229,17 @@
|
|||||||
config!.last_sync = Date.now();
|
config!.last_sync = Date.now();
|
||||||
config!.last_sync_data = syncData!;
|
config!.last_sync_data = syncData!;
|
||||||
|
|
||||||
const [saveConfigData, saveConfigError] = await awaiter(
|
const [, saveConfigError] = await awaiter(
|
||||||
invoke('save_config', { config }) as Promise<boolean>
|
invoke('save_config', { config }) as Promise<boolean>
|
||||||
);
|
);
|
||||||
if (saveConfigError) {
|
if (saveConfigError) {
|
||||||
error(`[FanslySync::syncNow] Failed to save config data. Error: ${saveConfigError}`);
|
await error(`[FanslySync::syncNow] Failed to save config data. Error: ${saveConfigError}`);
|
||||||
syncState.syncing = false;
|
syncState.syncing = false;
|
||||||
syncState.error = true;
|
syncState.error = true;
|
||||||
syncState.message = saveConfigError ?? 'Save config data was null';
|
syncState.message = saveConfigError ?? 'Save config data was null';
|
||||||
|
|
||||||
// Send failure notification
|
// Send failure notification
|
||||||
await sendNotification({
|
sendNotification({
|
||||||
title: 'FanslySync: Sync Failed!',
|
title: 'FanslySync: Sync Failed!',
|
||||||
body: 'An error occurred while syncing data. Please check the app for more details.'
|
body: 'An error occurred while syncing data. Please check the app for more details.'
|
||||||
});
|
});
|
||||||
@ -220,21 +261,29 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!auto)
|
if (!auto)
|
||||||
await sendNotification({
|
sendNotification({
|
||||||
title: 'FanslySync: Sync Successful!',
|
title: 'FanslySync: Sync Successful!',
|
||||||
body: 'Data synced successfully. Please look at the app for more details.',
|
body: 'Data synced successfully. Please look at the app for more details.',
|
||||||
sound: soundName
|
sound: soundName
|
||||||
});
|
});
|
||||||
|
|
||||||
info(`[FanslySync::syncNow] Manual sync completed successfully.`);
|
await info(`[FanslySync::syncNow] Manual sync completed successfully.`);
|
||||||
|
|
||||||
|
if (auto) {
|
||||||
|
setTimeout(() => {
|
||||||
|
syncState.show = false;
|
||||||
|
}, 5000);
|
||||||
|
}
|
||||||
|
|
||||||
if (auto) return syncData;
|
if (auto) return syncData;
|
||||||
else return null;
|
else return null;
|
||||||
|
|
||||||
|
// If auto is true, auto-hide the sync state after 5 seconds
|
||||||
}
|
}
|
||||||
|
|
||||||
async function doUpdate() {
|
async function doUpdate() {
|
||||||
if (!updateData || !updateData.available) {
|
if (!updateData || !updateData.available) {
|
||||||
message('You are up to date! Current version: ' + versionData.appVersion, {
|
await message('You are up to date! Current version: ' + versionData.appVersion, {
|
||||||
title: 'FanslySync | Update',
|
title: 'FanslySync | Update',
|
||||||
kind: 'info'
|
kind: 'info'
|
||||||
});
|
});
|
||||||
@ -303,6 +352,8 @@
|
|||||||
|
|
||||||
// Enable autosync
|
// Enable autosync
|
||||||
config!.auto_sync_enabled = !config?.auto_sync_enabled;
|
config!.auto_sync_enabled = !config?.auto_sync_enabled;
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
const [_, saveConfigError] = await awaiter(invoke('save_config', { config }));
|
const [_, saveConfigError] = await awaiter(invoke('save_config', { config }));
|
||||||
|
|
||||||
if (saveConfigError) {
|
if (saveConfigError) {
|
||||||
@ -485,16 +536,16 @@
|
|||||||
const [_, saveConfigError] = await awaiter(invoke('save_config', { config }));
|
const [_, saveConfigError] = await awaiter(invoke('save_config', { config }));
|
||||||
|
|
||||||
if (saveConfigError) {
|
if (saveConfigError) {
|
||||||
await toast.error('Failed to save Auto Sync configuration. Please try again.', {
|
toast.error('Failed to save Auto Sync configuration. Please try again.', {
|
||||||
id: savingToast
|
id: savingToast
|
||||||
});
|
});
|
||||||
error(
|
await error(
|
||||||
`[FanslySync::onAutoSyncSave] Failed to save Auto Sync configuration. Error: ${saveConfigError}`
|
`[FanslySync::onAutoSyncSave] Failed to save Auto Sync configuration. Error: ${saveConfigError}`
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
info(`[FanslySync::onAutoSyncSave] Auto Sync configuration saved successfully.`);
|
await info(`[FanslySync::onAutoSyncSave] Auto Sync configuration saved successfully.`);
|
||||||
await toast.success('Auto Sync configuration saved successfully.', { id: savingToast });
|
toast.success('Auto Sync configuration saved successfully.', { id: savingToast });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -515,6 +566,7 @@
|
|||||||
autoSyncConfig.didRunInitialValidation = true;
|
autoSyncConfig.didRunInitialValidation = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
|
||||||
function useDebounce(fn: Function, delay: number) {
|
function useDebounce(fn: Function, delay: number) {
|
||||||
let timeout: number;
|
let timeout: number;
|
||||||
return function (...args: any) {
|
return function (...args: any) {
|
||||||
@ -813,8 +865,8 @@
|
|||||||
<div class="flex flex-col">
|
<div class="flex flex-col">
|
||||||
<h1 class="text-lg font-bold">Syncing...</h1>
|
<h1 class="text-lg font-bold">Syncing...</h1>
|
||||||
<p class="text-sm">
|
<p class="text-sm">
|
||||||
Please wait while we sync your followers and subscriber data. This can take awhile on
|
We are currently {syncProgress.currentStep}. We've processed {syncProgress.current_count} of {syncProgress.total_count} items so far. We
|
||||||
some connections.
|
are about {syncProgress.percentage}% done with this step.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
{:else if syncState.success}
|
{:else if syncState.success}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user