Merge pull request 'new qmlfmt script and test application to main.qml' (#280) from dan/ui:qmlfmt into master
the build was successful Details

This commit is contained in:
Sarah Jamie Lewis 2020-04-27 15:18:26 -07:00
commit 73d8951d6e
45 changed files with 2556 additions and 2462 deletions

86
cmd/qmlfmt/main.go Normal file
View File

@ -0,0 +1,86 @@
package main
import (
"bufio"
"log"
"os"
"strings"
)
const (
indent = " "
)
func main() {
if len(os.Args) < 2 {
log.Fatal("Required argument(s): filename(s)")
}
for _, filename := range os.Args[1:] {
processFile(filename)
}
}
func processFile(filename string) {
file, err := os.Open(filename)
if err != nil {
log.Fatalf("Could not read file %v: %v\n", filename, err)
}
scanner := bufio.NewScanner(file)
var lines []string
for scanner.Scan() {
lines = append(lines, scanner.Text())
}
file.Close()
file, err = os.Create(filename)
defer file.Close()
if err != nil {
log.Fatalf("Could not write to file %v: %v\n", filename, err)
}
indentCount := 0
inMultiLineComment := false
for _, line := range lines {
singleCommentPos := strings.Index(line, "//")
multiLineCommentStartPos := strings.Index(line, "/*")
multiLineCommentEndPos := strings.Index(line, "*/")
closePos := strings.Index(line, "}")
if !inMultiLineComment && closePos > -1 && (singleCommentPos == -1 || closePos < singleCommentPos) &&
(multiLineCommentStartPos == -1 || closePos < multiLineCommentStartPos) &&
(multiLineCommentEndPos == -1 || closePos > multiLineCommentEndPos) {
indentCount--
}
trimedLine := strings.Trim(line, " \t")
if trimedLine == "" {
file.Write([]byte("\n"))
} else {
file.Write([]byte(strings.Repeat(indent, indentCount) + trimedLine + "\n"))
}
openPos := strings.Index(line, "{")
if !inMultiLineComment && openPos > -1 && (singleCommentPos == -1 || openPos < singleCommentPos) &&
(multiLineCommentStartPos == -1 || openPos < multiLineCommentStartPos) &&
(multiLineCommentEndPos == -1 || openPos > multiLineCommentEndPos) {
indentCount++
}
if multiLineCommentStartPos > -1 {
inMultiLineComment = true
}
if multiLineCommentEndPos > -1 {
inMultiLineComment = false
}
}
}

View File

@ -1,6 +1,6 @@
pragma Singleton pragma Singleton
import QtQuick 2.5 import QtQuick 2.5
QtObject { QtObject {
@ -24,4 +24,4 @@ QtObject {
source: "qrc:/qml/fonts/opensans/OpenSans-Light.ttf" source: "qrc:/qml/fonts/opensans/OpenSans-Light.ttf"
} }
} }

View File

