Add UUID to apps w/ add option to use App's id for virtual display (resolves #48)

This commit is contained in:
Yukino Song
2024-09-22 05:52:00 +08:00
parent 4d5cc526b5
commit 80fb7efc3d
8 changed files with 213 additions and 158 deletions

View File

@@ -86,16 +86,16 @@
</tr>
</thead>
<tbody>
<tr v-for="(app,i) in apps" :key="i">
<tr v-for="(app,i) in apps" :key="app.uuid">
<td>{{app.name}}</td>
<td>
<button class="btn btn-success me-2" :disabled="app.launching" @click="launchApp(i)">
<button class="btn btn-success me-2" :disabled="app.launching" @click="launchApp(app)">
<i class="fas fa-play"></i> {{ $t('apps.launch') }}
</button>
<button class="btn btn-primary me-2" :disabled="app.launching" @click="editApp(i)">
<button class="btn btn-primary me-2" :disabled="app.launching" @click="editApp(app)">
<i class="fas fa-edit"></i> {{ $t('apps.edit') }}
</button>
<button class="btn btn-danger" :disabled="app.launching" @click="showDeleteForm(i)">
<button class="btn btn-danger" :disabled="app.launching" @click="showDeleteForm(app)">
<i class="fas fa-trash"></i> {{ $t('apps.delete') }}
</button>
</td>
@@ -274,16 +274,23 @@
<div class="mb-3 form-check" v-if="platform === 'windows'">
<label for="virtualDisplay" class="form-check-label">{{ $t('apps.virtual_display') }}</label>
<input type="checkbox" class="form-check-input" id="virtualDisplay" v-model="editForm['virtual-display']"
true-value="true" false-value="false" />
true-value="true" false-value="false" />
<div class="form-text">{{ $t('apps.virtual_display_desc') }}</div>
</div>
<!-- set virtual display to primary -->
<div class="mb-3 form-check" v-if="platform === 'windows' && editForm['virtual-display'] == 'true'">
<label for="virtualDisplayPrimary" class="form-check-label">{{ $t('apps.virtual_display_primary') }}</label>
<input type="checkbox" class="form-check-input" id="virtualDisplayPrimary" v-model="editForm['virtual-display-primary']"
true-value="true" false-value="false" />
true-value="true" false-value="false" />
<div class="form-text">{{ $t('apps.virtual_display_primary_desc') }}</div>
</div>
<!-- use app identity -->
<div class="mb-3 form-check">
<label for="useAppIdentity" class="form-check-label">{{ $t('apps.use_app_identity') }}</label>
<input type="checkbox" class="form-check-input" id="useAppIdentity" v-model="editForm['use-app-identity']"
true-value="true" false-value="false" />
<div class="form-text">{{ $t('apps.use_app_identity_desc') }}</div>
</div>
<!-- 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>
@@ -392,6 +399,23 @@
import PlatformLayout from './PlatformLayout.vue'
import { Dropdown } from 'bootstrap/dist/js/bootstrap'
const newApp = {
name: "",
output: "",
cmd: [],
"exclude-global-prep-cmd": false,
elevated: false,
"auto-detach": true,
"wait-all": true,
"exit-timeout": 5,
"prep-cmd": [],
detached: [],
"image-path": "",
"virtual-display-primary": true,
"scale-factor": "100",
"use-app-identity": false
}
const app = createApp({
components: {
Navbar,
@@ -429,30 +453,13 @@
});
},
newApp() {
this.editForm = {
name: "",
output: "",
cmd: [],
index: -1,
"exclude-global-prep-cmd": false,
elevated: false,
"auto-detach": true,
"wait-all": true,
"exit-timeout": 5,
"prep-cmd": [],
detached: [],
"image-path": "",
"virtual-display-primary": true,
"scale-factor": "100"
};
this.editForm.index = -1;
this.editForm = Object.assign({}, newApp);
this.showEditForm = true;
},
launchApp(id) {
const app = this.apps[id];
launchApp(app) {
if (confirm(this.$t('apps.launch_warning'))) {
app.launching = true;
fetch("/api/apps/launch?id=" + id, {
fetch("/api/apps/launch?uuid=" + app.uuid, {
credentials: 'include',
method: "POST",
})
@@ -467,56 +474,31 @@
.finally(() => app.launching = false);
}
},
editApp(id) {
this.editForm = JSON.parse(JSON.stringify(this.apps[id]));
this.editForm.index = id;
if (this.editForm["prep-cmd"] === undefined)
this.editForm["prep-cmd"] = [];
if (this.editForm["detached"] === undefined)
this.editForm["detached"] = [];
if (this.editForm["exclude-global-prep-cmd"] === undefined)
this.editForm["exclude-global-prep-cmd"] = [];
if (this.editForm["elevated"] === undefined && this.platform === 'windows') {
this.editForm["elevated"] = [];
}
if (this.editForm["auto-detach"] === undefined) {
this.editForm["auto-detach"] = true;
}
if (this.editForm["wait-all"] === undefined) {
this.editForm["wait-all"] = true;
}
if (this.editForm["exit-timeout"] === undefined) {
this.editForm["exit-timeout"] = 5;
}
if (typeof this.editForm["virtual-display-primary"] === "undefined") {
this.editForm["virtual-display-primary"] = true;
}
if (typeof this.editForm["scale-factor"] === "undefined") {
this.editForm["scale-factor"] = "100"
}
editApp(app) {
this.editForm = Object.assign({}, newApp, JSON.parse(JSON.stringify(app)));
this.showEditForm = true;
},
showDeleteForm(id) {
let resp = confirm(
"Are you sure to delete " + this.apps[id].name + "?"
showDeleteForm(app) {
const resp = confirm(
"Are you sure to delete " + app.name + "?"
);
if (resp) {
fetch("/api/apps/" + id, {
fetch("/api/apps/delete?uuid=" + app.uuid, {
credentials: 'include',
method: "DELETE"
method: "POST"
}).then((r) => {
if (r.status == 200) document.location.reload();
});
}
},
addPrepCmd() {
let template = {
const template = {
do: "",
undo: ""
};
if (this.platform === 'windows') {
template = { ...template, elevated: false };
template.elevated = false;
}
this.editForm["prep-cmd"].push(template);
@@ -618,6 +600,8 @@
},
save() {
this.editForm["image-path"] = this.editForm["image-path"].toString().replace(/"/g, '');
delete this.editForm["launching"];
delete this.editForm["id"];
fetch("/api/apps", {
credentials: 'include',
method: "POST",

View File

@@ -427,9 +427,11 @@
}
})
.catch((e) => {
console.error(e)
location.reload();
return
console.error(e);
setTimeout(() => {
location.reload();
}, 1000);
return;
});
}
});

View File

@@ -92,7 +92,9 @@
"virtual_display_primary": "Enforce Virtual Display Primary",
"virtual_display_primary_desc": "Automatically set the virtual display as primary display when the app starts. Virtual display will always be set to primary when client requests to use virtual display. (Recommended to keep on)",
"resolution_scale_factor": "Resolution Scale Factor",
"resolution_scale_factor_desc": "Scale the client requested resolution based on this factor. e.g. 2000x1000 with a factor of 120% will become 2400x1200. Overrides client requested factor when the number isn't 100%. This option won't affect client requested streaming resolution."
"resolution_scale_factor_desc": "Scale the client requested resolution based on this factor. e.g. 2000x1000 with a factor of 120% will become 2400x1200. Overrides client requested factor when the number isn't 100%. This option won't affect client requested streaming resolution.",
"use_app_identity": "Use App Identity",
"use_app_identity_desc": "Use the app's own identity while creating virtual displays instead of client's. This is useful when you want display configuration for each APP separately."
},
"client_card": {
"clients": "Clients",

View File

@@ -86,11 +86,13 @@
"working_dir": "工作目录",
"working_dir_desc": "应传递给进程的工作目录。例如某些应用程序使用工作目录搜索配置文件。如果不设置Apollo 将默认使用命令的父目录",
"virtual_display": "总是使用虚拟显示器",
"virtual_display_desc": "在使用这个App的时候总是使用虚拟显示器覆盖客户端请求。请确保 SudoVDA 虚拟显示器驱动已安装并启用。",
"virtual_display_desc": "在使用这个 App 的时候总是使用虚拟显示器,覆盖客户端请求。请确保 SudoVDA 虚拟显示器驱动已安装并启用。",
"virtual_display_primary": "强制设置虚拟显示器为主显示器",
"virtual_display_primary_desc": "在App启动时强制将虚拟显示器设为主显示器。当客户端请求使用虚拟显示器时将无条件设为主显示器。覆盖全局设置推荐保持开启",
"virtual_display_primary_desc": "在 App 启动时强制将虚拟显示器设为主显示器。当客户端请求使用虚拟显示器时将无条件设为主显示器。(覆盖全局设置,推荐保持开启)",
"resolution_scale_factor": "分辨率缩放比例",
"resolution_scale_factor_desc": "基于此比例缩放客户端请求的分辨率。例如 2000x1000 缩放 120% 将变成 2400x1200。当此项为非 100% 时覆盖客户端请求的缩放比例。此选项不会影响客户端请求的串流分辨率。"
"resolution_scale_factor_desc": "基于此比例缩放客户端请求的分辨率。例如 2000x1000 缩放 120% 将变成 2400x1200。当此项为非 100% 时覆盖客户端请求的缩放比例。此选项不会影响客户端请求的串流分辨率。",
"use_app_identity": "使用 App 身份",
"use_app_identity_desc": "在创建虚拟显示器时使用 App 自身的身份,而非客户端的。这样可以针对 APP 进行单独的显示器组合配置。"
},
"client_card": {
"clients": "客户端",

View File

@@ -189,15 +189,19 @@
})
.then((resp) => {
if (resp.status !== 200) {
location.reload();
return
setTimeout(() => {
location.reload();
}, 1000);
return;
}
})
.catch((e) => {
this.serverRestarting = false
console.error(e)
location.reload();
return
console.error(e);
setTimeout(() => {
location.reload();
}, 1000);
return;
});
},
quit() {