1use gpui::Pixels;
2use schemars::JsonSchema;
3use serde::{Deserialize, Serialize};
4use settings::{Settings, SettingsSources};
5use workspace::dock::DockPosition;
6
7#[derive(Deserialize, Debug)]
8pub struct CollaborationPanelSettings {
9 pub button: bool,
10 pub dock: DockPosition,
11 pub default_width: Pixels,
12}
13
14#[derive(Clone, Copy, Default, Serialize, JsonSchema, Debug)]
15#[serde(rename_all = "snake_case")]
16pub enum ChatPanelButton {
17 Never,
18 Always,
19 #[default]
20 WhenInCall,
21}
22
23impl<'de> Deserialize<'de> for ChatPanelButton {
24 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
25 where
26 D: serde::Deserializer<'de>,
27 {
28 struct Visitor;
29
30 impl serde::de::Visitor<'_> for Visitor {
31 type Value = ChatPanelButton;
32
33 fn expecting(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
34 write!(
35 f,
36 r#"a boolean or one of "never", "always", "when_in_call""#
37 )
38 }
39
40 fn visit_bool<E>(self, b: bool) -> Result<Self::Value, E>
41 where
42 E: serde::de::Error,
43 {
44 match b {
45 false => Ok(ChatPanelButton::Never),
46 true => Ok(ChatPanelButton::Always),
47 }
48 }
49
50 fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
51 where
52 E: serde::de::Error,
53 {
54 match s {
55 "never" => Ok(ChatPanelButton::Never),
56 "always" => Ok(ChatPanelButton::Always),
57 "when_in_call" => Ok(ChatPanelButton::WhenInCall),
58 _ => Err(E::unknown_variant(s, &["never", "always", "when_in_call"])),
59 }
60 }
61 }
62
63 deserializer.deserialize_any(Visitor)
64 }
65}
66
67#[derive(Deserialize, Debug)]
68pub struct ChatPanelSettings {
69 pub button: ChatPanelButton,
70 pub dock: DockPosition,
71 pub default_width: Pixels,
72}
73
74#[derive(Clone, Default, Serialize, Deserialize, JsonSchema, Debug)]
75pub struct ChatPanelSettingsContent {
76 /// When to show the panel button in the status bar.
77 ///
78 /// Default: only when in a call
79 pub button: Option<ChatPanelButton>,
80 /// Where to dock the panel.
81 ///
82 /// Default: right
83 pub dock: Option<DockPosition>,
84 /// Default width of the panel in pixels.
85 ///
86 /// Default: 240
87 pub default_width: Option<f32>,
88}
89
90#[derive(Deserialize, Debug)]
91pub struct NotificationPanelSettings {
92 pub button: bool,
93 pub dock: DockPosition,
94 pub default_width: Pixels,
95}
96
97#[derive(Clone, Default, Serialize, Deserialize, JsonSchema, Debug)]
98pub struct PanelSettingsContent {
99 /// Whether to show the panel button in the status bar.
100 ///
101 /// Default: true
102 pub button: Option<bool>,
103 /// Where to dock the panel.
104 ///
105 /// Default: left
106 pub dock: Option<DockPosition>,
107 /// Default width of the panel in pixels.
108 ///
109 /// Default: 240
110 pub default_width: Option<f32>,
111}
112
113#[derive(Clone, Default, Serialize, Deserialize, JsonSchema, Debug)]
114pub struct MessageEditorSettings {
115 /// Whether to automatically replace emoji shortcodes with emoji characters.
116 /// For example: typing `:wave:` gets replaced with `👋`.
117 ///
118 /// Default: false
119 pub auto_replace_emoji_shortcode: Option<bool>,
120}
121
122impl Settings for CollaborationPanelSettings {
123 const KEY: Option<&'static str> = Some("collaboration_panel");
124
125 type FileContent = PanelSettingsContent;
126
127 fn load(
128 sources: SettingsSources<Self::FileContent>,
129 _: &mut gpui::App,
130 ) -> anyhow::Result<Self> {
131 sources.json_merge()
132 }
133}
134
135impl Settings for ChatPanelSettings {
136 const KEY: Option<&'static str> = Some("chat_panel");
137
138 type FileContent = ChatPanelSettingsContent;
139
140 fn load(
141 sources: SettingsSources<Self::FileContent>,
142 _: &mut gpui::App,
143 ) -> anyhow::Result<Self> {
144 sources.json_merge()
145 }
146}
147
148impl Settings for NotificationPanelSettings {
149 const KEY: Option<&'static str> = Some("notification_panel");
150
151 type FileContent = PanelSettingsContent;
152
153 fn load(
154 sources: SettingsSources<Self::FileContent>,
155 _: &mut gpui::App,
156 ) -> anyhow::Result<Self> {
157 sources.json_merge()
158 }
159}
160
161impl Settings for MessageEditorSettings {
162 const KEY: Option<&'static str> = Some("message_editor");
163
164 type FileContent = MessageEditorSettings;
165
166 fn load(
167 sources: SettingsSources<Self::FileContent>,
168 _: &mut gpui::App,
169 ) -> anyhow::Result<Self> {
170 sources.json_merge()
171 }
172}