Skip to content

Commit 2328a75

Browse files
committed
correct URL when issue is optimistically created
1 parent dc8322d commit 2328a75

File tree

10 files changed

+111
-29
lines changed

10 files changed

+111
-29
lines changed

Cargo.lock

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

shared/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ tracing-subscriber = "0.3.19"
3636
bon = "3.3.2"
3737
mockall = "0.13.1"
3838
maplit = "1.0.2"
39+
bimap = "0.6.3"
3940

4041
[dev-dependencies]
4142
wasm-bindgen-test = "0.3.50"

shared/src/sync_engine/optimistic/db/storage.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,4 +65,12 @@ impl<DbStoreMarkers> DbWithOptimisticChanges<DbStoreMarkers> {
6565
.build()
6666
.object_store::<S>()
6767
}
68+
69+
pub fn get_optimistic_to_realistic_for_creations<S: Store>(
70+
&self,
71+
optimistic_id: &S::Id,
72+
) -> Option<S::Id> {
73+
self.optimistic_updates
74+
.get_optimistic_to_realistic_for_creations::<S>(optimistic_id)
75+
}
6876
}

shared/src/sync_engine/optimistic/optimistic_change_map.rs

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use std::{
55
sync::Arc,
66
};
77

8+
use bimap::BiMap;
89
use parking_lot::RwLock;
910
pub use status::Status;
1011
use typesafe_idb::{Store, StoreName};
@@ -68,7 +69,7 @@ mod status {
6869
struct OptimisticChangeMapInner<T, RealisticId> {
6970
changes:
7071
HashMap<StoreName, HashMap<SerializedId, BTreeMap<MonotonicTime, Status<T, RealisticId>>>>,
71-
optimistic_to_realistic: HashMap<RealisticId, SerializedId>,
72+
optimistic_to_realistic: BiMap<RealisticId, SerializedId>,
7273
}
7374

7475
impl<T, RealisticId: std::cmp::Eq + std::hash::Hash> Default
@@ -77,7 +78,7 @@ impl<T, RealisticId: std::cmp::Eq + std::hash::Hash> Default
7778
fn default() -> Self {
7879
Self {
7980
changes: Default::default(),
80-
optimistic_to_realistic: HashMap::new(),
81+
optimistic_to_realistic: BiMap::default(),
8182
}
8283
}
8384
}
@@ -212,7 +213,15 @@ impl<T, RealisticId: Clone + Eq + std::hash::Hash + std::fmt::Debug>
212213
self.inner
213214
.read()
214215
.optimistic_to_realistic
215-
.get(realistic_id)
216+
.get_by_left(realistic_id)
217+
.cloned()
218+
}
219+
220+
pub fn get_optimistic_to_realistic(&self, optimistic_id: &SerializedId) -> Option<RealisticId> {
221+
self.inner
222+
.read()
223+
.optimistic_to_realistic
224+
.get_by_right(optimistic_id)
216225
.cloned()
217226
}
218227
}

shared/src/sync_engine/optimistic/optimistic_changes.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,4 +104,13 @@ impl OptimisticChanges {
104104
.get_realistic_to_optimistic(&SerializedId::new_from_id::<S>(realistic_id))
105105
.map(|id| id.to_unserialized_id::<S>())
106106
}
107+
108+
pub fn get_optimistic_to_realistic_for_creations<S: Store>(
109+
&self,
110+
optimistic_id: &S::Id,
111+
) -> Option<S::Id> {
112+
self.creations
113+
.get_optimistic_to_realistic(&SerializedId::new_from_id::<S>(optimistic_id))
114+
.map(|id| id.to_unserialized_id::<S>())
115+
}
107116
}

web/src/app/repository/issues_tab/new_issue.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ pub fn NewIssue(
6161
let owner_login = owner_login.clone();
6262
let issue_number = issue_number.to_string();
6363
let repo_name = repository.name.clone();
64-
set_pathname(zwang_url!("/owner_name={owner_login}/repo_name={repo_name}/issues/issue_number={issue_number}"));
64+
set_pathname(&zwang_url!("/owner_name={owner_login}/repo_name={repo_name}/issues/issue_number={issue_number}"));
6565
}
6666
});
6767
};

