ActivityItemContent.qml 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288
  1. import QtQml 2.15
  2. import QtQuick 2.15
  3. import QtQuick.Controls 2.15
  4. import QtQuick.Layouts 1.15
  5. import QtGraphicalEffects 1.15
  6. import Style 1.0
  7. import com.nextcloud.desktopclient 1.0
  8. RowLayout {
  9. id: root
  10. property variant activityData: {{}}
  11. property variant activity: {{}}
  12. property color activityTextTitleColor: Style.ncTextColor
  13. property bool showDismissButton: false
  14. property bool childHovered: fileDetailsButton.hovered || dismissActionButton.hovered
  15. property int iconSize: Style.trayListItemIconSize
  16. signal dismissButtonClicked()
  17. spacing: Style.standardSpacing
  18. Item {
  19. id: thumbnailItem
  20. readonly property int imageWidth: width * (1 - Style.thumbnailImageSizeReduction)
  21. readonly property int imageHeight: height * (1 - Style.thumbnailImageSizeReduction)
  22. readonly property int thumbnailRadius: model.thumbnail && model.thumbnail.isUserAvatar ? width / 2 : 3
  23. implicitWidth: root.iconSize
  24. implicitHeight: model.thumbnail && model.thumbnail.isMimeTypeIcon ? root.iconSize * 0.9 : root.iconSize
  25. Loader {
  26. id: thumbnailImageLoader
  27. anchors.fill: parent
  28. active: model.thumbnail !== undefined
  29. sourceComponent: Item {
  30. anchors.fill: parent
  31. readonly property int paintedWidth: model.thumbnail.isMimeTypeIcon ? thumbnailImage.paintedWidth * 0.8 : thumbnailImage.paintedWidth
  32. readonly property int paintedHeight: model.thumbnail.isMimeTypeIcon ? thumbnailImage.paintedHeight * 0.55 : thumbnailImage.paintedHeight
  33. Image {
  34. id: thumbnailImage
  35. width: thumbnailItem.imageWidth
  36. height: thumbnailItem.imageHeight
  37. anchors.verticalCenter: parent.verticalCenter
  38. anchors.left: parent.left
  39. cache: true
  40. fillMode: Image.PreserveAspectFit
  41. source: model.thumbnail.source
  42. visible: false
  43. sourceSize.height: 64
  44. sourceSize.width: 64
  45. }
  46. Rectangle {
  47. id: mask
  48. color: "white"
  49. radius: thumbnailItem.thumbnailRadius
  50. anchors.fill: thumbnailImage
  51. visible: false
  52. width: thumbnailImage.paintedWidth
  53. height: thumbnailImage.paintedHeight
  54. }
  55. OpacityMask {
  56. anchors.fill: thumbnailImage
  57. source: thumbnailImage
  58. maskSource: mask
  59. visible: model.thumbnail !== undefined
  60. }
  61. }
  62. }
  63. Image {
  64. id: activityIcon
  65. width: model.thumbnail !== undefined ? parent.width * 0.4 : thumbnailItem.imageWidth
  66. height: model.thumbnail !== undefined ? width : width * 0.9
  67. // Prevent bad access into unloaded item properties
  68. readonly property int thumbnailPaintedWidth: thumbnailImageLoader.item ? thumbnailImageLoader.item.paintedWidth : 0
  69. readonly property int thumbnailPaintedHeight: thumbnailImageLoader.item ? thumbnailImageLoader.item.paintedHeight : 0
  70. readonly property int negativeLeftMargin: -((width / 2) +
  71. ((width - paintedWidth) / 2) +
  72. ((thumbnailImageLoader.width - thumbnailItem.imageWidth) / 2) +
  73. ((thumbnailImageLoader.width - thumbnailPaintedWidth) / 2) +
  74. (thumbnailItem.thumbnailRadius / 4))
  75. readonly property int negativeTopMargin: -((height / 2) +
  76. ((height - paintedHeight) / 2) +
  77. ((thumbnailImageLoader.height - thumbnailItem.imageHeight) / 4) +
  78. ((thumbnailImageLoader.height - thumbnailPaintedHeight) / 4) +
  79. (thumbnailItem.thumbnailRadius / 4))
  80. anchors.verticalCenter: if(model.thumbnail === undefined) parent.verticalCenter
  81. anchors.left: model.thumbnail === undefined ? parent.left : thumbnailImageLoader.right
  82. anchors.leftMargin: if(model.thumbnail !== undefined) negativeLeftMargin
  83. anchors.top: if(model.thumbnail !== undefined) thumbnailImageLoader.bottom
  84. anchors.topMargin: if(model.thumbnail !== undefined) negativeTopMargin
  85. cache: true
  86. fillMode: Image.PreserveAspectFit
  87. source: Theme.darkMode ? model.darkIcon : model.lightIcon
  88. sourceSize.height: 64
  89. sourceSize.width: 64
  90. mipmap: true // Addresses grainy downscale
  91. }
  92. }
  93. ColumnLayout {
  94. id: activityContentLayout
  95. Layout.fillHeight: true
  96. Layout.fillWidth: true
  97. Layout.maximumWidth: root.width - Style.standardSpacing - root.iconSize
  98. implicitWidth: root.width - Style.standardSpacing - root.iconSize
  99. spacing: Style.smallSpacing
  100. RowLayout {
  101. Layout.fillWidth: true
  102. spacing: Style.trayHorizontalMargin
  103. EnforcedPlainTextLabel {
  104. id: activityTextTitle
  105. text: (root.activityData.type === "Activity" || root.activityData.type === "Notification") ? root.activityData.subject : root.activityData.message
  106. Layout.fillWidth: true
  107. Layout.alignment: Qt.AlignVCenter | Qt.AlignLeft
  108. elide: Text.ElideRight
  109. wrapMode: Text.Wrap
  110. maximumLineCount: 2
  111. font.pixelSize: Style.topLinePixelSize
  112. color: Style.ncTextColor
  113. visible: text !== ""
  114. NCToolTip {
  115. text: parent.text
  116. visible: parent.hovered
  117. }
  118. }
  119. Item {
  120. Layout.fillWidth: true
  121. Layout.leftMargin: -Style.trayHorizontalMargin
  122. }
  123. EnforcedPlainTextLabel {
  124. id: activityTextDateTime
  125. Layout.alignment: Qt.AlignVCenter | Qt.AlignRight
  126. height: (text === "") ? 0 : implicitHeight
  127. text: root.activityData.dateTime
  128. font.pixelSize: Style.subLinePixelSize
  129. color: Style.ncSecondaryTextColor
  130. visible: text !== ""
  131. }
  132. CustomButton {
  133. id: fileDetailsButton
  134. Layout.preferredWidth: Style.dismissButtonSize
  135. Layout.preferredHeight: Style.dismissButtonSize
  136. Layout.alignment: Qt.AlignTop | Qt.AlignRight
  137. icon.source: "image://svgimage-custom-color/more.svg/" + Style.ncTextColor
  138. NCToolTip {
  139. text: qsTr("Open file details")
  140. visible: parent.hovered
  141. }
  142. display: Button.IconOnly
  143. leftPadding: 0
  144. rightPadding: 0
  145. bgColor: Style.lightHover
  146. bgNormalOpacity: 0
  147. visible: model.showFileDetails
  148. onClicked: Systray.presentShareViewInTray(model.openablePath)
  149. }
  150. CustomButton {
  151. id: dismissActionButton
  152. Layout.preferredWidth: Style.dismissButtonSize
  153. Layout.preferredHeight: Style.dismissButtonSize
  154. Layout.alignment: Qt.AlignVCenter | Qt.AlignRight
  155. visible: root.showDismissButton && !fileDetailsButton.visible
  156. icon.source: "image://svgimage-custom-color/clear.svg/" + Style.ncTextColor
  157. display: Button.IconOnly
  158. leftPadding: 0
  159. rightPadding: 0
  160. bgColor: Style.lightHover
  161. bgNormalOpacity: 0
  162. NCToolTip {
  163. text: qsTr("Dismiss")
  164. visible: parent.hovered
  165. }
  166. onClicked: root.dismissButtonClicked()
  167. }
  168. }
  169. RowLayout {
  170. Layout.fillWidth: true
  171. Layout.fillHeight: true
  172. spacing: Style.trayHorizontalMargin
  173. visible: activityTextInfo.visible || talkReplyMessageSent.visible || activityActions.visible
  174. EnforcedPlainTextLabel {
  175. id: activityTextInfo
  176. Layout.fillWidth: true
  177. Layout.fillHeight: true
  178. Layout.alignment: Qt.AlignTop | Qt.AlignLeft
  179. text: (root.activityData.type === "Sync") ? root.activityData.displayPath
  180. : (root.activityData.type === "File") ? root.activityData.subject
  181. : (root.activityData.type === "Notification") ? root.activityData.message
  182. : ""
  183. height: (text === "") ? 0 : implicitHeight
  184. elide: Text.ElideRight
  185. wrapMode: Text.Wrap
  186. maximumLineCount: 2
  187. font.pixelSize: Style.subLinePixelSize
  188. color: Style.ncTextColor
  189. visible: text !== ""
  190. }
  191. Item {
  192. Layout.fillWidth: true
  193. }
  194. EnforcedPlainTextLabel {
  195. id: talkReplyMessageSent
  196. height: (text === "") ? 0 : implicitHeight
  197. width: parent.width
  198. Layout.alignment: Qt.AlignTop | Qt.AlignRight
  199. text: root.activityData.messageSent
  200. elide: Text.ElideRight
  201. wrapMode: Text.Wrap
  202. maximumLineCount: 2
  203. font.pixelSize: Style.topLinePixelSize
  204. color: Style.ncSecondaryTextColor
  205. visible: text !== ""
  206. }
  207. ActivityItemActions {
  208. id: activityActions
  209. visible: !isFileActivityList && activityData.linksForActionButtons.length > 0 && !isTalkReplyOptionVisible
  210. Layout.fillWidth: true
  211. Layout.leftMargin: Style.trayListItemIconSize + Style.trayHorizontalMargin
  212. Layout.preferredHeight: Style.standardPrimaryButtonHeight
  213. Layout.alignment: Qt.AlignTop | Qt.AlignRight
  214. displayActions: activityData.displayActions
  215. objectType: activityData.objectType
  216. linksForActionButtons: activityData.linksForActionButtons
  217. linksContextMenu: activityData.linksContextMenu
  218. maxActionButtons: activityModel.maxActionButtons
  219. onTriggerAction: activityModel.slotTriggerAction(model.activityIndex, actionIndex)
  220. onShowReplyField: isTalkReplyOptionVisible = true
  221. }
  222. }
  223. }
  224. }