@ -17,61 +17,61 @@ import "utils.js" as Utils
ApplicationWindow { ApplicationWindow {
id: windowItem id: windowItem
width: 1200 width: 1200
height: 800 height: 800
visible: true visible: true
title: "cwtch" + "" title: "cwtch" + ""
font.family: Fonts.applicationFontRegular.name font.family: Fonts.applicationFontRegular.name
font.styleName: "Light" font.styleName: "Light"
readonly property real ratio: height / width readonly property real ratio: height / width
readonly property string cwtch_background_color: '#FF0000' readonly property string cwtch_background_color: '#FF0000'
readonly property string cwtch_color: '#00FF00' readonly property string cwtch_color: '#00FF00'
readonly property string cwtch_dark_color: '#0000FF' readonly property string cwtch_dark_color: '#0000FF'
FontAwesome { // PRETTY BUTTON ICONS FontAwesome { // PRETTY BUTTON ICONS
id: awesome id: awesome
resource: "qrc:/qml/fonts/fontawesome.ttf" resource: "qrc:/qml/fonts/fontawesome.ttf"
} }
FontLoader { FontLoader {
source: "qrc:/qml/fonts/AdobeBlank.ttf" source: "qrc:/qml/fonts/AdobeBlank.ttf"
} }
function parse(text, size, isntEditable) { // REPLACE EMOJI WITH <IMG> TAGS function parse(text, size, isntEditable) { // REPLACE EMOJI WITH <IMG> TAGS
T.twemoji.base = gcd.assetPath + "twemoji/" T.twemoji.base = gcd.assetPath + "twemoji/"
T.twemoji.ext = ".png" T.twemoji.ext = ".png"
T.twemoji.size = "72x72" T.twemoji.size = "72x72"
T.twemoji.className = "\" height=\""+size+"\" width=\""+size T.twemoji.className = "\" height=\""+size+"\" width=\""+size
var retText = T.twemoji.parse(Utils.htmlEscaped(text)) var retText = T.twemoji.parse(Utils.htmlEscaped(text))
retText = retText.replace(/\n/g,"<br/>") retText = retText.replace(/\n/g,"<br/>")
// mutant standard stickers // mutant standard stickers
if (isntEditable) retText = Mutant.standard.parse(retText) if (isntEditable) retText = Mutant.standard.parse(retText)
return retText return retText
} }
function restoreEmoji(text) { // REPLACE <IMG> TAGS WITH EMOJI function restoreEmoji(text) { // REPLACE <IMG> TAGS WITH EMOJI
var re = RegExp('<img src="' + gcd.assetPath + 'twemoji/72x72/([^"]*?)\.png" width="10" height="10" \/>', 'g') var re = RegExp('<img src="' + gcd.assetPath + 'twemoji/72x72/([^"]*?)\.png" width="10" height="10" \/>', 'g')
var arr var arr
var newtext = text var newtext = text
while (arr = re.exec(text)) { while (arr = re.exec(text)) {
var pieces = arr[1].split("-") var pieces = arr[1].split("-")
var replacement = "" var replacement = ""
for (var i = 0; i < pieces.length; i++) { for (var i = 0; i < pieces.length; i++) {
replacement += T.twemoji.convert.fromCodePoint(pieces[i]) replacement += T.twemoji.convert.fromCodePoint(pieces[i])
} }
newtext = newtext.replace(arr[0], replacement) newtext = newtext.replace(arr[0], replacement)
} }
return newtext return newtext
} }
function ptToPx(pt) { function ptToPx(pt) {
return Screen.pixelDensity * 25.4 * pt / 72 return Screen.pixelDensity * 25.4 * pt / 72
@ -109,14 +109,14 @@ ApplicationWindow {
} }
Rectangle { // Profile login/management pane Rectangle { // Profile login/management pane
anchors.fill: parent anchors.fill: parent
visible: false visible: false
color: Theme.backgroundMainColor color: Theme.backgroundMainColor
ProfileManagerPane { ProfileManagerPane {
id: profilesPane id: profilesPane
anchors.fill: parent anchors.fill: parent
} }
} }
Rectangle { // Profile login/management pane Rectangle { // Profile login/management pane
@ -171,20 +171,20 @@ ApplicationWindow {
property string title property string title
Item { anchors.fill: parent } // empty Item { anchors.fill: parent } // empty
OverlayPane { // messagePane OverlayPane { // messagePane
title: theStack.title title: theStack.title
anchors.fill: parent anchors.fill: parent
} }
SettingsPane{ anchors.fill: parent } SettingsPane{ anchors.fill: parent }
PeerSettingsPane { anchors.fill: parent } PeerSettingsPane { anchors.fill: parent }
GroupSettingsPane{ anchors.fill: parent } GroupSettingsPane{ anchors.fill: parent }
AddGroupPane { anchors.fill: parent } AddGroupPane { anchors.fill: parent }
} }
} }
} }
@ -202,56 +202,56 @@ ApplicationWindow {
} }
} }
} }
} }
PropertyAnimation { id: anmPopup; easing.type: Easing.InQuart; duration: 7000; target: popup; property: "opacity"; to: 0; } PropertyAnimation { id: anmPopup; easing.type: Easing.InQuart; duration: 7000; target: popup; property: "opacity"; to: 0; }
Rectangle { // THE ERROR MESSAGE POPUP Rectangle { // THE ERROR MESSAGE POPUP
id: popup id: popup
anchors.top: parent.top anchors.top: parent.top
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
anchors.topMargin: 20 anchors.topMargin: 20
width: lblPopup.width + 30 width: lblPopup.width + 30
height: lblPopup.height + 8 * gcd.themeScale height: lblPopup.height + 8 * gcd.themeScale
color: "#000000" color: "#000000"
opacity: 0.5 opacity: 0.5
radius: 15 radius: 15
visible: false visible: false
Label { Label {
id: lblPopup id: lblPopup
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
font.pixelSize: 18 * gcd.themeScale font.pixelSize: 18 * gcd.themeScale
color: "#FFFFFF" color: "#FFFFFF"
} }
} }
Connections { // POPUPS ARE INVOKED BY GO FUNCS Connections { // POPUPS ARE INVOKED BY GO FUNCS
target: gcd target: gcd
onInvokePopup: function(str) { onInvokePopup: function(str) {
lblPopup.text = str lblPopup.text = str
popup.opacity = 0.5 popup.opacity = 0.5
popup.visible = true popup.visible = true
anmPopup.restart() anmPopup.restart()
} }
onSetToolbarTitle: function(str) { onSetToolbarTitle: function(str) {
theStack.title = str theStack.title = str
} }
onLoaded: function() { onLoaded: function() {
parentStack.pane = parentStack.managementPane parentStack.pane = parentStack.managementPane
splashPane.running = false splashPane.running = false
} }
} }
Component.onCompleted: Mutant.standard.imagePath = gcd.assetPath; Component.onCompleted: Mutant.standard.imagePath = gcd.assetPath;
Connections { Connections {
target: Qt.application target: Qt.application
onStateChanged: function() { onStateChanged: function() {
// https://doc.qt.io/qt-5/qt.html#ApplicationState-enum // https://doc.qt.io/qt-5/qt.html#ApplicationState-enum

View File

@ -12,51 +12,51 @@ import "../utils.js" as Utils
import "../styles" import "../styles"
ColumnLayout { ColumnLayout {
Layout.fillWidth: true Layout.fillWidth: true
width:parent.width width:parent.width
Text { Text {
Layout.fillWidth: true Layout.fillWidth: true
} }
TextField { TextField {
id: filter id: filter
placeholderText: "Search.." placeholderText: "Search.."
style: CwtchTextFieldStyle{} style: CwtchTextFieldStyle{}
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right
anchors.margins: 10 anchors.margins: 10
onTextChanged: { onTextChanged: {
bulletinView.filter = text bulletinView.filter = text
if (bulletinView.model.get(bulletinView.currentIndex).title.indexOf(text) == -1) { if (bulletinView.model.get(bulletinView.currentIndex).title.indexOf(text) == -1) {
bulletinView.currentIndex = -1 bulletinView.currentIndex = -1
} }
} }
} }
Flickable { // THE MESSAGE LIST ITSELF Flickable { // THE MESSAGE LIST ITSELF
id: sv id: sv
clip: true clip: true
Layout.alignment: Qt.AlignLeft | Qt.AlignTop Layout.alignment: Qt.AlignLeft | Qt.AlignTop
Layout.fillHeight: true Layout.fillHeight: true
Layout.fillWidth: true Layout.fillWidth: true
contentWidth: parent.width contentWidth: parent.width
contentHeight: parent.height contentHeight: parent.height
boundsBehavior: Flickable.StopAtBounds boundsBehavior: Flickable.StopAtBounds
maximumFlickVelocity: 800 maximumFlickVelocity: 800
Connections { Connections {
target: gcd target: gcd
onClearMessages: function() { onClearMessages: function() {
jsonModel4.clear() jsonModel4.clear()
} }
onAppendMessage: function(handle, from, displayName, message, image, mid, fromMe, ts, ack, error) { onAppendMessage: function(handle, from, displayName, message, image, mid, fromMe, ts, ack, error) {
handler(handle, from, displayName, message, image, mid, fromMe, ts, ack, error) handler(handle, from, displayName, message, image, mid, fromMe, ts, ack, error)
@ -67,29 +67,29 @@ ColumnLayout {
} }
function handler(handle, from, displayName, message, image, mid, fromMe, ts, ack, error) { function handler(handle, from, displayName, message, image, mid, fromMe, ts, ack, error) {
var msg var msg
try { try {
msg = JSON.parse(message) msg = JSON.parse(message)
} catch (e) { } catch (e) {
return return
} }
if (msg.o != 2) return if (msg.o != 2) return
if (msg.t != undefined && msg.b != undefined) { if (msg.t != undefined && msg.b != undefined) {
jsonModel4.insert(0,{ jsonModel4.insert(0,{
"title":msg.t, "title":msg.t,
"body": msg.b, "body": msg.b,
"selected":false, "selected":false,
"from": from, "from": from,
"displayName": displayName, "displayName": displayName,
"timestamp": ts "timestamp": ts
}) })
} }
/*if (sv.contentY + sv.height >= sv.contentHeight - colMessages.height && sv.contentHeight > sv.height) { /*if (sv.contentY + sv.height >= sv.contentHeight - colMessages.height && sv.contentHeight > sv.height) {
sv.contentY = sv.contentHeight - sv.height sv.contentY = sv.contentHeight - sv.height
}*/ }*/
} }
onUpdateContactStatus: function(_handle, _status, _loading) { onUpdateContactStatus: function(_handle, _status, _loading) {
if (gcd.selectedConversation == _handle) { if (gcd.selectedConversation == _handle) {
@ -105,153 +105,153 @@ ColumnLayout {
} }
} }
} }
ScrollBar.vertical: ScrollBar{ ScrollBar.vertical: ScrollBar{
policy: ScrollBar.AlwaysOn policy: ScrollBar.AlwaysOn
} }
ListView { ListView {
id: bulletinView id: bulletinView
anchors.left: parent.left anchors.left: parent.left
anchors.leftMargin: 10 anchors.leftMargin: 10
anchors.topMargin: 10 anchors.topMargin: 10
width: parent.width - 50 width: parent.width - 50
height: parent.height - 20 height: parent.height - 20
orientation: Qt.Vertical orientation: Qt.Vertical
spacing: 10 spacing: 10
model: jsonModel4 model: jsonModel4
property string filter: "" property string filter: ""
delegate: delegate:
Item { Item {
width: parent.width width: parent.width
height: title.indexOf(bulletinView.filter) >= 0 ? (selected ? texttitle.height + textbody.height + replybtn.height + 8 : texttitle.height * 2) : 0 height: title.indexOf(bulletinView.filter) >= 0 ? (selected ? texttitle.height + textbody.height + replybtn.height + 8 : texttitle.height * 2) : 0
visible: title.indexOf(bulletinView.filter) >= 0 visible: title.indexOf(bulletinView.filter) >= 0
Column { Column {
width: parent.width width: parent.width
RowLayout { RowLayout {
Button { Button {
text: selected ? "-" : "+" text: selected ? "-" : "+"
style: CwtchExpandingButton{} style: CwtchExpandingButton{}
} }
Text { Text {
id: texttitle id: texttitle
text: '<b>' + Utils.htmlEscaped(title) + '</b> by ' + from + "<br/>" + timestamp text: '<b>' + Utils.htmlEscaped(title) + '</b> by ' + from + "<br/>" + timestamp
leftPadding: 10 leftPadding: 10
topPadding: 5 topPadding: 5
bottomPadding:5 bottomPadding:5
color: windowItem.cwtch_dark_color color: windowItem.cwtch_dark_color
} }
MouseArea { MouseArea {
anchors.fill: parent anchors.fill: parent
onClicked: { onClicked: {
selected = !selected selected = !selected
bulletinView.currentIndex = index bulletinView.currentIndex = index
} }
} }
} }
Rectangle { Rectangle {
height: 1 height: 1
color: windowItem.cwtch_color color: windowItem.cwtch_color
anchors { anchors {
left: parent.left left: parent.left
right: parent.right right: parent.right
} }
} }
Text { Text {
id: textbody id: textbody
visible: selected visible: selected
text: Utils.htmlEscaped(body) text: Utils.htmlEscaped(body)
wrapMode: TextEdit.Wrap wrapMode: TextEdit.Wrap
leftPadding: 10 leftPadding: 10
topPadding: 10 topPadding: 10
width: parent.width - 50 width: parent.width - 50
} }
Widgets.Button { Widgets.Button {
id: replybtn id: replybtn
visible: selected visible: selected
text: "reply" text: "reply"
anchors.right: parent.right anchors.right: parent.right
anchors.rightMargin:10 anchors.rightMargin:10
onClicked: { onClicked: {
gcd.broadcast("ResetMessagePane") gcd.broadcast("ResetMessagePane")
theStack.pane = theStack.messagePane theStack.pane = theStack.messagePane
gcd.loadMessagesPane(from) gcd.loadMessagesPane(from)
overlayStack.overlay = overlayStack.chatOverlay overlayStack.overlay = overlayStack.chatOverlay
} }
} }
} }
} }
focus: true focus: true
ListModel { ListModel {
id: jsonModel4 id: jsonModel4
} }
} }
} }
GroupBox { GroupBox {
title: qsTr("new-bulletin-label") title: qsTr("new-bulletin-label")
Layout.fillWidth: true Layout.fillWidth: true
RowLayout { RowLayout {
Layout.fillWidth: true Layout.fillWidth: true
width: parent.width width: parent.width
ColumnLayout { ColumnLayout {
Layout.fillWidth: true Layout.fillWidth: true
Text { Text {
//: Post a new Bulletin Post //: Post a new Bulletin Post
text: qsTr("post-new-bulletin-label") text: qsTr("post-new-bulletin-label")
} }
TextField { TextField {
id: newposttitle id: newposttitle
//: title place holder text //: title place holder text
placeholderText: qsTr("title-placeholder") placeholderText: qsTr("title-placeholder")
Layout.fillWidth: true Layout.fillWidth: true
style: CwtchTextFieldStyle{} style: CwtchTextFieldStyle{}
} }
TextArea { TextArea {
id: newpostbody id: newpostbody
Layout.fillWidth: true Layout.fillWidth: true
style: CwtchTextAreaStyle{} style: CwtchTextAreaStyle{}
} }
Widgets.Button { // SEND MESSAGE BUTTON Widgets.Button { // SEND MESSAGE BUTTON
id: btnSend id: btnSend
icon: "regular/paper-plane" icon: "regular/paper-plane"
text: "post" text: "post"
anchors.right: parent.right anchors.right: parent.right
anchors.rightMargin: 2 anchors.rightMargin: 2
property int nextMessageID: 1 property int nextMessageID: 1
onClicked: { onClicked: {
if (newposttitle.text != "" && newpostbody.text != "") { if (newposttitle.text != "" && newpostbody.text != "") {
var msg = JSON.stringify({"o":2, "t":newposttitle.text, "b":newpostbody.text}) var msg = JSON.stringify({"o":2, "t":newposttitle.text, "b":newpostbody.text})
gcd.sendMessage(msg, nextMessageID++) gcd.sendMessage(msg, nextMessageID++)
} }
newposttitle.text = "" newposttitle.text = ""
newpostbody.text = "" newpostbody.text = ""
} }
} }
} }
} }
} }

View File

@ -10,7 +10,7 @@ import "../fonts/Twemoji.js" as T
import "../utils.js" as Utils import "../utils.js" as Utils
Item { Item {
width: parent.width width: parent.width
property bool loading property bool loading
ListModel { // MESSAGE OBJECTS ARE STORED HERE ... ListModel { // MESSAGE OBJECTS ARE STORED HERE ...
@ -26,7 +26,7 @@ Item {
model: messagesModel model: messagesModel
spacing: 6 spacing: 6
clip: true clip: true
ScrollBar.vertical: ScrollBar {} ScrollBar.vertical: ScrollBar {}
maximumFlickVelocity: 1250 maximumFlickVelocity: 1250
delegate: Widgets.Message { delegate: Widgets.Message {
@ -57,7 +57,7 @@ Item {
try { try {
msg = JSON.parse(message) msg = JSON.parse(message)
} catch (e) { } catch (e) {
msg = {"o": 1, "d": "(legacy message type) " + message} msg = {"o": 1, "d": "(legacy message type) " + message}
} }
if (msg.o != 1) return if (msg.o != 1) return
@ -90,7 +90,7 @@ Item {
try { try {
msg = JSON.parse(message) msg = JSON.parse(message)
} catch (e) { } catch (e) {
msg = {"o": 1, "d": "(legacy message type) " + message} msg = {"o": 1, "d": "(legacy message type) " + message}
} }
if (msg.o != 1) return if (msg.o != 1) return
@ -128,199 +128,199 @@ Item {
} }
} }
Widgets.EmojiDrawer { Widgets.EmojiDrawer {
id: emojiDrawer id: emojiDrawer
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right
anchors.bottom: rowDrawer.top anchors.bottom: rowDrawer.top
size: 24 * gcd.themeScale size: 24 * gcd.themeScale
onPicked: function(shortcode) { onPicked: function(shortcode) {
if (!txtMessage.enabled) return if (!txtMessage.enabled) return
txtMessage.insert(txtMessage.cursorPosition, ":" + shortcode + ":") txtMessage.insert(txtMessage.cursorPosition, ":" + shortcode + ":")
} }
} }
RowLayout { // THE BOTTOM DRAWER RowLayout { // THE BOTTOM DRAWER
id: rowDrawer id: rowDrawer
anchors.left: parent.left anchors.left: parent.left
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
anchors.right: parent.right anchors.right: parent.right
Rectangle { // MESSAGE ENTRY TEXTFIELD Rectangle { // MESSAGE ENTRY TEXTFIELD
id: rectMessage id: rectMessage
Layout.fillWidth: true Layout.fillWidth: true
Layout.minimumHeight: 40 * gcd.themeScale Layout.minimumHeight: 40 * gcd.themeScale
Layout.maximumHeight: 40 * gcd.themeScale Layout.maximumHeight: 40 * gcd.themeScale
color: txtMessage.isEnabled ? "#EDEDED" : "#CCCCCC" color: txtMessage.isEnabled ? "#EDEDED" : "#CCCCCC"
border.color: "#AAAAAA" border.color: "#AAAAAA"
radius: 10 radius: 10
MouseArea { MouseArea {
anchors.fill: parent anchors.fill: parent
onClicked: txtMessage.focus = true onClicked: txtMessage.focus = true
} }
Flickable { Flickable {
id: flkMessage id: flkMessage
anchors.fill: parent//this does nothing! bug in qt anchors.fill: parent//this does nothing! bug in qt
Layout.minimumWidth: parent.width Layout.minimumWidth: parent.width
Layout.maximumWidth: parent.width Layout.maximumWidth: parent.width
Layout.minimumHeight: rectMessage.height Layout.minimumHeight: rectMessage.height
Layout.maximumHeight: rectMessage.height Layout.maximumHeight: rectMessage.height
contentWidth: txtMessage.width contentWidth: txtMessage.width
contentHeight: txtMessage.height contentHeight: txtMessage.height
boundsBehavior: Flickable.StopAtBounds boundsBehavior: Flickable.StopAtBounds
clip:true clip:true
maximumFlickVelocity: 300 maximumFlickVelocity: 300
ScrollBar.vertical: ScrollBar{} ScrollBar.vertical: ScrollBar{}
TextEdit { TextEdit {
id: txtMessage id: txtMessage
font.pixelSize: 10 * gcd.themeScale font.pixelSize: 10 * gcd.themeScale
text: "" text: ""
padding: 6 padding: 6
wrapMode: TextEdit.Wrap wrapMode: TextEdit.Wrap
textFormat: Text.RichText textFormat: Text.RichText
width: rectMessage.width width: rectMessage.width
property bool skipOneUpdate: false property bool skipOneUpdate: false
property int previousCursor property int previousCursor
Keys.onReturnPressed: { // CTRL+ENTER = LINEBREAK Keys.onReturnPressed: { // CTRL+ENTER = LINEBREAK
if ((event.modifiers & Qt.ControlModifier) && gcd.os != "android") { if ((event.modifiers & Qt.ControlModifier) && gcd.os != "android") {
txtMessage.insert(txtMessage.cursorPosition, "<br>") txtMessage.insert(txtMessage.cursorPosition, "<br>")
} else if (event.modifiers == Qt.NoModifier) { } else if (event.modifiers == Qt.NoModifier) {
btnSend.clicked() btnSend.clicked()
} }
} }
// welcome to the emoji parser! it is horrifying code that needs to leave in <img src="[emoji]"> // welcome to the emoji parser! it is horrifying code that needs to leave in <img src="[emoji]">
// while also stripping any other tag, including other images. // while also stripping any other tag, including other images.
// TODO: this probably breaks if people actually do want to paste html // TODO: this probably breaks if people actually do want to paste html
onTextChanged: { onTextChanged: {
if (gcd.os == "android") { if (gcd.os == "android") {
return return
} }
// we're taking advantage of TextEdit.getText()'s parsing capability, which means occasionally // we're taking advantage of TextEdit.getText()'s parsing capability, which means occasionally
// passing text into it to be filtered. this prevents recursive calls putting us into an // passing text into it to be filtered. this prevents recursive calls putting us into an
// infinite loop // infinite loop
if (skipOneUpdate) { if (skipOneUpdate) {
skipOneUpdate = false skipOneUpdate = false
return return
} }
previousCursor = cursorPosition previousCursor = cursorPosition
//console.log("onTextChanged() at position " + previousCursor) //console.log("onTextChanged() at position " + previousCursor)
//console.log("1: " + txtMessage.getText(0, txtMessage.text.length)) //console.log("1: " + txtMessage.getText(0, txtMessage.text.length))
// convert <img> tags back to their emoji form // convert <img> tags back to their emoji form
// Then parse out the rest of the HTML // Then parse out the rest of the HTML
var nt = restoreEmoji(txtMessage.text) var nt = restoreEmoji(txtMessage.text)
if (nt != txtMessage.text) { if (nt != txtMessage.text) {
skipOneUpdate = true skipOneUpdate = true
txtMessage.text = nt txtMessage.text = nt
} }
//console.log("2: " + txtMessage.getText(0, txtMessage.text.length)) //console.log("2: " + txtMessage.getText(0, txtMessage.text.length))
var preserveSpaces = txtMessage.text.replace(/<br \/>/g,"[:newline:]"); var preserveSpaces = txtMessage.text.replace(/<br \/>/g,"[:newline:]");
if (preserveSpaces != txtMessage.text) { if (preserveSpaces != txtMessage.text) {
skipOneUpdate = true skipOneUpdate = true
txtMessage.text = preserveSpaces txtMessage.text = preserveSpaces
} }
// strip all HTML tags // strip all HTML tags
var theText = Utils.htmlEscaped(txtMessage.getText(0, txtMessage.text.length)) var theText = Utils.htmlEscaped(txtMessage.getText(0, txtMessage.text.length))
//console.log("3: " + theText) //console.log("3: " + theText)
// convert emoji back to <img> tags // convert emoji back to <img> tags
nt = parse(theText, 10) nt = parse(theText, 10)
//console.log("4: " + nt) //console.log("4: " + nt)
// preserve double spacing // preserve double spacing
nt = nt.replace(/\s\s/g, "&nbsp;&nbsp;"); nt = nt.replace(/\s\s/g, "&nbsp;&nbsp;");
nt = nt.replace(/\[\:newline\:\]/g, "<br/>"); nt = nt.replace(/\[\:newline\:\]/g, "<br/>");
// then we actually put the updated text in // then we actually put the updated text in
skipOneUpdate = true skipOneUpdate = true
txtMessage.text = nt txtMessage.text = nt
txtMessage.cursorPosition = previousCursor txtMessage.cursorPosition = previousCursor
// autoscroll down only when the scrollbar is already all the way down // autoscroll down only when the scrollbar is already all the way down
if (flkMessage.contentY + flkMessage.height >= flkMessage.contentHeight - txtMessage.height && flkMessage.contentHeight > flkMessage.height) { if (flkMessage.contentY + flkMessage.height >= flkMessage.contentHeight - txtMessage.height && flkMessage.contentHeight > flkMessage.height) {
flkMessage.contentY = flkMessage.contentHeight - flkMessage.height flkMessage.contentY = flkMessage.contentHeight - flkMessage.height
} }
} }
} }
} }
} }
ColumnLayout { ColumnLayout {
id: colRight id: colRight
spacing: 1 spacing: 1
Widgets.Button { // SEND MESSAGE BUTTON Widgets.Button { // SEND MESSAGE BUTTON
id: btnSend id: btnSend
icon: "regular/paper-plane" icon: "regular/paper-plane"
text: "send" text: "send"
Layout.minimumWidth: btnEmoji.width + btnAttach.width + 2 Layout.minimumWidth: btnEmoji.width + btnAttach.width + 2
Layout.maximumWidth: btnEmoji.width + btnAttach.width + 2 Layout.maximumWidth: btnEmoji.width + btnAttach.width + 2
anchors.right: parent.right anchors.right: parent.right
anchors.rightMargin: 2 anchors.rightMargin: 2
property int nextMessageID: 1 property int nextMessageID: 1
TextEdit { TextEdit {
id: txtHidden id: txtHidden
visible: false visible: false
textFormat: Text.RichText textFormat: Text.RichText
} }
onClicked: { onClicked: {
if (txtMessage.text != "") { if (txtMessage.text != "") {
txtHidden.text = restoreEmoji(txtMessage.text) txtHidden.text = restoreEmoji(txtMessage.text)
txtHidden.text = txtHidden.text.replace(/<br \/>/g,"[:newline:]"); txtHidden.text = txtHidden.text.replace(/<br \/>/g,"[:newline:]");
var txt = txtHidden.text.trim() var txt = txtHidden.text.trim()
if (txt.length > 0) { if (txt.length > 0) {
var rawText = txtHidden.getText(0, txtHidden.text.length) var rawText = txtHidden.getText(0, txtHidden.text.length)
var msg = JSON.stringify({"o":1, "d":rawText.replace(/\[\:newline\:\]/g,"\n")}) var msg = JSON.stringify({"o":1, "d":rawText.replace(/\[\:newline\:\]/g,"\n")})
gcd.sendMessage(msg, nextMessageID++) gcd.sendMessage(msg, nextMessageID++)
} }
} }
txtMessage.text = "" txtMessage.text = ""
} }
} }
RowLayout { RowLayout {
spacing: 1 spacing: 1
Widgets.Button { // EMOJI DRAWER BUTTON Widgets.Button { // EMOJI DRAWER BUTTON
id: btnEmoji id: btnEmoji
icon: "regular/smile" icon: "regular/smile"
anchors.right: btnAttach.left anchors.right: btnAttach.left
anchors.rightMargin: 2 anchors.rightMargin: 2
onClicked: emojiDrawer.visible ? emojiDrawer.slideclosed() : emojiDrawer.slideopen() onClicked: emojiDrawer.visible ? emojiDrawer.slideclosed() : emojiDrawer.slideopen()
} }
Widgets.Button { Widgets.Button {
id: btnAttach id: btnAttach
icon: "solid/paperclip" icon: "solid/paperclip"
anchors.right: parent.right anchors.right: parent.right
anchors.rightMargin: 2 anchors.rightMargin: 2
onClicked: { onClicked: {
gcd.popup("attachments not yet implemented, sorry") gcd.popup("attachments not yet implemented, sorry")
} }
} }
} }
} }
} }
} }

View File

@ -12,51 +12,51 @@ import "../utils.js" as Utils
import "../styles" import "../styles"
ColumnLayout { ColumnLayout {
Layout.fillWidth: true Layout.fillWidth: true
width:parent.width width:parent.width
Text { Text {
Layout.fillWidth: true Layout.fillWidth: true
} }
TextField { TextField {
id: filter id: filter
placeholderText: "Search.." placeholderText: "Search.."
style: CwtchTextFieldStyle{} style: CwtchTextFieldStyle{}
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right
anchors.margins: 10 anchors.margins: 10
onTextChanged: { onTextChanged: {
bulletinView.filter = text bulletinView.filter = text
if (bulletinView.model.get(bulletinView.currentIndex).title.indexOf(text) == -1) { if (bulletinView.model.get(bulletinView.currentIndex).title.indexOf(text) == -1) {
bulletinView.currentIndex = -1 bulletinView.currentIndex = -1
} }
} }
} }
Flickable { // THE MESSAGE LIST ITSELF Flickable { // THE MESSAGE LIST ITSELF
id: sv id: sv
clip: true clip: true
Layout.alignment: Qt.AlignLeft | Qt.AlignTop Layout.alignment: Qt.AlignLeft | Qt.AlignTop
Layout.fillHeight: true Layout.fillHeight: true
Layout.fillWidth: true Layout.fillWidth: true
contentWidth: parent.width contentWidth: parent.width
contentHeight: parent.height contentHeight: parent.height
boundsBehavior: Flickable.StopAtBounds boundsBehavior: Flickable.StopAtBounds
maximumFlickVelocity: 800 maximumFlickVelocity: 800
Connections { Connections {
target: gcd target: gcd
onClearMessages: function() { onClearMessages: function() {
jsonModel4.clear() jsonModel4.clear()
} }
onAppendMessage: function(handle, from, displayName, message, image, mid, fromMe, ts, ack, error) { onAppendMessage: function(handle, from, displayName, message, image, mid, fromMe, ts, ack, error) {
handler(handle, from, displayName, message, image, mid, fromMe, ts, ack, error) handler(handle, from, displayName, message, image, mid, fromMe, ts, ack, error)
@ -68,33 +68,33 @@ ColumnLayout {
function handler(handle, from, displayName, message, image, mid, fromMe, ts, ack, error) { function handler(handle, from, displayName, message, image, mid, fromMe, ts, ack, error) {
var msg var msg
try { try {
msg = JSON.parse(message) msg = JSON.parse(message)
} catch (e) { } catch (e) {
return return
} }
if (msg.o != 4) return if (msg.o != 4) return
if (msg.t != undefined) { if (msg.t != undefined) {
jsonModel4.insert(0,{ jsonModel4.insert(0,{
"title":msg.t, "title":msg.t,
"selected":false, "selected":false,
"from": from, "from": from,
"displayName": displayName, "displayName": displayName,
"timestamp": ts, "timestamp": ts,
"complete": false "complete": false
}) })
} }
/*if(msg.c != undefined) { /*if(msg.c != undefined) {
jsonModel4.get(msg.c).complete = true jsonModel4.get(msg.c).complete = true
} }
if (sv.contentY + sv.height >= sv.contentHeight - colMessages.height && sv.contentHeight > sv.height) { if (sv.contentY + sv.height >= sv.contentHeight - colMessages.height && sv.contentHeight > sv.height) {
sv.contentY = sv.contentHeight - sv.height sv.contentY = sv.contentHeight - sv.height
}*/ }*/
} }
onUpdateContactStatus: function(_handle, _status, _loading) { onUpdateContactStatus: function(_handle, _status, _loading) {
if (gcd.selectedConversation == _handle) { if (gcd.selectedConversation == _handle) {
@ -108,123 +108,123 @@ ColumnLayout {
} }
} }
} }
ScrollBar.vertical: ScrollBar{ ScrollBar.vertical: ScrollBar{
policy: ScrollBar.AlwaysOn policy: ScrollBar.AlwaysOn
} }
ListView { ListView {
id: bulletinView id: bulletinView
anchors.left: parent.left anchors.left: parent.left
anchors.leftMargin: 10 anchors.leftMargin: 10
anchors.topMargin: 10 anchors.topMargin: 10
width: parent.width - 50 width: parent.width - 50
height: parent.height - 20 height: parent.height - 20
orientation: Qt.Vertical orientation: Qt.Vertical
spacing: 10 spacing: 10
model: jsonModel4 model: jsonModel4
property string filter: "" property string filter: ""
delegate: delegate:
Item { Item {
width: parent.width width: parent.width
height: title.indexOf(bulletinView.filter) >= 0 ? texttitle.height : 0 height: title.indexOf(bulletinView.filter) >= 0 ? texttitle.height : 0
visible: title.indexOf(bulletinView.filter) >= 0 visible: title.indexOf(bulletinView.filter) >= 0
Column { Column {
width: parent.width width: parent.width
RowLayout { RowLayout {
CheckBox { CheckBox {
checked: complete checked: complete
onClicked: { onClicked: {
var msg = JSON.stringify({"o":4, "c":index}) var msg = JSON.stringify({"o":4, "c":index})
gcd.sendMessage(msg, btnSend.nextMessageID++) gcd.sendMessage(msg, btnSend.nextMessageID++)
} }
} }
RowLayout { RowLayout {
Text { Text {
id: texttitle id: texttitle
text: '<b>' + Utils.htmlEscaped(title) + '</b> by ' + from + "<br/>" + timestamp text: '<b>' + Utils.htmlEscaped(title) + '</b> by ' + from + "<br/>" + timestamp
leftPadding: 10 leftPadding: 10
topPadding: 5 topPadding: 5
bottomPadding:5 bottomPadding:5
color: windowItem.cwtch_dark_color color: windowItem.cwtch_dark_color
} }
} }
} }
Rectangle { Rectangle {
height: 1 height: 1
color: windowItem.cwtch_color color: windowItem.cwtch_color
anchors { anchors {
left: parent.left left: parent.left
right: parent.right right: parent.right
} }
} }
} }
} }
focus: true focus: true
ListModel { ListModel {
id: jsonModel4 id: jsonModel4
} }
} }
} }
GroupBox { GroupBox {
//: Add a New List Item //: Add a New List Item
title: qsTr("add-list-item") title: qsTr("add-list-item")
Layout.fillWidth: true Layout.fillWidth: true
RowLayout { RowLayout {
Layout.fillWidth: true Layout.fillWidth: true
width: parent.width width: parent.width
ColumnLayout { ColumnLayout {
Layout.fillWidth: true Layout.fillWidth: true
Text { Text {
//: Add a new item to the list //: Add a new item to the list
text: qsTr("add-new-item") text: qsTr("add-new-item")
} }
TextField { TextField {
id: newposttitle id: newposttitle
//: Todo... placeholder text //: Todo... placeholder text
placeholderText: qsTr("todo-placeholder") placeholderText: qsTr("todo-placeholder")
Layout.fillWidth: true Layout.fillWidth: true
style: CwtchTextFieldStyle{} style: CwtchTextFieldStyle{}
} }
Widgets.Button { // SEND MESSAGE BUTTON Widgets.Button { // SEND MESSAGE BUTTON
id: btnSend id: btnSend
icon: "regular/paper-plane" icon: "regular/paper-plane"
text: "add" text: "add"
anchors.right: parent.right anchors.right: parent.right
anchors.rightMargin: 2 anchors.rightMargin: 2
property int nextMessageID: 1 property int nextMessageID: 1
onClicked: { onClicked: {
if (newposttitle.text != "") { if (newposttitle.text != "") {
var msg = JSON.stringify({"o":4, "t":newposttitle.text}) var msg = JSON.stringify({"o":4, "t":newposttitle.text})
gcd.sendMessage(msg, nextMessageID++) gcd.sendMessage(msg, nextMessageID++)
} }
newposttitle.text = "" newposttitle.text = ""
} }
} }
} }
} }
} }

View File

@ -12,45 +12,45 @@ import "../utils.js" as Utils
import "../styles" import "../styles"
ColumnLayout { ColumnLayout {
Text { Text {
wrapMode: Text.Wrap wrapMode: Text.Wrap
Layout.maximumWidth: parent.width Layout.maximumWidth: parent.width
horizontalAlignment: Text.AlignHCenter horizontalAlignment: Text.AlignHCenter
padding: 1 padding: 1
//: Below is a list of users who have sent messages to the group. This list may not reflect all users who have access to the group. //: Below is a list of users who have sent messages to the group. This list may not reflect all users who have access to the group.
text: qsTr("membership-description") text: qsTr("membership-description")
} }
Flickable { // THE ACTUAL CONTACT LIST Flickable { // THE ACTUAL CONTACT LIST
id: sv id: sv
//Layout.alignment: Qt.AlignLeft | Qt.AlignTop //Layout.alignment: Qt.AlignLeft | Qt.AlignTop
clip: true clip: true
Layout.minimumHeight: 100 Layout.minimumHeight: 100
//Layout.maximumHeight: parent.height - 30 //Layout.maximumHeight: parent.height - 30
Layout.fillHeight: true Layout.fillHeight: true
Layout.minimumWidth: parent.width Layout.minimumWidth: parent.width
Layout.maximumWidth: parent.width Layout.maximumWidth: parent.width
contentWidth: colContacts.width contentWidth: colContacts.width
contentHeight: colContacts.height contentHeight: colContacts.height
boundsBehavior: Flickable.StopAtBounds boundsBehavior: Flickable.StopAtBounds
maximumFlickVelocity: 400 maximumFlickVelocity: 400
ScrollBar.vertical: ScrollBar { ScrollBar.vertical: ScrollBar {
policy: ScrollBar.AlwaysOn policy: ScrollBar.AlwaysOn
} }
ColumnLayout { ColumnLayout {
id: colContacts id: colContacts
width: sv.width width: sv.width
spacing: 0 spacing: 0
Connections { // ADD/REMOVE CONTACT ENTRIES Connections { // ADD/REMOVE CONTACT ENTRIES
target: gcd target: gcd
onClearMessages: function() { onClearMessages: function() {
contactsModel.clear() contactsModel.clear()
} }
onAppendMessage: function(handle, from, displayName, message, image, mid, fromMe, ts, ack, error) { onAppendMessage: function(handle, from, displayName, message, image, mid, fromMe, ts, ack, error) {
handler(handle, from, displayName, message, image, mid, fromMe, ts, ack, error) handler(handle, from, displayName, message, image, mid, fromMe, ts, ack, error)
@ -63,51 +63,51 @@ ColumnLayout {
function handler(handle, from, displayName, message, image, mid, fromMe, ts, ack, error) { function handler(handle, from, displayName, message, image, mid, fromMe, ts, ack, error) {
var msg var msg
try { try {
msg = JSON.parse(message) msg = JSON.parse(message)
} catch (e) { } catch (e) {
return return
} }
if (from == "me") { if (from == "me") {
return return
} }
for(var i = 0; i<contactsModel.count;i++){ for(var i = 0; i<contactsModel.count;i++){
if(contactsModel.get(i)["_handle"] == handle) { if(contactsModel.get(i)["_handle"] == handle) {
return return
} }
} }
if (fromMe) { if (fromMe) {
contactsModel.append({ contactsModel.append({
"_handle": handle, "_handle": handle,
"_displayName": "me", "_displayName": "me",
"_image": image, "_image": image,
}) })
} else { } else {
contactsModel.append({ contactsModel.append({
"_handle": handle, "_handle": handle,
"_displayName": displayName == "" ? handle : displayName, "_displayName": displayName == "" ? handle : displayName,
"_image": image, "_image": image,
}) })
} }
} }
} }
ListModel { // CONTACT OBJECTS ARE STORED HERE ... ListModel { // CONTACT OBJECTS ARE STORED HERE ...
id: contactsModel id: contactsModel
} }
Repeater { Repeater {
model: contactsModel // ... AND DISPLAYED HERE model: contactsModel // ... AND DISPLAYED HERE
delegate: ContactRow { delegate: ContactRow {
handle: _handle handle: _handle
displayName: _displayName displayName: _displayName
image: _image image: _image
blocked: false blocked: false
} }
} }
} }
} }
} }

View File

@ -11,64 +11,64 @@ import "../styles"
ColumnLayout { // settingsPane ColumnLayout { // settingsPane
id: root id: root
anchors.fill: parent anchors.fill: parent
Widgets.StackToolbar { Widgets.StackToolbar {
id: stb id: stb
text: qsTr("create-group-title") text: qsTr("create-group-title")
aux.visible: false aux.visible: false
membership.visible: false membership.visible: false
} }
Flickable { Flickable {
anchors.top: stb.bottom anchors.top: stb.bottom
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
boundsBehavior: Flickable.StopAtBounds boundsBehavior: Flickable.StopAtBounds
clip:true clip:true
contentWidth: tehcol.width contentWidth: tehcol.width
contentHeight: tehcol.height contentHeight: tehcol.height
Column { Column {
id: tehcol id: tehcol
leftPadding: 10 leftPadding: 10
spacing: 5 spacing: 5
width: root.width width: root.width
Widgets.ScalingLabel { Widgets.ScalingLabel {
//: Server label //: Server label
text: qsTr("server-label") + ":" text: qsTr("server-label") + ":"
} }
TextField { TextField {
id: txtServer id: txtServer
style: CwtchTextFieldStyle{ width: tehcol.width * 0.8 } style: CwtchTextFieldStyle{ width: tehcol.width * 0.8 }
text: "2c3kmoobnyghj2zw6pwv7d57yzld753auo3ugauezzpvfak3ahc4bdyd" text: "2c3kmoobnyghj2zw6pwv7d57yzld753auo3ugauezzpvfak3ahc4bdyd"
} }
Widgets.ScalingLabel{ Widgets.ScalingLabel{
//: Group name label //: Group name label
text: qsTr("group-name-label") + ":" text: qsTr("group-name-label") + ":"
} }
TextField { TextField {
id: txtGroupName id: txtGroupName
style: CwtchTextFieldStyle{ width: tehcol.width * 0.8 } style: CwtchTextFieldStyle{ width: tehcol.width * 0.8 }
//: default suggested group name //: default suggested group name
text: qsTr("default-group-name") text: qsTr("default-group-name")
} }
Widgets.Button { Widgets.Button {
//: create group button //: create group button
text: qsTr("create-group-btn") text: qsTr("create-group-btn")
onClicked: { onClicked: {
gcd.createGroup(txtServer.text, txtGroupName.text) gcd.createGroup(txtServer.text, txtGroupName.text)
} }
} }
}//end of column with padding }//end of column with padding
}//end of flickable }//end of flickable
} }

View File

@ -11,137 +11,137 @@ import "../styles"
import "../utils.js" as Utils import "../utils.js" as Utils
ColumnLayout { // groupSettingsPane ColumnLayout { // groupSettingsPane
id: gsp id: gsp
anchors.fill: parent anchors.fill: parent
property string groupID property string groupID
property variant addrbook property variant addrbook
Widgets.StackToolbar { Widgets.StackToolbar {
id: toolbar id: toolbar
aux.visible: false aux.visible: false
back.onClicked: theStack.pane = theStack.messagePane back.onClicked: theStack.pane = theStack.messagePane
} }
Flickable { Flickable {
anchors.top: toolbar.bottom anchors.top: toolbar.bottom
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
boundsBehavior: Flickable.StopAtBounds boundsBehavior: Flickable.StopAtBounds
clip:true clip:true
contentWidth: tehcol.width contentWidth: tehcol.width
contentHeight: tehcol.height contentHeight: tehcol.height
Column { Column {
id: tehcol id: tehcol
width: gsp.width width: gsp.width
leftPadding: 10 leftPadding: 10
spacing: 5 spacing: 5
Widgets.ScalingLabel { Widgets.ScalingLabel {
text: qsTr("server-label") + ":" text: qsTr("server-label") + ":"
} }
TextField { TextField {
id: txtServer id: txtServer
style: CwtchTextFieldStyle{ width: tehcol.width * 0.8 } style: CwtchTextFieldStyle{ width: tehcol.width * 0.8 }
readOnly: true readOnly: true
} }
Widgets.Button { Widgets.Button {
icon: "regular/clipboard" icon: "regular/clipboard"
text: qsTr("copy-btn") text: qsTr("copy-btn")
onClicked: { onClicked: {
gcd.popup("copied-clipboard-notification") gcd.popup("copied-clipboard-notification")
txtServer.selectAll() txtServer.selectAll()
txtServer.copy() txtServer.copy()
} }
} }
Widgets.ScalingLabel { Widgets.ScalingLabel {
text: qsTr("invitation-label") + ":" text: qsTr("invitation-label") + ":"
} }
TextField { TextField {
id: txtInvitation id: txtInvitation
style: CwtchTextFieldStyle{ width: tehcol.width * 0.8 } style: CwtchTextFieldStyle{ width: tehcol.width * 0.8 }
readOnly: true readOnly: true
} }
Widgets.Button { Widgets.Button {
icon: "regular/clipboard" icon: "regular/clipboard"
text: qsTr("copy-btn") text: qsTr("copy-btn")
onClicked: { onClicked: {
gcd.popup("copied-clipboard-notification") gcd.popup("copied-clipboard-notification")
txtInvitation.selectAll() txtInvitation.selectAll()
txtInvitation.copy() txtInvitation.copy()
} }
} }
Widgets.ScalingLabel{ Widgets.ScalingLabel{
text: qsTr("group-name-label") + ":" text: qsTr("group-name-label") + ":"
} }
TextField { TextField {
id: txtGroupName id: txtGroupName
style: CwtchTextFieldStyle{ width: tehcol.width * 0.8 } style: CwtchTextFieldStyle{ width: tehcol.width * 0.8 }
} }
Widgets.Button { Widgets.Button {
text: qsTr("save-btn") text: qsTr("save-btn")
onClicked: { onClicked: {
gcd.saveGroupSettings(groupID, txtGroupName.text) gcd.saveGroupSettings(groupID, txtGroupName.text)
theStack.title = txtGroupName.text theStack.title = txtGroupName.text
theStack.pane = theStack.messagePane theStack.pane = theStack.messagePane
} }
} }
//: Invite someone to the group //: Invite someone to the group
Widgets.ScalingLabel { text: qsTr("invite-to-group-label") } Widgets.ScalingLabel { text: qsTr("invite-to-group-label") }
ComboBox { ComboBox {
id: cbInvite id: cbInvite
//popup.font.pixelSize: 12 //popup.font.pixelSize: 12
width: 200 width: 200
//font.pixelSize: 20 //font.pixelSize: 20
style: CwtchComboBoxStyle{} style: CwtchComboBoxStyle{}
} }
Widgets.Button { Widgets.Button {
text: qsTr("invite-btn") text: qsTr("invite-btn")
onClicked: { onClicked: {
gcd.inviteToGroup(addrbook[cbInvite.currentIndex], groupID) gcd.inviteToGroup(addrbook[cbInvite.currentIndex], groupID)
} }
} }
Widgets.Button { Widgets.Button {
icon: "regular/trash-alt" icon: "regular/trash-alt"
text: qsTr("delete-btn") text: qsTr("delete-btn")
onClicked: { onClicked: {
gcd.leaveGroup(groupID) gcd.leaveGroup(groupID)
theStack.pane = theStack.emptyPane theStack.pane = theStack.emptyPane
} }
} }
}//end of column with padding }//end of column with padding
}//end of flickable }//end of flickable
Connections { Connections {
target: gcd target: gcd
onSupplyGroupSettings: function(gid, name, server, invite, accepted, addrbooknames, addrbookaddrs) { onSupplyGroupSettings: function(gid, name, server, invite, accepted, addrbooknames, addrbookaddrs) {
gsp.groupID = gid gsp.groupID = gid
toolbar.text = name toolbar.text = name
txtGroupName.text = name txtGroupName.text = name
txtServer.text = server txtServer.text = server
txtInvitation.text = invite txtInvitation.text = invite
cbInvite.model = addrbooknames.map(function(e){return Utils.htmlEscaped(e)}) cbInvite.model = addrbooknames.map(function(e){return Utils.htmlEscaped(e)})
addrbook = addrbookaddrs addrbook = addrbookaddrs
} }
} }
} }

View File

@ -8,68 +8,68 @@ import "../widgets" as Widgets
import "../overlays" import "../overlays"
ColumnLayout { ColumnLayout {
Layout.fillWidth: true Layout.fillWidth: true
property alias title: toolbar.text property alias title: toolbar.text
id: overlay id: overlay
property string name property string name
property bool accepted property bool accepted
property bool inGroup property bool inGroup
Widgets.StackToolbar { Widgets.StackToolbar {
id: toolbar id: toolbar
membership.visible: gcd.selectedConversation.length == 32 membership.visible: gcd.selectedConversation.length == 32
membership.onClicked: overlayStack.overlay = overlayStack.membershipOverlay membership.onClicked: overlayStack.overlay = overlayStack.membershipOverlay
aux.onClicked: { aux.onClicked: {
if (gcd.selectedConversation.length == 32) { if (gcd.selectedConversation.length == 32) {
theStack.pane = theStack.groupProfilePane theStack.pane = theStack.groupProfilePane
gcd.requestGroupSettings(gcd.selectedConversation) gcd.requestGroupSettings(gcd.selectedConversation)
} else { } else {
theStack.pane = theStack.userProfilePane theStack.pane = theStack.userProfilePane
gcd.requestPeerSettings() gcd.requestPeerSettings()
} }
} }
back.visible: true back.visible: true
} }
RowLayout {
visible:!overlay.accepted && (gcd.selectedConversation.length == 32)
Text {
//: Do you want to accept the invitation to $GROUP
text: qsTr("accept-group-invite-label") + " " + overlay.name + "?"
}
Widgets.Button {
//: Accept group invite button
text: qsTr("accept-group-btn")
icon: "regular/heart"
onClicked: {
gcd.acceptGroup(gcd.selectedConversation)
gcd.requestGroupSettings(gcd.selectedConversation)
}
}
Widgets.Button {
//: Reject Group invite button
text: qsTr("reject-group-btn")
icon: "regular/trash-alt"
onClicked: {
gcd.leaveGroup(gcd.selectedConversation)
theStack.pane = theStack.emptyPane
}
}
}
RowLayout { RowLayout {
id: switcher visible:!overlay.accepted && (gcd.selectedConversation.length == 32)
Widgets.Button { Text {
//: Do you want to accept the invitation to $GROUP
text: qsTr("accept-group-invite-label") + " " + overlay.name + "?"
}
Widgets.Button {
//: Accept group invite button
text: qsTr("accept-group-btn")
icon: "regular/heart"
onClicked: {
gcd.acceptGroup(gcd.selectedConversation)
gcd.requestGroupSettings(gcd.selectedConversation)
}
}
Widgets.Button {
//: Reject Group invite button
text: qsTr("reject-group-btn")
icon: "regular/trash-alt"
onClicked: {
gcd.leaveGroup(gcd.selectedConversation)
theStack.pane = theStack.emptyPane
}
}
}
RowLayout {
id: switcher
Widgets.Button {
text: qsTr("chat-btn") text: qsTr("chat-btn")
@ -124,18 +124,18 @@ ColumnLayout {
} }
MembershipOverlay { //3 MembershipOverlay { //3
Layout.maximumHeight: overlayStack.height Layout.maximumHeight: overlayStack.height
Layout.maximumWidth: overlayStack.width Layout.maximumWidth: overlayStack.width
} }
} }
Connections { Connections {
target: gcd target: gcd
onResetMessagePane: function() { onResetMessagePane: function() {
overlayStack.overlay = overlayStack.chatOverlay overlayStack.overlay = overlayStack.chatOverlay
overlay.inGroup = false overlay.inGroup = false
} }
onSupplyGroupSettings: function(gid, name, server, invite, accepted, addrbooknames, addrbookaddrs) { onSupplyGroupSettings: function(gid, name, server, invite, accepted, addrbooknames, addrbookaddrs) {
overlay.name = name overlay.name = name
@ -143,4 +143,4 @@ ColumnLayout {
overlay.inGroup = true overlay.inGroup = true
} }
} }
} }

View File

@ -12,114 +12,114 @@ import "../theme"
ColumnLayout { // peerSettingsPane ColumnLayout { // peerSettingsPane
id: root id: root
anchors.fill: parent anchors.fill: parent
property bool blocked property bool blocked
Widgets.StackToolbar { Widgets.StackToolbar {
id: toolbar id: toolbar
aux.visible: false aux.visible: false
back.onClicked: theStack.pane = theStack.messagePane back.onClicked: theStack.pane = theStack.messagePane
}
Flickable {
anchors.top: toolbar.bottom
anchors.left: parent.left
anchors.right: parent.right
anchors.bottom: parent.bottom
boundsBehavior: Flickable.StopAtBounds
clip:true
contentWidth: tehcol.width
contentHeight: tehcol.height
Column {
id: tehcol
width: root.width
leftPadding: 10
padding:10
spacing: 5
Widgets.EllipsisLabel {
color: Theme.mainTextColor
text: qsTr("address-label")
font.styleName: "ExtraBold"
font.pointSize: 15 * gcd.themeScale
}
Widgets.ButtonTextField {
id: txtOnion
//style: CwtchTextFieldStyle{ width: tehcol.width * 0.8 }
readOnly: true
button_text: qsTr("copy-btn")
onClicked: {
//: notification: copied to clipboard
gcd.popup(qsTr("copied-to-clipboard-notification"))
txtOnion.selectAll()
txtOnion.copy()
}
}
Widgets.EllipsisLabel {
color: Theme.mainTextColor
text: qsTr("display-name-label")
font.styleName: "ExtraBold"
font.pointSize: 15 * gcd.themeScale
}
Widgets.ButtonTextField {
id: txtDisplayName
button_text: qsTr("save-btn")
onClicked: {
gcd.savePeerSettings(txtOnion.text, txtDisplayName.text)
theStack.title = txtDisplayName.text
theStack.pane = theStack.messagePane
}
}
Widgets.Button {
icon: "solid/hand-paper"
text: root.blocked ? qsTr("unblock-btn") : qsTr("block-btn")
onClicked: {
if (root.blocked) {
gcd.unblockPeer(txtOnion.text)
} else {
gcd.blockPeer(txtOnion.text)
}
root.blocked = !root.blocked
}
} }
Widgets.Button { Flickable {
icon: "regular/trash-alt" anchors.top: toolbar.bottom
text: qsTr("delete-btn") anchors.left: parent.left
anchors.right: parent.right
anchors.bottom: parent.bottom
boundsBehavior: Flickable.StopAtBounds
clip:true
contentWidth: tehcol.width
contentHeight: tehcol.height
onClicked: { Column {
gcd.deleteContact(txtOnion.text) id: tehcol
theStack.pane = theStack.emptyPane width: root.width
} leftPadding: 10
} padding:10
spacing: 5
}//end of column with padding Widgets.EllipsisLabel {
color: Theme.mainTextColor
text: qsTr("address-label")
font.styleName: "ExtraBold"
font.pointSize: 15 * gcd.themeScale
}
Widgets.ButtonTextField {
id: txtOnion
//style: CwtchTextFieldStyle{ width: tehcol.width * 0.8 }
readOnly: true
button_text: qsTr("copy-btn")
onClicked: {
//: notification: copied to clipboard
gcd.popup(qsTr("copied-to-clipboard-notification"))
txtOnion.selectAll()
txtOnion.copy()
}
}
Widgets.EllipsisLabel {
color: Theme.mainTextColor
text: qsTr("display-name-label")
font.styleName: "ExtraBold"
font.pointSize: 15 * gcd.themeScale
}
Widgets.ButtonTextField {
id: txtDisplayName
button_text: qsTr("save-btn")
onClicked: {
gcd.savePeerSettings(txtOnion.text, txtDisplayName.text)
theStack.title = txtDisplayName.text
theStack.pane = theStack.messagePane
}
}
Widgets.Button {
icon: "solid/hand-paper"
text: root.blocked ? qsTr("unblock-btn") : qsTr("block-btn")
onClicked: {
if (root.blocked) {
gcd.unblockPeer(txtOnion.text)
} else {
gcd.blockPeer(txtOnion.text)
}
root.blocked = !root.blocked
}
}
Widgets.Button {
icon: "regular/trash-alt"
text: qsTr("delete-btn")
onClicked: {
gcd.deleteContact(txtOnion.text)
theStack.pane = theStack.emptyPane
}
}
}//end of column with padding
}//end of flickable }//end of flickable
Connections { Connections {
target: gcd target: gcd
onSupplyPeerSettings: function(onion, nick, blocked) { onSupplyPeerSettings: function(onion, nick, blocked) {
toolbar.text = nick toolbar.text = nick
txtOnion.text = onion txtOnion.text = onion
txtDisplayName.text = nick txtDisplayName.text = nick
root.blocked = blocked root.blocked = blocked
} }
} }
} }

View File

@ -11,7 +11,7 @@ import "../widgets" as Widgets
ColumnLayout { // Add Profile Pane ColumnLayout { // Add Profile Pane
id: profileAddEditPane id: profileAddEditPane
anchors.fill: parent anchors.fill: parent
property string mode // edit or add property string mode // edit or add
property string onion property string onion
@ -19,16 +19,16 @@ ColumnLayout { // Add Profile Pane
property bool deleting property bool deleting
property bool changingPassword property bool changingPassword
Widgets.StackToolbar { Widgets.StackToolbar {
id: stb id: stb
text: mode == "add" ? qsTr("add-profile-title") : qsTr("edit-profile-title") text: mode == "add" ? qsTr("add-profile-title") : qsTr("edit-profile-title")
aux.visible: false aux.visible: false
membership.visible: false membership.visible: false
stack: "management" stack: "management"
} }
function reset() { function reset() {
mode = "add" mode = "add"
txtProfileName.text = qsTr("default-profile-name") txtProfileName.text = qsTr("default-profile-name")
changingPassword = false changingPassword = false
txtPassword1.text = "" txtPassword1.text = ""
@ -42,17 +42,17 @@ ColumnLayout { // Add Profile Pane
confirmDeleteTxt.text = "" confirmDeleteTxt.text = ""
radioUsePassword.checked = true radioUsePassword.checked = true
passwordChangeErrorLabel.visible = false passwordChangeErrorLabel.visible = false
} }
function load(userOnion, name, userTag) { function load(userOnion, name, userTag) {
reset() reset()
mode = "edit" mode = "edit"
tag = userTag tag = userTag
onion = userOnion onion = userOnion
txtPassword1.text = "" txtPassword1.text = ""
txtPassword2.text = "" txtPassword2.text = ""
onionLabel.text = onion onionLabel.text = onion
txtProfileName.text = name txtProfileName.text = name
if (tag == "v1-defaultPassword" || tag == "v1-default-password") { if (tag == "v1-defaultPassword" || tag == "v1-default-password") {
@ -64,240 +64,240 @@ ColumnLayout { // Add Profile Pane
Flickable { Flickable {
anchors.top: stb.bottom anchors.top: stb.bottom
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
boundsBehavior: Flickable.StopAtBounds boundsBehavior: Flickable.StopAtBounds
clip:true clip:true
contentWidth: tehcol.width contentWidth: tehcol.width
contentHeight: tehcol.height contentHeight: tehcol.height
Column { Column {
id: tehcol id: tehcol
leftPadding: 10 leftPadding: 10
spacing: 5 spacing: 5
width: profileAddEditPane.width width: profileAddEditPane.width
Widgets.ScalingLabel { Widgets.ScalingLabel {
//: Onion //: Onion
text: qsTr("profile-onion-label") + ":" text: qsTr("profile-onion-label") + ":"
visible: mode == "edit" visible: mode == "edit"
}
Widgets.ScalingLabel {
id: onionLabel
visible: mode == "edit"
}
Widgets.ScalingLabel {
//: Display name
text: qsTr("profile-name") + ":"
}
Widgets.TextField {
id: txtProfileName
Layout.fillWidth: true
//style: CwtchTextFieldStyle{ width: tehcol.width * 0.8 }
//: default suggested profile name
text: qsTr("default-profile-name")
}
RowLayout {
//id: radioButtons
Widgets.RadioButton {
id: radioUsePassword
checked: true
//: Password
text: qsTr("radio-use-password")
visible: mode == "add" || tag == "v1-defaultPassword"
onClicked: {
changingPassword = true
}
}
Widgets.RadioButton {
id: radioNoPassword
//: Unencrypted (No password)
text: qsTr("radio-no-password")
visible: mode == "add" || tag == "v1-defaultPassword"
onClicked: {
changingPassword = true
} }
}
}
Widgets.ScalingLabel { Widgets.ScalingLabel {
id: noPasswordLabel id: onionLabel
//: Not using a password on this account means that all data stored locally will not be encrypted visible: mode == "edit"
text: qsTr("no-password-warning") }
visible: radioNoPassword.checked
}
Widgets.ScalingLabel { Widgets.ScalingLabel {
id: currentPasswordLabel //: Display name
//: Current Password text: qsTr("profile-name") + ":"
text: qsTr("current-password-label") + ":" }
visible: radioUsePassword.checked && mode == "edit" && tag != "v1-defaultPassword"
}
Widgets.TextField { Widgets.TextField {
id: txtCurrentPassword id: txtProfileName
Layout.fillWidth: true Layout.fillWidth: true
echoMode: TextInput.Password //style: CwtchTextFieldStyle{ width: tehcol.width * 0.8 }
visible: radioUsePassword.checked && mode == "edit" && tag != "v1-defaultPassword" //: default suggested profile name
} text: qsTr("default-profile-name")
Widgets.ScalingLabel {
id: passwordLabel
//: Password
text: qsTr("password1-label") + ":"
visible: radioUsePassword.checked
}
Widgets.TextField {
id: txtPassword1
Layout.fillWidth: true
//style: CwtchTextFieldStyle{ width: tehcol.width * 0.8 }
echoMode: TextInput.Password
visible: radioUsePassword.checked
onTextEdited: {
changingPassword = true
}
}
Widgets.ScalingLabel { }
id: passwordReLabel
//: Reenter password
text: qsTr("password2-label") + ":"
visible: radioUsePassword.checked
}
Widgets.TextField { RowLayout {
id: txtPassword2 //id: radioButtons
Layout.fillWidth: true
//style: CwtchTextFieldStyle{ width: tehcol.width * 0.8 }
echoMode: TextInput.Password
visible: radioUsePassword.checked
}
Widgets.Button { // ADD or SAVE button Widgets.RadioButton {
//: Create Profile || Save Profile id: radioUsePassword
text: mode == "add" ? qsTr("create-profile-btn") : qsTr("save-profile-btn") checked: true
//: Password
onClicked: { text: qsTr("radio-use-password")
if (mode == "add") { visible: mode == "add" || tag == "v1-defaultPassword"
if (txtPassword1.text != txtPassword2.text) { onClicked: {
passwordErrorLabel.visible = true changingPassword = true
} else { }
gcd.createProfile(txtProfileName.text, radioNoPassword.checked, txtPassword1.text)
gcd.reloadProfileList()
parentStack.pane = parentStack.managementPane
} }
} else {
gcd.updateNick(onion, txtProfileName.text)
if (changingPassword) { Widgets.RadioButton {
if (txtPassword1.text != txtPassword2.text) { id: radioNoPassword
passwordErrorLabel.visible = true //: Unencrypted (No password)
} else { text: qsTr("radio-no-password")
gcd.changePassword(onion, txtCurrentPassword.text, txtPassword1.text, radioNoPassword.checked) visible: mode == "add" || tag == "v1-defaultPassword"
} onClicked: {
} else { changingPassword = true
gcd.reloadProfileList() }
parentStack.pane = parentStack.managementPane }
}
}
}
}
Widgets.ScalingLabel {
id: passwordErrorLabel
//: Passwords do not match
text: qsTr("password-error-match")
visible: false
color: "red"
}
Widgets.ScalingLabel {
id: passwordChangeErrorLabel
//: Error changing password: Supplied password rejected
text: qsTr("password-change-error")
visible: false
color: "red"
}
// ***** Delete button and confirm flow *****
Widgets.Button {
//: Delete Profile
text: qsTr("delete-profile-btn")
icon: "regular/trash-alt"
visible: mode == "edit"
onClicked: {
deleting = true
}
}
Widgets.ScalingLabel {
id: deleteConfirmLabel
//: Type DELETE to confirm
text: qsTr("delete-confirm-label")+ ":"
visible: deleting
}
Widgets.TextField {
id: confirmDeleteTxt
Layout.fillWidth: true
//style: CwtchTextFieldStyle{ width: tehcol.width * 0.8 }
visible: deleting
}
Widgets.Button {
id: confirmDeleteBtn
icon: "regular/trash-alt"
//: Really Delete Profile
text: qsTr("delete-profile-confirm-btn")
color: "red"
visible: deleting
onClicked: {
//: DELETE
if (confirmDeleteTxt.text == qsTr("delete-confirm-text")) {
deleteConfirmLabel.color = "black"
gcd.deleteProfile(onion)
gcd.reloadProfileList()
parentStack.pane = parentStack.managementPane
} else {
deleteConfirmLabel.color = "red"
} }
} Widgets.ScalingLabel {
} id: noPasswordLabel
//: Not using a password on this account means that all data stored locally will not be encrypted
text: qsTr("no-password-warning")
visible: radioNoPassword.checked
}
Widgets.ScalingLabel {
id: currentPasswordLabel
//: Current Password
text: qsTr("current-password-label") + ":"
visible: radioUsePassword.checked && mode == "edit" && tag != "v1-defaultPassword"
}
Widgets.TextField {
id: txtCurrentPassword
Layout.fillWidth: true
echoMode: TextInput.Password
visible: radioUsePassword.checked && mode == "edit" && tag != "v1-defaultPassword"
}
Widgets.ScalingLabel {
id: passwordLabel
//: Password
text: qsTr("password1-label") + ":"
visible: radioUsePassword.checked
}
Widgets.TextField {
id: txtPassword1
Layout.fillWidth: true
//style: CwtchTextFieldStyle{ width: tehcol.width * 0.8 }
echoMode: TextInput.Password
visible: radioUsePassword.checked
onTextEdited: {
changingPassword = true
}
}
}//end of column with padding Widgets.ScalingLabel {
id: passwordReLabel
//: Reenter password
text: qsTr("password2-label") + ":"
visible: radioUsePassword.checked
}
Widgets.TextField {
id: txtPassword2
Layout.fillWidth: true
//style: CwtchTextFieldStyle{ width: tehcol.width * 0.8 }
echoMode: TextInput.Password
visible: radioUsePassword.checked
}
Widgets.Button { // ADD or SAVE button
//: Create Profile || Save Profile
text: mode == "add" ? qsTr("create-profile-btn") : qsTr("save-profile-btn")
onClicked: {
if (mode == "add") {
if (txtPassword1.text != txtPassword2.text) {
passwordErrorLabel.visible = true
} else {
gcd.createProfile(txtProfileName.text, radioNoPassword.checked, txtPassword1.text)
gcd.reloadProfileList()
parentStack.pane = parentStack.managementPane
}
} else {
gcd.updateNick(onion, txtProfileName.text)
if (changingPassword) {
if (txtPassword1.text != txtPassword2.text) {
passwordErrorLabel.visible = true
} else {
gcd.changePassword(onion, txtCurrentPassword.text, txtPassword1.text, radioNoPassword.checked)
}
} else {
gcd.reloadProfileList()
parentStack.pane = parentStack.managementPane
}
}
}
}
Widgets.ScalingLabel {
id: passwordErrorLabel
//: Passwords do not match
text: qsTr("password-error-match")
visible: false
color: "red"
}
Widgets.ScalingLabel {
id: passwordChangeErrorLabel
//: Error changing password: Supplied password rejected
text: qsTr("password-change-error")
visible: false
color: "red"
}
// ***** Delete button and confirm flow *****
Widgets.Button {
//: Delete Profile
text: qsTr("delete-profile-btn")
icon: "regular/trash-alt"
visible: mode == "edit"
onClicked: {
deleting = true
}
}
Widgets.ScalingLabel {
id: deleteConfirmLabel
//: Type DELETE to confirm
text: qsTr("delete-confirm-label")+ ":"
visible: deleting
}
Widgets.TextField {
id: confirmDeleteTxt
Layout.fillWidth: true
//style: CwtchTextFieldStyle{ width: tehcol.width * 0.8 }
visible: deleting
}
Widgets.Button {
id: confirmDeleteBtn
icon: "regular/trash-alt"
//: Really Delete Profile
text: qsTr("delete-profile-confirm-btn")
color: "red"
visible: deleting
onClicked: {
//: DELETE
if (confirmDeleteTxt.text == qsTr("delete-confirm-text")) {
deleteConfirmLabel.color = "black"
gcd.deleteProfile(onion)
gcd.reloadProfileList()
parentStack.pane = parentStack.managementPane
} else {
deleteConfirmLabel.color = "red"
}
}
}
}//end of column with padding
}//end of flickable }//end of flickable
Connections { // UPDATE UNREAD MESSAGES COUNTER Connections { // UPDATE UNREAD MESSAGES COUNTER
target: gcd target: gcd
onChangePasswordResponse: function(error) { onChangePasswordResponse: function(error) {
if (!error) { if (!error) {
gcd.reloadProfileList() gcd.reloadProfileList()
parentStack.pane = parentStack.managementPane parentStack.pane = parentStack.managementPane
} else { } else {
passwordChangeErrorLabel.visible = true passwordChangeErrorLabel.visible = true
} }
} }
} }
} }

View File

@ -30,7 +30,7 @@ ColumnLayout {
TextField { TextField {
id: txtPassword id: txtPassword
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
style: CwtchTextFieldStyle{ width: thecol.width * 0.8 } style: CwtchTextFieldStyle{ width: thecol.width * 0.8 }
echoMode: TextInput.Password echoMode: TextInput.Password
onAccepted: button.clicked() onAccepted: button.clicked()
} }
@ -60,26 +60,26 @@ ColumnLayout {
} }
Connections { // ADD/REMOVE CONTACT ENTRIES Connections { // ADD/REMOVE CONTACT ENTRIES
target: gcd target: gcd
onErrorLoaded0: function() { onErrorLoaded0: function() {
error.visible = true error.visible = true
} }
} }
Rectangle { // THE LEFT PANE WITH TOOLS AND CONTACTS Rectangle { // THE LEFT PANE WITH TOOLS AND CONTACTS
color: Theme.backgroundMainColor color: Theme.backgroundMainColor
width: thecol.width width: thecol.width
Layout.fillHeight: true Layout.fillHeight: true
Layout.fillWidth: true Layout.fillWidth: true
Layout.minimumWidth: Layout.maximumWidth Layout.minimumWidth: Layout.maximumWidth
//Layout.maximumWidth: theStack.pane == theStack.emptyPane ? parent.width : 450 //Layout.maximumWidth: theStack.pane == theStack.emptyPane ? parent.width : 450
Widgets.ProfileList { Widgets.ProfileList {
anchors.fill: parent anchors.fill: parent
} }
} }

View File

@ -12,125 +12,125 @@ import "../widgets/controls"
ColumnLayout { // settingsPane ColumnLayout { // settingsPane
id: root id: root
anchors.fill: parent anchors.fill: parent
StackToolbar { StackToolbar {
id: stb id: stb
//: Cwtch Settings title //: Cwtch Settings title
text: qsTr("cwtch-settings-title") text: qsTr("cwtch-settings-title")
aux.visible: false aux.visible: false
membership.visible: false membership.visible: false
} }
Flickable { Flickable {
anchors.top: stb.bottom anchors.top: stb.bottom
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
boundsBehavior: Flickable.StopAtBounds boundsBehavior: Flickable.StopAtBounds
clip:true clip:true
contentWidth: tehcol.width contentWidth: tehcol.width
contentHeight: tehcol.height contentHeight: tehcol.height
Column { Column {
id: tehcol id: tehcol
leftPadding: 10 leftPadding: 10
spacing: 5 spacing: 5
width: root.width width: root.width
ScalingLabel { ScalingLabel {
width: parent.width width: parent.width
wrapMode: TextEdit.Wrap wrapMode: TextEdit.Wrap
//: Version: %1 Built on: %2 //: Version: %1 Built on: %2
text: qsTr("version %1 builddate %2").arg(gcd.version).arg(gcd.buildDate) text: qsTr("version %1 builddate %2").arg(gcd.version).arg(gcd.buildDate)
} }
ScalingLabel { ScalingLabel {
width: parent.width width: parent.width
wrapMode: TextEdit.Wrap wrapMode: TextEdit.Wrap
//: Interface zoom (mostly affects text and button sizes) //: Interface zoom (mostly affects text and button sizes)
text: qsTr("zoom-label") + ":" text: qsTr("zoom-label") + ":"
} }
Slider { Slider {
id: zoomSlider id: zoomSlider
minimumValue: 0.5 minimumValue: 0.5
maximumValue: 4.0 maximumValue: 4.0
value: gcd.themeScale value: gcd.themeScale
updateValueWhileDragging: false updateValueWhileDragging: false
onValueChanged: { onValueChanged: {
gcd.themeScale = zoomSlider.value gcd.themeScale = zoomSlider.value
saveSettings() saveSettings()
} }
width: 400 width: 400
} }
CheckBox { CheckBox {
id: blockUnknownToggle id: blockUnknownToggle
checked: true checked: true
onClicked: { onClicked: {
if (blockUnknownToggle.checked) { if (blockUnknownToggle.checked) {
gcd.blockUnknownPeers() gcd.blockUnknownPeers()
} else { } else {
gcd.allowUnknownPeers() gcd.allowUnknownPeers()
} }
} }
style: CheckBoxStyle { style: CheckBoxStyle {
label: ScalingLabel { label: ScalingLabel {
text: qsTr("block-unknown-label") text: qsTr("block-unknown-label")
} }
} }
} }
ScalingLabel { ScalingLabel {
wrapMode: TextEdit.Wrap wrapMode: TextEdit.Wrap
text: qsTr("large-text-label") text: qsTr("large-text-label")
size: 20 size: 20
} }
ScalingLabel{ ScalingLabel{
width: parent.width width: parent.width
wrapMode: TextEdit.Wrap wrapMode: TextEdit.Wrap
//: "Default size text (scale factor: " //: "Default size text (scale factor: "
text: qsTr("default-scaling-text") + " " + Math.round(zoomSlider.value * 100) / 100 + ")" text: qsTr("default-scaling-text") + " " + Math.round(zoomSlider.value * 100) / 100 + ")"
} }
ScalingLabel { ScalingLabel {
text: qsTr("small-text-label") text: qsTr("small-text-label")
size: 8 size: 8
} }
GridLayout { GridLayout {
columns: 2 columns: 2
columnSpacing: 10 columnSpacing: 10
FlagButton { FlagButton {
emoji: "1f1e9-1f1ea" emoji: "1f1e9-1f1ea"
locale: "de" locale: "de"
} }
FlagButton { FlagButton {
emoji: "1f1e8-1f1e6" emoji: "1f1e8-1f1e6"
locale: "en" locale: "en"
selected: true selected: true
} }
FlagButton { FlagButton {
locale: "fr" locale: "fr"
emoji: "1f1eb-1f1f7" emoji: "1f1eb-1f1f7"
} }
FlagButton { FlagButton {
locale: "pt" locale: "pt"
emoji: "1f1e7-1f1f7" emoji: "1f1e7-1f1f7"
} }
} }
}//end of column with padding }//end of column with padding
}//end of flickable }//end of flickable
function saveSettings() { function saveSettings() {
@ -138,13 +138,13 @@ ColumnLayout { // settingsPane
gcd.saveSettings(zoomSlider.value, "") gcd.saveSettings(zoomSlider.value, "")
} }
Connections { Connections {
target: gcd target: gcd
onSupplySettings: function(zoom, locale, blockunknown) { onSupplySettings: function(zoom, locale, blockunknown) {
if (zoom != "") zoomSlider.value = zoom if (zoom != "") zoomSlider.value = zoom
// (locale is handled automatically by FlagButton) // (locale is handled automatically by FlagButton)
blockUnknownToggle.checked = blockunknown blockUnknownToggle.checked = blockunknown
} }
} }
} }

View File

@ -8,8 +8,8 @@ import QtQuick.Controls.Styles 1.4
import "../styles" import "../styles"
Item { Item {
id: sp id: sp
property bool running property bool running
Image { Image {
id: splashImage id: splashImage
@ -20,17 +20,17 @@ Item {
} }
ProgressBar { ProgressBar {
id: progressBar id: progressBar
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
anchors.top: splashImage.bottom anchors.top: splashImage.bottom
anchors.topMargin: 10 anchors.topMargin: 10
width: splashImage.width width: splashImage.width
indeterminate: true indeterminate: true
style: ProgressBarStyle { style: ProgressBarStyle {
progress: CwtchProgress { running: sp.running } progress: CwtchProgress { running: sp.running }
} }
} }
} }

View File

@ -3,5 +3,5 @@ import QtQuick 2.7
ComboBoxStyle { ComboBoxStyle {
textColor: "#000" textColor: "#000"
} }

View File

@ -2,20 +2,20 @@ import QtQuick.Controls.Styles 1.4
import QtQuick 2.7 import QtQuick 2.7
ButtonStyle { ButtonStyle {
background: Rectangle { background: Rectangle {
width:25 width:25
height:25 height:25
color: windowItem.cwtch_dark_color color: windowItem.cwtch_dark_color
border.color: windowItem.cwtch_color border.color: windowItem.cwtch_color
} }
label: Text { label: Text {
renderType: Text.NativeRendering renderType: Text.NativeRendering
verticalAlignment: Text.AlignVCenter verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter horizontalAlignment: Text.AlignHCenter
font.family: "Monospace" font.family: "Monospace"
font.pointSize: 8 font.pointSize: 8
color: windowItem.cwtch_background_color color: windowItem.cwtch_background_color
text: control.text text: control.text
} }
} }

View File

@ -8,32 +8,32 @@ import QtQuick.Controls.Styles 1.4
Rectangle { Rectangle {
id: pb id: pb
border.color: "#FFFFFF" border.color: "#FFFFFF"
border.width: 1 border.width: 1
color: "#D2C0DD" color: "#D2C0DD"
property bool running property bool running
// Indeterminate animation by animating alternating stripes: // Indeterminate animation by animating alternating stripes:
Item { Item {
anchors.fill: parent anchors.fill: parent
anchors.margins: 1 anchors.margins: 1
visible: control.indeterminate visible: control.indeterminate
clip: true clip: true
Row { Row {
Repeater { Repeater {
Rectangle { Rectangle {
color: index % 2 ? "#D2C0DD" : "#b29dbe" color: index % 2 ? "#D2C0DD" : "#b29dbe"
width: 20 ; height: control.height width: 20 ; height: control.height
} }
model: control.width / 20 + 2 model: control.width / 20 + 2
} }
XAnimator on x { XAnimator on x {
from: 0 ; to: -40 from: 0 ; to: -40
loops: Animation.Infinite loops: Animation.Infinite
running: pb.running running: pb.running
} }
} }
} }
} }

View File

@ -3,6 +3,6 @@ import QtQuick 2.7
TextAreaStyle { TextAreaStyle {
textColor: "black" textColor: "black"
backgroundColor: windowItem.cwtch_background_color backgroundColor: windowItem.cwtch_background_color
} }

View File

@ -3,13 +3,13 @@ import QtQuick 2.7
TextFieldStyle { TextFieldStyle {
id: root id: root
textColor: "black" textColor: "black"
font.pointSize: 10 * gcd.themeScale font.pointSize: 10 * gcd.themeScale
property int width: parent.width property int width: parent.width
background: Rectangle { background: Rectangle {
radius: 2 radius: 2
color: windowItem.cwtch_background_color color: windowItem.cwtch_background_color
border.color: windowItem.cwtch_color border.color: windowItem.cwtch_color
} }
} }

View File

@ -1,34 +1,34 @@
ThemeType { ThemeType {
readonly property color darkGrayPurple: "#281831" readonly property color darkGrayPurple: "#281831"
readonly property color deepPurple: "#422850" readonly property color deepPurple: "#422850"
readonly property color mauvePurple: "#8E64A5" readonly property color mauvePurple: "#8E64A5"
readonly property color purple: "#DFB9DE" readonly property color purple: "#DFB9DE"
readonly property color whitePurple: "#FFFDFF" readonly property color whitePurple: "#FFFDFF"
readonly property color softPurple: "#FDF3FC" readonly property color softPurple: "#FDF3FC"
readonly property color pink: "#E85DA1" readonly property color pink: "#E85DA1"
readonly property color hotPink: "#D01972" readonly property color hotPink: "#D01972"
backgroundMainColor: darkGrayPurple backgroundMainColor: darkGrayPurple
backgroundPaneColor: deepPurple backgroundPaneColor: deepPurple
mainTextColor: whitePurple mainTextColor: whitePurple
defaultButtonColor: mauvePurple defaultButtonColor: mauvePurple
defaultButtonActiveColor: pink defaultButtonActiveColor: pink
defaultButtonTextColor: whitePurple defaultButtonTextColor: whitePurple
portraitOnlineBorderColor: whitePurple portraitOnlineBorderColor: whitePurple
portraitOnlineBackgroundColor: darkGrayPurple portraitOnlineBackgroundColor: darkGrayPurple
portraitOnlineTextColor: whitePurple portraitOnlineTextColor: whitePurple
portraitConnectingBorderColor: mauvePurple portraitConnectingBorderColor: mauvePurple
portraitConnectingBackgroundColor: darkGrayPurple portraitConnectingBackgroundColor: darkGrayPurple
portraitConnectingTextColor: whitePurple portraitConnectingTextColor: whitePurple
portraitOfflineBorderColor: deepPurple portraitOfflineBorderColor: deepPurple
portraitOfflineBackgroundColor: darkGrayPurple portraitOfflineBackgroundColor: darkGrayPurple
portraitOfflineTextColor: softPurple portraitOfflineTextColor: softPurple
portraitContactBadgeColor: hotPink portraitContactBadgeColor: hotPink
portraitContactBadgeTextColor: whitePurple portraitContactBadgeTextColor: whitePurple
portraitProfileBadgeColor: mauvePurple portraitProfileBadgeColor: mauvePurple
dropShadowColor: darkGrayPurple dropShadowColor: darkGrayPurple
} }

View File

@ -1,34 +1,34 @@
ThemeType { ThemeType {
readonly property color whitePurple: "#FFFDFF" readonly property color whitePurple: "#FFFDFF"
readonly property color softPurple: "#FDF3FC" readonly property color softPurple: "#FDF3FC"
readonly property color purple: "#DFB9DE" readonly property color purple: "#DFB9DE"
readonly property color brightPurple: "#760388" readonly property color brightPurple: "#760388"
readonly property color darkPurple: "#350052" readonly property color darkPurple: "#350052"
readonly property color greyPurple: "#775F84" readonly property color greyPurple: "#775F84"
readonly property color pink: "#E85DA1" readonly property color pink: "#E85DA1"
readonly property color hotPink: "#D01972" readonly property color hotPink: "#D01972"
backgroundMainColor: whitePurple backgroundMainColor: whitePurple
backgroundPaneColor: softPurple backgroundPaneColor: softPurple
mainTextColor: darkPurple mainTextColor: darkPurple
defaultButtonColor: hotPink defaultButtonColor: hotPink
defaultButtonActiveColor: pink defaultButtonActiveColor: pink
defaultButtonTextColor: whitePurple defaultButtonTextColor: whitePurple
portraitOnlineBorderColor: darkPurple portraitOnlineBorderColor: darkPurple
portraitOnlineBackgroundColor: darkPurple portraitOnlineBackgroundColor: darkPurple
portraitOnlineTextColor: darkPurple portraitOnlineTextColor: darkPurple
portraitConnectingBorderColor: greyPurple portraitConnectingBorderColor: greyPurple
portraitConnectingBackgroundColor: greyPurple portraitConnectingBackgroundColor: greyPurple
portraitConnectingTextColor: greyPurple portraitConnectingTextColor: greyPurple
portraitOfflineBorderColor: purple portraitOfflineBorderColor: purple
portraitOfflineBackgroundColor: purple portraitOfflineBackgroundColor: purple
portraitOfflineTextColor: purple portraitOfflineTextColor: purple
portraitContactBadgeColor: hotPink portraitContactBadgeColor: hotPink
portraitContactBadgeTextColor: whitePurple portraitContactBadgeTextColor: whitePurple
portraitProfileBadgeColor: brightPurple portraitProfileBadgeColor: brightPurple
dropShadowColor: purple dropShadowColor: purple
} }

View File

@ -38,5 +38,5 @@ Item {
readonly property int sidePaneMinSize: 700 readonly property int sidePaneMinSize: 700
readonly property int doublePaneMinSize: 1000 readonly property int doublePaneMinSize: 1000
property ThemeType theme: CwtchDark { } property ThemeType theme: CwtchDark { }
} }

View File

@ -1,31 +1,31 @@
import QtQuick 2.0 import QtQuick 2.0
QtObject { QtObject {
property color backgroundMainColor: "red" property color backgroundMainColor: "red"
property color backgroundPaneColor: "red" property color backgroundPaneColor: "red"
property color mainTextColor: "red" property color mainTextColor: "red"
property color defaultButtonColor: "red" property color defaultButtonColor: "red"
property color defaultButtonActiveColor: "red" property color defaultButtonActiveColor: "red"
property color defaultButtonTextColor: "red" property color defaultButtonTextColor: "red"
property color portraitOnlineBorderColor: "red" property color portraitOnlineBorderColor: "red"
property color portraitOnlineBackgroundColor: "red" property color portraitOnlineBackgroundColor: "red"
property color portraitOnlineTextColor: "red" property color portraitOnlineTextColor: "red"
property color portraitConnectingBorderColor: "red" property color portraitConnectingBorderColor: "red"
property color portraitConnectingBackgroundColor: "red" property color portraitConnectingBackgroundColor: "red"
property color portraitConnectingTextColor: "red" property color portraitConnectingTextColor: "red"
property color portraitOfflineBorderColor: "red" property color portraitOfflineBorderColor: "red"
property color portraitOfflineBackgroundColor: "red" property color portraitOfflineBackgroundColor: "red"
property color portraitOfflineTextColor: "red" property color portraitOfflineTextColor: "red"
property color portraitContactBadgeColor: "red" property color portraitContactBadgeColor: "red"
property color portraitContactBadgeTextColor: "red" property color portraitContactBadgeTextColor: "red"
property color portraitProfileBadgeColor: "red" property color portraitProfileBadgeColor: "red"
property color dropShadowColor: "black" property color dropShadowColor: "black"
// ... more to come // ... more to come
} }

View File

@ -21,4 +21,4 @@ Rectangle {
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
} }
} }

View File

@ -15,9 +15,9 @@ Rectangle {
height: 20 * gcd.themeScale height: 20 * gcd.themeScale
Layout.minimumHeight: height Layout.minimumHeight: height
Layout.maximumHeight: height Layout.maximumHeight: height
color: mousedown ? Theme.defaultButtonActiveColor : Theme.defaultButtonColor color: mousedown ? Theme.defaultButtonActiveColor : Theme.defaultButtonColor
border.color: mousedown ? Theme.defaultButtonActiveColor : Theme.defaultButtonColor border.color: mousedown ? Theme.defaultButtonActiveColor : Theme.defaultButtonColor
border.width: 1 border.width: 1
radius: override_radius radius: override_radius
antialiasing: true antialiasing: true
@ -31,31 +31,31 @@ Rectangle {
signal clicked signal clicked
RowLayout { RowLayout {
anchors.centerIn: parent anchors.centerIn: parent
Image { Image {
anchors.left: parent.left anchors.left: parent.left
id: ico id: ico
source: icon!="" ? gcd.assetPath + "fontawesome/"+icon+".svg" : ""; source: icon!="" ? gcd.assetPath + "fontawesome/"+icon+".svg" : "";
height: button.height / 2 height: button.height / 2
sourceSize.height: button.height / 2 sourceSize.height: button.height / 2
} }
Label { Label {
id: buttonText id: buttonText
font.family: Fonts.applicationFontRegular.name font.family: Fonts.applicationFontRegular.name
font.styleName: "ExtraBold" font.styleName: "ExtraBold"
font.pixelSize: button.height / 2 font.pixelSize: button.height / 2
color: Theme.defaultButtonTextColor color: Theme.defaultButtonTextColor
anchors.left: ico.right anchors.left: ico.right
anchors.leftMargin: 6 anchors.leftMargin: 6
visible: button.text != "" && button.text != undefined visible: button.text != "" && button.text != undefined
} }
ToolTip.visible: tooltip != "" && mouseArea.containsMouse ToolTip.visible: tooltip != "" && mouseArea.containsMouse
ToolTip.text: tooltip ToolTip.text: tooltip
} }
MouseArea { MouseArea {
@ -63,16 +63,16 @@ Rectangle {
anchors.fill: parent anchors.fill: parent
onClicked: { onClicked: {
parent.focus = true parent.focus = true
parent.clicked() parent.clicked()
} }
onPressed: mousedown = true onPressed: mousedown = true
onReleased: mousedown = false onReleased: mousedown = false
hoverEnabled: true hoverEnabled: true
} }
Keys.onSpacePressed: clicked() Keys.onSpacePressed: clicked()
} }

View File

@ -31,17 +31,17 @@ TextField {
} }
} }
Widgets.Button { Widgets.Button {
icon: "" icon: ""
text: button_text text: button_text
anchors { top: parent.top; right: parent.right } anchors { top: parent.top; right: parent.right }
override_radius: 10 override_radius: 10
height: parent.height; width: parent.height * 4 height: parent.height; width: parent.height * 4
onClicked: { onClicked: {
parent.focus = true; parent.focus = true;
parent.clicked(); parent.clicked();
} }
} }
} }

View File

@ -6,9 +6,9 @@ import QtQuick.Layouts 1.3
import "../theme" import "../theme"
ColumnLayout { ColumnLayout {
id: root id: root
property alias dualPane: myprof.dualPane property alias dualPane: myprof.dualPane
MouseArea { MouseArea {
@ -20,26 +20,26 @@ ColumnLayout {
} }
MyProfile { // CURRENT PROFILE INFO AND CONTROL BAR MyProfile { // CURRENT PROFILE INFO AND CONTROL BAR
id: myprof id: myprof
} }
Flickable { // THE ACTUAL CONTACT LIST Flickable { // THE ACTUAL CONTACT LIST
id: sv id: sv
//Layout.alignment: Qt.AlignLeft | Qt.AlignTop //Layout.alignment: Qt.AlignLeft | Qt.AlignTop
clip: true clip: true
Layout.minimumHeight: 100 Layout.minimumHeight: 100
//Layout.maximumHeight: parent.height - 30 //Layout.maximumHeight: parent.height - 30
Layout.fillHeight: true Layout.fillHeight: true
Layout.minimumWidth: parent.width Layout.minimumWidth: parent.width
Layout.maximumWidth: parent.width Layout.maximumWidth: parent.width
contentWidth: colContacts.width contentWidth: colContacts.width
contentHeight: colContacts.height contentHeight: colContacts.height
boundsBehavior: Flickable.StopAtBounds boundsBehavior: Flickable.StopAtBounds
maximumFlickVelocity: 400 maximumFlickVelocity: 400
ScrollBar.vertical: ScrollBar { ScrollBar.vertical: ScrollBar {
policy: ScrollBar.AsNeeded policy: ScrollBar.AsNeeded
background: Rectangle { background: Rectangle {
implicitWidth: 6 implicitWidth: 6
@ -50,15 +50,15 @@ ColumnLayout {
implicitHeight:1 implicitHeight:1
color: Theme.backgroundPaneColor color: Theme.backgroundPaneColor
} }
} }
ColumnLayout { ColumnLayout {
id: colContacts id: colContacts
width: root.width width: root.width
spacing: 0 spacing: 0
Connections { // ADD/REMOVE CONTACT ENTRIES Connections { // ADD/REMOVE CONTACT ENTRIES
target: gcd target: gcd
onAddContact: function(handle, displayName, image, badge, status, blocked, loading, lastMsgTs) { onAddContact: function(handle, displayName, image, badge, status, blocked, loading, lastMsgTs) {
@ -77,33 +77,33 @@ ColumnLayout {
} }
var newContact = { var newContact = {
"_handle": handle, "_handle": handle,
"_displayName": displayName + (blocked ? " (blocked)" : "" ), "_displayName": displayName + (blocked ? " (blocked)" : "" ),
"_image": image, "_image": image,
"_badge": badge, "_badge": badge,
"_status": status, "_status": status,
"_blocked": blocked, "_blocked": blocked,
"_loading": loading, "_loading": loading,
"_loading": loading, "_loading": loading,
"_lastMsgTs": lastMsgTs "_lastMsgTs": lastMsgTs
} }
contactsModel.insert(index, newContact) contactsModel.insert(index, newContact)
} }
onRemoveContact: function(handle) { onRemoveContact: function(handle) {
for(var i = 0; i < contactsModel.count; i++){ for(var i = 0; i < contactsModel.count; i++){
if(contactsModel.get(i)["_handle"] == handle) { if(contactsModel.get(i)["_handle"] == handle) {
console.log("deleting contact " + contactsModel.get(i)["_handle"]) console.log("deleting contact " + contactsModel.get(i)["_handle"])
contactsModel.remove(i) contactsModel.remove(i)
return return
} }
} }
} }
onIncContactUnreadCount: function(handle) { onIncContactUnreadCount: function(handle) {
var ts = Math.round((new Date()).getTime() / 1000); var ts = Math.round((new Date()).getTime() / 1000);
for(var i = 0; i < contactsModel.count; i++){ for(var i = 0; i < contactsModel.count; i++){
if(contactsModel.get(i)["_handle"] == handle) { if(contactsModel.get(i)["_handle"] == handle) {
var contact = contactsModel.get(i) var contact = contactsModel.get(i)
contact["_lastMsgTs"] = ts contact["_lastMsgTs"] = ts
@ -112,31 +112,31 @@ ColumnLayout {
} }
} }
onResetProfile: function() { onResetProfile: function() {
contactsModel.clear() contactsModel.clear()
} }
} }
ListModel { // CONTACT OBJECTS ARE STORED HERE ... ListModel { // CONTACT OBJECTS ARE STORED HERE ...
id: contactsModel id: contactsModel
} }
Repeater { Repeater {
model: contactsModel // ... AND DISPLAYED HERE model: contactsModel // ... AND DISPLAYED HERE
delegate: ContactRow { delegate: ContactRow {
handle: _handle handle: _handle
displayName: _displayName displayName: _displayName
image: _image image: _image
badge: _badge badge: _badge
status: _status status: _status
blocked: _blocked blocked: _blocked
loading: _loading loading: _loading
} }
} }
} }
} }
} }

View File

@ -12,7 +12,7 @@ import QtQuick.Controls.Styles 1.4
PortraitRow { PortraitRow {
property int status: 0 property int status: 0
property int badge property int badge
property bool loading property bool loading
@ -28,24 +28,24 @@ PortraitRow {
} }
ProgressBar { // LOADING ? ProgressBar { // LOADING ?
id: loadingProgress id: loadingProgress
property bool running property bool running
running: loading running: loading
visible: loading visible: loading
anchors.right: parent.right anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
anchors.leftMargin: 1 * gcd.themeScale anchors.leftMargin: 1 * gcd.themeScale
anchors.rightMargin: 25 * gcd.themeScale anchors.rightMargin: 25 * gcd.themeScale
height: parent.height * .1 height: parent.height * .1
width: 100 * gcd.themeScale width: 100 * gcd.themeScale
indeterminate: true indeterminate: true
style: ProgressBarStyle { style: ProgressBarStyle {
progress: CwtchProgress { running: loadingProgress.running} progress: CwtchProgress { running: loadingProgress.running}
} }
} }
onClicked: function(handle) { onClicked: function(handle) {
@ -59,39 +59,39 @@ PortraitRow {
} }
} }
Component.onCompleted: { setColors(status) } Component.onCompleted: { setColors(status) }
onStatusChanged: { setColors(status) } onStatusChanged: { setColors(status) }
function setColors(status) { function setColors(status) {
//-2:WtfCodeError,-1:Error,0:Disconnected,1:Connecting,2:Connected,3:Authenticated,4:Synced,5:Failed,6:Killed //-2:WtfCodeError,-1:Error,0:Disconnected,1:Connecting,2:Connected,3:Authenticated,4:Synced,5:Failed,6:Killed
if (status == 4 || status == 3) { if (status == 4 || status == 3) {
portraitBorderColor = Theme.portraitOnlineBorderColor portraitBorderColor = Theme.portraitOnlineBorderColor
portraitColor = Theme.portraitOnlineBackgroundColor portraitColor = Theme.portraitOnlineBackgroundColor
nameColor = Theme.portraitOnlineTextColor nameColor = Theme.portraitOnlineTextColor
onionColor = Theme.portraitOnlineTextColor onionColor = Theme.portraitOnlineTextColor
} else if (status == 2 || status == 1) { } else if (status == 2 || status == 1) {
portraitBorderColor = Theme.portraitConnectingBorderColor portraitBorderColor = Theme.portraitConnectingBorderColor
portraitColor = Theme.portraitConnectingBackgroundColor portraitColor = Theme.portraitConnectingBackgroundColor
nameColor = Theme.portraitConnectingTextColor nameColor = Theme.portraitConnectingTextColor
onionColor = Theme.portraitConnectingTextColor onionColor = Theme.portraitConnectingTextColor
} else { } else {
portraitBorderColor = Theme.portraitOfflineBorderColor portraitBorderColor = Theme.portraitOfflineBorderColor
portraitColor = Theme.portraitOfflineBackgroundColor portraitColor = Theme.portraitOfflineBackgroundColor
nameColor = Theme.portraitOfflineTextColor nameColor = Theme.portraitOfflineTextColor
onionColor = Theme.portraitOfflineTextColor onionColor = Theme.portraitOfflineTextColor
} }
} }
Connections { // UPDATE UNREAD MESSAGES COUNTER Connections { // UPDATE UNREAD MESSAGES COUNTER
target: gcd target: gcd
onUpdateContactStatus: function(_handle, _status, _loading) { onUpdateContactStatus: function(_handle, _status, _loading) {
if (handle == _handle) { if (handle == _handle) {
status = _status status = _status
loadingProgress.visible = loadingProgress.running = loading = _loading loadingProgress.visible = loadingProgress.running = loading = _loading
} }
} }
onIncContactUnreadCount: function(handle) { onIncContactUnreadCount: function(handle) {
if (handle == _handle && gcd.selectedConversation != handle) { if (handle == _handle && gcd.selectedConversation != handle) {
@ -99,4 +99,4 @@ PortraitRow {
} }
} }
} }
} }

View File

@ -24,7 +24,7 @@ Item {
Label { Label {
id: label id: label
textFormat: Text.PlainText textFormat: Text.PlainText
elide: Text.ElideRight elide: Text.ElideRight
text: textMetric.text text: textMetric.text
@ -37,7 +37,7 @@ Item {
} }
/*onWidthChanged: { /*onWidthChanged: {
setTextResize() setTextResize()
}*/ }*/
onTextChanged: { onTextChanged: {
@ -54,4 +54,4 @@ Item {
} }
} }
} }

