/
erhoof
/
telegraf
Обзор
Документация
Войти
/
erhoof
/
telegraf
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
develop
qml/components/VideoComponent.qml
195 строк
6 KB
mbarashkov
Обработка ошибок проигрывания видео
11 апр 2025, 17:28
11 апр 2025, 17:28
091cde2
Код
Авторство
О чём код?
import QtQuick 2.6 import Sailfish.Silica 1.0 import ru.telegrafaurora.telegraf 1.0 import QtMultimedia 5.6 import QtGraphicalEffects 1.0 Video { id: video property var videoData: model.modelData.content.video readonly property bool isPlaying: playbackState === MediaPlayer.PlayingState readonly property bool isCurrent: index === page.index property bool shouldPlay autoLoad: true source: file.isDownloadingCompleted ? file.path : '' onIsCurrentChanged: { if(!isCurrent) { pause() } } onStatusChanged: { if(status === MediaPlayer.EndOfMedia) { page.overlayActive = true } } onErrorChanged: { console.log("*** error is: " + error); } function getErrorText() { switch(error) { case MediaPlayer.FormatError: return qsTr("VideoFormatError"); case MediaPlayer.NetworkError: return qsTr("VideoNetworkError"); case MediaPlayer.NoError: return ""; default: return qsTr("VideoOtherError"); } } TDLibThumbnail { id: tdLibImage property bool active: !file.isDownloadingCompleted || (!video.isPlaying && (video.position === 0 || video.status === MediaPlayer.EndOfMedia)) opacity: active ? 1 : 0 visible: active || opacity > 0 width: parent.width //don't use anchors here for easier custom scaling height: parent.height thumbnail: videoData.thumbnail minithumbnail: videoData.minithumbnail fillMode: Image.PreserveAspectFit } TDLibFile { id: file autoLoad: false fileInformation: videoData.video property real progress: isDownloadingCompleted ? 1.0 : (downloadedSize / size) onDownloadingCompletedChanged: { if(isDownloadingCompleted) { video.source = file.path if(video.shouldPlay) { video.play() delayedOverlayHide.start() video.shouldPlay = false } } } } MouseArea { anchors.fill: parent onClicked: page.overlayActive = !page.overlayActive } RadialGradient { // white videos = invisible button. I can't tell since which SFOS version the opaque button is available, so: id: buttonBg anchors.centerIn: parent width: Theme.itemSizeLarge; height: Theme.itemSizeLarge property color baseColor: Theme.rgba(palette.overlayBackgroundColor, 0.2) enabled: videoUI.active || !file.isDownloadingCompleted opacity: enabled ? 1 : 0 Behavior on opacity { FadeAnimator {} } gradient: Gradient { GradientStop { position: 0.0; color: buttonBg.baseColor } GradientStop { position: 0.3; color: buttonBg.baseColor } GradientStop { position: 0.5; color: 'transparent' } } IconButton { anchors.fill: parent icon.source: "image://theme/icon-l-"+(video.isPlaying || video.shouldPlay ? 'pause' : 'play')+"?" + (pressed ? Theme.highlightColor : Theme.lightPrimaryColor) onClicked: { if (!file.isDownloadingCompleted) { video.shouldPlay = !video.shouldPlay; if(video.shouldPlay) { file.load() } else { file.cancel() } return; } if (video.isPlaying) { video.pause() } else { video.play() delayedOverlayHide.start() } } } } ProgressCircle { property bool active: file.isDownloadingActive opacity: active ? 1 : 0 Behavior on opacity { FadeAnimator {} } anchors.centerIn: parent value: file.progress } Item { id: videoUI property bool active: page.overlayActive anchors.fill: parent opacity: active ? 1 : 0 Behavior on opacity { FadeAnimator {} } Text { id: errorMessage color: Theme.highlightColor anchors.bottom: slider.top anchors.horizontalCenter: parent.horizontalCenter text: getErrorText() font.pixelSize: Theme.fontSizeSmall visible: video.error !== MediaPlayer.NoError } Slider { id: slider value: video.position minimumValue: 0 maximumValue: video.duration || 0.1 enabled: parent.active && video.seekable width: parent.width handleVisible: false animateValue: true stepSize: 500 anchors { bottom: parent.bottom bottomMargin: Theme.itemSizeMedium } valueText: value > 0 || down ? Format.formatDuration((value)/1000, Formatter.Duration) : '' leftMargin: Theme.horizontalPageMargin rightMargin: Theme.horizontalPageMargin onDownChanged: { if(!down) { video.seek(value) value = Qt.binding(function() { return video.position }) } } Label { anchors { right: parent.right rightMargin: Theme.horizontalPageMargin bottom: parent.bottom topMargin: Theme.paddingSmall } font.pixelSize: Theme.fontSizeExtraSmall text: file.isDownloadingCompleted ? Format.formatDuration((parent.maximumValue - parent.value)/1000, Formatter.Duration) : (video.videoData.duration ? Format.formatDuration(video.videoData.duration, Formatter.Duration) + ', ' : '') + Format.formatFileSize(file.size || file.expectedSize) color: Theme.highlightColor } } Timer { id: delayedOverlayHide interval: 500 onTriggered: { if(video.isPlaying) { page.overlayActive = false } } } } }