-
Notifications
You must be signed in to change notification settings - Fork 9
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
2 changed files
with
256 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,155 @@ | ||
<!doctype html> | ||
<html> | ||
<head> | ||
<meta charset="UTF-8" /> | ||
<title>WebUI - Web App Multi-Client Example</title> | ||
<style> | ||
body { | ||
font-family: 'Arial', sans-serif; | ||
color: white; | ||
background: linear-gradient(to right, #507d91, #1c596f, #022737); | ||
text-align: center; | ||
font-size: 18px; | ||
} | ||
button, | ||
input { | ||
padding: 10px; | ||
border-radius: 3px; | ||
border: 1px solid #ccc; | ||
box-shadow: 0 3px 5px rgba(0, 0, 0, 0.1); | ||
transition: 0.2s; | ||
} | ||
button { | ||
background: #3498db; | ||
color: #fff; | ||
cursor: pointer; | ||
font-size: 16px; | ||
} | ||
h1 { | ||
text-shadow: -7px 10px 7px rgb(67 57 57 / 76%); | ||
} | ||
button:hover { | ||
background: #c9913d; | ||
} | ||
input:focus { | ||
outline: none; | ||
border-color: #3498db; | ||
} | ||
|
||
a:link { | ||
color: #fd5723; | ||
} | ||
a:active { | ||
color: #fd5723; | ||
} | ||
a:visited { | ||
color: #fd5723; | ||
} | ||
a:hover { | ||
color: #f0bcac; | ||
} | ||
span { | ||
color:#d69d48; | ||
font-size: larger; | ||
} | ||
</style> | ||
</head> | ||
<body> | ||
<h3>Web App Multi-Client Example</h3> | ||
<br /> | ||
<span id="status">Connecting...</span> | ||
<br /> | ||
<br /> | ||
You are user number <span id="userNumber">0</span> | ||
<br /> | ||
<br /> | ||
Your connection numer is <span id="connectionNumber">0</span> | ||
<br /> | ||
<br /> | ||
There are <span id="userCount">0</span> users connected, and <span id="tabCount">0</span> tabs opened. | ||
<br /> | ||
<br /> | ||
Current user input: <input id="privateInput"></input> <button OnClick="save(document.getElementById('privateInput').value)">Save</button> <a href="">Reload This Page</a> | ||
<br /> | ||
<br /> | ||
All users input: <input id="publicInput"></input> <button OnClick="saveAll(document.getElementById('publicInput').value);">Update All Users</button> | ||
<br /> | ||
<br /> | ||
<a href="" target="_blank">Open New Tab</a> | ||
<br /> | ||
<br /> | ||
<button OnClick="exit_app();">Exit</button> | ||
<br /> | ||
<br /> | ||
<br /> | ||
Note: <br /><em>Copy URL, and open it in a private window, or another web browser to create new users.</em> | ||
</body> | ||
|
||
<!-- Connect this window to the background app --> | ||
<script src="/webui.js"></script> | ||
|
||
<script> | ||
// JavaScript Example | ||
/* | ||
document.addEventListener('DOMContentLoaded', function() { | ||
// DOM is loaded. Check if `webui` object is available | ||
if (typeof webui !== 'undefined') { | ||
// Set events callback | ||
webui.setEventCallback((e) => { | ||
if (e == webui.event.CONNECTED) { | ||
// Connection to the backend is established | ||
console.log('Connected.'); | ||
webuiTest(); | ||
} else if (e == webui.event.DISCONNECTED) { | ||
// Connection to the backend is lost | ||
console.log('Disconnected.'); | ||
} | ||
}); | ||
} else { | ||
// The virtual file `webui.js` is not included | ||
alert('Please add webui.js to your HTML.'); | ||
} | ||
}); | ||
function webuiTest() { | ||
// Call a backend function | ||
if (webui.isConnected()) { | ||
// When you bind a func in the backend | ||
// webui will create the `func` object | ||
// in three places: | ||
// | ||
// Global : func(...) | ||
// Property : webui.func(...) | ||
// Method : webui.call('func', ...) | ||
// | ||
// [!] Note: Objects creation fails when | ||
// a similar object already exist. | ||
const foo = 'Hello'; | ||
const bar = 123456; | ||
// Calling as global object | ||
myBackendFunction(foo, bar).then((response) => { | ||
// Do something with `response` | ||
}); | ||
// Calling as property of `webui.` object | ||
webui.myBackendFunction(foo, bar).then((response) => { | ||
// Do something with `response` | ||
}); | ||
// Calling using the method `webui.call()` | ||
webui.call('myBackendFunction', foo, bar).then((response) => { | ||
// Do something with `response` | ||
}); | ||
// Using await | ||
// const response = await myBackendFunction(foo, bar); | ||
// const response = await webui.myBackendFunction(foo, bar); | ||
// const response = await webui.call('myBackendFunction', foo, bar); | ||
} | ||
} | ||
*/ | ||
</script> | ||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
import std/strformat | ||
|
||
import webui | ||
|
||
# Arrays to hold permanent data | ||
var | ||
privateInput: array[256, string] # One for each user | ||
publicInput: string # One for all users | ||
usersCount: int | ||
tabCount: int | ||
|
||
proc save(e: Event) = | ||
# Get input value and save it in the array | ||
privateInput[e.clientId] = e.getString() | ||
|
||
proc saveAll(e: Event) = | ||
# Get input value and save it in the array | ||
publicInput = e.getString() | ||
|
||
# Update all users | ||
e.window.run(fmt"document.getElementById('publicInput').value = '{publicInput}';") | ||
|
||
proc events(e: Event) = | ||
# This function gets called every time there is an event | ||
|
||
# Get full web browser cookies | ||
# this is a port of the C example, which declares, | ||
# but doesnt use the `cookies` variable | ||
let cookies {.used.} = e.cookies | ||
|
||
# Static client (Based on web browser cookies) | ||
let clientId = e.clientId | ||
|
||
# Dynamic client connection ID (Changes on connect/disconnect events) | ||
let connectionId = e.connectionId | ||
|
||
case e.eventType | ||
of weConnected: # New connection | ||
if users_count < (client_id + 1): # +1 because it starts from 0 | ||
users_count = client_id + 1 | ||
|
||
inc tabCount | ||
of weDisconnected: # Disconnection | ||
if tab_count > 0: | ||
dec tab_count | ||
else: | ||
discard | ||
|
||
# --- Update this current user only | ||
|
||
# status | ||
e.runClient("document.getElementById('status').innerText = 'Connected!';") | ||
|
||
# userNumber | ||
e.runClient(fmt"document.getElementById('userNumber').innerText = '{clientId}';") | ||
|
||
# connectionId | ||
e.runClient(fmt"document.getElementById('connectionNumber').innerText = '{connectionId}';") | ||
|
||
# privateInput | ||
e.runClient(fmt"document.getElementById('privateInput').value = '{privateInput[clientId]}';") | ||
|
||
# publicInput | ||
e.runClient(fmt"document.getElementById('publicInput').value = '{publicInput}';") | ||
|
||
# --- Update all connected users | ||
|
||
# userCount | ||
e.runClient(fmt"document.getElementById('userCount').innerText = '{usersCount}';") | ||
|
||
# tabCount | ||
e.runClient(fmt"document.getElementById('tabCount').innerText = '{tabCount}';") | ||
|
||
proc main() = | ||
# Allow multi-user connection and cookies | ||
setConfig({wcMultiClient, wcUseCookies}, true) | ||
|
||
# Create new window | ||
let window = newWindow() | ||
|
||
# Bind HTML with Nim functions | ||
window.bind("save", save) | ||
window.bind("saveAll", saveAll) | ||
window.bind("exit_app", exit) | ||
|
||
# Bind all events | ||
window.bind("", events) | ||
|
||
# Start server only | ||
let url = window.startServer("index.html") | ||
|
||
# Open a new page in the default native web browser | ||
openUrl(url) | ||
|
||
# Wait until all windows get closed | ||
wait() | ||
|
||
# Free all memory resources (Optional) | ||
clean() | ||
|
||
main() |