restoring cwtch-specific widgets that were accidentally moved to opaque
the build was successful Details

This commit is contained in:
erinn 2020-05-19 18:39:57 -07:00
parent 282cc9d516
commit 533b0d3fe0
6 changed files with 800 additions and 0 deletions

171
qml/widgets/ContactList.qml Normal file
View File

@ -0,0 +1,171 @@
import QtGraphicalEffects 1.0
import QtQuick 2.7
import QtQuick.Controls 2.4
import QtQuick.Controls.Material 2.0
import QtQuick.Layouts 1.3
import "theme"
ColumnLayout {
id: root
property alias dualPane: myprof.dualPane
spacing: 10
MouseArea {
anchors.fill: parent
onClicked: {
forceActiveFocus()
}
}
MyProfile { // CURRENT PROFILE INFO AND CONTROL BAR
id: myprof
}
IconTextField {
id: searchAddText
anchors.horizontalCenter: parent.horizontalCenter
Layout.minimumWidth: parent.width - 60
Layout.maximumWidth: parent.width - 60
//: ex: "... paste an address here to add a contact ..."
placeholderText: qsTr("paste-address-to-add-contact")
horizontalAlignment: TextInput.AlignHCenter
icon: gcd.assetPath + "core/search-24px.svg"
onTextChanged: {
if (text != "") {
gcd.importString(text)
text = ""
}
}
}
Flickable { // THE ACTUAL CONTACT LIST
id: sv
//Layout.alignment: Qt.AlignLeft | Qt.AlignTop
clip: true
Layout.minimumHeight: 100
//Layout.maximumHeight: parent.height - 30
Layout.fillHeight: true
Layout.minimumWidth: parent.width
Layout.maximumWidth: parent.width
contentWidth: colContacts.width
contentHeight: colContacts.height
boundsBehavior: Flickable.StopAtBounds
maximumFlickVelocity: 400
ScrollBar.vertical: ScrollBar {
policy: ScrollBar.AsNeeded
background: Rectangle {
implicitWidth: 6
color: Theme.backgroundMainColor
}
contentItem: Rectangle {
implicitWidth: 6
implicitHeight:1
color: Theme.backgroundPaneColor
}
}
ColumnLayout {
id: colContacts
width: root.width
spacing: 0
Connections { // ADD/REMOVE CONTACT ENTRIES
target: gcd
onAddContact: function(handle, displayName, image, badge, status, blocked, loading, lastMsgTs) {
for (var i = 0; i < contactsModel.count; i++) {
if (contactsModel.get(i)["_handle"] == handle) {
return
}
}
var index = contactsModel.count
for (var i = 0; i < contactsModel.count; i++) {
if (contactsModel.get(i)["_lastMsgTs"] < lastMsgTs) {
index = i
break
}
}
var newContact = {
"_handle": handle,
"_displayName": displayName + (blocked ? " (blocked)" : "" ),
"_image": image,
"_badge": badge,
"_status": status,
"_blocked": blocked,
"_loading": loading,
"_loading": loading,
"_lastMsgTs": lastMsgTs
}
contactsModel.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
}
}
}
onIncContactUnreadCount: function(handle) {
var ts = Math.round((new Date()).getTime() / 1000);
for(var i = 0; i < contactsModel.count; i++){
if(contactsModel.get(i)["_handle"] == handle) {
var contact = contactsModel.get(i)
contact["_lastMsgTs"] = ts
contactsModel.move(i, 0, 1)
}
}
}
onResetProfile: function() {
contactsModel.clear()
}
}
ListModel { // CONTACT OBJECTS ARE STORED HERE ...
id: contactsModel
}
Repeater {
model: contactsModel // ... AND DISPLAYED HERE
delegate: ContactRow {
handle: _handle
displayName: _displayName
image: _image
badge: _badge
status: _status
blocked: _blocked
loading: _loading
}
}
}
}
}

102
qml/widgets/ContactRow.qml Normal file
View File

