<!DOCTYPE html>
<html lang="en" data-bs-theme="auto">

<head>
      <!-- TEMPLATE_HEADER - Used by Every UI Page -->
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Apollo</title>
<link rel="icon" type="image/x-icon" href="./images/apollo.ico">
<link href="./assets/css/apollo.css" rel="stylesheet" />

      <style>
        .precmd-head {
          width: 200px;
        }

        .monospace {
          font-family: monospace;
        }

        .cover-finder {}

        .cover-finder .cover-results {
          max-height: 400px;
          overflow-x: hidden;
          overflow-y: auto;
        }

        .cover-finder .cover-results.busy * {
          cursor: wait !important;
          pointer-events: none;
        }

        .cover-container {
          padding-top: 133.33%;
          position: relative;
        }

        .cover-container.result {
          cursor: pointer;
        }

        .spinner-border {
          position: absolute;
          left: 0;
          top: 0;
          right: 0;
          bottom: 0;
          margin: auto;
        }

        .cover-container img {
          display: block;
          position: absolute;
          top: 0;
          width: 100%;
          height: 100%;
          object-fit: cover;
        }

        .config-page {
          padding: 1em;
          border: 1px solid #dee2e6;
          border-top: none;
        }

        td {
          padding: 0 0.5em;
        }

        .env-table td {
          padding: 0.25em;
          border-bottom: rgba(0, 0, 0, 0.25) 1px solid;
          vertical-align: top;
        }

        .actions-col {
          min-width: 150px;
        }

        .pre-wrap {
          white-space: pre-wrap;
        }

        .dragover {
          border-top: 2px solid #ffc400;
        }
      </style>
  <script type="module" crossorigin src="./assets/apps-C3LUtg9C.js"></script>
  <link rel="modulepreload" crossorigin href="./assets/init-Ck7wRxmZ.js">
  <link rel="modulepreload" crossorigin href="./assets/theme-BfDtj5yE.js">
  <link rel="modulepreload" crossorigin href="./assets/_plugin-vue_export-helper-DlAUqK2U.js">
  <link rel="modulepreload" crossorigin href="./assets/Navbar-CshJBn-L.js">
  <link rel="modulepreload" crossorigin href="./assets/Checkbox-Cnqtybr8.js">
  <link rel="stylesheet" crossorigin href="./assets/init-D_k9xtOw.css">
  <link rel="stylesheet" crossorigin href="./assets/Navbar-dej49bs7.css">
</head>

<body id="app" v-cloak>
  <Navbar></Navbar>
  <div class="container">
    <div class="my-4" v-if="!showEditForm">
        <h1>{{ $t('apps.applications_title') }}</h1>
        <div>{{ $t('apps.applications_desc') }}</div>
        <div>{{ $t('apps.applications_reorder_desc') }}</div>
        <div class="pre-wrap">{{ $t('apps.applications_tips') }}</div>
    </div>
    <div class="my-4" v-else>
        <h1>{{ editForm.name || "&lt; NO NAME &gt;"}}</h1>
        <div>
          <button @click="showEditForm = false" class="btn btn-secondary me-2 mt-2">
            <i class="fas fa-xmark"></i> {{ $t('_common.cancel') }}
          </button>
          <button class="btn btn-primary me-2 mt-2" :disabled="actionDisabled || !editForm.name.trim()" @click="save">
            <i class="fas fa-floppy-disk"></i> {{ $t('_common.save') }}
          </button>
          <button class="btn btn-success mt-2" @click="exportLauncherFile(editForm)" :disabled="!editForm.uuid">
            <i class="fas fa-arrow-up-from-bracket"></i> {{ $t('apps.export_launcher_file') }}
          </button>
        </div>
    </div>
    <div class="card p-4" v-if="!showEditForm">
      <table class="table">
        <thead>
          <tr>
            <th scope="col">{{ $t('apps.name') }}</th>
            <th scope="col" class="text-end actions-col">{{ $t('apps.actions') }}</th>
          </tr>
        </thead>
        <tbody>
          <tr
            v-for="(app,i) in apps"
            :key="app.uuid"
            :class="{dragover: app.dragover}"
            draggable="true"
            @dragstart="onDragStart($event, i)"
            @dragenter="onDragEnter($event, app)"
            @dragover="onDragOver($event)"
            @dragleave="onDragLeave(app)"
            @dragend="onDragEnd()"
            @drop="onDrop($event, app, i)"
          >
            <td @dblclick="exportLauncherFile(app)">{{app.name || ' '}}</td>
            <td v-if="app.uuid" class="text-end">
              <button class="btn btn-primary me-1" :disabled="actionDisabled" @click="editApp(app)">
                <i class="fas fa-edit"></i>
              </button>
              <button class="btn btn-danger me-1" :disabled="actionDisabled" @click="showDeleteForm(app)">
                <i class="fas fa-trash"></i>
              </button>
              <button class="btn btn-warning" :disabled="actionDisabled" @click="closeApp()" v-if="currentApp === app.uuid">
                <i class="fas fa-stop"></i>
              </button>
              <a class="btn btn-success" :disabled="actionDisabled" @click.prevent="launchApp(event, app)" :href="'art://launch?host_uuid=' + hostUUID + '&host_name=' + hostName + '&app_uuid=' + app.uuid + '&app_name=' + app.name" v-else>
                <i class="fas fa-play"></i>
              </a>
            </td>
            <td v-else></td>
          </tr>
        </tbody>
      </table>
      <div class="mt-2">
        <button class="btn btn-primary" @click="newApp" :disabled="actionDisabled">
          <i class="fas fa-plus"></i> {{ $t('apps.add_new') }}
        </button>
        <button class="btn btn-secondary float-end" @click="alphabetizeApps" :disabled="actionDisabled" v-if="!listReordered">
          <i class="fas fa-sort-alpha-up"></i> {{ $t('apps.alphabetize') }}
        </button>
        <button class="btn btn-warning float-end" @click="saveOrder" :disabled="actionDisabled" v-if="listReordered">
          <i class="fas fa-floppy-disk"></i> {{ $t('apps.save_order') }}
        </button>
      </div>
    </div>
    <div class="edit-form card mt-2" v-else>
      <div class="p-4">
        <!-- Application Name -->
        <div class="mb-3">
          <label for="appName" class="form-label">{{ $t('apps.app_name') }}</label>
          <div class="input-group dropup">
            <input type="text" class="form-control" id="appName" aria-describedby="appNameHelp" v-model="editForm.name" />
            <button class="btn btn-secondary dropdown-toggle" type="button" id="findCoverToggle"
              aria-expanded="false" @click="showCoverFinder" ref="coverFinderDropdown">
              {{ $t('apps.find_cover') }} (Online)
            </button>
            <div class="dropdown-menu dropdown-menu-end w-50 cover-finder overflow-hidden"
              aria-labelledby="findCoverToggle">
              <div class="modal-header px-2">
                <h4 class="modal-title">{{ $t('apps.covers_found') }}</h4>
                <button type="button" class="btn-close mr-2" aria-label="Close" @click="closeCoverFinder"></button>
              </div>
              <div class="modal-body cover-results px-3 pt-3" :class="{ busy: coverFinderBusy }">
                <div class="row">
                  <div v-if="coverSearching" class="col-12 col-sm-6 col-lg-4 mb-3">
                    <div class="cover-container">
                      <div class="spinner-border" role="status">
                        <span class="visually-hidden">{{ $t('apps.loading') }}</span>
                      </div>
                    </div>
                  </div>
                  <div v-for="(cover,i) in coverCandidates" :key="'i'" class="col-12 col-sm-6 col-lg-4 mb-3"
                    @click="useCover(cover)">
                    <div class="cover-container result">
                      <img class="rounded" :src="cover.url" />
                    </div>
                    <label class="d-block text-nowrap text-center text-truncate">
                      {{cover.name}}
                    </label>
                  </div>
                </div>
              </div>
            </div>
          </div>
          <div id="appNameHelp" class="form-text">{{ $t('apps.app_name_desc') }}</div>
        </div>
        <!-- Application Image -->
        <div class="mb-3">
          <label for="appImagePath" class="form-label">{{ $t('apps.image') }}</label>
          <input type="text" class="form-control monospace" id="appImagePath" aria-describedby="appImagePathHelp"
            v-model="editForm['image-path']" />
          <div id="appImagePathHelp" class="form-text">{{ $t('apps.image_desc') }}</div>
        </div>
        <!-- gamepad override -->
        <div class="mb-3" v-if="platform !== 'macos'">
          <label for="gamepad" class="form-label">{{ $t('config.gamepad') }}</label>
          <select id="gamepad" class="form-select" v-model="editForm.gamepad">
            <option value="">{{ $t('_common.default_global') }}</option>
            <option value="disabled">{{ $t('_common.disabled') }}</option>
            <option value="auto">{{ $t('_common.auto') }}</option>

            <template v-if="platform === 'linux'">
              <option value="ds5">{{ $t("config.gamepad_ds5") }}</option>
              <option value="switch">{{ $t("config.gamepad_switch") }}</option>
              <option value="xone">{{ $t("config.gamepad_xone") }}</option>
            </template>

            <template v-if="platform === 'windows'">
              <option value="ds4">{{ $t('config.gamepad_ds4') }}</option>
              <option value="x360">{{ $t('config.gamepad_x360') }}</option>
            </template>

          </select>
          <div class="form-text">{{ $t('config.gamepad_desc') }}</div>
        </div>
        <!-- command -->
        <div class="mb-3">
          <label for="appCmd" class="form-label">{{ $t('apps.cmd') }}</label>
          <input type="text" class="form-control monospace" id="appCmd" aria-describedby="appCmdHelp"
            v-model="editForm.cmd" />
          <div id="appCmdHelp" class="form-text">
            {{ $t('apps.cmd_desc') }}<br>
            <b>{{ $t('_common.note') }}</b> {{ $t('apps.cmd_note') }}
          </div>
        </div>
        <!-- elevation -->
        <Checkbox v-if="platform === 'windows'"
                  class="mb-3"
                  id="appElevation"
                  label="_common.run_as"
                  desc="apps.run_as_desc"
                  v-model="editForm.elevated"
                  default="false"
        ></Checkbox>
        <!-- detached -->
        <div class="mb-3">
          <label class="form-label">{{ $t('apps.detached_cmds') }}</label>
          <div v-for="(c,i) in editForm.detached" class="d-flex justify-content-between my-2">
            <input type="text" v-model="editForm.detached[i]" class="form-control monospace">
            <button class="btn btn-danger mx-2" @click="editForm.detached.splice(i,1)">
              <i class="fas fa-trash"></i>
            </button>
            <button class="btn btn-success" @click="editForm.detached.splice(i, 0, '')">
              <i class="fas fa-plus"></i>
            </button>
          </div>
          <div class="d-flex justify-content-between">
            <button class="btn btn-success" @click="editForm.detached.push('');">
              <i class="fas fa-plus mr-1"></i> {{ $t('apps.detached_cmds_add') }}
            </button>
          </div>
          <div class="form-text">
            {{ $t('apps.detached_cmds_desc') }}<br>
            <b>{{ $t('_common.note') }}</b> {{ $t('apps.detached_cmds_note') }}
          </div>
        </div>
        <!-- allow client commands -->
        <Checkbox class="mb-3"
                  id="clientCommands"
                  label="apps.allow_client_commands"
                  desc="apps.allow_client_commands_desc"
                  v-model="editForm['allow-client-commands']"
                  default="true"
        ></Checkbox>
        <!-- prep and state-cmd -->
        <template v-for="type in ['prep', 'state']">
          <Checkbox class="mb-3"
                    :id="'excludeGlobal_' + type"
                    :label="'apps.global_' + type + '_name'"
                    :desc="'apps.global_' + type + '_desc'"
                    v-model="editForm['exclude-global-' + type + '-cmd']"
                    default="true"
                    inverse-values
          ></Checkbox>
          <div class="mb-3">
            <label class="form-label">{{ $t('apps.cmd_' + type + '_name') }}</label>
            <div class="form-text pre-wrap">{{ $t('apps.cmd_' + type + '_desc') }}</div>
            <table class="table" v-if="editForm[type + '-cmd'].length > 0">
              <thead>
                <tr>
                  <th scope="col"><i class="fas fa-play"></i> {{ $t('_common.do_cmd') }}</th>
                  <th scope="col"><i class="fas fa-undo"></i> {{ $t('_common.undo_cmd') }}</th>
                  <th scope="col" v-if="platform === 'windows'">
                    <i class="fas fa-shield-alt"></i> {{ $t('_common.run_as') }}
                  </th>
                  <th scope="col"></th>
                </tr>
              </thead>
              <tbody>
                <tr v-for="(c, i) in editForm[type + '-cmd']">
                  <td>
                    <input type="text" class="form-control monospace" v-model="c.do" />
                  </td>
                  <td>
                    <input type="text" class="form-control monospace" v-model="c.undo" />
                  </td>
                  <td v-if="platform === 'windows'" class="align-middle">
                    <Checkbox :id="type + '-cmd-admin-' + i"
                              label="_common.elevated"
                              desc=""
                              v-model="c.elevated"
                    ></Checkbox>
                  </td>
                  <td class="text-end">
                    <button class="btn btn-danger mx-2" @click="editForm[type + '-cmd'].splice(i,1)">
                      <i class="fas fa-trash"></i>
                    </button>
                    <button class="btn btn-success" @click="addCmd(editForm[type + '-cmd'], i)">
                      <i class="fas fa-plus"></i>
                    </button>
                  </td>
                </tr>
              </tbody>
            </table>
            <div class="d-flex justify-content-start mb-3 mt-3">
              <button class="btn btn-success" @click="addCmd(editForm[type + '-cmd'], -1)">
                <i class="fas fa-plus mr-1"></i> {{ $t('apps.add_cmds') }}
              </button>
            </div>
          </div>
        </template>
        <!-- working dir -->
        <div class="mb-3">
          <label for="appWorkingDir" class="form-label">{{ $t('apps.working_dir') }}</label>
          <input type="text" class="form-control monospace" id="appWorkingDir" aria-describedby="appWorkingDirHelp"
            v-model="editForm['working-dir']" />
          <div id="appWorkingDirHelp" class="form-text">{{ $t('apps.working_dir_desc') }}</div>
        </div>
        <!-- output -->
        <div class="mb-3">
          <label for="appOutput" class="form-label">{{ $t('apps.output_name') }}</label>
          <input type="text" class="form-control monospace" id="appOutput" aria-describedby="appOutputHelp"
            v-model="editForm.output" />
          <div id="appOutputHelp" class="form-text">{{ $t('apps.output_desc') }}</div>
        </div>
        <!-- auto-detach -->
        <Checkbox class="mb-3"
                  id="autoDetach"
                  label="apps.auto_detach"
                  desc="apps.auto_detach_desc"
                  v-model="editForm['auto-detach']"
                  default="true"
        ></Checkbox>
        <!-- wait for all processes -->
        <Checkbox class="mb-3"
                  id="waitAll"
                  label="apps.wait_all"
                  desc="apps.wait_all_desc"
                  v-model="editForm['wait-all']"
                  default="true"
        ></Checkbox>
        <!-- terminate on pause -->
        <Checkbox class="mb-3"
                  id="terminateOnPause"
                  label="apps.terminate_on_pause"
                  desc="apps.terminate_on_pause_desc"
                  v-model="editForm['terminate-on-pause']"
                  default="false"
        ></Checkbox>
        <!-- exit timeout -->
        <div class="mb-3">
          <label for="exitTimeout" class="form-label">{{ $t('apps.exit_timeout') }}</label>
          <input type="number" class="form-control monospace" id="exitTimeout" aria-describedby="exitTimeoutHelp"
                 v-model="editForm['exit-timeout']" min="0" placeholder="5" />
          <div id="exitTimeoutHelp" class="form-text">{{ $t('apps.exit_timeout_desc') }}</div>
        </div>
        <!-- use virtual display -->
        <Checkbox class="mb-3"
                  id="virtualDisplay"
                  label="apps.virtual_display"
                  desc="apps.virtual_display_desc"
                  v-model="editForm['virtual-display']"
                  default="false"
        ></Checkbox>
        <!-- use app identity -->
        <Checkbox class="mb-3"
                  id="useAppIdentity"
                  label="apps.use_app_identity"
                  desc="apps.use_app_identity_desc"
                  v-model="editForm['use-app-identity']"
                  default="false"
        ></Checkbox>
        <!-- per-client app identity -->
        <Checkbox class="mb-3"
                  v-if="editForm['use-app-identity']"
                  id="perClientAppIdentity"
                  label="apps.per_client_app_identity"
                  desc="apps.per_client_app_identity_desc"
                  v-model="editForm['per-client-app-identity']"
                  default="false"
        ></Checkbox>
        <!-- resolution scale factor -->
        <div class="mb-3" v-if="platform === 'windows'">
          <label for="resolutionScaleFactor" class="form-label">{{ $t('apps.resolution_scale_factor') }}: {{editForm['scale-factor']}}%</label>
          <input type="range" step="1" min="20" max="200" class="form-range" id="resolutionScaleFactor" v-model="editForm['scale-factor']"/>
          <div class="form-text">{{ $t('apps.resolution_scale_factor_desc') }}</div>
        </div>
        <div class="env-hint alert alert-info overflow-auto">
          <div class="form-text">
            <h4>{{ $t('apps.env_vars_about') }}</h4>
            {{ $t('apps.env_vars_desc') }}
          </div>
          <table class="env-table">
            <tr>
              <td><b>{{ $t('apps.env_var_name') }}</b></td>
              <td><b></b></td>
            </tr>
            <tr>
              <td style="font-family: monospace">APOLLO_APP_ID</td>
              <td>{{ $t('apps.env_app_id') }}</td>
            </tr>
            <tr>
              <td style="font-family: monospace">APOLLO_APP_NAME</td>
              <td>{{ $t('apps.env_app_name') }}</td>
            </tr>
            <tr>
              <td style="font-family: monospace">APOLLO_APP_UUID</td>
              <td>{{ $t('apps.env_app_uuid') }}</td>
            </tr>
            <tr>
              <td style="font-family: monospace">APOLLO_APP_STATUS</td>
              <td>{{ $t('apps.env_app_status') }}</td>
            </tr>
            <tr>
              <td style="font-family: monospace">APOLLO_CLIENT_UUID</td>
              <td>{{ $t('apps.env_client_uuid') }}</td>
            </tr>
            <tr>
              <td style="font-family: monospace">APOLLO_CLIENT_NAME</td>
              <td>{{ $t('apps.env_client_name') }}</td>
            </tr>
            <tr>
              <td style="font-family: monospace">APOLLO_CLIENT_WIDTH</td>
              <td>{{ $t('apps.env_client_width') }}</td>
            </tr>
            <tr>
              <td style="font-family: monospace">APOLLO_CLIENT_HEIGHT</td>
              <td>{{ $t('apps.env_client_height') }}</td>
            </tr>
            <tr>
              <td style="font-family: monospace">APOLLO_CLIENT_FPS</td>
              <td>{{ $t('apps.env_client_fps') }}</td>
            </tr>
            <tr>
              <td style="font-family: monospace">APOLLO_CLIENT_HDR</td>
              <td>{{ $t('apps.env_client_hdr') }}</td>
            </tr>
            <tr>
              <td style="font-family: monospace">APOLLO_CLIENT_GCMAP</td>
              <td>{{ $t('apps.env_client_gcmap') }}</td>
            </tr>
            <tr>
              <td style="font-family: monospace">APOLLO_CLIENT_HOST_AUDIO</td>
              <td>{{ $t('apps.env_client_host_audio') }}</td>
            </tr>
            <tr>
              <td style="font-family: monospace">APOLLO_CLIENT_ENABLE_SOPS</td>
              <td>{{ $t('apps.env_client_enable_sops') }}</td>
            </tr>
            <tr>
              <td style="font-family: monospace">APOLLO_CLIENT_AUDIO_CONFIGURATION</td>
              <td>{{ $t('apps.env_client_audio_config') }}</td>
            </tr>
          </table>

          <template v-if="platform === 'windows'">
            <div class="form-text"><b>{{ $t('apps.env_rtss_cli_example') }}</b>
              <pre>cmd /C \path\to\rtss-cli.exe limit:set %APOLLO_CLIENT_FPS%</pre>
            </div>
          </template>
          <template v-if="platform === 'linux'">
            <div class="form-text"><b>{{ $t('apps.env_xrandr_example') }}</b>
              <pre>sh -c "xrandr --output HDMI-1 --mode \"${APOLLO_CLIENT_WIDTH}x${APOLLO_CLIENT_HEIGHT}\" --rate ${APOLLO_CLIENT_FPS}"</pre>
            </div>
          </template>
          <template v-if="platform === 'macos'">
            <div class="form-text"><b>{{ $t('apps.env_displayplacer_example') }}</b>
              <pre>sh -c "displayplacer "id:&lt;screenId&gt; res:${APOLLO_CLIENT_WIDTH}x${APOLLO_CLIENT_HEIGHT} hz:${APOLLO_CLIENT_FPS} scaling:on origin:(0,0) degree:0""</pre>
            </div>
          </template>

          <div class="form-text">
            <a
              href="https://docs.lizardbyte.dev/projects/sunshine/latest/md_docs_2app__examples.html"
              target="_blank"
              class="text-decoration-none"
            >
              {{ $t('_common.see_more') }}
            </a>
          </div>
        </div>

        <div class="alert alert-info">
          <i class="fa-solid fa-xl fa-circle-info"></i> {{ $t('apps.env_sunshine_compatibility') }}
        </div>

        <!-- Save buttons -->
        <div class="d-flex">
          <button @click="showEditForm = false" class="btn btn-secondary me-2">
            <i class="fas fa-xmark"></i> {{ $t('_common.cancel') }}
          </button>
          <button class="btn btn-primary" :disabled="actionDisabled || !editForm.name.trim()" @click="save">
            <i class="fas fa-floppy-disk"></i> {{ $t('_common.save') }}
          </button>
        </div>
      </div>
    </div>
  </div>
</body>
