WebUI: Support starting apps from local client
This commit is contained in:
@@ -541,6 +541,8 @@ namespace confighttp {
|
|||||||
nlohmann::json file_tree = nlohmann::json::parse(content);
|
nlohmann::json file_tree = nlohmann::json::parse(content);
|
||||||
|
|
||||||
file_tree["current_app"] = proc::proc.get_running_app_uuid();
|
file_tree["current_app"] = proc::proc.get_running_app_uuid();
|
||||||
|
file_tree["host_uuid"] = http::unique_id;
|
||||||
|
file_tree["host_name"] = config::nvhttp.sunshine_name;
|
||||||
|
|
||||||
send_response(response, file_tree);
|
send_response(response, file_tree);
|
||||||
} catch (std::exception &e) {
|
} catch (std::exception &e) {
|
||||||
|
|||||||
@@ -68,6 +68,10 @@
|
|||||||
vertical-align: top;
|
vertical-align: top;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.actions-col {
|
||||||
|
min-width: 150px;
|
||||||
|
}
|
||||||
|
|
||||||
.pre-wrap {
|
.pre-wrap {
|
||||||
white-space: pre-wrap;
|
white-space: pre-wrap;
|
||||||
}
|
}
|
||||||
@@ -91,7 +95,7 @@
|
|||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th scope="col">{{ $t('apps.name') }}</th>
|
<th scope="col">{{ $t('apps.name') }}</th>
|
||||||
<th scope="col" class="text-end">{{ $t('apps.actions') }}</th>
|
<th scope="col" class="text-end actions-col">{{ $t('apps.actions') }}</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
@@ -109,10 +113,10 @@
|
|||||||
>
|
>
|
||||||
<td>{{app.name || ' '}}</td>
|
<td>{{app.name || ' '}}</td>
|
||||||
<td v-if="app.uuid" class="text-end">
|
<td v-if="app.uuid" class="text-end">
|
||||||
<button class="btn btn-primary me-2" :disabled="actionDisabled" @click="editApp(app)">
|
<button class="btn btn-primary me-1" :disabled="actionDisabled" @click="editApp(app)">
|
||||||
<i class="fas fa-edit"></i>
|
<i class="fas fa-edit"></i>
|
||||||
</button>
|
</button>
|
||||||
<button class="btn btn-danger me-2" :disabled="actionDisabled" @click="showDeleteForm(app)">
|
<button class="btn btn-danger me-1" :disabled="actionDisabled" @click="showDeleteForm(app)">
|
||||||
<i class="fas fa-trash"></i>
|
<i class="fas fa-trash"></i>
|
||||||
</button>
|
</button>
|
||||||
<button class="btn btn-warning" :disabled="actionDisabled" @click="closeApp()" v-if="currentApp === app.uuid">
|
<button class="btn btn-warning" :disabled="actionDisabled" @click="closeApp()" v-if="currentApp === app.uuid">
|
||||||
@@ -548,6 +552,8 @@
|
|||||||
platform: "",
|
platform: "",
|
||||||
currentApp: "",
|
currentApp: "",
|
||||||
draggingApp: -1,
|
draggingApp: -1,
|
||||||
|
hostName: "",
|
||||||
|
hostUUID: "",
|
||||||
listReordered: false
|
listReordered: false
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
@@ -666,6 +672,8 @@
|
|||||||
.then(r => {
|
.then(r => {
|
||||||
this.apps = r.apps.filter(i => i.uuid).map(i => ({...i, launching: false, dragover: false}));
|
this.apps = r.apps.filter(i => i.uuid).map(i => ({...i, launching: false, dragover: false}));
|
||||||
this.currentApp = r.current_app;
|
this.currentApp = r.current_app;
|
||||||
|
this.hostName = r.host_name;
|
||||||
|
this.hostUUID = r.host_uuid;
|
||||||
this.listReordered = false;
|
this.listReordered = false;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
@@ -674,6 +682,15 @@
|
|||||||
this.showEditForm = true;
|
this.showEditForm = true;
|
||||||
},
|
},
|
||||||
launchApp(app) {
|
launchApp(app) {
|
||||||
|
const isLocalHost = ['localhost', '127.0.0.1', '[::1]'].indexOf(location.hostname) >= 0
|
||||||
|
|
||||||
|
if (!isLocalHost && confirm(this.$t('apps.launch_local_client'))) {
|
||||||
|
const link = document.createElement('a');
|
||||||
|
link.href = `art://launch?host_uuid=${this.hostUUID}&host_name=${this.hostName}&app_uuid=${app.uuid}&app_name=${app.name}`;
|
||||||
|
link.click();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (confirm(this.$t('apps.launch_warning'))) {
|
if (confirm(this.$t('apps.launch_warning'))) {
|
||||||
this.actionDisabled = true;
|
this.actionDisabled = true;
|
||||||
fetch("./api/apps/launch", {
|
fetch("./api/apps/launch", {
|
||||||
|
|||||||
@@ -471,7 +471,7 @@
|
|||||||
this.otpStatus = 'success'
|
this.otpStatus = 'success'
|
||||||
this.otpMessage = this.i18n.t('pin.otp_success')
|
this.otpMessage = this.i18n.t('pin.otp_success')
|
||||||
|
|
||||||
const isLocalHost = ['localhost', '127.0.0.1', '[::1]'].indexOf(location.hostname) < 0
|
const isLocalHost = ['localhost', '127.0.0.1', '[::1]'].indexOf(location.hostname) >= 0
|
||||||
|
|
||||||
if (hostManuallySet) {
|
if (hostManuallySet) {
|
||||||
Object.assign(this, hostInfoCache);
|
Object.assign(this, hostInfoCache);
|
||||||
@@ -479,7 +479,7 @@
|
|||||||
this.hostAddr = resp.ip
|
this.hostAddr = resp.ip
|
||||||
this.hostPort = parseInt(location.port, 10) - 1
|
this.hostPort = parseInt(location.port, 10) - 1
|
||||||
|
|
||||||
if (isLocalHost) {
|
if (!isLocalHost) {
|
||||||
this.hostAddr = location.hostname
|
this.hostAddr = location.hostname
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -498,7 +498,7 @@
|
|||||||
resetOTPTimeout = null
|
resetOTPTimeout = null
|
||||||
}, 3 * 60 * 1000)
|
}, 3 * 60 * 1000)
|
||||||
|
|
||||||
if (isLocalHost) {
|
if (!isLocalHost) {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
if (window.confirm(this.i18n.t('pin.otp_pair_now'))) {
|
if (window.confirm(this.i18n.t('pin.otp_pair_now'))) {
|
||||||
window.open(this.deepLink);
|
window.open(this.deepLink);
|
||||||
|
|||||||
@@ -96,6 +96,7 @@
|
|||||||
"image": "Image",
|
"image": "Image",
|
||||||
"image_desc": "Application icon/picture/image path that will be sent to client. Image must be a PNG file. If not set, Apollo will send default box image.",
|
"image_desc": "Application icon/picture/image path that will be sent to client. Image must be a PNG file. If not set, Apollo will send default box image.",
|
||||||
"launch": "Launch",
|
"launch": "Launch",
|
||||||
|
"launch_local_client": "Do you want to launch the app from local client on this device?",
|
||||||
"launch_warning": "Are you sure you want to launch this app? This will terminate the currently running app.",
|
"launch_warning": "Are you sure you want to launch this app? This will terminate the currently running app.",
|
||||||
"launch_failed": "App launch failed: ",
|
"launch_failed": "App launch failed: ",
|
||||||
"loading": "Loading...",
|
"loading": "Loading...",
|
||||||
|
|||||||
@@ -96,6 +96,7 @@
|
|||||||
"image": "图片",
|
"image": "图片",
|
||||||
"image_desc": "发送到客户端的应用程序图标/图片/图像的路径。图片必须是 PNG 文件。如果未设置,Apollo 将发送默认图片。",
|
"image_desc": "发送到客户端的应用程序图标/图片/图像的路径。图片必须是 PNG 文件。如果未设置,Apollo 将发送默认图片。",
|
||||||
"launch": "启动",
|
"launch": "启动",
|
||||||
|
"launch_local_client": "要通过此设备上的客户端启动应用吗?",
|
||||||
"launch_warning": "确定要启动此应用吗?这将会终止当前已启动的应用。",
|
"launch_warning": "确定要启动此应用吗?这将会终止当前已启动的应用。",
|
||||||
"launch_success": "应用启动成功!",
|
"launch_success": "应用启动成功!",
|
||||||
"launch_failed": "应用启动失败:",
|
"launch_failed": "应用启动失败:",
|
||||||
|
|||||||
Reference in New Issue
Block a user