View File

@ -10,391 +10,391 @@ import "../fonts/MutantStandard.js" as Mutant
import "controls" import "controls"
Item { Item {
id: root id: root
height: 0 height: 0
property int size: 24 property int size: 24
property int requestedHeight: size * 8 property int requestedHeight: size * 8
property string morph: "clw" property string morph: "clw"
property string color: "v1" property string color: "v1"
property bool narrowMode: width < (txtSearch.width + root.size * 14 + btnX.width) property bool narrowMode: width < (txtSearch.width + root.size * 14 + btnX.width)
signal picked(string shortcode) signal picked(string shortcode)
signal slideopen() signal slideopen()
signal slideclosed() signal slideclosed()
visible: height != 0 visible: height != 0
Rectangle { Rectangle {
color: windowItem.cwtch_dark_color color: windowItem.cwtch_dark_color
anchors.fill: parent anchors.fill: parent
} }
PropertyAnimation { PropertyAnimation {
id: animClose; id: animClose;
target: root; target: root;
properties: "height"; properties: "height";
to: 0; to: 0;
duration: 400; duration: 400;
} }
PropertyAnimation { PropertyAnimation {
id: animOpen; id: animOpen;
target: root; target: root;
properties: "height"; properties: "height";
to: requestedHeight; to: requestedHeight;
duration: 400; duration: 400;
} }
Button { Button {
id: btnX id: btnX
anchors.top: parent.top anchors.top: parent.top
anchors.right: parent.right anchors.right: parent.right
text: "x" text: "x"
onClicked: animClose.start() onClicked: animClose.start()
} }
ColumnLayout { ColumnLayout {
anchors.fill: parent anchors.fill: parent
RowLayout { RowLayout {
TextField { TextField {
id: txtSearch id: txtSearch
//: Search... //: Search...
placeholderText: qsTr("search") placeholderText: qsTr("search")
onTextChanged: { onTextChanged: {
if (text == "") emojiModel.model = folder_expressions if (text == "") emojiModel.model = folder_expressions
else emojiModel.model = folder_search else emojiModel.model = folder_search
emojiModel.updatefilters() emojiModel.updatefilters()
} }
} }
ImageButton { ImageButton {
id: btnEmojiExpressionsGroup id: btnEmojiExpressionsGroup
visible: !root.narrowMode visible: !root.narrowMode
//: Expressions //: Expressions
tooltip: qsTr("emojicat-expressions") tooltip: qsTr("emojicat-expressions")
source: gcd.assetPath + "mutstd/smile.webp" source: gcd.assetPath + "mutstd/smile.webp"
size: root.size size: root.size
onClicked: emojiModel.model = folder_expressions onClicked: emojiModel.model = folder_expressions
} }
ImageButton { ImageButton {
visible: !root.narrowMode visible: !root.narrowMode
//: Activities //: Activities
tooltip: qsTr("emojicat-activities") tooltip: qsTr("emojicat-activities")
source: gcd.assetPath + "mutstd/artist_r1.webp" source: gcd.assetPath + "mutstd/artist_r1.webp"
size: root.size size: root.size
onClicked: emojiModel.model = folder_activities_clothing onClicked: emojiModel.model = folder_activities_clothing
} }
ImageButton { ImageButton {
visible: !root.narrowMode visible: !root.narrowMode
//: Food, drink & herbs //: Food, drink & herbs
tooltip: qsTr("emojicat-food") tooltip: qsTr("emojicat-food")
source: gcd.assetPath + "mutstd/red_apple.webp" source: gcd.assetPath + "mutstd/red_apple.webp"
size: root.size size: root.size
onClicked: emojiModel.model = folder_food_drink_herbs onClicked: emojiModel.model = folder_food_drink_herbs
} }
ImageButton { ImageButton {
visible: !root.narrowMode visible: !root.narrowMode
//: Gender, relationships & sexuality //: Gender, relationships & sexuality
tooltip: qsTr("emojicat-gender") tooltip: qsTr("emojicat-gender")
size: root.size size: root.size
source: gcd.assetPath + "mutstd/pride_100.webp" source: gcd.assetPath + "mutstd/pride_100.webp"
onClicked: emojiModel.model = folder_gsr onClicked: emojiModel.model = folder_gsr
} }
ImageButton { ImageButton {
visible: !root.narrowMode visible: !root.narrowMode
//: Nature and effects //: Nature and effects
tooltip: qsTr("emojicat-nature") tooltip: qsTr("emojicat-nature")
source: gcd.assetPath + "mutstd/sun_behind_small_cloud.webp" source: gcd.assetPath + "mutstd/sun_behind_small_cloud.webp"
size: root.size size: root.size
onClicked: emojiModel.model = folder_nature onClicked: emojiModel.model = folder_nature
} }
ImageButton { ImageButton {
visible: !root.narrowMode visible: !root.narrowMode
//: Objects //: Objects
tooltip: qsTr("emojicat-objects") tooltip: qsTr("emojicat-objects")
source: gcd.assetPath + "mutstd/crystal_ball.webp" source: gcd.assetPath + "mutstd/crystal_ball.webp"
size: root.size size: root.size
onClicked: emojiModel.model = folder_objects onClicked: emojiModel.model = folder_objects
} }
ImageButton { ImageButton {
visible: !root.narrowMode visible: !root.narrowMode
//: People and animals //: People and animals
tooltip: qsTr("emojicat-people") tooltip: qsTr("emojicat-people")
source: gcd.assetPath + "mutstd/crow.webp" source: gcd.assetPath + "mutstd/crow.webp"
size: root.size size: root.size
onClicked: emojiModel.model = folder_people onClicked: emojiModel.model = folder_people
} }
ImageButton { ImageButton {
visible: !root.narrowMode visible: !root.narrowMode
//: Symbols //: Symbols
tooltip: qsTr("emojicat-symbols") tooltip: qsTr("emojicat-symbols")
source: gcd.assetPath + "mutstd/purple_heart.webp" source: gcd.assetPath + "mutstd/purple_heart.webp"
size: root.size size: root.size
onClicked: emojiModel.model = folder_symbols onClicked: emojiModel.model = folder_symbols
} }
ImageButton { ImageButton {
visible: !root.narrowMode visible: !root.narrowMode
//: Travel & places //: Travel & places
tooltip: qsTr("emojicat-travel") tooltip: qsTr("emojicat-travel")
source: gcd.assetPath + "mutstd/airplane.webp" source: gcd.assetPath + "mutstd/airplane.webp"
size: root.size size: root.size
onClicked: emojiModel.model = folder_travel_places onClicked: emojiModel.model = folder_travel_places
} }
ImageButton { ImageButton {
visible: !root.narrowMode visible: !root.narrowMode
//: Miscellaneous //: Miscellaneous
tooltip: qsTr("emojicat-misc") tooltip: qsTr("emojicat-misc")
source: gcd.assetPath + "mutstd/hash_char.webp" source: gcd.assetPath + "mutstd/hash_char.webp"
size: root.size size: root.size
onClicked: emojiModel.model = folder_utils onClicked: emojiModel.model = folder_utils
} }
ImageButton { ImageButton {
visible: !root.narrowMode visible: !root.narrowMode
id: btnUndefinedGroup id: btnUndefinedGroup
// (no tooltip; this is a catchall group meant to detect unclassified emoji during development) // (no tooltip; this is a catchall group meant to detect unclassified emoji during development)
//TODO: remove this category upon finalizing the Emoji Drawer //TODO: remove this category upon finalizing the Emoji Drawer
source: gcd.assetPath + "mutstd/undefined_character.webp" source: gcd.assetPath + "mutstd/undefined_character.webp"
size: root.size size: root.size
onClicked: emojiModel.model = folder_other onClicked: emojiModel.model = folder_other
} }
Item { Item {
visible: root.narrowMode visible: root.narrowMode
height: root.size height: root.size
width: root.size width: root.size
Image { Image {
id: imgCatRot id: imgCatRot
anchors.centerIn: parent anchors.centerIn: parent
source: cats[index].source source: cats[index].source
property int index: 0 property int index: 0
property var cats: [ property var cats: [
{source: gcd.assetPath + "mutstd/smile.webp", model: folder_expressions}, {source: gcd.assetPath + "mutstd/smile.webp", model: folder_expressions},
{source: gcd.assetPath + "mutstd/artist_r1.webp", model: folder_activities_clothing}, {source: gcd.assetPath + "mutstd/artist_r1.webp", model: folder_activities_clothing},
{source: gcd.assetPath + "mutstd/red_apple.webp", model: folder_food_drink_herbs}, {source: gcd.assetPath + "mutstd/red_apple.webp", model: folder_food_drink_herbs},
{source: gcd.assetPath + "mutstd/pride_100.webp", model: folder_gsr}, {source: gcd.assetPath + "mutstd/pride_100.webp", model: folder_gsr},
{source: gcd.assetPath + "mutstd/sun_behind_small_cloud.webp", model: folder_nature}, {source: gcd.assetPath + "mutstd/sun_behind_small_cloud.webp", model: folder_nature},
{source: gcd.assetPath + "mutstd/crystal_ball.webp", model: folder_objects}, {source: gcd.assetPath + "mutstd/crystal_ball.webp", model: folder_objects},
{source: gcd.assetPath + "mutstd/crow.webp", model: folder_people}, {source: gcd.assetPath + "mutstd/crow.webp", model: folder_people},
{source: gcd.assetPath + "mutstd/purple_heart.webp", model: folder_symbols}, {source: gcd.assetPath + "mutstd/purple_heart.webp", model: folder_symbols},
{source: gcd.assetPath + "mutstd/airplane.webp", model: folder_travel_places}, {source: gcd.assetPath + "mutstd/airplane.webp", model: folder_travel_places},
{source: gcd.assetPath + "mutstd/hash_char.webp", model: folder_utils}, {source: gcd.assetPath + "mutstd/hash_char.webp", model: folder_utils},
{source: gcd.assetPath + "mutstd/undefined_character.webp", model: folder_other} {source: gcd.assetPath + "mutstd/undefined_character.webp", model: folder_other}
] ]
height: root.size * (maCatRot.pressed ? 0.8 : 1.0) height: root.size * (maCatRot.pressed ? 0.8 : 1.0)
width: root.size * (maCatRot.pressed ? 0.8 : 1.0) width: root.size * (maCatRot.pressed ? 0.8 : 1.0)
ToolTip.visible: maCatRot.containsMouse ToolTip.visible: maCatRot.containsMouse
ToolTip.text: gcd.os == "android" ? qsTr("cycle-cats-android") : qsTr("cycle-cats-desktop") ToolTip.text: gcd.os == "android" ? qsTr("cycle-cats-android") : qsTr("cycle-cats-desktop")
MouseArea { MouseArea {
id: maCatRot id: maCatRot
hoverEnabled: true hoverEnabled: true
acceptedButtons: Qt.LeftButton | Qt.RightButton acceptedButtons: Qt.LeftButton | Qt.RightButton
anchors.fill: parent; anchors.fill: parent;
onClicked: { onClicked: {
if (mouse.button == Qt.RightButton) {//todo: long press on android if (mouse.button == Qt.RightButton) {//todo: long press on android
imgCatRot.index = 0 imgCatRot.index = 0
} else { } else {
imgCatRot.index = (imgCatRot.index + 1) % imgCatRot.cats.length imgCatRot.index = (imgCatRot.index + 1) % imgCatRot.cats.length
} }
emojiModel.model = imgCatRot.cats[imgCatRot.index].model emojiModel.model = imgCatRot.cats[imgCatRot.index].model
//root.morph = Mutant.standard.morphs[imgMorph.index] //root.morph = Mutant.standard.morphs[imgMorph.index]
//emojiModel.updatefilters() //emojiModel.updatefilters()
} }
} }
} }
} }
Item { Item {
height: root.size height: root.size
width: root.size width: root.size
Image { Image {
id: imgMorph id: imgMorph
anchors.centerIn: parent anchors.centerIn: parent
source: gcd.assetPath + "mutstd/hand_"+Mutant.standard.morphs[index]+"_"+root.color+".webp" source: gcd.assetPath + "mutstd/hand_"+Mutant.standard.morphs[index]+"_"+root.color+".webp"
property int index: 0 property int index: 0
height: root.size height: root.size
width: root.size width: root.size
ToolTip.visible: maMorph.containsMouse ToolTip.visible: maMorph.containsMouse
ToolTip.text: gcd.os == "android" ? qsTr("cycle-morphs-android") : qsTr("cycle-morphs-desktop") ToolTip.text: gcd.os == "android" ? qsTr("cycle-morphs-android") : qsTr("cycle-morphs-desktop")
MouseArea { MouseArea {
id: maMorph id: maMorph
hoverEnabled: true hoverEnabled: true
acceptedButtons: Qt.LeftButton | Qt.RightButton acceptedButtons: Qt.LeftButton | Qt.RightButton
anchors.fill: parent; anchors.fill: parent;
onClicked: { onClicked: {
if (mouse.button == Qt.RightButton) {//todo: long press on android if (mouse.button == Qt.RightButton) {//todo: long press on android
imgMorph.index = 0//TODO: saved morph imgMorph.index = 0//TODO: saved morph
} else { } else {
imgMorph.index = (imgMorph.index + 1) % Mutant.standard.morphs.length imgMorph.index = (imgMorph.index + 1) % Mutant.standard.morphs.length
} }
root.morph = Mutant.standard.morphs[imgMorph.index] root.morph = Mutant.standard.morphs[imgMorph.index]
emojiModel.updatefilters() emojiModel.updatefilters()
} }
} }
} }
} }
Item { Item {
height: root.size height: root.size
width: root.size width: root.size
Image { Image {
id: imgColor id: imgColor
anchors.centerIn: parent anchors.centerIn: parent
source: gcd.assetPath + "mutstd/color_modifier_"+Mutant.standard.colorByIndex(index, root.morph)+".webp" source: gcd.assetPath + "mutstd/color_modifier_"+Mutant.standard.colorByIndex(index, root.morph)+".webp"
property int index: 0 property int index: 0
height: root.size height: root.size
width: root.size width: root.size
ToolTip.visible: ma.containsMouse ToolTip.visible: ma.containsMouse
ToolTip.text: gcd.os == "android" ? qsTr("cycle-colours-android") : qsTr("cycle-colours-desktop") ToolTip.text: gcd.os == "android" ? qsTr("cycle-colours-android") : qsTr("cycle-colours-desktop")
MouseArea { MouseArea {
id: ma id: ma
anchors.fill: parent; anchors.fill: parent;
hoverEnabled: true hoverEnabled: true
acceptedButtons: Qt.LeftButton | Qt.RightButton acceptedButtons: Qt.LeftButton | Qt.RightButton
onClicked: function(mouse){ onClicked: function(mouse){
if (mouse.button == Qt.RightButton) {//todo: long press on android if (mouse.button == Qt.RightButton) {//todo: long press on android
imgColor.index = 0//todo: saved color imgColor.index = 0//todo: saved color
} else { } else {
imgColor.index = (imgColor.index + 1) % Mutant.standard.numColors(root.morph) imgColor.index = (imgColor.index + 1) % Mutant.standard.numColors(root.morph)
} }
root.color = Mutant.standard.colorByIndex(imgColor.index, root.morph) root.color = Mutant.standard.colorByIndex(imgColor.index, root.morph)
emojiModel.updatefilters() emojiModel.updatefilters()
} }
} }
} }
} }
} }
GridView { GridView {
Layout.fillWidth: true Layout.fillWidth: true
Layout.fillHeight: true Layout.fillHeight: true
height: root.size * 3 height: root.size * 3
cellWidth: root.size cellWidth: root.size
cellHeight: root.size cellHeight: root.size
clip: true clip: true
ScrollBar.vertical: ScrollBar {} ScrollBar.vertical: ScrollBar {}
maximumFlickVelocity: 1250 maximumFlickVelocity: 1250
boundsBehavior: GridView.StopAtBounds boundsBehavior: GridView.StopAtBounds
model: emojiModel model: emojiModel
} }
} }
ListModel { id: folder_activities_clothing } ListModel { id: folder_activities_clothing }
ListModel { id: folder_expressions } ListModel { id: folder_expressions }
ListModel { id: folder_food_drink_herbs } ListModel { id: folder_food_drink_herbs }
ListModel { id: folder_gsr } ListModel { id: folder_gsr }
ListModel { id: folder_nature } ListModel { id: folder_nature }
ListModel { id: folder_objects } ListModel { id: folder_objects }
ListModel { id: folder_people } ListModel { id: folder_people }
ListModel { id: folder_symbols } ListModel { id: folder_symbols }
ListModel { id: folder_travel_places } ListModel { id: folder_travel_places }
ListModel { id: folder_utils } ListModel { id: folder_utils }
ListModel { id: folder_other } ListModel { id: folder_other }
ListModel { id: folder_search } ListModel { id: folder_search }
DelegateModel { DelegateModel {
id: emojiModel id: emojiModel
model: folder_expressions model: folder_expressions
delegate: Item { delegate: Item {
width: root.size width: root.size
height: root.size height: root.size
Image { Image {
id: img id: img
//source: "file://" + gcd.binaryPath + "/assets/mutstd/" + code + ".webp" //source: "file://" + gcd.binaryPath + "/assets/mutstd/" + code + ".webp"
source: gcd.assetPath + "mutstd/" + code + ".webp" source: gcd.assetPath + "mutstd/" + code + ".webp"
width: root.size * (mouseArea.pressed ? 0.7 : 0.8) width: root.size * (mouseArea.pressed ? 0.7 : 0.8)
height: width height: width
anchors.centerIn: parent anchors.centerIn: parent
property string shortcode: code property string shortcode: code
ToolTip.visible: mouseArea.containsMouse ToolTip.visible: mouseArea.containsMouse
ToolTip.text: desc + "\n:" + shortcode + ":" ToolTip.text: desc + "\n:" + shortcode + ":"
MouseArea { MouseArea {
id: mouseArea id: mouseArea
anchors.fill: parent anchors.fill: parent
hoverEnabled: true hoverEnabled: true
onClicked: root.picked(img.shortcode) onClicked: root.picked(img.shortcode)
} }
} }
} }
Component.onCompleted: updatefilters() Component.onCompleted: updatefilters()
function clearall() { function clearall() {
folder_activities_clothing.clear() folder_activities_clothing.clear()
folder_expressions.clear() folder_expressions.clear()
folder_food_drink_herbs.clear() folder_food_drink_herbs.clear()
folder_gsr.clear() folder_gsr.clear()
folder_nature.clear() folder_nature.clear()
folder_objects.clear() folder_objects.clear()
folder_people.clear() folder_people.clear()
folder_symbols.clear() folder_symbols.clear()
folder_travel_places.clear() folder_travel_places.clear()
folder_utils.clear() folder_utils.clear()
folder_other.clear() folder_other.clear()
folder_search.clear() folder_search.clear()
} }
function updatefilters() { function updatefilters() {
clearall() clearall()
for (var i in Mutant.standard.manifest) { for (var i in Mutant.standard.manifest) {
if (typeof Mutant.standard.manifest[i].morph !== "undefined" && Mutant.standard.manifest[i].morph != root.morph) if (typeof Mutant.standard.manifest[i].morph !== "undefined" && Mutant.standard.manifest[i].morph != root.morph)
continue; continue;
if (typeof Mutant.standard.manifest[i].color !== "undefined" && Mutant.standard.manifest[i].color != root.color) if (typeof Mutant.standard.manifest[i].color !== "undefined" && Mutant.standard.manifest[i].color != root.color)
continue; continue;
if (txtSearch.text != "" && !(Mutant.standard.manifest[i].code.includes(txtSearch.text) || Mutant.standard.manifest[i].desc.includes(txtSearch.text))) { if (txtSearch.text != "" && !(Mutant.standard.manifest[i].code.includes(txtSearch.text) || Mutant.standard.manifest[i].desc.includes(txtSearch.text))) {
continue; continue;
} }
var model = folder_other var model = folder_other
if (txtSearch.text == "") { if (txtSearch.text == "") {
switch(Mutant.standard.manifest[i].cat) { switch(Mutant.standard.manifest[i].cat) {
case "activities_clothing": model = folder_activities_clothing; break; case "activities_clothing": model = folder_activities_clothing; break;
case "expressions": model = folder_expressions; break; case "expressions": model = folder_expressions; break;
case "symbols": model = folder_symbols; break; case "symbols": model = folder_symbols; break;
case "food_drink_herbs": model = folder_food_drink_herbs; break; case "food_drink_herbs": model = folder_food_drink_herbs; break;
case "gsr": model = folder_gsr; break; case "gsr": model = folder_gsr; break;
case "nature": model = folder_nature; break; case "nature": model = folder_nature; break;
case "objects": model = folder_objects; break; case "objects": model = folder_objects; break;
case "people": model = folder_people; break; case "people": model = folder_people; break;
case "travel_places": model = folder_travel_places; break; case "travel_places": model = folder_travel_places; break;
case "utils": model = folder_utils; break; case "utils": model = folder_utils; break;
} }
} else { } else {
model = folder_search model = folder_search
} }
model.append({ model.append({
cat: Mutant.standard.manifest[i].cat, cat: Mutant.standard.manifest[i].cat,
code: Mutant.standard.manifest[i].code, code: Mutant.standard.manifest[i].code,
color: Mutant.standard.manifest[i].color, color: Mutant.standard.manifest[i].color,
morph: Mutant.standard.manifest[i].morph, morph: Mutant.standard.manifest[i].morph,
desc: Mutant.standard.manifest[i].desc desc: Mutant.standard.manifest[i].desc
}) })
} }
} }
} }
onSlideopen: animOpen.start() onSlideopen: animOpen.start()
onSlideclosed: animClose.start() onSlideclosed: animClose.start()
} }

