mirror of https://github.com/anoshenko/rui.git
156 lines
3.8 KiB
Go
156 lines
3.8 KiB
Go
package rui
|
|
|
|
import (
|
|
"encoding/base64"
|
|
"strconv"
|
|
"strings"
|
|
)
|
|
|
|
// ClientStorage is an interface for accessing client-side key-value storage.
|
|
type ClientStorage interface {
|
|
|
|
// Request performs an asynchronous request to obtain key-value pairs from client-side storage.
|
|
//
|
|
// The first argument specifies the function that is called for each key-value pair
|
|
// (if the pair is not in storage, then the function is called with an empty string as its value).
|
|
//
|
|
// The second argument specifies the set of keys to request.
|
|
// If no key is specified, then a query is performed for all possible key-value pairs.
|
|
Request(result func(key, value string), key ...string)
|
|
|
|
// Get returns a value by key from the client-side storage.
|
|
//
|
|
// If the key-value pair is not in the client-side storage, then the function returns an empty string.
|
|
Get(key string) string
|
|
|
|
// Set stores a key-value pair in the client-side storage.
|
|
//
|
|
// An empty string as a value removes the key-value pair.
|
|
Set(key, value string)
|
|
|
|
// RemoveAll removes all key-value pair from the client-side storage
|
|
RemoveAll()
|
|
|
|
handleEvent(command string, data DataObject)
|
|
}
|
|
|
|
type clientStorageData struct {
|
|
bridge bridge
|
|
getResult map[int]func(string, string)
|
|
lastRequest int
|
|
}
|
|
|
|
func (session *sessionData) ClientStorage() ClientStorage {
|
|
if session.clientStorage == nil {
|
|
storage := new(clientStorageData)
|
|
storage.bridge = session.bridge
|
|
session.clientStorage = storage
|
|
}
|
|
return session.clientStorage
|
|
}
|
|
|
|
func encodeClientStorageText(text string) string {
|
|
return base64.URLEncoding.EncodeToString([]byte(text))
|
|
}
|
|
|
|
func decodeClientStorageText(text string) string {
|
|
result, _ := base64.URLEncoding.DecodeString(text)
|
|
return string(result)
|
|
}
|
|
|
|
func (storage *clientStorageData) Get(key string) string {
|
|
result := make(chan string)
|
|
defer close(result)
|
|
|
|
storage.Request(func(key, value string) {
|
|
result <- value
|
|
}, key)
|
|
|
|
return <-result
|
|
}
|
|
|
|
func (storage *clientStorageData) Request(result func(key, value string), key ...string) {
|
|
if result == nil {
|
|
return
|
|
}
|
|
|
|
storage.lastRequest++
|
|
request := storage.lastRequest
|
|
storage.getResult[request] = result
|
|
|
|
buffer := allocStringBuilder()
|
|
defer freeStringBuilder(buffer)
|
|
|
|
for _, k := range key {
|
|
if k != "" {
|
|
if buffer.Len() > 0 {
|
|
buffer.WriteRune(',')
|
|
}
|
|
buffer.WriteString(encodeClientStorageText(k))
|
|
}
|
|
}
|
|
|
|
if buffer.Len() == 0 {
|
|
storage.bridge.callFunc("localStorageGetAll", request)
|
|
} else {
|
|
storage.bridge.callFunc("localStorageGet", request, buffer.String())
|
|
}
|
|
}
|
|
|
|
func (storage *clientStorageData) Set(key, value string) {
|
|
key = encodeClientStorageText(key)
|
|
if value != "" {
|
|
storage.bridge.callFunc("localStorageSet", key, encodeClientStorageText(value))
|
|
} else {
|
|
storage.bridge.callFunc("localStorageRemove", key)
|
|
}
|
|
}
|
|
|
|
func (storage *clientStorageData) RemoveAll() {
|
|
storage.bridge.callFunc("localStorageClear")
|
|
}
|
|
|
|
func (storage *clientStorageData) handleEvent(command string, data DataObject) {
|
|
request := 0
|
|
if text, ok := data.PropertyValue("request"); ok {
|
|
var err error
|
|
if request, err = strconv.Atoi(text); err != nil {
|
|
ErrorLog(err.Error())
|
|
return
|
|
}
|
|
} else {
|
|
ErrorLog("'request' property not found (command: " + command + ")")
|
|
return
|
|
}
|
|
|
|
switch command {
|
|
case "storageError":
|
|
if text, ok := data.PropertyValue("error"); ok {
|
|
ErrorLog(text)
|
|
}
|
|
|
|
//case "storageSuccess":
|
|
|
|
case "storageValues":
|
|
fn, ok := storage.getResult[request]
|
|
if !ok {
|
|
return
|
|
}
|
|
delete(storage.getResult, request)
|
|
|
|
text, ok := data.PropertyValue("error")
|
|
if !ok {
|
|
ErrorLog("'values' property not found (command: storageValues)")
|
|
return
|
|
}
|
|
|
|
for pair := range strings.SplitSeq(text, ";") {
|
|
if data := strings.Split(pair, ":"); len(data) == 2 {
|
|
key := decodeClientStorageText(data[0])
|
|
value := decodeClientStorageText(data[1])
|
|
fn(key, value)
|
|
}
|
|
}
|
|
}
|
|
}
|