Show running app in Apps page

This commit is contained in:
Yukino Song
2025-02-07 21:11:03 +08:00
parent 9481418e0d
commit 58bbfc3e67
6 changed files with 50 additions and 12 deletions

View File

@@ -552,6 +552,8 @@ namespace confighttp {
} }
} }
file_tree["current_app"] = proc::proc.get_running_app_uuid();
send_response(response, file_tree); send_response(response, file_tree);
} catch (std::exception &e) { } catch (std::exception &e) {
BOOST_LOG(warning) << "GetApps: "sv << e.what(); BOOST_LOG(warning) << "GetApps: "sv << e.what();

View File

@@ -604,6 +604,7 @@ namespace proc {
_app_id = -1; _app_id = -1;
_app_name.clear(); _app_name.clear();
_app = {};
display_name.clear(); display_name.clear();
initial_display.clear(); initial_display.clear();
_launch_session.reset(); _launch_session.reset();
@@ -636,6 +637,10 @@ namespace proc {
return _app_name; return _app_name;
} }
std::string proc_t::get_running_app_uuid() {
return _app.uuid;
}
boost::process::environment proc_t::get_env() { boost::process::environment proc_t::get_env() {
return _env; return _env;
} }

View File

@@ -117,6 +117,7 @@ namespace proc {
std::vector<ctx_t> &get_apps(); std::vector<ctx_t> &get_apps();
std::string get_app_image(int app_id); std::string get_app_image(int app_id);
std::string get_last_run_app_name(); std::string get_last_run_app_name();
std::string get_running_app_uuid();
boost::process::environment get_env(); boost::process::environment get_env();
void terminate(bool immediate = false); void terminate(bool immediate = false);

View File

@@ -89,15 +89,18 @@
<tr v-for="(app,i) in apps" :key="app.uuid"> <tr v-for="(app,i) in apps" :key="app.uuid">
<td>{{app.name}}</td> <td>{{app.name}}</td>
<td> <td>
<button class="btn btn-success me-2" :disabled="app.launching" @click="launchApp(app)"> <button class="btn btn-primary me-2" :disabled="actionDisabled" @click="editApp(app)">
<i class="fas fa-play"></i> {{ $t('apps.launch') }}
</button>
<button class="btn btn-primary me-2" :disabled="app.launching" @click="editApp(app)">
<i class="fas fa-edit"></i> {{ $t('apps.edit') }} <i class="fas fa-edit"></i> {{ $t('apps.edit') }}
</button> </button>
<button class="btn btn-danger" :disabled="app.launching" @click="showDeleteForm(app)"> <button class="btn btn-danger me-2" :disabled="actionDisabled" @click="showDeleteForm(app)">
<i class="fas fa-trash"></i> {{ $t('apps.delete') }} <i class="fas fa-trash"></i> {{ $t('apps.delete') }}
</button> </button>
<button class="btn btn-warning" :disabled="actionDisabled" @click="closeApp()" v-if="currentApp === app.uuid">
<i class="fas fa-stop"></i> {{ $t('apps.close') }}
</button>
<button class="btn btn-success" :disabled="actionDisabled" @click="launchApp(app)" v-else>
<i class="fas fa-play"></i> {{ $t('apps.launch') }}
</button>
</td> </td>
</tr> </tr>
</tbody> </tbody>
@@ -444,12 +447,14 @@
return { return {
apps: [], apps: [],
showEditForm: false, showEditForm: false,
actionDisabled: false,
editForm: null, editForm: null,
detachedCmd: "", detachedCmd: "",
coverSearching: false, coverSearching: false,
coverFinderBusy: false, coverFinderBusy: false,
coverCandidates: [], coverCandidates: [],
platform: "", platform: "",
currentApp: ""
}; };
}, },
created() { created() {
@@ -469,6 +474,7 @@
.then(r => r.json()) .then(r => r.json())
.then(r => { .then(r => {
this.apps = r.apps.map(i => ({...i, launching: false})); this.apps = r.apps.map(i => ({...i, launching: false}));
this.currentApp = r.current_app;
}); });
}, },
newApp() { newApp() {
@@ -477,20 +483,40 @@
}, },
launchApp(app) { launchApp(app) {
if (confirm(this.$t('apps.launch_warning'))) { if (confirm(this.$t('apps.launch_warning'))) {
app.launching = true; this.actionDisabled = true;
fetch("./api/apps/launch?uuid=" + app.uuid, { fetch("./api/apps/launch?uuid=" + app.uuid, {
credentials: 'include', credentials: 'include',
method: "POST", method: "POST",
}) })
.then(r => r.json()) .then(r => r.json())
.then(r => { .then(r => {
if (r.status) { if (!r.status) {
alert(this.$t('apps.launch_success'));
} else {
alert(this.$t('apps.launch_failed') + r.error); alert(this.$t('apps.launch_failed') + r.error);
} }
}) })
.finally(() => app.launching = false); .finally(() => {
this.actionDisabled = false;
this.loadApps()
});
}
},
closeApp() {
if (confirm(this.$t('apps.close_warning'))) {
this.actionDisabled = true;
fetch("./api/apps/close", {
credentials: 'include',
method: "POST"
})
.then((r) => r.json())
.then((r) => {
if (!r.status) {
alert("apps.close_failed")
}
})
.finally(() => {
this.actionDisabled = false;
this.loadApps()
});
} }
}, },
editApp(app) { editApp(app) {
@@ -620,7 +646,6 @@
save() { save() {
this.editForm.name = this.editForm.name.trim(); this.editForm.name = this.editForm.name.trim();
this.editForm["image-path"] = this.editForm["image-path"].toString().trim().replace(/"/g, ''); this.editForm["image-path"] = this.editForm["image-path"].toString().trim().replace(/"/g, '');
delete this.editForm["launching"];
delete this.editForm["id"]; delete this.editForm["id"];
fetch("./api/apps", { fetch("./api/apps", {
credentials: 'include', credentials: 'include',

View File

@@ -40,6 +40,9 @@
"applications_title": "Applications", "applications_title": "Applications",
"auto_detach": "Continue streaming if the application exits quickly", "auto_detach": "Continue streaming if the application exits quickly",
"auto_detach_desc": "This will attempt to automatically detect launcher-type apps that close quickly after launching another program or instance of themselves. When a launcher-type app is detected, it is treated as a detached app.", "auto_detach_desc": "This will attempt to automatically detect launcher-type apps that close quickly after launching another program or instance of themselves. When a launcher-type app is detected, it is treated as a detached app.",
"close": "Terminate",
"close_warning": "Are you sure to terminate the current running app?",
"close_failed": "App termination failed.",
"cmd": "Command", "cmd": "Command",
"cmd_desc": "The main application to start. If blank, no application will be started.", "cmd_desc": "The main application to start. If blank, no application will be started.",
"cmd_note": "If the path to the command executable contains spaces, you must enclose it in quotes.", "cmd_note": "If the path to the command executable contains spaces, you must enclose it in quotes.",
@@ -80,7 +83,6 @@
"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_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_success": "App launched successfully!",
"launch_failed": "App launch failed: ", "launch_failed": "App launch failed: ",
"loading": "Loading...", "loading": "Loading...",
"name": "Name", "name": "Name",

View File

@@ -40,6 +40,9 @@
"applications_title": "应用", "applications_title": "应用",
"auto_detach": "启动串流后应用突然关闭时不退出串流", "auto_detach": "启动串流后应用突然关闭时不退出串流",
"auto_detach_desc": "这将尝试自动检测在启动另一个程序或自身实例后很快关闭的启动类应用。 检测到启动型应用程序时,它会被视为一个分离的应用程序。", "auto_detach_desc": "这将尝试自动检测在启动另一个程序或自身实例后很快关闭的启动类应用。 检测到启动型应用程序时,它会被视为一个分离的应用程序。",
"close": "终止",
"close_warning": "确定要终止当前正在运行的APP吗",
"close_failed": "APP终止失败。",
"cmd": "命令", "cmd": "命令",
"cmd_desc": "要启动的主要应用程序。如果为空,将不会启动任何应用程序。", "cmd_desc": "要启动的主要应用程序。如果为空,将不会启动任何应用程序。",
"cmd_note": "如果命令中可执行文件的路径包含空格,则必须用引号括起来。", "cmd_note": "如果命令中可执行文件的路径包含空格,则必须用引号括起来。",