Restyle the chat UI
This commit is contained in:
parent
f65ea9dd0d
commit
5650234e3b
4
TODO.md
4
TODO.md
|
@ -6,6 +6,7 @@
|
|||
- Better names and organization for the Message components
|
||||
|
||||
- Bug fixes
|
||||
- 100% CPU usage when hitting top edge to trigger messages loading
|
||||
- Fix tooltip hide()
|
||||
- Sending `![A picture](https://picsum.photos/256/256)` → not clickable?
|
||||
- Icons aren't reloaded
|
||||
|
@ -13,7 +14,10 @@
|
|||
- HStyle singleton isn't reloaded
|
||||
|
||||
- UI
|
||||
- Server selection
|
||||
- Register/Forgot? for SignIn dialog
|
||||
- Scaling
|
||||
- See [Text.fontSizeMode](https://doc.qt.io/qt-5/qml-qtquick-text.html#fontSizeMode-prop)
|
||||
- Test HGlassRectangle elements when no effects are available
|
||||
- Leave room
|
||||
- Forget room warning popup
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import QtQuick 2.7
|
||||
import QtQuick.Controls 2.0
|
||||
import QtQuick.Layouts 1.4
|
||||
import "../base" as Base
|
||||
|
||||
Item {
|
||||
property bool invisible: false
|
||||
|
@ -22,13 +23,18 @@ Item {
|
|||
anchors.fill: parent
|
||||
visible: ! invisible && imageSource === null
|
||||
color: resolvedName === "?" ?
|
||||
Qt.hsla(0, 0, 0.22, 1) :
|
||||
Qt.hsla(Backend.hueFromString(resolvedName), 0.22, 0.5, 1)
|
||||
Base.HStyle.avatar.background.unknown :
|
||||
Qt.hsla(
|
||||
Backend.hueFromString(resolvedName),
|
||||
Base.HStyle.avatar.background.saturation,
|
||||
Base.HStyle.avatar.background.lightness,
|
||||
Base.HStyle.avatar.background.alpha
|
||||
)
|
||||
|
||||
HLabel {
|
||||
anchors.centerIn: parent
|
||||
text: resolvedName.charAt(0)
|
||||
color: "white"
|
||||
color: Base.HStyle.avatar.letter
|
||||
font.pixelSize: letterRectangle.height / 1.4
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,8 @@ import QtQuick 2.7
|
|||
import QtGraphicalEffects 1.0
|
||||
|
||||
Item {
|
||||
property bool isPageStackDescendant: true
|
||||
|
||||
default property alias children: rectangle.children
|
||||
property alias color: rectangle.color
|
||||
property alias gradient: rectangle.gradient
|
||||
|
@ -14,16 +16,18 @@ Item {
|
|||
sourceItem: mainUIBackground
|
||||
anchors.fill: parent
|
||||
sourceRect: Qt.rect(
|
||||
pageStack.x + parent.x, pageStack.y + parent.y, width, height
|
||||
(isPageStackDescendant ? pageStack.x : 0) + parent.x,
|
||||
(isPageStackDescendant ? pageStack.y : 0) + parent.y,
|
||||
width,
|
||||
height
|
||||
)
|
||||
}
|
||||
|
||||
FastBlur {
|
||||
id: fastBlur
|
||||
cached: true
|
||||
anchors.fill: effectSource
|
||||
source: effectSource
|
||||
radius: 8
|
||||
radius: rectangle.color == "#00000000" ? 0 : 8
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
|
|
31
harmonyqml/components/base/HNoticeLabel.qml
Normal file
31
harmonyqml/components/base/HNoticeLabel.qml
Normal file
|
@ -0,0 +1,31 @@
|
|||
import QtQuick 2.7
|
||||
import QtQuick.Controls 2.2
|
||||
import QtQuick.Layouts 1.4
|
||||
import "../base" as Base
|
||||
|
||||
Base.HRowLayout {
|
||||
property alias text: noticeLabel.text
|
||||
property alias color: noticeLabel.color
|
||||
property alias font: noticeLabel.font
|
||||
property alias backgroundColor: noticeLabelBackground.color
|
||||
property alias radius: noticeLabelBackground.radius
|
||||
|
||||
Base.HLabel {
|
||||
id: noticeLabel
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
wrapMode: Text.Wrap
|
||||
padding: 3
|
||||
leftPadding: 10
|
||||
rightPadding: 10
|
||||
|
||||
Layout.margins: 10
|
||||
Layout.alignment: Qt.AlignCenter
|
||||
Layout.maximumWidth: parent.width - Layout.margins * 2
|
||||
|
||||
background: Rectangle {
|
||||
id: noticeLabelBackground
|
||||
color: Base.HStyle.box.background
|
||||
radius: Base.HStyle.box.radius
|
||||
}
|
||||
}
|
||||
}
|
|
@ -8,7 +8,7 @@ HGlassRectangle {
|
|||
readonly property int baseWidth: baseHeight * widthForHeight
|
||||
readonly property int margins: baseHeight * 0.03
|
||||
|
||||
color: HStyle.boxes.background
|
||||
color: HStyle.box.background
|
||||
height: Math.min(parent.height, baseHeight)
|
||||
width: Math.min(parent.width, baseWidth)
|
||||
scale: Math.max(1, parent.height / startScalingUpAboveHeight)
|
||||
|
|
|
@ -2,6 +2,8 @@ pragma Singleton
|
|||
import QtQuick 2.7
|
||||
|
||||
QtObject {
|
||||
id: style
|
||||
|
||||
readonly property QtObject fontSize: QtObject {
|
||||
property int smallest: 6
|
||||
property int smaller: 8
|
||||
|
@ -19,19 +21,78 @@ QtObject {
|
|||
}
|
||||
|
||||
readonly property QtObject colors: QtObject {
|
||||
property color background0: Qt.hsla(1, 1, 1, 0.4)
|
||||
property color background0: Qt.hsla(0, 0, 0.8, 0.7)
|
||||
property color foreground: "black"
|
||||
property color foregroundDim: Qt.hsla(0, 0, 0.2, 1)
|
||||
property color foregroundError: Qt.hsla(0.95, 0.64, 0.32, 1)
|
||||
}
|
||||
|
||||
property int radius: 5
|
||||
|
||||
readonly property QtObject sidePane: QtObject {
|
||||
property color background: colors.background0
|
||||
}
|
||||
|
||||
readonly property QtObject boxes: QtObject {
|
||||
readonly property QtObject chat: QtObject {
|
||||
readonly property QtObject roomHeader: QtObject {
|
||||
property color background: colors.background0
|
||||
property int radius: 5
|
||||
}
|
||||
|
||||
readonly property QtObject avatars: QtObject {
|
||||
property int radius: 5
|
||||
readonly property QtObject messageList: QtObject {
|
||||
property color background: colors.background0
|
||||
}
|
||||
|
||||
readonly property QtObject message: QtObject {
|
||||
property color background: colors.background0
|
||||
property color body: colors.foreground
|
||||
property color date: colors.foregroundDim
|
||||
}
|
||||
|
||||
readonly property QtObject event: QtObject {
|
||||
property color background: colors.background0
|
||||
property real saturation: 0.22
|
||||
property real lightness: 0.24
|
||||
property color date: colors.foregroundDim
|
||||
}
|
||||
|
||||
readonly property QtObject daybreak: QtObject {
|
||||
property color background: colors.background0
|
||||
property color foreground: colors.foreground
|
||||
property int radius: style.radius
|
||||
}
|
||||
|
||||
readonly property QtObject inviteBanner: QtObject {
|
||||
property color background: colors.background0
|
||||
}
|
||||
|
||||
readonly property QtObject leftBanner: QtObject {
|
||||
property color background: colors.background0
|
||||
}
|
||||
|
||||
readonly property QtObject sendBox: QtObject {
|
||||
property color background: colors.background0
|
||||
}
|
||||
}
|
||||
|
||||
readonly property QtObject box: QtObject {
|
||||
property color background: colors.background0
|
||||
property int radius: style.radius
|
||||
}
|
||||
|
||||
readonly property QtObject avatar: QtObject {
|
||||
property int radius: style.radius
|
||||
property color letter: "white"
|
||||
|
||||
readonly property QtObject background: QtObject {
|
||||
property real saturation: 0.22
|
||||
property real lightness: 0.5
|
||||
property real alpha: 1
|
||||
property color unknown: Qt.hsla(0, 0, 0.22, 1)
|
||||
}
|
||||
}
|
||||
|
||||
readonly property QtObject displayName: QtObject {
|
||||
property real saturation: 0.32
|
||||
property real lightness: 0.3
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,11 +3,10 @@ import QtQuick.Controls 2.2
|
|||
import QtQuick.Layouts 1.4
|
||||
import "../base" as Base
|
||||
|
||||
Rectangle {
|
||||
Base.HGlassRectangle {
|
||||
id: banner
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: 32
|
||||
color: "#BBB"
|
||||
|
||||
signal buttonClicked(string signalId)
|
||||
|
||||
|
|
|
@ -1,21 +1,14 @@
|
|||
import QtQuick 2.7
|
||||
import "../base" as Base
|
||||
|
||||
Base.HLabel {
|
||||
property bool isToday: {
|
||||
const today = new Date()
|
||||
return dateTime.getDate() == today.getDate() &&
|
||||
dateTime.getMonth() == today.getMonth() &&
|
||||
dateTime.getFullYear() == today.getFullYear()
|
||||
}
|
||||
Base.HNoticeLabel {
|
||||
text: dateTime.toLocaleDateString()
|
||||
color: Base.HStyle.chat.daybreak.foreground
|
||||
backgroundColor: Base.HStyle.chat.daybreak.background
|
||||
radius: Base.HStyle.chat.daybreak.radius
|
||||
|
||||
width: messageDelegate.width
|
||||
topPadding: messageDelegate.isFirstMessage ?
|
||||
0 : messageDelegate.standardSpacing
|
||||
bottomPadding: messageDelegate.standardSpacing
|
||||
|
||||
text: dateTime.toLocaleDateString() + (isToday ? qsTr(" (Today)") : "")
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
font.pixelSize: Base.HStyle.fontSize.big
|
||||
color: "darkolivegreen"
|
||||
//topPadding: messageDelegate.isFirstMessage ?
|
||||
//0 : messageDelegate.standardSpacing
|
||||
//bottomPadding: messageDelegate.standardSpacing
|
||||
}
|
||||
|
|
|
@ -23,16 +23,23 @@ RowLayout {
|
|||
Base.HLabel {
|
||||
id: contentLabel
|
||||
text: "<font color='" +
|
||||
(isUndecryptableEvent ? "darkred" : "gray") + "'>" +
|
||||
(displayName.value || dict.sender) +
|
||||
(contentText.startsWith("'s ") ? "" : " ") +
|
||||
Qt.hsla(Backend.hueFromString(displayName.value || dict.sender),
|
||||
Base.HStyle.chat.event.saturation,
|
||||
Base.HStyle.chat.event.lightness,
|
||||
1) +
|
||||
"'>" +
|
||||
(displayName.value || dict.sender) + " " +
|
||||
contentText +
|
||||
" <font size=" + Base.HStyle.fontSize.small +
|
||||
"px color='gray'>" +
|
||||
|
||||
" " +
|
||||
"<font size=" + Base.HStyle.fontSize.small + "px " +
|
||||
"color=" + Base.HStyle.chat.event.date + ">" +
|
||||
Qt.formatDateTime(dateTime, "hh:mm:ss") +
|
||||
"</font></font>"
|
||||
"</font> " +
|
||||
"</font>"
|
||||
|
||||
textFormat: Text.RichText
|
||||
background: Rectangle {color: "#DDD"}
|
||||
background: Rectangle {color: Base.HStyle.chat.event.background}
|
||||
wrapMode: Text.Wrap
|
||||
|
||||
leftPadding: horizontalPadding
|
||||
|
|
|
@ -6,6 +6,8 @@ import "../base" as Base
|
|||
Banner {
|
||||
property var inviter: null
|
||||
|
||||
color: Base.HStyle.chat.inviteBanner.background
|
||||
|
||||
avatarName: inviter ? inviter.displayname : ""
|
||||
//avatarSource: inviter ? inviter.avatar_url : ""
|
||||
|
||||
|
|
|
@ -7,6 +7,8 @@ import "utils.js" as ChatJS
|
|||
Banner {
|
||||
property var leftEvent: null
|
||||
|
||||
color: Base.HStyle.chat.leftBanner.background
|
||||
|
||||
onButtonClicked: if (signalId === "forget") {
|
||||
chatPage.canLoadPastEvents = false
|
||||
pageStack.clear()
|
||||
|
|
|
@ -18,8 +18,11 @@ Row {
|
|||
visible: ! combine
|
||||
id: nameLabel
|
||||
text: displayName.value || dict.sender
|
||||
background: Rectangle {color: "#DDD"}
|
||||
color: Qt.hsla(Backend.hueFromString(text), 0.22, 0.4, 1)
|
||||
background: Rectangle {color: Base.HStyle.chat.message.background}
|
||||
color: Qt.hsla(Backend.hueFromString(text),
|
||||
Base.HStyle.displayName.saturation,
|
||||
Base.HStyle.displayName.lightness,
|
||||
1)
|
||||
elide: Text.ElideRight
|
||||
maximumLineCount: 1
|
||||
Layout.preferredWidth: contentLabel.width
|
||||
|
@ -36,14 +39,15 @@ Row {
|
|||
Backend.htmlFilter.filter(dict.formatted_body) :
|
||||
dict.body) +
|
||||
" <font size=" + Base.HStyle.fontSize.small +
|
||||
"px color=gray>" +
|
||||
"px color=" + Base.HStyle.chat.message.date + ">" +
|
||||
Qt.formatDateTime(dateTime, "hh:mm:ss") +
|
||||
"</font>" +
|
||||
(isLocalEcho ?
|
||||
" <font size=" + Base.HStyle.fontSize.small +
|
||||
"px>⏳</font>" : "")
|
||||
textFormat: Text.RichText
|
||||
background: Rectangle {color: "#DDD"}
|
||||
background: Rectangle {color: Base.HStyle.chat.message.background}
|
||||
color: Base.HStyle.chat.message.body
|
||||
wrapMode: Text.Wrap
|
||||
|
||||
leftPadding: horizontalPadding
|
||||
|
|
|
@ -67,12 +67,19 @@ Column {
|
|||
|
||||
topPadding:
|
||||
isFirstEvent ? 0 :
|
||||
dayBreak ? standardSpacing * 2 :
|
||||
talkBreak ? standardSpacing * 3 :
|
||||
combine ? standardSpacing / 4 :
|
||||
standardSpacing
|
||||
|
||||
Daybreak { visible: dayBreak }
|
||||
|
||||
Item {
|
||||
visible: dayBreak
|
||||
width: parent.width
|
||||
height: topPadding
|
||||
}
|
||||
|
||||
MessageContent { visible: isMessage }
|
||||
|
||||
EventContent { visible: ! isMessage }
|
||||
|
|
|
@ -3,21 +3,24 @@ import QtQuick.Controls 2.2
|
|||
import QtQuick.Layouts 1.4
|
||||
import "../base" as Base
|
||||
|
||||
Rectangle {
|
||||
Base.HGlassRectangle {
|
||||
property bool canLoadPastEvents: true
|
||||
property int space: 8
|
||||
|
||||
color: "transparent"
|
||||
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
Layout.leftMargin: space
|
||||
Layout.rightMargin: space
|
||||
|
||||
ListView {
|
||||
id: messageListView
|
||||
anchors.fill: parent
|
||||
delegate: MessageDelegate {}
|
||||
model: Backend.models.roomEvents.get(chatPage.roomId)
|
||||
|
||||
anchors.fill: parent
|
||||
anchors.leftMargin: space
|
||||
anchors.rightMargin: space
|
||||
|
||||
clip: true
|
||||
topMargin: space
|
||||
bottomMargin: space
|
||||
|
@ -45,7 +48,7 @@ Rectangle {
|
|||
topPadding: padding / 3
|
||||
bottomPadding: topPadding
|
||||
background: Rectangle {
|
||||
color: "lightgray"
|
||||
color: Base.HStyle.chat.messageList.background
|
||||
radius: 5
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ import QtQuick.Controls 2.2
|
|||
import QtQuick.Layouts 1.4
|
||||
import "../base" as Base
|
||||
|
||||
Rectangle {
|
||||
Base.HGlassRectangle {
|
||||
property string displayName: ""
|
||||
property string topic: ""
|
||||
|
||||
|
@ -11,7 +11,7 @@ Rectangle {
|
|||
Layout.fillWidth: true
|
||||
Layout.minimumHeight: 36
|
||||
Layout.maximumHeight: Layout.minimumHeight
|
||||
color: "#BBB"
|
||||
color: Base.HStyle.chat.roomHeader.background
|
||||
|
||||
RowLayout {
|
||||
id: row
|
||||
|
|
|
@ -3,7 +3,7 @@ import QtQuick.Controls 2.2
|
|||
import QtQuick.Layouts 1.4
|
||||
import "../base" as Base
|
||||
|
||||
Rectangle {
|
||||
Base.HGlassRectangle {
|
||||
function setFocus() { textArea.forceActiveFocus() }
|
||||
|
||||
id: root
|
||||
|
@ -12,7 +12,7 @@ Rectangle {
|
|||
Layout.preferredHeight: textArea.implicitHeight
|
||||
// parent.height / 2 causes binding loop?
|
||||
Layout.maximumHeight: pageStack.height / 2
|
||||
color: "#BBB"
|
||||
color: Base.HStyle.chat.sendBox.background
|
||||
|
||||
RowLayout {
|
||||
anchors.fill: parent
|
||||
|
|
|
@ -3,21 +3,6 @@ import QtQuick.Controls 2.2
|
|||
import QtQuick.Layouts 1.4
|
||||
import "../base" as Base
|
||||
|
||||
Base.HRowLayout {
|
||||
Base.HLabel {
|
||||
Base.HNoticeLabel {
|
||||
text: "Select or add a room to start."
|
||||
wrapMode: Text.Wrap
|
||||
padding: 3
|
||||
leftPadding: 10
|
||||
rightPadding: 10
|
||||
|
||||
Layout.margins: 10
|
||||
Layout.alignment: Qt.AlignCenter
|
||||
Layout.maximumWidth: parent.width - Layout.margins * 2
|
||||
|
||||
background: Rectangle {
|
||||
color: Base.HStyle.boxes.background
|
||||
radius: Base.HStyle.boxes.radius
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,5 +11,5 @@ Base.HLabel {
|
|||
elide: Text.ElideRight
|
||||
maximumLineCount: 1
|
||||
|
||||
font.bold: true
|
||||
font.weight: Font.DemiBold
|
||||
}
|
||||
|
|
|
@ -8,6 +8,8 @@ Base.HGlassRectangle {
|
|||
id: sidePane
|
||||
clip: true // Avoid artifacts when resizing pane width to minimum
|
||||
|
||||
isPageStackDescendant: false
|
||||
|
||||
ColumnLayout {
|
||||
anchors.fill: parent
|
||||
spacing: 0
|
||||
|
|
|
@ -19,21 +19,16 @@ function getLastRoomEventText(roomId, accountId) {
|
|||
var undecryptable = ev.type === "OlmEvent" || ev.type === "MegolmEvent"
|
||||
|
||||
if (undecryptable || ev.type.startsWith("RoomMessage")) {
|
||||
var color = ev.dict.sender === roomList.forUserId ?
|
||||
"darkblue" : "purple"
|
||||
var color = Qt.hsla(Backend.hueFromString(name), 0.32, 0.3, 1)
|
||||
|
||||
return "<font color='" +
|
||||
color +
|
||||
"'>" +
|
||||
return "<font color='" + color + "'>" +
|
||||
name +
|
||||
":</font> " +
|
||||
(undecryptable ?
|
||||
"<font color='darkred'>Undecryptable<font>" :
|
||||
"<font color='darkred'>" + qsTr("Undecryptable") + "<font>" :
|
||||
ev.dict.body)
|
||||
} else {
|
||||
return "<font color='" +
|
||||
(undecryptable ? "darkred" : "#444") +
|
||||
"'>" +
|
||||
return "<font color='" + (undecryptable ? "darkred" : "#444") + "'>" +
|
||||
name +
|
||||
" " +
|
||||
ChatJS.getEventText(ev.type, ev.dict) +
|
||||
|
|
Binary file not shown.
Loading…
Reference in New Issue
Block a user