Navigation up/back split, faster startup, and CI versionCode fix
🏗️ Build and Test JellyTau / Run Tests (push) Successful in 4m57s
Traceability Validation / Check Requirement Traces (push) Successful in 22s
Build & Release / Run Tests (push) Successful in 5m13s
🏗️ Build and Test JellyTau / Android Compile Check (push) Successful in 4m30s
Build & Release / Build Linux (push) Successful in 17m52s
Build & Release / Build Android (push) Failing after 58s
Build & Release / Create Release (push) Has been skipped
🏗️ Build and Test JellyTau / Run Tests (push) Successful in 4m57s
Traceability Validation / Check Requirement Traces (push) Successful in 22s
Build & Release / Run Tests (push) Successful in 5m13s
🏗️ Build and Test JellyTau / Android Compile Check (push) Successful in 4m30s
Build & Release / Build Linux (push) Successful in 17m52s
Build & Release / Build Android (push) Failing after 58s
Build & Release / Create Release (push) Has been skipped
Navigation: - Split conflated "back" into navigateUp (deterministic route parent) and a history-safe navigateBack that tracks in-app depth via afterNavigate instead of history.length. Fixes the resume-from-background trap where a stale WebView stack left the header arrow stuck on the current page. - /library self-corrects for music/tv/movies (which have dedicated landing pages): a leftover currentLibrary no longer forces the inline content-list view, so "up"/back shows the libraries overview. Live TV / channels / other types still render inline. Startup (unblock first paint): - auth.initialize() no longer awaits security-status, player-config, or session verification before flipping isInitialized. These run fire-and-forget after the session is restored, so the library overview paints without waiting on several serial IPC round-trips. Versioning / CI: - tauri.conf.json + package.json aligned to 0.0.15 (the tag series had drifted to 0.1.0, whose formula-derived versionCode 1000 outran the v0.0.x tags). - Release workflow now pins a monotonic Android versionCode (1000 + major*10000 + minor*100 + patch) so tagged builds never downgrade below prior installs and always increase in semver order. Tests: navigation (4), auth (29), playbackMode (23) green. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+50
-36
@@ -139,20 +139,23 @@ function createAuthStore() {
|
||||
update((s) => ({ ...s, isLoading: true, error: null }));
|
||||
|
||||
try {
|
||||
// Check security status
|
||||
try {
|
||||
const securityStatus = await commands.storageGetSecurityStatus();
|
||||
console.log("[Auth] Security status:", securityStatus);
|
||||
if (!securityStatus.usingKeyring) {
|
||||
update((s) => ({
|
||||
...s,
|
||||
securityWarning:
|
||||
"Credentials are stored with reduced security (encrypted file instead of system keyring).",
|
||||
}));
|
||||
// Check security status — fire-and-forget. It only sets a warning banner,
|
||||
// so it must not sit in front of session restore (and thus first paint).
|
||||
void (async () => {
|
||||
try {
|
||||
const securityStatus = await commands.storageGetSecurityStatus();
|
||||
console.log("[Auth] Security status:", securityStatus);
|
||||
if (!securityStatus.usingKeyring) {
|
||||
update((s) => ({
|
||||
...s,
|
||||
securityWarning:
|
||||
"Credentials are stored with reduced security (encrypted file instead of system keyring).",
|
||||
}));
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn("[Auth] Failed to get security status:", error);
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn("[Auth] Failed to get security status:", error);
|
||||
}
|
||||
})();
|
||||
|
||||
// Initialize auth manager and get session
|
||||
console.log("[Auth] Initializing auth manager...");
|
||||
@@ -162,24 +165,30 @@ function createAuthStore() {
|
||||
if (session) {
|
||||
console.log("[Auth] Restoring session for user:", session.username, "on server:", session.serverUrl);
|
||||
|
||||
// Create RepositoryClient for cache-first access
|
||||
// Create RepositoryClient for cache-first access. This IS required before
|
||||
// we mark authenticated — the first screen (library overview) reads
|
||||
// through it — so keep it awaited.
|
||||
repository = new RepositoryClient();
|
||||
await repository.create(session.serverUrl, session.userId, session.accessToken, session.serverId);
|
||||
|
||||
// Configure Jellyfin client in Rust player for automatic playback reporting
|
||||
const deviceId = await getDeviceId();
|
||||
try {
|
||||
console.log("[Auth] Configuring Rust player with restored session...");
|
||||
await commands.playerConfigureJellyfin(
|
||||
session.serverUrl,
|
||||
session.accessToken,
|
||||
session.userId,
|
||||
deviceId
|
||||
);
|
||||
console.log("[Auth] Rust player configured for automatic playback reporting");
|
||||
} catch (error) {
|
||||
console.error("[Auth] Failed to configure Rust player:", error);
|
||||
}
|
||||
// Configure the Rust player for playback reporting. This is NOT needed to
|
||||
// render the first screen (it only matters once playback starts), so run
|
||||
// it fire-and-forget instead of blocking first paint on two more IPC
|
||||
// round-trips (getDeviceId + playerConfigureJellyfin).
|
||||
void (async () => {
|
||||
try {
|
||||
const deviceId = await getDeviceId();
|
||||
await commands.playerConfigureJellyfin(
|
||||
session.serverUrl,
|
||||
session.accessToken,
|
||||
session.userId,
|
||||
deviceId
|
||||
);
|
||||
console.log("[Auth] Rust player configured for automatic playback reporting");
|
||||
} catch (error) {
|
||||
console.error("[Auth] Failed to configure Rust player:", error);
|
||||
}
|
||||
})();
|
||||
|
||||
// Set authenticated immediately (offline-first)
|
||||
set({
|
||||
@@ -211,14 +220,19 @@ function createAuthStore() {
|
||||
console.error("[Auth] Failed to start connectivity monitoring:", error);
|
||||
});
|
||||
|
||||
// Start background session verification
|
||||
try {
|
||||
const verifyDeviceId = await getDeviceId();
|
||||
await commands.authStartVerification(verifyDeviceId);
|
||||
console.log("[Auth] Background verification started");
|
||||
} catch (error) {
|
||||
console.error("[Auth] Failed to start verification:", error);
|
||||
}
|
||||
// Start background session verification — fire-and-forget. This is
|
||||
// already asynchronous work (results arrive via the auth:* events wired
|
||||
// above), so awaiting getDeviceId + authStartVerification here only
|
||||
// delayed first paint by two IPC round-trips for no UI benefit.
|
||||
void (async () => {
|
||||
try {
|
||||
const verifyDeviceId = await getDeviceId();
|
||||
await commands.authStartVerification(verifyDeviceId);
|
||||
console.log("[Auth] Background verification started");
|
||||
} catch (error) {
|
||||
console.error("[Auth] Failed to start verification:", error);
|
||||
}
|
||||
})();
|
||||
} else {
|
||||
// No stored session
|
||||
console.log("[Auth] No active session found");
|
||||
|
||||
Reference in New Issue
Block a user