mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-25 19:38:12 +08:00
Refactor the TypeScript data flow for full type safety and auto-generation of Rust types (#3865)
* Migrate Specta to Tsify to auto-generate messages.ts, working except colors and widgets * Adopt the generated FillColor/Color/GradientStops * Fix widget typing * Separate WidgetGroup enum variants into wrapper structs * Small rename * Simplify widgets further * Clean up message type references * Switch type imports to the auto-generated file * Remove lowercase serde rename * Fix FillChoice deserialization * Fix small regression from #3837 * Improve type safety * Make WidgetSpan type-safe * More cleanup and type safety * More type safety * More type safety * Get the rest to type-check without errors; improve widget builder macro to have optional icons; improve Svelte 5 configs * Cargo fmt * Fix imports * Update outdated readme info * Fix lint command rename references * Fix typos * One more typos fix * Remove unnecessary dep: prefix from the edited Cargo.toml files * Remove excess parts from Cargo.toml * Fix compiling on desktop * Revert "Remove excess parts from Cargo.toml" This reverts commit 6b711117b3a5d5d8a3ee20f36a43bc74930b7c82. * Update dev docs with simpler, more accurate instructions
This commit is contained in:
@@ -15,7 +15,7 @@ impl DialogLayoutHolder for AboutGraphiteDialog {
|
||||
fn layout_buttons(&self) -> Layout {
|
||||
let widgets = vec![TextButton::new("OK").emphasized(true).on_update(|_| FrontendMessage::DialogClose.into()).widget_instance()];
|
||||
|
||||
Layout(vec![LayoutGroup::Row { widgets }])
|
||||
Layout(vec![LayoutGroup::row(widgets)])
|
||||
}
|
||||
|
||||
fn layout_column_2(&self) -> Layout {
|
||||
@@ -29,7 +29,7 @@ impl DialogLayoutHolder for AboutGraphiteDialog {
|
||||
.into_iter()
|
||||
.map(|(icon, label, url)| {
|
||||
TextButton::new(label)
|
||||
.icon(Some(icon.into()))
|
||||
.icon(icon)
|
||||
.flush(true)
|
||||
.on_update(|_| FrontendMessage::TriggerVisitLink { url: url.into() }.into())
|
||||
.widget_instance()
|
||||
@@ -40,7 +40,7 @@ impl DialogLayoutHolder for AboutGraphiteDialog {
|
||||
let localized_commit_year = self.localized_commit_year.clone();
|
||||
widgets.push(
|
||||
TextButton::new("Licenses")
|
||||
.icon(Some("License".into()))
|
||||
.icon("License")
|
||||
.flush(true)
|
||||
.on_update(move |_| {
|
||||
DialogMessage::RequestLicensesDialogWithLocalizedCommitDate {
|
||||
@@ -51,22 +51,16 @@ impl DialogLayoutHolder for AboutGraphiteDialog {
|
||||
.widget_instance(),
|
||||
);
|
||||
|
||||
Layout(vec![LayoutGroup::Column { widgets }])
|
||||
Layout(vec![LayoutGroup::column(widgets)])
|
||||
}
|
||||
}
|
||||
|
||||
impl LayoutHolder for AboutGraphiteDialog {
|
||||
fn layout(&self) -> Layout {
|
||||
Layout(vec![
|
||||
LayoutGroup::Row {
|
||||
widgets: vec![TextLabel::new("About this release").bold(true).widget_instance()],
|
||||
},
|
||||
LayoutGroup::Row {
|
||||
widgets: vec![TextLabel::new(commit_info_localized(&self.localized_commit_date)).multiline(true).widget_instance()],
|
||||
},
|
||||
LayoutGroup::Row {
|
||||
widgets: vec![TextLabel::new(format!("Copyright © {} Graphite contributors", self.localized_commit_year)).widget_instance()],
|
||||
},
|
||||
LayoutGroup::row(vec![TextLabel::new("About this release").bold(true).widget_instance()]),
|
||||
LayoutGroup::row(vec![TextLabel::new(commit_info_localized(&self.localized_commit_date)).multiline(true).widget_instance()]),
|
||||
LayoutGroup::row(vec![TextLabel::new(format!("Copyright © {} Graphite contributors", self.localized_commit_year)).widget_instance()]),
|
||||
])
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ impl DialogLayoutHolder for CloseAllDocumentsDialog {
|
||||
TextButton::new("Cancel").on_update(|_| FrontendMessage::DialogClose.into()).widget_instance(),
|
||||
];
|
||||
|
||||
Layout(vec![LayoutGroup::Row { widgets }])
|
||||
Layout(vec![LayoutGroup::row(widgets)])
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,12 +33,8 @@ impl LayoutHolder for CloseAllDocumentsDialog {
|
||||
let unsaved_list = "• ".to_string() + &self.unsaved_document_names.join("\n• ");
|
||||
|
||||
Layout(vec![
|
||||
LayoutGroup::Row {
|
||||
widgets: vec![TextLabel::new("Save documents before closing them?").bold(true).multiline(true).widget_instance()],
|
||||
},
|
||||
LayoutGroup::Row {
|
||||
widgets: vec![TextLabel::new(format!("Documents with unsaved changes:\n{unsaved_list}")).multiline(true).widget_instance()],
|
||||
},
|
||||
LayoutGroup::row(vec![TextLabel::new("Save documents before closing them?").bold(true).multiline(true).widget_instance()]),
|
||||
LayoutGroup::row(vec![TextLabel::new(format!("Documents with unsaved changes:\n{unsaved_list}")).multiline(true).widget_instance()]),
|
||||
])
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ impl DialogLayoutHolder for CloseDocumentDialog {
|
||||
TextButton::new("Cancel").on_update(|_| FrontendMessage::DialogClose.into()).widget_instance(),
|
||||
];
|
||||
|
||||
Layout(vec![LayoutGroup::Row { widgets }])
|
||||
Layout(vec![LayoutGroup::row(widgets)])
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,12 +52,8 @@ impl LayoutHolder for CloseDocumentDialog {
|
||||
let break_lines = if self.document_name.len() > max_one_line_length { '\n' } else { ' ' };
|
||||
|
||||
Layout(vec![
|
||||
LayoutGroup::Row {
|
||||
widgets: vec![TextLabel::new("Save document before closing it?").bold(true).widget_instance()],
|
||||
},
|
||||
LayoutGroup::Row {
|
||||
widgets: vec![TextLabel::new(format!("\"{name}{ellipsis}\"{break_lines}has unsaved changes")).multiline(true).widget_instance()],
|
||||
},
|
||||
LayoutGroup::row(vec![TextLabel::new("Save document before closing it?").bold(true).widget_instance()]),
|
||||
LayoutGroup::row(vec![TextLabel::new(format!("\"{name}{ellipsis}\"{break_lines}has unsaved changes")).multiline(true).widget_instance()]),
|
||||
])
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ impl DialogLayoutHolder for ConfirmRestartDialog {
|
||||
TextButton::new("Later").on_update(|_| FrontendMessage::DialogClose.into()).widget_instance(),
|
||||
];
|
||||
|
||||
Layout(vec![LayoutGroup::Row { widgets }])
|
||||
Layout(vec![LayoutGroup::row(widgets)])
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,27 +33,23 @@ impl LayoutHolder for ConfirmRestartDialog {
|
||||
let changed_settings = "• ".to_string() + &self.changed_settings.join("\n• ");
|
||||
|
||||
Layout(vec![
|
||||
LayoutGroup::Row {
|
||||
widgets: vec![TextLabel::new("Restart to apply changes?").bold(true).multiline(true).widget_instance()],
|
||||
},
|
||||
LayoutGroup::Row {
|
||||
widgets: vec![
|
||||
TextLabel::new(
|
||||
format!(
|
||||
"
|
||||
LayoutGroup::row(vec![TextLabel::new("Restart to apply changes?").bold(true).multiline(true).widget_instance()]),
|
||||
LayoutGroup::row(vec![
|
||||
TextLabel::new(
|
||||
format!(
|
||||
"
|
||||
Settings that only take effect on next launch:\n\
|
||||
{changed_settings}\n\
|
||||
\n\
|
||||
This only takes a few seconds. Open documents,\n\
|
||||
even unsaved ones, will be automatically restored.
|
||||
"
|
||||
)
|
||||
.trim(),
|
||||
)
|
||||
.multiline(true)
|
||||
.widget_instance(),
|
||||
],
|
||||
},
|
||||
.trim(),
|
||||
)
|
||||
.multiline(true)
|
||||
.widget_instance(),
|
||||
]),
|
||||
])
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ impl DialogLayoutHolder for DemoArtworkDialog {
|
||||
fn layout_buttons(&self) -> Layout {
|
||||
let widgets = vec![TextButton::new("Close").emphasized(true).on_update(|_| FrontendMessage::DialogClose.into()).widget_instance()];
|
||||
|
||||
Layout(vec![LayoutGroup::Row { widgets }])
|
||||
Layout(vec![LayoutGroup::row(widgets)])
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ impl LayoutHolder for DemoArtworkDialog {
|
||||
|
||||
let images = chunk
|
||||
.iter()
|
||||
.map(|(name, thumbnail, filename)| ImageButton::new(*thumbnail).width(Some("256px".into())).on_update(|_| make_dialog(name, filename)).widget_instance())
|
||||
.map(|(name, thumbnail, filename)| ImageButton::new(*thumbnail).width("256px").on_update(|_| make_dialog(name, filename)).widget_instance())
|
||||
.collect();
|
||||
|
||||
let buttons = chunk
|
||||
@@ -54,7 +54,7 @@ impl LayoutHolder for DemoArtworkDialog {
|
||||
.map(|(name, _, filename)| TextButton::new(*name).min_width(256).flush(true).on_update(|_| make_dialog(name, filename)).widget_instance())
|
||||
.collect();
|
||||
|
||||
vec![LayoutGroup::Row { widgets: images }, LayoutGroup::Row { widgets: buttons }, LayoutGroup::Row { widgets: vec![] }]
|
||||
vec![LayoutGroup::row(images), LayoutGroup::row(buttons), LayoutGroup::row(vec![])]
|
||||
})
|
||||
.collect();
|
||||
let _ = rows_of_images_with_buttons.pop();
|
||||
|
||||
@@ -14,19 +14,15 @@ impl DialogLayoutHolder for ErrorDialog {
|
||||
fn layout_buttons(&self) -> Layout {
|
||||
let widgets = vec![TextButton::new("OK").emphasized(true).on_update(|_| FrontendMessage::DialogClose.into()).widget_instance()];
|
||||
|
||||
Layout(vec![LayoutGroup::Row { widgets }])
|
||||
Layout(vec![LayoutGroup::row(widgets)])
|
||||
}
|
||||
}
|
||||
|
||||
impl LayoutHolder for ErrorDialog {
|
||||
fn layout(&self) -> Layout {
|
||||
Layout(vec![
|
||||
LayoutGroup::Row {
|
||||
widgets: vec![TextLabel::new(&self.title).bold(true).widget_instance()],
|
||||
},
|
||||
LayoutGroup::Row {
|
||||
widgets: vec![TextLabel::new(&self.description).multiline(true).widget_instance()],
|
||||
},
|
||||
LayoutGroup::row(vec![TextLabel::new(&self.title).bold(true).widget_instance()]),
|
||||
LayoutGroup::row(vec![TextLabel::new(&self.description).multiline(true).widget_instance()]),
|
||||
])
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ impl DialogLayoutHolder for LicensesDialog {
|
||||
fn layout_buttons(&self) -> Layout {
|
||||
let widgets = vec![TextButton::new("OK").emphasized(true).on_update(|_| FrontendMessage::DialogClose.into()).widget_instance()];
|
||||
|
||||
Layout(vec![LayoutGroup::Row { widgets }])
|
||||
Layout(vec![LayoutGroup::row(widgets)])
|
||||
}
|
||||
|
||||
fn layout_column_2(&self) -> Layout {
|
||||
@@ -34,10 +34,10 @@ impl DialogLayoutHolder for LicensesDialog {
|
||||
];
|
||||
let widgets = button_definitions
|
||||
.iter()
|
||||
.map(|&(icon, label, message_factory)| TextButton::new(label).icon(Some((icon).into())).flush(true).on_update(move |_| message_factory()).widget_instance())
|
||||
.map(|&(icon, label, message_factory)| TextButton::new(label).icon(icon).flush(true).on_update(move |_| message_factory()).widget_instance())
|
||||
.collect();
|
||||
|
||||
Layout(vec![LayoutGroup::Column { widgets }])
|
||||
Layout(vec![LayoutGroup::column(widgets)])
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,12 +56,8 @@ impl LayoutHolder for LicensesDialog {
|
||||
let description = description.trim();
|
||||
|
||||
Layout(vec![
|
||||
LayoutGroup::Row {
|
||||
widgets: vec![TextLabel::new("Graphite is free, open source software").bold(true).widget_instance()],
|
||||
},
|
||||
LayoutGroup::Row {
|
||||
widgets: vec![TextLabel::new(description).multiline(true).widget_instance()],
|
||||
},
|
||||
LayoutGroup::row(vec![TextLabel::new("Graphite is free, open source software").bold(true).widget_instance()]),
|
||||
LayoutGroup::row(vec![TextLabel::new(description).multiline(true).widget_instance()]),
|
||||
])
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ impl DialogLayoutHolder for LicensesThirdPartyDialog {
|
||||
fn layout_buttons(&self) -> Layout {
|
||||
let widgets = vec![TextButton::new("OK").emphasized(true).on_update(|_| FrontendMessage::DialogClose.into()).widget_instance()];
|
||||
|
||||
Layout(vec![LayoutGroup::Row { widgets }])
|
||||
Layout(vec![LayoutGroup::row(widgets)])
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,14 +31,12 @@ impl LayoutHolder for LicensesThirdPartyDialog {
|
||||
// Two characters (one before, one after) the sequence of underscore characters, plus one additional column to provide a space between the text and the scrollbar
|
||||
let non_wrapping_column_width = license_text.split('\n').map(|line| line.chars().filter(|&c| c == '_').count() as u32).max().unwrap_or(0) + 2 + 1;
|
||||
|
||||
Layout(vec![LayoutGroup::Row {
|
||||
widgets: vec![
|
||||
TextLabel::new(license_text)
|
||||
.monospace(true)
|
||||
.multiline(true)
|
||||
.min_width_characters(non_wrapping_column_width)
|
||||
.widget_instance(),
|
||||
],
|
||||
}])
|
||||
Layout(vec![LayoutGroup::row(vec![
|
||||
TextLabel::new(license_text)
|
||||
.monospace(true)
|
||||
.multiline(true)
|
||||
.min_width_characters(non_wrapping_column_width)
|
||||
.widget_instance(),
|
||||
])])
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user