refactor(v2): inline offline status, settings, and pending playlist delegates
Inlines bodies of get_offline_status, get_offline_settings, set_manual_offline, check_network, and get_pending_playlists from offline::commands directly into the v2 wrappers in commands_v2/library.rs. Deletes the entire offline::commands submodule (the inlined commands and the additional dead Tauri command shims that lived alongside them — none were registered with Tauri or referenced outside the submodule). Prunes the now-unused tauri AppHandle/Emitter imports from offline/mod.rs. Step 8 of legacy cleanup, group H. cc
This commit is contained in:
2 files changed
+153
-372
No files matched your search
@@ -1296,14 +1296,56 @@ pub fn v2_set_show_network_folders_in_manual_offline(
|
|||||||
pub async fn v2_get_offline_status(
|
pub async fn v2_get_offline_status(
|
||||||
state: State<'_, OfflineState>,
|
state: State<'_, OfflineState>,
|
||||||
) -> Result<crate::offline::OfflineStatus, String> {
|
) -> Result<crate::offline::OfflineStatus, String> {
|
||||||
crate::offline::commands::get_offline_status(state).await
|
let settings = {
|
||||||
|
let guard__ = state
|
||||||
|
.store
|
||||||
|
.lock()
|
||||||
|
.map_err(|e| format!("Lock error: {}", e))?;
|
||||||
|
let store = guard__
|
||||||
|
.as_ref()
|
||||||
|
.ok_or("No active session - please log in")?;
|
||||||
|
store.get_settings()?
|
||||||
|
};
|
||||||
|
|
||||||
|
// If manual offline mode is enabled, return immediately
|
||||||
|
if settings.manual_offline_mode {
|
||||||
|
return Ok(crate::offline::OfflineStatus {
|
||||||
|
is_offline: true,
|
||||||
|
reason: Some(crate::offline::OfflineReason::ManualOverride),
|
||||||
|
manual_mode_enabled: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check network connectivity
|
||||||
|
let has_network = crate::offline::check_network_connectivity().await;
|
||||||
|
|
||||||
|
if !has_network {
|
||||||
|
return Ok(crate::offline::OfflineStatus {
|
||||||
|
is_offline: true,
|
||||||
|
reason: Some(crate::offline::OfflineReason::NoNetwork),
|
||||||
|
manual_mode_enabled: false,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(crate::offline::OfflineStatus {
|
||||||
|
is_offline: false,
|
||||||
|
reason: None,
|
||||||
|
manual_mode_enabled: false,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
pub fn v2_get_offline_settings(
|
pub fn v2_get_offline_settings(
|
||||||
state: State<'_, OfflineState>,
|
state: State<'_, OfflineState>,
|
||||||
) -> Result<crate::offline::OfflineSettings, String> {
|
) -> Result<crate::offline::OfflineSettings, String> {
|
||||||
crate::offline::commands::get_offline_settings(state)
|
let guard__ = state
|
||||||
|
.store
|
||||||
|
.lock()
|
||||||
|
.map_err(|e| format!("Lock error: {}", e))?;
|
||||||
|
let store = guard__
|
||||||
|
.as_ref()
|
||||||
|
.ok_or("No active session - please log in")?;
|
||||||
|
store.get_settings()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
@@ -1313,12 +1355,111 @@ pub async fn v2_set_manual_offline(
|
|||||||
audio_state: State<'_, crate::config::audio_settings::AudioSettingsState>,
|
audio_state: State<'_, crate::config::audio_settings::AudioSettingsState>,
|
||||||
app_handle: tauri::AppHandle,
|
app_handle: tauri::AppHandle,
|
||||||
) -> Result<crate::offline::OfflineStatus, String> {
|
) -> Result<crate::offline::OfflineStatus, String> {
|
||||||
crate::offline::commands::set_manual_offline(enabled, state, audio_state, app_handle).await
|
use tauri::Emitter;
|
||||||
|
|
||||||
|
// 1) Persist the manual offline flag first so any concurrent reads
|
||||||
|
// see the new mode immediately.
|
||||||
|
let (was_offline, stream_first_before): (bool, Option<bool>) = {
|
||||||
|
let guard__ = state
|
||||||
|
.store
|
||||||
|
.lock()
|
||||||
|
.map_err(|e| format!("Lock error: {}", e))?;
|
||||||
|
let store = guard__
|
||||||
|
.as_ref()
|
||||||
|
.ok_or("No active session - please log in")?;
|
||||||
|
let prev = store
|
||||||
|
.get_settings()
|
||||||
|
.map(|s| s.manual_offline_mode)
|
||||||
|
.unwrap_or(false);
|
||||||
|
let snapshot = store
|
||||||
|
.get_pre_offline_stream_first_track()
|
||||||
|
.unwrap_or(None);
|
||||||
|
store.set_manual_offline_mode(enabled)?;
|
||||||
|
(prev, snapshot)
|
||||||
|
};
|
||||||
|
|
||||||
|
// 2) Coordinate the stream_first_track snapshot/restore. This is best-
|
||||||
|
// effort — if the audio store isn't initialized yet (pre-login), we
|
||||||
|
// just skip; the offline flag itself has been persisted.
|
||||||
|
if enabled && !was_offline {
|
||||||
|
// Entering offline mode: stash current value and force to false.
|
||||||
|
let current = {
|
||||||
|
let guard = audio_state
|
||||||
|
.store
|
||||||
|
.lock()
|
||||||
|
.map_err(|e| format!("Audio settings lock error: {}", e))?;
|
||||||
|
guard
|
||||||
|
.as_ref()
|
||||||
|
.and_then(|s| s.get_settings().ok())
|
||||||
|
.map(|s| s.stream_first_track)
|
||||||
|
};
|
||||||
|
if let Some(current_value) = current {
|
||||||
|
{
|
||||||
|
let guard = state
|
||||||
|
.store
|
||||||
|
.lock()
|
||||||
|
.map_err(|e| format!("Lock error: {}", e))?;
|
||||||
|
if let Some(store) = guard.as_ref() {
|
||||||
|
let _ = store.set_pre_offline_stream_first_track(Some(current_value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if current_value {
|
||||||
|
let guard = audio_state
|
||||||
|
.store
|
||||||
|
.lock()
|
||||||
|
.map_err(|e| format!("Audio settings lock error: {}", e))?;
|
||||||
|
if let Some(store) = guard.as_ref() {
|
||||||
|
let _ = store.set_stream_first_track(false);
|
||||||
|
log::info!(
|
||||||
|
"[Offline] stream_first_track snapshot={}; forced to false while offline",
|
||||||
|
current_value
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if !enabled && was_offline {
|
||||||
|
// Exiting offline mode: restore snapshot if we have one.
|
||||||
|
if let Some(snapshot_value) = stream_first_before {
|
||||||
|
{
|
||||||
|
let guard = audio_state
|
||||||
|
.store
|
||||||
|
.lock()
|
||||||
|
.map_err(|e| format!("Audio settings lock error: {}", e))?;
|
||||||
|
if let Some(store) = guard.as_ref() {
|
||||||
|
let _ = store.set_stream_first_track(snapshot_value);
|
||||||
|
log::info!(
|
||||||
|
"[Offline] restored stream_first_track to {}",
|
||||||
|
snapshot_value
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{
|
||||||
|
let guard = state
|
||||||
|
.store
|
||||||
|
.lock()
|
||||||
|
.map_err(|e| format!("Lock error: {}", e))?;
|
||||||
|
if let Some(store) = guard.as_ref() {
|
||||||
|
let _ = store.set_pre_offline_stream_first_track(None);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3) Get updated status
|
||||||
|
let status = v2_get_offline_status(state).await?;
|
||||||
|
|
||||||
|
// 4) Emit events. offline-status-changed for the offline store;
|
||||||
|
// audio-settings-changed so the SettingsView reloads its local
|
||||||
|
// state of stream_first_track (we may have just mutated it).
|
||||||
|
let _ = app_handle.emit("offline-status-changed", &status);
|
||||||
|
let _ = app_handle.emit("audio-settings-changed", ());
|
||||||
|
|
||||||
|
Ok(status)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
pub async fn v2_check_network() -> bool {
|
pub async fn v2_check_network() -> bool {
|
||||||
crate::offline::commands::check_network().await
|
crate::offline::check_network_connectivity().await
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
@@ -1391,7 +1532,14 @@ pub fn v2_mark_scrobbles_sent(ids: Vec<i64>, state: State<'_, OfflineState>) ->
|
|||||||
pub fn v2_get_pending_playlists(
|
pub fn v2_get_pending_playlists(
|
||||||
state: State<'_, OfflineState>,
|
state: State<'_, OfflineState>,
|
||||||
) -> Result<Vec<crate::offline::PendingPlaylist>, String> {
|
) -> Result<Vec<crate::offline::PendingPlaylist>, String> {
|
||||||
crate::offline::commands::get_pending_playlists(state)
|
let guard__ = state
|
||||||
|
.store
|
||||||
|
.lock()
|
||||||
|
.map_err(|e| format!("Lock error: {}", e))?;
|
||||||
|
let store = guard__
|
||||||
|
.as_ref()
|
||||||
|
.ok_or("No active session - please log in")?;
|
||||||
|
store.get_pending_playlists()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ use rusqlite::{params, Connection};
|
|||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use tauri::{AppHandle, Emitter};
|
|
||||||
|
|
||||||
/// Reason why the app is in offline mode
|
/// Reason why the app is in offline mode
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
|
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
|
||||||
@@ -670,369 +669,3 @@ pub async fn check_network_connectivity() -> bool {
|
|||||||
log::info!("Network connectivity check failed after all attempts");
|
log::info!("Network connectivity check failed after all attempts");
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tauri commands
|
|
||||||
pub mod commands {
|
|
||||||
use super::*;
|
|
||||||
use tauri::State;
|
|
||||||
|
|
||||||
/// Get current offline status
|
|
||||||
/// Note: Login state is not checked here because the frontend already handles
|
|
||||||
/// showing LoginView when not logged in. This prevents race conditions on startup.
|
|
||||||
#[tauri::command]
|
|
||||||
pub async fn get_offline_status(
|
|
||||||
offline_state: State<'_, OfflineState>,
|
|
||||||
) -> Result<OfflineStatus, String> {
|
|
||||||
let settings = {
|
|
||||||
let guard__ = offline_state
|
|
||||||
.store
|
|
||||||
.lock()
|
|
||||||
.map_err(|e| format!("Lock error: {}", e))?;
|
|
||||||
let store = guard__
|
|
||||||
.as_ref()
|
|
||||||
.ok_or("No active session - please log in")?;
|
|
||||||
store.get_settings()?
|
|
||||||
};
|
|
||||||
|
|
||||||
// If manual offline mode is enabled, return immediately
|
|
||||||
if settings.manual_offline_mode {
|
|
||||||
return Ok(OfflineStatus {
|
|
||||||
is_offline: true,
|
|
||||||
reason: Some(OfflineReason::ManualOverride),
|
|
||||||
manual_mode_enabled: true,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check network connectivity
|
|
||||||
let has_network = check_network_connectivity().await;
|
|
||||||
|
|
||||||
if !has_network {
|
|
||||||
return Ok(OfflineStatus {
|
|
||||||
is_offline: true,
|
|
||||||
reason: Some(OfflineReason::NoNetwork),
|
|
||||||
manual_mode_enabled: false,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(OfflineStatus {
|
|
||||||
is_offline: false,
|
|
||||||
reason: None,
|
|
||||||
manual_mode_enabled: false,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get offline settings
|
|
||||||
#[tauri::command]
|
|
||||||
pub fn get_offline_settings(state: State<'_, OfflineState>) -> Result<OfflineSettings, String> {
|
|
||||||
let guard__ = state
|
|
||||||
.store
|
|
||||||
.lock()
|
|
||||||
.map_err(|e| format!("Lock error: {}", e))?;
|
|
||||||
let store = guard__
|
|
||||||
.as_ref()
|
|
||||||
.ok_or("No active session - please log in")?;
|
|
||||||
store.get_settings()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Enable or disable manual offline mode.
|
|
||||||
///
|
|
||||||
/// When entering offline mode, snapshots the user's current
|
|
||||||
/// `stream_first_track` audio setting and forces it to `false` so the
|
|
||||||
/// player won't attempt a network pre-buffer. When exiting, restores the
|
|
||||||
/// snapshot. This makes "offline mode" mean what it says — issue #279.
|
|
||||||
#[tauri::command]
|
|
||||||
pub async fn set_manual_offline(
|
|
||||||
enabled: bool,
|
|
||||||
state: State<'_, OfflineState>,
|
|
||||||
audio_state: State<'_, crate::config::audio_settings::AudioSettingsState>,
|
|
||||||
app_handle: AppHandle,
|
|
||||||
) -> Result<OfflineStatus, String> {
|
|
||||||
// 1) Persist the manual offline flag first so any concurrent reads
|
|
||||||
// see the new mode immediately.
|
|
||||||
let (was_offline, stream_first_before): (bool, Option<bool>) = {
|
|
||||||
let guard__ = state
|
|
||||||
.store
|
|
||||||
.lock()
|
|
||||||
.map_err(|e| format!("Lock error: {}", e))?;
|
|
||||||
let store = guard__
|
|
||||||
.as_ref()
|
|
||||||
.ok_or("No active session - please log in")?;
|
|
||||||
let prev = store
|
|
||||||
.get_settings()
|
|
||||||
.map(|s| s.manual_offline_mode)
|
|
||||||
.unwrap_or(false);
|
|
||||||
let snapshot = store
|
|
||||||
.get_pre_offline_stream_first_track()
|
|
||||||
.unwrap_or(None);
|
|
||||||
store.set_manual_offline_mode(enabled)?;
|
|
||||||
(prev, snapshot)
|
|
||||||
};
|
|
||||||
|
|
||||||
// 2) Coordinate the stream_first_track snapshot/restore. This is best-
|
|
||||||
// effort — if the audio store isn't initialized yet (pre-login), we
|
|
||||||
// just skip; the offline flag itself has been persisted.
|
|
||||||
if enabled && !was_offline {
|
|
||||||
// Entering offline mode: stash current value and force to false.
|
|
||||||
let current = {
|
|
||||||
let guard = audio_state
|
|
||||||
.store
|
|
||||||
.lock()
|
|
||||||
.map_err(|e| format!("Audio settings lock error: {}", e))?;
|
|
||||||
guard
|
|
||||||
.as_ref()
|
|
||||||
.and_then(|s| s.get_settings().ok())
|
|
||||||
.map(|s| s.stream_first_track)
|
|
||||||
};
|
|
||||||
if let Some(current_value) = current {
|
|
||||||
{
|
|
||||||
let guard = state
|
|
||||||
.store
|
|
||||||
.lock()
|
|
||||||
.map_err(|e| format!("Lock error: {}", e))?;
|
|
||||||
if let Some(store) = guard.as_ref() {
|
|
||||||
let _ = store.set_pre_offline_stream_first_track(Some(current_value));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if current_value {
|
|
||||||
let guard = audio_state
|
|
||||||
.store
|
|
||||||
.lock()
|
|
||||||
.map_err(|e| format!("Audio settings lock error: {}", e))?;
|
|
||||||
if let Some(store) = guard.as_ref() {
|
|
||||||
let _ = store.set_stream_first_track(false);
|
|
||||||
log::info!(
|
|
||||||
"[Offline] stream_first_track snapshot={}; forced to false while offline",
|
|
||||||
current_value
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if !enabled && was_offline {
|
|
||||||
// Exiting offline mode: restore snapshot if we have one.
|
|
||||||
if let Some(snapshot_value) = stream_first_before {
|
|
||||||
{
|
|
||||||
let guard = audio_state
|
|
||||||
.store
|
|
||||||
.lock()
|
|
||||||
.map_err(|e| format!("Audio settings lock error: {}", e))?;
|
|
||||||
if let Some(store) = guard.as_ref() {
|
|
||||||
let _ = store.set_stream_first_track(snapshot_value);
|
|
||||||
log::info!(
|
|
||||||
"[Offline] restored stream_first_track to {}",
|
|
||||||
snapshot_value
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
{
|
|
||||||
let guard = state
|
|
||||||
.store
|
|
||||||
.lock()
|
|
||||||
.map_err(|e| format!("Lock error: {}", e))?;
|
|
||||||
if let Some(store) = guard.as_ref() {
|
|
||||||
let _ = store.set_pre_offline_stream_first_track(None);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 3) Get updated status
|
|
||||||
let status = get_offline_status(state).await?;
|
|
||||||
|
|
||||||
// 4) Emit events. offline-status-changed for the offline store;
|
|
||||||
// audio-settings-changed so the SettingsView reloads its local
|
|
||||||
// state of stream_first_track (we may have just mutated it).
|
|
||||||
let _ = app_handle.emit("offline-status-changed", &status);
|
|
||||||
let _ = app_handle.emit("audio-settings-changed", ());
|
|
||||||
|
|
||||||
Ok(status)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Set whether to show playlists with partial local content in offline mode
|
|
||||||
#[tauri::command]
|
|
||||||
pub fn set_show_partial_playlists(
|
|
||||||
enabled: bool,
|
|
||||||
state: State<'_, OfflineState>,
|
|
||||||
) -> Result<(), String> {
|
|
||||||
let guard__ = state
|
|
||||||
.store
|
|
||||||
.lock()
|
|
||||||
.map_err(|e| format!("Lock error: {}", e))?;
|
|
||||||
let store = guard__
|
|
||||||
.as_ref()
|
|
||||||
.ok_or("No active session - please log in")?;
|
|
||||||
store.set_show_partial_playlists(enabled)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Set whether to allow Chromecast while in manual offline mode
|
|
||||||
#[tauri::command]
|
|
||||||
pub fn set_allow_cast_while_offline(
|
|
||||||
enabled: bool,
|
|
||||||
state: State<'_, OfflineState>,
|
|
||||||
) -> Result<(), String> {
|
|
||||||
let guard__ = state
|
|
||||||
.store
|
|
||||||
.lock()
|
|
||||||
.map_err(|e| format!("Lock error: {}", e))?;
|
|
||||||
let store = guard__
|
|
||||||
.as_ref()
|
|
||||||
.ok_or("No active session - please log in")?;
|
|
||||||
store.set_allow_cast_while_offline(enabled)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Set whether to allow immediate scrobbling to Last.fm in manual offline mode
|
|
||||||
#[tauri::command]
|
|
||||||
pub fn set_allow_immediate_scrobbling(
|
|
||||||
enabled: bool,
|
|
||||||
state: State<'_, OfflineState>,
|
|
||||||
) -> Result<(), String> {
|
|
||||||
let guard__ = state
|
|
||||||
.store
|
|
||||||
.lock()
|
|
||||||
.map_err(|e| format!("Lock error: {}", e))?;
|
|
||||||
let store = guard__
|
|
||||||
.as_ref()
|
|
||||||
.ok_or("No active session - please log in")?;
|
|
||||||
store.set_allow_immediate_scrobbling(enabled)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Set whether to queue scrobbles for later submission when back online
|
|
||||||
#[tauri::command]
|
|
||||||
pub fn set_allow_accumulated_scrobbling(
|
|
||||||
enabled: bool,
|
|
||||||
state: State<'_, OfflineState>,
|
|
||||||
) -> Result<(), String> {
|
|
||||||
let guard__ = state
|
|
||||||
.store
|
|
||||||
.lock()
|
|
||||||
.map_err(|e| format!("Lock error: {}", e))?;
|
|
||||||
let store = guard__
|
|
||||||
.as_ref()
|
|
||||||
.ok_or("No active session - please log in")?;
|
|
||||||
store.set_allow_accumulated_scrobbling(enabled)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Set whether to show network folder content in manual offline mode
|
|
||||||
#[tauri::command]
|
|
||||||
pub fn set_show_network_folders_in_manual_offline(
|
|
||||||
enabled: bool,
|
|
||||||
state: State<'_, OfflineState>,
|
|
||||||
) -> Result<(), String> {
|
|
||||||
let guard__ = state
|
|
||||||
.store
|
|
||||||
.lock()
|
|
||||||
.map_err(|e| format!("Lock error: {}", e))?;
|
|
||||||
let store = guard__
|
|
||||||
.as_ref()
|
|
||||||
.ok_or("No active session - please log in")?;
|
|
||||||
store.set_show_network_folders_in_manual_offline(enabled)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Check if network connectivity is available
|
|
||||||
#[tauri::command]
|
|
||||||
pub async fn check_network() -> bool {
|
|
||||||
super::check_network_connectivity().await
|
|
||||||
}
|
|
||||||
|
|
||||||
// === Pending Playlist Sync Commands ===
|
|
||||||
|
|
||||||
/// Get all playlists pending sync
|
|
||||||
#[tauri::command]
|
|
||||||
pub fn get_pending_playlists(
|
|
||||||
state: State<'_, OfflineState>,
|
|
||||||
) -> Result<Vec<PendingPlaylist>, String> {
|
|
||||||
let guard__ = state
|
|
||||||
.store
|
|
||||||
.lock()
|
|
||||||
.map_err(|e| format!("Lock error: {}", e))?;
|
|
||||||
let store = guard__
|
|
||||||
.as_ref()
|
|
||||||
.ok_or("No active session - please log in")?;
|
|
||||||
store.get_pending_playlists()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Add tracks to a pending playlist
|
|
||||||
#[tauri::command]
|
|
||||||
pub fn add_tracks_to_pending_playlist(
|
|
||||||
pending_id: i64,
|
|
||||||
qobuz_track_ids: Vec<u64>,
|
|
||||||
local_track_paths: Vec<String>,
|
|
||||||
state: State<'_, OfflineState>,
|
|
||||||
) -> Result<(), String> {
|
|
||||||
let guard__ = state
|
|
||||||
.store
|
|
||||||
.lock()
|
|
||||||
.map_err(|e| format!("Lock error: {}", e))?;
|
|
||||||
let store = guard__
|
|
||||||
.as_ref()
|
|
||||||
.ok_or("No active session - please log in")?;
|
|
||||||
store.add_tracks_to_pending_playlist(pending_id, &qobuz_track_ids, &local_track_paths)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Update Qobuz playlist ID without marking as synced (for partial sync recovery)
|
|
||||||
#[tauri::command]
|
|
||||||
pub fn update_pending_playlist_qobuz_id(
|
|
||||||
pending_id: i64,
|
|
||||||
qobuz_playlist_id: u64,
|
|
||||||
state: State<'_, OfflineState>,
|
|
||||||
) -> Result<(), String> {
|
|
||||||
let guard__ = state
|
|
||||||
.store
|
|
||||||
.lock()
|
|
||||||
.map_err(|e| format!("Lock error: {}", e))?;
|
|
||||||
let store = guard__
|
|
||||||
.as_ref()
|
|
||||||
.ok_or("No active session - please log in")?;
|
|
||||||
store.update_qobuz_playlist_id(pending_id, qobuz_playlist_id)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Mark a pending playlist as synced after successful Qobuz creation
|
|
||||||
#[tauri::command]
|
|
||||||
pub fn mark_pending_playlist_synced(
|
|
||||||
pending_id: i64,
|
|
||||||
qobuz_playlist_id: u64,
|
|
||||||
state: State<'_, OfflineState>,
|
|
||||||
) -> Result<(), String> {
|
|
||||||
let guard__ = state
|
|
||||||
.store
|
|
||||||
.lock()
|
|
||||||
.map_err(|e| format!("Lock error: {}", e))?;
|
|
||||||
let store = guard__
|
|
||||||
.as_ref()
|
|
||||||
.ok_or("No active session - please log in")?;
|
|
||||||
store.mark_playlist_synced(pending_id, qobuz_playlist_id)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Delete a pending playlist
|
|
||||||
#[tauri::command]
|
|
||||||
pub fn delete_pending_playlist(
|
|
||||||
pending_id: i64,
|
|
||||||
state: State<'_, OfflineState>,
|
|
||||||
) -> Result<(), String> {
|
|
||||||
let guard__ = state
|
|
||||||
.store
|
|
||||||
.lock()
|
|
||||||
.map_err(|e| format!("Lock error: {}", e))?;
|
|
||||||
let store = guard__
|
|
||||||
.as_ref()
|
|
||||||
.ok_or("No active session - please log in")?;
|
|
||||||
store.delete_pending_playlist(pending_id)
|
|
||||||
}
|
|
||||||
|
|
||||||
// === Scrobble Queue Commands ===
|
|
||||||
|
|
||||||
/// Mark scrobbles as sent after successful Last.fm submission
|
|
||||||
#[tauri::command]
|
|
||||||
pub fn mark_scrobbles_sent(
|
|
||||||
ids: Vec<i64>,
|
|
||||||
state: State<'_, OfflineState>,
|
|
||||||
) -> Result<(), String> {
|
|
||||||
let guard__ = state
|
|
||||||
.store
|
|
||||||
.lock()
|
|
||||||
.map_err(|e| format!("Lock error: {}", e))?;
|
|
||||||
let store = guard__
|
|
||||||
.as_ref()
|
|
||||||
.ok_or("No active session - please log in")?;
|
|
||||||
store.mark_scrobbles_sent(&ids)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in new issue
Block a user