diff --git a/assets/core/account_blocked.svg b/assets/core/account_blocked.svg
new file mode 100644
index 00000000..412efcff
--- /dev/null
+++ b/assets/core/account_blocked.svg
@@ -0,0 +1,19 @@
+
+
+
diff --git a/go.mod b/go.mod
index 96f34001..c53c6bc6 100644
--- a/go.mod
+++ b/go.mod
@@ -3,12 +3,13 @@ module cwtch.im/ui
go 1.12
require (
- cwtch.im/cwtch v0.3.11
+ cwtch.im/cwtch v0.3.15
git.openprivacy.ca/openprivacy/connectivity v1.1.4
- git.openprivacy.ca/openprivacy/log v1.0.0
+ git.openprivacy.ca/openprivacy/log v1.0.1
github.com/gopherjs/gopherjs v0.0.0-20200209183636-89e6cbcd0b6d // indirect
github.com/therecipe/qt v0.0.0-20200126204426-5074eb6d8c41
github.com/therecipe/qt/internal/binding/files/docs/5.12.0 v0.0.0-20200126204426-5074eb6d8c41 // indirect
github.com/therecipe/qt/internal/binding/files/docs/5.13.0 v0.0.0-20200126204426-5074eb6d8c41 // indirect
- golang.org/x/crypto v0.0.0-20200320181102-891825fb96df
+ golang.org/x/crypto v0.0.0-20200420104511-884d27f42877 // indirect
)
+
diff --git a/go.sum b/go.sum
index 976949b9..e6e5746f 100644
--- a/go.sum
+++ b/go.sum
@@ -2,6 +2,10 @@ cwtch.im/cwtch v0.3.10 h1:akrIwsc1KnLbT3K6ZIFkhmA7kI62L03EWna7Ul1vszU=
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/cwtch v0.3.14 h1:XL8UbCUyIosdFTD5nSlpvhbQQGFLjvFmd81/SmfBSP8=
+cwtch.im/cwtch v0.3.14/go.mod h1:wDmgxWBWak/xvZ5GurdYNOJ8b8eha1MwVdiWsCS/pwI=
+cwtch.im/cwtch v0.3.15 h1:Z7fFREwXY728q2YmmwgHL357zAobrsWJ2oPkkGwzvo0=
+cwtch.im/cwtch v0.3.15/go.mod h1:iI9q4C3njHFBYQkNEbzMdK6QWPS0Vbkc0FigRHZNTvM=
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.17 h1:2jVZUe1a88tMI4aJPvRTO4Id3NN3PsM62cT5lntEChk=
@@ -23,6 +27,8 @@ git.openprivacy.ca/openprivacy/libricochet-go v1.0.13 h1:Z86uL9K47onznY1wP1P/wWf
git.openprivacy.ca/openprivacy/libricochet-go v1.0.13/go.mod h1:ZUuX1SOrgV4K18IEcp0hQJNPKszRr2oGb3UeK2iYe5U=
git.openprivacy.ca/openprivacy/log v1.0.0 h1:Rvqm1weUdR4AOnJ79b1upHCc9vC/QF1rhSD2Um7sr1Y=
git.openprivacy.ca/openprivacy/log v1.0.0/go.mod h1:gGYK8xHtndRLDymFtmjkG26GaMQNgyhioNS82m812Iw=
+git.openprivacy.ca/openprivacy/log v1.0.1 h1:NWV5oBTatvlSzUE6wtB+UQCulgyMOtm4BXGd34evMys=
+git.openprivacy.ca/openprivacy/log v1.0.1/go.mod h1:gGYK8xHtndRLDymFtmjkG26GaMQNgyhioNS82m812Iw=
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/c-bata/go-prompt v0.2.3/go.mod h1:VzqtzE2ksDBcdln8G7mk2RX9QyGjH+OVqOCSiVIqS34=
diff --git a/go/handlers/peerHandler.go b/go/handlers/peerHandler.go
index c6c8f02e..c4f940db 100644
--- a/go/handlers/peerHandler.go
+++ b/go/handlers/peerHandler.go
@@ -3,6 +3,7 @@ package handlers
import (
"cwtch.im/cwtch/app"
"cwtch.im/cwtch/event"
+ "cwtch.im/cwtch/model"
"cwtch.im/cwtch/model/attr"
peerC "cwtch.im/cwtch/peer"
"cwtch.im/cwtch/protocol/connections"
@@ -77,13 +78,12 @@ func PeerHandler(onion string, uiManager ui.Manager, subscribed chan bool) {
case event.PeerStateChange:
cxnState := connections.ConnectionStateToType[e.Data[event.ConnectionState]]
- // if it's not in the.PeerHandler it's new. Only add once Authed
- 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
- // So if we get any other state from an unknown contact we do nothing
- // (the next exists check will fail)
- if cxnState == connections.AUTHENTICATED {
- peer.AddContact(e.Data[event.RemotePeer], e.Data[event.RemotePeer], false)
+ // New connection established
+ if cxnState == connections.AUTHENTICATED {
+ // if it's not in the peer it's new
+ if contact := peer.GetContact(e.Data[event.RemotePeer]); contact == nil {
+ // Contact does not exist, we will add them
+ peer.AddContact(e.Data[event.RemotePeer], e.Data[event.RemotePeer], model.AuthUnknown)
uiManager.AddContact(e.Data[event.RemotePeer])
}
}
diff --git a/go/ui/gcd.go b/go/ui/gcd.go
index 0910fc7a..0860b098 100644
--- a/go/ui/gcd.go
+++ b/go/ui/gcd.go
@@ -3,6 +3,7 @@ package ui
import (
"cwtch.im/cwtch/app"
"cwtch.im/cwtch/event"
+ "cwtch.im/cwtch/model"
"cwtch.im/cwtch/model/attr"
"cwtch.im/cwtch/protocol/connections"
"cwtch.im/ui/go/constants"
@@ -52,14 +53,13 @@ type GrandCentralDispatcher struct {
_ func(failed bool) `signal:"ChangePasswordResponse"`
// contact list stuff
- _ func(handle, displayName, image string, badge, status int, blocked bool, loading bool, lastMsgTime int) `signal:"AddContact"`
- _ func(handle, displayName string) `signal:"UpdateContactDisplayName"`
- _ func(handle, image string) `signal:"UpdateContactPicture"`
- _ func(handle string, status int, loading bool) `signal:"UpdateContactStatus"`
- _ func(handle string, blocked bool) `signal:"UpdateContactBlocked"`
- _ func(handle string) `signal:"IncContactUnreadCount"`
- _ func(handle string) `signal:"RemoveContact"`
- _ func(handle, key, value string) `signal:"UpdateContactAttribute"`
+ _ func(handle, displayName, image string, badge, status int, authorization string, loading bool, lastMsgTime int) `signal:"AddContact"`
+ _ func(handle, displayName string) `signal:"UpdateContactDisplayName"`
+ _ func(handle, image string) `signal:"UpdateContactPicture"`
+ _ func(handle string, status int, loading bool) `signal:"UpdateContactStatus"`
+ _ func(handle string) `signal:"IncContactUnreadCount"`
+ _ func(handle string) `signal:"RemoveContact"`
+ _ func(handle, key, value string) `signal:"UpdateContactAttribute"`
// messages pane stuff
_ func(handle, from, displayName, message, image string, mID string, fromMe bool, ts string, ackd bool, error bool) `signal:"AppendMessage"`
@@ -79,7 +79,7 @@ type GrandCentralDispatcher struct {
_ func(str string) `signal:"InvokePopup"`
_ func(locale string, zoom float32, theme string) `signal:"SupplySettings"`
_ func(groupID, name, server, invitation string, accepted bool, addrbooknames, addrbookaddrs []string) `signal:"SupplyGroupSettings"`
- _ func(onion, nick string, blocked bool) `signal:"SupplyPeerSettings"`
+ _ func(onion, nick string, authorization string) `signal:"SupplyPeerSettings"`
// signals emitted from the ui (written in go, below)
// ui
@@ -94,8 +94,7 @@ type GrandCentralDispatcher struct {
_ func(onion, currentPassword, newPassword string, defaultPass bool) `signal:"changePassword,auto""`
// operating a profile
_ func(message string, mid string) `signal:"sendMessage,auto"`
- _ func(onion string) `signal:"blockPeer,auto"`
- _ func(onion string) `signal:"unblockPeer,auto"`
+ _ func(onion string, auth string) `signal:"setPeerAuthorization,auto"`
_ func(onion string) `signal:"loadMessagesPane,auto"`
_ func(signal string) `signal:"broadcast,auto"` // convenience relay signal
_ func(str string) `signal:"importString,auto"`
@@ -339,7 +338,7 @@ func (this *GrandCentralDispatcher) requestPeerSettings() {
contact := the.Peer.GetContact(this.SelectedConversation())
if contact == nil {
log.Errorf("error: requested settings for unknown contact %v?", this.SelectedConversation())
- this.SupplyPeerSettings(this.SelectedConversation(), this.SelectedConversation(), false)
+ this.SupplyPeerSettings(this.SelectedConversation(), this.SelectedConversation(), string(contact.Authorization))
return
}
@@ -348,7 +347,7 @@ func (this *GrandCentralDispatcher) requestPeerSettings() {
// Todo: Move to profile settings
//blockunkownpeers, _ := the.Peer.GetAttribute(attr.GetPeerScope(constants.BlockUnknownPeersSetting))
- this.SupplyPeerSettings(contact.Onion, name, contact.Blocked)
+ this.SupplyPeerSettings(contact.Onion, name, string(contact.Authorization))
}
func (this *GrandCentralDispatcher) savePeerSettings(onion, nick string) {
@@ -397,7 +396,7 @@ func (this *GrandCentralDispatcher) createContact(onion string) {
if contact := the.Peer.GetContact(onion); contact != nil {
return
}
- the.Peer.AddContact(onion, onion, false)
+ the.Peer.AddContact(onion, onion, model.AuthApproved)
the.Peer.PeerWithOnion(onion)
}
@@ -460,7 +459,7 @@ func (this *GrandCentralDispatcher) importString(str string) {
this.InvokePopup("already have this contact")
return //TODO: bring them to the duplicate
} else {
- the.Peer.AddContact(name, onion, false)
+ the.Peer.AddContact(name, onion, model.AuthApproved)
the.Peer.PeerWithOnion(onion)
}
@@ -496,21 +495,18 @@ func (this *GrandCentralDispatcher) createGroup(server, groupName string) {
the.Peer.JoinServer(server)
}
-func (this *GrandCentralDispatcher) blockPeer(onion string) {
- err := the.Peer.BlockPeer(onion)
+func (this *GrandCentralDispatcher) setPeerAuthorization(onion string, authorization string) {
+ log.Debugf("Setting peer auth level to %v for %v\n", authorization, onion)
+ err := the.Peer.SetContactAuthorization(onion, model.Authorization(authorization))
if err != nil {
- this.InvokePopup("Error Blocking Peer: " + err.Error())
+ log.Errorf("Could not set peer authorization %v to %v\n", onion, authorization)
+ return
}
- this.UpdateContactBlocked(onion, true)
-}
-
-func (this *GrandCentralDispatcher) unblockPeer(onion string) {
- err := the.Peer.UnblockPeer(onion)
- if err != nil {
- this.InvokePopup("Error Unblocking Peer: " + err.Error())
+ this.RemoveContact(onion)
+ this.GetUiManager(this.selectedProfile()).AddContact(onion)
+ if model.Authorization(authorization) == model.AuthApproved {
+ the.Peer.PeerWithOnion(onion)
}
- the.Peer.PeerWithOnion(onion)
- this.UpdateContactBlocked(onion, false)
}
func (this *GrandCentralDispatcher) inviteToGroup(onion, groupID string) {
diff --git a/go/ui/manager.go b/go/ui/manager.go
index c22d92ba..87d7fd75 100644
--- a/go/ui/manager.go
+++ b/go/ui/manager.go
@@ -123,7 +123,7 @@ func getProfilePic(id string) string {
return getPicturePath(pic)
}
}
- return getPicturePath(NewImage("fontawesome/regular/user.svg", TypeImageDistro))
+ return RandomProfileImage(id)
}
}
@@ -241,7 +241,7 @@ func (this *manager) AddContact(handle string) {
unread := countUnread(group.Timeline.GetMessages(), lastRead)
picture := getProfilePic(handle)
- this.gcd.AddContact(handle, getNick(handle), picture, unread, int(connections.ConnectionStateToType[group.State]), false, false, getLastMessageTime(&group.Timeline))
+ this.gcd.AddContact(handle, getNick(handle), picture, unread, int(connections.ConnectionStateToType[group.State]), string(model.AuthApproved), false, getLastMessageTime(&group.Timeline))
}
return
} else if !isPeer(handle) {
@@ -256,7 +256,7 @@ func (this *manager) AddContact(handle string) {
unread := countUnread(contact.Timeline.GetMessages(), lastRead)
picture := getProfilePic(handle)
- this.gcd.AddContact(handle, getNick(handle), 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]), string(contact.Authorization), false, getLastMessageTime(&contact.Timeline))
}
})
}
diff --git a/go/ui/settings.go b/go/ui/settings.go
index 1b4e4208..18ffdcfd 100644
--- a/go/ui/settings.go
+++ b/go/ui/settings.go
@@ -1,15 +1,11 @@
package ui
import (
- "crypto/rand"
"cwtch.im/cwtch/storage/v1"
"cwtch.im/ui/go/the"
"encoding/json"
"git.openprivacy.ca/openprivacy/log"
"github.com/therecipe/qt/core"
- "golang.org/x/crypto/pbkdf2"
- "golang.org/x/crypto/sha3"
- "io"
"io/ioutil"
"os"
"path"
@@ -31,34 +27,12 @@ var DefaultGlobalSettings = GlobalSettings{
Theme: "light",
}
-// createKeySalt derives a key from a password: returns key, salt, err
-func createKeySalt(password string) ([32]byte, [128]byte, error) {
- var salt [128]byte
- if _, err := io.ReadFull(rand.Reader, salt[:]); err != nil {
- log.Errorf("Cannot read from random: %v\n", err)
- return [32]byte{}, salt, err
- }
- dk := pbkdf2.Key([]byte(password), salt[:], 4096, 32, sha3.New512)
-
- var dkr [32]byte
- copy(dkr[:], dk)
- return dkr, salt, nil
-}
-
-func createKey(password string, salt []byte) [32]byte {
- dk := pbkdf2.Key([]byte(password), salt, 4096, 32, sha3.New512)
-
- var dkr [32]byte
- copy(dkr[:], dk)
- return dkr
-}
-
func InitGlobalSettingsFile(directory string, password string) error {
var key [32]byte
salt, err := ioutil.ReadFile(path.Join(directory, saltFile))
if err != nil {
var newSalt [128]byte
- key, newSalt, err = createKeySalt(password)
+ key, newSalt, err = v1.CreateKeySalt(password)
if err != nil {
return err
}
@@ -68,7 +42,7 @@ func InitGlobalSettingsFile(directory string, password string) error {
return err
}
} else {
- key = createKey(password, salt)
+ key = v1.CreateKey(password, salt)
}
the.GlobalSettingsFile = v1.NewFileStore(directory, GlobalSettingsFilename, key)
diff --git a/i18n/translation_de.ts b/i18n/translation_de.ts
index b843b25d..5e0ea234 100644
--- a/i18n/translation_de.ts
+++ b/i18n/translation_de.ts
@@ -55,11 +55,16 @@
ContactList
-
+
ex: "... paste an address here to add a contact ..."
Adresse hier hinzufügen, um einen Kontakt aufzunehmen
+
+
+
+
+
GroupSettingsPane
@@ -227,38 +232,38 @@
PeerSettingsPane
-
+
Adresse
-
+
Kopieren
-
+
notification: copied to clipboard
in die Zwischenablage kopiert
-
+
Angezeigter Name
-
+
speichern
-
+
löschen
-
+
@@ -371,7 +376,7 @@
ProfileList
-
+
@@ -447,34 +452,34 @@
-
+
Groß
-
+
Theme
-
+
-
+
-
+
Version %1
-
+
Built on: %2
diff --git a/i18n/translation_en.qm b/i18n/translation_en.qm
index 49063bb7..295db41b 100644
Binary files a/i18n/translation_en.qm and b/i18n/translation_en.qm differ
diff --git a/i18n/translation_en.ts b/i18n/translation_en.ts
index 91af2302..d075bdc8 100644
--- a/i18n/translation_en.ts
+++ b/i18n/translation_en.ts
@@ -55,11 +55,16 @@
ContactList
-
+
ex: "... paste an address here to add a contact ..."
... paste an address here to add a contact...
+
+
+
+ Blocked
+
EmojiDrawer
@@ -322,33 +327,33 @@ Right-click to reset.
PeerSettingsPane
-
+
Address
-
+
Copy
-
+
notification: copied to clipboard
Copied to Clipboard
-
+
Display Name
-
+
Save
-
+
Block Peer
@@ -357,7 +362,7 @@ Right-click to reset.
Unblock Peer
-
+
Delete
@@ -478,7 +483,7 @@ Right-click to reset.
ProfileList
-
+
Add new profile
@@ -563,34 +568,34 @@ Right-click to reset.
Zoom level
-
+
Large
-
+
Theme
Theme
-
+
Light
-
+
Dark
-
+
Version %1
Version %1
-
+
Built on: %2
Built on: %2
diff --git a/i18n/translation_fr.ts b/i18n/translation_fr.ts
index 0193e6f0..f80bbf5b 100644
--- a/i18n/translation_fr.ts
+++ b/i18n/translation_fr.ts
@@ -55,11 +55,16 @@
ContactList
-
+
ex: "... paste an address here to add a contact ..."
... coller une adresse ici pour ajouter un contact...
+
+
+
+
+
GroupSettingsPane
@@ -227,38 +232,38 @@
PeerSettingsPane
-
+
Adresse
-
+
Copier
-
+
notification: copied to clipboard
Copié dans le presse-papier
-
+
Pseudo
-
+
Sauvegarder
-
+
Effacer
-
+
@@ -371,7 +376,7 @@
ProfileList
-
+
@@ -447,34 +452,34 @@
-
+
Large
-
+
Theme
-
+
-
+
-
+
Version %1
-
+
Built on: %2
diff --git a/i18n/translation_pt.ts b/i18n/translation_pt.ts
index 4bcda35a..0f7938bc 100644
--- a/i18n/translation_pt.ts
+++ b/i18n/translation_pt.ts
@@ -55,11 +55,16 @@
ContactList
-
+
ex: "... paste an address here to add a contact ..."
… cole um endereço aqui para adicionar um contato…
+
+
+
+
+
GroupSettingsPane
@@ -227,38 +232,38 @@
PeerSettingsPane
-
+
Endereço
-
+
Copiar
-
+
notification: copied to clipboard
Copiado
-
+
Nome de Exibição
-
+
Salvar
-
+
Deletar
-
+
@@ -371,7 +376,7 @@
ProfileList
-
+
@@ -447,34 +452,34 @@
-
+
Grande
-
+
Theme
-
+
-
+
-
+
Version %1
-
+
Built on: %2
diff --git a/qml/const/Const.qml b/qml/const/Const.qml
new file mode 100644
index 00000000..f4f48631
--- /dev/null
+++ b/qml/const/Const.qml
@@ -0,0 +1,12 @@
+pragma Singleton
+
+import QtQuick 2.0
+
+Item {
+
+ // defined in cwtch.im/cwtch/model/profile.go ln24
+ readonly property string auth_unknown: "unknown"
+ readonly property string auth_blocked: "blocked"
+ readonly property string auth_approved: "approved"
+
+}
diff --git a/qml/const/qmldir b/qml/const/qmldir
new file mode 100644
index 00000000..4830b8b4
--- /dev/null
+++ b/qml/const/qmldir
@@ -0,0 +1 @@
+singleton Const 1.0 Const.qml
\ No newline at end of file
diff --git a/qml/main.qml b/qml/main.qml
index bcd04f89..6b033d8d 100644
--- a/qml/main.qml
+++ b/qml/main.qml
@@ -348,8 +348,6 @@ ApplicationWindow {
if (Qt.application.state == 4) {
// Active
gcd.onActivate()
- console.log(Fonts.applicationFontRegular.name)
- console.log(Fonts.applicationFontBold.name)
}
}
}
diff --git a/qml/opaque b/qml/opaque
index 0ec6a2df..12d74e8f 160000
--- a/qml/opaque
+++ b/qml/opaque
@@ -1 +1 @@
-Subproject commit 0ec6a2df571e1a9c462d902cfc89f2402a9bef97
+Subproject commit 12d74e8f9756e62b1a41e1da18041cfdc2e0c7a4
diff --git a/qml/panes/PeerSettingsPane.qml b/qml/panes/PeerSettingsPane.qml
index b6b9904c..dffded18 100644
--- a/qml/panes/PeerSettingsPane.qml
+++ b/qml/panes/PeerSettingsPane.qml
@@ -10,12 +10,13 @@ import QtQuick.Controls.Styles 1.4
import "../opaque" as Opaque
import "../opaque/styles"
import "../opaque/theme"
+import "../const"
Opaque.SettingsList { // settingsPane
id: root
anchors.fill: parent
- property bool blocked
+ property string authorization
settings: Column {
anchors.fill: parent
@@ -59,8 +60,6 @@ Opaque.SettingsList { // settingsPane
}
-
-
Opaque.Setting {
label: qsTr("block-btn")
@@ -68,15 +67,19 @@ Opaque.SettingsList { // settingsPane
field: Opaque.ToggleSwitch {
anchors.right: parent.right
- isToggled: root.blocked // ? qsTr("unblock-btn") : qsTr("block-btn")
+ isToggled: root.authorization == Const.auth_blocked
onToggled: function() {
- if (root.blocked) {
- gcd.unblockPeer(txtOnion.text)
+ console.log("peer block toddle for " + txtOnion.text + " currently: " + root.authorization)
+ if (root.authorization == Const.auth_blocked) {
+ root.authorization = Const.auth_unknown
+ console.log("setPeerAuthorization to " + Const.auth_unknown + " for " + txtOnion.text)
+ gcd.setPeerAuthorization(txtOnion.text, Const.auth_unknown)
} else {
- gcd.blockPeer(txtOnion.text)
+ root.authorization = Const.auth_blocked
+ console.log("setPeerAuthorization to " + Const.auth_blocked + " for " + txtOnion.text)
+ gcd.setPeerAuthorization(txtOnion.text, Const.auth_blocked)
}
- root.blocked = !root.blocked
- isToggled = root.blocked
+ isToggled = root.authorization == Const.auth_blocked
}
}
}
@@ -103,10 +106,10 @@ Opaque.SettingsList { // settingsPane
Connections {
target: gcd
- onSupplyPeerSettings: function(onion, nick, blocked) {
+ onSupplyPeerSettings: function(onion, nick, authorization) {
txtOnion.text = onion
txtDisplayName.text = nick
- root.blocked = blocked
+ root.authorization = authorization
}
}
diff --git a/qml/panes/SettingsPane.qml b/qml/panes/SettingsPane.qml
index 914d967f..35342804 100644
--- a/qml/panes/SettingsPane.qml
+++ b/qml/panes/SettingsPane.qml
@@ -193,43 +193,6 @@ text: qsTr("block-unknown-label")
}
}
}
-
-
-=======
-}
-
-
-/* Opaque.ScalingLabel {
-width: parent.width
-wrapMode: TextEdit.Wrap
-//: Interface zoom (mostly affects text and button sizes)
-text: qsTr("zoom-label") + ":"
-}
-
-
-
-
-CheckBox {
-id: blockUnknownToggle
-checked: true
-onClicked: {
-if (blockUnknownToggle.checked) {
-gcd.blockUnknownPeers()
-} else {
-gcd.allowUnknownPeers()
-}
-}
-style: CheckBoxStyle {
-label: Opaque.ScalingLabel {
-text: qsTr("block-unknown-label")
-}
-}
-}
-
-
->>>>>>> 007b851f... Add global settings pane; migrate peer settings to new opaque settings widgets; minor fixes; add global settings storage; rework global settings settings
-
-
*/
diff --git a/qml/widgets/ContactList.qml b/qml/widgets/ContactList.qml
index f2cf8fdf..1ab55ed8 100644
--- a/qml/widgets/ContactList.qml
+++ b/qml/widgets/ContactList.qml
@@ -6,11 +6,13 @@ import QtQuick.Layouts 1.3
import "../opaque" as Opaque
import "../opaque/theme"
+import "../const"
ColumnLayout {
id: root
property alias dualPane: myprof.dualPane
+ property real logscale: 4 * Math.log10(gcd.themeScale + 1)
spacing: 10
@@ -26,6 +28,16 @@ ColumnLayout {
id: myprof
}
+ function removeContact(model, handle) {
+ for(var i = 0; i < model.count; i++){
+ if(model.get(i)["_handle"] == handle) {
+ model.remove(i)
+ return true
+ }
+ }
+ return false
+ }
+
Opaque.IconTextField {
id: searchAddText
@@ -64,7 +76,6 @@ ColumnLayout {
contentWidth: colContacts.width
contentHeight: colContacts.height
boundsBehavior: Flickable.StopAtBounds
- maximumFlickVelocity: 400
ScrollBar.vertical: ScrollBar {
policy: ScrollBar.AsNeeded
@@ -80,6 +91,8 @@ ColumnLayout {
}
}
+
+
ColumnLayout {
id: colContacts
width: root.width
@@ -88,17 +101,30 @@ ColumnLayout {
Connections { // ADD/REMOVE CONTACT ENTRIES
target: gcd
- onAddContact: function(handle, displayName, image, badge, status, blocked, loading, lastMsgTs) {
+ onAddContact: function(handle, displayName, image, badge, status, authorization, loading, lastMsgTs) {
- for (var i = 0; i < contactsModel.count; i++) {
- if (contactsModel.get(i)["_handle"] == handle) {
+ var model = contactsModel
+ if (authorization == Const.auth_blocked) {
+ model = blockedContactsModel
+ }
+
+ for (var i = 0; i < model.count; i++) {
+ if (model.get(i)["_handle"] == handle) {
return
}
}
- var index = contactsModel.count
- for (var i = 0; i < contactsModel.count; i++) {
- if (contactsModel.get(i)["_lastMsgTs"] < lastMsgTs) {
+ // Sort order: [unknown,authed][most recent message]
+ var index = model.count
+ for (var i = 0; i < model.count; i++) {
+ var contact = model.get(i)
+
+ if (contact["_authorization"] == authorization) {
+ if (contact["_lastMsgTs"] < lastMsgTs) {
+ index = i
+ break
+ }
+ } else if (authorization == Const.auth_unknown) {
index = i
break
}
@@ -106,26 +132,23 @@ ColumnLayout {
var newContact = {
"_handle": handle,
- "_displayName": displayName + (blocked ? " (blocked)" : "" ),
+ "_displayName": displayName,
"_image": image,
"_badge": badge,
"_status": status,
- "_blocked": blocked,
+ "_authorization": authorization,
"_loading": loading,
"_loading": loading,
"_lastMsgTs": lastMsgTs
}
- contactsModel.insert(index, newContact)
+ model.insert(index, newContact)
}
onRemoveContact: function(handle) {
- for(var i = 0; i < contactsModel.count; i++){
- if(contactsModel.get(i)["_handle"] == handle) {
- console.log("deleting contact " + contactsModel.get(i)["_handle"])
- contactsModel.remove(i)
- return
- }
+ var removed = root.removeContact(contactsModel, handle)
+ if (!removed) {
+ root.removeContact(blockedContactsModel, handle)
}
}
@@ -142,6 +165,7 @@ ColumnLayout {
onResetProfile: function() {
contactsModel.clear()
+ blockedContactsModel.clear()
}
}
@@ -150,6 +174,7 @@ ColumnLayout {
}
Repeater {
+ id: contactRepeater
model: contactsModel // ... AND DISPLAYED HERE
delegate: ContactRow {
handle: _handle
@@ -157,17 +182,117 @@ ColumnLayout {
image: _image
badge: _badge
status: _status
- blocked: _blocked
+ authorization: _authorization
loading: _loading
+ rowColor: (_authorization == Const.auth_unknown) ? Theme.backgroundHilightElementColor : Theme.backgroundMainColor
}
}
+
+ Item {
+ id: blockItem
+ height: blockedToggle.height
+ Layout.fillWidth: true
+ visible: blockedContactsModel.count > 0
+
+ MouseArea {
+ anchors.fill: blockItem
+
+ hoverEnabled: true
+
+ onClicked: {
+ blockedToggle.showing = !blockedToggle.showing
+ if (blockedToggle.showing) {
+ hideBlocked.stop()
+ openBlocked.start()
+ } else {
+ openBlocked.stop()
+ hideBlocked.start()
+ }
+ }
+
+ SequentialAnimation { id: openBlocked
+ PropertyAnimation {target: blockedContacts; property: "implicitHeight"; to: blockedContacts.childrenRect.height; duration: 100 }
+ PropertyAnimation {target: sv; property: "contentY"; to: sv.contentY + (40 * logscale); duration: 200}
+ }
+
+ PropertyAnimation { id: hideBlocked; target: blockedContacts; property: "implicitHeight"; to: 0; duration: 200 }
+
+ onEntered: {
+ blockedBG.color = Theme.backgroundPaneColor
+ }
+
+ onExited: {
+ blockedBG.color = Theme.backgroundMainColor
+ }
+ }
+
+ Rectangle {
+ id: blockedBG
+ property bool isHover: false
+
+ anchors.fill: blockItem
+ color: Theme.backgroundMainColor
+ }
+
+ Row {
+ id: blockedToggle
+ property bool showing: true
+
+ leftPadding: 32 * logscale
+ topPadding: 16 * logscale
+ bottomPadding: 8 * logscale
+ spacing: 5 * logscale
+
+ Opaque.ScalingLabel {
+ id: blockLbl
+
+ text: qsTr("blocked")
+ size: Theme.chatMetaTextSize
+ color: Theme.portraitBlockedTextColor
+ }
+
+ Opaque.ScalingLabel {
+ id: blockBtn
+
+ text: blockedToggle.showing ? "▲" : "▼"
+ size: Theme.chatMetaTextSize
+ color: Theme.portraitBlockedTextColor
+ }
+ }
+ }
+
+
+ ListModel {
+ id: blockedContactsModel
+ }
+
+ Item {
+ id: blockedContacts
+
+ anchors.left: parent.left
+ anchors.right: parent.right
+ height: childrenRect.height
+ implicitHeight: childrenRect.height
+
+ property real logscale: 4 * Math.log10(gcd.themeScale + 1)
+
+ Repeater {
+ id: blockedContactsRepeater
+ model: blockedContactsModel // ... AND DISPLAYED HERE
+ delegate: ContactRow {
+ handle: _handle
+ displayName: _displayName
+ image: _image
+ badge: _badge
+ status: _status
+ authorization: _authorization
+ loading: _loading
+ rowColor: Theme.backgroundHilightElementColor
+ }
+ }
+ }
}
}
-
-
}
-
-
-
diff --git a/qml/widgets/ContactRow.qml b/qml/widgets/ContactRow.qml
index 061fe130..4be5090b 100644
--- a/qml/widgets/ContactRow.qml
+++ b/qml/widgets/ContactRow.qml
@@ -10,11 +10,16 @@ import QtQuick.Controls.Styles 1.4
import "../opaque" as Opaque
import "../opaque/styles"
import "../opaque/theme"
+import "../const"
Opaque.PortraitRow {
property int status: 0
property int badge
property bool loading
+ property string authorization
+
+ // TODO: should be in ContactRow
+ property bool blocked
badgeColor: Theme.portraitContactBadgeColor
badgeVisible: badge > 0
@@ -48,6 +53,35 @@ Opaque.PortraitRow {
}
}
+ Column {
+ visible: authorization == Const.auth_unknown
+ anchors.right: parent.right
+ anchors.verticalCenter: parent.verticalCenter
+ anchors.leftMargin: 1 * gcd.themeScale
+ anchors.rightMargin: 25 * gcd.themeScale
+ spacing: 16 * gcd.themeScale
+
+ Opaque.Icon {
+ source: gcd.assetPath + "core/favorite-24px.svg"
+ iconColor: Theme.toolbarIconColor
+ backgroundColor: rowColor
+ height: 18 * gcd.themeScale
+ width: 18 * gcd.themeScale
+
+ onClicked: { gcd.setPeerAuthorization(handle, Const.auth_approved)}
+ }
+
+ Opaque.Icon {
+ source: gcd.assetPath + "core/delete-24px.svg"
+ iconColor: Theme.toolbarIconColor
+ backgroundColor: rowColor
+ height: 18 * gcd.themeScale
+ width: 18 * gcd.themeScale
+
+ onClicked: { console.log("approve"); gcd.setPeerAuthorization(handle, Const.auth_blocked)}
+ }
+ }
+
onClicked: function(handle) {
gcd.broadcast("ResetMessagePane")
isActive = true
@@ -65,7 +99,13 @@ Opaque.PortraitRow {
function setColors(status) {
//-2:WtfCodeError,-1:Error,0:Disconnected,1:Connecting,2:Connected,3:Authenticated,4:Synced,5:Failed,6:Killed
- if (status == 4 || status == 3) {
+
+ if (authorization == Const.auth_blocked) {
+ portraitBorderColor = Theme.portraitBlockedBorderColor
+ portraitColor = Theme.portraitBlockedBackgroundColor
+ nameColor = Theme.portraitBlockedTextColor
+ onionColor = Theme.portraitBlockedTextColor
+ } else if (status == 4 || status == 3) {
portraitBorderColor = Theme.portraitOnlineBorderColor
portraitColor = Theme.portraitOnlineBackgroundColor
nameColor = Theme.portraitOnlineTextColor
diff --git a/qml/widgets/ProfileList.qml b/qml/widgets/ProfileList.qml
index 1a65846c..05ad86bb 100644
--- a/qml/widgets/ProfileList.qml
+++ b/qml/widgets/ProfileList.qml
@@ -98,7 +98,6 @@ ColumnLayout {
handle: _handle
displayName: _displayName
image: _image
- blocked: false
tag: _tag
}
}