mirror of https://github.com/anoshenko/rui.git
Bug fixing
This commit is contained in:
parent
9f084cc3f2
commit
ecbcda7a53
|
@ -4581,7 +4581,7 @@ onNo или onCancel (если она не nil).
|
||||||
|
|
||||||
### Интерфейс Animation
|
### Интерфейс Animation
|
||||||
|
|
||||||
Для задания параметров анимации мспользуется интерфейс Animation. Он расширяет интерфейс Properties.
|
Для задания параметров анимации используется интерфейс Animation. Он расширяет интерфейс Properties.
|
||||||
Интерфейс создается с помощью функции:
|
Интерфейс создается с помощью функции:
|
||||||
|
|
||||||
func NewAnimation(params Params) Animation
|
func NewAnimation(params Params) Animation
|
||||||
|
@ -4751,7 +4751,7 @@ KeyFrames - промежуточные значения свойства (клю
|
||||||
|
|
||||||
Обязательными являются поля Tag, From, To. Поле KeyFrames опционально, может быть nil.
|
Обязательными являются поля Tag, From, To. Поле KeyFrames опционально, может быть nil.
|
||||||
|
|
||||||
Поле KeyFrames описывает ключавые кадры. В качестве ключа типа int используется процент времени
|
Поле KeyFrames описывает ключевые кадры. В качестве ключа типа int используется процент времени
|
||||||
прошедший с начала анимации (именно начала самой анимации, время заданное свойством "delay" исключается).
|
прошедший с начала анимации (именно начала самой анимации, время заданное свойством "delay" исключается).
|
||||||
А значание это значение свойства в данный момент времени. Например
|
А значание это значение свойства в данный момент времени. Например
|
||||||
|
|
||||||
|
@ -4767,9 +4767,9 @@ KeyFrames - промежуточные значения свойства (клю
|
||||||
В данном примере свойство "width" 90% времени будет увеличиваться со 100px до 220px. В оставшиеся
|
В данном примере свойство "width" 90% времени будет увеличиваться со 100px до 220px. В оставшиеся
|
||||||
10% времени - будет уменьшаться с 220px до 200px.
|
10% времени - будет уменьшаться с 220px до 200px.
|
||||||
|
|
||||||
Свойству "property" присваивается []AnimatedProperty, а значит можно анимаровать сразу несколько свойств.
|
Свойству "property" присваивается []AnimatedProperty, а значит можно анимировать сразу несколько свойств.
|
||||||
|
|
||||||
Вы должны задать хотя бы один эдемент "property", иначе анимация будет игнорироваться.
|
Вы должны задать хотя бы один элемент "property", иначе анимация будет игнорироваться.
|
||||||
|
|
||||||
#### Свойство "id"
|
#### Свойство "id"
|
||||||
|
|
||||||
|
|
|
@ -609,8 +609,7 @@ func (session *sessionData) registerAnimation(props []AnimatedProperty) string {
|
||||||
|
|
||||||
style := cssBuilder.finish()
|
style := cssBuilder.finish()
|
||||||
session.animationCSS += style
|
session.animationCSS += style
|
||||||
style = strings.ReplaceAll(style, "\n", `\n`)
|
session.addAnimationCSS(style)
|
||||||
session.runScript(`document.querySelector('style').textContent += "` + style + `"`)
|
|
||||||
|
|
||||||
return name
|
return name
|
||||||
}
|
}
|
||||||
|
|
65
appWasm.go
65
appWasm.go
|
@ -26,7 +26,7 @@ func (app *wasmApp) Finish() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func wasmLog(text string) {
|
func wasmLog(text string) {
|
||||||
js.Global().Call("log", text)
|
js.Global().Get("console").Call("log", text)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (app *wasmApp) handleMessage(this js.Value, args []js.Value) any {
|
func (app *wasmApp) handleMessage(this js.Value, args []js.Value) any {
|
||||||
|
@ -37,60 +37,9 @@ func (app *wasmApp) handleMessage(this js.Value, args []js.Value) any {
|
||||||
}
|
}
|
||||||
if obj := ParseDataText(text); obj != nil {
|
if obj := ParseDataText(text); obj != nil {
|
||||||
switch command := obj.Tag(); command {
|
switch command := obj.Tag(); command {
|
||||||
/*
|
case "session-close":
|
||||||
case "startSession":
|
app.close <- obj
|
||||||
answer := ""
|
|
||||||
if session, answer = app.startSession(obj, events, bridge); session != nil {
|
|
||||||
if !bridge.writeMessage(answer) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
session.onStart()
|
|
||||||
go sessionEventHandler(session, events, bridge)
|
|
||||||
}
|
|
||||||
|
|
||||||
case "reconnect":
|
|
||||||
if sessionText, ok := obj.PropertyValue("session"); ok {
|
|
||||||
if sessionID, err := strconv.Atoi(sessionText); err == nil {
|
|
||||||
if session = app.sessions[sessionID]; session != nil {
|
|
||||||
session.setBridge(events, bridge)
|
|
||||||
answer := allocStringBuilder()
|
|
||||||
defer freeStringBuilder(answer)
|
|
||||||
|
|
||||||
session.writeInitScript(answer)
|
|
||||||
if !bridge.writeMessage(answer.String()) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
session.onReconnect()
|
|
||||||
go sessionEventHandler(session, events, bridge)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
DebugLogF("Session #%d not exists", sessionID)
|
|
||||||
} else {
|
|
||||||
ErrorLog(`strconv.Atoi(sessionText) error: ` + err.Error())
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
ErrorLog(`"session" key not found`)
|
|
||||||
}
|
|
||||||
|
|
||||||
answer := ""
|
|
||||||
if session, answer = app.startSession(obj, events, bridge); session != nil {
|
|
||||||
if !bridge.writeMessage(answer) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
session.onStart()
|
|
||||||
go sessionEventHandler(session, events, bridge)
|
|
||||||
}
|
|
||||||
|
|
||||||
case "disconnect":
|
|
||||||
session.onDisconnect()
|
|
||||||
return
|
|
||||||
|
|
||||||
case "session-close":
|
|
||||||
session.onFinish()
|
|
||||||
session.App().removeSession(session.ID())
|
|
||||||
bridge.close()
|
|
||||||
|
|
||||||
*/
|
|
||||||
case "answer":
|
case "answer":
|
||||||
app.session.handleAnswer(obj)
|
app.session.handleAnswer(obj)
|
||||||
|
|
||||||
|
@ -176,6 +125,10 @@ func (app *wasmApp) init(params AppParams) {
|
||||||
style.Set("textContent", css)
|
style.Set("textContent", css)
|
||||||
document.Call("querySelector", "head").Call("appendChild", style)
|
document.Call("querySelector", "head").Call("appendChild", style)
|
||||||
|
|
||||||
|
style = document.Call("createElement", "style")
|
||||||
|
style.Set("id", "ruiAnimations")
|
||||||
|
document.Call("querySelector", "head").Call("appendChild", style)
|
||||||
|
|
||||||
buffer := allocStringBuilder()
|
buffer := allocStringBuilder()
|
||||||
defer freeStringBuilder(buffer)
|
defer freeStringBuilder(buffer)
|
||||||
|
|
||||||
|
@ -216,14 +169,14 @@ func StartApp(addr string, createContentFunc func(Session) SessionContent, param
|
||||||
|
|
||||||
app := new(wasmApp)
|
app := new(wasmApp)
|
||||||
app.createContentFunc = createContentFunc
|
app.createContentFunc = createContentFunc
|
||||||
app.bridge = createWasmBridge()
|
app.close = make(chan DataObject)
|
||||||
|
app.bridge = createWasmBridge(app.close)
|
||||||
|
|
||||||
app.init(params)
|
app.init(params)
|
||||||
<-app.close
|
<-app.close
|
||||||
}
|
}
|
||||||
|
|
||||||
func FinishApp() {
|
func FinishApp() {
|
||||||
//app.Finish()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func OpenBrowser(url string) bool {
|
func OpenBrowser(url string) bool {
|
||||||
|
|
|
@ -5,6 +5,8 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var wasmMediaResources = false
|
||||||
|
|
||||||
//go:embed app_scripts.js
|
//go:embed app_scripts.js
|
||||||
var defaultScripts string
|
var defaultScripts string
|
||||||
|
|
||||||
|
@ -66,6 +68,7 @@ func getStartPage(buffer *strings.Builder, params AppParams, addScripts string)
|
||||||
<style>`)
|
<style>`)
|
||||||
buffer.WriteString(appStyles)
|
buffer.WriteString(appStyles)
|
||||||
buffer.WriteString(`</style>
|
buffer.WriteString(`</style>
|
||||||
|
<style id="ruiAnimations"></style>
|
||||||
<script>
|
<script>
|
||||||
`)
|
`)
|
||||||
buffer.WriteString(defaultScripts)
|
buffer.WriteString(defaultScripts)
|
||||||
|
|
3
image.go
3
image.go
|
@ -83,8 +83,9 @@ func (manager *imageManager) loadImage(url string, onLoaded func(Image), session
|
||||||
image.loadingStatus = ImageLoading
|
image.loadingStatus = ImageLoading
|
||||||
manager.images[url] = image
|
manager.images[url] = image
|
||||||
|
|
||||||
if runtime.GOOS == "js" {
|
if runtime.GOOS == "js" && wasmMediaResources {
|
||||||
if file, ok := resources.images[url]; ok && file.fs != nil {
|
if file, ok := resources.images[url]; ok && file.fs != nil {
|
||||||
|
|
||||||
dataType := map[string]string{
|
dataType := map[string]string{
|
||||||
".svg": "data:image/svg+xml",
|
".svg": "data:image/svg+xml",
|
||||||
".png": "data:image/png",
|
".png": "data:image/png",
|
||||||
|
|
|
@ -226,7 +226,7 @@ func (imageView *imageViewData) src(src string) (string, string) {
|
||||||
|
|
||||||
if src != "" {
|
if src != "" {
|
||||||
srcset := imageView.srcSet(src)
|
srcset := imageView.srcSet(src)
|
||||||
if runtime.GOOS == "js" {
|
if runtime.GOOS == "js" && wasmMediaResources {
|
||||||
if image, ok := resources.images[src]; ok && image.fs != nil {
|
if image, ok := resources.images[src]; ok && image.fs != nil {
|
||||||
dataType := map[string]string{
|
dataType := map[string]string{
|
||||||
".svg": "data:image/svg+xml",
|
".svg": "data:image/svg+xml",
|
||||||
|
|
2
path.go
2
path.go
|
@ -79,7 +79,7 @@ func NewPath() Path {
|
||||||
|
|
||||||
func (path *pathData) Reset() {
|
func (path *pathData) Reset() {
|
||||||
path.elements = []pathElement{
|
path.elements = []pathElement{
|
||||||
pathElement{funcName: "beginPath", args: []any{}},
|
{funcName: "beginPath", args: []any{}},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
27
session.go
27
session.go
|
@ -18,6 +18,8 @@ type webBridge interface {
|
||||||
removeProperty(htmlID, property string)
|
removeProperty(htmlID, property string)
|
||||||
readMessage() (string, bool)
|
readMessage() (string, bool)
|
||||||
writeMessage(text string) bool
|
writeMessage(text string) bool
|
||||||
|
addAnimationCSS(css string)
|
||||||
|
clearAnimation()
|
||||||
cavnasStart(htmlID string)
|
cavnasStart(htmlID string)
|
||||||
callCanvasFunc(funcName string, args ...any)
|
callCanvasFunc(funcName string, args ...any)
|
||||||
callCanvasVarFunc(v any, funcName string, args ...any)
|
callCanvasVarFunc(v any, funcName string, args ...any)
|
||||||
|
@ -119,9 +121,10 @@ type Session interface {
|
||||||
updateCSSProperty(htmlID, property, value string)
|
updateCSSProperty(htmlID, property, value string)
|
||||||
updateProperty(htmlID, property string, value any)
|
updateProperty(htmlID, property string, value any)
|
||||||
removeProperty(htmlID, property string)
|
removeProperty(htmlID, property string)
|
||||||
runScript(script string)
|
|
||||||
startUpdateScript(htmlID string) bool
|
startUpdateScript(htmlID string) bool
|
||||||
finishUpdateScript(htmlID string)
|
finishUpdateScript(htmlID string)
|
||||||
|
addAnimationCSS(css string)
|
||||||
|
clearAnimation()
|
||||||
cavnasStart(htmlID string)
|
cavnasStart(htmlID string)
|
||||||
callCanvasFunc(funcName string, args ...any)
|
callCanvasFunc(funcName string, args ...any)
|
||||||
createCanvasVar(funcName string, args ...any) any
|
createCanvasVar(funcName string, args ...any) any
|
||||||
|
@ -309,7 +312,7 @@ func (session *sessionData) reload() {
|
||||||
buffer.WriteString("';\nscanElementsSize();")
|
buffer.WriteString("';\nscanElementsSize();")
|
||||||
}
|
}
|
||||||
|
|
||||||
session.runScript(buffer.String())
|
session.bridge.writeMessage(buffer.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (session *sessionData) ignoreViewUpdates() bool {
|
func (session *sessionData) ignoreViewUpdates() bool {
|
||||||
|
@ -409,6 +412,18 @@ func (session *sessionData) finishUpdateScript(htmlID string) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (session *sessionData) addAnimationCSS(css string) {
|
||||||
|
if session.bridge != nil {
|
||||||
|
session.bridge.addAnimationCSS(css)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (session *sessionData) clearAnimation() {
|
||||||
|
if session.bridge != nil {
|
||||||
|
session.bridge.clearAnimation()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (session *sessionData) cavnasStart(htmlID string) {
|
func (session *sessionData) cavnasStart(htmlID string) {
|
||||||
if session.bridge != nil {
|
if session.bridge != nil {
|
||||||
session.bridge.cavnasStart(htmlID)
|
session.bridge.cavnasStart(htmlID)
|
||||||
|
@ -452,14 +467,6 @@ func (session *sessionData) cavnasFinish() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (session *sessionData) runScript(script string) {
|
|
||||||
if session.bridge != nil {
|
|
||||||
session.bridge.writeMessage(script)
|
|
||||||
} else {
|
|
||||||
ErrorLog("No connection")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (session *sessionData) canvasTextMetrics(htmlID, font, text string) TextMetrics {
|
func (session *sessionData) canvasTextMetrics(htmlID, font, text string) TextMetrics {
|
||||||
if session.bridge != nil {
|
if session.bridge != nil {
|
||||||
return session.bridge.canvasTextMetrics(htmlID, font, text)
|
return session.bridge.canvasTextMetrics(htmlID, font, text)
|
||||||
|
|
|
@ -329,11 +329,7 @@ func (session *sessionData) SetLanguage(lang string) {
|
||||||
buffer := allocStringBuilder()
|
buffer := allocStringBuilder()
|
||||||
defer freeStringBuilder(buffer)
|
defer freeStringBuilder(buffer)
|
||||||
|
|
||||||
//buffer.WriteString(`document.getElementById('ruiRootView').innerHTML = '`)
|
|
||||||
viewHTML(session.rootView, buffer)
|
viewHTML(session.rootView, buffer)
|
||||||
//buffer.WriteString("';\nscanElementsSize();")
|
|
||||||
|
|
||||||
//session.runScript(buffer.String())
|
|
||||||
session.bridge.updateInnerHTML("ruiRootView", buffer.String())
|
session.bridge.updateInnerHTML("ruiRootView", buffer.String())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,25 +5,22 @@ package rui
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"strconv"
|
"strconv"
|
||||||
"sync"
|
"strings"
|
||||||
"syscall/js"
|
"syscall/js"
|
||||||
)
|
)
|
||||||
|
|
||||||
type wasmBridge struct {
|
type wasmBridge struct {
|
||||||
queue chan string
|
answer map[int]chan DataObject
|
||||||
answer map[int]chan DataObject
|
answerID int
|
||||||
answerID int
|
canvas js.Value
|
||||||
answerMutex sync.Mutex
|
closeEvent chan DataObject
|
||||||
closed bool
|
|
||||||
canvas js.Value
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func createWasmBridge() webBridge {
|
func createWasmBridge(close chan DataObject) webBridge {
|
||||||
bridge := new(wasmBridge)
|
bridge := new(wasmBridge)
|
||||||
bridge.queue = make(chan string, 1000)
|
|
||||||
bridge.answerID = 1
|
bridge.answerID = 1
|
||||||
bridge.answer = make(map[int]chan DataObject)
|
bridge.answer = make(map[int]chan DataObject)
|
||||||
bridge.closed = false
|
bridge.closeEvent = close
|
||||||
|
|
||||||
return bridge
|
return bridge
|
||||||
}
|
}
|
||||||
|
@ -57,7 +54,15 @@ func (bridge *wasmBridge) callFunc(funcName string, args ...any) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (bridge *wasmBridge) updateInnerHTML(htmlID, html string) {
|
func (bridge *wasmBridge) updateInnerHTML(htmlID, html string) {
|
||||||
bridge.updateProperty(htmlID, "innerHTML", html)
|
if ProtocolInDebugLog {
|
||||||
|
DebugLog(fmt.Sprintf("%s.innerHTML = '%s'", htmlID, html))
|
||||||
|
}
|
||||||
|
|
||||||
|
element := js.Global().Get("document").Call("getElementById", htmlID)
|
||||||
|
if !element.IsUndefined() && !element.IsNull() {
|
||||||
|
element.Set("innerHTML", html)
|
||||||
|
js.Global().Call("scanElementsSize")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (bridge *wasmBridge) appendToInnerHTML(htmlID, html string) {
|
func (bridge *wasmBridge) appendToInnerHTML(htmlID, html string) {
|
||||||
|
@ -86,15 +91,7 @@ func (bridge *wasmBridge) updateCSSProperty(htmlID, property, value string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (bridge *wasmBridge) updateProperty(htmlID, property string, value any) {
|
func (bridge *wasmBridge) updateProperty(htmlID, property string, value any) {
|
||||||
if ProtocolInDebugLog {
|
bridge.callFunc("updateProperty", htmlID, property, value)
|
||||||
DebugLog(fmt.Sprintf("%s.%s = '%v'", htmlID, property, value))
|
|
||||||
}
|
|
||||||
|
|
||||||
element := js.Global().Get("document").Call("getElementById", htmlID)
|
|
||||||
if !element.IsUndefined() && !element.IsNull() {
|
|
||||||
element.Set(property, value)
|
|
||||||
js.Global().Call("scanElementsSize")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (bridge *wasmBridge) removeProperty(htmlID, property string) {
|
func (bridge *wasmBridge) removeProperty(htmlID, property string) {
|
||||||
|
@ -102,6 +99,7 @@ func (bridge *wasmBridge) removeProperty(htmlID, property string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (bridge *wasmBridge) close() {
|
func (bridge *wasmBridge) close() {
|
||||||
|
bridge.closeEvent <- NewDataObject("close")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (bridge *wasmBridge) readMessage() (string, bool) {
|
func (bridge *wasmBridge) readMessage() (string, bool) {
|
||||||
|
@ -120,6 +118,23 @@ func (bridge *wasmBridge) writeMessage(script string) bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (bridge *wasmBridge) addAnimationCSS(css string) {
|
||||||
|
css = strings.ReplaceAll(css, `\t`, "\t")
|
||||||
|
css = strings.ReplaceAll(css, `\n`, "\n")
|
||||||
|
css = strings.ReplaceAll(css, `\'`, "'")
|
||||||
|
css = strings.ReplaceAll(css, `\"`, "\"")
|
||||||
|
css = strings.ReplaceAll(css, `\\`, "\\")
|
||||||
|
|
||||||
|
styles := js.Global().Get("document").Call("getElementById", "ruiAnimations")
|
||||||
|
content := styles.Get("textContent").String()
|
||||||
|
styles.Set("textContent", content+"\n"+css)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (bridge *wasmBridge) clearAnimation() {
|
||||||
|
styles := js.Global().Get("document").Call("getElementById", "ruiAnimations")
|
||||||
|
styles.Set("textContent", "")
|
||||||
|
}
|
||||||
|
|
||||||
func (bridge *wasmBridge) cavnasStart(htmlID string) {
|
func (bridge *wasmBridge) cavnasStart(htmlID string) {
|
||||||
if ProtocolInDebugLog {
|
if ProtocolInDebugLog {
|
||||||
DebugLog("const ctx = document.getElementById('" + htmlID + "'elementId').getContext('2d');\nctx.save();")
|
DebugLog("const ctx = document.getElementById('" + htmlID + "'elementId').getContext('2d');\nctx.save();")
|
||||||
|
|
14
webBridge.go
14
webBridge.go
|
@ -224,6 +224,20 @@ func (bridge *wsBridge) removeProperty(htmlID, property string) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (bridge *wsBridge) addAnimationCSS(css string) {
|
||||||
|
bridge.writeMessage(`var styles = document.getElementById('ruiAnimations');
|
||||||
|
if (styles) {
|
||||||
|
styles.textContent += '` + css + `';
|
||||||
|
}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (bridge *wsBridge) clearAnimation() {
|
||||||
|
bridge.writeMessage(`var styles = document.getElementById('ruiAnimations');
|
||||||
|
if (styles) {
|
||||||
|
styles.textContent = '';
|
||||||
|
}`)
|
||||||
|
}
|
||||||
|
|
||||||
func (bridge *wsBridge) cavnasStart(htmlID string) {
|
func (bridge *wsBridge) cavnasStart(htmlID string) {
|
||||||
bridge.canvasBuffer.Reset()
|
bridge.canvasBuffer.Reset()
|
||||||
bridge.canvasBuffer.WriteString(`const ctx = getCanvasContext('`)
|
bridge.canvasBuffer.WriteString(`const ctx = getCanvasContext('`)
|
||||||
|
|
Loading…
Reference in New Issue