history warning and overlay model fixes
the build was successful Details

This commit is contained in:
erinn 2020-12-08 16:37:08 -08:00
parent 49bee4deb1
commit 1a556d05ce
11 changed files with 170 additions and 81 deletions

View File

@ -9,6 +9,7 @@ import (
"cwtch.im/ui/go/constants"
"cwtch.im/ui/go/features/groups"
"cwtch.im/ui/go/ui/android"
"encoding/json"
"github.com/therecipe/qt/qml"
"strconv"
"sync"
@ -143,7 +144,7 @@ type GrandCentralDispatcher struct {
_ func() `constructor:"init"`
// legacy overlay model support
_ func(onion string, overlay int) `signal:"legacyLoadOverlay,auto"`
_ func(onion string) `signal:"legacyLoadOverlay,auto"`
_ func(handle, from, displayName, message, image string, mID string, fromMe bool, ts int64, ackd bool, error bool) `signal:"AppendMessage"`
_ func(handle, from, displayName, message, image string, mID string, fromMe bool, ts int64, ackd bool, error bool) `signal:"PrependMessage"`
}
@ -334,20 +335,31 @@ func (this *GrandCentralDispatcher) loadMessagesPaneHelper(handle string) {
updateLastReadTime(contact.Onion)
this.SetToolbarTitle(nick)
this.legacyLoadOverlay(handle, 4)
this.legacyLoadOverlay(handle)
}
func (this *GrandCentralDispatcher) legacyLoadOverlay(handle string, overlay int) {
go this.legacyLoadOverlay_helper(handle, overlay)
func (this *GrandCentralDispatcher) legacyLoadOverlay(handle string) {
// only do this for overlays 2 (bulletin) and 4 (lists)
go this.legacyLoadOverlay_helper(handle, []int{2,4})
}
func (this *GrandCentralDispatcher) legacyLoadOverlay_helper(handle string, overlay int) {
func contains(arr []int, x int) bool {
for _, v := range arr {
if v == x {
return true
}
}
return false
}
func (this *GrandCentralDispatcher) legacyLoadOverlay_helper(handle string, overlays []int) {
if isGroup(handle) {
group := the.CwtchApp.GetPeer(this.selectedProfile()).GetGroup(handle)
tl := group.GetTimeline()
for i := len(tl) - 1; i >= 0; i-- {
if tl[i].PeerID == the.Peer.GetOnion() {
if tl[i].PeerID == this.selectedProfile() {
handle = "me"
} else {
handle = tl[i].PeerID
@ -356,18 +368,22 @@ func (this *GrandCentralDispatcher) legacyLoadOverlay_helper(handle string, over
name := GetNick(tl[i].PeerID)
image := GetProfilePic(tl[i].PeerID)
this.PrependMessage(
handle,
tl[i].PeerID,
name,
tl[i].Message,
image,
string(tl[i].Signature),
tl[i].PeerID == the.Peer.GetOnion(),
tl[i].Timestamp.Unix(),
tl[i].Received.Equal(time.Unix(0, 0)) == false, // If the received timestamp is epoch, we have not yet received this message through an active server
false,
)
obj := &OverlayJSONObject{}
err := json.Unmarshal([]byte(tl[i].Message), obj)
if err == nil && contains(overlays, obj.Overlay) {
this.PrependMessage(
handle,
tl[i].PeerID,
name,
tl[i].Message,
image,
string(tl[i].Signature),
tl[i].PeerID == this.selectedProfile(),
tl[i].Timestamp.Unix(),
tl[i].Received.Equal(time.Unix(0, 0)) == false, // If the received timestamp is epoch, we have not yet received this message through an active server
false,
)
}
}
} else {// !isGroup
@ -382,18 +398,22 @@ func (this *GrandCentralDispatcher) legacyLoadOverlay_helper(handle string, over
displayname := GetNick(messages[i].PeerID)
image := GetProfilePic(messages[i].PeerID)
this.PrependMessage(
from,
messages[i].PeerID,
displayname,
messages[i].Message,
image,
string(messages[i].Signature),
fromMe,
messages[i].Timestamp.Unix(),
messages[i].Acknowledged,
messages[i].Error != "",
)
obj := &OverlayJSONObject{}
err := json.Unmarshal([]byte(messages[i].Message), obj)
if err == nil && contains(overlays, obj.Overlay) {
this.PrependMessage(
from,
messages[i].PeerID,
displayname,
messages[i].Message,
image,
string(messages[i].Signature),
fromMe,
messages[i].Timestamp.Unix(),
messages[i].Acknowledged,
messages[i].Error != "",
)
}
}
}

View File

@ -4,6 +4,8 @@ import (
"cwtch.im/cwtch/model"
"cwtch.im/ui/go/the"
"encoding/hex"
//"encoding/hex"
"git.openprivacy.ca/openprivacy/log"
"github.com/therecipe/qt/core"
"reflect"
@ -20,6 +22,7 @@ type MessageModel struct {
_ map[int]*core.QByteArray `property:"roles"`
_ func() `constructor:"init"`
_ func(int) *MessageWrapper `slot:"getMessage,auto"`
_ func(int) `signal:"addMessage,auto"`
_ func(int) `signal:"editMessage,auto"`
_ func() `signal:"requestEIR,auto"`
@ -29,17 +32,22 @@ type MessageModel struct {
}
type MessageWrapper struct {
model.Message
core.QObject
model.Message
Timestamp int64
PeerID string
Acknowledged bool
RawMessage string
Error string
Day string
Signature string
_ bool `property:"ackd"`
_ int64 `property:"timestamp"`
_ string `property:"peerID"`
_ bool `property:"acknowledged"`
_ string `property:"rawMessage"`
_ string `property:"error"`
_ string `property:"day"`
_ string `property:"signature"`
_ bool `property:"ackd"`
}
type OverlayJSONObject struct {
Overlay int `json:"o"`
Data string `json:"d"`
}
func (this *MessageModel) Handle() string {
@ -51,13 +59,19 @@ func (this *MessageModel) setHandle(handle string) {
}
func (this *MessageModel) init() {
mdt := reflect.TypeOf([]MessageWrapper{}).Elem()
sacrificialObject := NewMessageWrapper(nil)
mdt := reflect.TypeOf(*sacrificialObject)
roles := make(map[int]*core.QByteArray)
for i := 0; i < mdt.NumField(); i++ {
if mdt.Field(i).Name == "Acknowledged" {
fieldName := mdt.Field(i).Name
if fieldName == "_" {
fieldName = mdt.Field(i).Tag.Get("property")
}
if fieldName == "acknowledged" {
this.ackIdx = int(core.Qt__UserRole) + 1 + i
}
roles[int(core.Qt__UserRole)+1+i] = core.NewQByteArray2(mdt.Field(i).Name, -1)
roles[int(core.Qt__UserRole)+1+i] = core.NewQByteArray2(fieldName, -1)
}
roles[int(core.Qt__DisplayRole)] = core.NewQByteArray2("display", -1)
this.SetRoles(roles)
@ -133,16 +147,17 @@ func (this *MessageModel) getMessage(idx int) *MessageWrapper {
}
}
return &MessageWrapper{
Message: modelmsg,
Timestamp: modelmsg.Timestamp.Unix(),
RawMessage: modelmsg.Message,
PeerID: modelmsg.PeerID,
Error: modelmsg.Error,
Acknowledged: ackd,
Day: modelmsg.Timestamp.Format("January 2, 2006"),
Signature: hex.EncodeToString(modelmsg.Signature),
}
mw := NewMessageWrapper(nil)
mw.Message = modelmsg
mw.SetTimestamp(modelmsg.Timestamp.Unix())
mw.SetPeerID(modelmsg.PeerID)
mw.SetError(modelmsg.Error)
mw.SetAcknowledged(ackd)
mw.SetAckd(ackd)//??why both??
mw.SetDay(modelmsg.Timestamp.Format("January 2, 2006"))
mw.SetSignature(hex.EncodeToString(modelmsg.Signature))
mw.SetRawMessage(modelmsg.Message)
return mw
}
func (this *MessageModel) data(index *core.QModelIndex, role int) *core.QVariant {

View File

@ -40,6 +40,7 @@ var (
func init() {
// make go-defined types available in qml
ui.GrandCentralDispatcher_QmlRegisterType2("CustomQmlTypes", 1, 0, "GrandCentralDispatcher")
ui.MessageWrapper_QmlRegisterType2("CustomQmlTypes", 1, 0, "MessageWrapper")
}
func main() {

@ -1 +1 @@
Subproject commit 365eedbd90eb936043e42f632355862d2a34c77a
Subproject commit dd8dde1fb38e296530570d31e95780ff707e2895

View File

@ -8,6 +8,7 @@ import QtQuick.Layouts 1.3
import "../opaque" as Opaque
import "../opaque/styles"
import "../opaque/theme"
import "../utils.js" as Utils
ColumnLayout {
@ -50,7 +51,18 @@ ColumnLayout {
maximumFlickVelocity: 800
Connections {
id: cnxns1
target: mm
onRowsInserted: {
var msg = mm.getMessage(first);
var name = msg.peerID == gcd.selectedProfile ? "me" : mm.getNick(msg.peerID);
cnxns2.handler(msg.peerID, msg.peerID, name, msg.rawMessage, mm.getImage(msg.peerID), msg.signature, msg.peerID == gcd.selectedProfile, msg.timestamp, msg.ack, msg.error)
}
}
Connections {
id: cnxns2
target: gcd
onClearMessages: function() {
@ -139,11 +151,11 @@ ColumnLayout {
}
Text {
id: texttitle
text: '<b>' + Utils.htmlEscaped(title) + '</b> by ' + from + "<br/>" + Qt.formatDateTime(new Date(timestamp*1000), "MMMM d, h:mm ap")
text: '<b>' + Utils.htmlEscaped(title) + '</b> by ' + displayName + "<br/>" + Qt.formatDateTime(new Date(timestamp*1000), "MMMM d, h:mm ap")
leftPadding: 10
topPadding: 5
bottomPadding:5
color: windowItem.cwtch_dark_color
color: Theme.mainTextColor
}
MouseArea {
anchors.fill: parent
@ -172,6 +184,7 @@ ColumnLayout {
leftPadding: 10
topPadding: 10
width: parent.width - 50
color: Theme.mainTextColor
}
Opaque.Button {
@ -212,6 +225,7 @@ ColumnLayout {
Text {
//: Post a new Bulletin Post
text: qsTr("post-new-bulletin-label")
color: Theme.mainTextColor
}
TextField {

View File

@ -3,6 +3,7 @@ import QtQuick 2.7
import QtQuick.Controls 2.4
import QtQuick.Controls.Material 2.0
import QtQuick.Layouts 1.3
import CustomQmlTypes 1.0
import "../opaque" as Opaque
import "../opaque/controls" as Awesome
@ -11,7 +12,9 @@ import "../widgets" as W
import "../opaque/theme"
W.Overlay {
id: overlayRoot
property bool loading
property string historyState: "DefaultDeleteHistory"
//horizontalPadding: 15 * gcd.themeScale
@ -59,8 +62,17 @@ W.Overlay {
header: Component {
Column {
width: messagesListView.width
Label {
width: messagesListView.width
font.pointSize: Theme.textSmallPt
font.weight: Font.Bold
color: Theme.chatOverlayWarningTextColor
horizontalAlignment: Text.AlignHCenter
text: overlayRoot.historyState
}
Label {
id: historyWarning
wrapMode: Text.WordWrap
width: messagesListView.width
font.pointSize: Theme.textSmallPt
@ -68,9 +80,12 @@ W.Overlay {
color: Theme.chatOverlayWarningTextColor
horizontalAlignment: Text.AlignHCenter
//: This conversation will be deleted when Cwtch is closed! Message history can be enabled per-conversation via the Settings menu in the upper right.
text: true ? qsTr("chat-history-disabled") :
//: Message history is enabled.
qsTr("chat-history-enabled")
text: overlayRoot.historyState == "DefaultDeleteHistory" ? qsTr("chat-history-default") : (
//: Message history is disabled.
overlayRoot.historyState == "DeleteHistoryConfirmed" ? qsTr("chat-history-disabled") :
//: Message history is enabled.
qsTr("chat-history-enabled")
)
}
Opaque.Icon {
@ -89,20 +104,26 @@ W.Overlay {
}
}
delegate: W.Message {
handle: PeerID
from: PeerID
displayName: mm.getNick(PeerID)
message: JSON.parse(RawMessage).d
rawMessage: RawMessage
image: mm.getImage(PeerID)
messageID: Signature
fromMe: PeerID == gcd.selectedProfile
timestamp: parseInt(Timestamp)
ackd: Acknowledged
error: Error
calendarEvent: PeerID == "calendar"
// unusual msg... syntax is due to qt stack weirdnesses
// model injection doesn't work properly because MessageWrapper uses tagged QML properties
// but reverting to struct properties prevents us from using mm.getMessage() in onRowsInserted sooooo
property variant msg: mm.getMessage(index)
property variant obj: JSON.parse(msg.rawMessage)
visible: obj.o == 1
height: visible ? implicitHeight : -messagesListView.spacing
handle: msg.peerID
from: msg.peerID
displayName: mm.getNick(msg.peerID)
message: obj.o == 1 ? obj.d : ""
//rawMessage: msg.rawMessage
image: mm.getImage(msg.peerID)
messageID: msg.signature
fromMe: msg.peerID == gcd.selectedProfile
timestamp: parseInt(msg.timestamp)
//ackd: acknowledged
//error: msg.error
calendarEvent: msg.peerID == "calendar"
// listview doesnt do anchors right
// https://stackoverflow.com/questions/31381997/why-does-anchors-fill-does-not-work-in-a-qml-listviews-delegates-subviews-and/31382307
width: messagesListView.width - scrollbar.width
@ -159,6 +180,10 @@ W.Overlay {
messagesListView.positionViewAtEnd()
thymer.running = true
}
onSupplyPeerSettings: function(onion, nick, authorization, saveHistory) {
overlayRoot.historyState = saveHistory
}
}
}

View File

@ -4,6 +4,7 @@ import QtQuick.Controls 2.4
import QtQuick.Controls.Material 2.0
import QtQuick.Controls 1.4
import QtQuick.Layouts 1.3
import CustomQmlTypes 1.0
import "../opaque" as Opaque
import "../opaque/controls" as Awesome
@ -28,7 +29,7 @@ ColumnLayout {
anchors.right: parent.right
anchors.margins: 10
//: ex: "... paste an address here to add a contact ..."
//: ex: "Find..."
placeholderText: qsTr("search-list")
horizontalAlignment: TextInput.AlignHCenter
icon: gcd.assetPath + "core/search-24px.webp"
@ -78,7 +79,18 @@ ColumnLayout {
maximumFlickVelocity: 800
Connections {
id: cnxns1
target: mm
onRowsInserted: {
var msg = mm.getMessage(first);
var name = msg.peerID == gcd.selectedProfile ? "me" : mm.getNick(msg.peerID);
cnxns2.handler(msg.peerID, msg.peerID, name, msg.rawMessage, mm.getImage(msg.peerID), msg.signature, msg.peerID == gcd.selectedProfile, msg.timestamp, msg.ack, msg.error)
}
}
Connections {
id: cnxns2
target: gcd
onClearMessages: function() {

View File

@ -82,14 +82,11 @@ Opaque.SettingsList { // settingsPane
isToggled: root.authorization == Const.auth_blocked
onToggled: function() {
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 {
root.authorization = Const.auth_blocked
console.log("setPeerAuthorization to " + Const.auth_blocked + " for " + txtOnion.text)
gcd.setPeerAuthorization(txtOnion.text, Const.auth_blocked)
}
isToggled = root.authorization == Const.auth_blocked

View File

@ -12,7 +12,8 @@ import "../opaque/fonts"
Rectangle {
id: root
height: Math.max(imgProfile.height, rectMessageBubble.height)
implicitHeight: Math.max(imgProfile.height, rectMessageBubble.height)
height: implicitHeight
color: Theme.backgroundMainColor
property string message

View File

@ -79,6 +79,10 @@ ColumnLayout {
id: statusText
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
width: parent.width - 2 * Theme.paddingMinimal
horizontalAlignment: Text.AlignHCenter
elide: Text.ElideRight
wrapMode: Text.NoWrap
text: ""
visible: text != ""
size: Theme.chatMetaTextSize

View File

@ -28,12 +28,12 @@ Item {
id: control
width: parent.width
anchors.top: parent.top
anchors.topMargin: 10 * gcd.themeScale
anchors.topMargin: 10
anchors.bottom: msgEd.top
anchors.bottomMargin: 10 * gcd.themeScale
anchors.bottomMargin: 10
horizontalPadding: 15 * gcd.themeScale
horizontalPadding: 15
}
@ -44,8 +44,8 @@ Item {
anchors.bottom: parent.bottom
anchors.right: parent.right
anchors.left: parent.left
anchors.rightMargin: 15 * gcd.themeScale
anchors.leftMargin: 15 * gcd.themeScale
anchors.rightMargin: 15
anchors.leftMargin: 15
onSendClicked: function(messageText) {
root.sendClicked(messageText)