Add initial Android app support
This commit is contained in:
parent
0024d6692b
commit
9f7dee08a8
11 changed files with 306 additions and 30 deletions
7
.gitignore
vendored
7
.gitignore
vendored
|
@ -1,3 +1,4 @@
|
|||
/blend-settings/node_modules
|
||||
/blend-settings/package-lock.json
|
||||
/blend-settings/build/
|
||||
/blend-settings/node_modules/
|
||||
/blend-settings/build/
|
||||
/blend-settings/dist/
|
||||
/blend-settings/package-lock.json
|
2
blend
2
blend
|
@ -107,7 +107,7 @@ def check_container(name):
|
|||
_list = subprocess.run(['podman', 'ps', '-a', '--no-trunc', '--size', '--format',
|
||||
'{{.Names}}:{{.Mounts}}'], stdout=subprocess.PIPE).stdout.decode('utf-8').strip()
|
||||
for container in _list.splitlines(keepends=False):
|
||||
if 'blend' in container.split(':')[1] and name.strip() == container.split(':')[0]:
|
||||
if ('blend' in container.split(':')[1] or 'distrobox' in container.split(':')[1]) and name.strip() == container.split(':')[0]:
|
||||
return True
|
||||
return False
|
||||
|
||||
|
|
|
@ -4,6 +4,9 @@ const pty = require("node-pty");
|
|||
|
||||
var mainWindow, terminalWindow, ptyProcess
|
||||
|
||||
app.commandLine.appendSwitch('enable-transparent-visuals');
|
||||
app.disableHardwareAcceleration();
|
||||
|
||||
function createWindow() {
|
||||
mainWindow = new BrowserWindow({
|
||||
minWidth: 1000,
|
||||
|
@ -138,7 +141,9 @@ function loadTerminalWindow(title, cmd) {
|
|||
app.whenReady().then(() => {
|
||||
app.allowRendererProcessReuse = false
|
||||
|
||||
createWindow()
|
||||
setTimeout(() => {
|
||||
createWindow();
|
||||
}, 1000);
|
||||
createTerminalWindow()
|
||||
|
||||
ipcMain.on('create-term', (event, data) => {
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
"scripts": {
|
||||
"start": "electron .",
|
||||
"icons": "electron-icon-maker --input=./static/icon.png --output=./build/",
|
||||
"electron-builder": "electron-builder",
|
||||
"pack": "electron-builder --dir",
|
||||
"dist": "electron-builder"
|
||||
},
|
||||
|
|
|
@ -14,9 +14,11 @@
|
|||
<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>
|
||||
<button class="btn btn-outline-light active shadow-none" id="containers-button" onclick="page('containers')">Linux
|
||||
Containers</button>
|
||||
<button class="btn btn-outline-light shadow-none" id="android-button" onclick="page('android')">Android
|
||||
Apps</button>
|
||||
<button class="btn btn-outline-light shadow-none" id="system-button" onclick="page('system')">System</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@ -44,12 +46,20 @@
|
|||
case 'containers':
|
||||
$('#webview').load("pages/containers.html");
|
||||
$('#containers-button').addClass('active')
|
||||
$('#overlay-button').removeClass('active')
|
||||
$('#android-button').removeClass('active')
|
||||
$('#system-button').removeClass('active')
|
||||
break;
|
||||
case 'overlay':
|
||||
$('#webview').load("pages/overlay.html");
|
||||
case 'android':
|
||||
$('#webview').load("pages/android.html");
|
||||
$('#containers-button').removeClass('active')
|
||||
$('#overlay-button').addClass('active')
|
||||
$('#android-button').addClass('active')
|
||||
$('#system-button').removeClass('active')
|
||||
break;
|
||||
case 'system':
|
||||
$('#webview').load("pages/system.html");
|
||||
$('#containers-button').removeClass('active')
|
||||
$('#android-button').removeClass('active')
|
||||
$('#system-button').addClass('active')
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
171
blend-settings/src/internal/js/android.js
Normal file
171
blend-settings/src/internal/js/android.js
Normal file
|
@ -0,0 +1,171 @@
|
|||
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 init_waydroid() {
|
||||
document.getElementById('initialize-btn').outerHTML =
|
||||
'<button type="button" id="initialize-btn" onclick="init_waydroid()" class="btn btn-primary" disabled>Initializing...</button>'
|
||||
let init_worker = new Worker(
|
||||
`data:text/javascript,
|
||||
require('child_process').spawnSync('pkexec', ['waydroid', 'init'])
|
||||
require('child_process').spawn('sh', ['-c', 'waydroid session start & disown'])
|
||||
setTimeout(() => {
|
||||
require('child_process').spawnSync('pkexec', ['waydroid', 'shell', 'pm', 'disable', 'com.android.inputmethod.latin'])
|
||||
require('child_process').spawnSync('waydroid', ['prop', 'set', 'persist.waydroid.multi_windows', 'true'])
|
||||
postMessage('success')
|
||||
}, 2000)
|
||||
`
|
||||
)
|
||||
init_worker.onmessage = e => {
|
||||
if (e.data == 'success') {
|
||||
document.getElementById('init-waydroid').classList.add('d-none')
|
||||
document.getElementById('waydroid-initialized-settings').classList.remove('d-none')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function enable_multi_window() {
|
||||
document.getElementById('multiwindow-btn').outerHTML =
|
||||
'<button type="button" id="multiwindow-btn" onclick="enable_multi_window()" class="btn btn-primary" disabled>Enabling...</button>'
|
||||
let multi_window_worker = new Worker(
|
||||
`data:text/javascript,
|
||||
require('child_process').spawn('sh', ['-c', 'waydroid session start & disown'])
|
||||
setTimeout(() => { require('child_process').spawnSync('waydroid', ['prop', 'set', 'persist.waydroid.multi_windows', 'true']); require('child_process').spawn('sh', ['-c', 'waydroid session stop']); postMessage('success') }, 500)
|
||||
`
|
||||
)
|
||||
multi_window_worker.onmessage = e => {
|
||||
if (e.data == 'success') {
|
||||
document.getElementById('multiwindow-btn').outerHTML =
|
||||
'<button type="button" id="multiwindow-btn" onclick="disable_multi_window()" class="btn btn-primary">Disable</button>'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function disable_multi_window() {
|
||||
document.getElementById('multiwindow-btn').outerHTML =
|
||||
'<button type="button" id="multiwindow-btn" onclick="enable_multi_window()" class="btn btn-primary" disabled>Disabling...</button>'
|
||||
let multi_window_worker = new Worker(
|
||||
`data:text/javascript,
|
||||
require('child_process').spawn('sh', ['-c', 'waydroid session start & disown'])
|
||||
setTimeout(() => { require('child_process').spawnSync('waydroid', ['prop', 'set', 'persist.waydroid.multi_windows', 'false']); require('child_process').spawn('sh', ['-c', 'waydroid session stop']); postMessage('success') }, 500)
|
||||
`
|
||||
)
|
||||
multi_window_worker.onmessage = e => {
|
||||
if (e.data == 'success') {
|
||||
document.getElementById('multiwindow-btn').outerHTML =
|
||||
'<button type="button" id="multiwindow-btn" onclick="enable_multi_window()" class="btn btn-primary">Enable</button>'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function check_multi_window_enabled() {
|
||||
let check_worker = new Worker(
|
||||
`data:text/javascript,
|
||||
require('child_process').spawn('sh', ['-c', 'waydroid session start & disown'])
|
||||
setTimeout(() => { let val = require('child_process').spawnSync('waydroid', ['prop', 'get', 'persist.waydroid.multi_windows']).stdout; postMessage(val) }, 500)
|
||||
`
|
||||
)
|
||||
check_worker.onmessage = e => {
|
||||
if (new TextDecoder("utf-8").decode(e.data).trim() == 'true') {
|
||||
document.getElementById('multiwindow-btn').outerHTML =
|
||||
'<button type="button" id="multiwindow-btn" onclick="disable_multi_window()" class="btn btn-primary">Disable</button>'
|
||||
} else {
|
||||
document.getElementById('multiwindow-btn').outerHTML =
|
||||
'<button type="button" id="multiwindow-btn" onclick="enable_multi_window()" class="btn btn-primary">Enable</button>'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
require('fs').stat('/var/lib/waydroid', (err, stat) => {
|
||||
if (err == null) {
|
||||
document.getElementById('waydroid-initialize-settings').classList.add('d-none')
|
||||
document.getElementById('waydroid-initialized-settings').classList.remove('d-none')
|
||||
}
|
||||
})
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
93
blend-settings/src/pages/android.html
Normal file
93
blend-settings/src/pages/android.html
Normal file
|
@ -0,0 +1,93 @@
|
|||
<div class="container-fluid d-flex justify-content-center">
|
||||
<div class="col-12 col-lg-10 col-xl-8 mx-auto">
|
||||
<div id="waydroid-initialize-settings">
|
||||
<div class="list-group mt-3 mb-5 shadow" id="waydroid-initialize-settings">
|
||||
<div class="list-group-item">
|
||||
<div class="row align-items-center">
|
||||
<div class="col">
|
||||
<strong class="mb-0">Initialize Android App Support</strong>
|
||||
<p class="text-muted mb-0">Initialize WayDroid to be able to run Android apps.</p>
|
||||
</div>
|
||||
<div class="col-auto">
|
||||
<div class="form-check form-switch align-middle">
|
||||
<button type="button" id="initialize-btn" onclick="init_waydroid()"
|
||||
class="btn btn-primary">Initialize</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="d-none" id="waydroid-initialized-settings">
|
||||
<div id="main-list" class="mb-3">
|
||||
<div class="list-group-item" id="">
|
||||
<div class="row align-items-center">
|
||||
<div class="col">
|
||||
<strong class="mb-0">App Lounge (/e/)</strong>
|
||||
<p class="text-muted mb-0">An installable catalogue of FOSS Android applications.</p>
|
||||
</div>
|
||||
<div class="col-auto">
|
||||
<div class="form-check form-switch align-middle">
|
||||
<button type="button" id="e-applounge-inst-btn" onclick="install_e_applounge()" class="btn btn-primary"
|
||||
disabled>Checking status...</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<strong>Install a store</strong>
|
||||
<div class="list-group mt-3 mb-4 shadow">
|
||||
<div>
|
||||
<div class="list-group-item" id="multi-window">
|
||||
<div class="row align-items-center">
|
||||
<div class="col">
|
||||
<strong class="mb-0">App Lounge (/e/)</strong>
|
||||
<p class="text-muted mb-0">An installable catalogue of FOSS Android applications.</p>
|
||||
</div>
|
||||
<div class="col-auto">
|
||||
<div class="form-check form-switch align-middle">
|
||||
<button type="button" id="e-applounge-inst-btn" onclick="install_e_applounge()"
|
||||
class="btn btn-primary" disabled>Checking status...</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="list-group-item" id="multi-window">
|
||||
<div class="row align-items-center">
|
||||
<div class="col">
|
||||
<strong class="mb-0">Aurora Store (Nightly)</strong>
|
||||
<p class="text-muted mb-0">An open-source Google Play Store client.</p>
|
||||
</div>
|
||||
<div class="col-auto">
|
||||
<div class="form-check form-switch align-middle">
|
||||
<button type="button" id="aurora-store-inst-btn" onclick="install_aurora_store()"
|
||||
class="btn btn-primary" disabled>Checking status...</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="list-group-item" id="multi-window">
|
||||
<div class="row align-items-center">
|
||||
<div class="col">
|
||||
<strong class="mb-0">F-Droid</strong>
|
||||
<p class="text-muted mb-0">An installable catalogue of FOSS Android applications.</p>
|
||||
</div>
|
||||
<div class="col-auto">
|
||||
<div class="form-check form-switch align-middle">
|
||||
<button type="button" id="f-droid-btn" onclick="install_f_droid()" class="btn btn-primary"
|
||||
disabled>Checking status...</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Import generic page JS. -->
|
||||
<script src="internal/js/generic_page.js"></script>
|
||||
|
||||
<!-- Import overlay JS. -->
|
||||
<script src="internal/js/android.js"></script>
|
|
@ -61,4 +61,4 @@
|
|||
<script src="internal/js/generic_page.js"></script>
|
||||
|
||||
<!-- Import overlay JS. -->
|
||||
<script src="internal/js/overlay.js"></script>
|
||||
<script src="internal/js/system.js"></script>
|
13
blend-system
13
blend-system
|
@ -87,19 +87,6 @@ def current_state():
|
|||
_state = int(s[5:-7])
|
||||
return _state
|
||||
|
||||
def load_overlay():
|
||||
if os.path.isfile('/blend/states/.load_prev_state') and os.path.isfile(f'/blend/states/state{current_state()}.tar.gz'):
|
||||
load_prev_state()
|
||||
os.remove('/blend/states/.load_prev_state')
|
||||
subprocess.call(['mkdir', '-p', '/blend/overlay/current/usr'], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
|
||||
subprocess.call(['rm', '-rf', '/blend/overlay/workdir'], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
|
||||
subprocess.call(['mkdir', '-p', '/blend/overlay/workdir'], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
|
||||
subprocess.call(['touch', '/blend/overlay/current/usr/.blend_overlay'], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
|
||||
subprocess.call(['chattr', '+i', '/blend/overlay/current/usr/.blend_overlay'], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
|
||||
subprocess.call(['mount', '-t', 'overlay', 'overlay', '-o', 'rw,lowerdir=/usr,upperdir=/blend/overlay/current/usr,workdir=/blend/overlay/workdir',
|
||||
'/usr', '-o', 'index=off'], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
|
||||
info('mounted overlay')
|
||||
|
||||
def save_state():
|
||||
subprocess.call(['mkdir', '-p', '/blend/states'], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
|
||||
state = current_state() + 1
|
||||
|
|
16
blend.hook
16
blend.hook
|
@ -15,8 +15,16 @@ run_latehook() {
|
|||
rm -f "/new_root/blend/states/state${c}.tar.gz" "/new_root/blend/states/.load_prev_state"
|
||||
fi
|
||||
|
||||
mkdir -p /new_root/blend/overlay/current/usr /new_root/usr
|
||||
rm -rf /new_root/blend/overlay/workdir
|
||||
mkdir -p /new_root/blend/overlay/workdir
|
||||
mount -t overlay overlay -o 'lowerdir=/new_root/usr,upperdir=/new_root/blend/overlay/current/usr,workdir=/new_root/blend/overlay/workdir' /new_root/usr -o index=off
|
||||
mkdir -p /new_root/blend/overlay/current/usr/bin \
|
||||
/new_root/blend/overlay/current/usr/sbin \
|
||||
/new_root/blend/overlay/current/usr/share/plymouth
|
||||
|
||||
mkdir -p /new_root/usr/bin \
|
||||
/new_root/usr/sbin \
|
||||
/new_root/usr/share/plymouth
|
||||
rm -rf /new_root/blend/overlay/workdir_1 /new_root/blend/overlay/workdir_2 /new_root/blend/overlay/workdir_3
|
||||
mkdir -p /new_root/blend/overlay/workdir_1 /new_root/blend/overlay/workdir_2 /new_root/blend/overlay/workdir_3
|
||||
mount -t overlay overlay -o 'lowerdir=/new_root/usr/bin,upperdir=/new_root/blend/overlay/current/usr/bin,workdir=/new_root/blend/overlay/workdir_1' /new_root/usr/bin -o index=off
|
||||
mount -t overlay overlay -o 'lowerdir=/new_root/usr/sbin,upperdir=/new_root/blend/overlay/current/usr/sbin,workdir=/new_root/blend/overlay/workdir_2' /new_root/usr/sbin -o index=off
|
||||
mount -t overlay overlay -o 'lowerdir=/new_root/usr/share/plymouth,upperdir=/new_root/blend/overlay/current/usr/share/plymouth,workdir=/new_root/blend/overlay/workdir_3' /new_root/usr/share/plymouth -o index=off
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue