New getVal/retVal message handling, and new attribute storage schema
the build was successful Details

This commit is contained in:
Dan Ballard 2020-03-06 23:41:38 -08:00
parent 631810df5b
commit fc3bdb76f6
11 changed files with 319 additions and 124 deletions

5
go.mod
View File

@ -3,11 +3,10 @@ module cwtch.im/ui
go 1.12 go 1.12
require ( require (
cwtch.im/cwtch v0.3.10 cwtch.im/cwtch v0.3.11
git.openprivacy.ca/openprivacy/connectivity v1.1.1 git.openprivacy.ca/openprivacy/connectivity v1.1.1
git.openprivacy.ca/openprivacy/log v1.0.0 git.openprivacy.ca/openprivacy/log v1.0.0
github.com/gopherjs/gopherjs v0.0.0-20200209183636-89e6cbcd0b6d // indirect github.com/gopherjs/gopherjs v0.0.0-20200209183636-89e6cbcd0b6d // indirect
github.com/therecipe/qt v0.0.0-20191101232336-18864661ae4f github.com/therecipe/qt v0.0.0-20191101232336-18864661ae4f
github.com/therecipe/qt/internal/binding/files/docs/5.13.0 v0.0.0-20191002095216-73192f6811d0 // indirect; Required - do not delete or `go tidy` away github.com/therecipe/qt/internal/binding/files/docs/5.13.0 v0.0.0-20191002095216-73192f6811d0 // indirect; Required - do not delete or `go tidy` away
golang.org/x/crypto v0.0.0-20200210222208-86ce3cb69678 // indirect
) )

17
go.sum
View File

