FileDetailsPage.qml 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270
  1. /*
  2. * Copyright (C) 2022 by Claudio Cambra <claudio.cambra@nextcloud.com>
  3. *
  4. * This program is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation; either version 2 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful, but
  10. * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
  11. * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
  12. * for more details.
  13. */
  14. import QtQuick 2.15
  15. import QtQuick.Layouts 1.15
  16. import QtQuick.Controls 2.15
  17. import com.nextcloud.desktopclient 1.0
  18. import Style 1.0
  19. import "../tray"
  20. Page {
  21. id: root
  22. signal closeButtonClicked
  23. property var accountState: ({})
  24. property string localPath: ""
  25. // We want the SwipeView to "spill" over the edges of the window to really
  26. // make it look nice. If we apply page-wide padding, however, the swipe
  27. // contents only go as far as the page contents, clipped by the padding.
  28. // This property reflects the padding we intend to display, but not the real
  29. // padding, which we have to apply selectively to achieve our desired effect.
  30. property int intendedPadding: Style.standardSpacing * 2
  31. property int iconSize: 32
  32. property StackView rootStackView: StackView {}
  33. property bool showCloseButton: false
  34. property bool backgroundsVisible: true
  35. property FileDetails fileDetails: FileDetails {
  36. id: fileDetails
  37. localPath: root.localPath
  38. }
  39. Connections {
  40. target: Systray
  41. function onShowFileDetailsPage(fileLocalPath, page) {
  42. if(fileLocalPath === root.localPath) {
  43. switch(page) {
  44. case Systray.FileDetailsPage.Activity:
  45. swipeView.currentIndex = fileActivityView.swipeIndex;
  46. break;
  47. case Systray.FileDetailsPage.Sharing:
  48. swipeView.currentIndex = shareView.swipeIndex;
  49. break;
  50. }
  51. }
  52. }
  53. }
  54. topPadding: intendedPadding
  55. bottomPadding: intendedPadding
  56. background: Rectangle {
  57. color: palette.window
  58. visible: root.backgroundsVisible
  59. }
  60. header: ColumnLayout {
  61. spacing: root.intendedPadding
  62. GridLayout {
  63. id: headerGridLayout
  64. readonly property bool showFileLockedString: root.fileDetails.lockExpireString !== ""
  65. readonly property int textRightMargin: root.showCloseButton ? root.intendedPadding : 0
  66. Layout.fillWidth: parent
  67. Layout.topMargin: root.topPadding
  68. columns: root.showCloseButton ? 3 : 2
  69. rows: {
  70. let rows = 2;
  71. if (showFileLockedString) {
  72. rows++;
  73. }
  74. if (root.fileDetails.fileTagModel.totalTags > 0) {
  75. rows++;
  76. }
  77. return rows;
  78. }
  79. rowSpacing: Style.standardSpacing / 2
  80. columnSpacing: Style.standardSpacing
  81. Image {
  82. id: fileIcon
  83. Layout.rowSpan: headerGridLayout.rows
  84. Layout.preferredWidth: Style.trayListItemIconSize
  85. Layout.leftMargin: root.intendedPadding
  86. Layout.fillHeight: true
  87. verticalAlignment: Image.AlignVCenter
  88. horizontalAlignment: Image.AlignHCenter
  89. source: root.fileDetails.iconUrl
  90. sourceSize.width: Style.trayListItemIconSize
  91. sourceSize.height: Style.trayListItemIconSize
  92. fillMode: Image.PreserveAspectFit
  93. }
  94. EnforcedPlainTextLabel {
  95. id: fileNameLabel
  96. Layout.fillWidth: true
  97. Layout.rightMargin: headerGridLayout.textRightMargin
  98. text: root.fileDetails.name
  99. font.bold: true
  100. wrapMode: Text.Wrap
  101. }
  102. CustomButton {
  103. id: closeButton
  104. Layout.rowSpan: headerGridLayout.rows
  105. Layout.preferredWidth: Style.iconButtonWidth
  106. Layout.preferredHeight: width
  107. Layout.rightMargin: headerGridLayout.textRightMargin
  108. icon.source: "image://svgimage-custom-color/clear.svg" + "/" + palette.buttonText
  109. bgColor: palette.highlight
  110. bgNormalOpacity: 0
  111. toolTipText: qsTr("Dismiss")
  112. visible: root.showCloseButton
  113. onClicked: root.closeButtonClicked()
  114. }
  115. EnforcedPlainTextLabel {
  116. id: fileDetailsLabel
  117. Layout.fillWidth: true
  118. Layout.rightMargin: headerGridLayout.textRightMargin
  119. text: `${root.fileDetails.sizeString} · ${root.fileDetails.lastChangedString}`
  120. color: palette.midlight
  121. wrapMode: Text.Wrap
  122. }
  123. EnforcedPlainTextLabel {
  124. id: fileLockedLabel
  125. Layout.fillWidth: true
  126. Layout.rightMargin: headerGridLayout.textRightMargin
  127. text: root.fileDetails.lockExpireString
  128. color: palette.midlight
  129. wrapMode: Text.Wrap
  130. visible: headerGridLayout.showFileLockedString
  131. }
  132. Row {
  133. id: tagRow
  134. Layout.fillWidth: true
  135. Layout.rightMargin: headerGridLayout.textRightMargin
  136. Repeater {
  137. id: tagRepeater
  138. readonly property var fileTagModel: root.fileDetails.fileTagModel
  139. readonly property int maxTags: 3
  140. model: fileTagModel
  141. delegate: FileTag {
  142. readonly property int availableLayoutSpace: tagRow.width - tagRow.spacing - overflowTag.width
  143. readonly property int maxWidth: (availableLayoutSpace / tagRepeater.maxTags) - tagRow.spacing
  144. width: Math.min(maxWidth, implicitWidth)
  145. text: model.display
  146. }
  147. Component.onCompleted: fileTagModel.maxTags = 3
  148. }
  149. FileTag {
  150. id: overflowTag
  151. readonly property int totalFileTags: tagRepeater.fileTagModel.totalTags
  152. readonly property int maxFileTags: tagRepeater.fileTagModel.maxTags
  153. visible: totalFileTags > maxFileTags
  154. text: "+" + String(totalFileTags - maxFileTags)
  155. HoverHandler {
  156. id: hoverHandler
  157. }
  158. NCToolTip {
  159. visible: hoverHandler.hovered
  160. text: tagRepeater.fileTagModel.overflowTagsString
  161. }
  162. }
  163. }
  164. }
  165. TabBar {
  166. id: viewBar
  167. Layout.leftMargin: root.intendedPadding
  168. Layout.rightMargin: root.intendedPadding
  169. padding: 0
  170. NCTabButton {
  171. svgCustomColorSource: "image://svgimage-custom-color/activity.svg"
  172. text: qsTr("Activity")
  173. checked: swipeView.currentIndex === fileActivityView.swipeIndex
  174. onClicked: swipeView.currentIndex = fileActivityView.swipeIndex
  175. }
  176. NCTabButton {
  177. svgCustomColorSource: "image://svgimage-custom-color/share.svg"
  178. text: qsTr("Sharing")
  179. checked: swipeView.currentIndex === shareView.swipeIndex
  180. onClicked: swipeView.currentIndex = shareView.swipeIndex
  181. }
  182. }
  183. }
  184. SwipeView {
  185. id: swipeView
  186. anchors.fill: parent
  187. clip: true
  188. FileActivityView {
  189. id: fileActivityView
  190. property int swipeIndex: SwipeView.index
  191. delegateHorizontalPadding: root.intendedPadding
  192. accountState: root.accountState
  193. localPath: root.localPath
  194. iconSize: root.iconSize
  195. }
  196. ShareView {
  197. id: shareView
  198. property int swipeIndex: SwipeView.index
  199. accountState: root.accountState
  200. localPath: root.localPath
  201. fileDetails: root.fileDetails
  202. horizontalPadding: root.intendedPadding
  203. iconSize: root.iconSize
  204. rootStackView: root.rootStackView
  205. backgroundsVisible: root.backgroundsVisible
  206. }
  207. }
  208. }