diff --git a/Cargo.lock b/Cargo.lock index 73fd068..8c135bf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -107,6 +107,11 @@ name = "bitflags" version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "block" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "build_const" version = "0.2.1" @@ -377,6 +382,15 @@ dependencies = [ "memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "dbus" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)", + "pkg-config 0.3.12 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "debug_unreachable" version = "0.1.1" @@ -514,6 +528,14 @@ dependencies = [ "cfg-if 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "error-chain" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "backtrace 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "error-chain" version = "0.12.0" @@ -596,6 +618,11 @@ dependencies = [ "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "gcc" +version = "0.3.54" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "gdk" version = "0.8.0" @@ -1094,6 +1121,43 @@ dependencies = [ "crc 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "libhandy" +version = "0.1.0" +source = "git+https://gitlab.gnome.org/jsparber/libhandy-rs#f174e76882896c32959d0d16fe11eaadfce1c674" +dependencies = [ + "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "gdk 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "gdk-sys 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "gio 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "gio-sys 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "glib 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "glib-sys 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "gobject-sys 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "gtk 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "gtk-sys 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)", + "libhandy-sys 0.1.0 (git+https://gitlab.gnome.org/jsparber/libhandy-sys-rs)", + "notify-rust 3.4.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "libhandy-sys" +version = "0.1.0" +source = "git+https://gitlab.gnome.org/jsparber/libhandy-sys-rs#2caa9f6e0b68d391a6cdb45123f85c73b9852553" +dependencies = [ + "failure 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "glib 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "glib-sys 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "gobject-sys 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "gtk 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "gtk-sys 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)", + "pkg-config 0.3.12 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "libsqlite3-sys" version = "0.9.1" @@ -1145,6 +1209,25 @@ name = "mac" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "mac-notification-sys" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "chrono 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", + "error-chain 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)", + "objc-foundation 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "malloc_buf" +version = "0.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "maplit" version = "1.0.1" @@ -1310,6 +1393,16 @@ name = "nodrop" version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "notify-rust" +version = "3.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "dbus 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "error-chain 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "mac-notification-sys 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "num-integer" version = "0.1.39" @@ -1348,6 +1441,32 @@ dependencies = [ "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "objc" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "malloc_buf 0.0.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "objc-foundation" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "block 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "objc 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", + "objc_id 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "objc_id" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "objc 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "open" version = "1.2.1" @@ -1559,6 +1678,7 @@ dependencies = [ "html2text 0.1.8 (git+https://github.com/alatiera/rust-html2text)", "humansize 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libhandy 0.1.0 (git+https://gitlab.gnome.org/jsparber/libhandy-rs)", "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "loggerv 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "open 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2527,6 +2647,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum base64 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)" = "85415d2594767338a74a30c1d370b2f3262ec1b4ed2d7bba5b3faf4de40467d9" "checksum bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4efd02e230a02e18f92fc2735f44597385ed02ad8f831e7c1c1156ee5e1ab3a5" "checksum bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d0c54bb8f454c567f21197eefcdbf5679d0bd99f2ddbe52e84c77061952e6789" +"checksum block 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a" "checksum build_const 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "39092a32794787acd8525ee150305ff051b0aa6cc2abaf193924f5ab05425f39" "checksum byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "74c0b906e9446b0a2e4f760cdb3fa4b2c48cdc6db8766a845c54b6ff063fd2e9" "checksum bytes 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e178b8e0e239e844b083d5a0d4a156b2654e67f9f80144d48398fcd736a24fb8" @@ -2556,6 +2677,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum crossbeam-utils 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ea52fab26a99d96cdff39d0ca75c9716125937f5dba2ab83923aaaf5928f684a" "checksum csv 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "71903184af9960c555e7f3b32ff17390d20ecaaf17d4f18c4a0993f2df8a49e3" "checksum csv-core 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "4dd8e6d86f7ba48b4276ef1317edc8cc36167546d8972feb4a2b5fec0b374105" +"checksum dbus 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "58ec7b4cac6f79f36af1cd9cfdb9b935fc5a4e899f494ee03a3a6165f7d10b4b" "checksum debug_unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9a032eac705ca39214d169f83e3d3da290af06d8d1d344d1baad2fd002dca4b3" "checksum derive_builder 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c998e6ab02a828dd9735c18f154e14100e674ed08cb4e1938f0e4177543f439" "checksum derive_builder_core 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "735e24ee9e5fa8e16b86da5007856e97d592e11867e45d76e0c0d0a164a0b757" @@ -2573,6 +2695,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum encoding-index-tradchinese 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)" = "fd0e20d5688ce3cab59eb3ef3a2083a5c77bf496cb798dc6fcdb75f323890c18" "checksum encoding_index_tests 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a246d82be1c9d791c5dfde9a2bd045fc3cbba3fa2b11ad558f27d01712f00569" "checksum encoding_rs 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "98fd0f24d1fb71a4a6b9330c8ca04cbd4e7cc5d846b54ca74ff376bc7c9f798d" +"checksum error-chain 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d9435d864e017c3c6afeac1654189b06cdb491cf2ff73dbf0d73b0f292f42ff8" "checksum error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "07e791d3be96241c77c43846b665ef1384606da2cd2a48730abe606a12906e02" "checksum failure 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "934799b6c1de475a012a02dab0ace1ace43789ee4b99bcfbf1a2e3e8ced5de82" "checksum failure_derive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c7cdda555bb90c9bb67a3b670a0f42de8e73f5981524123ad8578aafec8ddb8b" @@ -2584,6 +2707,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum futf 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "7c9c1ce3fa9336301af935ab852c437817d14cd33690446569392e65170aac3b" "checksum futures 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)" = "884dbe32a6ae4cd7da5c6db9b78114449df9953b8d490c9d7e1b51720b922c62" "checksum futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "ab90cde24b3319636588d0c35fe03b1333857621051837ed769faefb4c2162e4" +"checksum gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)" = "5e33ec290da0d127825013597dbdfc28bee4964690c7ce1166cbc2a7bd08b1bb" "checksum gdk 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "dd30051ff3d908ff2fc7e5776ffe1c699821e043809f294c3a61004f11d6c3a9" "checksum gdk-pixbuf 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c2d2199eba47ebcb9977ce28179649bdd59305ef465c4e6f9b65aaa41c24e6b5" "checksum gdk-pixbuf-sys 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "df6a3b73e04fafc07f5ebc083f1096a773412e627828e1103a55e921f81187d8" @@ -2627,12 +2751,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum lazycell 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a6f08839bc70ef4a3fe1d566d5350f519c5912ea86be0df1740a7d247c7fc0ef" "checksum libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)" = "b685088df2b950fccadf07a7187c8ef846a959c142338a48f9dc0b94517eb5f1" "checksum libflate 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "7d4b4c7aff5bac19b956f693d0ea0eade8066deb092186ae954fa6ba14daab98" +"checksum libhandy 0.1.0 (git+https://gitlab.gnome.org/jsparber/libhandy-rs)" = "" +"checksum libhandy-sys 0.1.0 (git+https://gitlab.gnome.org/jsparber/libhandy-sys-rs)" = "" "checksum libsqlite3-sys 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0e9eb7b8e152b6a01be6a4a2917248381875758250dc3df5d46caf9250341dda" "checksum locale_config 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "14fbee0e39bc2dd6a2427c4fdea66e9826cc1fd09b0a0b7550359f5f6efe1dab" "checksum log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b" "checksum log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "61bd98ae7f7b754bc53dca7d44b604f733c6bba044ea6f41bc8d89272d8161d2" "checksum loggerv 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ba6b0664956d197c6e0223870c1cd1ec4117aea282b4c0bd5ab01119d31d708d" "checksum mac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4" +"checksum mac-notification-sys 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6a3639b6caa2db7443e5df80e12c450982f77fc3c140f53d6e48be91f965ea66" +"checksum malloc_buf 0.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb" "checksum maplit 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "08cbb6b4fef96b6d77bfc40ec491b1690c779e77b05cd9f07f787ed376fd4c43" "checksum markup5ever 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bfedc97d5a503e96816d10fedcd5b42f760b2e525ce2f7ec71f6a41780548475" "checksum matches 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "835511bab37c34c47da5cb44844bea2cfde0236db0b506f90ea4224482c9774a" @@ -2651,11 +2779,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "42550d9fb7b6684a6d404d9fa7250c2eb2646df731d1c06afc06dcee9e1bcf88" "checksum new_debug_unreachable 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0cdc457076c78ab54d5e0d6fa7c47981757f1e34dc39ff92787f217dede586c4" "checksum nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "9a2228dca57108069a5262f2ed8bd2e82496d2e074a06d1ccc7ce1687b6ae0a2" +"checksum notify-rust 3.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0e58d0671a337f5616ada6b4fca9d792948c5ab03e6ce9376f9b7f31aa31545c" "checksum num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "e83d528d2677f0518c570baf2b7abdcf0cd2d248860b68507bdcb3e91d4c0cea" "checksum num-rational 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "ee314c74bd753fc86b4780aa9475da469155f3848473a261d2d18e35245a784e" "checksum num-traits 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)" = "92e5113e9fd4cc14ded8e499429f396a20f98c772a47cc8622a736e1ec843c31" "checksum num-traits 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "630de1ef5cc79d0cdd78b7e33b81f083cbfe90de0f4b2b2f07f905867c70e9fe" "checksum num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c51a3322e4bca9d212ad9a158a02abc6934d005490c054a2778df73a70aa0a30" +"checksum objc 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "9833ab0efe5361b1e2122a0544a5d3359576911a42cb098c2e59be8650807367" +"checksum objc-foundation 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1add1b659e36c9607c7aab864a76c7a4c2760cd0cd2e120f3fb8b952c7e22bf9" +"checksum objc_id 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c92d4ddb4bd7b50d730c215ff871754d0da6b2178849f8a2a2ab69712d0c073b" "checksum open 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c281318d992e4432cfa799969467003d05921582a7489a8325e37f8a450d5113" "checksum openssl 0.9.24 (registry+https://github.com/rust-lang/crates.io-index)" = "a3605c298474a3aa69de92d21139fb5e2a81688d308262359d85cdd0d12a7985" "checksum openssl-sys 0.9.33 (registry+https://github.com/rust-lang/crates.io-index)" = "d8abc04833dcedef24221a91852931df2f63e3369ae003134e70aff3645775cc" diff --git a/org.gnome.Podcasts.json b/org.gnome.Podcasts.json index bbfba50..662d37a 100644 --- a/org.gnome.Podcasts.json +++ b/org.gnome.Podcasts.json @@ -35,6 +35,16 @@ } }, "modules" : [ + { + "name" : "libhandy", + "buildsystem" : "meson", + "sources" : [ + { + "type" : "git", + "url" : "https://source.puri.sm/Librem5/libhandy" + } + ] + }, { "name" : "gnome-podcasts", "buildsystem" : "meson", diff --git a/podcasts-gtk/Cargo.toml b/podcasts-gtk/Cargo.toml index 4abd3cd..57ed53d 100644 --- a/podcasts-gtk/Cargo.toml +++ b/podcasts-gtk/Cargo.toml @@ -38,6 +38,9 @@ version = "0.4.1" features = ["v2_50"] version = "0.4.1" +[dependencies.libhandy] +git = "https://gitlab.gnome.org/jsparber/libhandy-rs" + [dependencies.podcasts-data] path = "../podcasts-data" diff --git a/podcasts-gtk/resources/gtk/episode_widget.ui b/podcasts-gtk/resources/gtk/episode_widget.ui index 08f03b0..f89c41f 100644 --- a/podcasts-gtk/resources/gtk/episode_widget.ui +++ b/podcasts-gtk/resources/gtk/episode_widget.ui @@ -54,7 +54,6 @@ Tobias Bernard False Episode Title end - 55 True False 1 diff --git a/podcasts-gtk/resources/gtk/headerbar.ui b/podcasts-gtk/resources/gtk/headerbar.ui index 6dd061b..2879d0b 100644 --- a/podcasts-gtk/resources/gtk/headerbar.ui +++ b/podcasts-gtk/resources/gtk/headerbar.ui @@ -3,20 +3,20 @@ Copyright (C) 2017 - 2018 -This file is part of Hammond. +This file is part of GNOEM Podcasts. -Hammond is free software: you can redistribute it and/or modify +GNOEM Podcasts 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. -Hammond is distributed in the hope that it will be useful, +GNOEM Podcasts 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 Hammond. If not, see . +along with GNOEM Podcasts. If not, see . Authors: Jordan Petridis @@ -24,9 +24,9 @@ Tobias Bernard --> - + - + @@ -41,10 +41,7 @@ Tobias Bernard True False center - 6 - 6 - 6 - 6 + 6 vertical 6 @@ -147,6 +144,43 @@ Tobias Bernard False True + + + True + False + vertical + + + True + False + center + center + + + False + True + 0 + + + + + False + True + Show Title + end + False + + + + + + False + True + 1 + + + + True @@ -191,72 +225,6 @@ Tobias Bernard 1 - - - False - True - - - False - - - False - True - 6 - 0 - - - - - False - Fetching new episodes - - - False - True - 1 - - - - - 3 - - - - - True - False - vertical - - - True - False - center - center - - - False - True - 0 - - - - - False - True - Show Title - - - - - - False - True - 1 - - - - True @@ -303,5 +271,41 @@ Tobias Bernard 2 + + + False + True + + + False + center + center + + + False + True + 6 + 0 + + + + + False + center + center + Fetching new episodes + end + + + False + True + 1 + + + + + 3 + + diff --git a/podcasts-gtk/resources/gtk/home_view.ui b/podcasts-gtk/resources/gtk/home_view.ui index 4d018bf..e64b1ba 100644 --- a/podcasts-gtk/resources/gtk/home_view.ui +++ b/podcasts-gtk/resources/gtk/home_view.ui @@ -3,20 +3,20 @@ Copyright (C) 2017 - 2018 -This file is part of Hammond. +This file is part of GNOME Podcasts. -Hammond is free software: you can redistribute it and/or modify +GNOME Podcasts 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. -Hammond is distributed in the hope that it will be useful, +GNOME Podcasts 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 Hammond. If not, see . +along with GNOME Podcasts. If not, see . Authors: Jordan Petridis @@ -24,376 +24,312 @@ Tobias Bernard --> - + - + - - container - 290 - 420 + True False + 32 + 32 + True vertical + 24 - - scrolled_window - True - True - never + + False + True + True + vertical + 6 - + True False + start + True + Today + + + + + + + False + False + 0 + + + + + True + False + 6 + 6 + True + 0 + in - + True False - - - True - False - True - vertical - - - - - - False - False - 0 - - - - - True - False - 32 - 32 - 32 - 32 - True - vertical - 24 - - - False - True - True - vertical - 6 - - - True - False - start - True - Today - - - - - - - False - False - 0 - - - - - True - False - True - 0 - in - - - True - False - True - none - - - - - - - - False - False - 1 - - - - - False - False - 0 - - - - - False - True - True - vertical - 6 - - - True - False - start - Yesterday - - - - - - - False - False - 0 - - - - - True - False - True - 0 - in - - - True - False - True - none - - - - - - - - False - False - 1 - - - - - False - False - 1 - - - - - False - True - True - vertical - 6 - - - True - False - start - This Week - - - - - - - False - False - 0 - - - - - True - False - True - 0 - in - - - True - False - True - none - - - - - - - - False - False - 1 - - - - - False - False - 2 - - - - - False - True - True - vertical - 6 - - - True - False - start - This Month - - - - - - - False - False - 0 - - - - - True - False - True - 0 - in - - - True - False - True - none - - - - - - - - False - False - 1 - - - - - False - False - 3 - - - - - False - True - True - vertical - 6 - - - True - False - start - True - Older - - - - - - - False - False - 0 - - - - - True - False - True - 0 - in - - - True - False - True - True - none - - - - - - - - False - False - 1 - - - - - False - False - 5 - - - - - False - True - 1 - - - - - True - False - True - vertical - - - - - - False - False - 2 - - + True + none + + + + + False + False + 1 + - True - True + False + False 0 + + + False + True + True + vertical + 6 + + + True + False + start + Yesterday + + + + + + + False + False + 0 + + + + + True + False + 6 + 6 + True + 0 + in + + + True + False + True + none + + + + + + + + False + False + 1 + + + + + False + False + 1 + + + + + False + True + True + vertical + 6 + + + True + False + start + This Week + + + + + + + False + False + 0 + + + + + True + False + 6 + 6 + True + 0 + in + + + True + False + True + none + + + + + + + + False + False + 1 + + + + + False + False + 2 + + + + + False + True + True + vertical + 6 + + + True + False + start + This Month + + + + + + + False + False + 0 + + + + + True + False + 6 + 6 + True + 0 + in + + + True + False + True + none + + + + + + + + False + False + 1 + + + + + False + False + 3 + + + + + False + True + True + vertical + 6 + + + True + False + start + True + Older + + + + + + + False + False + 0 + + + + + True + False + 6 + 6 + True + 0 + in + + + True + False + True + True + none + + + + + + + + False + False + 1 + + + + + False + False + 5 + + diff --git a/podcasts-gtk/resources/gtk/inapp_notif.ui b/podcasts-gtk/resources/gtk/inapp_notif.ui index 9fd61f0..0b76e4f 100644 --- a/podcasts-gtk/resources/gtk/inapp_notif.ui +++ b/podcasts-gtk/resources/gtk/inapp_notif.ui @@ -1,7 +1,35 @@ - + - + + + + + + True False @@ -21,18 +49,20 @@ False center center - 3 - 3 + 3 + 3 6 + 150 True False center center - 12 - 12 + 12 + 12 An in-app action notification + start False diff --git a/podcasts-gtk/resources/gtk/show_widget.ui b/podcasts-gtk/resources/gtk/show_widget.ui index e27aaae..0eccaa1 100644 --- a/podcasts-gtk/resources/gtk/show_widget.ui +++ b/podcasts-gtk/resources/gtk/show_widget.ui @@ -3,20 +3,20 @@ Copyright (C) 2017 - 2018 -This file is part of Hammond. +This file is part of GNOME Podcasts. -Hammond is free software: you can redistribute it and/or modify +GNOME Podcasts 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. -Hammond is distributed in the hope that it will be useful, +GNOME Podcasts 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 Hammond. If not, see . +along with GNOME Podcasts. If not, see . Authors: Jordan Petridis @@ -24,209 +24,112 @@ Tobias Bernard --> - + - + - - 290 - 420 + True False + 32 + 32 + True vertical - - - scrolled_window - True - True - True - never - - - True - False - - - True - False - True - True - - - True - False - True - vertical - - - - - - False - False - 0 - - - - - True - False - 32 - 32 - 32 - 32 - True - vertical - 6 - - - True - False - vertical - 6 - - - True - False - 256 - image-x-generic-symbolic - - - False - False - 0 - - - - - True - True - never - 80 - - - True - False - none - - - True - False - center - center - This is embarrassing! -Sorry, we could not find a description for this show. - True - center - True - 70 - - - - - - - False - False - 1 - - - - - False - False - 6 - 1 - - - - - True - False - 0 - in - - - True - False - none - - - - - - - - False - False - 2 - - - - - False - True - 1 - - - - - True - False - True - vertical - - - - - - False - False - end - 2 - - - - - - - - - False - True - 0 - - - - - False - bottom + 6 True False - 6 - 6 - 6 - 6 vertical + 6 - + True - True - True - Mark all episodes as listened - True + False + 256 + image-x-generic-symbolic False - True + False 0 + + + True + True + never + 80 + + + True + False + none + + + True + False + center + center + This is embarrasing! +Sorry, we could not find a description for this Show. + True + center + True + 70 + + + + + + + False + False + 1 + + + + False + False + 6 + 0 + + + + + True + False + 6 + 6 + 0 + in + + + True + False + + + True + False + none + False + + + + + + + + + + True + True + 1 + diff --git a/podcasts-gtk/resources/gtk/shows_child.ui b/podcasts-gtk/resources/gtk/shows_child.ui deleted file mode 100644 index 1a7d5fd..0000000 --- a/podcasts-gtk/resources/gtk/shows_child.ui +++ /dev/null @@ -1,58 +0,0 @@ - - - - - - - - - - - 256 - 256 - True - False - center - center - vertical - - - True - False - center - center - 256 - image-x-generic-symbolic - 0 - - - False - True - 0 - - - - diff --git a/podcasts-gtk/resources/gtk/shows_view.ui b/podcasts-gtk/resources/gtk/shows_view.ui deleted file mode 100644 index 044233a..0000000 --- a/podcasts-gtk/resources/gtk/shows_view.ui +++ /dev/null @@ -1,74 +0,0 @@ - - - - - - - - - - - fb_parent - 290 - 420 - True - False - vertical - - - scrolled_window - True - True - - - True - False - - - True - False - center - start - 24 - 24 - True - 12 - 12 - 20 - none - - - - - - - True - True - 0 - - - - diff --git a/podcasts-gtk/resources/resources.xml b/podcasts-gtk/resources/resources.xml index e2cd94b..e04850a 100644 --- a/podcasts-gtk/resources/resources.xml +++ b/podcasts-gtk/resources/resources.xml @@ -7,8 +7,6 @@ gtk/empty_show.ui gtk/home_view.ui gtk/home_episode.ui - gtk/shows_view.ui - gtk/shows_child.ui gtk/headerbar.ui gtk/inapp_notif.ui gtk/hamburger.ui @@ -20,4 +18,4 @@ gtk/prefs.ui gtk/style.css - \ No newline at end of file + diff --git a/podcasts-gtk/src/main.rs b/podcasts-gtk/src/main.rs index ef5364d..5f4b34e 100644 --- a/podcasts-gtk/src/main.rs +++ b/podcasts-gtk/src/main.rs @@ -61,8 +61,10 @@ extern crate pretty_assertions; extern crate chrono; extern crate crossbeam_channel; extern crate fragile; +extern crate gettextrs; extern crate html2text; extern crate humansize; +extern crate libhandy; extern crate loggerv; extern crate open; extern crate podcasts_data; @@ -73,8 +75,6 @@ extern crate reqwest; extern crate serde_json; extern crate url; -extern crate gettextrs; - use log::Level; use gtk::prelude::*; diff --git a/podcasts-gtk/src/stacks/home.rs b/podcasts-gtk/src/stacks/home.rs index 58b6743..252bd59 100644 --- a/podcasts-gtk/src/stacks/home.rs +++ b/podcasts-gtk/src/stacks/home.rs @@ -29,12 +29,12 @@ pub(crate) struct HomeStack { impl HomeStack { pub(crate) fn new(sender: Sender) -> Result { - let episodes = HomeView::new(sender.clone())?; + let episodes = HomeView::new(sender.clone(), None)?; let empty = EmptyView::new(); let stack = gtk::Stack::new(); let state = State::Empty; - stack.add_named(&episodes.container, "home"); + stack.add_named(episodes.view.container(), "home"); stack.add_named(&empty.container, "empty"); let mut home = HomeStack { @@ -54,12 +54,6 @@ impl HomeStack { } pub(crate) fn update(&mut self) -> Result<(), Error> { - // Copy the vertical scrollbar adjustment from the old view. - self.episodes - .save_alignment() - .map_err(|err| error!("Failed to set episodes_view alignment: {}", err)) - .ok(); - self.replace_view()?; // Determine the actual state. self.determine_state().map_err(From::from) @@ -67,14 +61,17 @@ impl HomeStack { fn replace_view(&mut self) -> Result<(), Error> { // Get the container of the view - let old = &self.episodes.container.clone(); - let eps = HomeView::new(self.sender.clone())?; + let old = &self.episodes.view.container().clone(); + + // Copy the vertical scrollbar adjustment from the old view. + let vadj = self.episodes.view.get_vadjustment(); + let eps = HomeView::new(self.sender.clone(), vadj)?; // Remove the old widget and add the new one // 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.container, "home"); + self.stack.add_named(eps.view.container(), "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 ad58ba9..f275699 100644 --- a/podcasts-gtk/src/stacks/populated.rs +++ b/podcasts-gtk/src/stacks/populated.rs @@ -34,12 +34,12 @@ impl PopulatedStack { pub(crate) fn new(sender: Sender) -> PopulatedStack { let stack = gtk::Stack::new(); let state = PopulatedState::View; - let populated = ShowsView::new(sender.clone()); + let populated = ShowsView::new(sender.clone(), None); let show = Rc::new(ShowWidget::default()); let container = gtk::Box::new(gtk::Orientation::Horizontal, 0); - stack.add_named(&populated.container, "shows"); - stack.add_named(&show.container, "widget"); + stack.add_named(populated.view.container(), "shows"); + stack.add_named(show.view.container(), "widget"); container.add(&stack); container.show_all(); @@ -70,33 +70,35 @@ impl PopulatedStack { } pub(crate) fn replace_shows(&mut self) -> Result<(), Error> { - let old = &self.populated.container.clone(); + let old = &self.populated.view.container().clone(); debug!("Name: {:?}", WidgetExt::get_name(old)); - self.populated - .save_alignment() - .map_err(|err| error!("Failed to set episodes_view alignment: {}", err)) - .ok(); - - let pop = ShowsView::new(self.sender.clone()); + let vadj = self.populated.view.get_vadjustment(); + let pop = ShowsView::new(self.sender.clone(), vadj); self.populated = pop; self.stack.remove(old); - self.stack.add_named(&self.populated.container, "shows"); + self.stack + .add_named(self.populated.view.container(), "shows"); old.destroy(); Ok(()) } pub(crate) fn replace_widget(&mut self, pd: Arc) -> Result<(), Error> { - let old = self.show.container.clone(); + let old = self.show.view.container().clone(); - // save the ShowWidget vertical scrollbar alignment - self.show.show_id().map(|id| self.show.save_vadjustment(id)); + // Get the ShowWidget vertical alignment + let vadj = self.show.view.get_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(), vadj), + // else leave the valignemnt to default + _ => ShowWidget::new(pd.clone(), self.sender.clone(), None), + }; - let new = ShowWidget::new(pd, self.sender.clone()); self.show = new; self.stack.remove(&old); - self.stack.add_named(&self.show.container, "widget"); + self.stack.add_named(self.show.view.container(), "widget"); // The current visible child might change depending on // removal and insertion in the gtk::Stack, so we have @@ -108,7 +110,7 @@ impl PopulatedStack { } pub(crate) fn update_widget(&mut self) -> Result<(), Error> { - let old = self.show.container.clone(); + let old = self.show.view.container().clone(); let id = self.show.show_id(); if id.is_none() { return Ok(()); diff --git a/podcasts-gtk/src/widgets/base_view.rs b/podcasts-gtk/src/widgets/base_view.rs new file mode 100644 index 0000000..f9e901e --- /dev/null +++ b/podcasts-gtk/src/widgets/base_view.rs @@ -0,0 +1,56 @@ +use gtk::{self, prelude::*, Adjustment, Orientation, PolicyType}; +use utils::smooth_scroll_to; + +#[derive(Debug, Clone)] +pub(crate) struct BaseView { + container: gtk::Box, + 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(None, None); + + scrolled_window.set_policy(PolicyType::Never, PolicyType::Automatic); + container.add(&scrolled_window); + container.show_all(); + + BaseView { + container, + scrolled_window, + } + } +} + +impl BaseView { + pub(crate) fn container(&self) -> >k::Box { + &self.container + } + + pub(crate) fn scrolled_window(&self) -> >k::ScrolledWindow { + &self.scrolled_window + } + + pub(crate) fn add>(&self, widget: &T) { + self.scrolled_window.add(widget); + } + + pub(crate) fn set_adjutments<'a, 'b>( + &self, + hadjustment: Option<&'a Adjustment>, + vadjustment: Option<&'b Adjustment>, + ) { + if let Some(h) = hadjustment { + smooth_scroll_to(&self.scrolled_window, h); + } + + if let Some(v) = vadjustment { + smooth_scroll_to(&self.scrolled_window, v); + } + } + + pub(crate) fn get_vadjustment(&self) -> Option { + self.scrolled_window().get_vadjustment() + } +} diff --git a/podcasts-gtk/src/widgets/home_view.rs b/podcasts-gtk/src/widgets/home_view.rs index 442b016..af85708 100644 --- a/podcasts-gtk/src/widgets/home_view.rs +++ b/podcasts-gtk/src/widgets/home_view.rs @@ -1,26 +1,19 @@ use chrono::prelude::*; use failure::Error; -use gtk; -use gtk::prelude::*; +use gtk::{self, prelude::*, Adjustment}; use crossbeam_channel::Sender; -use fragile::Fragile; +use libhandy::{Column, ColumnExt}; use podcasts_data::dbqueries; use podcasts_data::EpisodeWidgetModel; use app::Action; use utils::{self, lazy_load_full}; -use widgets::EpisodeWidget; +use widgets::{BaseView, EpisodeWidget}; use std::cell::Cell; use std::rc::Rc; -use std::sync::Mutex; - -lazy_static! { - pub(crate) static ref EPISODES_VIEW_VALIGNMENT: Mutex>> = - Mutex::new(None); -} #[derive(Debug, Clone)] enum ListSplit { @@ -33,8 +26,7 @@ enum ListSplit { #[derive(Debug, Clone)] pub(crate) struct HomeView { - pub(crate) container: gtk::Box, - scrolled_window: gtk::ScrolledWindow, + pub(crate) view: BaseView, frame_parent: gtk::Box, today_box: gtk::Box, yday_box: gtk::Box, @@ -50,9 +42,8 @@ pub(crate) struct HomeView { impl Default for HomeView { fn default() -> Self { + let view = BaseView::default(); let builder = gtk::Builder::new_from_resource("/org/gnome/Podcasts/gtk/home_view.ui"); - let container: gtk::Box = builder.get_object("container").unwrap(); - let scrolled_window: gtk::ScrolledWindow = builder.get_object("scrolled_window").unwrap(); let frame_parent: gtk::Box = builder.get_object("frame_parent").unwrap(); let today_box: gtk::Box = builder.get_object("today_box").unwrap(); let yday_box: gtk::Box = builder.get_object("yday_box").unwrap(); @@ -65,9 +56,19 @@ impl Default for HomeView { let month_list: gtk::ListBox = builder.get_object("month_list").unwrap(); let rest_list: gtk::ListBox = builder.get_object("rest_list").unwrap(); + let column = Column::new(); + column.show(); + column.set_maximum_width(700); + // For some reason the Column is not seen as a gtk::container + // and therefore we can't call add() without the cast + let column = column.upcast::(); + let column = column.downcast::().unwrap(); + + column.add(&frame_parent); + view.add(&column); + HomeView { - container, - scrolled_window, + view, frame_parent, today_box, yday_box, @@ -85,73 +86,51 @@ impl Default for HomeView { // TODO: REFACTOR ME impl HomeView { - pub(crate) fn new(sender: Sender) -> Result, Error> { + pub(crate) fn new( + sender: Sender, + vadj: Option, + ) -> Result, Error> { use self::ListSplit::*; - let view = Rc::new(HomeView::default()); + let home = Rc::new(HomeView::default()); let ignore = utils::get_ignored_shows()?; let episodes = dbqueries::get_episodes_widgets_filter_limit(&ignore, 100)?; let now_utc = Utc::now(); - let view_ = view.clone(); + let home_weak = Rc::downgrade(&home); let func = move |ep: EpisodeWidgetModel| { + let home = match home_weak.upgrade() { + Some(h) => h, + None => return, + }; + let epoch = ep.epoch(); let widget = HomeEpisode::new(ep, &sender); match split(&now_utc, i64::from(epoch)) { - Today => add_to_box(&widget, &view_.today_list, &view_.today_box), - Yday => add_to_box(&widget, &view_.yday_list, &view_.yday_box), - Week => add_to_box(&widget, &view_.week_list, &view_.week_box), - Month => add_to_box(&widget, &view_.month_list, &view_.month_box), - Rest => add_to_box(&widget, &view_.rest_list, &view_.rest_box), + Today => add_to_box(&widget, &home.today_list, &home.today_box), + Yday => add_to_box(&widget, &home.yday_list, &home.yday_box), + Week => add_to_box(&widget, &home.week_list, &home.week_box), + Month => add_to_box(&widget, &home.month_list, &home.month_box), + Rest => add_to_box(&widget, &home.rest_list, &home.rest_box), } }; - let view_ = view.clone(); + let home_weak = Rc::downgrade(&home); let callback = move || { - view_ - .set_vadjustment() - .map_err(|err| format!("{}", err)) - .ok(); + let home = match home_weak.upgrade() { + Some(h) => h, + None => return, + }; + + if let Some(ref v) = vadj { + home.view.set_adjutments(None, Some(v)) + }; }; lazy_load_full(episodes, func, callback); - view.container.show_all(); - Ok(view) - } - - /// Set scrolled window vertical adjustment. - fn set_vadjustment(&self) -> Result<(), Error> { - let guard = EPISODES_VIEW_VALIGNMENT - .lock() - .map_err(|err| format_err!("Failed to lock widget align mutex: {}", err))?; - - if let Some(ref fragile) = *guard { - // Copy the vertical scrollbar adjustment from the old view into the new one. - let res = fragile - .try_get() - .map(|x| utils::smooth_scroll_to(&self.scrolled_window, &x)) - .map_err(From::from); - - debug_assert!(res.is_ok()); - return res; - } - - Ok(()) - } - - /// Save the vertical scrollbar position. - pub(crate) fn save_alignment(&self) -> Result<(), Error> { - if let Ok(mut guard) = EPISODES_VIEW_VALIGNMENT.lock() { - let adj = self - .scrolled_window - .get_vadjustment() - .ok_or_else(|| format_err!("Could not get the adjustment"))?; - *guard = Some(Fragile::new(adj)); - info!("Saved episodes_view alignment."); - } - - Ok(()) + home.view.container().show_all(); + Ok(home) } } diff --git a/podcasts-gtk/src/widgets/mod.rs b/podcasts-gtk/src/widgets/mod.rs index 7ff0246..85aae87 100644 --- a/podcasts-gtk/src/widgets/mod.rs +++ b/podcasts-gtk/src/widgets/mod.rs @@ -1,5 +1,6 @@ mod aboutdialog; pub(crate) mod appnotif; +mod base_view; mod empty; mod episode; mod home_view; @@ -9,6 +10,7 @@ pub(crate) mod show_menu; 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::episode::EpisodeWidget; pub(crate) use self::home_view::HomeView; diff --git a/podcasts-gtk/src/widgets/show.rs b/podcasts-gtk/src/widgets/show.rs index 68e6191..acdd588 100644 --- a/podcasts-gtk/src/widgets/show.rs +++ b/podcasts-gtk/src/widgets/show.rs @@ -1,11 +1,11 @@ use glib; -use gtk; -use gtk::prelude::*; +use gtk::{self, prelude::*, Adjustment}; use crossbeam_channel::Sender; use failure::Error; use fragile::Fragile; use html2text; +use libhandy::{Column, ColumnExt}; use rayon; use podcasts_data::dbqueries; @@ -13,20 +13,14 @@ use podcasts_data::Show; use app::Action; use utils::{self, lazy_load}; -use widgets::{EpisodeWidget, ShowMenu}; +use widgets::{BaseView, EpisodeWidget, ShowMenu}; use std::rc::Rc; -use std::sync::{Arc, Mutex}; - -lazy_static! { - static ref SHOW_WIDGET_VALIGNMENT: Mutex)>> = - Mutex::new(None); -} +use std::sync::Arc; #[derive(Debug, Clone)] pub(crate) struct ShowWidget { - pub(crate) container: gtk::Box, - scrolled_window: gtk::ScrolledWindow, + pub(crate) view: BaseView, cover: gtk::Image, description: gtk::Label, episodes: gtk::ListBox, @@ -36,16 +30,25 @@ pub(crate) struct ShowWidget { impl Default for ShowWidget { fn default() -> Self { let builder = gtk::Builder::new_from_resource("/org/gnome/Podcasts/gtk/show_widget.ui"); - let container: gtk::Box = builder.get_object("container").unwrap(); - let scrolled_window: gtk::ScrolledWindow = builder.get_object("scrolled_window").unwrap(); - let episodes = builder.get_object("episodes").unwrap(); - + let sub_cont: gtk::Box = builder.get_object("sub_container").unwrap(); let cover: gtk::Image = builder.get_object("cover").unwrap(); let description: gtk::Label = builder.get_object("description").unwrap(); + let episodes = builder.get_object("episodes").unwrap(); + let view = BaseView::default(); + + let column = Column::new(); + column.set_maximum_width(700); + // For some reason the Column is not seen as a gtk::container + // and therefore we can't call add() without the cast + let column = column.upcast::(); + let column = column.downcast::().unwrap(); + + column.add(&sub_cont); + view.add(&column); + column.show_all(); ShowWidget { - container, - scrolled_window, + view, cover, description, episodes, @@ -55,7 +58,11 @@ impl Default for ShowWidget { } impl ShowWidget { - pub(crate) fn new(pd: Arc, sender: Sender) -> Rc { + pub(crate) fn new( + pd: Arc, + sender: Sender, + vadj: Option, + ) -> Rc { let mut pdw = ShowWidget::default(); pdw.init(&pd); @@ -63,7 +70,7 @@ impl ShowWidget { sender.send(Action::InitShowMenu(Fragile::new(menu))); let pdw = Rc::new(pdw); - let res = populate_listbox(&pdw, pd.clone(), sender); + let res = populate_listbox(&pdw, pd.clone(), sender, vadj); debug_assert!(res.is_ok()); pdw @@ -85,49 +92,7 @@ impl ShowWidget { /// Set the description text. fn set_description(&self, text: &str) { self.description - .set_markup(html2text::from_read(text.as_bytes(), 70).trim()); - } - - /// Save the scrollbar adjustment to the cache. - pub(crate) fn save_vadjustment(&self, oldid: i32) -> Result<(), Error> { - if let Ok(mut guard) = SHOW_WIDGET_VALIGNMENT.lock() { - let adj = self - .scrolled_window - .get_vadjustment() - .ok_or_else(|| format_err!("Could not get the adjustment"))?; - *guard = Some((oldid, Fragile::new(adj))); - debug!("Widget Alignment was saved with ID: {}.", oldid); - } - - Ok(()) - } - - /// Set scrolled window vertical adjustment. - fn set_vadjustment(&self, pd: &Arc) -> Result<(), Error> { - let guard = SHOW_WIDGET_VALIGNMENT - .lock() - .map_err(|err| format_err!("Failed to lock widget align mutex: {}", err))?; - - if let Some((oldid, ref fragile)) = *guard { - // Only copy the old scrollbar if both widgets represent the same podcast. - debug!("PID: {}", pd.id()); - debug!("OLDID: {}", oldid); - if pd.id() != oldid { - debug!("Early return"); - return Ok(()); - }; - - // Copy the vertical scrollbar adjustment from the old view into the new one. - let res = fragile - .try_get() - .map(|x| utils::smooth_scroll_to(&self.scrolled_window, &x)) - .map_err(From::from); - - debug_assert!(res.is_ok()); - return res; - } - - Ok(()) + .set_markup(html2text::from_read(text.as_bytes(), 90).trim()); } pub(crate) fn show_id(&self) -> Option { @@ -137,9 +102,11 @@ impl ShowWidget { /// Populate the listbox with the shows episodes. fn populate_listbox( + // FIXME: we are leaking strong refs here show: &Rc, pd: Arc, sender: Sender, + vadj: Option, ) -> Result<(), Error> { use crossbeam_channel::bounded; @@ -176,9 +143,10 @@ fn populate_listbox( EpisodeWidget::new(ep, &sender).container.clone() }); - let callback = clone!(pd, show_ => move || { - let res = show_.set_vadjustment(&pd); - debug_assert!(res.is_ok()); + let callback = clone!(show_, vadj => move || { + if let Some(ref v) = vadj { + show_.view.set_adjutments(None, Some(v)) + }; }); lazy_load(episodes, list.clone(), constructor, callback); diff --git a/podcasts-gtk/src/widgets/shows_view.rs b/podcasts-gtk/src/widgets/shows_view.rs index 668be0c..e4bace7 100644 --- a/podcasts-gtk/src/widgets/shows_view.rs +++ b/podcasts-gtk/src/widgets/shows_view.rs @@ -1,53 +1,54 @@ -use gtk; -use gtk::prelude::*; +use gtk::{self, prelude::*, Adjustment, Align, SelectionMode}; use crossbeam_channel::Sender; use failure::Error; -use fragile::Fragile; use podcasts_data::dbqueries; use podcasts_data::Show; use app::Action; -use utils::{self, get_ignored_shows, lazy_load, set_image_from_path}; +use utils::{get_ignored_shows, lazy_load, set_image_from_path}; +use widgets::BaseView; use std::cell::Cell; use std::rc::Rc; use std::sync::Arc; -use std::sync::Mutex; - -lazy_static! { - static ref SHOWS_VIEW_VALIGNMENT: Mutex>> = Mutex::new(None); -} #[derive(Debug, Clone)] pub(crate) struct ShowsView { - pub(crate) container: gtk::Box, - scrolled_window: gtk::ScrolledWindow, + pub(crate) view: BaseView, flowbox: gtk::FlowBox, } impl Default for ShowsView { fn default() -> Self { - let builder = gtk::Builder::new_from_resource("/org/gnome/Podcasts/gtk/shows_view.ui"); - let container: gtk::Box = builder.get_object("fb_parent").unwrap(); - let scrolled_window: gtk::ScrolledWindow = builder.get_object("scrolled_window").unwrap(); - let flowbox: gtk::FlowBox = builder.get_object("flowbox").unwrap(); + let view = BaseView::default(); + let flowbox = gtk::FlowBox::new(); - ShowsView { - container, - scrolled_window, - flowbox, - } + flowbox.show(); + flowbox.set_vexpand(true); + flowbox.set_hexpand(true); + flowbox.set_row_spacing(12); + flowbox.set_can_focus(false); + flowbox.set_margin_top(32); + flowbox.set_margin_bottom(32); + flowbox.set_homogeneous(true); + flowbox.set_column_spacing(12); + flowbox.set_valign(Align::Start); + flowbox.set_halign(Align::Center); + flowbox.set_selection_mode(SelectionMode::None); + view.add(&flowbox); + + ShowsView { view, flowbox } } } impl ShowsView { - pub(crate) fn new(sender: Sender) -> Rc { + pub(crate) fn new(sender: Sender, vadj: Option) -> Rc { let pop = Rc::new(ShowsView::default()); pop.init(sender); // Populate the flowbox with the Shows. - let res = populate_flowbox(&pop); + let res = populate_flowbox(&pop, vadj); debug_assert!(res.is_ok()); pop } @@ -58,51 +59,18 @@ impl ShowsView { debug_assert!(res.is_ok()); }); } - - /// Set scrolled window vertical adjustment. - fn set_vadjustment(&self) -> Result<(), Error> { - let guard = SHOWS_VIEW_VALIGNMENT - .lock() - .map_err(|err| format_err!("Failed to lock widget align mutex: {}", err))?; - - if let Some(ref fragile) = *guard { - // Copy the vertical scrollbar adjustment from the old view into the new one. - let res = fragile - .try_get() - .map(|x| utils::smooth_scroll_to(&self.scrolled_window, &x)) - .map_err(From::from); - - debug_assert!(res.is_ok()); - return res; - } - - Ok(()) - } - - /// Save the vertical scrollbar position. - pub(crate) fn save_alignment(&self) -> Result<(), Error> { - if let Ok(mut guard) = SHOWS_VIEW_VALIGNMENT.lock() { - let adj = self - .scrolled_window - .get_vadjustment() - .ok_or_else(|| format_err!("Could not get the adjustment"))?; - *guard = Some(Fragile::new(adj)); - info!("Saved episodes_view alignment."); - } - - Ok(()) - } } -fn populate_flowbox(shows: &Rc) -> Result<(), Error> { +fn populate_flowbox(shows: &Rc, vadj: Option) -> Result<(), Error> { let ignore = get_ignored_shows()?; let podcasts = dbqueries::get_podcasts_filter(&ignore)?; let constructor = move |parent| ShowsChild::new(&parent).child; + // FIXME: We are, possibly,leaking the strong ref here let callback = clone!(shows => move || { - shows.set_vadjustment() - .map_err(|err| error!("Failed to set ShowsView Alignment: {}", err)) - .ok(); + if let Some(ref v) = vadj { + shows.view.set_adjutments(None, Some(v)) + }; }); let flowbox = shows.flowbox.clone(); @@ -125,28 +93,22 @@ fn on_child_activate(child: >k::FlowBoxChild, sender: &Sender) -> Resu Ok(()) } -#[derive(Debug)] +#[derive(Debug, Clone)] struct ShowsChild { - container: gtk::Box, cover: gtk::Image, child: gtk::FlowBoxChild, } impl Default for ShowsChild { fn default() -> Self { - let builder = gtk::Builder::new_from_resource("/org/gnome/Podcasts/gtk/shows_child.ui"); - - let container: gtk::Box = builder.get_object("fb_child").unwrap(); - let cover: gtk::Image = builder.get_object("pd_cover").unwrap(); - + let cover = gtk::Image::new_from_icon_name("image-x-generic-symbolic", -1); let child = gtk::FlowBoxChild::new(); - child.add(&container); - ShowsChild { - container, - cover, - child, - } + cover.set_pixel_size(256); + child.add(&cover); + child.show_all(); + + ShowsChild { cover, child } } } @@ -158,7 +120,7 @@ impl ShowsChild { } fn init(&self, pd: &Show) { - self.container.set_tooltip_text(pd.title()); + self.child.set_tooltip_text(pd.title()); WidgetExt::set_name(&self.child, &pd.id().to_string()); self.set_cover(pd.id())