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. Он расширяет интерфейс Properties. | ||||
| Для задания параметров анимации используется интерфейс Animation. Он расширяет интерфейс Properties. | ||||
| Интерфейс создается с помощью функции: | ||||
| 
 | ||||
| 	func NewAnimation(params Params) Animation | ||||
|  | @ -4751,7 +4751,7 @@ KeyFrames - промежуточные значения свойства (клю | |||
| 
 | ||||
| Обязательными являются поля Tag, From, To. Поле KeyFrames опционально, может быть nil. | ||||
| 
 | ||||
| Поле KeyFrames описывает ключавые кадры. В качестве ключа типа int используется процент времени  | ||||
| Поле KeyFrames описывает ключевые кадры. В качестве ключа типа int используется процент времени  | ||||
| прошедший с начала анимации (именно начала самой анимации, время заданное свойством "delay" исключается). | ||||
| А значание это значение свойства в данный момент времени. Например | ||||
| 
 | ||||
|  | @ -4767,9 +4767,9 @@ KeyFrames - промежуточные значения свойства (клю | |||
| В данном примере свойство "width" 90% времени будет увеличиваться со 100px до 220px. В оставшиеся  | ||||
| 10% времени - будет уменьшаться с 220px до 200px. | ||||
| 
 | ||||
| Свойству "property" присваивается []AnimatedProperty, а значит можно анимаровать сразу несколько свойств. | ||||
| Свойству "property" присваивается []AnimatedProperty, а значит можно анимировать сразу несколько свойств. | ||||
| 
 | ||||
| Вы должны задать хотя бы один эдемент "property", иначе анимация будет игнорироваться. | ||||
| Вы должны задать хотя бы один элемент "property", иначе анимация будет игнорироваться. | ||||
| 
 | ||||
| #### Свойство "id" | ||||
| 
 | ||||
|  |  | |||
|  | @ -609,8 +609,7 @@ func (session *sessionData) registerAnimation(props []AnimatedProperty) string { | |||
| 
 | ||||
| 	style := cssBuilder.finish() | ||||
| 	session.animationCSS += style | ||||
| 	style = strings.ReplaceAll(style, "\n", `\n`) | ||||
| 	session.runScript(`document.querySelector('style').textContent += "` + style + `"`) | ||||
| 	session.addAnimationCSS(style) | ||||
| 
 | ||||
| 	return name | ||||
| } | ||||
|  |  | |||
							
								
								
									
										65
									
								
								appWasm.go
								
								
								
								
							
							
						
						
									
										65
									
								
								appWasm.go
								
								
								
								
							|  | @ -26,7 +26,7 @@ func (app *wasmApp) Finish() { | |||
| } | ||||
| 
 | ||||
| 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 { | ||||
|  | @ -37,60 +37,9 @@ func (app *wasmApp) handleMessage(this js.Value, args []js.Value) any { | |||
| 		} | ||||
| 		if obj := ParseDataText(text); obj != nil { | ||||
| 			switch command := obj.Tag(); command { | ||||
| 			/* | ||||
| 						case "startSession": | ||||
| 							answer := "" | ||||
| 							if session, answer = app.startSession(obj, events, bridge); session != nil { | ||||
| 								if !bridge.writeMessage(answer) { | ||||
| 									return | ||||
| 								} | ||||
| 								session.onStart() | ||||
| 								go sessionEventHandler(session, events, bridge) | ||||
| 							} | ||||
| 			case "session-close": | ||||
| 				app.close <- obj | ||||
| 
 | ||||
| 						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": | ||||
| 				app.session.handleAnswer(obj) | ||||
| 
 | ||||
|  | @ -176,6 +125,10 @@ func (app *wasmApp) init(params AppParams) { | |||
| 	style.Set("textContent", css) | ||||
| 	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() | ||||
| 	defer freeStringBuilder(buffer) | ||||
| 
 | ||||
|  | @ -216,14 +169,14 @@ func StartApp(addr string, createContentFunc func(Session) SessionContent, param | |||
| 
 | ||||
| 	app := new(wasmApp) | ||||
| 	app.createContentFunc = createContentFunc | ||||
| 	app.bridge = createWasmBridge() | ||||
| 	app.close = make(chan DataObject) | ||||
| 	app.bridge = createWasmBridge(app.close) | ||||
| 
 | ||||
| 	app.init(params) | ||||
| 	<-app.close | ||||
| } | ||||
| 
 | ||||
| func FinishApp() { | ||||
| 	//app.Finish()
 | ||||
| } | ||||
| 
 | ||||
| func OpenBrowser(url string) bool { | ||||
|  |  | |||
|  | @ -5,6 +5,8 @@ import ( | |||
| 	"strings" | ||||
| ) | ||||
| 
 | ||||
| var wasmMediaResources = false | ||||
| 
 | ||||
| //go:embed app_scripts.js
 | ||||
| var defaultScripts string | ||||
| 
 | ||||
|  | @ -66,6 +68,7 @@ func getStartPage(buffer *strings.Builder, params AppParams, addScripts string) | |||
| 		<style>`) | ||||
| 	buffer.WriteString(appStyles) | ||||
| 	buffer.WriteString(`</style> | ||||
| 		<style id="ruiAnimations"></style> | ||||
| 		<script> | ||||
| `) | ||||
| 	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 | ||||
| 	manager.images[url] = image | ||||
| 
 | ||||
| 	if runtime.GOOS == "js" { | ||||
| 	if runtime.GOOS == "js" && wasmMediaResources { | ||||
| 		if file, ok := resources.images[url]; ok && file.fs != nil { | ||||
| 
 | ||||
| 			dataType := map[string]string{ | ||||
| 				".svg":  "data:image/svg+xml", | ||||
| 				".png":  "data:image/png", | ||||
|  |  | |||
|  | @ -226,7 +226,7 @@ func (imageView *imageViewData) src(src string) (string, string) { | |||
| 
 | ||||
| 	if src != "" { | ||||
| 		srcset := imageView.srcSet(src) | ||||
| 		if runtime.GOOS == "js" { | ||||
| 		if runtime.GOOS == "js" && wasmMediaResources { | ||||
| 			if image, ok := resources.images[src]; ok && image.fs != nil { | ||||
| 				dataType := map[string]string{ | ||||
| 					".svg":  "data:image/svg+xml", | ||||
|  |  | |||
							
								
								
									
										2
									
								
								path.go
								
								
								
								
							
							
						
						
									
										2
									
								
								path.go
								
								
								
								
							|  | @ -79,7 +79,7 @@ func NewPath() Path { | |||
| 
 | ||||
| func (path *pathData) Reset() { | ||||
| 	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) | ||||
| 	readMessage() (string, bool) | ||||
| 	writeMessage(text string) bool | ||||
| 	addAnimationCSS(css string) | ||||
| 	clearAnimation() | ||||
| 	cavnasStart(htmlID string) | ||||
| 	callCanvasFunc(funcName string, args ...any) | ||||
| 	callCanvasVarFunc(v any, funcName string, args ...any) | ||||
|  | @ -119,9 +121,10 @@ type Session interface { | |||
| 	updateCSSProperty(htmlID, property, value string) | ||||
| 	updateProperty(htmlID, property string, value any) | ||||
| 	removeProperty(htmlID, property string) | ||||
| 	runScript(script string) | ||||
| 	startUpdateScript(htmlID string) bool | ||||
| 	finishUpdateScript(htmlID string) | ||||
| 	addAnimationCSS(css string) | ||||
| 	clearAnimation() | ||||
| 	cavnasStart(htmlID string) | ||||
| 	callCanvasFunc(funcName string, args ...any) | ||||
| 	createCanvasVar(funcName string, args ...any) any | ||||
|  | @ -309,7 +312,7 @@ func (session *sessionData) reload() { | |||
| 		buffer.WriteString("';\nscanElementsSize();") | ||||
| 	} | ||||
| 
 | ||||
| 	session.runScript(buffer.String()) | ||||
| 	session.bridge.writeMessage(buffer.String()) | ||||
| } | ||||
| 
 | ||||
| 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) { | ||||
| 	if session.bridge != nil { | ||||
| 		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 { | ||||
| 	if session.bridge != nil { | ||||
| 		return session.bridge.canvasTextMetrics(htmlID, font, text) | ||||
|  |  | |||
|  | @ -329,11 +329,7 @@ func (session *sessionData) SetLanguage(lang string) { | |||
| 			buffer := allocStringBuilder() | ||||
| 			defer freeStringBuilder(buffer) | ||||
| 
 | ||||
| 			//buffer.WriteString(`document.getElementById('ruiRootView').innerHTML = '`)
 | ||||
| 			viewHTML(session.rootView, buffer) | ||||
| 			//buffer.WriteString("';\nscanElementsSize();")
 | ||||
| 
 | ||||
| 			//session.runScript(buffer.String())
 | ||||
| 			session.bridge.updateInnerHTML("ruiRootView", buffer.String()) | ||||
| 		} | ||||
| 	} | ||||
|  |  | |||
|  | @ -5,25 +5,22 @@ package rui | |||
| import ( | ||||
| 	"fmt" | ||||
| 	"strconv" | ||||
| 	"sync" | ||||
| 	"strings" | ||||
| 	"syscall/js" | ||||
| ) | ||||
| 
 | ||||
| type wasmBridge struct { | ||||
| 	queue       chan string | ||||
| 	answer      map[int]chan DataObject | ||||
| 	answerID    int | ||||
| 	answerMutex sync.Mutex | ||||
| 	closed      bool | ||||
| 	canvas      js.Value | ||||
| 	answer     map[int]chan DataObject | ||||
| 	answerID   int | ||||
| 	canvas     js.Value | ||||
| 	closeEvent chan DataObject | ||||
| } | ||||
| 
 | ||||
| func createWasmBridge() webBridge { | ||||
| func createWasmBridge(close chan DataObject) webBridge { | ||||
| 	bridge := new(wasmBridge) | ||||
| 	bridge.queue = make(chan string, 1000) | ||||
| 	bridge.answerID = 1 | ||||
| 	bridge.answer = make(map[int]chan DataObject) | ||||
| 	bridge.closed = false | ||||
| 	bridge.closeEvent = close | ||||
| 
 | ||||
| 	return bridge | ||||
| } | ||||
|  | @ -57,7 +54,15 @@ func (bridge *wasmBridge) callFunc(funcName string, args ...any) bool { | |||
| } | ||||
| 
 | ||||
| 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) { | ||||
|  | @ -86,15 +91,7 @@ func (bridge *wasmBridge) updateCSSProperty(htmlID, property, value string) { | |||
| } | ||||
| 
 | ||||
| func (bridge *wasmBridge) updateProperty(htmlID, property string, value any) { | ||||
| 	if ProtocolInDebugLog { | ||||
| 		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") | ||||
| 	} | ||||
| 	bridge.callFunc("updateProperty", htmlID, property, value) | ||||
| } | ||||
| 
 | ||||
| func (bridge *wasmBridge) removeProperty(htmlID, property string) { | ||||
|  | @ -102,6 +99,7 @@ func (bridge *wasmBridge) removeProperty(htmlID, property string) { | |||
| } | ||||
| 
 | ||||
| func (bridge *wasmBridge) close() { | ||||
| 	bridge.closeEvent <- NewDataObject("close") | ||||
| } | ||||
| 
 | ||||
| func (bridge *wasmBridge) readMessage() (string, bool) { | ||||
|  | @ -120,6 +118,23 @@ func (bridge *wasmBridge) writeMessage(script string) bool { | |||
| 	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) { | ||||
| 	if ProtocolInDebugLog { | ||||
| 		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) { | ||||
| 	bridge.canvasBuffer.Reset() | ||||
| 	bridge.canvasBuffer.WriteString(`const ctx = getCanvasContext('`) | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue