diff --git a/README.md b/README.md index a01d17e8..ef99c7ed 100644 --- a/README.md +++ b/README.md @@ -13,8 +13,8 @@

- - 2023 Roadmaps - I'm back! + + 2024 Roadmaps - I'm back!

@@ -259,6 +259,21 @@ $ yarn create nextron-app my-app --example basic-lang-javascript $ pnpm dlx create-nextron-app my-app --example basic-lang-javascript ``` +### [examples/basic-lang-javascript-python](./examples/basic-lang-javascript-python) + +

+ +``` +# with npx +$ npx create-nextron-app my-app --example basic-lang-javascript-python + +# with yarn +$ yarn create nextron-app my-app --example basic-lang-javascript-python + +# with pnpm +$ pnpm dlx create-nextron-app my-app --example basic-lang-javascript-python +``` + ### [examples/basic-lang-typescript](./examples/basic-lang-typescript)

diff --git a/examples/basic-lang-javascript-python/README.md b/examples/basic-lang-javascript-python/README.md new file mode 100644 index 00000000..436d0539 --- /dev/null +++ b/examples/basic-lang-javascript-python/README.md @@ -0,0 +1,38 @@ +

+ +## Usage + +### Create an App + +``` +# with npx +$ npx create-nextron-app my-app --example basic-lang-javascript-python + +# with yarn +$ yarn create nextron-app my-app --example basic-lang-javascript-python + +# with pnpm +$ pnpm dlx create-nextron-app my-app --example basic-lang-javascript-python +``` + +### Install Dependencies + +``` +$ cd my-app + +# using yarn or npm +$ yarn (or `npm install`) + +# using pnpm +$ pnpm install --shamefully-hoist +``` + +### Use it + +``` +# development mode +$ yarn dev (or `npm run dev` or `pnpm run dev`) + +# production build +$ yarn build (or `npm run build` or `pnpm run build`) +``` diff --git a/examples/basic-lang-javascript-python/electron-builder.yml b/examples/basic-lang-javascript-python/electron-builder.yml new file mode 100644 index 00000000..eaae8ab3 --- /dev/null +++ b/examples/basic-lang-javascript-python/electron-builder.yml @@ -0,0 +1,14 @@ +appId: com.example.nextron +productName: My Nextron App +copyright: Copyright © 2018 Yoshihide Shiono +directories: + output: dist + buildResources: resources +files: + - from: . + filter: + - package.json + - app +extraFiles: + - scripts +publish: null diff --git a/examples/basic-lang-javascript-python/main/background.js b/examples/basic-lang-javascript-python/main/background.js new file mode 100644 index 00000000..98132be7 --- /dev/null +++ b/examples/basic-lang-javascript-python/main/background.js @@ -0,0 +1,75 @@ +import path from 'path' +import { exec } from 'child_process' +import { app, ipcMain } from 'electron' +import serve from 'electron-serve' +import { createWindow } from './helpers' + +const isProd = process.env.NODE_ENV === 'production' + +async function startProcess(event, value) { + if (event) { + /* + 'parentDir' is used to get this folder -> /Applications/.app/Contents/ + so that we can run our .sh file which will also launch the Python or Rust script. + So the script folder will be moved into parentDir/ in prod mode. + Note: this will only work if the target mahcine have Python or Rust installed. + */ + let scriptPath + if (isProd) { + const parentDir = path.dirname(path.dirname(path.dirname(__dirname))) + scriptPath = path.join(parentDir, 'scripts/runner.sh') + } else { + scriptPath = path.join(__dirname, '../scripts/runner.sh') + } + // console.log(`DEBUG: scriptPath: ${scriptPath}`) + const cmd = `sh "${scriptPath}" ${value}` + + exec(cmd, (error, stdout) => { + if (error) { + console.error(`ERROR: Error executing post-install script: ${error}`) // will be seen only dev mode, not in prod mode + event.sender.send('log', error.message) // will be seen in both dev and prod mode (in the frontend) + return + } + event.sender.send('log', 'Python script executed successfully') + event.sender.send('message', stdout) + }) + + // ~/.yourApp.log will be helpfull to log process in production mode + } +} + +ipcMain.on('run-sh', async (event, value) => { + console.log('DEBUG: starting process') // for dev mode + event.sender.send('log', 'Running...') // for prod mode + await startProcess(event, value) +}) + +if (isProd) { + serve({ directory: 'app' }) +} else { + app.setPath('userData', `${app.getPath('userData')} (development)`) +} + +;(async () => { + await app.whenReady() + + const mainWindow = createWindow('main', { + width: 1000, + height: 600, + webPreferences: { + preload: path.join(__dirname, 'preload.js'), + }, + }) + + if (isProd) { + await mainWindow.loadURL('app://./home') + } else { + const port = process.argv[2] + await mainWindow.loadURL(`http://localhost:${port}/home`) + mainWindow.webContents.openDevTools() + } +})() + +app.on('window-all-closed', () => { + app.quit() +}) diff --git a/examples/basic-lang-javascript-python/package.json b/examples/basic-lang-javascript-python/package.json new file mode 100644 index 00000000..12b20c1e --- /dev/null +++ b/examples/basic-lang-javascript-python/package.json @@ -0,0 +1,25 @@ +{ + "private": true, + "name": "my-nextron-app", + "description": "My application description", + "version": "1.0.0", + "author": "Yoshihide Shiono ", + "main": "app/background.js", + "scripts": { + "dev": "nextron", + "build": "nextron build", + "postinstall": "electron-builder install-app-deps" + }, + "dependencies": { + "electron-serve": "^1.1.0", + "electron-store": "^8.1.0" + }, + "devDependencies": { + "electron": "^26.2.2", + "electron-builder": "^24.6.4", + "next": "^12.3.4", + "nextron": "^8.12.0", + "react": "^18.2.0", + "react-dom": "^18.2.0" + } +} diff --git a/examples/basic-lang-javascript-python/renderer/next.config.js b/examples/basic-lang-javascript-python/renderer/next.config.js new file mode 100644 index 00000000..60e1d31c --- /dev/null +++ b/examples/basic-lang-javascript-python/renderer/next.config.js @@ -0,0 +1,10 @@ +/** @type {import('next').NextConfig} */ +module.exports = { + trailingSlash: true, + images: { + unoptimized: true, + }, + webpack: (config) => { + return config + }, +} diff --git a/examples/basic-lang-javascript-python/renderer/pages/home.jsx b/examples/basic-lang-javascript-python/renderer/pages/home.jsx new file mode 100644 index 00000000..98670850 --- /dev/null +++ b/examples/basic-lang-javascript-python/renderer/pages/home.jsx @@ -0,0 +1,63 @@ +import React from 'react' +import Head from 'next/head' +import Link from 'next/link' +import Image from 'next/image' + +export default function HomePage() { + const [log, setLog] = React.useState('') + const [value, setValue] = React.useState('5') + const [message, setMessage] = React.useState('') + + const handleChange = (event) => { + setValue(event.target.value) + setMessage('') + } + + React.useEffect(() => { + window.ipc.on('log', (log) => { + setLog(log) + }) + window.ipc.on('message', (msg) => { + setMessage(msg) + }) + }, []) + + return ( + + + Home - Nextron (basic-lang-javascript-python) + +
+

