Commit 14712b42 authored by Steven's avatar Steven

chore: add pagination to list inboxes

parent b4d72e33
......@@ -61,10 +61,20 @@ message Inbox {
message ListInboxesRequest {
// Format: users/{id}
string user = 1;
// The maximum number of inbox to return.
int32 page_size = 2;
// Provide this to retrieve the subsequent page.
string page_token = 3;
}
message ListInboxesResponse {
repeated Inbox inboxes = 1;
// A token, which can be sent as `page_token` to retrieve the next page.
// If this field is omitted, there are no subsequent pages.
string next_page_token = 2;
}
message UpdateInboxRequest {
......
This diff is collapsed.
......@@ -194,6 +194,17 @@ paths:
in: query
required: false
type: string
- name: pageSize
description: The maximum number of inbox to return.
in: query
required: false
type: integer
format: int32
- name: pageToken
description: Provide this to retrieve the subsequent page.
in: query
required: false
type: string
tags:
- InboxService
/api/v1/markdown/link:metadata:
......@@ -2491,6 +2502,11 @@ definitions:
items:
type: object
$ref: '#/definitions/v1Inbox'
nextPageToken:
type: string
description: |-
A token, which can be sent as `page_token` to retrieve the next page.
If this field is omitted, there are no subsequent pages.
v1ListMemoCommentsResponse:
type: object
properties:
......
......@@ -14,30 +14,58 @@ import (
"github.com/usememos/memos/store"
)
func (s *APIV1Service) ListInboxes(ctx context.Context, _ *v1pb.ListInboxesRequest) (*v1pb.ListInboxesResponse, error) {
func (s *APIV1Service) ListInboxes(ctx context.Context, request *v1pb.ListInboxesRequest) (*v1pb.ListInboxesResponse, error) {
user, err := s.GetCurrentUser(ctx)
if err != nil {
return nil, status.Errorf(codes.Internal, "failed to get user")
}
var limit, offset int
if request.PageToken != "" {
var pageToken v1pb.PageToken
if err := unmarshalPageToken(request.PageToken, &pageToken); err != nil {
return nil, status.Errorf(codes.InvalidArgument, "invalid page token: %v", err)
}
limit = int(pageToken.Limit)
offset = int(pageToken.Offset)
} else {
limit = int(request.PageSize)
}
if limit <= 0 {
limit = DefaultPageSize
}
limitPlusOne := limit + 1
inboxes, err := s.Store.ListInboxes(ctx, &store.FindInbox{
ReceiverID: &user.ID,
Limit: &limitPlusOne,
Offset: &offset,
})
if err != nil {
return nil, status.Errorf(codes.Internal, "failed to list inbox: %v", err)
}
response := &v1pb.ListInboxesResponse{
Inboxes: []*v1pb.Inbox{},
inboxMessages := []*v1pb.Inbox{}
nextPageToken := ""
if len(inboxes) == limitPlusOne {
inboxes = inboxes[:limit]
nextPageToken, err = getPageToken(limit, offset+limit)
if err != nil {
return nil, status.Errorf(codes.Internal, "failed to get next page token, error: %v", err)
}
}
for _, inbox := range inboxes {
inboxMessage := convertInboxFromStore(inbox)
if inboxMessage.Type == v1pb.Inbox_TYPE_UNSPECIFIED {
continue
}
response.Inboxes = append(response.Inboxes, inboxMessage)
inboxMessages = append(inboxMessages, inboxMessage)
}
response := &v1pb.ListInboxesResponse{
Inboxes: inboxMessages,
NextPageToken: nextPageToken,
}
return response, nil
}
......
......@@ -30,6 +30,7 @@ import (
)
const (
// DefaultPageSize is the default page size for listing memos.
DefaultPageSize = 10
)
......
......@@ -2,6 +2,7 @@ package mysql
import (
"context"
"fmt"
"strings"
"github.com/pkg/errors"
......@@ -61,6 +62,12 @@ func (d *DB) ListInboxes(ctx context.Context, find *store.FindInbox) ([]*store.I
}
query := "SELECT `id`, UNIX_TIMESTAMP(`created_ts`), `sender_id`, `receiver_id`, `status`, `message` FROM `inbox` WHERE " + strings.Join(where, " AND ") + " ORDER BY `created_ts` DESC"
if find.Limit != nil {
query = fmt.Sprintf("%s LIMIT %d", query, *find.Limit)
if find.Offset != nil {
query = fmt.Sprintf("%s OFFSET %d", query, *find.Offset)
}
}
rows, err := d.db.QueryContext(ctx, query, args...)
if err != nil {
return nil, err
......
......@@ -2,6 +2,7 @@ package postgres
import (
"context"
"fmt"
"strings"
"github.com/pkg/errors"
......@@ -51,6 +52,12 @@ func (d *DB) ListInboxes(ctx context.Context, find *store.FindInbox) ([]*store.I
}
query := "SELECT id, created_ts, sender_id, receiver_id, status, message FROM inbox WHERE " + strings.Join(where, " AND ") + " ORDER BY created_ts DESC"
if find.Limit != nil {
query = fmt.Sprintf("%s LIMIT %d", query, *find.Limit)
if find.Offset != nil {
query = fmt.Sprintf("%s OFFSET %d", query, *find.Offset)
}
}
rows, err := d.db.QueryContext(ctx, query, args...)
if err != nil {
return nil, err
......
......@@ -2,6 +2,7 @@ package sqlite
import (
"context"
"fmt"
"strings"
"github.com/pkg/errors"
......@@ -53,6 +54,12 @@ func (d *DB) ListInboxes(ctx context.Context, find *store.FindInbox) ([]*store.I
}
query := "SELECT `id`, `created_ts`, `sender_id`, `receiver_id`, `status`, `message` FROM `inbox` WHERE " + strings.Join(where, " AND ") + " ORDER BY `created_ts` DESC"
if find.Limit != nil {
query = fmt.Sprintf("%s LIMIT %d", query, *find.Limit)
if find.Offset != nil {
query = fmt.Sprintf("%s OFFSET %d", query, *find.Offset)
}
}
rows, err := d.db.QueryContext(ctx, query, args...)
if err != nil {
return nil, err
......
......@@ -37,6 +37,10 @@ type FindInbox struct {
SenderID *int32
ReceiverID *int32
Status *InboxStatus
// Pagination
Limit *int
Offset *int
}
type DeleteInbox struct {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment