Merge pull request #327 from jgibbon/feature/messageContent_fileinfo_items
Add TDLibImage/TDLibThumbnail; rework Audio/VoiceNote/Document
This commit is contained in:
commit
32f884e547
26 changed files with 666 additions and 697 deletions
|
@ -61,6 +61,8 @@ DISTFILES += qml/harbour-fernschreiber.qml \
|
|||
qml/components/ReplyMarkupButtons.qml \
|
||||
qml/components/StickerPicker.qml \
|
||||
qml/components/PhotoTextsListItem.qml \
|
||||
qml/components/TDLibImage.qml \
|
||||
qml/components/TDLibThumbnail.qml \
|
||||
qml/components/VoiceNoteOverlay.qml \
|
||||
qml/components/chatInformationPage/ChatInformationEditArea.qml \
|
||||
qml/components/chatInformationPage/ChatInformationPageContent.qml \
|
||||
|
@ -91,6 +93,7 @@ DISTFILES += qml/harbour-fernschreiber.qml \
|
|||
qml/components/messageContent/MessageAnimation.qml \
|
||||
qml/components/messageContent/MessageAudio.qml \
|
||||
qml/components/messageContent/MessageContentBase.qml \
|
||||
qml/components/messageContent/MessageContentFileInfoBase.qml \
|
||||
qml/components/messageContent/MessageDocument.qml \
|
||||
qml/components/messageContent/MessageGame.qml \
|
||||
qml/components/messageContent/MessageLocation.qml \
|
||||
|
|
39
images/icon-m-copy-to-folder.svg
Normal file
39
images/icon-m-copy-to-folder.svg
Normal file
|
@ -0,0 +1,39 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xml:space="preserve"
|
||||
style="enable-background:new 0 0 64 64;"
|
||||
viewBox="0 0 64 64"
|
||||
y="0px"
|
||||
x="0px"
|
||||
id="Layer_1"
|
||||
version="1.1"><metadata
|
||||
id="metadata17"><rdf:RDF><cc:Work
|
||||
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
|
||||
id="defs15">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</defs>
|
||||
|
||||
<path
|
||||
style="fill:#ffffff"
|
||||
d="m 37.855477,15.759299 c -1.73926,0.0029 -4.47725,1.553014 -6.64098,2.8829 -1.6826,1.034172 -3.75291,1.108852 -5.69886,1.124912 h -8.64063 c -1.034,0 -1.875,0.841 -1.875,1.875 v 8.070312 l 2,1.359376 v -9.304688 h 8.51563 c 2.75742,-0.06081 4.84074,-0.2051 6.5836,-1.513027 2.1377,-1.604239 4.80361,-2.501457 7.17616,-2.486973 h 18.51758 c 0.666,0 1.20703,0.541031 1.20703,1.207031 v 31.542969 c 0,0.689 -0.561,1.25 -1.25,1.25 h -39.5 c -0.689,0 -1.25,-0.561 -1.25,-1.25 V 42.08547 l -2,1.359375 v 7.072266 c 0,1.792 1.458,3.25 3.25,3.25 h 39.5 c 1.792,0 3.25,-1.458 3.25,-3.25 V 18.974142 c 0,-1.769 -1.43803,-3.207984 -3.20703,-3.208984 h -18.51758 c -0.4765,0 -0.94899,-0.01047 -1.41992,-0.0059 z"
|
||||
id="path6-9" /><path
|
||||
id="path11-6"
|
||||
d="m 12.995027,29.476688 10.626,7.222 -10.626,7.222 v -14.444 m -2,-1.778 v 18 c 0,1.1 0.744,1.494 1.654,0.876 l 12.875,-8.752 c 0.455,-0.309 0.682,-0.717 0.682,-1.124 0,-0.408 -0.227,-0.815 -0.682,-1.124 l -12.875,-8.751 c -0.91,-0.619 -1.654,-0.225 -1.654,0.875 z"
|
||||
style="fill:#ffffff" /><path
|
||||
id="path5-0"
|
||||
d="m 15.000437,21.683979 v -6.5 c 0,-1.832003 1.6,-3.500003 3.357,-3.500003 h 10.636 c 1.967,0 3.809,0.854 4.848,2.238003 l 3.457,2.756 c -2.99546,1.819905 -4.21018,2.916329 -6.43718,3.672261 -5.13259,1.742208 -10.47736,1.018549 -15.86082,1.333739 z"
|
||||
style="opacity:0.6;fill:#ffffff" /><path
|
||||
id="path9-3-6"
|
||||
d="m 3.3670166,11.247132 c -0.004,1.278302 0.0179,17.502612 0.0179,17.502612 v 0.0059 0.0059 c 0.0626,4.141039 2.28159,6.407836 4.41211,7.382812 2.13052,0.974976 4.2070304,0.853516 4.2070304,0.853516"
|
||||
style="color:#000000;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:2;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none" /></svg>
|
After Width: | Height: | Size: 2.4 KiB |
55
qml/components/TDLibImage.qml
Normal file
55
qml/components/TDLibImage.qml
Normal file
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
Copyright (C) 2020 Sebastian J. Wolf and other contributors
|
||||
|
||||
This file is part of Fernschreiber.
|
||||
|
||||
Fernschreiber is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Fernschreiber is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fernschreiber. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
import QtQuick 2.6
|
||||
import WerkWolf.Fernschreiber 1.0
|
||||
import Sailfish.Silica 1.0
|
||||
|
||||
import "../js/debug.js" as Debug
|
||||
|
||||
Image {
|
||||
id: tdLibImage
|
||||
property alias fileInformation: file.fileInformation
|
||||
readonly property alias file: file
|
||||
property bool highlighted
|
||||
|
||||
asynchronous: true
|
||||
enabled: !!file.fileId
|
||||
fillMode: Image.PreserveAspectCrop
|
||||
clip: true
|
||||
opacity: status === Image.Ready ? 1.0 : 0.0
|
||||
source: enabled && file.isDownloadingCompleted ? file.path : ""
|
||||
visible: opacity > 0
|
||||
sourceSize {
|
||||
width: width
|
||||
height: height
|
||||
}
|
||||
|
||||
Behavior on opacity { FadeAnimation {} }
|
||||
|
||||
layer {
|
||||
enabled: tdLibImage.enabled && tdLibImage.highlighted
|
||||
effect: PressEffect { source: tdLibImage }
|
||||
}
|
||||
|
||||
TDLibFile {
|
||||
id: file
|
||||
autoLoad: true
|
||||
tdlib: tdLibWrapper
|
||||
}
|
||||
}
|
129
qml/components/TDLibThumbnail.qml
Normal file
129
qml/components/TDLibThumbnail.qml
Normal file
|
@ -0,0 +1,129 @@
|
|||
/*
|
||||
Copyright (C) 2020 Sebastian J. Wolf and other contributors
|
||||
|
||||
This file is part of Fernschreiber.
|
||||
|
||||
Fernschreiber is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Fernschreiber is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fernschreiber. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
import QtQuick 2.6
|
||||
import Sailfish.Silica 1.0
|
||||
import Nemo.Thumbnailer 1.0
|
||||
|
||||
Item {
|
||||
id: tdlibThumbnail
|
||||
/*
|
||||
Optional thumbnail, usually as property "thumbnail".
|
||||
The following TDLib objects can have it:
|
||||
- animation
|
||||
- audio (as "album_cover_thumbnail")
|
||||
- document
|
||||
- sticker (no minithumbnail)
|
||||
- video
|
||||
- videoNote
|
||||
- stickerSet (no minithumbnail)
|
||||
- stickerSetInfo (no minithumbnail)
|
||||
- inlineQueryResultArticle (no minithumbnail)
|
||||
- inlineQueryResultContact (no minithumbnail)
|
||||
- inlineQueryResultLocation (no minithumbnail)
|
||||
- inlineQueryResultVenue (no minithumbnail)
|
||||
*/
|
||||
property var thumbnail
|
||||
/*
|
||||
Optional minithumbnail, usually as property "minithumbnail".
|
||||
Has data inline: If present, it doesn't need another request.
|
||||
The following TDLib objects can have it:
|
||||
- animation
|
||||
- audio (as "album_cover_minithumbnail")
|
||||
- document
|
||||
- photo / chatPhoto (Note: No thumbnail, so not applicable here)
|
||||
- video
|
||||
- videoNote
|
||||
*/
|
||||
property var minithumbnail
|
||||
property bool useBackgroundImage: true
|
||||
property bool highlighted
|
||||
|
||||
property bool isVideo: !!thumbnail && thumbnail.format["@type"] === "thumbnailFormatMpeg4"
|
||||
property string videoMimeType: "video/mp4"
|
||||
|
||||
readonly property bool hasVisibleThumbnail: thumbnailImage.opacity !== 1.0
|
||||
&& !(videoThumbnailLoader.item && videoThumbnailLoader.item.opacity === 1.0)
|
||||
|
||||
layer {
|
||||
enabled: highlighted
|
||||
effect: PressEffect { source: tdlibThumbnail }
|
||||
}
|
||||
|
||||
Loader {
|
||||
id: backgroundLoader
|
||||
anchors.fill: parent
|
||||
active: !parent.hasVisibleThumbnail
|
||||
asynchronous: true
|
||||
sourceComponent: !!parent.minithumbnail ? miniThumbnailComponent : parent.useBackgroundImage ? backgroundImageComponent : ""
|
||||
Component {
|
||||
id: backgroundImageComponent
|
||||
BackgroundImage {}
|
||||
}
|
||||
Component {
|
||||
id: miniThumbnailComponent
|
||||
Image {
|
||||
clip: true
|
||||
asynchronous: true
|
||||
fillMode: Image.PreserveAspectCrop
|
||||
opacity: status === Image.Ready ? 1.0 : 0.0
|
||||
smooth: false
|
||||
source: "data:image/jpg;base64," + tdlibThumbnail.miniThumbnail.data
|
||||
visible: opacity > 0
|
||||
Behavior on opacity { FadeAnimation {} }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// image thumbnail
|
||||
TDLibImage {
|
||||
id: thumbnailImage
|
||||
anchors.fill: parent
|
||||
enabled: !parent.isVideo
|
||||
fileInformation: tdlibThumbnail.thumbnail ? tdlibThumbnail.thumbnail.file : {}
|
||||
onStatusChanged: { //TODO check if this is really how it is ;)
|
||||
if(status === Image.Error) {
|
||||
// in some cases, webp is used (without correct mime type).
|
||||
// we just try it blindly and cross our fingers:
|
||||
tdlibThumbnail.videoMimeType = "image/webp";
|
||||
tdlibThumbnail.isVideo = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback for video thumbnail format: try to use Nemo.Thumbnailer
|
||||
Loader {
|
||||
id: videoThumbnailLoader
|
||||
active: parent.isVideo
|
||||
asynchronous: true
|
||||
anchors.fill: parent
|
||||
sourceComponent: Component {
|
||||
id: videoThumbnail
|
||||
Thumbnail {
|
||||
id: thumbnail
|
||||
source: thumbnailImage.file.path
|
||||
sourceSize.width: width
|
||||
sourceSize.height: height
|
||||
mimeType: tdlibThumbnail.videoMimeType
|
||||
visible: opacity > 0
|
||||
opacity: status === Thumbnail.Ready ? 1.0 : 0.0
|
||||
Behavior on opacity { FadeAnimation {} }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -20,455 +20,77 @@ import QtQuick 2.6
|
|||
import Sailfish.Silica 1.0
|
||||
import QtMultimedia 5.6
|
||||
import "../"
|
||||
import "../../js/twemoji.js" as Emoji
|
||||
import "../../js/functions.js" as Functions
|
||||
import "../../js/debug.js" as Debug
|
||||
|
||||
|
||||
MessageContentBase {
|
||||
id: audioMessageComponent
|
||||
MessageContentFileInfoBase {
|
||||
id: contentItem
|
||||
|
||||
property var audioData: ( rawMessage.content['@type'] === "messageVoiceNote" ) ? rawMessage.content.voice_note : ( ( rawMessage.content['@type'] === "messageAudio" ) ? rawMessage.content.audio : "");
|
||||
property string audioUrl;
|
||||
property int previewFileId;
|
||||
property int audioFileId;
|
||||
property bool onScreen: messageListItem ? messageListItem.page.status === PageStatus.Active : true
|
||||
property string audioType : "voiceNote";
|
||||
fileInformation: rawMessage.content.audio.audio
|
||||
thumbnail: rawMessage.content.audio.album_cover_thumbnail
|
||||
minithumbnail: rawMessage.content.audio.album_cover_minithumbnail
|
||||
|
||||
height: width / 2
|
||||
primaryText: Emoji.emojify(rawMessage.content.audio.performer, primaryLabel.font.pixelSize)
|
||||
secondaryText: Emoji.emojify(rawMessage.content.audio.title, secondaryLabel.font.pixelSize)
|
||||
tertiaryLabel.visible: (duration || (audioPlayer.duration/1000)) > 0
|
||||
tertiaryText: (audioPlayer.position > 0 || audioPlayer.playbackState === Audio.PlayingState ? (Format.formatDuration(audioPlayer.position/1000, Formatter.DurationShort)+" / ") : "") + Format.formatDuration(contentItem.duration > 0 ? contentItem.duration : (audioPlayer.duration/1000), Formatter.DurationShort)
|
||||
|
||||
function getTimeString(rawSeconds) {
|
||||
var minutes = Math.floor( rawSeconds / 60 );
|
||||
var seconds = rawSeconds - ( minutes * 60 );
|
||||
|
||||
if ( minutes < 10 ) {
|
||||
minutes = "0" + minutes;
|
||||
}
|
||||
if ( seconds < 10 ) {
|
||||
seconds = "0" + seconds;
|
||||
}
|
||||
return minutes + ":" + seconds;
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
updateAudioThumbnail();
|
||||
}
|
||||
|
||||
function updateAudioThumbnail() {
|
||||
if (audioData) {
|
||||
audioType = ( audioData['@type'] === "voiceNote" ) ? "voice" : "audio";
|
||||
audioFileId = audioData[audioType].id;
|
||||
if (typeof audioData.album_cover_thumbnail !== "undefined") {
|
||||
previewFileId = audioData.album_cover_thumbnail.file.id;
|
||||
if (audioData.album_cover_thumbnail.file.local.is_downloading_completed) {
|
||||
placeholderImage.source = audioData.album_cover_thumbnail.file.local.path;
|
||||
leftButton {
|
||||
icon.source: audioPlayer.playbackState === Audio.PlayingState || (file.isDownloadingActive && audioPlayer.autoPlay) ? "image://theme/icon-m-pause": "image://theme/icon-m-play"
|
||||
onClicked: {
|
||||
if(!file.isDownloadingCompleted && !file.isDownloadingActive) {
|
||||
file.load();
|
||||
audioPlayer.autoPlay = true;
|
||||
} else if(file.isDownloadingActive) {
|
||||
audioPlayer.autoPlay = false;
|
||||
file.cancel();
|
||||
} else if(file.isDownloadingCompleted) {
|
||||
//playPause
|
||||
if(audioPlayer.playbackState === Audio.PlayingState) {
|
||||
audioPlayer.pause();
|
||||
} else {
|
||||
tdLibWrapper.downloadFile(previewFileId);
|
||||
}
|
||||
} else {
|
||||
placeholderImage.source = "image://theme/icon-l-music?white";
|
||||
placeholderImage.width = Theme.itemSizeLarge
|
||||
placeholderImage.height = Theme.itemSizeLarge
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function handlePlay() {
|
||||
if (audioData[audioType].local.is_downloading_completed) {
|
||||
audioUrl = audioData[audioType].local.path;
|
||||
audioComponentLoader.active = true;
|
||||
} else {
|
||||
audioDownloadBusyIndicator.running = true;
|
||||
tdLibWrapper.downloadFile(audioFileId);
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: tdLibWrapper
|
||||
onFileUpdated: {
|
||||
if (typeof audioData === "object") {
|
||||
if (fileInformation.local.is_downloading_completed) {
|
||||
if (fileId === previewFileId) {
|
||||
audioData.album_cover_thumbnail.file = fileInformation;
|
||||
placeholderImage.source = fileInformation.local.path;
|
||||
}
|
||||
if (fileId === audioFileId) {
|
||||
audioDownloadBusyIndicator.running = false;
|
||||
audioData[audioType] = fileInformation;
|
||||
audioUrl = fileInformation.local.path;
|
||||
if (onScreen) {
|
||||
audioComponentLoader.active = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (fileId === audioFileId) {
|
||||
downloadingProgressBar.maximumValue = fileInformation.size;
|
||||
downloadingProgressBar.value = fileInformation.local.downloaded_size;
|
||||
audioPlayer.play();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Image {
|
||||
id: placeholderImage
|
||||
property int duration: rawMessage.content.audio.duration
|
||||
|
||||
Audio {
|
||||
id: audioPlayer
|
||||
source: file.isDownloadingCompleted ? file.path : ""
|
||||
autoPlay: false
|
||||
}
|
||||
|
||||
Slider {
|
||||
width: parent.width
|
||||
height: parent.height
|
||||
anchors.centerIn: parent
|
||||
asynchronous: true
|
||||
fillMode: Image.PreserveAspectCrop
|
||||
visible: status === Image.Ready ? true : false
|
||||
layer.enabled: audioMessageComponent.highlighted
|
||||
layer.effect: PressEffect { source: placeholderImage }
|
||||
}
|
||||
|
||||
BackgroundImage {
|
||||
id: backgroundImage
|
||||
visible: placeholderImage.status !== Image.Ready
|
||||
layer.enabled: audioMessageComponent.highlighted
|
||||
layer.effect: PressEffect { source: backgroundImage }
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: placeholderBackground
|
||||
color: "black"
|
||||
opacity: 0.3
|
||||
height: parent.height
|
||||
width: parent.width
|
||||
visible: playButton.visible
|
||||
}
|
||||
Label {
|
||||
visible: !!(audioData.performer || audioData.title)
|
||||
color: placeholderBackground.visible ? "white" : Theme.secondaryHighlightColor
|
||||
wrapMode: Text.Wrap
|
||||
anchors {
|
||||
fill: placeholderBackground
|
||||
margins: Theme.paddingSmall
|
||||
left: parent.left
|
||||
leftMargin: -Screen.width/16
|
||||
right: parent.right
|
||||
rightMargin: -Screen.width/16
|
||||
top: primaryItem.bottom
|
||||
topMargin: -height/3
|
||||
}
|
||||
text: audioData.performer + (audioData.performer && audioData.title ? " - " : "") + audioData.title
|
||||
font.pixelSize: Theme.fontSizeTiny
|
||||
}
|
||||
minimumValue: 0
|
||||
maximumValue: audioPlayer.duration ? audioPlayer.duration : 0.1
|
||||
stepSize: 1
|
||||
value: audioPlayer.position
|
||||
enabled: audioPlayer.seekable
|
||||
visible: file.isDownloadingCompleted && audioPlayer.playbackState === Audio.PlayingState || audioPlayer.playbackState === Audio.PausedState
|
||||
opacity: visible ? 1.0 : 0.0
|
||||
Behavior on opacity { FadeAnimation {} }
|
||||
height: visible ? implicitHeight : 0
|
||||
Behavior on height { NumberAnimation { duration: 200 } }
|
||||
|
||||
Column {
|
||||
width: parent.width
|
||||
height: downloadingProgressBar.height + audioControlRow.height
|
||||
anchors.centerIn: parent
|
||||
Row {
|
||||
id: audioControlRow
|
||||
width: parent.width
|
||||
height: Theme.iconSizeLarge
|
||||
Item {
|
||||
height: Theme.iconSizeLarge
|
||||
width: downloadItem.visible ? parent.width / 2 : parent.width
|
||||
IconButton {
|
||||
id: playButton
|
||||
anchors.centerIn: parent
|
||||
width: Theme.iconSizeLarge
|
||||
height: Theme.iconSizeLarge
|
||||
icon {
|
||||
source: "image://theme/icon-l-play?white"
|
||||
asynchronous: true
|
||||
}
|
||||
highlighted: audioMessageComponent.highlighted || down
|
||||
visible: placeholderImage.status === Image.Ready ? true : false
|
||||
onClicked: {
|
||||
handlePlay();
|
||||
}
|
||||
}
|
||||
BusyIndicator {
|
||||
id: audioDownloadBusyIndicator
|
||||
running: false
|
||||
visible: running
|
||||
anchors.centerIn: parent
|
||||
size: BusyIndicatorSize.Large
|
||||
}
|
||||
}
|
||||
Item {
|
||||
id: downloadItem
|
||||
width: parent.width / 2
|
||||
height: Theme.iconSizeLarge
|
||||
visible: audioData[audioType].local.is_downloading_completed
|
||||
Rectangle {
|
||||
color: Theme.primaryColor
|
||||
opacity: Theme.opacityFaint
|
||||
width: Theme.iconSizeLarge * 0.9
|
||||
height: Theme.iconSizeLarge * 0.9
|
||||
anchors.centerIn: parent
|
||||
radius: width / 2
|
||||
}
|
||||
|
||||
IconButton {
|
||||
id: downloadButton
|
||||
anchors.centerIn: parent
|
||||
width: Theme.iconSizeLarge
|
||||
height: Theme.iconSizeLarge
|
||||
icon {
|
||||
source: "image://theme/icon-m-cloud-download?white"
|
||||
asynchronous: true
|
||||
}
|
||||
highlighted: audioMessageComponent.highlighted || down
|
||||
onClicked: {
|
||||
tdLibWrapper.copyFileToDownloads(audioData[audioType].local.path);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ProgressBar {
|
||||
id: downloadingProgressBar
|
||||
minimumValue: 0
|
||||
maximumValue: 100
|
||||
value: 0
|
||||
visible: audioDownloadBusyIndicator.visible
|
||||
width: parent.width
|
||||
highlighted: contentItem.highlighted || down
|
||||
onReleased: {
|
||||
audioPlayer.seek(Math.floor(value));
|
||||
audioPlayer.play();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Rectangle {
|
||||
id: audioErrorShade
|
||||
width: parent.width
|
||||
height: parent.height
|
||||
color: "lightgrey"
|
||||
visible: placeholderImage.status === Image.Error ? true : false
|
||||
opacity: 0.3
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: errorTextOverlay
|
||||
color: "black"
|
||||
opacity: 0.8
|
||||
width: parent.width
|
||||
height: parent.height
|
||||
visible: false
|
||||
}
|
||||
|
||||
Text {
|
||||
id: errorText
|
||||
visible: false
|
||||
width: parent.width
|
||||
color: Theme.primaryColor
|
||||
font.pixelSize: Theme.fontSizeExtraSmall
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
}
|
||||
wrapMode: Text.Wrap
|
||||
text: ""
|
||||
}
|
||||
|
||||
Loader {
|
||||
id: audioComponentLoader
|
||||
active: false
|
||||
width: parent.width
|
||||
height: parent.height
|
||||
sourceComponent: audioComponent
|
||||
}
|
||||
|
||||
Component {
|
||||
id: audioComponent
|
||||
|
||||
Item {
|
||||
width: parent ? parent.width : 0
|
||||
height: parent ? parent.height : 0
|
||||
|
||||
Connections {
|
||||
target: messageAudio
|
||||
onPlaying: {
|
||||
playButton.visible = false;
|
||||
downloadItem.visible = false;
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: audioMessageComponent
|
||||
onClicked: {
|
||||
if (messageAudio.playbackState === MediaPlayer.PlayingState) {
|
||||
messageAudio.pause();
|
||||
timeLeftItem.visible = true;
|
||||
} else {
|
||||
messageAudio.play();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Audio {
|
||||
id: messageAudio
|
||||
|
||||
Component.onCompleted: {
|
||||
if (messageAudio.error === MediaPlayer.NoError) {
|
||||
messageAudio.play();
|
||||
} else {
|
||||
errorText.text = qsTr("Error loading audio! " + messageAudio.errorString)
|
||||
errorTextOverlay.visible = true;
|
||||
errorText.visible = true;
|
||||
}
|
||||
}
|
||||
|
||||
onStatusChanged: {
|
||||
if (status == MediaPlayer.NoMedia) {
|
||||
Debug.log("No Media");
|
||||
audioBusyIndicator.visible = false;
|
||||
}
|
||||
if (status == MediaPlayer.Loading) {
|
||||
Debug.log("Loading");
|
||||
audioBusyIndicator.visible = true;
|
||||
}
|
||||
if (status == MediaPlayer.Loaded) {
|
||||
Debug.log("Loaded");
|
||||
audioBusyIndicator.visible = false;
|
||||
}
|
||||
if (status == MediaPlayer.Buffering) {
|
||||
Debug.log("Buffering");
|
||||
audioBusyIndicator.visible = true;
|
||||
}
|
||||
if (status == MediaPlayer.Stalled) {
|
||||
Debug.log("Stalled");
|
||||
audioBusyIndicator.visible = true;
|
||||
}
|
||||
if (status == MediaPlayer.Buffered) {
|
||||
Debug.log("Buffered");
|
||||
audioBusyIndicator.visible = false;
|
||||
}
|
||||
if (status == MediaPlayer.EndOfMedia) {
|
||||
Debug.log("End of Media");
|
||||
audioBusyIndicator.visible = false;
|
||||
}
|
||||
if (status == MediaPlayer.InvalidMedia) {
|
||||
Debug.log("Invalid Media");
|
||||
audioBusyIndicator.visible = false;
|
||||
}
|
||||
if (status == MediaPlayer.UnknownStatus) {
|
||||
Debug.log("Unknown Status");
|
||||
audioBusyIndicator.visible = false;
|
||||
}
|
||||
}
|
||||
|
||||
source: audioUrl
|
||||
|
||||
onStopped: {
|
||||
playButton.visible = true;
|
||||
downloadItem.visible = true;
|
||||
audioComponentLoader.active = false;
|
||||
}
|
||||
}
|
||||
|
||||
BusyIndicator {
|
||||
id: audioBusyIndicator
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
visible: false
|
||||
running: visible
|
||||
size: BusyIndicatorSize.Medium
|
||||
}
|
||||
|
||||
Item {
|
||||
id: timeLeftItem
|
||||
width: parent.width
|
||||
height: parent.height
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
opacity: visible ? 1 : 0
|
||||
Behavior on opacity { NumberAnimation {} }
|
||||
|
||||
Rectangle {
|
||||
id: positionTextOverlay
|
||||
color: "black"
|
||||
opacity: 0.3
|
||||
width: parent.width
|
||||
height: parent.height
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
visible: pausedRow.visible
|
||||
}
|
||||
|
||||
Row {
|
||||
id: pausedRow
|
||||
width: parent.width
|
||||
height: parent.height - ( messageAudioSlider.visible ? messageAudioSlider.height : 0 ) - ( positionText.visible ? positionText.height : 0 )
|
||||
visible: audioComponentLoader.active && messageAudio.playbackState === MediaPlayer.PausedState
|
||||
Item {
|
||||
height: parent.height
|
||||
width: parent.width / 2
|
||||
IconButton {
|
||||
id: pausedPlayButton
|
||||
anchors.centerIn: parent
|
||||
width: Theme.iconSizeLarge
|
||||
height: Theme.iconSizeLarge
|
||||
highlighted: audioMessageComponent.highlighted || down
|
||||
icon {
|
||||
asynchronous: true
|
||||
source: "image://theme/icon-l-play?white"
|
||||
}
|
||||
onClicked: {
|
||||
messageAudio.play();
|
||||
}
|
||||
}
|
||||
}
|
||||
Item {
|
||||
id: pausedDownloadItem
|
||||
width: parent.width / 2
|
||||
height: parent.height
|
||||
Rectangle {
|
||||
color: Theme.primaryColor
|
||||
opacity: Theme.opacityFaint
|
||||
width: Theme.iconSizeLarge * 0.9
|
||||
height: Theme.iconSizeLarge * 0.9
|
||||
anchors.centerIn: parent
|
||||
radius: width / 2
|
||||
}
|
||||
|
||||
IconButton {
|
||||
id: pausedDownloadButton
|
||||
anchors.centerIn: parent
|
||||
width: Theme.iconSizeLarge
|
||||
height: Theme.iconSizeLarge
|
||||
icon {
|
||||
source: "image://theme/icon-m-cloud-download?white"
|
||||
asynchronous: true
|
||||
}
|
||||
highlighted: audioMessageComponent.highlighted || down
|
||||
onClicked: {
|
||||
tdLibWrapper.copyFileToDownloads(audioData[audioType].local.path);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Slider {
|
||||
id: messageAudioSlider
|
||||
width: parent.width
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.bottom: positionText.top
|
||||
minimumValue: 0
|
||||
maximumValue: messageAudio.duration ? messageAudio.duration : 0.1
|
||||
stepSize: 1
|
||||
value: messageAudio.position
|
||||
enabled: messageAudio.seekable
|
||||
visible: (messageAudio.duration > 0)
|
||||
highlighted: audioMessageComponent.highlighted || down
|
||||
onReleased: {
|
||||
messageAudio.seek(Math.floor(value));
|
||||
messageAudio.play();
|
||||
}
|
||||
valueText: getTimeString(Math.round((messageAudio.duration - messageAudioSlider.value) / 1000))
|
||||
}
|
||||
|
||||
Text {
|
||||
id: positionText
|
||||
visible: messageAudio.duration === 0
|
||||
color: Theme.primaryColor
|
||||
font.pixelSize: Theme.fontSizeTiny
|
||||
anchors {
|
||||
bottom: parent.bottom
|
||||
bottomMargin: Theme.paddingSmall
|
||||
horizontalCenter: positionTextOverlay.horizontalCenter
|
||||
}
|
||||
wrapMode: Text.Wrap
|
||||
text: ( messageAudio.duration - messageAudio.position ) > 0 ? getTimeString(Math.round((messageAudio.duration - messageAudio.position) / 1000)) : "-:-"
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
201
qml/components/messageContent/MessageContentFileInfoBase.qml
Normal file
201
qml/components/messageContent/MessageContentFileInfoBase.qml
Normal file
|
@ -0,0 +1,201 @@
|
|||
/*
|
||||
Copyright (C) 2020 Sebastian J. Wolf and other contributors
|
||||
|
||||
This file is part of Fernschreiber.
|
||||
|
||||
Fernschreiber is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Fernschreiber is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fernschreiber. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
import QtQuick 2.6
|
||||
import Sailfish.Silica 1.0
|
||||
import QtMultimedia 5.6
|
||||
import WerkWolf.Fernschreiber 1.0
|
||||
import QtGraphicalEffects 1.0
|
||||
import "../"
|
||||
import "../../js/functions.js" as Functions
|
||||
import "../../js/twemoji.js" as Emoji
|
||||
import "../../js/debug.js" as Debug
|
||||
|
||||
MessageContentBase {
|
||||
id: contentItem
|
||||
height: childrenRect.height
|
||||
property alias fileInformation: file.fileInformation
|
||||
property alias primaryLabel: primaryLabel
|
||||
property alias primaryText: primaryLabel.text
|
||||
property alias secondaryLabel: secondaryLabel
|
||||
property alias secondaryText: secondaryLabel.text
|
||||
property alias tertiaryLabel: tertiaryLabel
|
||||
property alias tertiaryText: tertiaryLabel.text
|
||||
property var thumbnail
|
||||
property var minithumbnail
|
||||
|
||||
readonly property alias file: file
|
||||
readonly property alias primaryItem: primaryItem
|
||||
readonly property alias leftButton: leftButton
|
||||
readonly property alias labelsColumn: labelsColumn
|
||||
readonly property alias copyButton: copyButton
|
||||
// readonly property alias downloadNeededIndicatorIcon: downloadNeededIndicatorIcon
|
||||
|
||||
TDLibFile {
|
||||
id: file
|
||||
tdlib: tdLibWrapper
|
||||
autoLoad: false
|
||||
}
|
||||
|
||||
Item {
|
||||
id: primaryItem
|
||||
width: parent.width
|
||||
height: Theme.itemSizeLarge
|
||||
Loader {
|
||||
active: contentItem.thumbnail || contentItem.minithumbnail
|
||||
visible: active
|
||||
anchors.fill: leftButton
|
||||
sourceComponent: Component {
|
||||
TDLibThumbnail {
|
||||
opacity: 0.3
|
||||
thumbnail: contentItem.thumbnail
|
||||
minithumbnail: contentItem.minithumbnail
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
IconButton {
|
||||
id: leftButton
|
||||
highlighted: down || contentItem.highlighted
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
icon {
|
||||
asynchronous: true
|
||||
}
|
||||
|
||||
ProgressCircle {
|
||||
value: file.downloadedSize / file.expectedSize
|
||||
progressColor: Theme.highlightColor
|
||||
backgroundColor: Theme.highlightDimmerColor
|
||||
width: Theme.iconSizeMedium
|
||||
height: Theme.iconSizeMedium
|
||||
visible: opacity > 0
|
||||
opacity: file.isDownloadingActive ? 1.0 : 0.0
|
||||
anchors.centerIn: parent
|
||||
Behavior on opacity { FadeAnimation {} }
|
||||
}
|
||||
Rectangle {
|
||||
anchors.centerIn: downloadNeededIndicatorIcon
|
||||
width: downloadNeededIndicatorIcon.width + Theme.paddingMedium
|
||||
height: width
|
||||
|
||||
color: Theme.rgba(Theme.overlayBackgroundColor, 0.2)
|
||||
opacity: file.isDownloadingActive ? 1.0 : 0.0
|
||||
Behavior on opacity { FadeAnimation {} }
|
||||
visible: opacity > 0
|
||||
radius: width/2
|
||||
}
|
||||
|
||||
Icon {
|
||||
id: downloadNeededIndicatorIcon
|
||||
source: file.isDownloadingActive || file.isDownloadingCompleted ? "image://theme/icon-s-clear-opaque-cross" : "image://theme/icon-s-cloud-download"
|
||||
asynchronous: true
|
||||
width: Theme.iconSizeExtraSmall
|
||||
height: width
|
||||
visible: opacity > 0
|
||||
sourceSize.width: width
|
||||
sourceSize.height: height
|
||||
opacity: file.isDownloadingCompleted ? 0.0 : 1.0
|
||||
Behavior on opacity { FadeAnimation {} }
|
||||
anchors {
|
||||
right: parent.right
|
||||
bottom: parent.bottom
|
||||
margins: Theme.paddingSmall
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Column {
|
||||
id: labelsColumn
|
||||
anchors {
|
||||
left: leftButton.right
|
||||
leftMargin: Theme.paddingSmall
|
||||
right: copyButton.left
|
||||
verticalCenter: leftButton.verticalCenter
|
||||
}
|
||||
|
||||
Label {
|
||||
id: primaryLabel
|
||||
width: parent.width
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
fontSizeMode: Text.HorizontalFit
|
||||
minimumPixelSize: Theme.fontSizeTiny
|
||||
color: Theme.highlightColor
|
||||
visible: text.length > 0
|
||||
truncationMode: TruncationMode.Fade
|
||||
}
|
||||
|
||||
Label {
|
||||
id: secondaryLabel
|
||||
width: parent.width
|
||||
font.pixelSize: Theme.fontSizeExtraSmall
|
||||
fontSizeMode: Text.HorizontalFit
|
||||
minimumPixelSize: Theme.fontSizeTiny
|
||||
color: Theme.secondaryHighlightColor
|
||||
visible: text.length > 0
|
||||
truncationMode: TruncationMode.Fade
|
||||
}
|
||||
Item {
|
||||
height: sizeLabel.height
|
||||
width: parent.width
|
||||
Label {
|
||||
id: tertiaryLabel
|
||||
font.pixelSize: Theme.fontSizeTiny
|
||||
color: highlighted ? Theme.secondaryHighlightColor : Theme.secondaryColor
|
||||
visible: text.length > 0
|
||||
truncationMode: TruncationMode.Fade
|
||||
}
|
||||
Label {
|
||||
id: sizeLabel
|
||||
anchors.right: parent.right
|
||||
font.pixelSize: Theme.fontSizeTiny
|
||||
color: tertiaryLabel.color
|
||||
text: Format.formatFileSize(file.size || file.expectedSize)
|
||||
visible: (file.size || file.expectedSize) > 0
|
||||
truncationMode: TruncationMode.Fade
|
||||
}
|
||||
}
|
||||
}
|
||||
IconButton {
|
||||
id: copyButton
|
||||
anchors {
|
||||
right: parent.right
|
||||
verticalCenter: parent.verticalCenter
|
||||
}
|
||||
opacity: file.isDownloadingCompleted ? 1.0 : 0.0
|
||||
width: file.isDownloadingCompleted ? Theme.itemSizeMedium : 0
|
||||
visible: opacity > 0
|
||||
|
||||
Behavior on opacity { FadeAnimation {} }
|
||||
Behavior on width { NumberAnimation { duration: 200 } }
|
||||
icon {
|
||||
asynchronous: true
|
||||
source: "../../../images/icon-m-copy-to-folder.svg"
|
||||
sourceSize {
|
||||
width: Theme.iconSizeMedium
|
||||
height: Theme.iconSizeMedium
|
||||
}
|
||||
}
|
||||
onClicked: {
|
||||
tdLibWrapper.copyFileToDownloads(file.path);
|
||||
// not persistent:
|
||||
opacity = 0;
|
||||
width = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -18,108 +18,65 @@
|
|||
*/
|
||||
import QtQuick 2.6
|
||||
import Sailfish.Silica 1.0
|
||||
import "../../js/twemoji.js" as Emoji
|
||||
|
||||
MessageContentBase {
|
||||
MessageContentFileInfoBase {
|
||||
id: contentItem
|
||||
fileInformation: rawMessage.content.document.document
|
||||
|
||||
id: documentPreviewItem
|
||||
height: Theme.itemSizeLarge
|
||||
primaryText: Emoji.emojify(rawMessage.content.document.file_name || "", primaryLabel.font.pixelSize)
|
||||
secondaryText: Emoji.emojify(Functions.enhanceMessageText(rawMessage.content.caption) || "", secondaryLabel.font.pixelSize)
|
||||
|
||||
property var documentData: rawMessage.content.document
|
||||
property bool openRequested: false;
|
||||
minithumbnail: rawMessage.content.document.minithumbnail
|
||||
thumbnail: rawMessage.content.document.thumbnail
|
||||
|
||||
Component.onCompleted: {
|
||||
updateDocument();
|
||||
}
|
||||
|
||||
function updateDocument() {
|
||||
if (documentData) {
|
||||
if (documentData.document.local.is_downloading_completed) {
|
||||
downloadDocumentButton.visible = false;
|
||||
openDocumentArea.visible = true;
|
||||
} else {
|
||||
openDocumentArea.visible = false;
|
||||
downloadDocumentButton.visible = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: tdLibWrapper
|
||||
onFileUpdated: {
|
||||
if (documentData) {
|
||||
if (!fileInformation.remote.is_uploading_active && fileId === documentData.document.id && fileInformation.local.is_downloading_completed) {
|
||||
downloadingProgressBar.visible = false;
|
||||
documentData.document = fileInformation;
|
||||
downloadDocumentButton.visible = false;
|
||||
openDocumentArea.visible = true;
|
||||
if (documentPreviewItem.openRequested) {
|
||||
documentPreviewItem.openRequested = false;
|
||||
tdLibWrapper.openFileOnDevice(documentData.document.local.path);
|
||||
}
|
||||
}
|
||||
if (fileId === documentData.document.id) {
|
||||
downloadingProgressBar.maximumValue = fileInformation.size;
|
||||
downloadingProgressBar.value = fileInformation.local.downloaded_size;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Button {
|
||||
id: downloadDocumentButton
|
||||
preferredWidth: Theme.buttonWidthMedium
|
||||
anchors.centerIn: parent
|
||||
text: qsTr("Download Document")
|
||||
visible: false
|
||||
highlighted: documentPreviewItem.highlighted || down
|
||||
leftButton {
|
||||
icon.source: Theme.iconForMimeType(rawMessage.content.document.mime_type)
|
||||
onClicked: {
|
||||
downloadDocumentButton.visible = false;
|
||||
downloadingProgressBar.visible = true;
|
||||
tdLibWrapper.downloadFile(documentData.document.id);
|
||||
if(file.isDownloadingCompleted) {
|
||||
// in this case, the MouseArea should take over
|
||||
tdLibWrapper.openFileOnDevice(file.path);
|
||||
} else if(!file.isDownloadingActive) {
|
||||
file.load();
|
||||
} else {
|
||||
file.cancel()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ProgressBar {
|
||||
id: downloadingProgressBar
|
||||
minimumValue: 0
|
||||
maximumValue: 100
|
||||
value: 0
|
||||
visible: false
|
||||
width: parent.width
|
||||
anchors.centerIn: parent
|
||||
}
|
||||
|
||||
Column {
|
||||
id: openDocumentArea
|
||||
visible: false
|
||||
spacing: Theme.paddingMedium
|
||||
width: parent.width
|
||||
|
||||
onVisibleChanged: {
|
||||
visible ? (documentPreviewItem.height = openDocumentArea.height) : (documentPreviewItem.height = Theme.itemSizeLarge);
|
||||
}
|
||||
|
||||
Button {
|
||||
id: openDocumentButton
|
||||
preferredWidth: Theme.buttonWidthMedium
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
text: qsTr("Open Document")
|
||||
highlighted: documentPreviewItem.highlighted || down
|
||||
onClicked: {
|
||||
documentPreviewItem.openRequested = true;
|
||||
tdLibWrapper.openFileOnDevice(documentData.document.local.path);
|
||||
states: [
|
||||
State {
|
||||
when: file.isDownloadingCompleted
|
||||
PropertyChanges { target: openMouseArea; enabled: true }
|
||||
PropertyChanges {
|
||||
target: primaryLabel
|
||||
color: (contentItem.highlighted || openMouseArea.pressed) ? Theme.highlightColor : Theme.primaryColor
|
||||
}
|
||||
PropertyChanges {
|
||||
target: secondaryLabel
|
||||
color: (contentItem.highlighted || openMouseArea.pressed) ? Theme.secondaryHighlightColor : Theme.secondaryColor
|
||||
}
|
||||
PropertyChanges {
|
||||
target: tertiaryLabel
|
||||
color: (contentItem.highlighted || openMouseArea.pressed) ? Theme.secondaryHighlightColor : Theme.secondaryColor
|
||||
}
|
||||
PropertyChanges {
|
||||
target: leftButton
|
||||
highlighted: contentItem.highlighted || openMouseArea.pressed
|
||||
}
|
||||
}
|
||||
|
||||
Button {
|
||||
id: copyDocumentButton
|
||||
preferredWidth: Theme.buttonWidthMedium
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
text: qsTr("Copy Document to Downloads")
|
||||
highlighted: documentPreviewItem.highlighted || down
|
||||
onClicked: {
|
||||
tdLibWrapper.copyFileToDownloads(documentData.document.local.path);
|
||||
}
|
||||
]
|
||||
MouseArea {
|
||||
id: openMouseArea
|
||||
enabled: file.isDownloadingCompleted
|
||||
visible: enabled
|
||||
anchors {
|
||||
fill: primaryItem
|
||||
rightMargin: copyButton.width
|
||||
}
|
||||
onClicked: {
|
||||
tdLibWrapper.openFileOnDevice(file.path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,7 +29,7 @@ MessageContentBase {
|
|||
|
||||
property string chatId: rawMessage.chat_id
|
||||
property var pictureFileInformation;
|
||||
height: width / 2
|
||||
height: width * 0.66666666;
|
||||
property string fileExtra
|
||||
|
||||
Component.onCompleted: {
|
||||
|
|
|
@ -18,4 +18,11 @@
|
|||
*/
|
||||
import QtQuick 2.6
|
||||
|
||||
MessageAudio {}
|
||||
MessageAudio {
|
||||
fileInformation: rawMessage.content.voice_note.voice
|
||||
primaryText: qsTr("Voice Note")
|
||||
secondaryText: ""
|
||||
duration: rawMessage.content.voice_note.duration
|
||||
thumbnail: null
|
||||
minithumbnail: null
|
||||
}
|
||||
|
|
|
@ -79,7 +79,7 @@ function getMessageText(message, simple, currentUserId, ignoreEntities) {
|
|||
}
|
||||
case 'messageDocument':
|
||||
if (message.content.document.file_name !== "") {
|
||||
return simple ? qsTr("Document: %1").arg(message.content.document.file_name) : (message.content.document.file_name + ( message.content.caption.text !== "" ? ("<br />" + enhanceMessageText(message.content.caption, ignoreEntities) ) : "")).trim();
|
||||
return simple ? qsTr("Document: %1").arg(message.content.document.file_name) : (message.content.caption.text !== "" ? enhanceMessageText(message.content.caption, ignoreEntities) : "").trim();
|
||||
} else {
|
||||
return simple ? (myself ? qsTr("sent a document", "myself") : qsTr("sent a document")) : "";
|
||||
}
|
||||
|
|
|
@ -1062,9 +1062,8 @@ Page {
|
|||
return Functions.getVideoHeight(parentWidth, content.video);
|
||||
case "messageAudio":
|
||||
case "messageVoiceNote":
|
||||
return Theme.itemSizeLarge;
|
||||
case "messageDocument":
|
||||
return Theme.itemSizeSmall;
|
||||
return Theme.itemSizeLarge;
|
||||
case "messageGame":
|
||||
return parentWidth * 0.66666666 + Theme.itemSizeLarge; // 2 / 3;
|
||||
case "messageLocation":
|
||||
|
|
|
@ -194,6 +194,16 @@ void TDLibFile::setAutoLoad(bool enableAutoLoad)
|
|||
}
|
||||
}
|
||||
|
||||
bool TDLibFile::cancel()
|
||||
{
|
||||
if (id && tdLibWrapper && is_downloading_active) {
|
||||
tdLibWrapper->cancelDownloadFile(id);
|
||||
tdLibWrapper->deleteFile(id);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool TDLibFile::load()
|
||||
{
|
||||
// Manual load ignores hold-off timer
|
||||
|
|
|
@ -78,6 +78,7 @@ public:
|
|||
bool isUploadingActive() const;
|
||||
bool isUploadingCompleted() const;
|
||||
|
||||
Q_INVOKABLE bool cancel();
|
||||
Q_INVOKABLE bool load();
|
||||
|
||||
signals:
|
||||
|
|
|
@ -1146,6 +1146,37 @@ void TDLibWrapper::sendBotStartMessage(qlonglong botUserId, qlonglong chatId, co
|
|||
this->sendRequest(requestObject);
|
||||
}
|
||||
|
||||
void TDLibWrapper::cancelDownloadFile(int fileId)
|
||||
{
|
||||
LOG("Cancel Download File" << fileId);
|
||||
QVariantMap requestObject;
|
||||
requestObject.insert(_TYPE, "cancelDownloadFile");
|
||||
requestObject.insert("file_id", fileId);
|
||||
requestObject.insert("only_if_pending", false);
|
||||
|
||||
this->sendRequest(requestObject);
|
||||
}
|
||||
|
||||
void TDLibWrapper::cancelUploadFile(int fileId)
|
||||
{
|
||||
LOG("Cancel Upload File" << fileId);
|
||||
QVariantMap requestObject;
|
||||
requestObject.insert(_TYPE, "cancelUploadFile");
|
||||
requestObject.insert("file_id", fileId);
|
||||
|
||||
this->sendRequest(requestObject);
|
||||
}
|
||||
|
||||
void TDLibWrapper::deleteFile(int fileId)
|
||||
{
|
||||
LOG("Delete cached File" << fileId);
|
||||
QVariantMap requestObject;
|
||||
requestObject.insert(_TYPE, "deleteFile");
|
||||
requestObject.insert("file_id", fileId);
|
||||
|
||||
this->sendRequest(requestObject);
|
||||
}
|
||||
|
||||
void TDLibWrapper::searchEmoji(const QString &queryString)
|
||||
{
|
||||
LOG("Searching emoji" << queryString);
|
||||
|
|
|
@ -193,6 +193,9 @@ public:
|
|||
Q_INVOKABLE void getInlineQueryResults(qlonglong botUserId, qlonglong chatId, const QVariantMap &userLocation, const QString &query, const QString &offset, const QString &extra);
|
||||
Q_INVOKABLE void sendInlineQueryResultMessage(qlonglong chatId, qlonglong threadId, qlonglong replyToMessageId, const QString &queryId, const QString &resultId);
|
||||
Q_INVOKABLE void sendBotStartMessage(qlonglong botUserId, qlonglong chatId, const QString ¶meter, const QString &extra);
|
||||
Q_INVOKABLE void cancelDownloadFile(int fileId);
|
||||
Q_INVOKABLE void cancelUploadFile(int fileId);
|
||||
Q_INVOKABLE void deleteFile(int fileId);
|
||||
|
||||
// Others (candidates for extraction ;))
|
||||
Q_INVOKABLE void searchEmoji(const QString &queryString);
|
||||
|
|
|
@ -930,21 +930,6 @@
|
|||
<translation>Über Fernschreiber</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>MessageDocument</name>
|
||||
<message>
|
||||
<source>Download Document</source>
|
||||
<translation>Dokument herunterladen</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Open Document</source>
|
||||
<translation>Dokument öffnen</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Copy Document to Downloads</source>
|
||||
<translation>Dokument zu Downloads kopieren</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>MessageListViewItem</name>
|
||||
<message>
|
||||
|
@ -1075,6 +1060,13 @@
|
|||
<translation>via %1</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>MessageVoiceNote</name>
|
||||
<message>
|
||||
<source>Voice Note</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>NewChatPage</name>
|
||||
<message>
|
||||
|
|
|
@ -930,21 +930,6 @@
|
|||
<translation>About Fernschreiber</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>MessageDocument</name>
|
||||
<message>
|
||||
<source>Download Document</source>
|
||||
<translation>Download Document</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Open Document</source>
|
||||
<translation>Open Document</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Copy Document to Downloads</source>
|
||||
<translation>Copy Document to Downloads</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>MessageListViewItem</name>
|
||||
<message>
|
||||
|
@ -1075,6 +1060,13 @@
|
|||
<translation>via %1</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>MessageVoiceNote</name>
|
||||
<message>
|
||||
<source>Voice Note</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>NewChatPage</name>
|
||||
<message>
|
||||
|
|
|
@ -930,21 +930,6 @@
|
|||
<translation>Acerca de</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>MessageDocument</name>
|
||||
<message>
|
||||
<source>Download Document</source>
|
||||
<translation>Bajar Documento</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Open Document</source>
|
||||
<translation>Abrir Documento</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Copy Document to Downloads</source>
|
||||
<translation>Copiar documento a Downloads</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>MessageListViewItem</name>
|
||||
<message>
|
||||
|
@ -1062,7 +1047,7 @@
|
|||
<source>%Ln vote(s) total</source>
|
||||
<comment>number of total votes</comment>
|
||||
<translation type="unfinished">
|
||||
<numerusform></numerusform>
|
||||
<numerusform>%Ln total de votos</numerusform>
|
||||
<numerusform></numerusform>
|
||||
</translation>
|
||||
</message>
|
||||
|
@ -1075,6 +1060,13 @@
|
|||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>MessageVoiceNote</name>
|
||||
<message>
|
||||
<source>Voice Note</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>NewChatPage</name>
|
||||
<message>
|
||||
|
|
|
@ -931,21 +931,6 @@
|
|||
<translation>Tietoa Fernschreiberista</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>MessageDocument</name>
|
||||
<message>
|
||||
<source>Download Document</source>
|
||||
<translation>Lataa dokumentti</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Open Document</source>
|
||||
<translation>Avaa dokumentti</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Copy Document to Downloads</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>MessageListViewItem</name>
|
||||
<message>
|
||||
|
@ -1063,8 +1048,8 @@
|
|||
<source>%Ln vote(s) total</source>
|
||||
<comment>number of total votes</comment>
|
||||
<translation type="unfinished">
|
||||
<numerusform></numerusform>
|
||||
<numerusform></numerusform>
|
||||
<numerusform>yhteensä %Ln ääni </numerusform>
|
||||
<numerusform>yhteensä %Ln ääntä</numerusform>
|
||||
</translation>
|
||||
</message>
|
||||
</context>
|
||||
|
@ -1076,6 +1061,13 @@
|
|||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>MessageVoiceNote</name>
|
||||
<message>
|
||||
<source>Voice Note</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>NewChatPage</name>
|
||||
<message>
|
||||
|
|
|
@ -918,21 +918,6 @@
|
|||
<translation>A Fernschreiber névjegye</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>MessageDocument</name>
|
||||
<message>
|
||||
<source>Download Document</source>
|
||||
<translation type="unfinished">Dokumentum letöltése</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Open Document</source>
|
||||
<translation type="unfinished">Dokumentum megyitása</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Copy Document to Downloads</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>MessageListViewItem</name>
|
||||
<message>
|
||||
|
@ -1059,6 +1044,13 @@
|
|||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>MessageVoiceNote</name>
|
||||
<message>
|
||||
<source>Voice Note</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>NewChatPage</name>
|
||||
<message>
|
||||
|
|
|
@ -930,21 +930,6 @@
|
|||
<translation>Informazioni su Fernschreiber</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>MessageDocument</name>
|
||||
<message>
|
||||
<source>Download Document</source>
|
||||
<translation type="unfinished">Scarica documento</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Open Document</source>
|
||||
<translation type="unfinished">Apri documento</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Copy Document to Downloads</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>MessageListViewItem</name>
|
||||
<message>
|
||||
|
@ -1075,6 +1060,13 @@
|
|||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>MessageVoiceNote</name>
|
||||
<message>
|
||||
<source>Voice Note</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>NewChatPage</name>
|
||||
<message>
|
||||
|
|
|
@ -942,21 +942,6 @@
|
|||
<translation>O Fernschreiber</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>MessageDocument</name>
|
||||
<message>
|
||||
<source>Download Document</source>
|
||||
<translation type="unfinished">Pobierz dokument</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Open Document</source>
|
||||
<translation type="unfinished">Otwórz dokument</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Copy Document to Downloads</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>MessageListViewItem</name>
|
||||
<message>
|
||||
|
@ -1091,6 +1076,13 @@
|
|||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>MessageVoiceNote</name>
|
||||
<message>
|
||||
<source>Voice Note</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>NewChatPage</name>
|
||||
<message>
|
||||
|
|
|
@ -942,21 +942,6 @@
|
|||
<translation>О программе</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>MessageDocument</name>
|
||||
<message>
|
||||
<source>Download Document</source>
|
||||
<translation type="unfinished">Скачать документ</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Open Document</source>
|
||||
<translation type="unfinished">Открыть документ</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Copy Document to Downloads</source>
|
||||
<translation type="unfinished">Сохранить в Загрузках</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>MessageListViewItem</name>
|
||||
<message>
|
||||
|
@ -1091,6 +1076,13 @@
|
|||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>MessageVoiceNote</name>
|
||||
<message>
|
||||
<source>Voice Note</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>NewChatPage</name>
|
||||
<message>
|
||||
|
|
|
@ -930,21 +930,6 @@
|
|||
<translation>Om Fernschreiber</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>MessageDocument</name>
|
||||
<message>
|
||||
<source>Download Document</source>
|
||||
<translation type="unfinished">Ladda ner dokument</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Open Document</source>
|
||||
<translation type="unfinished">Öppna dokument</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Copy Document to Downloads</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>MessageListViewItem</name>
|
||||
<message>
|
||||
|
@ -1075,6 +1060,13 @@
|
|||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>MessageVoiceNote</name>
|
||||
<message>
|
||||
<source>Voice Note</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>NewChatPage</name>
|
||||
<message>
|
||||
|
|
|
@ -918,21 +918,6 @@
|
|||
<translation>关于 Fernschreiber</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>MessageDocument</name>
|
||||
<message>
|
||||
<source>Download Document</source>
|
||||
<translation type="unfinished">下载文档</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Open Document</source>
|
||||
<translation type="unfinished">打开文档</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Copy Document to Downloads</source>
|
||||
<translation type="unfinished">复制文档到下载</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>MessageListViewItem</name>
|
||||
<message>
|
||||
|
@ -1047,7 +1032,7 @@
|
|||
<source>%Ln vote(s) total</source>
|
||||
<comment>number of total votes</comment>
|
||||
<translation type="unfinished">
|
||||
<numerusform></numerusform>
|
||||
<numerusform>总计 %Ln 次投票</numerusform>
|
||||
</translation>
|
||||
</message>
|
||||
</context>
|
||||
|
@ -1059,6 +1044,13 @@
|
|||
<translation>通过机器用户 %1</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>MessageVoiceNote</name>
|
||||
<message>
|
||||
<source>Voice Note</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>NewChatPage</name>
|
||||
<message>
|
||||
|
|
|
@ -930,21 +930,6 @@
|
|||
<translation>About Fernschreiber</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>MessageDocument</name>
|
||||
<message>
|
||||
<source>Download Document</source>
|
||||
<translation type="unfinished">Download Document</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Open Document</source>
|
||||
<translation type="unfinished">Open Document</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Copy Document to Downloads</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>MessageListViewItem</name>
|
||||
<message>
|
||||
|
@ -1075,6 +1060,13 @@
|
|||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>MessageVoiceNote</name>
|
||||
<message>
|
||||
<source>Voice Note</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>NewChatPage</name>
|
||||
<message>
|
||||
|
|
Loading…
Reference in a new issue