Skip to content

Commit 25861a4

Browse files
authored
Feature/minor improvements (#51)
Minor improvements with trait implementations for the upcoming 0.3 release with a test pipeline
1 parent 5da920d commit 25861a4

File tree

11 files changed

+107
-98
lines changed

11 files changed

+107
-98
lines changed

.github/FUNDING.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
ko_fi: mawilms

Cargo.lock

Lines changed: 12 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ webbrowser = "^0"
3333
fs_extra = "^1"
3434
globset = "^0"
3535
chrono = "^0"
36+
async-trait = "^0"
3637

3738
[build-dependencies]
3839
embed-resource = "^1"

src/core/api_connector.rs

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
use crate::core::{Base as BasePlugin, Plugin as DetailsPlugin};
2+
use async_trait::async_trait;
3+
use serde::{Deserialize, Serialize};
4+
use std::collections::HashMap;
5+
6+
#[async_trait]
7+
pub trait APIOperations {
8+
async fn fetch_plugins() -> Result<HashMap<String, BasePlugin>, APIError>;
9+
10+
fn fetch_details(title: &str) -> DetailsPlugin;
11+
}
12+
13+
pub struct APIConnector {}
14+
15+
#[async_trait]
16+
impl APIOperations for APIConnector {
17+
async fn fetch_plugins() -> Result<HashMap<String, BasePlugin>, APIError> {
18+
match reqwest::get("https://young-hamlet-23901.herokuapp.com/plugins").await {
19+
Ok(response) => match response.json::<HashMap<String, BasePlugin>>().await {
20+
Ok(plugins) => Ok(plugins),
21+
Err(_) => Err(APIError::FetchError),
22+
},
23+
Err(_) => Err(APIError::FetchError),
24+
}
25+
}
26+
27+
fn fetch_details(title: &str) -> DetailsPlugin {
28+
let response = reqwest::blocking::get(format!(
29+
"https://young-hamlet-23901.herokuapp.com/plugins/{}",
30+
title.to_lowercase()
31+
))
32+
.expect("Failed to connect with API")
33+
.json::<JSONResponse>()
34+
.expect("Failed to parse response");
35+
36+
DetailsPlugin::new(
37+
response.plugin_id,
38+
&response.title,
39+
"",
40+
&response.category,
41+
&response.current_version,
42+
&response.latest_version,
43+
&response.folders,
44+
&response.files,
45+
)
46+
}
47+
}
48+
49+
#[derive(Default, Serialize, Deserialize, Debug, Clone, Eq, PartialEq, Hash, PartialOrd, Ord)]
50+
struct JSONResponse {
51+
pub plugin_id: i32,
52+
pub title: String,
53+
#[serde(default)]
54+
pub description: String,
55+
pub category: String,
56+
#[serde(default)]
57+
pub current_version: String,
58+
pub latest_version: String,
59+
pub folders: String,
60+
pub files: Vec<String>,
61+
}
62+
63+
#[derive(Debug, Clone)]
64+
pub enum APIError {
65+
FetchError,
66+
}

src/core/config.rs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,19 @@
11
use dirs::{cache_dir, data_dir, home_dir};
22
use lazy_static::lazy_static;
33
use serde::{Deserialize, Serialize};
4+
use std::path::Path;
45
use std::sync::Mutex;
5-
use std::{fs::OpenOptions, path::Path};
66
use std::{
77
fs::{self, write, File},
88
io::Read,
99
};
1010

11+
trait FileConfigurations {
12+
fn new() -> Self;
13+
}
14+
1115
lazy_static! {
12-
pub static ref CONFIGURATION: Mutex<Config> = Mutex::new(Config::default());
16+
pub static ref CONFIGURATION: Mutex<Config> = Mutex::new(Config::new());
1317
}
1418

1519
#[derive(Debug, Clone)]
@@ -21,8 +25,8 @@ pub struct Config {
2125
pub application_settings: SettingsFile,
2226
}
2327

24-
impl Default for Config {
25-
fn default() -> Self {
28+
impl FileConfigurations for Config {
29+
fn new() -> Self {
2630
let plugins_path = home_dir()
2731
.expect("Couldn't find your home directory")
2832
.join("Documents")

src/core/installer.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,6 @@ impl Installer {
107107
.join(&folder_name)
108108
.exists()
109109
{
110-
// TODO: Check if the options are really doing what I want
111110
fs::create_dir_all(
112111
Path::new(&CONFIGURATION.lock().unwrap().plugins_dir).join(&folder_name),
113112
)

src/core/mod.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
1+
pub mod api_connector;
12
pub mod config;
23
pub mod installer;
34
pub mod plugin;
45
pub mod plugin_parser;
56
pub mod synchronizer;
67

8+
pub use api_connector::APIConnector;
79
pub use config::Config;
810
pub use installer::Installer;
9-
pub use plugin::{Base, Plugin, Installed};
11+
pub use plugin::{Base, Installed, Plugin};
1012
pub use plugin_parser::PluginParser;
1113
pub use synchronizer::Synchronizer;

src/core/synchronizer.rs

Lines changed: 5 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,9 @@
1+
use super::api_connector::APIOperations;
12
use super::plugin_parser::Information;
23
use crate::core::config::CONFIGURATION;
3-
use crate::core::{
4-
Base as BasePlugin, Installed as InstalledPlugin, Plugin as DetailsPlugin, PluginParser,
5-
};
4+
use crate::core::{APIConnector, Installed as InstalledPlugin, PluginParser};
65
use globset::Glob;
76
use rusqlite::{params, Connection, Statement};
8-
use serde::{Deserialize, Serialize};
97
use std::{collections::HashMap, error::Error, fs::read_dir, path::Path};
108

119
pub struct Synchronizer {}
@@ -25,14 +23,15 @@ impl Synchronizer {
2523
db_plugins: &HashMap<String, InstalledPlugin>,
2624
) {
2725
for (key, element) in local_plugins {
28-
let retrieved_plugin = Self::fetch_plugin_details(&element.name);
26+
let retrieved_plugin = APIConnector::fetch_details(&element.name);
2927
if db_plugins.contains_key(key) {
3028
let local_plugin = db_plugins.get(key).unwrap();
3129
if local_plugin.latest_version != retrieved_plugin.base_plugin.latest_version {
3230
Self::update_plugin(
3331
&local_plugin.title,
3432
&retrieved_plugin.base_plugin.latest_version,
35-
);
33+
)
34+
.unwrap();
3635
}
3736
} else {
3837
Self::insert_plugin(&InstalledPlugin::new(
@@ -78,56 +77,6 @@ impl Synchronizer {
7877
Ok(local_plugins)
7978
}
8079

81-
pub async fn fetch_plugins(
82-
) -> Result<HashMap<String, BasePlugin>, crate::core::synchronizer::APIError> {
83-
match reqwest::get("https://young-hamlet-23901.herokuapp.com/plugins").await {
84-
Ok(response) => match response.json::<HashMap<String, BasePlugin>>().await {
85-
Ok(plugins) => Ok(plugins),
86-
Err(_) => Err(APIError::FetchError),
87-
},
88-
Err(_) => Err(APIError::FetchError),
89-
}
90-
}
91-
92-
pub fn fetch_plugin_details(title: &str) -> DetailsPlugin {
93-
let response = reqwest::blocking::get(format!(
94-
"https://young-hamlet-23901.herokuapp.com/plugins/{}",
95-
title.to_lowercase()
96-
))
97-
.expect("Failed to connect with API")
98-
.json::<JSONResponse>()
99-
.expect("Failed to parse response");
100-
101-
DetailsPlugin::new(
102-
response.plugin_id,
103-
&response.title,
104-
"",
105-
&response.category,
106-
&response.current_version,
107-
&response.latest_version,
108-
&response.folders,
109-
&response.files,
110-
)
111-
}
112-
113-
// Used to synchronize the local database with the remote plugin server
114-
pub async fn update_local_plugins() -> Result<(), ()> {
115-
let fetched_plugins = Self::fetch_plugins().await;
116-
let conn = Connection::open(&CONFIGURATION.lock().unwrap().db_file).unwrap();
117-
118-
if fetched_plugins.is_ok() {
119-
for (_, plugin) in fetched_plugins.unwrap() {
120-
let installed_plugin = Synchronizer::get_plugin(&plugin.title);
121-
if !installed_plugin.is_empty()
122-
&& installed_plugin[0].latest_version != plugin.latest_version
123-
{
124-
conn.execute("UPDATE plugin SET current_version = ?1, latest_version = ?2 WHERE plugin_id = ?3", params![installed_plugin[0].description, plugin.latest_version, plugin.plugin_id]).unwrap();
125-
}
126-
}
127-
}
128-
Ok(())
129-
}
130-
13180
// Creates the local database if it doesn't exist.
13281
pub fn create_plugins_db() {
13382
let conn = Connection::open(&CONFIGURATION.lock().unwrap().db_file).unwrap();
@@ -228,32 +177,4 @@ impl Synchronizer {
228177
}
229178
plugins
230179
}
231-
232-
pub fn get_plugin(name: &str) -> Vec<InstalledPlugin> {
233-
let conn = Connection::open(&CONFIGURATION.lock().unwrap().db_file).unwrap();
234-
let mut stmt = conn
235-
.prepare("SELECT plugin_id, title, description, category, current_version, latest_version, folder_name FROM plugin WHERE LOWER(title) = ?1")
236-
.unwrap();
237-
238-
Self::execute_stmt(&mut stmt, &name.to_lowercase())
239-
}
240-
}
241-
242-
#[derive(Default, Serialize, Deserialize, Debug, Clone, Eq, PartialEq, Hash, PartialOrd, Ord)]
243-
struct JSONResponse {
244-
pub plugin_id: i32,
245-
pub title: String,
246-
#[serde(default)]
247-
pub description: String,
248-
pub category: String,
249-
#[serde(default)]
250-
pub current_version: String,
251-
pub latest_version: String,
252-
pub folders: String,
253-
pub files: Vec<String>,
254-
}
255-
256-
#[derive(Debug, Clone)]
257-
pub enum APIError {
258-
FetchError,
259180
}

src/gui/views/catalog.rs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1-
use crate::core::{synchronizer::APIError, Base as BasePlugin, Installer, Synchronizer};
1+
use crate::core::api_connector::APIOperations;
2+
use crate::core::{
3+
api_connector::APIError, APIConnector, Base as BasePlugin, Installer, Synchronizer,
4+
};
25
use crate::gui::style;
36
use iced::{
47
button, scrollable, text_input, Align, Button, Column, Command, Container, Element,
@@ -65,7 +68,7 @@ impl Catalog {
6568
Command::none()
6669
}
6770
Message::LoadPlugins => {
68-
Command::perform(Synchronizer::fetch_plugins(), Message::LoadedPlugins)
71+
Command::perform(APIConnector::fetch_plugins(), Message::LoadedPlugins)
6972
}
7073
Message::LoadedPlugins(fetched_plugins) => {
7174
if fetched_plugins.is_ok() {
@@ -111,7 +114,7 @@ impl Catalog {
111114
},
112115
Catalog::NoInternet(state) => match message {
113116
Message::RetryPressed => {
114-
Command::perform(Synchronizer::fetch_plugins(), Message::LoadedPlugins)
117+
Command::perform(APIConnector::fetch_plugins(), Message::LoadedPlugins)
115118
}
116119
Message::LoadedPlugins(fetched_plugins) => {
117120
if fetched_plugins.is_ok() {
@@ -303,7 +306,7 @@ impl PluginRow {
303306
pub fn update(&mut self, message: RowMessage) {
304307
match message {
305308
RowMessage::InstallPressed(plugin) => {
306-
let fetched_plugin = Synchronizer::fetch_plugin_details(&plugin.title);
309+
let fetched_plugin = APIConnector::fetch_details(&plugin.title);
307310
if Installer::download(&fetched_plugin).is_ok() {
308311
self.status = "Downloaded".to_string();
309312
if Installer::extract(&fetched_plugin).is_ok() {

src/gui/views/mod.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -257,7 +257,6 @@ impl Lembas {
257257

258258
pub async fn init_application() -> State {
259259
Synchronizer::create_plugins_db();
260-
//Synchronizer::update_local_plugins();
261260
Synchronizer::synchronize_application();
262261

263262
State::default()

0 commit comments

Comments
 (0)