shared/
model.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
use crate::screens::initial::InitialScreenData;
use crate::screens::input_fields_and_tags::InputFieldsAndTagsScreenData;
use crate::screens::post_write_review::PostWriteReviewScreenData;
use crate::screens::select_org_bucket_measurements::SelectOrgBucketMeasurementScreenData;
use crate::screens::settings_previous_connections_actions::SettingsPreviousConnectionsActionsScreenData;
use log::Level;
use std::collections::VecDeque;
// ============================================================================
// Core data types used everywhere
// ============================================================================

pub const CREDENTIAL_FILENAME: &str = "credentials";
pub const PREVIOUS_CONNECTIONS_FILENAME: &str = "previous_connections";
pub const QUICK_ACTIONS_FILENAME: &str = "quick_actions";

/// Main structure
#[derive(Default, Clone, Debug)]
pub struct Model {
    pub screen: Screens,
    pub user_messages: UserMessages,
    pub example_data: ExampleData,
}

//region ...
/// this is both used to flag a tutorial and for me to code when offline
/// tutorial can be triggered using a specific url/token, on first lunch popup (todo) and an option in the settings screen (todo)
/// for offline use we only need to mock the capability calls..so I simply skip the capability calls
/// and make the appropriate model changes, ideally id like to call the functions directly but I can't
/// so settled on making the model changes
///
/// tutorial requires some UI thinking and will be done at a later date
#[derive(Default, Clone, Debug)]
pub enum ExampleData {
    /// we shall increment the number and let the UI choose what should and shouldn't be displayed for that number in the tutorial
    /// and also any actions the Ui should do as well. I think screens should reset the counter... but maybe not necessary
    /// counter is u8 because if my tutorial has more than 255 steps I have failed
    Tutorial(u8),
    FakeData,
    #[default]
    Real,
}
//endregion

// order is alphabetical to be in line with file browser
#[derive(Clone, Debug)]
pub enum Screens {
    InitialScreen(InitialScreenData),
    InputFieldsTagsScreen(InputFieldsAndTagsScreenData),
    PostWriteReviewScreen(PostWriteReviewScreenData),
    SelectOrgBucketMeasurementScreen(Box<SelectOrgBucketMeasurementScreenData>),
    SettingPreviousConnectionsScreen(SettingsPreviousConnectionsActionsScreenData), // provide a set of methods to delete/name/edit/add connections
    SettingsScreen,
}

impl Default for Screens {
    fn default() -> Self {
        Screens::InitialScreen(InitialScreenData::default())
    }
}

#[derive(Clone, Default, Debug)]
pub struct UserMessages {
    pub messages: VecDeque<UserMessage>,
    current_id: u64,
}

#[derive(Clone, Debug)]
pub struct UserMessage {
    pub message: String,
    pub level: Level,
    pub id: u64,
}

impl UserMessages {
    pub fn error_report_to_developer(&mut self, message: &'static str) {
        self.current_id += 1; // todo handle overflow
        self.messages.push_back(UserMessage {
            message: message.to_owned(),
            level: Level::Error,
            id: self.current_id,
        })
    }

    pub fn add_message(&mut self, message: impl Into<String>, level: Level) {
        self.current_id += 1; // todo handle overflow
        self.messages.push_back(UserMessage {
            message: message.into(),
            level,
            id: self.current_id,
        })
    }

    pub fn remove_messages_till(&mut self, id: u64) {
        'main_loop: loop {
            match self.messages.front() {
                None => break 'main_loop,
                Some(message) => {
                    if message.id <= id {
                        self.messages.pop_front();
                    }
                }
            }
        }
    }

    pub fn remove_all_messages(&mut self) {
        self.messages = VecDeque::new(); // todo is this the fastest best solution?
    }
}

// ============================================================================
// Common data types used across multiple screens live in screens_common/model.rs
// ============================================================================