Created stable-ish version of cfyne
This commit is contained in:
parent
31b2707c23
commit
feb5d22b2a
7
cmd/cfyne/actions.go
Normal file
7
cmd/cfyne/actions.go
Normal file
|
@ -0,0 +1,7 @@
|
|||
package main
|
||||
|
||||
const (
|
||||
ACTION_SET_SCENE_NICKNAME = 1 + iota
|
||||
ACTION_SET_SCENE_MAIN
|
||||
ACTION_UPDATE_USER_OPTS_CONTS
|
||||
)
|
61
cmd/cfyne/conUsers.go
Normal file
61
cmd/cfyne/conUsers.go
Normal file
|
@ -0,0 +1,61 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"log"
|
||||
"sync"
|
||||
)
|
||||
|
||||
var (
|
||||
userCenter UserCenter
|
||||
)
|
||||
|
||||
type UserCenter struct {
|
||||
UsersSTOI map[string]uint16
|
||||
UsersITOS map[uint16]string
|
||||
Mu sync.Mutex
|
||||
}
|
||||
|
||||
func (u *UserCenter) Init() {
|
||||
u.UsersSTOI = make(map[string]uint16)
|
||||
u.UsersITOS = make(map[uint16]string)
|
||||
}
|
||||
|
||||
func (u *UserCenter) AddUser(name string, id uint16) error {
|
||||
u.Mu.Lock()
|
||||
defer u.Mu.Unlock()
|
||||
_, alreadyHave := u.UsersSTOI[name]
|
||||
if alreadyHave {
|
||||
return ERROR_ALREADY_HAVE
|
||||
}
|
||||
log.Printf("Users: add %s with %d id\n", name, id)
|
||||
u.UsersITOS[id] = name
|
||||
u.UsersSTOI[name] = id
|
||||
return nil
|
||||
}
|
||||
|
||||
func (u *UserCenter) DeleteIfHaveOne(id uint16) {
|
||||
name, found := u.UsersITOS[id]
|
||||
if !found {
|
||||
log.Printf("User with %d id is not found; Can not delete\n", id)
|
||||
return
|
||||
}
|
||||
delete(u.UsersITOS, id)
|
||||
delete(u.UsersSTOI, name)
|
||||
log.Printf("User with %s name and %d id was found; User is deleted\n", name, id)
|
||||
}
|
||||
|
||||
func (u *UserCenter) GetID(name string) (uint16, error) {
|
||||
id, have := u.UsersSTOI[name]
|
||||
if !have {
|
||||
return 0, ERROR_DONT_HAVE
|
||||
}
|
||||
return id, nil
|
||||
}
|
||||
|
||||
func (u *UserCenter) GetName(id uint16) (string, error) {
|
||||
name, have := u.UsersITOS[id]
|
||||
if !have {
|
||||
return "", ERROR_DONT_HAVE
|
||||
}
|
||||
return name, nil
|
||||
}
|
15
cmd/cfyne/funcs.go
Normal file
15
cmd/cfyne/funcs.go
Normal file
|
@ -0,0 +1,15 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
// "fyne.io/fyne/v2/widget"
|
||||
com "git.qowevisa.me/Qowevisa/gotell/communication"
|
||||
)
|
||||
|
||||
func getSendMessageFuncToIntercom(intercom chan *com.Message, id uint8, data []byte) func() {
|
||||
return func() {
|
||||
intercom <- &com.Message{
|
||||
ID: id,
|
||||
Data: data,
|
||||
}
|
||||
}
|
||||
}
|
31
cmd/cfyne/linksmuar.go
Normal file
31
cmd/cfyne/linksmuar.go
Normal file
|
@ -0,0 +1,31 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
com "git.qowevisa.me/Qowevisa/gotell/communication"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// Non-Generic variant
|
||||
type MutexLinksArray struct {
|
||||
Ar []com.Link
|
||||
Mu sync.RWMutex
|
||||
}
|
||||
|
||||
func CreateMutexLinksArray() *MutexLinksArray {
|
||||
var tmp []com.Link
|
||||
return &MutexLinksArray{
|
||||
Ar: tmp,
|
||||
}
|
||||
}
|
||||
|
||||
func (ma *MutexLinksArray) Add(v com.Link) {
|
||||
ma.Mu.Lock()
|
||||
ma.Ar = append(ma.Ar, v)
|
||||
ma.Mu.Unlock()
|
||||
}
|
||||
|
||||
func (ma *MutexLinksArray) GetArray() []com.Link {
|
||||
ma.Mu.RLock()
|
||||
defer ma.Mu.RUnlock()
|
||||
return ma.Ar
|
||||
}
|
648
cmd/cfyne/main.go
Normal file
648
cmd/cfyne/main.go
Normal file
|
@ -0,0 +1,648 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
"net"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"fyne.io/fyne/v2"
|
||||
"fyne.io/fyne/v2/app"
|
||||
"fyne.io/fyne/v2/container"
|
||||
"fyne.io/fyne/v2/driver/desktop"
|
||||
"fyne.io/fyne/v2/layout"
|
||||
"fyne.io/fyne/v2/theme"
|
||||
"fyne.io/fyne/v2/widget"
|
||||
|
||||
com "git.qowevisa.me/Qowevisa/gotell/communication"
|
||||
"git.qowevisa.me/Qowevisa/gotell/env"
|
||||
"git.qowevisa.me/Qowevisa/gotell/extfyne/widgets"
|
||||
)
|
||||
|
||||
func updateTime(clock *widget.Label) {
|
||||
formatted := time.Now().Format("Time: 03:04:05")
|
||||
clock.SetText(formatted)
|
||||
}
|
||||
|
||||
var globalApp *MutableApplication
|
||||
var globalCfg *FyneConfig
|
||||
|
||||
var (
|
||||
ecdhKeyReceived = false
|
||||
ecdhKeySent = false
|
||||
)
|
||||
|
||||
var (
|
||||
globalClipboardChannel = make(chan string)
|
||||
)
|
||||
|
||||
func main() {
|
||||
tlepCenter.Init()
|
||||
userCenter.Init()
|
||||
loadingFileName := env.ServerFullchainFileName
|
||||
cert, err := os.ReadFile(loadingFileName)
|
||||
if err != nil {
|
||||
log.Fatalf("client: load root cert: %s", err)
|
||||
}
|
||||
log.Printf("Certificate %s loaded successfully!\n", loadingFileName)
|
||||
//
|
||||
roots := x509.NewCertPool()
|
||||
if ok := roots.AppendCertsFromPEM(cert); !ok {
|
||||
log.Fatalf("client: failed to parse root certificate")
|
||||
}
|
||||
|
||||
config := &tls.Config{
|
||||
RootCAs: roots,
|
||||
}
|
||||
host := "chat.qowevisa.click"
|
||||
port := 3232
|
||||
service := fmt.Sprintf("%s:%d", host, port)
|
||||
log.Printf("client: connecting to %s", service)
|
||||
conn, err := tls.Dial("tcp", service, config)
|
||||
if err != nil {
|
||||
log.Fatalf("client: dial: %s", err)
|
||||
}
|
||||
defer conn.Close()
|
||||
log.Printf("client: connected to %s", service)
|
||||
//
|
||||
|
||||
a := app.New()
|
||||
w := a.NewWindow("gotell-fyne")
|
||||
// w.Resize(fyne.NewSize(640, 400))
|
||||
|
||||
// dispatch clipboardChannel
|
||||
go func(w fyne.Window) {
|
||||
for val := range globalClipboardChannel {
|
||||
w.Clipboard().SetContent(val)
|
||||
}
|
||||
}(w)
|
||||
|
||||
clock := widget.NewLabel("")
|
||||
go func() {
|
||||
for range time.Tick(time.Second) {
|
||||
updateTime(clock)
|
||||
}
|
||||
}()
|
||||
|
||||
btn := widget.NewButtonWithIcon("testBtn", theme.AccountIcon(), func() {
|
||||
fmt.Println("I'm pressed!")
|
||||
})
|
||||
|
||||
mainContainer := container.New(layout.NewVBoxLayout(), clock, btn)
|
||||
|
||||
w.SetContent(mainContainer)
|
||||
// w.SetContent(widget.NewLabel("Hello World!"))
|
||||
// w2 := a.NewWindow("Larger")
|
||||
// w2.SetContent(widget.NewLabel("More content"))
|
||||
// w2.Resize(fyne.NewSize(100, 100))
|
||||
// w2.Show()
|
||||
intercomFromServer := make(chan *com.Message, 16)
|
||||
intercomToServer := make(chan *com.Message, 16)
|
||||
actionsChannel := make(chan int)
|
||||
cfg := FyneConfig{
|
||||
App: a,
|
||||
Window: w,
|
||||
}
|
||||
globalCfg = &cfg
|
||||
|
||||
go readFromServer(conn, intercomFromServer)
|
||||
go analyzeMessages(intercomFromServer, actionsChannel)
|
||||
go actOnActions(cfg, actionsChannel, intercomToServer)
|
||||
go readFromIntercom(intercomToServer, conn)
|
||||
w.ShowAndRun()
|
||||
}
|
||||
|
||||
var r com.RegisteredUser
|
||||
var tmpLink *com.Link
|
||||
var tmpNick string
|
||||
|
||||
func readFromServer(conn net.Conn, intercom chan *com.Message) {
|
||||
buf := make([]byte, 70000)
|
||||
for {
|
||||
err := conn.SetDeadline(time.Now().Add(1 * time.Minute))
|
||||
if err != nil {
|
||||
log.Printf("ERROR: conn.SetDeadline: %v", err)
|
||||
continue
|
||||
}
|
||||
n, err := conn.Read(buf)
|
||||
if err != nil {
|
||||
log.Printf("ERROR: client: read: %s", err)
|
||||
if errors.Is(err, net.ErrClosed) {
|
||||
log.Printf("caught ErrClosed!")
|
||||
}
|
||||
if netErr, ok := err.(net.Error); ok && netErr.Timeout() {
|
||||
log.Println("caught! Read timeout occurred")
|
||||
continue
|
||||
}
|
||||
return
|
||||
}
|
||||
msg, err := com.Decode(buf[:n])
|
||||
if err != nil {
|
||||
log.Printf("ERROR: %#v\n", err)
|
||||
continue
|
||||
}
|
||||
if msg == nil {
|
||||
continue
|
||||
}
|
||||
log.Printf("client: readServer: received message from server: %v", *msg)
|
||||
switch msg.ID {
|
||||
case com.ID_SERVER_APPROVE_CLIENT_NICKNAME:
|
||||
newID := binary.BigEndian.Uint16(msg.Data)
|
||||
msg.FromID = newID
|
||||
msg.Data = []byte{}
|
||||
r.ID = newID
|
||||
if tmpNick != "" {
|
||||
r.Name = tmpNick
|
||||
}
|
||||
r.IsRegistered = true
|
||||
case com.ID_SERVER_APPROVE_CLIENT_LINK:
|
||||
if tmpLink == nil {
|
||||
continue
|
||||
}
|
||||
msg.ToID = tmpLink.UseCount
|
||||
msg.Data = tmpLink.Data
|
||||
// Crypto stuff
|
||||
case com.ID_CLIENT_SEND_CLIENT_ECDH_PUBKEY:
|
||||
t, err := tlepCenter.GetTLEP(msg.FromID)
|
||||
if err != nil {
|
||||
log.Printf("ERROR: tlep: GetTLEP: %v\n", err)
|
||||
continue
|
||||
}
|
||||
err = t.ECDHApplyOtherKeyBytes(msg.Data)
|
||||
if err != nil {
|
||||
log.Printf("ERROR: tlep: ECDHApplyOtherKeyBytes: %v\n", err)
|
||||
continue
|
||||
}
|
||||
fromName, err := userCenter.GetName(msg.FromID)
|
||||
if err != nil {
|
||||
log.Printf("ERROR: userCenter: GetName: %v\n", err)
|
||||
} else {
|
||||
msg.Data = []byte(fromName)
|
||||
}
|
||||
case com.ID_CLIENT_SEND_CLIENT_CBES_SPECS:
|
||||
t, err := tlepCenter.GetTLEP(msg.FromID)
|
||||
if err != nil {
|
||||
log.Printf("ERROR: tlep: GetTLEP: %v\n", err)
|
||||
continue
|
||||
}
|
||||
cbes, err := t.DecryptMessageEA(msg.Data)
|
||||
if err != nil {
|
||||
log.Printf("ERROR: tlep: DecryptMessageEA: %v\n", err)
|
||||
continue
|
||||
}
|
||||
err = t.CBESSetFromBytes(cbes)
|
||||
if err != nil {
|
||||
log.Printf("ERROR: tlep: CBESSetFromBytes: %v\n", err)
|
||||
continue
|
||||
}
|
||||
fromName, err := userCenter.GetName(msg.FromID)
|
||||
if err != nil {
|
||||
log.Printf("ERROR: userCenter: GetName: %v\n", err)
|
||||
} else {
|
||||
msg.Data = []byte(fromName)
|
||||
}
|
||||
// message
|
||||
case com.ID_CLIENT_SEND_CLIENT_MESSAGE:
|
||||
t, err := tlepCenter.GetTLEP(msg.FromID)
|
||||
if err != nil {
|
||||
log.Printf("ERROR: tlep: GetTLEP: %v\n", err)
|
||||
continue
|
||||
}
|
||||
decrypedMsg, err := t.DecryptMessageAtMax(msg.Data)
|
||||
if err != nil {
|
||||
log.Printf("ERROR: tlep: DecryptMessageAtMax: %v\n", err)
|
||||
continue
|
||||
}
|
||||
msg.Data = decrypedMsg
|
||||
// switch
|
||||
}
|
||||
// user stuff
|
||||
switch msg.ID {
|
||||
case com.ID_CLIENT_ASK_CLIENT_HANDSHAKE,
|
||||
com.ID_CLIENT_APPROVE_CLIENT_HANDSHAKE:
|
||||
userCenter.AddUser(string(msg.Data), msg.FromID)
|
||||
}
|
||||
log.Printf("client: readServer: sending message to websocket: %v", *msg)
|
||||
intercom <- msg
|
||||
}
|
||||
}
|
||||
|
||||
func analyzeMessages(intercomFromServer chan *com.Message, actionsChannel chan int) {
|
||||
for msg := range intercomFromServer {
|
||||
if msg == nil {
|
||||
log.Printf("ERROR: msg is nil")
|
||||
continue
|
||||
}
|
||||
log.Printf("Handling %v from server", *msg)
|
||||
switch msg.ID {
|
||||
case com.ID_SERVER_ASK_CLIENT_NICKNAME:
|
||||
actionsChannel <- ACTION_SET_SCENE_NICKNAME
|
||||
case com.ID_SERVER_APPROVE_CLIENT_NICKNAME:
|
||||
actionsChannel <- ACTION_SET_SCENE_MAIN
|
||||
case com.ID_SERVER_DECLINE_CLIENT_NICKNAME:
|
||||
// TODO
|
||||
// Link stuff
|
||||
case com.ID_SERVER_APPROVE_CLIENT_LINK:
|
||||
globalApp.ArrayBundle.LinksMuAr.Add(*tmpLink)
|
||||
globalApp.Tabs.LinkTab.Content.Refresh()
|
||||
case com.ID_SERVER_SEND_CLIENT_ANOTHER_ID:
|
||||
selTab := globalApp.Tabs.AppTabs.Selected()
|
||||
id := msg.ToID
|
||||
userStr := getStdUserName(id, string(msg.Data))
|
||||
globalApp.Widgets.UsersSelect.Options = append(globalApp.Widgets.UsersSelect.Options, userStr)
|
||||
globalApp.Tabs.ConnsNoty++
|
||||
globalApp.ArrayBundle.UsersOpts[userStr] = &UserOptions{
|
||||
Status: USER_STATUS_VISIBLE,
|
||||
ToID: id,
|
||||
}
|
||||
_, exists := globalApp.ArrayBundle.UserShortcuts[id]
|
||||
if !exists {
|
||||
globalApp.ArrayBundle.UserShortcuts[id] = userStr
|
||||
globalApp.ArrayBundle.UserShortcutsRev[userStr] = id
|
||||
}
|
||||
if selTab != globalApp.Tabs.ConnectionTab {
|
||||
updateTabsBasedOnNotyVals(&globalApp.Tabs)
|
||||
}
|
||||
actionsChannel <- ACTION_UPDATE_USER_OPTS_CONTS
|
||||
case com.ID_CLIENT_ASK_CLIENT_HANDSHAKE:
|
||||
selTab := globalApp.Tabs.AppTabs.Selected()
|
||||
id := msg.FromID
|
||||
userStr := getStdUserName(id, string(msg.Data))
|
||||
globalApp.Widgets.UsersSelect.Options = append(globalApp.Widgets.UsersSelect.Options, userStr)
|
||||
globalApp.Tabs.ConnsNoty++
|
||||
globalApp.ArrayBundle.UsersOpts[userStr] = &UserOptions{
|
||||
Status: USER_STATUS_HANDSHAKE_INIT,
|
||||
ToID: id,
|
||||
}
|
||||
_, exists := globalApp.ArrayBundle.UserShortcuts[id]
|
||||
if !exists {
|
||||
globalApp.ArrayBundle.UserShortcuts[id] = userStr
|
||||
globalApp.ArrayBundle.UserShortcutsRev[userStr] = id
|
||||
}
|
||||
if selTab != globalApp.Tabs.ConnectionTab {
|
||||
updateTabsBasedOnNotyVals(&globalApp.Tabs)
|
||||
}
|
||||
actionsChannel <- ACTION_UPDATE_USER_OPTS_CONTS
|
||||
case com.ID_CLIENT_APPROVE_CLIENT_HANDSHAKE:
|
||||
id := msg.FromID
|
||||
userStr := getStdUserName(id, string(msg.Data))
|
||||
var shortcut string
|
||||
val, exists := globalApp.ArrayBundle.UserShortcuts[id]
|
||||
if !exists {
|
||||
globalApp.ArrayBundle.UserShortcuts[id] = userStr
|
||||
globalApp.ArrayBundle.UserShortcutsRev[userStr] = id
|
||||
shortcut = userStr
|
||||
} else {
|
||||
shortcut = val
|
||||
}
|
||||
u, exists := globalApp.ArrayBundle.UsersOpts[shortcut]
|
||||
if !exists {
|
||||
log.Printf("WARNING!!: UserOpts[%s] NOT exists!", shortcut)
|
||||
continue
|
||||
}
|
||||
u.Status = USER_STATUS_HANDSHAKE_ACCEPTED
|
||||
actionsChannel <- ACTION_UPDATE_USER_OPTS_CONTS
|
||||
case com.ID_CLIENT_SEND_CLIENT_ECDH_PUBKEY:
|
||||
id := msg.FromID
|
||||
if ecdhKeySent {
|
||||
val, exists := globalApp.ArrayBundle.UserShortcuts[id]
|
||||
if !exists {
|
||||
log.Printf("WARNING!!: UserShortcuts[%d] NOT exists!", id)
|
||||
continue
|
||||
}
|
||||
u, exists := globalApp.ArrayBundle.UsersOpts[val]
|
||||
if !exists {
|
||||
log.Printf("WARNING!!: UserOpts[%s] NOT exists!", val)
|
||||
continue
|
||||
}
|
||||
u.Status = USER_STATUS_ECDH_ESTABLISHED
|
||||
actionsChannel <- ACTION_UPDATE_USER_OPTS_CONTS
|
||||
}
|
||||
ecdhKeyReceived = true
|
||||
case com.ID_CLIENT_SEND_CLIENT_CBES_SPECS:
|
||||
id := msg.FromID
|
||||
val, exists := globalApp.ArrayBundle.UserShortcuts[id]
|
||||
if !exists {
|
||||
log.Printf("WARNING!!: UserShortcuts[%d] NOT exists!", id)
|
||||
continue
|
||||
}
|
||||
u, exists := globalApp.ArrayBundle.UsersOpts[val]
|
||||
if !exists {
|
||||
log.Printf("WARNING!!: UserOpts[%s] NOT exists!", val)
|
||||
continue
|
||||
}
|
||||
u.Status = USER_STATUS_ECDH_CBES_ESTABLISHED
|
||||
actionsChannel <- ACTION_UPDATE_USER_OPTS_CONTS
|
||||
//
|
||||
log.Printf("Checkin Messages tab")
|
||||
userStr := getStdUserName(id, string(msg.Data))
|
||||
var shortcut string
|
||||
if !exists {
|
||||
globalApp.ArrayBundle.UserShortcuts[id] = userStr
|
||||
shortcut = userStr
|
||||
} else {
|
||||
shortcut = val
|
||||
}
|
||||
//
|
||||
haveUser := false
|
||||
for _, v := range globalApp.Widgets.MessagesSelect.Options {
|
||||
if v == shortcut {
|
||||
haveUser = true
|
||||
break
|
||||
}
|
||||
}
|
||||
log.Printf("MessagesSelect.Options1 are %v\n", globalApp.Widgets.MessagesSelect.Options)
|
||||
log.Printf("have user is : %t\n", haveUser)
|
||||
if !haveUser {
|
||||
log.Printf("MessagesSelect.Options1.5 shortcut is '%s'\n", shortcut)
|
||||
// LOL wtf
|
||||
// globalApp.Widgets.MessagesSelect.Options = append(globalApp.Widgets.UsersSelect.Options, shortcut)
|
||||
globalApp.Widgets.MessagesSelect.Options = append(globalApp.Widgets.MessagesSelect.Options, shortcut)
|
||||
log.Printf("MessagesSelect.Options2 are %v\n", globalApp.Widgets.MessagesSelect.Options)
|
||||
globalApp.Tabs.UsersNoty++
|
||||
globalApp.Widgets.MessagesSelect.Refresh()
|
||||
updateTabsBasedOnNotyVals(&globalApp.Tabs)
|
||||
}
|
||||
case com.ID_CLIENT_SEND_CLIENT_MESSAGE:
|
||||
id := msg.FromID
|
||||
shortcut, exists := globalApp.ArrayBundle.UserShortcuts[id]
|
||||
if !exists {
|
||||
log.Printf("WARNING: UserShortcuts[%d] NOT exists!", id)
|
||||
continue
|
||||
}
|
||||
msgs, exists := globalApp.ArrayBundle.Messages[shortcut]
|
||||
mBoardMsg := widgets.MBoardMessage{
|
||||
LeftAlign: true,
|
||||
Data: widget.NewLabel(string(msg.Data)),
|
||||
}
|
||||
if !exists {
|
||||
tmp := CreateMutexArray[widgets.MBoardMessage]()
|
||||
tmp.Add(mBoardMsg)
|
||||
globalApp.ArrayBundle.Messages[shortcut] = &tmp
|
||||
globalApp.Widgets.MBoardCaretacker.Refresh()
|
||||
globalApp.Tabs.UsersTab.Content.Refresh()
|
||||
} else {
|
||||
msgs.Add(mBoardMsg)
|
||||
globalApp.Widgets.MBoardCaretacker.Refresh()
|
||||
globalApp.Tabs.UsersTab.Content.Refresh()
|
||||
}
|
||||
haveUser := false
|
||||
for _, v := range globalApp.Widgets.MessagesSelect.Options {
|
||||
if v == shortcut {
|
||||
haveUser = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !haveUser {
|
||||
globalApp.Widgets.MessagesSelect.Options = append(globalApp.Widgets.MessagesSelect.Options, shortcut)
|
||||
globalApp.Tabs.UsersNoty++
|
||||
updateTabsBasedOnNotyVals(&globalApp.Tabs)
|
||||
globalApp.Widgets.MessagesSelect.Refresh()
|
||||
}
|
||||
//
|
||||
mBoard, exists := globalApp.Widgets.MBoardMap[shortcut]
|
||||
if exists {
|
||||
mBoard.Add(mBoardMsg)
|
||||
}
|
||||
// TODO
|
||||
default:
|
||||
log.Printf("Can not handle msg with id %d", msg.ID)
|
||||
log.Printf("Msg is different : %v", *msg)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func actOnActions(cfg FyneConfig, actionsChannel chan int, intercomToServer chan *com.Message) {
|
||||
for action := range actionsChannel {
|
||||
log.Printf("Receive action %d", action)
|
||||
switch action {
|
||||
case ACTION_SET_SCENE_NICKNAME:
|
||||
// cfg.Window.Content()
|
||||
scene := GetNicknameScene(intercomToServer)
|
||||
cfg.Window.Resize(fyne.NewSize(640, 400))
|
||||
cfg.Window.SetContent(scene)
|
||||
case ACTION_SET_SCENE_MAIN:
|
||||
scene, app := GetMainScene(intercomToServer, MainSceneConfig{
|
||||
UserNickcname: tmpNick,
|
||||
UserNameSet: true,
|
||||
UserId: r.ID,
|
||||
UserIdSet: true,
|
||||
})
|
||||
globalApp = app
|
||||
globalApp.App.App = cfg.App
|
||||
globalApp.App.Window = cfg.Window
|
||||
// shortcuts
|
||||
ctrl1 := &desktop.CustomShortcut{KeyName: fyne.Key1, Modifier: fyne.KeyModifierControl}
|
||||
ctrl2 := &desktop.CustomShortcut{KeyName: fyne.Key2, Modifier: fyne.KeyModifierControl}
|
||||
ctrl3 := &desktop.CustomShortcut{KeyName: fyne.Key3, Modifier: fyne.KeyModifierControl}
|
||||
cfg.Window.Canvas().AddShortcut(ctrl1, func(shortcut fyne.Shortcut) {
|
||||
app.Tabs.AppTabs.Select(app.Tabs.LinkTab)
|
||||
})
|
||||
cfg.Window.Canvas().AddShortcut(ctrl2, func(shortcut fyne.Shortcut) {
|
||||
app.Tabs.AppTabs.Select(app.Tabs.ConnectionTab)
|
||||
})
|
||||
cfg.Window.Canvas().AddShortcut(ctrl3, func(shortcut fyne.Shortcut) {
|
||||
app.Tabs.AppTabs.Select(app.Tabs.UsersTab)
|
||||
})
|
||||
// cfg.Window.Resize(fyne.NewSize(640, 400))
|
||||
cfg.Window.SetContent(scene)
|
||||
// ACTION_UPDATE_USER_OPTS_CONTS
|
||||
case ACTION_UPDATE_USER_OPTS_CONTS:
|
||||
for _, u := range globalApp.ArrayBundle.UsersOpts {
|
||||
switch u.Status {
|
||||
case USER_STATUS_VISIBLE:
|
||||
btn := widget.NewButton("Init Handhake", func() {})
|
||||
btn.OnTapped = func() {
|
||||
intercomToServer <- &com.Message{
|
||||
ID: com.ID_CLIENT_ASK_CLIENT_HANDSHAKE,
|
||||
ToID: u.ToID,
|
||||
}
|
||||
btn.Hide()
|
||||
}
|
||||
u.OptsContainer = container.NewGridWithRows(1, btn)
|
||||
cTaker := globalApp.Widgets.UserOptsCaretaker
|
||||
cTaker.RemoveAll()
|
||||
cTaker.Add(u.OptsContainer)
|
||||
case USER_STATUS_HANDSHAKE_INIT:
|
||||
btn := widget.NewButton("Accept Handhake", func() {})
|
||||
btn.OnTapped = func() {
|
||||
intercomToServer <- &com.Message{
|
||||
ID: com.ID_CLIENT_APPROVE_CLIENT_HANDSHAKE,
|
||||
ToID: u.ToID,
|
||||
}
|
||||
btn.Hide()
|
||||
u.Status = USER_STATUS_HANDSHAKE_ACCEPTED
|
||||
actionsChannel <- ACTION_UPDATE_USER_OPTS_CONTS
|
||||
}
|
||||
u.OptsContainer = container.NewGridWithRows(1, btn)
|
||||
cTaker := globalApp.Widgets.UserOptsCaretaker
|
||||
cTaker.RemoveAll()
|
||||
cTaker.Add(u.OptsContainer)
|
||||
case USER_STATUS_HANDSHAKE_ACCEPTED:
|
||||
btn := widget.NewButton("Send ECDH PubKey", func() {})
|
||||
btn.OnTapped = func() {
|
||||
intercomToServer <- &com.Message{
|
||||
ID: com.ID_CLIENT_SEND_CLIENT_ECDH_PUBKEY,
|
||||
ToID: u.ToID,
|
||||
}
|
||||
btn.Hide()
|
||||
if ecdhKeyReceived {
|
||||
u.Status = USER_STATUS_ECDH_ESTABLISHED
|
||||
actionsChannel <- ACTION_UPDATE_USER_OPTS_CONTS
|
||||
}
|
||||
ecdhKeySent = true
|
||||
}
|
||||
u.OptsContainer = container.NewGridWithRows(1, btn)
|
||||
cTaker := globalApp.Widgets.UserOptsCaretaker
|
||||
cTaker.RemoveAll()
|
||||
cTaker.Add(u.OptsContainer)
|
||||
case USER_STATUS_ECDH_ESTABLISHED:
|
||||
btn := widget.NewButton("Send CBES Specs", func() {})
|
||||
btn.OnTapped = func() {
|
||||
intercomToServer <- &com.Message{
|
||||
ID: com.ID_CLIENT_SEND_CLIENT_CBES_SPECS,
|
||||
ToID: u.ToID,
|
||||
}
|
||||
btn.Hide()
|
||||
}
|
||||
u.OptsContainer = container.NewGridWithRows(1, btn)
|
||||
cTaker := globalApp.Widgets.UserOptsCaretaker
|
||||
cTaker.RemoveAll()
|
||||
cTaker.Add(u.OptsContainer)
|
||||
case USER_STATUS_ECDH_CBES_ESTABLISHED:
|
||||
btn := widget.NewButton("TBC", func() {})
|
||||
btn.OnTapped = func() {
|
||||
log.Println("TODO:: 1001")
|
||||
}
|
||||
u.OptsContainer = container.NewGridWithRows(1, btn)
|
||||
cTaker := globalApp.Widgets.UserOptsCaretaker
|
||||
cTaker.RemoveAll()
|
||||
cTaker.Add(u.OptsContainer)
|
||||
default:
|
||||
}
|
||||
}
|
||||
// globalApp.Tabs.ConnectionTab.Content.Refresh()
|
||||
// ACTION_UPDATE_USER_OPTS_CONTS
|
||||
default:
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func readFromIntercom(intercom chan *com.Message, conn net.Conn) {
|
||||
for msg := range intercom {
|
||||
log.Printf("client: received message from Intercom: %v", msg)
|
||||
msg.Version = com.V1
|
||||
switch msg.ID {
|
||||
case com.ID_CLIENT_SEND_SERVER_NICKNAME:
|
||||
tmpNick = string(msg.Data)
|
||||
case com.ID_CLIENT_SEND_SERVER_LINK:
|
||||
if !r.IsRegistered {
|
||||
continue
|
||||
}
|
||||
l, err := r.GenerateLink(msg.ToID)
|
||||
if err != nil {
|
||||
log.Printf("Error: link: %v", err)
|
||||
continue
|
||||
}
|
||||
tmpLink = &l
|
||||
answ, err := com.ClientSendServerLink(r.ID, l)
|
||||
if err != nil {
|
||||
log.Printf("Error: com: %v", err)
|
||||
continue
|
||||
}
|
||||
log.Printf("client: readWS: sending data to server: %v", answ)
|
||||
conn.Write(answ)
|
||||
continue
|
||||
case com.ID_CLIENT_ASK_CLIENT_HANDSHAKE,
|
||||
com.ID_CLIENT_APPROVE_CLIENT_HANDSHAKE,
|
||||
com.ID_CLIENT_DECLINE_CLIENT_HANDSHAKE,
|
||||
com.ID_CLIENT_SEND_CLIENT_ECDH_PUBKEY,
|
||||
com.ID_CLIENT_SEND_CLIENT_CBES_SPECS,
|
||||
com.ID_CLIENT_SEND_CLIENT_MKLG_FINGERPRINT,
|
||||
com.ID_CLIENT_DECLINE_CLIENT_MKLG_FINGERPRINT,
|
||||
com.ID_CLIENT_SEND_CLIENT_MESSAGE:
|
||||
if !r.IsRegistered {
|
||||
continue
|
||||
}
|
||||
msg.FromID = r.ID
|
||||
// switch
|
||||
}
|
||||
// user stuff
|
||||
switch msg.ID {
|
||||
case com.ID_CLIENT_ASK_CLIENT_HANDSHAKE,
|
||||
com.ID_CLIENT_APPROVE_CLIENT_HANDSHAKE:
|
||||
if r.IsRegistered {
|
||||
msg.Data = []byte(r.Name)
|
||||
}
|
||||
}
|
||||
// Crypto stuff
|
||||
switch msg.ID {
|
||||
case com.ID_CLIENT_ASK_CLIENT_HANDSHAKE,
|
||||
com.ID_CLIENT_APPROVE_CLIENT_HANDSHAKE:
|
||||
err := tlepCenter.AddTLEP(msg.ToID, fmt.Sprintf("%s-%d", r.Name, msg.ToID))
|
||||
if err != nil {
|
||||
log.Printf("ERROR: tlepCenter.AddUser: %v\n", err)
|
||||
}
|
||||
case com.ID_CLIENT_SEND_CLIENT_ECDH_PUBKEY:
|
||||
t, err := tlepCenter.GetTLEP(msg.ToID)
|
||||
if err != nil {
|
||||
log.Printf("ERROR: tlep: GetTLEP: %v\n", err)
|
||||
continue
|
||||
}
|
||||
key, err := t.ECDHGetPublicKey()
|
||||
if err != nil {
|
||||
log.Printf("ERROR: tlep: ECDHGetPublicKey: %v\n", err)
|
||||
continue
|
||||
}
|
||||
msg.Data = key
|
||||
case com.ID_CLIENT_SEND_CLIENT_CBES_SPECS:
|
||||
t, err := tlepCenter.GetTLEP(msg.ToID)
|
||||
if err != nil {
|
||||
log.Printf("ERROR: tlep: GetTLEP: %v\n", err)
|
||||
continue
|
||||
}
|
||||
err = t.CBESInitRandom()
|
||||
if err != nil {
|
||||
log.Printf("ERROR: tlep: CBESInitRandom: %v\n", err)
|
||||
continue
|
||||
}
|
||||
cbes, err := t.CBESGetBytes()
|
||||
if err != nil {
|
||||
log.Printf("ERROR: tlep: ECDHGetPublicKey: %v\n", err)
|
||||
continue
|
||||
}
|
||||
cbesEAEncr, err := t.EncryptMessageEA(cbes)
|
||||
if err != nil {
|
||||
log.Printf("ERROR: tlep: EncryptMessageEA: %v\n", err)
|
||||
continue
|
||||
}
|
||||
msg.Data = cbesEAEncr
|
||||
// message
|
||||
case com.ID_CLIENT_SEND_CLIENT_MESSAGE:
|
||||
t, err := tlepCenter.GetTLEP(msg.ToID)
|
||||
if err != nil {
|
||||
log.Printf("ERROR: tlep: GetTLEP: %v\n", err)
|
||||
continue
|
||||
}
|
||||
encrypedMsg, err := t.EncryptMessageAtMax(msg.Data)
|
||||
if err != nil {
|
||||
log.Printf("ERROR: tlep: EncryptMessageAtMax: %v\n", err)
|
||||
continue
|
||||
}
|
||||
msg.Data = encrypedMsg
|
||||
// switch
|
||||
}
|
||||
encodedMsg, err := msg.Bytes()
|
||||
if err != nil {
|
||||
log.Printf("Encoding error: %s", err)
|
||||
continue
|
||||
}
|
||||
log.Printf("client: readWS: sending data to server: %v", encodedMsg)
|
||||
conn.Write(encodedMsg)
|
||||
}
|
||||
}
|
377
cmd/cfyne/scenes.go
Normal file
377
cmd/cfyne/scenes.go
Normal file
|
@ -0,0 +1,377 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
"strconv"
|
||||
|
||||
"fyne.io/fyne/v2"
|
||||
"fyne.io/fyne/v2/container"
|
||||
"fyne.io/fyne/v2/layout"
|
||||
"fyne.io/fyne/v2/theme"
|
||||
|
||||
// "fyne.io/fyne/v2/theme"
|
||||
"fyne.io/fyne/v2/widget"
|
||||
com "git.qowevisa.me/Qowevisa/gotell/communication"
|
||||
"git.qowevisa.me/Qowevisa/gotell/extfyne/layouts"
|
||||
"git.qowevisa.me/Qowevisa/gotell/extfyne/widgets"
|
||||
)
|
||||
|
||||
func GetNicknameScene(intercom chan *com.Message) *fyne.Container {
|
||||
// button := widget.NewButtonWithIcon(
|
||||
// "Send",
|
||||
// theme.ConfirmIcon(),
|
||||
// getSendMessageFuncToIntercom(intercom, com.ID_CLIENT_SEND_SERVER_NICKNAME, []byte("test")))
|
||||
entry := widget.NewEntry()
|
||||
entry.SetPlaceHolder("Enter Nickname:")
|
||||
btn := widget.NewButtonWithIcon("Send", theme.MailSendIcon(), func() {
|
||||
log.Println("Nickname submitted:", entry.Text)
|
||||
intercom <- &com.Message{
|
||||
ID: com.ID_CLIENT_SEND_SERVER_NICKNAME,
|
||||
Data: []byte(entry.Text),
|
||||
}
|
||||
})
|
||||
contentInner := container.New(layout.NewVBoxLayout(), entry, btn)
|
||||
return container.NewGridWithRows(3,
|
||||
layout.NewSpacer(),
|
||||
container.NewGridWithColumns(3,
|
||||
layout.NewSpacer(),
|
||||
contentInner,
|
||||
layout.NewSpacer(),
|
||||
),
|
||||
layout.NewSpacer(),
|
||||
)
|
||||
}
|
||||
|
||||
func GetMainScene(intercom chan *com.Message, cfg MainSceneConfig) (*fyne.Container, *MutableApplication) {
|
||||
headerWidget := widget.NewLabel(fmt.Sprintf("Hello, %s! Your ID: %d", cfg.UserNickcname, cfg.UserId))
|
||||
header := container.NewGridWithColumns(3,
|
||||
layout.NewSpacer(),
|
||||
headerWidget,
|
||||
layout.NewSpacer(),
|
||||
)
|
||||
|
||||
linksSS, linksArr := GetLinksSubScene(intercom, header)
|
||||
linksTab := container.NewTabItemWithIcon("Links", theme.MailComposeIcon(), linksSS)
|
||||
conSS, conBundle, conWidgets := GetConnectionsSubScene(intercom, header)
|
||||
connsTab := container.NewTabItemWithIcon("Connections", theme.ComputerIcon(), conSS)
|
||||
userSS, userBundle, userWidgets := GetUsersSubScene(intercom, header, conBundle.UserShortcutsRev)
|
||||
usersTab := container.NewTabItemWithIcon("Users", theme.AccountIcon(), userSS)
|
||||
tabs := container.NewAppTabs(
|
||||
linksTab,
|
||||
connsTab,
|
||||
usersTab,
|
||||
)
|
||||
tabs.SetTabLocation(container.TabLocationLeading)
|
||||
|
||||
return container.NewGridWithColumns(1,
|
||||
tabs),
|
||||
&MutableApplication{
|
||||
Tabs: MutableStructAboutTabs{
|
||||
AppTabs: tabs,
|
||||
LinkTab: linksTab,
|
||||
LinksBT: "Links",
|
||||
LinksNoty: 0,
|
||||
ConnectionTab: connsTab,
|
||||
ConnsBT: "Connections",
|
||||
ConnsNoty: 0,
|
||||
UsersTab: usersTab,
|
||||
UsersBT: "Users",
|
||||
UsersNoty: 0,
|
||||
},
|
||||
ArrayBundle: BundleOfMutexArrays{
|
||||
LinksMuAr: linksArr,
|
||||
UsersMuAr: conBundle.UsersMuAr,
|
||||
UsersOpts: conBundle.UsersOpts,
|
||||
UserShortcuts: conBundle.UserShortcuts,
|
||||
UserShortcutsRev: conBundle.UserShortcutsRev,
|
||||
Messages: userBundle.Messages,
|
||||
},
|
||||
Widgets: MutableStructAboutWidgets{
|
||||
UsersSelect: conWidgets.UsersSelect,
|
||||
UserOptsCaretaker: conWidgets.UserOptsCaretaker,
|
||||
MessagesSelect: userWidgets.MessagesSelect,
|
||||
MBoardCaretacker: userWidgets.MBoardCaretacker,
|
||||
MsgButton: userWidgets.MsgButton,
|
||||
MBoardMap: userWidgets.MBoardMap,
|
||||
},
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func GetLinksSubScene(intercom chan *com.Message, header *fyne.Container) (*fyne.Container, *MutexLinksArray) {
|
||||
entry := widget.NewEntry()
|
||||
entry.SetPlaceHolder("Count:")
|
||||
entry.Validator = func(s string) error {
|
||||
val, err := strconv.ParseUint(s, 10, 16)
|
||||
if err == nil && val == 0 {
|
||||
return errors.New("Use count can't be 0")
|
||||
}
|
||||
return err
|
||||
}
|
||||
btn := widget.NewButtonWithIcon("Generate", theme.MailSendIcon(), func() {
|
||||
count, err := strconv.ParseUint(entry.Text, 10, 16)
|
||||
if err != nil || count == 0 {
|
||||
log.Printf("dafuq: GetLinksSubScene: %v ; %d\n", err, count)
|
||||
return
|
||||
}
|
||||
intercom <- &com.Message{
|
||||
ID: com.ID_CLIENT_SEND_SERVER_LINK,
|
||||
ToID: uint16(count),
|
||||
}
|
||||
})
|
||||
entry.SetOnValidationChanged(func(err error) {
|
||||
if err != nil {
|
||||
btn.Hide()
|
||||
} else {
|
||||
if btn.Hidden {
|
||||
btn.Show()
|
||||
}
|
||||
}
|
||||
})
|
||||
contentInner := container.NewGridWithColumns(2, entry, btn)
|
||||
// /
|
||||
linksMutAt := CreateMutexLinksArray()
|
||||
linksList := widget.NewList(func() int {
|
||||
return len(linksMutAt.GetArray())
|
||||
}, func() fyne.CanvasObject {
|
||||
return widget.NewLabel("template")
|
||||
}, func(lii widget.ListItemID, co fyne.CanvasObject) {
|
||||
link := linksMutAt.Ar[lii]
|
||||
str := fmt.Sprintf("Count: %d ; %s", link.UseCount, link.Data)
|
||||
co.(*widget.Label).SetText(str)
|
||||
},
|
||||
)
|
||||
linksList.OnSelected = func(id widget.ListItemID) {
|
||||
link := linksMutAt.Ar[id]
|
||||
globalClipboardChannel <- string(link.Data)
|
||||
}
|
||||
// //
|
||||
linksGetEntry := widget.NewEntry()
|
||||
linksGetEntry.SetPlaceHolder("Link:")
|
||||
linksGetEntry.Validator = func(s string) error {
|
||||
validated, err := com.IsThisALinkData(s)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !validated {
|
||||
return errors.New("Link is not validated")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
linksGetBtn := widget.NewButtonWithIcon("Get", theme.MailReplyIcon(), func() {
|
||||
link := linksGetEntry.Text
|
||||
validated, err := com.IsThisALinkData(link)
|
||||
if err != nil {
|
||||
log.Printf("linksGetBtn: Error: %v\n", err)
|
||||
return
|
||||
}
|
||||
if !validated {
|
||||
log.Printf("linksGetBtn: Error: link %v not validated\n", link)
|
||||
return
|
||||
}
|
||||
intercom <- &com.Message{
|
||||
ID: com.ID_CLIENT_ASK_SERVER_LINK,
|
||||
Data: []byte(link),
|
||||
}
|
||||
})
|
||||
linksGetEntry.SetOnValidationChanged(func(err error) {
|
||||
if err != nil {
|
||||
linksGetBtn.Hide()
|
||||
} else {
|
||||
if linksGetBtn.Hidden {
|
||||
linksGetBtn.Show()
|
||||
}
|
||||
}
|
||||
})
|
||||
contentInner2 := container.NewGridWithColumns(2, linksGetEntry, linksGetBtn)
|
||||
// /
|
||||
// //
|
||||
return container.NewGridWithRows(3,
|
||||
header,
|
||||
container.New(
|
||||
layouts.NewVariableGridWithColumns(
|
||||
6, []int{2, 1, 3}),
|
||||
container.NewGridWithRows(3,
|
||||
container.NewGridWithColumns(3,
|
||||
layout.NewSpacer(),
|
||||
widget.NewLabel("Create link:"),
|
||||
layout.NewSpacer()),
|
||||
contentInner,
|
||||
layout.NewSpacer(),
|
||||
),
|
||||
layout.NewSpacer(),
|
||||
linksList,
|
||||
),
|
||||
container.New(
|
||||
layouts.NewVariableGridWithColumns(
|
||||
6, []int{2, 4}),
|
||||
container.NewGridWithRows(3,
|
||||
container.NewGridWithColumns(3,
|
||||
layout.NewSpacer(),
|
||||
widget.NewLabel("Get user from link:"),
|
||||
layout.NewSpacer()),
|
||||
contentInner2,
|
||||
layout.NewSpacer(),
|
||||
),
|
||||
layout.NewSpacer(),
|
||||
),
|
||||
), linksMutAt
|
||||
}
|
||||
|
||||
func GetConnectionsSubScene(intercom chan *com.Message, header *fyne.Container) (*fyne.Container, BundleOfMutexArrays, MutableStructAboutWidgets) {
|
||||
optionsHeaderLabel := widget.NewLabel("Options for user: ")
|
||||
usersMuAr := CreateMutexStringArray()
|
||||
usersOptions := make(map[string]*UserOptions)
|
||||
userShortcuts := make(map[uint16]string)
|
||||
userShortcutsRev := make(map[string]uint16)
|
||||
userOptsCaretaker := container.NewGridWithRows(1)
|
||||
optsContainer := container.NewGridWithRows(2,
|
||||
optionsHeaderLabel,
|
||||
userOptsCaretaker,
|
||||
)
|
||||
userSelect := widget.NewSelect(usersMuAr.Ar, func(s string) {
|
||||
optionsHeaderLabel.SetText(fmt.Sprintf("Options for user: %s", s))
|
||||
uOpts, exists := usersOptions[s]
|
||||
if !exists {
|
||||
log.Printf("GetConnectionsSubScene::1 : TODO!!\n")
|
||||
// TODO
|
||||
return
|
||||
}
|
||||
userOptsCaretaker.RemoveAll()
|
||||
userOptsCaretaker.Add(uOpts.OptsContainer)
|
||||
optsContainer.Refresh()
|
||||
})
|
||||
|
||||
contentInner := container.New(layout.NewVBoxLayout(), userSelect, optsContainer)
|
||||
return container.New(
|
||||
layout.NewVBoxLayout(),
|
||||
header,
|
||||
container.New(
|
||||
layout.NewHBoxLayout(),
|
||||
layout.NewSpacer(),
|
||||
contentInner,
|
||||
layout.NewSpacer(),
|
||||
),
|
||||
), BundleOfMutexArrays{
|
||||
UsersMuAr: usersMuAr,
|
||||
UsersOpts: usersOptions,
|
||||
UserShortcuts: userShortcuts,
|
||||
UserShortcutsRev: userShortcutsRev,
|
||||
}, MutableStructAboutWidgets{
|
||||
UsersSelect: userSelect,
|
||||
UserOptsCaretaker: userOptsCaretaker,
|
||||
}
|
||||
}
|
||||
|
||||
func GetUsersSubScene(intercom chan *com.Message, header *fyne.Container, userShortcutsRev map[string]uint16) (*fyne.Container, BundleOfMutexArrays, MutableStructAboutWidgets) {
|
||||
msgHeader := widget.NewLabel("Messages With User: ")
|
||||
usersMessages := make(map[string]*MutexArray[widgets.MBoardMessage])
|
||||
usersMBoards := make(map[string]*widgets.MessageBoard)
|
||||
msgEntry := widget.NewEntry()
|
||||
msgEntry.SetPlaceHolder("Message...")
|
||||
userMsgSendBtn := widget.NewButtonWithIcon("Send", theme.MailSendIcon(), func() {})
|
||||
mBoardCareTaker := container.NewGridWithRows(1)
|
||||
userMsgsSelect := widget.NewSelect([]string{}, func(s string) {
|
||||
msgHeader.SetText(fmt.Sprintf("Messages With User: %s", s))
|
||||
msgsMuAr, exists := usersMessages[s]
|
||||
if !exists {
|
||||
tmp := CreateMutexArray[widgets.MBoardMessage]()
|
||||
usersMessages[s] = &tmp
|
||||
msgsMuAr = &tmp
|
||||
return
|
||||
}
|
||||
mBoardCareTaker.RemoveAll()
|
||||
mmBoard := widgets.NewMessageBoard(msgsMuAr.Ar)
|
||||
usersMBoards[s] = mmBoard
|
||||
mBoardCareTaker.Add(mmBoard)
|
||||
mBoardCareTaker.Refresh()
|
||||
id, exists := userShortcutsRev[s]
|
||||
if !exists {
|
||||
log.Printf("GetUsersSubScene::2 : TODO!!\n")
|
||||
// TODO
|
||||
return
|
||||
}
|
||||
userMsgSendBtn.Text = fmt.Sprintf("%s", s)
|
||||
userMsgSendBtn.OnTapped = func() {
|
||||
intercom <- &com.Message{
|
||||
ID: com.ID_CLIENT_SEND_CLIENT_MESSAGE,
|
||||
ToID: id,
|
||||
Data: []byte(msgEntry.Text),
|
||||
}
|
||||
msg := widgets.MBoardMessage{
|
||||
LeftAlign: false,
|
||||
Data: widget.NewLabel(msgEntry.Text),
|
||||
}
|
||||
msgsMuAr.Add(msg)
|
||||
mmBoard.Add(msg)
|
||||
msgEntry.Text = ""
|
||||
msgEntry.Refresh()
|
||||
mBoardCareTaker.Refresh()
|
||||
mmBoard.Refresh()
|
||||
}
|
||||
userMsgSendBtn.Refresh()
|
||||
})
|
||||
|
||||
// entryWithButton := container.NewHBox(
|
||||
// layout.NewSpacer(),
|
||||
// container.NewPadded(msgEntry),
|
||||
// userMsgSendBtn,
|
||||
// )
|
||||
entryWithButton := container.New(
|
||||
layouts.NewEntryBtn7030(),
|
||||
msgEntry,
|
||||
userMsgSendBtn,
|
||||
)
|
||||
fs := globalCfg.Window.Canvas().Size()
|
||||
|
||||
scene := container.New(
|
||||
layout.NewVBoxLayout(),
|
||||
header,
|
||||
container.NewGridWithColumns(2,
|
||||
container.New(
|
||||
layout.NewVBoxLayout(),
|
||||
layout.NewSpacer(),
|
||||
container.New(
|
||||
layout.NewHBoxLayout(),
|
||||
userMsgsSelect,
|
||||
msgHeader,
|
||||
),
|
||||
),
|
||||
container.New(
|
||||
layout.NewVBoxLayout(),
|
||||
container.New(
|
||||
layouts.NewFullWidthWithSize(fyne.NewSize(0, fs.Height*0.8)),
|
||||
mBoardCareTaker,
|
||||
),
|
||||
layout.NewSpacer(),
|
||||
entryWithButton,
|
||||
),
|
||||
),
|
||||
)
|
||||
// container.New(
|
||||
// layouts.NewVariableGridWithRows(3, []int{1, 2}),
|
||||
// header,
|
||||
// container.New(
|
||||
// layouts.NewVariableGridWithColumns(4, []int{1, 3}),
|
||||
// container.NewGridWithColumns(3,
|
||||
// layout.NewSpacer(),
|
||||
// container.NewVBox(userMsgsSelect, msgHeader),
|
||||
// layout.NewSpacer()),
|
||||
// container.New(
|
||||
// layouts.NewVariableGridWithRows(6, []int{5, 1}),
|
||||
// mBoardCareTaker,
|
||||
// container.NewHBox(msgEntry, userMsgSendBtn),
|
||||
// ),
|
||||
// ),
|
||||
// )
|
||||
return scene, BundleOfMutexArrays{
|
||||
Messages: usersMessages,
|
||||
}, MutableStructAboutWidgets{
|
||||
MessagesSelect: userMsgsSelect,
|
||||
MBoardCaretacker: mBoardCareTaker,
|
||||
MsgButton: userMsgSendBtn,
|
||||
MBoardMap: usersMBoards,
|
||||
}
|
||||
}
|
66
cmd/cfyne/tleps.go
Normal file
66
cmd/cfyne/tleps.go
Normal file
|
@ -0,0 +1,66 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"log"
|
||||
"sync"
|
||||
|
||||
"git.qowevisa.me/Qowevisa/gotell/gmyerr"
|
||||
"git.qowevisa.me/Qowevisa/gotell/tlep"
|
||||
)
|
||||
|
||||
var (
|
||||
tlepCenter TlepCenter
|
||||
)
|
||||
|
||||
type TlepCenter struct {
|
||||
TLEPs map[uint16]*tlep.TLEP
|
||||
Mu sync.Mutex
|
||||
}
|
||||
|
||||
func (t *TlepCenter) Init() {
|
||||
t.TLEPs = make(map[uint16]*tlep.TLEP)
|
||||
}
|
||||
|
||||
var (
|
||||
ERROR_ALREADY_HAVE = errors.New("Already taken")
|
||||
ERROR_DONT_HAVE = errors.New("Not found")
|
||||
)
|
||||
|
||||
func (t *TlepCenter) AddTLEP(id uint16, name string) error {
|
||||
t.Mu.Lock()
|
||||
defer t.Mu.Unlock()
|
||||
_, alreadyHave := t.TLEPs[id]
|
||||
if alreadyHave {
|
||||
return ERROR_ALREADY_HAVE
|
||||
}
|
||||
val, err := tlep.InitTLEP(name)
|
||||
if err != nil {
|
||||
return gmyerr.WrapPrefix("tlep.InitTLEP", err)
|
||||
}
|
||||
val.Debug = true
|
||||
t.TLEPs[id] = val
|
||||
log.Printf("TLEPs: add %p for %d id\n", val, id)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *TlepCenter) DeleteIfHaveOne(id uint16) {
|
||||
t.Mu.Lock()
|
||||
defer t.Mu.Unlock()
|
||||
val, found := t.TLEPs[id]
|
||||
if !found {
|
||||
log.Printf("TLEP with %d id is not found; Can not delete\n", id)
|
||||
return
|
||||
}
|
||||
delete(t.TLEPs, id)
|
||||
log.Printf("TLEP with %v val and %d id was found; TLEP is deleted\n", val, id)
|
||||
}
|
||||
|
||||
func (t *TlepCenter) GetTLEP(id uint16) (*tlep.TLEP, error) {
|
||||
log.Printf("Getting tlep by id = %d\n", id)
|
||||
name, have := t.TLEPs[id]
|
||||
if !have {
|
||||
return nil, ERROR_DONT_HAVE
|
||||
}
|
||||
return name, nil
|
||||
}
|
125
cmd/cfyne/types.go
Normal file
125
cmd/cfyne/types.go
Normal file
|
@ -0,0 +1,125 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"fyne.io/fyne/v2"
|
||||
"fyne.io/fyne/v2/container"
|
||||
"fyne.io/fyne/v2/widget"
|
||||
"git.qowevisa.me/Qowevisa/gotell/extfyne/widgets"
|
||||
// com "git.qowevisa.me/Qowevisa/gotell/communication"
|
||||
)
|
||||
|
||||
type FyneConfig struct {
|
||||
App fyne.App
|
||||
Window fyne.Window
|
||||
}
|
||||
|
||||
type MainSceneConfig struct {
|
||||
UserNickcname string
|
||||
// Just for my calmness
|
||||
UserNameSet bool
|
||||
UserId uint16
|
||||
// Just for my calmness
|
||||
UserIdSet bool
|
||||
}
|
||||
|
||||
type MutableStructAboutTabs struct {
|
||||
AppTabs *container.AppTabs
|
||||
LinkTab *container.TabItem
|
||||
LinksBT string
|
||||
LinksNoty uint
|
||||
ConnectionTab *container.TabItem
|
||||
ConnsBT string
|
||||
ConnsNoty uint
|
||||
UsersTab *container.TabItem
|
||||
UsersBT string
|
||||
UsersNoty uint
|
||||
}
|
||||
|
||||
type MutableStructAboutWidgets struct {
|
||||
UsersSelect *widget.Select
|
||||
UserOptsCaretaker *fyne.Container
|
||||
MessagesSelect *widget.Select
|
||||
MBoardCaretacker *fyne.Container
|
||||
MsgButton *widget.Button
|
||||
MBoardMap map[string]*widgets.MessageBoard
|
||||
}
|
||||
|
||||
type UserOptions struct {
|
||||
OptsContainer *fyne.Container
|
||||
Status int
|
||||
ToID uint16
|
||||
Name string
|
||||
}
|
||||
|
||||
type BundleOfMutexArrays struct {
|
||||
LinksMuAr *MutexLinksArray
|
||||
UsersMuAr *MutexStringArray
|
||||
UsersOpts map[string]*UserOptions
|
||||
UserShortcuts map[uint16]string
|
||||
UserShortcutsRev map[string]uint16
|
||||
Messages map[string]*MutexArray[widgets.MBoardMessage]
|
||||
}
|
||||
|
||||
type MutableApp struct {
|
||||
App fyne.App
|
||||
Window fyne.Window
|
||||
}
|
||||
|
||||
type MutableApplication struct {
|
||||
Tabs MutableStructAboutTabs
|
||||
Widgets MutableStructAboutWidgets
|
||||
ArrayBundle BundleOfMutexArrays
|
||||
App MutableApp
|
||||
}
|
||||
|
||||
// I don't know if it is a good idea
|
||||
type MutexArray[T any] struct {
|
||||
Ar []T
|
||||
Mu sync.RWMutex
|
||||
}
|
||||
|
||||
func CreateMutexArray[T any]() MutexArray[T] {
|
||||
var tmp []T
|
||||
return MutexArray[T]{
|
||||
Ar: tmp,
|
||||
}
|
||||
}
|
||||
|
||||
func (ma *MutexArray[T]) Add(v T) {
|
||||
ma.Mu.Lock()
|
||||
ma.Ar = append(ma.Ar, v)
|
||||
ma.Mu.Unlock()
|
||||
}
|
||||
|
||||
func (ma *MutexArray[T]) GetArray() []T {
|
||||
ma.Mu.RLock()
|
||||
defer ma.Mu.RUnlock()
|
||||
return ma.Ar
|
||||
}
|
||||
|
||||
// Non-Generic variant
|
||||
type MutexStringArray struct {
|
||||
Ar []string
|
||||
Mu sync.RWMutex
|
||||
}
|
||||
|
||||
func CreateMutexStringArray() *MutexStringArray {
|
||||
var tmp []string
|
||||
return &MutexStringArray{
|
||||
Ar: tmp,
|
||||
}
|
||||
}
|
||||
|
||||
func (ma *MutexStringArray) Add(v string) {
|
||||
ma.Mu.Lock()
|
||||
ma.Ar = append(ma.Ar, v)
|
||||
ma.Mu.Unlock()
|
||||
}
|
||||
|
||||
func (ma *MutexStringArray) GetArray() []string {
|
||||
ma.Mu.RLock()
|
||||
defer ma.Mu.RUnlock()
|
||||
return ma.Ar
|
||||
}
|
36
cmd/cfyne/uset_statuses.go
Normal file
36
cmd/cfyne/uset_statuses.go
Normal file
|
@ -0,0 +1,36 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
// "log"
|
||||
//
|
||||
// "fyne.io/fyne/v2"
|
||||
// "fyne.io/fyne/v2/container"
|
||||
// "fyne.io/fyne/v2/widget"
|
||||
// com "git.qowevisa.me/Qowevisa/gotell/communication"
|
||||
)
|
||||
|
||||
const (
|
||||
USER_STATUS_NOT_VISIBLE = 0 + iota
|
||||
USER_STATUS_VISIBLE
|
||||
USER_STATUS_HANDSHAKE_INIT
|
||||
USER_STATUS_HANDSHAKE_ACCEPTED
|
||||
USER_STATUS_ECDH_ESTABLISHED
|
||||
USER_STATUS_ECDH_CBES_ESTABLISHED
|
||||
USER_STATUS_ECDH_CBES_MKLG_ESTABLISHED
|
||||
)
|
||||
|
||||
// func getUserOptsContainer(userStatus int, intercom chan *com.Message) *fyne.Container {
|
||||
// switch {
|
||||
// case USER_STATUS_HANDSHAKE_INIT:
|
||||
// btn := widget.NewButton("Init Hadnshake", func() {
|
||||
// intercom <- &com.Message{
|
||||
// ID: ID_CLIENT_ASK_CLIENT_HANDSHAKE,
|
||||
// ToID: ,
|
||||
// }
|
||||
// })
|
||||
// return container.NewGridWithRows(1, )
|
||||
// default:
|
||||
// log.Printf("ERROR: getUserOptsContainer: status %d was not handled!", userStatus)
|
||||
// return container.NewGridWithRows(1, widget.NewLabel("ERROR: 500"))
|
||||
// }
|
||||
// }
|
18
cmd/cfyne/util.go
Normal file
18
cmd/cfyne/util.go
Normal file
|
@ -0,0 +1,18 @@
|
|||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
func getStdUserName(userID uint16, userName string) string {
|
||||
return fmt.Sprintf("User: %s; ID: %d", userName, userID)
|
||||
}
|
||||
|
||||
func getTabNameBasedOnBaseTextAndNoty(baseText string, noty uint) string {
|
||||
return fmt.Sprintf("%s (%d)", baseText, noty)
|
||||
}
|
||||
|
||||
func updateTabsBasedOnNotyVals(tabs *MutableStructAboutTabs) {
|
||||
tabs.LinkTab.Text = getTabNameBasedOnBaseTextAndNoty(tabs.LinksBT, tabs.LinksNoty)
|
||||
tabs.ConnectionTab.Text = getTabNameBasedOnBaseTextAndNoty(tabs.ConnsBT, tabs.ConnsNoty)
|
||||
tabs.UsersTab.Text = getTabNameBasedOnBaseTextAndNoty(tabs.UsersBT, tabs.UsersNoty)
|
||||
tabs.AppTabs.Refresh()
|
||||
}
|
Loading…
Reference in New Issue
Block a user