Skip to content

Commit

Permalink
Added asset handler and jsc calls.
Browse files Browse the repository at this point in the history
- implemented sudoku example
- reworked settings (WIP)
- added js promise call
  • Loading branch information
malivvan committed Dec 26, 2023
1 parent 0e7ee07 commit 60c5848
Show file tree
Hide file tree
Showing 11 changed files with 853 additions and 315 deletions.
11 changes: 5 additions & 6 deletions api.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,9 @@ class WebkitAPI {
});
}
}
let api = new WebkitAPI();
window.webkitAPI = new WebkitAPI();
{{range $api, $calls := .Calls}}window.{{$api}} = {};
{{range $calls}}window.{{$api}}.{{.}} = (obj) => api.request("{{$api}}", "{{.}}", obj);{{end}}{{end}}
window.webkit.api = api;
{{range $calls}}window.{{$api}}.{{.}} = (obj) => window.webkitAPI.request("{{$api}}", "{{.}}", obj);{{end}}{{end}}
})(document.cloneNode(),globalThis.window);`))

func apiHandler(bindings map[string]apiBinding, eval func(string), log func(interface{}, ...interface{})) func(string) {
Expand Down Expand Up @@ -88,17 +87,17 @@ func apiHandler(bindings map[string]apiBinding, eval func(string), log func(inte
log("api request", "id", id, "api", api, "fn", fn)
binding, ok := bindings[api]
if !ok {
eval("webkit.api.reject(" + string(id) + ",'api not found')")
eval("webkitAPI.reject(" + string(id) + ",'api not found')")
return
}
reply, err := binding.call(fn, req[cur:])
if err != nil {
log("api reject", "id", id, "error", err)
eval("webkit.api.reject(" + string(id) + ",'" + err.Error() + "')")
eval("webkitAPI.reject(" + string(id) + ",'" + err.Error() + "')")
return
}
log("api resolve", "id", id, "reply", reply)
eval("webkit.api.resolve(" + id + ",'" + reply + "')")
eval("webkitAPI.resolve(" + id + ",'" + reply + "')")
}
}

Expand Down
65 changes: 12 additions & 53 deletions app.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ type App struct {
windowsLock sync.RWMutex

runOnce runOnce

//web context
context ptr
}

func New(options AppOptions) *App {
Expand All @@ -41,11 +44,6 @@ func New(options AppOptions) *App {
} else {
options.Name = strings.ToLower(options.Name)
}
if options.PanicHandler == nil {
options.PanicHandler = func(v any) {
panic(v)
}
}

// Create app
app := &App{
Expand All @@ -57,20 +55,17 @@ func New(options AppOptions) *App {

// Setup debug logger
if options.Debug {
logger := &logger{
app.logger = &logger{
prefix: "webkit2gtk: " + options.Name,
writer: os.Stdout,
}
if options.LogWriter != nil {
logger.writer = options.LogWriter
writer: LogWriter,
}
app.logger = logger
}

/////////////////////////////////////
globalApplication = app // !important

return app
}

func (a *App) CurrentWindow() *Window {
if a.pointer == 0 {
return nil
Expand Down Expand Up @@ -103,56 +98,20 @@ func (a *App) Run() error {
if err := os.Setenv("JSC_SIGNAL_FOR_GC", "20"); err != nil {
return err
}
//
//// 2. Connect foreground signal (USR2)
//// TODO: Is this working?
//foreground := make(chan os.Signal, 1)
//signal.Notify(foreground, syscall.SIGUSR2)
//go func() {
// for {
// <-foreground
// for _, window := range a.windows {
// windowPresent(window.pointer)
//
// }
// a.info("application foregrounded", "main_thread", mainThreadId)
// }
//}()

// 3. Load shared libraries

// 2. Load shared libraries
if err := a.loadSharedLibs(); err != nil {
return err
}

// 4. Get Main Thread and create GTK Application
// 3. Get Main Thread and create GTK Application
mainThreadId = lib.g.ThreadSelf()
a.pointer = lib.gtk.ApplicationNew(a.ident, uint(0))

//dbusCli, err := newDBUSClient(a.ident)
//if err != nil {
// return err
//}
//running, pid := dbusCli.IsAppRunning()
//if running {
// // send signal
// proc, err := os.FindProcess(int(pid))
// if err != nil {
// return err
// }
// err = proc.Signal(syscall.SIGUSR2)
// if err != nil {
// return err
// }
// a.info("application already running", "pid", pid)
// return fmt.Errorf("application already running")
//}

//lib.g.ApplicationRegister(a.pointer, 0, 0)

// 3. Run deferred functions
// 4. Run deferred functions
a.runOnce.invoke(true)

// 4. Setup activate signal ipc
// 5. Setup activate signal ipc
app := ptr(a.pointer)
activate := func() {
a.log("application startup complete", "since_startup", time.Since(startupTime))
Expand Down
135 changes: 135 additions & 0 deletions examples/sudoku/assets/main.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
class Sudoku {
constructor(elem) {
this.elem = elem;
this.board = this.createBoard();
this.controls = this.createControls();
this.elem.appendChild(this.board)
this.elem.appendChild(this.controls)
}

createControls() {
let controls = document.createElement("div");
controls.classList.add("controls");
let genButton = this.createButton("Generate", this.fillBoard.bind(this));
let genAmount = this.createInput("number", 20, 0, 81);
controls.append(genButton, genAmount);
return controls;
}

createButton(text, onClick) {
let button = document.createElement("button");
button.innerText = text;
button.onclick = onClick;
return button;
}

createInput(type, value, min, max) {
let input = document.createElement("input");
input.type = type;
input.value = value;
input.min = min;
input.max = max;
return input;
}

createBoard() {
let board = document.createElement('div');
board.className = 'board';
for (let i = 0; i < 9; i++) {
let row = document.createElement('div');
row.className = 'row';
for (let j = 0; j < 9; j++) {
let cell = this.createCell(i, j);
row.appendChild(cell);
}
board.appendChild(row);
}
return board;
}

createCell(i, j) {
let cell = document.createElement('div');
cell.className = 'cell';
cell.id = `cell${i}${j}`;
cell.innerHTML = ' ';
cell.onclick = this.cellOnClick.bind(cell);
cell.oncontextmenu = this.cellOnRightClick.bind(cell);
return cell;
}

cellOnClick() {
this.innerHTML = this.innerHTML === ' ' ? 1 : (parseInt(this.innerHTML) % 9) + 1;
}

cellOnRightClick(e) {
e.preventDefault();
this.innerHTML = this.innerHTML === ' ' ? 9 : (parseInt(this.innerHTML) - 1) || ' ';
}

getValues(selector) {
let values = [];
for (let i = 0; i < 9; i++) {
values.push(parseInt(this.board.querySelector(selector(i)).innerHTML));
}
return values;
}

getRowValues = (row) => this.getValues(i => `#cell${row}${i}`);
getColValues = (col) => this.getValues(i => `#cell${i}${col}`);