@ -0,0 +1,102 @@
import QtGraphicalEffects 1.0
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 "styles"
import "." as Widgets
import "theme"
import QtQuick.Controls 1.4
import QtQuick.Controls.Styles 1.4
PortraitRow {
property int status: 0
property int badge
property bool loading
badgeColor: Theme.portraitContactBadgeColor
badgeVisible: badge > 0
badgeContent: Label {
id: lblUnread
color: Theme.portraitContactBadgeTextColor
font.pixelSize: Theme.badgeTextSize * gcd.themeScale
font.weight: Font.Bold
text: badge > 99 ? "99+" : badge
}
ProgressBar { // LOADING ?
id: loadingProgress
property bool running
running: loading
visible: loading
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
anchors.leftMargin: 1 * gcd.themeScale
anchors.rightMargin: 25 * gcd.themeScale
height: parent.height * .1
width: 100 * gcd.themeScale
indeterminate: true
style: ProgressBarStyle {
progress: CwtchProgress { running: loadingProgress.running}
}
}
onClicked: function(handle) {
gcd.broadcast("ResetMessagePane")
isActive = true
theStack.pane = theStack.messagePane
gcd.loadMessagesPane(handle)
badge = 0
if (handle.length == 32) {
gcd.requestGroupSettings(handle)
}
}
Component.onCompleted: { setColors(status) }
onStatusChanged: { setColors(status) }
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) {
portraitBorderColor = Theme.portraitOnlineBorderColor
portraitColor = Theme.portraitOnlineBackgroundColor
nameColor = Theme.portraitOnlineTextColor
onionColor = Theme.portraitOnlineTextColor
} else if (status == 2 || status == 1) {
portraitBorderColor = Theme.portraitConnectingBorderColor
portraitColor = Theme.portraitConnectingBackgroundColor
nameColor = Theme.portraitConnectingTextColor
onionColor = Theme.portraitConnectingTextColor
} else {
portraitBorderColor = Theme.portraitOfflineBorderColor
portraitColor = Theme.portraitOfflineBackgroundColor
nameColor = Theme.portraitOfflineTextColor
onionColor = Theme.portraitOfflineTextColor
}
}
Connections { // UPDATE UNREAD MESSAGES COUNTER
target: gcd
onUpdateContactStatus: function(_handle, _status, _loading) {
if (handle == _handle) {
status = _status
loadingProgress.visible = loadingProgress.running = loading = _loading
}
}
onIncContactUnreadCount: function(handle) {
if (handle == _handle && gcd.selectedConversation != handle) {
badge++
}
}
}
}

192
qml/widgets/Message.qml Normal file
View File

