[work] adding an access and created_at metadata to items for sorting
Some checks failed
/ clippy (push) Failing after 6m56s
/ test (push) Failing after 11m59s

This commit is contained in:
Chris Cochrun 2026-05-27 16:50:37 -05:00
parent 0a77ead382
commit 2f5d7b4d15
15 changed files with 443 additions and 260 deletions

355
Cargo.lock generated
View file

@ -730,12 +730,6 @@ version = "0.22.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
[[package]]
name = "base64ct"
version = "1.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2af50177e190e07a26ab74f8b1efbfe2ef87da2116221318cb1c2e82baf7de06"
[[package]]
name = "basic-toml"
version = "0.1.10"
@ -832,6 +826,15 @@ dependencies = [
"generic-array",
]
[[package]]
name = "block-buffer"
version = "0.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cdd35008169921d80bc60d3d0ab416eecb028c4cd653352907921d95084790be"
dependencies = [
"hybrid-array",
]
[[package]]
name = "block2"
version = "0.5.1"
@ -1159,6 +1162,12 @@ dependencies = [
"cc",
]
[[package]]
name = "cmov"
version = "0.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f88a43d011fc4a6876cb7344703e297c71dda42494fee094d5f7c76bf13f746"
[[package]]
name = "cocoa"
version = "0.25.0"
@ -1237,12 +1246,6 @@ version = "3.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e57e3272f0190c3f1584272d613719ba5fc7df7f4942fe542e63d949cf3a649b"
[[package]]
name = "const-oid"
version = "0.9.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8"
[[package]]
name = "core-foundation"
version = "0.9.4"
@ -1578,6 +1581,15 @@ dependencies = [
"typenum",
]
[[package]]
name = "crypto-common"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ce6e4c961d6cd6c9a86db418387425e8bdeaf05b3c8bc1411e6dca4c252f1453"
dependencies = [
"hybrid-array",
]
[[package]]
name = "css-color"
version = "0.2.8"
@ -1628,6 +1640,15 @@ dependencies = [
"dtor",
]
[[package]]
name = "ctutils"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7d5515a3834141de9eafb9717ad39eea8247b5674e6066c404e8c4b365d2a29e"
dependencies = [
"cmov",
]
[[package]]
name = "cursor-icon"
version = "1.2.0"
@ -1731,17 +1752,6 @@ dependencies = [
"libdbus-sys",
]
[[package]]
name = "der"
version = "0.7.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e7c1832837b905bbfb5101e07cc24c8deddf52f93225eee6ead5f4d63d53ddcb"
dependencies = [
"const-oid",
"pem-rfc7468",
"zeroize",
]
[[package]]
name = "deranged"
version = "0.5.8"
@ -1809,10 +1819,19 @@ version = "0.10.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
dependencies = [
"block-buffer",
"const-oid",
"crypto-common",
"subtle",
"block-buffer 0.10.4",
"crypto-common 0.1.7",
]
[[package]]
name = "digest"
version = "0.11.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f1dd6dbb5841937940781866fa1281a1ff7bd3bf827091440879f9994983d5c2"
dependencies = [
"block-buffer 0.12.0",
"crypto-common 0.2.2",
"ctutils",
]
[[package]]
@ -2101,13 +2120,12 @@ dependencies = [
[[package]]
name = "etcetera"
version = "0.8.0"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "136d1b5283a1ab77bd9257427ffd09d8667ced0570b6f938942bc7568ed5b943"
checksum = "de48cc4d1c1d97a20fd819def54b890cadde72ed3ad0c614822a0a433361be96"
dependencies = [
"cfg-if",
"home",
"windows-sys 0.48.0",
"windows-sys 0.61.2",
]
[[package]]
@ -2308,9 +2326,9 @@ dependencies = [
[[package]]
name = "flume"
version = "0.11.1"
version = "0.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da0e4dd2a88388a1f4ccc7c9ce104604dab68d9f408dc34cd45823d5a9069095"
checksum = "5e139bc46ca777eb5efaf62df0ab8cc5fd400866427e56c68b22e414e53bd3be"
dependencies = [
"futures-core",
"futures-sink",
@ -3086,8 +3104,6 @@ version = "0.15.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1"
dependencies = [
"allocator-api2",
"equivalent",
"foldhash 0.1.5",
]
@ -3110,11 +3126,11 @@ checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a"
[[package]]
name = "hashlink"
version = "0.10.0"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7382cf6263419f2d8df38c55d7da83da5c18aef87fc7a7fc1fb1e344edfe14c1"
checksum = "ea0b22561a9c04a7cb1a302c013e0259cd3b4bb619f145b32f72b8b4bcbed230"
dependencies = [
"hashbrown 0.15.5",
"hashbrown 0.16.1",
]
[[package]]
@ -3149,20 +3165,20 @@ checksum = "dfa686283ad6dd069f105e5ab091b04c62850d3e4cf5d67debad1933f55023df"
[[package]]
name = "hkdf"
version = "0.12.4"
version = "0.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b5f8eb2ad728638ea2c7d47a21db23b7b58a72ed6a38256b8a1849f15fbbdf7"
checksum = "4aaa26c720c68b866f2c96ef5c1264b3e6f473fe5d4ce61cd44bbe913e553018"
dependencies = [
"hmac",
]
[[package]]
name = "hmac"
version = "0.12.1"
version = "0.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e"
checksum = "6303bc9732ae41b04cb554b844a762b4115a61bfaa81e3e83050991eeb56863f"
dependencies = [
"digest",
"digest 0.11.3",
]
[[package]]
@ -3232,6 +3248,15 @@ version = "1.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87"
[[package]]
name = "hybrid-array"
version = "0.4.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9155a582abd142abc056962c29e3ce5ff2ad5469f4246b537ed42c5deba857da"
dependencies = [
"typenum",
]
[[package]]
name = "hyper"
version = "1.9.0"
@ -4199,9 +4224,6 @@ name = "lazy_static"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
dependencies = [
"spin",
]
[[package]]
name = "leb128fmt"
@ -4562,12 +4584,12 @@ dependencies = [
[[package]]
name = "md-5"
version = "0.10.6"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf"
checksum = "69b6441f590336821bb897fb28fc622898ccceb1d6cea3fde5ea86b090c4de98"
dependencies = [
"cfg-if",
"digest",
"digest 0.11.3",
]
[[package]]
@ -4909,22 +4931,6 @@ dependencies = [
"num-traits",
]
[[package]]
name = "num-bigint-dig"
version = "0.8.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e661dda6640fad38e827a6d4a310ff4763082116fe217f279885c97f511bb0b7"
dependencies = [
"lazy_static",
"libm",
"num-integer",
"num-iter",
"num-traits",
"rand 0.8.6",
"smallvec",
"zeroize",
]
[[package]]
name = "num-conv"
version = "0.2.1"
@ -4951,17 +4957,6 @@ dependencies = [
"num-traits",
]
[[package]]
name = "num-iter"
version = "0.1.45"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf"
dependencies = [
"autocfg",
"num-integer",
"num-traits",
]
[[package]]
name = "num-rational"
version = "0.4.2"
@ -5297,7 +5292,7 @@ dependencies = [
"serde_json",
"serde_repr",
"serde_with",
"sha2",
"sha2 0.10.9",
"thiserror 2.0.18",
"time",
"tokio",
@ -5544,15 +5539,6 @@ dependencies = [
"rustc_version",
]
[[package]]
name = "pem-rfc7468"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "88b39c9bfcfc231068454382784bb460aae594343fb030d46e9f50a645418412"
dependencies = [
"base64ct",
]
[[package]]
name = "percent-encoding"
version = "2.3.2"
@ -5705,27 +5691,6 @@ dependencies = [
"futures-io",
]
[[package]]
name = "pkcs1"
version = "0.7.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c8ffb9f10fa047879315e6625af03c164b16962a5368d724ed16323b68ace47f"
dependencies = [
"der",
"pkcs8",
"spki",
]
[[package]]
name = "pkcs8"
version = "0.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7"
dependencies = [
"der",
"spki",
]
[[package]]
name = "pkg-config"
version = "0.3.33"
@ -6060,8 +6025,6 @@ version = "0.8.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5ca0ecfa931c29007047d1bc58e623ab12e5590e8c7cc53200d5202b69266d8a"
dependencies = [
"libc",
"rand_chacha 0.3.1",
"rand_core 0.6.4",
]
@ -6071,7 +6034,7 @@ version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "44c5af06bb1b7d3216d91932aed5265164bf384dc89cd6ba05cf59a35f5f76ea"
dependencies = [
"rand_chacha 0.9.0",
"rand_chacha",
"rand_core 0.9.5",
]
@ -6086,16 +6049,6 @@ dependencies = [
"rand_core 0.10.1",
]
[[package]]
name = "rand_chacha"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
dependencies = [
"ppv-lite86",
"rand_core 0.6.4",
]
[[package]]
name = "rand_chacha"
version = "0.9.0"
@ -6111,9 +6064,6 @@ name = "rand_core"
version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
dependencies = [
"getrandom 0.2.17",
]
[[package]]
name = "rand_core"
@ -6195,7 +6145,7 @@ dependencies = [
"paste",
"profiling",
"rand 0.9.4",
"rand_chacha 0.9.0",
"rand_chacha",
"simd_helpers",
"thiserror 2.0.18",
"v_frame",
@ -6551,26 +6501,6 @@ dependencies = [
"memchr",
]
[[package]]
name = "rsa"
version = "0.9.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b8573f03f5883dcaebdfcf4725caa1ecb9c15b2ef50c43a07b816e06799bb12d"
dependencies = [
"const-oid",
"digest",
"num-bigint-dig",
"num-integer",
"num-traits",
"pkcs1",
"pkcs8",
"rand_core 0.6.4",
"signature",
"spki",
"subtle",
"zeroize",
]
[[package]]
name = "rtrb"
version = "0.3.4"
@ -6607,7 +6537,7 @@ version = "8.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5bcdef0be6fe7f6fa333b1073c949729274b05f123a0ad7efcb8efd878e5c3b1"
dependencies = [
"sha2",
"sha2 0.10.9",
"walkdir",
]
@ -7056,7 +6986,18 @@ checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba"
dependencies = [
"cfg-if",
"cpufeatures 0.2.17",
"digest",
"digest 0.10.7",
]
[[package]]
name = "sha1"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aacc4cc499359472b4abe1bf11d0b12e688af9a805fa5e3016f9a386dc2d0214"
dependencies = [
"cfg-if",
"cpufeatures 0.3.0",
"digest 0.11.3",
]
[[package]]
@ -7067,7 +7008,18 @@ checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283"
dependencies = [
"cfg-if",
"cpufeatures 0.2.17",
"digest",
"digest 0.10.7",
]
[[package]]
name = "sha2"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "446ba717509524cb3f22f17ecc096f10f4822d76ab5c0b9822c5f9c284e825f4"
dependencies = [
"cfg-if",
"cpufeatures 0.3.0",
"digest 0.11.3",
]
[[package]]
@ -7095,16 +7047,6 @@ dependencies = [
"libc",
]
[[package]]
name = "signature"
version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de"
dependencies = [
"digest",
"rand_core 0.6.4",
]
[[package]]
name = "simd-adler32"
version = "0.3.9"
@ -7291,21 +7233,11 @@ dependencies = [
"bitflags 2.11.1",
]
[[package]]
name = "spki"
version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d"
dependencies = [
"base64ct",
"der",
]
[[package]]
name = "sqlx"
version = "0.8.6"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1fefb893899429669dcdd979aff487bd78f4064e5e7907e4269081e0ef7d97dc"
checksum = "378620ccc25c62c89d8be1c819e76a88d59bdcc3304733330788948e619bfd71"
dependencies = [
"sqlx-core",
"sqlx-macros",
@ -7316,12 +7248,14 @@ dependencies = [
[[package]]
name = "sqlx-core"
version = "0.8.6"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ee6798b1838b6a0f69c007c133b8df5866302197e404e8b6ee8ed3e3a5e68dc6"
checksum = "05b44e85bf579a8eeb4ceaa77a3a523baf2bf0e9bac7e40f405d537b5d2d5ccb"
dependencies = [
"base64 0.22.1",
"bytes",
"cfg-if",
"chrono",
"crc",
"crossbeam-queue",
"either",
@ -7330,16 +7264,15 @@ dependencies = [
"futures-intrusive",
"futures-io",
"futures-util",
"hashbrown 0.15.5",
"hashbrown 0.16.1",
"hashlink",
"indexmap 2.14.0",
"log",
"memchr",
"once_cell",
"percent-encoding",
"serde",
"serde_json",
"sha2",
"sha2 0.10.9",
"smallvec",
"thiserror 2.0.18",
"tokio",
@ -7350,9 +7283,9 @@ dependencies = [
[[package]]
name = "sqlx-macros"
version = "0.8.6"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a2d452988ccaacfbf5e0bdbc348fb91d7c8af5bee192173ac3636b5fb6e6715d"
checksum = "bd2b84f2bc39a5705ef27ec785a11c934a41bbd4a24941e257927cddc26b60bf"
dependencies = [
"proc-macro2",
"quote",
@ -7363,81 +7296,68 @@ dependencies = [
[[package]]
name = "sqlx-macros-core"
version = "0.8.6"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "19a9c1841124ac5a61741f96e1d9e2ec77424bf323962dd894bdb93f37d5219b"
checksum = "fb8d96de5fdc85a5c4ec813432b523ec637e80ba98f046555f75f7908ddac7c3"
dependencies = [
"cfg-if",
"dotenvy",
"either",
"heck 0.5.0",
"hex",
"once_cell",
"proc-macro2",
"quote",
"serde",
"serde_json",
"sha2",
"sha2 0.10.9",
"sqlx-core",
"sqlx-mysql",
"sqlx-postgres",
"sqlx-sqlite",
"syn",
"thiserror 2.0.18",
"tokio",
"url",
]
[[package]]
name = "sqlx-mysql"
version = "0.8.6"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aa003f0038df784eb8fecbbac13affe3da23b45194bd57dba231c8f48199c526"
checksum = "90b8020fe17c5f2c245bfa2505d7ef59c5604839527c740266ad2214acebea27"
dependencies = [
"atoi",
"base64 0.22.1",
"bitflags 2.11.1",
"byteorder",
"bytes",
"chrono",
"crc",
"digest",
"digest 0.11.3",
"dotenvy",
"either",
"futures-channel",
"futures-core",
"futures-io",
"futures-util",
"generic-array",
"hex",
"hkdf",
"hmac",
"itoa",
"log",
"md-5",
"memchr",
"once_cell",
"percent-encoding",
"rand 0.8.6",
"rsa",
"serde",
"sha1",
"sha2",
"smallvec",
"sha1 0.11.0",
"sha2 0.11.0",
"sqlx-core",
"stringprep",
"thiserror 2.0.18",
"tracing",
"whoami",
]
[[package]]
name = "sqlx-postgres"
version = "0.8.6"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "db58fcd5a53cf07c184b154801ff91347e4c30d17a3562a635ff028ad5deda46"
checksum = "87a2bdd6e83f6b3ea525ca9fee568030508b58355a43d0b2c1674d5f79dcd65e"
dependencies = [
"atoi",
"base64 0.22.1",
"bitflags 2.11.1",
"byteorder",
"chrono",
"crc",
"dotenvy",
"etcetera",
@ -7447,16 +7367,14 @@ dependencies = [
"hex",
"hkdf",
"hmac",
"home",
"itoa",
"log",
"md-5",
"memchr",
"once_cell",
"rand 0.8.6",
"rand 0.10.1",
"serde",
"serde_json",
"sha2",
"sha2 0.11.0",
"smallvec",
"sqlx-core",
"stringprep",
@ -7467,12 +7385,14 @@ dependencies = [
[[package]]
name = "sqlx-sqlite"
version = "0.8.6"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c2d12fe70b2c1b4401038055f90f151b78208de1f9f89a7dbfd41587a10c3eea"
checksum = "488e99c397a62007e4229aec669a179816339afc6d2620ca6fa420dbee2e982c"
dependencies = [
"atoi",
"chrono",
"flume",
"form_urlencoded",
"futures-channel",
"futures-core",
"futures-executor",
@ -7482,7 +7402,6 @@ dependencies = [
"log",
"percent-encoding",
"serde",
"serde_urlencoded",
"sqlx-core",
"thiserror 2.0.18",
"tracing",
@ -8463,7 +8382,7 @@ dependencies = [
"httparse",
"log",
"rand 0.9.4",
"sha1",
"sha1 0.10.6",
"thiserror 2.0.18",
"utf-8",
]
@ -8811,12 +8730,6 @@ dependencies = [
"wit-bindgen 0.51.0",
]
[[package]]
name = "wasite"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b8dad83b4f25e74f184f64c43b150b91efe7647395b42289f38e50566d82855b"
[[package]]
name = "wasm-bindgen"
version = "0.2.121"
@ -9254,13 +9167,9 @@ dependencies = [
[[package]]
name = "whoami"
version = "1.6.1"
version = "2.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5d4a4db5077702ca3015d3d02d74974948aba2ad9e12ab7df718ee64ccd7e97d"
dependencies = [
"libredox",
"wasite",
]
checksum = "998767ef88740d1f5b0682a9c53c24431453923962269c2db68ee43788c5a40d"
[[package]]
name = "winapi"

View file

@ -17,7 +17,7 @@ tracing-subscriber = { version = "0.3.18", features = ["fmt", "std", "chrono", "
strum = "0.26.3"
strum_macros = "0.26.4"
ron = "0.8.1"
sqlx = { version = "0.8.2", features = ["sqlite", "runtime-tokio"] }
sqlx = { version = "0.9", features = ["sqlite", "sqlite-deserialize", "runtime-tokio", "chrono"] }
dirs = "6.0.0"
tokio = "1.41.1"
crisp = { git = "https://git.tfcconnection.org/chris/crisp", version = "0.1.3" }

View file

@ -0,0 +1,20 @@
-- Add migration script here
ALTER TABLE songs
ADD COLUMN created_at INTEGER;
ALTER TABLE songs
ADD COLUMN accessed_at INTEGER;
ALTER TABLE images
ADD COLUMN created_at INTEGER;
ALTER TABLE images
ADD COLUMN accessed_at INTEGER;
ALTER TABLE videos
ADD COLUMN created_at INTEGER;
ALTER TABLE videos
ADD COLUMN accessed_at INTEGER;
ALTER TABLE presentations
ADD COLUMN created_at INTEGER;
ALTER TABLE presentations
ADD COLUMN accessed_at INTEGER;

View file

@ -1,5 +1,5 @@
[lru]
capacity = 64
# [lru]
# capacity = 64
[semanticHighlighting]
operator.enable = false

View file

@ -1,3 +1,4 @@
use crate::core::model::Sort;
use crate::{Background, Slide, SlideBuilder, TextAlignment};
use super::content::Content;
@ -8,7 +9,8 @@ use crisp::types::{Keyword, Symbol, Value};
use itertools::Itertools;
use miette::{IntoDiagnostic, Result, miette};
use serde::{Deserialize, Serialize};
use sqlx::{SqliteConnection, SqlitePool, query, query_as};
use sqlx::types::chrono::{DateTime, Local};
use sqlx::{AssertSqlSafe, SqliteConnection, SqlitePool, query, query_as};
use std::mem::replace;
use std::path::{Path, PathBuf};
use std::sync::Arc;
@ -19,6 +21,10 @@ pub struct Image {
pub id: i32,
pub title: String,
pub path: PathBuf,
#[serde(skip)]
pub created_at: DateTime<Local>,
#[serde(skip)]
pub accessed_at: DateTime<Local>,
}
impl From<PathBuf> for Image {
@ -33,6 +39,8 @@ impl From<PathBuf> for Image {
id: 0,
title,
path: value.canonicalize().unwrap_or(value),
created_at: Local::now(),
accessed_at: Local::now(),
}
}
}
@ -150,6 +158,7 @@ impl Model<Image> {
let mut model = Self {
items: vec![],
kind: LibraryKind::Image,
sorting_method: Sort::AccessTime,
};
let mut db = db.acquire().await.expect("probs");
@ -161,7 +170,7 @@ impl Model<Image> {
pub async fn load_from_db(&mut self, db: &mut SqliteConnection) {
let result = query_as!(
Image,
r#"SELECT title as "title!", file_path as "path!", id as "id: i32" from images"#
r#"SELECT title as "title!", file_path as "path!", id as "id: i32", accessed_at as "accessed_at!: DateTime<Local>", created_at as "created_at!: DateTime<Local>" from images"#
)
.fetch_all(db)
.await;
@ -176,6 +185,23 @@ impl Model<Image> {
}
}
}
pub fn sort(&mut self) {
match self.sorting_method {
Sort::AccessTime => {
self.items.sort_by(|a, b| b.accessed_at.cmp(&a.accessed_at))
}
Sort::CreatedTime => todo!(),
Sort::Title => todo!(),
Sort::Secondary => todo!(),
}
}
pub fn set_sort(mut self, method: Sort) -> Self {
self.sorting_method = method;
self.sort();
self
}
}
pub async fn remove_images(
@ -193,7 +219,7 @@ pub async fn remove_images(
ids.iter().map(ToString::to_string).join(", ")
);
query(&delete)
query(AssertSqlSafe(delete))
.execute(&*db)
.await
.into_diagnostic()
@ -280,7 +306,7 @@ pub async fn update_image(
}
pub async fn get_from_db(database_id: i32, db: &mut SqliteConnection) -> Result<Image> {
query_as!(Image, r#"SELECT title as "title!", file_path as "path!", id as "id: i32" from images where id = ?"#, database_id).fetch_one(db).await.into_diagnostic()
query_as!(Image, r#"SELECT title as "title!", file_path as "path!", id as "id: i32", accessed_at as "accessed_at!: DateTime<Local>", created_at as "created_at!: DateTime<Local>" from images where id = ?"#, database_id).fetch_one(db).await.into_diagnostic()
}
#[cfg(test)]
@ -301,6 +327,7 @@ mod test {
let mut image_model: Model<Image> = Model {
items: vec![],
kind: LibraryKind::Image,
sorting_method: Sort::AccessTime,
};
let mut db = add_db()
.await
@ -323,6 +350,7 @@ mod test {
let mut image_model: Model<Image> = Model {
items: vec![],
kind: LibraryKind::Image,
sorting_method: Sort::AccessTime,
};
let result = image_model.add_item(image.clone());
let new_image = test_image("A newer image".into());

View file

@ -13,6 +13,7 @@ use tracing::debug;
pub struct Model<T> {
pub items: Vec<T>,
pub kind: LibraryKind,
pub sorting_method: Sort,
}
#[derive(Debug, Clone, PartialEq, Eq, Copy, Hash, Serialize, Deserialize)]
@ -23,6 +24,14 @@ pub enum LibraryKind {
Presentation,
}
#[derive(Debug, Clone, Eq, PartialEq, Copy, Serialize, Deserialize)]
pub enum Sort {
AccessTime,
CreatedTime,
Title,
Secondary, // This can be author or file name
}
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct KindWrapper(pub (LibraryKind, i32));

View file

@ -6,12 +6,14 @@ use mupdf::{Colorspace, Document, Matrix};
use serde::{Deserialize, Serialize};
use sqlx::prelude::FromRow;
use sqlx::sqlite::SqliteRow;
use sqlx::{Row, SqliteConnection, SqlitePool, query};
use sqlx::types::chrono::{DateTime, Local};
use sqlx::{AssertSqlSafe, Row, SqliteConnection, SqlitePool, query};
use std::mem::replace;
use std::path::{Path, PathBuf};
use std::sync::Arc;
use tracing::{debug, error};
use crate::core::model::Sort;
use crate::{Background, Slide, SlideBuilder, TextAlignment};
use super::content::Content;
@ -36,6 +38,10 @@ pub struct Presentation {
pub title: String,
pub path: PathBuf,
pub kind: PresKind,
#[serde(skip)]
pub created_at: DateTime<Local>,
#[serde(skip)]
pub accessed_at: DateTime<Local>,
}
impl Eq for Presentation {}
@ -89,6 +95,8 @@ impl From<PathBuf> for Presentation {
title,
path: value.canonicalize().unwrap_or(value),
kind,
created_at: Local::now(),
accessed_at: Local::now(),
}
}
}
@ -280,6 +288,8 @@ impl FromRow<'_, SqliteRow> for Presentation {
ending_index: row.try_get(5)?,
}
},
created_at: Local::now(),
accessed_at: Local::now(),
})
}
}
@ -289,6 +299,7 @@ impl Model<Presentation> {
let mut model = Self {
items: vec![],
kind: LibraryKind::Presentation,
sorting_method: Sort::AccessTime,
};
model.load_from_db(db).await;
model
@ -296,7 +307,7 @@ impl Model<Presentation> {
pub async fn load_from_db(&mut self, db: Arc<SqlitePool>) {
let result = query!(
r#"SELECT id as "id: i32", title, file_path as "path", html, starting_index, ending_index from presentations"#
r#"SELECT id as "id: i32", title, file_path as "path", html, starting_index, ending_index, accessed_at as "accessed_at!: DateTime<Local>", created_at as "created_at!: DateTime<Local>" from presentations"#
)
.fetch_all(&*db)
.await;
@ -341,12 +352,31 @@ impl Model<Presentation> {
},
)
},
created_at: presentation.created_at,
accessed_at: presentation.accessed_at,
});
}
}
Err(e) => error!("There was an error in converting presentations: {e}"),
}
}
pub fn sort(&mut self) {
match self.sorting_method {
Sort::AccessTime => {
self.items.sort_by(|a, b| b.accessed_at.cmp(&a.accessed_at))
}
Sort::CreatedTime => todo!(),
Sort::Title => todo!(),
Sort::Secondary => todo!(),
}
}
pub fn set_sort(mut self, method: Sort) -> Self {
self.sorting_method = method;
self.sort();
self
}
}
pub async fn remove_presentations(
@ -364,7 +394,7 @@ pub async fn remove_presentations(
ids.iter().map(ToString::to_string).join(", ")
);
query(&delete)
query(AssertSqlSafe(delete))
.execute(&*db)
.await
.into_diagnostic()
@ -480,7 +510,7 @@ pub async fn get_presentation_from_db(
database_id: i32,
db: &mut SqliteConnection,
) -> Result<Presentation> {
let row = query(r#"SELECT id as "id: i32", title, file_path as "path", html from presentations where id = $1"#).bind(database_id).fetch_one(db).await.into_diagnostic()?;
let row = query(r#"SELECT id as "id: i32", title, file_path as "path", html, accessed_at as "accessed_at!: DateTime<Local>", created_at as "created_at!: DateTime<Local>" from presentations where id = $1"#).bind(database_id).fetch_one(db).await.into_diagnostic()?;
Presentation::from_row(&row).into_diagnostic()
}
@ -498,6 +528,8 @@ mod test {
starting_index: 0,
ending_index: 67,
},
created_at: Local::now(),
accessed_at: Local::now(),
}
}
@ -517,6 +549,7 @@ mod test {
let mut presentation_model: Model<Presentation> = Model {
items: vec![],
kind: LibraryKind::Presentation,
sorting_method: Sort::AccessTime,
};
let db = Arc::new(add_db().await.expect("Getting db error"));
presentation_model.load_from_db(db).await;

View file

@ -374,6 +374,7 @@ mod test {
use super::*;
use pretty_assertions::assert_eq;
use sqlx::types::chrono::Local;
fn test_song() -> Song {
Song {
@ -390,6 +391,8 @@ mod test {
"~/docs/notes/lessons/20240327T133649--12-isaiah-and-jesus__lesson_project_tfc.html",
),
kind: PresKind::Html,
created_at: Local::now(),
accessed_at: Local::now(),
}
}

View file

@ -7,6 +7,8 @@ use serde::{Deserialize, Serialize};
use std::collections::VecDeque;
use std::path::PathBuf;
use crate::core::model::Sort;
pub const SETTINGS_VERSION: u64 = 1;
#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
@ -32,6 +34,10 @@ pub struct Settings {
pub app_theme: AppTheme,
pub obs_url: Option<url::Url>,
pub genius_token: Option<String>,
pub song_sort: Option<Sort>,
pub image_sort: Option<Sort>,
pub video_sort: Option<Sort>,
pub presentation_sort: Option<Sort>,
}
impl Default for Settings {
@ -40,6 +46,10 @@ impl Default for Settings {
app_theme: AppTheme::System,
obs_url: None,
genius_token: None,
song_sort: None,
image_sort: None,
video_sort: None,
presentation_sort: None,
}
}
}

View file

@ -13,12 +13,13 @@ use itertools::Itertools;
use miette::{IntoDiagnostic, Result, miette};
use serde::{Deserialize, Serialize};
use sqlx::sqlite::SqliteRow;
use sqlx::{FromRow, Row, SqlitePool, query};
use sqlx::types::chrono::{DateTime, Local};
use sqlx::{AssertSqlSafe, FromRow, Row, SqlitePool, query};
use tracing::{debug, error};
use crate::core::content::Content;
use crate::core::kinds::ServiceItemKind;
use crate::core::model::{LibraryKind, Model};
use crate::core::model::{LibraryKind, Model, Sort};
use crate::core::service_items::ServiceTrait;
use crate::core::slide::{self, Background, TextAlignment};
use crate::ui::text_svg::{Color, Font, Stroke, shadow, stroke};
@ -49,6 +50,10 @@ pub struct Song {
pub verse_map: Option<HashMap<VerseName, String>>,
pub lyric_video: Option<PathBuf>,
pub music_video: Option<PathBuf>,
#[serde(skip)]
pub created_at: DateTime<Local>,
#[serde(skip)]
pub accessed_at: DateTime<Local>,
}
#[derive(
@ -379,6 +384,20 @@ impl FromRow<'_, SqliteRow> for Song {
.try_get::<String, &str>("music_video")
.map_or(None, |vid| Some(PathBuf::from(vid)));
let created_at = row
.try_get::<DateTime<Local>, &str>("created_at")
.unwrap_or_else(|e| {
error!(?e);
Local::now()
});
let accessed_at = row
.try_get::<DateTime<Local>, &str>("created_at")
.unwrap_or_else(|e| {
error!(?e);
Local::now()
});
Ok(Self {
id: row.try_get("id")?,
title: row.try_get("title")?,
@ -428,6 +447,8 @@ impl FromRow<'_, SqliteRow> for Song {
verse_map,
lyric_video,
music_video,
created_at,
accessed_at,
..Default::default()
})
}
@ -646,6 +667,7 @@ impl Model<Song> {
let mut model = Self {
items: vec![],
kind: LibraryKind::Song,
sorting_method: Sort::AccessTime,
};
model.load_from_db(db).await;
@ -677,6 +699,23 @@ impl Model<Song> {
}
}
}
pub fn sort(&mut self) {
match self.sorting_method {
Sort::AccessTime => {
self.items.sort_by(|a, b| b.accessed_at.cmp(&a.accessed_at))
}
Sort::CreatedTime => todo!(),
Sort::Title => todo!(),
Sort::Secondary => todo!(),
}
}
pub fn set_sort(mut self, method: Sort) -> Self {
self.sorting_method = method;
self.sort();
self
}
}
pub async fn remove_songs(
@ -694,7 +733,7 @@ pub async fn remove_songs(
ids.iter().map(ToString::to_string).join(", ")
);
query(&delete)
query(AssertSqlSafe(delete))
.execute(&*db)
.await
.into_diagnostic()
@ -847,6 +886,8 @@ pub async fn update_song(
let style = ron::ser::to_string(&song.font_style).into_diagnostic()?;
let weight = ron::ser::to_string(&song.font_weight).into_diagnostic()?;
let accessed_at = song.accessed_at;
// debug!(
// ?stroke_size,
// ?stroke_color,
@ -857,7 +898,7 @@ pub async fn update_song(
// );
let result = query!(
r#"UPDATE songs SET title = $2, lyrics = $3, author = $4, ccli = $5, verse_order = $6, audio = $7, font = $8, font_size = $9, background = $10, horizontal_text_alignment = $11, vertical_text_alignment = $12, stroke_color = $13, shadow_color = $14, stroke_size = $15, shadow_size = $16, shadow_offset_x = $17, shadow_offset_y = $18, style = $19, weight = $20, lyric_video = $21, music_video = $22 WHERE id = $1"#,
r#"UPDATE songs SET title = $2, lyrics = $3, author = $4, ccli = $5, verse_order = $6, audio = $7, font = $8, font_size = $9, background = $10, horizontal_text_alignment = $11, vertical_text_alignment = $12, stroke_color = $13, shadow_color = $14, stroke_size = $15, shadow_size = $16, shadow_offset_x = $17, shadow_offset_y = $18, style = $19, weight = $20, lyric_video = $21, music_video = $22, accessed_at = $23 WHERE id = $1"#,
song.id,
song.title,
lyrics,
@ -879,7 +920,8 @@ pub async fn update_song(
style,
weight,
lyric_video,
music_video
music_video,
accessed_at
)
.execute(&*db)
.await
@ -1273,6 +1315,7 @@ You saved my soul"
let song_model: Model<Song> = Model {
items: vec![],
kind: LibraryKind::Song,
sorting_method: Sort::AccessTime,
// db: crate::core::model::get_db().await,
};
song_model

View file

@ -1,3 +1,4 @@
use crate::core::model::Sort;
use crate::{Background, SlideBuilder, TextAlignment};
use super::content::Content;
@ -9,13 +10,14 @@ use crisp::types::{Keyword, Symbol, Value};
use itertools::Itertools;
use miette::{IntoDiagnostic, Result, miette};
use serde::{Deserialize, Serialize};
use sqlx::{SqliteConnection, SqlitePool, query, query_as};
use sqlx::types::chrono::{DateTime, Local};
use sqlx::{AssertSqlSafe, Decode, SqliteConnection, SqlitePool, query, query_as};
use std::mem::replace;
use std::path::{Path, PathBuf};
use std::sync::Arc;
use tracing::error;
#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize, Decode)]
pub struct Video {
pub id: i32,
pub title: String,
@ -23,6 +25,10 @@ pub struct Video {
pub start_time: Option<f32>,
pub end_time: Option<f32>,
pub looping: bool,
#[serde(skip)]
pub accessed_at: DateTime<Local>,
#[serde(skip)]
pub created_at: DateTime<Local>,
}
impl From<&Video> for Value {
@ -178,13 +184,14 @@ impl Model<Video> {
let mut model = Self {
items: vec![],
kind: LibraryKind::Video,
sorting_method: Sort::AccessTime,
};
model.load_from_db(db).await;
model
}
pub async fn load_from_db(&mut self, db: Arc<SqlitePool>) {
let result = query_as!(Video, r#"SELECT title as "title!", file_path as "path!", start_time as "start_time!: f32", end_time as "end_time!: f32", loop as "looping!", id as "id: i32" from videos"#).fetch_all(&*db).await;
let result = query_as!(Video, r#"SELECT title as "title!", file_path as "path!", start_time as "start_time!: f32", end_time as "end_time!: f32", loop as "looping!", id as "id: i32", accessed_at as "accessed_at!: DateTime<Local>", created_at as "created_at!: DateTime<Local>" from videos"#).fetch_all(&*db).await;
match result {
Ok(v) => {
for video in v {
@ -196,6 +203,23 @@ impl Model<Video> {
}
}
}
pub fn sort(&mut self) {
match self.sorting_method {
Sort::AccessTime => {
self.items.sort_by(|a, b| b.accessed_at.cmp(&a.accessed_at))
}
Sort::CreatedTime => todo!(),
Sort::Title => todo!(),
Sort::Secondary => todo!(),
}
}
pub fn set_sort(mut self, method: Sort) -> Self {
self.sorting_method = method;
self.sort();
self
}
}
pub async fn remove_videos(
@ -213,7 +237,7 @@ pub async fn remove_videos(
ids.iter().map(ToString::to_string).join(", ")
);
query(&delete)
query(AssertSqlSafe(delete))
.execute(&*db)
.await
.into_diagnostic()
@ -306,7 +330,7 @@ pub async fn update_video(
}
pub async fn get_from_db(database_id: i32, db: &mut SqliteConnection) -> Result<Video> {
query_as!(Video, r#"SELECT title as "title!", file_path as "path!", start_time as "start_time!: f32", end_time as "end_time!: f32", loop as "looping!", id as "id: i32" from videos where id = ?"#, database_id).fetch_one(db).await.into_diagnostic()
query_as!(Video, r#"SELECT title as "title!", file_path as "path!", start_time as "start_time!: f32", end_time as "end_time!: f32", loop as "looping!", id as "id: i32", accessed_at as "accessed_at!: DateTime<Local>", created_at as "created_at!: DateTime<Local>" from videos where id = ?"#, database_id).fetch_one(db).await.into_diagnostic()
}
#[cfg(test)]
@ -329,6 +353,7 @@ mod test {
let mut video_model: Model<Video> = Model {
items: vec![],
kind: LibraryKind::Video,
sorting_method: Sort::AccessTime,
};
let db = Arc::new(add_db().await.expect(""));
video_model.load_from_db(db).await;
@ -346,6 +371,7 @@ mod test {
let mut video_model: Model<Video> = Model {
items: vec![],
kind: LibraryKind::Video,
sorting_method: Sort::AccessTime,
};
let result = video_model.add_item(video.clone());
let new_video = test_video("A newer video".into());

View file

@ -23,13 +23,14 @@ use itertools::Itertools;
use miette::{Context, IntoDiagnostic, Result};
use rapidfuzz::distance::levenshtein;
use sqlx::sqlite::SqliteConnectOptions;
use sqlx::types::chrono::Local;
use sqlx::{SqlitePool, migrate};
use tracing::{debug, error, warn};
use crate::core::content::Content;
use crate::core::images::{self, Image};
use crate::core::kinds::ServiceItemKind;
use crate::core::model::{KindWrapper, LibraryKind, Model};
use crate::core::model::{KindWrapper, LibraryKind, Model, Sort};
use crate::core::presentations::{self, Presentation};
use crate::core::service_items::ServiceItem;
use crate::core::songs::{self, Song, insert_song};
@ -94,6 +95,7 @@ pub enum Action {
pub enum Message {
AddItem,
DeleteItem,
AccessItem(Option<(LibraryKind, i32)>),
OpenItem(Option<(LibraryKind, i32)>),
OpenContextItem,
HoverLibrary(Option<LibraryKind>),
@ -129,6 +131,18 @@ pub enum Message {
HoverPoint(cosmic::iced::Point),
}
impl Action {
fn chain_task(self, task: Task<Message>) -> Self {
match self {
Action::Task(inner_task) => {
let task = inner_task.chain(task);
Self::Task(task)
}
_ => self,
}
}
}
impl<'a> Library {
pub async fn new(db: Arc<SqlitePool>) -> Self {
// let db = add_db().await.expect("probs");
@ -136,10 +150,18 @@ impl<'a> Library {
error!(?e);
}
Self {
song_library: Model::new_song_model(Arc::clone(&db)).await,
image_library: Model::new_image_model(Arc::clone(&db)).await,
video_library: Model::new_video_model(Arc::clone(&db)).await,
presentation_library: Model::new_presentation_model(Arc::clone(&db)).await,
song_library: Model::new_song_model(Arc::clone(&db))
.await
.set_sort(Sort::AccessTime),
image_library: Model::new_image_model(Arc::clone(&db))
.await
.set_sort(Sort::AccessTime),
video_library: Model::new_video_model(Arc::clone(&db))
.await
.set_sort(Sort::AccessTime),
presentation_library: Model::new_presentation_model(Arc::clone(&db))
.await
.set_sort(Sort::AccessTime),
library_open: None,
library_hovered: None,
selected_items: None,
@ -201,7 +223,7 @@ impl<'a> Library {
return Action::CreateSong;
}
Message::AddSongFromEditor(song) => {
let after_task = Task::done(Message::OpenItem(Some((
let after_task = Task::done(Message::AccessItem(Some((
LibraryKind::Song,
self.song_library.items.len() as i32,
))));
@ -247,7 +269,7 @@ impl<'a> Library {
let _index = self.video_library.items.len();
// Check if empty
let mut tasks = Vec::new();
let after_task = Task::done(Message::OpenItem(Some((
let after_task = Task::done(Message::AccessItem(Some((
LibraryKind::Video,
self.video_library.items.len() as i32,
))));
@ -295,7 +317,7 @@ impl<'a> Library {
let _index = self.presentation_library.items.len();
// Check if empty
let mut tasks = Vec::new();
let after_task = Task::done(Message::OpenItem(Some((
let after_task = Task::done(Message::AccessItem(Some((
LibraryKind::Presentation,
self.presentation_library.items.len() as i32,
))));
@ -321,7 +343,7 @@ impl<'a> Library {
let _index = self.image_library.items.len();
// Check if empty
let mut tasks = Vec::new();
let after_task = Task::done(Message::OpenItem(Some((
let after_task = Task::done(Message::AccessItem(Some((
LibraryKind::Image,
self.image_library.items.len() as i32,
))));
@ -343,10 +365,79 @@ impl<'a> Library {
return Action::Task(Task::batch(tasks).chain(after_task));
}
Message::OpenItem(item) => {
// if let Some((kind, _)) = item {
// match kind {
// LibraryKind::Song => {
// self.song_library.sort();
// debug!(?self.song_library);
// }
// LibraryKind::Video => self.video_library.sort(),
// LibraryKind::Image => self.image_library.sort(),
// LibraryKind::Presentation => self.presentation_library.sort(),
// }
// }
return Action::OpenItem(item);
}
Message::AccessItem(item) => {
debug!(?item);
self.context_menu = None;
self.editing_item = item;
return Action::OpenItem(item);
let task = Task::done(Message::OpenItem(item));
if let Some((kind, item)) = item {
match kind {
LibraryKind::Song
if let Some(song) = self
.song_library
.items
.clone()
.get_mut(item as usize) =>
{
song.accessed_at = Local::now();
debug!(?song);
return self
.update(Message::UpdateSong(song.clone()))
.chain_task(task);
}
LibraryKind::Video
if let Some(video) = self
.video_library
.items
.clone()
.get_mut(item as usize) =>
{
video.accessed_at = Local::now();
debug!(?video);
return self
.update(Message::UpdateVideo(video.clone()))
.chain_task(task);
}
LibraryKind::Image
if let Some(image) = self
.image_library
.items
.clone()
.get_mut(item as usize) =>
{
image.accessed_at = Local::now();
return self
.update(Message::UpdateImage(image.clone()))
.chain_task(task);
}
LibraryKind::Presentation
if let Some(presentation) = self
.presentation_library
.items
.clone()
.get_mut(item as usize) =>
{
presentation.accessed_at = Local::now();
return self
.update(Message::UpdatePresentation(presentation.clone()))
.chain_task(task);
}
_ => (),
}
}
}
Message::OpenContextItem => {
let Some(kind) = self.library_open else {
@ -355,7 +446,7 @@ impl<'a> Library {
let Some(index) = self.context_menu else {
return Action::None;
};
return self.update(Message::OpenItem(Some((kind, index))));
return self.update(Message::AccessItem(Some((kind, index))));
}
Message::HoverLibrary(library_kind) => {
self.library_hovered = library_kind;
@ -726,7 +817,7 @@ impl<'a> Library {
.on_enter(Message::HoverItem(Some((
model.kind, i32_index,
))))
.on_double_click(Message::OpenItem(Some((
.on_double_click(Message::AccessItem(Some((
model.kind, i32_index,
))))
.on_right_press(Message::OpenContext(Some(i32_index)))
@ -953,7 +1044,7 @@ impl<'a> Library {
};
let menu_items = column![
menu_item("Open", Message::OpenItem(Some((library, id)))),
menu_item("Open", Message::AccessItem(Some((library, id)))),
menu_item("Delete", Message::DeleteItem),
]
.spacing(theme::spacing().space_s)
@ -1173,7 +1264,7 @@ impl<'a> Library {
let after_task = match last_item {
Some(ServiceItemKind::Image(_image)) => {
Task::done(Message::OpenItem(Some((
Task::done(Message::AccessItem(Some((
LibraryKind::Image,
self.image_library
.items
@ -1184,7 +1275,7 @@ impl<'a> Library {
}
Some(ServiceItemKind::Video(_image)) => {
Task::done(Message::OpenItem(Some((
Task::done(Message::AccessItem(Some((
LibraryKind::Video,
self.video_library
.items
@ -1194,7 +1285,7 @@ impl<'a> Library {
))))
}
Some(ServiceItemKind::Presentation(_image)) => {
Task::done(Message::OpenItem(Some((
Task::done(Message::AccessItem(Some((
LibraryKind::Presentation,
self.presentation_library
.items

View file

@ -501,6 +501,8 @@ impl PresentationEditor {
},
_ => current_presentation.kind.clone(),
},
created_at: current_presentation.created_at,
accessed_at: current_presentation.accessed_at,
};
let second_presentation = Presentation {
id: 0,
@ -513,6 +515,8 @@ impl PresentationEditor {
},
_ => current_presentation.kind.clone(),
},
created_at: current_presentation.created_at,
accessed_at: current_presentation.accessed_at,
};
Ok((first_presentation, second_presentation))
} else {
@ -539,6 +543,8 @@ impl PresentationEditor {
},
_ => current_presentation.kind.clone(),
},
created_at: current_presentation.created_at,
accessed_at: current_presentation.accessed_at,
};
let second_presentation = Presentation {
id: 0,
@ -551,6 +557,8 @@ impl PresentationEditor {
},
_ => current_presentation.kind.clone(),
},
created_at: current_presentation.created_at,
accessed_at: current_presentation.accessed_at,
};
Ok((first_presentation, second_presentation))
} else {

View file

@ -1166,6 +1166,7 @@ mod test {
use super::*;
use pretty_assertions::assert_eq;
use sqlx::types::chrono::Local;
#[test]
fn test_next_slide() {
@ -1254,6 +1255,8 @@ mod test {
starting_index: 0,
ending_index: 67,
},
created_at: Local::now(),
accessed_at: Local::now(),
}
}
}

BIN
test.db

Binary file not shown.