diff --git a/Cargo.lock b/Cargo.lock index b02c2eb..8f125f5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5438,6 +5438,7 @@ dependencies = [ "log", "random-string", "reqwest_client", + "rust-embed", "scope-backend-discord", "scope-chat", "scope-util", diff --git a/assets/.gitkeep b/assets/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/assets/brand/scope-round-200.png b/assets/brand/scope-round-200.png new file mode 100644 index 0000000..05c4c00 Binary files /dev/null and b/assets/brand/scope-round-200.png differ diff --git a/assets/icons/a-large-small.svg b/assets/icons/a-large-small.svg new file mode 100644 index 0000000..cfba2de --- /dev/null +++ b/assets/icons/a-large-small.svg @@ -0,0 +1 @@ + diff --git a/assets/icons/arrow-down.svg b/assets/icons/arrow-down.svg new file mode 100644 index 0000000..bb5b04c --- /dev/null +++ b/assets/icons/arrow-down.svg @@ -0,0 +1 @@ + diff --git a/assets/icons/arrow-left.svg b/assets/icons/arrow-left.svg new file mode 100644 index 0000000..ed03495 --- /dev/null +++ b/assets/icons/arrow-left.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/assets/icons/arrow-right.svg b/assets/icons/arrow-right.svg new file mode 100644 index 0000000..519fffd --- /dev/null +++ b/assets/icons/arrow-right.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/assets/icons/arrow-up.svg b/assets/icons/arrow-up.svg new file mode 100644 index 0000000..ad12519 --- /dev/null +++ b/assets/icons/arrow-up.svg @@ -0,0 +1 @@ + diff --git a/assets/icons/asterisk.svg b/assets/icons/asterisk.svg new file mode 100644 index 0000000..b2d266f --- /dev/null +++ b/assets/icons/asterisk.svg @@ -0,0 +1 @@ + diff --git a/assets/icons/bell.svg b/assets/icons/bell.svg new file mode 100644 index 0000000..eecc3ef --- /dev/null +++ b/assets/icons/bell.svg @@ -0,0 +1 @@ + diff --git a/assets/icons/calendar.svg b/assets/icons/calendar.svg new file mode 100644 index 0000000..2724a48 --- /dev/null +++ b/assets/icons/calendar.svg @@ -0,0 +1 @@ + diff --git a/assets/icons/check.svg b/assets/icons/check.svg new file mode 100644 index 0000000..16bb379 --- /dev/null +++ b/assets/icons/check.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/assets/icons/chevron-down.svg b/assets/icons/chevron-down.svg new file mode 100644 index 0000000..1d316c7 --- /dev/null +++ b/assets/icons/chevron-down.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/assets/icons/chevron-left.svg b/assets/icons/chevron-left.svg new file mode 100644 index 0000000..f27e97c --- /dev/null +++ b/assets/icons/chevron-left.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/assets/icons/chevron-right.svg b/assets/icons/chevron-right.svg new file mode 100644 index 0000000..c1b76ee --- /dev/null +++ b/assets/icons/chevron-right.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/assets/icons/chevron-up.svg b/assets/icons/chevron-up.svg new file mode 100644 index 0000000..f1bb1ad --- /dev/null +++ b/assets/icons/chevron-up.svg @@ -0,0 +1 @@ + diff --git a/assets/icons/chevrons-up-down.svg b/assets/icons/chevrons-up-down.svg new file mode 100644 index 0000000..106fac0 --- /dev/null +++ b/assets/icons/chevrons-up-down.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/assets/icons/circle-check.svg b/assets/icons/circle-check.svg new file mode 100644 index 0000000..4a7e101 --- /dev/null +++ b/assets/icons/circle-check.svg @@ -0,0 +1 @@ + diff --git a/assets/icons/circle-x.svg b/assets/icons/circle-x.svg new file mode 100644 index 0000000..803c8cb --- /dev/null +++ b/assets/icons/circle-x.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/icons/close.svg b/assets/icons/close.svg new file mode 100644 index 0000000..346ec0b --- /dev/null +++ b/assets/icons/close.svg @@ -0,0 +1 @@ + diff --git a/assets/icons/copy.svg b/assets/icons/copy.svg new file mode 100644 index 0000000..f3b629c --- /dev/null +++ b/assets/icons/copy.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/icons/dash.svg b/assets/icons/dash.svg new file mode 100644 index 0000000..a1264e7 --- /dev/null +++ b/assets/icons/dash.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/icons/delete.svg b/assets/icons/delete.svg new file mode 100644 index 0000000..eb058d9 --- /dev/null +++ b/assets/icons/delete.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/icons/ellipsis-vertical.svg b/assets/icons/ellipsis-vertical.svg new file mode 100644 index 0000000..c75a25a --- /dev/null +++ b/assets/icons/ellipsis-vertical.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/icons/ellipsis.svg b/assets/icons/ellipsis.svg new file mode 100644 index 0000000..07dcab5 --- /dev/null +++ b/assets/icons/ellipsis.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/icons/eye-off.svg b/assets/icons/eye-off.svg new file mode 100644 index 0000000..abf1280 --- /dev/null +++ b/assets/icons/eye-off.svg @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/assets/icons/eye.svg b/assets/icons/eye.svg new file mode 100644 index 0000000..4b3a970 --- /dev/null +++ b/assets/icons/eye.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/assets/icons/github.svg b/assets/icons/github.svg new file mode 100644 index 0000000..92adec9 --- /dev/null +++ b/assets/icons/github.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/icons/globe.svg b/assets/icons/globe.svg new file mode 100644 index 0000000..2082a43 --- /dev/null +++ b/assets/icons/globe.svg @@ -0,0 +1 @@ + diff --git a/assets/icons/heart-off.svg b/assets/icons/heart-off.svg new file mode 100644 index 0000000..68cda02 --- /dev/null +++ b/assets/icons/heart-off.svg @@ -0,0 +1 @@ + diff --git a/assets/icons/heart.svg b/assets/icons/heart.svg new file mode 100644 index 0000000..2f267c9 --- /dev/null +++ b/assets/icons/heart.svg @@ -0,0 +1 @@ + diff --git a/assets/icons/inbox.svg b/assets/icons/inbox.svg new file mode 100644 index 0000000..15d6fae --- /dev/null +++ b/assets/icons/inbox.svg @@ -0,0 +1 @@ + diff --git a/assets/icons/info.svg b/assets/icons/info.svg new file mode 100644 index 0000000..8f9c59a --- /dev/null +++ b/assets/icons/info.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/icons/loader-circle.svg b/assets/icons/loader-circle.svg new file mode 100644 index 0000000..12cb72f --- /dev/null +++ b/assets/icons/loader-circle.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/assets/icons/loader.svg b/assets/icons/loader.svg new file mode 100644 index 0000000..f6ff93f --- /dev/null +++ b/assets/icons/loader.svg @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/assets/icons/maximize.svg b/assets/icons/maximize.svg new file mode 100644 index 0000000..b3504b5 --- /dev/null +++ b/assets/icons/maximize.svg @@ -0,0 +1 @@ + diff --git a/assets/icons/menu.svg b/assets/icons/menu.svg new file mode 100644 index 0000000..6598697 --- /dev/null +++ b/assets/icons/menu.svg @@ -0,0 +1 @@ + diff --git a/assets/icons/minimize.svg b/assets/icons/minimize.svg new file mode 100644 index 0000000..3f81a42 --- /dev/null +++ b/assets/icons/minimize.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/assets/icons/minus.svg b/assets/icons/minus.svg new file mode 100644 index 0000000..ab04a16 --- /dev/null +++ b/assets/icons/minus.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/assets/icons/moon.svg b/assets/icons/moon.svg new file mode 100644 index 0000000..dfadc20 --- /dev/null +++ b/assets/icons/moon.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/icons/palette.svg b/assets/icons/palette.svg new file mode 100644 index 0000000..b50674d --- /dev/null +++ b/assets/icons/palette.svg @@ -0,0 +1 @@ + diff --git a/assets/icons/panel-bottom-open.svg b/assets/icons/panel-bottom-open.svg new file mode 100644 index 0000000..df77e5b --- /dev/null +++ b/assets/icons/panel-bottom-open.svg @@ -0,0 +1 @@ + diff --git a/assets/icons/panel-bottom.svg b/assets/icons/panel-bottom.svg new file mode 100644 index 0000000..ebe599c --- /dev/null +++ b/assets/icons/panel-bottom.svg @@ -0,0 +1 @@ + diff --git a/assets/icons/panel-left-open.svg b/assets/icons/panel-left-open.svg new file mode 100644 index 0000000..579e458 --- /dev/null +++ b/assets/icons/panel-left-open.svg @@ -0,0 +1 @@ + diff --git a/assets/icons/panel-left.svg b/assets/icons/panel-left.svg new file mode 100644 index 0000000..2eed266 --- /dev/null +++ b/assets/icons/panel-left.svg @@ -0,0 +1 @@ + diff --git a/assets/icons/panel-right-open.svg b/assets/icons/panel-right-open.svg new file mode 100644 index 0000000..3b5ff0b --- /dev/null +++ b/assets/icons/panel-right-open.svg @@ -0,0 +1 @@ + diff --git a/assets/icons/panel-right.svg b/assets/icons/panel-right.svg new file mode 100644 index 0000000..d29a4a5 --- /dev/null +++ b/assets/icons/panel-right.svg @@ -0,0 +1 @@ + diff --git a/assets/icons/plus.svg b/assets/icons/plus.svg new file mode 100644 index 0000000..651bbd4 --- /dev/null +++ b/assets/icons/plus.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/icons/search.svg b/assets/icons/search.svg new file mode 100644 index 0000000..a658349 --- /dev/null +++ b/assets/icons/search.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/assets/icons/sort-ascending.svg b/assets/icons/sort-ascending.svg new file mode 100644 index 0000000..9be1b97 --- /dev/null +++ b/assets/icons/sort-ascending.svg @@ -0,0 +1,4 @@ + + + + diff --git a/assets/icons/sort-descending.svg b/assets/icons/sort-descending.svg new file mode 100644 index 0000000..ab65056 --- /dev/null +++ b/assets/icons/sort-descending.svg @@ -0,0 +1,4 @@ + + + + diff --git a/assets/icons/star-off.svg b/assets/icons/star-off.svg new file mode 100644 index 0000000..a262060 --- /dev/null +++ b/assets/icons/star-off.svg @@ -0,0 +1 @@ + diff --git a/assets/icons/star.svg b/assets/icons/star.svg new file mode 100644 index 0000000..8d93131 --- /dev/null +++ b/assets/icons/star.svg @@ -0,0 +1 @@ + diff --git a/assets/icons/sun.svg b/assets/icons/sun.svg new file mode 100644 index 0000000..668d778 --- /dev/null +++ b/assets/icons/sun.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/icons/thumbs-down.svg b/assets/icons/thumbs-down.svg new file mode 100644 index 0000000..816273e --- /dev/null +++ b/assets/icons/thumbs-down.svg @@ -0,0 +1 @@ + diff --git a/assets/icons/thumbs-up.svg b/assets/icons/thumbs-up.svg new file mode 100644 index 0000000..01fae76 --- /dev/null +++ b/assets/icons/thumbs-up.svg @@ -0,0 +1 @@ + diff --git a/assets/icons/triangle-alert.svg b/assets/icons/triangle-alert.svg new file mode 100644 index 0000000..1861c2e --- /dev/null +++ b/assets/icons/triangle-alert.svg @@ -0,0 +1 @@ + diff --git a/assets/icons/window-close.svg b/assets/icons/window-close.svg new file mode 100644 index 0000000..62b6b0c --- /dev/null +++ b/assets/icons/window-close.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/assets/icons/window-maximize.svg b/assets/icons/window-maximize.svg new file mode 100644 index 0000000..9da4cd7 --- /dev/null +++ b/assets/icons/window-maximize.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/assets/icons/window-minimize.svg b/assets/icons/window-minimize.svg new file mode 100644 index 0000000..708e27b --- /dev/null +++ b/assets/icons/window-minimize.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/assets/icons/window-restore.svg b/assets/icons/window-restore.svg new file mode 100644 index 0000000..896b6b6 --- /dev/null +++ b/assets/icons/window-restore.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/src/ui/Cargo.toml b/src/ui/Cargo.toml index 4c44451..1dfbc21 100644 --- a/src/ui/Cargo.toml +++ b/src/ui/Cargo.toml @@ -27,6 +27,7 @@ tokio = { version = "1.41.1", features = ["full"] } components = { package = "ui", git = "https://github.com/longbridgeapp/gpui-component", version = "0.1.0" } log = "0.4.22" random-string = "1.1.0" +rust-embed = "8.5.0" [features] default = ["gpui/x11"] diff --git a/src/ui/src/app.rs b/src/ui/src/app.rs new file mode 100644 index 0000000..e2f0d2a --- /dev/null +++ b/src/ui/src/app.rs @@ -0,0 +1,60 @@ +use gpui::{div, img, rgb, Context, Model, ParentElement, Render, Styled, View, ViewContext, VisualContext}; +use scope_backend_discord::{channel::DiscordChannel, client::DiscordClient, message::DiscordMessage, snowflake::Snowflake}; + +use crate::channel::ChannelView; + +pub struct App { + channel: Model>>>, +} + +impl App { + pub fn new(ctx: &mut ViewContext<'_, Self>) -> App { + let token = dotenv::var("DISCORD_TOKEN").expect("Must provide DISCORD_TOKEN in .env"); + let demo_channel_id = dotenv::var("DEMO_CHANNEL_ID").expect("Must provide DEMO_CHANNEL_ID in .env"); + + let mut context = ctx.to_async(); + + let channel = ctx.new_model(|_| None); + + let async_channel = channel.clone(); + + ctx + .foreground_executor() + .spawn(async move { + let client = DiscordClient::new(token).await; + + let channel = DiscordChannel::new( + client.clone(), + Snowflake { + content: demo_channel_id.parse().unwrap(), + }, + ) + .await; + + let view = context.new_view(|cx| ChannelView::::create(cx, channel)).unwrap(); + + async_channel.update(&mut context, |a, b| { + *a = Some(view); + b.notify() + }) + }) + .detach(); + + App { channel } + } +} + +impl Render for App { + fn render(&mut self, cx: &mut gpui::ViewContext) -> impl gpui::IntoElement { + let mut content = div().w_full().h_full(); + + if let Some(channel) = self.channel.read(cx).as_ref() { + content = content.child(channel.clone()); + } + + let title_bar = components::TitleBar::new() + .child(div().flex().flex_row().text_color(rgb(0xFFFFFF)).gap_2().child(img("brand/scope-round-200.png").w_6().h_6()).child("Scope")); + + div().w_full().h_full().flex().flex_col().child(title_bar).child(content) + } +} diff --git a/src/ui/src/channel/message.rs b/src/ui/src/channel/message.rs index e84de0d..5485cd3 100644 --- a/src/ui/src/channel/message.rs +++ b/src/ui/src/channel/message.rs @@ -60,8 +60,18 @@ pub fn message(message: MessageGroup) -> impl IntoElement { .flex() .flex_row() .text_color(rgb(0xFFFFFF)) - .gap_2() - .p_2() - .child(img(message.get_author().get_icon()).object_fit(gpui::ObjectFit::Fill).bg(rgb(0xFFFFFF)).rounded_full().w_12().h_12()) - .child(div().flex().flex_col().child(message.get_author().get_display_name()).child(div().children(message.contents()))) + .gap_4() + .pb_6() + .child(img(message.get_author().get_icon()).flex_shrink_0().object_fit(gpui::ObjectFit::Fill).bg(rgb(0xFFFFFF)).rounded_full().w_12().h_12()) + .child( + div() + .flex() + .min_w_0() + .flex_shrink() + .flex_col() + // enabling this, and thus enabling ellipsis causes a consistent panic!? + // .child(div().text_ellipsis().min_w_0().child(message.get_author().get_display_name())) + .child(div().min_w_0().child(message.get_author().get_display_name())) + .children(message.contents()), + ) } diff --git a/src/ui/src/channel/mod.rs b/src/ui/src/channel/mod.rs index 55b73fc..8ebbb0d 100644 --- a/src/ui/src/channel/mod.rs +++ b/src/ui/src/channel/mod.rs @@ -13,81 +13,77 @@ pub struct ChannelView { } impl ChannelView { - pub fn create(ctx: &mut gpui::WindowContext, channel: impl Channel + 'static) -> View { - let view = ctx.new_view(|ctx| { - let state_model = ctx.new_model(|_cx| MessageList::::new()); - - let async_model = state_model.clone(); - let mut async_ctx = ctx.to_async(); - let channel_listener = channel.clone(); - - ctx - .foreground_executor() - .spawn(async move { - loop { - let message = channel_listener.get_receiver().recv().await.unwrap(); - - async_model - .update(&mut async_ctx, |data, ctx| { - data.add_external_message(message); - ctx.notify(); - }) - .unwrap(); - } - }) - .detach(); - - ctx - .observe(&state_model, |this: &mut ChannelView, model, cx| { - this.list_state = model.read(cx).create_list_state(); - cx.notify(); - }) - .detach(); - - let message_input = ctx.new_view(|cx| { - let mut input = components::input::TextInput::new(cx); - - input.set_size(components::Size::Large, cx); - - input - }); - - ctx - .subscribe(&message_input, move |channel_view, text_input, input_event, ctx| match input_event { - InputEvent::PressEnter => { - let content = text_input.read(ctx).text().to_string(); - let channel_sender = channel.clone(); - - text_input.update(ctx, |text_input, cx| { - text_input.set_text("", cx); - }); - - let nonce = random_string::generate(20, random_string::charsets::ALPHANUMERIC); - let pending = channel_sender.send_message(content, nonce); - - channel_view.list_model.update(ctx, move |v, _| { - v.add_pending_message(pending); - }); - channel_view.list_state = channel_view.list_model.read(ctx).create_list_state(); - ctx.notify(); - } - _ => {} - }) - .detach(); - - ChannelView:: { - list_state: state_model.read(ctx).create_list_state(), - list_model: state_model, - message_input, - } + pub fn create(ctx: &mut gpui::ViewContext<'_, ChannelView>, channel: impl Channel + 'static) -> Self { + let state_model = ctx.new_model(|_cx| MessageList::::new()); + + let async_model = state_model.clone(); + let mut async_ctx = ctx.to_async(); + let channel_listener = channel.clone(); + + ctx + .foreground_executor() + .spawn(async move { + loop { + let message = channel_listener.get_receiver().recv().await.unwrap(); + + async_model + .update(&mut async_ctx, |data, ctx| { + data.add_external_message(message); + ctx.notify(); + }) + .unwrap(); + } + }) + .detach(); + + ctx + .observe(&state_model, |this: &mut ChannelView, model, cx| { + this.list_state = model.read(cx).create_list_state(); + cx.notify(); + }) + .detach(); + + let message_input = ctx.new_view(|cx| { + let mut input = components::input::TextInput::new(cx); + + input.set_size(components::Size::Large, cx); + + input }); - view + ctx + .subscribe(&message_input, move |channel_view, text_input, input_event, ctx| match input_event { + InputEvent::PressEnter => { + let content = text_input.read(ctx).text().to_string(); + let channel_sender = channel.clone(); + + text_input.update(ctx, |text_input, cx| { + text_input.set_text("", cx); + }); + + let nonce = random_string::generate(20, random_string::charsets::ALPHANUMERIC); + let pending = channel_sender.send_message(content, nonce); + + channel_view.list_model.update(ctx, move |v, _| { + v.add_pending_message(pending); + }); + channel_view.list_state = channel_view.list_model.read(ctx).create_list_state(); + ctx.notify(); + } + _ => {} + }) + .detach(); + + ChannelView:: { + list_state: state_model.read(ctx).create_list_state(), + list_model: state_model, + message_input, + } } } impl Render for ChannelView { fn render(&mut self, _: &mut gpui::ViewContext) -> impl gpui::IntoElement { - div().flex().flex_col().w_full().h_full().child(list(self.list_state.clone()).w_full().h_full()).child(self.message_input.clone()) + div().flex().flex_col().w_full().h_full().p_6().child(list(self.list_state.clone()).w_full().h_full()).child(self.message_input.clone()) } } diff --git a/src/ui/src/main.rs b/src/ui/src/main.rs index 64c21c1..dd67808 100644 --- a/src/ui/src/main.rs +++ b/src/ui/src/main.rs @@ -1,27 +1,25 @@ +pub mod app; pub mod app_state; pub mod channel; use std::{fs, path::PathBuf, sync::Arc}; use app_state::AppState; -use channel::ChannelView; use components::theme::Theme; use gpui::*; -use scope_backend_discord::{channel::DiscordChannel, client::DiscordClient, message::DiscordMessage, snowflake::Snowflake}; +use http_client::anyhow; -struct Assets { - base: PathBuf, -} +#[derive(rust_embed::RustEmbed)] +#[folder = "../../assets"] +struct Assets; impl AssetSource for Assets { fn load(&self, path: &str) -> Result>> { - fs::read(self.base.join(path)).map(|data| Some(std::borrow::Cow::Owned(data))).map_err(|e| e.into()) + Self::get(path).map(|f| Some(f.data)).ok_or_else(|| anyhow!("could not find asset at path \"{}\"", path)) } fn list(&self, path: &str) -> Result> { - fs::read_dir(self.base.join(path)) - .map(|entries| entries.filter_map(|entry| entry.ok().and_then(|entry| entry.file_name().into_string().ok()).map(SharedString::from)).collect()) - .map_err(|e| e.into()) + Ok(Self::iter().filter_map(|p| if p.starts_with(path) { Some(p.into()) } else { None }).collect()) } } @@ -41,31 +39,26 @@ async fn main() { let app_state = Arc::new(AppState {}); - let token = dotenv::var("DISCORD_TOKEN").expect("Must provide DISCORD_TOKEN in .env"); - let demo_channel_id = dotenv::var("DEMO_CHANNEL_ID").expect("Must provide DEMO_CHANNEL_ID in .env"); - - let client = DiscordClient::new(token).await; - - let channel = DiscordChannel::new( - client.clone(), - Snowflake { - content: demo_channel_id.parse().unwrap(), - }, - ) - .await; + App::new().with_assets(Assets).with_http_client(Arc::new(reqwest_client::ReqwestClient::new())).run(move |cx: &mut AppContext| { + AppState::set_global(Arc::downgrade(&app_state), cx); - App::new().with_assets(Assets { base: PathBuf::from("img") }).with_http_client(Arc::new(reqwest_client::ReqwestClient::new())).run( - move |cx: &mut AppContext| { - AppState::set_global(Arc::downgrade(&app_state), cx); + if let Err(e) = init(app_state.clone(), cx) { + log::error!("{}", e); + return; + } - if let Err(e) = init(app_state.clone(), cx) { - log::error!("{}", e); - return; - } + Theme::sync_system_appearance(cx); - Theme::sync_system_appearance(cx); + let opts = WindowOptions { + window_decorations: Some(WindowDecorations::Client), + titlebar: Some(TitlebarOptions { + appears_transparent: true, + title: Some(SharedString::new_static("scope")), + ..Default::default() + }), + ..Default::default() + }; - cx.open_window(WindowOptions::default(), |cx| ChannelView::::create(cx, channel)).unwrap(); - }, - ); + cx.open_window(opts, |cx| cx.new_view(|cx| crate::app::App::new(cx))).unwrap(); + }); }