Merge branch 'stack_redesign' into 'master'
Stack redesign See merge request alatiera/Hammond!4
This commit is contained in:
commit
da57a966d5
@ -20,6 +20,12 @@ It is recommended to add a pre-commit hook to run cargo test and cargo fmt
|
||||
cargo test -- --test-threads=1 && cargo fmt --all -- --write-mode=diff
|
||||
```
|
||||
|
||||
## Running the test suite
|
||||
|
||||
The test suite sets a temporary sqlite database in the /tmp folder. Due to that it's not possible to run them in parrallel.
|
||||
|
||||
In order to run the test suite use the following: `cargo test -- --test-threads=1`
|
||||
|
||||
# Issues, issues and more issues!
|
||||
|
||||
There are many ways you can contribute to Hammond, and all of them involve creating issues
|
||||
@ -67,8 +73,10 @@ Steps to reproduce:
|
||||
## Pull Request Process
|
||||
|
||||
1. Ensure your code compiles. Run `make` before creating the pull request.
|
||||
2. If you're adding new API, it must be properly documented.
|
||||
3. The commit message is formatted as follows:
|
||||
2. Ensure the test suit passes. Run `cargo test -- --test-threads=1`.
|
||||
3. Ensure your code is properly formated. Run `cargo fmt --all`.
|
||||
4. If you're adding new API, it must be properly documented.
|
||||
5. The commit message is formatted as follows:
|
||||
```
|
||||
component: <summary>
|
||||
|
||||
@ -78,7 +86,7 @@ Steps to reproduce:
|
||||
|
||||
<link to the bug ticket>
|
||||
```
|
||||
4. You may merge the pull request in once you have the sign-off of the maintainers, or if you
|
||||
6. You may merge the pull request in once you have the sign-off of the maintainers, or if you
|
||||
do not have permission to do that, you may request the second reviewer to merge it for you.
|
||||
|
||||
## Code of Conduct
|
||||
|
||||
78
Cargo.lock
generated
78
Cargo.lock
generated
@ -91,7 +91,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "base64"
|
||||
version = "0.6.0"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -590,7 +590,7 @@ dependencies = [
|
||||
"diesel 0.99.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"hammond-data 0.1.0",
|
||||
"hyper 0.11.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"hyper 0.11.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"mime_guess 1.8.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"reqwest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -636,10 +636,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "hyper"
|
||||
version = "0.11.7"
|
||||
version = "0.11.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"base64 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"base64 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bytes 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"futures 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"futures-cpupool 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -650,7 +650,7 @@ dependencies = [
|
||||
"percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"relay 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"time 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tokio-core 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tokio-core 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tokio-io 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tokio-proto 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tokio-service 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -663,9 +663,9 @@ version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"futures 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"hyper 0.11.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"hyper 0.11.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"native-tls 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tokio-core 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tokio-core 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tokio-io 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tokio-service 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tokio-tls 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -897,8 +897,8 @@ name = "native-tls"
|
||||
version = "0.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"openssl 0.9.22 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"schannel 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"openssl 0.9.23 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"schannel 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"security-framework 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"security-framework-sys 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -963,19 +963,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "openssl"
|
||||
version = "0.9.22"
|
||||
version = "0.9.23"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"openssl-sys 0.9.22 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"openssl-sys 0.9.23 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "openssl-sys"
|
||||
version = "0.9.22"
|
||||
version = "0.9.23"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"cc 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -1144,7 +1144,7 @@ dependencies = [
|
||||
"aho-corasick 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"regex-syntax 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"thread_local 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"thread_local 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
@ -1168,16 +1168,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"bytes 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"futures 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"hyper 0.11.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"hyper 0.11.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"hyper-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libflate 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"mime_guess 2.0.0-alpha.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"native-tls 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.23 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_json 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_json 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_urlencoded 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tokio-core 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tokio-core 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tokio-io 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tokio-tls 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"url 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -1220,13 +1220,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "schannel"
|
||||
version = "0.1.8"
|
||||
version = "0.1.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"advapi32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"crypt32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"secur32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -1281,18 +1281,18 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.23"
|
||||
version = "1.0.24"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.7"
|
||||
version = "1.0.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"itoa 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-traits 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.23 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1302,7 +1302,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"itoa 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.23 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"url 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
@ -1335,7 +1335,7 @@ dependencies = [
|
||||
"lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"phf_shared 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"precomputed-hash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.23 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"string_cache_codegen 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"string_cache_shared 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
@ -1409,10 +1409,10 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "thread_local"
|
||||
version = "0.3.4"
|
||||
version = "0.3.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
@ -1429,7 +1429,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tokio-core"
|
||||
version = "0.1.10"
|
||||
version = "0.1.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"bytes 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -1464,7 +1464,7 @@ dependencies = [
|
||||
"slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"smallvec 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"take 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tokio-core 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tokio-core 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tokio-io 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tokio-service 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
@ -1484,7 +1484,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"futures 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"native-tls 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tokio-core 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tokio-core 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tokio-io 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
@ -1619,7 +1619,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
"checksum atty 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "21e50800ec991574876040fff8ee46b136a53e985286fbe6a3bdfe6421b78860"
|
||||
"checksum backtrace 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8709cc7ec06f6f0ae6c2c7e12f6ed41540781f72b488d83734978295ceae182e"
|
||||
"checksum backtrace-sys 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "44585761d6161b0f57afc49482ab6bd067e4edef48c12a152c237eb0203f7661"
|
||||
"checksum base64 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "96434f987501f0ed4eb336a411e0631ecd1afa11574fe148587adc4ff96143c9"
|
||||
"checksum base64 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7c4a342b450b268e1be8036311e2c613d7f8a7ed31214dff1cc3b60852a3168d"
|
||||
"checksum bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aad18937a628ec6abcd26d1489012cc0e18c21798210f491af69ded9b881106d"
|
||||
"checksum bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4efd02e230a02e18f92fc2735f44597385ed02ad8f831e7c1c1156ee5e1ab3a5"
|
||||
"checksum bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b3c30d3802dfb7281680d6285f2ccdaa8c2d8fee41f93805dba5c4cf50dc23cf"
|
||||
@ -1672,7 +1672,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
"checksum gtk-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "905fcfbaaad1b44ec0b4bba9e4d527d728284c62bc2ba41fccedace2b096766f"
|
||||
"checksum html5ever 0.21.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ba3a1fd1857a714d410c191364c5d7bf8a6487c0ab5575146d37dd7eb17ef523"
|
||||
"checksum httparse 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "af2f2dd97457e8fb1ae7c5a420db346af389926e36f43768b96f101546b04a07"
|
||||
"checksum hyper 0.11.7 (registry+https://github.com/rust-lang/crates.io-index)" = "4959ca95f55df4265bff2ad63066147255e6fa733682cf6d1cb5eaff6e53324b"
|
||||
"checksum hyper 0.11.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e0594792d2109069d0caffd176f674d770a84adf024c5bb48e686b1ee5ac7659"
|
||||
"checksum hyper-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9c81fa95203e2a6087242c38691a0210f23e9f3f8f944350bd676522132e2985"
|
||||
"checksum idna 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "014b298351066f1512874135335d62a789ffe78a9974f94b43ed5621951eaf7d"
|
||||
"checksum iovec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b6e8b9c2247fcf6c6a1151f1156932be5606c9fd6f55a2d7f9fc1cb29386b2f7"
|
||||
@ -1709,8 +1709,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
"checksum num-traits 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "cacfcab5eb48250ee7d0c7896b51a2c5eec99c1feea5f32025635f5ae4b00070"
|
||||
"checksum num_cpus 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "514f0d73e64be53ff320680ca671b64fe3fb91da01e1ae2ddc99eb51d453b20d"
|
||||
"checksum open 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c281318d992e4432cfa799969467003d05921582a7489a8325e37f8a450d5113"
|
||||
"checksum openssl 0.9.22 (registry+https://github.com/rust-lang/crates.io-index)" = "419ef26bb651d72b6c5a603bcc4e4856a362460e62352dfffa53de91d2e81181"
|
||||
"checksum openssl-sys 0.9.22 (registry+https://github.com/rust-lang/crates.io-index)" = "5483bdc56756041ba6aa37c9cb59cc2219f012a2a1377d97ad35556ac6676ee7"
|
||||
"checksum openssl 0.9.23 (registry+https://github.com/rust-lang/crates.io-index)" = "169a4b9160baf9b9b1ab975418c673686638995ba921683a7f1e01470dcb8854"
|
||||
"checksum openssl-sys 0.9.23 (registry+https://github.com/rust-lang/crates.io-index)" = "2200ffec628e3f14c39fc0131a301db214f1a7d584e36507ee8700b0c7fb7a46"
|
||||
"checksum pango 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3e81c404ab81ea7ea2fc2431a0a7672507b80e4b8bf4b41eac3fc83cc665104e"
|
||||
"checksum pango-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "34f34a1be107fe16abb2744e0e206bee4b3b07460b5fddd3009a6aaf60bd69ab"
|
||||
"checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831"
|
||||
@ -1738,15 +1738,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
"checksum rustc-demangle 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "aee45432acc62f7b9a108cc054142dac51f979e69e71ddce7d6fc7adf29e817e"
|
||||
"checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda"
|
||||
"checksum safemem 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e27a8b19b835f7aea908818e871f5cc3a5a186550c30773be987e155e8163d8f"
|
||||
"checksum schannel 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7554288337c1110e34d7a2433518d889374c1de1a45f856b7bcddb03702131fc"
|
||||
"checksum schannel 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "4330c2e874379fbd28fa67ba43239dbe8c7fb00662ceb1078bd37474f08bf5ce"
|
||||
"checksum scheduled-thread-pool 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1a2ff3fc5223829be817806c6441279c676e454cc7da608faf03b0ccc09d3889"
|
||||
"checksum scoped-tls 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f417c22df063e9450888a7561788e9bd46d3bb3c1466435b4eccb903807f147d"
|
||||
"checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27"
|
||||
"checksum secur32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3f412dfa83308d893101dd59c10d6fda8283465976c28c287c5c855bf8d216bc"
|
||||
"checksum security-framework 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "dfa44ee9c54ce5eecc9de7d5acbad112ee58755239381f687e564004ba4a2332"
|
||||
"checksum security-framework-sys 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "5421621e836278a0b139268f36eee0dc7e389b784dc3f79d8f11aabadf41bead"
|
||||
"checksum serde 1.0.23 (registry+https://github.com/rust-lang/crates.io-index)" = "6a7c37d7f192f00041e8a613e936717923a71bc0c9051fc4425a49b104140f05"
|
||||
"checksum serde_json 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "ea28ea0cca944668919bec6af209864a8dfe769fd2b0b723f36b22e20c1bf69f"
|
||||
"checksum serde 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)" = "1c57ab4ec5fa85d08aaf8ed9245899d9bbdd66768945b21113b84d5f595cb6a1"
|
||||
"checksum serde_json 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7cf5b0b5b4bd22eeecb7e01ac2e1225c7ef5e4272b79ee28a8392a8c8489c839"
|
||||
"checksum serde_urlencoded 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ce0fd303af908732989354c6f02e05e2e6d597152870f2c6990efb0577137480"
|
||||
"checksum siphasher 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0df90a788073e8d0235a67e50441d47db7c8ad9debd91cbf43736a2a92d36537"
|
||||
"checksum slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "17b4fcaed89ab08ef143da37bc52adbcc04d4a69014f4c1208d6b51f0c47bc23"
|
||||
@ -1761,9 +1761,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
"checksum tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "87974a6f5c1dfb344d733055601650059a3363de2a6104819293baff662132d6"
|
||||
"checksum tendril 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9de21546595a0873061940d994bbbc5c35f024ae4fd61ec5c5b159115684f508"
|
||||
"checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096"
|
||||
"checksum thread_local 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "1697c4b57aeeb7a536b647165a2825faddffb1d3bad386d507709bd51a90bb14"
|
||||
"checksum thread_local 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "279ef31c19ededf577bfd12dfae728040a21f635b06a24cd670ff510edd38963"
|
||||
"checksum time 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)" = "d5d788d3aa77bc0ef3e9621256885555368b47bd495c13dd2e7413c89f845520"
|
||||
"checksum tokio-core 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "c843a027f7c1df5f81e7734a0df3f67bf329411781ebf36393ce67beef6071e3"
|
||||
"checksum tokio-core 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "c87c27560184212c9dc45cd8f38623f37918248aad5b58fb65303b5d07a98c6e"
|
||||
"checksum tokio-io 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "514aae203178929dbf03318ad7c683126672d4d96eccb77b29603d33c9e25743"
|
||||
"checksum tokio-proto 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8fbb47ae81353c63c487030659494b295f6cb6576242f907f203473b191b0389"
|
||||
"checksum tokio-service 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "24da22d077e0f15f55162bdbdc661228c1581892f52074fb242678d015b45162"
|
||||
|
||||
11
README.md
11
README.md
@ -8,8 +8,7 @@ This is a prototype of a podcast client written in Rust.
|
||||

|
||||
|
||||
## Getting in Touch
|
||||
If you have any questions regarding the
|
||||
use or development of Hammond, want to discuss design or simply hang out, please join us in [#hammond on irc.gnome.org.](irc://irc.gnome.org/#hammond)
|
||||
If you have any questions regarding the use or development of Hammond, want to discuss design or simply hang out, please join us in [#hammond on irc.gnome.org.](irc://irc.gnome.org/#hammond)
|
||||
|
||||
Sidenote:
|
||||
|
||||
@ -70,14 +69,6 @@ cd Hammond/
|
||||
cargo build --all
|
||||
```
|
||||
|
||||
## Call for designers
|
||||
|
||||
Currently there no design plans or mockups. They are highly needed in order to advance the Gtk Client.
|
||||
|
||||
There is the will for a complete client re-write if a someone contributes the mockups.
|
||||
|
||||
If you happen to be a designer and want to contribute please hope on [#hammond](irc://irc.gnome.org/#hammond) and get in touch with us.
|
||||
|
||||
## Contributing
|
||||
|
||||
There alot of thins yet to be done.
|
||||
|
||||
@ -81,7 +81,6 @@ pub(crate) fn new_episode(item: &Item, parent_id: i32) -> Result<NewEpisode> {
|
||||
.unwrap())
|
||||
}
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::fs::File;
|
||||
|
||||
@ -6,7 +6,7 @@ workspace = "../"
|
||||
|
||||
[dependencies]
|
||||
error-chain = "0.11.0"
|
||||
hyper = "0.11.7"
|
||||
hyper = "0.11.9"
|
||||
log = "0.3.8"
|
||||
mime_guess = "1.8.3"
|
||||
reqwest = "0.8.1"
|
||||
@ -14,7 +14,7 @@ tempdir = "0.3.5"
|
||||
|
||||
[dependencies.diesel]
|
||||
features = ["sqlite"]
|
||||
version = "0.99"
|
||||
version = "0.99.0"
|
||||
|
||||
[dependencies.hammond-data]
|
||||
path = "../hammond-data"
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Generated with glade 3.20.1 -->
|
||||
<!-- Generated with glade 3.20.2 -->
|
||||
<interface>
|
||||
<requires lib="gtk+" version="3.20"/>
|
||||
<object class="GtkBox" id="episode_box">
|
||||
@ -11,26 +11,23 @@
|
||||
<property name="margin_bottom">5</property>
|
||||
<property name="spacing">5</property>
|
||||
<child>
|
||||
<object class="GtkButton" id="play_button">
|
||||
<object class="GtkButton" id="delete_button">
|
||||
<property name="name">delete_button</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="halign">end</property>
|
||||
<property name="valign">center</property>
|
||||
<property name="margin_top">5</property>
|
||||
<property name="margin_bottom">5</property>
|
||||
<child>
|
||||
<object class="GtkImage">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="stock">gtk-media-play</property>
|
||||
<property name="use_fallback">True</property>
|
||||
<property name="icon_name">edit-delete-symbolic</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="padding">5</property>
|
||||
<property name="pack_type">end</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
@ -49,8 +46,7 @@
|
||||
<object class="GtkImage">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="stock">gtk-save</property>
|
||||
<property name="use_fallback">True</property>
|
||||
<property name="icon_name">document-save-symbolic</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
@ -63,23 +59,25 @@
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="delete_button">
|
||||
<property name="name">delete_button</property>
|
||||
<object class="GtkButton" id="play_button">
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="halign">end</property>
|
||||
<property name="valign">center</property>
|
||||
<property name="margin_top">5</property>
|
||||
<property name="margin_bottom">5</property>
|
||||
<child>
|
||||
<object class="GtkImage">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="stock">gtk-delete</property>
|
||||
<property name="icon_name">media-playback-start-symbolic</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="padding">5</property>
|
||||
<property name="pack_type">end</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
@ -95,7 +93,7 @@
|
||||
<object class="GtkImage">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="stock">gtk-undo</property>
|
||||
<property name="icon_name">edit-undo-symbolic</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
@ -118,7 +116,7 @@
|
||||
<object class="GtkImage">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="stock">gtk-apply</property>
|
||||
<property name="icon_name">object-select-symbolic</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Generated with glade 3.20.1 -->
|
||||
<!-- Generated with glade 3.20.2 -->
|
||||
<interface>
|
||||
<requires lib="gtk+" version="3.20"/>
|
||||
<object class="GtkPopover" id="add-popover">
|
||||
@ -109,24 +109,141 @@
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<object class="GtkHeaderBar" id="headerbar1">
|
||||
<object class="GtkBox" id="back_view">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="has_subtitle">False</property>
|
||||
<property name="show_close_button">True</property>
|
||||
<child>
|
||||
<object class="GtkMenuButton" id="add-toggle-button">
|
||||
<object class="GtkButton" id="back_button">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<child>
|
||||
<object class="GtkImage">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="icon_name">go-previous-symbolic</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child type="center">
|
||||
<object class="GtkLabel" id="show_title">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes">Show Title</property>
|
||||
<attributes>
|
||||
<attribute name="weight" value="bold"/>
|
||||
</attributes>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkSeparator">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="orientation">vertical</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="pack_type">end</property>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<object class="GtkHeaderBar" id="headerbar">
|
||||
<property name="can_focus">False</property>
|
||||
<property name="show_close_button">True</property>
|
||||
<child type="title">
|
||||
<object class="GtkStack" id="headerbar_stack">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="hexpand">True</property>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<object class="GtkBox" id="normal_view">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="spacing">5</property>
|
||||
<child>
|
||||
<object class="GtkSeparator">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="orientation">vertical</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="pack_type">end</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkMenuButton" id="menu">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<child>
|
||||
<object class="GtkImage">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="icon_name">open-menu-symbolic</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="pack_type">end</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="ref_button">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="always_show_image">True</property>
|
||||
<child>
|
||||
<object class="GtkImage">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="icon_name">view-refresh-symbolic</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="pack_type">end</property>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkMenuButton" id="add_toggle_button">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">False</property>
|
||||
<property name="tooltip_text" translatable="yes">Add a new feed</property>
|
||||
<property name="valign">center</property>
|
||||
<child>
|
||||
<object class="GtkImage" id="add-button-image">
|
||||
<object class="GtkImage" id="add-button-image1">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="stock">gtk-add</property>
|
||||
<property name="use_fallback">True</property>
|
||||
<property name="icon_name">list-add-symbolic</property>
|
||||
<property name="icon_size">1</property>
|
||||
</object>
|
||||
</child>
|
||||
@ -135,40 +252,23 @@
|
||||
</style>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="position">1</property>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">3</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<child type="center">
|
||||
<object class="GtkStackSwitcher" id="switch">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="halign">center</property>
|
||||
<property name="hexpand">True</property>
|
||||
<property name="icon_size">0</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="refbutton">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="valign">center</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="always_show_image">True</property>
|
||||
<child>
|
||||
<object class="GtkImage">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="stock">gtk-refresh</property>
|
||||
<property name="use_fallback">True</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="pack_type">end</property>
|
||||
<property name="position">-1</property>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">4</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Generated with glade 3.20.1 -->
|
||||
<!-- Generated with glade 3.20.2 -->
|
||||
<interface domain="gnome-music">
|
||||
<requires lib="gtk+" version="3.12"/>
|
||||
<object class="GtkBox" id="podcast_widget">
|
||||
@ -35,8 +35,6 @@
|
||||
<property name="margin_right">1</property>
|
||||
<property name="margin_start">1</property>
|
||||
<property name="margin_end">1</property>
|
||||
<property name="stock">gtk-missing-image</property>
|
||||
<property name="use_fallback">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
@ -95,7 +93,7 @@
|
||||
<property name="can_focus">False</property>
|
||||
<property name="tooltip_text" translatable="yes">Unsubrscribe from this Podcast.
|
||||
Warn: This will delete downloaded content associated with this Podcast.</property>
|
||||
<property name="stock">gtk-delete</property>
|
||||
<property name="icon_name">edit-delete-symbolic</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
@ -118,7 +116,7 @@ Warn: This will delete downloaded content associated with this Podcast.</propert
|
||||
<object class="GtkImage">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="stock">gtk-apply</property>
|
||||
<property name="icon_name">object-select-symbolic</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
@ -3,10 +3,10 @@
|
||||
<gresource prefix="/org/gnome/hammond/">
|
||||
<file>banner.png</file>
|
||||
<file preprocess="xml-stripblanks">gtk/episode_widget.ui</file>
|
||||
<file preprocess="xml-stripblanks">gtk/podcast_widget.ui</file>
|
||||
<file preprocess="xml-stripblanks">gtk/show_widget.ui</file>
|
||||
<file preprocess="xml-stripblanks">gtk/empty_view.ui</file>
|
||||
<file preprocess="xml-stripblanks">gtk/podcasts_view.ui</file>
|
||||
<file preprocess="xml-stripblanks">gtk/podcasts_child.ui</file>
|
||||
<file preprocess="xml-stripblanks">gtk/shows_view.ui</file>
|
||||
<file preprocess="xml-stripblanks">gtk/shows_child.ui</file>
|
||||
<file preprocess="xml-stripblanks">gtk/headerbar.ui</file>
|
||||
</gresource>
|
||||
</gresources>
|
||||
|
||||
@ -4,412 +4,174 @@ use gtk::prelude::*;
|
||||
use hammond_data::Podcast;
|
||||
use hammond_data::dbqueries;
|
||||
|
||||
use widgets::podcast::PodcastWidget;
|
||||
use views::podcasts::PopulatedView;
|
||||
use views::shows::ShowsPopulated;
|
||||
use views::empty::EmptyView;
|
||||
|
||||
#[derive(Debug)]
|
||||
use widgets::show::ShowWidget;
|
||||
use headerbar::Header;
|
||||
|
||||
use std::rc::Rc;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Content {
|
||||
pub stack: gtk::Stack,
|
||||
pub widget: PodcastWidget,
|
||||
pub podcasts: PopulatedView,
|
||||
pub empty: EmptyView,
|
||||
pub shows: Rc<ShowStack>,
|
||||
episodes: Rc<EpisodeStack>,
|
||||
}
|
||||
|
||||
impl Content {
|
||||
pub fn new() -> Content {
|
||||
pub fn new(header: Rc<Header>) -> Rc<Content> {
|
||||
let stack = gtk::Stack::new();
|
||||
let shows = ShowStack::new(header);
|
||||
let episodes = EpisodeStack::new();
|
||||
|
||||
let widget = PodcastWidget::new();
|
||||
let podcasts = PopulatedView::new();
|
||||
let empty = EmptyView::new();
|
||||
stack.add_titled(&episodes.stack, "episodes", "Episodes");
|
||||
stack.add_titled(&shows.stack, "shows", "Shows");
|
||||
|
||||
stack.add_titled(&widget.container, "widget", "Episodes");
|
||||
stack.add_titled(&podcasts.container, "podcasts", "Shows");
|
||||
stack.add_named(&empty.container, "empty");
|
||||
|
||||
Content {
|
||||
Rc::new(Content {
|
||||
stack,
|
||||
widget,
|
||||
empty,
|
||||
podcasts,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_initialized() -> Content {
|
||||
let ct = Content::new();
|
||||
ct.init();
|
||||
ct
|
||||
}
|
||||
|
||||
pub fn init(&self) {
|
||||
self.podcasts.init(&self.stack);
|
||||
if self.podcasts.flowbox.get_children().is_empty() {
|
||||
self.stack.set_visible_child_name("empty");
|
||||
return;
|
||||
}
|
||||
|
||||
self.stack.set_visible_child_name("podcasts");
|
||||
}
|
||||
|
||||
fn replace_widget(&mut self, pdw: PodcastWidget) {
|
||||
let vis = self.stack.get_visible_child_name().unwrap();
|
||||
let old = self.stack.get_child_by_name("widget").unwrap();
|
||||
self.stack.remove(&old);
|
||||
|
||||
self.widget = pdw;
|
||||
self.stack
|
||||
.add_titled(&self.widget.container, "widget", "Episodes");
|
||||
self.stack.set_visible_child_name(&vis);
|
||||
old.destroy();
|
||||
}
|
||||
|
||||
fn replace_podcasts(&mut self, pop: PopulatedView) {
|
||||
let vis = self.stack.get_visible_child_name().unwrap();
|
||||
let old = self.stack.get_child_by_name("podcasts").unwrap();
|
||||
self.stack.remove(&old);
|
||||
|
||||
self.podcasts = pop;
|
||||
self.stack
|
||||
.add_titled(&self.podcasts.container, "podcasts", "Shows");
|
||||
self.stack.set_visible_child_name(&vis);
|
||||
old.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
// Experiementing with Wrapping gtk::Stack into a State machine.
|
||||
// Gonna revist it when TryInto trais is stabilized.
|
||||
pub struct ContentState<S> {
|
||||
content: Content,
|
||||
state: S,
|
||||
}
|
||||
|
||||
pub trait UpdateView {
|
||||
fn update(&mut self);
|
||||
}
|
||||
|
||||
pub struct Empty;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct PodcastsView {}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct WidgetsView {}
|
||||
|
||||
impl Into<ContentState<PodcastsView>> for ContentState<Empty> {
|
||||
fn into(self) -> ContentState<PodcastsView> {
|
||||
self.content.stack.set_visible_child_name("podcasts");
|
||||
|
||||
ContentState {
|
||||
content: self.content,
|
||||
state: PodcastsView {},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl UpdateView for ContentState<Empty> {
|
||||
fn update(&mut self) {}
|
||||
}
|
||||
|
||||
impl Into<ContentState<Empty>> for ContentState<PodcastsView> {
|
||||
fn into(self) -> ContentState<Empty> {
|
||||
self.content.stack.set_visible_child_name("empty");
|
||||
ContentState {
|
||||
content: self.content,
|
||||
state: Empty {},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Into<ContentState<WidgetsView>> for ContentState<PodcastsView> {
|
||||
fn into(self) -> ContentState<WidgetsView> {
|
||||
self.content.stack.set_visible_child_name("widget");
|
||||
|
||||
ContentState {
|
||||
content: self.content,
|
||||
state: WidgetsView {},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl UpdateView for ContentState<PodcastsView> {
|
||||
fn update(&mut self) {
|
||||
let pop = PopulatedView::new_initialized(&self.content.stack);
|
||||
self.content.replace_podcasts(pop)
|
||||
}
|
||||
}
|
||||
|
||||
impl Into<ContentState<PodcastsView>> for ContentState<WidgetsView> {
|
||||
fn into(self) -> ContentState<PodcastsView> {
|
||||
self.content.stack.set_visible_child_name("podcasts");
|
||||
ContentState {
|
||||
content: self.content,
|
||||
state: PodcastsView {},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Into<ContentState<Empty>> for ContentState<WidgetsView> {
|
||||
fn into(self) -> ContentState<Empty> {
|
||||
self.content.stack.set_visible_child_name("empty");
|
||||
ContentState {
|
||||
content: self.content,
|
||||
state: Empty {},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl UpdateView for ContentState<WidgetsView> {
|
||||
fn update(&mut self) {
|
||||
let old = self.content.stack.get_child_by_name("widget").unwrap();
|
||||
let id = WidgetExt::get_name(&old).unwrap();
|
||||
let pd = dbqueries::get_podcast_from_id(id.parse::<i32>().unwrap()).unwrap();
|
||||
|
||||
let pdw = PodcastWidget::new_initialized(&self.content.stack, &pd);
|
||||
self.content.replace_widget(pdw);
|
||||
}
|
||||
}
|
||||
|
||||
impl ContentState<PodcastsView> {
|
||||
#[allow(dead_code)]
|
||||
pub fn new() -> Result<ContentState<PodcastsView>, ContentState<Empty>> {
|
||||
let content = Content::new();
|
||||
|
||||
content.podcasts.init(&content.stack);
|
||||
if content.podcasts.flowbox.get_children().is_empty() {
|
||||
content.stack.set_visible_child_name("empty");
|
||||
return Err(ContentState {
|
||||
content,
|
||||
state: Empty {},
|
||||
});
|
||||
}
|
||||
|
||||
content.stack.set_visible_child_name("podcasts");
|
||||
Ok(ContentState {
|
||||
content,
|
||||
state: PodcastsView {},
|
||||
shows,
|
||||
episodes,
|
||||
})
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn update(&self) {
|
||||
self.shows.update();
|
||||
self.episodes.update();
|
||||
}
|
||||
|
||||
pub fn get_stack(&self) -> gtk::Stack {
|
||||
self.content.stack.clone()
|
||||
self.stack.clone()
|
||||
}
|
||||
}
|
||||
|
||||
fn replace_widget(stack: >k::Stack, pdw: &PodcastWidget) {
|
||||
let old = stack.get_child_by_name("widget").unwrap();
|
||||
stack.remove(&old);
|
||||
stack.add_titled(&pdw.container, "widget", "Episode");
|
||||
old.destroy();
|
||||
}
|
||||
|
||||
fn replace_podcasts(stack: >k::Stack, pop: &PopulatedView) {
|
||||
let old = stack.get_child_by_name("podcasts").unwrap();
|
||||
stack.remove(&old);
|
||||
stack.add_titled(&pop.container, "podcasts", "Shows");
|
||||
old.destroy();
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn show_widget(stack: >k::Stack) {
|
||||
stack.set_visible_child_name("widget")
|
||||
}
|
||||
|
||||
pub fn show_podcasts(stack: >k::Stack) {
|
||||
stack.set_visible_child_name("podcasts")
|
||||
}
|
||||
|
||||
pub fn show_empty(stack: >k::Stack) {
|
||||
stack.set_visible_child_name("empty")
|
||||
}
|
||||
|
||||
pub fn update_podcasts(stack: >k::Stack) {
|
||||
let pods = PopulatedView::new_initialized(stack);
|
||||
|
||||
if pods.flowbox.get_children().is_empty() {
|
||||
show_empty(stack)
|
||||
}
|
||||
|
||||
replace_podcasts(stack, &pods);
|
||||
}
|
||||
|
||||
pub fn update_widget(stack: >k::Stack, pd: &Podcast) {
|
||||
let pdw = PodcastWidget::new_initialized(stack, pd);
|
||||
replace_widget(stack, &pdw);
|
||||
}
|
||||
|
||||
pub fn update_podcasts_preserve_vis(stack: >k::Stack) {
|
||||
let vis = stack.get_visible_child_name().unwrap();
|
||||
update_podcasts(stack);
|
||||
if vis != "empty" {
|
||||
stack.set_visible_child_name(&vis)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn update_widget_preserve_vis(stack: >k::Stack, pd: &Podcast) {
|
||||
let vis = stack.get_visible_child_name().unwrap();
|
||||
update_widget(stack, pd);
|
||||
stack.set_visible_child_name(&vis)
|
||||
}
|
||||
|
||||
pub fn on_podcasts_child_activate(stack: >k::Stack, pd: &Podcast) {
|
||||
update_widget(stack, pd);
|
||||
stack.set_visible_child_full("widget", gtk::StackTransitionType::SlideLeft);
|
||||
}
|
||||
|
||||
// FIXME: Rename and remove aliases
|
||||
type ShowsPopulated = PopulatedView;
|
||||
type ShowsEmpty = EmptyView;
|
||||
type EpisodesPopulated = PodcastWidget;
|
||||
type EpisodesEmpty = EmptyView;
|
||||
|
||||
struct Populated;
|
||||
// struct Empty;
|
||||
// struct Shows;
|
||||
// struct Episodes;
|
||||
|
||||
// Thats probably too overengineered
|
||||
// struct StackStateMachine<S, T> {
|
||||
// shows: ShowsMachine<S>,
|
||||
// episodes: EpisodesMachine<S>,
|
||||
// stack: gtk::Stack,
|
||||
// state: T,
|
||||
// }
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
struct ShowsMachine<S> {
|
||||
populated: ShowsPopulated,
|
||||
empty: ShowsEmpty,
|
||||
stack: gtk::Stack,
|
||||
state: S,
|
||||
pub struct ShowStack {
|
||||
pub stack: gtk::Stack,
|
||||
header: Rc<Header>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct EpisodesMachine<S> {
|
||||
populated: EpisodesPopulated,
|
||||
empty: EpisodesEmpty,
|
||||
stack: gtk::Stack,
|
||||
state: S,
|
||||
impl ShowStack {
|
||||
fn new(header: Rc<Header>) -> Rc<ShowStack> {
|
||||
let stack = gtk::Stack::new();
|
||||
|
||||
let show = Rc::new(ShowStack {
|
||||
stack,
|
||||
header: header.clone(),
|
||||
});
|
||||
|
||||
let pop = ShowsPopulated::new_initialized(show.clone(), header);
|
||||
let widget = ShowWidget::new();
|
||||
let empty = EmptyView::new();
|
||||
|
||||
show.stack.add_named(&pop.container, "podcasts");
|
||||
show.stack.add_named(&widget.container, "widget");
|
||||
show.stack.add_named(&empty.container, "empty");
|
||||
|
||||
if pop.is_empty() {
|
||||
show.stack.set_visible_child_name("empty")
|
||||
} else {
|
||||
show.stack.set_visible_child_name("podcasts")
|
||||
}
|
||||
|
||||
// impl Into<StackStateMachine<Populated, Shows>> for StackStateMachine<Populated, Episodes> {
|
||||
// fn into(self) -> StackStateMachine<Populated, Shows> {
|
||||
// self.stack.set_visible_child_name("shows");
|
||||
|
||||
// StackStateMachine {
|
||||
// shows: self.shows,
|
||||
// episodes: self.episodes,
|
||||
// stack: self.stack,
|
||||
// state: Shows {},
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// impl Into<StackStateMachine<Populated, Episodes>> for StackStateMachine<Populated, Shows> {
|
||||
// fn into(self) -> StackStateMachine<Populated, Episodes> {
|
||||
// self.stack.set_visible_child_name("episodes");
|
||||
|
||||
// StackStateMachine {
|
||||
// shows: self.shows,
|
||||
// episodes: self.episodes,
|
||||
// stack: self.stack,
|
||||
// state: Episodes {},
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
impl Into<ShowsMachine<Populated>> for ShowsMachine<Empty> {
|
||||
fn into(self) -> ShowsMachine<Populated> {
|
||||
self.stack.set_visible_child_name("populated");
|
||||
|
||||
ShowsMachine {
|
||||
populated: self.populated,
|
||||
empty: self.empty,
|
||||
stack: self.stack,
|
||||
state: Populated {},
|
||||
}
|
||||
}
|
||||
show
|
||||
}
|
||||
|
||||
impl Into<ShowsMachine<Empty>> for ShowsMachine<Populated> {
|
||||
fn into(self) -> ShowsMachine<Empty> {
|
||||
// fn is_empty(&self) -> bool {
|
||||
// self.podcasts.is_empty()
|
||||
// }
|
||||
|
||||
pub fn update(&self) {
|
||||
self.update_podcasts();
|
||||
self.update_widget();
|
||||
}
|
||||
|
||||
pub fn update_podcasts(&self) {
|
||||
let vis = self.stack.get_visible_child_name().unwrap();
|
||||
let old = self.stack.get_child_by_name("podcasts").unwrap();
|
||||
|
||||
let pop = ShowsPopulated::new();
|
||||
pop.init(Rc::new(self.clone()), self.header.clone());
|
||||
|
||||
self.stack.remove(&old);
|
||||
self.stack.add_named(&pop.container, "podcasts");
|
||||
|
||||
if pop.is_empty() {
|
||||
self.stack.set_visible_child_name("empty");
|
||||
|
||||
ShowsMachine {
|
||||
populated: self.populated,
|
||||
empty: self.empty,
|
||||
stack: self.stack,
|
||||
state: Empty {},
|
||||
} else if vis != "empty" {
|
||||
self.stack.set_visible_child_name(&vis);
|
||||
} else {
|
||||
self.stack.set_visible_child_name("podcasts");
|
||||
}
|
||||
|
||||
old.destroy();
|
||||
}
|
||||
|
||||
pub fn replace_widget(&self, pd: &Podcast) {
|
||||
let old = self.stack.get_child_by_name("widget").unwrap();
|
||||
let new = ShowWidget::new_initialized(Rc::new(self.clone()), self.header.clone(), pd);
|
||||
|
||||
self.stack.remove(&old);
|
||||
self.stack.add_named(&new.container, "widget");
|
||||
}
|
||||
|
||||
pub fn update_widget(&self) {
|
||||
let vis = self.stack.get_visible_child_name().unwrap();
|
||||
let old = self.stack.get_child_by_name("widget").unwrap();
|
||||
|
||||
let id = WidgetExt::get_name(&old).unwrap();
|
||||
if id == "GtkBox" {
|
||||
return;
|
||||
}
|
||||
|
||||
let pd = dbqueries::get_podcast_from_id(id.parse::<i32>().unwrap());
|
||||
if let Ok(pd) = pd {
|
||||
self.replace_widget(&pd);
|
||||
self.stack.set_visible_child_name(&vis);
|
||||
old.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
impl Into<EpisodesMachine<Populated>> for EpisodesMachine<Empty> {
|
||||
fn into(self) -> EpisodesMachine<Populated> {
|
||||
self.stack.set_visible_child_name("populated");
|
||||
|
||||
EpisodesMachine {
|
||||
populated: self.populated,
|
||||
empty: self.empty,
|
||||
stack: self.stack,
|
||||
state: Populated {},
|
||||
pub fn switch_podcasts_animated(&self) {
|
||||
self.stack
|
||||
.set_visible_child_full("podcasts", gtk::StackTransitionType::SlideRight);
|
||||
}
|
||||
|
||||
pub fn switch_widget_animated(&self) {
|
||||
self.stack
|
||||
.set_visible_child_full("widget", gtk::StackTransitionType::SlideLeft)
|
||||
}
|
||||
}
|
||||
|
||||
impl Into<EpisodesMachine<Empty>> for EpisodesMachine<Populated> {
|
||||
fn into(self) -> EpisodesMachine<Empty> {
|
||||
self.stack.set_visible_child_name("empty");
|
||||
#[derive(Debug, Clone)]
|
||||
struct RecentEpisodes;
|
||||
|
||||
EpisodesMachine {
|
||||
populated: self.populated,
|
||||
empty: self.empty,
|
||||
stack: self.stack,
|
||||
state: Empty {},
|
||||
}
|
||||
}
|
||||
#[derive(Debug, Clone)]
|
||||
struct EpisodeStack {
|
||||
// populated: RecentEpisodes,
|
||||
// empty: EmptyView,
|
||||
stack: gtk::Stack,
|
||||
}
|
||||
|
||||
// enum StackStateWrapper<S> {
|
||||
// Shows(StackStateMachine<S, Shows>),
|
||||
// Episodes(StackStateMachine<S, Episodes>),
|
||||
// }
|
||||
impl EpisodeStack {
|
||||
fn new() -> Rc<EpisodeStack> {
|
||||
let _pop = RecentEpisodes {};
|
||||
let empty = EmptyView::new();
|
||||
let stack = gtk::Stack::new();
|
||||
|
||||
enum ShowStateWrapper {
|
||||
Populated(EpisodesMachine<Populated>),
|
||||
Empty(EpisodesMachine<Empty>),
|
||||
// stack.add_named(&pop.container, "populated");
|
||||
stack.add_named(&empty.container, "empty");
|
||||
// FIXME:
|
||||
stack.set_visible_child_name("empty");
|
||||
|
||||
Rc::new(EpisodeStack {
|
||||
// empty,
|
||||
// populated: pop,
|
||||
stack,
|
||||
})
|
||||
}
|
||||
|
||||
enum EpisodeStateWrapper {
|
||||
Populated(EpisodesMachine<Populated>),
|
||||
Empty(EpisodesMachine<Empty>),
|
||||
}
|
||||
|
||||
// impl <S>StackStateWrapper<S> {
|
||||
// fn switch(mut self) -> Self {
|
||||
// match self {
|
||||
// StackStateWrapper::Shows(val) => StackStateWrapper::Episodes(val.into()),
|
||||
// StackStateWrapper::Episodes(val) => StackStateWrapper::Shows(val.into())
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
impl ShowStateWrapper {
|
||||
fn switch(self) -> Self {
|
||||
match self {
|
||||
ShowStateWrapper::Populated(val) => ShowStateWrapper::Empty(val.into()),
|
||||
ShowStateWrapper::Empty(val) => ShowStateWrapper::Populated(val.into()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl EpisodeStateWrapper {
|
||||
fn switch(self) -> Self {
|
||||
match self {
|
||||
EpisodeStateWrapper::Populated(val) => EpisodeStateWrapper::Empty(val.into()),
|
||||
EpisodeStateWrapper::Empty(val) => EpisodeStateWrapper::Populated(val.into()),
|
||||
}
|
||||
fn update(&self) {
|
||||
// unimplemented!()
|
||||
}
|
||||
}
|
||||
|
||||
@ -4,8 +4,10 @@ use gtk::prelude::*;
|
||||
use hammond_data::Source;
|
||||
use hammond_data::utils::url_cleaner;
|
||||
|
||||
use std::rc::Rc;
|
||||
|
||||
use utils;
|
||||
// use content;
|
||||
use content::Content;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Header {
|
||||
@ -13,47 +15,69 @@ pub struct Header {
|
||||
refresh: gtk::Button,
|
||||
add_toggle: gtk::MenuButton,
|
||||
switch: gtk::StackSwitcher,
|
||||
stack: gtk::Stack,
|
||||
back_button: gtk::Button,
|
||||
show_title: gtk::Label,
|
||||
}
|
||||
|
||||
impl Header {
|
||||
pub fn new() -> Header {
|
||||
pub fn new() -> Rc<Header> {
|
||||
let builder = gtk::Builder::new_from_resource("/org/gnome/hammond/gtk/headerbar.ui");
|
||||
|
||||
let header: gtk::HeaderBar = builder.get_object("headerbar1").unwrap();
|
||||
let refresh: gtk::Button = builder.get_object("refbutton").unwrap();
|
||||
let add_toggle: gtk::MenuButton = builder.get_object("add-toggle-button").unwrap();
|
||||
let header: gtk::HeaderBar = builder.get_object("headerbar").unwrap();
|
||||
let refresh: gtk::Button = builder.get_object("ref_button").unwrap();
|
||||
let add_toggle: gtk::MenuButton = builder.get_object("add_toggle_button").unwrap();
|
||||
let switch: gtk::StackSwitcher = builder.get_object("switch").unwrap();
|
||||
let stack: gtk::Stack = builder.get_object("headerbar_stack").unwrap();
|
||||
let normal_view: gtk::Box = builder.get_object("normal_view").unwrap();
|
||||
let back_view: gtk::Box = builder.get_object("back_view").unwrap();
|
||||
let back_button: gtk::Button = builder.get_object("back_button").unwrap();
|
||||
let show_title: gtk::Label = builder.get_object("show_title").unwrap();
|
||||
|
||||
let stack = stack.clone();
|
||||
back_button.connect_clicked(clone!(stack => move |_| {
|
||||
stack.set_visible_child_name("normal_view");
|
||||
}));
|
||||
|
||||
switch.set_halign(gtk::Align::Center);
|
||||
switch.show();
|
||||
|
||||
Header {
|
||||
stack.add_named(&normal_view, "normal_view");
|
||||
stack.add_named(&back_view, "back_view");
|
||||
stack.set_transition_type(gtk::StackTransitionType::Crossfade);
|
||||
stack.set_visible_child_name("normal_view");
|
||||
|
||||
Rc::new(Header {
|
||||
container: header,
|
||||
refresh,
|
||||
add_toggle,
|
||||
switch,
|
||||
}
|
||||
stack,
|
||||
back_button,
|
||||
show_title,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn new_initialized(stack: >k::Stack) -> Header {
|
||||
let header = Header::new();
|
||||
header.init(stack);
|
||||
header
|
||||
}
|
||||
// pub fn new_initialized(content: Rc<Content>) -> Rc<Header> {
|
||||
// let header = Header::new();
|
||||
// header.init(content);
|
||||
// header
|
||||
// }
|
||||
|
||||
fn init(&self, stack: >k::Stack) {
|
||||
pub fn init(&self, content: Rc<Content>) {
|
||||
let builder = gtk::Builder::new_from_resource("/org/gnome/hammond/gtk/headerbar.ui");
|
||||
|
||||
let add_popover: gtk::Popover = builder.get_object("add-popover").unwrap();
|
||||
let new_url: gtk::Entry = builder.get_object("new-url").unwrap();
|
||||
let add_button: gtk::Button = builder.get_object("add-button").unwrap();
|
||||
self.switch.set_stack(stack);
|
||||
self.switch.set_stack(&content.stack);
|
||||
|
||||
new_url.connect_changed(move |url| {
|
||||
println!("{:?}", url.get_text());
|
||||
});
|
||||
|
||||
add_button.connect_clicked(clone!(stack, add_popover, new_url => move |_| {
|
||||
on_add_bttn_clicked(&stack, &new_url);
|
||||
add_button.connect_clicked(clone!(content, add_popover, new_url => move |_| {
|
||||
on_add_bttn_clicked(content.clone(), &new_url);
|
||||
|
||||
// TODO: lock the button instead of hiding and add notification of feed added.
|
||||
// TODO: map the spinner
|
||||
@ -62,13 +86,32 @@ impl Header {
|
||||
self.add_toggle.set_popover(&add_popover);
|
||||
|
||||
// FIXME: There appears to be a memmory leak here.
|
||||
self.refresh.connect_clicked(clone!(stack => move |_| {
|
||||
utils::refresh_feed(&stack, None, None);
|
||||
self.refresh.connect_clicked(clone!(content => move |_| {
|
||||
utils::refresh_feed(content.clone(), None, None);
|
||||
}));
|
||||
|
||||
let stack = self.stack.clone();
|
||||
self.back_button
|
||||
.connect_clicked(clone!(content => move |_| {
|
||||
content.shows.stack.set_visible_child_full("podcasts", gtk::StackTransitionType::SlideLeft);
|
||||
stack.set_visible_child_name("normal_view")
|
||||
}));
|
||||
}
|
||||
|
||||
pub fn switch_to_normal(&self) {
|
||||
self.stack.set_visible_child_name("normal_view")
|
||||
}
|
||||
|
||||
pub fn switch_to_back(&self) {
|
||||
self.stack.set_visible_child_name("back_view")
|
||||
}
|
||||
|
||||
pub fn set_show_title(&self, title: &str) {
|
||||
self.show_title.set_text(title)
|
||||
}
|
||||
}
|
||||
|
||||
fn on_add_bttn_clicked(stack: >k::Stack, entry: >k::Entry) {
|
||||
fn on_add_bttn_clicked(content: Rc<Content>, entry: >k::Entry) {
|
||||
let url = entry.get_text().unwrap_or_default();
|
||||
let url = url_cleaner(&url);
|
||||
let source = Source::from_url(&url);
|
||||
@ -76,7 +119,7 @@ fn on_add_bttn_clicked(stack: >k::Stack, entry: >k::Entry) {
|
||||
if let Ok(s) = source {
|
||||
info!("{:?} feed added", url);
|
||||
// update the db
|
||||
utils::refresh_feed(stack, Some(vec![s]), None);
|
||||
utils::refresh_feed(content, Some(vec![s]), None);
|
||||
} else {
|
||||
error!("Feed probably already exists.");
|
||||
error!("Error: {:?}", source.unwrap_err());
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
#![cfg_attr(feature = "cargo-clippy", allow(clone_on_ref_ptr))]
|
||||
|
||||
extern crate gdk;
|
||||
extern crate gdk_pixbuf;
|
||||
extern crate gio;
|
||||
@ -67,9 +69,14 @@ fn build_ui(app: >k::Application) {
|
||||
// let ct = content::ContentState::new().unwrap();
|
||||
// let stack = ct.get_stack();
|
||||
|
||||
let ct = content::Content::new_initialized();
|
||||
let stack = ct.stack;
|
||||
window.add(&stack);
|
||||
// let ct = content::Content::new_initialized();
|
||||
|
||||
// Get the headerbar
|
||||
let header = headerbar::Header::new();
|
||||
let ct = content::Content::new(header.clone());
|
||||
header.init(ct.clone());
|
||||
window.set_titlebar(&header.container);
|
||||
window.add(&ct.get_stack());
|
||||
|
||||
window.connect_delete_event(|w, _| {
|
||||
w.destroy();
|
||||
@ -92,8 +99,8 @@ fn build_ui(app: >k::Application) {
|
||||
app.add_action(&check);
|
||||
|
||||
// queue a db update 1 minute after the startup.
|
||||
gtk::idle_add(clone!(stack => move || {
|
||||
utils::refresh_feed(&stack, None, Some(60));
|
||||
gtk::idle_add(clone!(ct => move || {
|
||||
utils::refresh_feed(ct.clone(), None, Some(60));
|
||||
glib::Continue(false)
|
||||
}));
|
||||
|
||||
@ -102,10 +109,6 @@ fn build_ui(app: >k::Application) {
|
||||
glib::Continue(false)
|
||||
});
|
||||
|
||||
// Get the headerbar
|
||||
let header = headerbar::Header::new_initialized(&stack);
|
||||
window.set_titlebar(&header.container);
|
||||
|
||||
window.show_all();
|
||||
window.activate();
|
||||
app.connect_activate(move |_| ());
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
use glib;
|
||||
use gtk;
|
||||
use gdk_pixbuf::Pixbuf;
|
||||
|
||||
use hammond_data::feed;
|
||||
@ -9,12 +8,12 @@ use hammond_downloader::downloader;
|
||||
use std::{thread, time};
|
||||
use std::cell::RefCell;
|
||||
use std::sync::mpsc::{channel, Receiver};
|
||||
use std::borrow::Cow;
|
||||
|
||||
use content;
|
||||
use regex::Regex;
|
||||
use content::Content;
|
||||
|
||||
type Foo = RefCell<Option<(gtk::Stack, Receiver<bool>)>>;
|
||||
use std::rc::Rc;
|
||||
|
||||
type Foo = RefCell<Option<(Rc<Content>, Receiver<bool>)>>;
|
||||
|
||||
// Create a thread local storage that will store the arguments to be transfered.
|
||||
thread_local!(static GLOBAL: Foo = RefCell::new(None));
|
||||
@ -23,13 +22,13 @@ thread_local!(static GLOBAL: Foo = RefCell::new(None));
|
||||
/// If `source` is None, Fetches all the `Source` entries in the database and updates them.
|
||||
/// `delay` represents the desired time in seconds for the thread to sleep before executing.
|
||||
/// When It's done,it queues up a `podcast_view` refresh.
|
||||
pub fn refresh_feed(stack: >k::Stack, source: Option<Vec<Source>>, delay: Option<u64>) {
|
||||
pub fn refresh_feed(content: Rc<Content>, source: Option<Vec<Source>>, delay: Option<u64>) {
|
||||
// Create a async channel.
|
||||
let (sender, receiver) = channel();
|
||||
|
||||
// Pass the desired arguments into the Local Thread Storage.
|
||||
GLOBAL.with(clone!(stack => move |global| {
|
||||
*global.borrow_mut() = Some((stack, receiver));
|
||||
GLOBAL.with(clone!(content => move |global| {
|
||||
*global.borrow_mut() = Some((content.clone(), receiver));
|
||||
}));
|
||||
|
||||
thread::spawn(move || {
|
||||
@ -57,9 +56,9 @@ pub fn refresh_feed(stack: >k::Stack, source: Option<Vec<Source>>, delay: Opti
|
||||
|
||||
fn refresh_podcasts_view() -> glib::Continue {
|
||||
GLOBAL.with(|global| {
|
||||
if let Some((ref stack, ref reciever)) = *global.borrow() {
|
||||
if let Some((ref content, ref reciever)) = *global.borrow() {
|
||||
if reciever.try_recv().is_ok() {
|
||||
content::update_podcasts_preserve_vis(stack);
|
||||
content.update();
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -71,18 +70,6 @@ pub fn get_pixbuf_from_path(pd: &Podcast) -> Option<Pixbuf> {
|
||||
Pixbuf::new_from_file_at_scale(&img_path, 256, 256, true).ok()
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
// WIP: parse html to markup
|
||||
pub fn html_to_markup(s: &mut str) -> Cow<str> {
|
||||
s.trim();
|
||||
s.replace('&', "&");
|
||||
s.replace('<', "<");
|
||||
s.replace('>', ">");
|
||||
|
||||
let re = Regex::new("(?P<url>https?://[^\\s&,)(\"]+(&\\w=[\\w._-]?)*(#[\\w._-]+)?)").unwrap();
|
||||
re.replace_all(s, "<a href=\"$url\">$url</a>")
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use hammond_data::Source;
|
||||
|
||||
1
hammond-gtk/src/views/episodes.rs
Normal file
1
hammond-gtk/src/views/episodes.rs
Normal file
@ -0,0 +1 @@
|
||||
|
||||
@ -1,2 +1,3 @@
|
||||
pub mod podcasts;
|
||||
pub mod shows;
|
||||
pub mod episodes;
|
||||
pub mod empty;
|
||||
|
||||
@ -7,18 +7,20 @@ use hammond_data::dbqueries;
|
||||
use hammond_data::Podcast;
|
||||
|
||||
use utils::get_pixbuf_from_path;
|
||||
use content::ShowStack;
|
||||
use headerbar::Header;
|
||||
|
||||
use content;
|
||||
use std::rc::Rc;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct PopulatedView {
|
||||
pub struct ShowsPopulated {
|
||||
pub container: gtk::Box,
|
||||
pub flowbox: gtk::FlowBox,
|
||||
flowbox: gtk::FlowBox,
|
||||
viewport: gtk::Viewport,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct PodcastChild {
|
||||
struct ShowsChild {
|
||||
container: gtk::Box,
|
||||
title: gtk::Label,
|
||||
cover: gtk::Image,
|
||||
@ -27,14 +29,14 @@ struct PodcastChild {
|
||||
child: gtk::FlowBoxChild,
|
||||
}
|
||||
|
||||
impl PopulatedView {
|
||||
pub fn new() -> PopulatedView {
|
||||
let builder = gtk::Builder::new_from_resource("/org/gnome/hammond/gtk/podcasts_view.ui");
|
||||
impl ShowsPopulated {
|
||||
pub fn new() -> ShowsPopulated {
|
||||
let builder = gtk::Builder::new_from_resource("/org/gnome/hammond/gtk/shows_view.ui");
|
||||
let container: gtk::Box = builder.get_object("fb_parent").unwrap();
|
||||
let flowbox: gtk::FlowBox = builder.get_object("flowbox").unwrap();
|
||||
let viewport: gtk::Viewport = builder.get_object("viewport").unwrap();
|
||||
|
||||
PopulatedView {
|
||||
ShowsPopulated {
|
||||
container,
|
||||
flowbox,
|
||||
viewport,
|
||||
@ -42,23 +44,27 @@ impl PopulatedView {
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn new_initialized(stack: >k::Stack) -> PopulatedView {
|
||||
let pop = PopulatedView::new();
|
||||
pop.init(stack);
|
||||
pub fn new_initialized(show: Rc<ShowStack>, header: Rc<Header>) -> ShowsPopulated {
|
||||
let pop = ShowsPopulated::new();
|
||||
pop.init(show, header);
|
||||
pop
|
||||
}
|
||||
|
||||
pub fn init(&self, stack: >k::Stack) {
|
||||
pub fn init(&self, show: Rc<ShowStack>, header: Rc<Header>) {
|
||||
use gtk::WidgetExt;
|
||||
|
||||
// TODO: handle unwraps.
|
||||
// TODO: implement back button.
|
||||
self.flowbox
|
||||
.connect_child_activated(clone!(stack => move |_, child| {
|
||||
.connect_child_activated(clone!(show => move |_, child| {
|
||||
// This is such an ugly hack...
|
||||
// let id = child.get_name().unwrap().parse::<i32>().unwrap();
|
||||
let id = WidgetExt::get_name(child).unwrap().parse::<i32>().unwrap();
|
||||
let parent = dbqueries::get_podcast_from_id(id).unwrap();
|
||||
on_flowbox_child_activate(&stack, &parent);
|
||||
let pd = dbqueries::get_podcast_from_id(id).unwrap();
|
||||
|
||||
show.replace_widget(&pd);
|
||||
header.set_show_title(pd.title());
|
||||
header.switch_to_back();
|
||||
show.switch_widget_animated();
|
||||
}));
|
||||
// Populate the flowbox with the Podcasts.
|
||||
self.populate_flowbox();
|
||||
@ -69,17 +75,21 @@ impl PopulatedView {
|
||||
|
||||
if let Ok(pds) = podcasts {
|
||||
pds.iter().for_each(|parent| {
|
||||
let flowbox_child = PodcastChild::new_initialized(parent);
|
||||
let flowbox_child = ShowsChild::new_initialized(parent);
|
||||
self.flowbox.add(&flowbox_child.child);
|
||||
});
|
||||
self.flowbox.show_all();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.flowbox.get_children().is_empty()
|
||||
}
|
||||
}
|
||||
|
||||
impl PodcastChild {
|
||||
fn new() -> PodcastChild {
|
||||
let builder = gtk::Builder::new_from_resource("/org/gnome/hammond/gtk/podcasts_child.ui");
|
||||
impl ShowsChild {
|
||||
fn new() -> ShowsChild {
|
||||
let builder = gtk::Builder::new_from_resource("/org/gnome/hammond/gtk/shows_child.ui");
|
||||
|
||||
// Copy of gnome-music AlbumWidget
|
||||
let container: gtk::Box = builder.get_object("fb_child").unwrap();
|
||||
@ -91,7 +101,7 @@ impl PodcastChild {
|
||||
let child = gtk::FlowBoxChild::new();
|
||||
child.add(&container);
|
||||
|
||||
PodcastChild {
|
||||
ShowsChild {
|
||||
container,
|
||||
title,
|
||||
cover,
|
||||
@ -113,8 +123,8 @@ impl PodcastChild {
|
||||
self.configure_banner(pd);
|
||||
}
|
||||
|
||||
pub fn new_initialized(pd: &Podcast) -> PodcastChild {
|
||||
let child = PodcastChild::new();
|
||||
pub fn new_initialized(pd: &Podcast) -> ShowsChild {
|
||||
let child = ShowsChild::new();
|
||||
child.init(pd);
|
||||
|
||||
child
|
||||
@ -138,7 +148,3 @@ impl PodcastChild {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn on_flowbox_child_activate(stack: >k::Stack, parent: &Podcast) {
|
||||
content::on_podcasts_child_activate(stack, parent)
|
||||
}
|
||||
@ -13,8 +13,6 @@ use hammond_data::utils::*;
|
||||
use hammond_data::errors::*;
|
||||
use hammond_data::utils::replace_extra_spaces;
|
||||
|
||||
// use utils::html_to_markup;
|
||||
|
||||
use std::thread;
|
||||
use std::cell::RefCell;
|
||||
use std::sync::mpsc::{channel, Receiver};
|
||||
|
||||
@ -1,2 +1,2 @@
|
||||
pub mod podcast;
|
||||
pub mod show;
|
||||
pub mod episode;
|
||||
|
||||
@ -10,10 +10,13 @@ use hammond_downloader::downloader;
|
||||
|
||||
use widgets::episode::episodes_listbox;
|
||||
use utils::get_pixbuf_from_path;
|
||||
use content;
|
||||
use content::ShowStack;
|
||||
use headerbar::Header;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct PodcastWidget {
|
||||
use std::rc::Rc;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ShowWidget {
|
||||
pub container: gtk::Box,
|
||||
cover: gtk::Image,
|
||||
title: gtk::Label,
|
||||
@ -23,10 +26,10 @@ pub struct PodcastWidget {
|
||||
played: gtk::Button,
|
||||
}
|
||||
|
||||
impl PodcastWidget {
|
||||
pub fn new() -> PodcastWidget {
|
||||
impl ShowWidget {
|
||||
pub fn new() -> ShowWidget {
|
||||
// Adapted from gnome-music AlbumWidget
|
||||
let builder = gtk::Builder::new_from_resource("/org/gnome/hammond/gtk/podcast_widget.ui");
|
||||
let builder = gtk::Builder::new_from_resource("/org/gnome/hammond/gtk/show_widget.ui");
|
||||
let container: gtk::Box = builder.get_object("podcast_widget").unwrap();
|
||||
|
||||
let cover: gtk::Image = builder.get_object("cover").unwrap();
|
||||
@ -36,7 +39,7 @@ impl PodcastWidget {
|
||||
let unsub: gtk::Button = builder.get_object("unsub_button").unwrap();
|
||||
let played: gtk::Button = builder.get_object("mark_all_played_button").unwrap();
|
||||
|
||||
PodcastWidget {
|
||||
ShowWidget {
|
||||
container,
|
||||
cover,
|
||||
title,
|
||||
@ -47,18 +50,19 @@ impl PodcastWidget {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_initialized(stack: >k::Stack, pd: &Podcast) -> PodcastWidget {
|
||||
let pdw = PodcastWidget::new();
|
||||
pdw.init(stack, pd);
|
||||
pub fn new_initialized(shows: Rc<ShowStack>, header: Rc<Header>, pd: &Podcast) -> ShowWidget {
|
||||
let pdw = ShowWidget::new();
|
||||
pdw.init(shows, header, pd);
|
||||
pdw
|
||||
}
|
||||
|
||||
pub fn init(&self, stack: >k::Stack, pd: &Podcast) {
|
||||
pub fn init(&self, shows: Rc<ShowStack>, header: Rc<Header>, pd: &Podcast) {
|
||||
WidgetExt::set_name(&self.container, &pd.id().to_string());
|
||||
|
||||
// TODO: should spawn a thread to avoid locking the UI probably.
|
||||
self.unsub.connect_clicked(clone!(stack, pd => move |bttn| {
|
||||
on_unsub_button_clicked(&stack, &pd, bttn);
|
||||
self.unsub.connect_clicked(clone!(shows, pd => move |bttn| {
|
||||
on_unsub_button_clicked(shows.clone(), &pd, bttn);
|
||||
header.switch_to_normal();
|
||||
}));
|
||||
|
||||
self.title.set_text(pd.title());
|
||||
@ -77,8 +81,8 @@ impl PodcastWidget {
|
||||
self.cover.set_from_pixbuf(&i);
|
||||
}
|
||||
|
||||
self.played.connect_clicked(clone!(stack, pd => move |_| {
|
||||
on_played_button_clicked(&stack, &pd);
|
||||
self.played.connect_clicked(clone!(shows, pd => move |_| {
|
||||
on_played_button_clicked(shows.clone(), &pd);
|
||||
}));
|
||||
|
||||
self.show_played_button(pd);
|
||||
@ -95,7 +99,7 @@ impl PodcastWidget {
|
||||
}
|
||||
}
|
||||
|
||||
fn on_unsub_button_clicked(stack: >k::Stack, pd: &Podcast, unsub_button: >k::Button) {
|
||||
fn on_unsub_button_clicked(shows: Rc<ShowStack>, pd: &Podcast, unsub_button: >k::Button) {
|
||||
let res = dbqueries::remove_feed(pd);
|
||||
if res.is_ok() {
|
||||
info!("{} was removed succesfully.", pd.title());
|
||||
@ -111,12 +115,12 @@ fn on_unsub_button_clicked(stack: >k::Stack, pd: &Podcast, unsub_button: >k:
|
||||
}
|
||||
};
|
||||
}
|
||||
content::update_podcasts(stack);
|
||||
content::show_podcasts(stack);
|
||||
shows.switch_podcasts_animated();
|
||||
shows.update_podcasts();
|
||||
}
|
||||
|
||||
fn on_played_button_clicked(stack: >k::Stack, pd: &Podcast) {
|
||||
fn on_played_button_clicked(shows: Rc<ShowStack>, pd: &Podcast) {
|
||||
let _ = dbqueries::update_none_to_played_now(pd);
|
||||
|
||||
content::update_widget_preserve_vis(stack, pd);
|
||||
shows.update_widget();
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user