View File

@ -8,54 +8,54 @@ import "../widgets" as Widgets
Item { Item {
id: root id: root
height: lbl.visible ? lbl.height : txt.height + (gcd.os == "android" ? btn.height + 3 : 0) //lbl.height height: lbl.visible ? lbl.height : txt.height + (gcd.os == "android" ? btn.height + 3 : 0) //lbl.height
implicitHeight: height //lbl.height implicitHeight: height //lbl.height
property alias text: lbl.text property alias text: lbl.text
signal updated signal updated
Text { // DISPLAY THE TEXT IN READONLY MODE Text { // DISPLAY THE TEXT IN READONLY MODE
id: lbl id: lbl
fontSizeMode: Text.HorizontalFit fontSizeMode: Text.HorizontalFit
font.pixelSize: 36 font.pixelSize: 36
minimumPixelSize: 8 minimumPixelSize: 8
horizontalAlignment: Text.AlignHCenter horizontalAlignment: Text.AlignHCenter
textFormat: Text.PlainText textFormat: Text.PlainText
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
} }
Image { Image {
id: img id: img
anchors.left: lbl.right anchors.left: lbl.right
anchors.leftMargin: 3 anchors.leftMargin: 3
source: gcd.assetPath + "fontawesome/solid/edit.svg" source: gcd.assetPath + "fontawesome/solid/edit.svg"
height: 16 height: 16
sourceSize.height: 16 sourceSize.height: 16
} }
MouseArea { MouseArea {
anchors.fill: lbl anchors.fill: lbl
onClicked: { onClicked: {
lbl.visible = img.visible = false lbl.visible = img.visible = false
txt.visible = true txt.visible = true
if (gcd.os == "android") btn.visible = true if (gcd.os == "android") btn.visible = true
txt.text = lbl.text txt.text = lbl.text
txt.selectAll() txt.selectAll()
txt.focus = true txt.focus = true
} }
} }
TextEdit { // MAKE IT AN EDITOR WHEN EDITING TextEdit { // MAKE IT AN EDITOR WHEN EDITING
id: txt id: txt
text: root.text text: root.text
visible: false visible: false
selectByMouse: true selectByMouse: true
font.pixelSize: lbl.font.pixelSize font.pixelSize: lbl.font.pixelSize
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
onActiveFocusChanged: { onActiveFocusChanged: {
@ -64,29 +64,29 @@ Item {
} }
} }
Keys.onReturnPressed: { Keys.onReturnPressed: {
if (event.modifiers == Qt.NoModifier) { if (event.modifiers == Qt.NoModifier) {
save() save()
} }
} }
function save() { function save() {
root.text = txt.text root.text = txt.text
txt.visible = btn.visible = false txt.visible = btn.visible = false
lbl.visible = img.visible = true lbl.visible = img.visible = true
root.updated(txt.text) root.updated(txt.text)
} }
} }
Widgets.Button { Widgets.Button {
id: btn id: btn
anchors.top: txt.bottom anchors.top: txt.bottom
anchors.topMargin: 3 anchors.topMargin: 3
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
visible: false visible: false
text: qsTr("Update") text: qsTr("Update")
onClicked: txt.save() onClicked: txt.save()
} }
} }