+ ⚡ Electron + Next.js ⚡ - + + Go to next page + +

+ Logo image +
+
+

+ Calculate the sqaure of your number: + +

+ +

{log}

+

+ the square of {value} is {'-> '} {message} +

+
+
+ ) +} diff --git a/examples/basic-lang-javascript-python/renderer/pages/next.jsx b/examples/basic-lang-javascript-python/renderer/pages/next.jsx new file mode 100644 index 00000000..d102e0bf --- /dev/null +++ b/examples/basic-lang-javascript-python/renderer/pages/next.jsx @@ -0,0 +1,21 @@ +import React from 'react' +import Head from 'next/head' +import Link from 'next/link' + +export default function NextPage() { + return ( + + + Next - Nextron (basic-lang-javascript-python) + +
+

+ ⚡ Electron + Next.js ⚡ - + + Go to home page + +

+
+
+ ) +} diff --git a/examples/basic-lang-javascript-python/scripts/main.py b/examples/basic-lang-javascript-python/scripts/main.py new file mode 100644 index 00000000..e06d2c4a --- /dev/null +++ b/examples/basic-lang-javascript-python/scripts/main.py @@ -0,0 +1,8 @@ +import sys, time + +def square_of_number(): + # time.sleep(3) # Simulate a long running process :), you can comment this line to have RT + print(int(sys.argv[1]) ** 2) + +if __name__ == "__main__": + square_of_number() diff --git a/examples/basic-lang-javascript-python/scripts/runner.sh b/examples/basic-lang-javascript-python/scripts/runner.sh new file mode 100644 index 00000000..3be934a9 --- /dev/null +++ b/examples/basic-lang-javascript-python/scripts/runner.sh @@ -0,0 +1,6 @@ +#!/bin/sh + +cd "$(dirname "$0")" || exit 1 # cd to the script directory or exit if failed + +# run the app and pass the second argument to the app +echo $(python main.py $1)