feat(android): use native webview instead of gioui framework
All checks were successful
arcad/arcast/pipeline/head This commit looks good
All checks were successful
arcad/arcast/pipeline/head This commit looks good
This commit is contained in:
parent
49c23e66de
commit
7c75b478a3
7
.vscode/settings.json
vendored
7
.vscode/settings.json
vendored
@ -1,5 +1,4 @@
|
||||
{
|
||||
"java.project.sourcePaths": [
|
||||
"apps/main/src"
|
||||
]
|
||||
}
|
||||
"java.project.sourcePaths": ["apps/main/src"],
|
||||
"java.configuration.updateBuildConfiguration": "automatic"
|
||||
}
|
||||
|
25
Makefile
25
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
|
||||
|
@ -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'
|
||||
|
3
android/app/libs/.gitignore
vendored
3
android/app/libs/.gitignore
vendored
@ -1 +1,2 @@
|
||||
/mobile.aar
|
||||
/mobile.aar
|
||||
/arcast*
|
Binary file not shown.
Binary file not shown.
@ -8,8 +8,6 @@
|
||||
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
|
||||
<uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE" />
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
||||
|
||||
<application
|
||||
@ -35,12 +33,6 @@
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity android:name="org.gioui.GioActivity"
|
||||
android:theme="@style/Theme.GioApp"
|
||||
android:configChanges="orientation|keyboardHidden"
|
||||
android:windowSoftInputMode="adjustResize"
|
||||
android:keepScreenOn="true">
|
||||
</activity>
|
||||
</application>
|
||||
|
||||
</manifest>
|
@ -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
|
||||
}
|
||||
}
|
@ -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()
|
||||
}
|
||||
}
|
@ -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)
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
height: auto;
|
||||
left: 0;
|
||||
object-fit: contain;
|
||||
/* position: absolute; */
|
||||
right: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
flex-grow: 1;
|
||||
width: 100%;
|
||||
}
|
||||
|
@ -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
|
||||
}
|
12
go.mod
12
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
|
||||
|
55
go.sum
55
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=
|
||||
|
86
pkg/android/binding.go
Normal file
86
pkg/android/binding.go
Normal file
@ -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)))
|
||||
}
|
||||
}
|
11
pkg/android/bridge.go
Normal file
11
pkg/android/bridge.go
Normal file
@ -0,0 +1,11 @@
|
||||
package android
|
||||
|
||||
import (
|
||||
_ "golang.org/x/mobile/bind"
|
||||
)
|
||||
|
||||
type Bridge interface {
|
||||
LoadURL(url string)
|
||||
GetTitle() string
|
||||
GetURL() string
|
||||
}
|
@ -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{}
|
110
pkg/browser/proxy/browser.go
Normal file
110
pkg/browser/proxy/browser.go
Normal file
@ -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{}
|
Loading…
Reference in New Issue
Block a user