> ## Documentation Index
> Fetch the complete documentation index at: https://globaliptv.misidev.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Settings

> The GlobalTV settings panel: safe area configuration, channel refresh, logout, and the server management panel with LAN/WAN profile switching.

The settings panel is a full-screen overlay that floats above the player. It provides access to display configuration, account actions, and a hidden server management panel for switching between backend profiles.

## Opening and closing the settings screen

Settings can be opened from both the `MainScreen` overlay and the `PlayerScreen`. `MainScene` listens to the `openSettings` field on both screens:

```brightscript theme={null}
sub OnOpenSettings()
    ' ...
    GTV_Log("MainScene", "Opening SettingsScreen")
    m.settingsReturnToOverlay = (m.isOverlayActive = true and m.mainScreen <> invalid)
    settings = m.top.CreateChild("SettingsScreen")
    settings.observeField("logoutRequested",           "OnSettingsLogout")
    settings.observeField("closeSettings",             "OnSettingsClose")
    settings.observeField("safeAreaChanged",           "OnSettingsSafeAreaChanged")
    settings.observeField("refreshChannelsRequested",  "OnSettingsRefreshChannelsRequested")
    settings.observeField("applyServerRequested",      "OnSettingsApplyServerRequested")
    settings.SetFocus(true)
    m.settingsScreen = settings
end sub
```

When closed, `MainScene` restores focus to the overlay or the player depending on how settings was opened.

## Safe area

The safe area margin compensates for TV overscan — some televisions crop the edges of the image. The setting is stored as a percentage (`uiSafeMarginPct`) and applied as an inset on all four sides of the design canvas.

* **Range:** 0 % to 10 % (`UI_SAFE_MARGIN_MIN_PCT` / `UI_SAFE_MARGIN_MAX_PCT` in `AppConstants.brs`)
* **Default:** 0 %
* **Adjustment:** Left/Right arrow keys on the focused safe area row; each press moves by 1 %.
* **Persistence:** Written to the Roku Registry under the key `uiSafeMarginPct` (`REG_KEY_SAFE_MARGIN`).

```brightscript theme={null}
sub AdjustSafeArea(delta as Integer)
    c = AppConstants()
    nextPct = m.safeMarginPct + delta
    if nextPct < c.UI_SAFE_MARGIN_MIN_PCT then nextPct = c.UI_SAFE_MARGIN_MAX_PCT
    if nextPct > c.UI_SAFE_MARGIN_MAX_PCT then nextPct = c.UI_SAFE_MARGIN_MIN_PCT
    if nextPct = m.safeMarginPct then return

    m.safeMarginPct = nextPct
    GTV_RegSaveSafeMarginPct(nextPct)
    m.statusMessage = "Área segura actualizada a " + nextPct.ToStr() + "%"
    ApplyResponsiveLayout()
    m.top.safeAreaChanged = m.top.safeAreaChanged + 1
    RebuildMenu()
end sub
```

When `safeAreaChanged` fires, `MainScene` calls `ApplySceneLayout()` and re-layouts all active screens immediately.

## Available actions

### Channel refresh

Selecting **Actualizar canales** emits `refreshChannelsRequested` to `MainScene`, which re-runs the playlist task in `"refreshCatalog"` context. The channel list is re-downloaded and the player is updated to the refreshed channel at the same index (or by matching `contentId` if available). The settings panel is closed before the refresh starts.

### Logout

Selecting **Cerrar sesión** emits `logoutRequested`, which triggers `OnLogoutRequested()` in `MainScene`:

```brightscript theme={null}
sub OnLogoutRequested()
    GTV_Log("MainScene", "Logout requested")
    ResetSessionStateAndShowLogin("", true)
end sub
```

This stops the player, clears saved credentials from the Roku Registry, clears the channel list and auth state from `m.global`, and navigates back to the login screen.

## Main menu items

The settings menu is built dynamically by `BuildMenuItems()` in `SettingsScreen.brs`. In the default `main` mode the menu contains:

| Item               | Key (`kind`)      | Description                                    |
| ------------------ | ----------------- | ---------------------------------------------- |
| Área segura: N%    | `safeArea`        | Adjust the UI safe margin with arrow keys      |
| Actualizar canales | `refreshChannels` | Re-download the channel playlist               |
| Cerrar sesión      | `logout`          | Log out and clear credentials                  |
| Acerca de GlobalTV | `about`           | Shows app version and support contact          |
| Ver servidores     | `viewServers`     | Visible only after unlocking server admin mode |
| Cerrar             | `close`           | Close the panel and return to the player       |

## Server management panel

The server panel is hidden by default. It is unlocked by pressing **OK** on the **Acerca de GlobalTV** item five times (`SERVER_ADMIN_UNLOCK_TAPS = 5`). Once unlocked, a **Ver servidores** item appears in the main menu.