View File

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

View File

@ -12,22 +12,22 @@ import "../styles"
import "../theme" import "../theme"
Item { Item {
id: root id: root
anchors.fill: parent anchors.fill: parent
width: parent.width width: parent.width
height: profile.height + searchAddText.height + 10 height: profile.height + searchAddText.height + 10
implicitHeight: profile.height + searchAddText.height + 10 implicitHeight: profile.height + searchAddText.height + 10
property string image property string image
property string nick property string nick
property string onion property string onion
property string tag property string tag
property bool dualPane: false property bool dualPane: false
property real logscale: 4 * Math.log10(gcd.themeScale + 1) property real logscale: 4 * Math.log10(gcd.themeScale + 1)
onDualPaneChanged: { realignProfile() } onDualPaneChanged: { realignProfile() }
function realignProfile() { function realignProfile() {
if (dualPane) { if (dualPane) {
@ -63,7 +63,7 @@ Item {
} }
} }
Component.onCompleted: { realignProfile() } Component.onCompleted: { realignProfile() }
@ -85,10 +85,10 @@ Item {
portraitColor: Theme.portraitOnlineBackgroundColor portraitColor: Theme.portraitOnlineBackgroundColor
badgeContent: Image {// Profle Type badgeContent: Image {// Profle Type
id: profiletype id: profiletype
source: tag == "v1-userPassword" ? gcd.assetPath + "/fontawesome/solid/lock.svg" : gcd.assetPath + "/fontawesome/solid/lock-open.svg" source: tag == "v1-userPassword" ? gcd.assetPath + "/fontawesome/solid/lock.svg" : gcd.assetPath + "/fontawesome/solid/lock-open.svg"
height: Theme.badgeTextSize * gcd.themeScale height: Theme.badgeTextSize * gcd.themeScale
width: height width: height
} }
} }
@ -124,34 +124,34 @@ Item {
onClicked: { onClicked: {
} }
} }
} }
} }
// TODO Remove for new global topbar // TODO Remove for new global topbar
Widgets.Button {// BACK BUTTON Widgets.Button {// BACK BUTTON
id: btnBack id: btnBack
icon: "solid/arrow-circle-left" icon: "solid/arrow-circle-left"
anchors.left: parent.left anchors.left: parent.left
anchors.leftMargin: 2 anchors.leftMargin: 2
anchors.top: parent.top anchors.top: parent.top
anchors.topMargin: 2 anchors.topMargin: 2
onClicked: function() { onClicked: function() {
gcd.selectedProfile = "none" gcd.selectedProfile = "none"
gcd.reloadProfileList() gcd.reloadProfileList()
parentStack.pane = parentStack.managementPane parentStack.pane = parentStack.managementPane
theStack.pane = theStack.emptyPane theStack.pane = theStack.emptyPane
} }
} }
TextField { TextField {
id: searchAddText id: searchAddText
anchors.top: profile.bottom anchors.top: profile.bottom
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
style: CwtchTextFieldStyle{ } style: CwtchTextFieldStyle{ }
width: parent.width - 30 width: parent.width - 30
//: ex: "... paste an address here to add a contact ..." //: ex: "... paste an address here to add a contact ..."
placeholderText: qsTr("paste-address-to-add-contact") placeholderText: qsTr("paste-address-to-add-contact")
@ -165,19 +165,19 @@ Item {
} }
} }
Connections { Connections {
target: gcd target: gcd
onUpdateMyProfile: function(_nick, _onion, _image, _tag) { onUpdateMyProfile: function(_nick, _onion, _image, _tag) {
nick = _nick nick = _nick
onion = _onion onion = _onion
image = _image image = _image
tag = _tag tag = _tag
} }
/*onTorStatus: function(code, str) { /*onTorStatus: function(code, str) {
rectTorStatus.code = code rectTorStatus.code = code
rectTorStatus.message = str rectTorStatus.message = str
}*/ }*/
} }
} }

