chore: fix messages not loading

This commit is contained in:
2025-08-25 12:13:45 +07:00
parent 5edcc97ada
commit 3a6fc2bcc5
19 changed files with 135 additions and 148 deletions

View File

@@ -1,3 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24">
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M19.25 21.25H6c-.69 0-1.25-.56-1.25-1.25M11.5 9.25h1M4.75 20V4.75a2 2 0 0 1 2-2h12.5v16H6c-.69 0-1.25.56-1.25 1.25Zm5-6.25s0-1.5 2.25-1.5 2.25 1.5 2.25 1.5h-4.5ZM13 9.25a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z"/>
</svg>

Before

Width:  |  Height:  |  Size: 404 B

View File

@@ -1,3 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="currentColor" viewBox="0 0 24 24">
<path fill="#000" fill-rule="evenodd" d="M2 12C2 6.477 6.477 2 12 2s10 4.477 10 10-4.477 10-10 10a9.967 9.967 0 0 1-4.098-.876.313.313 0 0 0-.195-.026l-3.471.78a1.75 1.75 0 0 1-2.084-2.12l.809-3.33a.313.313 0 0 0-.028-.204A9.965 9.965 0 0 1 2 12Zm4.5 0a1 1 0 1 0 2 0 1 1 0 0 0-2 0Zm4.5 0a1 1 0 1 0 2 0 1 1 0 0 0-2 0Zm5.5 1a1 1 0 1 1 0-2 1 1 0 0 1 0 2Z" clip-rule="evenodd"/>
</svg>

Before

Width:  |  Height:  |  Size: 488 B

4
assets/icons/edit.svg Normal file
View File

@@ -0,0 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24">
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M10.75 21.25h-4a2 2 0 0 1-2-2V4.75a2 2 0 0 1 2-2h10.5a2 2 0 0 1 2 2v7"/>
<path stroke="currentColor" stroke-linecap="square" stroke-linejoin="round" stroke-width="1.5" d="M13.75 21.25v-2.333l3.75-3.75a1.65 1.65 0 0 1 2.333 2.333l-3.75 3.75H13.75Z"/>
</svg>

After

Width:  |  Height:  |  Size: 454 B

View File

@@ -1,3 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24">
<path fill="currentColor" d="M5.75 3A2.75 2.75 0 0 0 3 5.75v1.422c0 .729.29 1.428.805 1.944l4.829 4.829c.234.234.366.552.366.883v6.422a.75.75 0 0 0 .95.723l4.5-1.25A.75.75 0 0 0 15 20v-5.172c0-.331.132-.649.366-.883l4.829-4.829A2.75 2.75 0 0 0 21 7.172V5.75A2.75 2.75 0 0 0 18.25 3H5.75Z"/>
</svg>

Before

Width:  |  Height:  |  Size: 396 B

View File

@@ -1,3 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24">
<path stroke="currentColor" stroke-linejoin="round" stroke-width="1.5" d="M18.25 3.75H5.75a2 2 0 0 0-2 2v1.422a2 2 0 0 0 .586 1.414l4.828 4.828a2 2 0 0 1 .586 1.414v6.422l4.5-1.25v-5.172a2 2 0 0 1 .586-1.414l4.828-4.828a2 2 0 0 0 .586-1.414V5.75a2 2 0 0 0-2-2Z"/>
</svg>

Before

Width:  |  Height:  |  Size: 369 B

View File

@@ -1,3 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24">
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M2.75 5.75v11.5a2 2 0 0 0 2 2h14.5a2 2 0 0 0 2-2v-8.5a2 2 0 0 0-2-2h-6.18a2 2 0 0 1-1.664-.89l-.812-1.22a2 2 0 0 0-1.664-.89H4.75a2 2 0 0 0-2 2Z"/>
</svg>

Before

Width:  |  Height:  |  Size: 350 B

View File

