v2.0.0: Built-in Termux — full Linux environment, no external app needed
This commit is contained in:
126
www/js/app.js
126
www/js/app.js
@@ -1043,6 +1043,7 @@
|
||||
var Shell = null;
|
||||
var Installer = null;
|
||||
var Wake = null;
|
||||
var Bootstrap = null;
|
||||
var termState = {
|
||||
history: [],
|
||||
historyIndex: -1,
|
||||
@@ -1062,10 +1063,12 @@
|
||||
Shell = window.Capacitor && window.Capacitor.Plugins && window.Capacitor.Plugins.Shell;
|
||||
Installer = window.Capacitor && window.Capacitor.Plugins && window.Capacitor.Plugins.Installer;
|
||||
Wake = window.Capacitor && window.Capacitor.Plugins && window.Capacitor.Plugins.Wake;
|
||||
Bootstrap = window.Capacitor && window.Capacitor.Plugins && window.Capacitor.Plugins.Bootstrap;
|
||||
} catch(e) {}
|
||||
if (!Shell) console.warn('Shell plugin not available');
|
||||
if (!Installer) console.warn('Installer plugin not available');
|
||||
if (!Wake) console.warn('Wake plugin not available');
|
||||
if (!Bootstrap) console.warn('Bootstrap plugin not available');
|
||||
}
|
||||
|
||||
async function setWakeLock(on) {
|
||||
@@ -1710,17 +1713,16 @@
|
||||
];
|
||||
|
||||
async function checkDevTools() {
|
||||
if (!Shell) return false;
|
||||
if (!Bootstrap) return false;
|
||||
try {
|
||||
var result = await shellExec('which aapt2 2>/dev/null && echo "OK" || echo "MISSING"', termState.homeDir, false);
|
||||
termState.devToolsInstalled = result.output && result.output.indexOf('OK') >= 0;
|
||||
return termState.devToolsInstalled;
|
||||
var status = await Bootstrap.getStatus();
|
||||
return status.installed === true;
|
||||
} catch(e) { return false; }
|
||||
}
|
||||
|
||||
async function setupDevTools() {
|
||||
if (!Shell) {
|
||||
alert('Shell plugin not available');
|
||||
if (!Bootstrap) {
|
||||
alert('Bootstrap plugin not available');
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1734,94 +1736,38 @@
|
||||
btn.querySelector('.btn-text').textContent = 'Installing...';
|
||||
btn.querySelector('.btn-loader').style.display = 'inline-block';
|
||||
progress.style.display = 'block';
|
||||
progressText.textContent = 'Starting...';
|
||||
|
||||
var toolsDir = termState.toolsDir || (termState.homeDir + '/tools');
|
||||
var binDir = toolsDir + '/bin';
|
||||
var steps = [
|
||||
{ label: 'Creating directories...', cmd: 'mkdir -p ' + binDir + ' ' + toolsDir + '/lib ' + toolsDir + '/java' },
|
||||
{ label: 'Setting up shell...', cmd: 'cp /system/bin/sh ' + binDir + '/sh 2>/dev/null; chmod +x ' + binDir + '/* 2>/dev/null; echo OK' },
|
||||
{ label: 'Checking environment...', cmd: 'ls -la ' + binDir + '/ && echo "Environment ready"' }
|
||||
];
|
||||
Bootstrap.addListener('bootstrap-progress', function(event) {
|
||||
if (progressFill) progressFill.style.width = event.percent + '%';
|
||||
if (progressText) progressText.textContent = event.message;
|
||||
});
|
||||
|
||||
for (var i = 0; i < steps.length; i++) {
|
||||
progressText.textContent = steps[i].label;
|
||||
progressFill.style.width = ((i + 1) / (steps.length + 1) * 100) + '%';
|
||||
var result = await shellExec(steps[i].cmd, termState.homeDir, false);
|
||||
if (result.exitCode !== 0 && result.exitCode !== undefined) {
|
||||
progressText.textContent = 'Warning: ' + steps[i].label + ' had issues';
|
||||
try {
|
||||
var result = await Bootstrap.install();
|
||||
statusEl.innerHTML = '<p style="color:var(--success);font-size:16px;font-weight:700">✔ Termux environment installed!</p>' +
|
||||
'<p>Full Linux shell with bash, coreutils, and package manager ready.</p>' +
|
||||
'<p>Install build tools: open Terminal → type <code>pkg install aapt2 ecj dx apksigner</code></p>';
|
||||
btn.querySelector('.btn-text').textContent = 'Installed';
|
||||
btn.querySelector('.btn-loader').style.display = 'none';
|
||||
|
||||
termState.homeDir = result.prefixDir ? result.prefixDir.replace('/usr', '') : termState.homeDir;
|
||||
termState.cwd = termState.homeDir + '/home';
|
||||
if (Shell) {
|
||||
var env = await Shell.getEnv();
|
||||
termState.homeDir = env.HOME;
|
||||
termState.toolsDir = env.TOOLS;
|
||||
termState.projectsDir = env.PROJECTS;
|
||||
termState.cwd = env.CWD || env.HOME;
|
||||
}
|
||||
updateCwdDisplay();
|
||||
} catch(e) {
|
||||
statusEl.innerHTML = '<p style="color:var(--danger)">Install failed: ' + e.message + '</p>' +
|
||||
'<p>Check your internet connection and try again.</p>';
|
||||
btn.disabled = false;
|
||||
btn.querySelector('.btn-text').textContent = 'Retry Install';
|
||||
btn.querySelector('.btn-loader').style.display = 'none';
|
||||
}
|
||||
|
||||
progressText.textContent = 'Writing setup scripts...';
|
||||
progressFill.style.width = '80%';
|
||||
|
||||
var setupScript = '#!/system/bin/sh\n' +
|
||||
'TOOLS_DIR="' + toolsDir + '"\n' +
|
||||
'BIN_DIR="' + binDir + '"\n' +
|
||||
'echo "[*] Z.AI Dev Tools Setup"\n' +
|
||||
'echo "[*] Tools directory: $TOOLS_DIR"\n' +
|
||||
'echo "[*] For full build support, install these via Termux:"\n' +
|
||||
'echo " pkg install aapt2 openjdk-17 dx ecj"\n' +
|
||||
'echo ""\n' +
|
||||
'echo "[*] Checking available tools..."\n' +
|
||||
'for tool in aapt2 d8 ecj java apksigner zipalign; do\n' +
|
||||
' if which $tool 2>/dev/null; then\n' +
|
||||
' echo " [+] $tool: $(which $tool)"\n' +
|
||||
' else\n' +
|
||||
' echo " [-] $tool: not found"\n' +
|
||||
' fi\n' +
|
||||
'done\n' +
|
||||
'echo ""\n' +
|
||||
'echo "[*] For on-device APK building, you need:"\n' +
|
||||
'echo " 1. Install Termux from F-Droid or GitHub"\n' +
|
||||
'echo " 2. In Termux: pkg install aapt2 openjdk-17 dx ecj apksigner"\n' +
|
||||
'echo " 3. Set TOOLS_PATH in terminal to point to Termux binaries"\n' +
|
||||
'echo ""\n' +
|
||||
'echo "[*] Device info:"\n' +
|
||||
'uname -a\n' +
|
||||
'echo "Arch: $(uname -m)"\n' +
|
||||
'echo "[*] Done"\n';
|
||||
|
||||
await shellWriteFile(toolsDir + '/setup.sh', setupScript);
|
||||
await shellExec('chmod +x ' + toolsDir + '/setup.sh', termState.homeDir, false);
|
||||
|
||||
var projectTemplate = '#!/system/bin/sh\n' +
|
||||
'# Z.AI Quick Project Creator\n' +
|
||||
'PROJECT_NAME="${1:-myapp}"\n' +
|
||||
'PROJECT_DIR="' + (termState.projectsDir || termState.homeDir + '/projects') + '/$PROJECT_NAME"\n' +
|
||||
'mkdir -p "$PROJECT_DIR"/app/src/main/java/ai/z/app\n' +
|
||||
'mkdir -p "$PROJECT_DIR"/app/src/main/res/values\n' +
|
||||
'mkdir -p "$PROJECT_DIR"/app/src/main/res/layout\n' +
|
||||
'mkdir -p "$PROJECT_DIR"/app/src/main/res/mipmap-hdpi\n' +
|
||||
'mkdir -p "$PROJECT_DIR"/build\n' +
|
||||
'# AndroidManifest.xml\n' +
|
||||
'cat > "$PROJECT_DIR"/app/src/main/AndroidManifest.xml << \'MANIFEST\'\n' +
|
||||
'<?xml version="1.0" encoding="utf-8"?>\n' +
|
||||
'<manifest xmlns:android="http://schemas.android.com/apk/res/android"\n' +
|
||||
' package="ai.z.app">\n' +
|
||||
' <application android:label="$PROJECT_NAME" android:theme="@android:style/Theme.Material.Light">\n' +
|
||||
' <activity android:name=".MainActivity" android:exported="true">\n' +
|
||||
' <intent-filter>\n' +
|
||||
' <action android:name="android.intent.action.MAIN"/>\n' +
|
||||
' <category android:name="android.intent.category.LAUNCHER"/>\n' +
|
||||
' </intent-filter>\n' +
|
||||
' </activity>\n' +
|
||||
' </application>\n' +
|
||||
'</manifest>\n' +
|
||||
'MANIFEST\n' +
|
||||
'echo "[OK] Project created: $PROJECT_DIR"\n' +
|
||||
'echo "[*] Next: Ask AI to generate the Java code, then build with Deploy"\n';
|
||||
|
||||
await shellWriteFile(toolsDir + '/create-project.sh', projectTemplate);
|
||||
await shellExec('chmod +x ' + toolsDir + '/create-project.sh', termState.homeDir, false);
|
||||
|
||||
progressFill.style.width = '100%';
|
||||
progressText.textContent = 'Setup complete!';
|
||||
statusEl.innerHTML = '<p style="color:var(--success)">Dev environment ready!</p>' +
|
||||
'<p>Use the terminal to build apps. Install Termux for full tool support (aapt2, d8, ecj).</p>';
|
||||
|
||||
btn.querySelector('.btn-text').textContent = 'Installed';
|
||||
btn.querySelector('.btn-loader').style.display = 'none';
|
||||
}
|
||||
|
||||
// ---- Init Terminal ----
|
||||
|
||||
Reference in New Issue
Block a user