View File

@ -7,16 +7,16 @@ import CustomQmlTypes 1.0
import "../theme" import "../theme"
Item { Item {
id: imgProfile id: imgProfile
implicitWidth: baseWidth implicitWidth: baseWidth
implicitHeight: baseWidth implicitHeight: baseWidth
property string source property string source
property alias badgeColor: badge.color property alias badgeColor: badge.color
property real logscale: 4 * Math.log10(gcd.themeScale + 1) property real logscale: 4 * Math.log10(gcd.themeScale + 1)
property int baseWidth: 78 * logscale property int baseWidth: 78 * logscale
height: 78 * logscale height: 78 * logscale
property alias portraitBorderColor: mainImage.color property alias portraitBorderColor: mainImage.color
property alias portraitColor: imageInner.color property alias portraitColor: imageInner.color
@ -24,48 +24,48 @@ Item {
property alias badgeContent: badge.content property alias badgeContent: badge.content
Rectangle { Rectangle {
id: mainImage id: mainImage
//anchors.leftMargin: baseWidth * 0.1 //anchors.leftMargin: baseWidth * 0.1
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
width: baseWidth * 0.8 width: baseWidth * 0.8
height: width height: width
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
color: Theme.portraitOfflineBorderColor color: Theme.portraitOfflineBorderColor
radius: width / 2 radius: width / 2
Rectangle { Rectangle {
id: imageInner id: imageInner
width: parent.width - 4 width: parent.width - 4
height: width height: width
color: Theme.portraitOfflineBorderColor color: Theme.portraitOfflineBorderColor
radius: width / 2 radius: width / 2
anchors.centerIn:parent anchors.centerIn:parent
Image { // PROFILE IMAGE Image { // PROFILE IMAGE
id: img id: img
source: gcd.assetPath + imgProfile.source source: gcd.assetPath + imgProfile.source
anchors.fill: parent anchors.fill: parent
fillMode: Image.PreserveAspectFit fillMode: Image.PreserveAspectFit
visible: false visible: false
} }
Image { // CIRCLE MASK Image { // CIRCLE MASK
id: mask id: mask
fillMode: Image.PreserveAspectFit fillMode: Image.PreserveAspectFit
visible: false visible: false
source: "qrc:/qml/images/extra/clipcircle.png" source: "qrc:/qml/images/extra/clipcircle.png"
} }
OpacityMask { OpacityMask {
anchors.fill: img anchors.fill: img
source: img source: img
maskSource: mask maskSource: mask
} }
} }
} }
Badge { Badge {
id: badge id: badge
} }
} }

