Upload UI/code improvements

This commit is contained in:
miruka 2019-12-06 16:44:25 -04:00
parent 54df551b08
commit 4ada039384
6 changed files with 87 additions and 89 deletions

View File

@ -0,0 +1,3 @@
<svg height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg">
<path d="m16 16h-3v5h-2v-5h-3l4-4zm3.479-5.908c-.212-3.951-3.473-7.092-7.479-7.092s-7.267 3.141-7.479 7.092c-2.57.463-4.521 2.706-4.521 5.408 0 3.037 2.463 5.5 5.5 5.5h3.5v-2h-3.5c-1.93 0-3.5-1.57-3.5-3.5 0-2.797 2.479-3.833 4.433-3.72-.167-4.218 2.208-6.78 5.567-6.78 3.453 0 5.891 2.797 5.567 6.78 1.745-.046 4.433.751 4.433 3.72 0 1.93-1.57 3.5-3.5 3.5h-3.5v2h3.5c3.037 0 5.5-2.463 5.5-5.5 0-2.702-1.951-4.945-4.521-5.408z"/>
</svg>

After

Width:  |  Height:  |  Size: 524 B

View File

@ -305,7 +305,11 @@ class MatrixClient(nio.AsyncClient):
except OSError as err: except OSError as err:
log.warning(f"Failed thumbnailing {path}: {err}") log.warning(f"Failed thumbnailing {path}: {err}")
else: else:
upload_item.status = UploadStatus.UploadingThumbnail thumb_name = f"{path.stem}_thumbnail{''.join(path.suffixes)}"
upload_item.status = UploadStatus.Uploading
upload_item.filepath = Path(thumb_name)
upload_item.total_size = len(thumb_data)
try: try:
thumb_url, _, thumb_crypt_dict = await self.upload( thumb_url, _, thumb_crypt_dict = await self.upload(
@ -317,7 +321,7 @@ class MatrixClient(nio.AsyncClient):
except MatrixError as err: except MatrixError as err:
log.warning(f"Failed uploading thumbnail {path}: {err}") log.warning(f"Failed uploading thumbnail {path}: {err}")
else: else:
upload_item.status = UploadStatus.CachingThumbnail upload_item.status = UploadStatus.Caching
await Thumbnail.from_bytes( await Thumbnail.from_bytes(
self.backend.media_cache, self.backend.media_cache,

View File

@ -107,8 +107,6 @@ class Member(ModelItem):
class UploadStatus(AutoStrEnum): class UploadStatus(AutoStrEnum):
Uploading = auto() Uploading = auto()
Caching = auto() Caching = auto()
UploadingThumbnail = auto()
CachingThumbnail = auto()
Error = auto() Error = auto()

View File

@ -29,7 +29,7 @@ HSplitView {
TransferList { TransferList {
Layout.fillWidth: true Layout.fillWidth: true
Layout.minimumHeight: implicitHeight Layout.minimumHeight: implicitHeight
Layout.preferredHeight: implicitHeight * uploadsCount Layout.preferredHeight: implicitHeight * transferCount
Layout.maximumHeight: chatSplitView.height / 6 Layout.maximumHeight: chatSplitView.height / 6
Behavior on Layout.preferredHeight { HNumberAnimation {} } Behavior on Layout.preferredHeight { HNumberAnimation {} }

View File

@ -5,29 +5,29 @@ import "../../utils.js" as Utils
HColumnLayout { HColumnLayout {
id: transfer id: transfer
width: uploadsList.width
property bool guiPaused: false property bool guiPaused: false
readonly property bool paused: model.status === "Paused" || guiPaused property int msLeft: model.time_left || 0
property int uploaded: model.uploaded
readonly property int speed: model.speed
readonly property int totalSize: model.total_size
readonly property string status: model.status
readonly property bool paused: status === "Paused" || guiPaused
Behavior on msLeft { HNumberAnimation { duration: 1000 } }
Behavior on uploaded { HNumberAnimation { duration: 1000 }}
Behavior on height { HNumberAnimation {} } Behavior on height { HNumberAnimation {} }
HRowLayout { HRowLayout {
HButton { HIcon {
icon.name: "upload-cancel" svgName: "uploading"
icon.color: theme.colors.negativeBackground colorize:
padded: false status === "Error" ? theme.colors.negativeBackground :
status === "Paused" ? theme.colors.middleBackground :
onClicked: { theme.icons.colorize
// Python might take a sec to cancel, but we want
// immediate visual feedback
transfer.height = 0
// Python will delete this model item on cancel
py.call(py.getattr(model.task, "cancel"))
}
Layout.preferredWidth: theme.baseElementsHeight Layout.preferredWidth: theme.baseElementsHeight
Layout.fillHeight: true Layout.fillHeight: true
@ -38,51 +38,33 @@ HColumnLayout {
elide: expand ? Text.ElideNone : Text.ElideRight elide: expand ? Text.ElideNone : Text.ElideRight
wrapMode: expand ? Text.Wrap : Text.NoWrap wrapMode: expand ? Text.Wrap : Text.NoWrap
color: model.status === "Error" ? color: status === "Error" ?
theme.colors.errorText : theme.colors.text theme.colors.errorText : theme.colors.text
text: text:
model.status === "Uploading" ? status === "Uploading" ? fileName :
qsTr("Uploading %1...").arg(fileName) :
model.status === "Caching" ? status === "Caching" ?
qsTr("Caching %1...").arg(fileName) : qsTr("Caching %1...").arg(fileName) :
model.status === "UploadingThumbnail" ?
qsTr("Uploading thumbnail for %1...").arg(fileName) :
model.status === "CachingThumbnail" ?
qsTr("Caching thumbnail for %1...").arg(fileName) :
model.status === "Error" ? (
model.error === "MatrixForbidden" ? model.error === "MatrixForbidden" ?
qsTr("Forbidden file type or quota exceeded: %1") qsTr("Forbidden file type or quota exceeded: %1")
.arg(fileName) : .arg(fileName) :
model.error === "MatrixTooLarge" ? model.error === "MatrixTooLarge" ?
qsTr("Too large for this server: %1") qsTr("Too large for this server: %1").arg(fileName) :
.arg(fileName) :
model.error === "IsADirectoryError" ? model.error === "IsADirectoryError" ?
qsTr("Can't upload folders, need a file: %1") qsTr("Can't upload folders, need a file: %1").arg(filePath) :
.arg(filePath) :
model.error === "FileNotFoundError" ? model.error === "FileNotFoundError" ?
qsTr("Non-existant file: %1") qsTr("Non-existant file: %1").arg(filePath) :
.arg(filePath) :
model.error === "PermissionError" ? model.error === "PermissionError" ?
qsTr("No permission to read this file: %1") qsTr("No permission to read this file: %1").arg(filePath) :
.arg(filePath) :
qsTr("Unknown error for %1: %2 - %3") qsTr("Unknown error for %1: %2 - %3")
.arg(filePath) .arg(filePath).arg(model.error).arg(model.error_args)
.arg(model.error)
.arg(model.error_args)
) :
qsTr("Invalid status for %1: %2")
.arg(fileName).arg(model.status)
topPadding: theme.spacing / 2 topPadding: theme.spacing / 2
bottomPadding: topPadding bottomPadding: topPadding
@ -92,7 +74,7 @@ HColumnLayout {
Layout.fillWidth: true Layout.fillWidth: true
property bool expand: model.status === "Error" property bool expand: status === "Error"
readonly property string fileName: readonly property string fileName:
model.filepath.split("/").slice(-1)[0] model.filepath.split("/").slice(-1)[0]
@ -111,32 +93,28 @@ HColumnLayout {
HSpacer {} HSpacer {}
HLabel { Repeater {
id: uploadCountLabel model: [
visible: Layout.preferredWidth > 0 msLeft ? qsTr("-%1").arg(Utils.formatDuration(msLeft)) : "",
text: qsTr("-%1 %2/s %3/%4")
.arg(model.time_left ?
Utils.formatDuration(msLeft) : "∞")
.arg(CppUtils.formattedBytes(model.speed))
.arg(CppUtils.formattedBytes(uploaded))
.arg(CppUtils.formattedBytes(model.total_size))
topPadding: theme.spacing / 2 speed ? qsTr("%1/s").arg(CppUtils.formattedBytes(speed)) : "",
bottomPadding: topPadding
qsTr("%1/%2").arg(CppUtils.formattedBytes(uploaded))
.arg(CppUtils.formattedBytes(totalSize)),
]
HLabel {
text: modelData
visible: text && Layout.preferredWidth > 0
leftPadding: theme.spacing / 1.5 leftPadding: theme.spacing / 1.5
rightPadding: leftPadding rightPadding: leftPadding
Layout.preferredWidth: Layout.preferredWidth:
model.status === "Uploading" ? implicitWidth : 0 status === "Uploading" ? implicitWidth : 0
property int msLeft: model.time_left || -1
property int uploaded: model.uploaded
Behavior on msLeft { HNumberAnimation { duration: 1000 } }
Behavior on uploaded { HNumberAnimation { duration: 1000 }}
Behavior on Layout.preferredWidth { HNumberAnimation {} } Behavior on Layout.preferredWidth { HNumberAnimation {} }
} }
}
HButton { HButton {
visible: Layout.preferredWidth > 0 visible: Layout.preferredWidth > 0
@ -160,7 +138,7 @@ HColumnLayout {
} }
Layout.preferredWidth: Layout.preferredWidth:
model.status === "Uploading" ? status === "Uploading" ?
theme.baseElementsHeight : 0 theme.baseElementsHeight : 0
Layout.fillHeight: true Layout.fillHeight: true
@ -168,8 +146,24 @@ HColumnLayout {
Behavior on Layout.preferredWidth { HNumberAnimation {} } Behavior on Layout.preferredWidth { HNumberAnimation {} }
} }
HButton {
icon.name: "upload-cancel"
icon.color: theme.colors.negativeBackground
padded: false
onClicked: {
// Python might take a sec to cancel, but we want
// immediate visual feedback
transfer.height = 0
// Python will delete this model item on cancel
py.call(py.getattr(model.task, "cancel"))
}
Layout.preferredWidth: theme.baseElementsHeight
Layout.fillHeight: true
}
TapHandler { TapHandler {
onTapped: if (model.status !== "Error") onTapped: if (status !== "Error")
statusLabel.expand = ! statusLabel.expand statusLabel.expand = ! statusLabel.expand
} }
} }
@ -177,13 +171,13 @@ HColumnLayout {
HProgressBar { HProgressBar {
id: progressBar id: progressBar
visible: Layout.maximumHeight !== 0 visible: Layout.maximumHeight !== 0
indeterminate: model.status !== "Uploading" indeterminate: status !== "Uploading"
value: model.uploaded value: uploaded
to: model.total_size to: totalSize
// TODO: bake this in hprogressbar // TODO: bake this in hprogressbar
foregroundColor: foregroundColor:
model.status === "Error" ? status === "Error" ?
theme.controls.progressBar.errorForeground : theme.controls.progressBar.errorForeground :
transfer.paused ? transfer.paused ?
@ -193,9 +187,8 @@ HColumnLayout {
Layout.fillWidth: true Layout.fillWidth: true
Layout.maximumHeight: Layout.maximumHeight:
model.status === "Error" && indeterminate ? 0 : -1 status === "Error" && indeterminate ? 0 : -1
Behavior on value { HNumberAnimation { duration: 1000 } }
Behavior on Layout.maximumHeight { HNumberAnimation {} } Behavior on Layout.maximumHeight { HNumberAnimation {} }
} }
} }

View File

@ -12,15 +12,15 @@ Rectangle {
property int delegateHeight: 0 property int delegateHeight: 0
readonly property var firstDelegate: readonly property var firstDelegate:
uploadsList.contentItem.visibleChildren[0] transferList.contentItem.visibleChildren[0]
readonly property alias uploadsCount: uploadsList.count readonly property alias transferCount: transferList.count
Behavior on implicitHeight { HNumberAnimation {} } Behavior on implicitHeight { HNumberAnimation {} }
HListView { HListView {
id: uploadsList id: transferList
anchors.fill: parent anchors.fill: parent
model: HListModel { model: HListModel {
@ -28,6 +28,6 @@ Rectangle {
source: modelSources[["Upload", chatPage.roomId]] || [] source: modelSources[["Upload", chatPage.roomId]] || []
} }
delegate: Transfer { width: uploadsList.width } delegate: Transfer { width: transferList.width }
} }
} }