diff options
Diffstat (limited to 'framework')
-rw-r--r-- | framework/qml/ConversationView.qml | 229 | ||||
-rw-r--r-- | framework/qml/MailViewer.qml | 3 |
2 files changed, 114 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 | |||
25 | import QtQml 2.2 as QtQml | 25 | import QtQml 2.2 as QtQml |
26 | 26 | ||
27 | 27 | ||
28 | Rectangle { | 28 | FocusScope { |
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 | } |
diff --git a/framework/qml/MailViewer.qml b/framework/qml/MailViewer.qml index d139b3d7..42c5080c 100644 --- a/framework/qml/MailViewer.qml +++ b/framework/qml/MailViewer.qml | |||
@@ -230,6 +230,7 @@ Rectangle { | |||
230 | 230 | ||
231 | Kube.IconButton { | 231 | Kube.IconButton { |
232 | anchors.fill: parent | 232 | anchors.fill: parent |
233 | activeFocusOnTab: false | ||
233 | 234 | ||
234 | iconName: header.state === "details" ? Kube.Icons.goUp : Kube.Icons.goDown | 235 | iconName: header.state === "details" ? Kube.Icons.goUp : Kube.Icons.goDown |
235 | 236 | ||
@@ -352,6 +353,7 @@ Rectangle { | |||
352 | left: parent.left | 353 | left: parent.left |
353 | leftMargin: Kube.Units.largeSpacing | 354 | leftMargin: Kube.Units.largeSpacing |
354 | } | 355 | } |
356 | activeFocusOnTab: false | ||
355 | 357 | ||
356 | text: model.trash ? qsTr("Delete Mail") : qsTr("Move to trash") | 358 | text: model.trash ? qsTr("Delete Mail") : qsTr("Move to trash") |
357 | opacity: 0.5 | 359 | opacity: 0.5 |
@@ -371,6 +373,7 @@ Rectangle { | |||
371 | right: parent.right | 373 | right: parent.right |
372 | rightMargin: Kube.Units.largeSpacing | 374 | rightMargin: Kube.Units.largeSpacing |
373 | } | 375 | } |
376 | activeFocusOnTab: false | ||
374 | 377 | ||
375 | iconName: model.draft ? Kube.Icons.edit : Kube.Icons.replyToSender | 378 | iconName: model.draft ? Kube.Icons.edit : Kube.Icons.replyToSender |
376 | onClicked: { | 379 | onClicked: { |