refactor 2
This commit is contained in:
@@ -393,16 +393,6 @@ impl InboxView {
|
||||
return;
|
||||
};
|
||||
|
||||
let Some(announcement) = RepoListStore::global(cx)
|
||||
.read(cx)
|
||||
.announcements
|
||||
.iter()
|
||||
.find(|announcement| announcement.addr() == address)
|
||||
.cloned()
|
||||
else {
|
||||
return;
|
||||
};
|
||||
|
||||
let item = match kind {
|
||||
Some(Kind::GitIssue) => RepoItem::Issue(root),
|
||||
Some(Kind::GitPullRequest) => RepoItem::PullRequest(root),
|
||||
@@ -410,7 +400,7 @@ impl InboxView {
|
||||
_ => return,
|
||||
};
|
||||
|
||||
open_repo_item(&self.dock_area, &announcement, item, window, cx);
|
||||
open_repo_item(&self.dock_area, &address, None, item, window, cx);
|
||||
}
|
||||
|
||||
fn render_entry(&self, ix: usize, cx: &Context<Self>) -> AnyElement {
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
use std::path::PathBuf;
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
|
||||
use anyhow::Error;
|
||||
use dock::{DockArea, add_center_panel, panel_handle};
|
||||
@@ -8,8 +7,8 @@ use gpui::prelude::*;
|
||||
use gpui::{App, Context, Entity, WeakEntity, Window};
|
||||
use gpui_base::dock::PanelView;
|
||||
use nostr::prelude::EventId;
|
||||
use signed_core::{Announcement, filters};
|
||||
use signed_state::{Backend, RepoListStore, RepoStore};
|
||||
use signed_core::{Announcement, RepoAddr};
|
||||
use signed_state::RepoStore;
|
||||
|
||||
use super::RepoDetailView;
|
||||
use crate::views::issues::IssuesView;
|
||||
@@ -114,74 +113,20 @@ impl RepoDetailView {
|
||||
}
|
||||
|
||||
/// Open the upstream repository, the `u` tag of this fork's announcement.
|
||||
/// The upstream announcement may not be in the local database yet.
|
||||
/// Subscribe for it and open the panel as soon as it lands.
|
||||
///
|
||||
/// The announcement may not be in the local database yet. The panel opens
|
||||
/// from the address and fills in when the store loads it; the store's
|
||||
/// `subscribe_remote` fetches it from the bootstrap relays.
|
||||
pub(super) fn open_upstream(&mut self, window: &mut Window, cx: &mut Context<Self>) {
|
||||
if self.pending_upstream.is_some() {
|
||||
return;
|
||||
}
|
||||
|
||||
let Some(announcement) = self.announcement(cx).cloned() else {
|
||||
let Some(addr) = self
|
||||
.announcement(cx)
|
||||
.and_then(|announcement| announcement.upstream.as_ref())
|
||||
.and_then(|upstream| upstream.addr.clone())
|
||||
else {
|
||||
return;
|
||||
};
|
||||
|
||||
let Some(addr) = announcement.upstream.and_then(|upstream| upstream.addr) else {
|
||||
return;
|
||||
};
|
||||
|
||||
if let Some(found) = RepoListStore::global(cx)
|
||||
.read(cx)
|
||||
.announcements
|
||||
.iter()
|
||||
.find(|a| a.addr() == addr)
|
||||
.cloned()
|
||||
{
|
||||
open_repo_panel(&self.dock_area, &found, window, &mut *cx);
|
||||
return;
|
||||
}
|
||||
|
||||
let backend = Backend::global(cx);
|
||||
backend.update(cx, |backend, cx| {
|
||||
backend.subscribe_bootstrap(vec![filters::announcement(&addr)], cx);
|
||||
});
|
||||
self.pending_upstream = Some(addr);
|
||||
|
||||
let task: gpui::Task<Result<(), Error>> = cx.spawn_in(window, async move |this, cx| {
|
||||
for _ in 0..60 {
|
||||
cx.background_executor()
|
||||
.timer(Duration::from_millis(250))
|
||||
.await;
|
||||
|
||||
let opened = this.update_in(cx, |this, window, cx| {
|
||||
let Some(addr) = this.pending_upstream.clone() else {
|
||||
return true;
|
||||
};
|
||||
let found = RepoListStore::global(cx)
|
||||
.read(cx)
|
||||
.announcements
|
||||
.iter()
|
||||
.find(|a| a.addr() == addr)
|
||||
.cloned();
|
||||
match found {
|
||||
Some(found) => {
|
||||
this.pending_upstream = None;
|
||||
open_repo_panel(&this.dock_area, &found, window, &mut *cx);
|
||||
true
|
||||
}
|
||||
None => false,
|
||||
}
|
||||
})?;
|
||||
|
||||
if opened {
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
|
||||
this.update(cx, |this, _cx| this.pending_upstream = None)?;
|
||||
Ok(())
|
||||
});
|
||||
|
||||
task.detach();
|
||||
open_repo_panel(&self.dock_area, &addr, None, window, &mut *cx);
|
||||
}
|
||||
|
||||
/// Open the dialog guiding the user through publishing the local repository to NIP-34.
|
||||
@@ -194,15 +139,21 @@ impl RepoDetailView {
|
||||
}
|
||||
}
|
||||
|
||||
/// Open `announcement` as a repository panel in the dock's center.
|
||||
/// Open `addr`'s repository as a panel in the dock's center.
|
||||
///
|
||||
/// `hint` is an announcement already in hand for `addr`. It seeds the store's
|
||||
/// relays and lets the explorer load without waiting for the database; the
|
||||
/// store loads the announcement itself when the hint is absent, so an entry
|
||||
/// point with only an address works too.
|
||||
pub(crate) fn open_repo_panel(
|
||||
dock_area: &WeakEntity<DockArea>,
|
||||
announcement: &Announcement,
|
||||
addr: &RepoAddr,
|
||||
hint: Option<&Announcement>,
|
||||
window: &mut Window,
|
||||
cx: &mut App,
|
||||
) -> Entity<RepoDetailView> {
|
||||
let detail =
|
||||
cx.new(|cx| RepoDetailView::new(dock_area.clone(), announcement.clone(), window, cx));
|
||||
let detail = cx
|
||||
.new(|cx| RepoDetailView::new(dock_area.clone(), addr.clone(), hint.cloned(), window, cx));
|
||||
|
||||
if let Some(dock_area) = dock_area.upgrade() {
|
||||
dock_area.update(cx, |dock_area, cx| {
|
||||
@@ -213,9 +164,16 @@ pub(crate) fn open_repo_panel(
|
||||
detail
|
||||
}
|
||||
|
||||
/// The nostr store of `announcement`'s repository, without opening a repository panel.
|
||||
fn repo_store(announcement: &Announcement, cx: &mut App) -> Entity<RepoStore> {
|
||||
cx.new(|cx| RepoStore::new(announcement.addr(), announcement.relays.clone(), cx))
|
||||
/// The nostr store of `addr`'s repository, without opening a repository panel.
|
||||
///
|
||||
/// `hint` is an announcement already in hand for `addr`. It only seeds the
|
||||
/// relays to connect to right away; the store loads the announcement from the
|
||||
/// local database on its first pass, so the hint is optional.
|
||||
fn repo_store(addr: &RepoAddr, hint: Option<&Announcement>, cx: &mut App) -> Entity<RepoStore> {
|
||||
let relays = hint
|
||||
.map(|announcement| announcement.relays.clone())
|
||||
.unwrap_or_default();
|
||||
cx.new(|cx| RepoStore::new(addr.clone(), relays, cx))
|
||||
}
|
||||
|
||||
/// An item of a repository to open from outside its detail panel.
|
||||
@@ -226,16 +184,21 @@ pub(crate) enum RepoItem {
|
||||
Patch,
|
||||
}
|
||||
|
||||
/// Open the detail panel of `item` in `announcement`'s repository, in the dock's center.
|
||||
/// Open the detail panel of `item` in `addr`'s repository, in the dock's center.
|
||||
///
|
||||
/// The repository store is built here, not taken from a `RepoDetailView`, so the
|
||||
/// item panel is the only panel docked.
|
||||
///
|
||||
/// `hint` is an announcement already in hand for `addr`, e.g. the inbox row the
|
||||
/// item was clicked from. The store resolves the repository from the local
|
||||
/// database on its own, so an entry point with only the address works too.
|
||||
///
|
||||
/// A patch opens nothing: patches are only consumed inside a pull request's
|
||||
/// detail panel, and have no panel of their own.
|
||||
pub(crate) fn open_repo_item(
|
||||
dock_area: &WeakEntity<DockArea>,
|
||||
announcement: &Announcement,
|
||||
addr: &RepoAddr,
|
||||
hint: Option<&Announcement>,
|
||||
item: RepoItem,
|
||||
window: &mut Window,
|
||||
cx: &mut App,
|
||||
@@ -243,11 +206,11 @@ pub(crate) fn open_repo_item(
|
||||
let panel: Arc<dyn PanelView> =
|
||||
match item {
|
||||
RepoItem::Issue(issue_id) => {
|
||||
let store = repo_store(announcement, cx);
|
||||
let store = repo_store(addr, hint, cx);
|
||||
panel_handle(cx.new(|cx| IssueDetailView::new(store, issue_id, window, cx)))
|
||||
}
|
||||
RepoItem::PullRequest(pr_id) => {
|
||||
let store = repo_store(announcement, cx);
|
||||
let store = repo_store(addr, hint, cx);
|
||||
panel_handle(cx.new(|cx| {
|
||||
PullRequestDetailView::new(dock_area.clone(), store, pr_id, window, cx)
|
||||
}))
|
||||
|
||||
@@ -190,7 +190,7 @@ fn init_repository(
|
||||
window.close_dialog(cx);
|
||||
if let Some(view) = view.upgrade() {
|
||||
view.update(cx, |this, cx| {
|
||||
this.apply_announcement(announcement, cx);
|
||||
this.apply_announcement(announcement, window, cx);
|
||||
});
|
||||
}
|
||||
})
|
||||
|
||||
@@ -73,7 +73,8 @@ pub struct RepoDetailView {
|
||||
dock_area: WeakEntity<DockArea>,
|
||||
/// Snapshot taken at open time.
|
||||
///
|
||||
/// `None` for local repositories that haven't been published yet.
|
||||
/// `None` for local repositories that haven't been published yet, and for a
|
||||
/// repository opened by address until its store loads the announcement.
|
||||
initial: Option<Announcement>,
|
||||
/// Per-repository nostr store, holding announcement, issues, PRs and statuses.
|
||||
///
|
||||
@@ -162,37 +163,32 @@ pub struct RepoDetailView {
|
||||
/// The global checkouts store's ready-to-push statuses of this repository,
|
||||
/// last seen when they drove a render.
|
||||
push_statuses: Vec<CheckoutStatus>,
|
||||
/// Upstream repository, from this fork's `u` tag, the user asked to open.
|
||||
/// Its announcement is still being fetched.
|
||||
pending_upstream: Option<RepoAddr>,
|
||||
}
|
||||
|
||||
impl RepoDetailView {
|
||||
/// Open a repository announced.
|
||||
/// Open a repository by address.
|
||||
///
|
||||
/// The store connects to the announcement's relays and loads issues, PRs and statuses.
|
||||
/// `hint` is an announcement already in hand. It seeds the store's relays
|
||||
/// and the explorer's clone URLs; without it the panel waits for the store
|
||||
/// to load the announcement from the local database.
|
||||
pub fn new(
|
||||
dock_area: WeakEntity<DockArea>,
|
||||
initial: Announcement,
|
||||
addr: RepoAddr,
|
||||
hint: Option<Announcement>,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
) -> Self {
|
||||
// The announcement we opened from already carries the NIP-34 `relays` tag.
|
||||
//
|
||||
// The store connects to those relays immediately, no bootstrap fetch wait.
|
||||
let addr = initial.addr();
|
||||
let relays = initial.relays.clone();
|
||||
let relays = hint
|
||||
.as_ref()
|
||||
.map(|announcement| announcement.relays.clone())
|
||||
.unwrap_or_default();
|
||||
let store = cx.new(|cx| RepoStore::new(addr, relays, cx));
|
||||
|
||||
let mut view = Self::new_common(
|
||||
dock_area,
|
||||
Some(initial),
|
||||
Some(store.clone()),
|
||||
None,
|
||||
window,
|
||||
cx,
|
||||
);
|
||||
view.attach_store(&store, cx);
|
||||
let mut view = Self::new_common(dock_area, hint, Some(store.clone()), None, window, cx);
|
||||
view.attach_store(&store, window, cx);
|
||||
view
|
||||
}
|
||||
|
||||
@@ -313,7 +309,6 @@ impl RepoDetailView {
|
||||
ready_head: None,
|
||||
ready_statuses: Vec::new(),
|
||||
push_statuses: Vec::new(),
|
||||
pending_upstream: None,
|
||||
focus_handle: cx.focus_handle(),
|
||||
_subscriptions: subscriptions,
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use gpui::prelude::*;
|
||||
use gpui::{Context, Entity};
|
||||
use gpui::{Context, Entity, Window};
|
||||
use signed_core::Announcement;
|
||||
use signed_state::{Backend, CheckoutsStore, LocalReposStore, RepoStore};
|
||||
|
||||
@@ -13,6 +13,7 @@ impl RepoDetailView {
|
||||
pub(crate) fn apply_announcement(
|
||||
&mut self,
|
||||
announcement: Announcement,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
) {
|
||||
// The repository is no longer a bare local repo.
|
||||
@@ -24,7 +25,7 @@ impl RepoDetailView {
|
||||
cx.new(|cx| RepoStore::new(announcement.addr(), announcement.relays.clone(), cx));
|
||||
// Re-render on store refreshes, issues, PRs and statuses.
|
||||
// Keep the ready-to-contribute statuses of this repository requested.
|
||||
self.attach_store(&store, cx);
|
||||
self.attach_store(&store, window, cx);
|
||||
self.store = Some(store);
|
||||
self.initial = Some(announcement);
|
||||
cx.notify();
|
||||
@@ -32,11 +33,27 @@ impl RepoDetailView {
|
||||
|
||||
/// Observe the repository's store, re-render on refreshes.
|
||||
/// Request the ready-to-contribute statuses for it.
|
||||
pub(super) fn attach_store(&mut self, store: &Entity<RepoStore>, cx: &mut Context<Self>) {
|
||||
pub(super) fn attach_store(
|
||||
&mut self,
|
||||
store: &Entity<RepoStore>,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
) {
|
||||
self._subscriptions
|
||||
.push(cx.observe(store, |this, _store, cx| {
|
||||
log::debug!("repo detail: store notify");
|
||||
.push(cx.observe_in(store, window, |this, store, window, cx| {
|
||||
this.refresh_ready_statuses(cx);
|
||||
|
||||
// A repository opened from its address alone starts without an
|
||||
// announcement. Adopt the store's first one so the explorer can
|
||||
// load; later passes leave the snapshot and the selection alone.
|
||||
let announcement = store.read(cx).announcement.clone();
|
||||
if this.initial.is_none()
|
||||
&& let Some(announcement) = announcement
|
||||
{
|
||||
this.initial = Some(announcement);
|
||||
this.load_repo(window, cx);
|
||||
}
|
||||
|
||||
cx.notify();
|
||||
}));
|
||||
self.refresh_ready_statuses(cx);
|
||||
|
||||
@@ -189,7 +189,13 @@ impl RepoListView {
|
||||
window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
) {
|
||||
open_repo_panel(&self.dock_area, announcement, window, cx);
|
||||
open_repo_panel(
|
||||
&self.dock_area,
|
||||
&announcement.addr(),
|
||||
Some(announcement),
|
||||
window,
|
||||
cx,
|
||||
);
|
||||
}
|
||||
|
||||
fn render_card(
|
||||
|
||||
@@ -257,5 +257,11 @@ fn open_repo(
|
||||
window: &mut Window,
|
||||
cx: &mut App,
|
||||
) {
|
||||
open_repo_panel(&dock_area, &announcement, window, cx);
|
||||
open_repo_panel(
|
||||
&dock_area,
|
||||
&announcement.addr(),
|
||||
Some(&announcement),
|
||||
window,
|
||||
cx,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -260,7 +260,13 @@ impl SidebarPanel {
|
||||
window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
) {
|
||||
open_repo_panel(&self.dock_area, announcement, window, &mut *cx);
|
||||
open_repo_panel(
|
||||
&self.dock_area,
|
||||
&announcement.addr(),
|
||||
Some(announcement),
|
||||
window,
|
||||
&mut *cx,
|
||||
);
|
||||
}
|
||||
|
||||
/// Open a local repository's detail view in the dock's center.
|
||||
|
||||
Reference in New Issue
Block a user