Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Basic js python example #428

Merged
merged 12 commits into from
Feb 3, 2024
19 changes: 17 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@
</p>

<h2 align="center">
<a aria-label="2023 Roadmaps - I'm back!" href="https://github.com/saltyshiomix/nextron/issues/398">
2023 Roadmaps - I'm back!
<a aria-label="2024 Roadmaps - I'm back!" href="https://github.com/saltyshiomix/nextron/issues/442">
2024 Roadmaps - I'm back!
</a>
</h2>

Expand Down Expand Up @@ -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)

<p align="center"><img src="https://i.imgur.com/RzAykrU.png"></p>

```
# 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)

<p align="center"><img src="https://i.imgur.com/NZfsD1p.png"></p>
Expand Down
38 changes: 38 additions & 0 deletions examples/basic-lang-javascript-python/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<p align="center"><img src="https://i.imgur.com/RzAykrU.png"></p>

## 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`)
```
14 changes: 14 additions & 0 deletions examples/basic-lang-javascript-python/electron-builder.yml
Original file line number Diff line number Diff line change
@@ -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
75 changes: 75 additions & 0 deletions examples/basic-lang-javascript-python/main/background.js
Original file line number Diff line number Diff line change
@@ -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/<youApp>.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()
})
25 changes: 25 additions & 0 deletions examples/basic-lang-javascript-python/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"private": true,
"name": "my-nextron-app",
"description": "My application description",
"version": "1.0.0",
"author": "Yoshihide Shiono <[email protected]>",
"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"
}
}
10 changes: 10 additions & 0 deletions examples/basic-lang-javascript-python/renderer/next.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/** @type {import('next').NextConfig} */
module.exports = {
trailingSlash: true,
images: {
unoptimized: true,
},
webpack: (config) => {
return config
},
}
63 changes: 63 additions & 0 deletions examples/basic-lang-javascript-python/renderer/pages/home.jsx
Original file line number Diff line number Diff line change
@@ -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 (
<React.Fragment>
<Head>
<title>Home - Nextron (basic-lang-javascript-python)</title>
</Head>
<div>
<p>
⚡ Electron + Next.js ⚡ -
<Link href="/next">
<a>Go to next page</a>
</Link>
</p>
<Image
src="/images/logo.png"
alt="Logo image"
width="256px"
height="256px"
/>
</div>
<div>
<p>
Calculate the sqaure of your number:
<input type="number" value={value} onChange={handleChange} />
</p>
<button
onClick={() => {
window.ipc.send('run-sh', value)
}}
>
Test running the Python script via IPC
</button>
<p>{log}</p>
<p>
the square of {value} is {'-> '} {message}
</p>
</div>
</React.Fragment>
)
}
21 changes: 21 additions & 0 deletions examples/basic-lang-javascript-python/renderer/pages/next.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import React from 'react'
import Head from 'next/head'
import Link from 'next/link'

export default function NextPage() {
return (
<React.Fragment>
<Head>
<title>Next - Nextron (basic-lang-javascript-python)</title>
</Head>
<div>
<p>
⚡ Electron + Next.js ⚡ -
<Link href="/home">
<a>Go to home page</a>
</Link>
</p>
</div>
</React.Fragment>
)
}
8 changes: 8 additions & 0 deletions examples/basic-lang-javascript-python/scripts/main.py
Original file line number Diff line number Diff line change
@@ -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()
6 changes: 6 additions & 0 deletions examples/basic-lang-javascript-python/scripts/runner.sh
Original file line number Diff line number Diff line change
@@ -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)
Loading