View File

@ -12,21 +12,21 @@ import QtQuick.Controls.Styles 1.4
Item { // LOTS OF NESTING TO DEAL WITH QT WEIRDNESS, SORRY Item { // LOTS OF NESTING TO DEAL WITH QT WEIRDNESS, SORRY
id: crItem id: crItem
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right
height: 78 * logscale + 3 height: 78 * logscale + 3
implicitHeight: 78 * logscale + 3 //height implicitHeight: 78 * logscale + 3 //height
property real logscale: 4 * Math.log10(gcd.themeScale + 1) property real logscale: 4 * Math.log10(gcd.themeScale + 1)
property string displayName property string displayName
property alias image: portrait.source property alias image: portrait.source
property string handle property string handle
property bool isActive property bool isActive
property bool isHover property bool isHover
property string tag // profile version/type property string tag // profile version/type
property alias badgeColor: portrait.badgeColor property alias badgeColor: portrait.badgeColor
property alias portraitBorderColor: portrait.portraitBorderColor property alias portraitBorderColor: portrait.portraitBorderColor
property alias portraitColor: portrait.portraitColor property alias portraitColor: portrait.portraitColor
property alias nameColor: cn.color property alias nameColor: cn.color
property alias onionColor: onion.color property alias onionColor: onion.color
@ -38,22 +38,22 @@ Item { // LOTS OF NESTING TO DEAL WITH QT WEIRDNESS, SORRY
property alias content: extraMeta.children property alias content: extraMeta.children
// TODO: should be in ContactRow // TODO: should be in ContactRow
property bool blocked property bool blocked
signal clicked(string handle) signal clicked(string handle)
Rectangle { // CONTACT ENTRY BACKGROUND COLOR Rectangle { // CONTACT ENTRY BACKGROUND COLOR
id: crRect id: crRect
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right
height: crItem.height height: crItem.height
width: parent.width width: parent.width
color: isHover ? Theme.backgroundPaneColor : (isActive ? Theme.backgroundPaneColor : Theme.backgroundMainColor) color: isHover ? Theme.backgroundPaneColor : (isActive ? Theme.backgroundPaneColor : Theme.backgroundMainColor)
Portrait { Portrait {
id: portrait id: portrait
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
anchors.left: parent.left anchors.left: parent.left
anchors.leftMargin: 25 * logscale anchors.leftMargin: 25 * logscale
} }
@ -83,10 +83,10 @@ Item { // LOTS OF NESTING TO DEAL WITH QT WEIRDNESS, SORRY
strikeout: blocked strikeout: blocked
} }
onWidthChanged: { onWidthChanged: {
cn.setTextResize() cn.setTextResize()
onion.setTextResize() onion.setTextResize()
} }
} }
@ -95,40 +95,40 @@ Item { // LOTS OF NESTING TO DEAL WITH QT WEIRDNESS, SORRY
anchors.left: portraitMeta.right anchors.left: portraitMeta.right
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
} }
} }
MouseArea { // Full row mouse area triggering onClick MouseArea { // Full row mouse area triggering onClick
id: buttonMA id: buttonMA
anchors.fill: parent anchors.fill: parent
hoverEnabled: true hoverEnabled: true
onClicked: { crItem.clicked(crItem.handle) } onClicked: { crItem.clicked(crItem.handle) }
onEntered: { onEntered: {
isHover = true isHover = true
} }
onExited: { onExited: {
isHover = false isHover = false
} }
} }
Connections { // UPDATE UNREAD MESSAGES COUNTER Connections { // UPDATE UNREAD MESSAGES COUNTER
target: gcd target: gcd
onResetMessagePane: function() { onResetMessagePane: function() {
isActive = false isActive = false
} }
onUpdateContactBlocked: function(_handle, _blocked) { onUpdateContactBlocked: function(_handle, _blocked) {
if (handle == _handle) { if (handle == _handle) {
blocked = _blocked blocked = _blocked
} }
} }
onUpdateContactDisplayName: function(_handle, _displayName) { onUpdateContactDisplayName: function(_handle, _displayName) {
if (handle == _handle) { if (handle == _handle) {
displayName = _displayName + (blocked == true ? " (blocked)" : "") displayName = _displayName + (blocked == true ? " (blocked)" : "")
} }
} }
@ -137,5 +137,5 @@ Item { // LOTS OF NESTING TO DEAL WITH QT WEIRDNESS, SORRY
image = _image image = _image
} }
} }
} }
} }

