summaryrefslogtreecommitdiffstats
path: root/framework/qml/ConversationView.qml
diff options
context:
space:
mode:
authorChristian Mollekopf <chrigi_1@fastmail.fm>2017-07-26 21:39:48 -0600
committerChristian Mollekopf <chrigi_1@fastmail.fm>2017-07-27 11:01:21 -0600
commit89f4c68f548b24d983309cc7337b7c0ffe8aa3f3 (patch)
treeb17891a6e956a70c71fb32a63d886852c7caf6ee /framework/qml/ConversationView.qml
parentdff119d85fd4d6ceaf792337fee59300c1b23579 (diff)
downloadkube-89f4c68f548b24d983309cc7337b7c0ffe8aa3f3.tar.gz
kube-89f4c68f548b24d983309cc7337b7c0ffe8aa3f3.zip
Keyboard navigation for the conversation view
Removed the manual currentIndex handling again as we seem to be able to use the regular stuff now. Additionally the listview is now resized if we don't have enough mails, so the first mail is shown on top. We can also move from mail to mail using keyboard navigation. The mail highlight also serves as focus indicator for the conversation view in general, and as such is cleared when loosing focus.
Diffstat (limited to 'framework/qml/ConversationView.qml')
-rw-r--r--framework/qml/ConversationView.qml229
1 files changed, 111 insertions, 118 deletions
diff --git a/framework/qml/ConversationView.qml b/framework/qml/ConversationView.qml
index fb7a435e..1da1a9db 100644
--- a/framework/qml/ConversationView.qml
+++ b/framework/qml/ConversationView.qml
@@ -25,13 +25,10 @@ import org.kube.framework 1.0 as Kube
25import QtQml 2.2 as QtQml 25import QtQml 2.2 as QtQml
26 26
27 27
28Rectangle { 28FocusScope {
29 id: root 29 id: root
30 30
31 property variant mail; 31 property variant mail;
32 property int currentIndex: 0;
33 property bool scrollToEnd: true;
34 property variant currentMail: null;
35 property bool hideTrash: true; 32 property bool hideTrash: true;
36 property bool hideNonTrash: false; 33 property bool hideNonTrash: false;
37 34
@@ -39,6 +36,7 @@ Rectangle {
39 filter: Kube.Messages.mailSelection 36 filter: Kube.Messages.mailSelection
40 onMessageReceived: { 37 onMessageReceived: {
41 root.mail = message.mail 38 root.mail = message.mail
39 listView.forceLayout()
42 } 40 }
43 } 41 }
44 42
@@ -50,143 +48,138 @@ Rectangle {
50 } 48 }
51 } 49 }
52 50
53 onCurrentIndexChanged: { 51 Rectangle {
54 markAsReadTimer.restart();
55 }
56 onMailChanged: {
57 scrollToEnd = true;
58 currentMail = null;
59 }
60
61 color: Kube.Colors.backgroundColor
62
63 Kube.ListView {
64 id: listView
65
66 anchors.fill: parent 52 anchors.fill: parent
53 color: Kube.Colors.backgroundColor
54
55 Kube.ListView {
56 id: listView
57 focus: true
67 58
68 ScrollBar.vertical: ScrollBar {} 59 anchors {
69 verticalLayoutDirection: ListView.BottomToTop 60 top: parent.top
70 61 left: parent.left
71 function setCurrentIndex() 62 right: parent.right
72 {
73 /**
74 * This will detect the index at the "scrollbar-position" (visibleArea.yPosition).
75 * This ensures that the first and last entry can become the currentIndex,
76 * but in the middle of the list the item in the middle is set as the current item.
77 */
78 var yPos = 0.5;
79 if (listView.visibleArea.yPosition < 0.4) {
80 yPos = 0.2 + (0.2 * listView.visibleArea.yPosition);
81 } 63 }
82 if (listView.visibleArea.yPosition > 0.6) { 64 //Shrink the listview if the content doesn't fill the full height, so the email appears on top instead of on the bottom.
83 yPos = 0.6 + (0.2 * listView.visibleArea.yPosition) 65 height: Math.min(contentHeight, parent.height)
66
67 verticalLayoutDirection: ListView.BottomToTop
68
69 onActiveFocusChanged: {
70 if (activeFocus) {
71 if (currentIndex < 0) {
72 currentIndex = 0
73 }
74 } else {
75 currentIndex = -1
76 }
84 } 77 }
85 var indexAtCenter = listView.indexAt(root.width / 2, contentY + root.height * yPos); 78
86 if (indexAtCenter >= 0) { 79 //Position view so the last email begins on top of the view
87 root.currentIndex = indexAtCenter; 80 onContentHeightChanged: {
88 } else { 81 //FIXME This doesn't work quite correctly when we have headers and footers in the listview and the mail loads to slowly and only one item to show.
89 root.currentIndex = count - 1; 82 listView.positionViewAtIndex(0, ListView.End)
83 //A futile attempt to fix the problem above
84 listView.returnToBounds()
90 } 85 }
91 }
92 86
93 clip: true 87 Keys.onDownPressed: {
88 decrementCurrentIndex()
89 positionViewAtIndex(listView.currentIndex, ListView.End)
90 }
94 91
95 model: Kube.MailListModel { 92 Keys.onUpPressed: {
96 mail: root.mail 93 incrementCurrentIndex()
97 } 94 positionViewAtIndex(listView.currentIndex, ListView.End)
95 }
98 96
99 header: Item { 97 onCurrentIndexChanged: {
100 height: Kube.Units.gridUnit * 0.5 98 markAsReadTimer.restart();
101 width: parent.width 99 }
102 100
103 } 101 model: Kube.MailListModel {
102 mail: root.mail
103 }
104 104
105 footer: Item { 105 header: Item {
106 height: Kube.Units.gridUnit 106 height: Kube.Units.gridUnit * 0.5
107 width: parent.width 107 width: parent.width
108 } 108 }
109 109
110 delegate: mailDelegate 110 footer: Item {
111 height: Kube.Units.gridUnit
112 width: parent.width
113 }
111 114
112 //Setting the currentIndex results in further lags. So we don't do that either. 115 delegate: FocusScope {
113 // currentIndex: root.currentIndex 116 id: delegateRoot
114 117
115 //Optimize for view quality 118 property var currentData: model
116 pixelAligned: true
117 119
118 onContentYChanged: { 120 focus: false
119 //We have to track our current mail manually 121 activeFocusOnTab: false
120 setCurrentIndex();
121 }
122 122
123 //The cacheBuffer needs to be large enough to fit the whole thread. 123 height: sheet.height + Kube.Units.gridUnit
124 //Otherwise the contentHeight will constantly increase and decrease, 124 width: parent.width
125 //which will break lot's of things. 125 visible: !((root.hideTrash && model.trash) || (root.hideNonTrash && !model.trash))
126 cacheBuffer: 100000 126
127 127 MouseArea {
128 Timer { 128 anchors.fill: parent
129 id: markAsReadTimer 129 hoverEnabled: true
130 interval: 2000 130 onEntered: delegateRoot.ListView.view.currentIndex = index
131 running: false 131 onClicked: delegateRoot.ListView.view.currentIndex = index
132 repeat: false
133 onTriggered: {
134 if (!!root.currentMail) {
135 Kube.Fabric.postMessage(Kube.Messages.markAsRead, {"mail": root.currentMail})
136 } 132 }
137 }
138 }
139 133
140 //Intercept all scroll events, 134 MailViewer {
141 //necessary due to the webengineview 135 id: sheet
142 Kube.MouseProxy { 136 anchors.centerIn: parent
143 anchors.fill: parent 137 width: parent.width - Kube.Units.gridUnit * 2
144 target: listView.mouseProxy 138
145 forwardWheelEvents: true 139 message: model.mimeMessage
146 } 140 subject: model.subject
147 } 141 sender: model.sender
148 Component { 142 senderName: model.senderName
149 id: mailDelegate 143 to: model.to
150 144 cc: model.cc
151 Item { 145 bcc: model.bcc
152 id: wrapper 146 date: model.date
153 property bool isCurrent: root.currentIndex === index; 147 trash: model.trash
154 onIsCurrentChanged: { 148 draft: model.draft
155 if (isCurrent) { 149 sent: model.sent
156 root.currentMail = model.mail 150 incomplete: model.incomplete
151 current: delegateRoot.ListView.isCurrentItem
157 } 152 }
158 } 153 }
159 154
160 height: sheet.height + Kube.Units.gridUnit
161 width: parent.width
162 visible: !((root.hideTrash && model.trash) || (root.hideNonTrash && !model.trash))
163 155
164 MouseArea { 156 //Optimize for view quality
165 anchors.fill: parent 157 pixelAligned: true
166 enabled: parent.enabled 158
167 hoverEnabled: true 159
168 onEntered: root.currentIndex = index 160 //The cacheBuffer needs to be large enough to fit the whole thread.
169 onClicked: root.currentIndex = index 161 //Otherwise the contentHeight will constantly increase and decrease,
162 //which will break lot's of things.
163 cacheBuffer: 100000
164
165 Timer {
166 id: markAsReadTimer
167 interval: 2000
168 running: false
169 repeat: false
170 onTriggered: {
171 if (listView.currentItem && !!listView.currentItem.currentData.mail) {
172 Kube.Fabric.postMessage(Kube.Messages.markAsRead, {"mail": listView.currentItem.currentData.mail})
173 }
174 }
170 } 175 }
171 176
172 MailViewer { 177 //Intercept all scroll events,
173 id: sheet 178 //necessary due to the webengineview
174 anchors.centerIn: parent 179 Kube.MouseProxy {
175 width: parent.width - Kube.Units.gridUnit * 2 180 anchors.fill: parent
176 181 target: listView.mouseProxy
177 message: model.mimeMessage 182 forwardWheelEvents: true
178 subject: model.subject
179 sender: model.sender
180 senderName: model.senderName
181 to: model.to
182 cc: model.cc
183 bcc: model.bcc
184 date: model.date
185 trash: model.trash
186 draft: model.draft
187 sent: model.sent
188 incomplete: model.incomplete
189 current: isCurrent
190 } 183 }
191 } 184 }
192 } 185 }