Skip to content

Commit

Permalink
Merge pull request #50 from atlanticaccent:atlanticaccent/issue45
Browse files Browse the repository at this point in the history
Fixes #45
Adds clickable forum links to the mod description box. Clicking them should open the link in the system default browser.
  • Loading branch information
Iain Laird committed Jun 13, 2021
2 parents 6c96581 + 5f1cfe1 commit c6f7400
Show file tree
Hide file tree
Showing 5 changed files with 158 additions and 37 deletions.
28 changes: 28 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Expand Up @@ -22,6 +22,7 @@ serde-aux = "2.1.1"
handwritten-json = { git = "https://github.com/atlanticaccent/rust-handwritten-json.git" }
zip = "0.5.9"
unrar = "0.4.4"
opener = "0.5"

[target.'cfg(unix)'.dependencies]
compress-tools = "0.11.1"
10 changes: 3 additions & 7 deletions src/gui/install.rs
Expand Up @@ -9,7 +9,7 @@ use std::{
use tokio::fs::{remove_dir_all, rename};

use crate::archive_handler;
use crate::gui::mod_list::{ModEntry, ModVersionMeta, ModVersion};
use crate::gui::mod_list::{ModEntry, ModVersionMeta};

#[derive(Debug, Clone)]
pub enum InstallError {
Expand Down Expand Up @@ -141,7 +141,7 @@ fn copy_dir_recursive(to: &PathBuf, from: &PathBuf) -> io::Result<()> {
Ok(())
}

pub async fn get_master_version(local: ModVersionMeta) -> (String, Result<Option<ModVersion>, String>) {
pub async fn get_master_version(local: ModVersionMeta) -> (String, Result<Option<ModVersionMeta>, String>) {
let res = send_request(local.remote_url.clone()).await;

match res {
Expand All @@ -156,11 +156,7 @@ pub async fn get_master_version(local: ModVersionMeta) -> (String, Result<Option
if remote.version > local.version {
(
local.id,
Ok(Some(ModVersion {
major: remote.version.major - local.version.major,
minor: remote.version.minor - remote.version.minor,
patch: remote.version.patch
}))
Ok(Some(remote))
)
} else {
(
Expand Down
131 changes: 101 additions & 30 deletions src/gui/mod_list.rs
Expand Up @@ -15,6 +15,7 @@ use json5;
use handwritten_json;
use if_chain::if_chain;
use native_dialog::{FileDialog, MessageDialog, MessageType};
use opener;

use serde_aux::prelude::*;

Expand Down Expand Up @@ -46,7 +47,7 @@ pub enum ModListMessage {
InstallPressed(InstallOptions),
EnabledModsSaved(Result<(), SaveError>),
ModInstalled(Result<String, install::InstallError>),
MasterVersionReceived((String, Result<Option<ModVersion>, String>)),
MasterVersionReceived((String, Result<Option<ModVersionMeta>, String>)),
SetSorting(ModEntryComp)
}

Expand Down Expand Up @@ -242,34 +243,42 @@ impl ModList {
}
},
ModListMessage::MasterVersionReceived((id, res)) => {
if let Some(entry) = self.mods.get_mut(&id) {
match res {
Ok(maybe_version) => {
match maybe_version {
Some(version) => {
// debug_print!("{}. ", entry.id);
if version.major > 0 {
// debug_println!("New major version available.");
entry.update_status = Some(UpdateStatus::Major(version))
} else if version.minor > 0 {
// debug_println!("New minor version available.");
entry.update_status = Some(UpdateStatus::Minor(version))
} else {
// debug_println!("New patch available.");
entry.update_status = Some(UpdateStatus::Patch(version.patch))
};
// debug_println!("{:?}", entry.version_checker.as_ref().unwrap().version);
},
None => {
// debug_println!("No update available for {}.", entry.id);
entry.update_status = Some(UpdateStatus::UpToDate)
if_chain! {
if let Some(entry) = self.mods.get_mut(&id);
if let Some(ModVersionMeta { version: local_version, .. }) = &entry.version_checker;
then {
match res {
Ok(maybe_version) => {
match maybe_version {
Some(remote_version_meta) => {
let version = remote_version_meta.version.clone();
// debug_print!("{}. ", entry.id);
if version.major - local_version.major > 0 {
// debug_println!("New major version available.");
entry.update_status = Some(UpdateStatus::Major(version))
} else if version.minor - local_version.minor > 0 {
// debug_println!("New minor version available.");
entry.update_status = Some(UpdateStatus::Minor(version))
} else {
// debug_println!("New patch available.");
entry.update_status = Some(UpdateStatus::Patch(version.patch))
};
// debug_println!("{:?}", entry.version_checker.as_ref().unwrap().version);
entry.remote_version = Some(remote_version_meta);
},
None => {
// debug_println!("No update available for {}.", entry.id);
entry.update_status = Some(UpdateStatus::UpToDate)
}
}
}
},
Err(err) => {
// debug_println!("Could not get remote update data for {}.\nError: {}", id, err);
entry.update_status = Some(UpdateStatus::Error)
},
Err(err) => {
// debug_println!("Could not get remote update data for {}.\nError: {}", id, err);
entry.update_status = Some(UpdateStatus::Error)
}
}
} else {
dbg!("Have a remote version file, but either local entry or local version file are missing, which is odd to say the least.");
}
};

Expand Down Expand Up @@ -639,6 +648,8 @@ pub struct ModEntry {
#[serde(skip)]
version_checker: Option<ModVersionMeta>,
#[serde(skip)]
remote_version: Option<ModVersionMeta>,
#[serde(skip)]
update_status: Option<UpdateStatus>,
#[serde(skip)]
path: PathBuf,
Expand Down Expand Up @@ -856,25 +867,35 @@ impl Display for ModVersion {

#[derive(Debug, Clone)]
pub struct ModDescription {
mod_entry: Option<ModEntry>
mod_entry: Option<ModEntry>,
fractal_link: button::State,
nexus_link: button::State
}

#[derive(Debug, Clone)]
pub enum ModDescriptionMessage {
ModChanged(ModEntry)
ModChanged(ModEntry),
LinkClicked(String)
}

impl ModDescription {
pub fn new() -> Self {
ModDescription {
mod_entry: None
mod_entry: None,
fractal_link: button::State::new(),
nexus_link: button::State::new()
}
}

pub fn update(&mut self, message: ModDescriptionMessage) -> Command<ModDescriptionMessage> {
match message {
ModDescriptionMessage::ModChanged(entry) => {
self.mod_entry = Some(entry)
},
ModDescriptionMessage::LinkClicked(url) => {
if let Err(_) = opener::open(url) {
ModList::make_alert(format!("Failed to open update link. This could be due to a number of issues unfortunately.\nMake sure you have a default browser set for your operating system, otherwise there's not much that can be done."))
}
}
}

Expand Down Expand Up @@ -914,6 +935,53 @@ impl ModDescription {
.push(Text::new(format!("{}", entry.version)).width(Length::FillPortion(10)))
.into()
);

if let (Some(version), _) | (None, Some(version)) = (&entry.remote_version, &entry.version_checker) {
dbg!(version);
if version.fractal_id.len() > 0 {
text.push(Row::new()
.push(Text::new(format!("Forum post:")).width(Length::FillPortion(1)))
.push(
Row::new()
.push(
Button::new(
&mut self.fractal_link,
Text::new(format!("{}{}", ModDescription::FRACTAL_URL, version.fractal_id))
)
.padding(0)
.style(style::hyperlink_block::Button)
.width(Length::Shrink)
.on_press(ModDescriptionMessage::LinkClicked(format!("{}{}", ModDescription::FRACTAL_URL, version.fractal_id)))
)
.push(Space::with_width(Length::Fill))
.width(Length::FillPortion(10))
)
.into()
);
}
if version.nexus_id.len() > 0 {
text.push(Row::new()
.push(Text::new(format!("Nexus post:")).width(Length::FillPortion(1)))
.push(
Row::new()
.push(
Button::new(
&mut self.nexus_link,
Text::new(format!("{}{}", ModDescription::NEXUS_URL, version.nexus_id))
)
.padding(0)
.style(style::hyperlink_block::Button)
.width(Length::Shrink)
.on_press(ModDescriptionMessage::LinkClicked(format!("{}{}", ModDescription::NEXUS_URL, version.nexus_id)))
)
.push(Space::with_width(Length::Fill))
.width(Length::FillPortion(10))
)
.into()
);
}
}

text.push(Text::new(format!("Description:")).into());
text.push(Text::new(entry.description.clone()).into());
} else {
Expand All @@ -924,6 +992,9 @@ impl ModDescription {
.padding(5)
.into()
}

const FRACTAL_URL: &'static str = "https://fractalsoftworks.com/forum/index.php?topic=";
const NEXUS_URL: &'static str = "https://www.nexusmods.com/starsector/mods/";
}

#[derive(Serialize, Deserialize)]
Expand Down
25 changes: 25 additions & 0 deletions src/style.rs
Expand Up @@ -225,3 +225,28 @@ pub mod update {
}
}
}

pub mod hyperlink_block {
use iced::{button, Color, Vector};

pub struct Button;

impl button::StyleSheet for Button {
fn active(&self) -> button::Style {
button::Style {
background: None,
shadow_offset: Vector::new(0.0, 0.0),
text_color: Color::from_rgb8(0x06, 0x45, 0xAD),
..button::Style::default()
}
}

fn hovered(&self) -> button::Style {
button::Style {
background: Color::from_rgb8(0x06, 0x45, 0xAD).into(),
text_color: Color::WHITE,
..self.active()
}
}
}
}

0 comments on commit c6f7400

Please sign in to comment.