- Source
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.
| Name | Type | Description |
|---|---|---|
deviceId | string | the stable per-device id (roDeviceInfo GetChannelClientId) |
friendlyName | string | URL-safe username, or "" when no user is resolved |
serverVersion | string | connected Jellyfin server version string (for example "10.11.11") |
- Source
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.
- Source
- Type:
- boolean
(static) LoadUserPreferences() → {void}
Load user preferences from Jellyfin server
- Source
- Type:
- void
(static) Login(userData, saveCredentialsopt) → {void}
Process user login from API authentication response
| Name | Type | Attributes | Default | Description |
|---|---|---|---|---|
userData | object | |||
saveCredentials | boolean | <optional> | false |
- Source
- Type:
- void
(static) Logout() → {void}
Logout and reset to defaults
- Source
- 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
| Name | Type | Description |
|---|---|---|
name | string | The raw username to sanitize |
- Source
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).
| Name | Type | Description |
|---|---|---|
userPreferences | object |
- Source
- Type:
- void
(static) SetServerDeviceName() → {void}
Set device name from user name
- Source
- Type:
- void
(static) getDefaultHomeSections() → {object}
Get default home sections configuration
- Source
- Type:
- object
(static) hasHomeSectionData(prefs) → {boolean}
Check if CustomPrefs contains any homesection data
| Name | Type | Description |
|---|---|---|
prefs | object |
- Source
- Type:
- boolean