shared/
app.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
use crate::capabilities::persistent_storage::PersistentStorage;
use crate::global::{global_events, GlEvGlobal};
use crate::model::Model;
use crate::model_ui::UiModel;
use crate::screens::initial::{initial_screen_events, ScEvInitial};
use crate::screens::input_fields_and_tags::{input_fields_and_tags_events, ScEvInputFieldsAndTags};
use crate::screens::post_write_review::{post_write_review_screen_events, ScEvPostWriteReview};
use crate::screens::select_org_bucket_measurements::{
    select_org_bucket_measurement_screen_events, ScEvSelectOrgBucketMeasurement,
};
use crate::screens::settings::{settings_events, ScEvSettings};
use crate::screens::settings_previous_connections_actions::{
    setting_previous_connections_events, ScEvSettingPreviousConnections,
};
use crate::Event::*;
use android_logger::Config;
use crux_core::{render::Render, App, Command};
use crux_http::Http;
use log::trace;
use serde::{Deserialize, Serialize};

// ordered alphabetically to keep inline with filesystem
#[derive(Serialize, Deserialize, Clone, Debug)]
pub enum Event {
    EvInitialScreen(ScEvInitial),
    EvInputFieldsAndTagsEventsScreen(ScEvInputFieldsAndTags),
    EvPostWriteReviewScreen(ScEvPostWriteReview),
    EvSelectOrgBucketMeasurementScreen(ScEvSelectOrgBucketMeasurement),
    EvSettingsScreen(ScEvSettings),
    EvSettingsPreviousConnectionsScreen(ScEvSettingPreviousConnections),
    EvGlobal(GlEvGlobal),
}

#[cfg_attr(feature = "typegen", derive(crux_core::macros::Export))]
#[derive(crux_core::macros::Effect)]
pub struct Capabilities {
    pub http: Http<Event>,
    pub render: Render<Event>,
    pub persistent_storage: PersistentStorage<Event>,
}

#[derive(Default)]
pub struct Counter;

use std::sync::Once;

static START: Once = Once::new();

impl App for Counter {
    type Event = Event;
    type Model = Model;
    type ViewModel = UiModel;
    type Capabilities = Capabilities;
    type Effect = Effect;

    fn update(
        &self,
        event: Self::Event,
        model: &mut Self::Model,
        _caps: &Self::Capabilities,
    ) -> Command<Effect, Event> {
        START.call_once(|| {
            android_logger::init_once(
                Config::default()
                    // for prod enable warn line
                    // .with_max_level(log::LevelFilter::Warn) // limit log level
                    // for dev enable trace line
                    .with_max_level(log::LevelFilter::Trace)
                    .with_tag("FL:C"),
            );
        });

        trace!("Clear all existing messages");
        model.user_messages.remove_all_messages();

        trace!("Run event");
        trace!("model:{:?}", model.screen);
        trace!("event:{:?}", event);
        match event {
            EvInitialScreen(internal_event) => initial_screen_events(internal_event, model),
            EvInputFieldsAndTagsEventsScreen(internal_event) => {
                input_fields_and_tags_events(internal_event, model)
            }
            EvPostWriteReviewScreen(event) => post_write_review_screen_events(event, model),
            EvSelectOrgBucketMeasurementScreen(internal_event) => {
                select_org_bucket_measurement_screen_events(internal_event, model)
            }
            EvSettingsScreen(internal_event) => settings_events(internal_event, model),
            EvSettingsPreviousConnectionsScreen(internal_event) => {
                setting_previous_connections_events(internal_event, model)
            }
            EvGlobal(event) => global_events(event, model),
        }
    }

    fn view(&self, model: &Self::Model) -> Self::ViewModel {
        model.into()
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::capabilities::persistent_storage::PersistentStorageOutput::FileData;
    use crate::screens::initial::ScEvInitial::LoadPreviousConnectionsResult;
    use crux_core::testing::AppTester;

    #[test]
    fn render() {
        let app = AppTester::<Counter>::default();
        // app.as_ref()
        let event = EvInitialScreen(LoadPreviousConnectionsResult(FileData("[{\"name\":null,\"api_token\":\"hRB1aa-CJ6Cn2ncYy7oDT1FrdHIZ7A6E03juEwOJv-_FpRf3tzZaldHMNb9HueXeMoeX8MF7-Y7FvyTB0kGpng==\",\"base_url\":\"http://100.108.38.15:8086\"}]".to_owned())));
        let mut model = Model::default();
        let commands = app.update(event, &mut model);
        let effect = commands.effects().next();
        assert!(effect.is_some());

        match effect {
            None => {
                assert!(false);
            }
            Some(render_maybe) => match render_maybe {
                Effect::Http(_) => {
                    assert!(false)
                }
                Effect::PersistentStorage(_) => {
                    assert!(false)
                }
                Effect::Render(_) => {
                    assert!(true)
                }
            },
        }
    }
}