From 024b259bbe774b1449e5921ae9bc1f42378b6081 Mon Sep 17 00:00:00 2001 From: arcayr Date: Tue, 20 Aug 2024 20:07:34 +1000 Subject: [PATCH] very badly coded gtk4 ui. --- Cargo.lock | 973 ++++++++++++++++++ crates/noteriety-gtk4/Cargo.toml | 12 + crates/noteriety-gtk4/src/configuration.rs | 11 + crates/noteriety-gtk4/src/main.rs | 11 + crates/noteriety-gtk4/src/note.rs | 30 + .../src/window/content_entry.rs | 86 ++ .../noteriety-gtk4/src/window/header_bar.rs | 54 + crates/noteriety-gtk4/src/window/mod.rs | 190 ++++ crates/noteriety-gtk4/src/window/sidebar.rs | 124 +++ .../noteriety-gtk4/src/window/title_entry.rs | 55 + crates/noteriety/src/note.rs | 32 +- crates/noteriety/src/notebook.rs | 2 +- 12 files changed, 1570 insertions(+), 10 deletions(-) create mode 100644 crates/noteriety-gtk4/Cargo.toml create mode 100644 crates/noteriety-gtk4/src/configuration.rs create mode 100644 crates/noteriety-gtk4/src/main.rs create mode 100644 crates/noteriety-gtk4/src/note.rs create mode 100644 crates/noteriety-gtk4/src/window/content_entry.rs create mode 100644 crates/noteriety-gtk4/src/window/header_bar.rs create mode 100644 crates/noteriety-gtk4/src/window/mod.rs create mode 100644 crates/noteriety-gtk4/src/window/sidebar.rs create mode 100644 crates/noteriety-gtk4/src/window/title_entry.rs diff --git a/Cargo.lock b/Cargo.lock index 270bfd5..d7a552d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,27 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "addr2line" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e4503c46a5c0c7844e948c9a4d6acd9f50cccb4de1c48eb9e291ea17470c678" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + +[[package]] +name = "ambient-authority" +version = "0.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9d4ee0d472d1cd2e28c97dfa124b3d8d992e10eb0a035f33f5d12e3a177ba3b" + [[package]] name = "android-tzdata" version = "0.1.1" @@ -23,6 +44,21 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" +[[package]] +name = "backtrace" +version = "0.3.73" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5cc23269a4f8976d0a4d2e7109211a419fe30e8d88d677cd60b6bc79c5732e0a" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] + [[package]] name = "bitflags" version = "2.6.0" @@ -35,6 +71,58 @@ version = "3.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" +[[package]] +name = "cairo-rs" +version = "0.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8a0ea147c94108c9613235388f540e4d14c327f7081c9e471fc8ee8a2533e69" +dependencies = [ + "bitflags", + "cairo-sys-rs", + "glib", + "libc", +] + +[[package]] +name = "cairo-sys-rs" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "428290f914b9b86089f60f5d8a9f6e440508e1bcff23b25afd51502b0a2da88f" +dependencies = [ + "glib-sys", + "libc", + "system-deps", +] + +[[package]] +name = "cap-primitives" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d00bd8d26c4270d950eaaa837387964a2089a1c3c349a690a1fa03221d29531" +dependencies = [ + "ambient-authority", + "fs-set-times", + "io-extras", + "io-lifetimes", + "ipnet", + "maybe-owned", + "rustix", + "windows-sys", + "winx", +] + +[[package]] +name = "cap-std" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19eb8e3d71996828751c1ed3908a439639752ac6bdc874e41469ef7fc15fbd7f" +dependencies = [ + "cap-primitives", + "io-extras", + "io-lifetimes", + "rustix", +] + [[package]] name = "cc" version = "1.1.13" @@ -44,6 +132,16 @@ dependencies = [ "shlex", ] +[[package]] +name = "cfg-expr" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "345c78335be0624ed29012dc10c49102196c6882c12dde65d9f35b02da2aada8" +dependencies = [ + "smallvec", + "target-lexicon", +] + [[package]] name = "cfg-if" version = "1.0.0" @@ -98,12 +196,222 @@ version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" +[[package]] +name = "crop" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0c36a21e864b7accff2cf3bef09af553704556ff2fb704ebee242bfc5c89f10" +dependencies = [ + "str_indices", +] + [[package]] name = "crunchy" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "errno" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" +dependencies = [ + "libc", + "windows-sys", +] + +[[package]] +name = "field-offset" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38e2275cc4e4fc009b0669731a1e5ab7ebf11f469eaede2bab9309a5b4d6057f" +dependencies = [ + "memoffset", + "rustc_version", +] + +[[package]] +name = "flume" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55ac459de2512911e4b674ce33cf20befaba382d05b62b008afc1c8b57cbf181" +dependencies = [ + "futures-core", + "futures-sink", + "nanorand", + "spin", +] + +[[package]] +name = "fragile" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c2141d6d6c8512188a7891b4b01590a45f6dac67afb4f255c4124dbb86d4eaa" + +[[package]] +name = "fs-set-times" +version = "0.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "033b337d725b97690d86893f9de22b67b80dcc4e9ad815f348254c38119db8fb" +dependencies = [ + "io-lifetimes", + "rustix", + "windows-sys", +] + +[[package]] +name = "futures" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" + +[[package]] +name = "futures-executor" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-io" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" + +[[package]] +name = "futures-macro" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "futures-sink" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" + +[[package]] +name = "futures-task" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" + +[[package]] +name = "futures-util" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "pin-utils", + "slab", +] + +[[package]] +name = "gdk-pixbuf" +version = "0.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8730751991b97419fc3f0c2dca2c9e45b48edf46e48e0f965964ecf33889812f" +dependencies = [ + "gdk-pixbuf-sys", + "gio", + "glib", + "libc", +] + +[[package]] +name = "gdk-pixbuf-sys" +version = "0.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ffbf649fd5b1c8c0f0feeb015b7533c3ef92da2887fb95ddd338bc2b1644a7c" +dependencies = [ + "gio-sys", + "glib-sys", + "gobject-sys", + "libc", + "system-deps", +] + +[[package]] +name = "gdk4" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b7d7237c1487ed4b300aac7744efcbf1319e12d60d7afcd6f505414bd5b5dea" +dependencies = [ + "cairo-rs", + "gdk-pixbuf", + "gdk4-sys", + "gio", + "glib", + "libc", + "pango", +] + +[[package]] +name = "gdk4-sys" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a67576c8ec012156d7f680e201a807b4432a77babb3157e0555e990ab6bcd878" +dependencies = [ + "cairo-sys-rs", + "gdk-pixbuf-sys", + "gio-sys", + "glib-sys", + "gobject-sys", + "libc", + "pango-sys", + "pkg-config", + "system-deps", +] + [[package]] name = "getopts" version = "0.2.21" @@ -120,8 +428,207 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ "cfg-if", + "js-sys", "libc", "wasi", + "wasm-bindgen", +] + +[[package]] +name = "gimli" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd" + +[[package]] +name = "gio" +version = "0.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcacaa37401cad0a95aadd266bc39c72a131d454fc012f6dfd217f891d76cc52" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-util", + "gio-sys", + "glib", + "libc", + "pin-project-lite", + "smallvec", +] + +[[package]] +name = "gio-sys" +version = "0.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5237611e97e9b86ab5768adc3eef853ae713ea797aa3835404acdfacffc9fb38" +dependencies = [ + "glib-sys", + "gobject-sys", + "libc", + "system-deps", + "windows-sys", +] + +[[package]] +name = "glib" +version = "0.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b19429cb83fcbf1f00b31ae3a123fab5cd3761bdd15b0cc07905804742f0d0e4" +dependencies = [ + "bitflags", + "futures-channel", + "futures-core", + "futures-executor", + "futures-task", + "futures-util", + "gio-sys", + "glib-macros", + "glib-sys", + "gobject-sys", + "libc", + "memchr", + "smallvec", +] + +[[package]] +name = "glib-macros" +version = "0.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "960349f56469b75794157e93bf04f0bc8a622d0a6612d6a8f8d7eac41e0e1ee1" +dependencies = [ + "heck", + "proc-macro-crate", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "glib-sys" +version = "0.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44edae63bea922f18f7e63977ee60a257ec27c4613aff1a6a9bb572ad0d88269" +dependencies = [ + "libc", + "system-deps", +] + +[[package]] +name = "gobject-sys" +version = "0.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa3d1dcd8a1eb2e7c22be3d5e792b14b186f3524f79b25631730f9a8c169d49a" +dependencies = [ + "glib-sys", + "libc", + "system-deps", +] + +[[package]] +name = "graphene-rs" +version = "0.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80aac87f74e81c0e13433e892a047237abdc37945c86887f5eed905038356e69" +dependencies = [ + "glib", + "graphene-sys", + "libc", +] + +[[package]] +name = "graphene-sys" +version = "0.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc2f91ecd32989efad60326cc20a8fb252bd2852239a08e4e70cde8c100de9ca" +dependencies = [ + "glib-sys", + "libc", + "pkg-config", + "system-deps", +] + +[[package]] +name = "gsk4" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3cf2091e1af185b347b3450817d93dea6fe435df7abd4c2cd7fb5bcb4cfda8" +dependencies = [ + "cairo-rs", + "gdk4", + "glib", + "graphene-rs", + "gsk4-sys", + "libc", + "pango", +] + +[[package]] +name = "gsk4-sys" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6aa69614a26d8760c186c3690f1b0fbb917572ca23ef83137445770ceddf8cde" +dependencies = [ + "cairo-sys-rs", + "gdk4-sys", + "glib-sys", + "gobject-sys", + "graphene-sys", + "libc", + "pango-sys", + "system-deps", +] + +[[package]] +name = "gtk4" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eaffc6c743c9160514cc9b67eace364e5dc5798369fa809cdb04e035c21c5c5d" +dependencies = [ + "cairo-rs", + "field-offset", + "futures-channel", + "gdk-pixbuf", + "gdk4", + "gio", + "glib", + "graphene-rs", + "gsk4", + "gtk4-macros", + "gtk4-sys", + "libc", + "pango", +] + +[[package]] +name = "gtk4-macros" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "188211f546ce5801f6d0245c37b6249143a2cb4fa040e54829ca1e76796e9f09" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "gtk4-sys" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1114a207af8ada02cf4658a76692f4190f06f093380d5be07e3ca8b43aa7c666" +dependencies = [ + "cairo-sys-rs", + "gdk-pixbuf-sys", + "gdk4-sys", + "gio-sys", + "glib-sys", + "gobject-sys", + "graphene-sys", + "gsk4-sys", + "libc", + "pango-sys", + "system-deps", ] [[package]] @@ -134,6 +641,18 @@ dependencies = [ "crunchy", ] +[[package]] +name = "hashbrown" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + [[package]] name = "iana-time-zone" version = "0.1.60" @@ -157,6 +676,44 @@ dependencies = [ "cc", ] +[[package]] +name = "indexmap" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93ead53efc7ea8ed3cfb0c79fc8023fbb782a5432b52830b6518941cebe6505c" +dependencies = [ + "equivalent", + "hashbrown", +] + +[[package]] +name = "io-extras" +version = "0.18.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9f046b9af244f13b3bd939f55d16830ac3a201e8a9ba9661bfcb03e2be72b9b" +dependencies = [ + "io-lifetimes", + "windows-sys", +] + +[[package]] +name = "io-lifetimes" +version = "2.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a611371471e98973dbcab4e0ec66c31a10bc356eeb4d54a0e05eac8158fe38c" + +[[package]] +name = "ipnet" +version = "2.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" + +[[package]] +name = "itoa" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" + [[package]] name = "js-sys" version = "0.3.70" @@ -166,12 +723,59 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "libadwaita" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ff9c222b5c783729de45185f07b2fec2d43a7f9c63961e777d3667e20443878" +dependencies = [ + "gdk4", + "gio", + "glib", + "gtk4", + "libadwaita-sys", + "libc", + "pango", +] + +[[package]] +name = "libadwaita-sys" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c44d8bdbad31d6639e1f20cc9c1424f1a8e02d751fc28d44659bf743fb9eca6" +dependencies = [ + "gdk4-sys", + "gio-sys", + "glib-sys", + "gobject-sys", + "gtk4-sys", + "libc", + "pango-sys", + "system-deps", +] + [[package]] name = "libc" version = "0.2.158" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439" +[[package]] +name = "linux-raw-sys" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" + +[[package]] +name = "lock_api" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" +dependencies = [ + "autocfg", + "scopeguard", +] + [[package]] name = "log" version = "0.4.22" @@ -188,12 +792,45 @@ dependencies = [ "pulldown-cmark-to-cmark", ] +[[package]] +name = "maybe-owned" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4facc753ae494aeb6e3c22f839b158aebd4f9270f55cd3c79906c45476c47ab4" + [[package]] name = "memchr" version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" +[[package]] +name = "memoffset" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" +dependencies = [ + "autocfg", +] + +[[package]] +name = "miniz_oxide" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" +dependencies = [ + "adler", +] + +[[package]] +name = "nanorand" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a51313c5820b0b02bd422f4b44776fbf47961755c74ce64afc73bfad10226c3" +dependencies = [ + "getrandom", +] + [[package]] name = "noteriety" version = "0.1.0" @@ -206,6 +843,18 @@ dependencies = [ "uuid", ] +[[package]] +name = "noteriety-gtk4" +version = "0.1.0" +dependencies = [ + "cap-std", + "crop", + "libadwaita", + "markdown-ast", + "noteriety", + "relm4", +] + [[package]] name = "num-traits" version = "0.2.19" @@ -215,12 +864,72 @@ dependencies = [ "autocfg", ] +[[package]] +name = "object" +version = "0.36.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27b64972346851a39438c60b341ebc01bba47464ae329e55cf343eb93964efd9" +dependencies = [ + "memchr", +] + [[package]] name = "once_cell" version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" +[[package]] +name = "pango" +version = "0.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5764e5a174a5a0ec054fe5962ce6d4fc7052e2d0dcc23bbc77202b40a4a403d3" +dependencies = [ + "gio", + "glib", + "libc", + "pango-sys", +] + +[[package]] +name = "pango-sys" +version = "0.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd317e1de76b14b3d3efe05518c08b360327f1ab7fec150473a89ffcad4b072d" +dependencies = [ + "glib-sys", + "gobject-sys", + "libc", + "system-deps", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "pkg-config" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" + +[[package]] +name = "proc-macro-crate" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d37c51ca738a55da99dc0c4a34860fd675453b8b36209178c2249bb13651284" +dependencies = [ + "toml_edit 0.21.1", +] + [[package]] name = "proc-macro2" version = "1.0.86" @@ -267,6 +976,83 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "relm4" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf0363f92b6a7eefd985b47f27b7ae168dd2fd5cd4013a338c9b111c33744d1f" +dependencies = [ + "flume", + "fragile", + "futures", + "gtk4", + "libadwaita", + "once_cell", + "relm4-css", + "relm4-macros", + "tokio", + "tracing", +] + +[[package]] +name = "relm4-css" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d3b924557df1cddc687b60b313c4b76620fdbf0e463afa4b29f67193ccf37f9" + +[[package]] +name = "relm4-macros" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc5885640821d60062497737dd42fd04248d13c7ecccee620caaa4b210fe9905" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" + +[[package]] +name = "rustc_version" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +dependencies = [ + "semver", +] + +[[package]] +name = "rustix" +version = "0.38.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" +dependencies = [ + "bitflags", + "errno", + "itoa", + "libc", + "linux-raw-sys", + "once_cell", + "windows-sys", +] + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "semver" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" + [[package]] name = "serde" version = "1.0.208" @@ -287,12 +1073,51 @@ dependencies = [ "syn", ] +[[package]] +name = "serde_spanned" +version = "0.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb5b1b31579f3811bf615c144393417496f152e12ac8b7663bf664f4a815306d" +dependencies = [ + "serde", +] + [[package]] name = "shlex" version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" +[[package]] +name = "slab" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +dependencies = [ + "autocfg", +] + +[[package]] +name = "smallvec" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" + +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" +dependencies = [ + "lock_api", +] + +[[package]] +name = "str_indices" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9557cb6521e8d009c51a8666f09356f4b817ba9ba0981a305bd86aee47bd35c" + [[package]] name = "syn" version = "2.0.75" @@ -304,6 +1129,25 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "system-deps" +version = "7.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "070a0a5e7da2d24be457809c4b3baa57a835fd2829ad8b86f9a049052fe71031" +dependencies = [ + "cfg-expr", + "heck", + "pkg-config", + "toml", + "version-compare", +] + +[[package]] +name = "target-lexicon" +version = "0.12.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1" + [[package]] name = "thiserror" version = "1.0.63" @@ -324,6 +1168,92 @@ dependencies = [ "syn", ] +[[package]] +name = "tokio" +version = "1.39.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9babc99b9923bfa4804bd74722ff02c0381021eafa4db9949217e3be8e84fff5" +dependencies = [ + "backtrace", + "pin-project-lite", +] + +[[package]] +name = "toml" +version = "0.8.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1ed1f98e3fdc28d6d910e6737ae6ab1a93bf1985935a1193e68f93eeb68d24e" +dependencies = [ + "serde", + "serde_spanned", + "toml_datetime", + "toml_edit 0.22.20", +] + +[[package]] +name = "toml_datetime" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" +dependencies = [ + "serde", +] + +[[package]] +name = "toml_edit" +version = "0.21.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1" +dependencies = [ + "indexmap", + "toml_datetime", + "winnow 0.5.40", +] + +[[package]] +name = "toml_edit" +version = "0.22.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "583c44c02ad26b0c3f3066fe629275e50627026c51ac2e595cca4c230ce1ce1d" +dependencies = [ + "indexmap", + "serde", + "serde_spanned", + "toml_datetime", + "winnow 0.6.18", +] + +[[package]] +name = "tracing" +version = "0.1.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +dependencies = [ + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tracing-core" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +dependencies = [ + "once_cell", +] + [[package]] name = "unicase" version = "2.7.0" @@ -355,6 +1285,12 @@ dependencies = [ "serde", ] +[[package]] +name = "version-compare" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "852e951cb7832cb45cb1169900d19760cfa39b82bc0ea9c0e5a14ae88411c98b" + [[package]] name = "version_check" version = "0.9.5" @@ -431,6 +1367,15 @@ dependencies = [ "windows-targets", ] +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets", +] + [[package]] name = "windows-targets" version = "0.52.6" @@ -494,3 +1439,31 @@ name = "windows_x86_64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "winnow" +version = "0.5.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876" +dependencies = [ + "memchr", +] + +[[package]] +name = "winnow" +version = "0.6.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68a9bda4691f099d435ad181000724da8e5899daa10713c2d432552b9ccd3a6f" +dependencies = [ + "memchr", +] + +[[package]] +name = "winx" +version = "0.36.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9643b83820c0cd246ecabe5fa454dd04ba4fa67996369466d0747472d337346" +dependencies = [ + "bitflags", + "windows-sys", +] diff --git a/crates/noteriety-gtk4/Cargo.toml b/crates/noteriety-gtk4/Cargo.toml new file mode 100644 index 0000000..fa48f51 --- /dev/null +++ b/crates/noteriety-gtk4/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "noteriety-gtk4" +version = "0.1.0" +edition = "2021" + +[dependencies] +relm4 = { version = "0.9.0", features = ["adw", "libadwaita"] } +libadwaita = { version = "0.7.0", features = ["gtk_v4_6", "v1_5"] } +markdown-ast = "0.1.1" +crop = "0.4.2" +noteriety = { version = "0.1.0", path = "../noteriety" } +cap-std = "3.2.0" diff --git a/crates/noteriety-gtk4/src/configuration.rs b/crates/noteriety-gtk4/src/configuration.rs new file mode 100644 index 0000000..429f059 --- /dev/null +++ b/crates/noteriety-gtk4/src/configuration.rs @@ -0,0 +1,11 @@ +pub(crate) struct Configuration { + pub notes_dir: String, +} + +impl Default for Configuration { + fn default() -> Self { + Self { + notes_dir: String::from("/home/arcayr/.local/share/noteriety/notebooks"), + } + } +} diff --git a/crates/noteriety-gtk4/src/main.rs b/crates/noteriety-gtk4/src/main.rs new file mode 100644 index 0000000..f1d53e2 --- /dev/null +++ b/crates/noteriety-gtk4/src/main.rs @@ -0,0 +1,11 @@ +use configuration::Configuration; +use relm4::prelude::*; + +mod window; +mod configuration; + +fn main() { + let config = Configuration::default(); + let app = RelmApp::new("expert.mischief.noteriety"); + app.run::(config); +} diff --git a/crates/noteriety-gtk4/src/note.rs b/crates/noteriety-gtk4/src/note.rs new file mode 100644 index 0000000..fbf027b --- /dev/null +++ b/crates/noteriety-gtk4/src/note.rs @@ -0,0 +1,30 @@ +pub struct NoteTitle(String); + +impl Default for NoteTitle { + fn default() -> Self { + Self(String::from("Untitled Note")) + } +} + +impl NoteTitle { + pub fn as_filename(&self) -> String { + filenamify::filenamify(&self.0) + } +} + +pub struct NoteBody(crop::Rope); + +pub struct Note { + title: NoteTitle, + body: NoteBody, +} + +pub struct Notebook { + basedir: String, + notes: Vec, +} + +pub struct Outline { + basedir: String, + body: NoteBody, +} diff --git a/crates/noteriety-gtk4/src/window/content_entry.rs b/crates/noteriety-gtk4/src/window/content_entry.rs new file mode 100644 index 0000000..a97920b --- /dev/null +++ b/crates/noteriety-gtk4/src/window/content_entry.rs @@ -0,0 +1,86 @@ +use gtk::{prelude::*, TextBuffer}; +use markdown_ast::markdown_to_ast; +use relm4::prelude::*; + +pub(crate) struct NoteContentEntry { + pub(crate) content: gtk::TextBuffer, + pub(crate) rope: crop::Rope, +} + +#[derive(Debug)] +pub(crate) enum NoteContentEntryInput { + SetContent(String), + Clear, +} + +#[derive(Debug)] +pub(crate) enum NoteContentEntryOutput { + Content(String), +} + +#[relm4::component(pub(crate))] +impl SimpleComponent for NoteContentEntry { + type Init = (); + type Input = NoteContentEntryInput; + type Output = NoteContentEntryOutput; + + view! { + #[root] + gtk::ScrolledWindow { + set_margin_horizontal: 10, + set_margin_vertical: 10, + + // libadwaita doesn't provide styling for gtk::TextView. + // reason unknown. + // https://gitlab.gnome.org/GNOME/libadwaita/-/issues/353 + gtk::TextView { + inline_css: "padding: 10px; border-radius: 6px", + set_hexpand: true, + set_vexpand: true, + set_buffer: Some(&model.content), + } + } + } + + fn init( + _init: Self::Init, + root: Self::Root, + sender: ComponentSender, + ) -> ComponentParts { + let model = Self { + content: TextBuffer::default(), + rope: crop::Rope::new(), + }; + + model.content.connect_text_notify(move |tb| { + let (min, max) = tb.bounds(); + // let ast = markdown_to_ast(.as_str()); + sender.output(NoteContentEntryOutput::Content(tb.text(&min, &max, true).to_string())); + }); + + let widgets = view_output!(); + + ComponentParts { model, widgets } + } + + fn update(&mut self, message: Self::Input, _sender: ComponentSender) { + match message { + Self::Input::Clear => { + self.content = TextBuffer::default(); + }, + + Self::Input::SetContent(body) => { + self.content = TextBuffer::builder().text(body.to_string()).build(); + } + } + } +} + +impl Default for NoteContentEntry { + fn default() -> Self { + Self { + content: TextBuffer::default(), + rope: crop::Rope::new(), + } + } +} diff --git a/crates/noteriety-gtk4/src/window/header_bar.rs b/crates/noteriety-gtk4/src/window/header_bar.rs new file mode 100644 index 0000000..b093c76 --- /dev/null +++ b/crates/noteriety-gtk4/src/window/header_bar.rs @@ -0,0 +1,54 @@ +use gtk::prelude::{ + ButtonExt, GtkWindowExt, ToggleButtonExt, WidgetExt, +}; +use relm4::*; + +pub(crate) struct HeaderBar; + +#[derive(Debug)] +pub(crate) enum Output { + OutlineMode, + NotesMode, +} + +#[relm4::component(pub(crate))] +impl SimpleComponent for HeaderBar { + type Init = (); + type Input = (); + type Output = Output; + + view! { + #[root] + >k::Box { + add_css_class: "linked", + + #[name = "group"] + gtk::ToggleButton { + set_label: "Outline", + set_active: false, + connect_toggled[sender] => move |btn| { + if btn.is_active() { + sender.output(Self::Output::OutlineMode).unwrap() + } + }, + }, + gtk::ToggleButton { + set_label: "Notes", + set_active: true, + set_group: Some(&group), + connect_toggled[sender] => move |btn| { + if btn.is_active() { + sender.output(Self::Output::NotesMode).unwrap() + } + }, + }, + } + } + + fn init(_params: Self::Init, root: Self::Root, sender: ComponentSender) -> ComponentParts { + let model = HeaderBar; + let widgets = view_output!(); + + ComponentParts { model, widgets } + } +} diff --git a/crates/noteriety-gtk4/src/window/mod.rs b/crates/noteriety-gtk4/src/window/mod.rs new file mode 100644 index 0000000..49d8938 --- /dev/null +++ b/crates/noteriety-gtk4/src/window/mod.rs @@ -0,0 +1,190 @@ +use core::panic; +use std::{cell::RefCell, rc::Rc}; + +use libadwaita::prelude::{ButtonExt, NavigationPageExt, WidgetExt}; +use libadwaita::{ + self as adw, + prelude::{GtkWindowExt, OrientableExt}, +}; +use noteriety::{self, note::Note, notebook::Notebook}; +use relm4::factory::Position; +use relm4::gtk; +use relm4::{ + Component, ComponentController, ComponentParts, ComponentSender, Controller, RelmWidgetExt, + SimpleComponent, +}; + +use crate::configuration::Configuration; + +mod content_entry; +mod header_bar; +mod sidebar; +mod title_entry; + +pub(crate) struct Window { + header_bar: Controller, + sidebar: Controller, + title_entry: Controller, + content_entry: Controller, + config: Configuration, + root_notebook: Notebook, + active_note: Note, +} + +#[derive(Debug)] +pub(crate) enum WindowInput { + SetActiveNote(Note), + UpdateActiveNoteTitle(String), + UpdateActiveNoteContent(String), + CreateNote(Note), + CreateNotebook(Notebook), + CreateNewNote, + SaveActiveNote, +} + +#[derive(Debug)] +enum WindowOutput {} + +#[relm4::component(pub(crate))] +impl SimpleComponent for Window { + type Init = Configuration; + type Input = WindowInput; + type Output = (); + + view! { + main_window = adw::ApplicationWindow { + set_default_width: 640, + set_default_height: 480, + + adw::NavigationSplitView { + #[wrap(Some)] + set_sidebar = &adw::NavigationPage { + #[wrap(Some)] + set_child = &adw::ToolbarView { + #[wrap(Some)] + set_content = >k::Box { + set_orientation: gtk::Orientation::Vertical, + set_margin_all: 10, + model.header_bar.widget(), + + model.sidebar.widget(), + } + }, + }, + + #[wrap(Some)] + set_content = &adw::NavigationPage { + #[wrap(Some)] + set_child = >k::Box { + set_orientation: gtk::Orientation::Vertical, + adw::HeaderBar { + #[wrap(Some)] + set_title_widget = &adw::WindowTitle { + #[watch] + set_title: &model.active_note.title.to_string() + }, + }, + + gtk::Box { + set_orientation: gtk::Orientation::Horizontal, + model.title_entry.widget(), + gtk::Box { + set_orientation: gtk::Orientation::Vertical, + gtk::Button { + set_label: "new note", + set_margin_bottom: 6, + set_halign: gtk::Align::Center, + set_valign: gtk::Align::Center, + connect_clicked => WindowInput::CreateNewNote + }, + gtk::Button { + set_label: "save note", + set_halign: gtk::Align::Center, + set_valign: gtk::Align::Center, + connect_clicked => WindowInput::SaveActiveNote + }, + }, + }, + + model.content_entry.widget(), + } + } + } + } + } + + fn init( + config: Self::Init, + window: Self::Root, + sender: ComponentSender, + ) -> ComponentParts { + let root_notebook = Notebook::read(&config.notes_dir).unwrap(); + + let title_entry = + title_entry::NoteTitleEntry::builder() + .launch(()) + .forward(sender.input_sender(), |m| match m { + title_entry::NoteTitleEntryOutput::Content(v) => { + WindowInput::UpdateActiveNoteTitle(v) + } + }); + + let content_entry = content_entry::NoteContentEntry::builder() + .launch(()) + .forward(sender.input_sender(), |m| match m { + content_entry::NoteContentEntryOutput::Content(content) => { + WindowInput::UpdateActiveNoteContent(content) + } + }); + + let sidebar = sidebar::Sidebar::builder().launch(()).detach(); + + let header_bar = header_bar::HeaderBar::builder().launch(()).detach(); + + let model = Self { + title_entry, + header_bar, + sidebar, + content_entry, + config, + root_notebook: root_notebook.clone(), + active_note: Note::new("untitled note"), + }; + + model.sidebar.emit(sidebar::Input::UpdateRoot(root_notebook.clone())); + + let widgets = view_output!(); + ComponentParts { model, widgets } + } + + fn update(&mut self, input: Self::Input, sender: ComponentSender) { + match input { + WindowInput::UpdateActiveNoteTitle(title) => { + self.active_note.title = title; + }, + + WindowInput::UpdateActiveNoteContent(content) => { + self.active_note.content = content; + }, + + WindowInput::SetActiveNote(note) => { + self.active_note = note; + }, + + WindowInput::SaveActiveNote => { + self.active_note + .write_in(&self.root_notebook.root_path) + .unwrap(); + + self.root_notebook = Notebook::read(&self.root_notebook.root_path).unwrap(); + self.sidebar.emit(sidebar::Input::UpdateRoot(self.root_notebook.clone())); + }, + + WindowInput::CreateNewNote => { + self.active_note = Note::new(""); + }, + + _ => (), + } + } +} diff --git a/crates/noteriety-gtk4/src/window/sidebar.rs b/crates/noteriety-gtk4/src/window/sidebar.rs new file mode 100644 index 0000000..4067489 --- /dev/null +++ b/crates/noteriety-gtk4/src/window/sidebar.rs @@ -0,0 +1,124 @@ +use std::rc::Rc; + +use binding::U8Binding; +use gtk::{prelude::{ + ButtonExt, GtkWindowExt, ListItemExt, WidgetExt, +}}; +use noteriety::{note::Note, notebook::Notebook}; +use relm4::*; +use typed_view::list::{RelmListItem, TypedListView}; + +pub struct SidebarItemWidgets { + label: gtk::Label, +} + +#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)] +pub(crate) struct SidebarItem { + note: Note, + title: String, + binding: U8Binding, +} + +impl SidebarItem { + fn new(note: Note) -> Self { + Self { + note: note.clone(), + title: note.title.clone(), + binding: U8Binding::new(0), + } + } +} + +impl RelmListItem for SidebarItem { + type Root = gtk::Box; + type Widgets = SidebarItemWidgets; + + fn setup(_list_item: >k::ListItem) -> (Self::Root, Self::Widgets) { + view! { + list_item = gtk::Box { + inline_css: "padding: 10px; border-radius: 6px", + + #[name = "label"] + gtk::Label, + } + } + + let widgets = SidebarItemWidgets { + label, + }; + + (list_item, widgets) + } + + fn bind(&mut self, widgets: &mut Self::Widgets, _root: &mut Self::Root) { + let SidebarItemWidgets { + label + } = widgets; + + label.set_label(&self.note.title.to_string()) + } +} + +pub(crate) struct Sidebar { + list_view: TypedListView, + root: Option, +} + +#[derive(Debug)] +pub(crate) enum Output { +} + +#[derive(Debug)] +pub(crate) enum Input { + UpdateRoot(Notebook), +} + +#[relm4::component(pub(crate))] +impl SimpleComponent for Sidebar { + type Init = (); + type Input = Input; + type Output = Output; + + view! { + #[root] + #[wrap(Some)] + >k::Box{ + set_margin_top: 12, + gtk::ScrolledWindow { + set_vexpand: true, + set_hexpand: true, + + #[local_ref] + sidebar_view -> gtk::ListView {} + } + } + } + + fn init(root_notebook: Self::Init, root: Self::Root, sender: ComponentSender) -> ComponentParts { + let list_view_wrapper: TypedListView = + TypedListView::with_sorting(); + + let model = Self { + list_view: list_view_wrapper, + root: None, + }; + + let sidebar_view = &model.list_view.view; + let widgets = view_output!(); + + ComponentParts { model, widgets } + } + + fn update(&mut self, message: Self::Input, sender: ComponentSender) { + match message { + Input::UpdateRoot(notebook) => { + self.list_view.clear(); + + notebook.child_notes.into_iter().for_each(|n| { + self.list_view.append(SidebarItem::new(n.clone())); + }); + }, + _ => todo!() + } + } +} diff --git a/crates/noteriety-gtk4/src/window/title_entry.rs b/crates/noteriety-gtk4/src/window/title_entry.rs new file mode 100644 index 0000000..b613bb8 --- /dev/null +++ b/crates/noteriety-gtk4/src/window/title_entry.rs @@ -0,0 +1,55 @@ +use gtk::prelude::*; +use relm4::prelude::*; + +#[derive(Default)] +pub(crate) struct NoteTitleEntry { + pub(crate) content: gtk::EntryBuffer, +} + +#[derive(Debug)] +pub(crate) enum NoteTitleEntryInput { +} + +#[derive(Debug)] +pub(crate) enum NoteTitleEntryOutput { + Content(String), +} + +#[relm4::component(pub(crate))] +impl SimpleComponent for NoteTitleEntry { + type Init = (); + type Input = NoteTitleEntryInput; + type Output = NoteTitleEntryOutput; + + view! { + #[root] + gtk::Entry { + set_hexpand: true, + set_margin_all: 12, + set_buffer: &model.content, + set_placeholder_text: Some("note title"), + connect_has_focus_notify: move |entry| { + if !entry.is_focus() { + sender.output(NoteTitleEntryOutput::Content(entry.buffer().text().to_string().into())).unwrap(); + } + }, + }, + } + + fn init( + _init: Self::Init, + root: Self::Root, + sender: ComponentSender, + ) -> ComponentParts { + let model = Self { + content: gtk::EntryBuffer::default(), + }; + let widgets = view_output!(); + ComponentParts { model, widgets } + } + + fn update(&mut self, message: Self::Input, _sender: ComponentSender) { + match message { + } + } +} diff --git a/crates/noteriety/src/note.rs b/crates/noteriety/src/note.rs index 675ecce..54cf03c 100644 --- a/crates/noteriety/src/note.rs +++ b/crates/noteriety/src/note.rs @@ -20,10 +20,10 @@ pub struct Note { pub title: String, /// todo: replace body type with something more appropriate. /// a rope-backed buffer, perhaps. - body: String, - created_at: chrono::DateTime, + pub content: String, + pub created_at: chrono::DateTime, /// if a note has never been updated since its creation, updated_at will be none. - updated_at: Option>, + pub updated_at: Option>, } impl PartialEq for Note { @@ -40,6 +40,12 @@ impl PartialOrd for Note { } } +impl Ord for Note { + fn cmp(&self, other: &Self) -> std::cmp::Ordering { + self.created_at.partial_cmp(&other.created_at).unwrap_or(std::cmp::Ordering::Equal) + } +} + impl Note { pub fn new(title: T) -> Self where @@ -48,7 +54,7 @@ impl Note { Self { id: Uuid::new_v4(), title: title.as_ref().to_string(), - body: Default::default(), + content: Default::default(), created_at: chrono::Utc::now(), updated_at: None, } @@ -61,7 +67,7 @@ impl Note { Self { id: self.id, title: title.as_ref().to_string(), - body: self.body, + content: self.content, created_at: self.created_at, updated_at: Some(Utc::now()) } @@ -71,7 +77,7 @@ impl Note { Self { id: self.id, title: self.title, - body: body.as_ref().to_string(), + content: body.as_ref().to_string(), created_at: self.created_at, updated_at: Some(Utc::now()), } @@ -88,7 +94,15 @@ impl Note { where P: AsRef, { - let file = File::open(path).map_err(|_| Error::NoteFileRead)?; + let file = File::create(path).map_err(|_| Error::NoteFileRead)?; + self.write(file) + } + + pub fn write_in

(&self, path: P) -> Result<(), Error> + where + P: AsRef, + { + let file = File::create(path.as_ref().join(self.id.to_string())).map_err(|_| Error::NoteFileRead)?; self.write(file) } @@ -128,7 +142,7 @@ mod test { let note1 = Note { id: Default::default(), title: Default::default(), - body: Default::default(), + content: Default::default(), created_at: DateTime::from_timestamp(2000000000, 0).unwrap(), updated_at: Default::default(), }; @@ -136,7 +150,7 @@ mod test { let note2 = Note { id: Default::default(), title: Default::default(), - body: Default::default(), + content: Default::default(), created_at: DateTime::from_timestamp(1000000000, 0).unwrap(), updated_at: Default::default(), }; diff --git a/crates/noteriety/src/notebook.rs b/crates/noteriety/src/notebook.rs index de2a740..4149963 100644 --- a/crates/noteriety/src/notebook.rs +++ b/crates/noteriety/src/notebook.rs @@ -8,7 +8,7 @@ use crate::{error::Error, note::Note}; /// a notebook is a representation of a named collection of notes and child notebooks. /// notebooks are ephemeral, and are represented on-disk by the directory tree. -#[derive(Default)] +#[derive(Clone, Debug, Default)] pub struct Notebook { pub root_path: PathBuf, pub name: String,