ui/main.go

213 lines
6.7 KiB
Go
Raw Normal View History

2018-10-23 18:52:13 +00:00
package main
import (
"os"
"github.com/therecipe/qt/core"
"github.com/therecipe/qt/quick"
"github.com/therecipe/qt/quickcontrols2"
"github.com/therecipe/qt/widgets"
"time"
"github.com/sethvargo/go-diceware/diceware"
libpeer "cwtch.im/cwtch/peer"
"path"
"os/user"
"fmt"
"encoding/base32"
"strings"
"cwtch.im/cwtch/peer/connections"
)
var gcd *GrandCentralDispatcher
type ContactManager map[string]*Contact
var contactMgr ContactManager
var peer libpeer.CwtchPeer
type Contact struct {
Messages []Message
Unread int
Status connections.ConnectionState
}
func (this *Contact) AddMessage(m Message) {
this.Messages = append(this.Messages, m)
}
type Message struct {
With, Message string
FromMe bool
}
func DeliverMessageToUI(from, message string, fromMe bool) {
_, found := contactMgr[from]
if !found {
contactMgr[from] = &Contact{[]Message{}, 0, 0}
}
contactMgr[from].AddMessage(Message{from, message, fromMe})
if gcd.currentOpenConversation == from {
if fromMe {
from = "me"
}
gcd.AppendMessage(from, message)
} else {
contactMgr[from].Unread++
gcd.SetUnread(from, contactMgr[from].Unread)
}
}
func init() {
GrandCentralDispatcher_QmlRegisterType2("CustomQmlTypes", 1, 0, "GrandCentralDispatcher")
}
func main() {
contactMgr = make(ContactManager)
core.QCoreApplication_SetAttribute(core.Qt__AA_EnableHighDpiScaling, true)
widgets.NewQApplication(len(os.Args), os.Args)
quickcontrols2.QQuickStyle_SetStyle("Universe")
view := quick.NewQQuickView(nil)
view.SetResizeMode(quick.QQuickView__SizeRootObjectToView)
view.SetTitle("bounce")
gcd = NewGrandCentralDispatcher(nil)
view.RootContext().SetContextProperty("gcd", gcd)
if len(os.Args) == 2 && os.Args[1] == "local" {
view.SetSource(core.QUrl_FromLocalFile("./qml/main.qml"))
} else {
view.SetSource(core.NewQUrl3("qrc:/qml/main.qml", 0))
}
initialize(view)
view.Show()
go presencePoller()
go ricochetListener()
go alice()
widgets.QApplication_Exec()
}
func alice() {
i := 0
for {
time.Sleep(time.Second * 3)
//words, _ := diceware.Generate(3)
//DeliverMessageToUI("f76b5vtleqx2puhwgkords34gs6crgbjqud6sebfzwtlrq4ngbqgcsyd", strings.Join(words, " "), i % 3 == 0)
i++
}
}
func presencePoller() { // TODO: make this subscribe-able in ricochet
time.Sleep(time.Second * 4)
for {
contacts := peer.GetContacts()
for i := range contacts {
_, found := contactMgr[contacts[i]]
if !found { // new contact has attempted to connect with us, treat it as an invite
contactMgr[contacts[i]] = &Contact{[]Message{}, 0, -1}
c, _ := peer.GetProfile().GetContact(contacts[i])
peer.GetProfile().SetCustomAttribute(contacts[i]+"_name", c.Name)
peer.GetProfile().SetCustomAttribute(c.Name+"_onion", contacts[i])
peer.Save()
gcd.AddContact(c.Name, contacts[i], randomProfileImage(contacts[i]), "0", c.Trusted)
}
c, found := peer.GetPeers()[contacts[i]]
if !found && contactMgr[contacts[i]].Status != -2 {
//log.Printf("setting %v to -2", contacts[i])
contactMgr[contacts[i]].Status = -2
gcd.SetConnectionStatus(contacts[i], -2)
} else if contactMgr[contacts[i]].Status != c {
//log.Printf("was: %v", contactMgr[contacts[i]].Status)
contactMgr[contacts[i]].Status = c
//log.Printf("setting %v to status %v", contacts[i], c)
gcd.SetConnectionStatus(contacts[i], int(c))
//log.Printf("now: %v", contactMgr[contacts[i]].Status)
}
}
time.Sleep(time.Second * 4)
}
}
func ricochetListener() {
processData := func(onion string, data []byte) []byte {
/* _, exists := peer.GetProfile().GetCustomAttribute(onion + "_name")
if !exists {
for peer.GetContact(onion) == nil {
time.Sleep(time.Millisecond * 30)
}
name := peer.GetContact(onion).Name
fmt.Printf("adding new untrusted contact %v <%v>\n", name, onion)
peer.GetProfile().SetCustomAttribute(onion+"_name", name)
peer.GetProfile().SetCustomAttribute(name+"_onion", onion)
peer.Save()
gcd.AddContact(name, onion, randomProfileImage(onion), "0", false)
} */
DeliverMessageToUI(onion, string(data), false)
return nil
}
peer.SetPeerDataHandler(processData)
fmt.Fprintf(os.Stderr, "waiting for messages...\n")
err := peer.Listen()
if err != nil {
fmt.Printf("error listening for connections: %v\n", err)
gcd.InvokePopup("error handling network connection")
}
}
func initialize(view *quick.QQuickView) {
//TODO: this section is ported over and has a lot of printf errors, need to show them in the ui
var dirname, filename string
if os.Getenv("SENDAFRIEND_FOLDER") != "" {
dirname = os.Getenv("SENDAFRIEND_FOLDER")
filename = path.Join(dirname, "identity.private")
} else {
usr, err := user.Current()
if err != nil {
fmt.Printf("\nerror: could not load current user: %v\n", err)
os.Exit(1)
}
dirname = path.Join(usr.HomeDir, ".sendafriend")
filename = path.Join(dirname, "identity.private")
}
os.MkdirAll(dirname, 0700)
var err error
peer, err = libpeer.LoadCwtchPeer(filename, "be gay do crime")
if err != nil {
fmt.Println("couldn't load your config file, attempting to create a new one now")
names, err := diceware.Generate(1)
peer, err = libpeer.NewCwtchPeer(names[0], "be gay do crime", filename)
if err != nil {
fmt.Println("couldn't create one either :( exiting")
os.Exit(1)
}
peer.Save()
}
gcd.UpdateMyProfile(peer.GetProfile().Name, peer.GetProfile().Onion, randomProfileImage(peer.GetProfile().Onion))
contacts := peer.GetContacts()
for i := range contacts {
attr, _ := peer.GetProfile().GetCustomAttribute(contacts[i] + "_name")
contactMgr[contacts[i]] = &Contact{[]Message{}, 0, 0}
gcd.AddContact(attr, contacts[i], randomProfileImage(contacts[i]), "0", peer.GetContact(contacts[i]).Trusted)
}
}
// temporary until we do real picture selection
func randomProfileImage(onion string) string {
choices := []string{"001-centaur","002-kraken","003-dinosaur","004-tree-1","005-hand","006-echidna","007-robot","008-mushroom","009-harpy","010-phoenix","011-dragon-1","012-devil","013-troll","014-alien","015-minotaur","016-madre-monte","017-satyr","018-karakasakozou","019-pirate","020-werewolf","021-scarecrow","022-valkyrie","023-curupira","024-loch-ness-monster","025-tree","026-cerberus","027-gryphon","028-mermaid","029-vampire","030-goblin","031-yeti","032-leprechaun","033-medusa","034-chimera","035-elf","036-hydra","037-cyclops","038-pegasus","039-narwhal","040-woodcutter","041-zombie","042-dragon","043-frankenstein","044-witch","045-fairy","046-genie","047-pinocchio","048-ghost","049-wizard","050-unicorn"}
barr, err := base32.StdEncoding.DecodeString(strings.ToUpper(onion))
if err != nil || len(barr) != 35 {
fmt.Printf("error: %v %v %v\n", onion, err, barr)
return "qrc:/qml/images/extra/openprivacy.png"
}
return "qrc:/qml/images/profiles/" + choices[int(barr[33]) % len(choices)] + ".png"
}