user

Methods

(static) ComputeServerDeviceName(deviceId, friendlyName, serverVersion) → {string}

Compute the Jellyfin DeviceId this device advertises. Every session-creating channel (auth header at baseRequest.bs, the ws:// socket URL via remoteProtocol.buildSocketUrl, and the /pair report) reads it from device.serverDeviceName, so it must be stable across the app lifecycle or the device splits into two Jellyfin sessions.

Appending the sanitized username was a workaround for OLD Jellyfin servers that revoked a device's sibling auth tokens on re-authentication, letting multiple users' saved tokens coexist on one Roku for fast user-switching. But the suffix is set post-login, making the DeviceId unstable across startup (bare before login, suffixed after), which on the HTTP (ws://) path splits one device+user into two sessions and breaks the #668 cold-launch cast producer (the phantom keys on one DeviceId, the live socket lands on the other).

Servers >= 10.11 tolerate multiple auth tokens per DeviceId (proven on 10.11.11), so the suffix is unneeded there: keep the DeviceId bare + stable. Older servers keep the suffix (unchanged behavior; those servers have no cold-cast producer anyway, since it is net9/10.11 floored). An empty/unknown server version falls through to the suffixed path, matching the conservative pre-10.11 behavior. See decision deviceid-header-authoritative (which supersedes deviceid-suffix-gate-10.11) + ADR 0023.

Parameters:
NameTypeDescription
deviceIdstring

the stable per-device id (roDeviceInfo GetChannelClientId)

friendlyNamestring

URL-safe username, or "" when no user is resolved

serverVersionstring

connected Jellyfin server version string (for example "10.11.11")

Returns:

the DeviceId to advertise on the auth header, ws:// socket, and /pair report

Type: 
string

(static) IsAuthenticated() → {boolean}

Is a user actually signed in RIGHT NOW?

Reads isLoaded, not id / authToken, and that distinction is the whole reason this exists. JellyfinUser.xml states the rule as "if user.id is not empty, user IS authenticated", and that is false in practice, because two paths populate the node SPECULATIVELY before anything has been authenticated:

onUserSelected writes id from the picker, before any auth validateSavedToken writes authToken, before validating it

Neither is rolled back when the attempt fails (the failure path clears the REGISTRY, not the node), so after a rejected token m.global.user still carries both fields and answers "authenticated" to anyone who asks it that way. Those writes are not sloppiness. validateSavedToken's is required, because AboutMe() reads the token straight back off the node through buildAuthHeader(). So the fix is a signal that only a completed login sets, rather than an attempt to stop the speculative writes.

isLoaded is that signal. It was already declared for exactly this ("tracks whether full user data has been fetched from server") and was dead: written only by SessionDataTransformer.transformUser, which builds a throwaway node the login flow never touches, and read by nobody. Logout() clears it for free via resetNodeToDefaults.

Returns:
Type: 
boolean

(static) LoadUserPreferences() → {void}

Load user preferences from Jellyfin server

Returns:
Type: 
void

(static) Login(userData, saveCredentialsopt) → {void}

Process user login from API authentication response

Parameters:
NameTypeAttributesDefaultDescription
userDataobject
saveCredentialsboolean<optional>
false
Returns:
Type: 
void

(static) Logout() → {void}

Logout and reset to defaults

Returns:
Type: 
void

(static) SanitizeUsernameForUrl(name) → {string}

Sanitize username to be URL-safe (removes spaces and special characters) Used for friendlyName which appears in serverDeviceName URLs and HTTP headers

Parameters:
NameTypeDescription
namestring

The raw username to sanitize

Returns:

URL-safe username with only alphanumeric, hyphens, and underscores

Type: 
string

(static) SaveUserHomeSections(userPreferences) → {void}

Apply server home sections to the settings node (in-memory only, no registry). Home sections are server-authoritative: the Jellyfin server's DisplayPreferences is the single source of truth. Writing to registry would create a stale cache that masks server-side changes (for example, user rearranges sections in the web client).

Parameters:
NameTypeDescription
userPreferencesobject
Returns:
Type: 
void

(static) SetServerDeviceName() → {void}

Set device name from user name

Returns:
Type: 
void

(static) getDefaultHomeSections() → {object}

Get default home sections configuration

Returns:
Type: 
object

(static) hasHomeSectionData(prefs) → {boolean}

Check if CustomPrefs contains any homesection data

Parameters:
NameTypeDescription
prefsobject
Returns:
Type: 
boolean