feat: add support for multi-themes (#210)
* chore: update deps * wip * add themes * add matrix theme * add flexoki and spaceduck themes * . * simple theme change function * . * respect shadow and radius settings * add rose pine themes * toggle theme
This commit is contained in:
@@ -16,6 +16,7 @@ actions!(
|
||||
DarkMode,
|
||||
ViewProfile,
|
||||
ViewRelays,
|
||||
Themes,
|
||||
Settings,
|
||||
Logout,
|
||||
Quit
|
||||
|
||||
@@ -9,7 +9,7 @@ use encryption::Encryption;
|
||||
use encryption_ui::EncryptionPanel;
|
||||
use gpui::prelude::FluentBuilder;
|
||||
use gpui::{
|
||||
deferred, div, px, rems, App, AppContext, Axis, ClipboardItem, Context, Entity,
|
||||
deferred, div, px, relative, rems, App, AppContext, Axis, ClipboardItem, Context, Entity,
|
||||
InteractiveElement, IntoElement, ParentElement, Render, SharedString,
|
||||
StatefulInteractiveElement, Styled, Subscription, Window,
|
||||
};
|
||||
@@ -20,7 +20,7 @@ use person::PersonRegistry;
|
||||
use relay_auth::RelayAuth;
|
||||
use settings::AppSettings;
|
||||
use smallvec::{smallvec, SmallVec};
|
||||
use theme::{ActiveTheme, Theme, ThemeMode};
|
||||
use theme::{ActiveTheme, Theme, ThemeMode, ThemeRegistry};
|
||||
use title_bar::TitleBar;
|
||||
use ui::avatar::Avatar;
|
||||
use ui::button::{Button, ButtonVariants};
|
||||
@@ -32,7 +32,9 @@ use ui::popover::{Popover, PopoverContent};
|
||||
use ui::popup_menu::PopupMenuExt;
|
||||
use ui::{h_flex, v_flex, ContextModal, IconName, Root, Sizable, StyledExt};
|
||||
|
||||
use crate::actions::{reset, DarkMode, KeyringPopup, Logout, Settings, ViewProfile, ViewRelays};
|
||||
use crate::actions::{
|
||||
reset, DarkMode, KeyringPopup, Logout, Settings, Themes, ViewProfile, ViewRelays,
|
||||
};
|
||||
use crate::user::viewer;
|
||||
use crate::views::compose::compose_button;
|
||||
use crate::views::{onboarding, preferences, setup_relay, startup, welcome};
|
||||
@@ -313,6 +315,58 @@ impl ChatSpace {
|
||||
}
|
||||
}
|
||||
|
||||
fn on_themes(&mut self, _ev: &Themes, window: &mut Window, cx: &mut Context<Self>) {
|
||||
window.open_modal(cx, move |this, _window, cx| {
|
||||
let registry = ThemeRegistry::global(cx);
|
||||
let themes = registry.read(cx).themes();
|
||||
|
||||
this.title("Select theme")
|
||||
.show_close(true)
|
||||
.overlay_closable(true)
|
||||
.child(v_flex().gap_2().pb_4().children({
|
||||
let mut items = Vec::with_capacity(themes.len());
|
||||
|
||||
for (name, theme) in themes.iter() {
|
||||
items.push(
|
||||
h_flex()
|
||||
.h_10()
|
||||
.justify_between()
|
||||
.child(
|
||||
v_flex()
|
||||
.child(
|
||||
div()
|
||||
.text_sm()
|
||||
.text_color(cx.theme().text)
|
||||
.line_height(relative(1.3))
|
||||
.child(theme.name.clone()),
|
||||
)
|
||||
.child(
|
||||
div()
|
||||
.text_xs()
|
||||
.text_color(cx.theme().text_muted)
|
||||
.child(theme.author.clone()),
|
||||
),
|
||||
)
|
||||
.child(
|
||||
Button::new(format!("change-{name}"))
|
||||
.label("Set")
|
||||
.small()
|
||||
.ghost()
|
||||
.on_click({
|
||||
let theme = theme.clone();
|
||||
move |_ev, window, cx| {
|
||||
Theme::apply_theme(theme.clone(), Some(window), cx);
|
||||
}
|
||||
}),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
items
|
||||
}))
|
||||
})
|
||||
}
|
||||
|
||||
fn on_sign_out(&mut self, _e: &Logout, _window: &mut Window, cx: &mut Context<Self>) {
|
||||
reset(cx);
|
||||
}
|
||||
@@ -567,6 +621,7 @@ impl ChatSpace {
|
||||
IconName::Sun,
|
||||
Box::new(DarkMode),
|
||||
)
|
||||
.menu_with_icon("Themes", IconName::Moon, Box::new(Themes))
|
||||
.menu_with_icon(
|
||||
"Settings",
|
||||
IconName::Settings,
|
||||
@@ -646,6 +701,7 @@ impl Render for ChatSpace {
|
||||
.on_action(cx.listener(Self::on_profile))
|
||||
.on_action(cx.listener(Self::on_relays))
|
||||
.on_action(cx.listener(Self::on_dark_mode))
|
||||
.on_action(cx.listener(Self::on_themes))
|
||||
.on_action(cx.listener(Self::on_sign_out))
|
||||
.on_action(cx.listener(Self::on_open_pubkey))
|
||||
.on_action(cx.listener(Self::on_copy_pubkey))
|
||||
|
||||
@@ -83,6 +83,9 @@ fn main() {
|
||||
// Initialize components
|
||||
ui::init(cx);
|
||||
|
||||
// Initialize theme registry
|
||||
theme::init(cx);
|
||||
|
||||
// Initialize backend for keys storage
|
||||
key_store::init(cx);
|
||||
|
||||
|
||||
@@ -120,8 +120,8 @@ impl RenderOnce for RoomListItem {
|
||||
.flex_1()
|
||||
.flex()
|
||||
.justify_between()
|
||||
.child(Skeleton::new().w_32().h_2p5().rounded_sm())
|
||||
.child(Skeleton::new().w_6().h_2p5().rounded_sm()),
|
||||
.child(Skeleton::new().w_32().h_2p5().rounded(cx.theme().radius))
|
||||
.child(Skeleton::new().w_6().h_2p5().rounded(cx.theme().radius)),
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -151,18 +151,20 @@ impl Sidebar {
|
||||
|
||||
let mut results: Vec<Event> = Vec::with_capacity(FIND_LIMIT);
|
||||
|
||||
while let Some(event) = stream.next().await {
|
||||
// Skip if author is match current user
|
||||
if event.pubkey == public_key {
|
||||
continue;
|
||||
}
|
||||
while let Some((_url, event)) = stream.next().await {
|
||||
if let Ok(event) = event {
|
||||
// Skip if author is match current user
|
||||
if event.pubkey == public_key {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Skip if the event has already been added
|
||||
if results.iter().any(|this| this.pubkey == event.pubkey) {
|
||||
continue;
|
||||
}
|
||||
// Skip if the event has already been added
|
||||
if results.iter().any(|this| this.pubkey == event.pubkey) {
|
||||
continue;
|
||||
}
|
||||
|
||||
results.push(event);
|
||||
results.push(event);
|
||||
}
|
||||
}
|
||||
|
||||
if results.is_empty() {
|
||||
|
||||
@@ -191,7 +191,7 @@ impl Onboarding {
|
||||
div()
|
||||
.id(ix)
|
||||
.flex_1()
|
||||
.rounded_md()
|
||||
.rounded(cx.theme().radius)
|
||||
.py_0p5()
|
||||
.px_2()
|
||||
.bg(cx.theme().ghost_element_background_alt)
|
||||
@@ -308,13 +308,13 @@ impl Render for Onboarding {
|
||||
.p_2()
|
||||
.flex_1()
|
||||
.h_full()
|
||||
.rounded_2xl()
|
||||
.rounded(cx.theme().radius_lg)
|
||||
.child(
|
||||
v_flex()
|
||||
.size_full()
|
||||
.justify_center()
|
||||
.bg(cx.theme().surface_background)
|
||||
.rounded_2xl()
|
||||
.rounded(cx.theme().radius_lg)
|
||||
.child(
|
||||
v_flex()
|
||||
.gap_5()
|
||||
@@ -324,8 +324,8 @@ impl Render for Onboarding {
|
||||
this.child(
|
||||
img(qr.clone())
|
||||
.size(px(256.))
|
||||
.rounded_xl()
|
||||
.shadow_lg()
|
||||
.rounded(cx.theme().radius_lg)
|
||||
.when(cx.theme().shadow, |this| this.shadow_lg())
|
||||
.border_1()
|
||||
.border_color(cx.theme().element_active),
|
||||
)
|
||||
|
||||
@@ -77,8 +77,10 @@ impl Screening {
|
||||
.stream_events_from(BOOTSTRAP_RELAYS, filter, Duration::from_secs(2))
|
||||
.await
|
||||
{
|
||||
while let Some(event) = stream.next().await {
|
||||
activity = Some(event.created_at);
|
||||
while let Some((_url, event)) = stream.next().await {
|
||||
if let Ok(event) = event {
|
||||
activity = Some(event.created_at);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -249,7 +249,7 @@ impl Render for Startup {
|
||||
.h_10()
|
||||
.w_72()
|
||||
.bg(cx.theme().elevated_surface_background)
|
||||
.rounded_lg()
|
||||
.rounded(cx.theme().radius_lg)
|
||||
.text_sm()
|
||||
.when(self.loading, |this| {
|
||||
this.child(
|
||||
|
||||
Reference in New Issue
Block a user