diff --git a/resources/qml/Avatar.qml b/resources/qml/Avatar.qml
index 6c12952a..9685dde1 100644
--- a/resources/qml/Avatar.qml
+++ b/resources/qml/Avatar.qml
@@ -11,10 +11,11 @@ import im.nheko 1.0
Rectangle {
id: avatar
- property alias url: img.source
+ property string url
property string userid
property string displayName
property alias textColor: label.color
+ property bool crop: true
signal clicked(var mouse)
@@ -44,12 +45,13 @@ Rectangle {
anchors.fill: parent
asynchronous: true
- fillMode: Image.PreserveAspectCrop
+ fillMode: avatar.crop ? Image.PreserveAspectCrop : Image.PreserveAspectFit
mipmap: true
smooth: true
sourceSize.width: avatar.width
sourceSize.height: avatar.height
layer.enabled: true
+ source: avatar.url + ((avatar.crop || !avatar.url) ? "" : "?scale")
MouseArea {
id: mouseArea
diff --git a/resources/qml/RoomSettings.qml b/resources/qml/RoomSettings.qml
index 6ba080c4..69cf427c 100644
--- a/resources/qml/RoomSettings.qml
+++ b/resources/qml/RoomSettings.qml
@@ -154,7 +154,7 @@ ApplicationWindow {
GridLayout {
columns: 2
- rowSpacing: 10
+ rowSpacing: Nheko.paddingLarge
MatrixText {
text: qsTr("SETTINGS")
@@ -180,7 +180,7 @@ ApplicationWindow {
}
MatrixText {
- text: "Room access"
+ text: qsTr("Room access")
Layout.fillWidth: true
}
diff --git a/resources/qml/ScrollHelper.qml b/resources/qml/ScrollHelper.qml
index 2dd56f27..e584ae3d 100644
--- a/resources/qml/ScrollHelper.qml
+++ b/resources/qml/ScrollHelper.qml
@@ -30,6 +30,10 @@ MouseArea {
property alias enabled: root.enabled
function calculateNewPosition(flickableItem, wheel) {
+ // breaks ListView's with headers...
+ //if (typeof (flickableItem.headerItem) !== "undefined" && flickableItem.headerItem)
+ // minYExtent += flickableItem.headerItem.height;
+
//Nothing to scroll
if (flickableItem.contentHeight < flickableItem.height)
return flickableItem.contentY;
@@ -55,9 +59,6 @@ MouseArea {
var minYExtent = flickableItem.originY + flickableItem.topMargin;
var maxYExtent = (flickableItem.contentHeight + flickableItem.bottomMargin + flickableItem.originY) - flickableItem.height;
- if (typeof (flickableItem.headerItem) !== "undefined" && flickableItem.headerItem)
- minYExtent += flickableItem.headerItem.height;
-
//Avoid overscrolling
return Math.max(minYExtent, Math.min(maxYExtent, flickableItem.contentY - pixelDelta));
}
diff --git a/resources/qml/components/AvatarListTile.qml b/resources/qml/components/AvatarListTile.qml
new file mode 100644
index 00000000..36c26a97
--- /dev/null
+++ b/resources/qml/components/AvatarListTile.qml
@@ -0,0 +1,133 @@
+// SPDX-FileCopyrightText: 2021 Nheko Contributors
+//
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+import ".."
+import QtQuick 2.15
+import QtQuick.Controls 2.15
+import QtQuick.Layouts 1.15
+import im.nheko 1.0
+
+Rectangle {
+ id: tile
+
+ property color background: Nheko.colors.window
+ property color importantText: Nheko.colors.text
+ property color unimportantText: Nheko.colors.buttonText
+ property color bubbleBackground: Nheko.colors.highlight
+ property color bubbleText: Nheko.colors.highlightedText
+ property int avatarSize: Math.ceil(fontMetrics.lineSpacing * 2.3)
+ required property string avatarUrl
+ required property string title
+ required property string subtitle
+ required property int index
+ required property int selectedIndex
+ property bool crop: true
+
+ color: background
+ height: avatarSize + 2 * Nheko.paddingMedium
+ width: ListView.view.width
+ state: "normal"
+ states: [
+ State {
+ name: "highlight"
+ when: hovered.hovered && !(index == selectedIndex)
+
+ PropertyChanges {
+ target: tile
+ background: Nheko.colors.dark
+ importantText: Nheko.colors.brightText
+ unimportantText: Nheko.colors.brightText
+ bubbleBackground: Nheko.colors.highlight
+ bubbleText: Nheko.colors.highlightedText
+ }
+
+ },
+ State {
+ name: "selected"
+ when: index == selectedIndex
+
+ PropertyChanges {
+ target: tile
+ background: Nheko.colors.highlight
+ importantText: Nheko.colors.highlightedText
+ unimportantText: Nheko.colors.highlightedText
+ bubbleBackground: Nheko.colors.highlightedText
+ bubbleText: Nheko.colors.highlight
+ }
+
+ }
+ ]
+
+ HoverHandler {
+ id: hovered
+ }
+
+ RowLayout {
+ spacing: Nheko.paddingMedium
+ anchors.fill: parent
+ anchors.margins: Nheko.paddingMedium
+
+ Avatar {
+ id: avatar
+
+ enabled: false
+ Layout.alignment: Qt.AlignVCenter
+ height: avatarSize
+ width: avatarSize
+ url: tile.avatarUrl.replace("mxc://", "image://MxcImage/")
+ displayName: title
+ crop: tile.crop
+ }
+
+ ColumnLayout {
+ id: textContent
+
+ Layout.alignment: Qt.AlignLeft
+ Layout.fillWidth: true
+ Layout.minimumWidth: 100
+ width: parent.width - avatar.width
+ Layout.preferredWidth: parent.width - avatar.width
+ spacing: Nheko.paddingSmall
+
+ RowLayout {
+ Layout.fillWidth: true
+ spacing: 0
+
+ ElidedLabel {
+ Layout.alignment: Qt.AlignBottom
+ color: tile.importantText
+ elideWidth: textContent.width - Nheko.paddingMedium
+ fullText: title
+ textFormat: Text.PlainText
+ }
+
+ Item {
+ Layout.fillWidth: true
+ }
+
+ }
+
+ RowLayout {
+ Layout.fillWidth: true
+ spacing: 0
+
+ ElidedLabel {
+ color: tile.unimportantText
+ font.pixelSize: fontMetrics.font.pixelSize * 0.9
+ elideWidth: textContent.width - Nheko.paddingSmall
+ fullText: subtitle
+ textFormat: Text.PlainText
+ }
+
+ Item {
+ Layout.fillWidth: true
+ }
+
+ }
+
+ }
+
+ }
+
+}
diff --git a/resources/qml/dialogs/ImagePackEditorDialog.qml b/resources/qml/dialogs/ImagePackEditorDialog.qml
new file mode 100644
index 00000000..0049d3b4
--- /dev/null
+++ b/resources/qml/dialogs/ImagePackEditorDialog.qml
@@ -0,0 +1,283 @@
+// SPDX-FileCopyrightText: 2021 Nheko Contributors
+//
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+import ".."
+import "../components"
+import QtQuick 2.12
+import QtQuick.Controls 2.12
+import QtQuick.Layouts 1.12
+import im.nheko 1.0
+
+ApplicationWindow {
+ //Component.onCompleted: Nheko.reparent(win)
+
+ id: win
+
+ property int avatarSize: Math.ceil(fontMetrics.lineSpacing * 2.3)
+ property SingleImagePackModel imagePack
+ property int currentImageIndex: -1
+ readonly property int stickerDim: 128
+ readonly property int stickerDimPad: 128 + Nheko.paddingSmall
+
+ title: qsTr("Editing image pack")
+ height: 600
+ width: 600
+ palette: Nheko.colors
+ color: Nheko.colors.base
+ modality: Qt.WindowModal
+ flags: Qt.Dialog | Qt.WindowCloseButtonHint
+
+ AdaptiveLayout {
+ id: adaptiveView
+
+ anchors.fill: parent
+ singlePageMode: false
+ pageIndex: 0
+
+ AdaptiveLayoutElement {
+ id: packlistC
+
+ visible: Settings.groupView
+ minimumWidth: 200
+ collapsedWidth: 200
+ preferredWidth: 300
+ maximumWidth: 300
+ clip: true
+
+ ListView {
+ //required property bool isEmote
+ //required property bool isSticker
+
+ model: imagePack
+
+ ScrollHelper {
+ flickable: parent
+ anchors.fill: parent
+ enabled: !Settings.mobileMode
+ }
+
+ header: AvatarListTile {
+ title: imagePack.packname
+ avatarUrl: imagePack.avatarUrl
+ subtitle: imagePack.statekey
+ index: -1
+ selectedIndex: currentImageIndex
+
+ TapHandler {
+ onSingleTapped: currentImageIndex = -1
+ }
+
+ Rectangle {
+ anchors.left: parent.left
+ anchors.verticalCenter: parent.verticalCenter
+ height: parent.height - Nheko.paddingSmall * 2
+ width: 3
+ color: Nheko.colors.highlight
+ }
+
+ }
+
+ delegate: AvatarListTile {
+ id: packItem
+
+ property color background: Nheko.colors.window
+ property color importantText: Nheko.colors.text
+ property color unimportantText: Nheko.colors.buttonText
+ property color bubbleBackground: Nheko.colors.highlight
+ property color bubbleText: Nheko.colors.highlightedText
+ required property string shortCode
+ required property string url
+ required property string body
+
+ title: shortCode
+ subtitle: body
+ avatarUrl: url
+ selectedIndex: currentImageIndex
+ crop: false
+
+ TapHandler {
+ onSingleTapped: currentImageIndex = index
+ }
+
+ }
+
+ }
+
+ }
+
+ AdaptiveLayoutElement {
+ id: packinfoC
+
+ Rectangle {
+ color: Nheko.colors.window
+
+ GridLayout {
+ anchors.fill: parent
+ anchors.margins: Nheko.paddingMedium
+ visible: currentImageIndex == -1
+ enabled: visible
+ columns: 2
+ rowSpacing: Nheko.paddingLarge
+
+ Avatar {
+ Layout.columnSpan: 2
+ url: imagePack.avatarUrl.replace("mxc://", "image://MxcImage/")
+ displayName: imagePack.packname
+ height: 130
+ width: 130
+ crop: false
+ Layout.alignment: Qt.AlignHCenter
+ }
+
+ MatrixText {
+ visible: imagePack.roomid
+ text: qsTr("State key")
+ }
+
+ MatrixTextField {
+ visible: imagePack.roomid
+ Layout.fillWidth: true
+ text: imagePack.statekey
+ onTextEdited: imagePack.statekey = text
+ }
+
+ MatrixText {
+ text: qsTr("Packname")
+ }
+
+ MatrixTextField {
+ Layout.fillWidth: true
+ text: imagePack.packname
+ onTextEdited: imagePack.packname = text
+ }
+
+ MatrixText {
+ text: qsTr("Attrbution")
+ }
+
+ MatrixTextField {
+ Layout.fillWidth: true
+ text: imagePack.attribution
+ onTextEdited: imagePack.attribution = text
+ }
+
+ MatrixText {
+ text: qsTr("Use as Emoji")
+ }
+
+ ToggleButton {
+ checked: imagePack.isEmotePack
+ onToggled: imagePack.isEmotePack = checked
+ Layout.alignment: Qt.AlignRight
+ }
+
+ MatrixText {
+ text: qsTr("Use as Sticker")
+ }
+
+ ToggleButton {
+ checked: imagePack.isStickerPack
+ onToggled: imagePack.isStickerPack = checked
+ Layout.alignment: Qt.AlignRight
+ }
+
+ Item {
+ Layout.columnSpan: 2
+ Layout.fillHeight: true
+ }
+
+ }
+
+ GridLayout {
+ anchors.fill: parent
+ anchors.margins: Nheko.paddingMedium
+ visible: currentImageIndex >= 0
+ enabled: visible
+ columns: 2
+ rowSpacing: Nheko.paddingLarge
+
+ Avatar {
+ Layout.columnSpan: 2
+ url: imagePack.data(imagePack.index(currentImageIndex, 0), SingleImagePackModel.Url).replace("mxc://", "image://MxcImage/")
+ displayName: imagePack.data(imagePack.index(currentImageIndex, 0), SingleImagePackModel.ShortCode)
+ height: 130
+ width: 130
+ crop: false
+ Layout.alignment: Qt.AlignHCenter
+ }
+
+ MatrixText {
+ text: qsTr("Shortcode")
+ }
+
+ MatrixTextField {
+ Layout.fillWidth: true
+ text: imagePack.data(imagePack.index(currentImageIndex, 0), SingleImagePackModel.ShortCode)
+ onTextEdited: imagePack.setData(imagePack.index(currentImageIndex, 0), text, SingleImagePackModel.ShortCode)
+ }
+
+ MatrixText {
+ text: qsTr("Body")
+ }
+
+ MatrixTextField {
+ Layout.fillWidth: true
+ text: imagePack.data(imagePack.index(currentImageIndex, 0), SingleImagePackModel.Body)
+ onTextEdited: imagePack.setData(imagePack.index(currentImageIndex, 0), text, SingleImagePackModel.Body)
+ }
+
+ MatrixText {
+ text: qsTr("Use as Emoji")
+ }
+
+ ToggleButton {
+ checked: imagePack.data(imagePack.index(currentImageIndex, 0), SingleImagePackModel.IsEmote)
+ onToggled: imagePack.setData(imagePack.index(currentImageIndex, 0), text, SingleImagePackModel.IsEmote)
+ Layout.alignment: Qt.AlignRight
+ }
+
+ MatrixText {
+ text: qsTr("Use as Sticker")
+ }
+
+ ToggleButton {
+ checked: imagePack.data(imagePack.index(currentImageIndex, 0), SingleImagePackModel.IsSticker)
+ onToggled: imagePack.setData(imagePack.index(currentImageIndex, 0), text, SingleImagePackModel.IsSticker)
+ Layout.alignment: Qt.AlignRight
+ }
+
+ Item {
+ Layout.columnSpan: 2
+ Layout.fillHeight: true
+ }
+
+ }
+
+ }
+
+ }
+
+ }
+
+ footer: DialogButtonBox {
+ id: buttons
+
+ Button {
+ text: qsTr("Cancel")
+ DialogButtonBox.buttonRole: DialogButtonBox.DestructiveRole
+ onClicked: win.close()
+ }
+
+ Button {
+ text: qsTr("Save")
+ DialogButtonBox.buttonRole: DialogButtonBox.ApplyRole
+ onClicked: {
+ imagePack.save();
+ win.close();
+ }
+ }
+
+ }
+
+}
diff --git a/resources/qml/dialogs/ImagePackSettingsDialog.qml b/resources/qml/dialogs/ImagePackSettingsDialog.qml
index 3d830bf7..c57867fd 100644
--- a/resources/qml/dialogs/ImagePackSettingsDialog.qml
+++ b/resources/qml/dialogs/ImagePackSettingsDialog.qml
@@ -20,14 +20,22 @@ ApplicationWindow {
readonly property int stickerDimPad: 128 + Nheko.paddingSmall
title: qsTr("Image pack settings")
- height: 400
- width: 600
+ height: 600
+ width: 800
palette: Nheko.colors
color: Nheko.colors.base
modality: Qt.NonModal
flags: Qt.Dialog | Qt.WindowCloseButtonHint
Component.onCompleted: Nheko.reparent(win)
+ Component {
+ id: packEditor
+
+ ImagePackEditorDialog {
+ }
+
+ }
+
AdaptiveLayout {
id: adaptiveView
@@ -54,7 +62,7 @@ ApplicationWindow {
enabled: !Settings.mobileMode
}
- delegate: Rectangle {
+ delegate: AvatarListTile {
id: packItem
property color background: Nheko.colors.window
@@ -63,131 +71,24 @@ ApplicationWindow {
property color bubbleBackground: Nheko.colors.highlight
property color bubbleText: Nheko.colors.highlightedText
required property string displayName
- required property string avatarUrl
required property bool fromAccountData
required property bool fromCurrentRoom
- required property int index
-
- color: background
- height: avatarSize + 2 * Nheko.paddingMedium
- width: ListView.view.width
- state: "normal"
- states: [
- State {
- name: "highlight"
- when: hovered.hovered && !(index == currentPackIndex)
-
- PropertyChanges {
- target: packItem
- background: Nheko.colors.dark
- importantText: Nheko.colors.brightText
- unimportantText: Nheko.colors.brightText
- bubbleBackground: Nheko.colors.highlight
- bubbleText: Nheko.colors.highlightedText
- }
-
- },
- State {
- name: "selected"
- when: index == currentPackIndex
-
- PropertyChanges {
- target: packItem
- background: Nheko.colors.highlight
- importantText: Nheko.colors.highlightedText
- unimportantText: Nheko.colors.highlightedText
- bubbleBackground: Nheko.colors.highlightedText
- bubbleText: Nheko.colors.highlight
- }
- }
- ]
+ title: displayName
+ subtitle: {
+ if (fromAccountData)
+ return qsTr("Private pack");
+ else if (fromCurrentRoom)
+ return qsTr("Pack from this room");
+ else
+ return qsTr("Globally enabled pack");
+ }
+ selectedIndex: currentPackIndex
TapHandler {
- margin: -Nheko.paddingSmall
onSingleTapped: currentPackIndex = index
}
- HoverHandler {
- id: hovered
- }
-
- RowLayout {
- spacing: Nheko.paddingMedium
- anchors.fill: parent
- anchors.margins: Nheko.paddingMedium
-
- Avatar {
- // In the future we could show an online indicator by setting the userid for the avatar
- //userid: Nheko.currentUser.userid
-
- id: avatar
-
- enabled: false
- Layout.alignment: Qt.AlignVCenter
- height: avatarSize
- width: avatarSize
- url: avatarUrl.replace("mxc://", "image://MxcImage/")
- displayName: packItem.displayName
- }
-
- ColumnLayout {
- id: textContent
-
- Layout.alignment: Qt.AlignLeft
- Layout.fillWidth: true
- Layout.minimumWidth: 100
- width: parent.width - avatar.width
- Layout.preferredWidth: parent.width - avatar.width
- spacing: Nheko.paddingSmall
-
- RowLayout {
- Layout.fillWidth: true
- spacing: 0
-
- ElidedLabel {
- Layout.alignment: Qt.AlignBottom
- color: packItem.importantText
- elideWidth: textContent.width - Nheko.paddingMedium
- fullText: displayName
- textFormat: Text.PlainText
- }
-
- Item {
- Layout.fillWidth: true
- }
-
- }
-
- RowLayout {
- Layout.fillWidth: true
- spacing: 0
-
- ElidedLabel {
- color: packItem.unimportantText
- font.pixelSize: fontMetrics.font.pixelSize * 0.9
- elideWidth: textContent.width - Nheko.paddingSmall
- fullText: {
- if (fromAccountData)
- return qsTr("Private pack");
- else if (fromCurrentRoom)
- return qsTr("Pack from this room");
- else
- return qsTr("Globally enabled pack");
- }
- textFormat: Text.PlainText
- }
-
- Item {
- Layout.fillWidth: true
- }
-
- }
-
- }
-
- }
-
}
}
@@ -201,15 +102,10 @@ ApplicationWindow {
color: Nheko.colors.window
ColumnLayout {
- //Button {
- // Layout.alignment: Qt.AlignHCenter
- // text: qsTr("Edit")
- // enabled: currentPack.canEdit
- //}
-
id: packinfo
property string packName: currentPack ? currentPack.packname : ""
+ property string attribution: currentPack ? currentPack.attribution : ""
property string avatarUrl: currentPack ? currentPack.avatarUrl : ""
anchors.fill: parent
@@ -227,8 +123,18 @@ ApplicationWindow {
MatrixText {
text: packinfo.packName
- font.pixelSize: 24
+ font.pixelSize: Math.ceil(fontMetrics.pixelSize * 1.1)
+ horizontalAlignment: TextEdit.AlignHCenter
+ Layout.alignment: Qt.AlignHCenter
+ Layout.preferredWidth: packinfoC.width - Nheko.paddingLarge * 2
+ }
+
+ MatrixText {
+ text: packinfo.attribution
+ wrapMode: TextEdit.Wrap
+ horizontalAlignment: TextEdit.AlignHCenter
Layout.alignment: Qt.AlignHCenter
+ Layout.preferredWidth: packinfoC.width - Nheko.paddingLarge * 2
}
GridLayout {
@@ -250,6 +156,18 @@ ApplicationWindow {
}
+ Button {
+ Layout.alignment: Qt.AlignHCenter
+ text: qsTr("Edit")
+ enabled: currentPack.canEdit
+ onClicked: {
+ var dialog = packEditor.createObject(timelineRoot, {
+ "imagePack": currentPack
+ });
+ dialog.show();
+ }
+ }
+
GridView {
Layout.fillHeight: true
Layout.fillWidth: true
@@ -272,7 +190,7 @@ ApplicationWindow {
width: stickerDim
height: stickerDim
hoverEnabled: true
- ToolTip.text: ":" + model.shortcode + ": - " + model.body
+ ToolTip.text: ":" + model.shortCode + ": - " + model.body
ToolTip.visible: hovered
contentItem: Image {
diff --git a/resources/res.qrc b/resources/res.qrc
index c911653c..d7187f42 100644
--- a/resources/res.qrc
+++ b/resources/res.qrc
@@ -160,6 +160,7 @@
<file>qml/device-verification/Success.qml</file>
<file>qml/dialogs/InputDialog.qml</file>
<file>qml/dialogs/ImagePackSettingsDialog.qml</file>
+ <file>qml/dialogs/ImagePackEditorDialog.qml</file>
<file>qml/ui/Ripple.qml</file>
<file>qml/ui/Spinner.qml</file>
<file>qml/ui/animations/BlinkAnimation.qml</file>
@@ -173,6 +174,7 @@
<file>qml/voip/VideoCall.qml</file>
<file>qml/components/AdaptiveLayout.qml</file>
<file>qml/components/AdaptiveLayoutElement.qml</file>
+ <file>qml/components/AvatarListTile.qml</file>
<file>qml/components/FlatButton.qml</file>
<file>qml/RoomMembers.qml</file>
<file>qml/InviteDialog.qml</file>
|