1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
use dioxus::prelude::*;
use matrix_sdk::ruma::OwnedRoomId;
use crate::state::app_state::AppState;
/// Jump to date picker component.
#[component]
pub fn JumpToDatePicker(
room_id: String,
on_close: EventHandler<()>,
) -> Element {
let state = use_context::<Signal<AppState>>();
let mut date_value = use_signal(|| String::new());
let mut is_loading = use_signal(|| false);
let mut error_msg = use_signal(|| Option::<String>::None);
rsx! {
div {
class: "jump-to-date",
div {
class: "jump-to-date__header",
h4 { "Jump to Date" }
button {
class: "jump-to-date__close",
onclick: move |_| on_close.call(()),
"✕"
}
}
div {
class: "jump-to-date__picker",
input {
r#type: "date",
class: "jump-to-date__input",
value: "{date_value}",
oninput: move |evt| date_value.set(evt.value()),
}
button {
class: "btn btn--primary btn--sm",
disabled: date_value.read().is_empty() || *is_loading.read(),
onclick: move |_| {
let date_str = date_value.read().clone();
let rid = room_id.clone();
is_loading.set(true);
error_msg.set(None);
spawn(async move {
// Parse date to timestamp
if let Ok(date) = chrono::NaiveDate::parse_from_str(&date_str, "%Y-%m-%d") {
let datetime = date.and_hms_opt(0, 0, 0).unwrap();
let ts = datetime.and_utc().timestamp_millis();
let client = { state.read().client.clone() };
if let Some(_client) = client {
if let Ok(room_id) = OwnedRoomId::try_from(rid.as_str()) {
// Use the timestamp_to_event endpoint
// For now, use a simplified approach - scroll to approximate position
// A full implementation would use the /timestamp_to_event API
tracing::info!("Jump to date: {date_str} (ts: {ts}) in room {room_id}");
// Signal the timeline to scroll to this date
// This would integrate with the timeline loading logic
}
}
} else {
error_msg.set(Some("Invalid date format".to_string()));
}
is_loading.set(false);
on_close.call(());
});
},
if *is_loading.read() { "Loading..." } else { "Go" }
}
}
// Quick date buttons
div {
class: "jump-to-date__quick-options",
{
let today = chrono::Utc::now();
let yesterday = today - chrono::Duration::days(1);
let last_week = today - chrono::Duration::days(7);
let last_month = today - chrono::Duration::days(30);
let yesterday_str = yesterday.format("%Y-%m-%d").to_string();
let last_week_str = last_week.format("%Y-%m-%d").to_string();
let last_month_str = last_month.format("%Y-%m-%d").to_string();
rsx! {
button {
class: "jump-to-date__quick-btn",
onclick: move |_| date_value.set(yesterday_str.clone()),
"Yesterday"
}
button {
class: "jump-to-date__quick-btn",
onclick: move |_| date_value.set(last_week_str.clone()),
"Last week"
}
button {
class: "jump-to-date__quick-btn",
onclick: move |_| date_value.set(last_month_str.clone()),
"Last month"
}
}
}
}
if let Some(ref err) = *error_msg.read() {
div { class: "jump-to-date__error", "{err}" }
}
}
}
}