Implement Nexus integration #54

Merged
lucas merged 15 commits from feat/nexus into master 2023-03-15 21:43:37 +01:00
4 changed files with 70 additions and 15 deletions
Showing only changes of commit 6a52f3efc2 - Show all commits

1
Cargo.lock generated
View file

@ -775,6 +775,7 @@ dependencies = [
"tracing", "tracing",
"tracing-error", "tracing-error",
"tracing-subscriber", "tracing-subscriber",
"usvg",
"zip", "zip",
] ]

View file

@ -29,3 +29,4 @@ time = { version = "0.3.20", features = ["serde", "serde-well-known", "local-off
strip-ansi-escapes = "0.1.1" strip-ansi-escapes = "0.1.1"
lazy_static = "1.4.0" lazy_static = "1.4.0"
colors-transform = "0.2.11" colors-transform = "0.2.11"
usvg = "0.25.0"

View file

@ -1 +1,41 @@
use druid::Color;
use usvg::{
Error, Fill, LineCap, LineJoin, NodeKind, NonZeroPositiveF64, Options, Paint, Stroke, Tree,
};
pub static ALERT_CIRCLE: &str = include_str!("../../../assets/icons/icons/alert-circle.svg"); pub static ALERT_CIRCLE: &str = include_str!("../../../assets/icons/icons/alert-circle.svg");
pub static ALERT_TRIANGLE: &str = include_str!("../../../assets/icons/icons/alert-triangle.svg");
pub fn parse_svg(svg: &str) -> Result<Tree, Error> {
let opt = Options::default();
Tree::from_str(svg, &opt.to_ref())
}
pub fn recolor_icon(tree: Tree, stroke: bool, color: Color) -> Tree {
let (red, green, blue, _) = color.as_rgba8();
let mut children = tree.root.children();
// The first element is always some kind of background placeholder
children.next();
for node in children {
if let NodeKind::Path(ref mut path) = *node.borrow_mut() {
if stroke {
path.stroke = Some(Stroke {
paint: Paint::Color(usvg::Color { red, green, blue }),
width: NonZeroPositiveF64::new(2.).expect("the value is not zero"),
linecap: LineCap::Round,
linejoin: LineJoin::Round,
..Default::default()
});
} else {
path.fill = Some(Fill {
paint: Paint::Color(usvg::Color { red, green, blue }),
..Default::default()
});
}
}
}
tree
}

View file

@ -2,15 +2,16 @@ use std::str::FromStr;
use std::sync::Arc; use std::sync::Arc;
use druid::im::Vector; use druid::im::Vector;
use druid::lens;
use druid::widget::{ use druid::widget::{
Checkbox, CrossAxisAlignment, Either, Flex, Image, Label, LineBreaking, List, Checkbox, CrossAxisAlignment, Either, Flex, Image, Label, LineBreaking, List,
MainAxisAlignment, Maybe, Scroll, SizedBox, Split, Svg, SvgData, TextBox, ViewSwitcher, MainAxisAlignment, Maybe, Scroll, SizedBox, Split, Svg, SvgData, TextBox, ViewSwitcher,
}; };
use druid::{lens, Data, ImageBuf, LifeCycleCtx};
use druid::{ use druid::{
Color, FileDialogOptions, FileSpec, FontDescriptor, FontFamily, LensExt, SingleUse, Widget, Color, FileDialogOptions, FileSpec, FontDescriptor, FontFamily, LensExt, SingleUse, Widget,
WidgetExt, WindowDesc, WindowId, WidgetExt, WindowDesc, WindowId,
}; };
use druid::{Data, ImageBuf, LifeCycleCtx};
use lazy_static::lazy_static; use lazy_static::lazy_static;
use crate::state::{ use crate::state::{
@ -18,7 +19,7 @@ use crate::state::{
ACTION_SELECT_MOD, ACTION_SET_WINDOW_HANDLE, ACTION_START_CHECK_UPDATE, ACTION_SELECT_MOD, ACTION_SET_WINDOW_HANDLE, ACTION_START_CHECK_UPDATE,
ACTION_START_DELETE_SELECTED_MOD, ACTION_START_DEPLOY, ACTION_START_RESET_DEPLOYMENT, ACTION_START_DELETE_SELECTED_MOD, ACTION_START_DEPLOY, ACTION_START_RESET_DEPLOYMENT,
}; };
use crate::ui::theme::{self, ColorExt}; use crate::ui::theme::{self, ColorExt, COLOR_YELLOW_LIGHT};
use crate::ui::widget::border::Border; use crate::ui::widget::border::Border;
use crate::ui::widget::button::Button; use crate::ui::widget::button::Button;
use crate::ui::widget::controller::{ use crate::ui::widget::controller::{
@ -126,19 +127,31 @@ fn build_mod_list() -> impl Widget<State> {
let name = let name =
Label::raw().lens(lens!((usize, Arc<ModInfo>, bool), 1).then(ModInfo::name.in_arc())); Label::raw().lens(lens!((usize, Arc<ModInfo>, bool), 1).then(ModInfo::name.in_arc()));
let version = Label::dynamic(|info: &Arc<ModInfo>, _| { let version = {
let has_update = info let icon = {
.nexus let tree =
theme::icons::parse_svg(theme::icons::ALERT_TRIANGLE).expect("invalid SVG");
let tree = theme::icons::recolor_icon(tree, true, COLOR_YELLOW_LIGHT);
Svg::new(Arc::new(tree)).fix_height(druid::theme::TEXT_SIZE_NORMAL)
};
Either::new(
|info, _| {
info.nexus
.as_ref() .as_ref()
.map(|n| info.version != n.version) .map(|n| info.version != n.version)
.unwrap_or(false); .unwrap_or(false)
if has_update { },
format!("! {}", info.version) Flex::row()
} else { .with_child(icon)
info.version.to_string() .with_spacer(3.)
} .with_child(Label::raw().lens(ModInfo::version.in_arc())),
}) Label::raw().lens(ModInfo::version.in_arc()),
.lens(lens!((usize, Arc<ModInfo>, bool), 1)); )
.lens(lens!((usize, Arc<ModInfo>, bool), 1))
};
let fields = Flex::row() let fields = Flex::row()
.must_fill_main_axis(true) .must_fill_main_axis(true)