mirror of
https://github.com/ivabus/gui
synced 2025-04-23 14:07:14 +03:00
Merge pull request #195 from teaxyz/open-terminal
open terminal on cli install or install package
This commit is contained in:
commit
ed7f45a32f
5 changed files with 91 additions and 5 deletions
|
@ -2,13 +2,11 @@ import windowStateManager from 'electron-window-state';
|
|||
import { app, BrowserWindow, ipcMain } from 'electron';
|
||||
import contextMenu from 'electron-context-menu';
|
||||
import serve from 'electron-serve';
|
||||
import path from 'path';
|
||||
import fs from 'fs';
|
||||
|
||||
import { getInstalledPackages } from './libs/teaDir';
|
||||
import { readSessionData, writeSessionData } from './libs/auth';
|
||||
import type { Session } from '../src/libs/types';
|
||||
import { installPackage } from './libs/cli';
|
||||
import { installPackage, openTerminal } from './libs/cli';
|
||||
|
||||
// try {
|
||||
// //@ts-ignore only used in dev should not be packaged inprod
|
||||
|
@ -130,3 +128,14 @@ ipcMain.handle('install-package', async (_, data) => {
|
|||
const result = await installPackage(data.full_name);
|
||||
return result;
|
||||
});
|
||||
|
||||
ipcMain.handle('open-terminal', async (_, data) => {
|
||||
const { cmd } = data as { cmd: string };
|
||||
try {
|
||||
// TODO: detect if mac or linux
|
||||
// current openTerminal is only design for Mac
|
||||
await openTerminal(cmd);
|
||||
} catch (error) {
|
||||
console.error('elast:', error);
|
||||
}
|
||||
});
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
import { spawn } from 'child_process';
|
||||
import { clean } from 'semver';
|
||||
import { getGuiPath } from './teaDir';
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
|
||||
export async function installPackage(full_name: string) {
|
||||
return await new Promise((resolve, reject) => {
|
||||
|
@ -27,3 +30,61 @@ export async function installPackage(full_name: string) {
|
|||
});
|
||||
});
|
||||
}
|
||||
|
||||
export async function openTerminal(cmd: string) {
|
||||
let scriptPath = '';
|
||||
try {
|
||||
// TODO SECURITY: escape the cmd if possible or create whitelist of acceptable commands
|
||||
scriptPath = await createCommandScriptFile(cmd);
|
||||
let stdout = ``;
|
||||
let stderr = ``;
|
||||
|
||||
await new Promise((resolve, reject) => {
|
||||
const child = spawn('/usr/bin/osascript', [scriptPath]);
|
||||
child.stdout.on('data', (data) => {
|
||||
stdout += data.toString().trim();
|
||||
});
|
||||
child.stderr.on('data', (data) => {
|
||||
stderr += data.toString().trim();
|
||||
});
|
||||
|
||||
child.on('exit', () => {
|
||||
console.log('exit:', stdout);
|
||||
resolve(stdout);
|
||||
});
|
||||
|
||||
child.on('error', () => {
|
||||
reject(new Error(stderr));
|
||||
});
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('root:', error);
|
||||
} finally {
|
||||
if (scriptPath) await fs.unlinkSync(scriptPath);
|
||||
}
|
||||
}
|
||||
|
||||
const createCommandScriptFile = async (cmd: string): Promise<string> => {
|
||||
const guiFolder = getGuiPath();
|
||||
const tmpFilePath = path.join(guiFolder, `${+new Date()}.scpt`);
|
||||
const command = `"${cmd.replace(/"/g, '\\"')}"`;
|
||||
const script = `
|
||||
tell application "iTerm"
|
||||
activate
|
||||
if application "iTerm" is running then
|
||||
try
|
||||
tell the first window to create tab with default profile
|
||||
on error
|
||||
create window with default profile
|
||||
end try
|
||||
end if
|
||||
|
||||
delay 0.1
|
||||
|
||||
tell the first window to tell current session to write text ${command}
|
||||
end tell
|
||||
`.trim();
|
||||
|
||||
await fs.writeFileSync(tmpFilePath, script, 'utf-8');
|
||||
return tmpFilePath;
|
||||
};
|
||||
|
|
|
@ -16,6 +16,10 @@ export const getTeaPath = () => {
|
|||
return teaPath;
|
||||
};
|
||||
|
||||
export const getGuiPath = () => {
|
||||
return path.join(getTeaPath(), 'tea.xyz/gui');
|
||||
};
|
||||
|
||||
export async function getInstalledPackages() {
|
||||
const pkgsPath = getTeaPath();
|
||||
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
<script lang="ts">
|
||||
import '$appcss';
|
||||
import Button from '@tea/ui/Button/Button.svelte';
|
||||
|
||||
const { ipcRenderer } = window.require('electron');
|
||||
let copyButtonText = 'COPY';
|
||||
const copyValue = `sh <(curl https://tea.xyz)`;
|
||||
|
||||
|
@ -8,6 +10,10 @@
|
|||
copyButtonText = 'COPIED!';
|
||||
navigator.clipboard.writeText(copyValue);
|
||||
};
|
||||
|
||||
const onInstall = () => {
|
||||
ipcRenderer.invoke('open-terminal', { cmd: copyValue });
|
||||
}
|
||||
</script>
|
||||
|
||||
<section class="border-gray mt-4 border bg-black">
|
||||
|
@ -20,7 +26,7 @@
|
|||
<footer class="border-gray flex h-20 border-t text-white">
|
||||
<input class="flex-grow bg-black pl-4" disabled value="sh <(curl tea.xyz)>" />
|
||||
<Button class="w-16 border-0 border-l-2 text-sm" onClick={onCopy}>{copyButtonText}</Button>
|
||||
<Button class="w-56 border-0 border-l-2 text-sm" onClick={() => console.log('cli')}
|
||||
<Button class="w-56 border-0 border-l-2 text-sm" onClick={onInstall}
|
||||
>OPEN IN TERMINAL</Button
|
||||
>
|
||||
</footer>
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
import { onMount } from 'svelte';
|
||||
import { getPackageBottles } from '@api';
|
||||
|
||||
const { ipcRenderer } = window.require('electron');
|
||||
|
||||
export let pkg: Package;
|
||||
let bottles: Bottle[] = [];
|
||||
let packageRating = 0;
|
||||
|
@ -18,6 +20,10 @@
|
|||
navigator.clipboard.writeText(copyValue);
|
||||
};
|
||||
|
||||
const onOpenTerminal = () => {
|
||||
ipcRenderer.invoke('open-terminal', { cmd: `sh <(curl tea.xyz) +${pkg.full_name}` });
|
||||
}
|
||||
|
||||
onMount(async () => {
|
||||
try {
|
||||
bottles = await getPackageBottles(pkg.full_name);
|
||||
|
@ -45,7 +51,7 @@
|
|||
<footer class="border-gray flex h-20 border-t text-white">
|
||||
<input class="click-copy flex-grow bg-black pl-4" disabled value={copyValue} />
|
||||
<Button class="w-16 border-0 border-l-2 text-sm" onClick={onCopy}>{copyButtonText}</Button>
|
||||
<Button class="w-56 border-0 border-l-2 text-sm" onClick={() => console.log('cli')}
|
||||
<Button class="w-56 border-0 border-l-2 text-sm" onClick={onOpenTerminal}
|
||||
>OPEN IN TERMINAL</Button
|
||||
>
|
||||
</footer>
|
||||
|
|
Loading…
Reference in a new issue