release blend 2.0.0
This commit is contained in:
parent
4e4bdd33d2
commit
37d4a6155e
36 changed files with 2557 additions and 458 deletions
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
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
Loading…
Add table
Add a link
Reference in a new issue