@ -0,0 +1,192 @@
import QtGraphicalEffects 1.0
import QtQuick 2.7
import QtQuick.Controls 2.4
import QtQuick.Controls.Material 2.0
import QtQuick.Layouts 1.3
import "controls" as Awesome
Item {
id: root
anchors.left: fromMe ? undefined : parent.left
anchors.right: fromMe ? parent.right : undefined
height: Math.max(imgProfile.height, rectMessageBubble.height)
property string message
property string rawMessage
property string from
property string handle
property string displayName
property string messageID
property bool fromMe
property bool ackd
property alias timestamp: ts.text
property alias image: imgProfile.source
property string error
Connections {
target: gcd
onAcknowledged: function(mid) {
if (mid == messageID) {
root.ackd = true
}
}
onGroupSendError: function(mid, error) {
if (mid == messageID) {
root.error = error
}
}
}
Portrait {
id: imgProfile
anchors.left: parent.left
// TODO: currently unused?
//handle: root.from
visible: !fromMe
//showStatus: false
//highlight: ima.containsMouse
ToolTip.visible: ima.containsMouse
//: Click to DM
ToolTip.text: qsTr("dm-tooltip")
MouseArea {
id: ima
anchors.fill: parent
hoverEnabled: overlay.inGroup
onClicked: {
gcd.createContact(from)
gcd.broadcast("ResetMessagePane")
theStack.pane = theStack.messagePane
gcd.loadMessagesPane(from)
overlayStack.overlay = overlayStack.chatOverlay
}
}
}
Rectangle { // THIS IS JUST A PRETTY MESSAGE-HOLDING RECTANGLE
id: rectMessageBubble
height: colMessageBubble.height + 8
width: colMessageBubble.width + 6
color: fromMe ? "#B09CBC" : "#4B3557"
radius: 5
// the console will complain constantly about me setting these anchors, but qt only allows margins if they've been set to something
// a kludge to fix this would be to have spacers before/after and set the widths according to the side they're on ^ea
anchors.left: fromMe ? undefined : imgProfile.right //parent.left
anchors.right: fromMe ? parent.right : undefined
anchors.leftMargin: 5
anchors.rightMargin: 9
anchors.topMargin: 5
ColumnLayout {
id: colMessageBubble
Column { // combine these into one element or else childrenRect won't play nicely
TextEdit { // this is used as a helper to calculate the message box width
id: dummy
visible: false
padding: 6
leftPadding: 10
font.pixelSize: gcd.themeScale * 12
wrapMode: TextEdit.NoWrap
text: lbl.text
textFormat: Text.RichText
}
TextEdit { // this is the actual text display
id: lbl
text: parse(message, 12, true)
color: "#FFFFFF"
padding: 6
leftPadding: 10
font.pixelSize: gcd.themeScale * 12
selectByMouse: gcd.os != "android"
readOnly: true
width: Math.min(dummy.width, root.parent.width - (imgProfile.visible ? imgProfile.width : 0) - 40)
wrapMode: TextEdit.Wrap
textFormat: Text.RichText
}
}
RowLayout {
id: rowBottom
anchors.left: parent.left
anchors.right: parent.right
Label { // TIMESTAMP
id: ts
color: "#FFFFFF"
font.pixelSize: 10 * gcd.themeScale
anchors.left: parent.left
leftPadding: 10
}
Label { // DISPLAY NAME FOR GROUPS
color: "#FFFFFF"
font.pixelSize: 10 * gcd.themeScale
anchors.right: parent.right
text: displayName.length > 12 ? displayName.substr(0,12) + "..." : displayName
visible: !fromMe
ToolTip.text: from
ToolTip.visible: ma2.containsMouse
ToolTip.delay: 200
MouseArea {
id: ma2
anchors.fill: parent
hoverEnabled: true
}
}
Image { // ACKNOWLEDGEMENT ICON
id: ack
anchors.right: parent.right
source: root.error != "" ? gcd.assetPath + "fontawesome/regular/window-close.svg" : (root.ackd ? gcd.assetPath + "fontawesome/regular/check-circle.svg" : gcd.assetPath + "fontawesome/regular/hourglass.svg")
height: 10 * gcd.themeScale
sourceSize.height: 10 * gcd.themeScale
visible: fromMe
ToolTip.visible: ma.containsMouse
ToolTip.delay: 200
//: Could not send this message
ToolTip.text: root.error != "" ? qsTr("could-not-send-msg-error") + ":" + root.error : (root.ackd ? qsTr("acknowledged-label") : qsTr("pending-label"))
MouseArea {
id: ma
anchors.fill: parent
hoverEnabled: true
}
}
}
}
TextEdit {
id: copyhelper
visible: false
text: root.rawMessage
}
MouseArea {
anchors.fill: gcd.os == "android" ? parent : null
onPressAndHold: {
copyhelper.selectAll()
copyhelper.copy()
gcd.popup("message copied")
}
}
}
}

155
qml/widgets/MyProfile.qml Normal file
View File