@ -1,7 +1,11 @@
cwtch.im/cwtch v0.3.10 h1:akrIwsc1KnLbT3K6ZIFkhmA7kI62L03EWna7Ul1vszU= cwtch.im/cwtch v0.3.10 h1:akrIwsc1KnLbT3K6ZIFkhmA7kI62L03EWna7Ul1vszU=
cwtch.im/cwtch v0.3.10/go.mod h1:tmYeI2v0IEeBMbqzhcndXWZ2oyflhK4Afcf27+49rKU= cwtch.im/cwtch v0.3.10/go.mod h1:tmYeI2v0IEeBMbqzhcndXWZ2oyflhK4Afcf27+49rKU=
cwtch.im/cwtch v0.3.11 h1:2+W2w9HDQowKwEGx4oRLywmn0NzQ0Sg9JEyBdR/V1mA=
cwtch.im/cwtch v0.3.11/go.mod h1:PnMJb9CyzdrdbYjmL99pl6Nu34s6+lmeENVnGaY0hzk=
cwtch.im/tapir v0.1.15 h1:XSCWOvjmNkzMT2IceFgTBXWGKtYfr3a8o+La1s10OhE= cwtch.im/tapir v0.1.15 h1:XSCWOvjmNkzMT2IceFgTBXWGKtYfr3a8o+La1s10OhE=
cwtch.im/tapir v0.1.15/go.mod h1:HzezugpEx+nZ3LdyDsl0w6n45IJYnOt8uqldkLWmaqs= cwtch.im/tapir v0.1.15/go.mod h1:HzezugpEx+nZ3LdyDsl0w6n45IJYnOt8uqldkLWmaqs=
cwtch.im/tapir v0.1.17 h1:2jVZUe1a88tMI4aJPvRTO4Id3NN3PsM62cT5lntEChk=
cwtch.im/tapir v0.1.17/go.mod h1:HzezugpEx+nZ3LdyDsl0w6n45IJYnOt8uqldkLWmaqs=
git.openprivacy.ca/openprivacy/connectivity v1.1.0/go.mod h1:4P8mirZZslKbo2zBrXXVjgEdqGwHo/6qoFBwFQW6d6E= git.openprivacy.ca/openprivacy/connectivity v1.1.0/go.mod h1:4P8mirZZslKbo2zBrXXVjgEdqGwHo/6qoFBwFQW6d6E=
git.openprivacy.ca/openprivacy/connectivity v1.1.1 h1:hKxBOmxP7Jdu3K1BJ93mRtKNiWUoP6YHt/o2snE2Z0w= git.openprivacy.ca/openprivacy/connectivity v1.1.1 h1:hKxBOmxP7Jdu3K1BJ93mRtKNiWUoP6YHt/o2snE2Z0w=
git.openprivacy.ca/openprivacy/connectivity v1.1.1/go.mod h1:4P8mirZZslKbo2zBrXXVjgEdqGwHo/6qoFBwFQW6d6E= git.openprivacy.ca/openprivacy/connectivity v1.1.1/go.mod h1:4P8mirZZslKbo2zBrXXVjgEdqGwHo/6qoFBwFQW6d6E=
@ -12,6 +16,7 @@ git.openprivacy.ca/openprivacy/log v1.0.0/go.mod h1:gGYK8xHtndRLDymFtmjkG26GaMQN
github.com/agl/ed25519 v0.0.0-20170116200512-5312a6153412 h1:w1UutsfOrms1J05zt7ISrnJIXKzwaspym5BTKGx93EI= github.com/agl/ed25519 v0.0.0-20170116200512-5312a6153412 h1:w1UutsfOrms1J05zt7ISrnJIXKzwaspym5BTKGx93EI=
github.com/agl/ed25519 v0.0.0-20170116200512-5312a6153412/go.mod h1:WPjqKcmVOxf0XSf3YxCJs6N6AOSrOx3obionmG7T0y0= github.com/agl/ed25519 v0.0.0-20170116200512-5312a6153412/go.mod h1:WPjqKcmVOxf0XSf3YxCJs6N6AOSrOx3obionmG7T0y0=
github.com/c-bata/go-prompt v0.2.3/go.mod h1:VzqtzE2ksDBcdln8G7mk2RX9QyGjH+OVqOCSiVIqS34= github.com/c-bata/go-prompt v0.2.3/go.mod h1:VzqtzE2ksDBcdln8G7mk2RX9QyGjH+OVqOCSiVIqS34=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/cretz/bine v0.1.1-0.20200124154328-f9f678b84cca h1:Q2r7AxHdJwWfLtBZwvW621M3sPqxPc6ITv2j1FGsYpw= github.com/cretz/bine v0.1.1-0.20200124154328-f9f678b84cca h1:Q2r7AxHdJwWfLtBZwvW621M3sPqxPc6ITv2j1FGsYpw=
github.com/cretz/bine v0.1.1-0.20200124154328-f9f678b84cca/go.mod h1:6PF6fWAvYtwjRGkAuDEJeWNOv3a2hUouSP/yRYXmvHw= github.com/cretz/bine v0.1.1-0.20200124154328-f9f678b84cca/go.mod h1:6PF6fWAvYtwjRGkAuDEJeWNOv3a2hUouSP/yRYXmvHw=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@ -36,6 +41,7 @@ github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfn
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84= github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84=
@ -44,6 +50,7 @@ github.com/mattn/go-runewidth v0.0.8/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m
github.com/mattn/go-tty v0.0.3/go.mod h1:ihxohKRERHTVzN+aSVRwACLCeqIoZAWpoICkkvrWyR0= github.com/mattn/go-tty v0.0.3/go.mod h1:ihxohKRERHTVzN+aSVRwACLCeqIoZAWpoICkkvrWyR0=
github.com/mimoo/StrobeGo v0.0.0-20181016162300-f8f6d4d2b643 h1:hLDRPB66XQT/8+wG9WsDpiCvZf1yKO7sz7scAjSlBa0= github.com/mimoo/StrobeGo v0.0.0-20181016162300-f8f6d4d2b643 h1:hLDRPB66XQT/8+wG9WsDpiCvZf1yKO7sz7scAjSlBa0=
github.com/mimoo/StrobeGo v0.0.0-20181016162300-f8f6d4d2b643/go.mod h1:43+3pMjjKimDBf5Kr4ZFNGbLql1zKkbImw+fZbw3geM= github.com/mimoo/StrobeGo v0.0.0-20181016162300-f8f6d4d2b643/go.mod h1:43+3pMjjKimDBf5Kr4ZFNGbLql1zKkbImw+fZbw3geM=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/pkg/term v0.0.0-20190109203006-aa71e9d9e942/go.mod h1:eCbImbZ95eXtAUIbLAuAVnBnwf83mjf6QIVH8SHYwqQ= github.com/pkg/term v0.0.0-20190109203006-aa71e9d9e942/go.mod h1:eCbImbZ95eXtAUIbLAuAVnBnwf83mjf6QIVH8SHYwqQ=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
@ -57,6 +64,7 @@ github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/struCoder/pidusage v0.1.3/go.mod h1:pWBlW3YuSwRl6h7R5KbvA4N8oOqe9LjaKW5CwT1SPjI= github.com/struCoder/pidusage v0.1.3/go.mod h1:pWBlW3YuSwRl6h7R5KbvA4N8oOqe9LjaKW5CwT1SPjI=
github.com/therecipe/qt v0.0.0-20191101232336-18864661ae4f h1:06ICDSmDOBUC9jwgv44ngvyHzwudJNLa5H+rbCyDFRY= github.com/therecipe/qt v0.0.0-20191101232336-18864661ae4f h1:06ICDSmDOBUC9jwgv44ngvyHzwudJNLa5H+rbCyDFRY=
github.com/therecipe/qt v0.0.0-20191101232336-18864661ae4f/go.mod h1:SUUR2j3aE1z6/g76SdD6NwACEpvCxb3fvG82eKbD6us= github.com/therecipe/qt v0.0.0-20191101232336-18864661ae4f/go.mod h1:SUUR2j3aE1z6/g76SdD6NwACEpvCxb3fvG82eKbD6us=
@ -71,6 +79,8 @@ github.com/therecipe/qt/internal/binding/files/docs/5.13.0 v0.0.0-20200126204426
github.com/therecipe/qt/internal/binding/files/docs/5.13.0 v0.0.0-20200126204426-5074eb6d8c41/go.mod h1:mH55Ek7AZcdns5KPp99O0bg+78el64YCYWHiQKrOdt4= github.com/therecipe/qt/internal/binding/files/docs/5.13.0 v0.0.0-20200126204426-5074eb6d8c41/go.mod h1:mH55Ek7AZcdns5KPp99O0bg+78el64YCYWHiQKrOdt4=
go.etcd.io/bbolt v1.3.3 h1:MUGmc65QhB3pIlaQ5bB4LwqSj6GIonVJXpZiaKNyaKk= go.etcd.io/bbolt v1.3.3 h1:MUGmc65QhB3pIlaQ5bB4LwqSj6GIonVJXpZiaKNyaKk=
go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
go.etcd.io/bbolt v1.3.4 h1:hi1bXHMVrlQh6WwxAy+qZCV/SYIlqo+Ushwdpa4tAKg=
go.etcd.io/bbolt v1.3.4/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190418165655-df01cb2cc480/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= golang.org/x/crypto v0.0.0-20190418165655-df01cb2cc480/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE=
golang.org/x/crypto v0.0.0-20200204104054-c9f3fb736b72 h1:+ELyKg6m8UBf0nPFSqD0mi7zUfwPyXo23HNjMnXPz7w= golang.org/x/crypto v0.0.0-20200204104054-c9f3fb736b72 h1:+ELyKg6m8UBf0nPFSqD0mi7zUfwPyXo23HNjMnXPz7w=
@ -80,11 +90,15 @@ golang.org/x/crypto v0.0.0-20200206161412-a0c6ece9d31a/go.mod h1:LzIPMQfyMNhhGPh
golang.org/x/crypto v0.0.0-20200210191831-6ca56c2f2e2b/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200210191831-6ca56c2f2e2b/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200210222208-86ce3cb69678 h1:wCWoJcFExDgyYx2m2hpHgwz8W3+FPdfldvIgzqDIhyg= golang.org/x/crypto v0.0.0-20200210222208-86ce3cb69678 h1:wCWoJcFExDgyYx2m2hpHgwz8W3+FPdfldvIgzqDIhyg=
golang.org/x/crypto v0.0.0-20200210222208-86ce3cb69678/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200210222208-86ce3cb69678/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200320181102-891825fb96df h1:lDWgvUvNnaTnNBc/dwOty86cFeKoKWbwy2wQj0gIxbU=
golang.org/x/crypto v0.0.0-20200320181102-891825fb96df/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190420063019-afa5a82059c6/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190420063019-afa5a82059c6/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20200202094626-16171245cfb2 h1:CCH4IOTTfewWjGOlSp+zGcjutRKlBEZQ6wTn8ozI/nI= golang.org/x/net v0.0.0-20200202094626-16171245cfb2 h1:CCH4IOTTfewWjGOlSp+zGcjutRKlBEZQ6wTn8ozI/nI=
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200320181208-1c781a10960a h1:KaxWXSFrOaE2ptiOotI+zFdzHxBsg9MW6XfCv497IRo=
golang.org/x/net v0.0.0-20200320181208-1c781a10960a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@ -98,12 +112,15 @@ golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5 h1:LfCXLvNmTYH9kEmVgqbnsWfruoXZIrh4YBgqVHtDvw0= golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5 h1:LfCXLvNmTYH9kEmVgqbnsWfruoXZIrh4YBgqVHtDvw0=
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200320181252-af34d8274f85 h1:fD99hd4ciR6T3oPhr2EkmuKe9oHixHx9Hj/hND89j3g=
golang.org/x/sys v0.0.0-20200320181252-af34d8274f85/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/tools v0.0.0-20190420181800-aa740d480789 h1:FF0rjo15h51+N6642mf5S3QuplmKo2aCrJUYkHTx85s= golang.org/x/tools v0.0.0-20190420181800-aa740d480789 h1:FF0rjo15h51+N6642mf5S3QuplmKo2aCrJUYkHTx85s=
golang.org/x/tools v0.0.0-20190420181800-aa740d480789/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190420181800-aa740d480789/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=

