release blend 2.0.0
This commit is contained in:
parent
4e4bdd33d2
commit
37d4a6155e
36 changed files with 2557 additions and 458 deletions
7
blend-settings/src/external/css/bootstrap.min.css
vendored
Normal file
7
blend-settings/src/external/css/bootstrap.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
7
blend-settings/src/external/js/bootstrap.bundle.min.js
vendored
Normal file
7
blend-settings/src/external/js/bootstrap.bundle.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
64
blend-settings/src/index.html
Normal file
64
blend-settings/src/index.html
Normal file
|
@ -0,0 +1,64 @@
|
|||
<html>
|
||||
|
||||
<head>
|
||||
<title>Settings</title>
|
||||
|
||||
<!-- Import bootstrap v5.0. -->
|
||||
<link href="external/css/bootstrap.min.css" rel="stylesheet">
|
||||
|
||||
<!-- Import common styling. -->
|
||||
<link href="internal/css/common.css" rel="stylesheet">
|
||||
</head>
|
||||
|
||||
<body style="height: 100%;">
|
||||
<br>
|
||||
<div class="topnav">
|
||||
<div class="btn-group" role="group" aria-label="Stores">
|
||||
<button class="btn btn-outline-light active shadow-none" id="containers-button"
|
||||
onclick="page('containers')">Containers</button>
|
||||
<button class="btn btn-outline-light shadow-none" id="overlay-button" onclick="page('overlay')">System</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Import bootstrap JS bundle. -->
|
||||
<script src="external/js/bootstrap.bundle.min.js"></script>
|
||||
|
||||
<script>
|
||||
const Sortable = require('sortablejs')
|
||||
const child_process = require('child_process')
|
||||
const path = require('path')
|
||||
const fs = require('fs')
|
||||
const ipc = require('electron').ipcRenderer
|
||||
|
||||
let webview = document.createElement("div")
|
||||
webview.style.flexGrow = 1
|
||||
webview.setAttribute("id", "webview")
|
||||
webview.style.marginTop = "70px"
|
||||
|
||||
document.body.appendChild(webview)
|
||||
|
||||
const $ = require("jquery")
|
||||
|
||||
function page(page) {
|
||||
switch (page) {
|
||||
case 'containers':
|
||||
$('#webview').load("pages/containers.html");
|
||||
$('#containers-button').addClass('active')
|
||||
$('#overlay-button').removeClass('active')
|
||||
break;
|
||||
case 'overlay':
|
||||
$('#webview').load("pages/overlay.html");
|
||||
$('#containers-button').removeClass('active')
|
||||
$('#overlay-button').addClass('active')
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
page('containers')
|
||||
</script>
|
||||
|
||||
<!-- Import generic page JS. -->
|
||||
<script src="internal/js/generic_page.js"></script>
|
||||
</body>
|
||||
|
||||
</html>
|
98
blend-settings/src/internal/css/common.css
Normal file
98
blend-settings/src/internal/css/common.css
Normal file
|
@ -0,0 +1,98 @@
|
|||
body {
|
||||
margin: 0 !important;
|
||||
background-color: rgb(36, 36, 48);
|
||||
color: rgba(240, 240, 255, 1);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.btn-dark {
|
||||
background-color: rgb(36, 36, 48);
|
||||
}
|
||||
|
||||
.btn-dark:focus {
|
||||
background-color: rgb(36, 36, 48);
|
||||
}
|
||||
|
||||
.btn-dark:hover {
|
||||
background-color: rgb(32, 32, 44);
|
||||
}
|
||||
|
||||
.topnav {
|
||||
display: flex;
|
||||
position: fixed;
|
||||
top: 20px;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
|
||||
.list-group-item {
|
||||
border: 1px solid rgba(255, 255, 255, 0.05);
|
||||
}
|
||||
|
||||
.form-control {
|
||||
border: 0;
|
||||
background-color: rgba(255, 255, 255, 0.05) !important;
|
||||
color: white !important;
|
||||
}
|
||||
|
||||
.form-check-input:not(:checked) {
|
||||
background-color: rgba(255, 255, 255, 0.05) !important;
|
||||
}
|
||||
|
||||
select option {
|
||||
color: white;
|
||||
background-color: rgb(36, 36, 48);
|
||||
border: 0;
|
||||
}
|
||||
|
||||
.form-group {
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
#webview {
|
||||
overflow-y: scroll !important;
|
||||
position: fixed;
|
||||
width: 100%;
|
||||
height: calc(100% - 100px);
|
||||
}
|
||||
|
||||
#webview::-webkit-scrollbar-track
|
||||
{
|
||||
background-color: rgb(36, 36, 48);
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
#webview::-webkit-scrollbar
|
||||
{
|
||||
width: 5px;
|
||||
background-color: rgb(36, 36, 48);
|
||||
}
|
||||
|
||||
#webview::-webkit-scrollbar-thumb
|
||||
{
|
||||
background-color: rgb(61, 61, 74);
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
.form-check-input {
|
||||
position: absolute;
|
||||
font-size: 1.5em;
|
||||
top: 0.67em;
|
||||
}
|
||||
|
||||
.list-group-item {
|
||||
background-color: rgb(29, 29, 37);
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
-webkit-scrollbar-track
|
||||
{
|
||||
box-shadow: inset 0 0 6px rgba(0,0,0,0.3);
|
||||
background-color: #F5F5F5;
|
||||
}
|
||||
|
||||
-webkit-scrollbar
|
||||
{
|
||||
width: 10px;
|
||||
background-color: #F5F5F5;
|
||||
}
|
184
blend-settings/src/internal/js/containers.js
Normal file
184
blend-settings/src/internal/js/containers.js
Normal file
|
@ -0,0 +1,184 @@
|
|||
var term
|
||||
|
||||
function open_container(name) {
|
||||
ipc.send("create-term", { 'title': `Container: ${name}`, 'cmd': `blend enter -cn ${name}` });
|
||||
}
|
||||
|
||||
function create_container () {
|
||||
container_name = $('#inputContainerName').val()
|
||||
if (!(/^[\w\-\.]+$/.test(container_name))) {
|
||||
$('#inputContainerName').get(0).setCustomValidity('Container name can only contain alphanumeric characters and dashes (no spaces allowed).')
|
||||
$('#inputContainerName').get(0).reportValidity();
|
||||
return
|
||||
}
|
||||
container_distro = $('#inputContainerDistro').val().toLowerCase().replace(' ', '-')
|
||||
ipc.send("create-term", { 'title': `Creating container: ${container_name}`,
|
||||
'cmd': `blend create-container -cn ${container_name} -d ${container_distro} \
|
||||
&& echo 'created container successfully (exiting automatically in 5 seconds)' \
|
||||
|| echo 'container creation failed (exiting automatically in 5 seconds)';
|
||||
sleep 5` });
|
||||
ipc.on('container-created', () => {
|
||||
worker.postMessage('update-list')
|
||||
})
|
||||
}
|
||||
|
||||
async function remove_container (name) {
|
||||
let rm_worker = new Worker(
|
||||
`data:text/javascript,
|
||||
require('child_process').spawnSync('podman', ['stop', '-t', '0', '${name}'], { encoding: 'utf8' })
|
||||
require('child_process').spawnSync('podman', ['rm', '-f', '${name}'], { encoding: 'utf8' })
|
||||
postMessage('')
|
||||
`
|
||||
)
|
||||
rm_worker.onmessage = e => worker.postMessage('update-list')
|
||||
}
|
||||
|
||||
window.worker = new Worker(
|
||||
`data:text/javascript,
|
||||
function list_containers() {
|
||||
let container_list = require('child_process').spawnSync('podman', ['ps', '-a', '--no-trunc', '--size', '--format', '{{.Names}}'], { encoding: 'utf8' }).stdout.split(/\\r?\\n/).filter(Boolean).reverse();
|
||||
if (require('fs').existsSync(require('path').join(require('os').homedir(), '.config/blend/config.yaml'), 'utf8')) {
|
||||
try {
|
||||
let fileContents = require('fs').readFileSync(require('path').join(require('os').homedir(), '.config/blend/config.yaml'), 'utf8')
|
||||
let data = require('js-yaml').load(fileContents);
|
||||
new_container_list = data['container_order']
|
||||
container_list.forEach(container => {
|
||||
if (!new_container_list.includes(container)) {
|
||||
new_container_list.push(container)
|
||||
}
|
||||
});
|
||||
new_container_list = new_container_list.filter(container => container_list.includes(container))
|
||||
new_container_list.filter((item, index) => arr.indexOf(item) === index)
|
||||
data = {
|
||||
container_order: [...new_container_list],
|
||||
use_container_bins: []
|
||||
};
|
||||
contents = require('js-yaml').dump(data)
|
||||
require('fs').writeFileSync(require('path').join(require('os').homedir(), '.config/blend/config.yaml'), contents, 'utf8')
|
||||
return new_container_list
|
||||
} catch (e) {
|
||||
let data = {
|
||||
container_order: [...container_list],
|
||||
use_container_bins: []
|
||||
};
|
||||
contents = require('js-yaml').dump(data)
|
||||
require('fs').writeFileSync(require('path').join(require('os').homedir(), '.config/blend/config.yaml'), contents, 'utf8')
|
||||
|
||||
return container_list
|
||||
}
|
||||
} else {
|
||||
let data = {
|
||||
container_order: [...container_list],
|
||||
use_container_bins: []
|
||||
};
|
||||
require('fs').mkdirSync(require('path').join(require('os').homedir(), '.config/blend'), { recursive: true });
|
||||
contents = require('js-yaml').dump(data)
|
||||
require('fs').writeFileSync(require('path').join(require('os').homedir(), '.config/blend/config.yaml'), contents, 'utf8')
|
||||
|
||||
return container_list
|
||||
}
|
||||
}
|
||||
|
||||
function truncateText(text, maxLength=30) {
|
||||
let truncated = text
|
||||
|
||||
if (truncated.length > maxLength) {
|
||||
truncated = truncated.substr(0, maxLength) + '...';
|
||||
}
|
||||
|
||||
return truncated;
|
||||
}
|
||||
|
||||
function update_container_list() {
|
||||
container_list = list_containers()
|
||||
|
||||
container_list_html_default = \`
|
||||
<div class="list-group-item">
|
||||
<div class="row align-items-center">
|
||||
<div class="col">
|
||||
<strong class="mb-0">No containers present.</strong>
|
||||
<p class="text-muted mb-0">Create one from below.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
\`
|
||||
|
||||
container_list_html = ''
|
||||
|
||||
container_list.forEach(container => {
|
||||
container_list_html += \`
|
||||
<div class="list-group-item" style="padding-top: 10px; padding-bottom: 10px; border: 0.5px solid rgba(255, 255, 255, 0.05);">
|
||||
<div class="row align-items-center" style="cursor: grab;">
|
||||
<div class="col">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor" class="bi bi-grip-vertical" viewBox="0 0 16 16" style="margin-right: 12px;">
|
||||
<path d="M7 2a1 1 0 1 1-2 0 1 1 0 0 1 2 0zm3 0a1 1 0 1 1-2 0 1 1 0 0 1 2 0zM7 5a1 1 0 1 1-2 0 1 1 0 0 1 2 0zm3 0a1 1 0 1 1-2 0 1 1 0 0 1 2 0zM7 8a1 1 0 1 1-2 0 1 1 0 0 1 2 0zm3 0a1 1 0 1 1-2 0 1 1 0 0 1 2 0zm-3 3a1 1 0 1 1-2 0 1 1 0 0 1 2 0zm3 0a1 1 0 1 1-2 0 1 1 0 0 1 2 0zm-3 3a1 1 0 1 1-2 0 1 1 0 0 1 2 0zm3 0a1 1 0 1 1-2 0 1 1 0 0 1 2 0z"/>
|
||||
</svg>
|
||||
<strong class="mb-0 container_name">\${container}</strong>
|
||||
</div>
|
||||
<div class="col-auto">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="currentColor" class="bi bi-play" viewBox="0 0 16 16" onclick="open_container('\${container}')" style="cursor: pointer; margin-right: 8px;">
|
||||
<path d="M10.804 8 5 4.633v6.734L10.804 8zm.792-.696a.802.802 0 0 1 0 1.392l-6.363 3.692C4.713 12.69 4 12.345 4 11.692V4.308c0-.653.713-.998 1.233-.696l6.363 3.692z"/>
|
||||
</svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor" class="bi bi-trash" viewBox="0 0 16 16" onclick="remove_container('\${container}')" style="cursor: pointer; margin-right: 20px; z-index: 10;">
|
||||
<path d="M5.5 5.5A.5.5 0 0 1 6 6v6a.5.5 0 0 1-1 0V6a.5.5 0 0 1 .5-.5zm2.5 0a.5.5 0 0 1 .5.5v6a.5.5 0 0 1-1 0V6a.5.5 0 0 1 .5-.5zm3 .5a.5.5 0 0 0-1 0v6a.5.5 0 0 0 1 0V6z"/>
|
||||
<path fill-rule="evenodd" d="M14.5 3a1 1 0 0 1-1 1H13v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V4h-.5a1 1 0 0 1-1-1V2a1 1 0 0 1 1-1H6a1 1 0 0 1 1-1h2a1 1 0 0 1 1 1h3.5a1 1 0 0 1 1 1v1zM4.118 4 4 4.059V13a1 1 0 0 0 1 1h6a1 1 0 0 0 1-1V4.059L11.882 4H4.118zM2.5 3V2h11v1h-11z"/>
|
||||
</svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor" class="bi bi-grip-vertical" viewBox="0 0 16 16">
|
||||
<path d="M7 2a1 1 0 1 1-2 0 1 1 0 0 1 2 0zm3 0a1 1 0 1 1-2 0 1 1 0 0 1 2 0zM7 5a1 1 0 1 1-2 0 1 1 0 0 1 2 0zm3 0a1 1 0 1 1-2 0 1 1 0 0 1 2 0zM7 8a1 1 0 1 1-2 0 1 1 0 0 1 2 0zm3 0a1 1 0 1 1-2 0 1 1 0 0 1 2 0zm-3 3a1 1 0 1 1-2 0 1 1 0 0 1 2 0zm3 0a1 1 0 1 1-2 0 1 1 0 0 1 2 0zm-3 3a1 1 0 1 1-2 0 1 1 0 0 1 2 0zm3 0a1 1 0 1 1-2 0 1 1 0 0 1 2 0z"/>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
\`
|
||||
});
|
||||
|
||||
if (container_list.length == 0) {
|
||||
postMessage(container_list_html_default)
|
||||
} else {
|
||||
postMessage(container_list_html)
|
||||
}
|
||||
}
|
||||
|
||||
self.onmessage = msg => {
|
||||
switch(msg) {
|
||||
case 'update-list':
|
||||
update_container_list()
|
||||
break;
|
||||
}
|
||||
update_container_list()
|
||||
}
|
||||
`
|
||||
);
|
||||
|
||||
worker.postMessage('update-list')
|
||||
|
||||
worker.onmessage = function (event) {
|
||||
window.data = event.data
|
||||
if (event.data.includes('bi-grip-vertical')) {
|
||||
$('#container-list').addClass('sortable')
|
||||
$('#container-list').html(event.data)
|
||||
} else {
|
||||
$('#container-list').removeClass('sortable')
|
||||
$('#container-list').html(event.data)
|
||||
}
|
||||
|
||||
$('.sortable').each((i, e) => {
|
||||
Sortable.create(e, {
|
||||
animation: 100,
|
||||
onEnd: () => {
|
||||
let container_list = []
|
||||
$('.container_name').each((i, e) => {
|
||||
container_list.push(e.innerText)
|
||||
})
|
||||
let data = {
|
||||
container_order: [...container_list],
|
||||
use_container_bins: []
|
||||
};
|
||||
require('fs').mkdirSync(require('path').join(require('os').homedir(), '.config/blend'), { recursive: true });
|
||||
contents = require('js-yaml').dump(data)
|
||||
require('fs').writeFileSync(require('path').join(require('os').homedir(), '.config/blend/config.yaml'), contents, 'utf8')
|
||||
}
|
||||
});
|
||||
e.addEventListener("dragstart", e => e.dataTransfer.setDragImage(new Image(), 0, 0), false);
|
||||
})
|
||||
}
|
15
blend-settings/src/internal/js/generic_page.js
Normal file
15
blend-settings/src/internal/js/generic_page.js
Normal file
|
@ -0,0 +1,15 @@
|
|||
if (typeof variable !== typeof undefined) {
|
||||
Sortable = undefined
|
||||
} else {
|
||||
window.Sortable = require('sortablejs')
|
||||
}
|
||||
|
||||
function truncateText(text, maxLength=30) {
|
||||
let truncated = text
|
||||
|
||||
if (truncated.length > maxLength) {
|
||||
truncated = truncated.substr(0, maxLength) + '...';
|
||||
}
|
||||
|
||||
return truncated;
|
||||
}
|
132
blend-settings/src/internal/js/overlay.js
Normal file
132
blend-settings/src/internal/js/overlay.js
Normal file
|
@ -0,0 +1,132 @@
|
|||
function rollback() {
|
||||
let rollback_worker = new Worker(
|
||||
`data:text/javascript,
|
||||
let s = require('child_process').spawnSync('pkexec', ['blend-system', 'rollback']).status
|
||||
if (s === 0) {
|
||||
postMessage('success')
|
||||
} else {
|
||||
postMessage('failure')
|
||||
}
|
||||
`
|
||||
)
|
||||
rollback_worker.onmessage = e => {
|
||||
if (e.data == 'success') {
|
||||
document.getElementById('rollback-btn').outerHTML =
|
||||
'<button type="button" class="btn btn-danger" onclick="undo_rollback()" id="rollback-btn">Cancel rollback</button>'
|
||||
} else {
|
||||
document.getElementById('rollback-btn').outerHTML =
|
||||
'<button type="button" class="btn btn-danger" id="rollback-btn" disabled>Failed</button>'
|
||||
setTimeout(() => document.getElementById('rollback-btn').outerHTML =
|
||||
'<button type="button" class="btn btn-danger" onclick="rollback()" id="rollback-btn">Rollback</button>', 2000)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function undo_rollback() {
|
||||
let undo_rollback_worker = new Worker(
|
||||
`data:text/javascript,
|
||||
let s = require('child_process').spawnSync('pkexec', ['rm', '-f', '/blend/states/.load_prev_state']).status
|
||||
if (s === 0) {
|
||||
postMessage('success')
|
||||
} else {
|
||||
postMessage('failure')
|
||||
}
|
||||
`
|
||||
)
|
||||
undo_rollback_worker.onmessage = e => {
|
||||
if (e.data == 'success') {
|
||||
document.getElementById('rollback-btn').outerHTML =
|
||||
'<button type="button" class="btn btn-danger" onclick="rollback()" id="rollback-btn">Rollback</button>'
|
||||
} else {
|
||||
document.getElementById('rollback-btn').outerHTML =
|
||||
'<button type="button" class="btn btn-danger" id="rollback-btn" disabled>Failed</button>'
|
||||
setTimeout(() => document.getElementById('rollback-btn').outerHTML =
|
||||
'<button type="button" class="btn btn-danger" onclick="undo_rollback()" id="rollback-btn">Cancel rollback</button>', 2000)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function save_state() {
|
||||
let save_state_worker = new Worker(
|
||||
`data:text/javascript,
|
||||
let s = require('child_process').spawnSync('pkexec', ['blend-system', 'save-state']).status
|
||||
if (s === 0) {
|
||||
postMessage('success')
|
||||
} else {
|
||||
postMessage('failure')
|
||||
}
|
||||
`
|
||||
)
|
||||
save_state_worker.onmessage = e => {
|
||||
if (e.data == 'success') {
|
||||
document.getElementById('save-state-btn').outerHTML =
|
||||
'<button type="button" class="btn btn-success" id="save-state-btn" disabled>Saved state</button>'
|
||||
setTimeout(() => document.getElementById('save-state-btn').outerHTML =
|
||||
'<button type="button" id="save-state-btn" onclick="save_state()" class="btn btn-success">Save state</button>', 2000)
|
||||
} else {
|
||||
document.getElementById('save-state-btn').outerHTML =
|
||||
'<button type="button" class="btn btn-success" id="save-state-btn" disabled>Failed</button>'
|
||||
setTimeout(() => document.getElementById('save-state-btn').outerHTML =
|
||||
'<button type="button" id="save-state-btn" onclick="save_state()" class="btn btn-success">Save state</button>', 2000)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function check_rollback() {
|
||||
if (require('fs').existsSync('/blend/states/.load_prev_state')) {
|
||||
document.getElementById('rollback-btn').outerHTML =
|
||||
'<button type="button" class="btn btn-danger" onclick="undo_rollback()" id="rollback-btn">Cancel rollback</button>'
|
||||
} else {
|
||||
document.getElementById('rollback-btn').outerHTML =
|
||||
'<button type="button" class="btn btn-danger" onclick="rollback()" id="rollback-btn">Rollback</button>'
|
||||
}
|
||||
}
|
||||
|
||||
function check_state_creation() {
|
||||
if (require('fs').existsSync('/blend/states/.disable_states')) {
|
||||
document.getElementById('automatic-state-toggle').setAttribute('checked', '')
|
||||
}
|
||||
}
|
||||
|
||||
check_state_creation()
|
||||
check_rollback()
|
||||
|
||||
$('#automatic-state-toggle').on('change', () => {
|
||||
if (!document.getElementById('automatic-state-toggle').checked) {
|
||||
let enable_autostate_worker = new Worker(
|
||||
`data:text/javascript,
|
||||
let s = require('child_process').spawnSync('pkexec', ['rm', '-f', '/blend/states/.disable_states']).status
|
||||
if (s === 0) {
|
||||
postMessage('success')
|
||||
} else {
|
||||
postMessage('failure')
|
||||
}
|
||||
`
|
||||
)
|
||||
enable_autostate_worker.onmessage = e => {
|
||||
if (e.data == 'success') {
|
||||
document.getElementById('automatic-state-toggle').checked = false
|
||||
} else {
|
||||
document.getElementById('automatic-state-toggle').checked = true
|
||||
}
|
||||
}
|
||||
} else {
|
||||
let disable_autostate_worker = new Worker(
|
||||
`data:text/javascript,
|
||||
let s = require('child_process').spawnSync('pkexec', ['blend-system', 'toggle-states']).status
|
||||
if (s === 0) {
|
||||
postMessage('success')
|
||||
} else {
|
||||
postMessage('failure')
|
||||
}
|
||||
`
|
||||
)
|
||||
disable_autostate_worker.onmessage = e => {
|
||||
if (e.data == 'success') {
|
||||
document.getElementById('automatic-state-toggle').checked = true
|
||||
} else {
|
||||
document.getElementById('automatic-state-toggle').checked = false
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
49
blend-settings/src/pages/containers.html
Normal file
49
blend-settings/src/pages/containers.html
Normal file
|
@ -0,0 +1,49 @@
|
|||
<div class="container-fluid d-flex justify-content-center">
|
||||
<div class="col-12 col-lg-10 col-xl-8 mx-auto">
|
||||
<strong class="mb-0">Containers</strong>
|
||||
<p>You can install any app from any of the supported distributions (Arch, Fedora, and Ubuntu). Any apps you install in them will appear as regular applications on your system, and so will any binaries. In case a binary is common between two containers, the binary from the most recently created container will be exported. You can override this by rearranging (dragging) the containers below to select the priority that should be assigned to each container.</p>
|
||||
<div class="list-group mb-5 shadow" id="container-list">
|
||||
<div class="list-group-item">
|
||||
<div class="row align-items-center">
|
||||
<div class="col">
|
||||
<strong class="mb-0">Loading list of containers.</strong>
|
||||
<p class="text-muted mb-0">You'll find a list of all the containers here.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="container-fluid d-flex justify-content-center">
|
||||
<div class="col-12 col-lg-10 col-xl-8 mx-auto">
|
||||
<strong class="mb-0">Create new container</strong>
|
||||
<form onsubmit="create_container(); return false">
|
||||
<div class="form-group row">
|
||||
<label for="inputContainerName" class="col-sm-3 col-form-label">Container name</label>
|
||||
<div class="col-sm-4">
|
||||
<input type="text" class="form-control" id="inputContainerName" placeholder="Container name" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<label for="inputContainerDistro" class="col-sm-3 col-form-label">Distribution</label>
|
||||
<div class="col-sm-4">
|
||||
<select class="form-control" id="inputContainerDistro">
|
||||
<option selected>Arch</option>
|
||||
<option>Fedora Rawhide</option>
|
||||
<option>Ubuntu 22.04</option>
|
||||
<option>Ubuntu 22.10</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<br>
|
||||
<button type="submit" id="publish-button" class="btn btn-primary">Create container</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Import generic page JS. -->
|
||||
<script src="internal/js/generic_page.js"></script>
|
||||
|
||||
<!-- Import containers JS. -->
|
||||
<script src="internal/js/containers.js"></script>
|
64
blend-settings/src/pages/overlay.html
Normal file
64
blend-settings/src/pages/overlay.html
Normal file
|
@ -0,0 +1,64 @@
|
|||
<div class="container-fluid d-flex justify-content-center">
|
||||
<div class="col-12 col-lg-10 col-xl-8 mx-auto">
|
||||
<strong class="mb-0">System Settings</strong>
|
||||
<br><br>
|
||||
<div class="list-group mb-5 shadow">
|
||||
<div class="list-group-item">
|
||||
<div class="row align-items-center">
|
||||
<div class="col">
|
||||
<strong class="mb-0">Disable automatic state creation</strong>
|
||||
<p class="text-muted mb-0">blendOS creates copies of apps and config every 6 hours (and keeps the
|
||||
last two).</p>
|
||||
</div>
|
||||
<div class="col-auto">
|
||||
<div class="form-check form-switch align-middle">
|
||||
<input class="form-check-input align-middle" type="checkbox" role="switch"
|
||||
id="automatic-state-toggle">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="list-group-item">
|
||||
<div class="row align-items-center">
|
||||
<div class="col">
|
||||
<strong class="mb-0">Save current state</strong>
|
||||
<p class="text-muted mb-0">Create a copy of the current system state, including apps and config.</p>
|
||||
</div>
|
||||
<div class="col-auto">
|
||||
<div class="form-check form-switch align-middle">
|
||||
<button type="button" id="save-state-btn" onclick="save_state()" class="btn btn-success">Save state</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="list-group-item">
|
||||
<div class="row align-items-center">
|
||||
<div class="col">
|
||||
<strong class="mb-0">Rollback</strong>
|
||||
<p class="text-muted mb-0">Rollback to the most recent state on the next boot. (note: this is irreversible)
|
||||
</p>
|
||||
</div>
|
||||
<div class="col-auto">
|
||||
<div class="form-check form-switch align-middle">
|
||||
<button type="button" class="btn btn-danger" onclick="rollback()" id="rollback-btn">Rollback</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="container-fluid d-flex justify-content-center">
|
||||
<div class="col-12 col-lg-10 col-xl-8 mx-auto">
|
||||
<p>
|
||||
You can install packages just like you would on a regular Arch system, or install them in containers.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Import generic page JS. -->
|
||||
<script src="internal/js/generic_page.js"></script>
|
||||
|
||||
<!-- Import overlay JS. -->
|
||||
<script src="internal/js/overlay.js"></script>
|
110
blend-settings/src/pages/terminal.html
Normal file
110
blend-settings/src/pages/terminal.html
Normal file
|
@ -0,0 +1,110 @@
|
|||
<html>
|
||||
|
||||
<head>
|
||||
<link rel="stylesheet" href="../../node_modules/xterm/css/xterm.css" />
|
||||
<style>
|
||||
html,
|
||||
body,
|
||||
#term {
|
||||
margin: 0;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
background-color: #242430;
|
||||
}
|
||||
|
||||
.xterm {
|
||||
padding: 30px !important;
|
||||
}
|
||||
|
||||
*,
|
||||
*::before,
|
||||
*::after {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
*::-webkit-scrollbar-track {
|
||||
background-color: rgb(36, 36, 48);
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
*::-webkit-scrollbar {
|
||||
width: 5px;
|
||||
background-color: rgb(36, 36, 48);
|
||||
}
|
||||
|
||||
*::-webkit-scrollbar-thumb {
|
||||
background-color: rgb(61, 61, 74);
|
||||
border-radius: 10px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body style="height: 100%;">
|
||||
<div id="term" style="height: 100%; width: 100%;"></div>
|
||||
<script>
|
||||
var os = require("os");
|
||||
var pty = require("node-pty");
|
||||
var xterm = require("xterm");
|
||||
var ipc = require("electron").ipcRenderer;
|
||||
var { FitAddon } = require("xterm-addon-fit");
|
||||
|
||||
const fit = new FitAddon();
|
||||
|
||||
var once;
|
||||
|
||||
function create_term() {
|
||||
ipc.removeAllListeners('terminal.reset')
|
||||
ipc.removeAllListeners('terminal.keystroke')
|
||||
ipc.removeAllListeners('terminal.incomingData')
|
||||
ipc.removeAllListeners('title')
|
||||
|
||||
ipc.on("terminal.reset", (event, data) => {
|
||||
document.getElementById('term').innerHTML = ''
|
||||
create_term()
|
||||
});
|
||||
|
||||
var term = new xterm.Terminal({
|
||||
fontSize: 14,
|
||||
experimentalCharAtlas: 'dynamic',
|
||||
theme: {
|
||||
background: '#242430'
|
||||
}
|
||||
});
|
||||
|
||||
once = true
|
||||
|
||||
term.loadAddon(fit)
|
||||
|
||||
var term_e = document.getElementById('term');
|
||||
term.open(term_e);
|
||||
fit.fit()
|
||||
|
||||
ipc.on("terminal.incomingData", (event, data) => {
|
||||
term.write(data);
|
||||
});
|
||||
|
||||
ipc.on("title", (event, title) => {
|
||||
document.title = title;
|
||||
});
|
||||
|
||||
window.addEventListener('beforeunload', (event) => {
|
||||
term.dispose()
|
||||
})
|
||||
|
||||
window.onresize = function () {
|
||||
fit.fit();
|
||||
term.resize(term.cols, term.rows)
|
||||
ipc.send("terminal.resize", [term.cols, term.rows])
|
||||
};
|
||||
|
||||
term.onData(e => {
|
||||
ipc.send("terminal.keystroke", e);
|
||||
});
|
||||
}
|
||||
|
||||
ipc.on("terminal.reset", (event) => create_term)
|
||||
create_term()
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
0
blend-settings/src/preload.js
Normal file
0
blend-settings/src/preload.js
Normal file
Loading…
Add table
Add a link
Reference in a new issue