From de663b13ceed88d682ffad5f7addf86e337f3f36 Mon Sep 17 00:00:00 2001 From: Kukuh Syafaat Date: Tue, 4 Jan 2022 05:00:04 +0000 Subject: [PATCH 001/102] Update Indonesian translation --- podcasts-gtk/po/id.po | 40 ++++++++++++++++++++++++++++------------ 1 file changed, 28 insertions(+), 12 deletions(-) diff --git a/podcasts-gtk/po/id.po b/podcasts-gtk/po/id.po index 533e9cd..a1fd42e 100644 --- a/podcasts-gtk/po/id.po +++ b/podcasts-gtk/po/id.po @@ -1,21 +1,21 @@ # Indonesian translation for podcasts. # Copyright (C) 2018 podcasts's COPYRIGHT HOLDER # This file is distributed under the same license as the podcasts package. -# Kukuh Syafaat , 2018-2021. +# Kukuh Syafaat , 2018-2022. # msgid "" msgstr "" "Project-Id-Version: podcasts master\n" "Report-Msgid-Bugs-To: https://gitlab.gnome.org/World/podcasts/issues\n" -"POT-Creation-Date: 2021-09-14 16:55+0000\n" -"PO-Revision-Date: 2021-09-20 18:02+0700\n" -"Last-Translator: Andika Triwidada \n" +"POT-Creation-Date: 2021-11-28 07:07+0000\n" +"PO-Revision-Date: 2022-01-04 11:59+0700\n" +"Last-Translator: Kukuh Syafaat \n" "Language-Team: Indonesian \n" "Language: id\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Generator: Poedit 2.4.3\n" +"X-Generator: Poedit 3.0\n" #: podcasts-gtk/resources/org.gnome.Podcasts.gschema.xml.in:15 msgid "Top position of the last open main window" @@ -74,7 +74,6 @@ msgid "Podcasts" msgstr "Siniar" #: podcasts-gtk/resources/org.gnome.Podcasts.desktop.in.in:4 -#: podcasts-gtk/resources/org.gnome.Podcasts.appdata.xml.in.in:10 msgid "Listen to your favorite podcasts, right from your desktop." msgstr "Dengarkan siniar favorit Anda, langsung dari destop Anda." @@ -84,14 +83,28 @@ msgid "Podcast;RSS;" msgstr "Siniar;RSS;" #: podcasts-gtk/resources/org.gnome.Podcasts.appdata.xml.in.in:8 -msgid "Podcast app for GNOME" -msgstr "Aplikasi Siniar untuk GNOME" +msgid "Listen to your favorite shows" +msgstr "Dengarkan acara favorit Anda" + +#: podcasts-gtk/resources/org.gnome.Podcasts.appdata.xml.in.in:10 +msgid "" +"Play, update, and manage your podcasts from a lightweight interface that " +"seamlessly integrates with GNOME. Podcasts can play various audio formats " +"and remember where you stopped listening. You can subscribe to shows via RSS/" +"Atom, iTunes, and Soundcloud links. Subscriptions from other apps can be " +"imported via OPML files." +msgstr "" +"Putar, mutakhirkan, dan kelola siniar Anda dari antarmuka ringan yang " +"terintegrasi dengan GNOME dengan mulus. Siniar dapat memutar berbagai format " +"audio dan mengingat di mana Anda berhenti mendengarkan. Anda dapat " +"berlangganan acara melalui tautan RSS/ Atom, iTunes, dan Soundcloud. " +"Langganan dari aplikasi lain dapat diimpor melalui berkas OPML." -#: podcasts-gtk/resources/org.gnome.Podcasts.appdata.xml.in.in:115 +#: podcasts-gtk/resources/org.gnome.Podcasts.appdata.xml.in.in:117 msgid "Jordan Petridis" msgstr "Jordan Petridis" -#: podcasts-gtk/resources/org.gnome.Podcasts.appdata.xml.in.in:116 +#: podcasts-gtk/resources/org.gnome.Podcasts.appdata.xml.in.in:118 msgid "Julian Hofer" msgstr "Julian Hofer" @@ -128,7 +141,7 @@ msgstr "Kembali" #: podcasts-gtk/resources/gtk/episode_description.ui:148 msgid "Podcast Title" -msgstr "Judul Podcast" +msgstr "Judul Siniar" #: podcasts-gtk/resources/gtk/episode_description.ui:186 msgid "Duration - Date" @@ -394,7 +407,7 @@ msgstr "Pelajari lebih lanjut tentang GNOME Siniar" #: podcasts-gtk/src/widgets/aboutdialog.rs:69 msgid "translator-credits" msgstr "" -"Kukuh Syafaat , 2018-2021.\n" +"Kukuh Syafaat , 2018-2022.\n" "Andika Triwidada , 2021." #: podcasts-gtk/src/widgets/episode.rs:145 @@ -416,3 +429,6 @@ msgstr "Tandai semua episode sebagai sudah didengarkan" #: podcasts-gtk/src/widgets/show_menu.rs:199 msgid "Unsubscribed from {}" msgstr "Berhenti berlangganan dari {}" + +#~ msgid "Podcast app for GNOME" +#~ msgstr "Aplikasi Siniar untuk GNOME" -- 2.40.1 From dd599ac288feb55a85621828f5f951b779407772 Mon Sep 17 00:00:00 2001 From: Alexey Rubtsov Date: Fri, 14 Jan 2022 11:26:44 +0000 Subject: [PATCH 002/102] Add Russian translation --- podcasts-gtk/po/LINGUAS | 1 + podcasts-gtk/po/ru.po | 432 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 433 insertions(+) create mode 100644 podcasts-gtk/po/ru.po diff --git a/podcasts-gtk/po/LINGUAS b/podcasts-gtk/po/LINGUAS index 1be165f..f68af90 100644 --- a/podcasts-gtk/po/LINGUAS +++ b/podcasts-gtk/po/LINGUAS @@ -23,6 +23,7 @@ pl pt pt_BR ro +ru sk sl sr diff --git a/podcasts-gtk/po/ru.po b/podcasts-gtk/po/ru.po new file mode 100644 index 0000000..4659921 --- /dev/null +++ b/podcasts-gtk/po/ru.po @@ -0,0 +1,432 @@ +# Russian translation for podcasts. +# Copyright (C) 2022 podcasts's COPYRIGHT HOLDER +# This file is distributed under the same license as the podcasts package. +# Alexey Rubtsov , 2022. +# +msgid "" +msgstr "" +"Project-Id-Version: podcasts master\n" +"Report-Msgid-Bugs-To: https://gitlab.gnome.org/World/podcasts/issues\n" +"POT-Creation-Date: 2022-01-04 05:00+0000\n" +"PO-Revision-Date: 2022-01-13 15:19+0200\n" +"Language-Team: Russian \n" +"Language: ru\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" +"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" +"Last-Translator: Alexey Rubtsov \n" +"X-Generator: Poedit 3.0\n" + +#: podcasts-gtk/resources/org.gnome.Podcasts.gschema.xml.in:15 +msgid "Top position of the last open main window" +msgstr "Верхняя позиция последнего открытого главного окна" + +#: podcasts-gtk/resources/org.gnome.Podcasts.gschema.xml.in:19 +msgid "Left position of the last open main window" +msgstr "Левая позиция последнего открытого главного окна" + +#: podcasts-gtk/resources/org.gnome.Podcasts.gschema.xml.in:23 +msgid "Height of the last open main window" +msgstr "Высота последнего открытого главного окна" + +#: podcasts-gtk/resources/org.gnome.Podcasts.gschema.xml.in:27 +msgid "Width of the last open main window" +msgstr "Ширина последнего открытого главного окна" + +#: podcasts-gtk/resources/org.gnome.Podcasts.gschema.xml.in:31 +msgid "Maximized state of the last open main window" +msgstr "Максимизированное состояние последнего открытого главного окна" + +#: podcasts-gtk/resources/org.gnome.Podcasts.gschema.xml.in:36 +msgid "Enable or disable dark theme" +msgstr "Включить или отключить темную тему" + +#: podcasts-gtk/resources/org.gnome.Podcasts.gschema.xml.in:41 +msgid "Whether to periodically refresh content" +msgstr "Следует ли периодически обновлять содержимое" + +#: podcasts-gtk/resources/org.gnome.Podcasts.gschema.xml.in:46 +msgid "How many periods of time to wait between automatic refreshes" +msgstr "" +"Сколько периодов времени нужно ждать между автоматическими обновлениями" + +#: podcasts-gtk/resources/org.gnome.Podcasts.gschema.xml.in:50 +msgid "What period of time to wait between automatic refreshes" +msgstr "Какой период времени должен пройти между автоматическими обновлениями" + +#: podcasts-gtk/resources/org.gnome.Podcasts.gschema.xml.in:54 +msgid "Whether to refresh content after startup" +msgstr "Обновлять ли содержимое после запуска" + +#: podcasts-gtk/resources/org.gnome.Podcasts.gschema.xml.in:60 +msgid "How many periods of time to wait between automatic cleanups" +msgstr "Сколько периодов времени должно пройти между автоматическими очистками" + +#: podcasts-gtk/resources/org.gnome.Podcasts.gschema.xml.in:64 +msgid "What period of time to wait between automatic cleanups" +msgstr "Какой период времени должен пройти между автоматическими очистками" + +#. Weird magic I copy-pasted that sets the Application Name in the Shell. +#: podcasts-gtk/resources/org.gnome.Podcasts.desktop.in.in:3 +#: podcasts-gtk/resources/org.gnome.Podcasts.appdata.xml.in.in:4 +#: podcasts-gtk/resources/gtk/headerbar.ui:137 podcasts-gtk/src/app.rs:438 +#: podcasts-gtk/src/widgets/aboutdialog.rs:63 podcasts-gtk/src/window.rs:66 +msgid "Podcasts" +msgstr "Подкасты" + +#: podcasts-gtk/resources/org.gnome.Podcasts.desktop.in.in:4 +msgid "Listen to your favorite podcasts, right from your desktop." +msgstr "Слушайте любимые подкасты прямо со своего рабочего стола." + +#. Translators: Search terms to find this application. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! +#: podcasts-gtk/resources/org.gnome.Podcasts.desktop.in.in:13 +msgid "Podcast;RSS;" +msgstr "Подкаст;RSS;" + +#: podcasts-gtk/resources/org.gnome.Podcasts.appdata.xml.in.in:8 +msgid "Listen to your favorite shows" +msgstr "Слушайте свои любимые передачи" + +#: podcasts-gtk/resources/org.gnome.Podcasts.appdata.xml.in.in:10 +msgid "" +"Play, update, and manage your podcasts from a lightweight interface that " +"seamlessly integrates with GNOME. Podcasts can play various audio formats " +"and remember where you stopped listening. You can subscribe to shows via RSS/" +"Atom, iTunes, and Soundcloud links. Subscriptions from other apps can be " +"imported via OPML files." +msgstr "" +"Воспроизводите, обновляйте и управляйте своими подкастами с помощью легкого " +"интерфейса, который легко интегрируется в GNOME. Подкасты могут " +"воспроизводить различные аудиоформаты и запоминать, где вы остановили " +"прослушивание. Вы можете подписаться на передачи через ссылки RSS/Atom, " +"iTunes и Soundcloud. Подписки из других приложений могут быть импортированы " +"через файлы OPML." + +#: podcasts-gtk/resources/org.gnome.Podcasts.appdata.xml.in.in:134 +msgid "Jordan Petridis" +msgstr "Джордан Петридис" + +#: podcasts-gtk/resources/org.gnome.Podcasts.appdata.xml.in.in:135 +msgid "Julian Hofer" +msgstr "Джулиан Хофер" + +#: podcasts-gtk/resources/gtk/empty_view.ui:46 +msgid "This show does not have episodes yet" +msgstr "У этого шоу пока нет эпизодов" + +#: podcasts-gtk/resources/gtk/empty_view.ui:57 +msgid "If you think this is an error, please consider writing a bug report." +msgstr "" +"Если вы считаете, что это ошибка, пожалуйста, напишите сообщение об ошибке." + +#: podcasts-gtk/resources/gtk/empty_view.ui:91 +msgid "Get some shows" +msgstr "Получите несколько шоу" + +#: podcasts-gtk/resources/gtk/empty_view.ui:123 +msgid "Add new shows via feed URL" +msgstr "Добавляйте новые шоу через URL-адрес фида" + +#: podcasts-gtk/resources/gtk/empty_view.ui:152 +msgid "Import shows from another device" +msgstr "Импорт шоу с другого устройства" + +#: podcasts-gtk/resources/gtk/episode_description.ui:49 +msgid "Episode Details" +msgstr "Подробности эпизода" + +#: podcasts-gtk/resources/gtk/episode_description.ui:64 +#: podcasts-gtk/resources/gtk/headerbar.ui:186 +msgid "Back" +msgstr "Назад" + +#: podcasts-gtk/resources/gtk/episode_description.ui:148 +msgid "Podcast Title" +msgstr "Название подкаста" + +#: podcasts-gtk/resources/gtk/episode_description.ui:186 +msgid "Duration - Date" +msgstr "Продолжительность - Дата" + +#: podcasts-gtk/resources/gtk/episode_description.ui:241 +msgid "Episode Description" +msgstr "Описание эпизода" + +#: podcasts-gtk/resources/gtk/episode_menu.ui:36 +msgid "Go to Show" +msgstr "Перейти к шоу" + +#: podcasts-gtk/resources/gtk/episode_menu.ui:40 +msgid "Copy Episode Url" +msgstr "Копирование Url эпизода" + +#: podcasts-gtk/resources/gtk/episode_widget.ui:82 +msgid "You’ve already listened to this episode." +msgstr "Вы уже прослушали этот эпизод." + +#: podcasts-gtk/resources/gtk/episode_widget.ui:187 +msgid "Calculating episode size…" +msgstr "Расчет размера эпизода.." + +#: podcasts-gtk/resources/gtk/episode_widget.ui:214 +msgid "Play this episode" +msgstr "Воспроизвести этот эпизод" + +#: podcasts-gtk/resources/gtk/episode_widget.ui:230 +msgid "Cancel the download process" +msgstr "Отменить процесс загрузки" + +#: podcasts-gtk/resources/gtk/episode_widget.ui:250 +msgid "Download this episode" +msgstr "Скачать этот эпизод" + +#: podcasts-gtk/resources/gtk/hamburger.ui:7 +msgid "_Check for New Episodes" +msgstr "_Проверить наличие новых эпизодов" + +#: podcasts-gtk/resources/gtk/hamburger.ui:12 +msgid "_Import Shows" +msgstr "_Импортировать шоу" + +#: podcasts-gtk/resources/gtk/hamburger.ui:16 +msgid "_Export Shows" +msgstr "_Экспорт шоу" + +#: podcasts-gtk/resources/gtk/hamburger.ui:22 +msgid "_Keyboard Shortcuts" +msgstr "_Горячие клавиши" + +#: podcasts-gtk/resources/gtk/hamburger.ui:30 +msgid "_About Podcasts" +msgstr "_О программе Подкасты" + +#: podcasts-gtk/resources/gtk/headerbar.ui:35 +#: podcasts-gtk/resources/gtk/headerbar.ui:165 +msgid "Add a new feed" +msgstr "Добавить новый канал" + +#: podcasts-gtk/resources/gtk/headerbar.ui:53 +msgid "Enter feed address to add" +msgstr "Введите адрес канала для добавления" + +#: podcasts-gtk/resources/gtk/headerbar.ui:79 +msgid "Add" +msgstr "Добавить" + +#: podcasts-gtk/resources/gtk/headerbar.ui:150 +msgid "Show Title" +msgstr "Показать заголовок" + +#: podcasts-gtk/resources/gtk/help-overlay.ui:12 +msgid "General" +msgstr "Общие" + +#: podcasts-gtk/resources/gtk/help-overlay.ui:18 +msgctxt "shortcut window" +msgid "Check for new episodes" +msgstr "Проверить наличие новых эпизодов" + +#: podcasts-gtk/resources/gtk/help-overlay.ui:25 +msgctxt "shortcut window" +msgid "Quit the application" +msgstr "Закрыть приложение" + +#: podcasts-gtk/resources/gtk/home_view.ui:56 +msgid "Today" +msgstr "Сегодня" + +#: podcasts-gtk/resources/gtk/home_view.ui:89 +msgid "Yesterday" +msgstr "Вчера" + +#: podcasts-gtk/resources/gtk/home_view.ui:122 +msgid "This Week" +msgstr "На этой неделе" + +#: podcasts-gtk/resources/gtk/home_view.ui:155 +msgid "This Month" +msgstr "В этом месяце" + +#: podcasts-gtk/resources/gtk/home_view.ui:189 +msgid "Older" +msgstr "Раньше" + +#: podcasts-gtk/resources/gtk/inapp_notif.ui:69 +msgid "An in-app action notification" +msgstr "Уведомление о действии в приложении" + +#: podcasts-gtk/resources/gtk/inapp_notif.ui:75 +msgid "Undo" +msgstr "Отменить" + +#: podcasts-gtk/resources/gtk/player_dialog.ui:14 +msgid "Now Playing" +msgstr "Воспроизводится" + +#: podcasts-gtk/resources/gtk/player_rate.ui:32 +msgid "Change the playback speed" +msgstr "Изменение скорости воспроизведения" + +#: podcasts-gtk/resources/gtk/player_rate.ui:46 +#: podcasts-gtk/resources/gtk/player_rate.ui:85 +msgid "1.00×" +msgstr "1.00×" + +#: podcasts-gtk/resources/gtk/player_rate.ui:65 +msgid "2.00×" +msgstr "2.00×" + +#: podcasts-gtk/resources/gtk/player_rate.ui:70 +msgid "1.75×" +msgstr "1.75×" + +#: podcasts-gtk/resources/gtk/player_rate.ui:75 +msgid "1.50×" +msgstr "1.50×" + +#: podcasts-gtk/resources/gtk/player_rate.ui:80 +msgid "1.25×" +msgstr "1.25×" + +#: podcasts-gtk/resources/gtk/player_rate.ui:90 +msgid "0.90×" +msgstr "0.90×" + +#: podcasts-gtk/resources/gtk/player_rate.ui:95 +msgid "0.75×" +msgstr "0.75×" + +#: podcasts-gtk/resources/gtk/player_toolbar.ui:97 +msgid "Rewind 10 seconds" +msgstr "Перемотка на 10 секунд" + +#: podcasts-gtk/resources/gtk/player_toolbar.ui:107 +msgid "Play" +msgstr "Воспроизвести" + +#: podcasts-gtk/resources/gtk/player_toolbar.ui:118 +msgid "Pause" +msgstr "Приостановить" + +#: podcasts-gtk/resources/gtk/player_toolbar.ui:129 +msgid "Fast forward 10 seconds" +msgstr "Перемотка вперед на 10 секунд" + +#: podcasts-gtk/resources/gtk/secondary_menu.ui:7 +msgid "_Mark All Episodes as Played" +msgstr "Отметить _все эпизоды как сыгранные" + +#: podcasts-gtk/resources/gtk/secondary_menu.ui:11 +msgid "_Website" +msgstr "_Веб-сайт" + +#: podcasts-gtk/resources/gtk/secondary_menu.ui:15 +msgid "_Unsubscribe" +msgstr "_Отказаться от подписки" + +#: podcasts-gtk/resources/gtk/show_menu.ui:36 +msgid "Open Website" +msgstr "Открыть Сайт" + +#: podcasts-gtk/resources/gtk/show_menu.ui:40 +msgid "Mark All as Played" +msgstr "Отметить все как воспроизведенные" + +#: podcasts-gtk/resources/gtk/show_menu.ui:46 +msgid "Unsubscribe" +msgstr "Отказаться от подписки" + +#: podcasts-gtk/resources/gtk/show_widget.ui:98 +msgid "Read More" +msgstr "Читать далее" + +#: podcasts-gtk/src/app.rs:353 +msgid "Fetching new episodes" +msgstr "Новые эпизоды" + +#: podcasts-gtk/src/stacks/content.rs:58 +msgid "New" +msgstr "Новые" + +#: podcasts-gtk/src/stacks/content.rs:59 +msgid "Shows" +msgstr "Шоу" + +#: podcasts-gtk/src/utils.rs:501 +msgid "Select the file from which to you want to import shows." +msgstr "Выберите файл, из которого вы хотите импортировать шоу." + +#: podcasts-gtk/src/utils.rs:504 +msgid "_Import" +msgstr "_Импортировать" + +#: podcasts-gtk/src/utils.rs:513 podcasts-gtk/src/utils.rs:562 +msgid "OPML file" +msgstr "OPML-файл" + +#: podcasts-gtk/src/utils.rs:531 +msgid "Failed to parse the imported file" +msgstr "Не удалось разобрать импортированный файл" + +#: podcasts-gtk/src/utils.rs:536 podcasts-gtk/src/utils.rs:581 +msgid "Selected file could not be accessed." +msgstr "Не удалось получить доступ к выбранному файлу." + +#: podcasts-gtk/src/utils.rs:547 +msgid "Export shows to…" +msgstr "_Экспорт шоу в…" + +#: podcasts-gtk/src/utils.rs:550 +msgid "_Export" +msgstr "_Экспортировать" + +#: podcasts-gtk/src/utils.rs:551 +msgid "_Cancel" +msgstr "О_тменить" + +#. Translators: This is the string of the suggested name for the exported opml file +#: podcasts-gtk/src/utils.rs:555 +msgid "gnome-podcasts-exported-shows" +msgstr "gnome-podcasts-exported-shows" + +#: podcasts-gtk/src/utils.rs:575 +msgid "GNOME Podcasts Subscriptions" +msgstr "Подписки на подкасты GNOME" + +#: podcasts-gtk/src/utils.rs:576 +msgid "Failed to export podcasts" +msgstr "Не удалось экспортировать подкасты" + +#: podcasts-gtk/src/widgets/aboutdialog.rs:58 +msgid "Podcast Client for the GNOME Desktop." +msgstr "Клиент подкастов для рабочего стола GNOME." + +#: podcasts-gtk/src/widgets/aboutdialog.rs:65 +msgid "Learn more about GNOME Podcasts" +msgstr "Узнайте больше о подкастах GNOME" + +#: podcasts-gtk/src/widgets/aboutdialog.rs:69 +msgid "translator-credits" +msgstr "Alexey Rubtsov , 2022" + +#: podcasts-gtk/src/widgets/episode.rs:145 +msgid "{} min" +msgstr "{} мин." + +#: podcasts-gtk/src/widgets/episode_description.rs:165 +msgid "Copied URL to clipboard!" +msgstr "URL в буфере обмена!" + +#: podcasts-gtk/src/widgets/player.rs:910 +msgid "The media player was unable to execute an action." +msgstr "Медиаплеер не смог выполнить действие." + +#: podcasts-gtk/src/widgets/show_menu.rs:194 +msgid "Marked all episodes as listened" +msgstr "Отметил все эпизоды как прослушанные" + +#: podcasts-gtk/src/widgets/show_menu.rs:199 +msgid "Unsubscribed from {}" +msgstr "Отказался от подписки на {}" -- 2.40.1 From 6614bb62ecbec7c3b18ea7fe44beb50fe7942b27 Mon Sep 17 00:00:00 2001 From: Jan Beich Date: Thu, 20 Jan 2022 01:27:48 +0000 Subject: [PATCH 003/102] meson: drop unused argument for i18n.merge_file() Ignored in Meson < 0.60.0, deprecated since 0.60.1 and fatal since 0.61.0. podcasts-gtk/resources/meson.build:5:0: ERROR: Function does not take positional arguments. podcasts-gtk/resources/meson.build:30:0: ERROR: Function does not take positional arguments. --- podcasts-gtk/resources/meson.build | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/podcasts-gtk/resources/meson.build b/podcasts-gtk/resources/meson.build index c1f1ee9..8714808 100644 --- a/podcasts-gtk/resources/meson.build +++ b/podcasts-gtk/resources/meson.build @@ -2,7 +2,7 @@ subdir('icons') desktop_conf = configuration_data() desktop_conf.set('icon', application_id) -desktop_file = i18n.merge_file ('desktop-file', +desktop_file = i18n.merge_file ( type: 'desktop', input: configure_file( input: files('org.gnome.Podcasts.desktop.in.in'), @@ -27,7 +27,7 @@ endif appdata_conf = configuration_data() appdata_conf.set('appid', application_id) -appdata_file = i18n.merge_file ('appdata-file', +appdata_file = i18n.merge_file ( input: configure_file( input: files('org.gnome.Podcasts.appdata.xml.in.in'), output: 'org.gnome.Podcasts.appdata.xml.in', -- 2.40.1 From 0e8ef1350f5fa940945a0ea9985ff6a6e7c569ea Mon Sep 17 00:00:00 2001 From: Charles Monzat Date: Tue, 25 Jan 2022 07:23:54 +0000 Subject: [PATCH 004/102] Update French translation --- podcasts-gtk/po/fr.po | 266 ++++++++++++++++++++++++++---------------- 1 file changed, 168 insertions(+), 98 deletions(-) diff --git a/podcasts-gtk/po/fr.po b/podcasts-gtk/po/fr.po index 4a4e55a..d791dfb 100644 --- a/podcasts-gtk/po/fr.po +++ b/podcasts-gtk/po/fr.po @@ -5,80 +5,80 @@ # Alexandre Franke , 2018, 2020 # Thibault Martin , 2020. # Sylvestris , 2020. +# Charles Monzat , 2022. # msgid "" msgstr "" "Project-Id-Version: podcasts master\n" "Report-Msgid-Bugs-To: https://gitlab.gnome.org/World/podcasts/issues\n" -"POT-Creation-Date: 2020-08-23 07:57+0000\n" -"PO-Revision-Date: 2020-08-27 10:52+0200\n" -"Last-Translator: Sylvestris \n" -"Language-Team: French \n" +"POT-Creation-Date: 2021-11-28 07:07+0000\n" +"PO-Revision-Date: 2022-01-24 20:39+0100\n" +"Last-Translator: Charles Monzat \n" +"Language-Team: GNOME French Team \n" "Language: fr\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=2; plural=(n > 1)\n" -"X-Generator: Gtranslator 3.36.0\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" +"X-Generator: Gtranslator 40.0\n" -#: podcasts-gtk/resources/org.gnome.Podcasts.gschema.xml:15 +#: podcasts-gtk/resources/org.gnome.Podcasts.gschema.xml.in:15 msgid "Top position of the last open main window" msgstr "Position supérieure de la dernière fenêtre principale ouverte" -#: podcasts-gtk/resources/org.gnome.Podcasts.gschema.xml:19 +#: podcasts-gtk/resources/org.gnome.Podcasts.gschema.xml.in:19 msgid "Left position of the last open main window" msgstr "Position gauche de la dernière fenêtre principale ouverte" -#: podcasts-gtk/resources/org.gnome.Podcasts.gschema.xml:23 +#: podcasts-gtk/resources/org.gnome.Podcasts.gschema.xml.in:23 msgid "Height of the last open main window" msgstr "Hauteur de la dernière fenêtre principale ouverte" -#: podcasts-gtk/resources/org.gnome.Podcasts.gschema.xml:27 +#: podcasts-gtk/resources/org.gnome.Podcasts.gschema.xml.in:27 msgid "Width of the last open main window" msgstr "Largeur de la dernière fenêtre principale ouverte" -#: podcasts-gtk/resources/org.gnome.Podcasts.gschema.xml:31 +#: podcasts-gtk/resources/org.gnome.Podcasts.gschema.xml.in:31 msgid "Maximized state of the last open main window" msgstr "État maximisé de la dernière fenêtre principale ouverte" -#: podcasts-gtk/resources/org.gnome.Podcasts.gschema.xml:36 +#: podcasts-gtk/resources/org.gnome.Podcasts.gschema.xml.in:36 msgid "Enable or disable dark theme" msgstr "Activer ou désactiver le thème sombre" -#: podcasts-gtk/resources/org.gnome.Podcasts.gschema.xml:41 +#: podcasts-gtk/resources/org.gnome.Podcasts.gschema.xml.in:41 msgid "Whether to periodically refresh content" msgstr "Indique s’il faut actualiser périodiquement le contenu" -#: podcasts-gtk/resources/org.gnome.Podcasts.gschema.xml:46 +#: podcasts-gtk/resources/org.gnome.Podcasts.gschema.xml.in:46 msgid "How many periods of time to wait between automatic refreshes" msgstr "Nombre de délais à attendre entre les actualisations automatiques" -#: podcasts-gtk/resources/org.gnome.Podcasts.gschema.xml:50 +#: podcasts-gtk/resources/org.gnome.Podcasts.gschema.xml.in:50 msgid "What period of time to wait between automatic refreshes" msgstr "Délai entre les actualisations automatiques" -#: podcasts-gtk/resources/org.gnome.Podcasts.gschema.xml:54 +#: podcasts-gtk/resources/org.gnome.Podcasts.gschema.xml.in:54 msgid "Whether to refresh content after startup" msgstr "Indique s’il faut actualiser le contenu au démarrage" -#: podcasts-gtk/resources/org.gnome.Podcasts.gschema.xml:60 +#: podcasts-gtk/resources/org.gnome.Podcasts.gschema.xml.in:60 msgid "How many periods of time to wait between automatic cleanups" msgstr "Nombre de périodes de délai entre les nettoyages automatiques" -#: podcasts-gtk/resources/org.gnome.Podcasts.gschema.xml:64 +#: podcasts-gtk/resources/org.gnome.Podcasts.gschema.xml.in:64 msgid "What period of time to wait between automatic cleanups" msgstr "Délai entre les nettoyages automatiques" #. Weird magic I copy-pasted that sets the Application Name in the Shell. #: podcasts-gtk/resources/org.gnome.Podcasts.desktop.in.in:3 #: podcasts-gtk/resources/org.gnome.Podcasts.appdata.xml.in.in:4 -#: podcasts-gtk/resources/gtk/headerbar.ui:158 podcasts-gtk/src/app.rs:365 -#: podcasts-gtk/src/widgets/aboutdialog.rs:56 podcasts-gtk/src/window.rs:66 +#: podcasts-gtk/resources/gtk/headerbar.ui:137 podcasts-gtk/src/app.rs:438 +#: podcasts-gtk/src/widgets/aboutdialog.rs:63 podcasts-gtk/src/window.rs:66 msgid "Podcasts" msgstr "Podcasts" #: podcasts-gtk/resources/org.gnome.Podcasts.desktop.in.in:4 -#: podcasts-gtk/resources/org.gnome.Podcasts.appdata.xml.in.in:10 msgid "Listen to your favorite podcasts, right from your desktop." msgstr "Écouter vos podcasts favoris directement sur votre bureau." @@ -88,50 +88,101 @@ msgid "Podcast;RSS;" msgstr "Podcast;RSS;Baladodiffusion;Émissions;" #: podcasts-gtk/resources/org.gnome.Podcasts.appdata.xml.in.in:8 -msgid "Podcast app for GNOME" -msgstr "Application de podcast pour GNOME" +#| msgid "Listen to your favorite podcasts, right from your desktop." +msgid "Listen to your favorite shows" +msgstr "Écouter vos émissions favorites" -#: podcasts-gtk/resources/org.gnome.Podcasts.appdata.xml.in.in:92 +#: podcasts-gtk/resources/org.gnome.Podcasts.appdata.xml.in.in:10 +msgid "" +"Play, update, and manage your podcasts from a lightweight interface that " +"seamlessly integrates with GNOME. Podcasts can play various audio formats " +"and remember where you stopped listening. You can subscribe to shows via RSS/" +"Atom, iTunes, and Soundcloud links. Subscriptions from other apps can be " +"imported via OPML files." +msgstr "" +"Lisez, mettez à jour et gérez vos podcasts à partir d’une interface légère " +"qui s’intègre parfaitement à GNOME. Les podcasts peuvent lire divers formats " +"audio et se rappeler où vous avez stoppé l’écoute. Vous pouvez vous abonner " +"à des émissions via des liens RSS/Atom, iTunes et Soundcloud. Les " +"abonnements d’autres applications peuvent être importés via des fichiers " +"OPML." + +#: podcasts-gtk/resources/org.gnome.Podcasts.appdata.xml.in.in:117 msgid "Jordan Petridis" msgstr "Jordan Petridis" +#: podcasts-gtk/resources/org.gnome.Podcasts.appdata.xml.in.in:118 +msgid "Julian Hofer" +msgstr "Julian Hofer" + #: podcasts-gtk/resources/gtk/empty_view.ui:46 msgid "This show does not have episodes yet" msgstr "Cette émission n’a pas encore d’épisode" -#: podcasts-gtk/resources/gtk/empty_view.ui:62 +#: podcasts-gtk/resources/gtk/empty_view.ui:57 msgid "If you think this is an error, please consider writing a bug report." msgstr "Si vous pensez qu’il s’agit d’une erreur, faites un rapport de bogue." -#: podcasts-gtk/resources/gtk/empty_view.ui:106 +#: podcasts-gtk/resources/gtk/empty_view.ui:91 msgid "Get some shows" msgstr "Obtenir des émissions" -#: podcasts-gtk/resources/gtk/empty_view.ui:143 +#: podcasts-gtk/resources/gtk/empty_view.ui:123 msgid "Add new shows via feed URL" msgstr "Ajouter de nouvelles émissions via une URL de flux" -#: podcasts-gtk/resources/gtk/empty_view.ui:172 +#: podcasts-gtk/resources/gtk/empty_view.ui:152 msgid "Import shows from another device" msgstr "Importer des émissions à partir d’un autre appareil" -#: podcasts-gtk/resources/gtk/episode_widget.ui:79 +#: podcasts-gtk/resources/gtk/episode_description.ui:49 +msgid "Episode Details" +msgstr "Détails de l’épisode" + +#: podcasts-gtk/resources/gtk/episode_description.ui:64 +#: podcasts-gtk/resources/gtk/headerbar.ui:186 +msgid "Back" +msgstr "Retour" + +#: podcasts-gtk/resources/gtk/episode_description.ui:148 +#| msgid "Podcasts" +msgid "Podcast Title" +msgstr "Titre du podcast" + +#: podcasts-gtk/resources/gtk/episode_description.ui:186 +msgid "Duration - Date" +msgstr "Durée - date" + +#: podcasts-gtk/resources/gtk/episode_description.ui:241 +msgid "Episode Description" +msgstr "Description de l’épisode" + +#: podcasts-gtk/resources/gtk/episode_menu.ui:36 +#| msgid "_Import Shows" +msgid "Go to Show" +msgstr "Aller à l’émission" + +#: podcasts-gtk/resources/gtk/episode_menu.ui:40 +msgid "Copy Episode Url" +msgstr "Copier l’URL de l’épisode" + +#: podcasts-gtk/resources/gtk/episode_widget.ui:82 msgid "You’ve already listened to this episode." msgstr "Vous avez déjà écouté cet épisode." -#: podcasts-gtk/resources/gtk/episode_widget.ui:217 +#: podcasts-gtk/resources/gtk/episode_widget.ui:187 msgid "Calculating episode size…" msgstr "Calcul de la taille de l’épisode…" -#: podcasts-gtk/resources/gtk/episode_widget.ui:260 +#: podcasts-gtk/resources/gtk/episode_widget.ui:214 msgid "Play this episode" msgstr "Lire cet épisode" -#: podcasts-gtk/resources/gtk/episode_widget.ui:281 +#: podcasts-gtk/resources/gtk/episode_widget.ui:230 msgid "Cancel the download process" msgstr "Annuler le téléchargement" -#: podcasts-gtk/resources/gtk/episode_widget.ui:304 +#: podcasts-gtk/resources/gtk/episode_widget.ui:250 msgid "Download this episode" msgstr "Télécharger cet épisode" @@ -156,7 +207,7 @@ msgid "_About Podcasts" msgstr "À _propos de Podcasts" #: podcasts-gtk/resources/gtk/headerbar.ui:35 -#: podcasts-gtk/resources/gtk/headerbar.ui:186 +#: podcasts-gtk/resources/gtk/headerbar.ui:165 msgid "Add a new feed" msgstr "Ajouter un nouveau flux" @@ -164,18 +215,14 @@ msgstr "Ajouter un nouveau flux" msgid "Enter feed address to add" msgstr "Entrer l’adresse du flux à ajouter" -#: podcasts-gtk/resources/gtk/headerbar.ui:89 +#: podcasts-gtk/resources/gtk/headerbar.ui:79 msgid "Add" msgstr "Ajouter" -#: podcasts-gtk/resources/gtk/headerbar.ui:171 +#: podcasts-gtk/resources/gtk/headerbar.ui:150 msgid "Show Title" msgstr "Titre de l’émission" -#: podcasts-gtk/resources/gtk/headerbar.ui:207 -msgid "Back" -msgstr "Retour" - #: podcasts-gtk/resources/gtk/help-overlay.ui:12 msgid "General" msgstr "Général" @@ -194,27 +241,27 @@ msgstr "Quitter l’application" msgid "Today" msgstr "Aujourd’hui" -#: podcasts-gtk/resources/gtk/home_view.ui:112 +#: podcasts-gtk/resources/gtk/home_view.ui:89 msgid "Yesterday" msgstr "Hier" -#: podcasts-gtk/resources/gtk/home_view.ui:168 +#: podcasts-gtk/resources/gtk/home_view.ui:122 msgid "This Week" msgstr "Cette semaine" -#: podcasts-gtk/resources/gtk/home_view.ui:224 +#: podcasts-gtk/resources/gtk/home_view.ui:155 msgid "This Month" msgstr "Ce mois-ci" -#: podcasts-gtk/resources/gtk/home_view.ui:281 +#: podcasts-gtk/resources/gtk/home_view.ui:189 msgid "Older" msgstr "Plus ancien" -#: podcasts-gtk/resources/gtk/inapp_notif.ui:101 +#: podcasts-gtk/resources/gtk/inapp_notif.ui:69 msgid "An in-app action notification" msgstr "Une notification d’action intégrée à l’application" -#: podcasts-gtk/resources/gtk/inapp_notif.ui:112 +#: podcasts-gtk/resources/gtk/inapp_notif.ui:75 msgid "Undo" msgstr "Annuler" @@ -226,45 +273,49 @@ msgstr "Lecture en cours" msgid "Change the playback speed" msgstr "Changer la vitesse de lecture" -#: podcasts-gtk/resources/gtk/player_rate.ui:47 +#: podcasts-gtk/resources/gtk/player_rate.ui:46 +#: podcasts-gtk/resources/gtk/player_rate.ui:85 msgid "1.00×" msgstr "1,00×" -#: podcasts-gtk/resources/gtk/player_rate.ui:88 -#| msgid "1.5 speed rate" -msgid "Double speed rate" -msgstr "Débit × 2" +#: podcasts-gtk/resources/gtk/player_rate.ui:65 +#| msgid "1.00×" +msgid "2.00×" +msgstr "2,00×" + +#: podcasts-gtk/resources/gtk/player_rate.ui:70 +msgid "1.75×" +msgstr "1,75×" -#: podcasts-gtk/resources/gtk/player_rate.ui:97 -#| msgid "1.5 speed rate" -msgid "1.75 speed rate" -msgstr "Débit × 1,75" +#: podcasts-gtk/resources/gtk/player_rate.ui:75 +msgid "1.50×" +msgstr "1,50×" -#: podcasts-gtk/resources/gtk/player_rate.ui:106 -msgid "1.5 speed rate" -msgstr "Débit × 1,5" +#: podcasts-gtk/resources/gtk/player_rate.ui:80 +msgid "1.25×" +msgstr "1,25×" -#: podcasts-gtk/resources/gtk/player_rate.ui:115 -msgid "1.25 speed rate" -msgstr "Débit × 1,25" +#: podcasts-gtk/resources/gtk/player_rate.ui:90 +msgid "0.90×" +msgstr "0,90×" -#: podcasts-gtk/resources/gtk/player_rate.ui:124 -msgid "Normal speed" -msgstr "Vitesse normale" +#: podcasts-gtk/resources/gtk/player_rate.ui:95 +msgid "0.75×" +msgstr "0,75×" #: podcasts-gtk/resources/gtk/player_toolbar.ui:97 msgid "Rewind 10 seconds" msgstr "Reculer de 10 secondes" -#: podcasts-gtk/resources/gtk/player_toolbar.ui:112 +#: podcasts-gtk/resources/gtk/player_toolbar.ui:107 msgid "Play" msgstr "Lire" -#: podcasts-gtk/resources/gtk/player_toolbar.ui:128 +#: podcasts-gtk/resources/gtk/player_toolbar.ui:118 msgid "Pause" msgstr "Pause" -#: podcasts-gtk/resources/gtk/player_toolbar.ui:144 +#: podcasts-gtk/resources/gtk/player_toolbar.ui:129 msgid "Fast forward 10 seconds" msgstr "Avancer de 10 secondes" @@ -280,114 +331,133 @@ msgstr "Site _Web" msgid "_Unsubscribe" msgstr "Se _désabonner" -#: podcasts-gtk/resources/gtk/show_menu.ui:51 +#: podcasts-gtk/resources/gtk/show_menu.ui:36 msgid "Open Website" msgstr "Aller sur le site Web" -#: podcasts-gtk/resources/gtk/show_menu.ui:64 +#: podcasts-gtk/resources/gtk/show_menu.ui:40 msgid "Mark All as Played" -msgstr "Marquer tout comme lu" +msgstr "Tout marquer comme lu" -#: podcasts-gtk/resources/gtk/show_menu.ui:89 +#: podcasts-gtk/resources/gtk/show_menu.ui:46 msgid "Unsubscribe" msgstr "Se désabonner" -#: podcasts-gtk/resources/gtk/show_widget.ui:99 +#: podcasts-gtk/resources/gtk/show_widget.ui:98 msgid "Read More" msgstr "En savoir plus" -#: podcasts-gtk/src/app.rs:302 +#: podcasts-gtk/src/app.rs:353 msgid "Fetching new episodes" msgstr "Récupérer les nouveaux épisodes" -#: podcasts-gtk/src/stacks/content.rs:54 +#: podcasts-gtk/src/stacks/content.rs:58 msgid "New" msgstr "Nouveau" -#: podcasts-gtk/src/stacks/content.rs:55 +#: podcasts-gtk/src/stacks/content.rs:59 msgid "Shows" msgstr "Émissions" -#: podcasts-gtk/src/utils.rs:437 +#: podcasts-gtk/src/utils.rs:501 msgid "Select the file from which to you want to import shows." msgstr "Sélectionnez le fichier à partir duquel importer les émissions." -#: podcasts-gtk/src/utils.rs:440 +#: podcasts-gtk/src/utils.rs:504 msgid "_Import" msgstr "_Importer" -#: podcasts-gtk/src/utils.rs:449 podcasts-gtk/src/utils.rs:498 +#: podcasts-gtk/src/utils.rs:513 podcasts-gtk/src/utils.rs:562 msgid "OPML file" msgstr "Fichier OPML" -#: podcasts-gtk/src/utils.rs:467 +#: podcasts-gtk/src/utils.rs:531 msgid "Failed to parse the imported file" msgstr "Échec de l’analyse du fichier importé" -#: podcasts-gtk/src/utils.rs:472 podcasts-gtk/src/utils.rs:517 +#: podcasts-gtk/src/utils.rs:536 podcasts-gtk/src/utils.rs:581 msgid "Selected file could not be accessed." msgstr "Le fichier sélectionné n’est pas accessible." -#: podcasts-gtk/src/utils.rs:483 +#: podcasts-gtk/src/utils.rs:547 msgid "Export shows to…" msgstr "Exporter les émissions vers…" -#: podcasts-gtk/src/utils.rs:486 +#: podcasts-gtk/src/utils.rs:550 msgid "_Export" msgstr "_Exporter" -#: podcasts-gtk/src/utils.rs:487 +#: podcasts-gtk/src/utils.rs:551 msgid "_Cancel" msgstr "A_nnuler" #. Translators: This is the string of the suggested name for the exported opml file -#: podcasts-gtk/src/utils.rs:491 +#: podcasts-gtk/src/utils.rs:555 msgid "gnome-podcasts-exported-shows" msgstr "gnome-podcasts-émissions-exportées" -#: podcasts-gtk/src/utils.rs:511 +#: podcasts-gtk/src/utils.rs:575 msgid "GNOME Podcasts Subscriptions" msgstr "Abonnements GNOME Podcasts" -#: podcasts-gtk/src/utils.rs:512 +#: podcasts-gtk/src/utils.rs:576 msgid "Failed to export podcasts" msgstr "Échec de l’exportation des podcasts" -#: podcasts-gtk/src/widgets/aboutdialog.rs:51 +#: podcasts-gtk/src/widgets/aboutdialog.rs:58 msgid "Podcast Client for the GNOME Desktop." msgstr "Client de podcast pour le bureau GNOME." -#: podcasts-gtk/src/widgets/aboutdialog.rs:58 +#: podcasts-gtk/src/widgets/aboutdialog.rs:65 msgid "Learn more about GNOME Podcasts" msgstr "En apprendre plus sur GNOME Podcasts" -#: podcasts-gtk/src/widgets/aboutdialog.rs:63 +#: podcasts-gtk/src/widgets/aboutdialog.rs:69 msgid "translator-credits" msgstr "" "Alexandre Franke\n" -"Thibault Martin" +"Thibault Martin\n" +"Charles Monzat" -#: podcasts-gtk/src/widgets/episode.rs:149 +#: podcasts-gtk/src/widgets/episode.rs:145 msgid "{} min" msgstr "{} min" -#: podcasts-gtk/src/widgets/player.rs:847 +#: podcasts-gtk/src/widgets/episode_description.rs:165 +msgid "Copied URL to clipboard!" +msgstr "URL copiée dans le presse-papiers !" + +#: podcasts-gtk/src/widgets/player.rs:902 msgid "The media player was unable to execute an action." msgstr "Le lecteur n’a pas pu réaliser l’action." -#: podcasts-gtk/src/widgets/show_menu.rs:172 +#: podcasts-gtk/src/widgets/show_menu.rs:194 msgid "Marked all episodes as listened" msgstr "Marquer tous les épisodes comme écoutés" -#: podcasts-gtk/src/widgets/show_menu.rs:177 +#: podcasts-gtk/src/widgets/show_menu.rs:199 msgid "Unsubscribed from {}" msgstr "Se désabonner de {}" -#~ msgid "1.50×" -#~ msgstr "1,50×" +#~ msgid "Podcast app for GNOME" +#~ msgstr "Application de podcast pour GNOME" + +#~| msgid "1.5 speed rate" +#~ msgid "Double speed rate" +#~ msgstr "Débit × 2" + +#~| msgid "1.5 speed rate" +#~ msgid "1.75 speed rate" +#~ msgstr "Débit × 1,75" + +#~ msgid "1.5 speed rate" +#~ msgstr "Débit × 1,5" + +#~ msgid "1.25 speed rate" +#~ msgstr "Débit × 1,25" -#~ msgid "1.25×" -#~ msgstr "1,25×" +#~ msgid "Normal speed" +#~ msgstr "Vitesse normale" #~ msgid "@icon@" #~ msgstr "@icon@" -- 2.40.1 From 78325a5748878faadca044d907e94af51d0dbe67 Mon Sep 17 00:00:00 2001 From: Luming Zh Date: Tue, 1 Feb 2022 22:56:48 +0000 Subject: [PATCH 005/102] Update Chinese (China) translation --- podcasts-gtk/po/zh_CN.po | 128 +++++++++++++++++++++++++++------------ 1 file changed, 90 insertions(+), 38 deletions(-) diff --git a/podcasts-gtk/po/zh_CN.po b/podcasts-gtk/po/zh_CN.po index b172809..ea01a75 100644 --- a/podcasts-gtk/po/zh_CN.po +++ b/podcasts-gtk/po/zh_CN.po @@ -3,21 +3,22 @@ # This file is distributed under the same license as the podcasts package. # Tranquilo Chan , 2020. # Dingzhong Chen , 2018-2021. +# lumingzh , 2022. # msgid "" msgstr "" "Project-Id-Version: podcasts master\n" "Report-Msgid-Bugs-To: https://gitlab.gnome.org/World/podcasts/issues\n" -"POT-Creation-Date: 2021-06-24 16:39+0000\n" -"PO-Revision-Date: 2021-06-27 15:32-0400\n" -"Last-Translator: Boyuan Yang <073plan@gmail.com>\n" +"POT-Creation-Date: 2021-11-28 07:07+0000\n" +"PO-Revision-Date: 2022-02-01 13:17+0800\n" +"Last-Translator: lumingzh \n" "Language-Team: Chinese - China \n" "Language: zh_CN\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Generator: Poedit 2.4.2\n" -"Plural-Forms: nplurals=1; plural=0;\n" +"X-Generator: Gtranslator 41.0\n" +"Plural-Forms: nplurals=1; plural=0\n" #: podcasts-gtk/resources/org.gnome.Podcasts.gschema.xml.in:15 msgid "Top position of the last open main window" @@ -70,13 +71,12 @@ msgstr "自动清理之间要等待的时间段" #. Weird magic I copy-pasted that sets the Application Name in the Shell. #: podcasts-gtk/resources/org.gnome.Podcasts.desktop.in.in:3 #: podcasts-gtk/resources/org.gnome.Podcasts.appdata.xml.in.in:4 -#: podcasts-gtk/resources/gtk/headerbar.ui:137 podcasts-gtk/src/app.rs:388 -#: podcasts-gtk/src/widgets/aboutdialog.rs:63 podcasts-gtk/src/window.rs:64 +#: podcasts-gtk/resources/gtk/headerbar.ui:137 podcasts-gtk/src/app.rs:438 +#: podcasts-gtk/src/widgets/aboutdialog.rs:63 podcasts-gtk/src/window.rs:66 msgid "Podcasts" msgstr "播客" #: podcasts-gtk/resources/org.gnome.Podcasts.desktop.in.in:4 -#: podcasts-gtk/resources/org.gnome.Podcasts.appdata.xml.in.in:10 msgid "Listen to your favorite podcasts, right from your desktop." msgstr "直接在您的桌面上收听喜欢的播客。" @@ -86,13 +86,30 @@ msgid "Podcast;RSS;" msgstr "Podcast;RSS;播客;订阅;聚合;" #: podcasts-gtk/resources/org.gnome.Podcasts.appdata.xml.in.in:8 -msgid "Podcast app for GNOME" -msgstr "GNOME 的播客应用" +#| msgid "Listen to your favorite podcasts, right from your desktop." +msgid "Listen to your favorite shows" +msgstr "收听您最爱的演出" + +#: podcasts-gtk/resources/org.gnome.Podcasts.appdata.xml.in.in:10 +msgid "" +"Play, update, and manage your podcasts from a lightweight interface that " +"seamlessly integrates with GNOME. Podcasts can play various audio formats " +"and remember where you stopped listening. You can subscribe to shows via RSS/" +"Atom, iTunes, and Soundcloud links. Subscriptions from other apps can be " +"imported via OPML files." +msgstr "" +"通过与 GNOME 无缝集成的轻量界面来播放、更新和管理您的播客。博客支持播放多种音" +"频格式和记住您停止收听的位置。您可以通过 RSS/Atom、iTunes 和 Soundcloud 链接" +"来订阅演出。可以通过 OPML 文件导入其它应用的订阅。" -#: podcasts-gtk/resources/org.gnome.Podcasts.appdata.xml.in.in:99 +#: podcasts-gtk/resources/org.gnome.Podcasts.appdata.xml.in.in:117 msgid "Jordan Petridis" msgstr "Jordan Petridis" +#: podcasts-gtk/resources/org.gnome.Podcasts.appdata.xml.in.in:118 +msgid "Julian Hofer" +msgstr "Julian Hofer" + #: podcasts-gtk/resources/gtk/empty_view.ui:46 msgid "This show does not have episodes yet" msgstr "这个节目还没有剧集" @@ -113,6 +130,37 @@ msgstr "通过订阅源 URL 添加新节目" msgid "Import shows from another device" msgstr "从另一设备导入节目" +#: podcasts-gtk/resources/gtk/episode_description.ui:49 +msgid "Episode Details" +msgstr "剧集详情" + +#: podcasts-gtk/resources/gtk/episode_description.ui:64 +#: podcasts-gtk/resources/gtk/headerbar.ui:186 +msgid "Back" +msgstr "后退" + +#: podcasts-gtk/resources/gtk/episode_description.ui:148 +#| msgid "Podcasts" +msgid "Podcast Title" +msgstr "播客标题" + +#: podcasts-gtk/resources/gtk/episode_description.ui:186 +msgid "Duration - Date" +msgstr "时长 - 日期" + +#: podcasts-gtk/resources/gtk/episode_description.ui:241 +msgid "Episode Description" +msgstr "剧集描述" + +#: podcasts-gtk/resources/gtk/episode_menu.ui:36 +#| msgid "_Import Shows" +msgid "Go to Show" +msgstr "前往演出" + +#: podcasts-gtk/resources/gtk/episode_menu.ui:40 +msgid "Copy Episode Url" +msgstr "复制剧集网址" + #: podcasts-gtk/resources/gtk/episode_widget.ui:82 msgid "You’ve already listened to this episode." msgstr "您已经听过此节目了。" @@ -170,10 +218,6 @@ msgstr "添加" msgid "Show Title" msgstr "显示标题" -#: podcasts-gtk/resources/gtk/headerbar.ui:186 -msgid "Back" -msgstr "后退" - #: podcasts-gtk/resources/gtk/help-overlay.ui:12 msgid "General" msgstr "常规" @@ -192,19 +236,19 @@ msgstr "退出程序" msgid "Today" msgstr "今天" -#: podcasts-gtk/resources/gtk/home_view.ui:88 +#: podcasts-gtk/resources/gtk/home_view.ui:89 msgid "Yesterday" msgstr "昨天" -#: podcasts-gtk/resources/gtk/home_view.ui:120 +#: podcasts-gtk/resources/gtk/home_view.ui:122 msgid "This Week" msgstr "本周" -#: podcasts-gtk/resources/gtk/home_view.ui:152 +#: podcasts-gtk/resources/gtk/home_view.ui:155 msgid "This Month" msgstr "本月" -#: podcasts-gtk/resources/gtk/home_view.ui:185 +#: podcasts-gtk/resources/gtk/home_view.ui:189 msgid "Older" msgstr "更早" @@ -297,60 +341,60 @@ msgstr "退订" msgid "Read More" msgstr "阅读更多" -#: podcasts-gtk/src/app.rs:303 +#: podcasts-gtk/src/app.rs:353 msgid "Fetching new episodes" msgstr "正在提取新剧集" -#: podcasts-gtk/src/stacks/content.rs:53 +#: podcasts-gtk/src/stacks/content.rs:58 msgid "New" msgstr "更新" -#: podcasts-gtk/src/stacks/content.rs:54 +#: podcasts-gtk/src/stacks/content.rs:59 msgid "Shows" msgstr "节目" -#: podcasts-gtk/src/utils.rs:472 +#: podcasts-gtk/src/utils.rs:501 msgid "Select the file from which to you want to import shows." msgstr "选择您想要从中导入节目的文件。" -#: podcasts-gtk/src/utils.rs:475 +#: podcasts-gtk/src/utils.rs:504 msgid "_Import" msgstr "导入(_I)" -#: podcasts-gtk/src/utils.rs:484 podcasts-gtk/src/utils.rs:533 +#: podcasts-gtk/src/utils.rs:513 podcasts-gtk/src/utils.rs:562 msgid "OPML file" msgstr "OPML 文件" -#: podcasts-gtk/src/utils.rs:502 +#: podcasts-gtk/src/utils.rs:531 msgid "Failed to parse the imported file" msgstr "解析导入文件失败" -#: podcasts-gtk/src/utils.rs:507 podcasts-gtk/src/utils.rs:552 +#: podcasts-gtk/src/utils.rs:536 podcasts-gtk/src/utils.rs:581 msgid "Selected file could not be accessed." msgstr "所选文件无法访问。" -#: podcasts-gtk/src/utils.rs:518 +#: podcasts-gtk/src/utils.rs:547 msgid "Export shows to…" msgstr "导出节目到…" -#: podcasts-gtk/src/utils.rs:521 +#: podcasts-gtk/src/utils.rs:550 msgid "_Export" msgstr "导出(_E)" -#: podcasts-gtk/src/utils.rs:522 +#: podcasts-gtk/src/utils.rs:551 msgid "_Cancel" msgstr "取消(_C)" #. Translators: This is the string of the suggested name for the exported opml file -#: podcasts-gtk/src/utils.rs:526 +#: podcasts-gtk/src/utils.rs:555 msgid "gnome-podcasts-exported-shows" msgstr "gnome播客导出的节目" -#: podcasts-gtk/src/utils.rs:546 +#: podcasts-gtk/src/utils.rs:575 msgid "GNOME Podcasts Subscriptions" msgstr "GNOME 播客订阅" -#: podcasts-gtk/src/utils.rs:547 +#: podcasts-gtk/src/utils.rs:576 msgid "Failed to export podcasts" msgstr "播客导出失败" @@ -366,24 +410,32 @@ msgstr "了解关于 GNOME 播客的更多信息" msgid "translator-credits" msgstr "" "Dingzhong Chen , 2018.\n" -"Tranquilo Chan , 2020." +"Tranquilo Chan , 2020.\n" +"lumingzh , 2022." -#: podcasts-gtk/src/widgets/episode.rs:144 +#: podcasts-gtk/src/widgets/episode.rs:145 msgid "{} min" msgstr "{} 分钟" -#: podcasts-gtk/src/widgets/player.rs:828 +#: podcasts-gtk/src/widgets/episode_description.rs:165 +msgid "Copied URL to clipboard!" +msgstr "已将网址复制到剪贴板!" + +#: podcasts-gtk/src/widgets/player.rs:902 msgid "The media player was unable to execute an action." msgstr "媒体播放器无法执行此操作。" -#: podcasts-gtk/src/widgets/show_menu.rs:198 +#: podcasts-gtk/src/widgets/show_menu.rs:194 msgid "Marked all episodes as listened" msgstr "标记所有剧集为已听过" -#: podcasts-gtk/src/widgets/show_menu.rs:203 +#: podcasts-gtk/src/widgets/show_menu.rs:199 msgid "Unsubscribed from {}" msgstr "已退订 {}" +#~ msgid "Podcast app for GNOME" +#~ msgstr "GNOME 的播客应用" + #~| msgid "1.5 speed rate" #~ msgid "Double speed rate" #~ msgstr "2 倍速率" -- 2.40.1 From b203c4a6ce09e2a12ab0543af2fef67fcb3438ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jiri=20Gr=C3=B6nroos?= Date: Wed, 2 Feb 2022 18:53:43 +0000 Subject: [PATCH 006/102] Update Finnish translation --- podcasts-gtk/po/fi.po | 32 ++++++++++++++++++++++++-------- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/podcasts-gtk/po/fi.po b/podcasts-gtk/po/fi.po index c97ebd8..71b8532 100644 --- a/podcasts-gtk/po/fi.po +++ b/podcasts-gtk/po/fi.po @@ -7,8 +7,8 @@ msgid "" msgstr "" "Project-Id-Version: podcasts master\n" "Report-Msgid-Bugs-To: https://gitlab.gnome.org/World/podcasts/issues\n" -"POT-Creation-Date: 2021-09-14 16:55+0000\n" -"PO-Revision-Date: 2021-09-21 09:48+0300\n" +"POT-Creation-Date: 2021-11-28 07:07+0000\n" +"PO-Revision-Date: 2022-02-02 20:53+0200\n" "Last-Translator: Jiri Grönroos \n" "Language-Team: Finnish \n" "Language: fi\n" @@ -16,7 +16,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -"X-Generator: Poedit 3.0\n" +"X-Generator: Poedit 3.0.1\n" #: podcasts-gtk/resources/org.gnome.Podcasts.gschema.xml.in:15 msgid "Top position of the last open main window" @@ -75,7 +75,6 @@ msgid "Podcasts" msgstr "Podcastit" #: podcasts-gtk/resources/org.gnome.Podcasts.desktop.in.in:4 -#: podcasts-gtk/resources/org.gnome.Podcasts.appdata.xml.in.in:10 msgid "Listen to your favorite podcasts, right from your desktop." msgstr "Kuuntele suosikkipodcastejasi suoraan työpöydältäsi." @@ -85,14 +84,28 @@ msgid "Podcast;RSS;" msgstr "Podcast;RSS;" #: podcasts-gtk/resources/org.gnome.Podcasts.appdata.xml.in.in:8 -msgid "Podcast app for GNOME" -msgstr "Podcast-sovellus Gnomelle" +msgid "Listen to your favorite shows" +msgstr "Kuuntele suosikkiohjelmiasi" + +#: podcasts-gtk/resources/org.gnome.Podcasts.appdata.xml.in.in:10 +msgid "" +"Play, update, and manage your podcasts from a lightweight interface that " +"seamlessly integrates with GNOME. Podcasts can play various audio formats " +"and remember where you stopped listening. You can subscribe to shows via RSS/" +"Atom, iTunes, and Soundcloud links. Subscriptions from other apps can be " +"imported via OPML files." +msgstr "" +"Toista, päivitä ja hallitse podcasteja Gnome-työpöytään integroituvasta " +"käyttöliittymästä. Podcastit kykenee toistamaan lukuisia äänimuotoja ja " +"muistaa, missä kohtaa lopetit kuuntelun. Voit tilata ohjelmia RSS-/Atom-, " +"iTunes ja Soundcloud-linkeillä. Tilauksia muista sovelluksista voi tuoda " +"OPML-tiedostoista." -#: podcasts-gtk/resources/org.gnome.Podcasts.appdata.xml.in.in:115 +#: podcasts-gtk/resources/org.gnome.Podcasts.appdata.xml.in.in:117 msgid "Jordan Petridis" msgstr "Jordan Petridis" -#: podcasts-gtk/resources/org.gnome.Podcasts.appdata.xml.in.in:116 +#: podcasts-gtk/resources/org.gnome.Podcasts.appdata.xml.in.in:118 msgid "Julian Hofer" msgstr "Julian Hofer" @@ -414,6 +427,9 @@ msgstr "Merkitse kaikki jaksot toistetuiksi" msgid "Unsubscribed from {}" msgstr "Lopeta syötteen {} tilaus" +#~ msgid "Podcast app for GNOME" +#~ msgstr "Podcast-sovellus Gnomelle" + #~ msgid "Double speed rate" #~ msgstr "Tuplanopeus" -- 2.40.1 From 6cb842e05b4e08d05e05cb360c0045a8da5644d5 Mon Sep 17 00:00:00 2001 From: Fran Dieguez Date: Fri, 4 Feb 2022 14:49:08 +0000 Subject: [PATCH 007/102] Update Galician translation --- podcasts-gtk/po/gl.po | 133 ++++++++++++++++++++++++++++-------------- 1 file changed, 90 insertions(+), 43 deletions(-) diff --git a/podcasts-gtk/po/gl.po b/podcasts-gtk/po/gl.po index 21bae71..be79e56 100644 --- a/podcasts-gtk/po/gl.po +++ b/podcasts-gtk/po/gl.po @@ -3,21 +3,22 @@ # This file is distributed under the same license as the gnome-podcasts package. # Automatically generated, 2018. # Fran Dieguez , 2018-2021. +# Fran Diéguez , 2022. # msgid "" msgstr "" "Project-Id-Version: gnome-podcasts\n" "Report-Msgid-Bugs-To: https://gitlab.gnome.org/World/podcasts/issues\n" -"POT-Creation-Date: 2021-06-19 18:35+0000\n" -"PO-Revision-Date: 2021-09-06 21:20+0200\n" -"Last-Translator: Fran Dieguez \n" +"POT-Creation-Date: 2021-11-28 07:07+0000\n" +"PO-Revision-Date: 2022-02-04 15:43+0100\n" +"Last-Translator: Fran Diéguez \n" "Language-Team: Galician \n" "Language: gl\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1)\n" -"X-Generator: Gtranslator 40.0\n" +"X-Generator: Gtranslator 41.0\n" "X-Project-Style: gnome\n" "X-DL-Team: gl\n" "X-DL-Module: podcasts\n" @@ -76,13 +77,12 @@ msgstr "Cantos periodos de tiempo hai que esperar entre limpiados automáticos" #. Weird magic I copy-pasted that sets the Application Name in the Shell. #: podcasts-gtk/resources/org.gnome.Podcasts.desktop.in.in:3 #: podcasts-gtk/resources/org.gnome.Podcasts.appdata.xml.in.in:4 -#: podcasts-gtk/resources/gtk/headerbar.ui:137 podcasts-gtk/src/app.rs:364 -#: podcasts-gtk/src/widgets/aboutdialog.rs:63 podcasts-gtk/src/window.rs:64 +#: podcasts-gtk/resources/gtk/headerbar.ui:137 podcasts-gtk/src/app.rs:438 +#: podcasts-gtk/src/widgets/aboutdialog.rs:63 podcasts-gtk/src/window.rs:66 msgid "Podcasts" msgstr "Podcasts" #: podcasts-gtk/resources/org.gnome.Podcasts.desktop.in.in:4 -#: podcasts-gtk/resources/org.gnome.Podcasts.appdata.xml.in.in:10 msgid "Listen to your favorite podcasts, right from your desktop." msgstr "" "Escoita os teus podcasts favoritos, directamente desde o teu escritorio." @@ -93,13 +93,32 @@ msgid "Podcast;RSS;" msgstr "Podcast;RSS;" #: podcasts-gtk/resources/org.gnome.Podcasts.appdata.xml.in.in:8 -msgid "Podcast app for GNOME" -msgstr "Aplicativo de Podcast para GNOME" +#| msgid "Listen to your favorite podcasts, right from your desktop." +msgid "Listen to your favorite shows" +msgstr "Escoita os teus podcasts favoritos" -#: podcasts-gtk/resources/org.gnome.Podcasts.appdata.xml.in.in:99 +#: podcasts-gtk/resources/org.gnome.Podcasts.appdata.xml.in.in:10 +msgid "" +"Play, update, and manage your podcasts from a lightweight interface that " +"seamlessly integrates with GNOME. Podcasts can play various audio formats " +"and remember where you stopped listening. You can subscribe to shows via RSS/" +"Atom, iTunes, and Soundcloud links. Subscriptions from other apps can be " +"imported via OPML files." +msgstr "" +"Reproduza, actualice e xestione os seus podcasts desde unha interface " +"liviana que se integre con GNOME. Podcasts pode reproducir varios formatos " +"de audio e recorda onde parou de escoitar. Pode subscribirse aos programas " +"mediante elementos de RSS/Atom, iTunes e Soundcloud. Pode importar ficheiros " +"OPML desde outras aplicacións." + +#: podcasts-gtk/resources/org.gnome.Podcasts.appdata.xml.in.in:117 msgid "Jordan Petridis" msgstr "Jordan Petridis" +#: podcasts-gtk/resources/org.gnome.Podcasts.appdata.xml.in.in:118 +msgid "Julian Hofer" +msgstr "Julian Hofer" + #: podcasts-gtk/resources/gtk/empty_view.ui:46 msgid "This show does not have episodes yet" msgstr "Este programa aínda non ten episodios" @@ -121,8 +140,38 @@ msgstr "Engadir novo programa a través do URL da canle" msgid "Import shows from another device" msgstr "Importar programas desde outro dispositivo" +#: podcasts-gtk/resources/gtk/episode_description.ui:49 +msgid "Episode Details" +msgstr "Detalles do episodio" + +#: podcasts-gtk/resources/gtk/episode_description.ui:64 +#: podcasts-gtk/resources/gtk/headerbar.ui:186 +msgid "Back" +msgstr "Atrás" + +#: podcasts-gtk/resources/gtk/episode_description.ui:148 +#| msgid "Podcasts" +msgid "Podcast Title" +msgstr "Título do podcast" + +#: podcasts-gtk/resources/gtk/episode_description.ui:186 +msgid "Duration - Date" +msgstr "Duración - Data" + +#: podcasts-gtk/resources/gtk/episode_description.ui:241 +msgid "Episode Description" +msgstr "Descrición do episodio" + +#: podcasts-gtk/resources/gtk/episode_menu.ui:36 +#| msgid "_Import Shows" +msgid "Go to Show" +msgstr "Ir ao programa" + +#: podcasts-gtk/resources/gtk/episode_menu.ui:40 +msgid "Copy Episode Url" +msgstr "Copiar URL do episodio" + #: podcasts-gtk/resources/gtk/episode_widget.ui:82 -#| msgid "You are already subscribed to this show" msgid "You’ve already listened to this episode." msgstr "Xa escoitaches este episodio." @@ -151,7 +200,6 @@ msgid "_Import Shows" msgstr "_Importar programas" #: podcasts-gtk/resources/gtk/hamburger.ui:16 -#| msgid "_Import Shows" msgid "_Export Shows" msgstr "_Exportar programas" @@ -160,7 +208,6 @@ msgid "_Keyboard Shortcuts" msgstr "Atallos de _teclado" #: podcasts-gtk/resources/gtk/hamburger.ui:30 -#| msgid "Podcasts" msgid "_About Podcasts" msgstr "_Sobre Podcasts" @@ -181,10 +228,6 @@ msgstr "Engadir" msgid "Show Title" msgstr "Título do Programa" -#: podcasts-gtk/resources/gtk/headerbar.ui:186 -msgid "Back" -msgstr "Atrás" - #: podcasts-gtk/resources/gtk/help-overlay.ui:12 msgid "General" msgstr "Xeral" @@ -203,19 +246,19 @@ msgstr "Saír do aplicativo" msgid "Today" msgstr "Hoxe" -#: podcasts-gtk/resources/gtk/home_view.ui:88 +#: podcasts-gtk/resources/gtk/home_view.ui:89 msgid "Yesterday" msgstr "Onte" -#: podcasts-gtk/resources/gtk/home_view.ui:120 +#: podcasts-gtk/resources/gtk/home_view.ui:122 msgid "This Week" msgstr "Esta semana" -#: podcasts-gtk/resources/gtk/home_view.ui:152 +#: podcasts-gtk/resources/gtk/home_view.ui:155 msgid "This Month" msgstr "Este mes" -#: podcasts-gtk/resources/gtk/home_view.ui:185 +#: podcasts-gtk/resources/gtk/home_view.ui:189 msgid "Older" msgstr "Antigo" @@ -241,7 +284,6 @@ msgid "1.00×" msgstr "1.00×" #: podcasts-gtk/resources/gtk/player_rate.ui:65 -#| msgid "1.00×" msgid "2.00×" msgstr "2.00×" @@ -309,62 +351,60 @@ msgstr "Cancelar subscrición" msgid "Read More" msgstr "Ler máis" -#: podcasts-gtk/src/app.rs:299 +#: podcasts-gtk/src/app.rs:353 msgid "Fetching new episodes" msgstr "Obtendo novos episodios" -#: podcasts-gtk/src/stacks/content.rs:53 +#: podcasts-gtk/src/stacks/content.rs:58 msgid "New" msgstr "Novo" -#: podcasts-gtk/src/stacks/content.rs:54 +#: podcasts-gtk/src/stacks/content.rs:59 msgid "Shows" msgstr "Programas" -#: podcasts-gtk/src/utils.rs:472 +#: podcasts-gtk/src/utils.rs:501 msgid "Select the file from which to you want to import shows." msgstr "Seleccione o fichero desde o cal queres importar programas." -#: podcasts-gtk/src/utils.rs:475 +#: podcasts-gtk/src/utils.rs:504 msgid "_Import" msgstr "_Importar" -#: podcasts-gtk/src/utils.rs:484 podcasts-gtk/src/utils.rs:533 +#: podcasts-gtk/src/utils.rs:513 podcasts-gtk/src/utils.rs:562 msgid "OPML file" msgstr "Fichero OPML" -#: podcasts-gtk/src/utils.rs:502 +#: podcasts-gtk/src/utils.rs:531 msgid "Failed to parse the imported file" msgstr "Produciuse un fallo ao leer o fichero importado" -#: podcasts-gtk/src/utils.rs:507 podcasts-gtk/src/utils.rs:552 +#: podcasts-gtk/src/utils.rs:536 podcasts-gtk/src/utils.rs:581 msgid "Selected file could not be accessed." msgstr "O fichero seleccionado non é accesíbel." -#: podcasts-gtk/src/utils.rs:518 +#: podcasts-gtk/src/utils.rs:547 msgid "Export shows to…" msgstr "Exportar programas a…" -#: podcasts-gtk/src/utils.rs:521 -#| msgid "_Import" +#: podcasts-gtk/src/utils.rs:550 msgid "_Export" msgstr "_Exportar" -#: podcasts-gtk/src/utils.rs:522 -#| msgid "Cancel" +#: podcasts-gtk/src/utils.rs:551 msgid "_Cancel" msgstr "_Cancelar" #. Translators: This is the string of the suggested name for the exported opml file -#: podcasts-gtk/src/utils.rs:526 +#: podcasts-gtk/src/utils.rs:555 msgid "gnome-podcasts-exported-shows" msgstr "gnome-podcasts-programas-exportados" -#: podcasts-gtk/src/utils.rs:546 +#: podcasts-gtk/src/utils.rs:575 msgid "GNOME Podcasts Subscriptions" msgstr "Subscricións de Podcasts de GNOME" -#: podcasts-gtk/src/utils.rs:547 +#: podcasts-gtk/src/utils.rs:576 msgid "Failed to export podcasts" msgstr "Produciuse un fallo ao exportar os podcasts" @@ -378,24 +418,31 @@ msgstr "Saber máis sobre Podcasts de GNOME" #: podcasts-gtk/src/widgets/aboutdialog.rs:69 msgid "translator-credits" -msgstr "Fran Dieguez , 2018-2021" +msgstr "Fran Dieguez , 2018-2022" -#: podcasts-gtk/src/widgets/episode.rs:144 +#: podcasts-gtk/src/widgets/episode.rs:145 msgid "{} min" msgstr "{} min" -#: podcasts-gtk/src/widgets/player.rs:818 +#: podcasts-gtk/src/widgets/episode_description.rs:165 +msgid "Copied URL to clipboard!" +msgstr "URL copiada no portapapeis!" + +#: podcasts-gtk/src/widgets/player.rs:902 msgid "The media player was unable to execute an action." msgstr "O reprodutor non puido reproducir unha acción." -#: podcasts-gtk/src/widgets/show_menu.rs:198 +#: podcasts-gtk/src/widgets/show_menu.rs:194 msgid "Marked all episodes as listened" msgstr "Marcar todos os episodios como escoitados" -#: podcasts-gtk/src/widgets/show_menu.rs:203 +#: podcasts-gtk/src/widgets/show_menu.rs:199 msgid "Unsubscribed from {}" msgstr "Subscrición cancelada para {}" +#~ msgid "Podcast app for GNOME" +#~ msgstr "Aplicativo de Podcast para GNOME" + #~ msgid "org.gnome.Podcasts" #~ msgstr "org.gnome.Podcasts" -- 2.40.1 From f74bb17be74abd146feae1895c7a690eb6885bc2 Mon Sep 17 00:00:00 2001 From: nee Date: Sun, 6 Feb 2022 17:38:48 +0100 Subject: [PATCH 008/102] podcast-data: correctly import non-utf8 encoded feeds Before non-utf-8 characters were lossy imported. rss:Channel does proper decoding when it receives bytes through read_from instead of being constructed through from_str. So we now use read_from. Also a test was added for iso-8859-1. Fixes #241 --- podcasts-data/src/feed.rs | 28 +- podcasts-data/src/models/source.rs | 37 +- .../tests/feeds/2022-series-i-cinema.xml | 860 ++++++++++++++++++ 3 files changed, 920 insertions(+), 5 deletions(-) create mode 100644 podcasts-data/tests/feeds/2022-series-i-cinema.xml diff --git a/podcasts-data/src/feed.rs b/podcasts-data/src/feed.rs index 3b2a58c..d6d334c 100644 --- a/podcasts-data/src/feed.rs +++ b/podcasts-data/src/feed.rs @@ -175,6 +175,11 @@ mod tests { "https://web.archive.org/web/20180120104741if_/https://www.greaterthancode.\ com/feed/podcast", ), + ( + "tests/feeds/2022-series-i-cinema.xml", + "https://web.archive.org/web/20220205205130_/https://dinamics.ccma.\ + cat/public/podcast/catradio/xml/series-i-cinema.xml", + ), ] }; @@ -197,9 +202,9 @@ mod tests { } // Assert the index rows equal the controlled results - assert_eq!(dbqueries::get_sources()?.len(), 5); - assert_eq!(dbqueries::get_podcasts()?.len(), 5); - assert_eq!(dbqueries::get_episodes()?.len(), 354); + assert_eq!(dbqueries::get_sources()?.len(), 6); + assert_eq!(dbqueries::get_podcasts()?.len(), 6); + assert_eq!(dbqueries::get_episodes()?.len(), 404); Ok(()) } @@ -231,4 +236,21 @@ mod tests { assert_eq!(dbqueries::get_episodes()?.len(), 43); Ok(()) } + + #[test] + fn test_feed_non_utf8() -> Result<()> { + truncate_db()?; + + let path = "tests/feeds/2022-series-i-cinema.xml"; + let feed = get_feed(path, 42); + + let file = fs::File::open(path)?; + let channel = Channel::read_from(BufReader::new(file))?; + + let description = feed.channel.description(); + assert_eq!(description, "Els clàssics, les novetats de la cartellera i les millors sèries, tot en un sol podcast."); + let pd = NewShow::new(&channel, 42); + assert_eq!(feed.parse_podcast(), pd); + Ok(()) + } } diff --git a/podcasts-data/src/models/source.rs b/podcasts-data/src/models/source.rs index 8d90fd8..ba9fbe7 100644 --- a/podcasts-data/src/models/source.rs +++ b/podcasts-data/src/models/source.rs @@ -21,6 +21,7 @@ use diesel::SaveChangesDsl; use rss::Channel; use url::Url; +use hyper::body::Buf; use hyper::client::HttpConnector; use hyper::{Body, Client}; use hyper_tls::HttpsConnector; @@ -318,8 +319,11 @@ impl Source { async fn response_to_channel(res: Response) -> Result { let chunk = hyper::body::to_bytes(res.into_body()).await?; - let buf = String::from_utf8_lossy(&chunk).into_owned(); - Channel::from_str(&buf).map_err(From::from) + + // Channel will do it's own decoding of strings + // based on what is specified in . + // So just pass it the raw byets. + Channel::read_from(chunk.reader()).map_err(From::from) } #[cfg(test)] @@ -328,6 +332,7 @@ mod tests { use anyhow::Result; use crate::database::truncate_db; + use crate::dbqueries; use crate::utils::get_feed; #[test] @@ -349,4 +354,32 @@ mod tests { assert_eq!(expected, feed); Ok(()) } + + #[test] + fn test_into_non_utf8() -> Result<()> { + truncate_db()?; + + let rt = tokio::runtime::Runtime::new()?; + let https = HttpsConnector::new(); + let client = Client::builder().build::<_, Body>(https); + + let url = "https://web.archive.org/web/20220205205130if_/https://dinamics.ccma.\ + cat/public/podcast/catradio/xml/series-i-cinema.xml"; + let source = Source::from_url(url)?; + let id = source.id(); + let feed = source.into_feed(&client); + let feed = rt.block_on(feed)?; + + let expected = get_feed("tests/feeds/2022-series-i-cinema.xml", id); + assert_eq!(expected, feed); + + feed.index()?; + assert_eq!(dbqueries::get_podcasts()?.len(), 1); + assert_eq!( + dbqueries::get_podcasts()?[0].description(), + "Els clàssics, les novetats de la cartellera i les millors \ + sèries, tot en un sol podcast." + ); + Ok(()) + } } diff --git a/podcasts-data/tests/feeds/2022-series-i-cinema.xml b/podcasts-data/tests/feeds/2022-series-i-cinema.xml new file mode 100644 index 0000000..de2a68e --- /dev/null +++ b/podcasts-data/tests/feeds/2022-series-i-cinema.xml @@ -0,0 +1,860 @@ + + +Sries i Cinema +https://www.ccma.cat/catradio/podcast/tematics/series-i-cinema/1334/ +Els clssics, les novetats de la cartellera i les millors sries, tot en un sol podcast. +61 +Sat, 05 Feb 2022 21:42:46 +0100 +Sat, 05 Feb 2022 21:42:46 +0100 +ca-es +Corporaci Catalana de Mitjans Audiovisuals, SA +Catalunya Ràdio + +Corporaci Catalana de Mitjans Audiovisuals, SA +crpodcast@catradio.cat + +Catalunya Rdio + +Sries i Cinema +https://statics.ccma.cat/multimedia/png/2/3/1561467550332.png +https://www.ccma.cat/catradio/podcast/tematics/series-i-cinema/1334/ + + +Els clssics, les novetats de la cartellera i les millors sries, tot en un sol podcast. +no +Podcasting +TV & Film + +no + +S'estrena, per fi, un dels millors films del 2021, "Drive my car" +Desprs que molts crtics el consideressin, si no el millor, un dels millors films de l'any passat, ara arriba a les sales "Drive my car", de Rysuke Hamaguchi. Tamb aterren "Moonfall" i "Los ojos de Tammy Faye". Directes a plataformes, s'estrenen "Old Henry", "A travs de mi ventana" de Maral Fors, "Se termin el tiempo" i "The story of looking". I pel que fa a les sries, destaquen "Pam y Tommy", "Reacher" i "Sospechosos". Totes, comentades pel nostre especialista, Marc Garriga. +Fri, 04 Feb 2022 17:20:00 +0100 + + +Desprs que molts crtics el consideressin, si no el millor, un dels millors films de l'any passat, ara arriba a les sales "Drive my car", de Rysuke Hamaguchi. Tamb aterren "Moonfall" i "Los ojos de Tammy Faye". Directes a plataformes, s'estrenen "Old Henry", "A travs de mi ventana" de Maral Fors, "Se termin el tiempo" i "The story of looking". I pel que fa a les sries, destaquen "Pam y Tommy", "Reacher" i "Sospechosos". Totes, comentades pel nostre especialista, Marc Garriga. +no + +https://audios.ccma.cat/multimedia/mp3/5/2/1643994008925.mp3 +00:05:31 +04/02/2022 +//www.ccma.cat/catradio/alacarta/travelling/sestrena-per-fi-un-dels-millors-films-del-2021-drive-my-car/audio/1124621/ +//statics.ccma.cat/multimedia/jpg/0/0/1643994021500.jpg +Travelling + + +Wong Kar-Wai, per Joana Serrat: la sincronia de l'amor +Memento #192. El cinema profundament esteticista de Wong Kar-Wai no busca tant explicar-nos una histria com fer-nos viure una experincia i recrear estats d'nim. Els seus temes de fons solen ser la melangia de la solitud i l'amor vist com una qesti d'atzar i sincronia. De l'autor d'una obra tan immortal com s "Desitjant estimar" ens en parla la Joana Serrat, que amb el seu ltim disc, "Hardcore from the heart", ha recollit totes les lloances possibles i se segueix consolidant com un dels grans talents musicals del pas. I resulta que, a ms, s una cinfila de primera. + +Thu, 03 Feb 2022 12:00:00 +0100 + + +Memento #192. El cinema profundament esteticista de Wong Kar-Wai no busca tant explicar-nos una histria com fer-nos viure una experincia i recrear estats d'nim. Els seus temes de fons solen ser la melangia de la solitud i l'amor vist com una qesti d'atzar i sincronia. De l'autor d'una obra tan immortal com s "Desitjant estimar" ens en parla la Joana Serrat, que amb el seu ltim disc, "Hardcore from the heart", ha recollit totes les lloances possibles i se segueix consolidant com un dels grans talents musicals del pas. I resulta que, a ms, s una cinfila de primera. + +no + +https://audios.ccma.cat/multimedia/mp3/4/1/1643885431214.mp3 +00:59:55 +03/02/2022 +//www.ccma.cat/catradio/alacarta/memento/wong-karwai-per-joana-serrat-la-sincronia-de-lamor/audio/1124425/ +//statics.ccma.cat/multimedia/jpg/2/3/1643885434732.jpg +Memento + + +Sries per mirar al febrer +SerieSelektor #58 El mes ms curt de l'any inclou una gran varietat de propostes per a tots els gustos, entre les quals destaquem "Pam & Tommy" (Disney+), "Quin es Anna?" (Netflix), "Furia" (Filmin), "Separacin" (Apple TV+) o "Super pumped" (Movistar+). A les recomanacions a la carta proposem "El visitante" (HBO Max) i "The after party" (Apple TV+). + +Wed, 02 Feb 2022 22:30:00 +0100 + + +SerieSelektor #58 El mes ms curt de l'any inclou una gran varietat de propostes per a tots els gustos, entre les quals destaquem "Pam & Tommy" (Disney+), "Quin es Anna?" (Netflix), "Furia" (Filmin), "Separacin" (Apple TV+) o "Super pumped" (Movistar+). A les recomanacions a la carta proposem "El visitante" (HBO Max) i "The after party" (Apple TV+). + +no + +https://audios.ccma.cat/multimedia/mp3/8/6/1643864446168.mp3 +00:59:54 +02/02/2022 +//www.ccma.cat/catradio/alacarta/serieselektor/series-per-mirar-al-febrer/audio/1124386/ +//statics.ccma.cat/multimedia/jpg/4/7/1643864466274.jpg +SerieSelektor + + +Gran Gala del programa 600 d'El viol vermell +Avui arribem als 600 programes d'"El viol vermell"! Cada dia no s'arriben als sis-cents programes setmanals! Per celebrar-ho, hem organitzat una Gran Gala amb pblic, orquestra i convidats. Comptarem amb les actuacions de grans actors i actrius del cinema, amics del programa que ens interpretaran temes que han cantat en algunes de les seves pellcules. Un gran espectacle musical cinematogrfic i radiofnic per fer-vos gaudir de valent. +Sun, 30 Jan 2022 13:00:00 +0100 + + +Avui arribem als 600 programes d'"El viol vermell"! Cada dia no s'arriben als sis-cents programes setmanals! Per celebrar-ho, hem organitzat una Gran Gala amb pblic, orquestra i convidats. Comptarem amb les actuacions de grans actors i actrius del cinema, amics del programa que ens interpretaran temes que han cantat en algunes de les seves pellcules. Un gran espectacle musical cinematogrfic i radiofnic per fer-vos gaudir de valent. +no + +https://audios.ccma.cat/multimedia/mp3/0/0/1643364624000.mp3 +00:54:07 +30/01/2022 +//www.ccma.cat/catradio/alacarta/el-violi-vermell/gran-gala-del-programa-600-del-violi-vermell/audio/1123767/ +//statics.ccma.cat/multimedia/jpg/5/1/1643364627915.jpg +El viol vermell + + +"Todos mienten" o la subversi del Cluedo +Pau Freixas, el creador de "Polseres vermelles", "Cites" i "Benvinguts a la famlia" estrena a Movistar+ "Todos mienten", la seva nova srie, un thriller que barreja suspens, drama, humor negre i uns personatges absolutament imprevisibles. La srie est protagonitzada, entre d'altres, per Leonardo Sbaraglia i Eva Santolaria. El nostre company Marc Garriga ha parlat amb tots tres. +Fri, 28 Jan 2022 07:00:00 +0100 + + +Pau Freixas, el creador de "Polseres vermelles", "Cites" i "Benvinguts a la famlia" estrena a Movistar+ "Todos mienten", la seva nova srie, un thriller que barreja suspens, drama, humor negre i uns personatges absolutament imprevisibles. La srie est protagonitzada, entre d'altres, per Leonardo Sbaraglia i Eva Santolaria. El nostre company Marc Garriga ha parlat amb tots tres. +no + +https://audios.ccma.cat/multimedia/mp3/8/6/1643346071068.mp3 +00:02:36 +28/01/2022 +//www.ccma.cat/catradio/alacarta/travelling/todos-mienten-o-la-subversio-del-cluedo/audio/1123730/ +//statics.ccma.cat/multimedia/jpg/5/9/1643346086895.jpg +Travelling + + +"La abuela" i "Belfast", per gaudir del cinema +Les pellcules de Paco Plaza i Kenneth Branagh sn les dues novetats ms destacades de la cartellera. Tamb arriben "Todo ha ido bien", "En un muelle de Normanda", "El pacte", "Mira per mi", "La mama s pura pluja", "Prisioneros de Ghostland" i "No somos nada". A les plataformes s'estrenen directament "Ice Age: Las aventuras de Buck", "Swan Song", "La magia del sonido del cine", "El asesinato de Kenneth Chamberlain" i "Attica". I, pel que fa a sries, "Todo es mentira", "Feria, la luz ms oscura", "The afterparty", "La mujer de la casa de enfrente de la chica de la ventana" i "The responder". Totes, comentades pel nostre especialista, Marc Garriga. +Thu, 27 Jan 2022 20:30:00 +0100 + + +Les pellcules de Paco Plaza i Kenneth Branagh sn les dues novetats ms destacades de la cartellera. Tamb arriben "Todo ha ido bien", "En un muelle de Normanda", "El pacte", "Mira per mi", "La mama s pura pluja", "Prisioneros de Ghostland" i "No somos nada". A les plataformes s'estrenen directament "Ice Age: Las aventuras de Buck", "Swan Song", "La magia del sonido del cine", "El asesinato de Kenneth Chamberlain" i "Attica". I, pel que fa a sries, "Todo es mentira", "Feria, la luz ms oscura", "The afterparty", "La mujer de la casa de enfrente de la chica de la ventana" i "The responder". Totes, comentades pel nostre especialista, Marc Garriga. +no + +https://audios.ccma.cat/multimedia/mp3/9/7/1643312442679.mp3 +00:05:31 +27/01/2022 +//www.ccma.cat/catradio/alacarta/travelling/la-abuela-i-belfast-per-gaudir-del-cinema/audio/1123713/ +//statics.ccma.cat/multimedia/jpg/4/9/1643312445494.jpg +Travelling + + +Andrei Tarkovsky, per Guillem Balart: esculpint la nostlgia +Memento #191. Ens acompanya un actor amb una fora escnica descomunal, que est posant a prova en l'espectacle "Hamlet Aribau". Guillem Balart s'ha deixat posseir pels versos de Shakespeare i ens ofereix una gran interpretaci del prncep de Dinamarca, per avui ens proposa viatjar una mica ms a l'est, fins a Rssia. Analitzem les claus del cinema potic i onric d'Andrei Tarkovsky, situat entre la nostlgia pel parads perdut i la recerca del sentit de la vida. Com els Monty Python, per ms solemne... + +Thu, 27 Jan 2022 12:00:00 +0100 + + +Memento #191. Ens acompanya un actor amb una fora escnica descomunal, que est posant a prova en l'espectacle "Hamlet Aribau". Guillem Balart s'ha deixat posseir pels versos de Shakespeare i ens ofereix una gran interpretaci del prncep de Dinamarca, per avui ens proposa viatjar una mica ms a l'est, fins a Rssia. Analitzem les claus del cinema potic i onric d'Andrei Tarkovsky, situat entre la nostlgia pel parads perdut i la recerca del sentit de la vida. Com els Monty Python, per ms solemne... + +no + +https://audios.ccma.cat/multimedia/mp3/8/9/1643283052198.mp3 +00:59:55 +27/01/2022 +//www.ccma.cat/catradio/alacarta/memento/andrei-tarkovsky-per-guillem-balart-esculpint-la-nostalgia/audio/1123653/ +//statics.ccma.cat/multimedia/jpg/2/1/1643283060212.jpg +Memento + + +"Somebody somewhere" i les sex tapes +SerieSelektor #57 Proposem algunes sries que no estan centrant gaires converses per que paga la pena mirar com "As we see it" (Prime Video), "Red light" (Sundance TV) o "Los ltimos tres das" (Filmin). A les sries a la carta recomanem "Somebody somewhere" (HBO Max) i "Cortar por la lnea de puntos" (Netflix). A ms, conversem amb el creador, guionista i director, Pau Freixas, que aquest divendres estrena "Todos mienten" (Movistar+). +Wed, 26 Jan 2022 22:30:00 +0100 + + +SerieSelektor #57 Proposem algunes sries que no estan centrant gaires converses per que paga la pena mirar com "As we see it" (Prime Video), "Red light" (Sundance TV) o "Los ltimos tres das" (Filmin). A les sries a la carta recomanem "Somebody somewhere" (HBO Max) i "Cortar por la lnea de puntos" (Netflix). A ms, conversem amb el creador, guionista i director, Pau Freixas, que aquest divendres estrena "Todos mienten" (Movistar+). +no + +https://audios.ccma.cat/multimedia/mp3/5/4/1643271648445.mp3 +01:02:09 +26/01/2022 +//www.ccma.cat/catradio/alacarta/serieselektor/somebody-somewhere-i-les-sex-tapes/audio/1123622/ +//statics.ccma.cat/multimedia/jpg/5/3/1643271047635.jpg +SerieSelektor + + +Pau Freixas: "'Todos mienten' no s un espiler" +Conversem amb el creador, guionista i director Pau Freixas sobre la seva nova srie, que es mou entre el suspens, el drama i l'humor negre. A travs de les vides d'un grup de vens d'una luxosa urbanitzaci, on comena a crrer un vdeo sexual entre una professora i un alumne, s'aniran descobrint secrets i mentides. Freixas la defineix com una mena de "Cluedo" difcil de resoldre en qu els personatges tenen una insatisfacci crnica. "Todos mienten" s'estrena aquest divendres a Movistar+. +Wed, 26 Jan 2022 22:29:00 +0100 + + +Conversem amb el creador, guionista i director Pau Freixas sobre la seva nova srie, que es mou entre el suspens, el drama i l'humor negre. A travs de les vides d'un grup de vens d'una luxosa urbanitzaci, on comena a crrer un vdeo sexual entre una professora i un alumne, s'aniran descobrint secrets i mentides. Freixas la defineix com una mena de "Cluedo" difcil de resoldre en qu els personatges tenen una insatisfacci crnica. "Todos mienten" s'estrena aquest divendres a Movistar+. +no + +https://audios.ccma.cat/multimedia/mp3/3/3/1643271044733.mp3 +00:14:55 +26/01/2022 +//www.ccma.cat/catradio/alacarta/serieselektor/pau-freixas-todos-mienten-no-es-un-espoiler/audio/1123619/ +//statics.ccma.cat/multimedia/jpg/2/8/1643271651582.jpg +SerieSelektor + + +Una "Cerdita" a Sundance +Carlota Pereda presenta al festival de Sundance, als Estats Units, el seu llargmetratge "Cerdita". La cinta neix d'un curt que es va endur el 2018 nombrosos premis, com ara el Goya i el Forqu. El nostre company Marc Garriga n'ha parlat amb ella. +Tue, 25 Jan 2022 08:00:00 +0100 + + +Carlota Pereda presenta al festival de Sundance, als Estats Units, el seu llargmetratge "Cerdita". La cinta neix d'un curt que es va endur el 2018 nombrosos premis, com ara el Goya i el Forqu. El nostre company Marc Garriga n'ha parlat amb ella. +no + +https://audios.ccma.cat/multimedia/mp3/2/2/1643086854422.mp3 +00:02:18 +25/01/2022 +//www.ccma.cat/catradio/alacarta/travelling/una-cerdita-a-sundance/audio/1123340/ +//statics.ccma.cat/multimedia/jpg/5/3/1643086869535.jpg +Travelling + + +El minimalisme dels 80 i dels 90. De l'inici exultant a la domesticaci +En aquest programa volem mostrar l'evoluci del minimalisme en la msica de cinema en els seus primers vint anys, en aquest cas a travs de les bandes sonores del compositor Michael Nyman. Sentirem msica de films com "El contracte del dibuixant", "Prospero's Books", "El marit de la perruquera", "Gattaca", "Wonderland", "El piano"... +Sun, 23 Jan 2022 13:00:00 +0100 + + +En aquest programa volem mostrar l'evoluci del minimalisme en la msica de cinema en els seus primers vint anys, en aquest cas a travs de les bandes sonores del compositor Michael Nyman. Sentirem msica de films com "El contracte del dibuixant", "Prospero's Books", "El marit de la perruquera", "Gattaca", "Wonderland", "El piano"... +no + +https://audios.ccma.cat/multimedia/mp3/3/2/1642771563023.mp3 +00:58:54 +23/01/2022 +//www.ccma.cat/catradio/alacarta/el-violi-vermell/el-minimalisme-dels-80-i-dels-90-de-linici-exultant-a-la-domesticacio/audio/1122993/ +//statics.ccma.cat/multimedia/jpg/0/9/1642771565190.jpg +El viol vermell + + +"El callejn de las almas perdidas", una nova joia de Guillermo del Toro +El nou film de Guillermo del Toro, "El callejn de las almas perdidas", sobresurt entre les estrenes cinematogrfiques de la setmana. Tamb arriben a les sales "El mtodo Williams", "Agentes 355", "One shot (Misin de rescate)", "El cas Villa Caprice" i "La meva mare s una gorilla". A les plataformes es poden veure "La casa de los conejos", "Munich en vsperas de una guerra", "Lizzie" i "Sin escapatoria", a banda de les sries "La edad dorada", "Hit Monkey", "Los Fraguel: la diversin contina", "As we see it" i "Los ltimos tres das". Totes, seleccionades i comentades pel nostre especialista Marc Garriga. +Fri, 21 Jan 2022 22:00:00 +0100 + + +El nou film de Guillermo del Toro, "El callejn de las almas perdidas", sobresurt entre les estrenes cinematogrfiques de la setmana. Tamb arriben a les sales "El mtodo Williams", "Agentes 355", "One shot (Misin de rescate)", "El cas Villa Caprice" i "La meva mare s una gorilla". A les plataformes es poden veure "La casa de los conejos", "Munich en vsperas de una guerra", "Lizzie" i "Sin escapatoria", a banda de les sries "La edad dorada", "Hit Monkey", "Los Fraguel: la diversin contina", "As we see it" i "Los ltimos tres das". Totes, seleccionades i comentades pel nostre especialista Marc Garriga. +no + +https://audios.ccma.cat/multimedia/mp3/1/7/1643086872471.mp3 +00:05:21 +21/01/2022 +//www.ccma.cat/catradio/alacarta/travelling/el-callejon-de-las-almas-perdidas-una-nova-joia-de-guillermo-del-toro/audio/1123348/ +//statics.ccma.cat/multimedia/jpg/5/9/1643086875795.jpg +Travelling + + +Mike Cahill, per Marc Rodrguez: viatge als confins de l'espai interior +Memento #190. Amb pressupostos relativament reduts i una esttica prpia del cinema independent, Mike Cahill s'interroga sobre qui som, on anem i com hi volem anar amb histries de cincia-ficci de caire filosfic com "Another Earth". En parlem amb un autntic fan del seu cinema, l'actor Marc Rodrguez, que aquests dies podeu veure al "Polnia" i a la comdia amb canons "T'estimo si he begut", al Teatre Poliorama. +Thu, 20 Jan 2022 12:00:00 +0100 + + +Memento #190. Amb pressupostos relativament reduts i una esttica prpia del cinema independent, Mike Cahill s'interroga sobre qui som, on anem i com hi volem anar amb histries de cincia-ficci de caire filosfic com "Another Earth". En parlem amb un autntic fan del seu cinema, l'actor Marc Rodrguez, que aquests dies podeu veure al "Polnia" i a la comdia amb canons "T'estimo si he begut", al Teatre Poliorama. +no + +https://audios.ccma.cat/multimedia/mp3/8/3/1642506930938.mp3 +00:59:55 +20/01/2022 +//www.ccma.cat/catradio/alacarta/memento/mike-cahill-per-marc-rodriguez-viatge-als-confins-de-lespai-interior/audio/1122618/ +//statics.ccma.cat/multimedia/jpg/0/4/1642506932940.jpg +Memento + + +"After life" i altres sries que acaben el 2022 +SerieSelektor #56. El geni de l'humor incmode Ricky Gervais tanca amb encert la tercera i ltima temporada de la dramdia sobre el dol i la depressi "After life" (Netflix). Repassem altres ficcions que tamb ens deixen aquest any com "Peaky Blinders" o "Killing Eve" i proposem comdies com "Hacks" (HBO Max) o "The other two" (Movistar +) per alleugerir les quarantenes. A les recomanacions a la carta suggerim "Condena" (Movistar +) i "No man's land" (HBO Max) + +Wed, 19 Jan 2022 22:30:00 +0100 + + +SerieSelektor #56. El geni de l'humor incmode Ricky Gervais tanca amb encert la tercera i ltima temporada de la dramdia sobre el dol i la depressi "After life" (Netflix). Repassem altres ficcions que tamb ens deixen aquest any com "Peaky Blinders" o "Killing Eve" i proposem comdies com "Hacks" (HBO Max) o "The other two" (Movistar +) per alleugerir les quarantenes. A les recomanacions a la carta suggerim "Condena" (Movistar +) i "No man's land" (HBO Max) + +no + +https://audios.ccma.cat/multimedia/mp3/7/1/1642664741617.mp3 +01:00:40 +19/01/2022 +//www.ccma.cat/catradio/alacarta/serieselektor/after-life-i-altres-series-que-acaben-el-2022/audio/1122825/ +//statics.ccma.cat/multimedia/jpg/5/9/1642664748095.jpg +SerieSelektor + + +Isaki Lacuesta: "Ser molt xulo competir a Berln amb cineastes a qui admiro" +Per primer cop a la histria, coincideixen dues pellcules catalanes a la secci oficial de la Berlinale, el prestigis festival de cinema de Berln. "Un ao, una noche", d'Isaki Lacuesta, n's una. El nostre company Marc Garriga ha entrevistat el director giron. +Wed, 19 Jan 2022 16:20:00 +0100 + + +Per primer cop a la histria, coincideixen dues pellcules catalanes a la secci oficial de la Berlinale, el prestigis festival de cinema de Berln. "Un ao, una noche", d'Isaki Lacuesta, n's una. El nostre company Marc Garriga ha entrevistat el director giron. +no + +https://audios.ccma.cat/multimedia/mp3/0/8/1642606824280.mp3 +00:05:33 +19/01/2022 +//www.ccma.cat/catradio/alacarta/travelling/isaki-lacuesta-sera-molt-xulo-competir-a-berlin-amb-cineastes-a-qui-admiro/audio/1122767/ +//statics.ccma.cat/multimedia/jpg/1/5/1642606827151.jpg +Travelling + + +Carla Simn: "Sento que a la prxima Berlinale ja seur a la taula dels grans" +El cinema catal est d'enhorabona. Per primer cop a la histria, coincideixen dos films catalans a la secci oficial de la Berlinale, el prestigis festival de cinema de Berln. Un d'ells s "Alcarrs", de Carla Simn. El nostre company Marc Garriga ha entrevistat la directora barcelonina. +Wed, 19 Jan 2022 16:15:00 +0100 + + +El cinema catal est d'enhorabona. Per primer cop a la histria, coincideixen dos films catalans a la secci oficial de la Berlinale, el prestigis festival de cinema de Berln. Un d'ells s "Alcarrs", de Carla Simn. El nostre company Marc Garriga ha entrevistat la directora barcelonina. +no + +https://audios.ccma.cat/multimedia/mp3/9/0/1642606226109.mp3 +00:06:26 +19/01/2022 +//www.ccma.cat/catradio/alacarta/travelling/carla-simon-sento-que-a-la-proxima-berlinale-ja-seure-a-la-taula-dels-grans/audio/1122766/ +//statics.ccma.cat/multimedia/jpg/5/6/1642606237265.jpg +Travelling + + +La msica de Vivaldi en la msica de cinema +Avui us volem mostrar diversos usos que la msica del compositor Antonio Vivaldi ha tingut en el cinema. I tamb alguns casos curiosos relacionats amb la msica vivaldiana i unes quantes versions i interpretacions que ha inspirat. Sentirem msica de bandes sonores com: "All that jazz", "Barry Lyndon", "Tots els homes del president", "El talent de Mr. Ripley" o "John Wick 3 Parabellum", entre d'altres. +Sun, 16 Jan 2022 13:00:00 +0100 + + +Avui us volem mostrar diversos usos que la msica del compositor Antonio Vivaldi ha tingut en el cinema. I tamb alguns casos curiosos relacionats amb la msica vivaldiana i unes quantes versions i interpretacions que ha inspirat. Sentirem msica de bandes sonores com: "All that jazz", "Barry Lyndon", "Tots els homes del president", "El talent de Mr. Ripley" o "John Wick 3 Parabellum", entre d'altres. +no + +https://audios.ccma.cat/multimedia/mp3/3/3/1642158024033.mp3 +01:00:21 +16/01/2022 +//www.ccma.cat/catradio/alacarta/el-violi-vermell/la-musica-de-vivaldi-en-la-musica-de-cinema/audio/1122216/ +//statics.ccma.cat/multimedia/jpg/1/0/1642158038201.jpg +El viol vermell + + +"Macbeth" illumina la cartellera +L'adaptaci del "Macbeth" de Shakespeare per part de Joel Coen s l'estrena ms destacada de la setmana. Tamb arriben a la cartellera "Madeleine Collins", "Buscant la mgica Doremi", "Lluntics" i "Scream". De les novetats en plataformes, el nostre especialista, Marc Garriga, recomana "Help", "El pacificador" i "Hotel Transsilvnia: Transformania", a banda de comentar "Archivo 81", "Raphaelismo", "Somebody somewhere", "Operacin Bfalo", "Express", "In the Earth" i "Naomi". +Thu, 13 Jan 2022 21:30:00 +0100 + + +L'adaptaci del "Macbeth" de Shakespeare per part de Joel Coen s l'estrena ms destacada de la setmana. Tamb arriben a la cartellera "Madeleine Collins", "Buscant la mgica Doremi", "Lluntics" i "Scream". De les novetats en plataformes, el nostre especialista, Marc Garriga, recomana "Help", "El pacificador" i "Hotel Transsilvnia: Transformania", a banda de comentar "Archivo 81", "Raphaelismo", "Somebody somewhere", "Operacin Bfalo", "Express", "In the Earth" i "Naomi". +no + +https://audios.ccma.cat/multimedia/mp3/5/2/1642106425025.mp3 +00:05:20 +13/01/2022 +//www.ccma.cat/catradio/alacarta/travelling/macbeth-illumina-la-cartellera/audio/1122158/ +//statics.ccma.cat/multimedia/jpg/6/6/1642106428166.jpg +Travelling + + +L'amistat femenina al cinema, per ngela Cervantes: fent cam juntes +Memento #189. L'actriu ngela Cervantes est nominada al Goya a la millor actriu revelaci pel seu paper a "Chavalas", una histria d'amistat entre quatre noies que van crixer a la mateixa barriada i mantenen el vincle tot i que la vida adulta les comena a portar per camins diferents. Amb ella volem repassar altres exemples de pellcules en qu els personatges femenins no actuen com a rivals, ni estan subordinats als masculins. Digueu-li sororitat, complicitat o, senzillament, amistat. + +Thu, 13 Jan 2022 12:00:00 +0100 + + +Memento #189. L'actriu ngela Cervantes est nominada al Goya a la millor actriu revelaci pel seu paper a "Chavalas", una histria d'amistat entre quatre noies que van crixer a la mateixa barriada i mantenen el vincle tot i que la vida adulta les comena a portar per camins diferents. Amb ella volem repassar altres exemples de pellcules en qu els personatges femenins no actuen com a rivals, ni estan subordinats als masculins. Digueu-li sororitat, complicitat o, senzillament, amistat. + +no + +https://audios.ccma.cat/multimedia/mp3/7/4/1641815749947.mp3 +00:59:55 +13/01/2022 +//www.ccma.cat/catradio/alacarta/memento/lamistat-femenina-al-cinema-per-angela-cervantes-fent-cami-juntes/audio/1121695/ +//statics.ccma.cat/multimedia/jpg/4/0/1641815755804.jpg +Memento + + +Chucky es passa a la televisi +Chucky, el ninot diablic, s'estrena a la televisi en format srie. Ha arribat aquesta setmana al canal Syfy, que est disponible a travs de les plataformes Movistar+, Vodafone i Orange, entre d'altres. La srie, que es diu "Chucky", mant el mateix esperit de les vuit pellcules anteriors de la saga. s un reportatge de Marc Garriga. +Mon, 10 Jan 2022 11:00:00 +0100 + + +Chucky, el ninot diablic, s'estrena a la televisi en format srie. Ha arribat aquesta setmana al canal Syfy, que est disponible a travs de les plataformes Movistar+, Vodafone i Orange, entre d'altres. La srie, que es diu "Chucky", mant el mateix esperit de les vuit pellcules anteriors de la saga. s un reportatge de Marc Garriga. +no + +https://audios.ccma.cat/multimedia/mp3/6/9/1642012264496.mp3 +00:02:33 +10/01/2022 +//www.ccma.cat/catradio/alacarta/travelling/chucky-es-passa-a-la-televisio/audio/1122018/ +//statics.ccma.cat/multimedia/jpg/3/1/1642012275313.jpg +Travelling + + +Quaranta anys del 1982: aquell gran any en la msica de cinema +Si repassem les bandes sonores de les pellicules que es van estrenar el 1982, hi podem trobar tota l'herncia rebuda fins aquell moment en la histria de la msica del cinema i, alhora, un bon grapat de tendncies que marcarien el futur de la msica cinematogrfica gaireb fins els nostres dies. El 1982 va ser un gran any, molt representatiu de la msica de cinema. Us ho mostrarem. +Sun, 09 Jan 2022 13:00:00 +0100 + + +Si repassem les bandes sonores de les pellicules que es van estrenar el 1982, hi podem trobar tota l'herncia rebuda fins aquell moment en la histria de la msica del cinema i, alhora, un bon grapat de tendncies que marcarien el futur de la msica cinematogrfica gaireb fins els nostres dies. El 1982 va ser un gran any, molt representatiu de la msica de cinema. Us ho mostrarem. +no + +https://audios.ccma.cat/multimedia/mp3/0/6/1641539734660.mp3 +01:02:51 +09/01/2022 +//www.ccma.cat/catradio/alacarta/el-violi-vermell/quaranta-anys-del-1982-aquell-gran-any-en-la-musica-de-cinema/audio/1121431/ +//statics.ccma.cat/multimedia/jpg/2/8/1641539741582.jpg +El viol vermell + + +Sean Penn encapala una setmana fluixa d'estrenes +Aquesta setmana arriba als cinemes "El dia de la bandera", dirigida i protagonitzada per Sean Penn. Ho fa amb opci d'udio o subtitulat en catal, igual com "Qu veiem quan mirem cap al cel?", "L'espia honest" i "No ploro mai". Completen les novetats en cartellera el film francs "Delicioso". En plataformes destaca l'estrena del film "El pramo" i les sries "Chucky", "Manhunt: The night stalke" i "Planeta verde". Totes, comentades pel nostre especialista, Marc Garriga. I amb intervencions de Fiona Dourif i David Casademunt. +Thu, 06 Jan 2022 22:45:00 +0100 + + +Aquesta setmana arriba als cinemes "El dia de la bandera", dirigida i protagonitzada per Sean Penn. Ho fa amb opci d'udio o subtitulat en catal, igual com "Qu veiem quan mirem cap al cel?", "L'espia honest" i "No ploro mai". Completen les novetats en cartellera el film francs "Delicioso". En plataformes destaca l'estrena del film "El pramo" i les sries "Chucky", "Manhunt: The night stalke" i "Planeta verde". Totes, comentades pel nostre especialista, Marc Garriga. I amb intervencions de Fiona Dourif i David Casademunt. +no + +https://audios.ccma.cat/multimedia/mp3/9/2/1641531624029.mp3 +00:04:55 +06/01/2022 +//www.ccma.cat/catradio/alacarta/travelling/sean-penn-encapcala-una-setmana-fluixa-destrenes/audio/1121417/ +//statics.ccma.cat/multimedia/jpg/7/4/1641531634347.jpg +Travelling + + +Les sries ms esperades del 2022 +Igual com passa amb el cinema, la petita pantalla tamb viur, als prxims mesos, dels superherois, de les preqeles i de les noves temporades de les sries d'xit. Per el 2022, a ms, reviur histries ja conegudes i en capgirar d'altres per sorprendre'ns com ara noms ho fa la televisi. s un reportatge de Marc Garriga. +Thu, 06 Jan 2022 21:55:00 +0100 + + +Igual com passa amb el cinema, la petita pantalla tamb viur, als prxims mesos, dels superherois, de les preqeles i de les noves temporades de les sries d'xit. Per el 2022, a ms, reviur histries ja conegudes i en capgirar d'altres per sorprendre'ns com ara noms ho fa la televisi. s un reportatge de Marc Garriga. +no + +https://audios.ccma.cat/multimedia/mp3/7/1/1641531617117.mp3 +00:03:42 +06/01/2022 +//www.ccma.cat/catradio/alacarta/travelling/les-series-mes-esperades-del-2022/audio/1121413/ +//statics.ccma.cat/multimedia/jpg/6/3/1641531632836.jpg +Travelling + + +El cinema del 2022: les pellcules ms esperades +Les sales de cinema confien, com ja s habitual, en el cinema de superherois i en les sagues per recuperar les xifres d'espectadors prepandmiques. Aquest 2022 tamb tornaran grans directors i intrprets de primera fila per animar el pblic. Per les cintes ms desitjades no sn noms les de Hollywood, sin que tamb n'hi ha algunes de catalanes molt esperades. s un reportatge de Marc Garriga. +Thu, 06 Jan 2022 21:50:00 +0100 + + +Les sales de cinema confien, com ja s habitual, en el cinema de superherois i en les sagues per recuperar les xifres d'espectadors prepandmiques. Aquest 2022 tamb tornaran grans directors i intrprets de primera fila per animar el pblic. Per les cintes ms desitjades no sn noms les de Hollywood, sin que tamb n'hi ha algunes de catalanes molt esperades. s un reportatge de Marc Garriga. +no + +https://audios.ccma.cat/multimedia/mp3/0/5/1641531619750.mp3 +00:03:30 +06/01/2022 +//www.ccma.cat/catradio/alacarta/travelling/el-cinema-del-2022-les-pellicules-mes-esperades/audio/1121415/ +//statics.ccma.cat/multimedia/jpg/5/6/1641531633965.jpg +Travelling + + +Steven Spielberg, per Quim Morales: l'autor ms taquiller +Memento #188. No se'ns acut millor regal de Reis que dedicar-li el programa a un dels cineastes ms taquillers de la histria, el creador d'"ET", "Salvem el soldat Ryan" i tantes altres obres clau, que amb 75 anys acabats de fer ha tornat a encertar-la amb el seu remake de "West Side Story". Tot i les seves incursions en temes molt adults, l'aposta per un cinema amb vocaci popular, en el millor sentit de la paraula, i una certa tendncia a mirar la vida amb la ingenutat i els sentiments d'un nen gran, han fet que sovint no se'l consideri com el que s: ms que un artes aplicat, un autor fonamental del Hollywood dels ltims cinquanta anys. En parlem amb un fill de la generaci que va somiar poder tenir una bicicleta voladora, Quim Morales, director i presentador de "L'ltima hora del mat de Catalunya Rdio". +Thu, 06 Jan 2022 12:00:00 +0100 + + +Memento #188. No se'ns acut millor regal de Reis que dedicar-li el programa a un dels cineastes ms taquillers de la histria, el creador d'"ET", "Salvem el soldat Ryan" i tantes altres obres clau, que amb 75 anys acabats de fer ha tornat a encertar-la amb el seu remake de "West Side Story". Tot i les seves incursions en temes molt adults, l'aposta per un cinema amb vocaci popular, en el millor sentit de la paraula, i una certa tendncia a mirar la vida amb la ingenutat i els sentiments d'un nen gran, han fet que sovint no se'l consideri com el que s: ms que un artes aplicat, un autor fonamental del Hollywood dels ltims cinquanta anys. En parlem amb un fill de la generaci que va somiar poder tenir una bicicleta voladora, Quim Morales, director i presentador de "L'ltima hora del mat de Catalunya Rdio". +no + +https://audios.ccma.cat/multimedia/mp3/4/2/1641384319924.mp3 +01:00:06 +06/01/2022 +//www.ccma.cat/catradio/alacarta/memento/steven-spielberg-per-quim-morales-lautor-mes-taquiller/audio/1121303/ +//statics.ccma.cat/multimedia/jpg/4/4/1641384321944.jpg +Memento + + +Concerts, per comenar l'any +En l'edici d'avui d''"El viol vermell", us proposem una selecci d'audicions de bandes sonores en les quals la protagonista de la pellcula s una obra musical concreta de format o aparena clssica, tot i que sigui composta originalment per a la pellcula per l'autor de la banda sonora, o en qu un concert orquestral clssic t un paper bsic, cabdal, en l'argument de la pellcula, tamb originalment compost per al film. +Sun, 02 Jan 2022 13:00:00 +0100 + + +En l'edici d'avui d''"El viol vermell", us proposem una selecci d'audicions de bandes sonores en les quals la protagonista de la pellcula s una obra musical concreta de format o aparena clssica, tot i que sigui composta originalment per a la pellcula per l'autor de la banda sonora, o en qu un concert orquestral clssic t un paper bsic, cabdal, en l'argument de la pellcula, tamb originalment compost per al film. +no + +https://audios.ccma.cat/multimedia/mp3/5/9/1640964331595.mp3 +00:55:03 +02/01/2022 +//www.ccma.cat/catradio/alacarta/el-violi-vermell/concerts-per-comencar-lany/audio/1120897/ +//statics.ccma.cat/multimedia/jpg/7/3/1640964335937.jpg +El viol vermell + + +Sries: Un any de fenmens i drames intensos +El recull de les sries ms destacades del 2021: les estrenes, els retorns, les que ja no tornaran mai ms, els documentals i un record a les personalitats vinculades a la ficci televisiva que ens han deixat per sempre. Ha estat un any marcat pel boom inesperat d'"El juego del calamar" i altres fenmens ms previsibles com els "Bridgerton" o el final de "La casa de papel". Al rnquing de les millors, apostem per drames d'alta volada com "Mare of Easttown" o la tercera temporada de "Succession". Amb Slvia Comet i Cristina Bordas. +Sat, 01 Jan 2022 12:10:00 +0100 + + +El recull de les sries ms destacades del 2021: les estrenes, els retorns, les que ja no tornaran mai ms, els documentals i un record a les personalitats vinculades a la ficci televisiva que ens han deixat per sempre. Ha estat un any marcat pel boom inesperat d'"El juego del calamar" i altres fenmens ms previsibles com els "Bridgerton" o el final de "La casa de papel". Al rnquing de les millors, apostem per drames d'alta volada com "Mare of Easttown" o la tercera temporada de "Succession". Amb Slvia Comet i Cristina Bordas. +no + +https://audios.ccma.cat/multimedia/mp3/5/1/1640016323715.mp3 +00:59:25 +01/01/2022 +//www.ccma.cat/catradio/alacarta/serieselektor/series-un-any-de-fenomens-i-drames-intensos/audio/1119792/ +//statics.ccma.cat/multimedia/jpg/2/2/1640018442622.jpg +SerieSelektor + + +El cinema del 2021, per Marta Ferrer i estrelles convidades: l'any de la reconstrucci +Memento #187. Repassem algunes de les millors histries que ens han acompanyat des de diferents pantalles, com ms grans millor, al llarg d'aquest any que ara s'acaba. Ha estat un any de moltes superproduccions que s'havien vist ajornades, de fora cinema musical i de pellcules amb segell autoral que deconstrueixen els gneres ms populars, especialment el western. Per fer la tria comptem amb la collaboraci de Marta Ferrer, l'experta en cinema i sries d'"El suplement" de Catalunya Rdio, i amb tretze estrelles convidades que ja han passat pel programa. No patiu, que al "Triler sincer" ho compensarem analitzant una de les pellcules ms mal valorades de l'any. +Thu, 30 Dec 2021 12:00:00 +0100 + + +Memento #187. Repassem algunes de les millors histries que ens han acompanyat des de diferents pantalles, com ms grans millor, al llarg d'aquest any que ara s'acaba. Ha estat un any de moltes superproduccions que s'havien vist ajornades, de fora cinema musical i de pellcules amb segell autoral que deconstrueixen els gneres ms populars, especialment el western. Per fer la tria comptem amb la collaboraci de Marta Ferrer, l'experta en cinema i sries d'"El suplement" de Catalunya Rdio, i amb tretze estrelles convidades que ja han passat pel programa. No patiu, que al "Triler sincer" ho compensarem analitzant una de les pellcules ms mal valorades de l'any. +no + +https://audios.ccma.cat/multimedia/mp3/0/1/1640686511110.mp3 +00:59:55 +30/12/2021 +//www.ccma.cat/catradio/alacarta/memento/el-cinema-del-2021-per-marta-ferrer-i-estrelles-convidades-lany-de-la-reconstruccio/audio/1120549/ +//statics.ccma.cat/multimedia/jpg/5/3/1640686516735.jpg +Memento + + +Top 10 de les sries de l'any +SerieSelektor #55. El clssic rnquing anual de les ficcions que ens han alegrat el 2021. El millor de l'any segons l'equip del "SerieSelektor" amb les aportacions de convidats especials com Cristina Bordas, de "Sries i punt", i Lorenzo Mejino, especialista en sries remotes i desconegudes, que ens acostar el seu top de les millors sries del 2021 que encara no tenen distribuci a Espanya. + + +Wed, 29 Dec 2021 22:30:00 +0100 + + +SerieSelektor #55. El clssic rnquing anual de les ficcions que ens han alegrat el 2021. El millor de l'any segons l'equip del "SerieSelektor" amb les aportacions de convidats especials com Cristina Bordas, de "Sries i punt", i Lorenzo Mejino, especialista en sries remotes i desconegudes, que ens acostar el seu top de les millors sries del 2021 que encara no tenen distribuci a Espanya. + + +no + +https://audios.ccma.cat/multimedia/mp3/0/5/1640706039750.mp3 +01:00:04 +29/12/2021 +//www.ccma.cat/catradio/alacarta/serieselektor/top-10-de-les-series-de-lany/audio/1120582/ +//statics.ccma.cat/multimedia/jpg/6/5/1640706041956.jpg +SerieSelektor + + +"El contador de cartas" passa per sobre dels homes del rei +Les estrenes de cinema es tornen a avanar a dimecres. Aquesta setmana destaquen "The King's Man: La primera misin" i "El contador de cartas", a banda de "100 das con la Tata" i "Vuelta a casa de mi madre". Pel que fa a les plataformes, l'1 de gener es presenta l'especial "Harry Potter: Regreso a Hogwarts". Abans, sries com "El libro de Boba Fett", "Qudate a mi lado", "Un escndalo muy britnico", "Upright" i "Los Larkin"; i films com "Rescate en las profundidades", "El silencio de los espas", "Stardust" i "John y el hoyo". Totes, comentades pel nostre especialista, Marc Garriga. +Wed, 29 Dec 2021 06:20:00 +0100 + + +Les estrenes de cinema es tornen a avanar a dimecres. Aquesta setmana destaquen "The King's Man: La primera misin" i "El contador de cartas", a banda de "100 das con la Tata" i "Vuelta a casa de mi madre". Pel que fa a les plataformes, l'1 de gener es presenta l'especial "Harry Potter: Regreso a Hogwarts". Abans, sries com "El libro de Boba Fett", "Qudate a mi lado", "Un escndalo muy britnico", "Upright" i "Los Larkin"; i films com "Rescate en las profundidades", "El silencio de los espas", "Stardust" i "John y el hoyo". Totes, comentades pel nostre especialista, Marc Garriga. +no + +https://audios.ccma.cat/multimedia/mp3/6/8/1640755523386.mp3 +00:05:20 +29/12/2021 +//www.ccma.cat/catradio/alacarta/travelling/el-contador-de-cartas-passa-per-sobre-dels-homes-del-rei/audio/1120639/ +//statics.ccma.cat/multimedia/jpg/7/8/1640755524287.jpg +Travelling + + +Per Sant Esteve, msica nadalenca de cinema +En un dia com avui, us oferim una selecci de musiques relacionades amb el Nadal; una selecci, naturalment, de msica cinematogrfica, tot i que amb una obertura i un tancament clssics, per agermanar la temtica del programa amb la temtica essencial de l'emissora. + + +Sun, 26 Dec 2021 13:00:00 +0100 + + +En un dia com avui, us oferim una selecci de musiques relacionades amb el Nadal; una selecci, naturalment, de msica cinematogrfica, tot i que amb una obertura i un tancament clssics, per agermanar la temtica del programa amb la temtica essencial de l'emissora. + + +no + +https://audios.ccma.cat/multimedia/mp3/4/6/1640334047264.mp3 +00:59:32 +26/12/2021 +//www.ccma.cat/catradio/alacarta/el-violi-vermell/per-sant-esteve-musica-nadalenca-de-cinema/audio/1120254/ +//statics.ccma.cat/multimedia/jpg/4/4/1640334049544.jpg +El viol vermell + + +La saga "Alien", per Luis Nostromo: crits a l'espai i molta mala bava +Memento #186. Des que vam pujar a la nau Nostromo per primera vegada amb la tinent Ripley i la resta de la tripulaci, ja fa ms de 40 anys, aquest sser d'esttica biomecnica anomenat Alien se'ns ha arrapat a la memria igual que s'enganxava a la cara del pobre John Hurt. Repassem els moments culminants de la saga de cincia-ficci ms terrorfica amb tota una autoritat en la matria: Luis Escribano, conegut a les xarxes com a Luis Nostromo, s un fan i colleccionista de tota mena d'objectes relacionats amb les pellcules, i ha acabat construint alguns dels decorats a escala real en el que ja s'ha convertit en el Museu Alien de Barcelona. + + +Thu, 23 Dec 2021 12:00:00 +0100 + + +Memento #186. Des que vam pujar a la nau Nostromo per primera vegada amb la tinent Ripley i la resta de la tripulaci, ja fa ms de 40 anys, aquest sser d'esttica biomecnica anomenat Alien se'ns ha arrapat a la memria igual que s'enganxava a la cara del pobre John Hurt. Repassem els moments culminants de la saga de cincia-ficci ms terrorfica amb tota una autoritat en la matria: Luis Escribano, conegut a les xarxes com a Luis Nostromo, s un fan i colleccionista de tota mena d'objectes relacionats amb les pellcules, i ha acabat construint alguns dels decorats a escala real en el que ja s'ha convertit en el Museu Alien de Barcelona. + + +no + +https://audios.ccma.cat/multimedia/mp3/2/8/1640000140282.mp3 +00:59:55 +23/12/2021 +//www.ccma.cat/catradio/alacarta/memento/la-saga-alien-per-luis-nostromo-crits-a-lespai-i-molta-mala-bava/audio/1119767/ +//statics.ccma.cat/multimedia/jpg/2/2/1640000143422.jpg +Memento + + +Cagada de sries +SeriSelektor #54. Al "SerieSelektor" fem que el ti cagui les ficcions ms decebedores de l'any. Les ms avorrides, fallides o directament dolentes que s millor passar per alt i entre les quals destaquen "Nine perfect strangers", "lite", "Al borde", "Hit and run" i "The morning show". Per contrarestar les hores perdudes davant la pantalla proposem "Homecoming" (Prime Video), "Cmo vender drogas online"(Netflix), "Perni" (Filmin), "Perdiendo a Alice" (Apple TV+) i "The hour" (Prime). + +Wed, 22 Dec 2021 22:30:00 +0100 + + +SeriSelektor #54. Al "SerieSelektor" fem que el ti cagui les ficcions ms decebedores de l'any. Les ms avorrides, fallides o directament dolentes que s millor passar per alt i entre les quals destaquen "Nine perfect strangers", "lite", "Al borde", "Hit and run" i "The morning show". Per contrarestar les hores perdudes davant la pantalla proposem "Homecoming" (Prime Video), "Cmo vender drogas online"(Netflix), "Perni" (Filmin), "Perdiendo a Alice" (Apple TV+) i "The hour" (Prime). + +no + +https://audios.ccma.cat/multimedia/mp3/1/7/1640242833671.mp3 +01:01:32 +22/12/2021 +//www.ccma.cat/catradio/alacarta/serieselektor/cagada-de-series/audio/1120098/ +//statics.ccma.cat/multimedia/jpg/8/5/1640255988458.jpg +SerieSelektor + + +"West Side Story" i "Matrix Resurrections", dues cares d'una mateixa moneda +Aquesta setmana s'estrenen dos exercicis de nostlgia molt diferents. Arriba als cinemes la nova versi de "West Side Story", dirigida per Steven Spielberg, i tamb "Matrix Resurrections", una nova seqela d'aquest univers creat per les germanes Wachowski. El nostre especialista en cinema i sries les analitza, juntament amb les altres estrenes, "Silent night" i "Canta 2", en sales; "Hierve" i "La noche del fin de los tiempos", a Filmin; i les sries "Mar de la tranquilidad" i "The wonder years". +Wed, 22 Dec 2021 18:50:00 +0100 + + +Aquesta setmana s'estrenen dos exercicis de nostlgia molt diferents. Arriba als cinemes la nova versi de "West Side Story", dirigida per Steven Spielberg, i tamb "Matrix Resurrections", una nova seqela d'aquest univers creat per les germanes Wachowski. El nostre especialista en cinema i sries les analitza, juntament amb les altres estrenes, "Silent night" i "Canta 2", en sales; "Hierve" i "La noche del fin de los tiempos", a Filmin; i les sries "Mar de la tranquilidad" i "The wonder years". +no + +https://audios.ccma.cat/multimedia/mp3/0/9/1640196317090.mp3 +00:05:23 +22/12/2021 +//www.ccma.cat/catradio/alacarta/travelling/west-side-story-i-matrix-resurrections-dues-cares-duna-mateixa-moneda/audio/1120055/ +//statics.ccma.cat/multimedia/jpg/2/3/1640196318632.jpg +Travelling + + +Agafem-nos-ho amb calma amb en Georges +S'acosten les festes de Nadal i el final de l'any i tots sabem que sn uns dies, que, ms enll de la festa, les celebracions i les trobades -si es pot i ens deixen- no deixen de ser dies plens de soroll i un cert atabalament ambiental. Per aix hem pensat que des d'"El viol vermell", us podrem regalar, gaireb com si us el cagus el ti, una horeta de msica tranquilla i sentimental, quan no directament romntica, obra d'un dels compositors ms meldics de la histria de la msica del cinema. Avui dediquem el programa a la msica del compositor francs Georges Dlerue. +Sun, 19 Dec 2021 13:00:00 +0100 + + +S'acosten les festes de Nadal i el final de l'any i tots sabem que sn uns dies, que, ms enll de la festa, les celebracions i les trobades -si es pot i ens deixen- no deixen de ser dies plens de soroll i un cert atabalament ambiental. Per aix hem pensat que des d'"El viol vermell", us podrem regalar, gaireb com si us el cagus el ti, una horeta de msica tranquilla i sentimental, quan no directament romntica, obra d'un dels compositors ms meldics de la histria de la msica del cinema. Avui dediquem el programa a la msica del compositor francs Georges Dlerue. +no + +https://audios.ccma.cat/multimedia/mp3/3/7/1639755914173.mp3 +00:57:29 +19/12/2021 +//www.ccma.cat/catradio/alacarta/el-violi-vermell/agafemnosho-amb-calma-amb-en-georges/audio/1119515/ +//statics.ccma.cat/multimedia/jpg/9/7/1639755918879.jpg +El viol vermell + + +Spiderman torna per la porta gran +"Spider-man: No way home" suposa no noms el retorn de l'home aranya de Tom Holland, sin el de molts altres personatges. s l'estrella de les estrenes d'aquesta setmana, juntament amb "Mam o pap", de Dani de la Orden, i "Cerca de ti", d'Uberto Pasolini. Tamb arriben als cinemes "La historia de mi mujer"; "15 horas", de Judith Colell, i "Una llibreria a Pars", entre d'altres. A les plataformes s'estrenen "Being the Ricardos", amb Nicole Kidman i Javier Bardem, "El canto del cisne" i "Cryptozoo". I en sries, destaquen "Sin novedad", "Dan Brown: El smbolo perdido" i "Station Eleven". Totes, comentades pel nostre especialista, Marc Garriga. +Fri, 17 Dec 2021 09:30:00 +0100 + + +"Spider-man: No way home" suposa no noms el retorn de l'home aranya de Tom Holland, sin el de molts altres personatges. s l'estrella de les estrenes d'aquesta setmana, juntament amb "Mam o pap", de Dani de la Orden, i "Cerca de ti", d'Uberto Pasolini. Tamb arriben als cinemes "La historia de mi mujer"; "15 horas", de Judith Colell, i "Una llibreria a Pars", entre d'altres. A les plataformes s'estrenen "Being the Ricardos", amb Nicole Kidman i Javier Bardem, "El canto del cisne" i "Cryptozoo". I en sries, destaquen "Sin novedad", "Dan Brown: El smbolo perdido" i "Station Eleven". Totes, comentades pel nostre especialista, Marc Garriga. +no + +https://audios.ccma.cat/multimedia/mp3/5/1/1639730452015.mp3 +00:06:06 +17/12/2021 +//www.ccma.cat/catradio/alacarta/travelling/spiderman-torna-per-la-porta-gran/audio/1119436/ +//statics.ccma.cat/multimedia/jpg/0/3/1639730453930.jpg +Travelling + + +Ulrich Seidl, per Nria Bendicho: l'entomleg de les imatges +Memento #185. L'escriptora Nria Bendicho ha debutat en la literatura amb una novella molt potent, tan srdida com ben escrita, "Terres mortes". Ens proposa analitzar l'obra del director austrac Ulrich Seidl, que des del documental o la ficci, en obres com la trilogia "Parads", s'ha dedicat a retratar els elements ms absurds, frgils i extravagants de la societat europea moderna, all que normalment s'intenta ocultar sota la catifa... o al soterrani. +Thu, 16 Dec 2021 12:00:00 +0100 + + +Memento #185. L'escriptora Nria Bendicho ha debutat en la literatura amb una novella molt potent, tan srdida com ben escrita, "Terres mortes". Ens proposa analitzar l'obra del director austrac Ulrich Seidl, que des del documental o la ficci, en obres com la trilogia "Parads", s'ha dedicat a retratar els elements ms absurds, frgils i extravagants de la societat europea moderna, all que normalment s'intenta ocultar sota la catifa... o al soterrani. +no + +https://audios.ccma.cat/multimedia/mp3/8/0/1639650353808.mp3 +00:59:55 +16/12/2021 +//www.ccma.cat/catradio/alacarta/memento/ulrich-seidl-per-nuria-bendicho-lentomoleg-de-les-imatges/audio/1119327/ +//statics.ccma.cat/multimedia/jpg/9/8/1639650355489.jpg +Memento + + +"Succession" i la nostlgia norantera +SerieSelektor #53. Ens desfem en elogis sobre el brillant final de la tercera temporada de "Succession" (HBO Max) sense fer ni un sol espiler i acceptem amb resignaci la febre de les plataformes per recuperar histries dels anys 90 com "And just like that", la seqela de "Sexe a Nova York". A les recomanacions a la carta, proposem "Yellowjackets" (Movistar +) i "Good omens" (Prime Video). + +Wed, 15 Dec 2021 22:30:00 +0100 + + +SerieSelektor #53. Ens desfem en elogis sobre el brillant final de la tercera temporada de "Succession" (HBO Max) sense fer ni un sol espiler i acceptem amb resignaci la febre de les plataformes per recuperar histries dels anys 90 com "And just like that", la seqela de "Sexe a Nova York". A les recomanacions a la carta, proposem "Yellowjackets" (Movistar +) i "Good omens" (Prime Video). + +no + +https://audios.ccma.cat/multimedia/mp3/6/5/1639640757956.mp3 +00:59:56 +15/12/2021 +//www.ccma.cat/catradio/alacarta/serieselektor/succession-i-la-nostalgia-norantera/audio/1119298/ +//statics.ccma.cat/multimedia/jpg/2/9/1639640763392.jpg +SerieSelektor + + +Msica d'adaptacions de cmics (abans de l'univers de Marvel) +Avui dediquem "El viol vermell" a oferir-vos fragments de bandes sonores de films que sn adaptacions de cmics a la gran pantalla, abans de l'aparici dels films de l'univers cinematogrfic de Marvel (abans de tot el munt de pellis de superherois del cmic que ens han arribat des del 2008). Sentirem msica de "El prncep valent", "Superman", "Batman", "Watchmen"... +Sun, 12 Dec 2021 13:00:00 +0100 + + +Avui dediquem "El viol vermell" a oferir-vos fragments de bandes sonores de films que sn adaptacions de cmics a la gran pantalla, abans de l'aparici dels films de l'univers cinematogrfic de Marvel (abans de tot el munt de pellis de superherois del cmic que ens han arribat des del 2008). Sentirem msica de "El prncep valent", "Superman", "Batman", "Watchmen"... +no + +https://audios.ccma.cat/multimedia/mp3/5/0/1638557717805.mp3 +00:59:02 +12/12/2021 +//www.ccma.cat/catradio/alacarta/el-violi-vermell/musica-dadaptacions-de-comics-abans-de-lunivers-de-marvel/audio/1118080/ +//statics.ccma.cat/multimedia/jpg/5/3/1638557720735.jpg +El viol vermell + + +Netflix dinamita la cartellera amb les seves estrenes de finals d'any +La plataforma de "streaming" lder al mn estrena grans films a finals d'any de cara a la temporada de premis. Aquesta setmana li toca a "No mires arriba" i "Imperdonable". Als cinemes, arriben, de moment, en exclusiva, "Querido Evan Hansen", "Tres pisos", "Qu hicimos mal?", "Demonic" i moltes altres. A les plataformes aterren dues sries revival: "And just like that..." (hereva de "Sexo en Nueva York") i "CSI: Vegas". Tots els ttols comentats pel nostre especialista, Marc Garriga. +Fri, 10 Dec 2021 07:15:00 +0100 + + +La plataforma de "streaming" lder al mn estrena grans films a finals d'any de cara a la temporada de premis. Aquesta setmana li toca a "No mires arriba" i "Imperdonable". Als cinemes, arriben, de moment, en exclusiva, "Querido Evan Hansen", "Tres pisos", "Qu hicimos mal?", "Demonic" i moltes altres. A les plataformes aterren dues sries revival: "And just like that..." (hereva de "Sexo en Nueva York") i "CSI: Vegas". Tots els ttols comentats pel nostre especialista, Marc Garriga. +no + +https://audios.ccma.cat/multimedia/mp3/1/2/1639112702221.mp3 +00:06:26 +10/12/2021 +//www.ccma.cat/catradio/alacarta/travelling/netflix-dinamita-la-cartellera-amb-les-seves-estrenes-de-finals-dany/audio/1118599/ +//statics.ccma.cat/multimedia/jpg/7/4/1639112703147.jpg +Travelling + + +Julie Andrews, per Fiona Amargs: un pessic de sucre, un polsim de geni +Memento #184. Una de les convidades ms joves que han passat mai pel programa s la Fiona Amargs, actriu i cantant, escollida nova prescriptora cultural d'iCat. Curiosament, ens proposa parlar de tota una veterana que va marcar la seva infncia i la d'unes quantes generacions anteriors a la seva: Julie Andrews. Repassem la carrera d'una actriu de veu prodigiosa que tot just debutar al cinema va encadenar dos xits tan clamorosos com "Mary Poppins" i "Somriures i llgrimes". +Thu, 09 Dec 2021 12:00:00 +0100 + + +Memento #184. Una de les convidades ms joves que han passat mai pel programa s la Fiona Amargs, actriu i cantant, escollida nova prescriptora cultural d'iCat. Curiosament, ens proposa parlar de tota una veterana que va marcar la seva infncia i la d'unes quantes generacions anteriors a la seva: Julie Andrews. Repassem la carrera d'una actriu de veu prodigiosa que tot just debutar al cinema va encadenar dos xits tan clamorosos com "Mary Poppins" i "Somriures i llgrimes". +no + +https://audios.ccma.cat/multimedia/mp3/7/7/1638971434977.mp3 +00:59:54 +09/12/2021 +//www.ccma.cat/catradio/alacarta/memento/julie-andrews-per-fiona-amargos-un-pessic-de-sucre-un-polsim-de-geni/audio/1118435/ +//statics.ccma.cat/multimedia/jpg/3/9/1638971436993.jpg +Memento + + +"Justified" i les paraulotes dels Beatles +SerieSelektor #52. Ens fixem en una srie infravalorada, subtitulada com "La ley de Rylan", un drama policial amb tocs de western ambientat en l'mbit rural dels Estats Units (Movistar+). A les recomanacions a mida tamb proposem "La ruta del dinero" (Filmin) i conversem sobre les notcies ms destacades de la setmana, sobretot al voltant de la srie documental "The Beatles: Get back" (Disney +). +Wed, 08 Dec 2021 22:30:00 +0100 + + +SerieSelektor #52. Ens fixem en una srie infravalorada, subtitulada com "La ley de Rylan", un drama policial amb tocs de western ambientat en l'mbit rural dels Estats Units (Movistar+). A les recomanacions a mida tamb proposem "La ruta del dinero" (Filmin) i conversem sobre les notcies ms destacades de la setmana, sobretot al voltant de la srie documental "The Beatles: Get back" (Disney +). +no + +https://audios.ccma.cat/multimedia/mp3/0/7/1638883816770.mp3 +01:02:44 +08/12/2021 +//www.ccma.cat/catradio/alacarta/serieselektor/justified-i-les-paraulotes-dels-beatles/audio/1118347/ +//statics.ccma.cat/multimedia/jpg/8/9/1638883828298.jpg +SerieSelektor + + +Entre l'original i la cpia +En el programa d'avui farem l'exercici de comparar fragments de bandes sonores entre parells de pellcules, essent, les segones pellcules, els remakes de les primeres. Sentirem msica d'"Els set samurais" i "Els set magnfics", "La mort se'n va de vacances" i "Coneixes Joe Black?", "Sabrina i Sabrina"... +Sun, 05 Dec 2021 13:00:00 +0100 + + +En el programa d'avui farem l'exercici de comparar fragments de bandes sonores entre parells de pellcules, essent, les segones pellcules, els remakes de les primeres. Sentirem msica d'"Els set samurais" i "Els set magnfics", "La mort se'n va de vacances" i "Coneixes Joe Black?", "Sabrina i Sabrina"... +no + +https://audios.ccma.cat/multimedia/mp3/8/6/1638557715968.mp3 +00:59:11 +05/12/2021 +//www.ccma.cat/catradio/alacarta/el-violi-vermell/entre-loriginal-i-la-copia/audio/1118079/ +//statics.ccma.cat/multimedia/jpg/3/4/1638557720543.jpg +El viol vermell + + +Arriba al cinema un pquer d'estrenes guanyador +4 pellcules excellents es poden veure ja en sales: "Cazafantasmas: Ms all", "Fue la mano de Dios" i les catalanes "Sis dies corrents" i "El amor en su lugar". A ms, tamb arriben "La familia perfecta", "Clifford, el gran perro rojo", "Black box" i "Nido de vboras". I en sries, "Harlem", "Los policas" i "Partisan". Totes, comentades pel nostre especialista, Marc Garriga. +Fri, 03 Dec 2021 22:00:00 +0100 + + +4 pellcules excellents es poden veure ja en sales: "Cazafantasmas: Ms all", "Fue la mano de Dios" i les catalanes "Sis dies corrents" i "El amor en su lugar". A ms, tamb arriben "La familia perfecta", "Clifford, el gran perro rojo", "Black box" i "Nido de vboras". I en sries, "Harlem", "Los policas" i "Partisan". Totes, comentades pel nostre especialista, Marc Garriga. +no + +https://audios.ccma.cat/multimedia/mp3/4/8/1638568214484.mp3 +00:05:03 +03/12/2021 +//www.ccma.cat/catradio/alacarta/travelling/arriba-al-cinema-un-poquer-destrenes-guanyador/audio/1118103/ +//statics.ccma.cat/multimedia/jpg/0/6/1638568216760.jpg +Travelling + + +Christopher Guest, per Carlo Padial: la vida en un gag +Memento #183. Ens visita Carlo Padial en plena ressaca per l'xit de la seva srie "Doctor Portuondo", basada en el llibre del mateix ttol. Padial, alg a qui li agrada jugar amb els lmits entre realitat i ficci, ens proposa parlar del cmic, guionista i director Christopher Guest, una autoritat a l'hora d'introduir l'humor en histries rodades com si fossin documentals, que parteixen d'una observaci atenta de la realitat i la porten a l'extrem (o potser no tant). El seu gui ms recordat s "This is Spinal Tap", un ttol de culte dels 80 que va acabar provocant el naixement d'un grup de rock dur. +Thu, 02 Dec 2021 12:00:00 +0100 + + +Memento #183. Ens visita Carlo Padial en plena ressaca per l'xit de la seva srie "Doctor Portuondo", basada en el llibre del mateix ttol. Padial, alg a qui li agrada jugar amb els lmits entre realitat i ficci, ens proposa parlar del cmic, guionista i director Christopher Guest, una autoritat a l'hora d'introduir l'humor en histries rodades com si fossin documentals, que parteixen d'una observaci atenta de la realitat i la porten a l'extrem (o potser no tant). El seu gui ms recordat s "This is Spinal Tap", un ttol de culte dels 80 que va acabar provocant el naixement d'un grup de rock dur. +no + +https://audios.ccma.cat/multimedia/mp3/5/7/1638442823875.mp3 +00:59:54 +02/12/2021 +//www.ccma.cat/catradio/alacarta/memento/christopher-guest-per-carlo-padial-la-vida-en-un-gag/audio/1117843/ +//statics.ccma.cat/multimedia/jpg/8/6/1638442861068.jpg +Memento + + +Sries per mirar al desembre +SerieSeleketor #51. Calendari serifil de la recta final de l'any. Proposem estrenes com "Voir"(Nexflix), "Los policias" (Filmin) o "El libro de Boba Fett"(Disney+) i retorns com "The Great" (Starzplay) o "Cobra Kai" (Netflix). Tamb conversem amb Diego San Jos, el creador de la stira poltica "Venga Juan" (HBO Max). A les sries a la carta recomanem "Watchmen" (HBO Max). + +Wed, 01 Dec 2021 22:30:00 +0100 + + +SerieSeleketor #51. Calendari serifil de la recta final de l'any. Proposem estrenes com "Voir"(Nexflix), "Los policias" (Filmin) o "El libro de Boba Fett"(Disney+) i retorns com "The Great" (Starzplay) o "Cobra Kai" (Netflix). Tamb conversem amb Diego San Jos, el creador de la stira poltica "Venga Juan" (HBO Max). A les sries a la carta recomanem "Watchmen" (HBO Max). + +no + +https://audios.ccma.cat/multimedia/mp3/5/3/1638208234435.mp3 +01:03:46 +01/12/2021 +//www.ccma.cat/catradio/alacarta/serieselektor/series-per-mirar-al-desembre/audio/1117492/ +//statics.ccma.cat/multimedia/jpg/6/6/1638256175966.jpg +SerieSelektor + + +Diego San Jos: "No hi ha res ms esperpntic que la corrupci poltica espanyola" +Conversem amb el creador de "Venga Juan", la tercera entrega de la stira poltica que protagonitza Javier Cmara. Aquesta temporada est marcada per la corrupci. El showrunner de la srie l'imagina com un poltic sense ideologia i seguidor del Logronys. Segons San Jos, a la vida real Juan Carrasco seria un personatge irrellevant que acabaria al Senat prenent decisions intranscendents. + +Wed, 01 Dec 2021 22:29:00 +0100 + + +Conversem amb el creador de "Venga Juan", la tercera entrega de la stira poltica que protagonitza Javier Cmara. Aquesta temporada est marcada per la corrupci. El showrunner de la srie l'imagina com un poltic sense ideologia i seguidor del Logronys. Segons San Jos, a la vida real Juan Carrasco seria un personatge irrellevant que acabaria al Senat prenent decisions intranscendents. + +no + +https://audios.ccma.cat/multimedia/mp3/7/5/1638207033157.mp3 +00:19:49 +01/12/2021 +//www.ccma.cat/catradio/alacarta/serieselektor/diego-san-jose-no-hi-ha-res-mes-esperpentic-que-la-corrupcio-politica-espanyola/audio/1117489/ +//statics.ccma.cat/multimedia/jpg/6/0/1638207044106.jpg +SerieSelektor + + +Recordant Kamen +En el divuit aniversari de la mort de Michael Kamen, recordem aquest compositor i les seves bandes sonores. Sentirem msica de "Brazil", "La jungla de vidre", "Cercle d'amics", "Robin Hood: Prncep dels lladres" i d'altres. +Sun, 28 Nov 2021 13:00:00 +0100 + + +En el divuit aniversari de la mort de Michael Kamen, recordem aquest compositor i les seves bandes sonores. Sentirem msica de "Brazil", "La jungla de vidre", "Cercle d'amics", "Robin Hood: Prncep dels lladres" i d'altres. +no + +https://audios.ccma.cat/multimedia/mp3/8/5/1637918735458.mp3 +00:55:10 +28/11/2021 +//www.ccma.cat/catradio/alacarta/el-violi-vermell/recordant-kamen/audio/1117148/ +//statics.ccma.cat/multimedia/jpg/1/6/1637918737261.jpg +El viol vermell + + +"La casa Gucci" o el festival de la sobreactuaci +El film de Ridley Scott protagonitzat per Lady Gaga s l'estrena ms destacada de la setmana. Tamb arriben "Encanto", "La hija", "Lamb" i "Resident Evil: Bienvenidos a Raccoon City". A ms, dins el camp ms experimental, aterren dues cintes especials: "Magaluf Ghost Town" i "Espritu sangrado". A les plataformes destaquen tres novetats: "Ojo de halcn", "The Beatles: Get Back" i "Possessions". +Fri, 26 Nov 2021 07:30:00 +0100 + + +El film de Ridley Scott protagonitzat per Lady Gaga s l'estrena ms destacada de la setmana. Tamb arriben "Encanto", "La hija", "Lamb" i "Resident Evil: Bienvenidos a Raccoon City". A ms, dins el camp ms experimental, aterren dues cintes especials: "Magaluf Ghost Town" i "Espritu sangrado". A les plataformes destaquen tres novetats: "Ojo de halcn", "The Beatles: Get Back" i "Possessions". +no + +https://audios.ccma.cat/multimedia/mp3/0/9/1637902824490.mp3 +00:05:16 +26/11/2021 +//www.ccma.cat/catradio/alacarta/travelling/la-casa-gucci-o-el-festival-de-la-sobreactuacio/audio/1117113/ +//statics.ccma.cat/multimedia/jpg/1/4/1637902842041.jpg +Travelling + + +Metratge trobat, per Vctor Esquirol: les cmeres les carrega la bruixa +Memento #182. En les dues ltimes dcades, sobretot a partir de l'xit d'"El projecte de la bruixa de Blair", un dels subgneres terrorfics ms fructfers ha estat el del metratge trobat ("found footage"), pellcules que juguen amb la confusi entre ficci i documental a travs de gravacions inquietants fetes per persones que, normalment, se suposa que ja no sn entre nosaltres. El crtic de cinema Vctor Esquirol ens proposa repassar les arrels d'aquest tipus d'histries, i destriar el gra de la palla en un subgnere que ha acabat caient un pl en la repetici. +Thu, 25 Nov 2021 12:00:00 +0100 + + +Memento #182. En les dues ltimes dcades, sobretot a partir de l'xit d'"El projecte de la bruixa de Blair", un dels subgneres terrorfics ms fructfers ha estat el del metratge trobat ("found footage"), pellcules que juguen amb la confusi entre ficci i documental a travs de gravacions inquietants fetes per persones que, normalment, se suposa que ja no sn entre nosaltres. El crtic de cinema Vctor Esquirol ens proposa repassar les arrels d'aquest tipus d'histries, i destriar el gra de la palla en un subgnere que ha acabat caient un pl en la repetici. +no + +https://audios.ccma.cat/multimedia/mp3/8/0/1637417418308.mp3 +00:59:54 +25/11/2021 +//www.ccma.cat/catradio/alacarta/memento/metratge-trobat-per-victor-esquirol-les-cameres-les-carrega-la-bruixa/audio/1116508/ +//statics.ccma.cat/multimedia/jpg/0/9/1637417421090.jpg +Memento + + + -- 2.40.1 From 4bf96ea87ed0ba7f84f27682bb9b19f01b04fa82 Mon Sep 17 00:00:00 2001 From: nee Date: Sun, 6 Feb 2022 19:25:13 +0100 Subject: [PATCH 009/102] tests: Fix utils::tests::test_itunes_lookup_id and utils::tests::test_itunes_to_rss. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The rss moved again 😢. Now both are tested in case it moves a 3rd time. --- podcasts-gtk/src/utils.rs | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/podcasts-gtk/src/utils.rs b/podcasts-gtk/src/utils.rs index d78d35f..17ce2e9 100644 --- a/podcasts-gtk/src/utils.rs +++ b/podcasts-gtk/src/utils.rs @@ -621,10 +621,11 @@ mod tests { #[tokio::test] async fn test_itunes_to_rss() -> Result<()> { let itunes_url = "https://itunes.apple.com/podcast/id1195206601"; - let rss_url = String::from( - "https://feeds.acast.com/public/shows/f5b64019-68c3-57d4-b70b-043e63e5cbf6", - ); - assert_eq!(rss_url, itunes_to_rss(itunes_url).await?); + // they keep changing the urls + let rss_url = "https://feeds.acast.com/public/shows/f5b64019-68c3-57d4-b70b-043e63e5cbf6"; + let rss_url2 = "https://rss.acast.com/intercepted-with-jeremy-scahill"; + let result_url = itunes_to_rss(itunes_url).await?; + assert!(result_url == rss_url || result_url == rss_url2); let itunes_url = "https://itunes.apple.com/podcast/id000000000000000"; assert!(itunes_to_rss(itunes_url).await.is_err()); @@ -642,8 +643,11 @@ mod tests { #[tokio::test] async fn test_itunes_lookup_id() -> Result<()> { let id = 1195206601; + // they keep changing the urls let rss_url = "https://feeds.acast.com/public/shows/f5b64019-68c3-57d4-b70b-043e63e5cbf6"; - assert_eq!(rss_url, itunes_lookup_id(id).await?); + let rss_url2 = "https://rss.acast.com/intercepted-with-jeremy-scahill"; + let result_url = itunes_lookup_id(id).await?; + assert!(result_url == rss_url || result_url == rss_url2); let id = 000000000; assert!(itunes_lookup_id(id).await.is_err()); -- 2.40.1 From 75cf686a1d0fb79ced30df61dd26fde7f7475b12 Mon Sep 17 00:00:00 2001 From: Yosef Or Boczko Date: Mon, 7 Feb 2022 18:16:45 +0000 Subject: [PATCH 010/102] Add Hebrew translation --- podcasts-gtk/po/LINGUAS | 1 + podcasts-gtk/po/he.po | 431 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 432 insertions(+) create mode 100644 podcasts-gtk/po/he.po diff --git a/podcasts-gtk/po/LINGUAS b/podcasts-gtk/po/LINGUAS index f68af90..2323e15 100644 --- a/podcasts-gtk/po/LINGUAS +++ b/podcasts-gtk/po/LINGUAS @@ -11,6 +11,7 @@ fi fr fur gl +he hr hu id diff --git a/podcasts-gtk/po/he.po b/podcasts-gtk/po/he.po new file mode 100644 index 0000000..dc678d7 --- /dev/null +++ b/podcasts-gtk/po/he.po @@ -0,0 +1,431 @@ +# Hebrew translation for podcasts. +# Copyright (C) 2022 podcasts's COPYRIGHT HOLDER +# This file is distributed under the same license as the podcasts package. +# Yosef Or Boczko , 2022. +# +msgid "" +msgstr "" +"Project-Id-Version: podcasts master\n" +"Report-Msgid-Bugs-To: https://gitlab.gnome.org/World/podcasts/issues\n" +"POT-Creation-Date: 2022-02-06 19:19+0000\n" +"PO-Revision-Date: 2022-02-07 20:15+0200\n" +"Last-Translator: Yosef Or Boczko \n" +"Language-Team: Hebrew <>\n" +"Language: he\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=4; plural=(n==1 ? 0 : n==2 ? 1 : n>10 && n%10==0 ? " +"2 : 3)\n" +"X-Generator: Gtranslator 40.0\n" + +#: podcasts-gtk/resources/org.gnome.Podcasts.gschema.xml.in:15 +msgid "Top position of the last open main window" +msgstr "Top position of the last open main window" + +#: podcasts-gtk/resources/org.gnome.Podcasts.gschema.xml.in:19 +msgid "Left position of the last open main window" +msgstr "Left position of the last open main window" + +#: podcasts-gtk/resources/org.gnome.Podcasts.gschema.xml.in:23 +msgid "Height of the last open main window" +msgstr "Height of the last open main window" + +#: podcasts-gtk/resources/org.gnome.Podcasts.gschema.xml.in:27 +msgid "Width of the last open main window" +msgstr "Width of the last open main window" + +#: podcasts-gtk/resources/org.gnome.Podcasts.gschema.xml.in:31 +msgid "Maximized state of the last open main window" +msgstr "Maximized state of the last open main window" + +#: podcasts-gtk/resources/org.gnome.Podcasts.gschema.xml.in:36 +msgid "Enable or disable dark theme" +msgstr "Enable or disable dark theme" + +#: podcasts-gtk/resources/org.gnome.Podcasts.gschema.xml.in:41 +msgid "Whether to periodically refresh content" +msgstr "Whether to periodically refresh content" + +#: podcasts-gtk/resources/org.gnome.Podcasts.gschema.xml.in:46 +msgid "How many periods of time to wait between automatic refreshes" +msgstr "How many periods of time to wait between automatic refreshes" + +#: podcasts-gtk/resources/org.gnome.Podcasts.gschema.xml.in:50 +msgid "What period of time to wait between automatic refreshes" +msgstr "What period of time to wait between automatic refreshes" + +#: podcasts-gtk/resources/org.gnome.Podcasts.gschema.xml.in:54 +msgid "Whether to refresh content after startup" +msgstr "Whether to refresh content after startup" + +#: podcasts-gtk/resources/org.gnome.Podcasts.gschema.xml.in:60 +msgid "How many periods of time to wait between automatic cleanups" +msgstr "How many periods of time to wait between automatic cleanups" + +#: podcasts-gtk/resources/org.gnome.Podcasts.gschema.xml.in:64 +msgid "What period of time to wait between automatic cleanups" +msgstr "What period of time to wait between automatic cleanups" + +#. Weird magic I copy-pasted that sets the Application Name in the Shell. +#: podcasts-gtk/resources/org.gnome.Podcasts.desktop.in.in:3 +#: podcasts-gtk/resources/org.gnome.Podcasts.appdata.xml.in.in:4 +#: podcasts-gtk/resources/gtk/headerbar.ui:137 podcasts-gtk/src/app.rs:438 +#: podcasts-gtk/src/widgets/aboutdialog.rs:63 podcasts-gtk/src/window.rs:66 +msgid "Podcasts" +msgstr "הסכתים" + +#: podcasts-gtk/resources/org.gnome.Podcasts.desktop.in.in:4 +msgid "Listen to your favorite podcasts, right from your desktop." +msgstr "האזנה להסכתים האהובים עליך, ישירות משולחן העבודה שלך." + +#. Translators: Search terms to find this application. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! +#: podcasts-gtk/resources/org.gnome.Podcasts.desktop.in.in:13 +msgid "Podcast;RSS;" +msgstr "הסכתים;RSS;הסקת;פודקאסט;פודקאסטים;" + +#: podcasts-gtk/resources/org.gnome.Podcasts.appdata.xml.in.in:8 +msgid "Listen to your favorite shows" +msgstr "האזנה לתכניות המועדפות שלך" + +#: podcasts-gtk/resources/org.gnome.Podcasts.appdata.xml.in.in:10 +msgid "" +"Play, update, and manage your podcasts from a lightweight interface that " +"seamlessly integrates with GNOME. Podcasts can play various audio formats " +"and remember where you stopped listening. You can subscribe to shows via RSS/" +"Atom, iTunes, and Soundcloud links. Subscriptions from other apps can be " +"imported via OPML files." +msgstr "" +"השמעה, עדכון וניהול ההסכתים ממשק קל המשתלב בצורה חלקה עם GNOME. הסכתים יכול " +"להשמיע סוגים שונים של תבניות שמע וזוכר את המקום האחרון בו עצרת את ההאזנה. " +"נתן להירשם לתכניות באמצעות RSS/Atom, ‏iTunes וקישורי Soundcloud. נִתן ליבא " +"מנויים והרשמות מיישומים אחרים באמצעות קובצי OPML." + +#: podcasts-gtk/resources/org.gnome.Podcasts.appdata.xml.in.in:134 +msgid "Jordan Petridis" +msgstr "Jordan Petridis" + +#: podcasts-gtk/resources/org.gnome.Podcasts.appdata.xml.in.in:135 +msgid "Julian Hofer" +msgstr "Julian Hofer" + +#: podcasts-gtk/resources/gtk/empty_view.ui:46 +msgid "This show does not have episodes yet" +msgstr "לתכנית זו עוד אין פרקים" + +#: podcasts-gtk/resources/gtk/empty_view.ui:57 +msgid "If you think this is an error, please consider writing a bug report." +msgstr "אם נראה לך שזו שגיאה, בבקשה שִקלו לדווח על תקלה." + +#: podcasts-gtk/resources/gtk/empty_view.ui:91 +msgid "Get some shows" +msgstr "הצגת תכניות" + +#: podcasts-gtk/resources/gtk/empty_view.ui:123 +msgid "Add new shows via feed URL" +msgstr "הוספת תכניות על ידי הזנת כתובת URL של הערוץ" + +#: podcasts-gtk/resources/gtk/empty_view.ui:152 +msgid "Import shows from another device" +msgstr "ייבוא תכניות מהתקן אחר" + +#: podcasts-gtk/resources/gtk/episode_description.ui:49 +msgid "Episode Details" +msgstr "פרטים על הפרק" + +#: podcasts-gtk/resources/gtk/episode_description.ui:64 +#: podcasts-gtk/resources/gtk/headerbar.ui:186 +msgid "Back" +msgstr "אחורה" + +#: podcasts-gtk/resources/gtk/episode_description.ui:148 +msgid "Podcast Title" +msgstr "כותרת הסכת" + +#: podcasts-gtk/resources/gtk/episode_description.ui:186 +msgid "Duration - Date" +msgstr "משך - תאריך" + +#: podcasts-gtk/resources/gtk/episode_description.ui:241 +msgid "Episode Description" +msgstr "תיאור פרק" + +#: podcasts-gtk/resources/gtk/episode_menu.ui:36 +msgid "Go to Show" +msgstr "מעבר לתכנית" + +#: podcasts-gtk/resources/gtk/episode_menu.ui:40 +msgid "Copy Episode Url" +msgstr "העתקת כתובת פרק" + +#: podcasts-gtk/resources/gtk/episode_widget.ui:82 +msgid "You’ve already listened to this episode." +msgstr "כבר האזנת לפרק זה." + +#: podcasts-gtk/resources/gtk/episode_widget.ui:187 +msgid "Calculating episode size…" +msgstr "מחשב גודל פרק…" + +#: podcasts-gtk/resources/gtk/episode_widget.ui:214 +msgid "Play this episode" +msgstr "השמעת פרק זה" + +#: podcasts-gtk/resources/gtk/episode_widget.ui:230 +msgid "Cancel the download process" +msgstr "ביטול תהליך ההורדה" + +#: podcasts-gtk/resources/gtk/episode_widget.ui:250 +msgid "Download this episode" +msgstr "הורדת פרק זה" + +#: podcasts-gtk/resources/gtk/hamburger.ui:7 +msgid "_Check for New Episodes" +msgstr "_בדיקה אם יש פרקים חדשים" + +#: podcasts-gtk/resources/gtk/hamburger.ui:12 +msgid "_Import Shows" +msgstr "_ייבוא תכניות" + +#: podcasts-gtk/resources/gtk/hamburger.ui:16 +msgid "_Export Shows" +msgstr "_ייצוא תכניות" + +#: podcasts-gtk/resources/gtk/hamburger.ui:22 +msgid "_Keyboard Shortcuts" +msgstr "_צירופי מקשים" + +#: podcasts-gtk/resources/gtk/hamburger.ui:30 +msgid "_About Podcasts" +msgstr "על _אודות הסכתים" + +#: podcasts-gtk/resources/gtk/headerbar.ui:35 +#: podcasts-gtk/resources/gtk/headerbar.ui:165 +msgid "Add a new feed" +msgstr "הוספת ערוץ חדש" + +#: podcasts-gtk/resources/gtk/headerbar.ui:53 +msgid "Enter feed address to add" +msgstr "הזנת כתובת ערוץ להוספה" + +#: podcasts-gtk/resources/gtk/headerbar.ui:79 +msgid "Add" +msgstr "הוספה" + +#: podcasts-gtk/resources/gtk/headerbar.ui:150 +msgid "Show Title" +msgstr "הצגת כותרת" + +#: podcasts-gtk/resources/gtk/help-overlay.ui:12 +msgid "General" +msgstr "כללי" + +#: podcasts-gtk/resources/gtk/help-overlay.ui:18 +msgctxt "shortcut window" +msgid "Check for new episodes" +msgstr "בדיקה אם יש פרקים חדשים" + +#: podcasts-gtk/resources/gtk/help-overlay.ui:25 +msgctxt "shortcut window" +msgid "Quit the application" +msgstr "יציאה מהיישום" + +#: podcasts-gtk/resources/gtk/home_view.ui:56 +msgid "Today" +msgstr "היום" + +#: podcasts-gtk/resources/gtk/home_view.ui:89 +msgid "Yesterday" +msgstr "אתמול" + +#: podcasts-gtk/resources/gtk/home_view.ui:122 +msgid "This Week" +msgstr "השבוע" + +#: podcasts-gtk/resources/gtk/home_view.ui:155 +msgid "This Month" +msgstr "החודש" + +#: podcasts-gtk/resources/gtk/home_view.ui:189 +msgid "Older" +msgstr "ישן יותר" + +#: podcasts-gtk/resources/gtk/inapp_notif.ui:69 +msgid "An in-app action notification" +msgstr "התרעותת על פעולות בתוך היישום" + +#: podcasts-gtk/resources/gtk/inapp_notif.ui:75 +msgid "Undo" +msgstr "ביטול" + +#: podcasts-gtk/resources/gtk/player_dialog.ui:14 +msgid "Now Playing" +msgstr "מושמע כעת" + +#: podcasts-gtk/resources/gtk/player_rate.ui:32 +msgid "Change the playback speed" +msgstr "שינוי מהירות השמעה" + +#: podcasts-gtk/resources/gtk/player_rate.ui:46 +#: podcasts-gtk/resources/gtk/player_rate.ui:85 +msgid "1.00×" +msgstr "1.00×" + +#: podcasts-gtk/resources/gtk/player_rate.ui:65 +msgid "2.00×" +msgstr "2.00×" + +#: podcasts-gtk/resources/gtk/player_rate.ui:70 +msgid "1.75×" +msgstr "1.75×" + +#: podcasts-gtk/resources/gtk/player_rate.ui:75 +msgid "1.50×" +msgstr "1.50×" + +#: podcasts-gtk/resources/gtk/player_rate.ui:80 +msgid "1.25×" +msgstr "1.25×" + +#: podcasts-gtk/resources/gtk/player_rate.ui:90 +msgid "0.90×" +msgstr "0.90×" + +#: podcasts-gtk/resources/gtk/player_rate.ui:95 +msgid "0.75×" +msgstr "0.75×" + +#: podcasts-gtk/resources/gtk/player_toolbar.ui:97 +msgid "Rewind 10 seconds" +msgstr "חזרה 10 שניות לאחור" + +#: podcasts-gtk/resources/gtk/player_toolbar.ui:107 +msgid "Play" +msgstr "השמעה" + +#: podcasts-gtk/resources/gtk/player_toolbar.ui:118 +msgid "Pause" +msgstr "השהיה" + +#: podcasts-gtk/resources/gtk/player_toolbar.ui:129 +msgid "Fast forward 10 seconds" +msgstr "דילוג 10 שניות קדימה" + +#: podcasts-gtk/resources/gtk/secondary_menu.ui:7 +msgid "_Mark All Episodes as Played" +msgstr "_סימון כל הפרקים כנוגנו" + +#: podcasts-gtk/resources/gtk/secondary_menu.ui:11 +msgid "_Website" +msgstr "_אתר אינטרנט" + +#: podcasts-gtk/resources/gtk/secondary_menu.ui:15 +msgid "_Unsubscribe" +msgstr "_ביטול מנוי" + +#: podcasts-gtk/resources/gtk/show_menu.ui:36 +msgid "Open Website" +msgstr "פתיחת אתר אינטרנט" + +#: podcasts-gtk/resources/gtk/show_menu.ui:40 +msgid "Mark All as Played" +msgstr "סימון הכל כנוגן" + +#: podcasts-gtk/resources/gtk/show_menu.ui:46 +msgid "Unsubscribe" +msgstr "ביטול מנוי" + +#: podcasts-gtk/resources/gtk/show_widget.ui:98 +msgid "Read More" +msgstr "לקרוא עוד" + +#: podcasts-gtk/src/app.rs:353 +msgid "Fetching new episodes" +msgstr "חיפוש פרקים חדשים" + +#: podcasts-gtk/src/stacks/content.rs:58 +msgid "New" +msgstr "חדש" + +#: podcasts-gtk/src/stacks/content.rs:59 +msgid "Shows" +msgstr "תכניות" + +#: podcasts-gtk/src/utils.rs:501 +msgid "Select the file from which to you want to import shows." +msgstr "בחירת הקובץ ממנו ברצונך לייבא תכניות." + +#: podcasts-gtk/src/utils.rs:504 +msgid "_Import" +msgstr "_ייבוא" + +#: podcasts-gtk/src/utils.rs:513 podcasts-gtk/src/utils.rs:562 +msgid "OPML file" +msgstr "קובץ OPML" + +#: podcasts-gtk/src/utils.rs:531 +msgid "Failed to parse the imported file" +msgstr "ארע כשל בניתוח הקובץ המיובא" + +#: podcasts-gtk/src/utils.rs:536 podcasts-gtk/src/utils.rs:581 +msgid "Selected file could not be accessed." +msgstr "לא נתן לגשת לקובץ הנבחר." + +#: podcasts-gtk/src/utils.rs:547 +msgid "Export shows to…" +msgstr "ייצוא תכניות אל…" + +#: podcasts-gtk/src/utils.rs:550 +msgid "_Export" +msgstr "_ייצוא" + +#: podcasts-gtk/src/utils.rs:551 +msgid "_Cancel" +msgstr "_ביטול" + +#. Translators: This is the string of the suggested name for the exported opml file +#: podcasts-gtk/src/utils.rs:555 +msgid "gnome-podcasts-exported-shows" +msgstr "קובץ-ייצוא-תכניות-הסכתים-גנום" + +#: podcasts-gtk/src/utils.rs:575 +msgid "GNOME Podcasts Subscriptions" +msgstr "מנויי GNOME הסכתים" + +#: podcasts-gtk/src/utils.rs:576 +msgid "Failed to export podcasts" +msgstr "ארע כשל בייצוא הסכתים" + +#: podcasts-gtk/src/widgets/aboutdialog.rs:58 +msgid "Podcast Client for the GNOME Desktop." +msgstr "לקוח הסכתים עבור שולחן העבודה GNOME." + +#: podcasts-gtk/src/widgets/aboutdialog.rs:65 +msgid "Learn more about GNOME Podcasts" +msgstr "ללמוד עוד על GNOME הסכתים" + +#: podcasts-gtk/src/widgets/aboutdialog.rs:69 +msgid "translator-credits" +msgstr "" +"יוסף אור בוצ׳קו \n" +"\n" +"מיזם תרגום GNOME לעברית" + +#: podcasts-gtk/src/widgets/episode.rs:145 +msgid "{} min" +msgstr "‏{} דק" + +#: podcasts-gtk/src/widgets/episode_description.rs:165 +msgid "Copied URL to clipboard!" +msgstr "כתובת UTRL הועתקה ללוח הגזירים!" + +#: podcasts-gtk/src/widgets/player.rs:910 +msgid "The media player was unable to execute an action." +msgstr "נגן המדיה לא הצליח לבצע את הפעולה." + +#: podcasts-gtk/src/widgets/show_menu.rs:194 +msgid "Marked all episodes as listened" +msgstr "כל הפרקים סומנו כנוגנו." + +#: podcasts-gtk/src/widgets/show_menu.rs:199 +msgid "Unsubscribed from {}" +msgstr "בוטל המנוי מהתכנית {}" -- 2.40.1 From 57a27885d806abb6b4728043eee72774fc869b23 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Urban=C4=8Di=C4=8D?= Date: Mon, 7 Feb 2022 18:18:33 +0000 Subject: [PATCH 011/102] Update Slovenian translation --- podcasts-gtk/po/sl.po | 34 +++++++++++++++++++++++++--------- 1 file changed, 25 insertions(+), 9 deletions(-) diff --git a/podcasts-gtk/po/sl.po b/podcasts-gtk/po/sl.po index 33ff69d..60e093a 100644 --- a/podcasts-gtk/po/sl.po +++ b/podcasts-gtk/po/sl.po @@ -2,14 +2,14 @@ # Copyright (C) 2020 podcasts's COPYRIGHT HOLDER # This file is distributed under the same license as the podcasts package. # -# Matej Urbančič , 2020–2021. +# Matej Urbančič , 2020–2022. # msgid "" msgstr "" "Project-Id-Version: podcasts master\n" "Report-Msgid-Bugs-To: https://gitlab.gnome.org/World/podcasts/issues\n" -"POT-Creation-Date: 2021-10-31 10:41+0000\n" -"PO-Revision-Date: 2021-11-02 20:31+0100\n" +"POT-Creation-Date: 2022-02-06 19:19+0000\n" +"PO-Revision-Date: 2022-02-07 18:56+0100\n" "Last-Translator: Matej Urbančič \n" "Language-Team: Slovenian GNOME Translation Team \n" "Language: sl_SI\n" @@ -78,7 +78,6 @@ msgid "Podcasts" msgstr "Podkasti" #: podcasts-gtk/resources/org.gnome.Podcasts.desktop.in.in:4 -#: podcasts-gtk/resources/org.gnome.Podcasts.appdata.xml.in.in:10 msgid "Listen to your favorite podcasts, right from your desktop." msgstr "Spremljanje priljubljenih podkastov neposredno z namizja" @@ -88,14 +87,28 @@ msgid "Podcast;RSS;" msgstr "Podcast;RSS;podkast;viri;" #: podcasts-gtk/resources/org.gnome.Podcasts.appdata.xml.in.in:8 -msgid "Podcast app for GNOME" -msgstr "Program Podkast za GNOME" +msgid "Listen to your favorite shows" +msgstr "Spremljanje priljubljenih oddaj" + +#: podcasts-gtk/resources/org.gnome.Podcasts.appdata.xml.in.in:10 +msgid "" +"Play, update, and manage your podcasts from a lightweight interface that " +"seamlessly integrates with GNOME. Podcasts can play various audio formats " +"and remember where you stopped listening. You can subscribe to shows via RSS/" +"Atom, iTunes, and Soundcloud links. Subscriptions from other apps can be " +"imported via OPML files." +msgstr "" +"Predvajanje, posodabljanje in upravljanje zbirke podkastov v preglednem " +"vmesniku, skladnem z namizjem GNOME. Program omogoča predvananje različnih " +"zvočnih zapisov in podpira možnost pomnjenja zadnjega poslušanega mesta. Na " +"oddaje se je mogoče naročiti po povezavah RSS/Atom, iTunes in Soundcloud. " +"Naročnine iz drugih prigramov je mogoče uvoziti z uporabo izvoza OPML." -#: podcasts-gtk/resources/org.gnome.Podcasts.appdata.xml.in.in:115 +#: podcasts-gtk/resources/org.gnome.Podcasts.appdata.xml.in.in:134 msgid "Jordan Petridis" msgstr "Jordan Petridis" -#: podcasts-gtk/resources/org.gnome.Podcasts.appdata.xml.in.in:116 +#: podcasts-gtk/resources/org.gnome.Podcasts.appdata.xml.in.in:135 msgid "Julian Hofer" msgstr "Julian Hofer" @@ -405,7 +418,7 @@ msgstr "{} min" msgid "Copied URL to clipboard!" msgstr "Naslov URL je kopiran v odložišče!" -#: podcasts-gtk/src/widgets/player.rs:902 +#: podcasts-gtk/src/widgets/player.rs:910 msgid "The media player was unable to execute an action." msgstr "S predvajalnikom ni mogoče izvesti zahtevanega dejanja." @@ -417,5 +430,8 @@ msgstr "Vse epizode so označene kot poslušane" msgid "Unsubscribed from {}" msgstr "Odjavi {}" +#~ msgid "Podcast app for GNOME" +#~ msgstr "Program Podkast za GNOME" + #~ msgid "Normal speed" #~ msgstr "Običajna hitrost" -- 2.40.1 From 7f48a19bf1bc98de7ea6c64cd336aaccc8fca460 Mon Sep 17 00:00:00 2001 From: Yosef Or Boczko Date: Mon, 7 Feb 2022 18:40:08 +0000 Subject: [PATCH 012/102] Update Hebrew translation --- podcasts-gtk/po/he.po | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/podcasts-gtk/po/he.po b/podcasts-gtk/po/he.po index dc678d7..1280e28 100644 --- a/podcasts-gtk/po/he.po +++ b/podcasts-gtk/po/he.po @@ -8,7 +8,7 @@ msgstr "" "Project-Id-Version: podcasts master\n" "Report-Msgid-Bugs-To: https://gitlab.gnome.org/World/podcasts/issues\n" "POT-Creation-Date: 2022-02-06 19:19+0000\n" -"PO-Revision-Date: 2022-02-07 20:15+0200\n" +"PO-Revision-Date: 2022-02-07 20:20+0200\n" "Last-Translator: Yosef Or Boczko \n" "Language-Team: Hebrew <>\n" "Language: he\n" @@ -96,9 +96,9 @@ msgid "" "Atom, iTunes, and Soundcloud links. Subscriptions from other apps can be " "imported via OPML files." msgstr "" -"השמעה, עדכון וניהול ההסכתים ממשק קל המשתלב בצורה חלקה עם GNOME. הסכתים יכול " +"השמעה, עדכון וניהול ההסכתים בממשק קל המשתלב בצורה חלקה עם GNOME. הסכתים יכול " "להשמיע סוגים שונים של תבניות שמע וזוכר את המקום האחרון בו עצרת את ההאזנה. " -"נתן להירשם לתכניות באמצעות RSS/Atom, ‏iTunes וקישורי Soundcloud. נִתן ליבא " +"נִתן להירשם לתכניות באמצעות RSS/Atom, ‏iTunes וקישורי Soundcloud. נִתן לייבא " "מנויים והרשמות מיישומים אחרים באמצעות קובצי OPML." #: podcasts-gtk/resources/org.gnome.Podcasts.appdata.xml.in.in:134 @@ -140,7 +140,7 @@ msgstr "אחורה" #: podcasts-gtk/resources/gtk/episode_description.ui:148 msgid "Podcast Title" -msgstr "כותרת הסכת" +msgstr "כותרת ההסכת" #: podcasts-gtk/resources/gtk/episode_description.ui:186 msgid "Duration - Date" @@ -164,7 +164,7 @@ msgstr "כבר האזנת לפרק זה." #: podcasts-gtk/resources/gtk/episode_widget.ui:187 msgid "Calculating episode size…" -msgstr "מחשב גודל פרק…" +msgstr "מחשב את גודל הפרק…" #: podcasts-gtk/resources/gtk/episode_widget.ui:214 msgid "Play this episode" @@ -251,7 +251,7 @@ msgstr "ישן יותר" #: podcasts-gtk/resources/gtk/inapp_notif.ui:69 msgid "An in-app action notification" -msgstr "התרעותת על פעולות בתוך היישום" +msgstr "התרעות על פעולות בתוך היישום" #: podcasts-gtk/resources/gtk/inapp_notif.ui:75 msgid "Undo" -- 2.40.1 From 271b9a877e4024aa6c2087d4396df96011041ca2 Mon Sep 17 00:00:00 2001 From: Daniel Mustieles Date: Mon, 21 Feb 2022 15:40:42 +0000 Subject: [PATCH 013/102] Update Spanish translation --- podcasts-gtk/po/es.po | 140 +++++++++++++++++++++++++++++------------- 1 file changed, 98 insertions(+), 42 deletions(-) diff --git a/podcasts-gtk/po/es.po b/podcasts-gtk/po/es.po index 594dd7f..ee18dc4 100644 --- a/podcasts-gtk/po/es.po +++ b/podcasts-gtk/po/es.po @@ -6,21 +6,22 @@ # Rodrigo , 2018. # Rodrigo Lledó , 2019. # Daniel Mustieles , 2018-2021. +# Daniel Mustieles García , 2022. # msgid "" msgstr "" "Project-Id-Version: gnome-podcasts\n" "Report-Msgid-Bugs-To: https://gitlab.gnome.org/World/podcasts/issues\n" -"POT-Creation-Date: 2021-06-19 18:35+0000\n" -"PO-Revision-Date: 2021-08-29 15:27+0200\n" -"Last-Translator: Daniel Mustieles \n" +"POT-Creation-Date: 2021-11-28 07:07+0000\n" +"PO-Revision-Date: 2022-02-21 16:40+0100\n" +"Last-Translator: Daniel Mustieles García \n" "Language-Team: Spanish - Spain \n" "Language: es_ES\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" -"X-Generator: Poedit 3.0\n" +"Plural-Forms: nplurals=2; plural=(n != 1)\n" +"X-Generator: Gtranslator 41.0\n" #: podcasts-gtk/resources/org.gnome.Podcasts.gschema.xml.in:15 msgid "Top position of the last open main window" @@ -52,11 +53,13 @@ msgstr "Indica si se debe actualizar el contenido periódicamente" #: podcasts-gtk/resources/org.gnome.Podcasts.gschema.xml.in:46 msgid "How many periods of time to wait between automatic refreshes" -msgstr "Cuántos periodos de tiempo hay que esperar entre actualizaciones automáticas" +msgstr "" +"Cuántos periodos de tiempo hay que esperar entre actualizaciones automáticas" #: podcasts-gtk/resources/org.gnome.Podcasts.gschema.xml.in:50 msgid "What period of time to wait between automatic refreshes" -msgstr "Qué periodo de tiempo hay que esperar entre actualizaciones automáticas" +msgstr "" +"Qué periodo de tiempo hay que esperar entre actualizaciones automáticas" #: podcasts-gtk/resources/org.gnome.Podcasts.gschema.xml.in:54 msgid "Whether to refresh content after startup" @@ -73,13 +76,12 @@ msgstr "Cuántos periodos de tiempo hay que esperar entre limpiezas automáticas #. Weird magic I copy-pasted that sets the Application Name in the Shell. #: podcasts-gtk/resources/org.gnome.Podcasts.desktop.in.in:3 #: podcasts-gtk/resources/org.gnome.Podcasts.appdata.xml.in.in:4 -#: podcasts-gtk/resources/gtk/headerbar.ui:137 podcasts-gtk/src/app.rs:364 -#: podcasts-gtk/src/widgets/aboutdialog.rs:63 podcasts-gtk/src/window.rs:64 +#: podcasts-gtk/resources/gtk/headerbar.ui:137 podcasts-gtk/src/app.rs:438 +#: podcasts-gtk/src/widgets/aboutdialog.rs:63 podcasts-gtk/src/window.rs:66 msgid "Podcasts" msgstr "Podcasts" #: podcasts-gtk/resources/org.gnome.Podcasts.desktop.in.in:4 -#: podcasts-gtk/resources/org.gnome.Podcasts.appdata.xml.in.in:10 msgid "Listen to your favorite podcasts, right from your desktop." msgstr "Escuche sus podcasts favoritos, directamente desde su escritorio." @@ -89,13 +91,33 @@ msgid "Podcast;RSS;" msgstr "Podcast;RSS;" #: podcasts-gtk/resources/org.gnome.Podcasts.appdata.xml.in.in:8 -msgid "Podcast app for GNOME" -msgstr "Aplicación de Podcast para GNOME" +#| msgid "Listen to your favorite podcasts, right from your desktop." +msgid "Listen to your favorite shows" +msgstr "Escuche sus progrmas favoritos" -#: podcasts-gtk/resources/org.gnome.Podcasts.appdata.xml.in.in:99 +#: podcasts-gtk/resources/org.gnome.Podcasts.appdata.xml.in.in:10 +msgid "" +"Play, update, and manage your podcasts from a lightweight interface that " +"seamlessly integrates with GNOME. Podcasts can play various audio formats " +"and remember where you stopped listening. You can subscribe to shows via RSS/" +"Atom, iTunes, and Soundcloud links. Subscriptions from other apps can be " +"imported via OPML files." +msgstr "" +"Reproduzca, actualice y administre sus podcasts desde una interfaz ligera " +"que se integra a la perfección con GNOME. Podcasts pueden reproducir varios " +"formatos de audio y recordar dónde dejó de escucharlos. Puede suscribirse a " +"programas a través de enlaces RSS/Atom, iTunes y Soundcloud. Las " +"suscripciones de otras aplicaciones se pueden importar a través de archivos " +"OPML." + +#: podcasts-gtk/resources/org.gnome.Podcasts.appdata.xml.in.in:117 msgid "Jordan Petridis" msgstr "Jordan Petridis" +#: podcasts-gtk/resources/org.gnome.Podcasts.appdata.xml.in.in:118 +msgid "Julian Hofer" +msgstr "Julian Hofer" + #: podcasts-gtk/resources/gtk/empty_view.ui:46 msgid "This show does not have episodes yet" msgstr "Este programa no tiene episodios todavía" @@ -116,6 +138,40 @@ msgstr "Añadir un programa nuevo a través de canal URL" msgid "Import shows from another device" msgstr "Importar programas de otro dispositivo" +#: podcasts-gtk/resources/gtk/episode_description.ui:49 +#| msgid "Episode Title" +msgid "Episode Details" +msgstr "Detalles del episodio" + +#: podcasts-gtk/resources/gtk/episode_description.ui:64 +#: podcasts-gtk/resources/gtk/headerbar.ui:186 +msgid "Back" +msgstr "Atrás" + +#: podcasts-gtk/resources/gtk/episode_description.ui:148 +#| msgid "Podcasts" +msgid "Podcast Title" +msgstr "Título del podcast" + +#: podcasts-gtk/resources/gtk/episode_description.ui:186 +msgid "Duration - Date" +msgstr "Duración - Fecha" + +#: podcasts-gtk/resources/gtk/episode_description.ui:241 +#| msgid "Episode Title" +msgid "Episode Description" +msgstr "Descripción del episodio" + +#: podcasts-gtk/resources/gtk/episode_menu.ui:36 +#| msgid "_Import Shows" +msgid "Go to Show" +msgstr "Ir al programa" + +#: podcasts-gtk/resources/gtk/episode_menu.ui:40 +#| msgid "Episode Title" +msgid "Copy Episode Url" +msgstr "Copiar URL del episodio" + #: podcasts-gtk/resources/gtk/episode_widget.ui:82 msgid "You’ve already listened to this episode." msgstr "Ya ha escuchado este episodio." @@ -173,10 +229,6 @@ msgstr "Añadir" msgid "Show Title" msgstr "Título del programa" -#: podcasts-gtk/resources/gtk/headerbar.ui:186 -msgid "Back" -msgstr "Atrás" - #: podcasts-gtk/resources/gtk/help-overlay.ui:12 msgid "General" msgstr "General" @@ -195,19 +247,19 @@ msgstr "Salir de la aplicación" msgid "Today" msgstr "Hoy" -#: podcasts-gtk/resources/gtk/home_view.ui:88 +#: podcasts-gtk/resources/gtk/home_view.ui:89 msgid "Yesterday" msgstr "Ayer" -#: podcasts-gtk/resources/gtk/home_view.ui:120 +#: podcasts-gtk/resources/gtk/home_view.ui:122 msgid "This Week" msgstr "Esta semana" -#: podcasts-gtk/resources/gtk/home_view.ui:152 +#: podcasts-gtk/resources/gtk/home_view.ui:155 msgid "This Month" msgstr "Este mes" -#: podcasts-gtk/resources/gtk/home_view.ui:185 +#: podcasts-gtk/resources/gtk/home_view.ui:189 msgid "Older" msgstr "Antiguo" @@ -300,60 +352,60 @@ msgstr "Cancelar suscripción" msgid "Read More" msgstr "Leer más" -#: podcasts-gtk/src/app.rs:299 +#: podcasts-gtk/src/app.rs:353 msgid "Fetching new episodes" msgstr "Obteniendo nuevos episodios" -#: podcasts-gtk/src/stacks/content.rs:53 +#: podcasts-gtk/src/stacks/content.rs:58 msgid "New" msgstr "Nuevo" -#: podcasts-gtk/src/stacks/content.rs:54 +#: podcasts-gtk/src/stacks/content.rs:59 msgid "Shows" msgstr "Programas" -#: podcasts-gtk/src/utils.rs:472 +#: podcasts-gtk/src/utils.rs:501 msgid "Select the file from which to you want to import shows." msgstr "Selecciona el fichero desde el que quiere importar programas." -#: podcasts-gtk/src/utils.rs:475 +#: podcasts-gtk/src/utils.rs:504 msgid "_Import" msgstr "_Importar" -#: podcasts-gtk/src/utils.rs:484 podcasts-gtk/src/utils.rs:533 +#: podcasts-gtk/src/utils.rs:513 podcasts-gtk/src/utils.rs:562 msgid "OPML file" msgstr "Archivo OPML" -#: podcasts-gtk/src/utils.rs:502 +#: podcasts-gtk/src/utils.rs:531 msgid "Failed to parse the imported file" msgstr "Fallo al analizar el fichero importado" -#: podcasts-gtk/src/utils.rs:507 podcasts-gtk/src/utils.rs:552 +#: podcasts-gtk/src/utils.rs:536 podcasts-gtk/src/utils.rs:581 msgid "Selected file could not be accessed." msgstr "No se ha podido acceder al archivo seleccionado." -#: podcasts-gtk/src/utils.rs:518 +#: podcasts-gtk/src/utils.rs:547 msgid "Export shows to…" msgstr "Exportar programas a…" -#: podcasts-gtk/src/utils.rs:521 +#: podcasts-gtk/src/utils.rs:550 msgid "_Export" msgstr "_Exportar" -#: podcasts-gtk/src/utils.rs:522 +#: podcasts-gtk/src/utils.rs:551 msgid "_Cancel" msgstr "_Cancelar" #. Translators: This is the string of the suggested name for the exported opml file -#: podcasts-gtk/src/utils.rs:526 +#: podcasts-gtk/src/utils.rs:555 msgid "gnome-podcasts-exported-shows" msgstr "gnome-podcasts-exported-shows" -#: podcasts-gtk/src/utils.rs:546 +#: podcasts-gtk/src/utils.rs:575 msgid "GNOME Podcasts Subscriptions" msgstr "Suscripciones a podcasts de GNOME" -#: podcasts-gtk/src/utils.rs:547 +#: podcasts-gtk/src/utils.rs:576 msgid "Failed to export podcasts" msgstr "Falló al exportar podcasts" @@ -371,22 +423,29 @@ msgstr "" "Daniel Mustieles , 2018-2019\n" "Daniel García Moreno " -#: podcasts-gtk/src/widgets/episode.rs:144 +#: podcasts-gtk/src/widgets/episode.rs:145 msgid "{} min" msgstr "{} min" -#: podcasts-gtk/src/widgets/player.rs:818 +#: podcasts-gtk/src/widgets/episode_description.rs:165 +msgid "Copied URL to clipboard!" +msgstr "URL copiado al portapapeles." + +#: podcasts-gtk/src/widgets/player.rs:902 msgid "The media player was unable to execute an action." msgstr "El reproductor no ha podido reproducir una acción." -#: podcasts-gtk/src/widgets/show_menu.rs:198 +#: podcasts-gtk/src/widgets/show_menu.rs:194 msgid "Marked all episodes as listened" msgstr "Marcar todos los episodios como escuchados" -#: podcasts-gtk/src/widgets/show_menu.rs:203 +#: podcasts-gtk/src/widgets/show_menu.rs:199 msgid "Unsubscribed from {}" msgstr "Suscripción cancelada para {}" +#~ msgid "Podcast app for GNOME" +#~ msgstr "Aplicación de Podcast para GNOME" + #~| msgid "1.5 speed rate" #~ msgid "Double speed rate" #~ msgstr "Doble velocidad" @@ -462,9 +521,6 @@ msgstr "Suscripción cancelada para {}" #~ msgid "Mark all episodes as listened" #~ msgstr "Marcar todos los episodios como escuchados" -#~ msgid "Episode Title" -#~ msgstr "Título del episodio" - #~ msgid "3 Jan" #~ msgstr "3 Jan" -- 2.40.1 From b1e231cc8dd9730daec401ec53f4dc3f0bf26ebe Mon Sep 17 00:00:00 2001 From: Alan Mortensen Date: Wed, 2 Mar 2022 16:45:18 +0000 Subject: [PATCH 014/102] Update Danish translation --- podcasts-gtk/po/da.po | 295 ++++++++++++++++++++++++++---------------- 1 file changed, 186 insertions(+), 109 deletions(-) diff --git a/podcasts-gtk/po/da.po b/podcasts-gtk/po/da.po index 78ec853..339d28a 100644 --- a/podcasts-gtk/po/da.po +++ b/podcasts-gtk/po/da.po @@ -2,78 +2,83 @@ # Copyright (C) 2019 podcasts's COPYRIGHT HOLDER # This file is distributed under the same license as the podcasts package. # scootergrisen, 2019. +# Alan Mortensen , 2022. +# +# Show = udsendelse +# Podcasts = Podcasts (programmet) eller podcast (flertalsform for ikke at forveksle med programmets navn) + msgid "" msgstr "" "Project-Id-Version: podcasts master\n" "Report-Msgid-Bugs-To: https://gitlab.gnome.org/World/podcasts/issues\n" -"POT-Creation-Date: 2019-05-19 10:38+0000\n" -"PO-Revision-Date: 2019-05-22 14:50+0200\n" -"Last-Translator: scootergrisen\n" +"POT-Creation-Date: 2021-11-28 07:07+0000\n" +"PO-Revision-Date: 2022-02-20 15:21+0100\n" +"Last-Translator: Alan Mortensen \n" "Language-Team: Danish \n" "Language: da\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: Poedit 2.3\n" -#: podcasts-gtk/resources/org.gnome.Podcasts.gschema.xml:15 +#: podcasts-gtk/resources/org.gnome.Podcasts.gschema.xml.in:15 msgid "Top position of the last open main window" msgstr "Øverste placering af hovedvindue som sidst var åbent" -#: podcasts-gtk/resources/org.gnome.Podcasts.gschema.xml:19 +#: podcasts-gtk/resources/org.gnome.Podcasts.gschema.xml.in:19 msgid "Left position of the last open main window" msgstr "Venstre placering af hovedvindue som sidst var åbent" -#: podcasts-gtk/resources/org.gnome.Podcasts.gschema.xml:23 +#: podcasts-gtk/resources/org.gnome.Podcasts.gschema.xml.in:23 msgid "Height of the last open main window" msgstr "Højde på hovedvindue som sidst var åbent" -#: podcasts-gtk/resources/org.gnome.Podcasts.gschema.xml:27 +#: podcasts-gtk/resources/org.gnome.Podcasts.gschema.xml.in:27 msgid "Width of the last open main window" msgstr "Bredde på hovedvindue som sidst var åbent" -#: podcasts-gtk/resources/org.gnome.Podcasts.gschema.xml:31 +#: podcasts-gtk/resources/org.gnome.Podcasts.gschema.xml.in:31 msgid "Maximized state of the last open main window" msgstr "Maksimeret tilstand på hovedvindue som sidst var åbent" -#: podcasts-gtk/resources/org.gnome.Podcasts.gschema.xml:36 +#: podcasts-gtk/resources/org.gnome.Podcasts.gschema.xml.in:36 msgid "Enable or disable dark theme" msgstr "Aktivér eller deaktivér mørkt tema" -#: podcasts-gtk/resources/org.gnome.Podcasts.gschema.xml:41 +#: podcasts-gtk/resources/org.gnome.Podcasts.gschema.xml.in:41 msgid "Whether to periodically refresh content" msgstr "Om indholdet jævnligt skal opdateres" -#: podcasts-gtk/resources/org.gnome.Podcasts.gschema.xml:46 +#: podcasts-gtk/resources/org.gnome.Podcasts.gschema.xml.in:46 msgid "How many periods of time to wait between automatic refreshes" msgstr "Hvor lang tid der skal gå mellem automatiske opdateringer" -#: podcasts-gtk/resources/org.gnome.Podcasts.gschema.xml:50 +#: podcasts-gtk/resources/org.gnome.Podcasts.gschema.xml.in:50 msgid "What period of time to wait between automatic refreshes" msgstr "Hvor lang tid der skal gå mellem automatiske opdateringer" -#: podcasts-gtk/resources/org.gnome.Podcasts.gschema.xml:54 +#: podcasts-gtk/resources/org.gnome.Podcasts.gschema.xml.in:54 msgid "Whether to refresh content after startup" msgstr "Om indholdet skal opdateres efter opstart" -#: podcasts-gtk/resources/org.gnome.Podcasts.gschema.xml:60 +#: podcasts-gtk/resources/org.gnome.Podcasts.gschema.xml.in:60 msgid "How many periods of time to wait between automatic cleanups" msgstr "Hvor lang tid der skal gå mellem automatiske oprydninger" -#: podcasts-gtk/resources/org.gnome.Podcasts.gschema.xml:64 +#: podcasts-gtk/resources/org.gnome.Podcasts.gschema.xml.in:64 msgid "What period of time to wait between automatic cleanups" msgstr "Hvor lang tid der skal gå mellem automatiske oprydninger" #. Weird magic I copy-pasted that sets the Application Name in the Shell. #: podcasts-gtk/resources/org.gnome.Podcasts.desktop.in.in:3 #: podcasts-gtk/resources/org.gnome.Podcasts.appdata.xml.in.in:4 -#: podcasts-gtk/src/app.rs:109 podcasts-gtk/src/app.rs:433 -#: podcasts-gtk/src/widgets/aboutdialog.rs:56 +#: podcasts-gtk/resources/gtk/headerbar.ui:137 podcasts-gtk/src/app.rs:438 +#: podcasts-gtk/src/widgets/aboutdialog.rs:63 podcasts-gtk/src/window.rs:66 msgid "Podcasts" msgstr "Podcasts" #: podcasts-gtk/resources/org.gnome.Podcasts.desktop.in.in:4 -#: podcasts-gtk/resources/org.gnome.Podcasts.appdata.xml.in.in:10 msgid "Listen to your favorite podcasts, right from your desktop." msgstr "Lyt til dine favorit podcasts fra dit skrivebord." @@ -83,51 +88,98 @@ msgid "Podcast;RSS;" msgstr "Podcast;RSS;" #: podcasts-gtk/resources/org.gnome.Podcasts.appdata.xml.in.in:8 -msgid "Podcast app for GNOME" -msgstr "Podcast-program til GNOME" +msgid "Listen to your favorite shows" +msgstr "Lyt til dine yndlingsudsendelser" + +#: podcasts-gtk/resources/org.gnome.Podcasts.appdata.xml.in.in:10 +msgid "" +"Play, update, and manage your podcasts from a lightweight interface that " +"seamlessly integrates with GNOME. Podcasts can play various audio formats " +"and remember where you stopped listening. You can subscribe to shows via RSS/" +"Atom, iTunes, and Soundcloud links. Subscriptions from other apps can be " +"imported via OPML files." +msgstr "" +"Afspil, opdatér og håndtér dine podcast fra en enkel grænseflade som sømløst " +"integrerer med GNOME. Podcasts kan afspille forskellige lydformater og " +"huske, hvor du nåede til i din lytning. Du kan abonnere på udsendelser via " +"RSS/Atom, iTunes og Soundcloud-links. Abonnementer fra andre programmer kan " +"importeres via OPML-filer." -#: podcasts-gtk/resources/org.gnome.Podcasts.appdata.xml.in.in:77 +#: podcasts-gtk/resources/org.gnome.Podcasts.appdata.xml.in.in:117 msgid "Jordan Petridis" msgstr "Jordan Petridis" +#: podcasts-gtk/resources/org.gnome.Podcasts.appdata.xml.in.in:118 +msgid "Julian Hofer" +msgstr "Julian Hofer" + #: podcasts-gtk/resources/gtk/empty_view.ui:46 msgid "This show does not have episodes yet" msgstr "Udsendelsen har endnu ikke nogen episoder" -#: podcasts-gtk/resources/gtk/empty_view.ui:62 +#: podcasts-gtk/resources/gtk/empty_view.ui:57 msgid "If you think this is an error, please consider writing a bug report." msgstr "" "Hvis du tror det er en fejl, så overvej venligst at skrive en fejlrapport." -#: podcasts-gtk/resources/gtk/empty_view.ui:106 +#: podcasts-gtk/resources/gtk/empty_view.ui:91 msgid "Get some shows" msgstr "Hent nogen udsendelser" -#: podcasts-gtk/resources/gtk/empty_view.ui:143 +#: podcasts-gtk/resources/gtk/empty_view.ui:123 msgid "Add new shows via feed URL" msgstr "Tilføj nye udsendelser via feed-URL" -#: podcasts-gtk/resources/gtk/empty_view.ui:172 +#: podcasts-gtk/resources/gtk/empty_view.ui:152 msgid "Import shows from another device" msgstr "Importér udsendelser fra en anden enhed" -#: podcasts-gtk/resources/gtk/episode_widget.ui:79 +#: podcasts-gtk/resources/gtk/episode_description.ui:49 +msgid "Episode Details" +msgstr "Episodedetaljer" + +#: podcasts-gtk/resources/gtk/episode_description.ui:64 +#: podcasts-gtk/resources/gtk/headerbar.ui:186 +msgid "Back" +msgstr "Tilbage" + +#: podcasts-gtk/resources/gtk/episode_description.ui:148 +msgid "Podcast Title" +msgstr "Podcasttitel" + +#: podcasts-gtk/resources/gtk/episode_description.ui:186 +msgid "Duration - Date" +msgstr "Varighed — dato" + +#: podcasts-gtk/resources/gtk/episode_description.ui:241 +msgid "Episode Description" +msgstr "Episodebeskrivelse" + +#: podcasts-gtk/resources/gtk/episode_menu.ui:36 +msgid "Go to Show" +msgstr "Gå til udsendelse" + +#: podcasts-gtk/resources/gtk/episode_menu.ui:40 +msgid "Copy Episode Url" +msgstr "Kopiér episodens URL" + +#: podcasts-gtk/resources/gtk/episode_widget.ui:82 msgid "You’ve already listened to this episode." msgstr "Du har allerede lyttet til episoden." -#: podcasts-gtk/resources/gtk/episode_widget.ui:208 +#: podcasts-gtk/resources/gtk/episode_widget.ui:187 msgid "Calculating episode size…" msgstr "Udregner episodestørrelse …" -#: podcasts-gtk/resources/gtk/episode_widget.ui:248 +#: podcasts-gtk/resources/gtk/episode_widget.ui:214 msgid "Play this episode" msgstr "Afspil episoden" -#: podcasts-gtk/resources/gtk/episode_widget.ui:269 +#: podcasts-gtk/resources/gtk/episode_widget.ui:230 msgid "Cancel the download process" msgstr "Annuller downloadprocessen" -#: podcasts-gtk/resources/gtk/episode_widget.ui:292 +#: podcasts-gtk/resources/gtk/episode_widget.ui:250 msgid "Download this episode" msgstr "Download episoden" @@ -152,7 +204,7 @@ msgid "_About Podcasts" msgstr "_Om Podcasts" #: podcasts-gtk/resources/gtk/headerbar.ui:35 -#: podcasts-gtk/resources/gtk/headerbar.ui:189 +#: podcasts-gtk/resources/gtk/headerbar.ui:165 msgid "Add a new feed" msgstr "Tilføj et nyt feed" @@ -160,22 +212,14 @@ msgstr "Tilføj et nyt feed" msgid "Enter feed address to add" msgstr "Indtast adresse på feed der skal tilføjes" -#: podcasts-gtk/resources/gtk/headerbar.ui:89 +#: podcasts-gtk/resources/gtk/headerbar.ui:79 msgid "Add" msgstr "Tilføj" -#: podcasts-gtk/resources/gtk/headerbar.ui:133 -msgid "You are already subscribed to that feed!" -msgstr "Du har allerede abonneret på feedet!" - -#: podcasts-gtk/resources/gtk/headerbar.ui:169 +#: podcasts-gtk/resources/gtk/headerbar.ui:150 msgid "Show Title" msgstr "Vis titel" -#: podcasts-gtk/resources/gtk/headerbar.ui:210 -msgid "Back" -msgstr "Tilbage" - #: podcasts-gtk/resources/gtk/help-overlay.ui:12 msgid "General" msgstr "Generelt" @@ -194,74 +238,82 @@ msgstr "Afslut programmet" msgid "Today" msgstr "I dag" -#: podcasts-gtk/resources/gtk/home_view.ui:112 +#: podcasts-gtk/resources/gtk/home_view.ui:89 msgid "Yesterday" msgstr "I går" -#: podcasts-gtk/resources/gtk/home_view.ui:168 +#: podcasts-gtk/resources/gtk/home_view.ui:122 msgid "This Week" msgstr "Denne uge" -#: podcasts-gtk/resources/gtk/home_view.ui:224 +#: podcasts-gtk/resources/gtk/home_view.ui:155 msgid "This Month" msgstr "Denne måned" -#: podcasts-gtk/resources/gtk/home_view.ui:281 +#: podcasts-gtk/resources/gtk/home_view.ui:189 msgid "Older" msgstr "Ældre" -#: podcasts-gtk/resources/gtk/inapp_notif.ui:101 +#: podcasts-gtk/resources/gtk/inapp_notif.ui:69 msgid "An in-app action notification" msgstr "En notifikation om programindbygget handling" -#: podcasts-gtk/resources/gtk/inapp_notif.ui:112 +#: podcasts-gtk/resources/gtk/inapp_notif.ui:75 msgid "Undo" msgstr "Fortryd" -#: podcasts-gtk/resources/gtk/player_toolbar.ui:72 -msgid "Rewind 10 seconds" -msgstr "Spol 10 sekunder tilbage" - -#: podcasts-gtk/resources/gtk/player_toolbar.ui:87 -msgid "Play" -msgstr "Afspil" - -#: podcasts-gtk/resources/gtk/player_toolbar.ui:103 -msgid "Pause" -msgstr "Pause" - -#: podcasts-gtk/resources/gtk/player_toolbar.ui:119 -msgid "Fast forward 10 seconds" -msgstr "Spol 10 sekunder fremad" +#: podcasts-gtk/resources/gtk/player_dialog.ui:14 +msgid "Now Playing" +msgstr "Afspiller nu" -#: podcasts-gtk/resources/gtk/player_toolbar.ui:285 +#: podcasts-gtk/resources/gtk/player_rate.ui:32 msgid "Change the playback speed" msgstr "Skift afspilningshastigheden" -#: podcasts-gtk/resources/gtk/player_toolbar.ui:300 -#: podcasts-gtk/resources/gtk/player_toolbar.ui:380 +#: podcasts-gtk/resources/gtk/player_rate.ui:46 +#: podcasts-gtk/resources/gtk/player_rate.ui:85 msgid "1.00×" msgstr "1,00×" -#: podcasts-gtk/resources/gtk/player_toolbar.ui:344 +#: podcasts-gtk/resources/gtk/player_rate.ui:65 +msgid "2.00×" +msgstr "2,00×" + +#: podcasts-gtk/resources/gtk/player_rate.ui:70 +msgid "1.75×" +msgstr "1,75×" + +#: podcasts-gtk/resources/gtk/player_rate.ui:75 msgid "1.50×" msgstr "1,50×" -#: podcasts-gtk/resources/gtk/player_toolbar.ui:348 -msgid "1.5 speed rate" -msgstr "1,5 hastighed" - -#: podcasts-gtk/resources/gtk/player_toolbar.ui:362 +#: podcasts-gtk/resources/gtk/player_rate.ui:80 msgid "1.25×" msgstr "1,25×" -#: podcasts-gtk/resources/gtk/player_toolbar.ui:366 -msgid "1.25 speed rate" -msgstr "1,25 hastighed" +#: podcasts-gtk/resources/gtk/player_rate.ui:90 +msgid "0.90×" +msgstr "0,90×" + +#: podcasts-gtk/resources/gtk/player_rate.ui:95 +msgid "0.75×" +msgstr "0,75×" + +#: podcasts-gtk/resources/gtk/player_toolbar.ui:97 +msgid "Rewind 10 seconds" +msgstr "Spol 10 sekunder tilbage" -#: podcasts-gtk/resources/gtk/player_toolbar.ui:384 -msgid "Normal speed" -msgstr "Normal hastighed" +#: podcasts-gtk/resources/gtk/player_toolbar.ui:107 +msgid "Play" +msgstr "Afspil" + +#: podcasts-gtk/resources/gtk/player_toolbar.ui:118 +msgid "Pause" +msgstr "Pause" + +#: podcasts-gtk/resources/gtk/player_toolbar.ui:129 +msgid "Fast forward 10 seconds" +msgstr "Spol 10 sekunder fremad" #: podcasts-gtk/resources/gtk/secondary_menu.ui:7 msgid "_Mark All Episodes as Played" @@ -275,103 +327,128 @@ msgstr "_Websted" msgid "_Unsubscribe" msgstr "_Afmeld abonnement" -#: podcasts-gtk/resources/gtk/show_menu.ui:51 +#: podcasts-gtk/resources/gtk/show_menu.ui:36 msgid "Open Website" msgstr "Åbn websted" -#: podcasts-gtk/resources/gtk/show_menu.ui:64 +#: podcasts-gtk/resources/gtk/show_menu.ui:40 msgid "Mark All as Played" msgstr "Markér alle som afspillet" -#: podcasts-gtk/resources/gtk/show_menu.ui:89 +#: podcasts-gtk/resources/gtk/show_menu.ui:46 msgid "Unsubscribe" msgstr "Afmeld abonnement" -#: podcasts-gtk/src/app.rs:351 +#: podcasts-gtk/resources/gtk/show_widget.ui:98 +msgid "Read More" +msgstr "Læs mere" + +#: podcasts-gtk/src/app.rs:353 msgid "Fetching new episodes" msgstr "Henter nye episoder" -#: podcasts-gtk/src/headerbar.rs:117 -msgid "You are already subscribed to this show" -msgstr "Du har allerede abonneret på udsendelsen" - -#: podcasts-gtk/src/headerbar.rs:125 -msgid "Invalid URL" -msgstr "Ugyldig URL" - -#: podcasts-gtk/src/stacks/content.rs:54 +#: podcasts-gtk/src/stacks/content.rs:58 msgid "New" msgstr "Nyt" -#: podcasts-gtk/src/stacks/content.rs:55 +#: podcasts-gtk/src/stacks/content.rs:59 msgid "Shows" msgstr "Udsendelser" -#: podcasts-gtk/src/utils.rs:397 +#: podcasts-gtk/src/utils.rs:501 msgid "Select the file from which to you want to import shows." msgstr "Vælg den fil du vil importere udsendelser fra." -#: podcasts-gtk/src/utils.rs:400 +#: podcasts-gtk/src/utils.rs:504 msgid "_Import" msgstr "_Importér" -#: podcasts-gtk/src/utils.rs:409 podcasts-gtk/src/utils.rs:457 +#: podcasts-gtk/src/utils.rs:513 podcasts-gtk/src/utils.rs:562 msgid "OPML file" msgstr "OPML-fil" -#: podcasts-gtk/src/utils.rs:426 +#: podcasts-gtk/src/utils.rs:531 msgid "Failed to parse the imported file" msgstr "Kunne ikke fortolke den importerede fil" -#: podcasts-gtk/src/utils.rs:431 podcasts-gtk/src/utils.rs:475 +#: podcasts-gtk/src/utils.rs:536 podcasts-gtk/src/utils.rs:581 msgid "Selected file could not be accessed." msgstr "Kunne ikke tilgå den valgte fil." -#: podcasts-gtk/src/utils.rs:445 +#: podcasts-gtk/src/utils.rs:547 msgid "Export shows to…" msgstr "Eksportér udsendelser til …" -#: podcasts-gtk/src/utils.rs:448 +#: podcasts-gtk/src/utils.rs:550 msgid "_Export" msgstr "_Eksportér" -#: podcasts-gtk/src/utils.rs:449 +#: podcasts-gtk/src/utils.rs:551 msgid "_Cancel" msgstr "_Annuller" -#: podcasts-gtk/src/utils.rs:469 +#. Translators: This is the string of the suggested name for the exported opml file +#: podcasts-gtk/src/utils.rs:555 +msgid "gnome-podcasts-exported-shows" +msgstr "gnome-podcasts-eksporterede-udsendelser" + +#: podcasts-gtk/src/utils.rs:575 msgid "GNOME Podcasts Subscriptions" msgstr "Abonneringer for GNOME Podcasts" -#: podcasts-gtk/src/utils.rs:470 +#: podcasts-gtk/src/utils.rs:576 msgid "Failed to export podcasts" msgstr "Kunne ikke eksportere podcasts" -#: podcasts-gtk/src/widgets/aboutdialog.rs:51 +#: podcasts-gtk/src/widgets/aboutdialog.rs:58 msgid "Podcast Client for the GNOME Desktop." msgstr "Podcast-klient til GNOME-skrivebordet." -#: podcasts-gtk/src/widgets/aboutdialog.rs:58 +#: podcasts-gtk/src/widgets/aboutdialog.rs:65 msgid "Learn more about GNOME Podcasts" msgstr "Lær mere om GNOME Podcasts" -#: podcasts-gtk/src/widgets/aboutdialog.rs:63 +#: podcasts-gtk/src/widgets/aboutdialog.rs:69 msgid "translator-credits" msgstr "scootergrisen" -#: podcasts-gtk/src/widgets/episode.rs:148 +#: podcasts-gtk/src/widgets/episode.rs:145 msgid "{} min" msgstr "{} min" -#. sender.send(Action::ErrorNotification(format!("Player Error: {}", error))); -#: podcasts-gtk/src/widgets/player.rs:534 +#: podcasts-gtk/src/widgets/episode_description.rs:165 +msgid "Copied URL to clipboard!" +msgstr "Kopierede URL'en til udklipsholderen!" + +#: podcasts-gtk/src/widgets/player.rs:902 msgid "The media player was unable to execute an action." msgstr "Medieafspilleren kunne ikke udføre en handling." -#: podcasts-gtk/src/widgets/show_menu.rs:179 +#: podcasts-gtk/src/widgets/show_menu.rs:194 msgid "Marked all episodes as listened" msgstr "Markerede alle episoder som hørt" -#: podcasts-gtk/src/widgets/show_menu.rs:184 +#: podcasts-gtk/src/widgets/show_menu.rs:199 msgid "Unsubscribed from {}" msgstr "Afmeldte abonnement fra {}" + +#~ msgid "Podcast app for GNOME" +#~ msgstr "Podcast-program til GNOME" + +#~ msgid "You are already subscribed to that feed!" +#~ msgstr "Du har allerede abonneret på feedet!" + +#~ msgid "1.5 speed rate" +#~ msgstr "1,5 hastighed" + +#~ msgid "1.25 speed rate" +#~ msgstr "1,25 hastighed" + +#~ msgid "Normal speed" +#~ msgstr "Normal hastighed" + +#~ msgid "You are already subscribed to this show" +#~ msgstr "Du har allerede abonneret på udsendelsen" + +#~ msgid "Invalid URL" +#~ msgstr "Ugyldig URL" -- 2.40.1 From f3d87ef768e051142d0375c2993f694c8bf775c5 Mon Sep 17 00:00:00 2001 From: DaeHyun Sung Date: Thu, 3 Mar 2022 12:50:27 +0000 Subject: [PATCH 015/102] Update Korean translation --- podcasts-gtk/po/ko.po | 37 ++++++++++++++++++++++++++----------- 1 file changed, 26 insertions(+), 11 deletions(-) diff --git a/podcasts-gtk/po/ko.po b/podcasts-gtk/po/ko.po index 59bb848..11b08a5 100644 --- a/podcasts-gtk/po/ko.po +++ b/podcasts-gtk/po/ko.po @@ -2,22 +2,22 @@ # Copyright (C) 2018 podcasts's COPYRIGHT HOLDER # This file is distributed under the same license as the podcasts package. # Seong-ho Cho , 2018-2021. -# DaeHyun Sung , 2020-2021. +# DaeHyun Sung , 2020-2022. # msgid "" msgstr "" "Project-Id-Version: podcasts master\n" "Report-Msgid-Bugs-To: https://gitlab.gnome.org/World/podcasts/issues\n" -"POT-Creation-Date: 2021-09-14 16:55+0000\n" -"PO-Revision-Date: 2021-10-01 12:22+0900\n" -"Last-Translator: Seong-ho Cho \n" +"POT-Creation-Date: 2021-11-28 07:07+0000\n" +"PO-Revision-Date: 2022-03-01 23:29+0900\n" +"Last-Translator: DaeHyun Sung \n" "Language-Team: Korean \n" "Language: ko\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" -"X-Generator: Poedit 2.3.1\n" +"X-Generator: Poedit 3.0.1\n" #: podcasts-gtk/resources/org.gnome.Podcasts.gschema.xml.in:15 msgid "Top position of the last open main window" @@ -76,7 +76,6 @@ msgid "Podcasts" msgstr "팟캐스트" #: podcasts-gtk/resources/org.gnome.Podcasts.desktop.in.in:4 -#: podcasts-gtk/resources/org.gnome.Podcasts.appdata.xml.in.in:10 msgid "Listen to your favorite podcasts, right from your desktop." msgstr "데스크톱에서 바로 원하는 팟캐스트를 듣습니다." @@ -86,14 +85,27 @@ msgid "Podcast;RSS;" msgstr "Podcast;팟캐스트;RSS;" #: podcasts-gtk/resources/org.gnome.Podcasts.appdata.xml.in.in:8 -msgid "Podcast app for GNOME" -msgstr "그놈용 팟캐스트 앱" +msgid "Listen to your favorite shows" +msgstr "원하는 팟캐스트를 듣기를 보여줍니다" + +#: podcasts-gtk/resources/org.gnome.Podcasts.appdata.xml.in.in:10 +msgid "" +"Play, update, and manage your podcasts from a lightweight interface that " +"seamlessly integrates with GNOME. Podcasts can play various audio formats " +"and remember where you stopped listening. You can subscribe to shows via RSS/" +"Atom, iTunes, and Soundcloud links. Subscriptions from other apps can be " +"imported via OPML files." +msgstr "" +"그놈과 매끄럽게 통합되는 가벼운 인터페이스로 팟캐스트를 재생, 업데이트 및 관" +"리합니다. 팟캐스트는 다양한 오디오 형식을 재생할 수 있고 듣다가 멈춘 곳을 기" +"억할 수 있습니다. RSS/Atom, iTunes 및 Soundcloud links를 통해 프로그램을 구독" +"할 수 있습니다. 다른 앱으로 구독은 OPML파일을 통해 가져올 수 있습니다." -#: podcasts-gtk/resources/org.gnome.Podcasts.appdata.xml.in.in:115 +#: podcasts-gtk/resources/org.gnome.Podcasts.appdata.xml.in.in:117 msgid "Jordan Petridis" msgstr "Jordan Petridis" -#: podcasts-gtk/resources/org.gnome.Podcasts.appdata.xml.in.in:116 +#: podcasts-gtk/resources/org.gnome.Podcasts.appdata.xml.in.in:118 msgid "Julian Hofer" msgstr "Julian Hofer" @@ -395,7 +407,7 @@ msgstr "그놈 팟캐스트에 대해 더 알아보세요" msgid "translator-credits" msgstr "" "조성호 , 2018\n" -"성대현 , 2020" +"성대현 , 2020-2022" #: podcasts-gtk/src/widgets/episode.rs:145 msgid "{} min" @@ -417,6 +429,9 @@ msgstr "모든 에피소드를 감청 상태로 표시했습니다" msgid "Unsubscribed from {}" msgstr "{}에서 가입 취소했습니다" +#~ msgid "Podcast app for GNOME" +#~ msgstr "그놈용 팟캐스트 앱" + #~ msgid "Double speed rate" #~ msgstr "2배 속도" -- 2.40.1 From ea3d01832411a0f29ced0ad621c096ccddc3fc89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20=C4=8Cernock=C3=BD?= Date: Wed, 9 Mar 2022 22:16:31 +0000 Subject: [PATCH 016/102] Update Czech translation --- podcasts-gtk/po/cs.po | 29 +++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/podcasts-gtk/po/cs.po b/podcasts-gtk/po/cs.po index 7ed7988..1263154 100644 --- a/podcasts-gtk/po/cs.po +++ b/podcasts-gtk/po/cs.po @@ -2,14 +2,14 @@ # Copyright (C) 2018 podcasts's COPYRIGHT HOLDER # This file is distributed under the same license as the podcasts package. # -# Marek Černocký , 2018, 2020, 2021. +# Marek Černocký , 2018, 2020, 2021, 2022. # msgid "" msgstr "" "Project-Id-Version: podcasts\n" "Report-Msgid-Bugs-To: https://gitlab.gnome.org/World/podcasts/issues\n" -"POT-Creation-Date: 2021-09-14 16:55+0000\n" -"PO-Revision-Date: 2021-09-28 11:14+0200\n" +"POT-Creation-Date: 2021-11-28 07:07+0000\n" +"PO-Revision-Date: 2022-03-09 23:10+0100\n" "Last-Translator: Marek Černocký \n" "Language-Team: čeština \n" "Language: cs\n" @@ -76,7 +76,6 @@ msgid "Podcasts" msgstr "Podcasty" #: podcasts-gtk/resources/org.gnome.Podcasts.desktop.in.in:4 -#: podcasts-gtk/resources/org.gnome.Podcasts.appdata.xml.in.in:10 msgid "Listen to your favorite podcasts, right from your desktop." msgstr "Poslouchejte své oblíbené podcasty přímo z počítače" @@ -86,14 +85,28 @@ msgid "Podcast;RSS;" msgstr "podcast;RSS;pořad;" #: podcasts-gtk/resources/org.gnome.Podcasts.appdata.xml.in.in:8 -msgid "Podcast app for GNOME" -msgstr "Podcastová aplikace pro GNOME" +msgid "Listen to your favorite shows" +msgstr "Poslouchejte své oblíbené pořady" + +#: podcasts-gtk/resources/org.gnome.Podcasts.appdata.xml.in.in:10 +msgid "" +"Play, update, and manage your podcasts from a lightweight interface that " +"seamlessly integrates with GNOME. Podcasts can play various audio formats " +"and remember where you stopped listening. You can subscribe to shows via RSS/" +"Atom, iTunes, and Soundcloud links. Subscriptions from other apps can be " +"imported via OPML files." +msgstr "" +"Přehrávejte si, aktualizujte a spravujte své podcasty v lehkém uživatelském " +"rozhraní, které je hladce zaintegrováno do GNOME. Aplikace Podcasty umí " +"přehrávat různé zvukové formáty a pamatuje si, kde jste přerušili poslech. " +"Pořady můžete odebírat přes RSS/Atom, iTunes a odkazy Soundcloud. Odběry " +"nastavené v jiných aplikacích lze naimportovat přes soubory OPML." -#: podcasts-gtk/resources/org.gnome.Podcasts.appdata.xml.in.in:115 +#: podcasts-gtk/resources/org.gnome.Podcasts.appdata.xml.in.in:117 msgid "Jordan Petridis" msgstr "Jordan Petridis" -#: podcasts-gtk/resources/org.gnome.Podcasts.appdata.xml.in.in:116 +#: podcasts-gtk/resources/org.gnome.Podcasts.appdata.xml.in.in:118 msgid "Julian Hofer" msgstr "Julian Hofer" -- 2.40.1 From 70f23fbee98c250576aec9a60733c98c5e114ccc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Goran=20Vidovi=C4=87?= Date: Fri, 11 Mar 2022 20:23:38 +0000 Subject: [PATCH 017/102] Update Croatian translation --- podcasts-gtk/po/hr.po | 36 ++++++++++++++++++++++++++---------- 1 file changed, 26 insertions(+), 10 deletions(-) diff --git a/podcasts-gtk/po/hr.po b/podcasts-gtk/po/hr.po index 2510a96..2d6e281 100644 --- a/podcasts-gtk/po/hr.po +++ b/podcasts-gtk/po/hr.po @@ -7,17 +7,17 @@ msgid "" msgstr "" "Project-Id-Version: podcasts master\n" "Report-Msgid-Bugs-To: https://gitlab.gnome.org/World/podcasts/issues\n" -"POT-Creation-Date: 2021-09-14 16:55+0000\n" -"PO-Revision-Date: 2021-10-01 18:50+0200\n" +"POT-Creation-Date: 2021-11-28 07:07+0000\n" +"PO-Revision-Date: 2022-03-11 21:15+0100\n" "Last-Translator: gogo \n" "Language-Team: Croatian \n" "Language: hr\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" -"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" -"X-Generator: Poedit 2.3\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && " +"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" +"X-Generator: Poedit 3.0.1\n" #: podcasts-gtk/resources/org.gnome.Podcasts.gschema.xml.in:15 msgid "Top position of the last open main window" @@ -79,7 +79,6 @@ msgid "Podcasts" msgstr "Podcasti" #: podcasts-gtk/resources/org.gnome.Podcasts.desktop.in.in:4 -#: podcasts-gtk/resources/org.gnome.Podcasts.appdata.xml.in.in:10 msgid "Listen to your favorite podcasts, right from your desktop." msgstr "Slušajte svoje omiljene podcaste." @@ -89,14 +88,28 @@ msgid "Podcast;RSS;" msgstr "Podcast;RSS;" #: podcasts-gtk/resources/org.gnome.Podcasts.appdata.xml.in.in:8 -msgid "Podcast app for GNOME" -msgstr "Podcast aplikacija za GNOME" +msgid "Listen to your favorite shows" +msgstr "Slušajte svoje omiljene emisije" + +#: podcasts-gtk/resources/org.gnome.Podcasts.appdata.xml.in.in:10 +msgid "" +"Play, update, and manage your podcasts from a lightweight interface that " +"seamlessly integrates with GNOME. Podcasts can play various audio formats " +"and remember where you stopped listening. You can subscribe to shows via RSS/" +"Atom, iTunes, and Soundcloud links. Subscriptions from other apps can be " +"imported via OPML files." +msgstr "" +"Slušajte, nadopunite i upravljajte svojim podcastima s jednostavnog sučelja " +"koje se neprimjetno integrira s GNOMOM. Podcasti mogu reproducirati razne " +"zvučne formate i zapamtiti gdje ste prestali slušati. Možete se pretplatiti " +"na emisije putem RSS/Atom, iTunes, i Soundcloud poveznica. Pretplate s " +"drugih aplikacija se mogu uvesti putem OPML datoteka." -#: podcasts-gtk/resources/org.gnome.Podcasts.appdata.xml.in.in:115 +#: podcasts-gtk/resources/org.gnome.Podcasts.appdata.xml.in.in:117 msgid "Jordan Petridis" msgstr "Jordan Petridis" -#: podcasts-gtk/resources/org.gnome.Podcasts.appdata.xml.in.in:116 +#: podcasts-gtk/resources/org.gnome.Podcasts.appdata.xml.in.in:118 msgid "Julian Hofer" msgstr "Julian Hofer" @@ -420,6 +433,9 @@ msgstr "Označi sve epizodae kao odslušane" msgid "Unsubscribed from {}" msgstr "Ukini pretplatu za {}" +#~ msgid "Podcast app for GNOME" +#~ msgstr "Podcast aplikacija za GNOME" + #~ msgid "Double speed rate" #~ msgstr "Dvostruko brže" -- 2.40.1 From 0aa00a25320fc2c3160569f57b84c91a89586541 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bal=C3=A1zs=20=C3=9Ar?= Date: Sun, 13 Mar 2022 01:26:49 +0000 Subject: [PATCH 018/102] Update Hungarian translation --- podcasts-gtk/po/hu.po | 73 ++++++++++++++++++++++++++++++++++--------- 1 file changed, 59 insertions(+), 14 deletions(-) diff --git a/podcasts-gtk/po/hu.po b/podcasts-gtk/po/hu.po index 45e6954..3d20fe1 100644 --- a/podcasts-gtk/po/hu.po +++ b/podcasts-gtk/po/hu.po @@ -1,15 +1,15 @@ # Hungarian translation for podcasts. -# Copyright (C) 2018, 2019, 2020, 2021 Free Software Foundation, Inc. +# Copyright (C) 2018, 2019, 2020, 2021, 2022 Free Software Foundation, Inc. # This file is distributed under the same license as the podcasts package. # # Meskó Balázs , 2018. -# Balázs Úr , 2019, 2020, 2021. +# Balázs Úr , 2019, 2020, 2021, 2022. msgid "" msgstr "" "Project-Id-Version: podcasts master\n" "Report-Msgid-Bugs-To: https://gitlab.gnome.org/World/podcasts/issues\n" -"POT-Creation-Date: 2021-09-07 14:56+0000\n" -"PO-Revision-Date: 2021-09-10 22:59+0200\n" +"POT-Creation-Date: 2021-11-28 07:07+0000\n" +"PO-Revision-Date: 2022-03-13 02:25+0100\n" "Last-Translator: Balázs Úr \n" "Language-Team: Hungarian \n" "Language: hu\n" @@ -76,7 +76,6 @@ msgid "Podcasts" msgstr "Podcastok" #: podcasts-gtk/resources/org.gnome.Podcasts.desktop.in.in:4 -#: podcasts-gtk/resources/org.gnome.Podcasts.appdata.xml.in.in:10 msgid "Listen to your favorite podcasts, right from your desktop." msgstr "Hallgassa kedvenc podcastjait, közvetlenül az asztalán." @@ -86,14 +85,30 @@ msgid "Podcast;RSS;" msgstr "Podcast;RSS;" #: podcasts-gtk/resources/org.gnome.Podcasts.appdata.xml.in.in:8 -msgid "Podcast app for GNOME" -msgstr "Podcast alkalmazás a GNOME-hoz" +#| msgid "Listen to your favorite podcasts, right from your desktop." +msgid "Listen to your favorite shows" +msgstr "Hallgassa kedvenc műsorait" -#: podcasts-gtk/resources/org.gnome.Podcasts.appdata.xml.in.in:115 +#: podcasts-gtk/resources/org.gnome.Podcasts.appdata.xml.in.in:10 +msgid "" +"Play, update, and manage your podcasts from a lightweight interface that " +"seamlessly integrates with GNOME. Podcasts can play various audio formats " +"and remember where you stopped listening. You can subscribe to shows via RSS/" +"Atom, iTunes, and Soundcloud links. Subscriptions from other apps can be " +"imported via OPML files." +msgstr "" +"Játssza le, frissítse és kezelje a podcastjait egy könnyűsúlyú felületről, " +"amely zökkenőmentesen illeszkedik a GNOME-hoz. A Podcastok különböző " +"hangformátumokat tud lejátszani, és megjegyzi, hogy hol hagyta abba a " +"hallgatásukat. Feliratkozhat a műsorokra RSS/Atom hírcsatornákkal, iTunes és " +"Soundcloud hivatkozásokkal. A más alkalmazásokban lévő feliratkozások is " +"importálhatók OPML-fájlok segítségével." + +#: podcasts-gtk/resources/org.gnome.Podcasts.appdata.xml.in.in:117 msgid "Jordan Petridis" msgstr "Jordan Petridis" -#: podcasts-gtk/resources/org.gnome.Podcasts.appdata.xml.in.in:116 +#: podcasts-gtk/resources/org.gnome.Podcasts.appdata.xml.in.in:118 msgid "Julian Hofer" msgstr "Julian Hofer" @@ -117,6 +132,37 @@ msgstr "Új műsorok hozzáadása csatorna URL-ből" msgid "Import shows from another device" msgstr "Műsorok importálása egy másik eszközről" +#: podcasts-gtk/resources/gtk/episode_description.ui:49 +msgid "Episode Details" +msgstr "Epizód részletei" + +#: podcasts-gtk/resources/gtk/episode_description.ui:64 +#: podcasts-gtk/resources/gtk/headerbar.ui:186 +msgid "Back" +msgstr "Vissza" + +#: podcasts-gtk/resources/gtk/episode_description.ui:148 +#| msgid "Podcasts" +msgid "Podcast Title" +msgstr "Podcast címe" + +#: podcasts-gtk/resources/gtk/episode_description.ui:186 +msgid "Duration - Date" +msgstr "Hossz – Dátum" + +#: podcasts-gtk/resources/gtk/episode_description.ui:241 +msgid "Episode Description" +msgstr "Epizód leírása" + +#: podcasts-gtk/resources/gtk/episode_menu.ui:36 +#| msgid "_Import Shows" +msgid "Go to Show" +msgstr "Ugrás a műsorhoz" + +#: podcasts-gtk/resources/gtk/episode_menu.ui:40 +msgid "Copy Episode Url" +msgstr "Epizód URL másolása" + #: podcasts-gtk/resources/gtk/episode_widget.ui:82 msgid "You’ve already listened to this episode." msgstr "Már meghallgatta ezt az epizódot." @@ -174,10 +220,6 @@ msgstr "Hozzáadás" msgid "Show Title" msgstr "Műsor címe" -#: podcasts-gtk/resources/gtk/headerbar.ui:186 -msgid "Back" -msgstr "Vissza" - #: podcasts-gtk/resources/gtk/help-overlay.ui:12 msgid "General" msgstr "Általános" @@ -254,7 +296,6 @@ msgid "0.90×" msgstr "0,90×" #: podcasts-gtk/resources/gtk/player_rate.ui:95 -#| msgid "1.75×" msgid "0.75×" msgstr "0,75×" @@ -375,6 +416,10 @@ msgstr "Meskó Balázs " msgid "{} min" msgstr "{} perc" +#: podcasts-gtk/src/widgets/episode_description.rs:165 +msgid "Copied URL to clipboard!" +msgstr "URL a vágólapra másolva." + #: podcasts-gtk/src/widgets/player.rs:902 msgid "The media player was unable to execute an action." msgstr "A médialejátszó nem tudott végrehajtani egy műveletet." -- 2.40.1 From 6b96c5f1d125d694cf41839e4e500b537199915f Mon Sep 17 00:00:00 2001 From: Davide Ferracin Date: Tue, 15 Mar 2022 16:56:47 +0000 Subject: [PATCH 019/102] Update Italian translation --- podcasts-gtk/po/it.po | 274 +++++++++++++++++++++++++----------------- 1 file changed, 164 insertions(+), 110 deletions(-) diff --git a/podcasts-gtk/po/it.po b/podcasts-gtk/po/it.po index 2e08e4e..695f9ed 100644 --- a/podcasts-gtk/po/it.po +++ b/podcasts-gtk/po/it.po @@ -7,9 +7,9 @@ msgid "" msgstr "" "Project-Id-Version: podcasts master\n" "Report-Msgid-Bugs-To: https://gitlab.gnome.org/World/podcasts/issues\n" -"POT-Creation-Date: 2020-02-07 11:33+0000\n" -"PO-Revision-Date: 2020-03-06 09:41+0100\n" -"Last-Translator: Milo Casagrande \n" +"POT-Creation-Date: 2021-09-14 16:55+0000\n" +"PO-Revision-Date: 2021-11-03 08:44+0100\n" +"Last-Translator: Davide Ferracin \n" "Language-Team: Italian \n" "Language: it\n" "MIME-Version: 1.0\n" @@ -18,66 +18,67 @@ msgstr "" "Plural-Forms: nplurals=2; plural=(n != 1);\n" "X-Generator: Poedit 2.2.4\n" -#: podcasts-gtk/resources/org.gnome.Podcasts.gschema.xml:15 +#: podcasts-gtk/resources/org.gnome.Podcasts.gschema.xml.in:15 msgid "Top position of the last open main window" msgstr "Posizione superiore dell'ultima finestra principale aperta" -#: podcasts-gtk/resources/org.gnome.Podcasts.gschema.xml:19 +#: podcasts-gtk/resources/org.gnome.Podcasts.gschema.xml.in:19 msgid "Left position of the last open main window" msgstr "Posizione sinistra dell'ultima finestra principale aperta" -#: podcasts-gtk/resources/org.gnome.Podcasts.gschema.xml:23 +#: podcasts-gtk/resources/org.gnome.Podcasts.gschema.xml.in:23 msgid "Height of the last open main window" msgstr "Altezza dell'ultima finestra principale aperta" -#: podcasts-gtk/resources/org.gnome.Podcasts.gschema.xml:27 +#: podcasts-gtk/resources/org.gnome.Podcasts.gschema.xml.in:27 msgid "Width of the last open main window" msgstr "Larghezza dell'ultima finestra principale aperta" -#: podcasts-gtk/resources/org.gnome.Podcasts.gschema.xml:31 +#: podcasts-gtk/resources/org.gnome.Podcasts.gschema.xml.in:31 msgid "Maximized state of the last open main window" msgstr "Stato di massimizzazione dell'ultima finestra principale aperta" -#: podcasts-gtk/resources/org.gnome.Podcasts.gschema.xml:36 +#: podcasts-gtk/resources/org.gnome.Podcasts.gschema.xml.in:36 msgid "Enable or disable dark theme" msgstr "Abilita/Disabilita il tema scuro" -#: podcasts-gtk/resources/org.gnome.Podcasts.gschema.xml:41 +#: podcasts-gtk/resources/org.gnome.Podcasts.gschema.xml.in:41 msgid "Whether to periodically refresh content" msgstr "Indica se aggiornare i contenuti periodicamente" -#: podcasts-gtk/resources/org.gnome.Podcasts.gschema.xml:46 +#: podcasts-gtk/resources/org.gnome.Podcasts.gschema.xml.in:46 msgid "How many periods of time to wait between automatic refreshes" msgstr "Quanto tempo aspettare tra gli aggiornamenti automatici" -#: podcasts-gtk/resources/org.gnome.Podcasts.gschema.xml:50 +#: podcasts-gtk/resources/org.gnome.Podcasts.gschema.xml.in:50 msgid "What period of time to wait between automatic refreshes" msgstr "Che periodo di tempo aspettare tra gli aggiornamenti automatici" -#: podcasts-gtk/resources/org.gnome.Podcasts.gschema.xml:54 +#: podcasts-gtk/resources/org.gnome.Podcasts.gschema.xml.in:54 msgid "Whether to refresh content after startup" msgstr "Indica se aggiornare i contenuti dopo l'avvio" -#: podcasts-gtk/resources/org.gnome.Podcasts.gschema.xml:60 +#: podcasts-gtk/resources/org.gnome.Podcasts.gschema.xml.in:60 msgid "How many periods of time to wait between automatic cleanups" -msgstr "Quanto tempo aspettare tra la pulizia automatica" +msgstr "Quanto tempo aspettare tra una pulizia automatica e la successiva" -#: podcasts-gtk/resources/org.gnome.Podcasts.gschema.xml:64 +#: podcasts-gtk/resources/org.gnome.Podcasts.gschema.xml.in:64 msgid "What period of time to wait between automatic cleanups" -msgstr "Che periodi di tempo aspettare tra la pulizia automatica" +msgstr "" +"Che periodo di tempo aspettare tra una pulizia automatica e la successiva" #. Weird magic I copy-pasted that sets the Application Name in the Shell. #: podcasts-gtk/resources/org.gnome.Podcasts.desktop.in.in:3 #: podcasts-gtk/resources/org.gnome.Podcasts.appdata.xml.in.in:4 -#: podcasts-gtk/resources/gtk/headerbar.ui:158 podcasts-gtk/src/app.rs:330 -#: podcasts-gtk/src/widgets/aboutdialog.rs:56 podcasts-gtk/src/window.rs:80 +#: podcasts-gtk/resources/gtk/headerbar.ui:137 podcasts-gtk/src/app.rs:438 +#: podcasts-gtk/src/widgets/aboutdialog.rs:63 podcasts-gtk/src/window.rs:66 msgid "Podcasts" msgstr "Podcast" #: podcasts-gtk/resources/org.gnome.Podcasts.desktop.in.in:4 #: podcasts-gtk/resources/org.gnome.Podcasts.appdata.xml.in.in:10 msgid "Listen to your favorite podcasts, right from your desktop." -msgstr "Ascoltare i propri podcast preferiti, direttamente proprio computer." +msgstr "Ascolta i tuoi podcast preferiti, direttamente dal tuo computer." #. Translators: Search terms to find this application. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! #: podcasts-gtk/resources/org.gnome.Podcasts.desktop.in.in:13 @@ -88,47 +89,81 @@ msgstr "Podcast;RSS;" msgid "Podcast app for GNOME" msgstr "Applicazione per podcast per GNOME" -#: podcasts-gtk/resources/org.gnome.Podcasts.appdata.xml.in.in:84 +#: podcasts-gtk/resources/org.gnome.Podcasts.appdata.xml.in.in:115 msgid "Jordan Petridis" msgstr "Jordan Petridis" +#: podcasts-gtk/resources/org.gnome.Podcasts.appdata.xml.in.in:116 +msgid "Julian Hofer" +msgstr "Julian Hofer" + #: podcasts-gtk/resources/gtk/empty_view.ui:46 msgid "This show does not have episodes yet" -msgstr "Questo show non ha ancora episodi" +msgstr "Questa trasmissione non ha ancora episodi" -#: podcasts-gtk/resources/gtk/empty_view.ui:62 +#: podcasts-gtk/resources/gtk/empty_view.ui:57 msgid "If you think this is an error, please consider writing a bug report." -msgstr "Se considerate questo evento un errore, inviare una segnalazione." +msgstr "" +"Se consideri che sia un errore, invia una segnalazione, per favore." -#: podcasts-gtk/resources/gtk/empty_view.ui:106 +#: podcasts-gtk/resources/gtk/empty_view.ui:91 msgid "Get some shows" -msgstr "Ottieni show" +msgstr "Ottieni trasmissioni" -#: podcasts-gtk/resources/gtk/empty_view.ui:143 +#: podcasts-gtk/resources/gtk/empty_view.ui:123 msgid "Add new shows via feed URL" -msgstr "Aggiungi nuovi show via URL" +msgstr "Aggiungi nuove trasmissioni da un URL" -#: podcasts-gtk/resources/gtk/empty_view.ui:172 +#: podcasts-gtk/resources/gtk/empty_view.ui:152 msgid "Import shows from another device" -msgstr "Importa show da un altro dispositivo" +msgstr "Importa trasmissioni da un altro dispositivo" + +#: podcasts-gtk/resources/gtk/episode_description.ui:49 +msgid "Episode Details" +msgstr "Dettagli dell'episodio" + +#: podcasts-gtk/resources/gtk/episode_description.ui:64 +#: podcasts-gtk/resources/gtk/headerbar.ui:186 +msgid "Back" +msgstr "Indietro" -#: podcasts-gtk/resources/gtk/episode_widget.ui:79 +#: podcasts-gtk/resources/gtk/episode_description.ui:148 +msgid "Podcast Title" +msgstr "Titolo del podcast" + +#: podcasts-gtk/resources/gtk/episode_description.ui:186 +msgid "Duration - Date" +msgstr "Durata - Data" + +#: podcasts-gtk/resources/gtk/episode_description.ui:241 +msgid "Episode Description" +msgstr "Descrizione dell'episodio" + +#: podcasts-gtk/resources/gtk/episode_menu.ui:36 +msgid "Go to Show" +msgstr "Vai alla trasmissione" + +#: podcasts-gtk/resources/gtk/episode_menu.ui:40 +msgid "Copy Episode Url" +msgstr "Copia l'URL della trasmissione" + +#: podcasts-gtk/resources/gtk/episode_widget.ui:82 msgid "You’ve already listened to this episode." msgstr "Questo episodio è già stato ascoltato." -#: podcasts-gtk/resources/gtk/episode_widget.ui:208 +#: podcasts-gtk/resources/gtk/episode_widget.ui:187 msgid "Calculating episode size…" -msgstr "Calcolo dimensione episodio…" +msgstr "Calcolo la dimensione dell'episodio…" -#: podcasts-gtk/resources/gtk/episode_widget.ui:248 +#: podcasts-gtk/resources/gtk/episode_widget.ui:214 msgid "Play this episode" msgstr "Riproduci questo episodio" -#: podcasts-gtk/resources/gtk/episode_widget.ui:269 +#: podcasts-gtk/resources/gtk/episode_widget.ui:230 msgid "Cancel the download process" msgstr "Annulla lo scaricamento" -#: podcasts-gtk/resources/gtk/episode_widget.ui:292 +#: podcasts-gtk/resources/gtk/episode_widget.ui:250 msgid "Download this episode" msgstr "Scarica questo episodio" @@ -138,11 +173,11 @@ msgstr "Controlla per _nuovi episodi" #: podcasts-gtk/resources/gtk/hamburger.ui:12 msgid "_Import Shows" -msgstr "_Importa show" +msgstr "_Importa trasmissioni" #: podcasts-gtk/resources/gtk/hamburger.ui:16 msgid "_Export Shows" -msgstr "_Esporta show" +msgstr "_Esporta trasmissioni" #: podcasts-gtk/resources/gtk/hamburger.ui:22 msgid "_Keyboard Shortcuts" @@ -153,25 +188,21 @@ msgid "_About Podcasts" msgstr "I_nformazioni su Podcast" #: podcasts-gtk/resources/gtk/headerbar.ui:35 -#: podcasts-gtk/resources/gtk/headerbar.ui:186 +#: podcasts-gtk/resources/gtk/headerbar.ui:165 msgid "Add a new feed" -msgstr "Aggiungi nuovo feed" +msgstr "Aggiungi un nuovo feed" #: podcasts-gtk/resources/gtk/headerbar.ui:53 msgid "Enter feed address to add" -msgstr "Inserire un indirizzo da aggiungere" +msgstr "Inserisci un indirizzo da aggiungere" -#: podcasts-gtk/resources/gtk/headerbar.ui:89 +#: podcasts-gtk/resources/gtk/headerbar.ui:79 msgid "Add" msgstr "Aggiungi" -#: podcasts-gtk/resources/gtk/headerbar.ui:171 +#: podcasts-gtk/resources/gtk/headerbar.ui:150 msgid "Show Title" -msgstr "Titolo show" - -#: podcasts-gtk/resources/gtk/headerbar.ui:207 -msgid "Back" -msgstr "Indietro" +msgstr "Titolo della trasmissione" #: podcasts-gtk/resources/gtk/help-overlay.ui:12 msgid "General" @@ -180,38 +211,38 @@ msgstr "Generale" #: podcasts-gtk/resources/gtk/help-overlay.ui:18 msgctxt "shortcut window" msgid "Check for new episodes" -msgstr "Controlla presenza nuovi episodi" +msgstr "Controlla presenza di nuovi episodi" #: podcasts-gtk/resources/gtk/help-overlay.ui:25 msgctxt "shortcut window" msgid "Quit the application" -msgstr "Esce dall'applicazione" +msgstr "Esci dall'applicazione" #: podcasts-gtk/resources/gtk/home_view.ui:56 msgid "Today" msgstr "Oggi" -#: podcasts-gtk/resources/gtk/home_view.ui:112 +#: podcasts-gtk/resources/gtk/home_view.ui:89 msgid "Yesterday" msgstr "Ieri" -#: podcasts-gtk/resources/gtk/home_view.ui:168 +#: podcasts-gtk/resources/gtk/home_view.ui:122 msgid "This Week" msgstr "Questa settimana" -#: podcasts-gtk/resources/gtk/home_view.ui:224 +#: podcasts-gtk/resources/gtk/home_view.ui:155 msgid "This Month" msgstr "Questo mese" -#: podcasts-gtk/resources/gtk/home_view.ui:281 +#: podcasts-gtk/resources/gtk/home_view.ui:189 msgid "Older" msgstr "Più vecchi" -#: podcasts-gtk/resources/gtk/inapp_notif.ui:101 +#: podcasts-gtk/resources/gtk/inapp_notif.ui:69 msgid "An in-app action notification" msgstr "Una notifica" -#: podcasts-gtk/resources/gtk/inapp_notif.ui:112 +#: podcasts-gtk/resources/gtk/inapp_notif.ui:75 msgid "Undo" msgstr "Annulla" @@ -223,44 +254,48 @@ msgstr "In riproduzione" msgid "Change the playback speed" msgstr "Modifica la velocità di riproduzione" -#: podcasts-gtk/resources/gtk/player_rate.ui:47 -#: podcasts-gtk/resources/gtk/player_rate.ui:122 +#: podcasts-gtk/resources/gtk/player_rate.ui:46 +#: podcasts-gtk/resources/gtk/player_rate.ui:85 msgid "1.00×" msgstr "1,00×" -#: podcasts-gtk/resources/gtk/player_rate.ui:86 +#: podcasts-gtk/resources/gtk/player_rate.ui:65 +msgid "2.00×" +msgstr "2,00×" + +#: podcasts-gtk/resources/gtk/player_rate.ui:70 +msgid "1.75×" +msgstr "1,75×" + +#: podcasts-gtk/resources/gtk/player_rate.ui:75 msgid "1.50×" msgstr "1,50×" -#: podcasts-gtk/resources/gtk/player_rate.ui:90 -msgid "1.5 speed rate" -msgstr "1,5 volte la velocità" - -#: podcasts-gtk/resources/gtk/player_rate.ui:104 +#: podcasts-gtk/resources/gtk/player_rate.ui:80 msgid "1.25×" msgstr "1,25×" -#: podcasts-gtk/resources/gtk/player_rate.ui:108 -msgid "1.25 speed rate" -msgstr "1,25 volte la velocità" +#: podcasts-gtk/resources/gtk/player_rate.ui:90 +msgid "0.90×" +msgstr "0,90×" -#: podcasts-gtk/resources/gtk/player_rate.ui:126 -msgid "Normal speed" -msgstr "Velocità normale" +#: podcasts-gtk/resources/gtk/player_rate.ui:95 +msgid "0.75×" +msgstr "0,75×" #: podcasts-gtk/resources/gtk/player_toolbar.ui:97 msgid "Rewind 10 seconds" msgstr "Indietro 10 secondi" -#: podcasts-gtk/resources/gtk/player_toolbar.ui:112 +#: podcasts-gtk/resources/gtk/player_toolbar.ui:107 msgid "Play" msgstr "Riproduci" -#: podcasts-gtk/resources/gtk/player_toolbar.ui:128 +#: podcasts-gtk/resources/gtk/player_toolbar.ui:118 msgid "Pause" msgstr "Pausa" -#: podcasts-gtk/resources/gtk/player_toolbar.ui:144 +#: podcasts-gtk/resources/gtk/player_toolbar.ui:129 msgid "Fast forward 10 seconds" msgstr "Avanti veloce 10 secondi" @@ -276,99 +311,118 @@ msgstr "Sito _web" msgid "_Unsubscribe" msgstr "_Annulla abbonamento" -#: podcasts-gtk/resources/gtk/show_menu.ui:51 +#: podcasts-gtk/resources/gtk/show_menu.ui:36 msgid "Open Website" msgstr "Apri sito web" -#: podcasts-gtk/resources/gtk/show_menu.ui:64 +#: podcasts-gtk/resources/gtk/show_menu.ui:40 msgid "Mark All as Played" -msgstr "Segna tutti ascoltati" +msgstr "Segna tutti come ascoltati" -#: podcasts-gtk/resources/gtk/show_menu.ui:89 +#: podcasts-gtk/resources/gtk/show_menu.ui:46 msgid "Unsubscribe" msgstr "Annulla abbonamento" -#: podcasts-gtk/resources/gtk/show_widget.ui:99 +#: podcasts-gtk/resources/gtk/show_widget.ui:98 msgid "Read More" -msgstr "Leggi altro" +msgstr "Leggi di più" -#: podcasts-gtk/src/app.rs:265 +#: podcasts-gtk/src/app.rs:353 msgid "Fetching new episodes" msgstr "Scaricamento nuovi episodi" -#: podcasts-gtk/src/stacks/content.rs:54 +#: podcasts-gtk/src/stacks/content.rs:58 msgid "New" -msgstr "Nuovo" +msgstr "Nuove puntate" -#: podcasts-gtk/src/stacks/content.rs:55 +#: podcasts-gtk/src/stacks/content.rs:59 msgid "Shows" -msgstr "Show" +msgstr "Trasmissioni" -#: podcasts-gtk/src/utils.rs:396 +#: podcasts-gtk/src/utils.rs:501 msgid "Select the file from which to you want to import shows." -msgstr "Selezionare il file da cui importare gli show." +msgstr "Seleziona il file da cui importare le trasmissioni." -#: podcasts-gtk/src/utils.rs:399 +#: podcasts-gtk/src/utils.rs:504 msgid "_Import" msgstr "_Importa" -#: podcasts-gtk/src/utils.rs:408 podcasts-gtk/src/utils.rs:456 +#: podcasts-gtk/src/utils.rs:513 podcasts-gtk/src/utils.rs:562 msgid "OPML file" msgstr "File OPML" -#: podcasts-gtk/src/utils.rs:425 +#: podcasts-gtk/src/utils.rs:531 msgid "Failed to parse the imported file" msgstr "Analisi del file importato non riuscita" -#: podcasts-gtk/src/utils.rs:430 podcasts-gtk/src/utils.rs:474 +#: podcasts-gtk/src/utils.rs:536 podcasts-gtk/src/utils.rs:581 msgid "Selected file could not be accessed." msgstr "Impossibile accedere al file selezionato." -#: podcasts-gtk/src/utils.rs:444 +#: podcasts-gtk/src/utils.rs:547 msgid "Export shows to…" -msgstr "Esporta show su…" +msgstr "Esporta trasmissioni su…" -#: podcasts-gtk/src/utils.rs:447 +#: podcasts-gtk/src/utils.rs:550 msgid "_Export" msgstr "_Esporta" -#: podcasts-gtk/src/utils.rs:448 +#: podcasts-gtk/src/utils.rs:551 msgid "_Cancel" msgstr "A_nnulla" -#: podcasts-gtk/src/utils.rs:468 +#. Translators: This is the string of the suggested name for the exported opml file +#: podcasts-gtk/src/utils.rs:555 +msgid "gnome-podcasts-exported-shows" +msgstr "gnome-podcast-trasmissioni-esportate" + +#: podcasts-gtk/src/utils.rs:575 msgid "GNOME Podcasts Subscriptions" -msgstr "Abbonamenti Podcast GNOME" +msgstr "Abbonamenti di GNOME Podcast" -#: podcasts-gtk/src/utils.rs:469 +#: podcasts-gtk/src/utils.rs:576 msgid "Failed to export podcasts" -msgstr "Esportazioni podcast non riuscita" +msgstr "Esportazione dei podcast non riuscita" -#: podcasts-gtk/src/widgets/aboutdialog.rs:51 +#: podcasts-gtk/src/widgets/aboutdialog.rs:58 msgid "Podcast Client for the GNOME Desktop." msgstr "Client podcast per l'ambiente grafico GNOME." -#: podcasts-gtk/src/widgets/aboutdialog.rs:58 +#: podcasts-gtk/src/widgets/aboutdialog.rs:65 msgid "Learn more about GNOME Podcasts" -msgstr "Maggiori informazioni su Podcast GNOME" +msgstr "Maggiori informazioni su GNOME Podcast" -#: podcasts-gtk/src/widgets/aboutdialog.rs:63 +#: podcasts-gtk/src/widgets/aboutdialog.rs:69 msgid "translator-credits" -msgstr "Milo Casagrande " +msgstr "" +"Milo Casagrande \n" +"Davide Ferracin " -#: podcasts-gtk/src/widgets/episode.rs:148 +#: podcasts-gtk/src/widgets/episode.rs:145 msgid "{} min" msgstr "{} min" -#. sender.send(Action::ErrorNotification(format!("Player Error: {}", error))); -#: podcasts-gtk/src/widgets/player.rs:824 +#: podcasts-gtk/src/widgets/episode_description.rs:165 +msgid "Copied URL to clipboard!" +msgstr "URL copiato negli appunti!" + +#: podcasts-gtk/src/widgets/player.rs:902 msgid "The media player was unable to execute an action." -msgstr "Il riproduttore multimediale non può eseguire un'azione." +msgstr "Il riproduttore multimediale non ha potuto eseguire un'azione." -#: podcasts-gtk/src/widgets/show_menu.rs:179 +#: podcasts-gtk/src/widgets/show_menu.rs:194 msgid "Marked all episodes as listened" -msgstr "Episodi segnati come letti" +msgstr "Tutti gli episodi segnati come letti" -#: podcasts-gtk/src/widgets/show_menu.rs:184 +#: podcasts-gtk/src/widgets/show_menu.rs:199 msgid "Unsubscribed from {}" msgstr "Abbonamento a {} annullato" + +#~ msgid "1.5 speed rate" +#~ msgstr "1,5 volte la velocità" + +#~ msgid "1.25 speed rate" +#~ msgstr "1,25 volte la velocità" + +#~ msgid "Normal speed" +#~ msgstr "Velocità normale" -- 2.40.1 From 69664bb694c42f3ca736e4d1d0ea0c364fc47097 Mon Sep 17 00:00:00 2001 From: Jordan Petridis Date: Sun, 20 Mar 2022 16:04:35 +0200 Subject: [PATCH 020/102] README.md: Update flatpak instructions And bump the recommended Builder version to avoid bugs, etc Close #257 --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 3c9692a..d1336b9 100644 --- a/README.md +++ b/README.md @@ -13,13 +13,13 @@ Listen to your favorite podcasts, right from your desktop. ## Quick start -GNOME Podcasts can be built and run with [GNOME Builder][builder] >= 3.28. +GNOME Podcasts can be built and run with [GNOME Builder][builder] >= 41. You can get Builder from [here][get_builder]. You will also need to install the rust-stable extension from flathub. ```sh -flatpak install --user flathub org.freedesktop.Sdk.Extension.rust-stable//20.08 +flatpak install --user flathub org.freedesktop.Sdk.Extension.rust-stable//21.08 ``` Then from Builder, just clone the repo and hit the run button! -- 2.40.1 From a19dea8e67fdb96d43ee895b910fc3b7d97aee3c Mon Sep 17 00:00:00 2001 From: Nathan Follens Date: Fri, 25 Mar 2022 15:59:50 +0000 Subject: [PATCH 021/102] Update Dutch translation --- podcasts-gtk/po/nl.po | 128 +++++++++++++++++++++++++++++------------- 1 file changed, 89 insertions(+), 39 deletions(-) diff --git a/podcasts-gtk/po/nl.po b/podcasts-gtk/po/nl.po index 7790677..f87a2cd 100644 --- a/podcasts-gtk/po/nl.po +++ b/podcasts-gtk/po/nl.po @@ -1,14 +1,14 @@ # Dutch translation for podcasts. # Copyright (C) 2019 podcasts's COPYRIGHT HOLDER # This file is distributed under the same license as the podcasts package. -# Nathan Follens , 2019-2021. +# Nathan Follens , 2019-2022. # msgid "" msgstr "" "Project-Id-Version: podcasts master\n" "Report-Msgid-Bugs-To: https://gitlab.gnome.org/World/podcasts/issues\n" -"POT-Creation-Date: 2021-06-19 18:35+0000\n" -"PO-Revision-Date: 2021-09-07 14:40+0200\n" +"POT-Creation-Date: 2021-11-28 07:07+0000\n" +"PO-Revision-Date: 2022-03-25 16:59+0100\n" "Last-Translator: Nathan Follens \n" "Language-Team: Dutch \n" "Language: nl\n" @@ -16,7 +16,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -"X-Generator: Poedit 3.0\n" +"X-Generator: Poedit 3.0.1\n" #: podcasts-gtk/resources/org.gnome.Podcasts.gschema.xml.in:15 msgid "Top position of the last open main window" @@ -69,13 +69,12 @@ msgstr "Hoe lang te wachten tussen automatische opruimbeurten" #. Weird magic I copy-pasted that sets the Application Name in the Shell. #: podcasts-gtk/resources/org.gnome.Podcasts.desktop.in.in:3 #: podcasts-gtk/resources/org.gnome.Podcasts.appdata.xml.in.in:4 -#: podcasts-gtk/resources/gtk/headerbar.ui:137 podcasts-gtk/src/app.rs:364 -#: podcasts-gtk/src/widgets/aboutdialog.rs:63 podcasts-gtk/src/window.rs:64 +#: podcasts-gtk/resources/gtk/headerbar.ui:137 podcasts-gtk/src/app.rs:438 +#: podcasts-gtk/src/widgets/aboutdialog.rs:63 podcasts-gtk/src/window.rs:66 msgid "Podcasts" msgstr "Podcasts" #: podcasts-gtk/resources/org.gnome.Podcasts.desktop.in.in:4 -#: podcasts-gtk/resources/org.gnome.Podcasts.appdata.xml.in.in:10 msgid "Listen to your favorite podcasts, right from your desktop." msgstr "Luister naar uw favoriete podcasts, rechtstreeks vanop uw bureaublad." @@ -85,20 +84,40 @@ msgid "Podcast;RSS;" msgstr "Podcast;RSS;" #: podcasts-gtk/resources/org.gnome.Podcasts.appdata.xml.in.in:8 -msgid "Podcast app for GNOME" -msgstr "Podcast-toepassing voor Gnome" +msgid "Listen to your favorite shows" +msgstr "Luister naar uw favoriete shows" -#: podcasts-gtk/resources/org.gnome.Podcasts.appdata.xml.in.in:99 +#: podcasts-gtk/resources/org.gnome.Podcasts.appdata.xml.in.in:10 +msgid "" +"Play, update, and manage your podcasts from a lightweight interface that " +"seamlessly integrates with GNOME. Podcasts can play various audio formats " +"and remember where you stopped listening. You can subscribe to shows via RSS/" +"Atom, iTunes, and Soundcloud links. Subscriptions from other apps can be " +"imported via OPML files." +msgstr "" +"Speel uw favoriete podcasts af, werk ze bij en beheer ze via een lichte " +"interface die naadloos integreert met GNOME. Podcasts kan verschillende " +"audioformaten afspelen en onthoudt waar u gestopt bent met luisteren. U kunt " +"zich abonneren op shows via RSS-/Atom-, iTunes- en SoundCloud-verwijzingen. " +"Abonnementen van andere toepassingen kunnen geïmporteerd worden via OPML-" +"bestanden." + +#: podcasts-gtk/resources/org.gnome.Podcasts.appdata.xml.in.in:117 msgid "Jordan Petridis" msgstr "Jordan Petridis" +#: podcasts-gtk/resources/org.gnome.Podcasts.appdata.xml.in.in:118 +msgid "Julian Hofer" +msgstr "Julian Hofer" + #: podcasts-gtk/resources/gtk/empty_view.ui:46 msgid "This show does not have episodes yet" msgstr "Deze show heeft nog geen afleveringen" #: podcasts-gtk/resources/gtk/empty_view.ui:57 msgid "If you think this is an error, please consider writing a bug report." -msgstr "Als u denkt dat dit een fout is, overweeg dan een foutmelding in te dienen." +msgstr "" +"Als u denkt dat dit een fout is, overweeg dan een foutmelding in te dienen." #: podcasts-gtk/resources/gtk/empty_view.ui:91 msgid "Get some shows" @@ -112,9 +131,38 @@ msgstr "Nieuwe shows toevoegen via feed-URL" msgid "Import shows from another device" msgstr "Shows importeren van een ander apparaat" +#: podcasts-gtk/resources/gtk/episode_description.ui:49 +msgid "Episode Details" +msgstr "Informatie over aflevering" + +#: podcasts-gtk/resources/gtk/episode_description.ui:64 +#: podcasts-gtk/resources/gtk/headerbar.ui:186 +msgid "Back" +msgstr "Terug" + +#: podcasts-gtk/resources/gtk/episode_description.ui:148 +msgid "Podcast Title" +msgstr "Podcasttitel" + +#: podcasts-gtk/resources/gtk/episode_description.ui:186 +msgid "Duration - Date" +msgstr "Duur - datum" + +#: podcasts-gtk/resources/gtk/episode_description.ui:241 +msgid "Episode Description" +msgstr "Afleveringsbeschrijving" + +#: podcasts-gtk/resources/gtk/episode_menu.ui:36 +msgid "Go to Show" +msgstr "Ga naar show" + +#: podcasts-gtk/resources/gtk/episode_menu.ui:40 +msgid "Copy Episode Url" +msgstr "Afleverings-URL kopiëren" + #: podcasts-gtk/resources/gtk/episode_widget.ui:82 msgid "You’ve already listened to this episode." -msgstr "U heeft deze aflevering reeds beluisterd." +msgstr "U hebt deze aflevering reeds beluisterd." #: podcasts-gtk/resources/gtk/episode_widget.ui:187 msgid "Calculating episode size…" @@ -169,10 +217,6 @@ msgstr "Toevoegen" msgid "Show Title" msgstr "Titel tonen" -#: podcasts-gtk/resources/gtk/headerbar.ui:186 -msgid "Back" -msgstr "Terug" - #: podcasts-gtk/resources/gtk/help-overlay.ui:12 msgid "General" msgstr "Algemeen" @@ -191,19 +235,19 @@ msgstr "De toepassing afsluiten" msgid "Today" msgstr "Vandaag" -#: podcasts-gtk/resources/gtk/home_view.ui:88 +#: podcasts-gtk/resources/gtk/home_view.ui:89 msgid "Yesterday" msgstr "Gisteren" -#: podcasts-gtk/resources/gtk/home_view.ui:120 +#: podcasts-gtk/resources/gtk/home_view.ui:122 msgid "This Week" msgstr "Deze week" -#: podcasts-gtk/resources/gtk/home_view.ui:152 +#: podcasts-gtk/resources/gtk/home_view.ui:155 msgid "This Month" msgstr "Deze maand" -#: podcasts-gtk/resources/gtk/home_view.ui:185 +#: podcasts-gtk/resources/gtk/home_view.ui:189 msgid "Older" msgstr "Ouder" @@ -249,7 +293,6 @@ msgid "0.90×" msgstr "0.90×" #: podcasts-gtk/resources/gtk/player_rate.ui:95 -#| msgid "1.75×" msgid "0.75×" msgstr "0.75×" @@ -297,60 +340,60 @@ msgstr "Opzeggen" msgid "Read More" msgstr "Lees meer" -#: podcasts-gtk/src/app.rs:299 +#: podcasts-gtk/src/app.rs:353 msgid "Fetching new episodes" msgstr "Nieuwe afleveringen worden opgehaald" -#: podcasts-gtk/src/stacks/content.rs:53 +#: podcasts-gtk/src/stacks/content.rs:58 msgid "New" msgstr "Nieuw" -#: podcasts-gtk/src/stacks/content.rs:54 +#: podcasts-gtk/src/stacks/content.rs:59 msgid "Shows" msgstr "Shows" -#: podcasts-gtk/src/utils.rs:472 +#: podcasts-gtk/src/utils.rs:501 msgid "Select the file from which to you want to import shows." msgstr "Selecteer het bestand waaruit u shows wilt importeren." -#: podcasts-gtk/src/utils.rs:475 +#: podcasts-gtk/src/utils.rs:504 msgid "_Import" msgstr "_Importeren" -#: podcasts-gtk/src/utils.rs:484 podcasts-gtk/src/utils.rs:533 +#: podcasts-gtk/src/utils.rs:513 podcasts-gtk/src/utils.rs:562 msgid "OPML file" msgstr "OPML-bestand" -#: podcasts-gtk/src/utils.rs:502 +#: podcasts-gtk/src/utils.rs:531 msgid "Failed to parse the imported file" msgstr "Verwerken van geïmporteerd bestand mislukt" -#: podcasts-gtk/src/utils.rs:507 podcasts-gtk/src/utils.rs:552 +#: podcasts-gtk/src/utils.rs:536 podcasts-gtk/src/utils.rs:581 msgid "Selected file could not be accessed." msgstr "Kon geen toegang verkrijgen tot geselecteerd bestand." -#: podcasts-gtk/src/utils.rs:518 +#: podcasts-gtk/src/utils.rs:547 msgid "Export shows to…" msgstr "Shows exporteren naar…" -#: podcasts-gtk/src/utils.rs:521 +#: podcasts-gtk/src/utils.rs:550 msgid "_Export" msgstr "_Exporteren" -#: podcasts-gtk/src/utils.rs:522 +#: podcasts-gtk/src/utils.rs:551 msgid "_Cancel" msgstr "_Annuleren" #. Translators: This is the string of the suggested name for the exported opml file -#: podcasts-gtk/src/utils.rs:526 +#: podcasts-gtk/src/utils.rs:555 msgid "gnome-podcasts-exported-shows" msgstr "gnome-podcasts-geëxporteerde-shows" -#: podcasts-gtk/src/utils.rs:546 +#: podcasts-gtk/src/utils.rs:575 msgid "GNOME Podcasts Subscriptions" msgstr "Gnome Podcasts-abonnementen" -#: podcasts-gtk/src/utils.rs:547 +#: podcasts-gtk/src/utils.rs:576 msgid "Failed to export podcasts" msgstr "Exporteren van podcasts mislukt" @@ -369,22 +412,29 @@ msgstr "" "\n" "Meer info over Gnome-NL https://nl.gnome.org/" -#: podcasts-gtk/src/widgets/episode.rs:144 +#: podcasts-gtk/src/widgets/episode.rs:145 msgid "{} min" msgstr "{} min" -#: podcasts-gtk/src/widgets/player.rs:818 +#: podcasts-gtk/src/widgets/episode_description.rs:165 +msgid "Copied URL to clipboard!" +msgstr "URL gekopieerd naar klembord!" + +#: podcasts-gtk/src/widgets/player.rs:902 msgid "The media player was unable to execute an action." msgstr "De mediaspeler kon een handeling niet uitvoeren." -#: podcasts-gtk/src/widgets/show_menu.rs:198 +#: podcasts-gtk/src/widgets/show_menu.rs:194 msgid "Marked all episodes as listened" msgstr "Alle afleveringen markeren als beluisterd" -#: podcasts-gtk/src/widgets/show_menu.rs:203 +#: podcasts-gtk/src/widgets/show_menu.rs:199 msgid "Unsubscribed from {}" msgstr "Abonnement op {} opgezegd" +#~ msgid "Podcast app for GNOME" +#~ msgstr "Podcast-toepassing voor Gnome" + #~ msgid "Double speed rate" #~ msgstr "Dubbele snelheid" -- 2.40.1 From d32b6f5591ae0d59917f99f642ea345614b7f19b Mon Sep 17 00:00:00 2001 From: Jordan Petridis Date: Wed, 6 Apr 2022 19:50:54 +0300 Subject: [PATCH 022/102] ci: remove the rusftm hack Our config.rs is generated by meson and thus we were creating a dummy file to avoid failing to import it. Instead we can skip the file in main.rs --- .gitlab-ci.yml | 3 --- podcasts-gtk/src/main.rs | 1 + 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 6677518..091947c 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -21,9 +21,6 @@ rustfmt: stage: ".pre" script: - rustup component add rustfmt - # Create blank versions of our configured files - # so rustfmt does not yell about non-existent files or completely empty files - - echo -e "" >> podcasts-gtk/src/config.rs - rustc -Vv && cargo -Vv - cargo fmt --version - cargo fmt --all -- --color=always --check diff --git a/podcasts-gtk/src/main.rs b/podcasts-gtk/src/main.rs index 9beac4b..da3300d 100644 --- a/podcasts-gtk/src/main.rs +++ b/podcasts-gtk/src/main.rs @@ -58,6 +58,7 @@ mod stacks; mod widgets; mod app; +#[rustfmt::skip] mod config; mod headerbar; mod window; -- 2.40.1 From fadc8648d14ed9c776bf590114c42cad3e6609f6 Mon Sep 17 00:00:00 2001 From: Jordan Petridis Date: Wed, 6 Apr 2022 19:51:24 +0300 Subject: [PATCH 023/102] fmt: commit a rustfmt.toml that sets the edition --- rustfmt.toml | 1 + 1 file changed, 1 insertion(+) create mode 100644 rustfmt.toml diff --git a/rustfmt.toml b/rustfmt.toml new file mode 100644 index 0000000..3a26366 --- /dev/null +++ b/rustfmt.toml @@ -0,0 +1 @@ +edition = "2021" -- 2.40.1 From 7366ab431c50ecdd885435161b2eeac36b946f72 Mon Sep 17 00:00:00 2001 From: Alexandre Franke Date: Mon, 2 May 2022 17:15:54 +0000 Subject: [PATCH 024/102] Update French translation --- podcasts-gtk/po/fr.po | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/podcasts-gtk/po/fr.po b/podcasts-gtk/po/fr.po index d791dfb..341c35a 100644 --- a/podcasts-gtk/po/fr.po +++ b/podcasts-gtk/po/fr.po @@ -6,21 +6,27 @@ # Thibault Martin , 2020. # Sylvestris , 2020. # Charles Monzat , 2022. +# mathieu , 2022. # msgid "" msgstr "" "Project-Id-Version: podcasts master\n" "Report-Msgid-Bugs-To: https://gitlab.gnome.org/World/podcasts/issues\n" -"POT-Creation-Date: 2021-11-28 07:07+0000\n" -"PO-Revision-Date: 2022-01-24 20:39+0100\n" -"Last-Translator: Charles Monzat \n" -"Language-Team: GNOME French Team \n" +"POT-Creation-Date: 2022-01-25 07:24+0000\n" +"PO-Revision-Date: 2022-05-02 18:29+0200\n" +"Last-Translator: mathieu \n" +"Language-Team: French \n" "Language: fr\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=2; plural=(n > 1);\n" -"X-Generator: Gtranslator 40.0\n" +"Plural-Forms: nplurals=2; plural=(n > 1)\n" +"X-Generator: Gtranslator 42.0\n" +"X-DL-Team: fr\n" +"X-DL-Module: podcasts\n" +"X-DL-Branch: master\n" +"X-DL-Domain: po\n" +"X-DL-State: Translating\n" #: podcasts-gtk/resources/org.gnome.Podcasts.gschema.xml.in:15 msgid "Top position of the last open main window" @@ -88,7 +94,6 @@ msgid "Podcast;RSS;" msgstr "Podcast;RSS;Baladodiffusion;Émissions;" #: podcasts-gtk/resources/org.gnome.Podcasts.appdata.xml.in.in:8 -#| msgid "Listen to your favorite podcasts, right from your desktop." msgid "Listen to your favorite shows" msgstr "Écouter vos émissions favorites" @@ -107,11 +112,11 @@ msgstr "" "abonnements d’autres applications peuvent être importés via des fichiers " "OPML." -#: podcasts-gtk/resources/org.gnome.Podcasts.appdata.xml.in.in:117 +#: podcasts-gtk/resources/org.gnome.Podcasts.appdata.xml.in.in:134 msgid "Jordan Petridis" msgstr "Jordan Petridis" -#: podcasts-gtk/resources/org.gnome.Podcasts.appdata.xml.in.in:118 +#: podcasts-gtk/resources/org.gnome.Podcasts.appdata.xml.in.in:135 msgid "Julian Hofer" msgstr "Julian Hofer" @@ -145,7 +150,6 @@ msgid "Back" msgstr "Retour" #: podcasts-gtk/resources/gtk/episode_description.ui:148 -#| msgid "Podcasts" msgid "Podcast Title" msgstr "Titre du podcast" @@ -158,7 +162,6 @@ msgid "Episode Description" msgstr "Description de l’épisode" #: podcasts-gtk/resources/gtk/episode_menu.ui:36 -#| msgid "_Import Shows" msgid "Go to Show" msgstr "Aller à l’émission" @@ -279,7 +282,6 @@ msgid "1.00×" msgstr "1,00×" #: podcasts-gtk/resources/gtk/player_rate.ui:65 -#| msgid "1.00×" msgid "2.00×" msgstr "2,00×" @@ -349,7 +351,7 @@ msgstr "En savoir plus" #: podcasts-gtk/src/app.rs:353 msgid "Fetching new episodes" -msgstr "Récupérer les nouveaux épisodes" +msgstr "Récupération des nouveaux épisodes" #: podcasts-gtk/src/stacks/content.rs:58 msgid "New" @@ -427,7 +429,7 @@ msgstr "{} min" msgid "Copied URL to clipboard!" msgstr "URL copiée dans le presse-papiers !" -#: podcasts-gtk/src/widgets/player.rs:902 +#: podcasts-gtk/src/widgets/player.rs:910 msgid "The media player was unable to execute an action." msgstr "Le lecteur n’a pas pu réaliser l’action." -- 2.40.1 From c3c77254cceabc0a417d157c5ee5aa55f24007b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BCrgen=20Benvenuti?= Date: Wed, 25 May 2022 20:20:21 +0000 Subject: [PATCH 025/102] Update German translation --- podcasts-gtk/po/de.po | 39 ++++++++++++++++++++++++++++----------- 1 file changed, 28 insertions(+), 11 deletions(-) diff --git a/podcasts-gtk/po/de.po b/podcasts-gtk/po/de.po index 0481d85..b4a780a 100644 --- a/podcasts-gtk/po/de.po +++ b/podcasts-gtk/po/de.po @@ -9,16 +9,16 @@ msgid "" msgstr "" "Project-Id-Version: podcasts master\n" "Report-Msgid-Bugs-To: https://gitlab.gnome.org/World/podcasts/issues\n" -"POT-Creation-Date: 2021-09-14 16:55+0000\n" -"PO-Revision-Date: 2021-09-20 01:04+0200\n" -"Last-Translator: Philipp Kiemle \n" +"POT-Creation-Date: 2022-05-02 17:16+0000\n" +"PO-Revision-Date: 2022-05-24 23:02+0200\n" +"Last-Translator: Jürgen Benvenuti \n" "Language-Team: Deutsch \n" "Language: de\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -"X-Generator: Poedit 3.0\n" +"X-Generator: Poedit 3.0.1\n" #: podcasts-gtk/resources/org.gnome.Podcasts.gschema.xml.in:15 msgid "Top position of the last open main window" @@ -78,7 +78,6 @@ msgid "Podcasts" msgstr "Podcasts" #: podcasts-gtk/resources/org.gnome.Podcasts.desktop.in.in:4 -#: podcasts-gtk/resources/org.gnome.Podcasts.appdata.xml.in.in:10 msgid "Listen to your favorite podcasts, right from your desktop." msgstr "Hören Sie Ihre Lieblings-Podcasts direkt in Ihrer Arbeitsumgebung." @@ -88,14 +87,30 @@ msgid "Podcast;RSS;" msgstr "Podcast;RSS;" #: podcasts-gtk/resources/org.gnome.Podcasts.appdata.xml.in.in:8 -msgid "Podcast app for GNOME" -msgstr "Podcast-Anwendung für GNOME" +msgid "Listen to your favorite shows" +msgstr "Hören Sie Ihre Lieblingssendungen" -#: podcasts-gtk/resources/org.gnome.Podcasts.appdata.xml.in.in:115 +# Ziemlich frei übersetzt, aber wenn ich "Play" hier mit "abspielen" oder "wiedergeben" übersetze, kommen mir das "ab" und "wieder" in die Quere. +#: podcasts-gtk/resources/org.gnome.Podcasts.appdata.xml.in.in:10 +msgid "" +"Play, update, and manage your podcasts from a lightweight interface that " +"seamlessly integrates with GNOME. Podcasts can play various audio formats " +"and remember where you stopped listening. You can subscribe to shows via RSS/" +"Atom, iTunes, and Soundcloud links. Subscriptions from other apps can be " +"imported via OPML files." +msgstr "" +"Hören, aktualisieren und verwalten Sie Ihre Podcasts aus einer " +"leichtgewichtigen Oberfläche, die sich nahtlos in die GNOME-Umgebung " +"einfügt. Podcasts kann verschiedene Audio-Formate abspielen und merkt sich, " +"wo Sie beim Zuhören gestoppt haben. Sie können Sendungen via RSS/Atom, " +"iTunes und Soundcloud-Verweisen abonnieren. Abonnements von anderen " +"Programmen können via OPML-Datei importiert werden." + +#: podcasts-gtk/resources/org.gnome.Podcasts.appdata.xml.in.in:134 msgid "Jordan Petridis" msgstr "Jordan Petridis" -#: podcasts-gtk/resources/org.gnome.Podcasts.appdata.xml.in.in:116 +#: podcasts-gtk/resources/org.gnome.Podcasts.appdata.xml.in.in:135 msgid "Julian Hofer" msgstr "Julian Hofer" @@ -263,7 +278,6 @@ msgid "1.00×" msgstr "1,00×" #: podcasts-gtk/resources/gtk/player_rate.ui:65 -#| msgid "1.00×" msgid "2.00×" msgstr "2.00×" @@ -412,7 +426,7 @@ msgstr "{} min" msgid "Copied URL to clipboard!" msgstr "Adresse in die Zwischenablage kopiert!" -#: podcasts-gtk/src/widgets/player.rs:902 +#: podcasts-gtk/src/widgets/player.rs:910 msgid "The media player was unable to execute an action." msgstr "Die Medienwiedergabe konnte eine Aktion nicht ausführen." @@ -424,6 +438,9 @@ msgstr "Alle Folgen als angehört markieren" msgid "Unsubscribed from {}" msgstr "Abonnement von {} gekündigt" +#~ msgid "Podcast app for GNOME" +#~ msgstr "Podcast-Anwendung für GNOME" + #~ msgid "Double speed rate" #~ msgstr "Doppelte Geschwindigkeit" -- 2.40.1 From f00c96e09e382c3b7cbc375f1454b5a9c194cc1f Mon Sep 17 00:00:00 2001 From: Christopher Davis Date: Sun, 18 Oct 2020 01:56:05 -0700 Subject: [PATCH 026/102] Port to GTK4 Co-authored-by: Maximiliano Sandoval R --- Cargo.lock | 269 +++++++++++------- README.md | 4 +- meson.build | 4 +- org.gnome.Podcasts.Devel.json | 1 + podcasts-gtk/Cargo.toml | 8 +- podcasts-gtk/resources/gtk/empty_view.ui | 71 ++--- .../resources/gtk/episode_description.ui | 128 +-------- podcasts-gtk/resources/gtk/episode_menu.ui | 1 - podcasts-gtk/resources/gtk/episode_widget.ui | 87 +----- podcasts-gtk/resources/gtk/headerbar.ui | 132 ++------- podcasts-gtk/resources/gtk/help-overlay.ui | 4 - podcasts-gtk/resources/gtk/home_episode.ui | 8 - podcasts-gtk/resources/gtk/home_view.ui | 39 +-- podcasts-gtk/resources/gtk/inapp_notif.ui | 25 +- podcasts-gtk/resources/gtk/player_dialog.ui | 98 +------ podcasts-gtk/resources/gtk/player_rate.ui | 28 +- podcasts-gtk/resources/gtk/player_toolbar.ui | 163 ++++------- podcasts-gtk/resources/gtk/show_menu.ui | 1 - podcasts-gtk/resources/gtk/show_widget.ui | 107 +++---- podcasts-gtk/resources/gtk/style.css | 2 +- .../org.gnome.Podcasts.gschema.xml.in | 8 - podcasts-gtk/src/app.rs | 62 ++-- podcasts-gtk/src/headerbar.rs | 32 +-- podcasts-gtk/src/main.rs | 16 +- podcasts-gtk/src/settings.rs | 29 +- podcasts-gtk/src/stacks/content.rs | 28 +- podcasts-gtk/src/stacks/home.rs | 12 +- podcasts-gtk/src/stacks/populated.rs | 23 +- podcasts-gtk/src/stacks/show.rs | 6 +- podcasts-gtk/src/utils.rs | 126 ++++---- podcasts-gtk/src/widgets/aboutdialog.rs | 40 ++- podcasts-gtk/src/widgets/appnotif.rs | 7 +- podcasts-gtk/src/widgets/base_view.rs | 13 +- podcasts-gtk/src/widgets/empty.rs | 7 +- podcasts-gtk/src/widgets/episode.rs | 28 +- .../src/widgets/episode_description.rs | 23 +- podcasts-gtk/src/widgets/episode_menu.rs | 4 +- podcasts-gtk/src/widgets/home_view.rs | 42 +-- podcasts-gtk/src/widgets/player.rs | 75 ++--- podcasts-gtk/src/widgets/show.rs | 27 +- podcasts-gtk/src/widgets/show_menu.rs | 49 ++-- podcasts-gtk/src/widgets/shows_view.rs | 38 +-- podcasts-gtk/src/window.rs | 47 ++- 43 files changed, 649 insertions(+), 1273 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0c91dab..8a79674 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -41,30 +41,6 @@ version = "1.0.52" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "84450d0b4a8bd1ba4144ce8ce718fbc5d071358b1e5384bace6536b3d1f2d5b3" -[[package]] -name = "atk" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a83b21d2aa75e464db56225e1bda2dd5993311ba1095acaa8fa03d1ae67026ba" -dependencies = [ - "atk-sys", - "bitflags", - "glib 0.14.8", - "libc", -] - -[[package]] -name = "atk-sys" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "badcf670157c84bb8b1cf6b5f70b650fed78da2033c9eed84c4e49b11cbe83ea" -dependencies = [ - "glib-sys 0.14.0", - "gobject-sys 0.14.0", - "libc", - "system-deps 3.2.0", -] - [[package]] name = "atom_syndication" version = "0.11.0" @@ -164,6 +140,15 @@ dependencies = [ "smallvec", ] +[[package]] +name = "cfg-expr" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edae0b9625d1fce32f7d64b71784d9b1bf8469ec1a9c417e44aaf16a9cbd7571" +dependencies = [ + "smallvec", +] + [[package]] name = "cfg-if" version = "1.0.0" @@ -638,22 +623,6 @@ dependencies = [ "slab", ] -[[package]] -name = "gdk" -version = "0.14.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9d749dcfc00d8de0d7c3a289e04a04293eb5ba3d8a4e64d64911d481fa9933b" -dependencies = [ - "bitflags", - "cairo-rs", - "gdk-pixbuf", - "gdk-sys", - "gio", - "glib 0.14.8", - "libc", - "pango", -] - [[package]] name = "gdk-pixbuf" version = "0.14.0" @@ -680,20 +649,36 @@ dependencies = [ ] [[package]] -name = "gdk-sys" -version = "0.14.0" +name = "gdk4" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e091b3d3d6696949ac3b3fb3c62090e5bfd7bd6850bef5c3c5ea701de1b1f1e" +checksum = "f97a162c17214d1bf981af3f683156a0b1667dd1927057c4f0a68513251ecf0f" +dependencies = [ + "bitflags", + "cairo-rs", + "gdk-pixbuf", + "gdk4-sys", + "gio", + "glib 0.14.8", + "libc", + "pango", +] + +[[package]] +name = "gdk4-sys" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9498f4e06969fb96a4e4234dfe1d308a3ac6b120b3c6d93e3ec5c77fe88bc6d5" dependencies = [ "cairo-sys-rs", "gdk-pixbuf-sys", "gio-sys", "glib-sys 0.14.0", "gobject-sys 0.14.0", + "graphene-sys", "libc", "pango-sys", - "pkg-config", - "system-deps 3.2.0", + "system-deps 5.0.0", ] [[package]] @@ -882,6 +867,61 @@ dependencies = [ "system-deps 3.2.0", ] +[[package]] +name = "graphene-rs" +version = "0.14.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3380f132530ef9eb9e0a2bac180e30390aa5e49892d20294f822a974117a563" +dependencies = [ + "glib 0.14.8", + "graphene-sys", + "libc", +] + +[[package]] +name = "graphene-sys" +version = "0.14.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a9ac7450b3aa80792513a3c029920a2ede419de13fb5169a4e51b07a5685332" +dependencies = [ + "glib-sys 0.14.0", + "libc", + "pkg-config", + "system-deps 3.2.0", +] + +[[package]] +name = "gsk4" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eff59ca46c4fc5087fd7a0c3770a71ea4b6e94f8c24c12e2c2e8538f9f6fd764" +dependencies = [ + "bitflags", + "cairo-rs", + "gdk4", + "glib 0.14.8", + "graphene-rs", + "gsk4-sys", + "libc", + "pango", +] + +[[package]] +name = "gsk4-sys" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13aa53ce70234da02f9954339d988d5ab853d746a8f47a4ae17735ff873545b5" +dependencies = [ + "cairo-sys-rs", + "gdk4-sys", + "glib-sys 0.14.0", + "gobject-sys 0.14.0", + "graphene-sys", + "libc", + "pango-sys", + "system-deps 5.0.0", +] + [[package]] name = "gstreamer" version = "0.17.4" @@ -1005,54 +1045,37 @@ dependencies = [ ] [[package]] -name = "gtk" -version = "0.14.3" +name = "gtk4" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2eb51122dd3317e9327ec1e4faa151d1fa0d95664cd8fb8dcfacf4d4d29ac70c" +checksum = "58a04f421d1485ba4739e723199f5828bca05ab4e622ed39a96a342b6b1a6a3d" dependencies = [ - "atk", "bitflags", "cairo-rs", "field-offset", "futures-channel", - "gdk", "gdk-pixbuf", + "gdk4", "gio", "glib 0.14.8", - "gtk-sys", - "gtk3-macros", + "graphene-rs", + "gsk4", + "gtk4-macros", + "gtk4-sys", "libc", "once_cell", "pango", - "pkg-config", -] - -[[package]] -name = "gtk-sys" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c14c8d3da0545785a7c5a120345b3abb534010fb8ae0f2ef3f47c027fba303e" -dependencies = [ - "atk-sys", - "cairo-sys-rs", - "gdk-pixbuf-sys", - "gdk-sys", - "gio-sys", - "glib-sys 0.14.0", - "gobject-sys 0.14.0", - "libc", - "pango-sys", - "system-deps 3.2.0", ] [[package]] -name = "gtk3-macros" -version = "0.14.0" +name = "gtk4-macros" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21de1da96dc117443fb03c2e270b2d34b7de98d0a79a19bbb689476173745b79" +checksum = "5068d4354af02454f44687adc613100aa98ae11e273cdcac84f89dc08be2b4a1" dependencies = [ "anyhow", "heck", + "itertools 0.10.3", "proc-macro-crate 1.1.0", "proc-macro-error", "proc-macro2", @@ -1060,6 +1083,25 @@ dependencies = [ "syn", ] +[[package]] +name = "gtk4-sys" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e20a64c8f0ddcff8902ff04c130747f2fb7834a43530f75d03d6c71335733b49" +dependencies = [ + "cairo-sys-rs", + "gdk-pixbuf-sys", + "gdk4-sys", + "gio-sys", + "glib-sys 0.14.0", + "gobject-sys 0.14.0", + "graphene-sys", + "gsk4-sys", + "libc", + "pango-sys", + "system-deps 5.0.0", +] + [[package]] name = "h2" version = "0.3.9" @@ -1302,56 +1344,52 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] -name = "libc" -version = "0.2.112" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b03d17f364a3a042d5e5d46b053bbbf82c92c9430c592dd4c064dc6ee997125" - -[[package]] -name = "libdbus-sys" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c185b5b7ad900923ef3a8ff594083d4d9b5aea80bb4f32b8342363138c0d456b" -dependencies = [ - "pkg-config", -] - -[[package]] -name = "libhandy" -version = "0.8.0" +name = "libadwaita" +version = "0.1.0-beta-1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bcf9c79ec810a62f442ffd568d2de233983dc91c160abee4949b67a647024ed" +checksum = "cef1e2d4b5490caff8a1d44648f68721ab917f765a7fa1d0226fcdac42d86552" dependencies = [ - "bitflags", - "gdk", "gdk-pixbuf", + "gdk4", "gio", "glib 0.14.8", - "gtk", - "lazy_static", + "gtk4", + "libadwaita-sys", "libc", - "libhandy-sys", + "once_cell", "pango", ] [[package]] -name = "libhandy-sys" -version = "0.8.0" +name = "libadwaita-sys" +version = "0.1.0-beta-1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1938b93a8f29417992c452b7f43e7eff8a9f8d25b7f0bc923ae9d75b50a9cde3" +checksum = "7a165d8c96824753ec072b70a9149790efa3d5abb07e130cda7eb04ef2006d4c" dependencies = [ - "gdk-pixbuf-sys", - "gdk-sys", + "gdk4-sys", "gio-sys", "glib-sys 0.14.0", "gobject-sys 0.14.0", - "gtk-sys", + "gtk4-sys", "libc", - "pango-sys", - "pkg-config", "system-deps 3.2.0", ] +[[package]] +name = "libc" +version = "0.2.112" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b03d17f364a3a042d5e5d46b053bbbf82c92c9430c592dd4c064dc6ee997125" + +[[package]] +name = "libdbus-sys" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c185b5b7ad900923ef3a8ff594083d4d9b5aea80bb4f32b8342363138c0d456b" +dependencies = [ + "pkg-config", +] + [[package]] name = "libsqlite3-sys" version = "0.22.2" @@ -1840,19 +1878,17 @@ dependencies = [ "chrono", "crossbeam-channel", "fragile", - "gdk", - "gdk-pixbuf", "gettext-rs", "gio", "glib 0.14.8", "gstreamer", "gstreamer-player", - "gtk", + "gtk4", "html2text", "html5ever", "humansize", "lazy_static", - "libhandy", + "libadwaita", "log", "markup5ever_rcdom", "mpris-player", @@ -2497,7 +2533,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "480c269f870722b3b08d2f13053ce0c2ab722839f472863c3e2d61ff3a1c2fa6" dependencies = [ "anyhow", - "cfg-expr", + "cfg-expr 0.8.1", "heck", "itertools 0.10.3", "pkg-config", @@ -2508,6 +2544,19 @@ dependencies = [ "version-compare 0.0.11", ] +[[package]] +name = "system-deps" +version = "5.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18db855554db7bd0e73e06cf7ba3df39f97812cb11d3f75e71c39bf45171797e" +dependencies = [ + "cfg-expr 0.9.0", + "heck", + "pkg-config", + "toml", + "version-compare 0.0.11", +] + [[package]] name = "tempdir" version = "0.3.7" diff --git a/README.md b/README.md index d1336b9..59257d6 100644 --- a/README.md +++ b/README.md @@ -72,9 +72,9 @@ sudo ninja -C build install #### Dependencies * Rust stable 1.34 or later along with cargo. -* Gtk+ 3.24.11 or later +* Gtk 4.0.0 or later * Gstreamer 1.16 or later -* libhandy 0.0.11 or later +* libadwaita 1.0.0 or later * Meson * A network connection diff --git a/meson.build b/meson.build index c68518d..c7768dd 100644 --- a/meson.build +++ b/meson.build @@ -11,8 +11,8 @@ dependency('dbus-1') dependency('glib-2.0', version: '>= 2.56') dependency('gio-2.0', version: '>= 2.56') dependency('gdk-pixbuf-2.0') -dependency('gtk+-3.0', version: '>= 3.24.22') -dependency('libhandy-1', version: '>= 1.0.3') +dependency('gtk4', version: '>= 4.5.0') +dependency('libadwaita-1', version :'>=1.0.0') dependency('gstreamer-1.0', version: '>= 1.16') dependency('gstreamer-base-1.0', version: '>= 1.16') diff --git a/org.gnome.Podcasts.Devel.json b/org.gnome.Podcasts.Devel.json index 2a1af4c..c4d7b50 100644 --- a/org.gnome.Podcasts.Devel.json +++ b/org.gnome.Podcasts.Devel.json @@ -11,6 +11,7 @@ "nightly" ], "finish-args": [ + "--device=dri", "--share=network", "--share=ipc", "--socket=x11", diff --git a/podcasts-gtk/Cargo.toml b/podcasts-gtk/Cargo.toml index 6e6463c..df64822 100644 --- a/podcasts-gtk/Cargo.toml +++ b/podcasts-gtk/Cargo.toml @@ -7,8 +7,6 @@ edition = "2018" [dependencies] chrono = "0.4" crossbeam-channel = "0.5.1" -gdk = "0.14.0" -gdk-pixbuf = "0.14.0" gst = { version = "0.17.0", package = "gstreamer" } gst-player = { version = "0.17.0", package = "gstreamer-player" } humansize = "1.1" @@ -27,7 +25,7 @@ html5ever = "0.25" markup5ever_rcdom = "0.1" html2text = "0.2.1" glib = "0.14.2" -libhandy = "0.8.0" +adw = {package = "libadwaita", version = "0.1.0-beta"} [dependencies.gettext-rs] git = "https://github.com/danigm/gettext-rs" @@ -39,8 +37,8 @@ features = ["v2_50"] version = "0.14.0" [dependencies.gtk] -features = ["v3_24"] -version = "0.14.0" +package = "gtk4" +version = "0.3.0" [dependencies.mpris-player] # git = "https://gitlab.gnome.org/World/Rust/mpris-player.git" diff --git a/podcasts-gtk/resources/gtk/empty_view.ui b/podcasts-gtk/resources/gtk/empty_view.ui index b674180..3c12a28 100644 --- a/podcasts-gtk/resources/gtk/empty_view.ui +++ b/podcasts-gtk/resources/gtk/empty_view.ui @@ -24,36 +24,27 @@ Tobias Bernard --> - - True - False - center - center - True - True vertical - 12 + 6 + 6 + 6 + 6 - True - False This show does not have episodes yet - - - - + - True - False If you think this is an error, please consider writing a bug report. + + 0 + 0 + - - 0 - 0 - - True - False start Add new shows via feed URL + + 1 + 0 + - - 1 - 0 - - True - False open-menu-symbolic + + 0 + 1 + - - 0 - 1 - - True - False start Import shows from another device + + 1 + 1 + - - 1 - 1 - diff --git a/podcasts-gtk/resources/gtk/episode_description.ui b/podcasts-gtk/resources/gtk/episode_description.ui index 82340a1..bcefb81 100644 --- a/podcasts-gtk/resources/gtk/episode_description.ui +++ b/podcasts-gtk/resources/gtk/episode_description.ui @@ -24,8 +24,6 @@ Tobias Bernard --> - - @@ -33,19 +31,12 @@ Tobias Bernard 64 - True - False True vertical - - True - False - True + - True - False Episode Details - - False - True - 0 - - True - False Episode Title True word-char - False 1 0 - - True - True - 1 - - True - False Duration - Date 0 - - False - True - 2 - - - True - True - 1 - - - True - True - 1 - - - False - True - 0 - - True - True True - 0 never - True - False True - 0 - True - False start - 18 - 18 + 18 + 18 18 True Episode Description @@ -249,20 +153,10 @@ Tobias Bernard - - False - True - 2 - - - True - True - 1 - @@ -112,10 +95,8 @@ Tobias Bernard start - False - True + False · - False @@ -124,11 +105,9 @@ Tobias Bernard start - False - True + False 42 min True - False @@ -140,10 +119,8 @@ Tobias Bernard start - False - True + False · - False @@ -152,12 +129,10 @@ Tobias Bernard start - False - True + False 0 MB end True - False @@ -169,11 +144,9 @@ Tobias Bernard start - False - True + False / True - False @@ -182,12 +155,10 @@ Tobias Bernard start - False - True + False Calculating episode size… end True - False @@ -202,75 +173,43 @@ Tobias Bernard - True - False end 6 - True True - True + False Play this episode center center - - - True - False - media-playback-start-symbolic - - + media-playback-start-symbolic - True False Cancel the download process center center - - - True - False - media-playback-stop-symbolic - - + media-playback-stop-symbolic - - end - - True - True True Download this episode center center - True - - - True - False - document-save-symbolic - - + document-save-symbolic - - end - - False - True + False 6 6 6 diff --git a/podcasts-gtk/resources/gtk/headerbar.ui b/podcasts-gtk/resources/gtk/headerbar.ui index ec065ef..f2d01d2 100644 --- a/podcasts-gtk/resources/gtk/headerbar.ui +++ b/podcasts-gtk/resources/gtk/headerbar.ui @@ -24,30 +24,21 @@ Tobias Bernard --> - - False Add a new feed center - add_toggle - bottom - True - False center - 6 vertical 6 - True - False start False Enter feed address to add @@ -58,48 +49,41 @@ Tobias Bernard - True - False 6 - True - True 26 url - True - True True - - Add - True - False - True - False - - - + button - + + + Add + False + False + + + + - - True - False - start - center - True - - + spinner - + + + start + center + + + @@ -108,32 +92,22 @@ Tobias Bernard - - False - True + strict - True - False crossfade - - True - False + crossfade - - True - False + center wide - True - False Podcasts @@ -159,20 +129,11 @@ Tobias Bernard - True - True True Add a new feed center add_popover - - - True - False - list-add-symbolic - 1 - - + list-add-symbolic @@ -180,67 +141,36 @@ Tobias Bernard - True False - True + False Back center - - - True - False - go-previous-symbolic - 1 - - + go-previous-symbolic - + - True - True False center - - - True - False - open-menu-symbolic - 1 - - + open-menu-symbolic - - end - - + - True False - True + False center - - - True - False - view-more-symbolic - 1 - - + view-more-symbolic - - end - diff --git a/podcasts-gtk/resources/gtk/help-overlay.ui b/podcasts-gtk/resources/gtk/help-overlay.ui index 33c2749..2f4b2d0 100644 --- a/podcasts-gtk/resources/gtk/help-overlay.ui +++ b/podcasts-gtk/resources/gtk/help-overlay.ui @@ -6,21 +6,17 @@ shortcuts 12 - True General - True - True <primary>r Check for new episodes - True <primary>q Quit the application diff --git a/podcasts-gtk/resources/gtk/home_episode.ui b/podcasts-gtk/resources/gtk/home_episode.ui index cea6ba5..ad8f6c4 100644 --- a/podcasts-gtk/resources/gtk/home_episode.ui +++ b/podcasts-gtk/resources/gtk/home_episode.ui @@ -24,29 +24,21 @@ Tobias Bernard --> - - True - False center 6 6 - True - False 8 64 image-x-generic-symbolic - - - diff --git a/podcasts-gtk/resources/gtk/home_view.ui b/podcasts-gtk/resources/gtk/home_view.ui index 71ac76d..ab29733 100644 --- a/podcasts-gtk/resources/gtk/home_view.ui +++ b/podcasts-gtk/resources/gtk/home_view.ui @@ -24,15 +24,12 @@ Tobias Bernard --> - - True - False 6 6 32 @@ -42,15 +39,12 @@ Tobias Bernard 24 - False - True + False True vertical 6 - True - False start True Today @@ -62,8 +56,6 @@ Tobias Bernard - True - False True True none @@ -76,15 +68,12 @@ Tobias Bernard - False - True + False True vertical 6 - True - False start Yesterday @@ -95,8 +84,6 @@ Tobias Bernard - True - False True True none @@ -109,15 +96,12 @@ Tobias Bernard - False - True + False True vertical 6 - True - False start This Week @@ -128,8 +112,6 @@ Tobias Bernard - True - False True True none @@ -142,15 +124,12 @@ Tobias Bernard - False - True + False True vertical 6 - True - False start This Month @@ -161,8 +140,6 @@ Tobias Bernard - True - False True True none @@ -175,15 +152,12 @@ Tobias Bernard - False - True + False True vertical 6 - True - False start True Older @@ -195,9 +169,6 @@ Tobias Bernard - True - False - True True True none diff --git a/podcasts-gtk/resources/gtk/inapp_notif.ui b/podcasts-gtk/resources/gtk/inapp_notif.ui index c58c08a..36bd938 100644 --- a/podcasts-gtk/resources/gtk/inapp_notif.ui +++ b/podcasts-gtk/resources/gtk/inapp_notif.ui @@ -24,29 +24,21 @@ Tobias Bernard --> - - True - False center start - True - False center center 0 - none - True - False center center 3 @@ -54,14 +46,11 @@ Tobias Bernard 6 - False 150 - True - False center center 12 @@ -73,7 +62,6 @@ Tobias Bernard Undo - True True center center @@ -84,22 +72,13 @@ Tobias Bernard - True - True False True center center - none - - - True - False - window-close-symbolic - - + window-close-symbolic diff --git a/podcasts-gtk/resources/gtk/player_dialog.ui b/podcasts-gtk/resources/gtk/player_dialog.ui index 6f0479a..116f7e0 100644 --- a/podcasts-gtk/resources/gtk/player_dialog.ui +++ b/podcasts-gtk/resources/gtk/player_dialog.ui @@ -1,39 +1,28 @@ - - - - False - dialog True - - True - False - Now Playing + + False + + + Now Playing + + - True - - - True - go-previous-symbolic - - + go-previous-symbolic - + - False vertical 2 - True - False 6 6 6 @@ -45,8 +34,6 @@ center - True - False center True True @@ -57,12 +44,11 @@ 256 True True - 18 + 18 + 18 36 6 center - True - False gtk-missing-image @@ -70,15 +56,12 @@ - True 6 vertical 6 6 - True - False center Episode Title True @@ -90,8 +73,6 @@ - True - False center Show Title True @@ -105,14 +86,10 @@ - True - False 12 12 - True - False 5 1 @@ -126,8 +103,6 @@ - True - True False True True @@ -135,8 +110,6 @@ - True - False 5 @@ -151,26 +124,15 @@ - True - False center 12 - True - True 60 60 center 12 - - - True - False - skip-back-large-symbolic - 5 - - + skip-back-large-symbolic @@ -178,22 +140,12 @@ - True - True - True True 80 80 - - - True - False - media-playback-start-symbolic - 6 - - + media-playback-start-symbolic @@ -201,18 +153,9 @@ - True - True 80 80 - - - True - False - media-playback-pause-symbolic - 6 - - + media-playback-pause-symbolic @@ -222,21 +165,12 @@ - True - True True 60 60 center 12 - - - True - False - skip-forward-large-symbolic - 5 - - + skip-forward-large-symbolic @@ -248,8 +182,6 @@ - True - False 12 12 12 diff --git a/podcasts-gtk/resources/gtk/player_rate.ui b/podcasts-gtk/resources/gtk/player_rate.ui index ce8c151..9ddae1e 100644 --- a/podcasts-gtk/resources/gtk/player_rate.ui +++ b/podcasts-gtk/resources/gtk/player_rate.ui @@ -24,40 +24,14 @@ Tobias Bernard --> - - True - True True Change the playback speed center center up rate_menu - - - True - False - 6 - - - True - False - 1.00× - - - - - - - - True - False - pan-down-symbolic - - - - + 1.00×
diff --git a/podcasts-gtk/resources/gtk/player_toolbar.ui b/podcasts-gtk/resources/gtk/player_toolbar.ui index a7de73d..b0bf546 100644 --- a/podcasts-gtk/resources/gtk/player_toolbar.ui +++ b/podcasts-gtk/resources/gtk/player_toolbar.ui @@ -24,111 +24,67 @@ Tobias Bernard --> - - - True - False - skip-forward-symbolic - - - True - False - 1 - media-playback-pause-symbolic - 1 - - - True - False - 1 - media-playback-start-symbolic - 1 - - - True - False - skip-back-symbolic - - True - False - vertical - 0 - - True - - - - - - True + + center - - False - True - center + + True + crossfade + False - - True - crossfade + + vertical + center + + + - True 6 + 6 + 6 + 6 + 6 - True - False center 42 - True - True True Rewind 10 seconds - rewind - True + skip-back-symbolic 60 - True True Play - play_image - True + media-playback-start-symbolic 60 - True - True True Pause - pause_image - True + media-playback-pause-symbolic 42 - True - True True Fast forward 10 seconds - fast_forward - True + skip-forward-symbolic + + - - True - False + 6 + 6 + 6 + 6 + 6 - True - False center 34 image-x-generic-symbolic @@ -263,16 +210,12 @@ Tobias Bernard - True - False True - center center vertical + True - True - False start Show Title end @@ -284,8 +227,6 @@ Tobias Bernard - True - False start Episode Title end @@ -299,42 +240,34 @@ Tobias Bernard - True True end + center - True - - - True - media-playback-start-symbolic - - + media-playback-start-symbolic - True - - - True - media-playback-pause-symbolic - - + media-playback-pause-symbolic + + + + - + diff --git a/podcasts-gtk/resources/gtk/show_menu.ui b/podcasts-gtk/resources/gtk/show_menu.ui index b665b4f..0bd8d00 100644 --- a/podcasts-gtk/resources/gtk/show_menu.ui +++ b/podcasts-gtk/resources/gtk/show_menu.ui @@ -24,7 +24,6 @@ Tobias Bernard --> - diff --git a/podcasts-gtk/resources/gtk/show_widget.ui b/podcasts-gtk/resources/gtk/show_widget.ui index 5562155..aba5a89 100644 --- a/podcasts-gtk/resources/gtk/show_widget.ui +++ b/podcasts-gtk/resources/gtk/show_widget.ui @@ -24,15 +24,12 @@ Tobias Bernard --> - - True - False 32 32 True @@ -40,8 +37,6 @@ Tobias Bernard 6 - True - False vertical 6 6 @@ -50,80 +45,74 @@ Tobias Bernard 6 - True - False 256 image-x-generic-symbolic - - True + 600 - True - True False + False none True - 12 + 12 + 12 + 12 + 12 - - True - False - fill - vertical - - - True - False - center - center - True - center - True - word-char - end - 4 - - - - - True - False - 1 + + short + + + fill + vertical - - Read More - True - False - False + center - 12 + center + True + center + True + word-char + end + 4 + + + + + False + 1 + + + Read More + False + center + 12 + + - + - - short - - - True - False - center - center - True - center - True - word-char - - + full - + + + center + center + True + center + True + word-char + + + @@ -133,8 +122,6 @@ Tobias Bernard - True - False start none True diff --git a/podcasts-gtk/resources/gtk/style.css b/podcasts-gtk/resources/gtk/style.css index ab43121..9ca86aa 100644 --- a/podcasts-gtk/resources/gtk/style.css +++ b/podcasts-gtk/resources/gtk/style.css @@ -25,7 +25,7 @@ progressbar.playback-progress trough progress { } actionbar.player-small revealer box { - border-top: none + border-top: none; } popover modelbutton > box > label { diff --git a/podcasts-gtk/resources/org.gnome.Podcasts.gschema.xml.in b/podcasts-gtk/resources/org.gnome.Podcasts.gschema.xml.in index bd6ecc7..fc0fca1 100644 --- a/podcasts-gtk/resources/org.gnome.Podcasts.gschema.xml.in +++ b/podcasts-gtk/resources/org.gnome.Podcasts.gschema.xml.in @@ -10,14 +10,6 @@ - - -1 - Top position of the last open main window - - - -1 - Left position of the last open main window - 640 Height of the last open main window diff --git a/podcasts-gtk/src/app.rs b/podcasts-gtk/src/app.rs index 7b330b7..1526d26 100644 --- a/podcasts-gtk/src/app.rs +++ b/podcasts-gtk/src/app.rs @@ -21,11 +21,8 @@ use glib::clone; use glib::prelude::*; use glib::subclass::prelude::*; -use gio::subclass::prelude::ApplicationImplExt; -use gio::{self, prelude::*, ApplicationFlags}; - use gtk::prelude::*; -use libhandy::prelude::*; +use gtk::subclass::prelude::*; use gettextrs::{bindtextdomain, setlocale, textdomain, LocaleCategory}; @@ -82,13 +79,12 @@ impl ObjectSubclass for PdApplicationPrivate { impl ObjectImpl for PdApplicationPrivate {} -impl gio::subclass::prelude::ApplicationImpl for PdApplicationPrivate { +impl ApplicationImpl for PdApplicationPrivate { fn activate(&self, app: &PdApplication) { debug!("GtkApplication::activate"); if let Some(ref window) = *self.window.borrow() { // Ideally Gtk4/GtkBuilder make this irrelvent - window.show_all(); window.present(); info!("Window presented"); return; @@ -99,7 +95,6 @@ impl gio::subclass::prelude::ApplicationImpl for PdApplicationPrivate { let window = MainWindow::new(&app, &self.sender); window.setup_gactions(); - window.show_all(); window.present(); self.window.replace(Some(window)); @@ -128,7 +123,7 @@ impl gio::subclass::prelude::ApplicationImpl for PdApplicationPrivate { } } -impl gtk::subclass::application::GtkApplicationImpl for PdApplicationPrivate {} +impl GtkApplicationImpl for PdApplicationPrivate {} glib::wrapper! { pub struct PdApplication(ObjectSubclass) @extends gio::Application, gtk::Application; @@ -166,15 +161,11 @@ pub(crate) enum Action { impl PdApplication { pub(crate) fn new() -> Self { - let application = glib::Object::new::(&[ + glib::Object::new(&[ ("application-id", &Some(APP_ID)), - ("flags", &ApplicationFlags::empty()), + ("resource-base-path", &Some("/org/gnome/Podcasts")), ]) - .expect("Application initialization failed..."); - - application.set_resource_base_path(Some("/org/gnome/Podcasts")); - - application + .expect("Application initialization failed...") } fn setup_timed_callbacks(&self) { @@ -261,57 +252,50 @@ impl PdApplication { .ok(); } Action::ShowWidgetAnimated => { - window - .main_deck - .navigate(libhandy::NavigationDirection::Back); + window.main_deck.navigate(adw::NavigationDirection::Back); let shows = window.content.get_shows(); let pop = shows.borrow().populated(); - window - .content - .get_stack() - .set_visible_child_full("shows", gtk::StackTransitionType::SlideLeft); + window.content.get_stack().set_visible_child_name("shows"); pop.borrow_mut() .switch_visible(PopulatedState::Widget, gtk::StackTransitionType::SlideLeft); } Action::ShowShowsAnimated => { - window - .main_deck - .navigate(libhandy::NavigationDirection::Back); + window.main_deck.navigate(adw::NavigationDirection::Back); let shows = window.content.get_shows(); let pop = shows.borrow().populated(); pop.borrow_mut() .switch_visible(PopulatedState::View, gtk::StackTransitionType::SlideRight); } Action::MoveBackOnDeck => { - window - .main_deck - .navigate(libhandy::NavigationDirection::Back); + window.main_deck.navigate(adw::NavigationDirection::Back); window.headerbar.reveal_bottom_switcher(true); window.headerbar.update_bottom_switcher(); } Action::GoToEpisodeDescription(show, ep) => { window.clear_deck(); let description_widget = EpisodeDescription::new(ep, show, window.sender.clone()); - description_widget.container.set_widget_name("description"); - window.main_deck.add(&description_widget.container); + window.main_deck.append(&description_widget.container); window .main_deck - .navigate(libhandy::NavigationDirection::Forward); + .page(&description_widget.container) + .unwrap() + .set_name(Some("description")); + window.main_deck.navigate(adw::NavigationDirection::Forward); window.headerbar.reveal_bottom_switcher(false); } Action::HeaderBarShowTile(title) => window.headerbar.switch_to_back(&title), Action::HeaderBarNormal => window.headerbar.switch_to_normal(), Action::CopiedUrlNotification => { let notif = EpisodeDescription::copied_url_notif(); - notif.show(&window.overlay, &window.headerbar.container); + notif.show(&window.overlay); } Action::MarkAllPlayerNotification(pd) => { let notif = mark_all_notif(pd, &data.sender); - notif.show(&window.overlay, &window.headerbar.container); + notif.show(&window.overlay); } Action::RemoveShow(pd) => { let notif = remove_show_notif(pd, data.sender.clone()); - notif.show(&window.overlay, &window.headerbar.container); + notif.show(&window.overlay); } Action::ErrorNotification(err) => { error!("An error notification was triggered: {}", err); @@ -321,7 +305,7 @@ impl PdApplication { }; let undo_cb: Option = None; let notif = InAppNotification::new(&err, 6000, callback, undo_cb); - notif.show(&window.overlay, &window.headerbar.container); + notif.show(&window.overlay); } Action::UpdateFeed(source) => { if window.updating.get() { @@ -356,13 +340,8 @@ impl PdApplication { updater.set_close_state(State::Hidden); updater.set_spinner_state(SpinnerState::Active); - let old = window.updater.replace(Some(updater)); - if let Some(i) = old { - unsafe { i.destroy() } - } - if let Some(i) = window.updater.borrow().as_ref() { - i.show(&window.overlay, &window.headerbar.container) + i.show(&window.overlay) } } Action::InitEpisode(rowid) => { @@ -436,7 +415,6 @@ impl PdApplication { // Weird magic I copy-pasted that sets the Application Name in the Shell. glib::set_application_name(&i18n("Podcasts")); - glib::set_prgname(Some("gnome-podcasts")); gtk::Window::set_default_icon_name(APP_ID); let args: Vec = env::args().collect(); ApplicationExtManual::run_with_args(&application, &args); diff --git a/podcasts-gtk/src/headerbar.rs b/podcasts-gtk/src/headerbar.rs index 5eff276..ce9a94f 100644 --- a/podcasts-gtk/src/headerbar.rs +++ b/podcasts-gtk/src/headerbar.rs @@ -37,10 +37,10 @@ use crate::i18n::i18n; #[derive(Debug, Clone)] // TODO: Make a proper state machine for the headerbar states pub(crate) struct Header { - pub(crate) container: libhandy::HeaderBar, - pub(crate) switch: libhandy::ViewSwitcher, - pub(crate) bottom_switcher: libhandy::ViewSwitcherBar, - switch_squeezer: libhandy::Squeezer, + pub(crate) container: adw::HeaderBar, + pub(crate) switch: adw::ViewSwitcher, + pub(crate) bottom_switcher: adw::ViewSwitcherBar, + switch_squeezer: adw::Squeezer, back: gtk::Button, title_stack: gtk::Stack, show_title: gtk::Label, @@ -92,9 +92,10 @@ impl AddPopover { // FIXME: THIS ALSO SUCKS! fn on_add_clicked(&self, sender: &Sender) -> Result<()> { let url = self.entry.text(); - let sender2 = sender.clone(); - tokio::spawn(async move { add_podcast_from_url(url.to_string(), &sender2).await }); + tokio::spawn(clone!(@strong sender => async move { + add_podcast_from_url(url.to_string(), &sender).await; + })); self.container.hide(); Ok(()) @@ -153,19 +154,16 @@ impl AddPopover { icon_tooltip: Option<&str>, ) { let entry = &self.entry; - let icon_position = gtk::EntryIconPosition::Secondary; - entry.set_icon_from_icon_name(icon_position, icon_name); + entry.set_secondary_icon_name(icon_name); if let Some(icon_tooltip_text) = icon_tooltip { - entry.set_icon_tooltip_text(icon_position, Some(i18n(icon_tooltip_text).as_str())); + entry.set_secondary_icon_tooltip_text(Some(i18n(icon_tooltip_text).as_str())); } self.add.set_sensitive(sensitive); - let error_style_class = >k::STYLE_CLASS_ERROR; - let style_context = entry.style_context(); if error { - style_context.add_class(error_style_class); + entry.add_css_class("error"); } else { - style_context.remove_class(error_style_class); + entry.remove_css_class("error"); } } } @@ -176,10 +174,10 @@ impl Default for Header { let menus = gtk::Builder::from_resource("/org/gnome/Podcasts/gtk/hamburger.ui"); let header = builder.object("headerbar").unwrap(); - let switch: libhandy::ViewSwitcher = builder.object("switch").unwrap(); + let switch: adw::ViewSwitcher = builder.object("switch").unwrap(); let back = builder.object("back").unwrap(); let title_stack = builder.object("title_stack").unwrap(); - let switch_squeezer: libhandy::Squeezer = builder.object("switch_squeezer").unwrap(); + let switch_squeezer: adw::Squeezer = builder.object("switch_squeezer").unwrap(); let show_title = builder.object("show_title").unwrap(); // The hamburger menu @@ -202,7 +200,7 @@ impl Default for Header { }; // View switcher bar that goes at the bottom of the window - let switcher = libhandy::ViewSwitcherBar::new(); + let switcher = adw::ViewSwitcherBar::new(); switcher.set_reveal(false); Header { @@ -289,7 +287,7 @@ impl Header { } pub(crate) fn open_menu(&self) { - self.hamburger.clicked(); + self.hamburger.popup(); } pub(crate) fn set_secondary_menu(&self, menu: &gio::MenuModel) { diff --git a/podcasts-gtk/src/main.rs b/podcasts-gtk/src/main.rs index da3300d..8a4d367 100644 --- a/podcasts-gtk/src/main.rs +++ b/podcasts-gtk/src/main.rs @@ -18,7 +18,7 @@ // SPDX-License-Identifier: GPL-3.0-or-later // Enable lint group collections -#![warn(nonstandard_style, rust_2018_idioms, bad_style, unused)] +#![warn(nonstandard_style, rust_2018_idioms, bad_style)] // standalone lints #![warn( const_err, @@ -47,8 +47,6 @@ extern crate pretty_assertions; #[macro_use] extern crate html5ever; -use gtk::prelude::*; - // Exports the macros defined in utils to the namespace of the crate so they can be used // easily without import #[macro_use] @@ -82,7 +80,7 @@ fn init_gtk_tests() -> anyhow::Result<()> { gst::init()?; gtk::init()?; - libhandy::init(); + adw::init(); register_resources()?; Ok(()) } @@ -92,16 +90,16 @@ async fn main() { pretty_env_logger::init(); gst::init().expect("Error initializing gstreamer"); gtk::init().expect("Error initializing gtk."); - libhandy::init(); + adw::init(); register_resources().expect("Error registering resources"); // Add custom style let provider = gtk::CssProvider::new(); - gtk::CssProvider::load_from_resource(&provider, "/org/gnome/Podcasts/gtk/style.css"); - gtk::StyleContext::add_provider_for_screen( - &gdk::Screen::default().expect("Error initializing gtk css provider."), + provider.load_from_resource("/org/gnome/Podcasts/gtk/style.css"); + gtk::StyleContext::add_provider_for_display( + >k::gdk::Display::default().expect("Error initializing gtk css provider."), &provider, - 600, + gtk::STYLE_PROVIDER_PRIORITY_APPLICATION, ); PdApplication::run(); diff --git a/podcasts-gtk/src/settings.rs b/podcasts-gtk/src/settings.rs index 0c6e0fb..fff6a7c 100644 --- a/podcasts-gtk/src/settings.rs +++ b/podcasts-gtk/src/settings.rs @@ -19,32 +19,23 @@ use gio::{prelude::SettingsExt, Settings}; use gtk::prelude::GtkWindowExt; -use libhandy as hdy; - use chrono::prelude::*; use chrono::Duration; pub(crate) struct WindowGeometry { - left: i32, - top: i32, width: i32, height: i32, is_maximized: bool, } impl WindowGeometry { - pub(crate) fn from_window(window: &hdy::ApplicationWindow) -> WindowGeometry { - let position = window.position(); - let size = window.size(); - let left = position.0; - let top = position.1; + pub(crate) fn from_window(window: &adw::ApplicationWindow) -> WindowGeometry { + let size = window.default_size(); let width = size.0; let height = size.1; let is_maximized = window.is_maximized(); WindowGeometry { - left, - top, width, height, is_maximized, @@ -52,40 +43,28 @@ impl WindowGeometry { } pub(crate) fn from_settings(settings: &gio::Settings) -> WindowGeometry { - let top = settings.int("persist-window-geometry-top"); - let left = settings.int("persist-window-geometry-left"); let width = settings.int("persist-window-geometry-width"); let height = settings.int("persist-window-geometry-height"); let is_maximized = settings.boolean("persist-window-geometry-maximized"); WindowGeometry { - left, - top, width, height, is_maximized, } } - pub(crate) fn apply(&self, window: &hdy::ApplicationWindow) { + pub(crate) fn apply(&self, window: &adw::ApplicationWindow) { if self.width > 0 && self.height > 0 { - window.resize(self.width, self.height); + window.set_default_size(self.width, self.height); } if self.is_maximized { window.maximize(); - } else if self.top > 0 && self.left > 0 { - window.move_(self.left, self.top); } } pub(crate) fn write(&self, settings: &gio::Settings) { - settings - .set_int("persist-window-geometry-left", self.left) - .unwrap(); - settings - .set_int("persist-window-geometry-top", self.top) - .unwrap(); settings .set_int("persist-window-geometry-width", self.width) .unwrap(); diff --git a/podcasts-gtk/src/stacks/content.rs b/podcasts-gtk/src/stacks/content.rs index 5440f32..b6f22fd 100644 --- a/podcasts-gtk/src/stacks/content.rs +++ b/podcasts-gtk/src/stacks/content.rs @@ -39,7 +39,7 @@ pub(crate) enum State { #[derive(Debug, Clone)] pub(crate) struct Content { container: gtk::Box, - stack: gtk::Stack, + stack: adw::ViewStack, shows: Rc>, home: Rc>, sender: Sender, @@ -48,24 +48,22 @@ pub(crate) struct Content { impl Content { pub(crate) fn new(sender: &Sender) -> Result> { let container = gtk::Box::new(gtk::Orientation::Vertical, 0); - let stack = gtk::Stack::new(); + let stack = adw::ViewStack::new(); let home = Rc::new(RefCell::new(HomeStack::new(sender.clone())?)); let shows = Rc::new(RefCell::new(ShowStack::new(sender.clone()))); // container will hold the header bar and the content container.set_widget_name("content"); - container.pack_end(&stack, true, true, 0); - stack.add_titled(&home.borrow().get_stack(), "home", &i18n("New")); - stack.add_titled(&shows.borrow().get_stack(), "shows", &i18n("Shows")); - - stack.set_child_icon_name( - &home.borrow().get_stack(), - Some("document-open-recent-symbolic"), - ); - stack.set_child_icon_name( - &shows.borrow().get_stack(), - Some("audio-input-microphone-symbolic"), - ); + container.append(&stack); + let home_page = stack + .add_titled(&home.borrow().get_stack(), Some("home"), &i18n("New")) + .unwrap(); + let shows_page = stack + .add_titled(&shows.borrow().get_stack(), Some("shows"), &i18n("Shows")) + .unwrap(); + + home_page.set_icon_name(Some("document-open-recent-symbolic")); + shows_page.set_icon_name(Some("audio-input-microphone-symbolic")); let con = Content { container, @@ -120,7 +118,7 @@ impl Content { .ok(); } - pub(crate) fn get_stack(&self) -> gtk::Stack { + pub(crate) fn get_stack(&self) -> adw::ViewStack { self.stack.clone() } pub(crate) fn get_container(&self) -> gtk::Box { diff --git a/podcasts-gtk/src/stacks/home.rs b/podcasts-gtk/src/stacks/home.rs index 40b3d57..9de89c0 100644 --- a/podcasts-gtk/src/stacks/home.rs +++ b/podcasts-gtk/src/stacks/home.rs @@ -17,7 +17,6 @@ // // SPDX-License-Identifier: GPL-3.0-or-later -use gtk::prelude::*; use gtk::StackTransitionType; use anyhow::Result; @@ -46,8 +45,8 @@ impl HomeStack { let stack = gtk::Stack::new(); let state = State::Empty; - stack.add_named(episodes.view.container(), "home"); - stack.add_named(empty.deref(), "empty"); + stack.add_named(episodes.view.container(), Some("home")); + stack.add_named(empty.deref(), Some("empty")); let home = HomeStack { empty, @@ -76,7 +75,7 @@ impl HomeStack { // during this the previous view is removed, // and the visible child falls back to empty view. self.stack.remove(old); - self.stack.add_named(eps.view.container(), "home"); + self.stack.add_named(eps.view.container(), Some("home")); // Keep the previous state. let s = self.state; // Set the visible child back to the previous one to avoid @@ -86,11 +85,6 @@ impl HomeStack { // replace view in the struct too self.episodes = eps; - // This might not be needed - unsafe { - old.destroy(); - } - Ok(()) } diff --git a/podcasts-gtk/src/stacks/populated.rs b/podcasts-gtk/src/stacks/populated.rs index 23d2a70..68ba768 100644 --- a/podcasts-gtk/src/stacks/populated.rs +++ b/podcasts-gtk/src/stacks/populated.rs @@ -56,10 +56,9 @@ impl PopulatedStack { let show = Rc::new(ShowWidget::default()); let container = gtk::Box::new(gtk::Orientation::Horizontal, 0); - stack.add_named(populated.view.container(), "shows"); - stack.add_named(show.view.container(), "widget"); - container.add(&stack); - container.show_all(); + stack.add_named(populated.view.container(), Some("shows")); + stack.add_named(show.view.container(), Some("widget")); + container.append(&stack); PopulatedStack { container, @@ -96,12 +95,7 @@ impl PopulatedStack { self.populated = pop; self.stack.remove(old); self.stack - .add_named(self.populated.view.container(), "shows"); - - // This might not be needed - unsafe { - old.destroy(); - } + .add_named(self.populated.view.container(), Some("shows")); Ok(()) } @@ -120,7 +114,8 @@ impl PopulatedStack { self.show = new; self.stack.remove(&old); - self.stack.add_named(self.show.view.container(), "widget"); + self.stack + .add_named(self.show.view.container(), Some("widget")); // The current visible child might change depending on // removal and insertion in the gtk::Stack, so we have @@ -132,7 +127,6 @@ impl PopulatedStack { } pub(crate) fn update_widget(&mut self) -> Result<()> { - let old = self.show.view.container().clone(); let id = self.show.show_id(); if id.is_none() { return Ok(()); @@ -147,11 +141,6 @@ impl PopulatedStack { let s = self.state; self.switch_visible(s, StackTransitionType::Crossfade); - // This might not be needed - unsafe { - old.destroy(); - } - Ok(()) } diff --git a/podcasts-gtk/src/stacks/show.rs b/podcasts-gtk/src/stacks/show.rs index 7e5ede5..a5f3e27 100644 --- a/podcasts-gtk/src/stacks/show.rs +++ b/podcasts-gtk/src/stacks/show.rs @@ -17,8 +17,6 @@ // // SPDX-License-Identifier: GPL-3.0-or-later -use gtk::prelude::*; - use anyhow::Result; use glib::Sender; use podcasts_data::dbqueries::is_episodes_populated; @@ -49,8 +47,8 @@ impl ShowStack { let stack = gtk::Stack::new(); let state = State::Empty; - stack.add_named(&populated.borrow().container(), "populated"); - stack.add_named(empty.deref(), "empty"); + stack.add_named(&populated.borrow().container(), Some("populated")); + stack.add_named(empty.deref(), Some("empty")); let mut show = ShowStack { empty, diff --git a/podcasts-gtk/src/utils.rs b/podcasts-gtk/src/utils.rs index 17ce2e9..0c099c9 100644 --- a/podcasts-gtk/src/utils.rs +++ b/podcasts-gtk/src/utils.rs @@ -17,13 +17,13 @@ // // SPDX-License-Identifier: GPL-3.0-or-later -use gdk_pixbuf::Pixbuf; use gio::prelude::ActionMapExt; use glib::clone; +use glib::IsA; use glib::Sender; use glib::Variant; use glib::{self, object::WeakRef}; -use glib::{IsA, Object}; +use gtk::gdk_pixbuf::Pixbuf; use gtk::prelude::*; use gtk::Widget; @@ -130,15 +130,14 @@ where /// let list = gtk::ListBox::new(); /// lazy_load(widgets, list, |w| w, || {}); /// ``` -pub(crate) fn lazy_load( +pub(crate) fn lazy_load( data: T, - container: WeakRef, + container: WeakRef, mut constructor: F, callback: U, ) where T: IntoIterator + 'static, T::Item: 'static, - C: IsA + ContainerExt + 'static, F: FnMut(T::Item) -> W + 'static, W: IsA + WidgetExt, U: Fn() + 'static, @@ -150,7 +149,32 @@ pub(crate) fn lazy_load( }; let widget = constructor(x); - container.add(&widget); + container.append(&widget); + widget.show(); + }; + lazy_load_full(data, func, callback); +} + +pub(crate) fn lazy_load_flowbox( + data: T, + container: WeakRef, + mut constructor: F, + callback: U, +) where + T: IntoIterator + 'static, + T::Item: 'static, + F: FnMut(T::Item) -> W + 'static, + W: IsA + WidgetExt, + U: Fn() + 'static, +{ + let func = move |x| { + let container = match container.upgrade() { + Some(c) => c, + None => return, + }; + + let widget = constructor(x); + container.insert(&widget, -1); widget.show(); }; lazy_load_full(data, func, callback); @@ -186,7 +210,7 @@ where // https://blogs.gnome.org/jsparber/2018/04/29/animate-a-scrolledwindow/ #[allow(clippy::float_cmp)] pub(crate) fn smooth_scroll_to(view: >k::ScrolledWindow, target: >k::Adjustment) { - let adj = view.vadjustment(); + let adj = view.vadjustment().unwrap(); if let Some(clock) = view.frame_clock() { let duration = 200; let start = adj.value(); @@ -390,10 +414,7 @@ pub(crate) fn set_image_from_path(image: >k::Image, show_id: i32, size: u32) - } } Err(DownloadError::NoImageLocation) => { - image.set_from_icon_name( - Some("image-x-generic-symbolic"), - gtk::IconSize::__Unknown(s), - ); + image.set_from_icon_name(Some("image-x-generic-symbolic")); } _ => {} } @@ -505,9 +526,6 @@ pub(crate) fn on_import_clicked(window: >k::ApplicationWindow, sender: &Sender None, ); - // Do not show hidden(.thing) files - dialog.set_show_hidden(false); - // Set a filter to show only xml files let filter = FileFilter::new(); FileFilter::set_name(&filter, Some(i18n("OPML file").as_str())); @@ -516,27 +534,31 @@ pub(crate) fn on_import_clicked(window: >k::ApplicationWindow, sender: &Sender filter.add_mime_type("text/x-opml"); dialog.add_filter(&filter); - let resp = dialog.run(); - debug!("Dialog Response {}", resp); - if resp == ResponseType::Accept { - if let Some(filename) = dialog.filename() { - debug!("File selected: {:?}", filename); - - rayon::spawn(clone!(@strong sender => move || { - // Parse the file and import the feeds - if let Ok(sources) = opml::import_from_file(filename) { - // Refresh the successfully parsed feeds to index them - schedule_refresh(Some(sources), sender) - } else { - let text = i18n("Failed to parse the imported file"); - send!(sender, Action::ErrorNotification(text)); + dialog.connect_response(clone!(@strong sender, @strong dialog => move |_, resp| { + debug!("Dialog Response {}", resp); + dialog.destroy(); + if resp == ResponseType::Accept { + if let Some(file) = dialog.file() { + if let Some(path) = file.peek_path() { + rayon::spawn(clone!(@strong sender => move || { + // Parse the file and import the feeds + if let Ok(sources) = opml::import_from_file(path) { + // Refresh the successfully parsed feeds to index them + schedule_refresh(Some(sources), sender) + } else { + let text = i18n("Failed to parse the imported file"); + send!(sender, Action::ErrorNotification(text)); + } + })) } - })) - } else { - let text = i18n("Selected file could not be accessed."); - send!(sender, Action::ErrorNotification(text)) + } else { + let text = i18n("Selected file could not be accessed."); + send!(sender, Action::ErrorNotification(text)) + } } - } + })); + + dialog.show(); } pub(crate) fn on_export_clicked(window: >k::ApplicationWindow, sender: &Sender) { @@ -554,9 +576,6 @@ pub(crate) fn on_export_clicked(window: >k::ApplicationWindow, sender: &Sender // Translators: This is the string of the suggested name for the exported opml file dialog.set_current_name(&format!("{}.opml", i18n("gnome-podcasts-exported-shows"))); - // Do not show hidden(.thing) files - dialog.set_show_hidden(false); - // Set a filter to show only xml files let filter = FileFilter::new(); FileFilter::set_name(&filter, Some(i18n("OPML file").as_str())); @@ -565,23 +584,28 @@ pub(crate) fn on_export_clicked(window: >k::ApplicationWindow, sender: &Sender filter.add_mime_type("text/x-opml"); dialog.add_filter(&filter); - let resp = dialog.run(); - debug!("Dialog Response {}", resp); - if resp == ResponseType::Accept { - if let Some(filename) = dialog.filename() { - debug!("File selected: {:?}", filename); - - rayon::spawn(clone!(@strong sender => move || { - if opml::export_from_db(filename, i18n("GNOME Podcasts Subscriptions").as_str()).is_err() { - let text = i18n("Failed to export podcasts"); - send!(sender, Action::ErrorNotification(text)); + dialog.connect_response(clone!(@strong sender, @strong dialog => move |_, resp| { + debug!("Dialog Response {}", resp); + dialog.destroy(); + if resp == ResponseType::Accept { + if let Some(file) = dialog.file() { + if let Some(path) = file.peek_path() { + debug!("File selected: {:?}", path); + rayon::spawn(clone!(@strong sender => move || { + if opml::export_from_db(path, i18n("GNOME Podcasts Subscriptions").as_str()).is_err() { + let text = i18n("Failed to export podcasts"); + send!(sender, Action::ErrorNotification(text)); + } + })) } - })) - } else { - let text = i18n("Selected file could not be accessed."); - send!(sender, Action::ErrorNotification(text)); + } else { + let text = i18n("Selected file could not be accessed."); + send!(sender, Action::ErrorNotification(text)); + } } - } + })); + + dialog.show(); } #[cfg(test)] diff --git a/podcasts-gtk/src/widgets/aboutdialog.rs b/podcasts-gtk/src/widgets/aboutdialog.rs index 1e20b8c..fba52fe 100644 --- a/podcasts-gtk/src/widgets/aboutdialog.rs +++ b/podcasts-gtk/src/widgets/aboutdialog.rs @@ -18,7 +18,7 @@ // SPDX-License-Identifier: GPL-3.0-or-later use crate::config::{APP_ID, VERSION}; -use gtk::{prelude::*, AboutDialogBuilder}; +use gtk::prelude::*; use crate::i18n::i18n; @@ -43,31 +43,23 @@ pub(crate) fn about_dialog(window: >k::ApplicationWindow) { "Piotr Drąg", "Rowan Lewis", "Zander Brown", - ] - .iter() - .map(|name| name.to_string()) - .collect(); + ]; - let artists = ["Tobias Bernard", "Sam Hewitt"] - .iter() - .map(|name| name.to_string()) - .collect(); + let dialog = gtk::AboutDialog::new(); + dialog.set_logo_icon_name(Some(APP_ID)); + dialog.set_comments(Some(i18n("Podcast Client for the GNOME Desktop.").as_str())); + dialog.set_copyright(Some("© 2017, 2018 Jordan Petridis")); + dialog.set_license_type(gtk::License::Gpl30); + dialog.set_modal(true); + dialog.set_version(Some(VERSION)); + dialog.set_program_name(Some(&i18n("Podcasts"))); + dialog.set_website(Some("https://wiki.gnome.org/Apps/Podcasts")); + dialog.set_website_label(&i18n("Learn more about GNOME Podcasts")); + dialog.set_transient_for(Some(window)); - let dialog = AboutDialogBuilder::new() - .logo_icon_name(APP_ID) - .comments(i18n("Podcast Client for the GNOME Desktop.").as_str()) - .copyright("© 2017-2021 Jordan Petridis") - .license_type(gtk::License::Gpl30) - .modal(true) - .version(VERSION) - .program_name(&i18n("Podcasts")) - .website("https://gitlab.gnome.org/World/podcasts") - .website_label(i18n("Learn more about GNOME Podcasts").as_str()) - .transient_for(window) - .artists(artists) - .authors(authors) - .translator_credits(i18n("translator-credits").as_str()) - .build(); + dialog.set_artists(&["Tobias Bernard", "Sam Hewitt"]); + dialog.set_authors(&authors); + dialog.set_translator_credits(Some(i18n("translator-credits").as_str())); dialog.show(); } diff --git a/podcasts-gtk/src/widgets/appnotif.rs b/podcasts-gtk/src/widgets/appnotif.rs index afc7d3e..602b55f 100644 --- a/podcasts-gtk/src/widgets/appnotif.rs +++ b/podcasts-gtk/src/widgets/appnotif.rs @@ -139,8 +139,7 @@ impl InAppNotification { // the revealer should be attached to something that displays it. // Previously we where doing it in the constructor, which had the result // of the animation being skipped cause there was no parent widget to display it. - pub(crate) fn show(&self, overlay: >k::Overlay, headerbar: &libhandy::HeaderBar) { - self.revealer.set_margin_top(headerbar.preferred_height().1); + pub(crate) fn show(&self, overlay: >k::Overlay) { overlay.add_overlay(&self.revealer); // We need to display the notification after the widget is added to the overlay // so there will be a nice animation. @@ -173,8 +172,4 @@ impl InAppNotification { } } } - - pub(crate) unsafe fn destroy(self) { - self.revealer.destroy(); - } } diff --git a/podcasts-gtk/src/widgets/base_view.rs b/podcasts-gtk/src/widgets/base_view.rs index bbaac32..1c3a001 100644 --- a/podcasts-gtk/src/widgets/base_view.rs +++ b/podcasts-gtk/src/widgets/base_view.rs @@ -18,7 +18,7 @@ // SPDX-License-Identifier: GPL-3.0-or-later use crate::utils::smooth_scroll_to; -use gtk::{self, prelude::*, Adjustment, Orientation, PolicyType}; +use gtk::{prelude::*, Adjustment, Orientation, PolicyType}; #[derive(Debug, Clone)] pub(crate) struct BaseView { @@ -29,12 +29,11 @@ pub(crate) struct BaseView { impl Default for BaseView { fn default() -> Self { let container = gtk::Box::new(Orientation::Horizontal, 0); - let scrolled_window = gtk::ScrolledWindow::new(None::<&Adjustment>, None::<&Adjustment>); + let scrolled_window = gtk::ScrolledWindow::new(); scrolled_window.set_policy(PolicyType::Never, PolicyType::Automatic); container.set_size_request(360, -1); - container.add(&scrolled_window); - container.show_all(); + container.append(&scrolled_window); BaseView { container, @@ -52,8 +51,8 @@ impl BaseView { &self.scrolled_window } - pub(crate) fn add>(&self, widget: &T) { - self.scrolled_window.add(widget); + pub(crate) fn set_child>(&self, widget: &T) { + self.scrolled_window.set_child(Some(widget)); } pub(crate) fn set_adjustments( @@ -71,6 +70,6 @@ impl BaseView { } pub(crate) fn vadjustment(&self) -> Adjustment { - self.scrolled_window().vadjustment() + self.scrolled_window().vadjustment().unwrap() } } diff --git a/podcasts-gtk/src/widgets/empty.rs b/podcasts-gtk/src/widgets/empty.rs index 539dcb0..8d438d1 100644 --- a/podcasts-gtk/src/widgets/empty.rs +++ b/podcasts-gtk/src/widgets/empty.rs @@ -18,7 +18,7 @@ // SPDX-License-Identifier: GPL-3.0-or-later use crate::config::APP_ID; -use gtk::{self, prelude::*}; + use std::ops::Deref; #[derive(Clone, Debug)] @@ -36,10 +36,7 @@ impl Default for EmptyView { let builder = gtk::Builder::from_resource("/org/gnome/Podcasts/gtk/empty_view.ui"); let view: gtk::Box = builder.object("empty_view").unwrap(); let image: gtk::Image = builder.object("image").unwrap(); - image.set_from_icon_name( - Some(format!("{}-symbolic", APP_ID).as_str()), - gtk::IconSize::__Unknown(256), - ); + image.set_from_icon_name(Some(format!("{}-symbolic", APP_ID).as_str())); EmptyView(view) } } diff --git a/podcasts-gtk/src/widgets/episode.rs b/podcasts-gtk/src/widgets/episode.rs index d69a52c..0948de0 100644 --- a/podcasts-gtk/src/widgets/episode.rs +++ b/podcasts-gtk/src/widgets/episode.rs @@ -230,22 +230,11 @@ impl Default for EpisodeWidget { impl EpisodeWidget { pub(crate) fn new(episode: EpisodeWidgetModel, sender: &Sender) -> Rc { let widget = Rc::new(Self::default()); - let episode = RefCell::new(Some(episode)); let weak = Rc::downgrade(&widget); - widget - .container - .connect_draw(clone!(@strong sender => move |_, _| { - if let Some(ep) = episode.borrow_mut().take() { - if let Some(w) = weak.upgrade() { - w.info.init(&ep) - } - Self::determine_buttons_state(&weak, &ep, &sender) - .map_err(|err| error!("Error: {}", err)) - .ok(); - }; - - gtk::Inhibit(false) - })); + widget.info.init(&episode); + Self::determine_buttons_state(&weak, &episode, &sender) + .map_err(|err| error!("Error: {}", err)) + .ok(); // When the widget is attached to a parent, // since it's a rust struct and not a widget the @@ -258,9 +247,10 @@ impl EpisodeWidget { // // When the widget is detached from its parent view this // callback runs freeing the last reference we were holding. - let episode_widget = RefCell::new(Some(widget.clone())); - widget.container.connect_remove(move |_, _| { - episode_widget.borrow_mut().take(); + // FIXME This hack feels even worse for GTK4; Use subclassing for EpisodeWidget? + let foo = RefCell::new(Some(widget.clone())); + widget.container.connect_destroy(move |_| { + foo.borrow_mut().take(); }); widget @@ -459,8 +449,6 @@ impl EpisodeWidget { .buttons .download .connect_clicked(clone!(@strong weak, @strong sender => move |dl| { - // Make the button insensitive so it won't be pressed twice - dl.set_sensitive(false); if let Ok(ep) = dbqueries::get_episode_widget_from_rowid(id) { on_download_clicked(&ep, &sender) .and_then(|_| { diff --git a/podcasts-gtk/src/widgets/episode_description.rs b/podcasts-gtk/src/widgets/episode_description.rs index 783d798..7efca7b 100644 --- a/podcasts-gtk/src/widgets/episode_description.rs +++ b/podcasts-gtk/src/widgets/episode_description.rs @@ -17,7 +17,7 @@ // // SPDX-License-Identifier: GPL-3.0-or-later -use gtk::{self, prelude::*}; +use gtk::prelude::*; use glib::{clone, Sender}; use podcasts_data::{Episode, Show}; @@ -30,7 +30,6 @@ use crate::widgets::EpisodeMenu; use crate::episode_description_parser; use crate::i18n::i18n; use chrono::prelude::*; -use std::cell::Cell; use std::rc::Rc; use std::sync::Arc; @@ -138,23 +137,9 @@ impl EpisodeDescription { } fn set_cover(&self, show_id: i32) { - // The closure above is a regular `Fn` closure. - // which means we can't mutate stuff inside it easily, - // so Cell is used. - // - // `Option` along with the `.take()` method ensure - // that the function will only be run once, during the first execution. - let show_id = Cell::new(Some(show_id)); - - self.image.connect_draw(move |image, _| { - if let Some(id) = show_id.take() { - utils::set_image_from_path(image, id, 64) - .map_err(|err| error!("Failed to set a cover: {}", err)) - .ok(); - } - - gtk::Inhibit(false) - }); + utils::set_image_from_path(&self.image, show_id, 64) + .map_err(|err| error!("Failed to set a cover: {}", err)) + .ok(); } pub(crate) fn copied_url_notif() -> InAppNotification { diff --git a/podcasts-gtk/src/widgets/episode_menu.rs b/podcasts-gtk/src/widgets/episode_menu.rs index a4c500b..3cd3a26 100644 --- a/podcasts-gtk/src/widgets/episode_menu.rs +++ b/podcasts-gtk/src/widgets/episode_menu.rs @@ -97,8 +97,8 @@ impl EpisodeMenu { } fn copy_text(text: &str) -> Option<()> { - let display = gdk::Display::default()?; - let clipboard = gtk::Clipboard::default(&display)?; + let display = gtk::gdk::Display::default()?; + let clipboard = display.clipboard(); clipboard.set_text(text); Some(()) } diff --git a/podcasts-gtk/src/widgets/home_view.rs b/podcasts-gtk/src/widgets/home_view.rs index 3e61a03..2f452e1 100644 --- a/podcasts-gtk/src/widgets/home_view.rs +++ b/podcasts-gtk/src/widgets/home_view.rs @@ -20,12 +20,12 @@ use anyhow::Result; use chrono::prelude::*; -use gtk::{self, prelude::*, Adjustment}; +use gtk::{prelude::*, Adjustment}; use glib::clone; +use adw::Clamp; use glib::Sender; -use libhandy::Clamp; use podcasts_data::dbqueries; use podcasts_data::EpisodeWidgetModel; @@ -33,7 +33,6 @@ use crate::app::Action; use crate::utils::{self, lazy_load_full}; use crate::widgets::{BaseView, EpisodeWidget}; -use std::cell::Cell; use std::rc::Rc; #[derive(Debug, Clone)] @@ -81,8 +80,8 @@ impl Default for HomeView { clamp.show(); clamp.set_maximum_size(700); - clamp.add(&frame_parent); - view.add(&clamp); + clamp.set_child(Some(&frame_parent)); + view.set_child(&clamp); HomeView { view, @@ -130,20 +129,19 @@ impl HomeView { } }; - let callback = clone!(@weak home => move || { + let callback = clone!(@weak home => @default-return (), move || { if let Some(ref v) = vadj { home.view.set_adjustments(None, Some(v)) }; }); lazy_load_full(episodes, func, callback); - home.view.container().show_all(); Ok(home) } } fn add_to_box(widget: &HomeEpisode, listbox: >k::ListBox, box_: >k::Box) { - listbox.add(&widget.row); + listbox.append(&widget.row); box_.show(); } @@ -180,9 +178,9 @@ impl Default for HomeEpisode { let container: gtk::Box = builder.object("container").unwrap(); let image: gtk::Image = builder.object("cover").unwrap(); let ep = EpisodeWidget::default(); - container.pack_start(&ep.container, true, true, 0); + container.append(&ep.container); let row = gtk::ListBoxRow::new(); - row.add(&container); + row.set_child(Some(&container)); row.show(); HomeEpisode { @@ -203,7 +201,7 @@ impl HomeEpisode { let id = episode.rowid(); let ep = EpisodeWidget::new(episode, sender); let row = gtk::ListBoxRow::new(); - row.add(&container); + row.set_child(Some(&container)); row.set_action_name(Some("app.go-to-episode")); row.set_action_target_value(Some(&id.to_variant())); row.show(); @@ -221,26 +219,12 @@ impl HomeEpisode { fn init(&self, show_id: i32) { self.set_cover(show_id); - self.container.pack_start(&self.episode, true, true, 0); + self.container.append(&self.episode); } fn set_cover(&self, show_id: i32) { - // The closure above is a regular `Fn` closure. - // which means we can't mutate stuff inside it easily, - // so Cell is used. - // - // `Option` along with the `.take()` method ensure - // that the function will only be run once, during the first execution. - let show_id = Cell::new(Some(show_id)); - - self.image.connect_draw(move |image, _| { - if let Some(id) = show_id.take() { - utils::set_image_from_path(image, id, 64) - .map_err(|err| error!("Failed to set a cover: {}", err)) - .ok(); - } - - gtk::Inhibit(false) - }); + utils::set_image_from_path(&self.image, show_id, 64) + .map_err(|err| error!("Failed to set a cover: {}", err)) + .ok(); } } diff --git a/podcasts-gtk/src/widgets/player.rs b/podcasts-gtk/src/widgets/player.rs index 423680c..e0ee37c 100644 --- a/podcasts-gtk/src/widgets/player.rs +++ b/podcasts-gtk/src/widgets/player.rs @@ -21,8 +21,6 @@ use gst::ClockTime; use gtk::prelude::*; -use libhandy as hdy; - use gio::File; use glib::clone; use glib::{SignalHandlerId, WeakRef}; @@ -92,10 +90,6 @@ impl PlayerInfo { .bind_property("label", &self.episode_small, "label") .flags(glib::BindingFlags::SYNC_CREATE) .build(); - self.cover - .bind_property("pixbuf", &self.cover_small, "pixbuf") - .flags(glib::BindingFlags::SYNC_CREATE) - .build(); } // FIXME: create a Diesel Model of the joined episode and podcast query instead @@ -139,6 +133,9 @@ impl PlayerInfo { set_image_from_path(&self.cover, show.id(), 34) .map_err(|err| error!("Player Cover: {}", err)) .ok(); + set_image_from_path(&self.cover_small, show.id(), 34) + .map_err(|err| error!("Player Cover: {}", err)) + .ok(); } } @@ -220,7 +217,6 @@ fn format_duration(seconds: u32) -> String { struct PlayerRate { action: gio::SimpleAction, btn: gtk::MenuButton, - label: gtk::Label, } impl PlayerRate { @@ -232,9 +228,8 @@ impl PlayerRate { let action = gio::SimpleAction::new_stateful("set", Some(&variant_type), &"1.00".to_variant()); let btn: gtk::MenuButton = builder.object("rate_button").unwrap(); - let label = builder.object("rate_label").unwrap(); - PlayerRate { action, label, btn } + PlayerRate { action, btn } } fn connect_signals(&self, widget: &Rc>) { @@ -280,7 +275,7 @@ struct PlayerControls { struct PlayerDialog { dialog: gtk::Dialog, close: gtk::Button, - headerbar: hdy::HeaderBar, + headerbar: gtk::HeaderBar, cover: gtk::Image, play_pause: gtk::Stack, play: gtk::Button, @@ -315,7 +310,7 @@ impl PlayerDialog { let show = builder.object("show_label").unwrap(); let episode = builder.object("episode_label").unwrap(); - bottom.pack_start(&rate.btn, false, true, 0); + bottom.prepend(&rate.btn); PlayerDialog { dialog, @@ -349,13 +344,13 @@ impl PlayerDialog { #[derive(Debug, Clone)] pub(crate) struct PlayerWidget { pub(crate) container: gtk::Box, - action_bar: gtk::ActionBar, - evbox: gtk::EventBox, + revealer: gtk::Revealer, + gesture_click: gtk::GestureClick, player: gst_player::Player, controls: PlayerControls, dialog: PlayerDialog, full: gtk::Box, - squeezer: hdy::Squeezer, + squeezer: adw::Squeezer, timer: PlayerTimes, info: PlayerInfo, rate: PlayerRate, @@ -459,19 +454,19 @@ impl Default for PlayerWidget { let dialog = PlayerDialog::new(dialog_rate); let container = builder.object("container").unwrap(); - let action_bar: gtk::ActionBar = builder.object("action_bar").unwrap(); - let evbox = builder.object("evbox").unwrap(); + let revealer: gtk::Revealer = builder.object("revealer").unwrap(); + let gesture_click = builder.object("gesture_click").unwrap(); let full: gtk::Box = builder.object("full").unwrap(); let squeezer = builder.object("squeezer").unwrap(); let rate = PlayerRate::new(); - full.pack_end(&rate.btn, false, true, 0); + full.append(&rate.btn); PlayerWidget { player, container, - action_bar, - evbox, + revealer, + gesture_click, controls, dialog, full, @@ -487,12 +482,12 @@ impl Default for PlayerWidget { impl PlayerWidget { fn on_rate_changed(&self, rate: f64) { self.set_playback_rate(rate); - self.rate.label.set_text(&format!("{:.2}×", rate)); - self.dialog.rate.label.set_text(&format!("{:.2}×", rate)); + self.rate.btn.set_label(&format!("{:.2}×", rate)); + self.dialog.rate.btn.set_label(&format!("{:.2}×", rate)); } fn reveal(&self) { - self.action_bar.show(); + self.revealer.set_reveal_child(true); } pub(crate) fn initialize_episode(&mut self, rowid: i32) -> Result<()> { @@ -749,11 +744,10 @@ impl PlayerWrapper { let widget = this.borrow(); if let Some(child) = widget.squeezer.visible_child() { let full = child == this.borrow().full; - this.borrow().timer.progress_bar.set_visible(!full); if full { - this.borrow().action_bar.style_context().remove_class("player-small"); + this.borrow().revealer.remove_css_class("player-small"); } else { - this.borrow().action_bar.style_context().add_class("player-small"); + this.borrow().revealer.add_css_class("player-small"); } } })); @@ -775,32 +769,19 @@ impl PlayerWrapper { .slider .set_adjustment(&widget.timer.slider.adjustment()); - widget.evbox.connect_button_press_event( - clone!(@weak this => @default-return Inhibit(false), move |_, event| { - let widget = this.borrow(); - if event.button() != 1 { - return Inhibit(false); - } - // only open the dialog when the small toolbar is visible - if let Some(child) = widget.squeezer.visible_child() { - if child == widget.full { - return Inhibit(false); - } - } + widget + .gesture_click + .connect_released(clone!(@weak this => move |_, _, _, _| { + let this = this.borrow(); - let parent = widget.container.toplevel().and_then(|toplevel| { - toplevel - .downcast::() - .ok() + let parent = this.container.root().and_then(|root| { + root.downcast::().ok() }).unwrap(); info!("showing dialog"); - widget.dialog.dialog.set_transient_for(Some(&parent)); - widget.dialog.dialog.show(); - - Inhibit(false) - }), - ); + this.dialog.dialog.set_transient_for(Some(&parent)); + this.dialog.dialog.show(); + })); widget .dialog diff --git a/podcasts-gtk/src/widgets/show.rs b/podcasts-gtk/src/widgets/show.rs index 70eb2c7..c958eca 100644 --- a/podcasts-gtk/src/widgets/show.rs +++ b/podcasts-gtk/src/widgets/show.rs @@ -19,12 +19,12 @@ use glib::clone; use glib::Sender; -use gtk::{self, prelude::*, Adjustment}; +use gtk::{prelude::*, Adjustment}; +use adw::Clamp; use anyhow::Result; use crossbeam_channel::bounded; use fragile::Fragile; -use libhandy::Clamp; use podcasts_data::dbqueries; use podcasts_data::EpisodeWidgetModel; @@ -67,9 +67,8 @@ impl Default for ShowWidget { let clamp = Clamp::new(); clamp.set_maximum_size(700); - clamp.add(&sub_cont); - view.add(&clamp); - clamp.show_all(); + clamp.set_child(Some(&sub_cont)); + view.set_child(&clamp); ShowWidget { view, @@ -101,10 +100,7 @@ impl ShowWidget { let res = populate_listbox(&pdw, pd, sender, vadj); debug_assert!(res.is_ok()); - pdw.description_short - .connect_size_allocate(clone!(@weak pdw => move |_, _2| { - pdw.update_read_more(); - })); + pdw.update_read_more(); pdw.description_button .connect_clicked(clone!(@weak pdw => move |_| { @@ -128,11 +124,10 @@ impl ShowWidget { } fn update_read_more(&self) { - if let Some(layout) = self.description_short.layout() { - let more = layout.is_ellipsized() - || self.description.label() != self.description_short.label(); - self.description_button_revealer.set_reveal_child(more); - } + let layout = self.description_short.layout(); + let more = + layout.is_ellipsized() || self.description.label() != self.description_short.label(); + self.description_button_revealer.set_reveal_child(more); } /// Set the description text. @@ -181,7 +176,7 @@ fn populate_listbox( if count == 0 { let empty = EmptyShow::default(); - show.episodes.add(empty.deref()); + show.episodes.append(empty.deref()); return Ok(()); } @@ -200,7 +195,7 @@ fn populate_listbox( let id = ep.rowid(); let episode_widget = EpisodeWidget::new(ep, &sender).container.clone(); let row = gtk::ListBoxRow::new(); - row.add(&episode_widget); + row.set_child(Some(&episode_widget)); row.set_action_name(Some("app.go-to-episode")); row.set_action_target_value(Some(&id.to_variant())); row diff --git a/podcasts-gtk/src/widgets/show_menu.rs b/podcasts-gtk/src/widgets/show_menu.rs index 488f932..1a33f14 100644 --- a/podcasts-gtk/src/widgets/show_menu.rs +++ b/podcasts-gtk/src/widgets/show_menu.rs @@ -133,40 +133,29 @@ impl ShowMenu { // But now I can't think of a better way to do it than hardcoding the title // position relative to the EpisodeWidget container gtk::Box. fn dim_titles(episodes: >k::ListBox) -> Option<()> { - let children = episodes.children(); - - for row in children { - let row = row.downcast::().ok()?; - let container = row.children().remove(0).downcast::().ok()?; - let first_children_box = container.children().remove(0).downcast::().ok()?; - let second_children_box = first_children_box - .children() - .remove(0) - .downcast::() - .ok()?; - let third_children_box = second_children_box - .children() - .remove(0) - .downcast::() - .ok()?; - let title = third_children_box - .children() - .remove(0) - .downcast::() - .ok()?; - - title.style_context().add_class("dim-label"); - - let checkmark = third_children_box - .children() - .remove(1) - .downcast::() - .ok()?; - checkmark.show(); + let listmodel = episodes.observe_children(); + for i in 0..listmodel.n_items() { + let obj = listmodel.item(i)?; + let row = obj.downcast_ref::()?; + dim_row_title(&row)?; } Some(()) } +fn dim_row_title(row: >k::ListBoxRow) -> Option<()> { + let container = row.first_child()?.downcast::().ok()?; + let foo = container.first_child()?.downcast::().ok()?; + let bar = foo.first_child()?.downcast::().ok()?; + let baz = bar.first_child()?.downcast::().ok()?; + let title = baz.first_child()?.downcast::().ok()?; + + title.add_css_class("dim-label"); + + let checkmark = title.next_sibling()?.downcast::().ok()?; + checkmark.show(); + Some(()) +} + fn mark_all_watched(pd: &Show, sender: &Sender) -> Result<()> { // TODO: If this fails for whatever reason, it should be impossible, show an error dbqueries::update_none_to_played_now(pd)?; diff --git a/podcasts-gtk/src/widgets/shows_view.rs b/podcasts-gtk/src/widgets/shows_view.rs index 8f8a3fc..f7b21a7 100644 --- a/podcasts-gtk/src/widgets/shows_view.rs +++ b/podcasts-gtk/src/widgets/shows_view.rs @@ -18,7 +18,8 @@ // SPDX-License-Identifier: GPL-3.0-or-later use glib::clone; -use gtk::{self, prelude::*, Adjustment, Align, SelectionMode}; +use gtk::glib; +use gtk::{prelude::*, Adjustment, Align, SelectionMode}; use anyhow::Result; use glib::Sender; @@ -27,10 +28,9 @@ use podcasts_data::dbqueries; use podcasts_data::Show; use crate::app::Action; -use crate::utils::{get_ignored_shows, lazy_load, set_image_from_path}; +use crate::utils::{get_ignored_shows, lazy_load_flowbox, set_image_from_path}; use crate::widgets::BaseView; -use std::cell::Cell; use std::rc::Rc; use std::sync::Arc; @@ -57,7 +57,7 @@ impl Default for ShowsView { flowbox.set_valign(Align::Start); flowbox.set_halign(Align::Center); flowbox.set_selection_mode(SelectionMode::None); - view.add(&flowbox); + view.set_child(&flowbox); ShowsView { view, flowbox } } @@ -93,7 +93,7 @@ fn populate_flowbox(shows: &Rc, vadj: Option) -> Result<( } }); - lazy_load(podcasts, flowbox_weak, constructor, callback); + lazy_load_flowbox(podcasts, flowbox_weak, constructor, callback); Ok(()) } @@ -116,15 +116,11 @@ struct ShowsChild { impl Default for ShowsChild { fn default() -> Self { - let cover = gtk::Image::from_icon_name( - Some("image-x-generic-symbolic"), - gtk::IconSize::__Unknown(-1), - ); + let cover = gtk::Image::from_icon_name(Some("image-x-generic-symbolic")); let child = gtk::FlowBoxChild::new(); cover.set_pixel_size(256); - child.add(&cover); - child.show_all(); + child.set_child(Some(&cover)); ShowsChild { cover, child } } @@ -145,22 +141,8 @@ impl ShowsChild { } fn set_cover(&self, show_id: i32) { - // The closure above is a regular `Fn` closure. - // which means we can't mutate stuff inside it easily, - // so Cell is used. - // - // `Option` along with the `.take()` method ensure - // that the function will only be run once, during the first execution. - let show_id = Cell::new(Some(show_id)); - - self.cover.connect_draw(move |cover, _| { - if let Some(id) = show_id.take() { - set_image_from_path(cover, id, 256) - .map_err(|err| error!("Failed to set a cover: {}", err)) - .ok(); - } - - gtk::Inhibit(false) - }); + set_image_from_path(&self.cover, show_id, 256) + .map_err(|err| error!("Failed to set a cover: {}", err)) + .ok(); } } diff --git a/podcasts-gtk/src/window.rs b/podcasts-gtk/src/window.rs index 653fc44..f62e900 100644 --- a/podcasts-gtk/src/window.rs +++ b/podcasts-gtk/src/window.rs @@ -24,9 +24,6 @@ use gio::{self, prelude::*}; use gtk::prelude::*; -use libhandy as hdy; -use libhandy::prelude::DeckExt; - use crate::app::{Action, PdApplication}; use crate::headerbar::Header; use crate::settings::{self, WindowGeometry}; @@ -45,12 +42,12 @@ use crate::i18n::i18n; #[derive(Debug)] pub struct MainWindow { - pub(crate) window: hdy::ApplicationWindow, + pub(crate) window: adw::ApplicationWindow, pub(crate) overlay: gtk::Overlay, pub(crate) content: Rc, pub(crate) headerbar: Rc
, pub(crate) player: player::PlayerWrapper, - pub(crate) main_deck: libhandy::Deck, + pub(crate) main_deck: adw::Leaflet, pub(crate) updating: Cell, pub(crate) updater: RefCell>, pub(crate) sender: Sender, @@ -60,23 +57,22 @@ impl MainWindow { pub(crate) fn new(app: &PdApplication, sender: &Sender) -> Self { let settings = gio::Settings::new(APP_ID); - let window = hdy::ApplicationWindow::new(); - window.set_application(Some(app)); + let window = adw::ApplicationWindow::new(app); - window.set_title(&i18n("Podcasts")); + window.set_title(Some(&i18n("Podcasts"))); if APP_ID.ends_with("Devel") { window.style_context().add_class("devel"); } - window.connect_delete_event( - clone!(@strong settings, @weak app => @default-return Inhibit(false), move |window, _| { + window.connect_close_request( + clone!(@strong settings, @weak app => @default-return gtk::Inhibit(false), move |window| { info!("Saving window position"); WindowGeometry::from_window(&window).write(&settings); info!("Application is exiting"); let app = app.upcast::(); app.quit(); - Inhibit(false) + gtk::Inhibit(false) }), ); @@ -88,28 +84,27 @@ impl MainWindow { // Add the content main stack to the overlay. let overlay = gtk::Overlay::new(); - let main_deck = libhandy::Deck::new(); - main_deck.set_can_swipe_forward(false); - main_deck.add(&content.get_container()); - overlay.add(&main_deck); + let main_deck = adw::Leaflet::new(); + main_deck.set_can_unfold(false); + main_deck.set_can_navigate_forward(false); + main_deck.append(&content.get_container()); + overlay.set_child(Some(&main_deck)); let wrap = gtk::Box::new(gtk::Orientation::Vertical, 0); // Add the Headerbar to the window. - content - .get_container() - .pack_start(&header.container, false, true, 0); + content.get_container().prepend(&header.container); // Add the overlay to the main Box - wrap.add(&overlay); + wrap.append(&overlay); let player = player::PlayerWrapper::new(&sender); // Add the player to the main Box - wrap.add(&player.borrow().container); + wrap.append(&player.borrow().container); - wrap.add(&header.bottom_switcher); + wrap.append(&header.bottom_switcher); - window.add(&wrap); + adw::traits::ApplicationWindowExt::set_content(&window, Some(&wrap)); // Retrieve the previous window position and size. WindowGeometry::from_settings(&settings).apply(&window); @@ -201,16 +196,14 @@ impl MainWindow { } /// Remove all items from the `main_deck` except from the content pub fn clear_deck(&self) { - for c in self.main_deck.children() { - if c.widget_name() != "content" { - self.main_deck.remove(&c); - } + if let Some(page) = self.main_deck.child_by_name("description") { + self.main_deck.remove(&page); } } } impl Deref for MainWindow { - type Target = hdy::ApplicationWindow; + type Target = adw::ApplicationWindow; fn deref(&self) -> &Self::Target { &self.window -- 2.40.1 From a5a07acea3bb48cef2be1b7acc4e0a07217a0da4 Mon Sep 17 00:00:00 2001 From: Julian Hofer Date: Sun, 18 Oct 2020 23:05:20 +0200 Subject: [PATCH 027/102] player_dialog: Set icon sizes --- podcasts-gtk/resources/gtk/player_dialog.ui | 28 ++++++++++++++++++--- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/podcasts-gtk/resources/gtk/player_dialog.ui b/podcasts-gtk/resources/gtk/player_dialog.ui index 116f7e0..bc0bcb6 100644 --- a/podcasts-gtk/resources/gtk/player_dialog.ui +++ b/podcasts-gtk/resources/gtk/player_dialog.ui @@ -132,7 +132,12 @@ 60 center 12 - skip-back-large-symbolic + + + skip-back-large-symbolic + 2 + + @@ -145,7 +150,12 @@ True 80 80 - media-playback-start-symbolic + + + media-playback-start-symbolic + 2 + + @@ -155,7 +165,12 @@ 80 80 - media-playback-pause-symbolic + + + media-playback-pause-symbolic + 2 + + @@ -170,7 +185,12 @@ 60 center 12 - skip-forward-large-symbolic + + + skip-forward-large-symbolic + 2 + + -- 2.40.1 From 1d1a1dbc23c1385782269306128b16d33215ef3d Mon Sep 17 00:00:00 2001 From: Jordan Petridis Date: Tue, 29 Dec 2020 11:04:03 +0200 Subject: [PATCH 028/102] podcast-gtk: bundle gresource icons as gtk4 wants to --- .../{ => scalable/actions}/skip-back-large-symbolic.svg | 0 .../icons/{ => scalable/actions}/skip-back-symbolic.svg | 0 .../actions}/skip-forward-large-symbolic.svg | 0 .../{ => scalable/actions}/skip-forward-symbolic.svg | 0 podcasts-gtk/resources/resources.xml | 8 ++++---- 5 files changed, 4 insertions(+), 4 deletions(-) rename podcasts-gtk/resources/icons/{ => scalable/actions}/skip-back-large-symbolic.svg (100%) rename podcasts-gtk/resources/icons/{ => scalable/actions}/skip-back-symbolic.svg (100%) rename podcasts-gtk/resources/icons/{ => scalable/actions}/skip-forward-large-symbolic.svg (100%) rename podcasts-gtk/resources/icons/{ => scalable/actions}/skip-forward-symbolic.svg (100%) diff --git a/podcasts-gtk/resources/icons/skip-back-large-symbolic.svg b/podcasts-gtk/resources/icons/scalable/actions/skip-back-large-symbolic.svg similarity index 100% rename from podcasts-gtk/resources/icons/skip-back-large-symbolic.svg rename to podcasts-gtk/resources/icons/scalable/actions/skip-back-large-symbolic.svg diff --git a/podcasts-gtk/resources/icons/skip-back-symbolic.svg b/podcasts-gtk/resources/icons/scalable/actions/skip-back-symbolic.svg similarity index 100% rename from podcasts-gtk/resources/icons/skip-back-symbolic.svg rename to podcasts-gtk/resources/icons/scalable/actions/skip-back-symbolic.svg diff --git a/podcasts-gtk/resources/icons/skip-forward-large-symbolic.svg b/podcasts-gtk/resources/icons/scalable/actions/skip-forward-large-symbolic.svg similarity index 100% rename from podcasts-gtk/resources/icons/skip-forward-large-symbolic.svg rename to podcasts-gtk/resources/icons/scalable/actions/skip-forward-large-symbolic.svg diff --git a/podcasts-gtk/resources/icons/skip-forward-symbolic.svg b/podcasts-gtk/resources/icons/scalable/actions/skip-forward-symbolic.svg similarity index 100% rename from podcasts-gtk/resources/icons/skip-forward-symbolic.svg rename to podcasts-gtk/resources/icons/scalable/actions/skip-forward-symbolic.svg diff --git a/podcasts-gtk/resources/resources.xml b/podcasts-gtk/resources/resources.xml index 729d633..6503c90 100644 --- a/podcasts-gtk/resources/resources.xml +++ b/podcasts-gtk/resources/resources.xml @@ -16,10 +16,10 @@ gtk/player_dialog.ui gtk/player_rate.ui gtk/player_toolbar.ui - icons/skip-back-large-symbolic.svg - icons/skip-back-symbolic.svg - icons/skip-forward-large-symbolic.svg - icons/skip-forward-symbolic.svg + icons/scalable/actions/skip-back-large-symbolic.svg + icons/scalable/actions/skip-back-symbolic.svg + icons/scalable/actions/skip-forward-large-symbolic.svg + icons/scalable/actions/skip-forward-symbolic.svg gtk/style.css -- 2.40.1 From eb41e73ff3a28ef33d7c5670bec622520251b19d Mon Sep 17 00:00:00 2001 From: Maximiliano Sandoval R Date: Sat, 21 Aug 2021 11:31:32 +0200 Subject: [PATCH 029/102] shows_view: Subclass ShowCover --- podcasts-gtk/src/widgets/shows_view.rs | 95 ++++++++++++++++++++++---- 1 file changed, 83 insertions(+), 12 deletions(-) diff --git a/podcasts-gtk/src/widgets/shows_view.rs b/podcasts-gtk/src/widgets/shows_view.rs index f7b21a7..8b48c47 100644 --- a/podcasts-gtk/src/widgets/shows_view.rs +++ b/podcasts-gtk/src/widgets/shows_view.rs @@ -17,9 +17,10 @@ // // SPDX-License-Identifier: GPL-3.0-or-later +use adw::{prelude::BinExt, subclass::prelude::*}; use glib::clone; use gtk::glib; -use gtk::{prelude::*, Adjustment, Align, SelectionMode}; +use gtk::{prelude::*, subclass::prelude::*, Adjustment, Align, SelectionMode}; use anyhow::Result; use glib::Sender; @@ -31,6 +32,7 @@ use crate::app::Action; use crate::utils::{get_ignored_shows, lazy_load_flowbox, set_image_from_path}; use crate::widgets::BaseView; +use std::cell::Cell; use std::rc::Rc; use std::sync::Arc; @@ -99,7 +101,12 @@ fn populate_flowbox(shows: &Rc, vadj: Option) -> Result<( fn on_child_activate(child: >k::FlowBoxChild, sender: &Sender) -> Result<()> { // This is such an ugly hack... - let id = child.widget_name().parse::()?; + let id = child + .child() + .unwrap() + .downcast::() + .expect("Could not downcast Widget to PdShowCover") + .id(); let pd = Arc::new(dbqueries::get_podcast_from_id(id)?); send!(sender, Action::HeaderBarShowTile(pd.title().into())); @@ -108,18 +115,76 @@ fn on_child_activate(child: >k::FlowBoxChild, sender: &Sender) -> Resu Ok(()) } +#[derive(Debug)] +pub struct ShowCoverPrivate { + pub cover: gtk::Image, + pub show_id: Cell, +} + +#[glib::object_subclass] +impl ObjectSubclass for ShowCoverPrivate { + const NAME: &'static str = "PdShowCover"; + type Type = ShowCover; + type ParentType = adw::Bin; + + fn new() -> Self { + Self { + // FIXME: bundle the symbolic in resources + cover: gtk::Image::from_icon_name(Some("image-x-generic-symbolic")), + show_id: Cell::default(), + } + } +} + +impl ObjectImpl for ShowCoverPrivate { + fn constructed(&self, obj: &Self::Type) { + self.parent_constructed(obj); + self.cover.set_pixel_size(256); + + obj.set_child(Some(&self.cover)); + } +} + +impl WidgetImpl for ShowCoverPrivate {} +impl BinImpl for ShowCoverPrivate {} + +glib::wrapper! { + pub struct ShowCover(ObjectSubclass) + @extends gtk::Widget, adw::Bin; +} + +impl ShowCover { + fn new() -> Self { + glib::Object::new(&[]).expect("Failed to create PdShowCover") + } + + fn set_id(&self, id: i32) { + let self_ = ShowCoverPrivate::from_instance(self); + self_.show_id.set(id); + } + + fn id(&self) -> i32 { + self.imp().show_id.get() + } + + fn load_image(&self) -> Result<()> { + let imp = self.imp(); + set_image_from_path(&imp.cover, imp.show_id.get(), 256)?; + Ok(()) + } +} + #[derive(Debug, Clone)] struct ShowsChild { - cover: gtk::Image, + cover: ShowCover, child: gtk::FlowBoxChild, } impl Default for ShowsChild { fn default() -> Self { - let cover = gtk::Image::from_icon_name(Some("image-x-generic-symbolic")); + let cover = ShowCover::new(); let child = gtk::FlowBoxChild::new(); - cover.set_pixel_size(256); child.set_child(Some(&cover)); ShowsChild { cover, child } @@ -128,20 +193,26 @@ impl Default for ShowsChild { impl ShowsChild { pub(crate) fn new(pd: &Show) -> ShowsChild { - let child = ShowsChild::default(); - child.init(pd); - child + let cover = ShowCover::new(); + let child = gtk::FlowBoxChild::new(); + + child.set_child(Some(&cover)); + + let shows_child = ShowsChild { cover, child }; + shows_child.init(pd); + shows_child } fn init(&self, pd: &Show) { self.child.set_tooltip_text(Some(pd.title())); - self.child.set_widget_name(&pd.id().to_string()); - self.set_cover(pd.id()) + self.cover.set_id(pd.id()); + self.set_cover(); } - fn set_cover(&self, show_id: i32) { - set_image_from_path(&self.cover, show_id, 256) + fn set_cover(&self) { + self.cover + .load_image() .map_err(|err| error!("Failed to set a cover: {}", err)) .ok(); } -- 2.40.1 From ecc2edddeeabf1747b32ee04033ef91026420cf2 Mon Sep 17 00:00:00 2001 From: Maximiliano Sandoval R Date: Sun, 22 Aug 2021 10:14:32 +0200 Subject: [PATCH 030/102] podcasts-gtk: Port notifications to AdwToast --- Cargo.lock | 1 + podcasts-gtk/Cargo.toml | 1 + podcasts-gtk/po/POTFILES.in | 2 - podcasts-gtk/resources/gtk/inapp_notif.ui | 99 ---------- podcasts-gtk/resources/resources.xml | 1 - podcasts-gtk/src/app.rs | 149 +++++++++++---- podcasts-gtk/src/main.rs | 1 - podcasts-gtk/src/meson.build | 1 - podcasts-gtk/src/utils.rs | 29 ++- podcasts-gtk/src/widgets/appnotif.rs | 175 ------------------ .../src/widgets/episode_description.rs | 12 -- podcasts-gtk/src/widgets/mod.rs | 1 - podcasts-gtk/src/widgets/show.rs | 3 +- podcasts-gtk/src/widgets/show_menu.rs | 78 ++++---- podcasts-gtk/src/window.rs | 25 ++- 15 files changed, 180 insertions(+), 398 deletions(-) delete mode 100644 podcasts-gtk/resources/gtk/inapp_notif.ui delete mode 100644 podcasts-gtk/src/widgets/appnotif.rs diff --git a/Cargo.lock b/Cargo.lock index 8a79674..35756f2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1892,6 +1892,7 @@ dependencies = [ "log", "markup5ever_rcdom", "mpris-player", + "once_cell", "open", "podcasts-data", "pretty_assertions", diff --git a/podcasts-gtk/Cargo.toml b/podcasts-gtk/Cargo.toml index df64822..6b3cb87 100644 --- a/podcasts-gtk/Cargo.toml +++ b/podcasts-gtk/Cargo.toml @@ -26,6 +26,7 @@ markup5ever_rcdom = "0.1" html2text = "0.2.1" glib = "0.14.2" adw = {package = "libadwaita", version = "0.1.0-beta"} +once_cell = "1.9" [dependencies.gettext-rs] git = "https://github.com/danigm/gettext-rs" diff --git a/podcasts-gtk/po/POTFILES.in b/podcasts-gtk/po/POTFILES.in index 3de9057..75028ad 100644 --- a/podcasts-gtk/po/POTFILES.in +++ b/podcasts-gtk/po/POTFILES.in @@ -14,7 +14,6 @@ podcasts-gtk/resources/gtk/headerbar.ui podcasts-gtk/resources/gtk/help-overlay.ui podcasts-gtk/resources/gtk/home_episode.ui podcasts-gtk/resources/gtk/home_view.ui -podcasts-gtk/resources/gtk/inapp_notif.ui podcasts-gtk/resources/gtk/player_dialog.ui podcasts-gtk/resources/gtk/player_rate.ui podcasts-gtk/resources/gtk/player_toolbar.ui @@ -35,7 +34,6 @@ podcasts-gtk/src/stacks/populated.rs podcasts-gtk/src/stacks/show.rs podcasts-gtk/src/utils.rs podcasts-gtk/src/widgets/aboutdialog.rs -podcasts-gtk/src/widgets/appnotif.rs podcasts-gtk/src/widgets/base_view.rs podcasts-gtk/src/widgets/empty.rs podcasts-gtk/src/widgets/episode.rs diff --git a/podcasts-gtk/resources/gtk/inapp_notif.ui b/podcasts-gtk/resources/gtk/inapp_notif.ui deleted file mode 100644 index 36bd938..0000000 --- a/podcasts-gtk/resources/gtk/inapp_notif.ui +++ /dev/null @@ -1,99 +0,0 @@ - - - - - - - - - - center - start - - - center - center - 0 - - - center - center - 3 - 3 - 6 - - - - - - - 150 - center - center - 12 - 12 - An in-app action notification - start - - - - - Undo - True - center - center - - - - - - False - True - center - center - window-close-symbolic - - - - - - - - - - - - - - diff --git a/podcasts-gtk/resources/resources.xml b/podcasts-gtk/resources/resources.xml index 6503c90..b46973d 100644 --- a/podcasts-gtk/resources/resources.xml +++ b/podcasts-gtk/resources/resources.xml @@ -9,7 +9,6 @@ gtk/home_view.ui gtk/home_episode.ui gtk/headerbar.ui - gtk/inapp_notif.ui gtk/hamburger.ui gtk/show_menu.ui gtk/help-overlay.ui diff --git a/podcasts-gtk/src/app.rs b/podcasts-gtk/src/app.rs index 1526d26..f37bfde 100644 --- a/podcasts-gtk/src/app.rs +++ b/podcasts-gtk/src/app.rs @@ -34,7 +34,6 @@ use podcasts_data::{Episode, Show, Source}; use crate::settings; use crate::stacks::PopulatedState; use crate::utils; -use crate::widgets::appnotif::{InAppNotification, SpinnerState, State}; use crate::widgets::show_menu::{mark_all_notif, remove_show_notif}; use crate::widgets::EpisodeDescription; use crate::window::MainWindow; @@ -54,6 +53,8 @@ pub struct PdApplicationPrivate { window: RefCell>, settings: RefCell>, inhibit_cookie: RefCell, + undo_remove_ids: RefCell>, + undo_marked_ids: RefCell>, } #[glib::object_subclass] @@ -73,6 +74,8 @@ impl ObjectSubclass for PdApplicationPrivate { window: RefCell::new(None), settings: RefCell::new(None), inhibit_cookie: RefCell::new(0), + undo_remove_ids: RefCell::new(vec![]), + undo_marked_ids: RefCell::new(vec![]), } } } @@ -145,7 +148,8 @@ pub(crate) enum Action { CopiedUrlNotification, MarkAllPlayerNotification(Arc), UpdateFeed(Option>), - ShowUpdateNotif(crossbeam_channel::Receiver), + ShowUpdateNotif, + FeedRefreshed, StopUpdating, RemoveShow(Arc), ErrorNotification(String), @@ -174,6 +178,7 @@ impl PdApplication { fn setup_gactions(&self) { let app = self.upcast_ref::(); + let data = PdApplicationPrivate::from_instance(self); // Create the quit action utils::make_action( app, @@ -191,6 +196,69 @@ impl PdApplication { } })); app.add_action(&show_episode); + + let undo_mark_all = gio::SimpleAction::new("undo-mark-all", Some(&i32_variant_type)); + undo_mark_all.connect_activate( + clone!(@weak self as app, @strong data.sender as sender => move |_, id_variant_option| { + let data = PdApplicationPrivate::from_instance(&app); + let id = id_variant_option.unwrap().get::().unwrap(); + let mut ids = data.undo_marked_ids.borrow_mut(); + if !ids.contains(&id) { + ids.push(id); + } + + send!(sender, Action::RefreshWidgetIfSame(id)); + }), + ); + app.add_action(&undo_mark_all); + + let undo_remove_show = gio::SimpleAction::new("undo-remove-show", Some(&i32_variant_type)); + undo_remove_show.connect_activate( + clone!(@weak self as app, @strong data.sender as sender => move |_, id_variant_option| { + let data = PdApplicationPrivate::from_instance(&app); + let id = id_variant_option.unwrap().get::().unwrap(); + let mut ids = data.undo_remove_ids.borrow_mut(); + if !ids.contains(&id) { + ids.push(id); + } + + let res = utils::unignore_show(id); + debug_assert!(res.is_ok()); + send!(sender, Action::RefreshShowsView); + send!(sender, Action::RefreshEpisodesView); + }), + ); + app.add_action(&undo_remove_show); + } + + /// We check if the User pressed the Undo button, which would add + /// the id into undo_revove_ids. + pub fn is_show_marked_delete(&self, pd: &Show) -> bool { + let data = PdApplicationPrivate::from_instance(self); + let id = pd.id(); + let mut undo_remove_ids = data.undo_remove_ids.borrow_mut(); + + if let Some(pos) = undo_remove_ids.iter().position(|x| *x == id) { + undo_remove_ids.remove(pos); + + return false; + } + + true + } + + pub fn is_show_marked_mark(&self, pd: &Show) -> bool { + let data = PdApplicationPrivate::from_instance(self); + let id = pd.id(); + let mut undo_marked_ids = data.undo_marked_ids.borrow_mut(); + + if let Some(pos) = undo_marked_ids.iter().position(|x| *x == id) { + undo_marked_ids.remove(pos); + + return false; + } + + true } fn go_to_episode(&self, id_variant_option: Option<&glib::Variant>) -> Result<()> { @@ -286,26 +354,22 @@ impl PdApplication { Action::HeaderBarShowTile(title) => window.headerbar.switch_to_back(&title), Action::HeaderBarNormal => window.headerbar.switch_to_normal(), Action::CopiedUrlNotification => { - let notif = EpisodeDescription::copied_url_notif(); - notif.show(&window.overlay); + let text = i18n("Copied URL to clipboard!"); + let toast = adw::Toast::new(&text); + self.send_toast(&toast); } Action::MarkAllPlayerNotification(pd) => { - let notif = mark_all_notif(pd, &data.sender); - notif.show(&window.overlay); + let toast = mark_all_notif(pd, &data.sender); + self.send_toast(&toast); } Action::RemoveShow(pd) => { - let notif = remove_show_notif(pd, data.sender.clone()); - notif.show(&window.overlay); + let toast = remove_show_notif(pd, data.sender.clone()); + self.send_toast(&toast); } Action::ErrorNotification(err) => { error!("An error notification was triggered: {}", err); - let callback = |revealer: gtk::Revealer| { - revealer.set_reveal_child(false); - glib::Continue(false) - }; - let undo_cb: Option = None; - let notif = InAppNotification::new(&err, 6000, callback, undo_cb); - notif.show(&window.overlay); + let toast = adw::Toast::new(&err); + window.toast_overlay.add_toast(&toast); } Action::UpdateFeed(source) => { if window.updating.get() { @@ -317,33 +381,29 @@ impl PdApplication { } Action::StopUpdating => { window.updating.set(false); + if let Some(timeout) = window.updating_timeout.replace(None) { + glib::source_remove(timeout); + } + window.progress_bar.hide(); } - Action::ShowUpdateNotif(receiver) => { - use crossbeam_channel::TryRecvError; - - let sender = data.sender.clone(); - let callback = move |revealer: gtk::Revealer| match receiver.try_recv() { - Err(TryRecvError::Empty) => glib::Continue(true), - Err(TryRecvError::Disconnected) => glib::Continue(false), - Ok(_) => { - revealer.set_reveal_child(false); - - send!(sender, Action::StopUpdating); - send!(sender, Action::RefreshAllViews); - - glib::Continue(false) - } - }; - let txt = i18n("Fetching new episodes"); - let undo_cb: Option = None; - let updater = InAppNotification::new(&txt, 250, callback, undo_cb); - updater.set_close_state(State::Hidden); - updater.set_spinner_state(SpinnerState::Active); - - if let Some(i) = window.updater.borrow().as_ref() { - i.show(&window.overlay) + Action::ShowUpdateNotif => { + let updating_timeout = glib::timeout_add_local( + std::time::Duration::from_millis(100), + clone!(@weak window.progress_bar as progress => @default-return Continue(false), move || { + progress.show(); + progress.pulse(); + Continue(true) + }), + ); + if let Some(old_timeout) = window.updating_timeout.replace(Some(updating_timeout)) { + glib::source_remove(old_timeout); } } + Action::FeedRefreshed => { + let sender = data.sender.clone(); + send!(sender, Action::StopUpdating); + send!(sender, Action::RefreshAllViews); + } Action::InitEpisode(rowid) => { let res = window.player.borrow_mut().initialize_episode(rowid); debug_assert!(res.is_ok()); @@ -419,4 +479,15 @@ impl PdApplication { let args: Vec = env::args().collect(); ApplicationExtManual::run_with_args(&application, &args); } + + pub(crate) fn send_toast(&self, toast: &adw::Toast) { + let self_ = PdApplicationPrivate::from_instance(self); + self_ + .window + .borrow() + .as_ref() + .unwrap() + .toast_overlay + .add_toast(toast); + } } diff --git a/podcasts-gtk/src/main.rs b/podcasts-gtk/src/main.rs index 8a4d367..39fb2aa 100644 --- a/podcasts-gtk/src/main.rs +++ b/podcasts-gtk/src/main.rs @@ -132,7 +132,6 @@ fn test_stuff() -> anyhow::Result<()> { EmptyShow::default(); EpisodeDescription::default(); - appnotif::InAppNotification::default(); show_menu::ShowMenu::default(); episode_menu::EpisodeMenu::default(); diff --git a/podcasts-gtk/src/meson.build b/podcasts-gtk/src/meson.build index 75b75ac..f9e7ad3 100644 --- a/podcasts-gtk/src/meson.build +++ b/podcasts-gtk/src/meson.build @@ -23,7 +23,6 @@ podcasts_sources = files( 'stacks/populated.rs', 'stacks/show.rs', 'widgets/aboutdialog.rs', - 'widgets/appnotif.rs', 'widgets/base_view.rs', 'widgets/empty.rs', 'widgets/episode.rs', diff --git a/podcasts-gtk/src/utils.rs b/podcasts-gtk/src/utils.rs index 0c099c9..fd2cead 100644 --- a/podcasts-gtk/src/utils.rs +++ b/podcasts-gtk/src/utils.rs @@ -29,7 +29,7 @@ use gtk::Widget; use anyhow::{anyhow, Result}; use chrono::prelude::*; -use crossbeam_channel::{bounded, unbounded}; +use crossbeam_channel::unbounded; use fragile::Fragile; use regex::Regex; use serde_json::Value; @@ -297,27 +297,20 @@ pub(crate) fn schedule_refresh(source: Option>, sender: Sender>, sender: Sender) { - let (up_sender, up_receiver) = bounded(1); - send!(sender, Action::ShowUpdateNotif(up_receiver)); + send!(sender, Action::ShowUpdateNotif); - if let Some(s) = source { - // Refresh only specified feeds - tokio::spawn(async move { + tokio::spawn(clone!(@strong sender => async move { + if let Some(s) = source { + // Refresh only specified feeds pipeline(s).await; - up_sender - .send(true) - .expect("Channel was dropped unexpectedly"); - }) - } else { - // Refresh all the feeds - tokio::spawn(async move { + send!(sender, Action::FeedRefreshed); + } else { + // Refresh all the feeds let sources = dbqueries::get_sources().map(|s| s.into_iter()).unwrap(); pipeline(sources).await; - up_sender - .send(true) - .expect("Channel was dropped unexpectedly"); - }) - }; + send!(sender, Action::FeedRefreshed); + } + })); } lazy_static! { diff --git a/podcasts-gtk/src/widgets/appnotif.rs b/podcasts-gtk/src/widgets/appnotif.rs deleted file mode 100644 index 602b55f..0000000 --- a/podcasts-gtk/src/widgets/appnotif.rs +++ /dev/null @@ -1,175 +0,0 @@ -// appnotif.rs -// -// Copyright 2017 Jordan Petridis -// -// This program 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. -// -// This program 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 this program. If not, see . -// -// SPDX-License-Identifier: GPL-3.0-or-later - -use glib::clone; -use gtk::prelude::*; - -use std::cell::RefCell; -use std::rc::Rc; -use std::time::Duration; - -#[derive(Debug, Clone, Copy)] -#[allow(dead_code)] -pub(crate) enum State { - Shown, - Hidden, -} - -#[derive(Debug, Clone, Copy)] -#[allow(dead_code)] -pub(crate) enum SpinnerState { - Active, - Stopped, -} - -#[derive(Debug, Clone)] -pub(crate) struct InAppNotification { - revealer: gtk::Revealer, - text: gtk::Label, - undo: gtk::Button, - close: gtk::Button, - spinner: gtk::Spinner, -} - -impl Default for InAppNotification { - fn default() -> Self { - let builder = gtk::Builder::from_resource("/org/gnome/Podcasts/gtk/inapp_notif.ui"); - - let revealer: gtk::Revealer = builder.object("revealer").unwrap(); - let text: gtk::Label = builder.object("text").unwrap(); - let undo: gtk::Button = builder.object("undo").unwrap(); - let close: gtk::Button = builder.object("close").unwrap(); - let spinner = builder.object("spinner").unwrap(); - - InAppNotification { - revealer, - text, - undo, - close, - spinner, - } - } -} - -impl InAppNotification { - /// Creates a new instance of InAppNotification - /// - /// # Arguments - /// - /// * `text` - Text which is displayed within the revealer - /// * `timer` - Time in ms until the callback is called, in milliseconds - /// * `callback` - Function to call after `timer` is passed. - /// You will probably want to call `set_reveal_child(false)` within it - /// * `undo_callback` - If undo_callback is `is_some()`, then the revealer will include an undo-button. - /// If the undo-button is pressed, undo_callback will be called. - pub(crate) fn new( - text: &str, - timer: u32, - mut callback: F, - undo_callback: Option, - ) -> Self - where - F: FnMut(gtk::Revealer) -> glib::Continue + 'static, - U: Fn() + 'static, - { - let notif = InAppNotification::default(); - notif.text.set_text(&text); - - let mut time = Duration::from_millis(0); - let interval = Duration::from_millis(250); - let id = glib::timeout_add_local( - interval, - clone!(@weak notif.revealer as revealer => @default-return glib::Continue(false), move || { - if time.as_millis() < timer as u128 { - time += interval; - return glib::Continue(true); - }; - callback(revealer) - }), - ); - let id = Rc::new(RefCell::new(Some(id))); - - if undo_callback.is_some() { - notif.set_undo_state(State::Shown) - }; - - notif - .undo - .connect_clicked(clone!(@weak notif.revealer as revealer => move |_| { - if let Some(id) = id.borrow_mut().take() { - // Cancel the callback - glib::source::source_remove(id); - } - - if let Some(ref f) = undo_callback { - f(); - } - - // Hide the notification - revealer.set_reveal_child(false); - })); - - // Hide the revealer when the close button is clicked - notif - .close - .connect_clicked(clone!(@weak notif.revealer as revealer => move |_| { - revealer.set_reveal_child(false); - })); - - notif - } - - // This is a separate method cause in order to get a nice animation - // the revealer should be attached to something that displays it. - // Previously we where doing it in the constructor, which had the result - // of the animation being skipped cause there was no parent widget to display it. - pub(crate) fn show(&self, overlay: >k::Overlay) { - overlay.add_overlay(&self.revealer); - // We need to display the notification after the widget is added to the overlay - // so there will be a nice animation. - self.revealer.set_reveal_child(true); - } - - pub(crate) fn set_undo_state(&self, state: State) { - match state { - State::Shown => self.undo.show(), - State::Hidden => self.undo.hide(), - } - } - - pub(crate) fn set_close_state(&self, state: State) { - match state { - State::Shown => self.close.show(), - State::Hidden => self.close.hide(), - } - } - - pub(crate) fn set_spinner_state(&self, state: SpinnerState) { - match state { - SpinnerState::Active => { - self.spinner.start(); - self.spinner.show(); - } - SpinnerState::Stopped => { - self.spinner.stop(); - self.spinner.hide(); - } - } - } -} diff --git a/podcasts-gtk/src/widgets/episode_description.rs b/podcasts-gtk/src/widgets/episode_description.rs index 7efca7b..ec080a3 100644 --- a/podcasts-gtk/src/widgets/episode_description.rs +++ b/podcasts-gtk/src/widgets/episode_description.rs @@ -24,11 +24,9 @@ use podcasts_data::{Episode, Show}; use crate::app::Action; use crate::utils::{self}; -use crate::widgets::appnotif::InAppNotification; use crate::widgets::EpisodeMenu; use crate::episode_description_parser; -use crate::i18n::i18n; use chrono::prelude::*; use std::rc::Rc; use std::sync::Arc; @@ -141,14 +139,4 @@ impl EpisodeDescription { .map_err(|err| error!("Failed to set a cover: {}", err)) .ok(); } - - pub(crate) fn copied_url_notif() -> InAppNotification { - let callback = move |revealer: gtk::Revealer| { - revealer.set_reveal_child(false); - glib::Continue(false) - }; - let text = i18n("Copied URL to clipboard!"); - let undo_callback: Option = None; - InAppNotification::new(&text, 2000, callback, undo_callback) - } } diff --git a/podcasts-gtk/src/widgets/mod.rs b/podcasts-gtk/src/widgets/mod.rs index cf9a7dd..ea3e9bb 100644 --- a/podcasts-gtk/src/widgets/mod.rs +++ b/podcasts-gtk/src/widgets/mod.rs @@ -18,7 +18,6 @@ // SPDX-License-Identifier: GPL-3.0-or-later mod aboutdialog; -pub(crate) mod appnotif; mod base_view; mod empty; mod episode; diff --git a/podcasts-gtk/src/widgets/show.rs b/podcasts-gtk/src/widgets/show.rs index c958eca..636098d 100644 --- a/podcasts-gtk/src/widgets/show.rs +++ b/podcasts-gtk/src/widgets/show.rs @@ -166,7 +166,7 @@ fn populate_listbox( let count = dbqueries::get_pd_episodes_count(&pd)?; let (sender_, receiver) = bounded(1); - rayon::spawn(clone!(@strong pd => move || { + tokio::spawn(clone!(@strong pd => async move { if let Ok(episodes) = dbqueries::get_pd_episodeswidgets(&pd) { // The receiver can be dropped if there's an early return // like on show without episodes for example. @@ -182,6 +182,7 @@ fn populate_listbox( let show_weak = Rc::downgrade(&show); let list_weak = show.episodes.downgrade(); + glib::idle_add_local(move || { let episodes = match receiver.try_recv() { Ok(e) => e, diff --git a/podcasts-gtk/src/widgets/show_menu.rs b/podcasts-gtk/src/widgets/show_menu.rs index 1a33f14..fc85fbe 100644 --- a/podcasts-gtk/src/widgets/show_menu.rs +++ b/podcasts-gtk/src/widgets/show_menu.rs @@ -30,7 +30,6 @@ use podcasts_data::Show; use crate::app::Action; use crate::utils; -use crate::widgets::appnotif::InAppNotification; use std::sync::Arc; @@ -166,56 +165,59 @@ fn mark_all_watched(pd: &Show, sender: &Sender) -> Result<()> { Ok(()) } -pub(crate) fn mark_all_notif(pd: Arc, sender: &Sender) -> InAppNotification { +pub(crate) fn mark_all_notif(pd: Arc, sender: &Sender) -> adw::Toast { let id = pd.id(); - let sender_ = sender.clone(); - let callback = move |revealer: gtk::Revealer| { - let res = mark_all_watched(&pd, &sender_); - debug_assert!(res.is_ok()); + let toast = adw::Toast::new(&i18n("Marked all episodes as listened")); + toast.set_button_label(Some(&i18n("Undo"))); + toast.set_action_target_value(Some(&id.to_variant())); + toast.set_action_name(Some("app.undo-mark-all")); - revealer.set_reveal_child(false); - glib::Continue(false) - }; + toast.connect_dismissed(clone!(@strong sender => move |_| { + let app = gio::Application::default() + .expect("Could not get default application") + .downcast::() + .unwrap(); + if app.is_show_marked_mark(&pd) { + let res = mark_all_watched(&pd, &sender); + debug_assert!(res.is_ok()); + } + })); - let undo_callback = clone!(@strong sender => move || { - send!(sender, Action::RefreshWidgetIfSame(id)); - }); - let text = i18n("Marked all episodes as listened"); - InAppNotification::new(&text, 6000, callback, Some(undo_callback)) + toast } -pub(crate) fn remove_show_notif(pd: Arc, sender: Sender) -> InAppNotification { +pub(crate) fn remove_show_notif(pd: Arc, sender: Sender) -> adw::Toast { let text = i18n_f("Unsubscribed from {}", &[pd.title()]); + let id = pd.id(); - let res = utils::ignore_show(pd.id()); + let toast = adw::Toast::new(&text); + toast.set_button_label(Some(&i18n("Undo"))); + toast.set_action_target_value(Some(&id.to_variant())); + toast.set_action_name(Some("app.undo-remove-show")); + + let res = utils::ignore_show(id); debug_assert!(res.is_ok()); - let sender_ = sender.clone(); - let pd_ = pd.clone(); - let callback = move |revealer: gtk::Revealer| { - let res = utils::unignore_show(pd_.id()); + toast.connect_dismissed(clone!(@strong sender => move |_args| { + let res = utils::unignore_show(id); debug_assert!(res.is_ok()); // Spawn a thread so it won't block the ui. - rayon::spawn(clone!(@strong pd_, @strong sender_ => move || { - delete_show(&pd_) - .map_err(|err| error!("Error: {}", err)) - .map_err(|_| error!("Failed to delete {}", pd_.title())) - .ok(); + rayon::spawn(clone!(@strong pd, @strong sender => move || { + let app = gio::Application::default() + .expect("Could not get default application") + .downcast::() + .unwrap(); + if app.is_show_marked_delete(&pd) { + delete_show(&pd) + .map_err(|err| error!("Error: {}", err)) + .map_err(|_| error!("Failed to delete {}", pd.title())) + .ok(); - send!(sender_, Action::RefreshEpisodesView); + send!(sender, Action::RefreshEpisodesView); + } })); + })); - revealer.set_reveal_child(false); - glib::Continue(false) - }; - - let undo_callback = move || { - let res = utils::unignore_show(pd.id()); - debug_assert!(res.is_ok()); - send!(sender, Action::RefreshShowsView); - send!(sender, Action::RefreshEpisodesView); - }; - - InAppNotification::new(&text, 6000, callback, Some(undo_callback)) + toast } diff --git a/podcasts-gtk/src/window.rs b/podcasts-gtk/src/window.rs index f62e900..b72c402 100644 --- a/podcasts-gtk/src/window.rs +++ b/podcasts-gtk/src/window.rs @@ -30,7 +30,6 @@ use crate::settings::{self, WindowGeometry}; use crate::stacks::Content; use crate::utils::{self, make_action}; use crate::widgets::about_dialog; -use crate::widgets::appnotif::InAppNotification; use crate::widgets::player; use std::cell::{Cell, RefCell}; @@ -43,13 +42,14 @@ use crate::i18n::i18n; #[derive(Debug)] pub struct MainWindow { pub(crate) window: adw::ApplicationWindow, - pub(crate) overlay: gtk::Overlay, pub(crate) content: Rc, pub(crate) headerbar: Rc
, pub(crate) player: player::PlayerWrapper, pub(crate) main_deck: adw::Leaflet, + pub(crate) toast_overlay: adw::ToastOverlay, + pub(crate) progress_bar: Rc, + pub(crate) updating_timeout: RefCell>, pub(crate) updating: Cell, - pub(crate) updater: RefCell>, pub(crate) sender: Sender, } @@ -58,6 +58,7 @@ impl MainWindow { let settings = gio::Settings::new(APP_ID); let window = adw::ApplicationWindow::new(app); + let toast_overlay = adw::ToastOverlay::new(); window.set_title(Some(&i18n("Podcasts"))); if APP_ID.ends_with("Devel") { @@ -83,20 +84,22 @@ impl MainWindow { let header = Header::new(&content, &sender); // Add the content main stack to the overlay. - let overlay = gtk::Overlay::new(); let main_deck = adw::Leaflet::new(); main_deck.set_can_unfold(false); main_deck.set_can_navigate_forward(false); main_deck.append(&content.get_container()); - overlay.set_child(Some(&main_deck)); let wrap = gtk::Box::new(gtk::Orientation::Vertical, 0); + let progress_bar = gtk::ProgressBar::new(); + progress_bar.hide(); + progress_bar.add_css_class("osd"); + content.get_container().prepend(&progress_bar); // Add the Headerbar to the window. content.get_container().prepend(&header.container); - // Add the overlay to the main Box - wrap.append(&overlay); + // Add the deck to the main Box + wrap.append(&main_deck); let player = player::PlayerWrapper::new(&sender); // Add the player to the main Box @@ -104,7 +107,8 @@ impl MainWindow { wrap.append(&header.bottom_switcher); - adw::traits::ApplicationWindowExt::set_content(&window, Some(&wrap)); + toast_overlay.set_child(Some(&wrap)); + adw::traits::ApplicationWindowExt::set_content(&window, Some(&toast_overlay)); // Retrieve the previous window position and size. WindowGeometry::from_settings(&settings).apply(&window); @@ -128,13 +132,14 @@ impl MainWindow { Self { window, - overlay, headerbar: header, content, player, main_deck, + toast_overlay, + progress_bar: Rc::new(progress_bar), updating: Cell::new(false), - updater: RefCell::new(None), + updating_timeout: RefCell::new(None), sender: sender.clone(), } } -- 2.40.1 From f40f73b7a492cf5ebdc1439f0784a0da7ae47b30 Mon Sep 17 00:00:00 2001 From: Maximiliano Sandoval R Date: Fri, 10 Dec 2021 09:44:25 +0100 Subject: [PATCH 031/102] podcasts-gtk: Support dark mode api --- .../org.gnome.Podcasts.gschema.xml.in | 5 ---- podcasts-gtk/src/app.rs | 24 ------------------- 2 files changed, 29 deletions(-) diff --git a/podcasts-gtk/resources/org.gnome.Podcasts.gschema.xml.in b/podcasts-gtk/resources/org.gnome.Podcasts.gschema.xml.in index fc0fca1..1b94de4 100644 --- a/podcasts-gtk/resources/org.gnome.Podcasts.gschema.xml.in +++ b/podcasts-gtk/resources/org.gnome.Podcasts.gschema.xml.in @@ -23,11 +23,6 @@ Maximized state of the last open main window - - false - Enable or disable dark theme - - true Whether to periodically refresh content diff --git a/podcasts-gtk/src/app.rs b/podcasts-gtk/src/app.rs index f37bfde..0d333d3 100644 --- a/podcasts-gtk/src/app.rs +++ b/podcasts-gtk/src/app.rs @@ -120,9 +120,6 @@ impl ApplicationImpl for PdApplicationPrivate { utils::cleanup(cleanup_date); self.settings.replace(Some(settings)); - - let app = app.clone().downcast::().expect("How?"); - app.setup_timed_callbacks(); } } @@ -172,10 +169,6 @@ impl PdApplication { .expect("Application initialization failed...") } - fn setup_timed_callbacks(&self) { - self.setup_dark_theme(); - } - fn setup_gactions(&self) { let app = self.upcast_ref::(); let data = PdApplicationPrivate::from_instance(self); @@ -281,23 +274,6 @@ impl PdApplication { self.set_accels_for_action("win.refresh", &["r"]); } - fn setup_dark_theme(&self) { - let data = PdApplicationPrivate::from_instance(self); - if let Some(ref settings) = *data.settings.borrow() { - let gtk_settings = gtk::Settings::default().unwrap(); - settings - .bind( - "dark-theme", - >k_settings, - "gtk-application-prefer-dark-theme", - ) - .flags(gio::SettingsBindFlags::DEFAULT) - .build(); - } else { - debug_assert!(false, "Well how'd you manage that?"); - } - } - fn do_action(&self, action: Action) -> glib::Continue { let data = PdApplicationPrivate::from_instance(self); let w = data.window.borrow(); -- 2.40.1 From 360f8dd08dfaa0d69bd6fe1162cf45355f11be58 Mon Sep 17 00:00:00 2001 From: Maximiliano Sandoval R Date: Fri, 10 Dec 2021 22:44:57 +0100 Subject: [PATCH 032/102] episode_description: Wrap in scrolled window Wrap the entire view in a scrolled window. Before if the view overflowed the scrollbar would appear inside the Clamp instead of the edges of the view. --- .../resources/gtk/episode_description.ui | 139 +++++++++--------- 1 file changed, 68 insertions(+), 71 deletions(-) diff --git a/podcasts-gtk/resources/gtk/episode_description.ui b/podcasts-gtk/resources/gtk/episode_description.ui index bcefb81..0fd9131 100644 --- a/podcasts-gtk/resources/gtk/episode_description.ui +++ b/podcasts-gtk/resources/gtk/episode_description.ui @@ -32,6 +32,7 @@ Tobias Bernard 64 True + True vertical @@ -59,97 +60,93 @@ Tobias Bernard - + True - 700 + True + never - + True - vertical - top + 700 - - start - 18 - 18 - True + + True vertical + top - - 18 - 18 - - - 12 - False - False - 64 - image-x-generic-symbolic - - + + start + 18 + 18 + True + vertical - vertical - - - Podcast Title - True - word-char - 0 - - - + 18 + 18 - - Episode Title - True - word-char - 1 - 0 - + + 12 + False + False + 64 + image-x-generic-symbolic - - Duration - Date - 0 - + + vertical + + + Podcast Title + True + word-char + 0 + + + + + + Episode Title + True + word-char + 1 + 0 + + + + + + Duration - Date + 0 + + + - - - - - True - never - + + start + 18 + 18 + 18 True - - - start - 18 - 18 - 18 - True - Episode Description - True - 0 - - - + Episode Description + True + 0 + -- 2.40.1 From fefe9999cec44ccda43c246f35d1cc9e95ea5a0b Mon Sep 17 00:00:00 2001 From: Maximiliano Sandoval R Date: Wed, 29 Dec 2021 15:56:04 +0100 Subject: [PATCH 033/102] podcasts-gtk: Subclass BaseView and ShowWidget --- podcasts-gtk/resources/gtk/show_widget.ui | 172 +++++++++-------- podcasts-gtk/src/stacks/home.rs | 6 +- podcasts-gtk/src/stacks/populated.rs | 20 +- podcasts-gtk/src/widgets/base_view.rs | 109 ++++++++--- podcasts-gtk/src/widgets/home_view.rs | 2 +- podcasts-gtk/src/widgets/show.rs | 222 +++++++++++++--------- podcasts-gtk/src/widgets/shows_view.rs | 9 +- 7 files changed, 319 insertions(+), 221 deletions(-) diff --git a/podcasts-gtk/resources/gtk/show_widget.ui b/podcasts-gtk/resources/gtk/show_widget.ui index aba5a89..d4e1d9a 100644 --- a/podcasts-gtk/resources/gtk/show_widget.ui +++ b/podcasts-gtk/resources/gtk/show_widget.ui @@ -29,106 +29,116 @@ Tobias Bernard - - 32 - 32 - True - vertical - 6 + diff --git a/podcasts-gtk/src/stacks/home.rs b/podcasts-gtk/src/stacks/home.rs index 9de89c0..0eef163 100644 --- a/podcasts-gtk/src/stacks/home.rs +++ b/podcasts-gtk/src/stacks/home.rs @@ -45,7 +45,7 @@ impl HomeStack { let stack = gtk::Stack::new(); let state = State::Empty; - stack.add_named(episodes.view.container(), Some("home")); + stack.add_named(&episodes.view, Some("home")); stack.add_named(empty.deref(), Some("empty")); let home = HomeStack { @@ -65,7 +65,7 @@ impl HomeStack { pub(crate) fn update(&mut self) -> Result<()> { // Get the container of the view - let old = &self.episodes.view.container().clone(); + let old = &self.episodes.view; // Copy the vertical scrollbar adjustment from the old view. let vadj = self.episodes.view.vadjustment(); @@ -75,7 +75,7 @@ impl HomeStack { // during this the previous view is removed, // and the visible child falls back to empty view. self.stack.remove(old); - self.stack.add_named(eps.view.container(), Some("home")); + self.stack.add_named(&eps.view, Some("home")); // Keep the previous state. let s = self.state; // Set the visible child back to the previous one to avoid diff --git a/podcasts-gtk/src/stacks/populated.rs b/podcasts-gtk/src/stacks/populated.rs index 68ba768..9ea4361 100644 --- a/podcasts-gtk/src/stacks/populated.rs +++ b/podcasts-gtk/src/stacks/populated.rs @@ -42,7 +42,7 @@ pub(crate) enum PopulatedState { pub(crate) struct PopulatedStack { container: gtk::Box, populated: Rc, - show: Rc, + show: ShowWidget, stack: gtk::Stack, state: PopulatedState, sender: Sender, @@ -53,11 +53,11 @@ impl PopulatedStack { let stack = gtk::Stack::new(); let state = PopulatedState::View; let populated = ShowsView::new(sender.clone(), None); - let show = Rc::new(ShowWidget::default()); + let show = ShowWidget::default(); let container = gtk::Box::new(gtk::Orientation::Horizontal, 0); - stack.add_named(populated.view.container(), Some("shows")); - stack.add_named(show.view.container(), Some("widget")); + stack.add_named(&populated.view, Some("shows")); + stack.add_named(&show, Some("widget")); container.append(&stack); PopulatedStack { @@ -87,24 +87,23 @@ impl PopulatedStack { } pub(crate) fn replace_shows(&mut self) -> Result<()> { - let old = &self.populated.view.container().clone(); + let old = &self.populated.view.clone(); debug!("Name: {:?}", old.widget_name()); let vadj = self.populated.view.vadjustment(); let pop = ShowsView::new(self.sender.clone(), Some(vadj)); self.populated = pop; self.stack.remove(old); - self.stack - .add_named(self.populated.view.container(), Some("shows")); + self.stack.add_named(&self.populated.view, Some("shows")); Ok(()) } pub(crate) fn replace_widget(&mut self, pd: Arc) -> Result<()> { - let old = self.show.view.container().clone(); + let old = self.show.clone(); // Get the ShowWidget vertical alignment - let vadj = self.show.view.vadjustment(); + let vadj = self.show.view().vadjustment(); let new = match self.show.show_id() { // If the previous show was the same, restore the alignment Some(id) if id == pd.id() => ShowWidget::new(pd, self.sender.clone(), Some(vadj)), @@ -114,8 +113,7 @@ impl PopulatedStack { self.show = new; self.stack.remove(&old); - self.stack - .add_named(self.show.view.container(), Some("widget")); + self.stack.add_named(&self.show, Some("widget")); // The current visible child might change depending on // removal and insertion in the gtk::Stack, so we have diff --git a/podcasts-gtk/src/widgets/base_view.rs b/podcasts-gtk/src/widgets/base_view.rs index 1c3a001..3abb4f5 100644 --- a/podcasts-gtk/src/widgets/base_view.rs +++ b/podcasts-gtk/src/widgets/base_view.rs @@ -18,41 +18,94 @@ // SPDX-License-Identifier: GPL-3.0-or-later use crate::utils::smooth_scroll_to; -use gtk::{prelude::*, Adjustment, Orientation, PolicyType}; -#[derive(Debug, Clone)] -pub(crate) struct BaseView { - container: gtk::Box, - scrolled_window: gtk::ScrolledWindow, +use gtk::glib; +use gtk::prelude::*; +use gtk::subclass::prelude::*; +use gtk::{Adjustment, PolicyType}; + +use adw::prelude::*; +use adw::subclass::prelude::*; + +use once_cell::sync::Lazy; + +#[derive(Debug, Default)] +pub struct BaseViewPriv { + pub scrolled_window: gtk::ScrolledWindow, } -impl Default for BaseView { - fn default() -> Self { - let container = gtk::Box::new(Orientation::Horizontal, 0); - let scrolled_window = gtk::ScrolledWindow::new(); +#[glib::object_subclass] +impl ObjectSubclass for BaseViewPriv { + const NAME: &'static str = "PdBaseView"; + type Type = super::BaseView; + type ParentType = adw::Bin; +} - scrolled_window.set_policy(PolicyType::Never, PolicyType::Automatic); - container.set_size_request(360, -1); - container.append(&scrolled_window); +impl ObjectImpl for BaseViewPriv { + fn constructed(&self, obj: &Self::Type) { + self.parent_constructed(obj); - BaseView { - container, - scrolled_window, + self.scrolled_window + .set_policy(PolicyType::Never, PolicyType::Automatic); + obj.set_size_request(360, -1); + obj.set_child(Some(&self.scrolled_window)); + } + + fn properties() -> &'static [glib::ParamSpec] { + static PROPERTIES: Lazy> = Lazy::new(|| { + vec![glib::ParamSpec::new_object( + "child", + "child", + "child", + gtk::Widget::static_type(), + glib::ParamFlags::READWRITE, + )] + }); + PROPERTIES.as_ref() + } + + fn property(&self, _obj: &Self::Type, _id: usize, pspec: &glib::ParamSpec) -> glib::Value { + match pspec.name() { + "child" => self.scrolled_window.child().to_value(), + _ => unimplemented!(), } } -} -impl BaseView { - pub(crate) fn container(&self) -> >k::Box { - &self.container + fn set_property( + &self, + _obj: &Self::Type, + _id: usize, + value: &glib::Value, + pspec: &glib::ParamSpec, + ) { + match pspec.name() { + "child" => self + .scrolled_window + .set_child(value.get::().ok().as_ref()), + _ => unimplemented!(), + }; } +} + +impl WidgetImpl for BaseViewPriv {} +impl BinImpl for BaseViewPriv {} - pub(crate) fn scrolled_window(&self) -> >k::ScrolledWindow { - &self.scrolled_window +glib::wrapper! { + pub struct BaseView(ObjectSubclass) + @extends gtk::Widget, adw::Bin; +} + +impl Default for BaseView { + fn default() -> Self { + glib::Object::new(&[]).unwrap() } +} + +impl BaseView { + pub(crate) fn set_content>(&self, widget: &T) { + let self_ = BaseViewPriv::from_instance(&self); - pub(crate) fn set_child>(&self, widget: &T) { - self.scrolled_window.set_child(Some(widget)); + self_.scrolled_window.set_child(Some(widget)); } pub(crate) fn set_adjustments( @@ -60,16 +113,20 @@ impl BaseView { hadjustment: Option<&Adjustment>, vadjustment: Option<&Adjustment>, ) { + let self_ = BaseViewPriv::from_instance(&self); + if let Some(h) = hadjustment { - smooth_scroll_to(&self.scrolled_window, h); + smooth_scroll_to(&self_.scrolled_window, h); } if let Some(v) = vadjustment { - smooth_scroll_to(&self.scrolled_window, v); + smooth_scroll_to(&self_.scrolled_window, v); } } pub(crate) fn vadjustment(&self) -> Adjustment { - self.scrolled_window().vadjustment().unwrap() + let self_ = BaseViewPriv::from_instance(&self); + + self_.scrolled_window.vadjustment().unwrap() } } diff --git a/podcasts-gtk/src/widgets/home_view.rs b/podcasts-gtk/src/widgets/home_view.rs index 2f452e1..ab0c875 100644 --- a/podcasts-gtk/src/widgets/home_view.rs +++ b/podcasts-gtk/src/widgets/home_view.rs @@ -81,7 +81,7 @@ impl Default for HomeView { clamp.set_maximum_size(700); clamp.set_child(Some(&frame_parent)); - view.set_child(&clamp); + view.set_content(&clamp); HomeView { view, diff --git a/podcasts-gtk/src/widgets/show.rs b/podcasts-gtk/src/widgets/show.rs index 636098d..fdfaba8 100644 --- a/podcasts-gtk/src/widgets/show.rs +++ b/podcasts-gtk/src/widgets/show.rs @@ -19,9 +19,8 @@ use glib::clone; use glib::Sender; -use gtk::{prelude::*, Adjustment}; +use gtk::Adjustment; -use adw::Clamp; use anyhow::Result; use crossbeam_channel::bounded; use fragile::Fragile; @@ -34,53 +33,69 @@ use crate::app::Action; use crate::utils::{self, lazy_load}; use crate::widgets::{BaseView, EmptyShow, EpisodeWidget, ShowMenu}; +use std::cell::Cell; use std::ops::Deref; -use std::rc::Rc; use std::sync::Arc; -#[derive(Debug, Clone)] -pub(crate) struct ShowWidget { - pub(crate) view: BaseView, - cover: gtk::Image, - description: gtk::Label, - description_short: gtk::Label, - description_stack: gtk::Stack, - description_button: gtk::Button, - description_button_revealer: gtk::Revealer, - episodes: gtk::ListBox, - show_id: Option, +use gtk::glib; +use gtk::subclass::prelude::*; +use gtk::{prelude::*, CompositeTemplate}; + +#[derive(Debug, Default, CompositeTemplate)] +#[template(resource = "/org/gnome/Podcasts/gtk/show_widget.ui")] +pub struct ShowWidgetPriv { + #[template_child] + pub cover: TemplateChild, + #[template_child] + pub description: TemplateChild, + #[template_child] + pub description_short: TemplateChild, + #[template_child] + pub description_stack: TemplateChild, + #[template_child] + pub description_button: TemplateChild, + #[template_child] + pub description_button_revealer: TemplateChild, + #[template_child] + pub episodes: TemplateChild, + #[template_child] + pub(crate) view: TemplateChild, + + pub show_id: Cell>, +} + +#[glib::object_subclass] +impl ObjectSubclass for ShowWidgetPriv { + const NAME: &'static str = "PdShowWidget"; + type Type = super::ShowWidget; + type ParentType = gtk::Widget; + + fn class_init(klass: &mut Self::Class) { + Self::bind_template(klass); + klass.set_layout_manager_type::(); + } + + fn instance_init(obj: &glib::subclass::InitializingObject) { + obj.init_template(); + } +} + +impl ObjectImpl for ShowWidgetPriv { + fn dispose(&self, _obj: &Self::Type) { + self.view.unparent(); + } +} + +impl WidgetImpl for ShowWidgetPriv {} + +glib::wrapper! { + pub struct ShowWidget(ObjectSubclass) + @extends gtk::Widget; } impl Default for ShowWidget { fn default() -> Self { - let builder = gtk::Builder::from_resource("/org/gnome/Podcasts/gtk/show_widget.ui"); - let sub_cont: gtk::Box = builder.object("sub_container").unwrap(); - let cover: gtk::Image = builder.object("cover").unwrap(); - let description: gtk::Label = builder.object("description").unwrap(); - let description_short: gtk::Label = builder.object("description_short").unwrap(); - let description_stack: gtk::Stack = builder.object("description_stack").unwrap(); - let description_button: gtk::Button = builder.object("description_button").unwrap(); - let description_button_revealer = builder.object("description_button_revealer").unwrap(); - let episodes: gtk::ListBox = builder.object("episodes").unwrap(); - let view = BaseView::default(); - - let clamp = Clamp::new(); - clamp.set_maximum_size(700); - - clamp.set_child(Some(&sub_cont)); - view.set_child(&clamp); - - ShowWidget { - view, - cover, - description, - description_short, - description_stack, - description_button, - description_button_revealer, - episodes, - show_id: None, - } + glib::Object::new(&[]).unwrap() } } @@ -89,74 +104,90 @@ impl ShowWidget { pd: Arc, sender: Sender, vadj: Option, - ) -> Rc { - let mut pdw = ShowWidget::default(); + ) -> ShowWidget { + let pdw = ShowWidget::default(); + let pdw_ = ShowWidgetPriv::from_instance(&pdw); pdw.init(&pd); - let menu = ShowMenu::new(&pd, &pdw.episodes, &sender); + let menu = ShowMenu::new(&pd, &pdw_.episodes, &sender); send!(sender, Action::InitSecondaryMenu(Fragile::new(menu.menu))); - let pdw = Rc::new(pdw); let res = populate_listbox(&pdw, pd, sender, vadj); debug_assert!(res.is_ok()); - pdw.update_read_more(); - - pdw.description_button + pdw_.description_button .connect_clicked(clone!(@weak pdw => move |_| { - pdw.description_stack.set_visible_child_name("full"); + let pdw_ = ShowWidgetPriv::from_instance(&pdw); + + pdw_.description_stack.set_visible_child_name("full"); })); pdw } - pub(crate) fn init(&mut self, pd: &Arc) { + pub(crate) fn init(&self, pd: &Arc) { + let self_ = ShowWidgetPriv::from_instance(self); + self.set_description(pd.description()); - self.show_id = Some(pd.id()); + self_.show_id.set(Some(pd.id())); let res = self.set_cover(&pd); + debug_assert!(res.is_ok()); } /// Set the show cover. fn set_cover(&self, pd: &Arc) -> Result<()> { - utils::set_image_from_path(&self.cover, pd.id(), 256) + let self_ = ShowWidgetPriv::from_instance(self); + + utils::set_image_from_path(&self_.cover, pd.id(), 256) } fn update_read_more(&self) { - let layout = self.description_short.layout(); - let more = - layout.is_ellipsized() || self.description.label() != self.description_short.label(); - self.description_button_revealer.set_reveal_child(more); + let self_ = ShowWidgetPriv::from_instance(self); + + let more = self_.description.label() != self_.description_short.label(); + self_.description_button_revealer.set_reveal_child(more); } /// Set the description text. fn set_description(&self, text: &str) { + let self_ = ShowWidgetPriv::from_instance(self); + let markup = html2text::from_read(text.as_bytes(), text.as_bytes().len()); let markup = markup.trim(); let lines: Vec<&str> = markup.lines().collect(); if markup.is_empty() { - self.description_stack.set_visible(false); + self_.description_stack.set_visible(false); } else { - self.description_stack.set_visible(true); + self_.description_stack.set_visible(true); - self.description.set_markup(markup); + self_.description.set_markup(markup); debug_assert!(!lines.is_empty()); if !lines.is_empty() { - self.description_short.set_markup(lines[0]); + self_.description_short.set_markup(lines[0]); + self.update_read_more() } } } pub(crate) fn show_id(&self) -> Option { - self.show_id + let self_ = ShowWidgetPriv::from_instance(self); + + self_.show_id.get() + } + + pub(crate) fn view(&self) -> BaseView { + let self_ = ShowWidgetPriv::from_instance(self); + + self_.view.clone() } } /// Populate the listbox with the shows episodes. fn populate_listbox( - show: &Rc, + show: &ShowWidget, pd: Arc, sender: Sender, vadj: Option, @@ -164,6 +195,7 @@ fn populate_listbox( use crossbeam_channel::TryRecvError; let count = dbqueries::get_pd_episodes_count(&pd)?; + let show_ = ShowWidgetPriv::from_instance(show); let (sender_, receiver) = bounded(1); tokio::spawn(clone!(@strong pd => async move { @@ -176,43 +208,43 @@ fn populate_listbox( if count == 0 { let empty = EmptyShow::default(); - show.episodes.append(empty.deref()); + show_.episodes.append(empty.deref()); return Ok(()); } - let show_weak = Rc::downgrade(&show); - let list_weak = show.episodes.downgrade(); - - glib::idle_add_local(move || { - let episodes = match receiver.try_recv() { - Ok(e) => e, - Err(TryRecvError::Empty) => return glib::Continue(true), - Err(TryRecvError::Disconnected) => return glib::Continue(false), - }; - - debug_assert!(episodes.len() as i64 == count); - - let constructor = clone!(@strong sender => move |ep: EpisodeWidgetModel| { - let id = ep.rowid(); - let episode_widget = EpisodeWidget::new(ep, &sender).container.clone(); - let row = gtk::ListBoxRow::new(); - row.set_child(Some(&episode_widget)); - row.set_action_name(Some("app.go-to-episode")); - row.set_action_target_value(Some(&id.to_variant())); - row - }); - - let callback = clone!(@strong show_weak, @strong vadj => move || { - if let (Some(ref shows), Some(ref v)) = (show_weak.upgrade(), &vadj) - { - shows.view.set_adjustments(None, Some(v)) - } - }); + let list_weak = show_.episodes.downgrade(); + + glib::idle_add_local( + glib::clone!(@weak show => @default-return glib::Continue(false), move || { + let episodes = match receiver.try_recv() { + Ok(e) => e, + Err(TryRecvError::Empty) => return glib::Continue(true), + Err(TryRecvError::Disconnected) => return glib::Continue(false), + }; + + debug_assert!(episodes.len() as i64 == count); + + let constructor = clone!(@strong sender => move |ep: EpisodeWidgetModel| { + let id = ep.rowid(); + let episode_widget = EpisodeWidget::new(ep, &sender).container.clone(); + let row = gtk::ListBoxRow::new(); + row.set_child(Some(&episode_widget)); + row.set_action_name(Some("app.go-to-episode")); + row.set_action_target_value(Some(&id.to_variant())); + row + }); + + let callback = clone!(@weak show, @strong vadj => move || { + let show_ = ShowWidgetPriv::from_instance(&show); + + show_.view.set_adjustments(None, vadj.as_ref()); + }); - lazy_load(episodes, list_weak.clone(), constructor, callback); + lazy_load(episodes, list_weak.clone(), constructor, callback); - glib::Continue(false) - }); + glib::Continue(false) + }), + ); Ok(()) } diff --git a/podcasts-gtk/src/widgets/shows_view.rs b/podcasts-gtk/src/widgets/shows_view.rs index 8b48c47..fa1a6c4 100644 --- a/podcasts-gtk/src/widgets/shows_view.rs +++ b/podcasts-gtk/src/widgets/shows_view.rs @@ -59,7 +59,7 @@ impl Default for ShowsView { flowbox.set_valign(Align::Start); flowbox.set_halign(Align::Center); flowbox.set_selection_mode(SelectionMode::None); - view.set_child(&flowbox); + view.set_content(&flowbox); ShowsView { view, flowbox } } @@ -164,12 +164,13 @@ impl ShowCover { } fn id(&self) -> i32 { - self.imp().show_id.get() + let self_ = ShowCoverPrivate::from_instance(self); + self_.show_id.get() } fn load_image(&self) -> Result<()> { - let imp = self.imp(); - set_image_from_path(&imp.cover, imp.show_id.get(), 256)?; + let self_ = ShowCoverPrivate::from_instance(self); + set_image_from_path(&self_.cover, self_.show_id.get(), 256)?; Ok(()) } } -- 2.40.1 From e4e7587a377798a26ca022eec24da49956cb2204 Mon Sep 17 00:00:00 2001 From: Maximiliano Sandoval R Date: Thu, 30 Dec 2021 18:42:50 +0100 Subject: [PATCH 034/102] wip, figur out what's wrong and fix commit message: Detect if short description is ellipsized This sucks. is_ellipsized has to be called during allocation, but for some reason implementing the allocation directly on the ShortDesc widget won't work correctly. --- podcasts-gtk/resources/gtk/show_widget.ui | 10 +-- podcasts-gtk/src/meson.build | 2 + podcasts-gtk/src/widgets/mod.rs | 4 + podcasts-gtk/src/widgets/short_desc.rs | 81 +++++++++++++++++++ podcasts-gtk/src/widgets/short_desc_layout.rs | 65 +++++++++++++++ podcasts-gtk/src/widgets/show.rs | 26 ++++-- 6 files changed, 173 insertions(+), 15 deletions(-) create mode 100644 podcasts-gtk/src/widgets/short_desc.rs create mode 100644 podcasts-gtk/src/widgets/short_desc_layout.rs diff --git a/podcasts-gtk/resources/gtk/show_widget.ui b/podcasts-gtk/resources/gtk/show_widget.ui index d4e1d9a..37e9c4d 100644 --- a/podcasts-gtk/resources/gtk/show_widget.ui +++ b/podcasts-gtk/resources/gtk/show_widget.ui @@ -73,17 +73,9 @@ Tobias Bernard short - fill vertical - - center - center - True - center - True - word-char - + diff --git a/podcasts-gtk/src/meson.build b/podcasts-gtk/src/meson.build index f9e7ad3..4b394ac 100644 --- a/podcasts-gtk/src/meson.build +++ b/podcasts-gtk/src/meson.build @@ -34,6 +34,8 @@ podcasts_sources = files( 'widgets/show.rs', 'widgets/show_menu.rs', 'widgets/shows_view.rs', + 'widgets/short_desc.rs', + 'widgets/short_desc_layout.rs', 'app.rs', 'episode_description_parser.rs', 'headerbar.rs', diff --git a/podcasts-gtk/src/widgets/mod.rs b/podcasts-gtk/src/widgets/mod.rs index ea3e9bb..9e2ebab 100644 --- a/podcasts-gtk/src/widgets/mod.rs +++ b/podcasts-gtk/src/widgets/mod.rs @@ -25,6 +25,8 @@ mod episode_description; pub(crate) mod episode_menu; mod home_view; pub(crate) mod player; +mod short_desc; +mod short_desc_layout; mod show; pub(crate) mod show_menu; mod shows_view; @@ -36,6 +38,8 @@ pub(crate) use self::episode::EpisodeWidget; pub(crate) use self::episode_description::EpisodeDescription; pub(crate) use self::episode_menu::EpisodeMenu; pub(crate) use self::home_view::HomeView; +pub(crate) use self::short_desc::ShortDesc; +pub(crate) use self::short_desc_layout::ShortDescLayout; pub(crate) use self::show::ShowWidget; pub(crate) use self::show_menu::ShowMenu; pub(crate) use self::shows_view::ShowsView; diff --git a/podcasts-gtk/src/widgets/short_desc.rs b/podcasts-gtk/src/widgets/short_desc.rs new file mode 100644 index 0000000..b588965 --- /dev/null +++ b/podcasts-gtk/src/widgets/short_desc.rs @@ -0,0 +1,81 @@ +use glib::subclass::Signal; +use gtk::glib; +use gtk::prelude::*; +use gtk::subclass::prelude::*; + +use once_cell::sync::Lazy; + +use crate::widgets::ShortDescLayout; + +#[derive(Debug, Default)] +pub struct ShortDescPriv { + pub label: gtk::Label, +} + +#[glib::object_subclass] +impl ObjectSubclass for ShortDescPriv { + const NAME: &'static str = "PdShortDesc"; + type Type = ShortDesc; + type ParentType = gtk::Widget; +} + +impl ObjectImpl for ShortDescPriv { + fn signals() -> &'static [Signal] { + static SIGNALS: Lazy> = Lazy::new(|| { + vec![Signal::builder( + "is-ellipsized", + &[::static_type().into()], + <()>::static_type().into(), + ) + .flags(glib::SignalFlags::ACTION) + .build()] + }); + SIGNALS.as_ref() + } + + fn constructed(&self, obj: &Self::Type) { + self.parent_constructed(obj); + self.label.set_parent(obj); + + self.label.set_valign(gtk::Align::Center); + self.label.set_halign(gtk::Align::Center); + self.label.set_use_markup(true); + self.label.set_wrap(true); + self.label.set_lines(4); + self.label.set_wrap_mode(gtk::pango::WrapMode::WordChar); + self.label.set_justify(gtk::Justification::Center); + self.label.set_ellipsize(gtk::pango::EllipsizeMode::End); + + let layout = ShortDescLayout::default(); + obj.set_layout_manager(Some(&layout)); + } + + fn dispose(&self, _obj: &Self::Type) { + self.label.unparent(); + } +} + +impl WidgetImpl for ShortDescPriv {} + +glib::wrapper! { + pub struct ShortDesc(ObjectSubclass) + @extends gtk::Widget; +} + +impl Default for ShortDesc { + fn default() -> Self { + glib::Object::new(&[]).unwrap() + } +} + +impl ShortDesc { + pub fn label(&self) -> glib::GString { + let self_ = ShortDescPriv::from_instance(self); + self_.label.label() + } + + pub fn set_label(&self, label: &str) { + let self_ = ShortDescPriv::from_instance(self); + self_.label.set_markup(label); + } +} diff --git a/podcasts-gtk/src/widgets/short_desc_layout.rs b/podcasts-gtk/src/widgets/short_desc_layout.rs new file mode 100644 index 0000000..ae7193c --- /dev/null +++ b/podcasts-gtk/src/widgets/short_desc_layout.rs @@ -0,0 +1,65 @@ +use gtk::glib; +use gtk::prelude::*; +use gtk::subclass::prelude::*; + +#[derive(Debug, Default)] +pub struct ShortDescLayoutPriv {} + +#[glib::object_subclass] +impl ObjectSubclass for ShortDescLayoutPriv { + const NAME: &'static str = "PdShortDescLayout"; + type Type = ShortDescLayout; + type ParentType = gtk::LayoutManager; +} + +impl ObjectImpl for ShortDescLayoutPriv {} +impl LayoutManagerImpl for ShortDescLayoutPriv { + fn allocate( + &self, + _layout_manager: &Self::Type, + widget: >k::Widget, + width: i32, + height: i32, + baseline: i32, + ) { + if let Some(label) = widget.first_child() { + if label.is_visible() { + label.allocate(width, height, baseline, None); + + let value = label + .downcast::() + .unwrap() + .layout() + .is_ellipsized() + .to_value(); + widget.emit_by_name("is-ellipsized", &[&value]).unwrap(); + } + } + } + fn measure( + &self, + _layout_manager: &Self::Type, + widget: >k::Widget, + orientation: gtk::Orientation, + for_size: i32, + ) -> (i32, i32, i32, i32) { + if let Some(label) = widget.first_child() { + label.measure(orientation, for_size) + } else { + (0, 0, -1, -1) + } + } +} + +glib::wrapper! { + pub struct ShortDescLayout(ObjectSubclass) + @extends gtk::LayoutManager; +} + +impl Default for ShortDescLayout { + fn default() -> Self { + glib::Object::new(&[]).unwrap() + } +} + +impl ShortDescLayout {} diff --git a/podcasts-gtk/src/widgets/show.rs b/podcasts-gtk/src/widgets/show.rs index fdfaba8..2b5efcc 100644 --- a/podcasts-gtk/src/widgets/show.rs +++ b/podcasts-gtk/src/widgets/show.rs @@ -31,7 +31,7 @@ use podcasts_data::Show; use crate::app::Action; use crate::utils::{self, lazy_load}; -use crate::widgets::{BaseView, EmptyShow, EpisodeWidget, ShowMenu}; +use crate::widgets::{BaseView, EmptyShow, EpisodeWidget, ShortDesc, ShowMenu}; use std::cell::Cell; use std::ops::Deref; @@ -49,7 +49,7 @@ pub struct ShowWidgetPriv { #[template_child] pub description: TemplateChild, #[template_child] - pub description_short: TemplateChild, + pub description_short: TemplateChild, #[template_child] pub description_stack: TemplateChild, #[template_child] @@ -81,6 +81,21 @@ impl ObjectSubclass for ShowWidgetPriv { } impl ObjectImpl for ShowWidgetPriv { + fn constructed(&self, obj: &Self::Type) { + self.parent_constructed(obj); + self.description_short + .connect_local( + "is-ellipsized", + false, + clone!(@weak obj => @default-return None, move |args| { + let is_ellipsized = args[1].get().unwrap(); + obj.update_read_more(is_ellipsized); + None + }), + ) + .unwrap(); + } + fn dispose(&self, _obj: &Self::Type) { self.view.unparent(); } @@ -143,10 +158,10 @@ impl ShowWidget { utils::set_image_from_path(&self_.cover, pd.id(), 256) } - fn update_read_more(&self) { + fn update_read_more(&self, is_ellipsized: bool) { let self_ = ShowWidgetPriv::from_instance(self); - let more = self_.description.label() != self_.description_short.label(); + let more = is_ellipsized || self_.description.label() != self_.description_short.label(); self_.description_button_revealer.set_reveal_child(more); } @@ -166,8 +181,7 @@ impl ShowWidget { self_.description.set_markup(markup); debug_assert!(!lines.is_empty()); if !lines.is_empty() { - self_.description_short.set_markup(lines[0]); - self.update_read_more() + self_.description_short.set_label(lines[0]); } } } -- 2.40.1 From e881d58a78764fef7f18fb17558b3beb427072db Mon Sep 17 00:00:00 2001 From: Maximiliano Sandoval R Date: Sun, 2 Jan 2022 21:12:00 +0100 Subject: [PATCH 035/102] podcasts-gtk: Round cover images --- podcasts-gtk/resources/gtk/episode_description.ui | 4 ++++ podcasts-gtk/resources/gtk/home_episode.ui | 7 ++++++- podcasts-gtk/resources/gtk/player_dialog.ui | 4 ++++ podcasts-gtk/resources/gtk/player_toolbar.ui | 8 ++++++++ podcasts-gtk/resources/gtk/show_widget.ui | 5 +++++ podcasts-gtk/resources/gtk/style.css | 8 ++++++++ podcasts-gtk/src/widgets/shows_view.rs | 2 ++ 7 files changed, 37 insertions(+), 1 deletion(-) diff --git a/podcasts-gtk/resources/gtk/episode_description.ui b/podcasts-gtk/resources/gtk/episode_description.ui index 0fd9131..b51fc8e 100644 --- a/podcasts-gtk/resources/gtk/episode_description.ui +++ b/podcasts-gtk/resources/gtk/episode_description.ui @@ -91,6 +91,10 @@ Tobias Bernard False 64 image-x-generic-symbolic + hidden + diff --git a/podcasts-gtk/resources/gtk/home_episode.ui b/podcasts-gtk/resources/gtk/home_episode.ui index ad8f6c4..2b9aab6 100644 --- a/podcasts-gtk/resources/gtk/home_episode.ui +++ b/podcasts-gtk/resources/gtk/home_episode.ui @@ -31,13 +31,18 @@ Tobias Bernard center + 6 + 6 6 6 - 8 64 image-x-generic-symbolic + hidden + diff --git a/podcasts-gtk/resources/gtk/player_dialog.ui b/podcasts-gtk/resources/gtk/player_dialog.ui index bc0bcb6..9103f0f 100644 --- a/podcasts-gtk/resources/gtk/player_dialog.ui +++ b/podcasts-gtk/resources/gtk/player_dialog.ui @@ -50,6 +50,10 @@ 6 center gtk-missing-image + hidden + diff --git a/podcasts-gtk/resources/gtk/player_toolbar.ui b/podcasts-gtk/resources/gtk/player_toolbar.ui index b0bf546..b9b161f 100644 --- a/podcasts-gtk/resources/gtk/player_toolbar.ui +++ b/podcasts-gtk/resources/gtk/player_toolbar.ui @@ -101,6 +101,10 @@ Tobias Bernard center 34 image-x-generic-symbolic + hidden + @@ -206,6 +210,10 @@ Tobias Bernard center 34 image-x-generic-symbolic + hidden + diff --git a/podcasts-gtk/resources/gtk/show_widget.ui b/podcasts-gtk/resources/gtk/show_widget.ui index 37e9c4d..45520c0 100644 --- a/podcasts-gtk/resources/gtk/show_widget.ui +++ b/podcasts-gtk/resources/gtk/show_widget.ui @@ -52,7 +52,12 @@ Tobias Bernard 256 + center image-x-generic-symbolic + hidden + diff --git a/podcasts-gtk/resources/gtk/style.css b/podcasts-gtk/resources/gtk/style.css index 9ca86aa..b23f4bf 100644 --- a/podcasts-gtk/resources/gtk/style.css +++ b/podcasts-gtk/resources/gtk/style.css @@ -42,3 +42,11 @@ popover modelbutton > box > label { .episode_description .episode_duration_date { color: @insensitive_fg_color; } + +.rounded-big { + border-radius: 8px; +} + +.rounded-small { + border-radius: 4px; +} diff --git a/podcasts-gtk/src/widgets/shows_view.rs b/podcasts-gtk/src/widgets/shows_view.rs index fa1a6c4..6aed4dc 100644 --- a/podcasts-gtk/src/widgets/shows_view.rs +++ b/podcasts-gtk/src/widgets/shows_view.rs @@ -140,6 +140,8 @@ impl ObjectImpl for ShowCoverPrivate { fn constructed(&self, obj: &Self::Type) { self.parent_constructed(obj); self.cover.set_pixel_size(256); + self.cover.add_css_class("rounded-big"); + self.cover.set_overflow(gtk::Overflow::Hidden); obj.set_child(Some(&self.cover)); } -- 2.40.1 From 920c122c5b76f604dd34cc1bfe6b779199847d8c Mon Sep 17 00:00:00 2001 From: Maximiliano Sandoval R Date: Mon, 7 Feb 2022 21:45:30 +0100 Subject: [PATCH 036/102] Update gtk-rs stack --- Cargo.lock | 877 ++++++++++-------- podcasts-gtk/Cargo.toml | 12 +- podcasts-gtk/src/app.rs | 5 +- podcasts-gtk/src/stacks/content.rs | 9 +- podcasts-gtk/src/utils.rs | 2 +- podcasts-gtk/src/widgets/aboutdialog.rs | 64 +- podcasts-gtk/src/widgets/base_view.rs | 4 +- podcasts-gtk/src/widgets/player.rs | 2 +- podcasts-gtk/src/widgets/short_desc_layout.rs | 2 +- podcasts-gtk/src/widgets/show.rs | 52 +- podcasts-gtk/src/widgets/shows_view.rs | 2 +- podcasts-gtk/src/window.rs | 4 +- 12 files changed, 542 insertions(+), 493 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 35756f2..aae2d86 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -13,15 +13,14 @@ dependencies = [ [[package]] name = "ammonia" -version = "3.1.2" +version = "3.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e445c26125ff80316eaea16e812d717b147b82a68682bd4730f74d4845c8b35" +checksum = "ea9f21d23d82bae9d33c21080572af1fa749788e68234b5d8fa5e39d3e0783ed" dependencies = [ "html5ever", "lazy_static", "maplit", "markup5ever_rcdom", - "matches", "tendril", "url", ] @@ -37,9 +36,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.52" +version = "1.0.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84450d0b4a8bd1ba4144ce8ce718fbc5d071358b1e5384bace6536b3d1f2d5b3" +checksum = "4361135be9122e0870de935d7c439aef945b9f9ddd4199a553b5270b49c82a27" [[package]] name = "atom_syndication" @@ -67,9 +66,9 @@ dependencies = [ [[package]] name = "autocfg" -version = "1.0.1" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "base64" @@ -85,9 +84,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bumpalo" -version = "3.8.0" +version = "3.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f1e260c3a9040a7c19a12468758f4c16f31a81a1fe087482be9570ec864bb6c" +checksum = "a4a45a46ab1f2412e53d3a0ade76ffad2025804294569aae387231a0cd6e0899" [[package]] name = "byteorder" @@ -103,48 +102,39 @@ checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8" [[package]] name = "cairo-rs" -version = "0.14.9" +version = "0.15.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33b5725979db0c586d98abad2193cdb612dd40ef95cd26bd99851bf93b3cb482" +checksum = "129e928d3eda625f53ce257589efbe5143416875fd01bddd08c8c6feb8b9962b" dependencies = [ "bitflags", "cairo-sys-rs", - "glib 0.14.8", + "glib 0.15.10", "libc", "thiserror", ] [[package]] name = "cairo-sys-rs" -version = "0.14.9" +version = "0.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b448b876970834fda82ba3aeaccadbd760206b75388fc5c1b02f1e343b697570" +checksum = "3c55d429bef56ac9172d25fecb85dc8068307d17acd74b377866b7a1ef25d3c8" dependencies = [ - "glib-sys 0.14.0", + "glib-sys 0.15.10", "libc", - "system-deps 3.2.0", + "system-deps 6.0.2", ] [[package]] name = "cc" -version = "1.0.72" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22a9137b95ea06864e018375b72adfb7db6e6f68cfc8df5a04d00288050485ee" - -[[package]] -name = "cfg-expr" -version = "0.8.1" +version = "1.0.73" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b412e83326147c2bb881f8b40edfbf9905b9b8abaebd0e47ca190ba62fda8f0e" -dependencies = [ - "smallvec", -] +checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11" [[package]] name = "cfg-expr" -version = "0.9.0" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edae0b9625d1fce32f7d64b71784d9b1bf8469ec1a9c417e44aaf16a9cbd7571" +checksum = "5e068cb2806bbc15b439846dc16c5f89f8599f2c3e4d73d4449d38f9b2f0b6c5" dependencies = [ "smallvec", ] @@ -170,9 +160,9 @@ dependencies = [ [[package]] name = "core-foundation" -version = "0.9.2" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6888e10551bb93e424d8df1d07f1a8b4fceb0001a3a4b048bfc47554946f47b3" +checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" dependencies = [ "core-foundation-sys", "libc", @@ -186,9 +176,9 @@ checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" [[package]] name = "crossbeam-channel" -version = "0.5.1" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06ed27e177f16d65f0f0c22a213e17c696ace5dd64b14258b52f9417ccb52db4" +checksum = "5aaa7bd5fb665c6864b5f963dd9097905c54125909c7aa94c9e18507cdbe6c53" dependencies = [ "cfg-if", "crossbeam-utils", @@ -207,10 +197,11 @@ dependencies = [ [[package]] name = "crossbeam-epoch" -version = "0.9.5" +version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ec02e091aa634e2c3ada4a392989e7c3116673ef0ac5b72232439094d73b7fd" +checksum = "1145cf131a2c6ba0615079ab6a638f7e1973ac9c2634fcbeaaad6114246efe8c" dependencies = [ + "autocfg", "cfg-if", "crossbeam-utils", "lazy_static", @@ -220,9 +211,9 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.8.5" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d82cfc11ce7f2c3faef78d8a684447b40d503d9681acebed6cb728d45940c4db" +checksum = "0bf124c720b7686e3c2663cf54062ab0f68a88af2fb6a030e87e30bf721fcb38" dependencies = [ "cfg-if", "lazy_static", @@ -230,9 +221,9 @@ dependencies = [ [[package]] name = "ctor" -version = "0.1.21" +version = "0.1.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccc0a48a9b826acdf4028595adc9db92caea352f7af011a3034acd172a52a0aa" +checksum = "f877be4f7c9f246b183111634f75baa039715e3f46ce860677d3b19a69fb229c" dependencies = [ "quote", "syn", @@ -425,18 +416,18 @@ dependencies = [ [[package]] name = "dirs" -version = "3.0.2" +version = "4.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30baa043103c9d0c2a57cf537cc2f35623889dc0d405e6c3cccfadbc81c71309" +checksum = "ca3aa72a6f96ea37bbc5aa912f6788242832f75369bdfdadcb0e38423f100059" dependencies = [ "dirs-sys", ] [[package]] name = "dirs-sys" -version = "0.3.6" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03d86534ed367a67548dc68113a0f5db55432fdfbb6e6f9d77704397d95d5780" +checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6" dependencies = [ "libc", "redox_users", @@ -451,9 +442,9 @@ checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" [[package]] name = "encoding_rs" -version = "0.8.30" +version = "0.8.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7896dc8abb250ffdda33912550faa54c88ec8b998dec0b2c55ab224921ce11df" +checksum = "9852635589dc9f9ea1b6fe9f05b50ef208c85c834a562f0c6abb1c475736ec2b" dependencies = [ "cfg-if", ] @@ -471,6 +462,15 @@ dependencies = [ "termcolor", ] +[[package]] +name = "fastrand" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3fcf0cee53519c866c09b5de1f6c56ff9d647101f81c1964fa632e148896cdf" +dependencies = [ + "instant", +] + [[package]] name = "field-offset" version = "0.3.4" @@ -514,9 +514,9 @@ dependencies = [ [[package]] name = "fragile" -version = "1.0.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69a039c3498dc930fe810151a34ba0c1c70b02b8625035592e74432f678591f2" +checksum = "e9d758e60b45e8d749c89c1b389ad8aee550f86aa12e2b9298b546dda7a82ab1" [[package]] name = "fuchsia-cprng" @@ -526,9 +526,9 @@ checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" [[package]] name = "futf" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c9c1ce3fa9336301af935ab852c437817d14cd33690446569392e65170aac3b" +checksum = "df420e2e84819663797d1ec6544b13c5be84629e7bb00dc960d6917db2987843" dependencies = [ "mac", "new_debug_unreachable", @@ -536,9 +536,9 @@ dependencies = [ [[package]] name = "futures" -version = "0.3.19" +version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28560757fe2bb34e79f907794bb6b22ae8b0e5c669b638a1132f2592b19035b4" +checksum = "f73fe65f54d1e12b726f517d3e2135ca3125a437b6d998caf1962961f7172d9e" dependencies = [ "futures-channel", "futures-core", @@ -551,9 +551,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.19" +version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba3dda0b6588335f360afc675d0564c17a77a2bda81ca178a4b6081bd86c7f0b" +checksum = "c3083ce4b914124575708913bca19bfe887522d6e2e6d0952943f5eac4a74010" dependencies = [ "futures-core", "futures-sink", @@ -561,15 +561,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.19" +version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0c8ff0461b82559810cdccfde3215c3f373807f5e5232b71479bff7bb2583d7" +checksum = "0c09fd04b7e4073ac7156a9539b57a484a8ea920f79c7c675d05d289ab6110d3" [[package]] name = "futures-executor" -version = "0.3.19" +version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29d6d2ff5bb10fb95c85b8ce46538a2e5f5e7fdc755623a7d4529ab8a4ed9d2a" +checksum = "9420b90cfa29e327d0429f19be13e7ddb68fa1cccb09d65e5706b8c7a749b8a6" dependencies = [ "futures-core", "futures-task", @@ -578,15 +578,15 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.19" +version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1f9d34af5a1aac6fb380f735fe510746c38067c5bf16c7fd250280503c971b2" +checksum = "fc4045962a5a5e935ee2fdedaa4e08284547402885ab326734432bed5d12966b" [[package]] name = "futures-macro" -version = "0.3.19" +version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6dbd947adfffb0efc70599b3ddcf7b5597bb5fa9e245eb99f62b3a5f7bb8bd3c" +checksum = "33c1e13800337f4d4d7a316bf45a567dbcb6ffe087f16424852d97e97a91f512" dependencies = [ "proc-macro2", "quote", @@ -595,21 +595,21 @@ dependencies = [ [[package]] name = "futures-sink" -version = "0.3.19" +version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3055baccb68d74ff6480350f8d6eb8fcfa3aa11bdc1a1ae3afdd0514617d508" +checksum = "21163e139fa306126e6eedaf49ecdb4588f939600f0b1e770f4205ee4b7fa868" [[package]] name = "futures-task" -version = "0.3.19" +version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ee7c6485c30167ce4dfb83ac568a849fe53274c831081476ee13e0dce1aad72" +checksum = "57c66a976bf5909d801bbef33416c41372779507e7a6b3a5e25e4749c58f776a" [[package]] name = "futures-util" -version = "0.3.19" +version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b5cf40b47a271f77a8b1bec03ca09044d99d2372c0de244e66430761127164" +checksum = "d8b7abd5d659d9b90c8cba917f6ec750a74e2dc23902ef9cd4cc8c8b22e6036a" dependencies = [ "futures-channel", "futures-core", @@ -625,60 +625,61 @@ dependencies = [ [[package]] name = "gdk-pixbuf" -version = "0.14.0" +version = "0.15.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "534192cb8f01daeb8fab2c8d4baa8f9aae5b7a39130525779f5c2608e235b10f" +checksum = "678516f1baef591d270ca10587c01a12542a731a7879cc62391a18191a470831" dependencies = [ + "bitflags", "gdk-pixbuf-sys", "gio", - "glib 0.14.8", + "glib 0.15.10", "libc", ] [[package]] name = "gdk-pixbuf-sys" -version = "0.14.0" +version = "0.15.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f097c0704201fbc8f69c1762dc58c6947c8bb188b8ed0bc7e65259f1894fe590" +checksum = "140b2f5378256527150350a8346dbdb08fadc13453a7a2d73aecd5fab3c402a7" dependencies = [ "gio-sys", - "glib-sys 0.14.0", - "gobject-sys 0.14.0", + "glib-sys 0.15.10", + "gobject-sys 0.15.10", "libc", - "system-deps 3.2.0", + "system-deps 6.0.2", ] [[package]] name = "gdk4" -version = "0.3.1" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f97a162c17214d1bf981af3f683156a0b1667dd1927057c4f0a68513251ecf0f" +checksum = "d4a2fc0bd03d59383fc10b71a8cb731a1fac2998732a36a0c03e9b1de1513218" dependencies = [ "bitflags", "cairo-rs", "gdk-pixbuf", "gdk4-sys", "gio", - "glib 0.14.8", + "glib 0.15.10", "libc", "pango", ] [[package]] name = "gdk4-sys" -version = "0.3.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9498f4e06969fb96a4e4234dfe1d308a3ac6b120b3c6d93e3ec5c77fe88bc6d5" +checksum = "48a39e34abe35ee2cf54a1e29dd983accecd113ad30bdead5050418fa92f2a1b" dependencies = [ "cairo-sys-rs", "gdk-pixbuf-sys", "gio-sys", - "glib-sys 0.14.0", - "gobject-sys 0.14.0", - "graphene-sys", + "glib-sys 0.15.10", + "gobject-sys 0.15.10", "libc", "pango-sys", - "system-deps 5.0.0", + "pkg-config", + "system-deps 6.0.2", ] [[package]] @@ -694,13 +695,13 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.3" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753" +checksum = "9be70c98951c83b8d2f8f60d7065fa6d5146873094452a1008da8c2f1e4205ad" dependencies = [ "cfg-if", "libc", - "wasi 0.10.2+wasi-snapshot-preview1", + "wasi 0.10.0+wasi-snapshot-preview1", ] [[package]] @@ -722,16 +723,16 @@ dependencies = [ [[package]] name = "gio" -version = "0.14.8" +version = "0.15.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "711c3632b3ebd095578a9c091418d10fed492da9443f58ebc8f45efbeb215cb0" +checksum = "76cd21a7a674ea811749661012512b0ba5237ba404ccbcab2850db5537549b64" dependencies = [ "bitflags", "futures-channel", "futures-core", "futures-io", "gio-sys", - "glib 0.14.8", + "glib 0.15.10", "libc", "once_cell", "thiserror", @@ -739,14 +740,14 @@ dependencies = [ [[package]] name = "gio-sys" -version = "0.14.0" +version = "0.15.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0a41df66e57fcc287c4bcf74fc26b884f31901ea9792ec75607289b456f48fa" +checksum = "32157a475271e2c4a023382e9cab31c4584ee30a97da41d3c4e9fdd605abcf8d" dependencies = [ - "glib-sys 0.14.0", - "gobject-sys 0.14.0", + "glib-sys 0.15.10", + "gobject-sys 0.15.10", "libc", - "system-deps 3.2.0", + "system-deps 6.0.2", "winapi", ] @@ -771,21 +772,22 @@ dependencies = [ [[package]] name = "glib" -version = "0.14.8" +version = "0.15.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c515f1e62bf151ef6635f528d05b02c11506de986e43b34a5c920ef0b3796a4" +checksum = "a826fad715b57834920839d7a594c3b5e416358c7d790bdaba847a40d7c1d96d" dependencies = [ "bitflags", "futures-channel", "futures-core", "futures-executor", "futures-task", - "glib-macros 0.14.1", - "glib-sys 0.14.0", - "gobject-sys 0.14.0", + "glib-macros 0.15.10", + "glib-sys 0.15.10", + "gobject-sys 0.15.10", "libc", "once_cell", "smallvec", + "thiserror", ] [[package]] @@ -795,8 +797,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "41486a26d1366a8032b160b59065a59fb528530a46a49f627e7048fb8c064039" dependencies = [ "anyhow", - "heck", - "itertools 0.9.0", + "heck 0.3.3", + "itertools", "proc-macro-crate 0.1.5", "proc-macro-error", "proc-macro2", @@ -806,13 +808,13 @@ dependencies = [ [[package]] name = "glib-macros" -version = "0.14.1" +version = "0.15.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2aad66361f66796bfc73f530c51ef123970eb895ffba991a234fcf7bea89e518" +checksum = "dac4d47c544af67747652ab1865ace0ffa1155709723ac4f32e97587dd4735b2" dependencies = [ "anyhow", - "heck", - "proc-macro-crate 1.1.0", + "heck 0.4.0", + "proc-macro-crate 1.1.3", "proc-macro-error", "proc-macro2", "quote", @@ -831,12 +833,12 @@ dependencies = [ [[package]] name = "glib-sys" -version = "0.14.0" +version = "0.15.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c1d60554a212445e2a858e42a0e48cece1bd57b311a19a9468f70376cf554ae" +checksum = "ef4b192f8e65e9cf76cbf4ea71fa8e3be4a0e18ffe3d68b8da6836974cc5bad4" dependencies = [ "libc", - "system-deps 3.2.0", + "system-deps 6.0.2", ] [[package]] @@ -858,48 +860,48 @@ dependencies = [ [[package]] name = "gobject-sys" -version = "0.14.0" +version = "0.15.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa92cae29759dae34ab5921d73fff5ad54b3d794ab842c117e36cafc7994c3f5" +checksum = "0d57ce44246becd17153bd035ab4d32cfee096a657fc01f2231c9278378d1e0a" dependencies = [ - "glib-sys 0.14.0", + "glib-sys 0.15.10", "libc", - "system-deps 3.2.0", + "system-deps 6.0.2", ] [[package]] name = "graphene-rs" -version = "0.14.8" +version = "0.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3380f132530ef9eb9e0a2bac180e30390aa5e49892d20294f822a974117a563" +checksum = "7c54f9fbbeefdb62c99f892dfca35f83991e2cb5b46a8dc2a715e58612f85570" dependencies = [ - "glib 0.14.8", + "glib 0.15.10", "graphene-sys", "libc", ] [[package]] name = "graphene-sys" -version = "0.14.8" +version = "0.15.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a9ac7450b3aa80792513a3c029920a2ede419de13fb5169a4e51b07a5685332" +checksum = "fa691fc7337ba1df599afb55c3bcb85c04f1b3f17362570e9bb0ff0d1bc3028a" dependencies = [ - "glib-sys 0.14.0", + "glib-sys 0.15.10", "libc", "pkg-config", - "system-deps 3.2.0", + "system-deps 6.0.2", ] [[package]] name = "gsk4" -version = "0.3.1" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eff59ca46c4fc5087fd7a0c3770a71ea4b6e94f8c24c12e2c2e8538f9f6fd764" +checksum = "14d5a47a78c682bb67496b562495ed84972c0512ba0654888c4dc92b80a85bd3" dependencies = [ "bitflags", "cairo-rs", "gdk4", - "glib 0.14.8", + "glib 0.15.10", "graphene-rs", "gsk4-sys", "libc", @@ -908,38 +910,39 @@ dependencies = [ [[package]] name = "gsk4-sys" -version = "0.3.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13aa53ce70234da02f9954339d988d5ab853d746a8f47a4ae17735ff873545b5" +checksum = "e31d21d7ce02ba261bb24c50c4ab238a10b41a2c97c32afffae29471b7cca69b" dependencies = [ "cairo-sys-rs", "gdk4-sys", - "glib-sys 0.14.0", - "gobject-sys 0.14.0", + "glib-sys 0.15.10", + "gobject-sys 0.15.10", "graphene-sys", "libc", "pango-sys", - "system-deps 5.0.0", + "system-deps 6.0.2", ] [[package]] name = "gstreamer" -version = "0.17.4" +version = "0.18.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6a255f142048ba2c4a4dce39106db1965abe355d23f4b5335edea43a553faa4" +checksum = "cd58af6f8b268fc335122a3ccc66efa0cd56584948f49a37e5feef0b89dfc29b" dependencies = [ "bitflags", "cfg-if", "futures-channel", "futures-core", "futures-util", - "glib 0.14.8", + "glib 0.15.10", "gstreamer-sys", "libc", "muldiv", "num-integer", "num-rational", "once_cell", + "option-operations", "paste", "pretty-hex", "thiserror", @@ -947,13 +950,13 @@ dependencies = [ [[package]] name = "gstreamer-base" -version = "0.17.2" +version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c0c1d8c62eb5d08fb80173609f2eea71d385393363146e4e78107facbd67715" +checksum = "224f35f36582407caf58ded74854526beeecc23d0cf64b8d1c3e00584ed6863f" dependencies = [ "bitflags", "cfg-if", - "glib 0.14.8", + "glib 0.15.10", "gstreamer", "gstreamer-base-sys", "libc", @@ -961,25 +964,25 @@ dependencies = [ [[package]] name = "gstreamer-base-sys" -version = "0.17.0" +version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28169a7b58edb93ad8ac766f0fa12dcd36a2af4257a97ee10194c7103baf3e27" +checksum = "a083493c3c340e71fa7c66eebda016e9fafc03eb1b4804cf9b2bad61994b078e" dependencies = [ - "glib-sys 0.14.0", - "gobject-sys 0.14.0", + "glib-sys 0.15.10", + "gobject-sys 0.15.10", "gstreamer-sys", "libc", - "system-deps 3.2.0", + "system-deps 6.0.2", ] [[package]] name = "gstreamer-player" -version = "0.17.0" +version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c503dba6f79b5cd8a4be5329119892c196db013ce66fce16079a7df8ce819a3a" +checksum = "5f14ee02352ba73cadebe640bfb33f12fe8d03cbcad816a102d55a0251fb99bb" dependencies = [ "bitflags", - "glib 0.14.8", + "glib 0.15.10", "gstreamer", "gstreamer-player-sys", "gstreamer-video", @@ -989,40 +992,40 @@ dependencies = [ [[package]] name = "gstreamer-player-sys" -version = "0.17.0" +version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e50bed2a120574750ea1370163df21b50762d0b4967f569fdc58232f4c930d5" +checksum = "1f9b674b39a4d0e18710f6e3d2b109f1793d8028ee4e39da3909b55b4529d399" dependencies = [ - "glib-sys 0.14.0", - "gobject-sys 0.14.0", + "glib-sys 0.15.10", + "gobject-sys 0.15.10", "gstreamer-sys", "gstreamer-video-sys", "libc", - "system-deps 3.2.0", + "system-deps 6.0.2", ] [[package]] name = "gstreamer-sys" -version = "0.17.3" +version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a81704feeb3e8599913bdd1e738455c2991a01ff4a1780cb62200993e454cc3e" +checksum = "e3517a65d3c2e6f8905b456eba5d53bda158d664863aef960b44f651cb7d33e2" dependencies = [ - "glib-sys 0.14.0", - "gobject-sys 0.14.0", + "glib-sys 0.15.10", + "gobject-sys 0.15.10", "libc", - "system-deps 3.2.0", + "system-deps 6.0.2", ] [[package]] name = "gstreamer-video" -version = "0.17.2" +version = "0.18.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3447ee95c8e79daec0b163260cf6a3de9bc19ff47a01b533787f900074a3476" +checksum = "9418adfc72dafa1ad9eb106527ce4804887d101027c4528ec28c7d29cc899519" dependencies = [ "bitflags", "cfg-if", "futures-channel", - "glib 0.14.8", + "glib 0.15.10", "gstreamer", "gstreamer-base", "gstreamer-video-sys", @@ -1032,23 +1035,23 @@ dependencies = [ [[package]] name = "gstreamer-video-sys" -version = "0.17.0" +version = "0.18.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b81608f4182bdddd5bd33aaaa341d5544eda12b067a3dab75b1b7d2de01a3ba7" +checksum = "33331b1675e73b5b000c796354278eca7fdde9327015971d9f41afe28b96e0dc" dependencies = [ - "glib-sys 0.14.0", - "gobject-sys 0.14.0", + "glib-sys 0.15.10", + "gobject-sys 0.15.10", "gstreamer-base-sys", "gstreamer-sys", "libc", - "system-deps 3.2.0", + "system-deps 6.0.2", ] [[package]] name = "gtk4" -version = "0.3.1" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58a04f421d1485ba4739e723199f5828bca05ab4e622ed39a96a342b6b1a6a3d" +checksum = "eb5d40303dabe4608fc260de2bd7563da6f85bc90af956323f0cd8ae0abcfe03" dependencies = [ "bitflags", "cairo-rs", @@ -1057,7 +1060,7 @@ dependencies = [ "gdk-pixbuf", "gdk4", "gio", - "glib 0.14.8", + "glib 0.15.10", "graphene-rs", "gsk4", "gtk4-macros", @@ -1069,44 +1072,43 @@ dependencies = [ [[package]] name = "gtk4-macros" -version = "0.3.1" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5068d4354af02454f44687adc613100aa98ae11e273cdcac84f89dc08be2b4a1" +checksum = "7f3c4aa605fb3d78205c7aef0eeaa6db61d8cc4dd05a465dc6ffdfdaee84f825" dependencies = [ "anyhow", - "heck", - "itertools 0.10.3", - "proc-macro-crate 1.1.0", + "proc-macro-crate 1.1.3", "proc-macro-error", "proc-macro2", + "quick-xml", "quote", "syn", ] [[package]] name = "gtk4-sys" -version = "0.3.1" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e20a64c8f0ddcff8902ff04c130747f2fb7834a43530f75d03d6c71335733b49" +checksum = "c47c075e8f795c38f6e9a47b51a73eab77b325f83c0154979ed4d4245c36490d" dependencies = [ "cairo-sys-rs", "gdk-pixbuf-sys", "gdk4-sys", "gio-sys", - "glib-sys 0.14.0", - "gobject-sys 0.14.0", + "glib-sys 0.15.10", + "gobject-sys 0.15.10", "graphene-sys", "gsk4-sys", "libc", "pango-sys", - "system-deps 5.0.0", + "system-deps 6.0.2", ] [[package]] name = "h2" -version = "0.3.9" +version = "0.3.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f072413d126e57991455e0a922b31e4c8ba7c2ffbebf6b78b4f8521397d65cd" +checksum = "37a82c6d637fc9515a4694bbf1cb2457b79d81ce52b3108bdeea58b07dd34a57" dependencies = [ "bytes", "fnv", @@ -1136,6 +1138,12 @@ dependencies = [ "unicode-segmentation", ] +[[package]] +name = "heck" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9" + [[package]] name = "hermit-abi" version = "0.1.19" @@ -1158,9 +1166,9 @@ dependencies = [ [[package]] name = "html5ever" -version = "0.25.1" +version = "0.25.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aafcf38a1a36118242d29b92e1b08ef84e67e4a5ed06e0a80be20e6a32bfed6b" +checksum = "e5c13fb08e5d4dfc151ee5e88bae63f7773d61852f3bdc73c9f4b9e1bde03148" dependencies = [ "log", "mac", @@ -1178,7 +1186,7 @@ checksum = "31f4c6746584866f0feabcc69893c5b51beef3831656a968ed7ae254cdc4fd03" dependencies = [ "bytes", "fnv", - "itoa 1.0.1", + "itoa", ] [[package]] @@ -1194,9 +1202,9 @@ dependencies = [ [[package]] name = "httparse" -version = "1.5.1" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acd94fdbe1d4ff688b67b04eee2e17bd50995534a61539e45adfefb45e5e5503" +checksum = "9100414882e15fb7feccb4897e5f0ff0ff1ca7d1a86a23208ada4d7a18e6c6c4" [[package]] name = "httpdate" @@ -1221,9 +1229,9 @@ dependencies = [ [[package]] name = "hyper" -version = "0.14.16" +version = "0.14.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7ec3e62bdc98a2f0393a5048e4c30ef659440ea6e0e572965103e72bd836f55" +checksum = "b26ae0a80afebe130861d90abf98e3814a4f28a4c6ffeb5ab8ebb2be311e0ef2" dependencies = [ "bytes", "futures-channel", @@ -1234,7 +1242,7 @@ dependencies = [ "http-body", "httparse", "httpdate", - "itoa 0.4.8", + "itoa", "pin-project-lite", "socket2", "tokio", @@ -1275,9 +1283,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "1.7.0" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc633605454125dec4b66843673f01c7df2b89479b32e0ed634e43a91cff62a5" +checksum = "0f647032dfaa1f8b6dc29bd3edb7bbef4861b8b8007ebb118d6db284fd59f6ee" dependencies = [ "autocfg", "hashbrown", @@ -1294,9 +1302,9 @@ dependencies = [ [[package]] name = "ipnet" -version = "2.3.1" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68f2d64f2edebec4ce84ad108148e67e1064789bee435edc5b60ad398714a3a9" +checksum = "35e70ee094dc02fd9c13fdad4940090f22dbd6ac7c9e7094a46cf0232a50bc7c" [[package]] name = "itertools" @@ -1307,21 +1315,6 @@ dependencies = [ "either", ] -[[package]] -name = "itertools" -version = "0.10.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9a9d19fa1e79b6215ff29b9d6880b706147f16e9b1dbb1e4e5947b5b02bc5e3" -dependencies = [ - "either", -] - -[[package]] -name = "itoa" -version = "0.4.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" - [[package]] name = "itoa" version = "1.0.1" @@ -1330,9 +1323,9 @@ checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35" [[package]] name = "js-sys" -version = "0.3.55" +version = "0.3.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cc9ffccd38c451a86bf13657df244e9c3f37493cce8e5e21e940963777acc84" +checksum = "a38fc24e30fd564ce974c02bf1d337caddff65be6cc4735a1f7eab22a7440f04" dependencies = [ "wasm-bindgen", ] @@ -1345,14 +1338,14 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libadwaita" -version = "0.1.0-beta-1" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cef1e2d4b5490caff8a1d44648f68721ab917f765a7fa1d0226fcdac42d86552" +checksum = "f2ae453d28e3b91f03749f02b1531e8cfe315a1d0762b77a61797d2ab80bb87d" dependencies = [ "gdk-pixbuf", "gdk4", "gio", - "glib 0.14.8", + "glib 0.15.10", "gtk4", "libadwaita-sys", "libc", @@ -1362,24 +1355,24 @@ dependencies = [ [[package]] name = "libadwaita-sys" -version = "0.1.0-beta-1" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a165d8c96824753ec072b70a9149790efa3d5abb07e130cda7eb04ef2006d4c" +checksum = "f18b6ac4cadd252a89f5cba0a5a4e99836131795d6fad37b859ac79e8cb7d2c8" dependencies = [ "gdk4-sys", "gio-sys", - "glib-sys 0.14.0", - "gobject-sys 0.14.0", + "glib-sys 0.15.10", + "gobject-sys 0.15.10", "gtk4-sys", "libc", - "system-deps 3.2.0", + "system-deps 6.0.2", ] [[package]] name = "libc" -version = "0.2.112" +version = "0.2.122" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b03d17f364a3a042d5e5d46b053bbbf82c92c9430c592dd4c064dc6ee997125" +checksum = "ec647867e2bf0772e28c8bcde4f0d19a9216916e890543b5a03ed8ef27b8f259" [[package]] name = "libdbus-sys" @@ -1413,18 +1406,19 @@ dependencies = [ [[package]] name = "lock_api" -version = "0.4.5" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712a4d093c9976e24e7dbca41db895dabcbac38eb5f4045393d17a95bdfb1109" +checksum = "327fa5b6a6940e4699ec49a9beae1ea4845c6bab9314e4f84ac68742139d8c53" dependencies = [ + "autocfg", "scopeguard", ] [[package]] name = "log" -version = "0.4.14" +version = "0.4.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" +checksum = "6389c490849ff5bc16be905ae24bc913a9c8892e19b2341dbc175e14c341c2b8" dependencies = [ "cfg-if", ] @@ -1517,9 +1511,9 @@ checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d" [[package]] name = "mime_guess" -version = "2.0.3" +version = "2.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2684d4c2e97d99848d30b324b00c8fcc7e5c897b7cbb5819b09e7c90e8baf212" +checksum = "4192263c238a5f0d0c6bfd21f336a313a4ce1c450542449ca191bb657b4642ef" dependencies = [ "mime", "unicase", @@ -1527,14 +1521,15 @@ dependencies = [ [[package]] name = "mio" -version = "0.7.14" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8067b404fe97c70829f082dec8bcf4f71225d7eaea1d8645349cb76fa06205cc" +checksum = "52da4364ffb0e4fe33a9841a98a3f3014fb964045ce4f7a45a398243c8d6b0c9" dependencies = [ "libc", "log", "miow", "ntapi", + "wasi 0.11.0+wasi-snapshot-preview1", "winapi", ] @@ -1565,9 +1560,9 @@ checksum = "b5136edda114182728ccdedb9f5eda882781f35fa6e80cc360af12a8932507f3" [[package]] name = "native-tls" -version = "0.2.8" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48ba9f7719b5a0f42f338907614285fb5fd70e53858141f69898a1fb7203b24d" +checksum = "fd7e2f3618557f980e0b17e8856252eee3c97fa12c54dff0ca290fb6266ca4a9" dependencies = [ "lazy_static", "libc", @@ -1595,9 +1590,9 @@ checksum = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54" [[package]] name = "ntapi" -version = "0.3.6" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f6bb902e437b6d86e03cce10a7e2af662292c5dfef23b65899ea3ac9354ad44" +checksum = "c28774a7fd2fbb4f0babd8237ce554b73af68021b5f695a3cebd6c59bac0980f" dependencies = [ "winapi", ] @@ -1644,15 +1639,15 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.9.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da32515d9f6e6e489d7bc9d84c71b060db7247dc035bbe44eac88cf87486d8d5" +checksum = "87f3e037eac156d1775da914196f0f37741a274155e34a0b7e427c35d2a2ecb9" [[package]] name = "open" -version = "2.0.2" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "176ee4b630d174d2da8241336763bb459281dddc0f4d87f72c3b1efc9a6109b7" +checksum = "9213e7b66aa06a7722828ee2980c1adff22a3922b582baaa1e62e30ca2a6c018" dependencies = [ "pathdiff", "winapi", @@ -1674,9 +1669,9 @@ dependencies = [ [[package]] name = "openssl-probe" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28988d872ab76095a6e6ac88d99b54fd267702734fd7ffe610ca27f533ddb95a" +checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-sys" @@ -1691,23 +1686,32 @@ dependencies = [ "vcpkg", ] +[[package]] +name = "option-operations" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95d6113415f41b268f1195907427519769e40ee6f28cbb053795098a2c16f447" +dependencies = [ + "paste", +] + [[package]] name = "output_vt100" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53cdc5b785b7a58c5aad8216b3dfa114df64b0b06ae6e1501cef91df2fbdf8f9" +checksum = "628223faebab4e3e40667ee0b2336d34a5b960ff60ea743ddfdbcf7770bcfb66" dependencies = [ "winapi", ] [[package]] name = "pango" -version = "0.14.8" +version = "0.15.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "546fd59801e5ca735af82839007edd226fe7d3bb06433ec48072be4439c28581" +checksum = "22e4045548659aee5313bde6c582b0d83a627b7904dd20dc2d9ef0895d414e4f" dependencies = [ "bitflags", - "glib 0.14.8", + "glib 0.15.10", "libc", "once_cell", "pango-sys", @@ -1715,14 +1719,14 @@ dependencies = [ [[package]] name = "pango-sys" -version = "0.14.0" +version = "0.15.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2367099ca5e761546ba1d501955079f097caa186bb53ce0f718dca99ac1942fe" +checksum = "d2a00081cde4661982ed91d80ef437c20eacaf6aa1a5962c0279ae194662c3aa" dependencies = [ - "glib-sys 0.14.0", - "gobject-sys 0.14.0", + "glib-sys 0.15.10", + "gobject-sys 0.15.10", "libc", - "system-deps 3.2.0", + "system-deps 6.0.2", ] [[package]] @@ -1733,7 +1737,17 @@ checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" dependencies = [ "instant", "lock_api", - "parking_lot_core", + "parking_lot_core 0.8.5", +] + +[[package]] +name = "parking_lot" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87f5ec2493a61ac0506c0f4199f99070cbe83857b0337006a30f3e6719b8ef58" +dependencies = [ + "lock_api", + "parking_lot_core 0.9.2", ] [[package]] @@ -1750,11 +1764,24 @@ dependencies = [ "winapi", ] +[[package]] +name = "parking_lot_core" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "995f667a6c822200b0433ac218e05582f0e2efa1b922a3fd2fbaadc5f87bab37" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-sys", +] + [[package]] name = "paste" -version = "1.0.6" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0744126afe1a6dd7f394cb50a716dbe086cb06e255e53d8d0185d82828358fb5" +checksum = "0c520e05135d6e763148b6426a837e239041653ba7becd2e538c076c738025fc" [[package]] name = "pathdiff" @@ -1783,7 +1810,7 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3dfb61232e34fcb633f43d12c58f83c1df82962dcdfa565a4e866ffc17dafe12" dependencies = [ - "phf_shared", + "phf_shared 0.8.0", ] [[package]] @@ -1792,8 +1819,8 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cbffee61585b0411840d3ece935cce9cb6321f01c45477d30066498cd5e1a815" dependencies = [ - "phf_generator", - "phf_shared", + "phf_generator 0.8.0", + "phf_shared 0.8.0", ] [[package]] @@ -1802,10 +1829,20 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "17367f0cc86f2d25802b2c26ee58a7b23faeccf78a396094c13dced0d0182526" dependencies = [ - "phf_shared", + "phf_shared 0.8.0", "rand 0.7.3", ] +[[package]] +name = "phf_generator" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d5285893bb5eb82e6aaf5d59ee909a06a16737a8970984dd7746ba9283498d6" +dependencies = [ + "phf_shared 0.10.0", + "rand 0.8.5", +] + [[package]] name = "phf_shared" version = "0.8.0" @@ -1815,6 +1852,15 @@ dependencies = [ "siphasher", ] +[[package]] +name = "phf_shared" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6796ad771acdc0123d2a88dc428b5e38ef24456743ddb1744ed628f9815c096" +dependencies = [ + "siphasher", +] + [[package]] name = "pin-project-lite" version = "0.2.8" @@ -1829,9 +1875,9 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "pkg-config" -version = "0.3.24" +version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58893f751c9b0412871a09abd62ecd2a00298c6c83befa223ef98c52aef40cbe" +checksum = "1df8c4ec4b0627e53bdf214615ad287367e482558cf84b109250b37464dc03ae" [[package]] name = "podcasts-data" @@ -1857,7 +1903,7 @@ dependencies = [ "native-tls", "num_cpus", "pretty_assertions", - "rand 0.8.4", + "rand 0.8.5", "rayon", "reqwest", "rfc822_sanitizer", @@ -1880,7 +1926,7 @@ dependencies = [ "fragile", "gettext-rs", "gio", - "glib 0.14.8", + "glib 0.15.10", "gstreamer", "gstreamer-player", "gtk4", @@ -1925,9 +1971,9 @@ checksum = "bc5c99d529f0d30937f6f4b8a86d988047327bb88d04d2c4afc356de74722131" [[package]] name = "pretty_assertions" -version = "1.0.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0cfe1b2403f172ba0f234e500906ee0a3e493fb81092dac23ebefe129301cc" +checksum = "c89f989ac94207d048d92db058e4f6ec7342b0971fc58d1271ca148b799b3563" dependencies = [ "ansi_term", "ctor", @@ -1956,9 +2002,9 @@ dependencies = [ [[package]] name = "proc-macro-crate" -version = "1.1.0" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ebace6889caf889b4d3f76becee12e90353f2b8c7d875534a71e5742f8f6f83" +checksum = "e17d47ce914bf4de440332250b0edd23ce48c005f59fab39d3335866b114f11a" dependencies = [ "thiserror", "toml", @@ -1990,9 +2036,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.36" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7342d5883fbccae1cc37a2353b09c87c9b0f3afd73f5fb9bba687a1f733b029" +checksum = "ec757218438d5fda206afc041538b2f6d889286160d649a86a24d37e1235afd1" dependencies = [ "unicode-xid", ] @@ -2015,9 +2061,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.14" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47aa80447ce4daf1717500037052af176af5d38cc3e571d9ec1c7353fc10c87d" +checksum = "632d02bff7f874a36f33ea8bb416cd484b90cc66c1194b1a1110d067a7013f58" dependencies = [ "proc-macro2", ] @@ -2029,7 +2075,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "545c5bc2b880973c9c10e4067418407a0ccaa3091781d1671d46eb35107cb26f" dependencies = [ "log", - "parking_lot", + "parking_lot 0.11.2", "scheduled-thread-pool", ] @@ -2056,20 +2102,19 @@ dependencies = [ "libc", "rand_chacha 0.2.2", "rand_core 0.5.1", - "rand_hc 0.2.0", + "rand_hc", "rand_pcg", ] [[package]] name = "rand" -version = "0.8.4" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", "rand_chacha 0.3.1", "rand_core 0.6.3", - "rand_hc 0.3.1", ] [[package]] @@ -2122,7 +2167,7 @@ version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" dependencies = [ - "getrandom 0.2.3", + "getrandom 0.2.6", ] [[package]] @@ -2134,15 +2179,6 @@ dependencies = [ "rand_core 0.5.1", ] -[[package]] -name = "rand_hc" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d51e9f596de227fda2ea6c84607f5558e196eeaf43c986b724ba4fb8fdf497e7" -dependencies = [ - "rand_core 0.6.3", -] - [[package]] name = "rand_pcg" version = "0.2.1" @@ -2188,28 +2224,29 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.2.10" +version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff" +checksum = "62f25bc4c7e55e0b0b7a1d43fb893f4fa1361d0abe38b9ce4f323c2adfe6ef42" dependencies = [ "bitflags", ] [[package]] name = "redox_users" -version = "0.4.0" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "528532f3d801c87aec9def2add9ca802fe569e44a544afe633765267840abe64" +checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" dependencies = [ - "getrandom 0.2.3", + "getrandom 0.2.6", "redox_syscall", + "thiserror", ] [[package]] name = "regex" -version = "1.5.4" +version = "1.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461" +checksum = "1a11647b6b25ff05a515cb92c365cec08801e83423a235b51e231e1808747286" dependencies = [ "aho-corasick", "memchr", @@ -2233,15 +2270,16 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.11.8" +version = "0.11.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c4e0a76dc12a116108933f6301b95e83634e0c47b0afbed6abbaa0601e99258" +checksum = "46a1f7aa4f35e5e8b4160449f51afc758f0ce6454315a9fa7d0d113e958c41eb" dependencies = [ "base64", "bytes", "encoding_rs", "futures-core", "futures-util", + "h2", "http", "http-body", "hyper", @@ -2268,9 +2306,9 @@ dependencies = [ [[package]] name = "rfc822_sanitizer" -version = "0.3.4" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ae57cb2820842d1ba94ba719453fffc6f8ab953059e133a04e2bf4016b3c4f9" +checksum = "d95e6ac0e635800681025bddc2fa6747cf1159bb897223a74e481ec54b4f5d44" dependencies = [ "chrono", "lazy_static", @@ -2320,7 +2358,7 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc6f74fd1204073fa02d5d5d68bec8021be4c38690b61264b2fdb48083d0e7d7" dependencies = [ - "parking_lot", + "parking_lot 0.11.2", ] [[package]] @@ -2331,9 +2369,9 @@ checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" [[package]] name = "security-framework" -version = "2.4.2" +version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "525bc1abfda2e1998d152c45cf13e696f76d0a4972310b22fac1658b05df7c87" +checksum = "2dc14f172faf8a0194a3aded622712b0de276821addc574fa54fc0a1167e10dc" dependencies = [ "bitflags", "core-foundation", @@ -2344,9 +2382,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.4.2" +version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9dd14d83160b528b7bfd66439110573efcfbe281b17fc2ca9f39f550d619c7e" +checksum = "0160a13a177a45bfb43ce71c01580998474f556ad854dcbca936dd2841a5c556" dependencies = [ "core-foundation-sys", "libc", @@ -2372,56 +2410,56 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.133" +version = "1.0.136" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97565067517b60e2d1ea8b268e59ce036de907ac523ad83a0475da04e818989a" +checksum = "ce31e24b01e1e524df96f1c2fdd054405f8d7376249a5110886fb4b658484789" [[package]] name = "serde_json" -version = "1.0.74" +version = "1.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee2bb9cd061c5865d345bb02ca49fcef1391741b672b54a0bf7b679badec3142" +checksum = "8e8d9fa5c3b304765ce1fd9c4c8a3de2c8db365a5b91be52f186efc675681d95" dependencies = [ - "itoa 1.0.1", + "itoa", "ryu", "serde", ] [[package]] name = "serde_urlencoded" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edfa57a7f8d9c1d260a549e7224100f6c43d43f9103e06dd8b4095a9b2b43ce9" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" dependencies = [ "form_urlencoded", - "itoa 0.4.8", + "itoa", "ryu", "serde", ] [[package]] name = "siphasher" -version = "0.3.7" +version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "533494a8f9b724d33625ab53c6c4800f7cc445895924a8ef649222dcb76e938b" +checksum = "7bd3e3206899af3f8b12af284fafc038cc1dc2b41d1b89dd17297221c5d225de" [[package]] name = "slab" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9def91fd1e018fe007022791f865d0ccc9b3a0d5001e01aabb8b40e46000afb5" +checksum = "eb703cfe953bccee95685111adeedb76fabe4e97549a58d16f03ea7b9367bb32" [[package]] name = "smallvec" -version = "1.7.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ecab6c735a6bb4139c0caafd0cc3635748bbb3acf4550e8138122099251f309" +checksum = "f2dd574626839106c320a323308629dcb1acfc96e32a8cba364ddc61ac23ee83" [[package]] name = "socket2" -version = "0.4.2" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dc90fe6c7be1a323296982db1836d1ea9e47b6839496dde9a541bc496df3516" +checksum = "66d72b759436ae32898a2af0a14218dbf55efde3feeb170eb623637db85ee1e0" dependencies = [ "libc", "winapi", @@ -2429,26 +2467,26 @@ dependencies = [ [[package]] name = "string_cache" -version = "0.8.2" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "923f0f39b6267d37d23ce71ae7235602134b250ace715dd2c90421998ddac0c6" +checksum = "213494b7a2b503146286049378ce02b482200519accc31872ee8be91fa820a08" dependencies = [ - "lazy_static", "new_debug_unreachable", - "parking_lot", - "phf_shared", + "once_cell", + "parking_lot 0.12.0", + "phf_shared 0.10.0", "precomputed-hash", "serde", ] [[package]] name = "string_cache_codegen" -version = "0.5.1" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f24c8e5e19d22a726626f1a5e16fe15b132dcf21d10177fa5a45ce7962996b97" +checksum = "6bb30289b722be4ff74a408c3cc27edeaad656e06cb1fe8fa9231fa59c728988" dependencies = [ - "phf_generator", - "phf_shared", + "phf_generator 0.10.0", + "phf_shared 0.10.0", "proc-macro2", "quote", ] @@ -2471,31 +2509,13 @@ version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57bd81eb48f4c437cadc685403cad539345bf703d78e63707418431cecd4522b" -[[package]] -name = "strum" -version = "0.21.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aaf86bbcfd1fa9670b7a129f64fc0c9fcbbfe4f1bc4210e9e98fe71ffc12cde2" - [[package]] name = "strum_macros" version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "87c85aa3f8ea653bfd3ddf25f7ee357ee4d204731f6aa9ad04002306f6e2774c" dependencies = [ - "heck", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "strum_macros" -version = "0.21.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d06aaeeee809dbc59eb4556183dd927df67db1540de5be8d3ec0b6636358a5ec" -dependencies = [ - "heck", + "heck 0.3.3", "proc-macro2", "quote", "syn", @@ -2503,9 +2523,9 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.84" +version = "1.0.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecb2e6da8ee5eb9a61068762a32fa9619cc591ceb055b3687f4cd4051ec2e06b" +checksum = "b683b2b825c8eef438b77c36a06dc262294da3d5a5813fac20da149241dcd44d" dependencies = [ "proc-macro2", "quote", @@ -2518,10 +2538,10 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0f3ecc17269a19353b3558b313bba738b25d82993e30d62a18406a24aba4649b" dependencies = [ - "heck", + "heck 0.3.3", "pkg-config", - "strum 0.18.0", - "strum_macros 0.18.0", + "strum", + "strum_macros", "thiserror", "toml", "version-compare 0.0.10", @@ -2529,33 +2549,15 @@ dependencies = [ [[package]] name = "system-deps" -version = "3.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "480c269f870722b3b08d2f13053ce0c2ab722839f472863c3e2d61ff3a1c2fa6" -dependencies = [ - "anyhow", - "cfg-expr 0.8.1", - "heck", - "itertools 0.10.3", - "pkg-config", - "strum 0.21.0", - "strum_macros 0.21.1", - "thiserror", - "toml", - "version-compare 0.0.11", -] - -[[package]] -name = "system-deps" -version = "5.0.0" +version = "6.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18db855554db7bd0e73e06cf7ba3df39f97812cb11d3f75e71c39bf45171797e" +checksum = "a1a45a1c4c9015217e12347f2a411b57ce2c4fc543913b14b6fe40483328e709" dependencies = [ - "cfg-expr 0.9.0", - "heck", + "cfg-expr", + "heck 0.4.0", "pkg-config", "toml", - "version-compare 0.0.11", + "version-compare 0.1.0", ] [[package]] @@ -2570,13 +2572,13 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.2.0" +version = "3.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dac1c663cfc93810f88aed9b8941d48cabf856a1b111c29a40439018d870eb22" +checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4" dependencies = [ "cfg-if", + "fastrand", "libc", - "rand 0.8.4", "redox_syscall", "remove_dir_all", "winapi", @@ -2584,9 +2586,9 @@ dependencies = [ [[package]] name = "tendril" -version = "0.4.2" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9ef557cb397a4f0a5a3a628f06515f78563f2209e64d47055d9dc6052bf5e33" +checksum = "d24a120c5fc464a3458240ee02c299ebcb9d67b5249c8848b09d639dca8d7bb0" dependencies = [ "futf", "mac", @@ -2595,9 +2597,9 @@ dependencies = [ [[package]] name = "termcolor" -version = "1.1.2" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4" +checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755" dependencies = [ "winapi-util", ] @@ -2624,11 +2626,12 @@ dependencies = [ [[package]] name = "time" -version = "0.1.43" +version = "0.1.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca8a50ef2360fbd1eeb0ecd46795a87a19024eb4b53c5dc916ca1fd95fe62438" +checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255" dependencies = [ "libc", + "wasi 0.10.0+wasi-snapshot-preview1", "winapi", ] @@ -2649,9 +2652,9 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" [[package]] name = "tokio" -version = "1.15.0" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbbf1c778ec206785635ce8ad57fe52b3009ae9e0c9f574a728f3049d3e55838" +checksum = "2af73ac49756f3f7c01172e34a23e5d0216f6c32333757c2c61feb2bbff5a5ee" dependencies = [ "bytes", "libc", @@ -2659,6 +2662,7 @@ dependencies = [ "mio", "num_cpus", "pin-project-lite", + "socket2", "tokio-macros", "winapi", ] @@ -2686,16 +2690,16 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.6.9" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e99e1983e5d376cd8eb4b66604d2e99e79f5bd988c3055891dcd8c9e2604cc0" +checksum = "0edfdeb067411dba2044da6d1cb2df793dd35add7888d73c16e3381ded401764" dependencies = [ "bytes", "futures-core", "futures-sink", - "log", "pin-project-lite", "tokio", + "tracing", ] [[package]] @@ -2715,20 +2719,32 @@ checksum = "360dfd1d6d30e05fda32ace2c8c70e9c0a9da713275777f5a4dbb8a1893930c6" [[package]] name = "tracing" -version = "0.1.29" +version = "0.1.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "375a639232caf30edfc78e8d89b2d4c375515393e7af7e16f01cd96917fb2105" +checksum = "4a1bdf54a7c28a2bbf701e1d2233f6c77f473486b94bee4f9678da5a148dca7f" dependencies = [ "cfg-if", "pin-project-lite", + "tracing-attributes", "tracing-core", ] +[[package]] +name = "tracing-attributes" +version = "0.1.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e65ce065b4b5c53e73bb28912318cb8c9e9ad3921f1d669eb0e68b4c8143a2b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "tracing-core" -version = "0.1.21" +version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f4ed65637b8390770814083d20756f87bfa2c21bf2f110babdc5438351746e4" +checksum = "90442985ee2f57c9e1b548ee72ae842f4a9a20e3f417cc38dbc5dc684d9bb4ee" dependencies = [ "lazy_static", ] @@ -2771,9 +2787,9 @@ dependencies = [ [[package]] name = "unicode-segmentation" -version = "1.8.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8895849a949e7845e06bd6dc1aa51731a103c42707010a5b591c0038fb73385b" +checksum = "7e8820f5d777f6224dc4be3632222971ac30164d4a258d595640799554ebfd99" [[package]] name = "unicode-width" @@ -2819,9 +2835,9 @@ checksum = "d63556a25bae6ea31b52e640d7c41d1ab27faba4ccb600013837a3d0b3994ca1" [[package]] name = "version-compare" -version = "0.0.11" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c18c859eead79d8b95d09e4678566e8d70105c4e7b251f707a03df32442661b" +checksum = "fe88247b92c1df6b6de80ddc290f3976dbdf2f5f5d3fd049a9fb598c6dd5ca73" [[package]] name = "version_check" @@ -2847,15 +2863,21 @@ checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" [[package]] name = "wasi" -version = "0.10.2+wasi-snapshot-preview1" +version = "0.10.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" +checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.78" +version = "0.2.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "632f73e236b219150ea279196e54e610f5dbafa5d61786303d4da54f84e47fce" +checksum = "25f1af7423d8588a3d840681122e72e6a24ddbcb3f0ec385cac0d12d24256c06" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -2863,9 +2885,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.78" +version = "0.2.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a317bf8f9fba2476b4b2c85ef4c4af8ff39c3c7f0cdfeed4f82c34a880aa837b" +checksum = "8b21c0df030f5a177f3cba22e9bc4322695ec43e7257d865302900290bcdedca" dependencies = [ "bumpalo", "lazy_static", @@ -2878,9 +2900,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.28" +version = "0.4.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e8d7523cb1f2a4c96c1317ca690031b714a51cc14e05f712446691f413f5d39" +checksum = "2eb6ec270a31b1d3c7e266b999739109abce8b6c87e4b31fcfcd788b65267395" dependencies = [ "cfg-if", "js-sys", @@ -2890,9 +2912,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.78" +version = "0.2.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d56146e7c495528bf6587663bea13a8eb588d39b36b679d83972e1a2dbbdacf9" +checksum = "2f4203d69e40a52ee523b2529a773d5ffc1dc0071801c87b3d270b471b80ed01" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -2900,9 +2922,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.78" +version = "0.2.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7803e0eea25835f8abdc585cd3021b3deb11543c6fe226dcd30b228857c5c5ab" +checksum = "bfa8a30d46208db204854cadbb5d4baf5fcf8071ba5bf48190c3e59937962ebc" dependencies = [ "proc-macro2", "quote", @@ -2913,15 +2935,15 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.78" +version = "0.2.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0237232789cf037d5480773fe568aac745bfe2afbc11a863e97901780a6b47cc" +checksum = "3d958d035c4438e28c70e4321a2911302f10135ce78a9c7834c0cab4123d06a2" [[package]] name = "web-sys" -version = "0.3.55" +version = "0.3.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38eb105f1c59d9eaa6b5cdc92b859d85b926e82cb2e0945cd0c9259faa6fe9fb" +checksum = "c060b319f29dd25724f09a2ba1418f142f539b2be99fbf4d2d5a8f7330afb8eb" dependencies = [ "js-sys", "wasm-bindgen", @@ -2958,20 +2980,63 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "windows-sys" +version = "0.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5acdd78cb4ba54c0045ac14f62d8f94a03d10047904ae2a40afa1e99d8f70825" +dependencies = [ + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_msvc" +version = "0.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17cffbe740121affb56fad0fc0e421804adf0ae00891205213b5cecd30db881d" + +[[package]] +name = "windows_i686_gnu" +version = "0.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2564fde759adb79129d9b4f54be42b32c89970c18ebf93124ca8870a498688ed" + +[[package]] +name = "windows_i686_msvc" +version = "0.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9cd9d32ba70453522332c14d38814bceeb747d80b3958676007acadd7e166956" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfce6deae227ee8d356d19effc141a509cc503dfd1f850622ec4b0f84428e1f4" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d19538ccc21819d01deaf88d6a17eae6596a12e9aafdbb97916fb49896d89de9" + [[package]] name = "winreg" -version = "0.7.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0120db82e8a1e0b9fb3345a539c478767c0048d842860994d96113d5b667bd69" +checksum = "80d0f4e272c85def139476380b12f9ac60926689dd2e01d4923222f40580869d" dependencies = [ "winapi", ] [[package]] name = "xdg" -version = "2.4.0" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a23fe958c70412687039c86f578938b4a0bb50ec788e96bce4d6ab00ddd5803" +checksum = "0c4583db5cbd4c4c0303df2d15af80f0539db703fa1c68802d4cbbd2dd0f88f6" dependencies = [ "dirs", ] diff --git a/podcasts-gtk/Cargo.toml b/podcasts-gtk/Cargo.toml index 6b3cb87..8639163 100644 --- a/podcasts-gtk/Cargo.toml +++ b/podcasts-gtk/Cargo.toml @@ -7,8 +7,8 @@ edition = "2018" [dependencies] chrono = "0.4" crossbeam-channel = "0.5.1" -gst = { version = "0.17.0", package = "gstreamer" } -gst-player = { version = "0.17.0", package = "gstreamer-player" } +gst = { version = "0.18.0", package = "gstreamer" } +gst-player = { version = "0.18.0", package = "gstreamer-player" } humansize = "1.1" lazy_static = "1.4" log = "0.4" @@ -24,8 +24,8 @@ serde_json = "1.0" html5ever = "0.25" markup5ever_rcdom = "0.1" html2text = "0.2.1" -glib = "0.14.2" -adw = {package = "libadwaita", version = "0.1.0-beta"} +glib = "0.15.0" +adw = {package = "libadwaita", version = "0.1.0"} once_cell = "1.9" [dependencies.gettext-rs] @@ -35,11 +35,11 @@ features = ["gettext-system"] [dependencies.gio] features = ["v2_50"] -version = "0.14.0" +version = "0.15.0" [dependencies.gtk] package = "gtk4" -version = "0.3.0" +version = "0.4.0" [dependencies.mpris-player] # git = "https://gitlab.gnome.org/World/Rust/mpris-player.git" diff --git a/podcasts-gtk/src/app.rs b/podcasts-gtk/src/app.rs index 0d333d3..a528ed7 100644 --- a/podcasts-gtk/src/app.rs +++ b/podcasts-gtk/src/app.rs @@ -322,7 +322,6 @@ impl PdApplication { window .main_deck .page(&description_widget.container) - .unwrap() .set_name(Some("description")); window.main_deck.navigate(adw::NavigationDirection::Forward); window.headerbar.reveal_bottom_switcher(false); @@ -358,7 +357,7 @@ impl PdApplication { Action::StopUpdating => { window.updating.set(false); if let Some(timeout) = window.updating_timeout.replace(None) { - glib::source_remove(timeout); + timeout.remove(); } window.progress_bar.hide(); } @@ -372,7 +371,7 @@ impl PdApplication { }), ); if let Some(old_timeout) = window.updating_timeout.replace(Some(updating_timeout)) { - glib::source_remove(old_timeout); + old_timeout.remove(); } } Action::FeedRefreshed => { diff --git a/podcasts-gtk/src/stacks/content.rs b/podcasts-gtk/src/stacks/content.rs index b6f22fd..11a2d99 100644 --- a/podcasts-gtk/src/stacks/content.rs +++ b/podcasts-gtk/src/stacks/content.rs @@ -55,12 +55,9 @@ impl Content { // container will hold the header bar and the content container.set_widget_name("content"); container.append(&stack); - let home_page = stack - .add_titled(&home.borrow().get_stack(), Some("home"), &i18n("New")) - .unwrap(); - let shows_page = stack - .add_titled(&shows.borrow().get_stack(), Some("shows"), &i18n("Shows")) - .unwrap(); + let home_page = stack.add_titled(&home.borrow().get_stack(), Some("home"), &i18n("New")); + let shows_page = + stack.add_titled(&shows.borrow().get_stack(), Some("shows"), &i18n("Shows")); home_page.set_icon_name(Some("document-open-recent-symbolic")); shows_page.set_icon_name(Some("audio-input-microphone-symbolic")); diff --git a/podcasts-gtk/src/utils.rs b/podcasts-gtk/src/utils.rs index fd2cead..9b0cc87 100644 --- a/podcasts-gtk/src/utils.rs +++ b/podcasts-gtk/src/utils.rs @@ -210,7 +210,7 @@ where // https://blogs.gnome.org/jsparber/2018/04/29/animate-a-scrolledwindow/ #[allow(clippy::float_cmp)] pub(crate) fn smooth_scroll_to(view: >k::ScrolledWindow, target: >k::Adjustment) { - let adj = view.vadjustment().unwrap(); + let adj = view.vadjustment(); if let Some(clock) = view.frame_clock() { let duration = 200; let start = adj.value(); diff --git a/podcasts-gtk/src/widgets/aboutdialog.rs b/podcasts-gtk/src/widgets/aboutdialog.rs index fba52fe..00d4754 100644 --- a/podcasts-gtk/src/widgets/aboutdialog.rs +++ b/podcasts-gtk/src/widgets/aboutdialog.rs @@ -26,40 +26,42 @@ use crate::i18n::i18n; pub(crate) fn about_dialog(window: >k::ApplicationWindow) { // Feel free to add yourself if you contributed. // Please keep it sorted alphabetically - let authors = [ - "Alexandre Franke", - "Carlos Soriano", - "Constantin Nickel", - "Daniel García Moreno", - "Felix Häcker", - "Gabriele Musco", - "Ivan Augusto", - "James Wykeham-Martin", - "Jordan Petridis", - "Jordan Williams", - "Julian Hofer", - "Julian Sparber", - "Matthew Martin", - "Piotr Drąg", - "Rowan Lewis", - "Zander Brown", + let authors = vec![ + String::from("Alexandre Franke"), + String::from("Carlos Soriano"), + String::from("Constantin Nickel"), + String::from("Daniel García Moreno"), + String::from("Felix Häcker"), + String::from("Gabriele Musco"), + String::from("Ivan Augusto"), + String::from("James Wykeham-Martin"), + String::from("Jordan Petridis"), + String::from("Jordan Williams"), + String::from("Julian Hofer"), + String::from("Julian Sparber"), + String::from("Matthew Martin"), + String::from("Piotr Drąg"), + String::from("Rowan Lewis"), + String::from("Zander Brown"), ]; - let dialog = gtk::AboutDialog::new(); - dialog.set_logo_icon_name(Some(APP_ID)); - dialog.set_comments(Some(i18n("Podcast Client for the GNOME Desktop.").as_str())); - dialog.set_copyright(Some("© 2017, 2018 Jordan Petridis")); - dialog.set_license_type(gtk::License::Gpl30); - dialog.set_modal(true); - dialog.set_version(Some(VERSION)); - dialog.set_program_name(Some(&i18n("Podcasts"))); - dialog.set_website(Some("https://wiki.gnome.org/Apps/Podcasts")); - dialog.set_website_label(&i18n("Learn more about GNOME Podcasts")); - dialog.set_transient_for(Some(window)); + let artists = vec![String::from("Tobias Bernard"), String::from("Sam Hewitt")]; - dialog.set_artists(&["Tobias Bernard", "Sam Hewitt"]); - dialog.set_authors(&authors); - dialog.set_translator_credits(Some(i18n("translator-credits").as_str())); + let dialog = gtk::AboutDialog::builder() + .logo_icon_name(APP_ID) + .comments(i18n("Podcast Client for the GNOME Desktop.").as_str()) + .copyright("© 2017-2021 Jordan Petridis") + .license_type(gtk::License::Gpl30) + .modal(true) + .version(VERSION) + .program_name(&i18n("Podcasts")) + .website("https://gitlab.gnome.org/World/podcasts") + .website_label(i18n("Learn more about GNOME Podcasts").as_str()) + .transient_for(window) + .artists(artists) + .authors(authors) + .translator_credits(i18n("translator-credits").as_str()) + .build(); dialog.show(); } diff --git a/podcasts-gtk/src/widgets/base_view.rs b/podcasts-gtk/src/widgets/base_view.rs index 3abb4f5..32957a3 100644 --- a/podcasts-gtk/src/widgets/base_view.rs +++ b/podcasts-gtk/src/widgets/base_view.rs @@ -53,7 +53,7 @@ impl ObjectImpl for BaseViewPriv { fn properties() -> &'static [glib::ParamSpec] { static PROPERTIES: Lazy> = Lazy::new(|| { - vec![glib::ParamSpec::new_object( + vec![glib::ParamSpecObject::new( "child", "child", "child", @@ -127,6 +127,6 @@ impl BaseView { pub(crate) fn vadjustment(&self) -> Adjustment { let self_ = BaseViewPriv::from_instance(&self); - self_.scrolled_window.vadjustment().unwrap() + self_.scrolled_window.vadjustment() } } diff --git a/podcasts-gtk/src/widgets/player.rs b/podcasts-gtk/src/widgets/player.rs index e0ee37c..a9ded5d 100644 --- a/podcasts-gtk/src/widgets/player.rs +++ b/podcasts-gtk/src/widgets/player.rs @@ -510,7 +510,7 @@ impl PlayerWidget { // If it's not the same file load the uri, otherwise just unpause if self.player.uri().map_or(true, |s| s != uri.as_str()) { - self.player.set_uri(uri.as_str()); + self.player.set_uri(Some(uri.as_str())); } else { // just unpause, no restore required self.info.finished_restore = true; diff --git a/podcasts-gtk/src/widgets/short_desc_layout.rs b/podcasts-gtk/src/widgets/short_desc_layout.rs index ae7193c..a607020 100644 --- a/podcasts-gtk/src/widgets/short_desc_layout.rs +++ b/podcasts-gtk/src/widgets/short_desc_layout.rs @@ -32,7 +32,7 @@ impl LayoutManagerImpl for ShortDescLayoutPriv { .layout() .is_ellipsized() .to_value(); - widget.emit_by_name("is-ellipsized", &[&value]).unwrap(); + widget.emit_by_name::<()>("is-ellipsized", &[&value]); } } } diff --git a/podcasts-gtk/src/widgets/show.rs b/podcasts-gtk/src/widgets/show.rs index 2b5efcc..e94c5a5 100644 --- a/podcasts-gtk/src/widgets/show.rs +++ b/podcasts-gtk/src/widgets/show.rs @@ -83,17 +83,15 @@ impl ObjectSubclass for ShowWidgetPriv { impl ObjectImpl for ShowWidgetPriv { fn constructed(&self, obj: &Self::Type) { self.parent_constructed(obj); - self.description_short - .connect_local( - "is-ellipsized", - false, - clone!(@weak obj => @default-return None, move |args| { - let is_ellipsized = args[1].get().unwrap(); - obj.update_read_more(is_ellipsized); - None - }), - ) - .unwrap(); + self.description_short.connect_local( + "is-ellipsized", + false, + clone!(@weak obj => @default-return None, move |args| { + let is_ellipsized = args[1].get().unwrap(); + obj.update_read_more(is_ellipsized); + None + }), + ); } fn dispose(&self, _obj: &Self::Type) { @@ -121,7 +119,7 @@ impl ShowWidget { vadj: Option, ) -> ShowWidget { let pdw = ShowWidget::default(); - let pdw_ = ShowWidgetPriv::from_instance(&pdw); + let pdw_ = pdw.imp(); pdw.init(&pd); let menu = ShowMenu::new(&pd, &pdw_.episodes, &sender); @@ -132,19 +130,15 @@ impl ShowWidget { pdw_.description_button .connect_clicked(clone!(@weak pdw => move |_| { - let pdw_ = ShowWidgetPriv::from_instance(&pdw); - - pdw_.description_stack.set_visible_child_name("full"); + pdw.imp().description_stack.set_visible_child_name("full"); })); pdw } pub(crate) fn init(&self, pd: &Arc) { - let self_ = ShowWidgetPriv::from_instance(self); - self.set_description(pd.description()); - self_.show_id.set(Some(pd.id())); + self.imp().show_id.set(Some(pd.id())); let res = self.set_cover(&pd); @@ -153,13 +147,11 @@ impl ShowWidget { /// Set the show cover. fn set_cover(&self, pd: &Arc) -> Result<()> { - let self_ = ShowWidgetPriv::from_instance(self); - - utils::set_image_from_path(&self_.cover, pd.id(), 256) + utils::set_image_from_path(&self.imp().cover, pd.id(), 256) } fn update_read_more(&self, is_ellipsized: bool) { - let self_ = ShowWidgetPriv::from_instance(self); + let self_ = self.imp(); let more = is_ellipsized || self_.description.label() != self_.description_short.label(); self_.description_button_revealer.set_reveal_child(more); @@ -167,7 +159,7 @@ impl ShowWidget { /// Set the description text. fn set_description(&self, text: &str) { - let self_ = ShowWidgetPriv::from_instance(self); + let self_ = self.imp(); let markup = html2text::from_read(text.as_bytes(), text.as_bytes().len()); let markup = markup.trim(); @@ -187,15 +179,11 @@ impl ShowWidget { } pub(crate) fn show_id(&self) -> Option { - let self_ = ShowWidgetPriv::from_instance(self); - - self_.show_id.get() + self.imp().show_id.get() } pub(crate) fn view(&self) -> BaseView { - let self_ = ShowWidgetPriv::from_instance(self); - - self_.view.clone() + self.imp().view.clone() } } @@ -209,7 +197,7 @@ fn populate_listbox( use crossbeam_channel::TryRecvError; let count = dbqueries::get_pd_episodes_count(&pd)?; - let show_ = ShowWidgetPriv::from_instance(show); + let show_ = show.imp(); let (sender_, receiver) = bounded(1); tokio::spawn(clone!(@strong pd => async move { @@ -249,9 +237,7 @@ fn populate_listbox( }); let callback = clone!(@weak show, @strong vadj => move || { - let show_ = ShowWidgetPriv::from_instance(&show); - - show_.view.set_adjustments(None, vadj.as_ref()); + show.imp().view.set_adjustments(None, vadj.as_ref()); }); lazy_load(episodes, list_weak.clone(), constructor, callback); diff --git a/podcasts-gtk/src/widgets/shows_view.rs b/podcasts-gtk/src/widgets/shows_view.rs index 6aed4dc..f9ae531 100644 --- a/podcasts-gtk/src/widgets/shows_view.rs +++ b/podcasts-gtk/src/widgets/shows_view.rs @@ -130,7 +130,7 @@ impl ObjectSubclass for ShowCoverPrivate { fn new() -> Self { Self { // FIXME: bundle the symbolic in resources - cover: gtk::Image::from_icon_name(Some("image-x-generic-symbolic")), + cover: gtk::Image::from_icon_name("image-x-generic-symbolic"), show_id: Cell::default(), } } diff --git a/podcasts-gtk/src/window.rs b/podcasts-gtk/src/window.rs index b72c402..77c2a87 100644 --- a/podcasts-gtk/src/window.rs +++ b/podcasts-gtk/src/window.rs @@ -22,7 +22,7 @@ use glib::Sender; use gio::{self, prelude::*}; -use gtk::prelude::*; +use adw::prelude::*; use crate::app::{Action, PdApplication}; use crate::headerbar::Header; @@ -108,7 +108,7 @@ impl MainWindow { wrap.append(&header.bottom_switcher); toast_overlay.set_child(Some(&wrap)); - adw::traits::ApplicationWindowExt::set_content(&window, Some(&toast_overlay)); + window.set_content(Some(&toast_overlay)); // Retrieve the previous window position and size. WindowGeometry::from_settings(&settings).apply(&window); -- 2.40.1 From 246386c789e36d45d8450ca176d8fb898e4635cf Mon Sep 17 00:00:00 2001 From: Jordan Petridis Date: Fri, 25 Dec 2020 02:13:32 +0200 Subject: [PATCH 037/102] podcasts-gtk: move empty_show to a composite template --- podcasts-gtk/po/POTFILES.in | 1 + podcasts-gtk/resources/gtk/empty_show.ui | 32 +++++++++++++ podcasts-gtk/resources/gtk/empty_view.ui | 29 +----------- podcasts-gtk/resources/resources.xml | 1 + podcasts-gtk/src/main.rs | 2 - podcasts-gtk/src/meson.build | 1 + podcasts-gtk/src/widgets/empty.rs | 19 -------- podcasts-gtk/src/widgets/empty_show.rs | 58 ++++++++++++++++++++++++ podcasts-gtk/src/widgets/mod.rs | 4 +- podcasts-gtk/src/widgets/show.rs | 3 +- 10 files changed, 98 insertions(+), 52 deletions(-) create mode 100644 podcasts-gtk/resources/gtk/empty_show.ui create mode 100644 podcasts-gtk/src/widgets/empty_show.rs diff --git a/podcasts-gtk/po/POTFILES.in b/podcasts-gtk/po/POTFILES.in index 75028ad..702d19a 100644 --- a/podcasts-gtk/po/POTFILES.in +++ b/podcasts-gtk/po/POTFILES.in @@ -5,6 +5,7 @@ podcasts-gtk/resources/org.gnome.Podcasts.desktop.in.in podcasts-gtk/resources/org.gnome.Podcasts.appdata.xml.in.in # ui files +podcasts-gtk/resources/gtk/empty_show.ui podcasts-gtk/resources/gtk/empty_view.ui podcasts-gtk/resources/gtk/episode_description.ui podcasts-gtk/resources/gtk/episode_menu.ui diff --git a/podcasts-gtk/resources/gtk/empty_show.ui b/podcasts-gtk/resources/gtk/empty_show.ui new file mode 100644 index 0000000..8958d5f --- /dev/null +++ b/podcasts-gtk/resources/gtk/empty_show.ui @@ -0,0 +1,32 @@ + + + + \ No newline at end of file diff --git a/podcasts-gtk/resources/gtk/empty_view.ui b/podcasts-gtk/resources/gtk/empty_view.ui index 3c12a28..9aefad6 100644 --- a/podcasts-gtk/resources/gtk/empty_view.ui +++ b/podcasts-gtk/resources/gtk/empty_view.ui @@ -24,34 +24,7 @@ Tobias Bernard --> - - - - - - - vertical - 6 - 6 - 6 - 6 - - - This show does not have episodes yet - - - - - - If you think this is an error, please consider writing a bug report. - - - - + center center diff --git a/podcasts-gtk/resources/resources.xml b/podcasts-gtk/resources/resources.xml index b46973d..5326e42 100644 --- a/podcasts-gtk/resources/resources.xml +++ b/podcasts-gtk/resources/resources.xml @@ -6,6 +6,7 @@ gtk/episode_description.ui gtk/show_widget.ui gtk/empty_view.ui + gtk/empty_show.ui gtk/home_view.ui gtk/home_episode.ui gtk/headerbar.ui diff --git a/podcasts-gtk/src/main.rs b/podcasts-gtk/src/main.rs index 39fb2aa..4c8c9ed 100644 --- a/podcasts-gtk/src/main.rs +++ b/podcasts-gtk/src/main.rs @@ -129,8 +129,6 @@ fn test_stuff() -> anyhow::Result<()> { HomeEpisode::default(); EpisodeWidget::default(); EmptyView::default(); - EmptyShow::default(); - EpisodeDescription::default(); show_menu::ShowMenu::default(); episode_menu::EpisodeMenu::default(); diff --git a/podcasts-gtk/src/meson.build b/podcasts-gtk/src/meson.build index 4b394ac..3cf321c 100644 --- a/podcasts-gtk/src/meson.build +++ b/podcasts-gtk/src/meson.build @@ -25,6 +25,7 @@ podcasts_sources = files( 'widgets/aboutdialog.rs', 'widgets/base_view.rs', 'widgets/empty.rs', + 'widgets/empty_show.rs', 'widgets/episode.rs', 'widgets/episode_menu.rs', 'widgets/episode_description.rs', diff --git a/podcasts-gtk/src/widgets/empty.rs b/podcasts-gtk/src/widgets/empty.rs index 8d438d1..168b2da 100644 --- a/podcasts-gtk/src/widgets/empty.rs +++ b/podcasts-gtk/src/widgets/empty.rs @@ -18,7 +18,6 @@ // SPDX-License-Identifier: GPL-3.0-or-later use crate::config::APP_ID; - use std::ops::Deref; #[derive(Clone, Debug)] @@ -40,21 +39,3 @@ impl Default for EmptyView { EmptyView(view) } } - -#[derive(Clone, Debug)] -pub(crate) struct EmptyShow(gtk::Box); - -impl Deref for EmptyShow { - type Target = gtk::Box; - fn deref(&self) -> &Self::Target { - &self.0 - } -} - -impl Default for EmptyShow { - fn default() -> Self { - let builder = gtk::Builder::from_resource("/org/gnome/Podcasts/gtk/empty_view.ui"); - let box_: gtk::Box = builder.object("empty_show").unwrap(); - EmptyShow(box_) - } -} diff --git a/podcasts-gtk/src/widgets/empty_show.rs b/podcasts-gtk/src/widgets/empty_show.rs new file mode 100644 index 0000000..e074e4a --- /dev/null +++ b/podcasts-gtk/src/widgets/empty_show.rs @@ -0,0 +1,58 @@ +// empty_show.rs +// +// Copyright 2022 Jordan Petridis +// +// This program 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. +// +// This program 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 this program. If not, see . +// +// SPDX-License-Identifier: GPL-3.0-or-later + +use gtk::prelude::*; +use gtk::subclass::prelude::*; +use gtk::{glib, CompositeTemplate}; + +#[derive(Debug, Default, CompositeTemplate)] +#[template(resource = "/org/gnome/Podcasts/gtk/empty_show.ui")] +pub struct EmptyShowPriv {} + +#[glib::object_subclass] +impl ObjectSubclass for EmptyShowPriv { + const NAME: &'static str = "PdEmptyShow"; + type Type = EmptyShow; + type ParentType = gtk::Box; + + fn class_init(klass: &mut Self::Class) { + klass.bind_template(); + } + + // You must call `Widget`'s `init_template()` within `instance_init()`. + fn instance_init(obj: &glib::subclass::InitializingObject) { + obj.init_template(); + } +} + +impl ObjectImpl for EmptyShowPriv {} + +impl WidgetImpl for EmptyShowPriv {} +impl BoxImpl for EmptyShowPriv {} + +glib::wrapper! { + pub struct EmptyShow(ObjectSubclass) + @extends gtk::Widget, gtk::Box; +} + +impl Default for EmptyShow { + fn default() -> Self { + glib::Object::new(&[]).expect("Failed to create EmptyShow Box") + } +} diff --git a/podcasts-gtk/src/widgets/mod.rs b/podcasts-gtk/src/widgets/mod.rs index 9e2ebab..a45b334 100644 --- a/podcasts-gtk/src/widgets/mod.rs +++ b/podcasts-gtk/src/widgets/mod.rs @@ -20,6 +20,7 @@ mod aboutdialog; mod base_view; mod empty; +mod empty_show; mod episode; mod episode_description; pub(crate) mod episode_menu; @@ -33,7 +34,8 @@ mod shows_view; pub(crate) use self::aboutdialog::about_dialog; pub(crate) use self::base_view::BaseView; -pub(crate) use self::empty::{EmptyShow, EmptyView}; +pub(crate) use self::empty::EmptyView; +pub(crate) use self::empty_show::EmptyShow; pub(crate) use self::episode::EpisodeWidget; pub(crate) use self::episode_description::EpisodeDescription; pub(crate) use self::episode_menu::EpisodeMenu; diff --git a/podcasts-gtk/src/widgets/show.rs b/podcasts-gtk/src/widgets/show.rs index e94c5a5..a30fff3 100644 --- a/podcasts-gtk/src/widgets/show.rs +++ b/podcasts-gtk/src/widgets/show.rs @@ -34,7 +34,6 @@ use crate::utils::{self, lazy_load}; use crate::widgets::{BaseView, EmptyShow, EpisodeWidget, ShortDesc, ShowMenu}; use std::cell::Cell; -use std::ops::Deref; use std::sync::Arc; use gtk::glib; @@ -210,7 +209,7 @@ fn populate_listbox( if count == 0 { let empty = EmptyShow::default(); - show_.episodes.append(empty.deref()); + show_.episodes.append(&empty); return Ok(()); } -- 2.40.1 From fb9291762afcd0959ba4e55bd82946fa7b3f4391 Mon Sep 17 00:00:00 2001 From: Jordan Petridis Date: Fri, 25 Dec 2020 03:07:47 +0200 Subject: [PATCH 038/102] podcasts-gtk: move empty_view to a composite template as well --- podcasts-gtk/po/POTFILES.in | 1 - podcasts-gtk/resources/gtk/empty_view.ui | 11 ++-- podcasts-gtk/src/main.rs | 1 - podcasts-gtk/src/meson.build | 2 +- podcasts-gtk/src/stacks/home.rs | 3 +- podcasts-gtk/src/stacks/show.rs | 3 +- podcasts-gtk/src/widgets/empty.rs | 41 ------------- podcasts-gtk/src/widgets/empty_view.rs | 75 ++++++++++++++++++++++++ podcasts-gtk/src/widgets/mod.rs | 4 +- 9 files changed, 87 insertions(+), 54 deletions(-) delete mode 100644 podcasts-gtk/src/widgets/empty.rs create mode 100644 podcasts-gtk/src/widgets/empty_view.rs diff --git a/podcasts-gtk/po/POTFILES.in b/podcasts-gtk/po/POTFILES.in index 702d19a..309ac38 100644 --- a/podcasts-gtk/po/POTFILES.in +++ b/podcasts-gtk/po/POTFILES.in @@ -36,7 +36,6 @@ podcasts-gtk/src/stacks/show.rs podcasts-gtk/src/utils.rs podcasts-gtk/src/widgets/aboutdialog.rs podcasts-gtk/src/widgets/base_view.rs -podcasts-gtk/src/widgets/empty.rs podcasts-gtk/src/widgets/episode.rs podcasts-gtk/src/widgets/episode_description.rs podcasts-gtk/src/widgets/episode_menu.rs diff --git a/podcasts-gtk/resources/gtk/empty_view.ui b/podcasts-gtk/resources/gtk/empty_view.ui index 9aefad6..ae5bc22 100644 --- a/podcasts-gtk/resources/gtk/empty_view.ui +++ b/podcasts-gtk/resources/gtk/empty_view.ui @@ -24,14 +24,17 @@ Tobias Bernard --> - - + diff --git a/podcasts-gtk/src/main.rs b/podcasts-gtk/src/main.rs index 4c8c9ed..d1f07aa 100644 --- a/podcasts-gtk/src/main.rs +++ b/podcasts-gtk/src/main.rs @@ -128,7 +128,6 @@ fn test_stuff() -> anyhow::Result<()> { HomeView::default(); HomeEpisode::default(); EpisodeWidget::default(); - EmptyView::default(); show_menu::ShowMenu::default(); episode_menu::EpisodeMenu::default(); diff --git a/podcasts-gtk/src/meson.build b/podcasts-gtk/src/meson.build index 3cf321c..8d4554c 100644 --- a/podcasts-gtk/src/meson.build +++ b/podcasts-gtk/src/meson.build @@ -24,7 +24,7 @@ podcasts_sources = files( 'stacks/show.rs', 'widgets/aboutdialog.rs', 'widgets/base_view.rs', - 'widgets/empty.rs', + 'widgets/empty_view.rs', 'widgets/empty_show.rs', 'widgets/episode.rs', 'widgets/episode_menu.rs', diff --git a/podcasts-gtk/src/stacks/home.rs b/podcasts-gtk/src/stacks/home.rs index 0eef163..0948c7f 100644 --- a/podcasts-gtk/src/stacks/home.rs +++ b/podcasts-gtk/src/stacks/home.rs @@ -26,7 +26,6 @@ use crate::app::Action; use crate::stacks::State; use crate::widgets::{EmptyView, HomeView}; -use std::ops::Deref; use std::rc::Rc; #[derive(Debug, Clone)] @@ -46,7 +45,7 @@ impl HomeStack { let state = State::Empty; stack.add_named(&episodes.view, Some("home")); - stack.add_named(empty.deref(), Some("empty")); + stack.add_named(&empty, Some("empty")); let home = HomeStack { empty, diff --git a/podcasts-gtk/src/stacks/show.rs b/podcasts-gtk/src/stacks/show.rs index a5f3e27..265bf67 100644 --- a/podcasts-gtk/src/stacks/show.rs +++ b/podcasts-gtk/src/stacks/show.rs @@ -28,7 +28,6 @@ use crate::utils::get_ignored_shows; use crate::widgets::EmptyView; use std::cell::RefCell; -use std::ops::Deref; use std::rc::Rc; #[derive(Debug, Clone)] @@ -48,7 +47,7 @@ impl ShowStack { let state = State::Empty; stack.add_named(&populated.borrow().container(), Some("populated")); - stack.add_named(empty.deref(), Some("empty")); + stack.add_named(&empty, Some("empty")); let mut show = ShowStack { empty, diff --git a/podcasts-gtk/src/widgets/empty.rs b/podcasts-gtk/src/widgets/empty.rs deleted file mode 100644 index 168b2da..0000000 --- a/podcasts-gtk/src/widgets/empty.rs +++ /dev/null @@ -1,41 +0,0 @@ -// empty.rs -// -// Copyright 2017 Jordan Petridis -// -// This program 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. -// -// This program 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 this program. If not, see . -// -// SPDX-License-Identifier: GPL-3.0-or-later - -use crate::config::APP_ID; -use std::ops::Deref; - -#[derive(Clone, Debug)] -pub(crate) struct EmptyView(gtk::Box); - -impl Deref for EmptyView { - type Target = gtk::Box; - fn deref(&self) -> &Self::Target { - &self.0 - } -} - -impl Default for EmptyView { - fn default() -> Self { - let builder = gtk::Builder::from_resource("/org/gnome/Podcasts/gtk/empty_view.ui"); - let view: gtk::Box = builder.object("empty_view").unwrap(); - let image: gtk::Image = builder.object("image").unwrap(); - image.set_from_icon_name(Some(format!("{}-symbolic", APP_ID).as_str())); - EmptyView(view) - } -} diff --git a/podcasts-gtk/src/widgets/empty_view.rs b/podcasts-gtk/src/widgets/empty_view.rs new file mode 100644 index 0000000..7f18748 --- /dev/null +++ b/podcasts-gtk/src/widgets/empty_view.rs @@ -0,0 +1,75 @@ +// empty_view.rs +// +// Copyright 2017 Jordan Petridis +// +// This program 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. +// +// This program 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 this program. If not, see . +// +// SPDX-License-Identifier: GPL-3.0-or-later + +use crate::config::APP_ID; + +use gtk::prelude::*; +use gtk::subclass::prelude::*; +use gtk::{glib, CompositeTemplate}; + +#[derive(Debug, CompositeTemplate)] +#[template(resource = "/org/gnome/Podcasts/gtk/empty_view.ui")] +pub struct EmptyViewPriv { + #[template_child] + pub image: TemplateChild, +} + +#[glib::object_subclass] +impl ObjectSubclass for EmptyViewPriv { + const NAME: &'static str = "PdEmptyView"; + type Type = EmptyView; + type ParentType = gtk::Box; + + fn new() -> Self { + Self { + image: TemplateChild::default(), + } + } + + fn class_init(klass: &mut Self::Class) { + klass.bind_template(); + } + + // You must call `Widget`'s `init_template()` within `instance_init()`. + fn instance_init(obj: &glib::subclass::InitializingObject) { + obj.init_template(); + } +} + +impl ObjectImpl for EmptyViewPriv { + fn constructed(&self, obj: &Self::Type) { + self.parent_constructed(obj); + self.image + .set_icon_name(Some(&format!("{}-symbolic", APP_ID))); + } +} + +impl WidgetImpl for EmptyViewPriv {} +impl BoxImpl for EmptyViewPriv {} + +glib::wrapper! { + pub struct EmptyView(ObjectSubclass) + @extends gtk::Widget, gtk::Box; +} + +impl Default for EmptyView { + fn default() -> Self { + glib::Object::new(&[]).expect("Failed to create EmptyView Box") + } +} diff --git a/podcasts-gtk/src/widgets/mod.rs b/podcasts-gtk/src/widgets/mod.rs index a45b334..efee542 100644 --- a/podcasts-gtk/src/widgets/mod.rs +++ b/podcasts-gtk/src/widgets/mod.rs @@ -19,8 +19,8 @@ mod aboutdialog; mod base_view; -mod empty; mod empty_show; +mod empty_view; mod episode; mod episode_description; pub(crate) mod episode_menu; @@ -34,8 +34,8 @@ mod shows_view; pub(crate) use self::aboutdialog::about_dialog; pub(crate) use self::base_view::BaseView; -pub(crate) use self::empty::EmptyView; pub(crate) use self::empty_show::EmptyShow; +pub(crate) use self::empty_view::EmptyView; pub(crate) use self::episode::EpisodeWidget; pub(crate) use self::episode_description::EpisodeDescription; pub(crate) use self::episode_menu::EpisodeMenu; -- 2.40.1 From 11ffc8c21b9c8580ebfd7fe306add0d840017ecc Mon Sep 17 00:00:00 2001 From: Jordan Petridis Date: Fri, 25 Dec 2020 07:03:55 +0200 Subject: [PATCH 039/102] show_view: simplify implementation of ShowsChild It doesn't need public functions and the default impl was only used in new. --- podcasts-gtk/src/widgets/shows_view.rs | 33 +++++++++----------------- 1 file changed, 11 insertions(+), 22 deletions(-) diff --git a/podcasts-gtk/src/widgets/shows_view.rs b/podcasts-gtk/src/widgets/shows_view.rs index f9ae531..0be2ef5 100644 --- a/podcasts-gtk/src/widgets/shows_view.rs +++ b/podcasts-gtk/src/widgets/shows_view.rs @@ -88,7 +88,7 @@ fn populate_flowbox(shows: &Rc, vadj: Option) -> Result<( let podcasts = dbqueries::get_podcasts_filter(&ignore)?; let flowbox_weak = shows.flowbox.downgrade(); - let constructor = move |parent| ShowsChild::new(&parent).child; + let constructor = move |parent| ShowsChild::new(&parent).row; let callback = clone!(@weak shows => move || { if vadj.is_some() { shows.view.set_adjustments(None, vadj.as_ref()) @@ -177,37 +177,26 @@ impl ShowCover { } } -#[derive(Debug, Clone)] +#[derive(Debug)] struct ShowsChild { cover: ShowCover, - child: gtk::FlowBoxChild, -} - -impl Default for ShowsChild { - fn default() -> Self { - let cover = ShowCover::new(); - let child = gtk::FlowBoxChild::new(); - - child.set_child(Some(&cover)); - - ShowsChild { cover, child } - } + row: gtk::FlowBoxChild, } impl ShowsChild { - pub(crate) fn new(pd: &Show) -> ShowsChild { + fn new(pd: &Show) -> ShowsChild { let cover = ShowCover::new(); - let child = gtk::FlowBoxChild::new(); + let row = gtk::FlowBoxChild::new(); + row.set_child(Some(&cover)); - child.set_child(Some(&cover)); - - let shows_child = ShowsChild { cover, child }; - shows_child.init(pd); - shows_child + let child = ShowsChild { cover, row }; + child.init(pd); + child } fn init(&self, pd: &Show) { - self.child.set_tooltip_text(Some(pd.title())); + self.row.set_tooltip_text(Some(pd.title())); + self.cover.set_id(pd.id()); self.cover.set_id(pd.id()); self.set_cover(); -- 2.40.1 From 8d078e30071e383c389e8b1df10bcf29972147d0 Mon Sep 17 00:00:00 2001 From: Jordan Petridis Date: Fri, 25 Dec 2020 07:50:01 +0200 Subject: [PATCH 040/102] podcasts-gtk: remove the pixbuf cover cache As we are going to move to GtkPicture we won't really need this hack anymore. --- podcasts-gtk/src/utils.rs | 43 +++----------------------- podcasts-gtk/src/widgets/shows_view.rs | 1 + 2 files changed, 6 insertions(+), 38 deletions(-) diff --git a/podcasts-gtk/src/utils.rs b/podcasts-gtk/src/utils.rs index 9b0cc87..3a75758 100644 --- a/podcasts-gtk/src/utils.rs +++ b/podcasts-gtk/src/utils.rs @@ -30,7 +30,7 @@ use gtk::Widget; use anyhow::{anyhow, Result}; use chrono::prelude::*; use crossbeam_channel::unbounded; -use fragile::Fragile; +use rayon; use regex::Regex; use serde_json::Value; use url::Url; @@ -43,7 +43,7 @@ use podcasts_data::pipeline::pipeline; use podcasts_data::utils::checkup; use podcasts_data::Source; -use std::collections::{HashMap, HashSet}; +use std::collections::HashSet; use std::sync::{Arc, Mutex, RwLock}; use std::time::Duration; @@ -314,48 +314,19 @@ pub(crate) fn refresh_feed(source: Option>, sender: Sender) } lazy_static! { - static ref CACHED_PIXBUFS: RwLock>>> = - RwLock::new(HashMap::new()); static ref COVER_DL_REGISTRY: RwLock> = RwLock::new(HashSet::new()); static ref THREADPOOL: rayon::ThreadPool = rayon::ThreadPoolBuilder::new().build().unwrap(); static ref CACHE_VALID_DURATION: chrono::Duration = chrono::Duration::weeks(4); } -// Since gdk_pixbuf::Pixbuf is reference counted and every episode, -// use the cover of the Podcast Feed/Show, We can only create a Pixbuf -// cover per show and pass around the Rc pointer. -// -// GObjects do not implement Send trait, so SendCell is a way around that. +// GObjects do not implement Send trait, so Fragile is a way around that. // Also lazy_static requires Sync trait, so that's what the mutexes are. // TODO: maybe use something that would just scale to requested size? // todo Unit test. pub(crate) fn set_image_from_path(image: >k::Image, show_id: i32, size: u32) -> Result<()> { - if let Ok(hashmap) = CACHED_PIXBUFS.read() { - if let Ok(pd) = dbqueries::get_podcast_cover_from_id(show_id) { - // If the image is still valid, check if the requested (cover + size) is already in the - // cache and if so do an early return after that. - if pd.is_cached_image_valid(&CACHE_VALID_DURATION) { - if let Some(guard) = hashmap.get(&(show_id, size)) { - guard - .lock() - .map_err(|err| anyhow!("Fragile Mutex: {}", err)) - .and_then(|fragile| { - fragile - .try_get() - .map(|px| image.set_from_pixbuf(Some(px))) - .map_err(From::from) - })?; - - return Ok(()); - } - } - } - } - // Check if there's an active download about this show cover. // If there is, a callback will be set so this function will be called again. - // If the download succeeds, there should be a quick return from the pixbuf cache_image - // If it fails another download will be scheduled. + // If it fails another download will be scheduled. WTF??? how is this not downlaoding infinitly if let Ok(guard) = COVER_DL_REGISTRY.read() { if guard.contains(&show_id) { let callback = clone!(@weak image => @default-return glib::Continue(false), move || { @@ -399,11 +370,7 @@ pub(crate) fn set_image_from_path(image: >k::Image, show_id: i32, size: u32) - match path { Ok(path) => { if let Ok(px) = Pixbuf::from_file_at_scale(&path, s, s, true) { - if let Ok(mut hashmap) = CACHED_PIXBUFS.write() { - hashmap - .insert((show_id, size), Mutex::new(Fragile::new(px.clone()))); - image.set_from_pixbuf(Some(&px)); - } + image.set_from_pixbuf(Some(&px)); } } Err(DownloadError::NoImageLocation) => { diff --git a/podcasts-gtk/src/widgets/shows_view.rs b/podcasts-gtk/src/widgets/shows_view.rs index 0be2ef5..b51b531 100644 --- a/podcasts-gtk/src/widgets/shows_view.rs +++ b/podcasts-gtk/src/widgets/shows_view.rs @@ -131,6 +131,7 @@ impl ObjectSubclass for ShowCoverPrivate { Self { // FIXME: bundle the symbolic in resources cover: gtk::Image::from_icon_name("image-x-generic-symbolic"), + // cover: gtk::Picture::new(), show_id: Cell::default(), } } -- 2.40.1 From 32f20aa44c3a2e0a9ceaffe45f85d345d87a7740 Mon Sep 17 00:00:00 2001 From: Jordan Petridis Date: Fri, 25 Dec 2020 10:17:33 +0200 Subject: [PATCH 041/102] podcasts-gtk: rework the cover image cache loading This adds a check if the image is already downloaded and loads it on the spot, which avoids needing to aqquire a lock for the download. --- Cargo.lock | 1 + podcasts-data/src/downloader.rs | 55 +++++++++++++++++++++------------ podcasts-gtk/Cargo.toml | 1 + podcasts-gtk/src/utils.rs | 22 ++++++++++--- 4 files changed, 55 insertions(+), 24 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index aae2d86..985bb4b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1927,6 +1927,7 @@ dependencies = [ "gettext-rs", "gio", "glib 0.15.10", + "glob", "gstreamer", "gstreamer-player", "gtk4", diff --git a/podcasts-data/src/downloader.rs b/podcasts-data/src/downloader.rs index e1a2050..9949e24 100644 --- a/podcasts-data/src/downloader.rs +++ b/podcasts-data/src/downloader.rs @@ -25,7 +25,7 @@ use tempdir::TempDir; use std::fs; use std::fs::{copy, remove_file, DirBuilder, File}; use std::io::{BufWriter, Read, Write}; -use std::path::Path; +use std::path::{Path, PathBuf}; use std::sync::{Arc, Mutex}; use crate::errors::DownloadError; @@ -237,7 +237,37 @@ pub fn get_episode( Ok(()) } +fn determine_cover_dir(pd: &ShowCoverModel) -> PathBuf { + let mut cache_path = PODCASTS_CACHE.clone(); + cache_path.push(pd.title()); + cache_path +} + +pub fn check_for_cached_cover(pd: &ShowCoverModel) -> Option { + let cache_path = determine_cover_dir(pd); + + // try to match the cover file + // FIXME: in case the cover changes filetype we will be matching the + // existing one instead of downloading the new one. + // Should probably make sure that 'cover.*' is removed when we + // download new files. + if let Ok(mut foo) = glob(&format!("{}/cover.*", cache_path.to_str().unwrap())) { + // For some reason there is no .first() method so nth(0) is used + let path = foo.nth(0).and_then(|x| x.ok()); + return path; + } + + return None; +} + pub fn cache_image(pd: &ShowCoverModel, download: bool) -> Result { + if let Some(path) = check_for_cached_cover(pd) { + return Ok(path + .to_str() + .ok_or_else(|| DownloadError::InvalidCachedImageLocation)? + .to_owned()); + } + let url = pd .image_uri() .ok_or(DownloadError::NoImageLocation)? @@ -247,29 +277,16 @@ pub fn cache_image(pd: &ShowCoverModel, download: bool) -> Result Result<()> { + // get the PodcastCover struct + let pd = dbqueries::get_podcast_cover_from_id(show_id)?; + + // Check if the cover is already downloaded and set it + if pd.is_cached_image_valid(&CACHE_VALID_DURATION) { + if let Some(cached_path) = downloader::check_for_cached_cover(&pd) { + if let Ok(px) = Pixbuf::from_file_at_scale(&cached_path, size as i32, size as i32, true) + { + image.set_from_pixbuf(Some(&px)); + } + return Ok(()); + } + } + // Check if there's an active download about this show cover. // If there is, a callback will be set so this function will be called again. // If it fails another download will be scheduled. WTF??? how is this not downlaoding infinitly @@ -346,11 +360,9 @@ pub(crate) fn set_image_from_path(image: >k::Image, show_id: i32, size: u32) - THREADPOOL.spawn(move || { // This operation is polling and will block the thread till the download is finished - if let Ok(pd) = dbqueries::get_podcast_cover_from_id(show_id) { - sender - .send(downloader::cache_image(&pd, true)) - .expect("channel was dropped unexpectedly"); - } + sender + .send(downloader::cache_image(&pd, true)) + .expect("channel was dropped unexpectedly"); if let Ok(mut guard) = COVER_DL_REGISTRY.write() { guard.remove(&show_id); -- 2.40.1 From b503b4f9a3f85053f395fa246920a496586ed2bc Mon Sep 17 00:00:00 2001 From: Maximiliano Sandoval R Date: Thu, 7 Apr 2022 15:37:09 +0200 Subject: [PATCH 042/102] Port empty_view to AdwStatusPage --- podcasts-gtk/resources/gtk/empty_view.ui | 132 +++++++++-------------- podcasts-gtk/src/widgets/empty_view.rs | 15 +-- 2 files changed, 58 insertions(+), 89 deletions(-) diff --git a/podcasts-gtk/resources/gtk/empty_view.ui b/podcasts-gtk/resources/gtk/empty_view.ui index ae5bc22..e30d797 100644 --- a/podcasts-gtk/resources/gtk/empty_view.ui +++ b/podcasts-gtk/resources/gtk/empty_view.ui @@ -24,90 +24,58 @@ Tobias Bernard --> -