diff --git a/.vscode/settings.json b/.vscode/settings.json
index 55c5045..d0b268c 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -1,5 +1,4 @@
{
- "java.project.sourcePaths": [
- "apps/main/src"
- ]
-}
\ No newline at end of file
+ "java.project.sourcePaths": ["apps/main/src"],
+ "java.configuration.updateBuildConfiguration": "automatic"
+}
diff --git a/Makefile b/Makefile
index ebb6af1..3eb24dd 100644
--- a/Makefile
+++ b/Makefile
@@ -1,3 +1,5 @@
+export PATH := $(PATH):$(PWD)/tools/gomobile/bin:$(PWD)/tools/gobind/bin
+
LINT_ARGS ?= --timeout 5m
GORELEASER_VERSION ?= v1.25.1
GORELEASER_ARGS ?= release --snapshot --clean
@@ -50,9 +52,13 @@ build-client: deps ## Build executable
-o ./bin/client \
./cmd/client
-build-android: .mktools tools/gogio/bin/gogio deps ## Build executable
+.PHONY: android/app/libs/arcast.aar
+android/app/libs/arcast.aar: tools/gomobile/bin/gomobile tools/gobind/bin/gobind
+ mkdir -p android/app/libs
+ gomobile bind -v -javapkg com.cadoles.arcast -target android -o android/app/libs/arcast.aar ./pkg/android
+
+build-android: .mktools android/app/libs/arcast.aar deps ## Build executable
mkdir -p dist
- CGO_ENABLED=1 GOOS=android CGO_CFLAGS="-I${JDK_PATH}/include -I${JDK_PATH}/include/linux -w" tools/gogio/bin/gogio -target android -buildmode archive -o android/app/libs/mobile.aar -x ./cmd/mobile
( cd android && VERSION_CODE=$(VERSION_CODE) VERSION_NAME=$(MKT_PROJECT_VERSION)-debug ./gradlew assembleDebug )
$(ANDROID_KEYSTORE_FILE):
@@ -64,9 +70,8 @@ $(ANDROID_KEYSTORE_FILE):
-validity $(ANDROID_KEYSTORE_KEY_VALIDITY) \
-storepass "$(ANDROID_KEYSTORE_PASS)"
-release-android: $(ANDROID_KEYSTORE_FILE) tools/gogio/bin/gogio deps ## Build executable
+release-android: deps .mktools android/app/libs/arcast.aar $(ANDROID_KEYSTORE_FILE) ## Build executable
mkdir -p dist
- CGO_ENABLED=1 GOOS=android CGO_CFLAGS="-I${JDK_PATH}/include -I${JDK_PATH}/include/linux -w" tools/gogio/bin/gogio -target android -buildmode archive -o android/app/libs/mobile.aar -x ./cmd/mobile
( cd android && VERSION_CODE=$(VERSION_CODE) VERSION_NAME=$(MKT_PROJECT_VERSION) ./gradlew assemble )
rm -f android/app/build/outputs/apk/release/app-release-unsigned-aligned.apk
"$(ANDROID_HOME)/build-tools/$(ANDROID_BUILD_TOOLS_VERSION)/zipalign" -p 4 android/app/build/outputs/apk/release/app-release-unsigned.apk android/app/build/outputs/apk/release/app-release-unsigned-aligned.apk
@@ -103,10 +108,6 @@ tools/modd/bin/modd:
mkdir -p tools/modd/bin
GOBIN=$(PWD)/tools/modd/bin go install github.com/cortesi/modd/cmd/modd@latest
-tools/gogio/bin/gogio:
- mkdir -p tools/gogio/bin
- GOBIN=$(PWD)/tools/gogio/bin go install gioui.org/cmd/gogio@latest
-
release: gitea-release
gitea-release: .mktools build-apps goreleaser release-android
@@ -134,6 +135,14 @@ gitea-release: .mktools build-apps goreleaser release-android
goreleaser: .env .mktools
( set -o allexport && source .env && set +o allexport && curl -sfL https://goreleaser.com/static/run | VERSION=$(GORELEASER_VERSION) GORELEASER_CURRENT_TAG="$(MKT_PROJECT_VERSION)" GOPATH=$(shell go env GOPATH) bash /dev/stdin $(GORELEASER_ARGS) )
+tools/gomobile/bin/gomobile:
+ mkdir -p tools/gomobile/bin
+ GOBIN=$(PWD)/tools/gomobile/bin go install golang.org/x/mobile/cmd/gomobile@latest
+
+tools/gobind/bin/gobind:
+ mkdir -p tools/gobind/bin
+ GOBIN=$(PWD)/tools/gobind/bin go install golang.org/x/mobile/cmd/gobind@latest
+
.PHONY: mktools
mktools:
rm -rf .mktools
diff --git a/android/app/build.gradle b/android/app/build.gradle
index ba80947..9bf7879 100644
--- a/android/app/build.gradle
+++ b/android/app/build.gradle
@@ -63,7 +63,7 @@ dependencies {
implementation 'androidx.compose.ui:ui-graphics'
implementation 'androidx.compose.ui:ui-tooling-preview'
implementation 'androidx.compose.material3:material3'
- implementation files('libs/sys_android.jar')
+ implementation("androidx.webkit:webkit:1.10.0")
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
diff --git a/android/app/libs/.gitignore b/android/app/libs/.gitignore
index 19f0d59..0ddd624 100644
--- a/android/app/libs/.gitignore
+++ b/android/app/libs/.gitignore
@@ -1 +1,2 @@
-/mobile.aar
\ No newline at end of file
+/mobile.aar
+/arcast*
\ No newline at end of file
diff --git a/android/app/libs/safedata_android.jar b/android/app/libs/safedata_android.jar
deleted file mode 100644
index 8f6ee1f..0000000
Binary files a/android/app/libs/safedata_android.jar and /dev/null differ
diff --git a/android/app/libs/sys_android.jar b/android/app/libs/sys_android.jar
deleted file mode 100644
index b587458..0000000
Binary files a/android/app/libs/sys_android.jar and /dev/null differ
diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml
index 3d41627..ce5940f 100644
--- a/android/app/src/main/AndroidManifest.xml
+++ b/android/app/src/main/AndroidManifest.xml
@@ -8,8 +8,6 @@
-
-
-
-
\ No newline at end of file
diff --git a/android/app/src/main/java/com/example/arcast_player/ArcastBridge.kt b/android/app/src/main/java/com/example/arcast_player/ArcastBridge.kt
new file mode 100644
index 0000000..2781585
--- /dev/null
+++ b/android/app/src/main/java/com/example/arcast_player/ArcastBridge.kt
@@ -0,0 +1,31 @@
+package com.example.arcast_player
+
+import android.webkit.WebView
+import com.cadoles.arcast.android.Bridge
+
+class ArcastBridge(private val webview: WebView) : Bridge {
+ private var title: String = ""
+ private var url: String = ""
+
+ override fun getTitle(): String {
+ return title
+ }
+
+ override fun getURL(): String {
+ return url
+ }
+
+ override fun loadURL(url: String) {
+ webview.post(Runnable {
+ webview.loadUrl(url)
+ })
+ }
+
+ fun setURL(url: String) {
+ this.url = url
+ }
+
+ fun setTitle(title: String) {
+ this.title = title
+ }
+}
\ No newline at end of file
diff --git a/android/app/src/main/java/com/example/arcast_player/ArcastWebviewClient.kt b/android/app/src/main/java/com/example/arcast_player/ArcastWebviewClient.kt
new file mode 100644
index 0000000..7836ffd
--- /dev/null
+++ b/android/app/src/main/java/com/example/arcast_player/ArcastWebviewClient.kt
@@ -0,0 +1,18 @@
+package com.example.arcast_player
+
+import android.webkit.WebResourceRequest
+import android.webkit.WebView
+import android.webkit.WebViewClient
+
+class ArcastWebviewClient(private var bridge: ArcastBridge): WebViewClient() {
+
+ override fun shouldOverrideUrlLoading(view: WebView?, request: WebResourceRequest?): Boolean {
+ return false
+ }
+
+ override fun onPageFinished(view: WebView?, url: String?) {
+ super.onPageFinished(view, url)
+ bridge.title = view?.title.toString()
+ bridge.url = url.toString()
+ }
+}
\ No newline at end of file
diff --git a/android/app/src/main/java/com/example/arcast_player/MainActivity.kt b/android/app/src/main/java/com/example/arcast_player/MainActivity.kt
index 9f71bb4..97a7e44 100644
--- a/android/app/src/main/java/com/example/arcast_player/MainActivity.kt
+++ b/android/app/src/main/java/com/example/arcast_player/MainActivity.kt
@@ -12,29 +12,26 @@ import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import com.cadoles.arcast_player.ui.theme.ArcastplayerTheme
-import org.gioui.GioActivity
import android.view.WindowManager
+import android.webkit.WebView
+import com.cadoles.arcast.android.Android as Arcast
+import com.example.arcast_player.ArcastBridge
+import com.example.arcast_player.ArcastWebviewClient
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
- startActivity(Intent(this, GioActivity::class.java))
- window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
- }
-}
+ val wv = WebView(applicationContext)
+ val bridge: ArcastBridge = ArcastBridge(wv)
-@Composable
-fun Greeting(name: String, modifier: Modifier = Modifier) {
- Text(
- text = "Hello $name!",
- modifier = modifier
- )
-}
+ wv.webViewClient = ArcastWebviewClient(bridge)
+ Arcast.setBridge(bridge)
-@Preview(showBackground = true)
-@Composable
-fun GreetingPreview() {
- ArcastplayerTheme {
- Greeting("Android")
+ val port = Arcast.startServer(filesDir.absolutePath)
+
+ wv.settings.javaScriptEnabled = true
+ wv.loadUrl("http://127.0.0.1:${port}")
+
+ setContentView(wv)
}
}
\ No newline at end of file
diff --git a/apps/main/src/pages/ScreenSharingPage/ScreenViewer.module.css b/apps/main/src/pages/ScreenSharingPage/ScreenViewer.module.css
index df82d14..a908293 100644
--- a/apps/main/src/pages/ScreenSharingPage/ScreenViewer.module.css
+++ b/apps/main/src/pages/ScreenSharingPage/ScreenViewer.module.css
@@ -1,21 +1,22 @@
.root {
- position: absolute;
- top: 0;
- left: 0;
- bottom: 0;
- right: 0;
- display: flex;
- justify-content: center;
- align-items: center;
+ position: absolute;
+ top: 0;
+ left: 0;
+ bottom: 0;
+ right: 0;
+ display: flex;
+ justify-content: center;
+ align-items: center;
}
.video {
- object-fit: cover;
- width: 100%;
- height: auto;
- position: absolute;
- top: 0;
- left: 0;
- bottom: 0;
- right: 0;
-}
\ No newline at end of file
+ height: auto;
+ left: 0;
+ object-fit: contain;
+ /* position: absolute; */
+ right: 0;
+ top: 0;
+ width: 100%;
+ flex-grow: 1;
+ width: 100%;
+}
diff --git a/cmd/mobile/main.go b/cmd/mobile/main.go
deleted file mode 100644
index 15173ae..0000000
--- a/cmd/mobile/main.go
+++ /dev/null
@@ -1,120 +0,0 @@
-package main
-
-import (
- "context"
- "crypto/tls"
- "os"
- "path/filepath"
-
- "forge.cadoles.com/arcad/arcast"
- "forge.cadoles.com/arcad/arcast/pkg/browser/gioui"
- "forge.cadoles.com/arcad/arcast/pkg/config"
- "forge.cadoles.com/arcad/arcast/pkg/server"
- "gioui.org/app"
- "gioui.org/io/system"
- "gioui.org/layout"
- "gioui.org/op"
- "github.com/gioui-plugins/gio-plugins/plugin"
- "github.com/pkg/errors"
- "gitlab.com/wpetit/goweb/logger"
-)
-
-const packageName = "com.cadoles.arcast_player"
-
-func main() {
- ctx := context.Background()
-
- window := app.NewWindow(
- app.Fullscreen.Option(),
- app.AnyOrientation.Option(),
- )
-
- browser := gioui.NewBrowser(window)
-
- go func() {
- ops := new(op.Ops)
- for {
- evt := window.NextEvent()
- plugin.Install(window, evt)
- switch evt := evt.(type) {
- case system.DestroyEvent:
- os.Exit(0)
- return
- case system.FrameEvent:
- gtx := layout.NewContext(ops, evt)
- browser.Layout(gtx)
- evt.Frame(ops)
- }
- }
- }()
-
- go func() {
-
- for {
- ctx, cancel := context.WithCancel(ctx)
- defer cancel()
-
- conf := config.DefaultConfig()
- configFiles := getConfigFiles(ctx)
- for _, f := range configFiles {
- logger.Info(ctx, "loading or creating configuration file", logger.F("filename", f))
- if err := config.LoadOrCreate(ctx, f, conf, config.DefaultTransforms...); err != nil {
- logger.Error(ctx, "could not load configuration file", logger.CapturedE(errors.WithStack(err)))
- continue
- }
-
- break
- }
-
- cert, err := tls.X509KeyPair(conf.HTTPS.Cert, conf.HTTPS.Key)
- if err != nil {
- logger.Fatal(ctx, "could not parse x509 certificate", logger.CapturedE(errors.WithStack(err)))
- }
-
- server := server.New(
- browser,
- server.WithInstanceID(conf.InstanceID),
- server.WithAppsEnabled(conf.Apps.Enabled),
- server.WithDefaultApp(conf.Apps.DefaultApp),
- server.WithApps(arcast.DefaultApps...),
- server.WithTLSCertificate(&cert),
- server.WithAddress(conf.HTTP.Address),
- server.WithTLSAddress(conf.HTTPS.Address),
- server.WithAllowedOrigins(conf.AllowedOrigins...),
- )
-
- if err := server.Start(); err != nil {
- logger.Fatal(ctx, "could not start server", logger.CapturedE(errors.WithStack(err)))
- }
-
- defer func() {
- if err := server.Stop(); err != nil {
- logger.Error(ctx, "could not stop server", logger.CapturedE(errors.WithStack(err)))
- }
- }()
-
- if err := server.Wait(); err != nil {
- logger.Error(ctx, "could not wait for server", logger.CapturedE(errors.WithStack(err)))
- }
- }
- }()
-
- app.Main()
-}
-
-func getConfigFiles(ctx context.Context) []string {
- configFiles := make([]string, 0)
-
- sharedStorageConfigFile := filepath.Join("/storage/emulated/0/Android/data", packageName, "files/config.json")
- configFiles = append(configFiles, sharedStorageConfigFile)
-
- dataDir, err := app.DataDir()
- if err != nil {
- logger.Error(ctx, "could not retrieve app data dir", logger.CapturedE(errors.WithStack(err)))
- } else {
- appDataConfigFile := filepath.Join(dataDir, "config.json")
- configFiles = append(configFiles, appDataConfigFile)
- }
-
- return configFiles
-}
diff --git a/go.mod b/go.mod
index 173bade..4673cf9 100644
--- a/go.mod
+++ b/go.mod
@@ -3,9 +3,7 @@ module forge.cadoles.com/arcad/arcast
go 1.21.4
require (
- gioui.org v0.4.1
github.com/dschmidt/go-layerfs v0.1.0
- github.com/gioui-plugins/gio-plugins v0.0.0-20240323070753-3331d8c2df5d
github.com/go-chi/cors v1.2.1
github.com/gorilla/websocket v1.5.1
github.com/grandcat/zeroconf v1.0.1-0.20230119201135-e4f60f8407b1
@@ -13,21 +11,17 @@ require (
github.com/pkg/errors v0.9.1
github.com/wlynxg/anet v0.0.1
github.com/zserge/lorca v0.1.10
+ golang.org/x/mobile v0.0.0-20201217150744-e6ae53a27f4f
)
require (
cdr.dev/slog v1.6.1 // indirect
- gioui.org/cpu v0.0.0-20220412190645-f1e9e8c3b1f7 // indirect
- gioui.org/shader v1.0.8 // indirect
- git.wow.st/gmp/jni v0.0.0-20210610011705-34026c7e22d0 // indirect
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
github.com/cenkalti/backoff v2.2.1+incompatible // indirect
github.com/charmbracelet/lipgloss v0.7.1 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
github.com/go-playground/locales v0.14.0 // indirect
github.com/go-playground/universal-translator v0.18.0 // indirect
- github.com/go-text/typesetting v0.0.0-20230803102845-24e03d8b5372 // indirect
- github.com/inkeliz/go_inkwasm v0.0.0-20220912074516-049d3472c98a // indirect
github.com/jedib0t/go-pretty/v6 v6.4.9 // indirect
github.com/leodido/go-urn v1.2.1 // indirect
github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
@@ -42,12 +36,8 @@ require (
go.opentelemetry.io/otel v1.21.0 // indirect
go.opentelemetry.io/otel/trace v1.21.0 // indirect
golang.org/x/crypto v0.16.0 // indirect
- golang.org/x/exp v0.0.0-20221012211006-4de253d81b95 // indirect
- golang.org/x/exp/shiny v0.0.0-20220921164117-439092de6870 // indirect
- golang.org/x/image v0.5.0 // indirect
golang.org/x/mod v0.14.0 // indirect
golang.org/x/term v0.15.0 // indirect
- golang.org/x/text v0.14.0 // indirect
golang.org/x/tools v0.16.1 // indirect
golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 // indirect
gopkg.in/go-playground/validator.v9 v9.29.1 // indirect
diff --git a/go.sum b/go.sum
index 6d96fe9..6d5ab13 100644
--- a/go.sum
+++ b/go.sum
@@ -8,19 +8,9 @@ cloud.google.com/go/logging v1.7.0 h1:CJYxlNNNNAMkHp9em/YEXcfJg+rPDg7YfwoRpMU+t5
cloud.google.com/go/logging v1.7.0/go.mod h1:3xjP2CjkM3ZkO73aj4ASA5wRPGGCRrPIAeNqVNkzY8M=
cloud.google.com/go/longrunning v0.5.1 h1:Fr7TXftcqTudoyRJa113hyaqlGdiBQkp0Gq7tErFDWI=
cloud.google.com/go/longrunning v0.5.1/go.mod h1:spvimkwdz6SPWKEt/XBij79E9fiTkHSQl/fRUUQJYJc=
-eliasnaur.com/font v0.0.0-20230308162249-dd43949cb42d h1:ARo7NCVvN2NdhLlJE9xAbKweuI9L6UgfTbYb0YwPacY=
-eliasnaur.com/font v0.0.0-20230308162249-dd43949cb42d/go.mod h1:OYVuxibdk9OSLX8vAqydtRPP87PyTFcT9uH3MlEGBQA=
-gioui.org v0.4.1 h1:sCTw5Fexg0xg9CxYmbrkKtHXcobf0JMbl5XpF2TC/zc=
-gioui.org v0.4.1/go.mod h1:2atiYR4upH71/6ehnh6XsUELa7JZOrOHHNMDxGBZF0Q=
-gioui.org/cpu v0.0.0-20210808092351-bfe733dd3334/go.mod h1:A8M0Cn5o+vY5LTMlnRoK3O5kG+rH0kWfJjeKd9QpBmQ=
-gioui.org/cpu v0.0.0-20220412190645-f1e9e8c3b1f7 h1:tNJdnP5CgM39PRc+KWmBRRYX/zJ+rd5XaYxY5d5veqA=
-gioui.org/cpu v0.0.0-20220412190645-f1e9e8c3b1f7/go.mod h1:A8M0Cn5o+vY5LTMlnRoK3O5kG+rH0kWfJjeKd9QpBmQ=
-gioui.org/shader v1.0.8 h1:6ks0o/A+b0ne7RzEqRZK5f4Gboz2CfG+mVliciy6+qA=
-gioui.org/shader v1.0.8/go.mod h1:mWdiME581d/kV7/iEhLmUgUK5iZ09XR5XpduXzbePVM=
-git.wow.st/gmp/jni v0.0.0-20210610011705-34026c7e22d0 h1:bGG/g4ypjrCJoSvFrP5hafr9PPB5aw8SjcOWWila7ZI=
-git.wow.st/gmp/jni v0.0.0-20210610011705-34026c7e22d0/go.mod h1:+axXBRUTIDlCeE73IKeD/os7LoEnTKdkp8/gQOFjqyo=
github.com/Bornholm/lorca v0.0.0-20240121134933-d5e83569cb4c h1:xG9xSpEqZYOvd1Bvx/36i3RBTA17d7XnuvoMIG+/ry8=
github.com/Bornholm/lorca v0.0.0-20240121134933-d5e83569cb4c/go.mod h1:TUOtEogaMwy0b+p9e4NxZC1jbPRUaNaEw5DnjQF//F8=
+github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k=
github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8=
github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4=
@@ -34,8 +24,6 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dschmidt/go-layerfs v0.1.0 h1:jE6aHDfjNzS/31DS48th6EkmELwTa1Uf+aO4jRkBs3U=
github.com/dschmidt/go-layerfs v0.1.0/go.mod h1:m62aff0hn23Q/tQBRiNSeLD7EUuimDvsuCvCpzBr3Gw=
-github.com/gioui-plugins/gio-plugins v0.0.0-20240323070753-3331d8c2df5d h1:8b7owUJ8sNmgqEk+1d7ylr3TCH3vliCvY/6ycfize8o=
-github.com/gioui-plugins/gio-plugins v0.0.0-20240323070753-3331d8c2df5d/go.mod h1:3XVleuCdPpdajFL+ASh2wmXZNskitXQQ4jhVss0VHZg=
github.com/go-chi/chi/v5 v5.0.10 h1:rLz5avzKpjqxrYwXNfmjkrYYXOyLJd37pz53UFHC6vk=
github.com/go-chi/chi/v5 v5.0.10/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
github.com/go-chi/cors v1.2.1 h1:xEC8UT3Rlp2QuWNEr4Fs/c2EAGVKBwy/1vHx3bppil4=
@@ -48,10 +36,6 @@ github.com/go-playground/locales v0.14.0 h1:u50s323jtVGugKlcYeyzC0etD1HifMjqmJqb
github.com/go-playground/locales v0.14.0/go.mod h1:sawfccIbzZTqEDETgFXqTho0QybSa7l++s0DH+LDiLs=
github.com/go-playground/universal-translator v0.18.0 h1:82dyy6p4OuJq4/CByFNOn/jYrnRPArHwAcmLoJZxyho=
github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA=
-github.com/go-text/typesetting v0.0.0-20230803102845-24e03d8b5372 h1:FQivqchis6bE2/9uF70M2gmmLpe82esEm2QadL0TEJo=
-github.com/go-text/typesetting v0.0.0-20230803102845-24e03d8b5372/go.mod h1:evDBbvNR/KaVFZ2ZlDSOWWXIUKq0wCOEtzLxRM8SG3k=
-github.com/go-text/typesetting-utils v0.0.0-20230616150549-2a7df14b6a22 h1:LBQTFxP2MfsyEDqSKmUBZaDuDHN1vpqDyOZjcqS7MYI=
-github.com/go-text/typesetting-utils v0.0.0-20230616150549-2a7df14b6a22/go.mod h1:DDxDdQEnB70R8owOx3LVpEFvpMK9eeH1o2r0yZhFI9o=
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
@@ -60,8 +44,6 @@ github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/
github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY=
github.com/grandcat/zeroconf v1.0.1-0.20230119201135-e4f60f8407b1 h1:cNb52t5fkWv8ZiicKWnc2eZnhsCCoH7WmRBMIbMp04Q=
github.com/grandcat/zeroconf v1.0.1-0.20230119201135-e4f60f8407b1/go.mod h1:I6CSXU4zCGL08JOk9NbcT0ofAgnIkS/fVXbYzfSoDic=
-github.com/inkeliz/go_inkwasm v0.0.0-20220912074516-049d3472c98a h1:uZklbtdSPrDL/d1EUKd9s8a0Byla2TT01Wg/GZ4xj0w=
-github.com/inkeliz/go_inkwasm v0.0.0-20220912074516-049d3472c98a/go.mod h1:LPI3Qojj7OgTyc2R4RPB6BuMSgjoOXCObwnDzz1SOVk=
github.com/jaevor/go-nanoid v1.3.0 h1:nD+iepesZS6pr3uOVf20vR9GdGgJW1HPaR46gtrxzkg=
github.com/jaevor/go-nanoid v1.3.0/go.mod h1:SI+jFaPuddYkqkVQoNGHs81navCtH388TcrH0RqFKgY=
github.com/jedib0t/go-pretty/v6 v6.4.9 h1:vZ6bjGg2eBSrJn365qlxGcaWu09Id+LHtrfDWlB2Usc=
@@ -109,7 +91,6 @@ github.com/wlynxg/anet v0.0.1 h1:VbkEEgHxPSrRQSiyRd0pmrbcEQAEU2TTb8fb4DmSYoQ=
github.com/wlynxg/anet v0.0.1/go.mod h1:eay5PRQr7fIVAMbTbchTnO9gG65Hg/uYGdc7mguHxoA=
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU=
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8=
-github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
gitlab.com/wpetit/goweb v0.0.0-20231215190137-4a8add1d3d07 h1:0V95X1cBpdj5zyOe6oGtn/BQHlRpV8WlL3eTs3jaxiA=
gitlab.com/wpetit/goweb v0.0.0-20231215190137-4a8add1d3d07/go.mod h1:Nfr7aZPiSN6biFumhiHbh9k8A3rKQRzR+o0bVtv78UY=
go.opentelemetry.io/otel v1.21.0 h1:hzLeKBZEL7Okw2mGzZ0cc4k/A7Fta0uoPgaJCr8fsFc=
@@ -121,59 +102,59 @@ go.opentelemetry.io/otel/sdk v1.16.0/go.mod h1:tMsIuKXuuIWPBAOrH+eHtvhTL+SntFtXF
go.opentelemetry.io/otel/trace v1.21.0 h1:WD9i5gzvoUPuXIXH24ZNBudiarZDKuekPqi/E8fpfLc=
go.opentelemetry.io/otel/trace v1.21.0/go.mod h1:LGbsEB0f9LGjN+OZaQQ26sohbOmiMR+BaslueVtS/qQ=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
-golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
+golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.16.0 h1:mMMrFzRSCF0GvB7Ne27XVtVAaXLrPmgPC7/v0tkwHaY=
golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
-golang.org/x/exp v0.0.0-20221012211006-4de253d81b95 h1:sBdrWpxhGDdTAYNqbgBLAR+ULAPPhfgncLr1X0lyWtg=
-golang.org/x/exp v0.0.0-20221012211006-4de253d81b95/go.mod h1:cyybsKvd6eL0RnXn6p/Grxp8F5bW7iYuBgsNCOHpMYE=
-golang.org/x/exp/shiny v0.0.0-20220921164117-439092de6870 h1:GjCs9zNN8fojJskeK7QiiVecCaMk0dfGTyL6IUcmp0o=
-golang.org/x/exp/shiny v0.0.0-20220921164117-439092de6870/go.mod h1:VjAR7z0ngyATZTELrBSkxOOHhhlnVUxDye4mcjx5h/8=
-golang.org/x/image v0.5.0 h1:5JMiNunQeQw++mMOz48/ISeNu3Iweh/JaZU8ZLqHRrI=
-golang.org/x/image v0.5.0/go.mod h1:FVC7BI/5Ym8R25iw5OLsgshdUBbT1h5jZTpA+mvAdZ4=
-golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
+golang.org/x/exp v0.0.0-20190731235908-ec7cb31e5a56/go.mod h1:JhuoJpWY28nO4Vef9tZUw9qufEGTyX1+7lmHxV5q5G4=
+golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
+golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
+golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
+golang.org/x/mobile v0.0.0-20201217150744-e6ae53a27f4f h1:kgfVkAEEQXXQ0qc6dH7n6y37NAYmTFmz0YRwrRjgxKw=
+golang.org/x/mobile v0.0.0-20201217150744-e6ae53a27f4f/go.mod h1:skQtrUTUwhdJvXM/2KKJzY8pDgNr9I/FOMqDVRPBUS4=
+golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
+golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
+golang.org/x/mod v0.1.1-0.20191209134235-331c550502dd/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0=
golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
+golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210423184538-5f58ad60dda6/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
-golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c=
golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE=
golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210426080607-c94f62235c83/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
-golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4=
golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
-golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
-golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
-golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
+golang.org/x/tools v0.0.0-20200117012304-6edc0a871e69/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.16.1 h1:TLyB3WofjdOEepBHAU20JdNC1Zbg87elYofWYAY5oZA=
golang.org/x/tools v0.16.1/go.mod h1:kYVVN6I1mBNoB1OX+noeBjbRk4IUEPa7JJ+TJMEooJ0=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 h1:+cNy6SZtPcJQH3LJVLOSmiC7MMxXNOb3PU/VUEz+EhU=
golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90=
google.golang.org/genproto v0.0.0-20230726155614-23370e0ffb3e h1:xIXmWJ303kJCuogpj0bHq+dcjcZHU+XFyc1I0Yl9cRg=
diff --git a/pkg/android/binding.go b/pkg/android/binding.go
new file mode 100644
index 0000000..6ba641f
--- /dev/null
+++ b/pkg/android/binding.go
@@ -0,0 +1,86 @@
+package android
+
+import (
+ "context"
+ "crypto/tls"
+ "net"
+ "path/filepath"
+
+ "forge.cadoles.com/arcad/arcast"
+ "forge.cadoles.com/arcad/arcast/pkg/browser/proxy"
+ "forge.cadoles.com/arcad/arcast/pkg/config"
+ "forge.cadoles.com/arcad/arcast/pkg/server"
+ "github.com/pkg/errors"
+ "gitlab.com/wpetit/goweb/logger"
+)
+
+var (
+ browser = proxy.NewBrowser()
+)
+
+func SetBridge(bridge Bridge) {
+ browser.SetLoadURL(bridge.LoadURL)
+ browser.SetGetTitle(bridge.GetTitle)
+ browser.SetGetURL(bridge.GetURL)
+}
+
+func StartServer(dataDir string) string {
+ ctx := context.Background()
+
+ conf := config.DefaultConfig()
+ filename := filepath.Join(dataDir, "config.json")
+
+ logger.Info(ctx, "loading or creating configuration file", logger.F("filename", filename))
+ if err := config.LoadOrCreate(ctx, filename, conf, config.DefaultTransforms...); err != nil {
+ logger.Error(ctx, "could not load configuration file", logger.CapturedE(errors.WithStack(err)))
+ }
+
+ go func() {
+ for {
+ runServer(ctx, conf)
+ }
+ }()
+
+ _, port, err := net.SplitHostPort(conf.HTTP.Address)
+ if err != nil {
+ panic(errors.Wrap(err, "could not parse server listening address"))
+ }
+
+ return port
+}
+
+func runServer(ctx context.Context, conf *config.Config) {
+ ctx, cancel := context.WithCancel(ctx)
+ defer cancel()
+
+ cert, err := tls.X509KeyPair(conf.HTTPS.Cert, conf.HTTPS.Key)
+ if err != nil {
+ logger.Fatal(ctx, "could not parse x509 certificate", logger.CapturedE(errors.WithStack(err)))
+ }
+
+ server := server.New(
+ browser,
+ server.WithInstanceID(conf.InstanceID),
+ server.WithAppsEnabled(conf.Apps.Enabled),
+ server.WithDefaultApp(conf.Apps.DefaultApp),
+ server.WithApps(arcast.DefaultApps...),
+ server.WithTLSCertificate(&cert),
+ server.WithAddress(conf.HTTP.Address),
+ server.WithTLSAddress(conf.HTTPS.Address),
+ server.WithAllowedOrigins(conf.AllowedOrigins...),
+ )
+
+ if err := server.Start(); err != nil {
+ logger.Fatal(ctx, "could not start server", logger.CapturedE(errors.WithStack(err)))
+ }
+
+ defer func() {
+ if err := server.Stop(); err != nil {
+ logger.Error(ctx, "could not stop server", logger.CapturedE(errors.WithStack(err)))
+ }
+ }()
+
+ if err := server.Wait(); err != nil {
+ logger.Error(ctx, "could not wait for server", logger.CapturedE(errors.WithStack(err)))
+ }
+}
diff --git a/pkg/android/bridge.go b/pkg/android/bridge.go
new file mode 100644
index 0000000..532f274
--- /dev/null
+++ b/pkg/android/bridge.go
@@ -0,0 +1,11 @@
+package android
+
+import (
+ _ "golang.org/x/mobile/bind"
+)
+
+type Bridge interface {
+ LoadURL(url string)
+ GetTitle() string
+ GetURL() string
+}
diff --git a/pkg/browser/gioui/browser.go b/pkg/browser/gioui/browser.go
deleted file mode 100644
index 7917dcb..0000000
--- a/pkg/browser/gioui/browser.go
+++ /dev/null
@@ -1,118 +0,0 @@
-package gioui
-
-import (
- "context"
- "sync/atomic"
-
- "forge.cadoles.com/arcad/arcast/pkg/browser"
- "gioui.org/app"
- "gioui.org/f32"
- "gioui.org/layout"
- "github.com/gioui-plugins/gio-plugins/webviewer"
- "gitlab.com/wpetit/goweb/logger"
-)
-
-type Browser struct {
- window *app.Window
- tag int
-
- url *atomic.Value
- changed *atomic.Bool
- status *atomic.Value
- title *atomic.Value
-}
-
-func (b *Browser) Layout(gtx layout.Context) layout.Dimensions {
- events := gtx.Events(&b.tag)
- for _, evt := range events {
- switch ev := evt.(type) {
- case webviewer.TitleEvent:
- b.title.Store(ev.Title)
- case webviewer.NavigationEvent:
- b.url.Store(ev.URL)
- }
- }
-
- ctx := context.Background()
- logger.Debug(ctx, "drawing")
-
- webviewer.WebViewOp{Tag: &b.tag}.Push(gtx.Ops)
-
- webviewer.OffsetOp{
- Point: f32.Point{
- X: 0,
- Y: 0,
- },
- }.Add(gtx.Ops)
-
- webviewer.RectOp{
- Size: f32.Point{
- X: float32(gtx.Constraints.Max.X),
- Y: float32(gtx.Constraints.Max.Y),
- },
- }.Add(gtx.Ops)
-
- if b.changed.CompareAndSwap(true, false) {
- url := b.url.Load().(string)
- logger.Debug(ctx, "url changed", logger.F("url", url))
- webviewer.NavigateOp{URL: url}.Add(gtx.Ops)
- }
-
- return layout.Dimensions{Size: gtx.Constraints.Max}
-}
-
-// Load implements browser.Browser.
-func (b *Browser) Load(url string) error {
- b.url.Store(url)
- b.changed.Store(true)
- b.status.Store(browser.StatusCasting)
-
- b.window.Invalidate()
-
- return nil
-}
-
-// Status implements browser.Browser.
-func (b *Browser) Status() (browser.Status, error) {
- return b.status.Load().(browser.Status), nil
-}
-
-// Title implements browser.Browser.
-func (b *Browser) Title() (string, error) {
- return b.title.Load().(string), nil
-}
-
-// URL implements browser.Browser.
-func (b *Browser) URL() (string, error) {
- return b.url.Load().(string), nil
-}
-
-// Reset implements browser.Browser.
-func (b *Browser) Reset(url string) error {
- b.url.Store(url)
- b.changed.Store(true)
- b.status.Store(browser.StatusIdle)
-
- b.window.Invalidate()
-
- return nil
-}
-
-func NewBrowser(window *app.Window) *Browser {
- b := &Browser{
- window: window,
- url: &atomic.Value{},
- changed: &atomic.Bool{},
- status: &atomic.Value{},
- title: &atomic.Value{},
- }
-
- b.url.Store("")
- b.title.Store("")
- b.changed.Store(false)
- b.status.Store(browser.StatusIdle)
-
- return b
-}
-
-var _ browser.Browser = &Browser{}
diff --git a/pkg/browser/proxy/browser.go b/pkg/browser/proxy/browser.go
new file mode 100644
index 0000000..bf7bcf0
--- /dev/null
+++ b/pkg/browser/proxy/browser.go
@@ -0,0 +1,110 @@
+package proxy
+
+import (
+ "sync"
+
+ "forge.cadoles.com/arcad/arcast/pkg/browser"
+ "github.com/pkg/errors"
+)
+
+var (
+ ErrNotInitialized = errors.New("not initialized")
+)
+
+type Browser struct {
+ loadURL func(url string)
+ getURL func() string
+ getTitle func() string
+
+ status browser.Status
+ mutex sync.RWMutex
+}
+
+// Load implements browser.Browser.
+func (b *Browser) Load(url string) error {
+ b.mutex.Lock()
+ defer b.mutex.Unlock()
+
+ if b.loadURL == nil {
+ return errors.WithStack(ErrNotInitialized)
+ }
+
+ b.loadURL(url)
+ b.status = browser.StatusCasting
+
+ return nil
+}
+
+// Reset implements browser.Browser.
+func (b *Browser) Reset(url string) error {
+ b.mutex.Lock()
+ defer b.mutex.Unlock()
+
+ if b.loadURL == nil {
+ return errors.WithStack(ErrNotInitialized)
+ }
+
+ b.loadURL(url)
+ b.status = browser.StatusIdle
+
+ return nil
+}
+
+// Status implements browser.Browser.
+func (b *Browser) Status() (browser.Status, error) {
+ b.mutex.RLock()
+ defer b.mutex.RUnlock()
+
+ return b.status, nil
+}
+
+// Title implements browser.Browser.
+func (b *Browser) Title() (string, error) {
+ b.mutex.RLock()
+ defer b.mutex.RUnlock()
+
+ if b.getTitle == nil {
+ return "", errors.WithStack(ErrNotInitialized)
+ }
+
+ return b.getTitle(), nil
+}
+
+// URL implements browser.Browser.
+func (b *Browser) URL() (string, error) {
+ b.mutex.RLock()
+ defer b.mutex.RUnlock()
+
+ if b.getURL == nil {
+ return "", errors.WithStack(ErrNotInitialized)
+ }
+
+ return b.getURL(), nil
+}
+
+func (b *Browser) SetLoadURL(fn func(url string)) {
+ b.mutex.Lock()
+ defer b.mutex.Unlock()
+
+ b.loadURL = fn
+}
+
+func (b *Browser) SetGetTitle(fn func() string) {
+ b.mutex.Lock()
+ defer b.mutex.Unlock()
+
+ b.getTitle = fn
+}
+
+func (b *Browser) SetGetURL(fn func() string) {
+ b.mutex.Lock()
+ defer b.mutex.Unlock()
+
+ b.getURL = fn
+}
+
+func NewBrowser() *Browser {
+ return &Browser{}
+}
+
+var _ browser.Browser = &Browser{}