Warning, /multimedia/kasts/src/qml/EntryPage.qml is written in an unsupported language. File is not indexed.
0001 /** 0002 * SPDX-FileCopyrightText: 2020 Tobias Fella <tobias.fella@kde.org> 0003 * SPDX-FileCopyrightText: 2021-2023 Bart De Vries <bart@mogwai.be> 0004 * 0005 * SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL 0006 */ 0007 0008 import QtQuick 0009 import QtQuick.Controls as Controls 0010 import QtQuick.Layouts 0011 0012 import org.kde.kirigami as Kirigami 0013 import org.kde.kmediasession 0014 0015 import org.kde.kasts 0016 import org.kde.kasts.settings 0017 0018 Kirigami.ScrollablePage { 0019 id: page 0020 0021 property QtObject entry 0022 0023 title: i18nc("@title", "Episode Details") 0024 0025 padding: 0 // needed to get the inline header to fill the page 0026 0027 function openPodcast() { 0028 pushPage("FeedListPage"); 0029 lastFeed = entry.feed.url; 0030 pageStack.push("qrc:/qt/qml/org/kde/kasts/qml/FeedDetailsPage.qml", {"feed": entry.feed}); 0031 } 0032 0033 // This function is needed to close the EntryPage if it is opened over the 0034 // QueuePage when the episode is removed from the queue (e.g. when the 0035 // episode finishes). 0036 Connections { 0037 target: entry 0038 function onQueueStatusChanged() { 0039 if (!entry.queueStatus) { 0040 // this entry has just been removed from the queue 0041 if (pageStack.depth > 1) { 0042 if (pageStack.get(0).pageName === "queuepage") { 0043 if (pageStack.get(0).lastEntry) { 0044 if (pageStack.get(0).lastEntry === entry.id) { 0045 // if this EntryPage was open, then close it 0046 pageStack.pop() 0047 } 0048 } 0049 } 0050 } 0051 } 0052 } 0053 } 0054 0055 Connections { 0056 target: entry.enclosure 0057 function onStatusChanged() { 0058 if (entry.enclosure.status === Enclosure.Downloadable) { 0059 // this entry has just been deleted on the downloadpage 0060 if (pageStack.depth > 1) { 0061 if (pageStack.get(0).pageName === "downloadpage") { 0062 if (pageStack.get(0).lastEntry) { 0063 if (pageStack.get(0).lastEntry === entry.id) { 0064 // if this EntryPage was open, then close it 0065 pageStack.pop() 0066 } 0067 } 0068 } 0069 } 0070 } 0071 } 0072 } 0073 0074 ColumnLayout { 0075 spacing: 0 0076 0077 GenericHeader { 0078 id: infoHeader 0079 Layout.fillWidth: true 0080 image: entry.cachedImage 0081 title: entry.title 0082 subtitle: entry.feed.name 0083 subtitleClickable: true 0084 0085 onSubtitleClicked: page.openPodcast() 0086 } 0087 0088 // header actions 0089 Controls.Control { 0090 Layout.fillWidth: true 0091 0092 leftPadding: Kirigami.Units.largeSpacing 0093 rightPadding: Kirigami.Units.largeSpacing 0094 bottomPadding: Kirigami.Units.smallSpacing 0095 topPadding: Kirigami.Units.smallSpacing 0096 0097 background: Rectangle { 0098 color: Kirigami.Theme.alternateBackgroundColor 0099 0100 Kirigami.Separator { 0101 anchors.bottom: parent.bottom 0102 anchors.left: parent.left 0103 anchors.right: parent.right 0104 } 0105 } 0106 0107 contentItem: Kirigami.ActionToolBar { 0108 alignment: Qt.AlignLeft 0109 background: Item {} 0110 0111 actions: [ 0112 Kirigami.Action { 0113 text: i18nc("@action:intoolbar Button to open an episode URL in browser", "Open in Browser") 0114 visible: !entry.enclosure 0115 icon.name: "globe" 0116 onTriggered: { 0117 Qt.openUrlExternally(entry.link); 0118 } 0119 }, 0120 Kirigami.Action { 0121 text: i18nc("@action:intoolbar Button to start episode download", "Download") 0122 visible: entry.enclosure && (entry.enclosure.status === Enclosure.Downloadable || entry.enclosure.status === Enclosure.PartiallyDownloaded) 0123 icon.name: "download" 0124 onTriggered: { 0125 downloadOverlay.entry = entry; 0126 downloadOverlay.run(); 0127 } 0128 }, 0129 Kirigami.Action { 0130 text: i18nc("@action:intoolbar Button to cancel ongoing download of episode", "Cancel Download") 0131 visible: entry.enclosure && entry.enclosure.status === Enclosure.Downloading 0132 icon.name: "edit-delete-remove" 0133 onTriggered: { 0134 entry.enclosure.cancelDownload(); 0135 } 0136 }, 0137 Kirigami.Action { 0138 text: i18nc("@action:intoolbar Button to pause the playback of the episode", "Pause") 0139 visible: entry.enclosure && entry.queueStatus && (AudioManager.entry === entry && AudioManager.playbackState === KMediaSession.PlayingState) 0140 icon.name: "media-playback-pause" 0141 onTriggered: { 0142 AudioManager.pause(); 0143 } 0144 }, 0145 Kirigami.Action { 0146 text: i18nc("@action:intoolbar Button to start playback of the episode", "Play") 0147 visible: entry.enclosure && entry.enclosure.status === Enclosure.Downloaded && entry.queueStatus && (AudioManager.entry !== entry || AudioManager.playbackState !== KMediaSession.PlayingState) 0148 icon.name: "media-playback-start" 0149 onTriggered: { 0150 AudioManager.entry = entry; 0151 AudioManager.play(); 0152 } 0153 }, 0154 Kirigami.Action { 0155 text: i18nc("@action:intoolbar Action to start playback by streaming the episode rather than downloading it first", "Stream") 0156 visible: entry.enclosure && entry.enclosure.status !== Enclosure.Downloaded && NetworkConnectionManager.streamingAllowed && (AudioManager.entry !== entry || AudioManager.playbackState !== KMediaSession.PlayingState) 0157 icon.name: "media-playback-cloud" 0158 onTriggered: { 0159 if (!entry.queueStatus) { 0160 entry.queueStatus = true; 0161 } 0162 AudioManager.entry = entry; 0163 AudioManager.play(); 0164 } 0165 }, 0166 Kirigami.Action { 0167 text: !entry.queueStatus ? i18nc("@action:intoolbar Button to add an episode to the play queue", "Add to Queue") : i18nc("@action:intoolbar Button to remove an episode from the play queue", "Remove from Queue") 0168 icon.name: !entry.queueStatus ? "media-playlist-append" : "list-remove" 0169 visible: entry.enclosure || entry.queueStatus 0170 onTriggered: { 0171 if(!entry.queueStatus) { 0172 entry.queueStatus = true; 0173 } else { 0174 // first change to next track if this one is playing 0175 if (entry.hasEnclosure && entry === AudioManager.entry) { 0176 AudioManager.next() 0177 } 0178 entry.queueStatus = false 0179 } 0180 } 0181 }, 0182 Kirigami.Action { 0183 text: i18nc("@action:intoolbar Button to remove the downloaded episode audio file", "Delete Download") 0184 icon.name: "delete" 0185 visible: entry.enclosure && (entry.enclosure.status === Enclosure.Downloaded || entry.enclosure.status === Enclosure.PartiallyDownloaded) 0186 onTriggered: { 0187 entry.enclosure.deleteFile(); 0188 } 0189 }, 0190 Kirigami.Action { 0191 text: i18nc("@action:intoolbar Button to reset the play position of an episode to the start", "Reset Play Position") 0192 visible: entry.enclosure && entry.enclosure.playPosition > 1000 0193 onTriggered: entry.enclosure.playPosition = 0 0194 displayHint: Kirigami.DisplayHint.AlwaysHide 0195 }, 0196 Kirigami.Action { 0197 text: entry.read ? i18nc("@action:intoolbar Button to mark eposide as not played", "Mark as Unplayed") : i18nc("@action:intoolbar Button to mark episode as played", "Mark as Played") 0198 displayHint: Kirigami.DisplayHint.AlwaysHide 0199 onTriggered: { 0200 entry.read = !entry.read 0201 } 0202 }, 0203 Kirigami.Action { 0204 text: entry.new ? i18nc("@action:intoolbar", "Remove \"New\" Label") : i18nc("@action:intoolbar", "Label as \"New\"") 0205 displayHint: Kirigami.DisplayHint.AlwaysHide 0206 onTriggered: { 0207 entry.new = !entry.new 0208 } 0209 }, 0210 Kirigami.Action { 0211 text: entry.favorite ? i18nc("@action:intoolbar Button to remove the \"favorite\" property of a podcast episode", "Remove from Favorites") : i18nc("@action:intoolbar Button to add a podcast episode as favorite", "Add to Favorites") 0212 icon.name: !entry.favorite ? "starred-symbolic" : "non-starred-symbolic" 0213 displayHint: Kirigami.DisplayHint.AlwaysHide 0214 onTriggered: { 0215 entry.favorite = !entry.favorite 0216 } 0217 }, 0218 Kirigami.Action { 0219 text: i18nc("@action:intoolbar Button to open the podcast URL in browser", "Open Podcast") 0220 displayHint: Kirigami.DisplayHint.AlwaysHide 0221 onTriggered: page.openPodcast() 0222 } 0223 ] 0224 } 0225 } 0226 0227 TextEdit { 0228 id: textLabel 0229 Layout.topMargin: Kirigami.Units.gridUnit 0230 Layout.leftMargin: Kirigami.Units.gridUnit 0231 Layout.rightMargin: Kirigami.Units.gridUnit 0232 Layout.bottomMargin: Kirigami.Units.gridUnit 0233 Layout.fillWidth: true 0234 Layout.fillHeight: true 0235 0236 readOnly: true 0237 selectByMouse: !Kirigami.Settings.isMobile 0238 text: page.entry.content 0239 baseUrl: page.entry.baseUrl 0240 textFormat: Text.RichText 0241 wrapMode: Text.WordWrap 0242 font.pointSize: SettingsManager && !(SettingsManager.articleFontUseSystem) ? SettingsManager.articleFontSize : Kirigami.Theme.defaultFont.pointSize 0243 color: Kirigami.Theme.textColor 0244 0245 onLinkActivated: (link) => { 0246 if (link.split("://")[0] === "timestamp") { 0247 if (AudioManager.entry && AudioManager.entry.enclosure && entry.enclosure && (entry.enclosure.status === Enclosure.Downloaded || SettingsManager.prioritizeStreaming)) { 0248 if (AudioManager.entry !== entry) { 0249 if (!entry.queueStatus) { 0250 entry.queueStatus = true; 0251 } 0252 AudioManager.entry = entry; 0253 AudioManager.play(); 0254 } 0255 AudioManager.seek(link.split("://")[1]); 0256 } 0257 } else { 0258 Qt.openUrlExternally(link) 0259 } 0260 } 0261 onLinkHovered: { 0262 cursorShape: Qt.PointingHandCursor; 0263 } 0264 onWidthChanged: { text = entry.adjustedContent(width, font.pixelSize) } 0265 } 0266 0267 ListView { 0268 visible: count !== 0 0269 Layout.fillWidth: true 0270 implicitHeight: contentHeight 0271 interactive: false 0272 currentIndex: -1 0273 Layout.leftMargin: Kirigami.Units.gridUnit 0274 Layout.rightMargin: Kirigami.Units.gridUnit 0275 Layout.bottomMargin: Kirigami.Units.gridUnit 0276 model: ChapterModel { 0277 entry: page.entry 0278 } 0279 delegate: ChapterListDelegate { 0280 entry: page.entry 0281 } 0282 } 0283 0284 Controls.Button { 0285 Layout.leftMargin: Kirigami.Units.gridUnit 0286 Layout.rightMargin: Kirigami.Units.gridUnit 0287 Layout.bottomMargin: Kirigami.Units.gridUnit 0288 visible: entry.hasEnclosure 0289 0290 text: i18nc("@action:button", "Copy Episode Download URL") 0291 height: enclosureUrl.height 0292 width: enclosureUrl.height 0293 icon.name: "edit-copy" 0294 0295 onClicked: { 0296 applicationWindow().showPassiveNotification(i18nc("@info:status", "Link Copied")); 0297 enclosureUrl.selectAll(); 0298 enclosureUrl.copy(); 0299 enclosureUrl.deselect(); 0300 } 0301 0302 // copy url from this invisible textedit 0303 TextEdit { 0304 id: enclosureUrl 0305 visible: false 0306 readOnly: true 0307 textFormat:TextEdit.RichText 0308 text: entry.hasEnclosure ? entry.enclosure.url : "" 0309 color: Kirigami.Theme.textColor 0310 } 0311 } 0312 } 0313 }