View File

@ -1,9 +1,10 @@
package constants package constants
const Nick = "nick" const SchemaVersion = "schemaVersion"
const Name = "name"
const LastRead = "last-read" const LastRead = "last-read"
const Picture = "picture" const Picture = "picture"
const DefaultPassword = "default-password"
const ProfileTypeV1DefaultPassword = "v1-defaultPassword" const ProfileTypeV1DefaultPassword = "v1-defaultPassword"
const ProfileTypeV1Password = "v1-userPassword" const ProfileTypeV1Password = "v1-userPassword"

View File

@ -1,5 +1,5 @@
package constants package constants
const BlockUnknownPeersSetting = "settings.blockunknownpeers" const BlockUnknownPeersSetting = ".blockunknownpeers"
const LocaleSetting = "settings.locale" const LocaleSetting = ".locale"
const ZoomSetting = "settings.zoom" const ZoomSetting = ".zoom"

View File

@ -91,10 +91,10 @@ func App(gcd *ui.GrandCentralDispatcher, subscribed chan bool, reloadingAccounts
} }
case event.NewPeer: case event.NewPeer:
onion := e.Data[event.Identity] onion := e.Data[event.Identity]
peer := the.CwtchApp.GetPeer(onion) p := the.CwtchApp.GetPeer(onion)
if tag, exists := peer.GetAttribute(app.AttributeTag); !exists || tag == "" { if tag, exists := p.GetAttribute(app.AttributeTag); !exists || tag == "" {
peer.SetAttribute(app.AttributeTag, constants.ProfileTypeV1DefaultPassword) p.SetAttribute(app.AttributeTag, constants.ProfileTypeV1DefaultPassword)
} }
log.Infof("NewPeer for %v\n", onion) log.Infof("NewPeer for %v\n", onion)
@ -104,16 +104,16 @@ func App(gcd *ui.GrandCentralDispatcher, subscribed chan bool, reloadingAccounts
the.CwtchApp.AddPeerPlugin(onion, plugins.NETWORKCHECK) the.CwtchApp.AddPeerPlugin(onion, plugins.NETWORKCHECK)
incSubscribed := make(chan bool) incSubscribed := make(chan bool)
go PeerHandler(onion, gcd.GetUiManager(peer.GetOnion()), incSubscribed) go PeerHandler(onion, gcd.GetUiManager(p.GetOnion()), incSubscribed)
<-incSubscribed <-incSubscribed
if e.Data[event.Status] != "running" { if e.Data[event.Status] != "running" {
peer.Listen() p.Listen()
peer.StartPeersConnections() p.StartPeersConnections()
peer.StartGroupConnections() p.StartGroupConnections()
} }
blockUnkownPeers, exists := peer.GetAttribute(constants.BlockUnknownPeersSetting) blockUnkownPeers, exists := p.GetAttribute(constants.BlockUnknownPeersSetting)
if exists && blockUnkownPeers == "true" { if exists && blockUnkownPeers == "true" {
the.EventBus.Publish(event.NewEvent(event.BlockUnknownPeers, map[event.Field]string{})) the.EventBus.Publish(event.NewEvent(event.BlockUnknownPeers, map[event.Field]string{}))
} }

View File

@ -3,16 +3,21 @@ package handlers
import ( import (
"cwtch.im/cwtch/app" "cwtch.im/cwtch/app"
"cwtch.im/cwtch/event" "cwtch.im/cwtch/event"
"cwtch.im/cwtch/model/attr"
peerC "cwtch.im/cwtch/peer"
"cwtch.im/cwtch/protocol/connections" "cwtch.im/cwtch/protocol/connections"
"cwtch.im/ui/go/constants" "cwtch.im/ui/go/constants"
"cwtch.im/ui/go/the" "cwtch.im/ui/go/the"
"cwtch.im/ui/go/ui" "cwtch.im/ui/go/ui"
"git.openprivacy.ca/openprivacy/log" "git.openprivacy.ca/openprivacy/log"
"strconv"
"time" "time"
) )
func PeerHandler(onion string, uiManager ui.Manager, subscribed chan bool) { func PeerHandler(onion string, uiManager ui.Manager, subscribed chan bool) {
peer := the.CwtchApp.GetPeer(onion) peer := the.CwtchApp.GetPeer(onion)
upgradeSchema(peer)
eventBus := the.CwtchApp.GetEventBus(onion) eventBus := the.CwtchApp.GetEventBus(onion)
q := event.NewQueue() q := event.NewQueue()
eventBus.Subscribe(event.NewMessageFromPeer, q) eventBus.Subscribe(event.NewMessageFromPeer, q)
@ -27,6 +32,7 @@ func PeerHandler(onion string, uiManager ui.Manager, subscribed chan bool) {
eventBus.Subscribe(event.NetworkStatus, q) eventBus.Subscribe(event.NetworkStatus, q)
eventBus.Subscribe(event.ChangePasswordSuccess, q) eventBus.Subscribe(event.ChangePasswordSuccess, q)
eventBus.Subscribe(event.ChangePasswordError, q) eventBus.Subscribe(event.ChangePasswordError, q)
eventBus.Subscribe(event.NewRetValMessageFromPeer, q)
subscribed <- true subscribed <- true
@ -49,9 +55,6 @@ func PeerHandler(onion string, uiManager ui.Manager, subscribed chan bool) {
case event.NewMessageFromPeer: //event.TimestampReceived, event.RemotePeer, event.Data case event.NewMessageFromPeer: //event.TimestampReceived, event.RemotePeer, event.Data
ts, _ := time.Parse(time.RFC3339Nano, e.Data[event.TimestampReceived]) ts, _ := time.Parse(time.RFC3339Nano, e.Data[event.TimestampReceived])
uiManager.AddMessage(e.Data[event.RemotePeer], e.Data[event.RemotePeer], e.Data[event.Data], false, e.EventID, ts, true) uiManager.AddMessage(e.Data[event.RemotePeer], e.Data[event.RemotePeer], e.Data[event.Data], false, e.EventID, ts, true)
if peer.GetContact(e.Data[event.RemotePeer]) == nil {
peer.AddContact(e.Data[event.RemotePeer], e.Data[event.RemotePeer], false)
}
case event.PeerAcknowledgement: case event.PeerAcknowledgement:
uiManager.Acknowledge(e.Data[event.EventID]) uiManager.Acknowledge(e.Data[event.EventID])
@ -76,7 +79,7 @@ func PeerHandler(onion string, uiManager ui.Manager, subscribed chan bool) {
cxnState := connections.ConnectionStateToType[e.Data[event.ConnectionState]] cxnState := connections.ConnectionStateToType[e.Data[event.ConnectionState]]
// if it's not in the.PeerHandler it's new. Only add once Authed // if it's not in the.PeerHandler it's new. Only add once Authed
if contact := peer.GetContact(e.Data[event.RemotePeer]); contact != nil { if contact := peer.GetContact(e.Data[event.RemotePeer]); contact == nil {
// Contact does not exist, we will add them but we won't know who they are until they are authenticated // Contact does not exist, we will add them but we won't know who they are until they are authenticated
// So if we get any other state from an unknown contact we do nothing // So if we get any other state from an unknown contact we do nothing
// (the next exists check will fail) // (the next exists check will fail)
@ -90,8 +93,27 @@ func PeerHandler(onion string, uiManager ui.Manager, subscribed chan bool) {
if contact := peer.GetContact(e.Data[event.RemotePeer]); contact != nil { if contact := peer.GetContact(e.Data[event.RemotePeer]); contact != nil {
contact.State = e.Data[event.ConnectionState] contact.State = e.Data[event.ConnectionState]
uiManager.UpdateContactStatus(contact.Onion, int(cxnState), false) uiManager.UpdateContactStatus(contact.Onion, int(cxnState), false)
if cxnState == connections.AUTHENTICATED {
peer.SendGetValToPeer(e.Data[event.RemotePeer], attr.PublicScope, constants.Name)
peer.SendGetValToPeer(e.Data[event.RemotePeer], attr.PublicScope, constants.Picture)
}
} }
case event.NewRetValMessageFromPeer:
onion := e.Data[event.RemotePeer]
scope := e.Data[event.Scope]
path := e.Data[event.Path]
val := e.Data[event.Data]
exists, _ := strconv.ParseBool(e.Data[event.Exists])
if exists && scope == attr.PublicScope {
switch path {
case constants.Name:
uiManager.UpdateContactDisplayName(onion, val)
case constants.Picture:
uiManager.UpdateContactPicture(onion, val)
}
}
case event.ServerStateChange: case event.ServerStateChange:
serverOnion := e.Data[event.GroupServer] serverOnion := e.Data[event.GroupServer]
state := connections.ConnectionStateToType[e.Data[event.ConnectionState]] state := connections.ConnectionStateToType[e.Data[event.ConnectionState]]
@ -119,6 +141,72 @@ func PeerHandler(onion string, uiManager ui.Manager, subscribed chan bool) {
case event.ChangePasswordError: case event.ChangePasswordError:
uiManager.ChangePasswordResponse(true) uiManager.ChangePasswordResponse(true)
} }
} }
} }
func upgradeSchema(p peerC.CwtchPeer) {
schemaVerVal, exists := p.GetAttribute(constants.SchemaVersion)
if !exists {
schemaVerVal = "0"
}
schemaVer, err := strconv.Atoi(schemaVerVal)
if err != nil {
schemaVer = 0
}
if schemaVer < 1 {
upgradeSchema1(p)
}
}
func upgradeSchema1(p peerC.CwtchPeer) {
log.Infof("UpgradeSchema 1\n")
p.SetAttribute(attr.GetPublicScope(constants.Name), p.GetName())
if picture, exists := p.GetAttribute("picture"); exists {
p.SetAttribute(attr.GetPublicScope(constants.Picture), ui.ImageToString(ui.NewImage(picture, ui.TypeImageDistro)))
}
if locale, exists := p.GetAttribute("settings.locale"); exists {
p.SetAttribute(attr.GetSettingsScope(constants.LocaleSetting), locale)
}
if zoom, exists := p.GetAttribute("settings.zoom"); exists {
p.SetAttribute(attr.GetSettingsScope(constants.ZoomSetting), zoom)
}
if blockunknown, exists := p.GetAttribute("settings.blockunknownpeers"); exists {
p.SetAttribute(attr.GetSettingsScope(constants.BlockUnknownPeersSetting), blockunknown)
}
for _, contactID := range p.GetContacts() {
if nick, exists := p.GetContactAttribute(contactID, "nick"); exists {
p.SetContactAttribute(contactID, attr.GetLocalScope(constants.Name), nick)
}
if picture, exists := p.GetContactAttribute(contactID, "picture"); exists {
p.SetContactAttribute(contactID, attr.GetLocalScope(constants.Picture), ui.ImageToString(ui.NewImage(picture, ui.TypeImageDistro)))
}
if lastRead, exists := p.GetContactAttribute(contactID, "last-read"); exists {
p.SetContactAttribute(contactID, attr.GetLocalScope(constants.LastRead), lastRead)
}
}
for _, gID := range p.GetGroups() {
if nick, exists := p.GetGroupAttribute(gID, "nick"); exists {
p.SetGroupAttribute(gID, attr.GetLocalScope(constants.Name), nick)
}
if picture, exists := p.GetGroupAttribute(gID, "picture"); exists {
p.SetGroupAttribute(gID, attr.GetLocalScope(constants.Picture), ui.ImageToString(ui.NewImage(picture, ui.TypeImageDistro)))
}
if lastRead, exists := p.GetGroupAttribute(gID, "last-read"); exists {
p.SetGroupAttribute(gID, attr.GetLocalScope(constants.LastRead), lastRead)
}
}
p.SetAttribute(constants.SchemaVersion, "1")
}

View File

@ -3,6 +3,7 @@ package ui
import ( import (
"cwtch.im/cwtch/app" "cwtch.im/cwtch/app"
"cwtch.im/cwtch/event" "cwtch.im/cwtch/event"
"cwtch.im/cwtch/model/attr"
"cwtch.im/cwtch/protocol/connections" "cwtch.im/cwtch/protocol/connections"
"cwtch.im/ui/go/constants" "cwtch.im/ui/go/constants"
"github.com/therecipe/qt/qml" "github.com/therecipe/qt/qml"
@ -49,6 +50,7 @@ type GrandCentralDispatcher struct {
// contact list stuff // contact list stuff
_ func(handle, displayName, image, server string, badge, status int, blocked bool, loading bool, lastMsgTime int) `signal:"AddContact"` _ func(handle, displayName, image, server string, badge, status int, blocked bool, loading bool, lastMsgTime int) `signal:"AddContact"`
_ func(handle, displayName string) `signal:"UpdateContactDisplayName"` _ func(handle, displayName string) `signal:"UpdateContactDisplayName"`
_ func(handle, image string) `signal:"UpdateContactPicture"`
_ func(handle string, status int, loading bool) `signal:"UpdateContactStatus"` _ func(handle string, status int, loading bool) `signal:"UpdateContactStatus"`
_ func(handle string, blocked bool) `signal:"UpdateContactBlocked"` _ func(handle string, blocked bool) `signal:"UpdateContactBlocked"`
_ func(handle string) `signal:"IncContactUnreadCount"` _ func(handle string) `signal:"IncContactUnreadCount"`
@ -106,7 +108,6 @@ type GrandCentralDispatcher struct {
_ func() `signal:"requestPeerSettings,auto"` _ func() `signal:"requestPeerSettings,auto"`
_ func(onion, nick string) `signal:"savePeerSettings,auto"` _ func(onion, nick string) `signal:"savePeerSettings,auto"`
_ func(onion, groupID string) `signal:"inviteToGroup,auto"` _ func(onion, groupID string) `signal:"inviteToGroup,auto"`
_ func(onion, key, nick string) `signal:"setAttribute,auto"`
_ func(onion string) `signal:"deleteContact,auto"` _ func(onion string) `signal:"deleteContact,auto"`
_ func() `signal:"allowUnknownPeers,auto"` _ func() `signal:"allowUnknownPeers,auto"`
_ func() `signal:"blockUnknownPeers,auto"` _ func() `signal:"blockUnknownPeers,auto"`
@ -249,7 +250,7 @@ func (this *GrandCentralDispatcher) loadMessagesPaneHelper(handle string) {
this.UpdateContactStatus(group.GroupID, int(state), loading) this.UpdateContactStatus(group.GroupID, int(state), loading)
tl := group.GetTimeline() tl := group.GetTimeline()
nick, _ := group.GetAttribute(constants.Nick) nick := getNick(handle)
updateLastReadTime(group.GroupID) updateLastReadTime(group.GroupID)
if nick == "" { if nick == "" {
this.SetToolbarTitle(handle) this.SetToolbarTitle(handle)
@ -264,7 +265,7 @@ func (this *GrandCentralDispatcher) loadMessagesPaneHelper(handle string) {
handle = tl[i].PeerID handle = tl[i].PeerID
} }
name := getOrDefault(tl[i].PeerID, constants.Nick, tl[i].PeerID) name := getNick(tl[i].PeerID)
image := getProfilePic(tl[i].PeerID) image := getProfilePic(tl[i].PeerID)
this.PrependMessage( this.PrependMessage(
@ -289,10 +290,7 @@ func (this *GrandCentralDispatcher) loadMessagesPaneHelper(handle string) {
var nick string var nick string
if contact != nil { if contact != nil {
nick, _ = contact.GetAttribute(constants.Nick) nick = getNick(contact.Onion)
if nick == "" {
nick = handle
}
} }
updateLastReadTime(contact.Onion) updateLastReadTime(contact.Onion)
this.SetToolbarTitle(nick) this.SetToolbarTitle(nick)
@ -306,7 +304,7 @@ func (this *GrandCentralDispatcher) loadMessagesPaneHelper(handle string) {
from = "me" from = "me"
} }
displayname := getOrDefault(messages[i].PeerID, constants.Nick, messages[i].PeerID) displayname := getNick(messages[i].PeerID)
image := getProfilePic(messages[i].PeerID) image := getProfilePic(messages[i].PeerID)
this.AppendMessage( this.AppendMessage(
@ -325,9 +323,20 @@ func (this *GrandCentralDispatcher) loadMessagesPaneHelper(handle string) {
} }
func (this *GrandCentralDispatcher) requestSettings() { func (this *GrandCentralDispatcher) requestSettings() {
zoom, _ := the.Peer.GetAttribute(constants.ZoomSetting) zoom, exists := the.Peer.GetAttribute(attr.GetSettingsScope(constants.ZoomSetting))
locale, _ := the.Peer.GetAttribute(constants.LocaleSetting) if !exists {
blockunkownpeers, _ := the.Peer.GetAttribute(constants.BlockUnknownPeersSetting) zoom = "1.0"
}
locale, exists := the.Peer.GetAttribute(attr.GetSettingsScope(constants.LocaleSetting))
if !exists {
// TODO: pull env locale
locale = ""
}
blockunkownpeers, exists := the.Peer.GetAttribute(attr.GetSettingsScope(constants.BlockUnknownPeersSetting))
if !exists {
blockunkownpeers = "false"
}
this.SupplySettings(zoom, locale, blockunkownpeers == "true") this.SupplySettings(zoom, locale, blockunkownpeers == "true")
} }
@ -338,7 +347,7 @@ func (this *GrandCentralDispatcher) saveSettings(zoom, locale string) {
return return
} }
the.Peer.SetAttribute(constants.ZoomSetting, zoom) the.Peer.SetAttribute(attr.GetSettingsScope(constants.ZoomSetting), zoom)
} }
func (this *GrandCentralDispatcher) requestPeerSettings() { func (this *GrandCentralDispatcher) requestPeerSettings() {
@ -349,19 +358,13 @@ func (this *GrandCentralDispatcher) requestPeerSettings() {
return return
} }
name, exists := contact.GetAttribute(constants.Nick) name := getNick(contact.Onion)
if !exists {
log.Errorf("error: couldn't find contact %v", this.SelectedConversation())
this.SupplyPeerSettings(this.SelectedConversation(), this.SelectedConversation(), contact.Blocked)
this.SupplyPeerSettings(this.SelectedConversation(), this.SelectedConversation(), contact.Blocked)
return
}
this.SupplyPeerSettings(contact.Onion, name, contact.Blocked) this.SupplyPeerSettings(contact.Onion, name, contact.Blocked)
} }
func (this *GrandCentralDispatcher) savePeerSettings(onion, nick string) { func (this *GrandCentralDispatcher) savePeerSettings(onion, nick string) {
the.Peer.SetContactAttribute(onion, constants.Nick, nick) the.Peer.SetContactAttribute(onion, attr.GetLocalScope(constants.Name), nick)
this.UpdateContactDisplayName(onion, nick) this.UpdateContactDisplayName(onion, nick)
} }
@ -373,25 +376,21 @@ func (this *GrandCentralDispatcher) requestGroupSettings(groupID string) {
return return
} }
nick, _ := group.GetAttribute(constants.Nick) nick := getNick(groupID)
invite, _ := the.Peer.ExportGroup(groupID) invite, _ := the.Peer.ExportGroup(groupID)
contactaddrs := the.Peer.GetContacts() contactaddrs := the.Peer.GetContacts()
contactnames := make([]string, len(contactaddrs)) contactnames := make([]string, len(contactaddrs))
for i, contact := range contactaddrs { for i, contact := range contactaddrs {
name, hasname := the.Peer.GetContact(contact).GetAttribute(constants.Nick) contactnames[i] = getNick(contact)
if hasname {
contactnames[i] = name
} else {
contactnames[i] = contact
}
} }
this.SupplyGroupSettings(group.GroupID, nick, group.GroupServer, invite, group.Accepted, contactnames, contactaddrs) this.SupplyGroupSettings(group.GroupID, nick, group.GroupServer, invite, group.Accepted, contactnames, contactaddrs)
} }
func (this *GrandCentralDispatcher) saveGroupSettings(groupID, nick string) { func (this *GrandCentralDispatcher) saveGroupSettings(groupID, nick string) {
the.Peer.SetGroupAttribute(groupID, constants.Nick, nick) the.Peer.SetGroupAttribute(groupID, attr.GetLocalScope(constants.Name), nick)
this.UpdateContactDisplayName(groupID, nick) this.UpdateContactDisplayName(groupID, nick)
} }
@ -485,9 +484,10 @@ func (this *GrandCentralDispatcher) popup(str string) {
} }
func (this *GrandCentralDispatcher) updateNick(onion, nick string) { func (this *GrandCentralDispatcher) updateNick(onion, nick string) {
peer := the.CwtchApp.GetPeer(onion) p := the.CwtchApp.GetPeer(onion)
if peer != nil { if p != nil {
peer.SetName(nick) p.SetName(nick)
p.SetAttribute(attr.GetPublicScope(constants.Name), nick)
the.CwtchApp.GetEventBus(onion).Publish(event.NewEvent(event.SetProfileName, map[event.Field]string{ the.CwtchApp.GetEventBus(onion).Publish(event.NewEvent(event.SetProfileName, map[event.Field]string{
event.ProfileName: nick, event.ProfileName: nick,
})) }))
@ -503,7 +503,7 @@ func (this *GrandCentralDispatcher) createGroup(server, groupName string) {
this.GetUiManager(this.selectedProfile()).AddContact(groupID) this.GetUiManager(this.selectedProfile()).AddContact(groupID)
the.Peer.SetGroupAttribute(groupID, constants.Nick, groupName) the.Peer.SetGroupAttribute(groupID, attr.GetLocalScope(constants.Name), groupName)
the.Peer.JoinServer(server) the.Peer.JoinServer(server)
} }
@ -548,28 +548,23 @@ func (this *GrandCentralDispatcher) acceptGroup(groupID string) {
} }
} }
func (this *GrandCentralDispatcher) setAttribute(onion, key, value string) {
the.Peer.SetContactAttribute(onion, key, value)
this.GetUiManager(this.selectedProfile()).UpdateContactAttribute(onion, key, value)
}
func (this *GrandCentralDispatcher) blockUnknownPeers() { func (this *GrandCentralDispatcher) blockUnknownPeers() {
the.Peer.SetAttribute(constants.BlockUnknownPeersSetting, "true") the.Peer.SetAttribute(attr.GetSettingsScope(constants.BlockUnknownPeersSetting), "true")
the.EventBus.Publish(event.NewEvent(event.BlockUnknownPeers, map[event.Field]string{})) the.EventBus.Publish(event.NewEvent(event.BlockUnknownPeers, map[event.Field]string{}))
} }
func (this *GrandCentralDispatcher) allowUnknownPeers() { func (this *GrandCentralDispatcher) allowUnknownPeers() {
the.Peer.SetAttribute(constants.BlockUnknownPeersSetting, "false") the.Peer.SetAttribute(attr.GetSettingsScope(constants.BlockUnknownPeersSetting), "false")
the.EventBus.Publish(event.NewEvent(event.AllowUnknownPeers, map[event.Field]string{})) the.EventBus.Publish(event.NewEvent(event.AllowUnknownPeers, map[event.Field]string{}))
} }
func (this *GrandCentralDispatcher) setLocale(locale string) { func (this *GrandCentralDispatcher) setLocale(locale string) {
this.SetLocale_helper(locale) this.SetLocale_helper(locale)
the.Peer.SetAttribute(constants.LocaleSetting, locale) the.Peer.SetAttribute(attr.GetSettingsScope(constants.LocaleSetting), locale)
zoom, _ := the.Peer.GetAttribute(constants.ZoomSetting) zoom, _ := the.Peer.GetAttribute(attr.GetSettingsScope(constants.ZoomSetting))
blockunkownpeers, _ := the.Peer.GetAttribute(constants.BlockUnknownPeersSetting) blockunkownpeers, _ := the.Peer.GetAttribute(attr.GetPeerScope(constants.BlockUnknownPeersSetting))
this.SupplySettings(zoom, locale, blockunkownpeers == "true") this.SupplySettings(zoom, locale, blockunkownpeers == "true")
} }
@ -597,12 +592,17 @@ func (this *GrandCentralDispatcher) loadProfile(onion string) {
the.Peer = the.CwtchApp.GetPeer(onion) the.Peer = the.CwtchApp.GetPeer(onion)
the.EventBus = the.CwtchApp.GetEventBus(onion) the.EventBus = the.CwtchApp.GetEventBus(onion)
pic, exists := the.Peer.GetAttribute(constants.Picture) picVal, exists := the.Peer.GetAttribute(attr.GetPublicScope(constants.Picture))
if !exists { if !exists {
pic = RandomProfileImage(the.Peer.GetOnion()) picVal = ImageToString(NewImage(RandomProfileImage(onion), TypeImageDistro))
the.Peer.SetAttribute(constants.Picture, pic) the.Peer.SetAttribute(attr.GetPublicScope(constants.Picture), picVal)
} }
this.UpdateMyProfile(the.Peer.GetName(), the.Peer.GetOnion(), profilePicRelativize(pic)) pic, err := StringToImage(picVal)
if err != nil {
pic = NewImage(RandomProfileImage(onion), TypeImageDistro)
the.Peer.SetAttribute(attr.GetPublicScope(constants.Picture), ImageToString(pic))
}
this.UpdateMyProfile(the.Peer.GetName(), the.Peer.GetOnion(), getPicturePath(pic))
contacts := the.Peer.GetContacts() contacts := the.Peer.GetContacts()
for i := range contacts { for i := range contacts {
@ -617,7 +617,7 @@ func (this *GrandCentralDispatcher) loadProfile(onion string) {
// load ui preferences // load ui preferences
this.RequestSettings() this.RequestSettings()
locale, exists := the.Peer.GetAttribute(constants.LocaleSetting) locale, exists := the.Peer.GetAttribute(attr.GetSettingsScope(constants.LocaleSetting))
if exists { if exists {
this.SetLocale_helper(locale) this.SetLocale_helper(locale)
} }

34
go/ui/imageType.go Normal file
View File

@ -0,0 +1,34 @@
package ui
import "encoding/json"
// Image types we support
const (
// TypeImageDistro is a reletive path to any of the distributed images in cwtch/ui in the assets folder
TypeImageDistro = "distro"
// TypeImageComposition will be an face image composed of a recipe of parts like faceType, eyeType, etc
TypeImageComposition = "composition"
)
type image struct {
Val string
T string
}
func NewImage(val, t string) *image {
return &image{val, t}
}
func StringToImage(str string) (*image, error) {
var img image
err := json.Unmarshal([]byte(str), &img)
if err != nil {
return nil, err
}
return &img, nil
}
func ImageToString(img *image) string {
bytes, _ := json.Marshal(img)
return string(bytes)
}

View File

@ -3,6 +3,7 @@ package ui
import ( import (
"cwtch.im/cwtch/app" "cwtch.im/cwtch/app"
"cwtch.im/cwtch/model" "cwtch.im/cwtch/model"
"cwtch.im/cwtch/model/attr"
"cwtch.im/cwtch/protocol/connections" "cwtch.im/cwtch/protocol/connections"
"cwtch.im/ui/go/constants" "cwtch.im/ui/go/constants"
"cwtch.im/ui/go/the" "cwtch.im/ui/go/the"
@ -20,7 +21,7 @@ func isPeer(id string) bool {
return len(id) == 56 return len(id) == 56
} }
func getOrDefault(id, key, defaultVal string) string { func getOrDefault(id, key string, defaultVal string) string {
var val string var val string
var ok bool var ok bool
if isGroup(id) { if isGroup(id) {
@ -35,7 +36,7 @@ func getOrDefault(id, key, defaultVal string) string {
} }
} }
func getWithSetDefault(id string, key, defaultVal string) string { func getWithSetDefault(id string, key string, defaultVal string) string {
var val string var val string
var ok bool var ok bool
if isGroup(id) { if isGroup(id) {
@ -54,12 +55,34 @@ func getWithSetDefault(id string, key, defaultVal string) string {
return val return val
} }
func getNick(id string) string {
if isGroup(id) {
nick, exists := the.Peer.GetGroupAttribute(id, attr.GetLocalScope(constants.Name))
if !exists || nick == "" {
nick, exists = the.Peer.GetGroupAttribute(id, attr.GetPeerScope(constants.Name))
if !exists {
nick = id
}
}
return nick
} else {
nick, exists := the.Peer.GetContactAttribute(id, attr.GetLocalScope(constants.Name))
if !exists {
nick, exists = the.Peer.GetContactAttribute(id, attr.GetPeerScope(constants.Name))
if !exists {
nick = id
}
}
return nick
}
}
// initLastReadTime checks and gets the Attributable's LastRead time or sets it to now // initLastReadTime checks and gets the Attributable's LastRead time or sets it to now
func initLastReadTime(id string) time.Time { func initLastReadTime(id string) time.Time {
nowStr, _ := time.Now().MarshalText() nowStr, _ := time.Now().MarshalText()
lastReadStr := getWithSetDefault(id, constants.LastRead, string(nowStr)) lastReadAttr := getWithSetDefault(id, attr.GetLocalScope(constants.LastRead), string(nowStr))
var lastRead time.Time var lastRead time.Time
lastRead.UnmarshalText([]byte(lastReadStr)) lastRead.UnmarshalText([]byte(lastReadAttr))
return lastRead return lastRead
} }
@ -70,37 +93,57 @@ func profilePicRelativize(filename string) string {
return parts[len(parts)-1] return parts[len(parts)-1]
} }
func initProfilePicture(id string) string { // getProfilePic returns a string path to an image to display for hte given peer/group id
func getProfilePic(id string) string {
log.Debugf("getProfilePic for %v\n", id)
if isGroup(id) { if isGroup(id) {
return profilePicRelativize(getWithSetDefault(id, constants.Picture, RandomGroupImage(id))) if picVal, exists := the.Peer.GetGroupAttribute(id, attr.GetLocalScope(constants.Picture)); exists {
pic, err := StringToImage(picVal)
if err == nil {
return getPicturePath(pic)
}
}
if picVal, exists := the.Peer.GetGroupAttribute(id, attr.GetPeerScope(constants.Picture)); exists {
pic, err := StringToImage(picVal)
if err == nil {
return getPicturePath(pic)
}
}
return getPicturePath(NewImage(RandomGroupImage(id), TypeImageDistro))
} else { } else {
return profilePicRelativize(getWithSetDefault(id, constants.Picture, RandomProfileImage(id))) if picVal, exists := the.Peer.GetContactAttribute(id, attr.GetLocalScope(constants.Picture)); exists {
pic, err := StringToImage(picVal)
if err == nil {
return getPicturePath(pic)
}
}
if picVal, exists := the.Peer.GetContactAttribute(id, attr.GetPeerScope(constants.Picture)); exists {
pic, err := StringToImage(picVal)
if err == nil {
return getPicturePath(pic)
}
}
return getPicturePath(NewImage("fontawesome/regular/user.svg", TypeImageDistro))
} }
} }
// getProfilePic supplies a profile pic to use. In groups we may not have a contact so it will generate one func getPicturePath(pic *image) string {
func getProfilePic(id string) string { switch pic.T {
if isGroup(id) { case TypeImageDistro:
if pic, exists := the.Peer.GetGroupAttribute(id, constants.Picture); !exists { return profilePicRelativize(pic.Val)
return RandomGroupImage(id) default:
} else { log.Errorf("Unhandled profile picture type of %v\n", pic.T)
return profilePicRelativize(pic) return ""
}
} else {
if pic, exists := the.Peer.GetContactAttribute(id, constants.Picture); !exists {
return profilePicRelativize(RandomProfileImage(id))
} else {
return pic
}
} }
} }
func updateLastReadTime(id string) { func updateLastReadTime(id string) {
lastRead, _ := time.Now().MarshalText() lastRead, _ := time.Now().MarshalText()
if isGroup(id) { if isGroup(id) {
the.Peer.SetGroupAttribute(id, constants.LastRead, string(lastRead)) the.Peer.SetGroupAttribute(id, attr.GetLocalScope(constants.LastRead), string(lastRead))
} else { } else {
the.Peer.SetContactAttribute(id, constants.LastRead, string(lastRead)) the.Peer.SetContactAttribute(id, attr.GetLocalScope(constants.LastRead), string(lastRead))
} }
} }
@ -118,23 +161,27 @@ func countUnread(messages []model.Message, lastRead time.Time) int {
// AddProfile adds a new profile to the UI // AddProfile adds a new profile to the UI
func AddProfile(gcd *GrandCentralDispatcher, handle string) { func AddProfile(gcd *GrandCentralDispatcher, handle string) {
peer := the.CwtchApp.GetPeer(handle) p := the.CwtchApp.GetPeer(handle)
if peer != nil { if p != nil {
nick := peer.GetName() nick, exists := p.GetAttribute(attr.GetPublicScope(constants.Name))
if nick == "" { if !exists {
nick = handle nick = handle
peer.SetAttribute(constants.Nick, nick)
} }
pic, ok := peer.GetAttribute(constants.Picture) picVal, ok := p.GetAttribute(attr.GetPublicScope(constants.Picture))
if !ok { if !ok {
pic = RandomProfileImage(handle) picVal = ImageToString(NewImage(RandomProfileImage(handle), TypeImageDistro))
peer.SetAttribute(constants.Picture, pic)
} }
pic, err := StringToImage(picVal)
if err != nil {
pic = NewImage(RandomProfileImage(handle), TypeImageDistro)
}
picPath := getPicturePath(pic)
tag, _ := peer.GetAttribute(app.AttributeTag) tag, _ := p.GetAttribute(app.AttributeTag)
log.Infof("AddProfile %v %v %v %v\n", handle, nick, profilePicRelativize(pic), tag)
gcd.AddProfile(handle, nick, profilePicRelativize(pic), tag) log.Infof("AddProfile %v %v %v %v\n", handle, nick, picPath, tag)
gcd.AddProfile(handle, nick, picPath, tag)
} }
} }
@ -157,6 +204,7 @@ type Manager interface {
ReloadProfiles() ReloadProfiles()
UpdateContactDisplayName(handle string, name string) UpdateContactDisplayName(handle string, name string)
UpdateContactPicture(handle string, picVal string)
UpdateContactStatus(handle string, status int, loading bool) UpdateContactStatus(handle string, status int, loading bool)
UpdateContactAttribute(handle, key, value string) UpdateContactAttribute(handle, key, value string)
@ -184,40 +232,32 @@ func getLastMessageTime(tl *model.Timeline) int {
} }
// AddContact adds a new contact to the ui for this manager's profile // AddContact adds a new contact to the ui for this manager's profile
func (this *manager) AddContact(Handle string) { func (this *manager) AddContact(handle string) {
this.gcd.DoIfProfile(this.profile, func() { this.gcd.DoIfProfile(this.profile, func() {
if isGroup(Handle) { if isGroup(handle) {
group := the.Peer.GetGroup(Handle) group := the.Peer.GetGroup(handle)
if group != nil { if group != nil {
lastRead := initLastReadTime(group.GroupID) lastRead := initLastReadTime(group.GroupID)
unread := countUnread(group.Timeline.GetMessages(), lastRead) unread := countUnread(group.Timeline.GetMessages(), lastRead)
picture := initProfilePicture(Handle) picture := getProfilePic(handle)
nick, exists := group.GetAttribute(constants.Nick)
if !exists {
nick = Handle
}
this.gcd.AddContact(Handle, nick, picture, group.GroupServer, unread, int(connections.ConnectionStateToType[group.State]), false, false, getLastMessageTime(&group.Timeline)) this.gcd.AddContact(handle, getNick(handle), picture, group.GroupServer, unread, int(connections.ConnectionStateToType[group.State]), false, false, getLastMessageTime(&group.Timeline))
} }
return return
} else if !isPeer(Handle) { } else if !isPeer(handle) {
log.Errorf("sorry, unable to handle AddContact(%v)", Handle) log.Errorf("sorry, unable to handle AddContact(%v)", handle)
debug.PrintStack() debug.PrintStack()
return return
} }
contact := the.Peer.GetContact(Handle) contact := the.Peer.GetContact(handle)
if contact != nil { if contact != nil {
lastRead := initLastReadTime(contact.Onion) lastRead := initLastReadTime(contact.Onion)
unread := countUnread(contact.Timeline.GetMessages(), lastRead) unread := countUnread(contact.Timeline.GetMessages(), lastRead)
picture := initProfilePicture(Handle) picture := getProfilePic(handle)
nick, exists := contact.GetAttribute(constants.Nick)
if !exists {
nick = Handle
}
this.gcd.AddContact(Handle, nick, picture, "", unread, int(connections.ConnectionStateToType[contact.State]), contact.Blocked, false, getLastMessageTime(&contact.Timeline)) this.gcd.AddContact(handle, getNick(handle), picture, "", unread, int(connections.ConnectionStateToType[contact.State]), contact.Blocked, false, getLastMessageTime(&contact.Timeline))
} }
}) })
} }
@ -238,7 +278,7 @@ func (this *manager) AddSendMessageError(peer string, signature string, err stri
func (this *manager) AddMessage(handle string, from string, message string, fromMe bool, messageID string, timestamp time.Time, Acknowledged bool) { func (this *manager) AddMessage(handle string, from string, message string, fromMe bool, messageID string, timestamp time.Time, Acknowledged bool) {
this.gcd.DoIfProfile(this.profile, func() { this.gcd.DoIfProfile(this.profile, func() {
nick := getOrDefault(handle, constants.Nick, handle) nick := getNick(handle)
image := getProfilePic(handle) image := getProfilePic(handle)
// If we have this group loaded already // If we have this group loaded already
@ -270,6 +310,16 @@ func (this *manager) UpdateContactDisplayName(handle string, name string) {
}) })
} }
// UpdateContactPicture updates a contact's picture in the contact list and conversations
func (this *manager) UpdateContactPicture(handle string, picVal string) {
this.gcd.DoIfProfile(this.profile, func() {
pic, err := StringToImage(picVal)
if err == nil {
this.gcd.UpdateContactPicture(handle, getPicturePath(pic))
}
})
}
// UpdateContactStatus updates a contact's status in the ui // UpdateContactStatus updates a contact's status in the ui
func (this *manager) UpdateContactStatus(handle string, status int, loading bool) { func (this *manager) UpdateContactStatus(handle string, status int, loading bool) {
this.gcd.DoIfProfile(this.profile, func() { this.gcd.DoIfProfile(this.profile, func() {

View File

@ -25,13 +25,13 @@ Item {
id: mainImage id: mainImage
width: baseWidth width: baseWidth
height: baseWidth height: baseWidth
color: highlight ? windowItem.cwtch_dark_color: "#FFFFFF" color: "#350052" //: "#FFFFFF" //windowItem.cwtch_dark_color: "#FFFFFF"
radius: width / 2 radius: width / 2
Rectangle { Rectangle {
width: highlight ? baseWidth - 4 : baseWidth width: highlight ? baseWidth - 4 : baseWidth
height: highlight ? baseWidth - 4 : baseWidth height: highlight ? baseWidth - 4 : baseWidth
color: button ? windowItem.cwtch_dark_color: "#FFFFFF" color: "#350052" //: "#FFFFFF" // windowItem.cwtch_dark_color: "#FFFFFF"
radius: width / 2 radius: width / 2
anchors.centerIn:parent anchors.centerIn:parent

View File

@ -244,6 +244,12 @@ Item { // LOTS OF NESTING TO DEAL WITH QT WEIRDNESS, SORRY
} }
} }
onUpdateContactPicture: function(_handle, _image) {
if (handle == _handle) {
image = _image
}
}
onIncContactUnreadCount: function(handle) { onIncContactUnreadCount: function(handle) {
if (handle == _handle && gcd.selectedConversation != handle) { if (handle == _handle && gcd.selectedConversation != handle) {
badge++ badge++