Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
C
canifa_note
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Vũ Hoàng Anh
canifa_note
Commits
9972a77d
Commit
9972a77d
authored
Jun 18, 2025
by
Steven
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
refactor: memo service
parent
91c2a4ce
Changes
21
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
21 changed files
with
2413 additions
and
1012 deletions
+2413
-1012
memo_service.proto
proto/api/v1/memo_service.proto
+331
-94
reaction_service.proto
proto/api/v1/reaction_service.proto
+0
-19
memo_service.pb.go
proto/gen/api/v1/memo_service.pb.go
+817
-380
memo_service.pb.gw.go
proto/gen/api/v1/memo_service.pb.gw.go
+123
-11
reaction_service.pb.go
proto/gen/api/v1/reaction_service.pb.go
+0
-155
apidocs.swagger.yaml
proto/gen/apidocs.swagger.yaml
+344
-116
memo_service.go
server/router/api/v1/memo_service.go
+52
-4
reaction_service.go
server/router/api/v1/reaction_service.go
+13
-2
resource_name.go
server/router/api/v1/resource_name.go
+15
-0
reaction.go
store/reaction.go
+0
-1
index.tsx
web/src/components/MemoEditor/index.tsx
+4
-0
MemoReactionListView.tsx
web/src/components/MemoReactionListView.tsx
+1
-1
PagedMemoList.tsx
web/src/components/PagedMemoList/PagedMemoList.tsx
+4
-4
ReactionSelector.tsx
web/src/components/ReactionSelector.tsx
+1
-1
ReactionView.tsx
web/src/components/ReactionView.tsx
+1
-1
Archived.tsx
web/src/pages/Archived.tsx
+2
-2
Explore.tsx
web/src/pages/Explore.tsx
+2
-2
Home.tsx
web/src/pages/Home.tsx
+2
-2
UserProfile.tsx
web/src/pages/UserProfile.tsx
+2
-2
memo_service.ts
web/src/types/proto/api/v1/memo_service.ts
+699
-93
reaction_service.ts
web/src/types/proto/api/v1/reaction_service.ts
+0
-122
No files found.
proto/api/v1/memo_service.proto
View file @
9972a77d
This diff is collapsed.
Click to expand it.
proto/api/v1/reaction_service.proto
deleted
100644 → 0
View file @
91c2a4ce
syntax
=
"proto3"
;
package
memos
.
api.v1
;
option
go_package
=
"gen/api/v1"
;
message
Reaction
{
int32
id
=
1
;
// The name of the creator.
// Format: users/{user}
string
creator
=
2
;
// The content identifier.
// For memo, it should be the `Memo.name`.
string
content_id
=
3
;
string
reaction_type
=
4
;
}
proto/gen/api/v1/memo_service.pb.go
View file @
9972a77d
This diff is collapsed.
Click to expand it.
proto/gen/api/v1/memo_service.pb.gw.go
View file @
9972a77d
This diff is collapsed.
Click to expand it.
proto/gen/api/v1/reaction_service.pb.go
deleted
100644 → 0
View file @
91c2a4ce
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.36.6
// protoc (unknown)
// source: api/v1/reaction_service.proto
package
apiv1
import
(
protoreflect
"google.golang.org/protobuf/reflect/protoreflect"
protoimpl
"google.golang.org/protobuf/runtime/protoimpl"
reflect
"reflect"
sync
"sync"
unsafe
"unsafe"
)
const
(
// Verify that this generated code is sufficiently up-to-date.
_
=
protoimpl
.
EnforceVersion
(
20
-
protoimpl
.
MinVersion
)
// Verify that runtime/protoimpl is sufficiently up-to-date.
_
=
protoimpl
.
EnforceVersion
(
protoimpl
.
MaxVersion
-
20
)
)
type
Reaction
struct
{
state
protoimpl
.
MessageState
`protogen:"open.v1"`
Id
int32
`protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"`
// The name of the creator.
// Format: users/{user}
Creator
string
`protobuf:"bytes,2,opt,name=creator,proto3" json:"creator,omitempty"`
// The content identifier.
// For memo, it should be the `Memo.name`.
ContentId
string
`protobuf:"bytes,3,opt,name=content_id,json=contentId,proto3" json:"content_id,omitempty"`
ReactionType
string
`protobuf:"bytes,4,opt,name=reaction_type,json=reactionType,proto3" json:"reaction_type,omitempty"`
unknownFields
protoimpl
.
UnknownFields
sizeCache
protoimpl
.
SizeCache
}
func
(
x
*
Reaction
)
Reset
()
{
*
x
=
Reaction
{}
mi
:=
&
file_api_v1_reaction_service_proto_msgTypes
[
0
]
ms
:=
protoimpl
.
X
.
MessageStateOf
(
protoimpl
.
Pointer
(
x
))
ms
.
StoreMessageInfo
(
mi
)
}
func
(
x
*
Reaction
)
String
()
string
{
return
protoimpl
.
X
.
MessageStringOf
(
x
)
}
func
(
*
Reaction
)
ProtoMessage
()
{}
func
(
x
*
Reaction
)
ProtoReflect
()
protoreflect
.
Message
{
mi
:=
&
file_api_v1_reaction_service_proto_msgTypes
[
0
]
if
x
!=
nil
{
ms
:=
protoimpl
.
X
.
MessageStateOf
(
protoimpl
.
Pointer
(
x
))
if
ms
.
LoadMessageInfo
()
==
nil
{
ms
.
StoreMessageInfo
(
mi
)
}
return
ms
}
return
mi
.
MessageOf
(
x
)
}
// Deprecated: Use Reaction.ProtoReflect.Descriptor instead.
func
(
*
Reaction
)
Descriptor
()
([]
byte
,
[]
int
)
{
return
file_api_v1_reaction_service_proto_rawDescGZIP
(),
[]
int
{
0
}
}
func
(
x
*
Reaction
)
GetId
()
int32
{
if
x
!=
nil
{
return
x
.
Id
}
return
0
}
func
(
x
*
Reaction
)
GetCreator
()
string
{
if
x
!=
nil
{
return
x
.
Creator
}
return
""
}
func
(
x
*
Reaction
)
GetContentId
()
string
{
if
x
!=
nil
{
return
x
.
ContentId
}
return
""
}
func
(
x
*
Reaction
)
GetReactionType
()
string
{
if
x
!=
nil
{
return
x
.
ReactionType
}
return
""
}
var
File_api_v1_reaction_service_proto
protoreflect
.
FileDescriptor
const
file_api_v1_reaction_service_proto_rawDesc
=
""
+
"
\n
"
+
"
\x1d
api/v1/reaction_service.proto
\x12\f
memos.api.v1
\"
x
\n
"
+
"
\b
Reaction
\x12\x0e\n
"
+
"
\x02
id
\x18\x01
\x01
(
\x05
R
\x02
id
\x12\x18\n
"
+
"
\a
creator
\x18\x02
\x01
(
\t
R
\a
creator
\x12\x1d\n
"
+
"
\n
"
+
"content_id
\x18\x03
\x01
(
\t
R
\t
contentId
\x12
#
\n
"
+
"
\r
reaction_type
\x18\x04
\x01
(
\t
R
\f
reactionTypeB
\xac\x01\n
"
+
"
\x10
com.memos.api.v1B
\x14
ReactionServiceProtoP
\x01
Z0github.com/usememos/memos/proto/gen/api/v1;apiv1
\xa2\x02\x03
MAX
\xaa\x02\f
Memos.Api.V1
\xca\x02\f
Memos
\\
Api
\\
V1
\xe2\x02\x18
Memos
\\
Api
\\
V1
\\
GPBMetadata
\xea\x02\x0e
Memos::Api::V1b
\x06
proto3"
var
(
file_api_v1_reaction_service_proto_rawDescOnce
sync
.
Once
file_api_v1_reaction_service_proto_rawDescData
[]
byte
)
func
file_api_v1_reaction_service_proto_rawDescGZIP
()
[]
byte
{
file_api_v1_reaction_service_proto_rawDescOnce
.
Do
(
func
()
{
file_api_v1_reaction_service_proto_rawDescData
=
protoimpl
.
X
.
CompressGZIP
(
unsafe
.
Slice
(
unsafe
.
StringData
(
file_api_v1_reaction_service_proto_rawDesc
),
len
(
file_api_v1_reaction_service_proto_rawDesc
)))
})
return
file_api_v1_reaction_service_proto_rawDescData
}
var
file_api_v1_reaction_service_proto_msgTypes
=
make
([]
protoimpl
.
MessageInfo
,
1
)
var
file_api_v1_reaction_service_proto_goTypes
=
[]
any
{
(
*
Reaction
)(
nil
),
// 0: memos.api.v1.Reaction
}
var
file_api_v1_reaction_service_proto_depIdxs
=
[]
int32
{
0
,
// [0:0] is the sub-list for method output_type
0
,
// [0:0] is the sub-list for method input_type
0
,
// [0:0] is the sub-list for extension type_name
0
,
// [0:0] is the sub-list for extension extendee
0
,
// [0:0] is the sub-list for field type_name
}
func
init
()
{
file_api_v1_reaction_service_proto_init
()
}
func
file_api_v1_reaction_service_proto_init
()
{
if
File_api_v1_reaction_service_proto
!=
nil
{
return
}
type
x
struct
{}
out
:=
protoimpl
.
TypeBuilder
{
File
:
protoimpl
.
DescBuilder
{
GoPackagePath
:
reflect
.
TypeOf
(
x
{})
.
PkgPath
(),
RawDescriptor
:
unsafe
.
Slice
(
unsafe
.
StringData
(
file_api_v1_reaction_service_proto_rawDesc
),
len
(
file_api_v1_reaction_service_proto_rawDesc
)),
NumEnums
:
0
,
NumMessages
:
1
,
NumExtensions
:
0
,
NumServices
:
0
,
},
GoTypes
:
file_api_v1_reaction_service_proto_goTypes
,
DependencyIndexes
:
file_api_v1_reaction_service_proto_depIdxs
,
MessageInfos
:
file_api_v1_reaction_service_proto_msgTypes
,
}
.
Build
()
File_api_v1_reaction_service_proto
=
out
.
File
file_api_v1_reaction_service_proto_goTypes
=
nil
file_api_v1_reaction_service_proto_depIdxs
=
nil
}
proto/gen/apidocs.swagger.yaml
View file @
9972a77d
This diff is collapsed.
Click to expand it.
server/router/api/v1/memo_service.go
View file @
9972a77d
...
...
@@ -4,6 +4,7 @@ import (
"context"
"fmt"
"log/slog"
"strings"
"time"
"unicode/utf8"
...
...
@@ -99,9 +100,13 @@ func (s *APIV1Service) ListMemos(ctx context.Context, request *v1pb.ListMemosReq
// Exclude comments by default.
ExcludeComments
:
true
,
}
// Handle deprecated old_filter for backward compatibility
if
request
.
OldFilter
!=
""
&&
request
.
Filter
==
""
{
//nolint:staticcheck // SA1019: Using deprecated field for backward compatibility
if
err
:=
s
.
buildMemoFindWithFilter
(
ctx
,
memoFind
,
request
.
OldFilter
);
err
!=
nil
{
return
nil
,
status
.
Errorf
(
codes
.
InvalidArgument
,
"failed to build find memos with filter: %v"
,
err
)
}
}
if
request
.
Parent
!=
""
&&
request
.
Parent
!=
"users/-"
{
userID
,
err
:=
ExtractUserIDFromName
(
request
.
Parent
)
if
err
!=
nil
{
...
...
@@ -117,9 +122,17 @@ func (s *APIV1Service) ListMemos(ctx context.Context, request *v1pb.ListMemosReq
state
:=
store
.
Normal
memoFind
.
RowStatus
=
&
state
}
if
request
.
Direction
==
v1pb
.
Direction_ASC
{
memoFind
.
OrderByTimeAsc
=
true
// Parse order_by field (replaces the old sort and direction fields)
if
request
.
OrderBy
!=
""
{
if
err
:=
s
.
parseMemoOrderBy
(
request
.
OrderBy
,
memoFind
);
err
!=
nil
{
return
nil
,
status
.
Errorf
(
codes
.
InvalidArgument
,
"invalid order_by: %v"
,
err
)
}
}
else
{
// Default ordering by display_time desc
memoFind
.
OrderByTimeAsc
=
false
}
if
request
.
Filter
!=
""
{
if
err
:=
s
.
validateFilter
(
ctx
,
request
.
Filter
);
err
!=
nil
{
return
nil
,
status
.
Errorf
(
codes
.
InvalidArgument
,
"invalid filter: %v"
,
err
)
...
...
@@ -739,3 +752,38 @@ func substring(s string, length int) string {
return
s
[
:
byteIndex
]
}
// parseMemoOrderBy parses the order_by field and sets the appropriate ordering in memoFind.
func
(
*
APIV1Service
)
parseMemoOrderBy
(
orderBy
string
,
memoFind
*
store
.
FindMemo
)
error
{
// Parse order_by field like "display_time desc" or "create_time asc"
parts
:=
strings
.
Fields
(
strings
.
TrimSpace
(
orderBy
))
if
len
(
parts
)
==
0
{
return
errors
.
New
(
"empty order_by"
)
}
field
:=
parts
[
0
]
direction
:=
"desc"
// default
if
len
(
parts
)
>
1
{
direction
=
strings
.
ToLower
(
parts
[
1
])
if
direction
!=
"asc"
&&
direction
!=
"desc"
{
return
errors
.
Errorf
(
"invalid order direction: %s, must be 'asc' or 'desc'"
,
parts
[
1
])
}
}
switch
field
{
case
"display_time"
:
memoFind
.
OrderByTimeAsc
=
direction
==
"asc"
case
"create_time"
:
memoFind
.
OrderByTimeAsc
=
direction
==
"asc"
case
"update_time"
:
memoFind
.
OrderByUpdatedTs
=
true
memoFind
.
OrderByTimeAsc
=
direction
==
"asc"
case
"name"
:
// For ordering by memo name/id - not commonly used but supported
memoFind
.
OrderByTimeAsc
=
direction
==
"asc"
default
:
return
errors
.
Errorf
(
"unsupported order field: %s, supported fields are: display_time, create_time, update_time, name"
,
field
)
}
return
nil
}
server/router/api/v1/reaction_service.go
View file @
9972a77d
...
...
@@ -3,10 +3,12 @@ package v1
import
(
"context"
"fmt"
"time"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
"google.golang.org/protobuf/types/known/emptypb"
"google.golang.org/protobuf/types/known/timestamppb"
v1pb
"github.com/usememos/memos/proto/gen/api/v1"
"github.com/usememos/memos/store"
...
...
@@ -55,8 +57,13 @@ func (s *APIV1Service) UpsertMemoReaction(ctx context.Context, request *v1pb.Ups
}
func
(
s
*
APIV1Service
)
DeleteMemoReaction
(
ctx
context
.
Context
,
request
*
v1pb
.
DeleteMemoReactionRequest
)
(
*
emptypb
.
Empty
,
error
)
{
reactionID
,
err
:=
ExtractReactionIDFromName
(
request
.
Name
)
if
err
!=
nil
{
return
nil
,
status
.
Errorf
(
codes
.
InvalidArgument
,
"invalid reaction name: %v"
,
err
)
}
if
err
:=
s
.
Store
.
DeleteReaction
(
ctx
,
&
store
.
DeleteReaction
{
ID
:
re
quest
.
Id
,
ID
:
re
actionID
,
});
err
!=
nil
{
return
nil
,
status
.
Errorf
(
codes
.
Internal
,
"failed to delete reaction"
)
}
...
...
@@ -71,10 +78,14 @@ func (s *APIV1Service) convertReactionFromStore(ctx context.Context, reaction *s
if
err
!=
nil
{
return
nil
,
err
}
reactionUID
:=
fmt
.
Sprintf
(
"%d"
,
reaction
.
ID
)
return
&
v1pb
.
Reaction
{
Id
:
reaction
.
ID
,
Name
:
fmt
.
Sprintf
(
"%s%s"
,
ReactionNamePrefix
,
reactionUID
),
Uid
:
reactionUID
,
Creator
:
fmt
.
Sprintf
(
"%s%d"
,
UserNamePrefix
,
creator
.
ID
),
ContentId
:
reaction
.
ContentID
,
ReactionType
:
reaction
.
ReactionType
,
CreateTime
:
timestamppb
.
New
(
time
.
Unix
(
reaction
.
CreatedTs
,
0
)),
},
nil
}
server/router/api/v1/resource_name.go
View file @
9972a77d
...
...
@@ -14,6 +14,7 @@ const (
UserNamePrefix
=
"users/"
MemoNamePrefix
=
"memos/"
AttachmentNamePrefix
=
"attachments/"
ReactionNamePrefix
=
"reactions/"
InboxNamePrefix
=
"inboxes/"
IdentityProviderNamePrefix
=
"identityProviders/"
ActivityNamePrefix
=
"activities/"
...
...
@@ -93,6 +94,20 @@ func ExtractAttachmentUIDFromName(name string) (string, error) {
return
id
,
nil
}
// ExtractReactionIDFromName returns the reaction ID from a resource name.
// e.g., "reactions/123" -> 123.
func
ExtractReactionIDFromName
(
name
string
)
(
int32
,
error
)
{
tokens
,
err
:=
GetNameParentTokens
(
name
,
ReactionNamePrefix
)
if
err
!=
nil
{
return
0
,
err
}
id
,
err
:=
util
.
ConvertStringToInt32
(
tokens
[
0
])
if
err
!=
nil
{
return
0
,
errors
.
Errorf
(
"invalid reaction ID %q"
,
tokens
[
0
])
}
return
id
,
nil
}
// ExtractInboxIDFromName returns the inbox ID from a resource name.
func
ExtractInboxIDFromName
(
name
string
)
(
int32
,
error
)
{
tokens
,
err
:=
GetNameParentTokens
(
name
,
InboxNamePrefix
)
...
...
store/reaction.go
View file @
9972a77d
...
...
@@ -9,7 +9,6 @@ type Reaction struct {
CreatedTs
int64
CreatorID
int32
// ContentID is the id of the content that the reaction is for.
// This can be a memo. e.g. memos/101
ContentID
string
ReactionType
string
}
...
...
web/src/components/MemoEditor/index.tsx
View file @
9972a77d
...
...
@@ -396,6 +396,10 @@ const MemoEditor = observer((props: Props) => {
relations
:
state
.
relationList
,
location
:
state
.
location
,
}),
// Optional fields can be omitted
memoId
:
""
,
validateOnly
:
false
,
requestId
:
""
,
})
:
memoServiceClient
.
createMemoComment
({
...
...
web/src/components/MemoReactionListView.tsx
View file @
9972a77d
...
...
@@ -5,7 +5,7 @@ import useCurrentUser from "@/hooks/useCurrentUser";
import
{
userStore
}
from
"@/store/v2"
;
import
{
State
}
from
"@/types/proto/api/v1/common"
;
import
{
Memo
}
from
"@/types/proto/api/v1/memo_service"
;
import
{
Reaction
}
from
"@/types/proto/api/v1/
reaction
_service"
;
import
{
Reaction
}
from
"@/types/proto/api/v1/
memo
_service"
;
import
{
User
}
from
"@/types/proto/api/v1/user_service"
;
import
ReactionSelector
from
"./ReactionSelector"
;
import
ReactionView
from
"./ReactionView"
;
...
...
web/src/components/PagedMemoList/PagedMemoList.tsx
View file @
9972a77d
...
...
@@ -8,7 +8,7 @@ import { DEFAULT_LIST_MEMOS_PAGE_SIZE } from "@/helpers/consts";
import
useResponsiveWidth
from
"@/hooks/useResponsiveWidth"
;
import
{
Routes
}
from
"@/router"
;
import
{
memoStore
,
viewStore
}
from
"@/store/v2"
;
import
{
Direction
,
State
}
from
"@/types/proto/api/v1/common"
;
import
{
State
}
from
"@/types/proto/api/v1/common"
;
import
{
Memo
}
from
"@/types/proto/api/v1/memo_service"
;
import
{
useTranslate
}
from
"@/utils/i18n"
;
import
Empty
from
"../Empty"
;
...
...
@@ -20,7 +20,7 @@ interface Props {
listSort
?:
(
list
:
Memo
[])
=>
Memo
[];
owner
?:
string
;
state
?:
State
;
direction
?:
Direction
;
orderBy
?:
string
;
filter
?:
string
;
oldFilter
?:
string
;
pageSize
?:
number
;
...
...
@@ -51,7 +51,7 @@ const PagedMemoList = observer((props: Props) => {
const
response
=
await
memoStore
.
fetchMemos
({
parent
:
props
.
owner
||
""
,
state
:
props
.
state
||
State
.
NORMAL
,
direction
:
props
.
direction
||
Direction
.
DESC
,
orderBy
:
props
.
orderBy
||
"display_time desc"
,
filter
:
props
.
filter
||
""
,
oldFilter
:
props
.
oldFilter
||
""
,
pageSize
:
props
.
pageSize
||
DEFAULT_LIST_MEMOS_PAGE_SIZE
,
...
...
@@ -103,7 +103,7 @@ const PagedMemoList = observer((props: Props) => {
// Initial load and reload when props change
useEffect
(()
=>
{
refreshList
();
},
[
props
.
owner
,
props
.
state
,
props
.
direction
,
props
.
filter
,
props
.
oldFilter
,
props
.
pageSize
]);
},
[
props
.
owner
,
props
.
state
,
props
.
orderBy
,
props
.
filter
,
props
.
oldFilter
,
props
.
pageSize
]);
// Auto-fetch more content when list changes and page isn't full
useEffect
(()
=>
{
...
...
web/src/components/ReactionSelector.tsx
View file @
9972a77d
...
...
@@ -36,7 +36,7 @@ const ReactionSelector = observer((props: Props) => {
(
reaction
)
=>
reaction
.
reactionType
===
reactionType
&&
reaction
.
creator
===
currentUser
.
name
,
);
for
(
const
reaction
of
reactions
)
{
await
memoServiceClient
.
deleteMemoReaction
({
id
:
reaction
.
id
});
await
memoServiceClient
.
deleteMemoReaction
({
name
:
reaction
.
name
});
}
}
else
{
await
memoServiceClient
.
upsertMemoReaction
({
...
...
web/src/components/ReactionView.tsx
View file @
9972a77d
...
...
@@ -55,7 +55,7 @@ const ReactionView = observer((props: Props) => {
(
reaction
)
=>
reaction
.
reactionType
===
reactionType
&&
reaction
.
creator
===
currentUser
.
name
,
);
for
(
const
reaction
of
reactions
)
{
await
memoServiceClient
.
deleteMemoReaction
({
id
:
reaction
.
id
});
await
memoServiceClient
.
deleteMemoReaction
({
name
:
reaction
.
name
});
}
}
}
catch
{
...
...
web/src/pages/Archived.tsx
View file @
9972a77d
...
...
@@ -6,7 +6,7 @@ import PagedMemoList from "@/components/PagedMemoList";
import
useCurrentUser
from
"@/hooks/useCurrentUser"
;
import
{
viewStore
}
from
"@/store/v2"
;
import
memoFilterStore
from
"@/store/v2/memoFilter"
;
import
{
Direction
,
State
}
from
"@/types/proto/api/v1/common"
;
import
{
State
}
from
"@/types/proto/api/v1/common"
;
import
{
Memo
}
from
"@/types/proto/api/v1/memo_service"
;
const
Archived
=
observer
(()
=>
{
...
...
@@ -46,7 +46,7 @@ const Archived = observer(() => {
}
owner=
{
user
.
name
}
state=
{
State
.
ARCHIVED
}
direction=
{
viewStore
.
state
.
orderByTimeAsc
?
Direction
.
ASC
:
Direction
.
DESC
}
orderBy=
{
viewStore
.
state
.
orderByTimeAsc
?
"display_time asc"
:
"display_time desc"
}
oldFilter=
{
memoListFilter
}
/>
);
...
...
web/src/pages/Explore.tsx
View file @
9972a77d
...
...
@@ -5,7 +5,7 @@ import MobileHeader from "@/components/MobileHeader";
import
PagedMemoList
from
"@/components/PagedMemoList"
;
import
useResponsiveWidth
from
"@/hooks/useResponsiveWidth"
;
import
{
viewStore
}
from
"@/store/v2"
;
import
{
Direction
,
State
}
from
"@/types/proto/api/v1/common"
;
import
{
State
}
from
"@/types/proto/api/v1/common"
;
import
{
Memo
}
from
"@/types/proto/api/v1/memo_service"
;
const
Explore
=
observer
(()
=>
{
...
...
@@ -26,7 +26,7 @@ const Explore = observer(() => {
:
dayjs
(
b
.
displayTime
).
unix
()
-
dayjs
(
a
.
displayTime
).
unix
(),
)
}
direction=
{
viewStore
.
state
.
orderByTimeAsc
?
Direction
.
ASC
:
Direction
.
DESC
}
orderBy=
{
viewStore
.
state
.
orderByTimeAsc
?
"display_time asc"
:
"display_time desc"
}
/>
</
div
>
</
section
>
...
...
web/src/pages/Home.tsx
View file @
9972a77d
...
...
@@ -6,7 +6,7 @@ import PagedMemoList from "@/components/PagedMemoList";
import
useCurrentUser
from
"@/hooks/useCurrentUser"
;
import
{
viewStore
,
userStore
}
from
"@/store/v2"
;
import
memoFilterStore
from
"@/store/v2/memoFilter"
;
import
{
Direction
,
State
}
from
"@/types/proto/api/v1/common"
;
import
{
State
}
from
"@/types/proto/api/v1/common"
;
import
{
Memo
}
from
"@/types/proto/api/v1/memo_service"
;
// Helper function to extract shortcut ID from resource name
...
...
@@ -68,7 +68,7 @@ const Home = observer(() => {
.
sort
((
a
,
b
)
=>
Number
(
b
.
pinned
)
-
Number
(
a
.
pinned
))
}
owner=
{
user
.
name
}
direction=
{
viewStore
.
state
.
orderByTimeAsc
?
Direction
.
ASC
:
Direction
.
DESC
}
orderBy=
{
viewStore
.
state
.
orderByTimeAsc
?
"display_time asc"
:
"display_time desc"
}
filter=
{
selectedShortcut
?.
filter
||
""
}
oldFilter=
{
memoListFilter
}
/>
...
...
web/src/pages/UserProfile.tsx
View file @
9972a77d
...
...
@@ -12,7 +12,7 @@ import UserAvatar from "@/components/UserAvatar";
import
useLoading
from
"@/hooks/useLoading"
;
import
{
viewStore
,
userStore
}
from
"@/store/v2"
;
import
memoFilterStore
from
"@/store/v2/memoFilter"
;
import
{
Direction
,
State
}
from
"@/types/proto/api/v1/common"
;
import
{
State
}
from
"@/types/proto/api/v1/common"
;
import
{
Memo
}
from
"@/types/proto/api/v1/memo_service"
;
import
{
User
}
from
"@/types/proto/api/v1/user_service"
;
import
{
useTranslate
}
from
"@/utils/i18n"
;
...
...
@@ -112,7 +112,7 @@ const UserProfile = observer(() => {
.
sort
((
a
,
b
)
=>
Number
(
b
.
pinned
)
-
Number
(
a
.
pinned
))
}
owner=
{
user
.
name
}
direction=
{
viewStore
.
state
.
orderByTimeAsc
?
Direction
.
ASC
:
Direction
.
DESC
}
orderBy=
{
viewStore
.
state
.
orderByTimeAsc
?
"display_time asc"
:
"display_time desc"
}
oldFilter=
{
memoListFilter
}
/>
</>
...
...
web/src/types/proto/api/v1/memo_service.ts
View file @
9972a77d
This diff is collapsed.
Click to expand it.
web/src/types/proto/api/v1/reaction_service.ts
deleted
100644 → 0
View file @
91c2a4ce
// Code generated by protoc-gen-ts_proto. DO NOT EDIT.
// versions:
// protoc-gen-ts_proto v2.6.1
// protoc unknown
// source: api/v1/reaction_service.proto
/* eslint-disable */
import
{
BinaryReader
,
BinaryWriter
}
from
"@bufbuild/protobuf/wire"
;
export
const
protobufPackage
=
"memos.api.v1"
;
export
interface
Reaction
{
id
:
number
;
/**
* The name of the creator.
* Format: users/{user}
*/
creator
:
string
;
/**
* The content identifier.
* For memo, it should be the `Memo.name`.
*/
contentId
:
string
;
reactionType
:
string
;
}
function
createBaseReaction
():
Reaction
{
return
{
id
:
0
,
creator
:
""
,
contentId
:
""
,
reactionType
:
""
};
}
export
const
Reaction
:
MessageFns
<
Reaction
>
=
{
encode
(
message
:
Reaction
,
writer
:
BinaryWriter
=
new
BinaryWriter
()):
BinaryWriter
{
if
(
message
.
id
!==
0
)
{
writer
.
uint32
(
8
).
int32
(
message
.
id
);
}
if
(
message
.
creator
!==
""
)
{
writer
.
uint32
(
18
).
string
(
message
.
creator
);
}
if
(
message
.
contentId
!==
""
)
{
writer
.
uint32
(
26
).
string
(
message
.
contentId
);
}
if
(
message
.
reactionType
!==
""
)
{
writer
.
uint32
(
34
).
string
(
message
.
reactionType
);
}
return
writer
;
},
decode
(
input
:
BinaryReader
|
Uint8Array
,
length
?:
number
):
Reaction
{
const
reader
=
input
instanceof
BinaryReader
?
input
:
new
BinaryReader
(
input
);
let
end
=
length
===
undefined
?
reader
.
len
:
reader
.
pos
+
length
;
const
message
=
createBaseReaction
();
while
(
reader
.
pos
<
end
)
{
const
tag
=
reader
.
uint32
();
switch
(
tag
>>>
3
)
{
case
1
:
{
if
(
tag
!==
8
)
{
break
;
}
message
.
id
=
reader
.
int32
();
continue
;
}
case
2
:
{
if
(
tag
!==
18
)
{
break
;
}
message
.
creator
=
reader
.
string
();
continue
;
}
case
3
:
{
if
(
tag
!==
26
)
{
break
;
}
message
.
contentId
=
reader
.
string
();
continue
;
}
case
4
:
{
if
(
tag
!==
34
)
{
break
;
}
message
.
reactionType
=
reader
.
string
();
continue
;
}
}
if
((
tag
&
7
)
===
4
||
tag
===
0
)
{
break
;
}
reader
.
skip
(
tag
&
7
);
}
return
message
;
},
create
(
base
?:
DeepPartial
<
Reaction
>
):
Reaction
{
return
Reaction
.
fromPartial
(
base
??
{});
},
fromPartial
(
object
:
DeepPartial
<
Reaction
>
):
Reaction
{
const
message
=
createBaseReaction
();
message
.
id
=
object
.
id
??
0
;
message
.
creator
=
object
.
creator
??
""
;
message
.
contentId
=
object
.
contentId
??
""
;
message
.
reactionType
=
object
.
reactionType
??
""
;
return
message
;
},
};
type
Builtin
=
Date
|
Function
|
Uint8Array
|
string
|
number
|
boolean
|
undefined
;
export
type
DeepPartial
<
T
>
=
T
extends
Builtin
?
T
:
T
extends
globalThis
.
Array
<
infer
U
>
?
globalThis
.
Array
<
DeepPartial
<
U
>>
:
T
extends
ReadonlyArray
<
infer
U
>
?
ReadonlyArray
<
DeepPartial
<
U
>>
:
T
extends
{}
?
{
[
K
in
keyof
T
]?:
DeepPartial
<
T
[
K
]
>
}
:
Partial
<
T
>
;
export
interface
MessageFns
<
T
>
{
encode
(
message
:
T
,
writer
?:
BinaryWriter
):
BinaryWriter
;
decode
(
input
:
BinaryReader
|
Uint8Array
,
length
?:
number
):
T
;
create
(
base
?:
DeepPartial
<
T
>
):
T
;
fromPartial
(
object
:
DeepPartial
<
T
>
):
T
;
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment