feat: add KDE Plasma podcast plasmoid
This commit is contained in:
@@ -0,0 +1,10 @@
|
||||
import QtQuick
|
||||
import org.kde.plasma.configuration
|
||||
|
||||
ConfigModel {
|
||||
ConfigCategory {
|
||||
name: i18n("Podcast")
|
||||
icon: "audio-x-generic"
|
||||
source: "configGeneral.qml"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
import QtQuick
|
||||
import QtQuick.Controls as QQC2
|
||||
import QtQuick.Layouts
|
||||
import org.kde.kirigami as Kirigami
|
||||
import "../ui/podcastCatalog.js" as PodcastCatalog
|
||||
|
||||
Kirigami.FormLayout {
|
||||
id: page
|
||||
|
||||
property alias cfg_favoritePodcastIds: favoriteIds.text
|
||||
property alias cfg_maxEpisodes: maxEpisodes.value
|
||||
property alias cfg_refreshIntervalSec: refreshInterval.value
|
||||
property alias cfg_favoritesOnly: favoritesOnly.checked
|
||||
|
||||
function selectedIds() {
|
||||
return favoriteIds.text.split(",").map(function (id) { return id.trim() }).filter(function (id) { return id.length > 0 })
|
||||
}
|
||||
|
||||
function hasId(id) {
|
||||
return selectedIds().indexOf(String(id)) >= 0
|
||||
}
|
||||
|
||||
function toggleId(id, enabled) {
|
||||
var ids = selectedIds()
|
||||
var value = String(id)
|
||||
var index = ids.indexOf(value)
|
||||
if (enabled && index < 0)
|
||||
ids.push(value)
|
||||
else if (!enabled && index >= 0)
|
||||
ids.splice(index, 1)
|
||||
favoriteIds.text = ids.join(",")
|
||||
}
|
||||
|
||||
QQC2.TextField {
|
||||
id: favoriteIds
|
||||
Kirigami.FormData.label: i18n("Preferiti:")
|
||||
placeholderText: i18n("Seleziona dall'elenco sotto")
|
||||
visible: false
|
||||
}
|
||||
|
||||
QQC2.Label {
|
||||
Kirigami.FormData.label: i18n("Programmi:")
|
||||
text: i18n("Seleziona i programmi da mettere in cima alla lista.")
|
||||
wrapMode: Text.WordWrap
|
||||
Layout.maximumWidth: 440
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
Kirigami.FormData.label: ""
|
||||
Layout.preferredWidth: 440
|
||||
Layout.preferredHeight: 240
|
||||
color: Kirigami.Theme.backgroundColor
|
||||
border.color: Kirigami.Theme.disabledTextColor
|
||||
radius: 4
|
||||
|
||||
QQC2.ScrollView {
|
||||
anchors.fill: parent
|
||||
anchors.margins: 6
|
||||
clip: true
|
||||
|
||||
Column {
|
||||
width: parent.width
|
||||
spacing: 2
|
||||
|
||||
Repeater {
|
||||
model: PodcastCatalog.catalog
|
||||
delegate: QQC2.CheckBox {
|
||||
width: parent.width
|
||||
text: modelData.title + " (" + modelData.id + ")"
|
||||
checked: page.hasId(modelData.id)
|
||||
onClicked: page.toggleId(modelData.id, checked)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QQC2.SpinBox {
|
||||
id: maxEpisodes
|
||||
Kirigami.FormData.label: i18n("Episodi da mostrare:")
|
||||
from: 1
|
||||
to: 30
|
||||
}
|
||||
|
||||
QQC2.SpinBox {
|
||||
id: refreshInterval
|
||||
Kirigami.FormData.label: i18n("Aggiornamento (secondi):")
|
||||
from: 120
|
||||
to: 86400
|
||||
stepSize: 60
|
||||
editable: true
|
||||
}
|
||||
|
||||
QQC2.CheckBox {
|
||||
id: favoritesOnly
|
||||
Kirigami.FormData.label: i18n("Filtro:")
|
||||
text: i18n("Mostra solo i preferiti")
|
||||
}
|
||||
|
||||
QQC2.Label {
|
||||
Kirigami.FormData.label: ""
|
||||
text: i18n("Le credenziali vengono richieste nel widget e conservate in KWallet, non nella configurazione Plasma.")
|
||||
wrapMode: Text.WordWrap
|
||||
Layout.maximumWidth: 440
|
||||
color: Kirigami.Theme.disabledTextColor
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<kcfg xmlns="http://www.kde.org/standards/kcfg/1.0">
|
||||
<kcfgfile name=""/>
|
||||
<group name="General">
|
||||
<entry name="favoritePodcastIds" type="String">
|
||||
<default></default>
|
||||
<label>ID dei programmi preferiti</label>
|
||||
</entry>
|
||||
<entry name="maxEpisodes" type="Int">
|
||||
<default>8</default>
|
||||
<min>1</min>
|
||||
<max>30</max>
|
||||
<label>Numero massimo di episodi</label>
|
||||
</entry>
|
||||
<entry name="refreshIntervalSec" type="Int">
|
||||
<default>900</default>
|
||||
<min>120</min>
|
||||
<max>86400</max>
|
||||
<label>Intervallo aggiornamento (secondi)</label>
|
||||
</entry>
|
||||
<entry name="favoritesOnly" type="Bool">
|
||||
<default>false</default>
|
||||
<label>Mostra solo i programmi preferiti</label>
|
||||
</entry>
|
||||
</group>
|
||||
</kcfg>
|
||||
@@ -0,0 +1,2 @@
|
||||
module org.enne2.ilpost.credentials
|
||||
plugin ilpostcredentialsplugin
|
||||
@@ -0,0 +1,277 @@
|
||||
import QtQuick
|
||||
import QtQuick.Layouts
|
||||
import QtQuick.Controls as QQC2
|
||||
import org.kde.plasma.plasmoid
|
||||
import org.kde.plasma.core as PlasmaCore
|
||||
import org.kde.plasma.components 3.0 as PC3
|
||||
import org.kde.kirigami as Kirigami
|
||||
import "../lib" as Credentials
|
||||
|
||||
PlasmoidItem {
|
||||
id: root
|
||||
|
||||
property string favoriteIds: String(Plasmoid.configuration.favoritePodcastIds || "")
|
||||
property int maxEpisodes: Number(Plasmoid.configuration.maxEpisodes || 8)
|
||||
property int refreshSeconds: Number(Plasmoid.configuration.refreshIntervalSec || 900)
|
||||
property bool favoritesOnly: Boolean(Plasmoid.configuration.favoritesOnly)
|
||||
|
||||
Credentials.IlPostApiClient {
|
||||
id: api
|
||||
}
|
||||
|
||||
Plasmoid.title: i18n("Podcast de Il Post")
|
||||
Plasmoid.icon: "audio-x-generic"
|
||||
Plasmoid.backgroundHints: PlasmaCore.Types.DefaultBackground
|
||||
preferredRepresentation: fullRepresentation
|
||||
switchWidth: 320
|
||||
switchHeight: 360
|
||||
|
||||
function refresh() {
|
||||
api.refresh(root.favoriteIds, root.maxEpisodes, root.favoritesOnly)
|
||||
}
|
||||
|
||||
onFavoriteIdsChanged: if (api.authenticated) refresh()
|
||||
onMaxEpisodesChanged: if (api.authenticated) refresh()
|
||||
onFavoritesOnlyChanged: if (api.authenticated) refresh()
|
||||
|
||||
Component.onCompleted: api.restore()
|
||||
|
||||
Connections {
|
||||
target: api
|
||||
function onAuthenticatedChanged() {
|
||||
if (api.authenticated)
|
||||
root.refresh()
|
||||
}
|
||||
}
|
||||
|
||||
Timer {
|
||||
interval: Math.max(120, root.refreshSeconds) * 1000
|
||||
repeat: true
|
||||
running: api.authenticated
|
||||
onTriggered: root.refresh()
|
||||
}
|
||||
|
||||
compactRepresentation: Component {
|
||||
Item {
|
||||
implicitWidth: Kirigami.Units.iconSizes.smallMedium
|
||||
implicitHeight: Kirigami.Units.iconSizes.smallMedium
|
||||
Kirigami.Icon {
|
||||
anchors.fill: parent
|
||||
source: Plasmoid.icon
|
||||
color: api.authenticated ? Kirigami.Theme.textColor : Kirigami.Theme.disabledTextColor
|
||||
}
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: Plasmoid.expanded = !Plasmoid.expanded
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fullRepresentation: Component {
|
||||
Item {
|
||||
implicitWidth: 380
|
||||
implicitHeight: 430
|
||||
Layout.minimumWidth: 300
|
||||
|
||||
Connections {
|
||||
target: api
|
||||
function onLoginSucceeded() {
|
||||
passwordField.clear()
|
||||
}
|
||||
}
|
||||
Layout.minimumHeight: 260
|
||||
Layout.preferredWidth: 380
|
||||
Layout.preferredHeight: 430
|
||||
|
||||
ColumnLayout {
|
||||
anchors.fill: parent
|
||||
anchors.margins: Kirigami.Units.smallSpacing
|
||||
spacing: Kirigami.Units.smallSpacing
|
||||
|
||||
RowLayout {
|
||||
Layout.fillWidth: true
|
||||
PC3.Label {
|
||||
text: i18n("Podcast de Il Post")
|
||||
font.bold: true
|
||||
font.pointSize: Kirigami.Theme.defaultFont.pointSize + 2
|
||||
Layout.fillWidth: true
|
||||
elide: Text.ElideRight
|
||||
}
|
||||
PC3.Button {
|
||||
icon.name: "view-refresh"
|
||||
display: QQC2.AbstractButton.IconOnly
|
||||
enabled: !api.loading && api.authenticated
|
||||
onClicked: root.refresh()
|
||||
QQC2.ToolTip.text: i18n("Aggiorna")
|
||||
QQC2.ToolTip.visible: hovered
|
||||
}
|
||||
}
|
||||
|
||||
PC3.Label {
|
||||
Layout.fillWidth: true
|
||||
visible: api.statusMessage.length > 0
|
||||
text: api.statusMessage
|
||||
color: api.authenticated ? Kirigami.Theme.disabledTextColor : Kirigami.Theme.negativeTextColor
|
||||
elide: Text.ElideRight
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
visible: !api.authenticated
|
||||
Layout.fillWidth: true
|
||||
spacing: Kirigami.Units.smallSpacing
|
||||
|
||||
PC3.Label {
|
||||
Layout.fillWidth: true
|
||||
text: i18n("Accedi per visualizzare gli episodi. La password sarà salvata solo in KWallet.")
|
||||
wrapMode: Text.WordWrap
|
||||
}
|
||||
QQC2.TextField {
|
||||
id: emailField
|
||||
Layout.fillWidth: true
|
||||
placeholderText: i18n("Username / email Il Post")
|
||||
inputMethodHints: Qt.ImhEmailCharactersOnly
|
||||
enabled: !api.loading
|
||||
}
|
||||
QQC2.TextField {
|
||||
id: passwordField
|
||||
Layout.fillWidth: true
|
||||
placeholderText: i18n("Password")
|
||||
echoMode: TextInput.Password
|
||||
enabled: !api.loading
|
||||
onAccepted: loginButton.clicked()
|
||||
}
|
||||
PC3.Button {
|
||||
id: loginButton
|
||||
Layout.fillWidth: true
|
||||
text: api.loading ? i18n("Accesso…") : i18n("Accedi e salva in KWallet")
|
||||
enabled: !api.loading && emailField.text.length > 0 && passwordField.text.length > 0
|
||||
onClicked: api.login(emailField.text, passwordField.text)
|
||||
}
|
||||
}
|
||||
|
||||
QQC2.ScrollView {
|
||||
visible: api.authenticated
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
clip: true
|
||||
|
||||
ListView {
|
||||
id: episodeList
|
||||
anchors.fill: parent
|
||||
spacing: Kirigami.Units.smallSpacing
|
||||
model: api.episodes
|
||||
delegate: Rectangle {
|
||||
required property var modelData
|
||||
width: episodeList.width
|
||||
implicitHeight: episodeColumn.implicitHeight + 16
|
||||
radius: 5
|
||||
color: modelData.favorite
|
||||
? Qt.rgba(0.25, 0.45, 0.25, 0.16)
|
||||
: Kirigami.Theme.backgroundColor
|
||||
border.color: modelData.favorite
|
||||
? Kirigami.Theme.positiveTextColor
|
||||
: Kirigami.Theme.disabledTextColor
|
||||
border.width: 1
|
||||
|
||||
RowLayout {
|
||||
id: episodeRow
|
||||
anchors.fill: parent
|
||||
anchors.margins: 8
|
||||
spacing: Kirigami.Units.smallSpacing
|
||||
|
||||
Item {
|
||||
Layout.preferredWidth: 64
|
||||
Layout.preferredHeight: 64
|
||||
Layout.alignment: Qt.AlignTop
|
||||
|
||||
Image {
|
||||
id: coverImage
|
||||
anchors.fill: parent
|
||||
source: modelData.podcastImage || ""
|
||||
asynchronous: true
|
||||
cache: true
|
||||
fillMode: Image.PreserveAspectCrop
|
||||
smooth: true
|
||||
mipmap: true
|
||||
visible: status === Image.Ready
|
||||
}
|
||||
|
||||
Kirigami.Icon {
|
||||
anchors.centerIn: parent
|
||||
width: 36
|
||||
height: 36
|
||||
source: "audio-x-generic"
|
||||
visible: !coverImage.visible
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
color: "transparent"
|
||||
border.width: 1
|
||||
border.color: Kirigami.Theme.disabledTextColor
|
||||
opacity: 0.45
|
||||
}
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
id: episodeColumn
|
||||
Layout.fillWidth: true
|
||||
spacing: 2
|
||||
|
||||
RowLayout {
|
||||
Layout.fillWidth: true
|
||||
PC3.Label {
|
||||
text: modelData.podcastTitle || i18n("Podcast")
|
||||
color: modelData.favorite ? Kirigami.Theme.positiveTextColor : Kirigami.Theme.disabledTextColor
|
||||
font.bold: true
|
||||
font.pointSize: Kirigami.Theme.defaultFont.pointSize - 1
|
||||
Layout.fillWidth: true
|
||||
elide: Text.ElideRight
|
||||
}
|
||||
PC3.Label {
|
||||
visible: modelData.favorite
|
||||
text: i18n("Preferito")
|
||||
color: Kirigami.Theme.positiveTextColor
|
||||
font.pointSize: Kirigami.Theme.defaultFont.pointSize - 2
|
||||
}
|
||||
}
|
||||
PC3.Label {
|
||||
Layout.fillWidth: true
|
||||
text: modelData.title || i18n("Senza titolo")
|
||||
font.bold: true
|
||||
wrapMode: Text.WordWrap
|
||||
}
|
||||
PC3.Label {
|
||||
Layout.fillWidth: true
|
||||
text: modelData.date ? new Date(modelData.date).toLocaleDateString(Qt.locale()) : ""
|
||||
color: Kirigami.Theme.disabledTextColor
|
||||
font.pointSize: Kirigami.Theme.defaultFont.pointSize - 2
|
||||
}
|
||||
PC3.Button {
|
||||
visible: Boolean(modelData.audioUrl)
|
||||
text: i18n("Riproduci in Dragon Player")
|
||||
onClicked: api.playAudio(modelData.audioUrl)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
visible: api.authenticated
|
||||
Layout.fillWidth: true
|
||||
PC3.Label {
|
||||
text: i18n("%1 episodi · preferiti in cima", api.episodes.length)
|
||||
color: Kirigami.Theme.disabledTextColor
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
PC3.Button {
|
||||
text: i18n("Disconnetti")
|
||||
onClicked: api.clearCredentials()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
var catalog = [{"id":227193,"title":"Tienimi Bordone"},{"id":233679,"title":"Timbuctu"},{"id":232180,"title":"Globo"},{"id":227474,"title":"Morning"},{"id":236472,"title":"Sigmund"},{"id":235598,"title":"L'invasione"},{"id":236670,"title":"Altre Indagini"},{"id":233120,"title":"Comodino"},{"id":233226,"title":"Amare parole"},{"id":234755,"title":"Per fare il Post"},{"id":230388,"title":"Ci vuole una scienza"},{"id":230293,"title":"Indagini"},{"id":231758,"title":"Tienimi Morning"},{"id":235926,"title":"In soldoni"},{"id":227196,"title":"Un podcast su Sanremo"},{"id":227412,"title":"Audiopost"},{"id":235470,"title":"Wild Baricco"},{"id":234841,"title":"10 risposte sui migranti"},{"id":234250,"title":"L'ombelico di un mondo"},{"id":227194,"title":"Joypad"},{"id":232871,"title":"Cosa c'entra?"},{"id":234368,"title":"Ripassini"},{"id":234296,"title":"Tredici"},{"id":229701,"title":"Politics"},{"id":233678,"title":"Vicini e lontani"},{"id":233516,"title":"Il grande vecchio"},{"id":233318,"title":"Le onorate"},{"id":228236,"title":"M49 - Una storia di orsi e persone"},{"id":233144,"title":"La nave"},{"id":228710,"title":"La fine del mondo"},{"id":232619,"title":"L'erba del vicino"},{"id":231622,"title":"Le basi"},{"id":231088,"title":"La bomba"},{"id":231013,"title":"Un furto di quart'ordine"},{"id":232518,"title":"Racconti a Natale"},{"id":230754,"title":"La fabbrica dei soldi"},{"id":230476,"title":"Certe cose"},{"id":229228,"title":"Cose spiegate bene"},{"id":227496,"title":"Un podcast sull'Eurovision"},{"id":227768,"title":"Da Vermicino in poi"},{"id":227322,"title":"Mai più"},{"id":227244,"title":"La guerra dei gelati"},{"id":227259,"title":"L'anno del jazz"},{"id":228752,"title":"Strade blu"},{"id":227246,"title":"Immaginare l'apocalisse"},{"id":227195,"title":"Konrad"},{"id":227197,"title":"Storie dalla libreria"},{"id":227198,"title":"Weekly Post"},{"id":227736,"title":"Wembley"}];
|
||||
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"KPackageStructure": "Plasma/Applet",
|
||||
"KPlugin": {
|
||||
"Id": "org.enne2.ilpost.podcasts",
|
||||
"Name": "Il Post Podcasts",
|
||||
"Name[it]": "Podcast de Il Post",
|
||||
"Description": "Visualizza gli episodi più recenti dei podcast de Il Post",
|
||||
"Description[it]": "Visualizza gli episodi più recenti dei podcast de Il Post",
|
||||
"Icon": "audio-x-generic",
|
||||
"Category": "Multimedia",
|
||||
"License": "GPL-3.0-or-later",
|
||||
"Version": "0.1.0",
|
||||
"Authors": [{ "Name": "enne2" }]
|
||||
},
|
||||
"X-Plasma-API-Minimum-Version": "6.0"
|
||||
}
|
||||
Reference in New Issue
Block a user