web/src/app/repository/issues_tab/new_issue_button.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ pub fn NewIssueButton(
1313
let on_click = move |_ev| {
1414
let url =
1515
zwang_url!("/owner_name={owner_name.get()}/repo_name={repo_name.get()}/issues/new");
16-
set_pathname(url.clone());
16+
set_pathname(&url);
1717
};
1818
view! {
1919
<Button on:click=on_click>

web/src/app/repository/issues_tab/one_issue.rs

Lines changed: 62 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,18 @@ use futures::future::{join_all, OptionFuture};
22
use github_api::models::milestone::OpenOrClosed;
33
use jiff::Timestamp;
44
use leptos::prelude::*;
5+
use macros::zwang_url;
6+
use crate::app::routing::*;
57
use shared::{
68
avail::Avail,
9+
sync_engine::optimistic::db::MaybeOptimistic,
710
types::{
811
issue::{self, Issue},
912
issue_comment::{IssueComment, IssueIdIndex},
1013
user::User,
1114
},
1215
};
13-
use zwang_router::{ArgFromParent, RouteParams};
16+
use zwang_router::{set_pathname_untracked, ArgFromParent, RouteParams};
1417

1518
use crate::{
1619
app::{
@@ -39,34 +42,76 @@ pub fn OneIssue(
3942
repo_name,
4043
}): RouteParams<ParamsIssueNumberOwnerNameRepoName>,
4144
) -> impl IntoView {
45+
let prev_optimistic_id = RwSignal::new(None);
4246
let issue_number = move || issue_number.get().parse::<i64>();
4347
move || {
4448
let sync_engine = use_sync_engine();
4549
let issue_number = match issue_number() {
4650
Ok(i) => i,
4751
Err(_) => return view! { <NotFound /> }.into_any(),
4852
};
53+
let sync_engine2 = sync_engine.clone();
4954
let issue_and_user = sync_engine.idb_signal(
5055
move |txn| txn.with_store::<User>().with_store::<Issue>().build(),
51-
move |txn| async move {
52-
let issue = txn
53-
.object_store::<Issue>()?
54-
.index::<issue::RepositoryIdIndex>()?
55-
.get_all_optimistically(Some(&repository_page_context.read().repository.id))
56-
.await?
57-
.into_iter()
58-
.find(move |i| i.number == issue_number);
56+
move |txn| {
57+
let sync_engine2 = sync_engine2.clone();
58+
async move {
59+
let issue = txn
60+
.object_store::<Issue>()?
61+
.index::<issue::RepositoryIdIndex>()?
62+
.get_all_optimistically(Some(&repository_page_context.read().repository.id))
63+
.await?
64+
.into_iter()
65+
.find(move |i| i.number == issue_number);
5966

60-
Ok(if let Some(issue) = issue {
61-
let user = if let Avail::Yes(Some(user_id)) = issue.user_id {
62-
txn.object_store::<User>()?.get_optimistically(&user_id).await?
67+
let issue = if let Some(issue) = issue {
68+
Some(issue)
6369
} else {
64-
None
70+
if let Some(prev_optimistic_id) = prev_optimistic_id.get_untracked() {
71+
if let Some(realistic_id) = sync_engine2
72+
.db
73+
.get_optimistic_to_realistic_for_creations::<Issue>(
74+
&prev_optimistic_id,
75+
)
76+
{
77+
let issue = txn.object_store::<Issue>()?
78+
.get(&realistic_id)
79+
.await?
80+
.map(|issue| MaybeOptimistic::new(issue, false));
81+
82+
if let Some(issue) = &issue {
83+
set_pathname_untracked(&zwang_url!("/owner_name={owner_name.get()}/repo_name={repo_name.get()}/issues/issue_number={issue.number.to_string()}"));
84+
}
85+
86+
issue
87+
} else {
88+
None
89+
}
90+
} else {
91+
None
92+
}
6593
};
66-
Some((issue, user))
67-
} else {
68-
None
69-
})
94+
95+
Ok(if let Some(issue) = issue {
96+
if issue.is_optimistic {
97+
*prev_optimistic_id.write_untracked() = Some(issue.id);
98+
} else {
99+
*prev_optimistic_id.write_untracked() = None;
100+
}
101+
102+
let user = if let Avail::Yes(Some(user_id)) = issue.user_id {
103+
txn.object_store::<User>()?
104+
.get_optimistically(&user_id)
105+
.await?
106+
} else {
107+
None
108+
};
109+
Some((issue, user))
110+
} else {
111+
*prev_optimistic_id.write_untracked() = None;
112+
None
113+
})
114+
}
70115
},
71116
);
72117

web/src/app/repository/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ pub fn RepositoryPage(
8585
} = params;
8686

8787
let set_active_tab = move |new_active_tab: Tab| {
88-
set_pathname(Root::OwnerName {
88+
set_pathname(&Root::OwnerName {
8989
owner_name: owner_name.get_untracked(),
9090
child: RootOwnerName::RepoName {
9191
repo_name: repo_name.get_untracked(),

zwang_router/src/lib.rs

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use serde::de::DeserializeOwned;
77
use std::{fmt::Display, ops::Deref, sync::Arc};
88
use wasm_bindgen::{prelude::Closure, JsCast, JsValue};
99

10-
pub use macros::{zwang_url, zwang_routes};
10+
pub use macros::{zwang_routes, zwang_url};
1111

1212
pub trait MemoExt<T>
1313
where
@@ -236,13 +236,17 @@ pub fn use_pathname() -> ArcMemo<String> {
236236
PATHNAME_MANAGER.with(|i| i.pathname.clone())
237237
}
238238

239-
pub fn set_pathname(path: impl ToString) {
239+
pub fn set_pathname(path: &dyn ToString) {
240+
set_pathname_untracked(path);
241+
PATHNAME_MANAGER.with(|i| (i.set_pathname)(window().location().pathname().expect("")));
242+
}
243+
244+
pub fn set_pathname_untracked(path: &dyn ToString) {
240245
window()
241246
.history()
242247
.expect("")
243248
.push_state_with_url(&JsValue::NULL, "", Some(&path.to_string()))
244249
.expect("");
245-
PATHNAME_MANAGER.with(|i| (i.set_pathname)(window().location().pathname().expect("")));
246250
}
247251

248252
pub fn set_search(search: impl ToString) {
@@ -275,7 +279,7 @@ pub fn A(
275279
class=class
276280
href=href.clone()
277281
on:click=move |ev| {
278-
set_pathname(href.clone());
282+
set_pathname(&href);
279283
ev.prevent_default();
280284
}
281285
>
@@ -307,8 +311,7 @@ impl std::fmt::Display for NoPart {
307311
}
308312
}
309313

310-
pub fn empty_component<ArgFromParent>(_: ArgFromParent) -> impl IntoView {
311-
}
314+
pub fn empty_component<ArgFromParent>(_: ArgFromParent) -> impl IntoView {}
312315

313316
pub fn passthrough_component<A, V>(
314317
ArgFromParent(arg_from_parent): ArgFromParent<A>,

0 commit comments

Comments
 (0)