Skip to content

Commit 8226292

Browse files
committed
Built Electron helper UI and implemented WebSocket context for listening to and emitting events in React app
1 parent f70fb8b commit 8226292

File tree

13 files changed

+1837
-65
lines changed

13 files changed

+1837
-65
lines changed

desktop-helper-sample/helper/package.json

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
"main": "public/electron.js",
77
"homepage": "./",
88
"scripts": {
9-
"start": "concurrently -k \"npm run start:react\" \"npm run start:electron\"",
9+
"start": "concurrently -k \"npm:start:react\" \"npm:start:electron\"",
1010
"start:react": "cross-env BROWSER=none react-scripts start",
1111
"start:electron": "wait-on tcp:3000 && electron public/electron.js",
1212
"build": "npm run build:react && npm run build:electron",
@@ -15,19 +15,22 @@
1515
"eject": "react-scripts eject"
1616
},
1717
"devDependencies": {
18+
"@adobe/react-spectrum": "^3.11.2",
1819
"concurrently": "^6.2.0",
1920
"cross-env": "^7.0.3",
2021
"electron": "^13.1.6",
2122
"electron-builder": "^22.11.7",
2223
"wait-on": "^6.0.0"
2324
},
2425
"dependencies": {
26+
"cors": "^2.8.5",
2527
"electron-is-dev": "^2.0.0",
2628
"express": "^4.17.1",
2729
"react": "^17.0.2",
2830
"react-dom": "^17.0.2",
2931
"react-scripts": "4.0.3",
30-
"socket.io": "^4.1.2"
32+
"socket.io": "^4.1.2",
33+
"socket.io-client": "^4.1.3"
3134
},
3235
"build": {
3336
"appId": "com.electron.adobe.example.desktop-helper-sample",

desktop-helper-sample/helper/public/electron.js

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,15 @@ const createWindow = () => {
1414
});
1515

1616
// Configure electron development environment
17-
window.loadURL(isDevelopment
18-
? 'http://localhost:3000'
19-
: `file://${path.join(__dirname, '../build/index.html')}`);
20-
17+
window.loadURL(
18+
isDevelopment
19+
? 'http://localhost:3000'
20+
: `file://${path.join(__dirname, '../build/index.html')}`
21+
);
22+
2123
if (isDevelopment) {
22-
window.webContents.openDevTools({
23-
mode: 'detach'
24+
window.webContents.openDevTools({
25+
mode: 'detach',
2426
});
2527
}
2628
};
@@ -37,4 +39,4 @@ app.on('activate', () => {
3739
if (BrowserWindow.getAllWindows().length === 0) {
3840
createWindow();
3941
}
40-
});
42+
});
Lines changed: 26 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,58 @@
11
const http = require('http');
22
const express = require('express');
3+
const cors = require('cors');
34
const { Server } = require('socket.io');
45

56
const startServer = async () => {
67
const port = 4040;
8+
79
const app = express();
10+
app.use(cors());
11+
812
const server = http.createServer(app);
913

10-
const io = new Server(server);
14+
const io = new Server(server, {
15+
cors: {
16+
origin: 'http://localhost:3000',
17+
methods: ['GET'],
18+
},
19+
});
1120

1221
server.listen(port, () => {
1322
console.log(`[server] Server listening on port ${port}`);
1423
});
15-
24+
1625
io.on('connection', (socket) => {
17-
console.log('[socket.io] UXP plugin connected');
26+
io.emit('server-connection', true);
1827

19-
io.emit('uxp-connected', true);
28+
socket.on('uxp-connected', (socket) => {
29+
io.emit('uxp-connected', true);
30+
});
2031

2132
socket.on('message', (message) => {
22-
console.log(`Message received from client: ${message}`);
33+
io.emit('redirect-message', message);
34+
});
35+
36+
socket.on('helper-message', (message) => {
37+
io.emit('message', message);
2338
});
2439

2540
socket.on('disconnect', () => {
26-
console.log('[socket.io] UXP plugin disconnected');
41+
io.emit('uxp-connected', false);
2742
});
2843
});
2944

3045
// Emit connect when uxp attempts to reconnect
3146
io.on('reconnect', (socket) => {
32-
io.emit('uxp-connected', true);
47+
io.emit('server-connection', true);
3348
});
3449

35-
// Emit disconnect when helper app closes
50+
// Emit disconnect when helper app closes
3651
process.on('exit', () => {
37-
io.emit('uxp-connected', false);
52+
io.emit('server-connection', false);
3853
});
3954
};
4055

4156
startServer().catch((err) => {
42-
console.log(`[server] Error: ${err}`)
43-
});
57+
console.log(`[server] Error: ${err}`);
58+
});

desktop-helper-sample/helper/src/App.css

Lines changed: 0 additions & 14 deletions
This file was deleted.
Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,20 @@
1-
import './App.css';
1+
import { Flex, Heading } from '@adobe/react-spectrum';
2+
3+
import OptionsMenu from './components/OptionsMenu';
24

35
const App = () => {
46
return (
5-
<div className="container">
6-
<header className="header">
7-
<p>Welcome to the UXP Helper App</p>
8-
</header>
9-
</div>
7+
<Flex
8+
direction="column"
9+
gap="size-100"
10+
alignItems="center"
11+
justifyContent="center"
12+
height="100vh"
13+
>
14+
<Heading level={2}>Welcome to the UXP Helper App</Heading>
15+
<OptionsMenu />
16+
</Flex>
1017
);
11-
}
18+
};
1219

1320
export default App;
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
import React, { useState, useEffect, useContext } from 'react';
2+
import {
3+
Button,
4+
Flex,
5+
Item,
6+
Tabs,
7+
TabList,
8+
TabPanels,
9+
TextField,
10+
View,
11+
} from '@adobe/react-spectrum';
12+
13+
import { SocketContext } from './SocketContext';
14+
15+
const OptionsMenu = () => {
16+
const socket = useContext(SocketContext);
17+
18+
const [connectionStatus, setConnectionStatus] = useState(false);
19+
const [uxpMessage, setUXPMessage] = useState('');
20+
const [helperMessage, setHelperMessage] = useState('');
21+
22+
useEffect(() => {
23+
socket.on('uxp-connected', (isUXPConnected) => {
24+
setConnectionStatus(isUXPConnected);
25+
});
26+
27+
socket.on('redirect-message', (receivedMessage) => {
28+
setUXPMessage(receivedMessage);
29+
});
30+
}, []);
31+
32+
const sendHelperMessage = () => {
33+
socket.emit('helper-message', helperMessage);
34+
};
35+
36+
return (
37+
<Flex width="size-6000" height="size-8000">
38+
<Tabs aria-label="UXP Helper Options">
39+
<TabList>
40+
<Item key="status">UXP Status</Item>
41+
<Item key="message">Send Message</Item>
42+
<Item key="data">Data from UXP</Item>
43+
</TabList>
44+
<TabPanels marginX={4} marginY={16}>
45+
<Item key="status">
46+
{connectionStatus === false ? 'Disconnected' : 'Connected'}
47+
</Item>
48+
<Item key="message">
49+
<Flex alignItems="center">
50+
<TextField
51+
aria-label="Send Message"
52+
placeholder="Send a message to UXP"
53+
onChange={(s) => setHelperMessage(s)}
54+
></TextField>
55+
<Button
56+
variant="cta"
57+
marginX={16}
58+
onPress={() => sendHelperMessage()}
59+
>
60+
Send
61+
</Button>
62+
</Flex>
63+
</Item>
64+
<Item key="data">
65+
<View
66+
borderWidth="thin"
67+
borderColor="dark"
68+
borderRadius="medium"
69+
backgroundColor="dark"
70+
padding="size-100"
71+
>
72+
{uxpMessage === '' ? 'Data From UXP' : uxpMessage}
73+
</View>
74+
</Item>
75+
</TabPanels>
76+
</Tabs>
77+
</Flex>
78+
);
79+
};
80+
81+
export default OptionsMenu;
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import React, { createContext } from 'react';
2+
import io from 'socket.io-client';
3+
4+
export const socket = io('http://localhost:4040');
5+
6+
export const SocketContext = createContext();
Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,21 @@
11
import React from 'react';
22
import ReactDOM from 'react-dom';
3+
import {
4+
Provider as SpectrumProvider,
5+
defaultTheme,
6+
} from '@adobe/react-spectrum';
7+
38
import './index.css';
49
import App from './App';
10+
import { SocketContext, socket } from './components/SocketContext';
511

612
ReactDOM.render(
713
<React.StrictMode>
8-
<App />
14+
<SocketContext.Provider value={socket}>
15+
<SpectrumProvider theme={defaultTheme}>
16+
<App />
17+
</SpectrumProvider>
18+
</SocketContext.Provider>
919
</React.StrictMode>,
1020
document.getElementById('root')
11-
);
21+
);

0 commit comments

Comments
 (0)