Fix inbox pagination cursor and sorting

This commit is contained in:
Sebastian Martinez
2025-04-08 17:53:04 +02:00
parent 7f487be94b
commit 74bb631381
7 changed files with 44 additions and 51 deletions
+5 -9
View File
@@ -1,14 +1,13 @@
use std::collections::BTreeMap;
use radicle::identity::DocAt;
use radicle::identity;
use radicle::issue::cache::Issues;
use radicle::node;
use radicle::patch::cache::Patches;
use radicle::storage::{ReadRepository, ReadStorage};
use radicle::{git, identity};
use radicle_types::cobs::PaginatedQuery;
use radicle_types::domain::inbox::models::notification;
use radicle_types::domain::inbox::models::notification::{self, RepoGroupByItem};
use radicle_types::domain::inbox::service::Service;
use radicle_types::domain::inbox::traits::InboxService;
use radicle_types::error::Error;
@@ -20,10 +19,7 @@ pub fn list_notifications(
ctx: tauri::State<AppState>,
sqlite_service: tauri::State<Service<Sqlite>>,
params: notification::RepoGroupParams,
) -> Result<
PaginatedQuery<BTreeMap<git::Qualified<'static>, Vec<notification::NotificationItem>>>,
Error,
> {
) -> Result<PaginatedQuery<RepoGroupByItem>, Error> {
let profile = &ctx.profile;
let aliases = profile.aliases();
let cursor = params.skip.unwrap_or(0);
@@ -127,7 +123,7 @@ pub fn list_notifications(
(qualified, items)
})
.filter(|(_, v)| !v.is_empty())
.collect::<BTreeMap<git::Qualified<'static>, Vec<notification::NotificationItem>>>();
.collect::<RepoGroupByItem>();
Ok(PaginatedQuery {
cursor,
@@ -147,7 +143,7 @@ pub fn count_notifications_by_repo(
.filter_map(|s| {
let (rid, count) = s.ok()?;
let repo = profile.storage.repository(rid).ok()?;
let DocAt { doc, .. } = repo.identity_doc().ok()?;
let identity::DocAt { doc, .. } = repo.identity_doc().ok()?;
let project = doc.project().ok()?;
Some((
@@ -33,7 +33,8 @@ pub struct NotificationRow {
pub new: Option<git::Oid>,
}
pub type RepoGroup = std::collections::BTreeMap<git::Qualified<'static>, Vec<NotificationRow>>;
pub type RepoGroup = Vec<(git::Qualified<'static>, Vec<NotificationRow>)>;
pub type RepoGroupByItem = Vec<(git::Qualified<'static>, Vec<NotificationItem>)>;
pub type CountByRepo = (identity::RepoId, usize);
#[derive(Clone, Debug)]
@@ -1,7 +1,5 @@
use radicle::git;
use crate::domain::inbox::models::notification::{
CountByRepo, ListNotificationsError, NotificationRow, RepoGroupParams,
CountByRepo, ListNotificationsError, RepoGroup, RepoGroupParams,
};
use crate::domain::inbox::traits::{InboxService, InboxStorage};
@@ -35,13 +33,7 @@ where
self.inbox.counts_by_repo()
}
fn repo_group(
&self,
params: RepoGroupParams,
) -> Result<
std::collections::BTreeMap<git::Qualified<'static>, Vec<NotificationRow>>,
ListNotificationsError,
> {
fn repo_group(&self, params: RepoGroupParams) -> Result<RepoGroup, ListNotificationsError> {
self.inbox.repo_group(params)
}
}
+18 -15
View File
@@ -1,4 +1,3 @@
use std::collections::BTreeMap;
use std::path::Path;
use std::str::FromStr;
use std::sync::Arc;
@@ -137,17 +136,24 @@ impl InboxStorage for Sqlite {
fn repo_group(
&self,
params: notification::RepoGroupParams,
) -> Result<
std::collections::BTreeMap<git::Qualified<'static>, Vec<notification::NotificationRow>>,
notification::ListNotificationsError,
> {
) -> Result<notification::RepoGroup, notification::ListNotificationsError> {
let mut stmt = self.db.prepare(
"SELECT ref, substr(ref, 66) ref_without_namespace, json_group_array(json_object('row_id', rowid, 'timestamp', timestamp, 'remote', substr(ref, 17, 48), 'old', old, 'new', new)) as value
FROM 'repository-notifications'
WHERE repo = ?
GROUP BY ref_without_namespace
ORDER BY timestamp DESC"
)?;
"SELECT ref, substr(ref, 66) ref_without_namespace,
json_group_array(
json_object(
'row_id', rowid,
'timestamp', timestamp,
'remote', substr(ref, 17, 48),
'old', old,
'new', new
)
) as value,
MAX(timestamp) AS latest_timestamp
FROM 'repository-notifications'
WHERE repo = ?
GROUP BY ref_without_namespace
ORDER BY latest_timestamp DESC",
)?;
stmt.bind((1, &params.repo))?;
stmt.into_iter()
@@ -160,9 +166,6 @@ impl InboxStorage for Sqlite {
Ok((reference.to_owned(), items))
})
.collect::<Result<
BTreeMap<git::Qualified<'static>, Vec<notification::NotificationRow>>,
notification::ListNotificationsError,
>>()
.collect::<Result<notification::RepoGroup, notification::ListNotificationsError>>()
}
}
+2 -2
View File
@@ -13,7 +13,7 @@
clearByIds: (rid: string, ids: string[]) => Promise<void>;
clearByRepo: (rid: string) => Promise<void>;
repo: HomeInboxTab;
items: Record<string, NotificationItem[]>;
items: [string, NotificationItem[]][];
more: boolean;
}
@@ -58,7 +58,7 @@
{/if}
<div class="container">
{#each Object.entries(items).sort((a, b) => b[1][0].timestamp - a[1][0].timestamp) as [_, notificationItems]}
{#each items.sort((a, b) => b[1][0].timestamp - a[1][0].timestamp) as [_, notificationItems]}
<NotificationTeaser
{clearByIds}
rid={repo.rid}
+3 -3
View File
@@ -49,7 +49,7 @@ interface LoadedInboxRoute {
string,
{
repo: HomeInboxTab;
items: Record<string, NotificationItem[]>;
items: [string, NotificationItem[]][];
pagination: { cursor: number; more: boolean };
}
>;
@@ -115,7 +115,7 @@ export async function loadRoute(
new SvelteMap();
if (route.activeTab) {
const items = await invoke<
PaginatedQuery<Record<string, NotificationItem[]>>
PaginatedQuery<[string, NotificationItem[]][]>
>("list_notifications", {
params: {
repo: route.activeTab.rid,
@@ -129,7 +129,7 @@ export async function loadRoute(
} else {
for (const [rid, item] of notificationCount) {
const result = await invoke<
PaginatedQuery<Record<string, NotificationItem[]>>
PaginatedQuery<[string, NotificationItem[]][]>
>("list_notifications", {
params: {
repo: rid,
+12 -11
View File
@@ -25,7 +25,7 @@
string,
{
repo: HomeInboxTab;
items: Record<string, NotificationItem[]>;
items: [string, NotificationItem[]][];
pagination: { cursor: number; more: boolean };
}
>;
@@ -95,7 +95,7 @@
async function reload(rids: string[]) {
for (const rid of rids) {
const [n, count] = await Promise.all([
invoke<PaginatedQuery<Record<string, NotificationItem[]>>>(
invoke<PaginatedQuery<[string, NotificationItem[]][]>>(
"list_notifications",
{
params: {
@@ -124,16 +124,17 @@
async function loadMoreContent() {
if (more && activeTab) {
const c = cursor ? cursor : 20;
const p = await invoke<
PaginatedQuery<Record<string, NotificationItem[]>>
>("list_notifications", {
params: {
repo: activeTab.rid,
skip: more ? c + 20 : c,
take: 20,
const c = cursor ? cursor : 0;
const p = await invoke<PaginatedQuery<[string, NotificationItem[]][]>>(
"list_notifications",
{
params: {
repo: activeTab.rid,
skip: more ? c + 20 : c,
take: 20,
},
},
});
);
cursor = p.cursor;
more = p.more;