getValidValues(row, col) {
let rowValues = this.getRowValues(row);
let colValues = this.getColValues(col);
let squareValues = [1, 2, 3, 4, 5, 6, 7, 8, 9];
return squareValues.filter(i => !rowValues.includes(i) && !colValues.includes(i));
}

getEmptyCells() {
let emptyCells = [];
for (let i = 0; i < 9; i++) {
for (let j = 0; j < 9; j++) {
if (this.board.querySelector(`#cell${i}${j}`).innerHTML === ' ') {
emptyCells.push([i, j]);
}
}
}
return emptyCells;
}

fillCell(row, col) {
let cell = this.board.querySelector(`#cell${row}${col}`);

let possibleValues = this.getValidValues(row, col);
if (possibleValues.length === 0) {
return false;
}
possibleValues.sort(() => Math.random() - 0.5);
cell.classList.add("cell-generated");
cell.innerHTML = possibleValues.pop();
return true;
}

clearBoard() {
for (let i = 0; i < 9; i++) {
for (let j = 0; j < 9; j++) {
let cell = this.board.querySelector(`#cell${i}${j}`);
cell.classList.remove("cell-generated");
cell.innerHTML = ' ';
}
}
}

fillBoard() {
this.clearBoard();
let emptyCells = this.getEmptyCells();
emptyCells.sort(() => Math.random() - 0.5);
let amount = parseInt(this.controls.querySelector("input").value);
let n = 0;
while (n < amount) {
let [row, col] = emptyCells.pop();
if (this.fillCell(row, col)) n++;
}
}
}

let game = new Sudoku(document.body);
32 changes: 32 additions & 0 deletions examples/sudoku/sudoku.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package main

import (
"embed"
_ "embed"
ui "github.com/malivvan/webkitgtk"
"io/fs"
"net/http"
)

//go:embed assets
var assets embed.FS

func main() {
assets, _ := fs.Sub(assets, "assets")
app := ui.New(ui.AppOptions{
Name: "sudoku",
Debug: true,
Handle: map[string]http.Handler{
"main": http.FileServer(http.FS(assets)),
},
})
app.Open(ui.WindowOptions{
Title: "Sudoku",
Width: 600,
Height: 460,
URL: "app://main/",
})
if err := app.Run(); err != nil {
panic(err)
}
}
Loading

0 comments on commit 60c5848

Please sign in to comment.