@@ -1,4 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24">
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M3.75 5.816h8.5M8 5.75v-2m4 10.5C7.935 13.198 5.845 10.614 5.25 6"/>
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M4 14c4.064-1.02 6.154-3.527 6.75-8m3.594 11.125h5.312m1.594 2.125-3.314-8.774c-.326-.862-1.546-.862-1.872 0L12.75 19.25"/>
</svg>

Before

Width:  |  Height:  |  Size: 494 B

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="currentColor" viewBox="0 0 256 256"><path d="M104,152a8,8,0,0,1-8,8H56a8,8,0,0,1,0-16H96A8,8,0,0,1,104,152ZM168,32h24a8,8,0,0,0,0-16H160a8,8,0,0,0-8,8V56h16Zm72,84v60a16,16,0,0,1-16,16H136v32a8,8,0,0,1-16,0V192H32a16,16,0,0,1-16-16V116A60.07,60.07,0,0,1,76,56h76v88a8,8,0,0,0,16,0V56h12A60.07,60.07,0,0,1,240,116Zm-120,0a44,44,0,0,0-88,0v60h88Z"></path></svg>

Before

Width:  |  Height:  |  Size: 429 B

View File

@@ -1,3 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24">
<path fill="currentColor" fill-rule="evenodd" d="M12 2a7.795 7.795 0 0 0-7.696 6.554l-1.17 7.258A2.75 2.75 0 0 0 5.848 19h1.66c.849 1.75 2.512 3 4.492 3s3.643-1.25 4.492-3h1.66a2.75 2.75 0 0 0 2.714-3.188l-1.17-7.258A7.795 7.795 0 0 0 12 2Zm2.754 17H9.245c.678.937 1.68 1.5 2.754 1.5s2.076-.563 2.754-1.5Z" clip-rule="evenodd"/>
</svg>

Before

Width:  |  Height:  |  Size: 434 B

4
assets/icons/refresh.svg Normal file
View File

@@ -0,0 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24">
<path fill="currentColor" d="M13 21a1 1 0 1 0 0-2 1 1 0 0 0 0 2Zm8-10a1 1 0 1 0-2 0 1 1 0 0 0 2 0Zm-1.07 3.268a1 1 0 1 1-1 1.732 1 1 0 0 1 1-1.732Zm-2.562 5.026a1 1 0 1 0-1-1.732 1 1 0 0 0 1 1.732ZM18.927 8a1 1 0 1 1-1-1.732 1 1 0 0 1 1 1.732Z"/>
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M9.25 14.75v5.5h-5.5M9 19.688a8.25 8.25 0 1 1 6.25-15.273"/>
</svg>

After

Width:  |  Height:  |  Size: 512 B

View File

@@ -1,3 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24">
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="m7.5 3.25 4.5 3.5 4.5-3.5m-11.75 17h14.5a2 2 0 0 0 2-2v-9.5a2 2 0 0 0-2-2H4.75a2 2 0 0 0-2 2v9.5a2 2 0 0 0 2 2Z"/>
</svg>

Before

Width:  |  Height:  |  Size: 317 B

View File

@@ -1,3 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24">
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="m7.25 10.488 3.675 3.762 6.825-10m-14 10.5v2.3c0 1.12 0 1.68.218 2.108a2 2 0 0 0 .874.874c.428.218.988.218 2.108.218h10.1c1.12 0 1.68 0 2.108-.218a2 2 0 0 0 .874-.874c.218-.428.218-.988.218-2.108v-2.3"/>
</svg>

Before

Width:  |  Height:  |  Size: 406 B

View File

@@ -1,3 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24">
<path fill="currentColor" fill-rule="evenodd" d="M1 11.75A5.75 5.75 0 0 1 6.75 6h10.5A5.75 5.75 0 0 1 23 11.75v.5A5.75 5.75 0 0 1 17.25 18H6.75A5.75 5.75 0 0 1 1 12.25v-.5ZM17 7.5a4.5 4.5 0 1 0 0 9 4.5 4.5 0 0 0 0-9Z" clip-rule="evenodd"/>
</svg>

Before

Width:  |  Height:  |  Size: 345 B

View File