@ -0,0 +1,155 @@
import QtGraphicalEffects 1.0
import QtQuick 2.7
import QtQuick.Controls 2.4
import QtQuick.Controls.Material 2.0
import QtQuick.Controls.Styles 1.4
import QtQuick.Layouts 1.3
import QtQuick.Window 2.11
import QtQuick.Controls 1.4
import "." as Widgets
import "styles"
import "theme"
Item {
id: root
anchors.fill: parent
width: parent.width
height: profile.height
implicitHeight: profile.height
property string image
property string nick
property string onion
property string tag
property bool dualPane: false
property real logscale: 4 * Math.log10(gcd.themeScale + 1)
onDualPaneChanged: { realignProfile() }
function realignProfile() {
if (dualPane) {
profile.height = 78 * logscale
portrait.baseWidth = 78 * logscale
portrait.height = 78 * logscale
portrait.anchors.horizontalCenter = undefined
portrait.anchors.left = profile.left
portrait.anchors.leftMargin = 25 * logscale
nameRow.anchors.right = undefined
nameRow.anchors.left = portrait.right
nameRow.anchors.top = undefined
nameRow.anchors.verticalCenter = portrait.verticalCenter
nameCenter.anchors.horizontalCenter = undefined
nameCenter.anchors.left = nameRow.left
} else {
profile.height = (150 * logscale)
portrait.baseWidth = 100 * logscale
portrait.height = 100 * logscale
portrait.anchors.left = undefined
portrait.anchors.leftMargin = undefined
portrait.anchors.horizontalCenter = profile.horizontalCenter
nameRow.anchors.left = profile.left
nameRow.anchors.right = profile.right
nameRow.anchors.verticalCenter = undefined
nameRow.anchors.top = portrait.bottom
nameCenter.anchors.left = undefined
nameCenter.anchors.horizontalCenter = nameRow.horizontalCenter
}
}
Rectangle {
anchors.left: parent.left
anchors.right: parent.right
width: parent.width
id: profile
color: Theme.backgroundMainColor
Portrait {
id: portrait
source: root.image
badgeColor: Theme.portraitProfileBadgeColor
portraitBorderColor: Theme.portraitOnlineBorderColor
portraitColor: Theme.portraitOnlineBackgroundColor
badgeContent: Image {// Profle Type
id: profiletype
source: tag == "v1-userPassword" ? gcd.assetPath + "/fontawesome/solid/lock.svg" : gcd.assetPath + "/fontawesome/solid/lock-open.svg"
height: Theme.badgeTextSize * gcd.themeScale
width: height
}
}
Rectangle {
id: nameRow
height: name.height
onWidthChanged: { name.textResize() }
color: Theme.backgroundMainColor
Rectangle {
id: nameCenter
width: name.width + addBtn.width
EllipsisLabel {
id: name
anchors.right: undefined
anchors.left: undefined
color: Theme.portraitOnlineTextColor
pixelSize: Theme.usernameSize * gcd.themeScale
weight: Font.Bold
text: nick
extraPadding: addBtn.width + 30
container: nameRow
}
Widgets.Button { // Add Button
id: addBtn
anchors.left: name.right
anchors.top: name.top
icon: "solid/plus"
height: name.height
width: height
radius: width * 0.3
onClicked: {
}
}
}
}
}
Connections {
target: gcd
onUpdateMyProfile: function(_nick, _onion, _image, _tag) {
nick = _nick
onion = _onion
image = _image
tag = _tag
//realignProfile()
}
onResetProfile: { realignProfile() }
}
}

124
qml/widgets/ProfileList.qml Normal file
View File

