diff options
-rw-r--r-- | components/package/contents/ui/ConversationView.qml | 115 | ||||
-rw-r--r-- | framework/domain/mailcontroller.cpp | 2 |
2 files changed, 111 insertions, 6 deletions
diff --git a/components/package/contents/ui/ConversationView.qml b/components/package/contents/ui/ConversationView.qml index 3c76928f..6ecc59ae 100644 --- a/components/package/contents/ui/ConversationView.qml +++ b/components/package/contents/ui/ConversationView.qml | |||
@@ -31,11 +31,43 @@ Rectangle { | |||
31 | id: root | 31 | id: root |
32 | 32 | ||
33 | property variant mail; | 33 | property variant mail; |
34 | property int currentIndex: 0; | ||
35 | property bool scrollToEnd: true; | ||
36 | property variant currentMail: null; | ||
37 | onCurrentIndexChanged: { | ||
38 | markAsReadTimer.restart(); | ||
39 | } | ||
40 | onMailChanged: { | ||
41 | scrollToEnd = true; | ||
42 | currentMail = null; | ||
43 | } | ||
34 | 44 | ||
35 | color: Kirigami.Theme.backgroundColor | 45 | color: Kirigami.Theme.backgroundColor |
36 | 46 | ||
37 | ListView { | 47 | ListView { |
38 | id: listView | 48 | id: listView |
49 | function setCurrentIndex() | ||
50 | { | ||
51 | /** | ||
52 | * This will detect the index at the "scrollbar-position" (visibleArea.yPosition). | ||
53 | * This ensures that the first and last entry can become the currentIndex, | ||
54 | * but in the middle of the list the item in the middle is set as the current item. | ||
55 | */ | ||
56 | var yPos = 0.5; | ||
57 | if (listView.visibleArea.yPosition < 0.4) { | ||
58 | yPos = 0.2 + (0.2 * listView.visibleArea.yPosition); | ||
59 | } | ||
60 | if (listView.visibleArea.yPosition > 0.6) { | ||
61 | yPos = 0.6 + (0.2 * listView.visibleArea.yPosition) | ||
62 | } | ||
63 | var indexAtCenter = listView.indexAt(root.width / 2, contentY + root.height * yPos); | ||
64 | if (indexAtCenter >= 0) { | ||
65 | root.currentIndex = indexAtCenter; | ||
66 | } else { | ||
67 | root.currentIndex = count - 1; | ||
68 | } | ||
69 | } | ||
70 | |||
39 | anchors { | 71 | anchors { |
40 | top: parent.top | 72 | top: parent.top |
41 | left: parent.left | 73 | left: parent.left |
@@ -64,13 +96,68 @@ Rectangle { | |||
64 | 96 | ||
65 | boundsBehavior: Flickable.StopAtBounds | 97 | boundsBehavior: Flickable.StopAtBounds |
66 | 98 | ||
67 | //Always scroll to the end of the conversation | 99 | //default is 1500, which is not usable with a mouse |
68 | highlightFollowsCurrentItem: true | 100 | flickDeceleration: 10000 |
69 | //Scroll quickly | 101 | |
70 | highlightMoveDuration: 1 | 102 | //Optimize for view quality |
103 | pixelAligned: true | ||
104 | |||
105 | Timer { | ||
106 | id: scrollToEndTimer | ||
107 | interval: 10 | ||
108 | running: false | ||
109 | repeat: false | ||
110 | onTriggered: { | ||
111 | //Only do this once per conversation | ||
112 | root.scrollToEnd = false; | ||
113 | root.currentIndex = listView.count - 1 | ||
114 | //positionViewAtEnd/Index don't work | ||
115 | listView.contentY = listView.contentHeight - listView.height | ||
116 | } | ||
117 | } | ||
118 | |||
71 | onCountChanged: { | 119 | onCountChanged: { |
72 | //TODO: ideally we should only do this initially, not when new messages enter while you're reading. | 120 | if (root.scrollToEnd) { |
73 | currentIndex = count - 1; | 121 | scrollToEndTimer.restart() |
122 | } | ||
123 | } | ||
124 | |||
125 | onContentHeightChanged: { | ||
126 | //Initially it will resize a lot, so we keep waiting | ||
127 | if (root.scrollToEnd) { | ||
128 | scrollToEndTimer.restart() | ||
129 | } | ||
130 | } | ||
131 | |||
132 | onContentYChanged: { | ||
133 | //We have to track our current mail manually | ||
134 | setCurrentIndex(); | ||
135 | } | ||
136 | |||
137 | //The cacheBuffer needs to be large enough to fit the whole thread. | ||
138 | //Otherwise the contentHeight will constantly increase and decrease, | ||
139 | //which will break lot's of things. | ||
140 | cacheBuffer: 100000 | ||
141 | |||
142 | KubeFramework.MailController { | ||
143 | id: mailController | ||
144 | Binding on mail { | ||
145 | //!! checks for the availability of the type | ||
146 | when: !!root.currentMail | ||
147 | value: root.currentMail | ||
148 | } | ||
149 | } | ||
150 | |||
151 | Timer { | ||
152 | id: markAsReadTimer | ||
153 | interval: 2000 | ||
154 | running: false | ||
155 | repeat: false | ||
156 | onTriggered: { | ||
157 | if (mailController.markAsReadAction.enabled) { | ||
158 | mailController.markAsReadAction.execute(); | ||
159 | } | ||
160 | } | ||
74 | } | 161 | } |
75 | 162 | ||
76 | //Intercept all scroll events, | 163 | //Intercept all scroll events, |
@@ -85,6 +172,13 @@ Rectangle { | |||
85 | id: mailDelegate | 172 | id: mailDelegate |
86 | 173 | ||
87 | Item { | 174 | Item { |
175 | id: wrapper | ||
176 | property bool isCurrent: root.currentIndex === index; | ||
177 | onIsCurrentChanged: { | ||
178 | if (isCurrent) { | ||
179 | root.currentMail = model.mail | ||
180 | } | ||
181 | } | ||
88 | 182 | ||
89 | height: sheet.height + Kirigami.Units.gridUnit | 183 | height: sheet.height + Kirigami.Units.gridUnit |
90 | width: parent.width | 184 | width: parent.width |
@@ -95,6 +189,15 @@ Rectangle { | |||
95 | implicitHeight: header.height + attachments.height + body.height + footer.height + Kirigami.Units.largeSpacing | 189 | implicitHeight: header.height + attachments.height + body.height + footer.height + Kirigami.Units.largeSpacing |
96 | width: parent.width - Kirigami.Units.gridUnit * 2 | 190 | width: parent.width - Kirigami.Units.gridUnit * 2 |
97 | 191 | ||
192 | //Overlay for non-active mails | ||
193 | Rectangle { | ||
194 | anchors.fill: parent | ||
195 | visible: !wrapper.isCurrent | ||
196 | color: "lightGrey" | ||
197 | z: 1 | ||
198 | opacity: 0.2 | ||
199 | } | ||
200 | |||
98 | color: Kirigami.Theme.viewBackgroundColor | 201 | color: Kirigami.Theme.viewBackgroundColor |
99 | 202 | ||
100 | //BEGIN header | 203 | //BEGIN header |
diff --git a/framework/domain/mailcontroller.cpp b/framework/domain/mailcontroller.cpp index 962b785f..b912567a 100644 --- a/framework/domain/mailcontroller.cpp +++ b/framework/domain/mailcontroller.cpp | |||
@@ -61,6 +61,8 @@ void MailController::updateActions() | |||
61 | if (mail) { | 61 | if (mail) { |
62 | action_moveToTrash->setEnabled(!mail->getTrash()); | 62 | action_moveToTrash->setEnabled(!mail->getTrash()); |
63 | action_restoreFromTrash->setEnabled(mail->getTrash()); | 63 | action_restoreFromTrash->setEnabled(mail->getTrash()); |
64 | action_markAsRead->setEnabled(mail->getUnread()); | ||
65 | action_markAsUnread->setEnabled(!mail->getUnread()); | ||
64 | } | 66 | } |
65 | } | 67 | } |
66 | 68 | ||