Skip to content

Commit

Permalink
refactor: manage state on the rust side (#112)
Browse files Browse the repository at this point in the history
* chore: update PKGBUILD

* feat: first version of pomodoro state in Rust

* fix: update flatpak deps

* feat: get session from rust to elm

* feat: decode rust state to elm

* test: add cargo tests

* ci: add clippy

* refactor: clippy

* ci: install missing deps

* ci: merge clippy and test actions

* ci: fix clippy error

* ci: create dist dir for clippy

* chore: remove unused import

* refactor: manage play tick on Rust side

* refactor: split Elm code

* feat: store muted status in config file

* refactor: manage state in Rust

* fix: config modification save
  • Loading branch information
vjousse authored Oct 6, 2024
1 parent 3d4df94 commit 8e6fb4e
Show file tree
Hide file tree
Showing 13 changed files with 1,391 additions and 746 deletions.
25 changes: 25 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,12 @@ on:
push:
branches: [main]

env:
RUSTFLAGS: "-Dwarnings"

jobs:
linting:
name: Lint python and elm
runs-on: ubuntu-latest

steps:
Expand Down Expand Up @@ -36,3 +40,24 @@ jobs:

- name: Run pre-commit hooks on all files
run: uv run pre-commit run --all-files

rust_testing:
name: Lint and test rust code
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install -y libwebkit2gtk-4.1-dev libappindicator3-dev librsvg2-dev patchelf libasound2-dev
- name: Update Rust
run: rustup update stable && rustup default stable

- name: Run clippy
run: |
mkdir dist
cargo clippy --all-targets --all-features --manifest-path src-tauri/Cargo.toml
- name: Run cargo test
run: cargo test --verbose --manifest-path src-tauri/Cargo.toml
2 changes: 1 addition & 1 deletion aur/PKGBUILD
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ license=('MIT')
depends=('alsa-lib' 'gtk3' 'hicolor-icon-theme' 'glibc' 'webkit2gtk-4.1' 'libsoup' 'cairo' 'glib2' 'pango' 'gcc-libs' 'gdk-pixbuf2')
provides=('pomodorolm')
source=("https://github.com/vjousse/pomodorolm/releases/download/app-v$pkgver/pomodorolm_${pkgver}_amd64.deb")
sha256sums=('4aed027759bdc58cebdc372afc16635882bb0d11045d92f352ec942aba2de7a9')
sha256sums=('807ade5646cd287cb4932f25eaa7f9f56fe858b0fa9979015522320be5e828f6')
package() {
bsdtar -xf "$srcdir/data.tar.gz" -C "$pkgdir"
}
156 changes: 156 additions & 0 deletions flatpak/cargo-sources.json
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,71 @@
"dest": "cargo/vendor/android_system_properties-0.1.5",
"dest-filename": ".cargo-checksum.json"
},
{
"type": "archive",
"archive-type": "tar-gzip",
"url": "https://static.crates.io/crates/anstream/anstream-0.6.15.crate",
"sha256": "64e15c1ab1f89faffbf04a634d5e1962e9074f2741eef6d97f3c4e322426d526",
"dest": "cargo/vendor/anstream-0.6.15"
},
{
"type": "inline",
"contents": "{\"package\": \"64e15c1ab1f89faffbf04a634d5e1962e9074f2741eef6d97f3c4e322426d526\", \"files\": {}}",
"dest": "cargo/vendor/anstream-0.6.15",
"dest-filename": ".cargo-checksum.json"
},
{
"type": "archive",
"archive-type": "tar-gzip",
"url": "https://static.crates.io/crates/anstyle/anstyle-1.0.8.crate",
"sha256": "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1",
"dest": "cargo/vendor/anstyle-1.0.8"
},
{
"type": "inline",
"contents": "{\"package\": \"1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1\", \"files\": {}}",
"dest": "cargo/vendor/anstyle-1.0.8",
"dest-filename": ".cargo-checksum.json"
},
{
"type": "archive",
"archive-type": "tar-gzip",
"url": "https://static.crates.io/crates/anstyle-parse/anstyle-parse-0.2.5.crate",
"sha256": "eb47de1e80c2b463c735db5b217a0ddc39d612e7ac9e2e96a5aed1f57616c1cb",
"dest": "cargo/vendor/anstyle-parse-0.2.5"
},
{
"type": "inline",
"contents": "{\"package\": \"eb47de1e80c2b463c735db5b217a0ddc39d612e7ac9e2e96a5aed1f57616c1cb\", \"files\": {}}",
"dest": "cargo/vendor/anstyle-parse-0.2.5",
"dest-filename": ".cargo-checksum.json"
},
{
"type": "archive",
"archive-type": "tar-gzip",
"url": "https://static.crates.io/crates/anstyle-query/anstyle-query-1.1.1.crate",
"sha256": "6d36fc52c7f6c869915e99412912f22093507da8d9e942ceaf66fe4b7c14422a",
"dest": "cargo/vendor/anstyle-query-1.1.1"
},
{
"type": "inline",
"contents": "{\"package\": \"6d36fc52c7f6c869915e99412912f22093507da8d9e942ceaf66fe4b7c14422a\", \"files\": {}}",
"dest": "cargo/vendor/anstyle-query-1.1.1",
"dest-filename": ".cargo-checksum.json"
},
{
"type": "archive",
"archive-type": "tar-gzip",
"url": "https://static.crates.io/crates/anstyle-wincon/anstyle-wincon-3.0.4.crate",
"sha256": "5bf74e1b6e971609db8ca7a9ce79fd5768ab6ae46441c572e46cf596f59e57f8",
"dest": "cargo/vendor/anstyle-wincon-3.0.4"
},
{
"type": "inline",
"contents": "{\"package\": \"5bf74e1b6e971609db8ca7a9ce79fd5768ab6ae46441c572e46cf596f59e57f8\", \"files\": {}}",
"dest": "cargo/vendor/anstyle-wincon-3.0.4",
"dest-filename": ".cargo-checksum.json"
},
{
"type": "archive",
"archive-type": "tar-gzip",
Expand Down Expand Up @@ -987,6 +1052,58 @@
"dest": "cargo/vendor/clang-sys-1.8.1",
"dest-filename": ".cargo-checksum.json"
},
{
"type": "archive",
"archive-type": "tar-gzip",
"url": "https://static.crates.io/crates/clap/clap-4.5.18.crate",
"sha256": "b0956a43b323ac1afaffc053ed5c4b7c1f1800bacd1683c353aabbb752515dd3",
"dest": "cargo/vendor/clap-4.5.18"
},
{
"type": "inline",
"contents": "{\"package\": \"b0956a43b323ac1afaffc053ed5c4b7c1f1800bacd1683c353aabbb752515dd3\", \"files\": {}}",
"dest": "cargo/vendor/clap-4.5.18",
"dest-filename": ".cargo-checksum.json"
},
{
"type": "archive",
"archive-type": "tar-gzip",
"url": "https://static.crates.io/crates/clap_builder/clap_builder-4.5.18.crate",
"sha256": "4d72166dd41634086d5803a47eb71ae740e61d84709c36f3c34110173db3961b",
"dest": "cargo/vendor/clap_builder-4.5.18"
},
{
"type": "inline",
"contents": "{\"package\": \"4d72166dd41634086d5803a47eb71ae740e61d84709c36f3c34110173db3961b\", \"files\": {}}",
"dest": "cargo/vendor/clap_builder-4.5.18",
"dest-filename": ".cargo-checksum.json"
},
{
"type": "archive",
"archive-type": "tar-gzip",
"url": "https://static.crates.io/crates/clap_derive/clap_derive-4.5.18.crate",
"sha256": "4ac6a0c7b1a9e9a5186361f67dfa1b88213572f427fb9ab038efb2bd8c582dab",
"dest": "cargo/vendor/clap_derive-4.5.18"
},
{
"type": "inline",
"contents": "{\"package\": \"4ac6a0c7b1a9e9a5186361f67dfa1b88213572f427fb9ab038efb2bd8c582dab\", \"files\": {}}",
"dest": "cargo/vendor/clap_derive-4.5.18",
"dest-filename": ".cargo-checksum.json"
},
{
"type": "archive",
"archive-type": "tar-gzip",
"url": "https://static.crates.io/crates/clap_lex/clap_lex-0.7.2.crate",
"sha256": "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97",
"dest": "cargo/vendor/clap_lex-0.7.2"
},
{
"type": "inline",
"contents": "{\"package\": \"1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97\", \"files\": {}}",
"dest": "cargo/vendor/clap_lex-0.7.2",
"dest-filename": ".cargo-checksum.json"
},
{
"type": "archive",
"archive-type": "tar-gzip",
Expand Down Expand Up @@ -1065,6 +1182,19 @@
"dest": "cargo/vendor/color_quant-1.1.0",
"dest-filename": ".cargo-checksum.json"
},
{
"type": "archive",
"archive-type": "tar-gzip",
"url": "https://static.crates.io/crates/colorchoice/colorchoice-1.0.2.crate",
"sha256": "d3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0",
"dest": "cargo/vendor/colorchoice-1.0.2"
},
{
"type": "inline",
"contents": "{\"package\": \"d3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0\", \"files\": {}}",
"dest": "cargo/vendor/colorchoice-1.0.2",
"dest-filename": ".cargo-checksum.json"
},
{
"type": "archive",
"archive-type": "tar-gzip",
Expand Down Expand Up @@ -2898,6 +3028,19 @@
"dest": "cargo/vendor/is-wsl-0.4.0",
"dest-filename": ".cargo-checksum.json"
},
{
"type": "archive",
"archive-type": "tar-gzip",
"url": "https://static.crates.io/crates/is_terminal_polyfill/is_terminal_polyfill-1.70.1.crate",
"sha256": "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf",
"dest": "cargo/vendor/is_terminal_polyfill-1.70.1"
},
{
"type": "inline",
"contents": "{\"package\": \"7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf\", \"files\": {}}",
"dest": "cargo/vendor/is_terminal_polyfill-1.70.1",
"dest-filename": ".cargo-checksum.json"
},
{
"type": "archive",
"archive-type": "tar-gzip",
Expand Down Expand Up @@ -6837,6 +6980,19 @@
"dest": "cargo/vendor/utf8-width-0.1.7",
"dest-filename": ".cargo-checksum.json"
},
{
"type": "archive",
"archive-type": "tar-gzip",
"url": "https://static.crates.io/crates/utf8parse/utf8parse-0.2.2.crate",
"sha256": "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821",
"dest": "cargo/vendor/utf8parse-0.2.2"
},
{
"type": "inline",
"contents": "{\"package\": \"06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821\", \"files\": {}}",
"dest": "cargo/vendor/utf8parse-0.2.2",
"dest-filename": ".cargo-checksum.json"
},
{
"type": "archive",
"archive-type": "tar-gzip",
Expand Down
140 changes: 140 additions & 0 deletions src-elm/Json.elm
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
module Json exposing (elmMessageEncoder, externalMessageDecoder)

import Json.Decode as Decode
import Json.Decode.Pipeline as Pipe
import Json.Encode as Encode
import Themes exposing (Theme, ThemeColors)
import Types exposing (Config, ConfigAndThemes, ElmMessage, ExternalMessage(..), RustSession, RustState, SessionStatus(..), SessionType(..))


elmMessageEncoder : ElmMessage -> Encode.Value
elmMessageEncoder elmMessage =
Encode.object
[ ( "name", Encode.string elmMessage.name )
]


themeColorsDecoder : Decode.Decoder ThemeColors
themeColorsDecoder =
Decode.succeed ThemeColors
|> Pipe.required "accent" Decode.string
|> Pipe.required "background" Decode.string
|> Pipe.required "background_light" Decode.string
|> Pipe.required "background_lightest" Decode.string
|> Pipe.required "focus_round" Decode.string
|> Pipe.required "focus_round_end" Decode.string
|> Pipe.required "focus_round_middle" Decode.string
|> Pipe.required "foreground" Decode.string
|> Pipe.required "foreground_darker" Decode.string
|> Pipe.required "foreground_darkest" Decode.string
|> Pipe.required "long_round" Decode.string
|> Pipe.required "short_round" Decode.string


themeDecoder : Decode.Decoder Theme
themeDecoder =
Decode.succeed Theme
|> Pipe.required "colors" themeColorsDecoder
|> Pipe.required "name" Decode.string


themesDecoder : Decode.Decoder (List Theme)
themesDecoder =
Decode.list themeDecoder


configDecoder : Decode.Decoder Config
configDecoder =
let
fieldSet0 =
Decode.map8 Config
(Decode.field "always_on_top" Decode.bool)
(Decode.field "auto_start_break_timer" Decode.bool)
(Decode.field "auto_start_work_timer" Decode.bool)
(Decode.field "desktop_notifications" Decode.bool)
(Decode.field "long_break_duration" Decode.int)
(Decode.field "max_round_number" Decode.int)
(Decode.field "minimize_to_tray" Decode.bool)
(Decode.field "minimize_to_tray_on_close" Decode.bool)
in
Decode.map7 (<|)
fieldSet0
(Decode.field "muted" Decode.bool)
(Decode.field "pomodoro_duration" Decode.int)
(Decode.field "short_break_duration" Decode.int)
(Decode.field "theme" Decode.string)
(Decode.field "tick_sounds_during_break" Decode.bool)
(Decode.field "tick_sounds_during_work" Decode.bool)


configAndThemesDecoder : Decode.Decoder ConfigAndThemes
configAndThemesDecoder =
Decode.succeed ConfigAndThemes
|> Pipe.required "config" configDecoder
|> Pipe.required "themes" themesDecoder


rustStateDecoder : Decode.Decoder RustState
rustStateDecoder =
Decode.succeed RustState
|> Pipe.required "current_session" rustSessionDecoder
|> Pipe.required "current_work_round_number" Decode.int


sessionTypeFromStringDecoder : String -> Decode.Decoder SessionType
sessionTypeFromStringDecoder string =
case String.toLower string of
"focus" ->
Decode.succeed Focus

"shortbreak" ->
Decode.succeed ShortBreak

"longbreak" ->
Decode.succeed LongBreak

_ ->
Decode.fail ("Unknown sessionType: " ++ string)


sessionTypeDecoder : Decode.Decoder SessionType
sessionTypeDecoder =
Decode.string |> Decode.andThen sessionTypeFromStringDecoder


sessionStatusDecoder : Decode.Decoder SessionStatus
sessionStatusDecoder =
Decode.string |> Decode.andThen sessionStatusFromStringDecoder


sessionStatusFromStringDecoder : String -> Decode.Decoder SessionStatus
sessionStatusFromStringDecoder string =
case String.toLower string of
"paused" ->
Decode.succeed Paused

"notstarted" ->
Decode.succeed NotStarted

"running" ->
Decode.succeed Running

_ ->
Decode.fail ("Unknown sessionStatus: " ++ string)


rustSessionDecoder : Decode.Decoder RustSession
rustSessionDecoder =
Decode.succeed RustSession
|> Pipe.required "current_time" Decode.int
|> Pipe.optional "label" (Decode.maybe Decode.string) Nothing
|> Pipe.required "session_type" sessionTypeDecoder
|> Pipe.required "status" sessionStatusDecoder


externalMessageDecoder : Decode.Decoder ExternalMessage
externalMessageDecoder =
Decode.oneOf
[ rustStateDecoder |> Decode.map RustStateMsg
, configAndThemesDecoder |> Decode.map RustConfigAndThemesMsg
]
Loading

0 comments on commit 8e6fb4e

Please sign in to comment.