@ -0,0 +1,124 @@
import QtGraphicalEffects 1.0
import QtQuick 2.7
import QtQuick.Controls 2.4
import QtQuick.Controls.Material 2.0
import QtQuick.Layouts 1.3
import "theme"
ColumnLayout {
id: root
MouseArea {
anchors.fill: parent
onClicked: {
forceActiveFocus()
}
}
Flickable { // Profile List
id: sv
clip: true
Layout.minimumHeight: 100
Layout.fillHeight: true
Layout.minimumWidth: parent.width
Layout.maximumWidth: parent.width
contentWidth: colContacts.width
contentHeight: colContacts.height
boundsBehavior: Flickable.StopAtBounds
maximumFlickVelocity: 400
ScrollBar.vertical: ScrollBar {
policy: ScrollBar.AlwaysOn
}
ColumnLayout {
id: colContacts
width: root.width
spacing: 0
Connections { // ADD/REMOVE CONTACT ENTRIES
target: gcd
onAddProfile: function(handle, displayName, image, tag) {
// don't add duplicates
for (var i = 0; i < profilesModel.count; i++) {
if (profilesModel.get(i)["_handle"] == handle) {
return
}
}
// find index for insert (sort by onion)
var index = profilesModel.count
for (var i = 0; i < profilesModel.count; i++) {
if (profilesModel.get(i)["_handle"] > handle) {
index = i
break
}
}
profilesModel.insert(index,
{
_handle: handle,
_displayName: displayName,
_image: image,
_tag: tag,
_status: 4,
})
}
/*
onRemoveProfile: function(handle) {
for(var i = 0; i < profilesModel.count; i++){
if(profilesModel.get(i)["_handle"] == handle) {
console.log("deleting contact " + profilesModel.get(i)["_handle"])
profilesModel.remove(i)
return
}
}
}*/
onResetProfileList: function() {
profilesModel.clear()
}
}
ListModel { // Profile OBJECTS ARE STORED HERE ...
id: profilesModel
}
Repeater {
id: profileList
model: profilesModel // ... AND DISPLAYED HERE
delegate: ProfileRow {
handle: _handle
displayName: _displayName
image: _image
blocked: false
tag: _tag
}
}
PortraitRow {
handle: ""
displayName: qsTr("add-new-profile-btn")
nameColor: Theme.mainTextColor
image: "/fontawesome/regular/user.svg"
tag: ""
portraitBorderColor: Theme.portraitOnlineBorderColor
portraitColor: Theme.portraitOnlineBackgroundColor
badgeVisible: true
badgeContent: Image {
source: gcd.assetPath + "/fontawesome/solid/plus.svg"
height: Theme.badgeTextSize * gcd.themeScale
width: height
}
badgeColor: Theme.defaultButtonColor
onClicked: function(handle) { profileAddEditPane.reset(); parentStack.pane = parentStack.addEditProfilePane }
}
}
}
}

View File

@ -0,0 +1,56 @@
import QtGraphicalEffects 1.0
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 "styles"
import "." as Widgets
import "theme"
import QtQuick.Controls 1.4
import QtQuick.Controls.Styles 1.4
PortraitRow {
badgeColor: Theme.portraitProfileBadgeColor
portraitBorderColor: Theme.portraitOnlineBorderColor
portraitColor: Theme.portraitOnlineBackgroundColor
nameColor: Theme.portraitOnlineTextColor
onionColor: Theme.portraitOnlineTextColor
badgeContent: Image {// Profle Type
id: profiletype
source: tag == "v1-userPassword" ? gcd.assetPath + "/fontawesome/solid/lock.svg" : gcd.assetPath + "/fontawesome/solid/lock-open.svg"
height: Theme.badgeTextSize * gcd.themeScale
width: height
}
Widgets.Button {// Edit BUTTON
id: btnEdit
icon: "solid/user-edit"
anchors.right: parent.right
//rectUnread.left
anchors.verticalCenter: parent.verticalCenter
anchors.leftMargin: 1 * gcd.themeScale
anchors.rightMargin: 20 * gcd.themeScale
height: parent.height * 0.75
onClicked: {
profileAddEditPane.load(handle, displayName, tag)
parentStack.pane = parentStack.addEditProfilePane
}
}
onClicked: function openClick(handle) {
gcd.broadcast("ResetMessagePane");
gcd.broadcast("ResetProfile");
gcd.selectedProfile = handle
gcd.loadProfile(handle)
parentStack.pane = parentStack.profilePane
}
}