diff --git a/crates/settings/src/settings_ui.rs b/crates/settings/src/settings_ui.rs index 40ac3d9db9..3a77627d59 100644 --- a/crates/settings/src/settings_ui.rs +++ b/crates/settings/src/settings_ui.rs @@ -7,9 +7,16 @@ use crate::SettingsStore; pub trait SettingsUi { fn settings_ui_item() -> SettingsUiItem { + // todo(settings_ui): remove this default impl, only entry should have a default impl + // because it's expected that the macro or custom impl use the item and the known paths to create the entry SettingsUiItem::None } - fn settings_ui_entry() -> SettingsUiEntry; + + fn settings_ui_entry() -> SettingsUiEntry { + SettingsUiEntry { + item: SettingsUiEntryVariant::None, + } + } } pub struct SettingsUiEntry { @@ -106,11 +113,11 @@ impl SettingsUi for bool { fn settings_ui_item() -> SettingsUiItem { SettingsUiItem::Single(SettingsUiItemSingle::SwitchField) } +} - fn settings_ui_entry() -> SettingsUiEntry { - SettingsUiEntry { - item: SettingsUiEntryVariant::None, - } +impl SettingsUi for Option { + fn settings_ui_item() -> SettingsUiItem { + SettingsUiItem::Single(SettingsUiItemSingle::SwitchField) } } @@ -118,10 +125,4 @@ impl SettingsUi for u64 { fn settings_ui_item() -> SettingsUiItem { SettingsUiItem::Single(SettingsUiItemSingle::NumericStepper) } - - fn settings_ui_entry() -> SettingsUiEntry { - SettingsUiEntry { - item: SettingsUiEntryVariant::None, - } - } } diff --git a/crates/settings_ui_macros/src/settings_ui_macros.rs b/crates/settings_ui_macros/src/settings_ui_macros.rs index 5250febe98..3840bc38da 100644 --- a/crates/settings_ui_macros/src/settings_ui_macros.rs +++ b/crates/settings_ui_macros/src/settings_ui_macros.rs @@ -88,7 +88,34 @@ pub fn derive_settings_ui(input: proc_macro::TokenStream) -> proc_macro::TokenSt proc_macro::TokenStream::from(expanded) } +fn extract_type_from_option(ty: TokenStream) -> TokenStream { + match option_inner_type(ty.clone()) { + Some(inner_type) => inner_type, + None => ty, + } +} + +fn option_inner_type(ty: TokenStream) -> Option { + let ty = syn::parse2::(ty).ok()?; + let syn::Type::Path(path) = ty else { + return None; + }; + let segment = path.path.segments.last()?; + if segment.ident != "Option" { + return None; + } + let syn::PathArguments::AngleBracketed(args) = &segment.arguments else { + return None; + }; + let arg = args.args.first()?; + let syn::GenericArgument::Type(ty) = arg else { + return None; + }; + return Some(ty.to_token_stream()); +} + fn map_ui_item_to_render(path: &str, ty: TokenStream) -> TokenStream { + let ty = extract_type_from_option(ty); quote! { settings::SettingsUiEntry { item: match #ty::settings_ui_item() { diff --git a/crates/title_bar/src/title_bar_settings.rs b/crates/title_bar/src/title_bar_settings.rs index 3d34daefae..0dc301f7ee 100644 --- a/crates/title_bar/src/title_bar_settings.rs +++ b/crates/title_bar/src/title_bar_settings.rs @@ -15,7 +15,7 @@ pub struct TitleBarSettings { } #[derive(Copy, Clone, Default, Serialize, Deserialize, JsonSchema, Debug, SettingsUi)] -// #[settings_ui(group = "Title Bar", path = "title_bar")] +#[settings_ui(group = "Title Bar", path = "title_bar")] pub struct TitleBarSettingsContent { /// Whether to show the branch icon beside branch switcher in the title bar. ///