Dekko
Loading...
Searching...
No Matches
FlipableSelectionAvatar.qml
1/* Copyright (C) 2016 - 2017 Dan Chapman <dpniel@ubuntu.com>
2
3 This file is part of Dekko email client for Ubuntu devices
4
5 This program is free software; you can redistribute it and/or
6 modify it under the terms of the GNU General Public License as
7 published by the Free Software Foundation; either version 2 of
8 the License or (at your option) version 3
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17*/
18import QtQuick 2.4
19import QtQuick.Controls.Suru 2.2
20import QtFeedback 5.0
21import Lomiri.Components 1.3
22import Dekko.Components 1.0
23import Dekko.Mail.API 1.0
24import Dekko.Mail.Stores.Mail 1.0
25import "./private/UiUtils.js" as UiUtils
26import Dekko.Lomiri.Constants 1.0
27
28Flipable {
29 id: flipable
30 property var msg
31
32 signal clicked()
33
34 front: PixelPerfectItem {
35 id: inner_avatar
36 anchors.fill: parent
37 Component {
38 id: component_inner_av
39 LomiriShape {
40 id: avatarCircle
41 anchors.fill: parent
42 anchors.centerIn: parent
43 aspect: LomiriShape.Flat
44 backgroundColor: msg ? UiUtils.getIconColor(msg.from.name) : "transparent"
45 opacity: ma.containsMouse ? 0.8 : 1.0
46
47 Label {
48 id: initialsLabel
49 color: Suru.backgroundColor
50 text: msg ? msg.from.initials : ""
51 anchors.centerIn: parent
52 fontSize: "large"
53 }
54 Icon {
55 id: contactIcon
56 name: "contact"
57 anchors.centerIn: parent
58 height: parent.height - Style.defaultSpacing
59 width: height
60 color: Suru.backgroundColor
61 visible: !initialsLabel.text
62 }
63 }
64 }
65 Loader {
66 id: loader_inner_av
67 anchors.fill: parent
68 active: !inner_name.visible
69 sourceComponent: component_inner_av
70 }
71 LomiriShapeGravatar {
72 id: inner_name
73 emailAddress: msg ? msg.from.address : ""
74 clip: true
75 anchors.fill: parent
76 visible: status === Image.Ready
77 opacity: ma.containsMouse ? 0.8 : 1.0
78 }
79
80 MouseArea {
81 id: ma
82 hoverEnabled: true
83 anchors.fill: parent
84 visible: flipable.state === "front"
85 onClicked: flipable.clicked()
86 // For some weird reason we can't just bind
87 // avatarCircle to containsMouse. As during
88 // pushing and popping another page to the stack
89 // can cause multiple avatars with the search overaly visible.
90 // It's mighty weird!!!
91 // So instead we just manually show/hide when mouse enters/exits
92 // Not ideal but it enforces the overlay is only visible when we want
93 onEntered: {
94 if (containsMouse) {
95 avatarSearchOverlay.visible = true
96 }
97 }
98 onExited: {
99 if (!containsMouse) {
100 avatarSearchOverlay.visible = false
101 }
102 }
103 }
104
105 LomiriShape {
106 id: avatarSearchOverlay
107 anchors.fill: parent
108 anchors.centerIn: parent
109 aspect: LomiriShape.Flat
110 backgroundColor: Suru.secondaryForegroundColor
111 opacity: 0.8
112 visible: false
113 CachedImage {
114 width: parent.width - Style.defaultSpacing
115 height: width
116 anchors.centerIn: parent
117 name: Icons.SearchIcon
118 color: Suru.backgroundColor
119 }
120 }
121 }
122
123 back: PixelPerfectItem {
124 anchors.fill: parent
125 ListItemWithActionsCheckBox {
126 anchors.centerIn: parent
127 checked: msg && msg.checked
128 }
129
130 MouseArea {
131 id: mA
132 hoverEnabled: true
133 anchors.fill: parent
134 visible: flipable.state === "back"
135 onClicked: {
136 clickEffect.start()
137 if (msg.checked) {
138 MessageActions.setMessageCheck(model.index, Qt.Unchecked)
139 } else {
140 MessageActions.setMessageCheck(model.index, Qt.Checked)
141 }
142 }
143 }
144 }
145
146 transform: Rotation {
147 id: rotation
148 origin.x: flipable.width/2
149 origin.y: flipable.height/2
150 axis.x: 0; axis.y: 1; axis.z: 0
151 }
152
153 state: MailStore.isInSelectionMode ? "back" : "front"
154
155 states: [
156 State {
157 name: "front"
158 PropertyChanges { target: rotation; angle: 0 }
159
160 },
161 State {
162 name: "back"
163 PropertyChanges { target: rotation; angle: 180 }
164 }
165 ]
166
167 transitions: Transition {
168 SequentialAnimation {
169 PauseAnimation {
170 duration: {
171 var result;
172 if (model.index > listView.selectionIndex) {
173 result = model.index - listView.selectionIndex
174 } else if ( model.index < listView.selectionIndex) {
175 result = listView.selectionIndex - model.index
176 }
177 if (result > 0 && result <= 20) {
178 return result * 100
179 } else {
180 return 0
181 }
182 }
183 }
184 NumberAnimation { target: rotation; property: "angle"; duration: LomiriAnimation.FastDuration }
185 }
186 }
187
188 HapticsEffect {
189 id: clickEffect
190 attackIntensity: 0.0
191 attackTime: 50
192 intensity: 1.0
193 duration: 10
194 fadeTime: 50
195 fadeIntensity: 0.0
196 }
197}