View File

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

View File

@ -20,31 +20,31 @@ PortraitRow {
onionColor: Theme.portraitOnlineTextColor onionColor: Theme.portraitOnlineTextColor
badgeContent: Image {// Profle Type badgeContent: Image {// Profle Type
id: profiletype id: profiletype
source: tag == "v1-userPassword" ? gcd.assetPath + "/fontawesome/solid/lock.svg" : gcd.assetPath + "/fontawesome/solid/lock-open.svg" source: tag == "v1-userPassword" ? gcd.assetPath + "/fontawesome/solid/lock.svg" : gcd.assetPath + "/fontawesome/solid/lock-open.svg"
height: Theme.badgeTextSize * gcd.themeScale height: Theme.badgeTextSize * gcd.themeScale
width: height width: height
} }
Widgets.Button {// Edit BUTTON Widgets.Button {// Edit BUTTON
id: btnEdit id: btnEdit
icon: "solid/user-edit" icon: "solid/user-edit"
anchors.right: parent.right anchors.right: parent.right
//rectUnread.left //rectUnread.left
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
anchors.leftMargin: 1 * gcd.themeScale anchors.leftMargin: 1 * gcd.themeScale
anchors.rightMargin: 20 * gcd.themeScale anchors.rightMargin: 20 * gcd.themeScale
height: parent.height * 0.75 height: parent.height * 0.75
onClicked: { onClicked: {
profileAddEditPane.load(handle, displayName, tag) profileAddEditPane.load(handle, displayName, tag)
parentStack.pane = parentStack.addEditProfilePane parentStack.pane = parentStack.addEditProfilePane
}
} }
}
onClicked: function openClick(handle) { onClicked: function openClick(handle) {
gcd.broadcast("ResetMessagePane"); gcd.broadcast("ResetMessagePane");
@ -53,4 +53,4 @@ PortraitRow {
gcd.loadProfile(handle) gcd.loadProfile(handle)
parentStack.pane = parentStack.profilePane parentStack.pane = parentStack.profilePane
} }
} }

View File

@ -6,22 +6,22 @@ import QtQuick.Controls 2.13
RadioButton { RadioButton {
id: control id: control
property real size: 12 property real size: 12
spacing: 0 spacing: 0
indicator: Rectangle { indicator: Rectangle {
width: 16 * gcd.themeScale width: 16 * gcd.themeScale
height: 16 * gcd.themeScale height: 16 * gcd.themeScale
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
radius: 9 radius: 9
border.width: 1 border.width: 1
Rectangle { Rectangle {
anchors.fill: parent anchors.fill: parent
visible: control.checked visible: control.checked
color: "black" color: "black"
radius: 9 radius: 9
anchors.margins: 4 anchors.margins: 4
} }
} }
} }

View File

@ -7,9 +7,9 @@ import QtQuick.Window 2.11
Label { Label {
font.pixelSize: gcd.themeScale * size font.pixelSize: gcd.themeScale * size
wrapMode: Text.WordWrap wrapMode: Text.WordWrap
color: "#000000" color: "#000000"
textFormat: Text.PlainText textFormat: Text.PlainText
property real size: 12 property real size: 12
} }

View File

@ -8,62 +8,62 @@ import "../fonts/Twemoji.js" as T
import "." as Widgets import "." as Widgets
Rectangle { // OVERHEAD BAR ON STACK PANE Rectangle { // OVERHEAD BAR ON STACK PANE
id: toolbar id: toolbar
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right
anchors.top: parent.top anchors.top: parent.top
height: 20 * gcd.themeScale + 4 height: 20 * gcd.themeScale + 4
Layout.minimumHeight: height Layout.minimumHeight: height
Layout.maximumHeight: height Layout.maximumHeight: height
color: "#EDEDED" color: "#EDEDED"
property alias text: lbl.text property alias text: lbl.text
property alias aux: btnAux property alias aux: btnAux
property alias back: btnBack property alias back: btnBack
property alias membership: btnMembership property alias membership: btnMembership
property string stack: "profile" // profile(theStack) or management(parentStack) property string stack: "profile" // profile(theStack) or management(parentStack)
Widgets.Button {// BACK BUTTON Widgets.Button {// BACK BUTTON
id: btnBack id: btnBack
icon: "solid/arrow-circle-left" icon: "solid/arrow-circle-left"
anchors.left: parent.left anchors.left: parent.left
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
anchors.leftMargin: 6 anchors.leftMargin: 6
onClicked: { onClicked: {
if (stack == "profile") { if (stack == "profile") {
theStack.pane = theStack.emptyPane theStack.pane = theStack.emptyPane
} else { } else {
parentStack.pane = parentStack.managementPane parentStack.pane = parentStack.managementPane
} }
} }
} }
ScalingLabel { // TEXT ScalingLabel { // TEXT
id: lbl id: lbl
text: "open privacy exec" text: "open privacy exec"
font.family: Fonts.applicationFontRegular.name font.family: Fonts.applicationFontRegular.name
font.styleName: "ExtraBold" font.styleName: "ExtraBold"
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
} }
RowLayout { RowLayout {
anchors.right: parent.right anchors.right: parent.right
anchors.rightMargin: 6 anchors.rightMargin: 6
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
Widgets.Button { // Membership Button Widgets.Button { // Membership Button
id: btnMembership id: btnMembership
icon: "solid/users" icon: "solid/users"
//: View Group Membership //: View Group Membership
tooltip: qsTr("view-group-membership-tooltip") tooltip: qsTr("view-group-membership-tooltip")
} }
Widgets.Button { // COG BUTTON Widgets.Button { // COG BUTTON
id: btnAux id: btnAux
icon: "solid/cog" icon: "solid/cog"
} }
} }
} }

View File

@ -13,4 +13,4 @@ TextField {
color: windowItem.cwtch_background_color color: windowItem.cwtch_background_color
border.color: windowItem.cwtch_color border.color: windowItem.cwtch_color
} }
} }

View File

@ -33,11 +33,11 @@ Rectangle {
} }
} }
Connections { Connections {
target: gcd target: gcd
onSupplySettings: function(zoom, newLocale) { onSupplySettings: function(zoom, newLocale) {
selected = newLocale == locale selected = newLocale == locale
} }
} }
} }

View File

@ -3,31 +3,31 @@ import QtQuick.Controls 2.4
import QtQuick.Controls.Material 2.0 import QtQuick.Controls.Material 2.0
import QtQuick.Layouts 1.3 import QtQuick.Layouts 1.3
Item { Item {
id: root id: root
property alias source: img.source property alias source: img.source
property int size: 24 property int size: 24
property string tooltip: "" property string tooltip: ""
width: size width: size
height: size height: size
signal clicked() signal clicked()
ToolTip.visible: tooltip != "" && ma.containsMouse ToolTip.visible: tooltip != "" && ma.containsMouse
ToolTip.text: tooltip ToolTip.text: tooltip
Image { Image {
id: img id: img
width: root.size * (ma.pressed ? 0.5 : 0.8) width: root.size * (ma.pressed ? 0.5 : 0.8)
height: root.size * (ma.pressed ? 0.5 : 0.8) height: root.size * (ma.pressed ? 0.5 : 0.8)
anchors.topMargin: ma.pressed ? 2 : 0 anchors.topMargin: ma.pressed ? 2 : 0
anchors.leftMargin: anchors.topMargin anchors.leftMargin: anchors.topMargin
anchors.centerIn: parent anchors.centerIn: parent
} }
MouseArea { MouseArea {
id: ma id: ma
anchors.fill: root anchors.fill: root
onClicked: root.clicked() onClicked: root.clicked()
hoverEnabled: tooltip != "" hoverEnabled: tooltip != ""
} }
} }

8
quality.sh Executable file
View File

@ -0,0 +1,8 @@
#!/bin/sh
# go get cwtch.im/ui/cmd/qmlfmt
cd qml
find -iname "*.qml" | xargs qmlfmt
cd ..