@@ -1,3 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24">
<path stroke="currentColor" stroke-width="1.5" d="M17 17.25H7a5.25 5.25 0 1 1 0-10.5h10m0 10.5a5.25 5.25 0 1 0 0-10.5m0 10.5a5.25 5.25 0 1 1 0-10.5"/>
</svg>

Before

Width:  |  Height:  |  Size: 256 B

View File

@@ -133,19 +133,14 @@ impl ChatSpace {
subscriptions.push(
// Subscribe to open chat room requests
cx.subscribe_in(&registry, window, |this, _e, event, window, cx| {
match event {
cx.subscribe_in(
&registry,
window,
|this, _e, event, window, cx| match event {
RegistrySignal::Open(room) => {
if let Some(room) = room.upgrade() {
this.dock.update(cx, |this, cx| {
let panel = chat::init(room, window, cx);
// Load messages when the panel is created
panel.update(cx, |this, cx| {
this.load_messages(window, cx);
});
// Add the panel to the center dock (tabs)
this.add_panel(Arc::new(panel), DockPlacement::Center, window, cx);
});
} else {
@@ -163,8 +158,8 @@ impl ChatSpace {
});
}
_ => {}
}
}),
},
),
);
tasks.push(

View File

@@ -10,7 +10,7 @@ use gpui::{
ClipboardItem, Context, Div, Element, Entity, EventEmitter, Flatten, FocusHandle, Focusable,
InteractiveElement, IntoElement, ListAlignment, ListState, MouseButton, ObjectFit,
ParentElement, PathPromptOptions, Render, RetainAllImageCache, SharedString, Stateful,
StatefulInteractiveElement, Styled, StyledImage, Subscription, Window,
StatefulInteractiveElement, Styled, StyledImage, Subscription, Task, Window,
};
use gpui_tokio::Tokio;
use i18n::{shared_t, t};
@@ -68,8 +68,9 @@ pub struct Chat {
uploading: bool,
// System
image_cache: Entity<RetainAllImageCache>,
#[allow(dead_code)]
subscriptions: SmallVec<[Subscription; 3]>,
_subscriptions: SmallVec<[Subscription; 2]>,
_tasks: SmallVec<[Task<()>; 1]>,
}
impl Chat {
@@ -89,39 +90,52 @@ impl Chat {
.clean_on_escape()
});
let load_messages = room.read(cx).load_messages(cx);
let mut subscriptions = smallvec![];
let mut tasks = smallvec![];
subscriptions.push(cx.on_release_in(window, move |this, _window, cx| {
this.messages.clear();
this.rendered_texts_by_id.clear();
this.reports_by_id.clear();
this.attachments.update(cx, |this, _cx| {
this.clear();
});
this.replies_to.update(cx, |this, _cx| {
this.clear();
})
}));
subscriptions.push(cx.subscribe_in(
&input,
window,
move |this: &mut Self, _input, event, window, cx| {
match event {
InputEvent::PressEnter { .. } => {
this.send_message(window, cx);
tasks.push(
// Load all messages belonging to this room
cx.spawn_in(window, async move |this, cx| {
match load_messages.await {
Ok(events) => {
this.update(cx, |this, cx| {
this.insert_messages(events, cx);
})
.ok();
}
InputEvent::Change(_) => {
// this.mention_popup(text, input, cx);
Err(e) => {
cx.update(|window, cx| {
window.push_notification(Notification::error(e.to_string()), cx);
})
.ok();
}
_ => {}
};
},
));
}),
);
subscriptions.push(
// Subscribe to input events
cx.subscribe_in(
&input,
window,
move |this: &mut Self, _input, event, window, cx| {
match event {
InputEvent::PressEnter { .. } => {
this.send_message(window, cx);
}
InputEvent::Change(_) => {
// this.mention_popup(text, input, cx);
}
_ => {}
};
},
),
);
subscriptions.push(
// Subscribe to room events
cx.subscribe_in(&room, window, move |this, _, signal, window, cx| {
match signal {
RoomSignal::NewMessage(event) => {
@@ -150,26 +164,30 @@ impl Chat {
input,
replies_to,
attachments,
subscriptions,
_subscriptions: subscriptions,
_tasks: tasks,
}
}
/// Load all messages belonging to this room
pub(crate) fn load_messages(&self, window: &mut Window, cx: &mut Context<Self>) {
let room = self.room.read(cx);
let load_messages = room.load_messages(cx);
fn load_messages(&self, window: &mut Window, cx: &mut Context<Self>) {
let load_messages = self.room.read(cx).load_messages(cx);
cx.spawn_in(window, async move |this, cx| {
match load_messages.await {
Ok(events) => {
this.update(cx, |this, cx| {
this.insert_messages(events, cx);
cx.update(|window, cx| {
window.push_notification(t!("chat.reload_tooltip"), cx);
this.update(cx, |this, cx| {
this.insert_messages(events, cx);
})
.ok();
})
.ok();
}
Err(e) => {
cx.update(|window, cx| {
window.push_notification(Notification::error(e.to_string()), cx);
window.push_notification(e.to_string(), cx);
})
.ok();
}
@@ -1010,6 +1028,62 @@ impl Chat {
items
}
fn subject_button(&self, cx: &App) -> Button {
let room = self.room.downgrade();
let subject = self
.room
.read(cx)
.subject
.as_ref()
.map(|subject| subject.to_string());
Button::new("subject")
.icon(IconName::Edit)
.tooltip(t!("chat.subject_tooltip"))
.on_click(move |_, window, cx| {
let view = subject::init(subject.clone(), window, cx);
let room = room.clone();
let weak_view = view.downgrade();
window.open_modal(cx, move |this, _window, _cx| {
let room = room.clone();
let weak_view = weak_view.clone();
this.confirm()
.title(shared_t!("chat.subject_tooltip"))
.child(view.clone())
.button_props(ModalButtonProps::default().ok_text(t!("common.change")))
.on_ok(move |_, _window, cx| {
if let Ok(subject) =
weak_view.read_with(cx, |this, cx| this.new_subject(cx))
{
room.update(cx, |this, cx| {
this.subject = Some(subject);
cx.notify();
})
.ok();
}
// true to close the modal
true
})
});
})
}
fn reload_button(&self, _cx: &App) -> Button {
let room = self.room.downgrade();
Button::new("reload")
.icon(IconName::Refresh)
.tooltip(t!("chat.reload_tooltip"))
.on_click(move |_, _window, cx| {
room.update(cx, |this, cx| {
this.emit_refresh(cx);
})
.ok();
})
}
}
impl Panel for Chat {
@@ -1038,47 +1112,10 @@ impl Panel for Chat {
}
fn toolbar_buttons(&self, _window: &Window, cx: &App) -> Vec<Button> {
let room = self.room.downgrade();
let subject = self
.room
.read(cx)
.subject
.as_ref()
.map(|subject| subject.to_string());
let subject_button = self.subject_button(cx);
let reload_button = self.reload_button(cx);
let button = Button::new("subject")
.icon(IconName::EditFill)
.tooltip(t!("chat.change_subject_button"))
.on_click(move |_, window, cx| {
let view = subject::init(subject.clone(), window, cx);
let room = room.clone();
let weak_view = view.downgrade();
window.open_modal(cx, move |this, _window, _cx| {
let room = room.clone();
let weak_view = weak_view.clone();
this.confirm()
.title(SharedString::new(t!("chat.change_subject_modal_title")))
.child(view.clone())
.button_props(ModalButtonProps::default().ok_text(t!("common.change")))
.on_ok(move |_, _window, cx| {
if let Ok(subject) =
weak_view.read_with(cx, |this, cx| this.new_subject(cx))
{
room.update(cx, |this, cx| {
this.subject = Some(subject);
cx.notify();
})
.ok();
}
// true to close the modal
true
})
});
});
vec![button]
vec![subject_button, reload_button]
}
}

View File

@@ -223,7 +223,7 @@ where
.justify_center()
.py_6()
.text_color(cx.theme().text_muted)
.child(Icon::new(IconName::Inbox).size(px(28.)))
.child(Icon::new(IconName::Loader).size(px(28.)))
.into_any_element()
}
}

View File

@@ -9,7 +9,6 @@ use crate::{Sizable, Size};
#[derive(IntoElement, Clone)]
pub enum IconName {
AddressBook,
ArrowIn,
ArrowDown,
ArrowLeft,
@@ -28,18 +27,13 @@ pub enum IconName {
CloseCircle,
CloseCircleFill,
Copy,
Edit,
EditFill,
Ellipsis,
Eye,
EyeOff,
EmojiFill,
Folder,
FolderFill,
Filter,
FilterFill,
Inbox,
Info,
Language,
Loader,
Logout,
Moon,
@@ -54,20 +48,17 @@ pub enum IconName {
Plus,
PlusFill,
PlusCircleFill,
Relays,
ResizeCorner,
Reply,
Report,
Refresh,
Forward,
Search,
SearchFill,
Sent,
Settings,
SortAscending,
SortDescending,
Sun,
Toggle,
ToggleFill,
ThumbsDown,
ThumbsUp,
Upload,
@@ -82,7 +73,6 @@ pub enum IconName {
impl IconName {
pub fn path(self) -> SharedString {
match self {
Self::AddressBook => "icons/address-book.svg",
Self::ArrowIn => "icons/arrows-in.svg",
Self::ArrowDown => "icons/arrow-down.svg",
Self::ArrowLeft => "icons/arrow-left.svg",
@@ -101,18 +91,13 @@ impl IconName {
Self::CloseCircle => "icons/close-circle.svg",
Self::CloseCircleFill => "icons/close-circle-fill.svg",
Self::Copy => "icons/copy.svg",
Self::Edit => "icons/edit.svg",
Self::EditFill => "icons/edit-fill.svg",
Self::Ellipsis => "icons/ellipsis.svg",
Self::Eye => "icons/eye.svg",
Self::EmojiFill => "icons/emoji-fill.svg",
Self::EyeOff => "icons/eye-off.svg",
Self::Folder => "icons/folder.svg",
Self::FolderFill => "icons/folder-fill.svg",
Self::Filter => "icons/filter.svg",
Self::FilterFill => "icons/filter-fill.svg",
Self::Inbox => "icons/inbox.svg",
Self::Info => "icons/info.svg",
Self::Language => "icons/language.svg",
Self::Loader => "icons/loader.svg",
Self::Logout => "icons/logout.svg",
Self::Moon => "icons/moon.svg",
@@ -127,20 +112,17 @@ impl IconName {
Self::Plus => "icons/plus.svg",
Self::PlusFill => "icons/plus-fill.svg",
Self::PlusCircleFill => "icons/plus-circle-fill.svg",
Self::Relays => "icons/relays.svg",
Self::ResizeCorner => "icons/resize-corner.svg",
Self::Reply => "icons/reply.svg",
Self::Report => "icons/report.svg",
Self::Refresh => "icons/refresh.svg",
Self::Forward => "icons/forward.svg",
Self::Search => "icons/search.svg",
Self::SearchFill => "icons/search-fill.svg",
Self::Sent => "icons/sent.svg",
Self::Settings => "icons/settings.svg",
Self::SortAscending => "icons/sort-ascending.svg",
Self::SortDescending => "icons/sort-descending.svg",
Self::Sun => "icons/sun.svg",
Self::Toggle => "icons/toggle.svg",
Self::ToggleFill => "icons/toggle-fill.svg",
Self::ThumbsDown => "icons/thumbs-down.svg",
Self::ThumbsUp => "icons/thumbs-up.svg",
Self::Upload => "icons/upload.svg",

View File

@@ -309,9 +309,9 @@ chat:
en: "Copy Message"
reply_button:
en: "Reply"
change_subject_button:
en: "Change Subject"
change_subject_modal_title:
reload_tooltip:
en: "Refresh messages"
subject_tooltip:
en: "Change the subject of the conversation"
replying_to_label:
en: "Replying to:"