overlay framework
This commit is contained in:
parent
9357f184ba
commit
e620d48bc8
|
@ -6,6 +6,7 @@ import QtQuick.Layouts 1.3
|
|||
import QtQuick.Window 2.11
|
||||
|
||||
import "fonts/Twemoji.js" as T
|
||||
import "overlays"
|
||||
import "panes"
|
||||
import "widgets"
|
||||
|
||||
|
@ -117,7 +118,7 @@ Item {
|
|||
}
|
||||
}
|
||||
|
||||
Rectangle { // THE RIGHT PANE WHERE THE MESSAGES AND STuFF GO
|
||||
Rectangle { // THE RIGHT PANE WHERE THE MESSAGES AND STUFF GO
|
||||
color: "#EEEEFF"
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
|
@ -139,7 +140,7 @@ Item {
|
|||
|
||||
Item {} // empty
|
||||
|
||||
MessageList { // messagePane
|
||||
OverlayPane { // messagePane
|
||||
anchors.fill: parent
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,85 @@
|
|||
import QtGraphicalEffects 1.0
|
||||
import QtQuick 2.7
|
||||
import QtQuick.Controls 2.4
|
||||
import QtQuick.Controls.Material 2.0
|
||||
import QtQuick.Layouts 1.3
|
||||
|
||||
import "../widgets"
|
||||
import "../widgets/controls" as Awesome
|
||||
import "../fonts/Twemoji.js" as T
|
||||
|
||||
ColumnLayout {
|
||||
Layout.fillWidth: true
|
||||
|
||||
|
||||
Flickable { // THE MESSAGE LIST ITSELF
|
||||
id: sv
|
||||
clip: true
|
||||
Layout.alignment: Qt.AlignLeft | Qt.AlignTop
|
||||
Layout.fillHeight: true
|
||||
Layout.minimumWidth: parent.width
|
||||
Layout.maximumWidth: parent.width
|
||||
Layout.fillWidth: true
|
||||
contentWidth: colMessages.width
|
||||
contentHeight: colMessages.height
|
||||
boundsBehavior: Flickable.StopAtBounds
|
||||
maximumFlickVelocity: 800
|
||||
|
||||
|
||||
Connections {
|
||||
target: gcd
|
||||
|
||||
onClearMessages: function() {
|
||||
messagesModel.clear()
|
||||
}
|
||||
|
||||
onAppendMessage: function(handle, from, displayName, message, image, mid, fromMe, ts) {
|
||||
messagesModel.append({
|
||||
"_handle": handle,
|
||||
"_from": from,
|
||||
"_displayName": displayName,
|
||||
"_message": parse(message, 12),
|
||||
"_image": image,
|
||||
"_mid": mid,
|
||||
"_fromMe": fromMe,
|
||||
"_ts": ts,
|
||||
})
|
||||
|
||||
if (sv.contentY + sv.height >= sv.contentHeight - colMessages.height && sv.contentHeight > sv.height) {
|
||||
sv.contentY = sv.contentHeight - sv.height
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ScrollBar.vertical: ScrollBar{
|
||||
policy: ScrollBar.AlwaysOn
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
id: colMessages
|
||||
width: sv.width
|
||||
|
||||
|
||||
ListModel { // MESSAGE OBJECTS ARE STORED HERE ...
|
||||
id: messagesModel
|
||||
}
|
||||
|
||||
Item { height: 6 }
|
||||
|
||||
Repeater { // ... AND DISPLAYED HERE
|
||||
model: messagesModel
|
||||
delegate: Message {
|
||||
handle: _handle
|
||||
from: _from
|
||||
displayName: _displayName
|
||||
message: "bulletinbulletinbulletin"
|
||||
image: _image
|
||||
messageID: _mid
|
||||
fromMe: _fromMe
|
||||
timestamp: _ts
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -4,22 +4,14 @@ import QtQuick.Controls 2.4
|
|||
import QtQuick.Controls.Material 2.0
|
||||
import QtQuick.Layouts 1.3
|
||||
|
||||
import "controls" as Awesome
|
||||
import "../widgets"
|
||||
import "../widgets/controls" as Awesome
|
||||
import "../fonts/Twemoji.js" as T
|
||||
|
||||
ColumnLayout {
|
||||
Layout.fillWidth: true
|
||||
|
||||
|
||||
StackToolbar {
|
||||
text: "open privacy exec"
|
||||
|
||||
aux.onClicked: {
|
||||
theStack.pane = gcd.currentOpenConversation.length == 32 ? theStack.groupProfilePane : theStack.userProfilePane
|
||||
gcd.requestGroupSettings()
|
||||
}
|
||||
}
|
||||
|
||||
Flickable { // THE MESSAGE LIST ITSELF
|
||||
id: sv
|
||||
clip: true
|
||||
|
@ -42,11 +34,19 @@ ColumnLayout {
|
|||
}
|
||||
|
||||
onAppendMessage: function(handle, from, displayName, message, image, mid, fromMe, ts) {
|
||||
var msg
|
||||
try {
|
||||
msg = JSON.parse(message)
|
||||
} catch (e) {
|
||||
msg = {"o": 1, "d": "(legacy message type) " + message}
|
||||
}
|
||||
if (msg.o != 1) return
|
||||
|
||||
messagesModel.append({
|
||||
"_handle": handle,
|
||||
"_from": from,
|
||||
"_displayName": displayName,
|
||||
"_message": parse(message, 12),
|
||||
"_message": parse(msg.d, 12),
|
||||
"_image": image,
|
||||
"_mid": mid,
|
||||
"_fromMe": fromMe,
|
||||
|
@ -226,7 +226,8 @@ ColumnLayout {
|
|||
onClicked: {
|
||||
if (txtMessage.text != "") {
|
||||
txtHidden.text = restoreEmoji(txtMessage.text)
|
||||
gcd.sendMessage(txtHidden.getText(0, txtHidden.text.length), nextMessageID++)
|
||||
var msg = JSON.stringify({"o":1, "d":txtHidden.getText(0, txtHidden.text.length)})
|
||||
gcd.sendMessage(msg, nextMessageID++)
|
||||
}
|
||||
txtMessage.text = ""
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
import QtGraphicalEffects 1.0
|
||||
import QtQuick 2.7
|
||||
import QtQuick.Controls 2.4
|
||||
import QtQuick.Controls.Material 2.0
|
||||
import QtQuick.Layouts 1.3
|
||||
|
||||
import "../widgets"
|
||||
import "../widgets/controls" as Awesome
|
||||
import "../fonts/Twemoji.js" as T
|
||||
|
||||
ColumnLayout {
|
||||
Layout.fillWidth: true
|
||||
|
||||
|
||||
ScalingLabel {
|
||||
text: "gardening game or maybe some other cool cwtch-enabled game"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
import QtGraphicalEffects 1.0
|
||||
import QtQuick 2.7
|
||||
import QtQuick.Controls 2.4
|
||||
import QtQuick.Controls.Material 2.0
|
||||
import QtQuick.Layouts 1.3
|
||||
|
||||
import "../widgets"
|
||||
import "../widgets/controls" as Awesome
|
||||
import "../fonts/Twemoji.js" as T
|
||||
|
||||
ColumnLayout {
|
||||
Layout.fillWidth: true
|
||||
|
||||
|
||||
ScalingLabel {
|
||||
text: "rock paper scissors. or chess? basically the same thing"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,262 @@
|
|||
import QtGraphicalEffects 1.0
|
||||
import QtQuick 2.7
|
||||
import QtQuick.Controls 2.4
|
||||
import QtQuick.Controls.Material 2.0
|
||||
import QtQuick.Layouts 1.3
|
||||
|
||||
import "../widgets"
|
||||
import "../widgets/controls" as Awesome
|
||||
import "../fonts/Twemoji.js" as T
|
||||
|
||||
ColumnLayout {
|
||||
Layout.fillWidth: true
|
||||
|
||||
|
||||
Flickable { // THE MESSAGE LIST ITSELF
|
||||
id: sv
|
||||
clip: true
|
||||
Layout.alignment: Qt.AlignLeft | Qt.AlignTop
|
||||
Layout.fillHeight: true
|
||||
Layout.minimumWidth: parent.width
|
||||
Layout.maximumWidth: parent.width
|
||||
Layout.fillWidth: true
|
||||
contentWidth: colMessages.width
|
||||
contentHeight: colMessages.height
|
||||
boundsBehavior: Flickable.StopAtBounds
|
||||
maximumFlickVelocity: 800
|
||||
|
||||
|
||||
Connections {
|
||||
target: gcd
|
||||
|
||||
onClearMessages: function() {
|
||||
messagesModel.clear()
|
||||
}
|
||||
|
||||
onAppendMessage: function(handle, from, displayName, message, image, mid, fromMe, ts) {
|
||||
var msg
|
||||
try {
|
||||
msg = JSON.parse(message)
|
||||
} catch (e) {
|
||||
msg = {"o": 1, "d": "(legacy message type) " + message}
|
||||
}
|
||||
if (msg.o != 2) return
|
||||
|
||||
messagesModel.append({
|
||||
"_handle": handle,
|
||||
"_from": from,
|
||||
"_displayName": displayName,
|
||||
"_message": parse(msg.d, 12),
|
||||
"_image": image,
|
||||
"_mid": mid,
|
||||
"_fromMe": fromMe,
|
||||
"_ts": ts,
|
||||
})
|
||||
|
||||
if (sv.contentY + sv.height >= sv.contentHeight - colMessages.height && sv.contentHeight > sv.height) {
|
||||
sv.contentY = sv.contentHeight - sv.height
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ScrollBar.vertical: ScrollBar{
|
||||
policy: ScrollBar.AlwaysOn
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
id: colMessages
|
||||
width: sv.width
|
||||
|
||||
|
||||
ListModel { // MESSAGE OBJECTS ARE STORED HERE ...
|
||||
id: messagesModel
|
||||
}
|
||||
|
||||
Item { height: 6 }
|
||||
|
||||
Repeater { // ... AND DISPLAYED HERE
|
||||
model: messagesModel
|
||||
delegate: Message {
|
||||
handle: _handle
|
||||
from: _from
|
||||
displayName: _displayName
|
||||
message: "be gay, do crimes, and make lists"
|
||||
image: _image
|
||||
messageID: _mid
|
||||
fromMe: _fromMe
|
||||
timestamp: _ts
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RowLayout { // THE BOTTOM DRAWER
|
||||
Rectangle { // MESSAGE ENTRY TEXTFIELD
|
||||
id: rectMessage
|
||||
Layout.fillWidth: true
|
||||
Layout.minimumHeight: 40 * gcd.themeScale
|
||||
Layout.maximumHeight: 40 * gcd.themeScale
|
||||
color: "#EDEDED"
|
||||
border.color: "#AAAAAA"
|
||||
radius: 10
|
||||
|
||||
|
||||
Flickable {
|
||||
id: flkMessage
|
||||
anchors.fill: parent//this does nothing! bug in qt
|
||||
Layout.minimumWidth: parent.width
|
||||
Layout.maximumWidth: parent.width
|
||||
Layout.minimumHeight: rectMessage.height
|
||||
Layout.maximumHeight: rectMessage.height
|
||||
contentWidth: txtMessage.width
|
||||
contentHeight: txtMessage.height
|
||||
boundsBehavior: Flickable.StopAtBounds
|
||||
clip:true
|
||||
maximumFlickVelocity: 300
|
||||
|
||||
|
||||
ScrollBar.vertical: ScrollBar{}
|
||||
|
||||
TextEdit {
|
||||
id: txtMessage
|
||||
font.pixelSize: 10
|
||||
text: ""
|
||||
padding: 6
|
||||
wrapMode: TextEdit.Wrap
|
||||
textFormat: Text.RichText
|
||||
width: rectMessage.width
|
||||
//height: parent.height
|
||||
|
||||
property bool skipOneUpdate: false
|
||||
|
||||
Keys.onReturnPressed: { // CTRL+ENTER = LINEBREAK
|
||||
if (event.modifiers & Qt.ControlModifier) {
|
||||
txtMessage.insert(txtMessage.cursorPosition, "<br>")
|
||||
} else if (event.modifiers == Qt.NoModifier) {
|
||||
btnSend.clicked()
|
||||
}
|
||||
}
|
||||
|
||||
// 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.
|
||||
// TODO: this probably breaks if people actually do want to paste html
|
||||
onTextChanged: {
|
||||
//console.log("onTextChanged()")
|
||||
|
||||
// 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
|
||||
// infinite loop
|
||||
if (skipOneUpdate) {
|
||||
console.log("skipping one update")
|
||||
skipOneUpdate = false
|
||||
return
|
||||
}
|
||||
|
||||
//console.log("1: " + txtMessage.getText(0, txtMessage.text.length))
|
||||
|
||||
// convert <img> tags back to their emoji form
|
||||
var nt = restoreEmoji(txtMessage.text)
|
||||
if (nt != txtMessage.text) {
|
||||
skipOneUpdate = true
|
||||
txtMessage.text = nt
|
||||
}
|
||||
|
||||
//console.log("2: " + txtMessage.getText(0, txtMessage.text.length))
|
||||
|
||||
// strip all HTML tags
|
||||
var theText = txtMessage.getText(0, txtMessage.text.length)
|
||||
//console.log("3: " + theText)
|
||||
|
||||
// convert emoji back to <img> tags
|
||||
nt = parse(theText, 10)
|
||||
//console.log("4: " + nt)
|
||||
|
||||
// if there were changes...
|
||||
if (nt != txtMessage.getText(0, txtMessage.text.length)) {
|
||||
// first we need to update the cursor position to be the same distance from the end
|
||||
var oldcursor = txtMessage.cursorPosition
|
||||
var oldlen = txtMessage.getText(0, txtMessage.text.length).length
|
||||
|
||||
// then we actually put the updated text in
|
||||
skipOneUpdate = true
|
||||
txtMessage.text = nt
|
||||
|
||||
// and then restore the cursor
|
||||
var newlen = txtMessage.getText(0, txtMessage.text.length).length
|
||||
txtMessage.cursorPosition = newlen - (oldlen - oldcursor)
|
||||
}
|
||||
|
||||
// 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) {
|
||||
flkMessage.contentY = flkMessage.contentHeight - flkMessage.height
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: txtMessage.focus = true
|
||||
}
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
id: colRight
|
||||
spacing: 1
|
||||
|
||||
|
||||
SimpleButton { // SEND MESSAGE BUTTON
|
||||
id: btnSend
|
||||
icon: "regular/paper-plane"
|
||||
text: "send"
|
||||
Layout.minimumWidth: btnEmoji.width + btnAttach.width + 2
|
||||
Layout.maximumWidth: btnEmoji.width + btnAttach.width + 2
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: 2
|
||||
|
||||
property int nextMessageID: 1
|
||||
|
||||
TextEdit {
|
||||
id: txtHidden
|
||||
visible: false
|
||||
textFormat: Text.RichText
|
||||
}
|
||||
|
||||
onClicked: {
|
||||
if (txtMessage.text != "") {
|
||||
txtHidden.text = restoreEmoji(txtMessage.text)
|
||||
var msg = JSON.stringify({"o":2, "d":txtHidden.getText(0, txtHidden.text.length)})
|
||||
gcd.sendMessage(msg, nextMessageID++)
|
||||
}
|
||||
txtMessage.text = ""
|
||||
}
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
spacing: 1
|
||||
|
||||
|
||||
SimpleButton { // EMOJI DRAWER BUTTON
|
||||
id: btnEmoji
|
||||
icon: "regular/smile"
|
||||
anchors.right: btnAttach.left
|
||||
anchors.rightMargin: 2
|
||||
|
||||
onClicked: gcd.popup("emoji not yet implemented, sorry")
|
||||
}
|
||||
|
||||
SimpleButton {
|
||||
id: btnAttach
|
||||
icon: "solid/paperclip"
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: 2
|
||||
|
||||
onClicked: {
|
||||
gcd.popup("attachments not yet implemented, sorry")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,89 @@
|
|||
import QtGraphicalEffects 1.0
|
||||
import QtQuick 2.7
|
||||
import QtQuick.Controls 2.4
|
||||
import QtQuick.Controls.Material 2.0
|
||||
import QtQuick.Layouts 1.3
|
||||
|
||||
import "../widgets"
|
||||
import "../overlays"
|
||||
|
||||
ColumnLayout {
|
||||
Layout.fillWidth: true
|
||||
|
||||
|
||||
StackToolbar {
|
||||
text: "open privacy exec"
|
||||
|
||||
aux.onClicked: {
|
||||
theStack.pane = gcd.currentOpenConversation.length == 32 ? theStack.groupProfilePane : theStack.userProfilePane
|
||||
gcd.requestGroupSettings()
|
||||
}
|
||||
}
|
||||
|
||||
Row {
|
||||
id: switcher
|
||||
|
||||
|
||||
SimpleButton {
|
||||
text: "Chat"
|
||||
|
||||
|
||||
onClicked: overlayStack.overlay = overlayStack.chatOverlay
|
||||
}
|
||||
|
||||
SimpleButton {
|
||||
text: "Lists"
|
||||
|
||||
|
||||
onClicked: overlayStack.overlay = overlayStack.listOverlay
|
||||
}
|
||||
|
||||
SimpleButton {
|
||||
text: "Bulletins"
|
||||
|
||||
|
||||
onClicked: overlayStack.overlay = overlayStack.bulletinOverlay
|
||||
}
|
||||
|
||||
SimpleButton {
|
||||
text: "Game 1"
|
||||
|
||||
|
||||
onClicked: overlayStack.overlay = overlayStack.game1Overlay
|
||||
}
|
||||
|
||||
SimpleButton {
|
||||
text: "Game 2"
|
||||
|
||||
|
||||
onClicked: overlayStack.overlay = overlayStack.game2Overlay
|
||||
}
|
||||
}
|
||||
|
||||
StackLayout {
|
||||
id: overlayStack
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.top: switcher.bottom
|
||||
currentIndex: 0
|
||||
|
||||
property alias overlay: overlayStack.currentIndex
|
||||
readonly property int chatOverlay: 0
|
||||
readonly property int listOverlay: 1
|
||||
readonly property int bulletinOverlay: 2
|
||||
readonly property int game1Overlay: 3
|
||||
readonly property int game2Overlay: 4
|
||||
|
||||
|
||||
ChatOverlay {} //0
|
||||
|
||||
ListOverlay{} //1
|
||||
|
||||
BulletinOverlay{} //2
|
||||
|
||||
Game1Overlay{} //3
|
||||
|
||||
Game2Overlay{} //4
|
||||
}
|
||||
}
|
Reference in New Issue