### Server modes

The settings screen has three internal modes:

| Mode    | Constant       | Purpose                                        |
| ------- | -------------- | ---------------------------------------------- |
| Main    | `MODE_MAIN`    | Default settings menu                          |
| Servers | `MODE_SERVERS` | List of all server profiles                    |
| Actions | `MODE_ACTIONS` | Per-server actions (apply, test, edit, delete) |

### Default server profiles

The default profiles are defined in `source/utils/ServerManager.brs`:

```brightscript theme={null}
function GTV_DefaultServerProfiles() as Object
    return [
        {
            id: "local_default"
            name: "Local"
            baseUrl: "http://172.17.11.2:3333"
            type: "lan"
            builtIn: true
            enabled: true
        }
        {
            id: "public_default"
            name: "Publico"
            baseUrl: "https://admin.globaltv.lat"
            type: "wan"
            builtIn: true
            enabled: true
        }
    ]
end function
```

These correspond to the two entries in `SERVER_LIST` in `AppConstants.brs`. The `"Local"` profile is a LAN server on `172.17.11.2:3333`; the `"Publico"` profile is the WAN endpoint at `admin.globaltv.lat`.

### Applying a server

Selecting **Aplicar ahora** on a server profile emits `applyServerRequested` to `MainScene`, which calls `ApplyServerNow()`. This:

1. Saves the new server URL to the Registry under `lastServer`.
2. Updates `m.global.activeServer`.
3. Stops the current video stream.
4. Clears auth and catalog state.
5. Restarts the handshake flow against the new server, followed by auto-login and playlist load.

### Testing a server

Selecting **Probar conexión** launches a `ServerProbeTask` that calls `GTV_PingServer()` against the selected server's `/health` endpoint and reports the result as a status message in the detail panel — without affecting the active session.

## ServerManager: LAN vs WAN selection logic

When the app needs to find a reachable server (e.g., during handshake), `GTV_ServerBuildAutoProbeList()` builds an ordered probe sequence that always tries LAN servers before WAN servers:

```brightscript theme={null}
function GTV_ServerBuildAutoProbeList() as Object
    profiles = GTV_LoadServerProfiles()
    lan = []
    wan = []

    for each profile in profiles
        if profile.type <> invalid and profile.type = "lan"
            lan.Push(profile.baseUrl)
        else
            wan.Push(profile.baseUrl)
        end if
    end for

    order = []
    passes = AppConstants().SERVER_LAN_FORCE_RETRIES
    if passes < 1 then passes = 1

    if lan.Count() > 0
        for i = 0 to passes - 1
            for each baseUrl in lan
                order.Push(baseUrl)
            end for
        end for
    end if

    if wan.Count() > 0
        for each baseUrl in wan
            order.Push(baseUrl)
        end for
    end if

    return order
end function
```

### `SERVER_LAN_FORCE_RETRIES = 3`

LAN servers appear in the probe list `SERVER_LAN_FORCE_RETRIES` times (default `3`) before WAN servers are tried once. With the default profiles the probe order is:

```text theme={null}
1. http://172.17.11.2:3333   (LAN attempt 1)
2. http://172.17.11.2:3333   (LAN attempt 2)
3. http://172.17.11.2:3333   (LAN attempt 3)
4. https://admin.globaltv.lat (WAN)
```

This gives the LAN server three chances to respond before the app falls back to the public WAN endpoint — useful when the LAN server is temporarily slow or takes a moment to wake up.

<Info>
  Type inference (`GTV_ServerInferType()`) classifies any URL matching `172.17.*`, `192.168.*`, `10.*`, or `localhost` as `"lan"`. Everything else is classified as `"wan"`.
</Info>

## Registry persistence

Settings data is written to the Roku Registry under the `"GlobalTV"` section (`REG_SECTION`):

| Registry key      | Constant                  | What is stored                                |
| ----------------- | ------------------------- | --------------------------------------------- |
| `lastServer`      | `REG_KEY_SERVER`          | Base URL of the last successfully used server |
| `serverProfiles`  | `REG_KEY_SERVER_PROFILES` | Full JSON array of server profile objects     |
| `uiSafeMarginPct` | `REG_KEY_SAFE_MARGIN`     | Safe area margin percentage (integer, 0–10)   |

Server profiles are serialised with `FormatJson()` and deserialised with `ParseJson()` + `GTV_SanitizeServerProfiles()`, which validates and deduplicates each profile on load.

<Warning>
  Deleting all server profiles from the panel is blocked — `GTV_ServerCanDelete()` returns `false` when only one profile remains. At least one server must always be present.
</Warning>
