Unverified Commit c268551a authored by boojack's avatar boojack Committed by GitHub

feat(memos): choose created or updated time for memos (#5894)

parent 3949a252
......@@ -158,8 +158,8 @@ message InstanceSetting {
// Memo-related instance settings and policies.
message MemoRelatedSetting {
// display_with_update_time orders and displays memo with update time.
bool display_with_update_time = 2;
reserved 2;
reserved "display_with_update_time";
// content_length_limit is the limit of content length. Unit is byte.
int32 content_length_limit = 3;
// enable_double_click_edit enables editing on double click.
......
......@@ -204,8 +204,8 @@ message Memo {
// If not set on creation, the server will set it to the current time.
google.protobuf.Timestamp update_time = 5 [(google.api.field_behavior) = OPTIONAL];
// The display timestamp of the memo.
google.protobuf.Timestamp display_time = 6 [(google.api.field_behavior) = OPTIONAL];
reserved 6;
reserved "display_time";
// Required. The content of the memo in Markdown format.
string content = 7 [(google.api.field_behavior) = REQUIRED];
......@@ -291,10 +291,10 @@ message ListMemosRequest {
State state = 3 [(google.api.field_behavior) = OPTIONAL];
// Optional. The order to sort results by.
// Default to "display_time desc".
// Default to "create_time desc".
// Supports comma-separated list of fields following AIP-132.
// Example: "pinned desc, display_time desc" or "create_time asc"
// Supported fields: pinned, display_time, create_time, update_time, name
// Example: "pinned desc, create_time desc" or "update_time asc"
// Supported fields: pinned, create_time, update_time, name
string order_by = 4 [(google.api.field_behavior) = OPTIONAL];
// Optional. Filter to apply to the list results.
......
......@@ -354,8 +354,8 @@ message UserStats {
// Format: users/{user}
string name = 1 [(google.api.field_behavior) = IDENTIFIER];
// The timestamps when the memos were displayed.
repeated google.protobuf.Timestamp memo_display_timestamps = 2;
reserved 2;
reserved "memo_display_timestamps";
// The stats of memo types.
MemoTypeStats memo_type_stats = 3;
......@@ -363,6 +363,9 @@ message UserStats {
// The count of tags.
map<string, int32> tag_count = 4;
// The creation timestamps of the user's memos.
repeated google.protobuf.Timestamp memo_created_timestamps = 7;
// The pinned memos of the user.
repeated string pinned_memos = 5;
......
......@@ -756,8 +756,6 @@ func (x *InstanceSetting_StorageSetting) GetS3Config() *InstanceSetting_StorageS
// Memo-related instance settings and policies.
type InstanceSetting_MemoRelatedSetting struct {
state protoimpl.MessageState `protogen:"open.v1"`
// display_with_update_time orders and displays memo with update time.
DisplayWithUpdateTime bool `protobuf:"varint,2,opt,name=display_with_update_time,json=displayWithUpdateTime,proto3" json:"display_with_update_time,omitempty"`
// content_length_limit is the limit of content length. Unit is byte.
ContentLengthLimit int32 `protobuf:"varint,3,opt,name=content_length_limit,json=contentLengthLimit,proto3" json:"content_length_limit,omitempty"`
// enable_double_click_edit enables editing on double click.
......@@ -798,13 +796,6 @@ func (*InstanceSetting_MemoRelatedSetting) Descriptor() ([]byte, []int) {
return file_api_v1_instance_service_proto_rawDescGZIP(), []int{2, 2}
}
func (x *InstanceSetting_MemoRelatedSetting) GetDisplayWithUpdateTime() bool {
if x != nil {
return x.DisplayWithUpdateTime
}
return false
}
func (x *InstanceSetting_MemoRelatedSetting) GetContentLengthLimit() int32 {
if x != nil {
return x.ContentLengthLimit
......@@ -1392,7 +1383,7 @@ const file_api_v1_instance_service_proto_rawDesc = "" +
"\x04demo\x18\x03 \x01(\bR\x04demo\x12!\n" +
"\finstance_url\x18\x06 \x01(\tR\vinstanceUrl\x12(\n" +
"\x05admin\x18\a \x01(\v2\x12.memos.api.v1.UserR\x05admin\"\x1b\n" +
"\x19GetInstanceProfileRequest\"\xff\x19\n" +
"\x19GetInstanceProfileRequest\"\xe6\x19\n" +
"\x0fInstanceSetting\x12\x17\n" +
"\x04name\x18\x01 \x01(\tB\x03\xe0A\bR\x04name\x12W\n" +
"\x0fgeneral_setting\x18\x02 \x01(\v2,.memos.api.v1.InstanceSetting.GeneralSettingH\x00R\x0egeneralSetting\x12W\n" +
......@@ -1431,12 +1422,11 @@ const file_api_v1_instance_service_proto_rawDesc = "" +
"\x18STORAGE_TYPE_UNSPECIFIED\x10\x00\x12\f\n" +
"\bDATABASE\x10\x01\x12\t\n" +
"\x05LOCAL\x10\x02\x12\x06\n" +
"\x02S3\x10\x03\x1a\xd6\x01\n" +
"\x12MemoRelatedSetting\x127\n" +
"\x18display_with_update_time\x18\x02 \x01(\bR\x15displayWithUpdateTime\x120\n" +
"\x02S3\x10\x03\x1a\xbd\x01\n" +
"\x12MemoRelatedSetting\x120\n" +
"\x14content_length_limit\x18\x03 \x01(\x05R\x12contentLengthLimit\x127\n" +
"\x18enable_double_click_edit\x18\x04 \x01(\bR\x15enableDoubleClickEdit\x12\x1c\n" +
"\treactions\x18\a \x03(\tR\treactions\x1ao\n" +
"\treactions\x18\a \x03(\tR\treactionsJ\x04\b\x02\x10\x03R\x18display_with_update_time\x1ao\n" +
"\vTagMetadata\x12=\n" +
"\x10background_color\x18\x01 \x01(\v2\x12.google.type.ColorR\x0fbackgroundColor\x12!\n" +
"\fblur_content\x18\x02 \x01(\bR\vblurContent\x1a\xba\x01\n" +
......
......@@ -228,8 +228,6 @@ type Memo struct {
// The last update timestamp.
// If not set on creation, the server will set it to the current time.
UpdateTime *timestamppb.Timestamp `protobuf:"bytes,5,opt,name=update_time,json=updateTime,proto3" json:"update_time,omitempty"`
// The display timestamp of the memo.
DisplayTime *timestamppb.Timestamp `protobuf:"bytes,6,opt,name=display_time,json=displayTime,proto3" json:"display_time,omitempty"`
// Required. The content of the memo in Markdown format.
Content string `protobuf:"bytes,7,opt,name=content,proto3" json:"content,omitempty"`
// The visibility of the memo.
......@@ -322,13 +320,6 @@ func (x *Memo) GetUpdateTime() *timestamppb.Timestamp {
return nil
}
func (x *Memo) GetDisplayTime() *timestamppb.Timestamp {
if x != nil {
return x.DisplayTime
}
return nil
}
func (x *Memo) GetContent() string {
if x != nil {
return x.Content
......@@ -538,10 +529,10 @@ type ListMemosRequest struct {
// Default to `NORMAL`. Set to `ARCHIVED` to list archived memos.
State State `protobuf:"varint,3,opt,name=state,proto3,enum=memos.api.v1.State" json:"state,omitempty"`
// Optional. The order to sort results by.
// Default to "display_time desc".
// Default to "create_time desc".
// Supports comma-separated list of fields following AIP-132.
// Example: "pinned desc, display_time desc" or "create_time asc"
// Supported fields: pinned, display_time, create_time, update_time, name
// Example: "pinned desc, create_time desc" or "update_time asc"
// Supported fields: pinned, create_time, update_time, name
OrderBy string `protobuf:"bytes,4,opt,name=order_by,json=orderBy,proto3" json:"order_by,omitempty"`
// Optional. Filter to apply to the list results.
// Filter is a CEL expression to filter memos.
......@@ -2124,7 +2115,7 @@ const file_api_v1_memo_service_proto_rawDesc = "" +
"\rreaction_type\x18\x04 \x01(\tB\x03\xe0A\x02R\freactionType\x12@\n" +
"\vcreate_time\x18\x05 \x01(\v2\x1a.google.protobuf.TimestampB\x03\xe0A\x03R\n" +
"createTime:X\xeaAU\n" +
"\x15memos.api.v1/Reaction\x12!memos/{memo}/reactions/{reaction}\x1a\x04name*\treactions2\breaction\"\xee\b\n" +
"\x15memos.api.v1/Reaction\x12!memos/{memo}/reactions/{reaction}\x1a\x04name*\treactions2\breaction\"\xbe\b\n" +
"\x04Memo\x12\x17\n" +
"\x04name\x18\x01 \x01(\tB\x03\xe0A\bR\x04name\x12.\n" +
"\x05state\x18\x02 \x01(\x0e2\x13.memos.api.v1.StateB\x03\xe0A\x02R\x05state\x123\n" +
......@@ -2133,8 +2124,7 @@ const file_api_v1_memo_service_proto_rawDesc = "" +
"\vcreate_time\x18\x04 \x01(\v2\x1a.google.protobuf.TimestampB\x03\xe0A\x01R\n" +
"createTime\x12@\n" +
"\vupdate_time\x18\x05 \x01(\v2\x1a.google.protobuf.TimestampB\x03\xe0A\x01R\n" +
"updateTime\x12B\n" +
"\fdisplay_time\x18\x06 \x01(\v2\x1a.google.protobuf.TimestampB\x03\xe0A\x01R\vdisplayTime\x12\x1d\n" +
"updateTime\x12\x1d\n" +
"\acontent\x18\a \x01(\tB\x03\xe0A\x02R\acontent\x12=\n" +
"\n" +
"visibility\x18\t \x01(\x0e2\x18.memos.api.v1.VisibilityB\x03\xe0A\x02R\n" +
......@@ -2158,7 +2148,7 @@ const file_api_v1_memo_service_proto_rawDesc = "" +
"\x05title\x18\x05 \x01(\tR\x05title:7\xeaA4\n" +
"\x11memos.api.v1/Memo\x12\fmemos/{memo}\x1a\x04name*\x05memos2\x04memoB\t\n" +
"\a_parentB\v\n" +
"\t_location\"u\n" +
"\t_locationJ\x04\b\x06\x10\aR\fdisplay_time\"u\n" +
"\bLocation\x12%\n" +
"\vplaceholder\x18\x01 \x01(\tB\x03\xe0A\x01R\vplaceholder\x12\x1f\n" +
"\blatitude\x18\x02 \x01(\x01B\x03\xe0A\x01R\blatitude\x12!\n" +
......@@ -2377,74 +2367,73 @@ var file_api_v1_memo_service_proto_depIdxs = []int32{
34, // 1: memos.api.v1.Memo.state:type_name -> memos.api.v1.State
33, // 2: memos.api.v1.Memo.create_time:type_name -> google.protobuf.Timestamp
33, // 3: memos.api.v1.Memo.update_time:type_name -> google.protobuf.Timestamp
33, // 4: memos.api.v1.Memo.display_time:type_name -> google.protobuf.Timestamp
0, // 5: memos.api.v1.Memo.visibility:type_name -> memos.api.v1.Visibility
35, // 6: memos.api.v1.Memo.attachments:type_name -> memos.api.v1.Attachment
14, // 7: memos.api.v1.Memo.relations:type_name -> memos.api.v1.MemoRelation
2, // 8: memos.api.v1.Memo.reactions:type_name -> memos.api.v1.Reaction
31, // 9: memos.api.v1.Memo.property:type_name -> memos.api.v1.Memo.Property
4, // 10: memos.api.v1.Memo.location:type_name -> memos.api.v1.Location
3, // 11: memos.api.v1.CreateMemoRequest.memo:type_name -> memos.api.v1.Memo
34, // 12: memos.api.v1.ListMemosRequest.state:type_name -> memos.api.v1.State
3, // 13: memos.api.v1.ListMemosResponse.memos:type_name -> memos.api.v1.Memo
3, // 14: memos.api.v1.UpdateMemoRequest.memo:type_name -> memos.api.v1.Memo
36, // 15: memos.api.v1.UpdateMemoRequest.update_mask:type_name -> google.protobuf.FieldMask
35, // 16: memos.api.v1.SetMemoAttachmentsRequest.attachments:type_name -> memos.api.v1.Attachment
35, // 17: memos.api.v1.ListMemoAttachmentsResponse.attachments:type_name -> memos.api.v1.Attachment
32, // 18: memos.api.v1.MemoRelation.memo:type_name -> memos.api.v1.MemoRelation.Memo
32, // 19: memos.api.v1.MemoRelation.related_memo:type_name -> memos.api.v1.MemoRelation.Memo
1, // 20: memos.api.v1.MemoRelation.type:type_name -> memos.api.v1.MemoRelation.Type
14, // 21: memos.api.v1.SetMemoRelationsRequest.relations:type_name -> memos.api.v1.MemoRelation
14, // 22: memos.api.v1.ListMemoRelationsResponse.relations:type_name -> memos.api.v1.MemoRelation
3, // 23: memos.api.v1.CreateMemoCommentRequest.comment:type_name -> memos.api.v1.Memo
3, // 24: memos.api.v1.ListMemoCommentsResponse.memos:type_name -> memos.api.v1.Memo
2, // 25: memos.api.v1.ListMemoReactionsResponse.reactions:type_name -> memos.api.v1.Reaction
2, // 26: memos.api.v1.UpsertMemoReactionRequest.reaction:type_name -> memos.api.v1.Reaction
33, // 27: memos.api.v1.MemoShare.create_time:type_name -> google.protobuf.Timestamp
33, // 28: memos.api.v1.MemoShare.expire_time:type_name -> google.protobuf.Timestamp
25, // 29: memos.api.v1.CreateMemoShareRequest.memo_share:type_name -> memos.api.v1.MemoShare
25, // 30: memos.api.v1.ListMemoSharesResponse.memo_shares:type_name -> memos.api.v1.MemoShare
5, // 31: memos.api.v1.MemoService.CreateMemo:input_type -> memos.api.v1.CreateMemoRequest
6, // 32: memos.api.v1.MemoService.ListMemos:input_type -> memos.api.v1.ListMemosRequest
8, // 33: memos.api.v1.MemoService.GetMemo:input_type -> memos.api.v1.GetMemoRequest
9, // 34: memos.api.v1.MemoService.UpdateMemo:input_type -> memos.api.v1.UpdateMemoRequest
10, // 35: memos.api.v1.MemoService.DeleteMemo:input_type -> memos.api.v1.DeleteMemoRequest
11, // 36: memos.api.v1.MemoService.SetMemoAttachments:input_type -> memos.api.v1.SetMemoAttachmentsRequest
12, // 37: memos.api.v1.MemoService.ListMemoAttachments:input_type -> memos.api.v1.ListMemoAttachmentsRequest
15, // 38: memos.api.v1.MemoService.SetMemoRelations:input_type -> memos.api.v1.SetMemoRelationsRequest
16, // 39: memos.api.v1.MemoService.ListMemoRelations:input_type -> memos.api.v1.ListMemoRelationsRequest
18, // 40: memos.api.v1.MemoService.CreateMemoComment:input_type -> memos.api.v1.CreateMemoCommentRequest
19, // 41: memos.api.v1.MemoService.ListMemoComments:input_type -> memos.api.v1.ListMemoCommentsRequest
21, // 42: memos.api.v1.MemoService.ListMemoReactions:input_type -> memos.api.v1.ListMemoReactionsRequest
23, // 43: memos.api.v1.MemoService.UpsertMemoReaction:input_type -> memos.api.v1.UpsertMemoReactionRequest
24, // 44: memos.api.v1.MemoService.DeleteMemoReaction:input_type -> memos.api.v1.DeleteMemoReactionRequest
26, // 45: memos.api.v1.MemoService.CreateMemoShare:input_type -> memos.api.v1.CreateMemoShareRequest
27, // 46: memos.api.v1.MemoService.ListMemoShares:input_type -> memos.api.v1.ListMemoSharesRequest
29, // 47: memos.api.v1.MemoService.DeleteMemoShare:input_type -> memos.api.v1.DeleteMemoShareRequest
30, // 48: memos.api.v1.MemoService.GetMemoByShare:input_type -> memos.api.v1.GetMemoByShareRequest
3, // 49: memos.api.v1.MemoService.CreateMemo:output_type -> memos.api.v1.Memo
7, // 50: memos.api.v1.MemoService.ListMemos:output_type -> memos.api.v1.ListMemosResponse
3, // 51: memos.api.v1.MemoService.GetMemo:output_type -> memos.api.v1.Memo
3, // 52: memos.api.v1.MemoService.UpdateMemo:output_type -> memos.api.v1.Memo
37, // 53: memos.api.v1.MemoService.DeleteMemo:output_type -> google.protobuf.Empty
37, // 54: memos.api.v1.MemoService.SetMemoAttachments:output_type -> google.protobuf.Empty
13, // 55: memos.api.v1.MemoService.ListMemoAttachments:output_type -> memos.api.v1.ListMemoAttachmentsResponse
37, // 56: memos.api.v1.MemoService.SetMemoRelations:output_type -> google.protobuf.Empty
17, // 57: memos.api.v1.MemoService.ListMemoRelations:output_type -> memos.api.v1.ListMemoRelationsResponse
3, // 58: memos.api.v1.MemoService.CreateMemoComment:output_type -> memos.api.v1.Memo
20, // 59: memos.api.v1.MemoService.ListMemoComments:output_type -> memos.api.v1.ListMemoCommentsResponse
22, // 60: memos.api.v1.MemoService.ListMemoReactions:output_type -> memos.api.v1.ListMemoReactionsResponse
2, // 61: memos.api.v1.MemoService.UpsertMemoReaction:output_type -> memos.api.v1.Reaction
37, // 62: memos.api.v1.MemoService.DeleteMemoReaction:output_type -> google.protobuf.Empty
25, // 63: memos.api.v1.MemoService.CreateMemoShare:output_type -> memos.api.v1.MemoShare
28, // 64: memos.api.v1.MemoService.ListMemoShares:output_type -> memos.api.v1.ListMemoSharesResponse
37, // 65: memos.api.v1.MemoService.DeleteMemoShare:output_type -> google.protobuf.Empty
3, // 66: memos.api.v1.MemoService.GetMemoByShare:output_type -> memos.api.v1.Memo
49, // [49:67] is the sub-list for method output_type
31, // [31:49] is the sub-list for method input_type
31, // [31:31] is the sub-list for extension type_name
31, // [31:31] is the sub-list for extension extendee
0, // [0:31] is the sub-list for field type_name
0, // 4: memos.api.v1.Memo.visibility:type_name -> memos.api.v1.Visibility
35, // 5: memos.api.v1.Memo.attachments:type_name -> memos.api.v1.Attachment
14, // 6: memos.api.v1.Memo.relations:type_name -> memos.api.v1.MemoRelation
2, // 7: memos.api.v1.Memo.reactions:type_name -> memos.api.v1.Reaction
31, // 8: memos.api.v1.Memo.property:type_name -> memos.api.v1.Memo.Property
4, // 9: memos.api.v1.Memo.location:type_name -> memos.api.v1.Location
3, // 10: memos.api.v1.CreateMemoRequest.memo:type_name -> memos.api.v1.Memo
34, // 11: memos.api.v1.ListMemosRequest.state:type_name -> memos.api.v1.State
3, // 12: memos.api.v1.ListMemosResponse.memos:type_name -> memos.api.v1.Memo
3, // 13: memos.api.v1.UpdateMemoRequest.memo:type_name -> memos.api.v1.Memo
36, // 14: memos.api.v1.UpdateMemoRequest.update_mask:type_name -> google.protobuf.FieldMask
35, // 15: memos.api.v1.SetMemoAttachmentsRequest.attachments:type_name -> memos.api.v1.Attachment
35, // 16: memos.api.v1.ListMemoAttachmentsResponse.attachments:type_name -> memos.api.v1.Attachment
32, // 17: memos.api.v1.MemoRelation.memo:type_name -> memos.api.v1.MemoRelation.Memo
32, // 18: memos.api.v1.MemoRelation.related_memo:type_name -> memos.api.v1.MemoRelation.Memo
1, // 19: memos.api.v1.MemoRelation.type:type_name -> memos.api.v1.MemoRelation.Type
14, // 20: memos.api.v1.SetMemoRelationsRequest.relations:type_name -> memos.api.v1.MemoRelation
14, // 21: memos.api.v1.ListMemoRelationsResponse.relations:type_name -> memos.api.v1.MemoRelation
3, // 22: memos.api.v1.CreateMemoCommentRequest.comment:type_name -> memos.api.v1.Memo
3, // 23: memos.api.v1.ListMemoCommentsResponse.memos:type_name -> memos.api.v1.Memo
2, // 24: memos.api.v1.ListMemoReactionsResponse.reactions:type_name -> memos.api.v1.Reaction
2, // 25: memos.api.v1.UpsertMemoReactionRequest.reaction:type_name -> memos.api.v1.Reaction
33, // 26: memos.api.v1.MemoShare.create_time:type_name -> google.protobuf.Timestamp
33, // 27: memos.api.v1.MemoShare.expire_time:type_name -> google.protobuf.Timestamp
25, // 28: memos.api.v1.CreateMemoShareRequest.memo_share:type_name -> memos.api.v1.MemoShare
25, // 29: memos.api.v1.ListMemoSharesResponse.memo_shares:type_name -> memos.api.v1.MemoShare
5, // 30: memos.api.v1.MemoService.CreateMemo:input_type -> memos.api.v1.CreateMemoRequest
6, // 31: memos.api.v1.MemoService.ListMemos:input_type -> memos.api.v1.ListMemosRequest
8, // 32: memos.api.v1.MemoService.GetMemo:input_type -> memos.api.v1.GetMemoRequest
9, // 33: memos.api.v1.MemoService.UpdateMemo:input_type -> memos.api.v1.UpdateMemoRequest
10, // 34: memos.api.v1.MemoService.DeleteMemo:input_type -> memos.api.v1.DeleteMemoRequest
11, // 35: memos.api.v1.MemoService.SetMemoAttachments:input_type -> memos.api.v1.SetMemoAttachmentsRequest
12, // 36: memos.api.v1.MemoService.ListMemoAttachments:input_type -> memos.api.v1.ListMemoAttachmentsRequest
15, // 37: memos.api.v1.MemoService.SetMemoRelations:input_type -> memos.api.v1.SetMemoRelationsRequest
16, // 38: memos.api.v1.MemoService.ListMemoRelations:input_type -> memos.api.v1.ListMemoRelationsRequest
18, // 39: memos.api.v1.MemoService.CreateMemoComment:input_type -> memos.api.v1.CreateMemoCommentRequest
19, // 40: memos.api.v1.MemoService.ListMemoComments:input_type -> memos.api.v1.ListMemoCommentsRequest
21, // 41: memos.api.v1.MemoService.ListMemoReactions:input_type -> memos.api.v1.ListMemoReactionsRequest
23, // 42: memos.api.v1.MemoService.UpsertMemoReaction:input_type -> memos.api.v1.UpsertMemoReactionRequest
24, // 43: memos.api.v1.MemoService.DeleteMemoReaction:input_type -> memos.api.v1.DeleteMemoReactionRequest
26, // 44: memos.api.v1.MemoService.CreateMemoShare:input_type -> memos.api.v1.CreateMemoShareRequest
27, // 45: memos.api.v1.MemoService.ListMemoShares:input_type -> memos.api.v1.ListMemoSharesRequest
29, // 46: memos.api.v1.MemoService.DeleteMemoShare:input_type -> memos.api.v1.DeleteMemoShareRequest
30, // 47: memos.api.v1.MemoService.GetMemoByShare:input_type -> memos.api.v1.GetMemoByShareRequest
3, // 48: memos.api.v1.MemoService.CreateMemo:output_type -> memos.api.v1.Memo
7, // 49: memos.api.v1.MemoService.ListMemos:output_type -> memos.api.v1.ListMemosResponse
3, // 50: memos.api.v1.MemoService.GetMemo:output_type -> memos.api.v1.Memo
3, // 51: memos.api.v1.MemoService.UpdateMemo:output_type -> memos.api.v1.Memo
37, // 52: memos.api.v1.MemoService.DeleteMemo:output_type -> google.protobuf.Empty
37, // 53: memos.api.v1.MemoService.SetMemoAttachments:output_type -> google.protobuf.Empty
13, // 54: memos.api.v1.MemoService.ListMemoAttachments:output_type -> memos.api.v1.ListMemoAttachmentsResponse
37, // 55: memos.api.v1.MemoService.SetMemoRelations:output_type -> google.protobuf.Empty
17, // 56: memos.api.v1.MemoService.ListMemoRelations:output_type -> memos.api.v1.ListMemoRelationsResponse
3, // 57: memos.api.v1.MemoService.CreateMemoComment:output_type -> memos.api.v1.Memo
20, // 58: memos.api.v1.MemoService.ListMemoComments:output_type -> memos.api.v1.ListMemoCommentsResponse
22, // 59: memos.api.v1.MemoService.ListMemoReactions:output_type -> memos.api.v1.ListMemoReactionsResponse
2, // 60: memos.api.v1.MemoService.UpsertMemoReaction:output_type -> memos.api.v1.Reaction
37, // 61: memos.api.v1.MemoService.DeleteMemoReaction:output_type -> google.protobuf.Empty
25, // 62: memos.api.v1.MemoService.CreateMemoShare:output_type -> memos.api.v1.MemoShare
28, // 63: memos.api.v1.MemoService.ListMemoShares:output_type -> memos.api.v1.ListMemoSharesResponse
37, // 64: memos.api.v1.MemoService.DeleteMemoShare:output_type -> google.protobuf.Empty
3, // 65: memos.api.v1.MemoService.GetMemoByShare:output_type -> memos.api.v1.Memo
48, // [48:66] is the sub-list for method output_type
30, // [30:48] is the sub-list for method input_type
30, // [30:30] is the sub-list for extension type_name
30, // [30:30] is the sub-list for extension extendee
0, // [0:30] is the sub-list for field type_name
}
func init() { file_api_v1_memo_service_proto_init() }
......
......@@ -849,12 +849,12 @@ type UserStats struct {
// The resource name of the user whose stats these are.
// Format: users/{user}
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
// The timestamps when the memos were displayed.
MemoDisplayTimestamps []*timestamppb.Timestamp `protobuf:"bytes,2,rep,name=memo_display_timestamps,json=memoDisplayTimestamps,proto3" json:"memo_display_timestamps,omitempty"`
// The stats of memo types.
MemoTypeStats *UserStats_MemoTypeStats `protobuf:"bytes,3,opt,name=memo_type_stats,json=memoTypeStats,proto3" json:"memo_type_stats,omitempty"`
// The count of tags.
TagCount map[string]int32 `protobuf:"bytes,4,rep,name=tag_count,json=tagCount,proto3" json:"tag_count,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"varint,2,opt,name=value"`
// The creation timestamps of the user's memos.
MemoCreatedTimestamps []*timestamppb.Timestamp `protobuf:"bytes,7,rep,name=memo_created_timestamps,json=memoCreatedTimestamps,proto3" json:"memo_created_timestamps,omitempty"`
// The pinned memos of the user.
PinnedMemos []string `protobuf:"bytes,5,rep,name=pinned_memos,json=pinnedMemos,proto3" json:"pinned_memos,omitempty"`
// Total memo count.
......@@ -900,23 +900,23 @@ func (x *UserStats) GetName() string {
return ""
}
func (x *UserStats) GetMemoDisplayTimestamps() []*timestamppb.Timestamp {
func (x *UserStats) GetMemoTypeStats() *UserStats_MemoTypeStats {
if x != nil {
return x.MemoDisplayTimestamps
return x.MemoTypeStats
}
return nil
}
func (x *UserStats) GetMemoTypeStats() *UserStats_MemoTypeStats {
func (x *UserStats) GetTagCount() map[string]int32 {
if x != nil {
return x.MemoTypeStats
return x.TagCount
}
return nil
}
func (x *UserStats) GetTagCount() map[string]int32 {
func (x *UserStats) GetMemoCreatedTimestamps() []*timestamppb.Timestamp {
if x != nil {
return x.TagCount
return x.MemoCreatedTimestamps
}
return nil
}
......@@ -3172,12 +3172,12 @@ const file_api_v1_user_service_proto_rawDesc = "" +
"\x11DeleteUserRequest\x12-\n" +
"\x04name\x18\x01 \x01(\tB\x19\xe0A\x02\xfaA\x13\n" +
"\x11memos.api.v1/UserR\x04name\x12\x19\n" +
"\x05force\x18\x02 \x01(\bB\x03\xe0A\x01R\x05force\"\xe4\x04\n" +
"\x05force\x18\x02 \x01(\bB\x03\xe0A\x01R\x05force\"\x83\x05\n" +
"\tUserStats\x12\x17\n" +
"\x04name\x18\x01 \x01(\tB\x03\xe0A\bR\x04name\x12R\n" +
"\x17memo_display_timestamps\x18\x02 \x03(\v2\x1a.google.protobuf.TimestampR\x15memoDisplayTimestamps\x12M\n" +
"\x04name\x18\x01 \x01(\tB\x03\xe0A\bR\x04name\x12M\n" +
"\x0fmemo_type_stats\x18\x03 \x01(\v2%.memos.api.v1.UserStats.MemoTypeStatsR\rmemoTypeStats\x12B\n" +
"\ttag_count\x18\x04 \x03(\v2%.memos.api.v1.UserStats.TagCountEntryR\btagCount\x12!\n" +
"\ttag_count\x18\x04 \x03(\v2%.memos.api.v1.UserStats.TagCountEntryR\btagCount\x12R\n" +
"\x17memo_created_timestamps\x18\a \x03(\v2\x1a.google.protobuf.TimestampR\x15memoCreatedTimestamps\x12!\n" +
"\fpinned_memos\x18\x05 \x03(\tR\vpinnedMemos\x12(\n" +
"\x10total_memo_count\x18\x06 \x01(\x05R\x0etotalMemoCount\x1a\x8b\x01\n" +
"\rMemoTypeStats\x12\x1d\n" +
......@@ -3192,7 +3192,7 @@ const file_api_v1_user_service_proto_rawDesc = "" +
"\rTagCountEntry\x12\x10\n" +
"\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n" +
"\x05value\x18\x02 \x01(\x05R\x05value:\x028\x01:?\xeaA<\n" +
"\x16memos.api.v1/UserStats\x12\fusers/{user}*\tuserStats2\tuserStats\"D\n" +
"\x16memos.api.v1/UserStats\x12\fusers/{user}*\tuserStats2\tuserStatsJ\x04\b\x02\x10\x03R\x17memo_display_timestamps\"D\n" +
"\x13GetUserStatsRequest\x12-\n" +
"\x04name\x18\x01 \x01(\tB\x19\xe0A\x02\xfaA\x13\n" +
"\x11memos.api.v1/UserR\x04name\"\x19\n" +
......@@ -3475,9 +3475,9 @@ var file_api_v1_user_service_proto_depIdxs = []int32{
4, // 7: memos.api.v1.CreateUserRequest.user:type_name -> memos.api.v1.User
4, // 8: memos.api.v1.UpdateUserRequest.user:type_name -> memos.api.v1.User
53, // 9: memos.api.v1.UpdateUserRequest.update_mask:type_name -> google.protobuf.FieldMask
52, // 10: memos.api.v1.UserStats.memo_display_timestamps:type_name -> google.protobuf.Timestamp
45, // 11: memos.api.v1.UserStats.memo_type_stats:type_name -> memos.api.v1.UserStats.MemoTypeStats
46, // 12: memos.api.v1.UserStats.tag_count:type_name -> memos.api.v1.UserStats.TagCountEntry
45, // 10: memos.api.v1.UserStats.memo_type_stats:type_name -> memos.api.v1.UserStats.MemoTypeStats
46, // 11: memos.api.v1.UserStats.tag_count:type_name -> memos.api.v1.UserStats.TagCountEntry
52, // 12: memos.api.v1.UserStats.memo_created_timestamps:type_name -> google.protobuf.Timestamp
13, // 13: memos.api.v1.ListAllUserStatsResponse.stats:type_name -> memos.api.v1.UserStats
47, // 14: memos.api.v1.UserSetting.general_setting:type_name -> memos.api.v1.UserSetting.GeneralSetting
48, // 15: memos.api.v1.UserSetting.webhooks_setting:type_name -> memos.api.v1.UserSetting.WebhooksSetting
......
......@@ -579,10 +579,10 @@ paths:
in: query
description: |-
Optional. The order to sort results by.
Default to "display_time desc".
Default to "create_time desc".
Supports comma-separated list of fields following AIP-132.
Example: "pinned desc, display_time desc" or "create_time asc"
Supported fields: pinned, display_time, create_time, update_time, name
Example: "pinned desc, create_time desc" or "update_time asc"
Supported fields: pinned, create_time, update_time, name
schema:
type: string
- name: filter
......@@ -2626,9 +2626,6 @@ components:
InstanceSetting_MemoRelatedSetting:
type: object
properties:
displayWithUpdateTime:
type: boolean
description: display_with_update_time orders and displays memo with update time.
contentLengthLimit:
type: integer
description: content_length_limit is the limit of content length. Unit is byte.
......@@ -2959,10 +2956,6 @@ components:
The last update timestamp.
If not set on creation, the server will set it to the current time.
format: date-time
displayTime:
type: string
description: The display timestamp of the memo.
format: date-time
content:
type: string
description: Required. The content of the memo in Markdown format.
......@@ -3637,12 +3630,6 @@ components:
description: |-
The resource name of the user whose stats these are.
Format: users/{user}
memoDisplayTimestamps:
type: array
items:
type: string
format: date-time
description: The timestamps when the memos were displayed.
memoTypeStats:
allOf:
- $ref: '#/components/schemas/UserStats_MemoTypeStats'
......@@ -3653,6 +3640,12 @@ components:
type: integer
format: int32
description: The count of tags.
memoCreatedTimestamps:
type: array
items:
type: string
format: date-time
description: The creation timestamps of the user's memos.
pinnedMemos:
type: array
items:
......
......@@ -751,8 +751,6 @@ func (x *StorageS3Config) GetUsePathStyle() bool {
type InstanceMemoRelatedSetting struct {
state protoimpl.MessageState `protogen:"open.v1"`
// display_with_update_time orders and displays memo with update time.
DisplayWithUpdateTime bool `protobuf:"varint,2,opt,name=display_with_update_time,json=displayWithUpdateTime,proto3" json:"display_with_update_time,omitempty"`
// content_length_limit is the limit of content length. Unit is byte.
ContentLengthLimit int32 `protobuf:"varint,3,opt,name=content_length_limit,json=contentLengthLimit,proto3" json:"content_length_limit,omitempty"`
// enable_double_click_edit enables editing on double click.
......@@ -793,13 +791,6 @@ func (*InstanceMemoRelatedSetting) Descriptor() ([]byte, []int) {
return file_store_instance_setting_proto_rawDescGZIP(), []int{6}
}
func (x *InstanceMemoRelatedSetting) GetDisplayWithUpdateTime() bool {
if x != nil {
return x.DisplayWithUpdateTime
}
return false
}
func (x *InstanceMemoRelatedSetting) GetContentLengthLimit() int32 {
if x != nil {
return x.ContentLengthLimit
......@@ -1255,12 +1246,11 @@ const file_store_instance_setting_proto_rawDesc = "" +
"\bendpoint\x18\x03 \x01(\tR\bendpoint\x12\x16\n" +
"\x06region\x18\x04 \x01(\tR\x06region\x12\x16\n" +
"\x06bucket\x18\x05 \x01(\tR\x06bucket\x12$\n" +
"\x0euse_path_style\x18\x06 \x01(\bR\fusePathStyle\"\xde\x01\n" +
"\x1aInstanceMemoRelatedSetting\x127\n" +
"\x18display_with_update_time\x18\x02 \x01(\bR\x15displayWithUpdateTime\x120\n" +
"\x0euse_path_style\x18\x06 \x01(\bR\fusePathStyle\"\xc5\x01\n" +
"\x1aInstanceMemoRelatedSetting\x120\n" +
"\x14content_length_limit\x18\x03 \x01(\x05R\x12contentLengthLimit\x127\n" +
"\x18enable_double_click_edit\x18\x04 \x01(\bR\x15enableDoubleClickEdit\x12\x1c\n" +
"\treactions\x18\a \x03(\tR\treactions\"w\n" +
"\treactions\x18\a \x03(\tR\treactionsJ\x04\b\x02\x10\x03R\x18display_with_update_time\"w\n" +
"\x13InstanceTagMetadata\x12=\n" +
"\x10background_color\x18\x01 \x01(\v2\x12.google.type.ColorR\x0fbackgroundColor\x12!\n" +
"\fblur_content\x18\x02 \x01(\bR\vblurContent\"\xb0\x01\n" +
......
......@@ -103,8 +103,8 @@ message StorageS3Config {
}
message InstanceMemoRelatedSetting {
// display_with_update_time orders and displays memo with update time.
bool display_with_update_time = 2;
reserved 2;
reserved "display_with_update_time";
// content_length_limit is the limit of content length. Unit is byte.
int32 content_length_limit = 3;
// enable_double_click_edit enables editing on double click.
......
......@@ -325,7 +325,6 @@ func convertInstanceMemoRelatedSettingFromStore(setting *storepb.InstanceMemoRel
return nil
}
return &v1pb.InstanceSetting_MemoRelatedSetting{
DisplayWithUpdateTime: setting.DisplayWithUpdateTime,
ContentLengthLimit: setting.ContentLengthLimit,
EnableDoubleClickEdit: setting.EnableDoubleClickEdit,
Reactions: setting.Reactions,
......@@ -337,7 +336,6 @@ func convertInstanceMemoRelatedSettingToStore(setting *v1pb.InstanceSetting_Memo
return nil
}
return &storepb.InstanceMemoRelatedSetting{
DisplayWithUpdateTime: setting.DisplayWithUpdateTime,
ContentLengthLimit: setting.ContentLengthLimit,
EnableDoubleClickEdit: setting.EnableDoubleClickEdit,
Reactions: setting.Reactions,
......
......@@ -54,25 +54,7 @@ func (s *APIV1Service) CreateMemo(ctx context.Context, request *v1pb.CreateMemoR
Visibility: convertVisibilityToStore(request.Memo.Visibility),
}
instanceMemoRelatedSetting, err := s.Store.GetInstanceMemoRelatedSetting(ctx)
if err != nil {
return nil, status.Errorf(codes.Internal, "failed to get instance memo related setting")
}
// Handle display_time first: if provided, use it to set the appropriate timestamp
// based on the instance setting (similar to UpdateMemo logic)
// Note: explicit create_time/update_time below will override this if provided
if request.Memo.DisplayTime != nil && request.Memo.DisplayTime.IsValid() {
displayTs := request.Memo.DisplayTime.AsTime().Unix()
if instanceMemoRelatedSetting.DisplayWithUpdateTime {
create.UpdatedTs = displayTs
} else {
create.CreatedTs = displayTs
}
}
// Set custom timestamps if provided in the request
// These take precedence over display_time
// Set custom timestamps if provided in the request.
if request.Memo.CreateTime != nil && request.Memo.CreateTime.IsValid() {
createdTs := request.Memo.CreateTime.AsTime().Unix()
create.CreatedTs = createdTs
......@@ -196,7 +178,7 @@ func (s *APIV1Service) ListMemos(ctx context.Context, request *v1pb.ListMemosReq
return nil, status.Errorf(codes.InvalidArgument, "invalid order_by: %v", err)
}
} else {
// Default ordering by display_time desc
// Default ordering by create_time desc.
memoFind.OrderByTimeAsc = false
}
......@@ -218,14 +200,6 @@ func (s *APIV1Service) ListMemos(ctx context.Context, request *v1pb.ListMemosReq
}
}
instanceMemoRelatedSetting, err := s.Store.GetInstanceMemoRelatedSetting(ctx)
if err != nil {
return nil, status.Errorf(codes.Internal, "failed to get instance memo related setting")
}
if instanceMemoRelatedSetting.DisplayWithUpdateTime {
memoFind.OrderByUpdatedTs = true
}
var limit, offset int
if request.PageToken != "" {
var pageToken v1pb.PageToken
......@@ -312,15 +286,13 @@ func (s *APIV1Service) ListMemos(ctx context.Context, request *v1pb.ListMemosReq
if err != nil {
return nil, status.Errorf(codes.Internal, "failed to list memo creators: %v", err)
}
conversionOptions := memoConversionOptions{displayWithUpdateTime: instanceMemoRelatedSetting.DisplayWithUpdateTime}
for _, memo := range memos {
memoName := fmt.Sprintf("%s%s", MemoNamePrefix, memo.UID)
reactions := reactionMap[memoName]
attachments := attachmentMap[memo.ID]
relations := relationMap[memo.ID]
memoMessage, err := s.convertMemoFromStoreWithCreatorsAndOptions(ctx, memo, reactions, attachments, relations, creatorMap, conversionOptions)
memoMessage, err := s.convertMemoFromStoreWithCreators(ctx, memo, reactions, attachments, relations, creatorMap)
if err != nil {
if stderrors.Is(err, errMemoCreatorNotFound) {
slog.Warn("Skipping memo with missing creator",
......@@ -479,16 +451,7 @@ func (s *APIV1Service) UpdateMemo(ctx context.Context, request *v1pb.UpdateMemoR
}
update.UpdatedTs = &updatedTs
} else if path == "display_time" {
displayTs := request.Memo.DisplayTime.AsTime().Unix()
memoRelatedSetting, err := s.Store.GetInstanceMemoRelatedSetting(ctx)
if err != nil {
return nil, status.Errorf(codes.Internal, "failed to get instance memo related setting")
}
if memoRelatedSetting.DisplayWithUpdateTime {
update.UpdatedTs = &displayTs
} else {
update.CreatedTs = &displayTs
}
return nil, status.Errorf(codes.InvalidArgument, "display_time is not supported")
} else if path == "location" {
payload := memo.Payload
payload.Location = convertLocationToStore(request.Memo.Location)
......@@ -817,12 +780,6 @@ func (s *APIV1Service) ListMemoComments(ctx context.Context, request *v1pb.ListM
if err != nil {
return nil, status.Errorf(codes.Internal, "failed to list memo creators: %v", err)
}
instanceMemoRelatedSetting, err := s.Store.GetInstanceMemoRelatedSetting(ctx)
if err != nil {
return nil, status.Errorf(codes.Internal, "failed to get instance memo related setting")
}
conversionOptions := memoConversionOptions{displayWithUpdateTime: instanceMemoRelatedSetting.DisplayWithUpdateTime}
var memosResponse []*v1pb.Memo
for _, m := range memos {
memoName := memoIDToNameMap[m.ID]
......@@ -830,7 +787,7 @@ func (s *APIV1Service) ListMemoComments(ctx context.Context, request *v1pb.ListM
attachments := attachmentMap[m.ID]
relations := relationMap[m.ID]
memoMessage, err := s.convertMemoFromStoreWithCreatorsAndOptions(ctx, m, reactions, attachments, relations, creatorMap, conversionOptions)
memoMessage, err := s.convertMemoFromStoreWithCreators(ctx, m, reactions, attachments, relations, creatorMap)
if err != nil {
if stderrors.Is(err, errMemoCreatorNotFound) {
slog.Warn("Skipping memo comment with missing creator",
......@@ -939,7 +896,7 @@ func (s *APIV1Service) getMemoContentSnippet(content string) (string, error) {
// parseMemoOrderBy parses the order_by field and sets the appropriate ordering in memoFind.
// Follows AIP-132: supports comma-separated list of fields with optional "desc" suffix.
// Example: "pinned desc, display_time desc" or "create_time asc".
// Example: "pinned desc, create_time desc" or "update_time asc".
func (*APIV1Service) parseMemoOrderBy(orderBy string, memoFind *store.FindMemo) error {
if strings.TrimSpace(orderBy) == "" {
return errors.New("empty order_by")
......@@ -950,6 +907,7 @@ func (*APIV1Service) parseMemoOrderBy(orderBy string, memoFind *store.FindMemo)
// Track if we've seen pinned field.
hasPinned := false
hasExplicitTimeField := false
for _, field := range fields {
parts := strings.Fields(strings.TrimSpace(field))
......@@ -971,16 +929,21 @@ func (*APIV1Service) parseMemoOrderBy(orderBy string, memoFind *store.FindMemo)
hasPinned = true
memoFind.OrderByPinned = true
// Note: pinned is always DESC (true first) regardless of direction specified.
case "display_time", "create_time", "name":
case "create_time", "name":
// Only set if this is the first time field we encounter.
if !memoFind.OrderByUpdatedTs {
if !hasExplicitTimeField {
memoFind.OrderByTimeAsc = fieldDirection == "asc"
}
hasExplicitTimeField = true
case "update_time":
// Only set if this is the first time field we encounter.
if !hasExplicitTimeField {
memoFind.OrderByUpdatedTs = true
memoFind.OrderByTimeAsc = fieldDirection == "asc"
}
hasExplicitTimeField = true
default:
return errors.Errorf("unsupported order field: %s, supported fields are: pinned, display_time, create_time, update_time, name", fieldName)
return errors.Errorf("unsupported order field: %s, supported fields are: pinned, create_time, update_time, name", fieldName)
}
}
......
......@@ -20,10 +20,6 @@ var (
errReactionCreatorNotFound = stderrors.New("reaction creator not found")
)
type memoConversionOptions struct {
displayWithUpdateTime bool
}
func (s *APIV1Service) convertMemoFromStore(ctx context.Context, memo *store.Memo, reactions []*store.Reaction, attachments []*store.Attachment, relations []*v1pb.MemoRelation) (*v1pb.Memo, error) {
creatorMap, err := s.listUsersByID(ctx, []int32{memo.CreatorID})
if err != nil {
......@@ -33,27 +29,6 @@ func (s *APIV1Service) convertMemoFromStore(ctx context.Context, memo *store.Mem
}
func (s *APIV1Service) convertMemoFromStoreWithCreators(ctx context.Context, memo *store.Memo, reactions []*store.Reaction, attachments []*store.Attachment, relations []*v1pb.MemoRelation, creatorMap map[int32]*store.User) (*v1pb.Memo, error) {
instanceMemoRelatedSetting, err := s.Store.GetInstanceMemoRelatedSetting(ctx)
if err != nil {
return nil, errors.Wrap(err, "failed to get instance memo related setting")
}
return s.convertMemoFromStoreWithCreatorsAndOptions(
ctx,
memo,
reactions,
attachments,
relations,
creatorMap,
memoConversionOptions{displayWithUpdateTime: instanceMemoRelatedSetting.DisplayWithUpdateTime},
)
}
func (s *APIV1Service) convertMemoFromStoreWithCreatorsAndOptions(ctx context.Context, memo *store.Memo, reactions []*store.Reaction, attachments []*store.Attachment, relations []*v1pb.MemoRelation, creatorMap map[int32]*store.User, options memoConversionOptions) (*v1pb.Memo, error) {
displayTs := memo.CreatedTs
if options.displayWithUpdateTime {
displayTs = memo.UpdatedTs
}
name := fmt.Sprintf("%s%s", MemoNamePrefix, memo.UID)
creator := creatorMap[memo.CreatorID]
if creator == nil {
......@@ -65,7 +40,6 @@ func (s *APIV1Service) convertMemoFromStoreWithCreatorsAndOptions(ctx context.Co
Creator: BuildUserName(creator.Username),
CreateTime: timestamppb.New(time.Unix(memo.CreatedTs, 0)),
UpdateTime: timestamppb.New(time.Unix(memo.UpdatedTs, 0)),
DisplayTime: timestamppb.New(time.Unix(displayTs, 0)),
Content: memo.Content,
Visibility: convertVisibilityFromStore(memo.Visibility),
Pinned: memo.Pinned,
......
......@@ -254,6 +254,120 @@ func TestListMemos(t *testing.T) {
require.Equal(t, "👍", userTwoReaction.ReactionType)
}
func TestListMemosTimeOrderBy(t *testing.T) {
ctx := context.Background()
ts := NewTestService(t)
defer ts.Cleanup()
user, err := ts.CreateHostUser(ctx, "time-order-user")
require.NoError(t, err)
userCtx := ts.CreateUserContext(ctx, user.ID)
memoEarlyCreateLateUpdate, err := ts.Service.CreateMemo(userCtx, &apiv1.CreateMemoRequest{
Memo: &apiv1.Memo{
Content: "early create late update",
Visibility: apiv1.Visibility_PRIVATE,
CreateTime: timestamppb.New(time.Date(2020, 1, 1, 0, 0, 0, 0, time.UTC)),
UpdateTime: timestamppb.New(time.Date(2020, 1, 3, 0, 0, 0, 0, time.UTC)),
},
})
require.NoError(t, err)
memoMiddleCreateEarlyUpdate, err := ts.Service.CreateMemo(userCtx, &apiv1.CreateMemoRequest{
Memo: &apiv1.Memo{
Content: "middle create early update",
Visibility: apiv1.Visibility_PRIVATE,
CreateTime: timestamppb.New(time.Date(2020, 1, 2, 0, 0, 0, 0, time.UTC)),
UpdateTime: timestamppb.New(time.Date(2020, 1, 1, 0, 0, 0, 0, time.UTC)),
},
})
require.NoError(t, err)
memoLateCreateMiddleUpdate, err := ts.Service.CreateMemo(userCtx, &apiv1.CreateMemoRequest{
Memo: &apiv1.Memo{
Content: "late create middle update",
Visibility: apiv1.Visibility_PRIVATE,
CreateTime: timestamppb.New(time.Date(2020, 1, 3, 0, 0, 0, 0, time.UTC)),
UpdateTime: timestamppb.New(time.Date(2020, 1, 2, 0, 0, 0, 0, time.UTC)),
},
})
require.NoError(t, err)
tests := []struct {
name string
orderBy string
wantNames []string
}{
{
name: "default create time",
orderBy: "",
wantNames: []string{
memoLateCreateMiddleUpdate.Name,
memoMiddleCreateEarlyUpdate.Name,
memoEarlyCreateLateUpdate.Name,
},
},
{
name: "explicit create time",
orderBy: "create_time desc",
wantNames: []string{
memoLateCreateMiddleUpdate.Name,
memoMiddleCreateEarlyUpdate.Name,
memoEarlyCreateLateUpdate.Name,
},
},
{
name: "explicit update time",
orderBy: "update_time desc",
wantNames: []string{
memoEarlyCreateLateUpdate.Name,
memoLateCreateMiddleUpdate.Name,
memoMiddleCreateEarlyUpdate.Name,
},
},
{
name: "pinned with explicit create time",
orderBy: "pinned desc, create_time desc",
wantNames: []string{
memoLateCreateMiddleUpdate.Name,
memoMiddleCreateEarlyUpdate.Name,
memoEarlyCreateLateUpdate.Name,
},
},
{
name: "explicit create time ascending",
orderBy: "create_time asc",
wantNames: []string{
memoEarlyCreateLateUpdate.Name,
memoMiddleCreateEarlyUpdate.Name,
memoLateCreateMiddleUpdate.Name,
},
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
resp, err := ts.Service.ListMemos(userCtx, &apiv1.ListMemosRequest{
PageSize: 10,
OrderBy: test.orderBy,
})
require.NoError(t, err)
require.Len(t, resp.Memos, len(test.wantNames))
gotNames := make([]string, 0, len(resp.Memos))
for _, memo := range resp.Memos {
gotNames = append(gotNames, memo.Name)
}
require.Equal(t, test.wantNames, gotNames)
})
}
_, err = ts.Service.ListMemos(userCtx, &apiv1.ListMemosRequest{
PageSize: 10,
OrderBy: "display_time desc",
})
require.Error(t, err)
}
func TestListMemosSkipsReactionsWithMissingCreators(t *testing.T) {
ctx := context.Background()
......@@ -431,7 +545,6 @@ func TestCreateMemoWithCustomTimestamps(t *testing.T) {
// Define custom timestamps (January 1, 2020)
customCreateTime := time.Date(2020, 1, 1, 12, 0, 0, 0, time.UTC)
customUpdateTime := time.Date(2020, 1, 2, 12, 0, 0, 0, time.UTC)
customDisplayTime := time.Date(2020, 1, 3, 12, 0, 0, 0, time.UTC)
// Test 1: Create a memo with custom create_time
memoWithCreateTime, err := ts.Service.CreateMemo(userCtx, &apiv1.CreateMemoRequest{
......@@ -457,41 +570,21 @@ func TestCreateMemoWithCustomTimestamps(t *testing.T) {
require.NotNil(t, memoWithUpdateTime)
require.Equal(t, customUpdateTime.Unix(), memoWithUpdateTime.UpdateTime.AsTime().Unix(), "update_time should match the custom timestamp")
// Test 3: Create a memo with custom display_time
// Note: display_time is computed from either created_ts or updated_ts based on instance setting
// Since DisplayWithUpdateTime defaults to false, display_time maps to created_ts
memoWithDisplayTime, err := ts.Service.CreateMemo(userCtx, &apiv1.CreateMemoRequest{
Memo: &apiv1.Memo{
Content: "This memo has a custom display time",
Visibility: apiv1.Visibility_PRIVATE,
DisplayTime: timestamppb.New(customDisplayTime),
},
})
require.NoError(t, err)
require.NotNil(t, memoWithDisplayTime)
// Since DisplayWithUpdateTime is false by default, display_time sets created_ts
require.Equal(t, customDisplayTime.Unix(), memoWithDisplayTime.DisplayTime.AsTime().Unix(), "display_time should match the custom timestamp")
require.Equal(t, customDisplayTime.Unix(), memoWithDisplayTime.CreateTime.AsTime().Unix(), "create_time should also match since display_time maps to created_ts")
// Test 4: Create a memo with all custom timestamps
// When both display_time and create_time are provided, create_time takes precedence
// Test 3: Create a memo with all custom timestamps
memoWithAllTimestamps, err := ts.Service.CreateMemo(userCtx, &apiv1.CreateMemoRequest{
Memo: &apiv1.Memo{
Content: "This memo has all custom timestamps",
Visibility: apiv1.Visibility_PRIVATE,
CreateTime: timestamppb.New(customCreateTime),
UpdateTime: timestamppb.New(customUpdateTime),
DisplayTime: timestamppb.New(customDisplayTime),
},
})
require.NoError(t, err)
require.NotNil(t, memoWithAllTimestamps)
require.Equal(t, customCreateTime.Unix(), memoWithAllTimestamps.CreateTime.AsTime().Unix(), "create_time should match the custom timestamp")
require.Equal(t, customUpdateTime.Unix(), memoWithAllTimestamps.UpdateTime.AsTime().Unix(), "update_time should match the custom timestamp")
// display_time is computed from created_ts when DisplayWithUpdateTime is false
require.Equal(t, customCreateTime.Unix(), memoWithAllTimestamps.DisplayTime.AsTime().Unix(), "display_time should be derived from create_time")
// Test 5: Create a comment (memo relation) with custom timestamps
// Test 4: Create a comment (memo relation) with custom timestamps
parentMemo, err := ts.Service.CreateMemo(userCtx, &apiv1.CreateMemoRequest{
Memo: &apiv1.Memo{
Content: "This is the parent memo",
......@@ -514,7 +607,7 @@ func TestCreateMemoWithCustomTimestamps(t *testing.T) {
require.NotNil(t, comment)
require.Equal(t, customCommentCreateTime.Unix(), comment.CreateTime.AsTime().Unix(), "comment create_time should match the custom timestamp")
// Test 6: Verify that memos without custom timestamps still get auto-generated ones
// Test 5: Verify that memos without custom timestamps still get auto-generated ones
memoWithoutTimestamps, err := ts.Service.CreateMemo(userCtx, &apiv1.CreateMemoRequest{
Memo: &apiv1.Memo{
Content: "This memo has auto-generated timestamps",
......
......@@ -5,7 +5,6 @@ import (
"fmt"
"time"
"github.com/pkg/errors"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
"google.golang.org/protobuf/types/known/timestamppb"
......@@ -55,11 +54,6 @@ func (s *APIV1Service) listUsernamesByID(ctx context.Context, userIDs []int32) (
}
func (s *APIV1Service) ListAllUserStats(ctx context.Context, _ *v1pb.ListAllUserStatsRequest) (*v1pb.ListAllUserStatsResponse, error) {
instanceMemoRelatedSetting, err := s.Store.GetInstanceMemoRelatedSetting(ctx)
if err != nil {
return nil, errors.Wrap(err, "failed to get instance memo related setting")
}
normalStatus := store.Normal
memoFind := &store.FindMemo{
// Exclude comments by default.
......@@ -105,7 +99,7 @@ func (s *APIV1Service) ListAllUserStats(ctx context.Context, _ *v1pb.ListAllUser
userMemoStatMap[memo.CreatorID] = &v1pb.UserStats{
Name: "",
TagCount: make(map[string]int32),
MemoDisplayTimestamps: []*timestamppb.Timestamp{},
MemoCreatedTimestamps: []*timestamppb.Timestamp{},
PinnedMemos: []string{},
MemoTypeStats: &v1pb.UserStats_MemoTypeStats{
LinkCount: 0,
......@@ -118,12 +112,7 @@ func (s *APIV1Service) ListAllUserStats(ctx context.Context, _ *v1pb.ListAllUser
stats := userMemoStatMap[memo.CreatorID]
// Add display timestamp
displayTs := memo.CreatedTs
if instanceMemoRelatedSetting.DisplayWithUpdateTime {
displayTs = memo.UpdatedTs
}
stats.MemoDisplayTimestamps = append(stats.MemoDisplayTimestamps, timestamppb.New(time.Unix(displayTs, 0)))
stats.MemoCreatedTimestamps = append(stats.MemoCreatedTimestamps, timestamppb.New(time.Unix(memo.CreatedTs, 0)))
// Count memo stats
stats.TotalMemoCount++
......@@ -215,12 +204,7 @@ func (s *APIV1Service) GetUserStats(ctx context.Context, request *v1pb.GetUserSt
memoFind.VisibilityList = []store.Visibility{store.Public, store.Protected}
}
instanceMemoRelatedSetting, err := s.Store.GetInstanceMemoRelatedSetting(ctx)
if err != nil {
return nil, errors.Wrap(err, "failed to get instance memo related setting")
}
displayTimestamps := []*timestamppb.Timestamp{}
createdTimestamps := []*timestamppb.Timestamp{}
tagCount := make(map[string]int32)
linkCount := int32(0)
codeCount := int32(0)
......@@ -246,11 +230,7 @@ func (s *APIV1Service) GetUserStats(ctx context.Context, request *v1pb.GetUserSt
totalMemoCount += int32(len(memos))
for _, memo := range memos {
displayTs := memo.CreatedTs
if instanceMemoRelatedSetting.DisplayWithUpdateTime {
displayTs = memo.UpdatedTs
}
displayTimestamps = append(displayTimestamps, timestamppb.New(time.Unix(displayTs, 0)))
createdTimestamps = append(createdTimestamps, timestamppb.New(time.Unix(memo.CreatedTs, 0)))
// Count different memo types based on content.
if memo.Payload != nil {
for _, tag := range memo.Payload.Tags {
......@@ -281,7 +261,7 @@ func (s *APIV1Service) GetUserStats(ctx context.Context, request *v1pb.GetUserSt
userStats := &v1pb.UserStats{
Name: fmt.Sprintf("%s/stats", BuildUserName(user.Username)),
MemoDisplayTimestamps: displayTimestamps,
MemoCreatedTimestamps: createdTimestamps,
TagCount: tagCount,
PinnedMemos: pinnedMemos,
TotalMemoCount: totalMemoCount,
......
......@@ -35,7 +35,7 @@ export const buildMemoShareImagePreviewModel = ({
}: BuildMemoShareImagePreviewModelOptions): MemoShareImagePreviewModel => {
const displayName = creator?.displayName || creator?.username || fallbackDisplayName;
const avatarUrl = getMemoSharePreviewAvatarUrl(creator?.avatarUrl);
const displayTime = memo.displayTime ? timestampDate(memo.displayTime) : memo.createTime ? timestampDate(memo.createTime) : undefined;
const displayTime = memo.createTime ? timestampDate(memo.createTime) : undefined;
const formattedDisplayTime = displayTime?.toLocaleString(locale, {
dateStyle: "medium",
timeStyle: "short",
......
......@@ -67,7 +67,7 @@ const MemoCommentSection = ({ memo, comments, parentPage }: Props) => {
</div>
)}
{comments.map((comment) => (
<div className="w-full" key={`${comment.name}-${comment.displayTime}`} id={extractMemoIdFromName(comment.name)}>
<div className="w-full" key={`${comment.name}-${comment.updateTime}`} id={extractMemoIdFromName(comment.name)}>
<MemoView memo={comment} parentPage={parentPage} showCreator compact />
</div>
))}
......
......@@ -11,8 +11,8 @@ interface Props {
function MemoDisplaySettingMenu({ className }: Props) {
const t = useTranslate();
const { orderByTimeAsc, toggleSortOrder } = useView();
const isApplying = orderByTimeAsc !== false;
const { orderByTimeAsc, timeBasis, setTimeBasis, toggleSortOrder } = useView();
const isApplying = orderByTimeAsc !== false || timeBasis !== "create_time";
return (
<Popover>
......@@ -22,7 +22,19 @@ function MemoDisplaySettingMenu({ className }: Props) {
<PopoverContent align="end" alignOffset={-12} sideOffset={14}>
<div className="flex flex-col gap-2 p-1">
<div className="w-full flex flex-row justify-between items-center">
<span className="text-sm shrink-0 mr-3 text-foreground">{t("memo.direction")}</span>
<span className="text-sm shrink-0 mr-3 text-foreground">{t("memo.shown-time")}</span>
<Select value={timeBasis} onValueChange={(value) => setTimeBasis(value === "update_time" ? "update_time" : "create_time")}>
<SelectTrigger size="sm" className="w-32">
<SelectValue />
</SelectTrigger>
<SelectContent>
<SelectItem value="create_time">{t("common.created-at")}</SelectItem>
<SelectItem value="update_time">{t("common.last-updated-at")}</SelectItem>
</SelectContent>
</Select>
</div>
<div className="w-full flex flex-row justify-between items-center">
<span className="text-sm shrink-0 mr-3 text-foreground">{t("memo.order")}</span>
<Select
value={orderByTimeAsc.toString()}
onValueChange={(value) => {
......@@ -31,12 +43,12 @@ function MemoDisplaySettingMenu({ className }: Props) {
}
}}
>
<SelectTrigger size="sm">
<SelectTrigger size="sm" className="w-32">
<SelectValue />
</SelectTrigger>
<SelectContent>
<SelectItem value="false">{t("memo.direction-desc")}</SelectItem>
<SelectItem value="true">{t("memo.direction-asc")}</SelectItem>
<SelectItem value="false">{t("memo.newest-first")}</SelectItem>
<SelectItem value="true">{t("memo.oldest-first")}</SelectItem>
</SelectContent>
</Select>
</div>
......
......@@ -74,7 +74,7 @@ export const LinkMemoDialog = ({
<div className="w-full flex flex-col gap-1">
<div className="flex items-center gap-1.5 text-sm text-muted-foreground select-none">
{alreadyLinked && <LinkIcon className="w-3 h-3 shrink-0" />}
<span>{memo.displayTime && timestampDate(memo.displayTime).toLocaleString()}</span>
<span>{memo.createTime && timestampDate(memo.createTime).toLocaleString()}</span>
</div>
<MemoPreview name={memo.name} content={memo.content} attachments={memo.attachments} showMemoId />
</div>
......
import { timestampDate } from "@bufbuild/protobuf/wkt";
import { createContext, useContext } from "react";
import { useLocation } from "react-router-dom";
import { useView } from "@/contexts/ViewContext";
import type { Memo } from "@/types/proto/api/v1/memo_service_pb";
import { MemoRelation_Type } from "@/types/proto/api/v1/memo_service_pb";
import type { User } from "@/types/proto/api/v1/user_service_pb";
......@@ -37,12 +38,14 @@ export const computeCommentAmount = (memo: Memo): number =>
export const useMemoViewDerived = () => {
const { memo, isArchived, readonly } = useMemoViewContext();
const { timeBasis } = useView();
const location = useLocation();
const isInMemoDetailPage = location.pathname.startsWith(`/${memo.name}`) || location.pathname.startsWith("/memos/shares/");
const commentAmount = computeCommentAmount(memo);
const displayTime = memo.displayTime ? timestampDate(memo.displayTime) : undefined;
const displayTimestamp = timeBasis === "update_time" ? memo.updateTime : memo.createTime;
const displayTime = displayTimestamp ? timestampDate(displayTimestamp) : undefined;
const relativeTimeFormat: "datetime" | "auto" =
displayTime && Date.now() - displayTime.getTime() > RELATIVE_TIME_THRESHOLD_MS ? "datetime" : "auto";
......@@ -51,6 +54,7 @@ export const useMemoViewDerived = () => {
readonly,
isInMemoDetailPage,
commentAmount,
displayTime,
relativeTimeFormat,
};
};
import { timestampDate } from "@bufbuild/protobuf/wkt";
import { BookmarkIcon } from "lucide-react";
import { useCallback, useState } from "react";
import { Link } from "react-router-dom";
......@@ -23,7 +22,7 @@ const MemoHeader: React.FC<MemoHeaderProps> = ({ showCreator, showVisibility, sh
const [reactionSelectorOpen, setReactionSelectorOpen] = useState(false);
const { memo, creator, currentUser, parentPage, isArchived, readonly, openEditor } = useMemoViewContext();
const { relativeTimeFormat } = useMemoViewDerived();
const { displayTime: memoDisplayTime, relativeTimeFormat } = useMemoViewDerived();
const navigateTo = useNavigateTo();
const handleGotoMemoDetailPage = useCallback(() => {
......@@ -33,13 +32,9 @@ const MemoHeader: React.FC<MemoHeaderProps> = ({ showCreator, showVisibility, sh
const { unpinMemo } = useMemoActions(memo);
const displayTime = isArchived ? (
(memo.displayTime ? timestampDate(memo.displayTime) : undefined)?.toLocaleString(i18n.language)
memoDisplayTime?.toLocaleString(i18n.language)
) : (
<relative-time
datetime={(memo.displayTime ? timestampDate(memo.displayTime) : undefined)?.toISOString()}
lang={i18n.language}
format={relativeTimeFormat}
></relative-time>
<relative-time datetime={memoDisplayTime?.toISOString()} lang={i18n.language} format={relativeTimeFormat}></relative-time>
);
return (
......
......@@ -88,7 +88,7 @@ const PagedMemoList = (props: Props) => {
const { data, fetchNextPage, hasNextPage, isFetchingNextPage, isLoading } = useInfiniteMemos(
{
state: props.state || State.NORMAL,
orderBy: props.orderBy || "display_time desc",
orderBy: props.orderBy || "create_time desc",
filter: props.filter,
pageSize: props.pageSize || DEFAULT_LIST_MEMOS_PAGE_SIZE,
},
......
......@@ -72,13 +72,6 @@ const MemoRelatedSettings = () => {
return (
<SettingSection title={t("setting.memo.label")}>
<SettingGroup title={t("common.basic")}>
<SettingRow label={t("setting.system.display-with-updated-time")}>
<Switch
checked={memoRelatedSetting.displayWithUpdateTime}
onCheckedChange={(checked) => updatePartialSetting({ displayWithUpdateTime: checked })}
/>
</SettingRow>
<SettingRow label={t("setting.system.enable-double-click-to-edit")}>
<Switch
checked={memoRelatedSetting.enableDoubleClickEdit}
......
......@@ -52,7 +52,7 @@ const UserMemoMap = ({ creator, className }: Props) => {
const { data, isLoading } = useInfiniteMemos(
{
state: State.NORMAL,
orderBy: "display_time desc",
orderBy: "create_time desc",
pageSize: 1000,
filter: creatorFilter,
},
......@@ -133,8 +133,8 @@ const UserMemoMap = ({ creator, className }: Props) => {
Memo
</span>
<span className="block text-[11px] font-medium text-muted-foreground">
{memo.displayTime &&
timestampDate(memo.displayTime).toLocaleDateString(undefined, {
{memo.createTime &&
timestampDate(memo.createTime).toLocaleDateString(undefined, {
year: "numeric",
month: "short",
day: "numeric",
......
import { createContext, type ReactNode, useContext, useState } from "react";
export type MemoTimeBasis = "create_time" | "update_time";
interface ViewState {
orderByTimeAsc: boolean;
timeBasis?: MemoTimeBasis;
sortTimeField?: MemoTimeBasis;
}
interface ViewContextValue {
orderByTimeAsc: boolean;
timeBasis: MemoTimeBasis;
toggleSortOrder: () => void;
setTimeBasis: (field: MemoTimeBasis) => void;
}
const ViewContext = createContext<ViewContextValue | null>(null);
......@@ -10,13 +20,16 @@ const ViewContext = createContext<ViewContextValue | null>(null);
const LOCAL_STORAGE_KEY = "memos-view-setting";
export function ViewProvider({ children }: { children: ReactNode }) {
const getInitialState = () => {
const getInitialState = (): ViewState => {
try {
const cached = localStorage.getItem(LOCAL_STORAGE_KEY);
if (cached) {
const data = JSON.parse(cached);
const data = JSON.parse(cached) as Partial<ViewState>;
const cachedTimeBasis = data.timeBasis ?? data.sortTimeField;
const timeBasis = cachedTimeBasis === "create_time" || cachedTimeBasis === "update_time" ? cachedTimeBasis : undefined;
return {
orderByTimeAsc: Boolean(data.orderByTimeAsc ?? false),
timeBasis,
};
}
} catch (error) {
......@@ -26,8 +39,9 @@ export function ViewProvider({ children }: { children: ReactNode }) {
};
const [viewState, setViewState] = useState(getInitialState);
const timeBasis = viewState.timeBasis ?? "create_time";
const persistToStorage = (newState: typeof viewState) => {
const persistToStorage = (newState: ViewState) => {
try {
localStorage.setItem(LOCAL_STORAGE_KEY, JSON.stringify(newState));
} catch (error) {
......@@ -43,11 +57,21 @@ export function ViewProvider({ children }: { children: ReactNode }) {
});
};
const setTimeBasis = (field: MemoTimeBasis) => {
setViewState((prev) => {
const newState = { ...prev, timeBasis: field };
persistToStorage(newState);
return newState;
});
};
return (
<ViewContext.Provider
value={{
...viewState,
orderByTimeAsc: viewState.orderByTimeAsc,
timeBasis,
toggleSortOrder,
setTimeBasis,
}}
>
{children}
......
......@@ -49,15 +49,15 @@ export const useFilteredMemoStats = (options: UseFilteredMemoStatsOptions = {}):
}
}
const displayDates = (memosResponse?.memos ?? [])
.map((memo) => (memo.displayTime ? timestampDate(memo.displayTime) : undefined))
.map((memo) => (memo.createTime ? timestampDate(memo.createTime) : undefined))
.filter((date): date is Date => date !== undefined)
.map(toDateString);
activityStats = countBy(displayDates);
} else if (userName && userStats) {
// home/profile: use backend per-user stats
if (userStats.memoDisplayTimestamps && userStats.memoDisplayTimestamps.length > 0) {
if (userStats.memoCreatedTimestamps && userStats.memoCreatedTimestamps.length > 0) {
activityStats = countBy(
userStats.memoDisplayTimestamps
userStats.memoCreatedTimestamps
.map((ts) => (ts ? timestampDate(ts) : undefined))
.filter((date): date is Date => date !== undefined)
.map(toDateString),
......@@ -69,7 +69,7 @@ export const useFilteredMemoStats = (options: UseFilteredMemoStatsOptions = {}):
} else if (memosResponse?.memos) {
// archived/fallback: compute from cached memos
const displayDates = memosResponse.memos
.map((memo) => (memo.displayTime ? timestampDate(memo.displayTime) : undefined))
.map((memo) => (memo.createTime ? timestampDate(memo.createTime) : undefined))
.filter((date): date is Date => date !== undefined)
.map(toDateString);
activityStats = countBy(displayDates);
......
import { useMemo } from "react";
import { useAuth } from "@/contexts/AuthContext";
import { useInstance } from "@/contexts/InstanceContext";
import { useMemoFilterContext } from "@/contexts/MemoFilterContext";
import { buildMemoCreatorFilter } from "@/helpers/resource-names";
import { Visibility } from "@/types/proto/api/v1/memo_service_pb";
......@@ -37,7 +36,6 @@ export const useMemoFilters = (options: UseMemoFiltersOptions = {}): string | un
const { shortcuts } = useAuth();
const { filters, shortcut: currentShortcut } = useMemoFilterContext();
const { memoRelatedSetting } = useInstance();
// Get selected shortcut if needed
const selectedShortcut = useMemo(() => {
......@@ -79,14 +77,11 @@ export const useMemoFilters = (options: UseMemoFiltersOptions = {}): string | un
} else if (filter.factor === "property.hasCode") {
conditions.push(`has_code`);
} else if (filter.factor === "displayTime") {
const displayWithUpdateTime = memoRelatedSetting?.displayWithUpdateTime ?? false;
const factor = displayWithUpdateTime ? "updated_ts" : "created_ts";
const filterDate = new Date(filter.value);
const filterUtcTimestamp = filterDate.getTime() + filterDate.getTimezoneOffset() * 60 * 1000;
const timestampAfter = filterUtcTimestamp / 1000;
conditions.push(`${factor} >= ${timestampAfter} && ${factor} < ${timestampAfter + 60 * 60 * 24}`);
conditions.push(`created_ts >= ${timestampAfter} && created_ts < ${timestampAfter + 60 * 60 * 24}`);
}
}
......@@ -97,5 +92,5 @@ export const useMemoFilters = (options: UseMemoFiltersOptions = {}): string | un
}
return conditions.length > 0 ? conditions.join(" && ") : undefined;
}, [creatorName, includeShortcuts, includePinned, visibilities, selectedShortcut, filters, memoRelatedSetting]);
}, [creatorName, includeShortcuts, includePinned, visibilities, selectedShortcut, filters]);
};
import { timestampDate } from "@bufbuild/protobuf/wkt";
import dayjs from "dayjs";
import { useMemo } from "react";
import { useView } from "@/contexts/ViewContext";
import { type MemoTimeBasis, useView } from "@/contexts/ViewContext";
import { State } from "@/types/proto/api/v1/common_pb";
import { Memo } from "@/types/proto/api/v1/memo_service_pb";
import type { Memo } from "@/types/proto/api/v1/memo_service_pb";
export interface UseMemoSortingOptions {
pinnedFirst?: boolean;
......@@ -15,15 +15,20 @@ export interface UseMemoSortingResult {
orderBy: string;
}
const getMemoSortTime = (memo: Memo, timeBasis: MemoTimeBasis): Date | undefined => {
const timestamp = timeBasis === "update_time" ? memo.updateTime : memo.createTime;
return timestamp ? timestampDate(timestamp) : undefined;
};
export const useMemoSorting = (options: UseMemoSortingOptions = {}): UseMemoSortingResult => {
const { pinnedFirst = false, state = State.NORMAL } = options;
const { orderByTimeAsc } = useView();
const { orderByTimeAsc, timeBasis } = useView();
// Generate orderBy string for API
const orderBy = useMemo(() => {
const timeOrder = orderByTimeAsc ? "display_time asc" : "display_time desc";
const timeOrder = orderByTimeAsc ? `${timeBasis} asc` : `${timeBasis} desc`;
return pinnedFirst ? `pinned desc, ${timeOrder}` : timeOrder;
}, [pinnedFirst, orderByTimeAsc]);
}, [pinnedFirst, orderByTimeAsc, timeBasis]);
// Generate listSort function for client-side sorting
const listSort = useMemo(() => {
......@@ -36,13 +41,13 @@ export const useMemoSorting = (options: UseMemoSortingOptions = {}): UseMemoSort
return b.pinned ? 1 : -1;
}
// Then sort by display time
const aTime = a.displayTime ? timestampDate(a.displayTime) : undefined;
const bTime = b.displayTime ? timestampDate(b.displayTime) : undefined;
// Then sort by the selected time field.
const aTime = getMemoSortTime(a, timeBasis);
const bTime = getMemoSortTime(b, timeBasis);
return orderByTimeAsc ? dayjs(aTime).unix() - dayjs(bTime).unix() : dayjs(bTime).unix() - dayjs(aTime).unix();
});
};
}, [pinnedFirst, state, orderByTimeAsc]);
}, [pinnedFirst, state, orderByTimeAsc, timeBasis]);
return { listSort, orderBy };
};
......@@ -247,9 +247,13 @@
"load-more": "Load more",
"no-archived-memos": "No archived memos.",
"no-memos": "No memos.",
"newest-first": "Newest first",
"oldest-first": "Oldest first",
"order": "Order",
"order-by": "Order By",
"outline": "Outline",
"search-placeholder": "Search memos...",
"shown-time": "Shown time",
"share": {
"active-links": "Active share links",
"copied": "Copied!",
......
......@@ -209,8 +209,12 @@
"load-more": "加载更多",
"no-archived-memos": "没有已归档备忘录。",
"no-memos": "无备忘录",
"newest-first": "最新优先",
"oldest-first": "最早优先",
"order": "顺序",
"order-by": "排序",
"search-placeholder": "搜索备忘录",
"shown-time": "显示时间",
"show-less": "显示较少",
"show-more": "查看更多",
"to-do": "待办",
......
......@@ -206,8 +206,12 @@
"load-more": "載入更多",
"no-archived-memos": "無已封存的備忘錄",
"no-memos": "無備忘錄",
"newest-first": "最新優先",
"oldest-first": "最早優先",
"order": "順序",
"order-by": "排序",
"search-placeholder": "搜尋備忘錄",
"shown-time": "顯示時間",
"show-less": "顯示較少",
"show-more": "查看更多",
"to-do": "待辦事項",
......
......@@ -24,7 +24,7 @@ const Home = () => {
return (
<div className="w-full min-h-full bg-background text-foreground">
<PagedMemoList
renderer={(memo: Memo) => <MemoView key={`${memo.name}-${memo.displayTime}`} memo={memo} showVisibility showPinned compact />}
renderer={(memo: Memo) => <MemoView key={`${memo.name}-${memo.updateTime}`} memo={memo} showVisibility showPinned compact />}
listSort={listSort}
orderBy={orderBy}
filter={memoFilter}
......
......@@ -100,7 +100,7 @@ const MemoDetail = () => {
</div>
)}
<MemoView
key={`${displayMemo.name}-${displayMemo.displayTime}`}
key={`${displayMemo.name}-${displayMemo.updateTime}`}
memo={displayMemo}
compact={false}
parentPage={locationState?.from}
......
......@@ -130,7 +130,7 @@ const UserProfile = () => {
{activeTab === "memos" ? (
<PagedMemoList
renderer={(memo: Memo) => (
<MemoView key={`${memo.name}-${memo.displayTime}`} memo={memo} showVisibility showPinned compact />
<MemoView key={`${memo.name}-${memo.updateTime}`} memo={memo} showVisibility showPinned compact />
)}
listSort={listSort}
orderBy={orderBy}
......
// @generated by protoc-gen-es v2.11.0 with parameter "target=ts"
// @generated by protoc-gen-es v2.12.0 with parameter "target=ts"
// @generated from file api/v1/ai_service.proto (package memos.api.v1, syntax proto3)
/* eslint-disable */
......@@ -31,14 +31,14 @@ export type TranscribeRequest = Message<"memos.api.v1.TranscribeRequest"> & {
*
* @generated from field: memos.api.v1.TranscriptionConfig config = 2;
*/
config?: TranscriptionConfig;
config?: TranscriptionConfig | undefined;
/**
* Required. Audio input.
*
* @generated from field: memos.api.v1.TranscriptionAudio audio = 3;
*/
audio?: TranscriptionAudio;
audio?: TranscriptionAudio | undefined;
};
/**
......
// @generated by protoc-gen-es v2.11.0 with parameter "target=ts"
// @generated by protoc-gen-es v2.12.0 with parameter "target=ts"
// @generated from file api/v1/attachment_service.proto (package memos.api.v1, syntax proto3)
/* eslint-disable */
......@@ -72,7 +72,7 @@ export type Attachment = Message<"memos.api.v1.Attachment"> & {
*
* @generated from field: google.protobuf.Timestamp create_time = 2;
*/
createTime?: Timestamp;
createTime?: Timestamp | undefined;
/**
* The filename of the attachment.
......@@ -115,14 +115,14 @@ export type Attachment = Message<"memos.api.v1.Attachment"> & {
*
* @generated from field: optional string memo = 8;
*/
memo?: string;
memo?: string | undefined;
/**
* Optional. Motion media metadata.
*
* @generated from field: memos.api.v1.MotionMedia motion_media = 9;
*/
motionMedia?: MotionMedia;
motionMedia?: MotionMedia | undefined;
};
/**
......@@ -141,7 +141,7 @@ export type CreateAttachmentRequest = Message<"memos.api.v1.CreateAttachmentRequ
*
* @generated from field: memos.api.v1.Attachment attachment = 1;
*/
attachment?: Attachment;
attachment?: Attachment | undefined;
/**
* Optional. The attachment ID to use for this attachment.
......@@ -270,14 +270,14 @@ export type UpdateAttachmentRequest = Message<"memos.api.v1.UpdateAttachmentRequ
*
* @generated from field: memos.api.v1.Attachment attachment = 1;
*/
attachment?: Attachment;
attachment?: Attachment | undefined;
/**
* Required. The list of fields to update.
*
* @generated from field: google.protobuf.FieldMask update_mask = 2;
*/
updateMask?: FieldMask;
updateMask?: FieldMask | undefined;
};
/**
......
// @generated by protoc-gen-es v2.11.0 with parameter "target=ts"
// @generated by protoc-gen-es v2.12.0 with parameter "target=ts"
// @generated from file api/v1/auth_service.proto (package memos.api.v1, syntax proto3)
/* eslint-disable */
......@@ -40,7 +40,7 @@ export type GetCurrentUserResponse = Message<"memos.api.v1.GetCurrentUserRespons
*
* @generated from field: memos.api.v1.User user = 1;
*/
user?: User;
user?: User | undefined;
};
/**
......@@ -166,7 +166,7 @@ export type SignInResponse = Message<"memos.api.v1.SignInResponse"> & {
*
* @generated from field: memos.api.v1.User user = 1;
*/
user?: User;
user?: User | undefined;
/**
* The short-lived access token for API requests.
......@@ -182,7 +182,7 @@ export type SignInResponse = Message<"memos.api.v1.SignInResponse"> & {
*
* @generated from field: google.protobuf.Timestamp access_token_expires_at = 3;
*/
accessTokenExpiresAt?: Timestamp;
accessTokenExpiresAt?: Timestamp | undefined;
};
/**
......@@ -234,7 +234,7 @@ export type RefreshTokenResponse = Message<"memos.api.v1.RefreshTokenResponse">
*
* @generated from field: google.protobuf.Timestamp expires_at = 2;
*/
expiresAt?: Timestamp;
expiresAt?: Timestamp | undefined;
};
/**
......
// @generated by protoc-gen-es v2.11.0 with parameter "target=ts"
// @generated by protoc-gen-es v2.12.0 with parameter "target=ts"
// @generated from file api/v1/common.proto (package memos.api.v1, syntax proto3)
/* eslint-disable */
......
// @generated by protoc-gen-es v2.11.0 with parameter "target=ts"
// @generated by protoc-gen-es v2.12.0 with parameter "target=ts"
// @generated from file api/v1/idp_service.proto (package memos.api.v1, syntax proto3)
/* eslint-disable */
......@@ -56,7 +56,7 @@ export type IdentityProvider = Message<"memos.api.v1.IdentityProvider"> & {
*
* @generated from field: memos.api.v1.IdentityProviderConfig config = 5;
*/
config?: IdentityProviderConfig;
config?: IdentityProviderConfig | undefined;
};
/**
......@@ -181,7 +181,7 @@ export type OAuth2Config = Message<"memos.api.v1.OAuth2Config"> & {
/**
* @generated from field: memos.api.v1.FieldMapping field_mapping = 7;
*/
fieldMapping?: FieldMapping;
fieldMapping?: FieldMapping | undefined;
};
/**
......@@ -252,7 +252,7 @@ export type CreateIdentityProviderRequest = Message<"memos.api.v1.CreateIdentity
*
* @generated from field: memos.api.v1.IdentityProvider identity_provider = 1;
*/
identityProvider?: IdentityProvider;
identityProvider?: IdentityProvider | undefined;
/**
* Optional. The ID to use for the identity provider, which will become the final component of the resource name.
......@@ -279,7 +279,7 @@ export type UpdateIdentityProviderRequest = Message<"memos.api.v1.UpdateIdentity
*
* @generated from field: memos.api.v1.IdentityProvider identity_provider = 1;
*/
identityProvider?: IdentityProvider;
identityProvider?: IdentityProvider | undefined;
/**
* Required. The update mask applies to the resource. Only the top level fields of
......@@ -287,7 +287,7 @@ export type UpdateIdentityProviderRequest = Message<"memos.api.v1.UpdateIdentity
*
* @generated from field: google.protobuf.FieldMask update_mask = 2;
*/
updateMask?: FieldMask;
updateMask?: FieldMask | undefined;
};
/**
......
// @generated by protoc-gen-es v2.11.0 with parameter "target=ts"
// @generated by protoc-gen-es v2.12.0 with parameter "target=ts"
// @generated from file api/v1/instance_service.proto (package memos.api.v1, syntax proto3)
/* eslint-disable */
......@@ -20,7 +20,7 @@ import type { Message } from "@bufbuild/protobuf";
* Describes the file api/v1/instance_service.proto.
*/
export const file_api_v1_instance_service: GenFile = /*@__PURE__*/
fileDesc("Ch1hcGkvdjEvaW5zdGFuY2Vfc2VydmljZS5wcm90bxIMbWVtb3MuYXBpLnYxImkKD0luc3RhbmNlUHJvZmlsZRIPCgd2ZXJzaW9uGAIgASgJEgwKBGRlbW8YAyABKAgSFAoMaW5zdGFuY2VfdXJsGAYgASgJEiEKBWFkbWluGAcgASgLMhIubWVtb3MuYXBpLnYxLlVzZXIiGwoZR2V0SW5zdGFuY2VQcm9maWxlUmVxdWVzdCKjFAoPSW5zdGFuY2VTZXR0aW5nEhEKBG5hbWUYASABKAlCA+BBCBJHCg9nZW5lcmFsX3NldHRpbmcYAiABKAsyLC5tZW1vcy5hcGkudjEuSW5zdGFuY2VTZXR0aW5nLkdlbmVyYWxTZXR0aW5nSAASRwoPc3RvcmFnZV9zZXR0aW5nGAMgASgLMiwubWVtb3MuYXBpLnYxLkluc3RhbmNlU2V0dGluZy5TdG9yYWdlU2V0dGluZ0gAElAKFG1lbW9fcmVsYXRlZF9zZXR0aW5nGAQgASgLMjAubWVtb3MuYXBpLnYxLkluc3RhbmNlU2V0dGluZy5NZW1vUmVsYXRlZFNldHRpbmdIABJBCgx0YWdzX3NldHRpbmcYBSABKAsyKS5tZW1vcy5hcGkudjEuSW5zdGFuY2VTZXR0aW5nLlRhZ3NTZXR0aW5nSAASUQoUbm90aWZpY2F0aW9uX3NldHRpbmcYBiABKAsyMS5tZW1vcy5hcGkudjEuSW5zdGFuY2VTZXR0aW5nLk5vdGlmaWNhdGlvblNldHRpbmdIABI9CgphaV9zZXR0aW5nGAcgASgLMicubWVtb3MuYXBpLnYxLkluc3RhbmNlU2V0dGluZy5BSVNldHRpbmdIABqHAwoOR2VuZXJhbFNldHRpbmcSIgoaZGlzYWxsb3dfdXNlcl9yZWdpc3RyYXRpb24YAiABKAgSHgoWZGlzYWxsb3dfcGFzc3dvcmRfYXV0aBgDIAEoCBIZChFhZGRpdGlvbmFsX3NjcmlwdBgEIAEoCRIYChBhZGRpdGlvbmFsX3N0eWxlGAUgASgJElIKDmN1c3RvbV9wcm9maWxlGAYgASgLMjoubWVtb3MuYXBpLnYxLkluc3RhbmNlU2V0dGluZy5HZW5lcmFsU2V0dGluZy5DdXN0b21Qcm9maWxlEh0KFXdlZWtfc3RhcnRfZGF5X29mZnNldBgHIAEoBRIgChhkaXNhbGxvd19jaGFuZ2VfdXNlcm5hbWUYCCABKAgSIAoYZGlzYWxsb3dfY2hhbmdlX25pY2tuYW1lGAkgASgIGkUKDUN1c3RvbVByb2ZpbGUSDQoFdGl0bGUYASABKAkSEwoLZGVzY3JpcHRpb24YAiABKAkSEAoIbG9nb191cmwYAyABKAkaugMKDlN0b3JhZ2VTZXR0aW5nEk4KDHN0b3JhZ2VfdHlwZRgBIAEoDjI4Lm1lbW9zLmFwaS52MS5JbnN0YW5jZVNldHRpbmcuU3RvcmFnZVNldHRpbmcuU3RvcmFnZVR5cGUSGQoRZmlsZXBhdGhfdGVtcGxhdGUYAiABKAkSHAoUdXBsb2FkX3NpemVfbGltaXRfbWIYAyABKAMSSAoJczNfY29uZmlnGAQgASgLMjUubWVtb3MuYXBpLnYxLkluc3RhbmNlU2V0dGluZy5TdG9yYWdlU2V0dGluZy5TM0NvbmZpZxqGAQoIUzNDb25maWcSFQoNYWNjZXNzX2tleV9pZBgBIAEoCRIZChFhY2Nlc3Nfa2V5X3NlY3JldBgCIAEoCRIQCghlbmRwb2ludBgDIAEoCRIOCgZyZWdpb24YBCABKAkSDgoGYnVja2V0GAUgASgJEhYKDnVzZV9wYXRoX3N0eWxlGAYgASgIIkwKC1N0b3JhZ2VUeXBlEhwKGFNUT1JBR0VfVFlQRV9VTlNQRUNJRklFRBAAEgwKCERBVEFCQVNFEAESCQoFTE9DQUwQAhIGCgJTMxADGokBChJNZW1vUmVsYXRlZFNldHRpbmcSIAoYZGlzcGxheV93aXRoX3VwZGF0ZV90aW1lGAIgASgIEhwKFGNvbnRlbnRfbGVuZ3RoX2xpbWl0GAMgASgFEiAKGGVuYWJsZV9kb3VibGVfY2xpY2tfZWRpdBgEIAEoCBIRCglyZWFjdGlvbnMYByADKAkaUQoLVGFnTWV0YWRhdGESLAoQYmFja2dyb3VuZF9jb2xvchgBIAEoCzISLmdvb2dsZS50eXBlLkNvbG9yEhQKDGJsdXJfY29udGVudBgCIAEoCBqoAQoLVGFnc1NldHRpbmcSQQoEdGFncxgBIAMoCzIzLm1lbW9zLmFwaS52MS5JbnN0YW5jZVNldHRpbmcuVGFnc1NldHRpbmcuVGFnc0VudHJ5GlYKCVRhZ3NFbnRyeRILCgNrZXkYASABKAkSOAoFdmFsdWUYAiABKAsyKS5tZW1vcy5hcGkudjEuSW5zdGFuY2VTZXR0aW5nLlRhZ01ldGFkYXRhOgI4ARq1AgoTTm90aWZpY2F0aW9uU2V0dGluZxJNCgVlbWFpbBgBIAEoCzI+Lm1lbW9zLmFwaS52MS5JbnN0YW5jZVNldHRpbmcuTm90aWZpY2F0aW9uU2V0dGluZy5FbWFpbFNldHRpbmcazgEKDEVtYWlsU2V0dGluZxIPCgdlbmFibGVkGAEgASgIEhEKCXNtdHBfaG9zdBgCIAEoCRIRCglzbXRwX3BvcnQYAyABKAUSFQoNc210cF91c2VybmFtZRgEIAEoCRIVCg1zbXRwX3Bhc3N3b3JkGAUgASgJEhIKCmZyb21fZW1haWwYBiABKAkSEQoJZnJvbV9uYW1lGAcgASgJEhAKCHJlcGx5X3RvGAggASgJEg8KB3VzZV90bHMYCSABKAgSDwoHdXNlX3NzbBgKIAEoCBpOCglBSVNldHRpbmcSQQoJcHJvdmlkZXJzGAEgAygLMi4ubWVtb3MuYXBpLnYxLkluc3RhbmNlU2V0dGluZy5BSVByb3ZpZGVyQ29uZmlnGsYBChBBSVByb3ZpZGVyQ29uZmlnEgoKAmlkGAEgASgJEg0KBXRpdGxlGAIgASgJEjoKBHR5cGUYAyABKA4yLC5tZW1vcy5hcGkudjEuSW5zdGFuY2VTZXR0aW5nLkFJUHJvdmlkZXJUeXBlEhAKCGVuZHBvaW50GAQgASgJEhQKB2FwaV9rZXkYBSABKAlCA+BBBBIYCgthcGlfa2V5X3NldBgIIAEoCEID4EEDEhkKDGFwaV9rZXlfaGludBgJIAEoCUID4EEDImoKA0tleRITCg9LRVlfVU5TUEVDSUZJRUQQABILCgdHRU5FUkFMEAESCwoHU1RPUkFHRRACEhAKDE1FTU9fUkVMQVRFRBADEggKBFRBR1MQBBIQCgxOT1RJRklDQVRJT04QBRIGCgJBSRAGIkoKDkFJUHJvdmlkZXJUeXBlEiAKHEFJX1BST1ZJREVSX1RZUEVfVU5TUEVDSUZJRUQQABIKCgZPUEVOQUkQARIKCgZHRU1JTkkQAjph6kFeChxtZW1vcy5hcGkudjEvSW5zdGFuY2VTZXR0aW5nEhtpbnN0YW5jZS9zZXR0aW5ncy97c2V0dGluZ30qEGluc3RhbmNlU2V0dGluZ3MyD2luc3RhbmNlU2V0dGluZ0IHCgV2YWx1ZSJPChlHZXRJbnN0YW5jZVNldHRpbmdSZXF1ZXN0EjIKBG5hbWUYASABKAlCJOBBAvpBHgocbWVtb3MuYXBpLnYxL0luc3RhbmNlU2V0dGluZyKJAQocVXBkYXRlSW5zdGFuY2VTZXR0aW5nUmVxdWVzdBIzCgdzZXR0aW5nGAEgASgLMh0ubWVtb3MuYXBpLnYxLkluc3RhbmNlU2V0dGluZ0ID4EECEjQKC3VwZGF0ZV9tYXNrGAIgASgLMhouZ29vZ2xlLnByb3RvYnVmLkZpZWxkTWFza0ID4EEBMtsDCg9JbnN0YW5jZVNlcnZpY2USfgoSR2V0SW5zdGFuY2VQcm9maWxlEicubWVtb3MuYXBpLnYxLkdldEluc3RhbmNlUHJvZmlsZVJlcXVlc3QaHS5tZW1vcy5hcGkudjEuSW5zdGFuY2VQcm9maWxlIiCC0+STAhoSGC9hcGkvdjEvaW5zdGFuY2UvcHJvZmlsZRKPAQoSR2V0SW5zdGFuY2VTZXR0aW5nEicubWVtb3MuYXBpLnYxLkdldEluc3RhbmNlU2V0dGluZ1JlcXVlc3QaHS5tZW1vcy5hcGkudjEuSW5zdGFuY2VTZXR0aW5nIjHaQQRuYW1lgtPkkwIkEiIvYXBpL3YxL3tuYW1lPWluc3RhbmNlL3NldHRpbmdzLyp9ErUBChVVcGRhdGVJbnN0YW5jZVNldHRpbmcSKi5tZW1vcy5hcGkudjEuVXBkYXRlSW5zdGFuY2VTZXR0aW5nUmVxdWVzdBodLm1lbW9zLmFwaS52MS5JbnN0YW5jZVNldHRpbmciUdpBE3NldHRpbmcsdXBkYXRlX21hc2uC0+STAjU6B3NldHRpbmcyKi9hcGkvdjEve3NldHRpbmcubmFtZT1pbnN0YW5jZS9zZXR0aW5ncy8qfUKsAQoQY29tLm1lbW9zLmFwaS52MUIUSW5zdGFuY2VTZXJ2aWNlUHJvdG9QAVowZ2l0aHViLmNvbS91c2VtZW1vcy9tZW1vcy9wcm90by9nZW4vYXBpL3YxO2FwaXYxogIDTUFYqgIMTWVtb3MuQXBpLlYxygIMTWVtb3NcQXBpXFYx4gIYTWVtb3NcQXBpXFYxXEdQQk1ldGFkYXRh6gIOTWVtb3M6OkFwaTo6VjFiBnByb3RvMw", [file_api_v1_user_service, file_google_api_annotations, file_google_api_client, file_google_api_field_behavior, file_google_api_resource, file_google_protobuf_field_mask, file_google_type_color]);
fileDesc("Ch1hcGkvdjEvaW5zdGFuY2Vfc2VydmljZS5wcm90bxIMbWVtb3MuYXBpLnYxImkKD0luc3RhbmNlUHJvZmlsZRIPCgd2ZXJzaW9uGAIgASgJEgwKBGRlbW8YAyABKAgSFAoMaW5zdGFuY2VfdXJsGAYgASgJEiEKBWFkbWluGAcgASgLMhIubWVtb3MuYXBpLnYxLlVzZXIiGwoZR2V0SW5zdGFuY2VQcm9maWxlUmVxdWVzdCKhFAoPSW5zdGFuY2VTZXR0aW5nEhEKBG5hbWUYASABKAlCA+BBCBJHCg9nZW5lcmFsX3NldHRpbmcYAiABKAsyLC5tZW1vcy5hcGkudjEuSW5zdGFuY2VTZXR0aW5nLkdlbmVyYWxTZXR0aW5nSAASRwoPc3RvcmFnZV9zZXR0aW5nGAMgASgLMiwubWVtb3MuYXBpLnYxLkluc3RhbmNlU2V0dGluZy5TdG9yYWdlU2V0dGluZ0gAElAKFG1lbW9fcmVsYXRlZF9zZXR0aW5nGAQgASgLMjAubWVtb3MuYXBpLnYxLkluc3RhbmNlU2V0dGluZy5NZW1vUmVsYXRlZFNldHRpbmdIABJBCgx0YWdzX3NldHRpbmcYBSABKAsyKS5tZW1vcy5hcGkudjEuSW5zdGFuY2VTZXR0aW5nLlRhZ3NTZXR0aW5nSAASUQoUbm90aWZpY2F0aW9uX3NldHRpbmcYBiABKAsyMS5tZW1vcy5hcGkudjEuSW5zdGFuY2VTZXR0aW5nLk5vdGlmaWNhdGlvblNldHRpbmdIABI9CgphaV9zZXR0aW5nGAcgASgLMicubWVtb3MuYXBpLnYxLkluc3RhbmNlU2V0dGluZy5BSVNldHRpbmdIABqHAwoOR2VuZXJhbFNldHRpbmcSIgoaZGlzYWxsb3dfdXNlcl9yZWdpc3RyYXRpb24YAiABKAgSHgoWZGlzYWxsb3dfcGFzc3dvcmRfYXV0aBgDIAEoCBIZChFhZGRpdGlvbmFsX3NjcmlwdBgEIAEoCRIYChBhZGRpdGlvbmFsX3N0eWxlGAUgASgJElIKDmN1c3RvbV9wcm9maWxlGAYgASgLMjoubWVtb3MuYXBpLnYxLkluc3RhbmNlU2V0dGluZy5HZW5lcmFsU2V0dGluZy5DdXN0b21Qcm9maWxlEh0KFXdlZWtfc3RhcnRfZGF5X29mZnNldBgHIAEoBRIgChhkaXNhbGxvd19jaGFuZ2VfdXNlcm5hbWUYCCABKAgSIAoYZGlzYWxsb3dfY2hhbmdlX25pY2tuYW1lGAkgASgIGkUKDUN1c3RvbVByb2ZpbGUSDQoFdGl0bGUYASABKAkSEwoLZGVzY3JpcHRpb24YAiABKAkSEAoIbG9nb191cmwYAyABKAkaugMKDlN0b3JhZ2VTZXR0aW5nEk4KDHN0b3JhZ2VfdHlwZRgBIAEoDjI4Lm1lbW9zLmFwaS52MS5JbnN0YW5jZVNldHRpbmcuU3RvcmFnZVNldHRpbmcuU3RvcmFnZVR5cGUSGQoRZmlsZXBhdGhfdGVtcGxhdGUYAiABKAkSHAoUdXBsb2FkX3NpemVfbGltaXRfbWIYAyABKAMSSAoJczNfY29uZmlnGAQgASgLMjUubWVtb3MuYXBpLnYxLkluc3RhbmNlU2V0dGluZy5TdG9yYWdlU2V0dGluZy5TM0NvbmZpZxqGAQoIUzNDb25maWcSFQoNYWNjZXNzX2tleV9pZBgBIAEoCRIZChFhY2Nlc3Nfa2V5X3NlY3JldBgCIAEoCRIQCghlbmRwb2ludBgDIAEoCRIOCgZyZWdpb24YBCABKAkSDgoGYnVja2V0GAUgASgJEhYKDnVzZV9wYXRoX3N0eWxlGAYgASgIIkwKC1N0b3JhZ2VUeXBlEhwKGFNUT1JBR0VfVFlQRV9VTlNQRUNJRklFRBAAEgwKCERBVEFCQVNFEAESCQoFTE9DQUwQAhIGCgJTMxADGocBChJNZW1vUmVsYXRlZFNldHRpbmcSHAoUY29udGVudF9sZW5ndGhfbGltaXQYAyABKAUSIAoYZW5hYmxlX2RvdWJsZV9jbGlja19lZGl0GAQgASgIEhEKCXJlYWN0aW9ucxgHIAMoCUoECAIQA1IYZGlzcGxheV93aXRoX3VwZGF0ZV90aW1lGlEKC1RhZ01ldGFkYXRhEiwKEGJhY2tncm91bmRfY29sb3IYASABKAsyEi5nb29nbGUudHlwZS5Db2xvchIUCgxibHVyX2NvbnRlbnQYAiABKAgaqAEKC1RhZ3NTZXR0aW5nEkEKBHRhZ3MYASADKAsyMy5tZW1vcy5hcGkudjEuSW5zdGFuY2VTZXR0aW5nLlRhZ3NTZXR0aW5nLlRhZ3NFbnRyeRpWCglUYWdzRW50cnkSCwoDa2V5GAEgASgJEjgKBXZhbHVlGAIgASgLMikubWVtb3MuYXBpLnYxLkluc3RhbmNlU2V0dGluZy5UYWdNZXRhZGF0YToCOAEatQIKE05vdGlmaWNhdGlvblNldHRpbmcSTQoFZW1haWwYASABKAsyPi5tZW1vcy5hcGkudjEuSW5zdGFuY2VTZXR0aW5nLk5vdGlmaWNhdGlvblNldHRpbmcuRW1haWxTZXR0aW5nGs4BCgxFbWFpbFNldHRpbmcSDwoHZW5hYmxlZBgBIAEoCBIRCglzbXRwX2hvc3QYAiABKAkSEQoJc210cF9wb3J0GAMgASgFEhUKDXNtdHBfdXNlcm5hbWUYBCABKAkSFQoNc210cF9wYXNzd29yZBgFIAEoCRISCgpmcm9tX2VtYWlsGAYgASgJEhEKCWZyb21fbmFtZRgHIAEoCRIQCghyZXBseV90bxgIIAEoCRIPCgd1c2VfdGxzGAkgASgIEg8KB3VzZV9zc2wYCiABKAgaTgoJQUlTZXR0aW5nEkEKCXByb3ZpZGVycxgBIAMoCzIuLm1lbW9zLmFwaS52MS5JbnN0YW5jZVNldHRpbmcuQUlQcm92aWRlckNvbmZpZxrGAQoQQUlQcm92aWRlckNvbmZpZxIKCgJpZBgBIAEoCRINCgV0aXRsZRgCIAEoCRI6CgR0eXBlGAMgASgOMiwubWVtb3MuYXBpLnYxLkluc3RhbmNlU2V0dGluZy5BSVByb3ZpZGVyVHlwZRIQCghlbmRwb2ludBgEIAEoCRIUCgdhcGlfa2V5GAUgASgJQgPgQQQSGAoLYXBpX2tleV9zZXQYCCABKAhCA+BBAxIZCgxhcGlfa2V5X2hpbnQYCSABKAlCA+BBAyJqCgNLZXkSEwoPS0VZX1VOU1BFQ0lGSUVEEAASCwoHR0VORVJBTBABEgsKB1NUT1JBR0UQAhIQCgxNRU1PX1JFTEFURUQQAxIICgRUQUdTEAQSEAoMTk9USUZJQ0FUSU9OEAUSBgoCQUkQBiJKCg5BSVByb3ZpZGVyVHlwZRIgChxBSV9QUk9WSURFUl9UWVBFX1VOU1BFQ0lGSUVEEAASCgoGT1BFTkFJEAESCgoGR0VNSU5JEAI6YepBXgocbWVtb3MuYXBpLnYxL0luc3RhbmNlU2V0dGluZxIbaW5zdGFuY2Uvc2V0dGluZ3Mve3NldHRpbmd9KhBpbnN0YW5jZVNldHRpbmdzMg9pbnN0YW5jZVNldHRpbmdCBwoFdmFsdWUiTwoZR2V0SW5zdGFuY2VTZXR0aW5nUmVxdWVzdBIyCgRuYW1lGAEgASgJQiTgQQL6QR4KHG1lbW9zLmFwaS52MS9JbnN0YW5jZVNldHRpbmciiQEKHFVwZGF0ZUluc3RhbmNlU2V0dGluZ1JlcXVlc3QSMwoHc2V0dGluZxgBIAEoCzIdLm1lbW9zLmFwaS52MS5JbnN0YW5jZVNldHRpbmdCA+BBAhI0Cgt1cGRhdGVfbWFzaxgCIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5GaWVsZE1hc2tCA+BBATLbAwoPSW5zdGFuY2VTZXJ2aWNlEn4KEkdldEluc3RhbmNlUHJvZmlsZRInLm1lbW9zLmFwaS52MS5HZXRJbnN0YW5jZVByb2ZpbGVSZXF1ZXN0Gh0ubWVtb3MuYXBpLnYxLkluc3RhbmNlUHJvZmlsZSIggtPkkwIaEhgvYXBpL3YxL2luc3RhbmNlL3Byb2ZpbGUSjwEKEkdldEluc3RhbmNlU2V0dGluZxInLm1lbW9zLmFwaS52MS5HZXRJbnN0YW5jZVNldHRpbmdSZXF1ZXN0Gh0ubWVtb3MuYXBpLnYxLkluc3RhbmNlU2V0dGluZyIx2kEEbmFtZYLT5JMCJBIiL2FwaS92MS97bmFtZT1pbnN0YW5jZS9zZXR0aW5ncy8qfRK1AQoVVXBkYXRlSW5zdGFuY2VTZXR0aW5nEioubWVtb3MuYXBpLnYxLlVwZGF0ZUluc3RhbmNlU2V0dGluZ1JlcXVlc3QaHS5tZW1vcy5hcGkudjEuSW5zdGFuY2VTZXR0aW5nIlHaQRNzZXR0aW5nLHVwZGF0ZV9tYXNrgtPkkwI1OgdzZXR0aW5nMiovYXBpL3YxL3tzZXR0aW5nLm5hbWU9aW5zdGFuY2Uvc2V0dGluZ3MvKn1CrAEKEGNvbS5tZW1vcy5hcGkudjFCFEluc3RhbmNlU2VydmljZVByb3RvUAFaMGdpdGh1Yi5jb20vdXNlbWVtb3MvbWVtb3MvcHJvdG8vZ2VuL2FwaS92MTthcGl2MaICA01BWKoCDE1lbW9zLkFwaS5WMcoCDE1lbW9zXEFwaVxWMeICGE1lbW9zXEFwaVxWMVxHUEJNZXRhZGF0YeoCDk1lbW9zOjpBcGk6OlYxYgZwcm90bzM", [file_api_v1_user_service, file_google_api_annotations, file_google_api_client, file_google_api_field_behavior, file_google_api_resource, file_google_protobuf_field_mask, file_google_type_color]);
/**
* Instance profile message containing basic instance information.
......@@ -55,7 +55,7 @@ export type InstanceProfile = Message<"memos.api.v1.InstanceProfile"> & {
*
* @generated from field: memos.api.v1.User admin = 7;
*/
admin?: User;
admin?: User | undefined;
};
/**
......@@ -182,7 +182,7 @@ export type InstanceSetting_GeneralSetting = Message<"memos.api.v1.InstanceSetti
*
* @generated from field: memos.api.v1.InstanceSetting.GeneralSetting.CustomProfile custom_profile = 6;
*/
customProfile?: InstanceSetting_GeneralSetting_CustomProfile;
customProfile?: InstanceSetting_GeneralSetting_CustomProfile | undefined;
/**
* week_start_day_offset is the week start day offset from Sunday.
......@@ -277,7 +277,7 @@ export type InstanceSetting_StorageSetting = Message<"memos.api.v1.InstanceSetti
*
* @generated from field: memos.api.v1.InstanceSetting.StorageSetting.S3Config s3_config = 4;
*/
s3Config?: InstanceSetting_StorageSetting_S3Config;
s3Config?: InstanceSetting_StorageSetting_S3Config | undefined;
};
/**
......@@ -377,13 +377,6 @@ export const InstanceSetting_StorageSetting_StorageTypeSchema: GenEnum<InstanceS
* @generated from message memos.api.v1.InstanceSetting.MemoRelatedSetting
*/
export type InstanceSetting_MemoRelatedSetting = Message<"memos.api.v1.InstanceSetting.MemoRelatedSetting"> & {
/**
* display_with_update_time orders and displays memo with update time.
*
* @generated from field: bool display_with_update_time = 2;
*/
displayWithUpdateTime: boolean;
/**
* content_length_limit is the limit of content length. Unit is byte.
*
......@@ -425,7 +418,7 @@ export type InstanceSetting_TagMetadata = Message<"memos.api.v1.InstanceSetting.
*
* @generated from field: google.type.Color background_color = 1;
*/
backgroundColor?: Color;
backgroundColor?: Color | undefined;
/**
* Whether memos with this tag should have their content blurred.
......@@ -475,7 +468,7 @@ export type InstanceSetting_NotificationSetting = Message<"memos.api.v1.Instance
/**
* @generated from field: memos.api.v1.InstanceSetting.NotificationSetting.EmailSetting email = 1;
*/
email?: InstanceSetting_NotificationSetting_EmailSetting;
email?: InstanceSetting_NotificationSetting_EmailSetting | undefined;
};
/**
......@@ -746,14 +739,14 @@ export type UpdateInstanceSettingRequest = Message<"memos.api.v1.UpdateInstanceS
*
* @generated from field: memos.api.v1.InstanceSetting setting = 1;
*/
setting?: InstanceSetting;
setting?: InstanceSetting | undefined;
/**
* The list of fields to update.
*
* @generated from field: google.protobuf.FieldMask update_mask = 2;
*/
updateMask?: FieldMask;
updateMask?: FieldMask | undefined;
};
/**
......
// @generated by protoc-gen-es v2.11.0 with parameter "target=ts"
// @generated by protoc-gen-es v2.12.0 with parameter "target=ts"
// @generated from file api/v1/memo_service.proto (package memos.api.v1, syntax proto3)
/* eslint-disable */
......@@ -20,7 +20,7 @@ import type { Message } from "@bufbuild/protobuf";
* Describes the file api/v1/memo_service.proto.
*/
export const file_api_v1_memo_service: GenFile = /*@__PURE__*/
fileDesc("ChlhcGkvdjEvbWVtb19zZXJ2aWNlLnByb3RvEgxtZW1vcy5hcGkudjEipwIKCFJlYWN0aW9uEhQKBG5hbWUYASABKAlCBuBBA+BBCBIqCgdjcmVhdG9yGAIgASgJQhngQQP6QRMKEW1lbW9zLmFwaS52MS9Vc2VyEi0KCmNvbnRlbnRfaWQYAyABKAlCGeBBAvpBEwoRbWVtb3MuYXBpLnYxL01lbW8SGgoNcmVhY3Rpb25fdHlwZRgEIAEoCUID4EECEjQKC2NyZWF0ZV90aW1lGAUgASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcEID4EEDOljqQVUKFW1lbW9zLmFwaS52MS9SZWFjdGlvbhIhbWVtb3Mve21lbW99L3JlYWN0aW9ucy97cmVhY3Rpb259GgRuYW1lKglyZWFjdGlvbnMyCHJlYWN0aW9uIo0HCgRNZW1vEhEKBG5hbWUYASABKAlCA+BBCBInCgVzdGF0ZRgCIAEoDjITLm1lbW9zLmFwaS52MS5TdGF0ZUID4EECEioKB2NyZWF0b3IYAyABKAlCGeBBA/pBEwoRbWVtb3MuYXBpLnYxL1VzZXISNAoLY3JlYXRlX3RpbWUYBCABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wQgPgQQESNAoLdXBkYXRlX3RpbWUYBSABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wQgPgQQESNQoMZGlzcGxheV90aW1lGAYgASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcEID4EEBEhQKB2NvbnRlbnQYByABKAlCA+BBAhIxCgp2aXNpYmlsaXR5GAkgASgOMhgubWVtb3MuYXBpLnYxLlZpc2liaWxpdHlCA+BBAhIRCgR0YWdzGAogAygJQgPgQQMSEwoGcGlubmVkGAsgASgIQgPgQQESMgoLYXR0YWNobWVudHMYDCADKAsyGC5tZW1vcy5hcGkudjEuQXR0YWNobWVudEID4EEBEjIKCXJlbGF0aW9ucxgNIAMoCzIaLm1lbW9zLmFwaS52MS5NZW1vUmVsYXRpb25CA+BBARIuCglyZWFjdGlvbnMYDiADKAsyFi5tZW1vcy5hcGkudjEuUmVhY3Rpb25CA+BBAxIyCghwcm9wZXJ0eRgPIAEoCzIbLm1lbW9zLmFwaS52MS5NZW1vLlByb3BlcnR5QgPgQQMSLgoGcGFyZW50GBAgASgJQhngQQP6QRMKEW1lbW9zLmFwaS52MS9NZW1vSACIAQESFAoHc25pcHBldBgRIAEoCUID4EEDEjIKCGxvY2F0aW9uGBIgASgLMhYubWVtb3MuYXBpLnYxLkxvY2F0aW9uQgPgQQFIAYgBARpyCghQcm9wZXJ0eRIQCghoYXNfbGluaxgBIAEoCBIVCg1oYXNfdGFza19saXN0GAIgASgIEhAKCGhhc19jb2RlGAMgASgIEhwKFGhhc19pbmNvbXBsZXRlX3Rhc2tzGAQgASgIEg0KBXRpdGxlGAUgASgJOjfqQTQKEW1lbW9zLmFwaS52MS9NZW1vEgxtZW1vcy97bWVtb30aBG5hbWUqBW1lbW9zMgRtZW1vQgkKB19wYXJlbnRCCwoJX2xvY2F0aW9uIlMKCExvY2F0aW9uEhgKC3BsYWNlaG9sZGVyGAEgASgJQgPgQQESFQoIbGF0aXR1ZGUYAiABKAFCA+BBARIWCglsb25naXR1ZGUYAyABKAFCA+BBASJQChFDcmVhdGVNZW1vUmVxdWVzdBIlCgRtZW1vGAEgASgLMhIubWVtb3MuYXBpLnYxLk1lbW9CA+BBAhIUCgdtZW1vX2lkGAIgASgJQgPgQQEiswEKEExpc3RNZW1vc1JlcXVlc3QSFgoJcGFnZV9zaXplGAEgASgFQgPgQQESFwoKcGFnZV90b2tlbhgCIAEoCUID4EEBEicKBXN0YXRlGAMgASgOMhMubWVtb3MuYXBpLnYxLlN0YXRlQgPgQQESFQoIb3JkZXJfYnkYBCABKAlCA+BBARITCgZmaWx0ZXIYBSABKAlCA+BBARIZCgxzaG93X2RlbGV0ZWQYBiABKAhCA+BBASJPChFMaXN0TWVtb3NSZXNwb25zZRIhCgVtZW1vcxgBIAMoCzISLm1lbW9zLmFwaS52MS5NZW1vEhcKD25leHRfcGFnZV90b2tlbhgCIAEoCSI5Cg5HZXRNZW1vUmVxdWVzdBInCgRuYW1lGAEgASgJQhngQQL6QRMKEW1lbW9zLmFwaS52MS9NZW1vInAKEVVwZGF0ZU1lbW9SZXF1ZXN0EiUKBG1lbW8YASABKAsyEi5tZW1vcy5hcGkudjEuTWVtb0ID4EECEjQKC3VwZGF0ZV9tYXNrGAIgASgLMhouZ29vZ2xlLnByb3RvYnVmLkZpZWxkTWFza0ID4EECIlAKEURlbGV0ZU1lbW9SZXF1ZXN0EicKBG5hbWUYASABKAlCGeBBAvpBEwoRbWVtb3MuYXBpLnYxL01lbW8SEgoFZm9yY2UYAiABKAhCA+BBASJ4ChlTZXRNZW1vQXR0YWNobWVudHNSZXF1ZXN0EicKBG5hbWUYASABKAlCGeBBAvpBEwoRbWVtb3MuYXBpLnYxL01lbW8SMgoLYXR0YWNobWVudHMYAiADKAsyGC5tZW1vcy5hcGkudjEuQXR0YWNobWVudEID4EECInYKGkxpc3RNZW1vQXR0YWNobWVudHNSZXF1ZXN0EicKBG5hbWUYASABKAlCGeBBAvpBEwoRbWVtb3MuYXBpLnYxL01lbW8SFgoJcGFnZV9zaXplGAIgASgFQgPgQQESFwoKcGFnZV90b2tlbhgDIAEoCUID4EEBImUKG0xpc3RNZW1vQXR0YWNobWVudHNSZXNwb25zZRItCgthdHRhY2htZW50cxgBIAMoCzIYLm1lbW9zLmFwaS52MS5BdHRhY2htZW50EhcKD25leHRfcGFnZV90b2tlbhgCIAEoCSKzAgoMTWVtb1JlbGF0aW9uEjIKBG1lbW8YASABKAsyHy5tZW1vcy5hcGkudjEuTWVtb1JlbGF0aW9uLk1lbW9CA+BBAhI6CgxyZWxhdGVkX21lbW8YAiABKAsyHy5tZW1vcy5hcGkudjEuTWVtb1JlbGF0aW9uLk1lbW9CA+BBAhIyCgR0eXBlGAMgASgOMh8ubWVtb3MuYXBpLnYxLk1lbW9SZWxhdGlvbi5UeXBlQgPgQQIaRQoETWVtbxInCgRuYW1lGAEgASgJQhngQQL6QRMKEW1lbW9zLmFwaS52MS9NZW1vEhQKB3NuaXBwZXQYAiABKAlCA+BBAyI4CgRUeXBlEhQKEFRZUEVfVU5TUEVDSUZJRUQQABINCglSRUZFUkVOQ0UQARILCgdDT01NRU5UEAIidgoXU2V0TWVtb1JlbGF0aW9uc1JlcXVlc3QSJwoEbmFtZRgBIAEoCUIZ4EEC+kETChFtZW1vcy5hcGkudjEvTWVtbxIyCglyZWxhdGlvbnMYAiADKAsyGi5tZW1vcy5hcGkudjEuTWVtb1JlbGF0aW9uQgPgQQIidAoYTGlzdE1lbW9SZWxhdGlvbnNSZXF1ZXN0EicKBG5hbWUYASABKAlCGeBBAvpBEwoRbWVtb3MuYXBpLnYxL01lbW8SFgoJcGFnZV9zaXplGAIgASgFQgPgQQESFwoKcGFnZV90b2tlbhgDIAEoCUID4EEBImMKGUxpc3RNZW1vUmVsYXRpb25zUmVzcG9uc2USLQoJcmVsYXRpb25zGAEgAygLMhoubWVtb3MuYXBpLnYxLk1lbW9SZWxhdGlvbhIXCg9uZXh0X3BhZ2VfdG9rZW4YAiABKAkihgEKGENyZWF0ZU1lbW9Db21tZW50UmVxdWVzdBInCgRuYW1lGAEgASgJQhngQQL6QRMKEW1lbW9zLmFwaS52MS9NZW1vEigKB2NvbW1lbnQYAiABKAsyEi5tZW1vcy5hcGkudjEuTWVtb0ID4EECEhcKCmNvbW1lbnRfaWQYAyABKAlCA+BBASKKAQoXTGlzdE1lbW9Db21tZW50c1JlcXVlc3QSJwoEbmFtZRgBIAEoCUIZ4EEC+kETChFtZW1vcy5hcGkudjEvTWVtbxIWCglwYWdlX3NpemUYAiABKAVCA+BBARIXCgpwYWdlX3Rva2VuGAMgASgJQgPgQQESFQoIb3JkZXJfYnkYBCABKAlCA+BBASJqChhMaXN0TWVtb0NvbW1lbnRzUmVzcG9uc2USIQoFbWVtb3MYASADKAsyEi5tZW1vcy5hcGkudjEuTWVtbxIXCg9uZXh0X3BhZ2VfdG9rZW4YAiABKAkSEgoKdG90YWxfc2l6ZRgDIAEoBSJ0ChhMaXN0TWVtb1JlYWN0aW9uc1JlcXVlc3QSJwoEbmFtZRgBIAEoCUIZ4EEC+kETChFtZW1vcy5hcGkudjEvTWVtbxIWCglwYWdlX3NpemUYAiABKAVCA+BBARIXCgpwYWdlX3Rva2VuGAMgASgJQgPgQQEicwoZTGlzdE1lbW9SZWFjdGlvbnNSZXNwb25zZRIpCglyZWFjdGlvbnMYASADKAsyFi5tZW1vcy5hcGkudjEuUmVhY3Rpb24SFwoPbmV4dF9wYWdlX3Rva2VuGAIgASgJEhIKCnRvdGFsX3NpemUYAyABKAUicwoZVXBzZXJ0TWVtb1JlYWN0aW9uUmVxdWVzdBInCgRuYW1lGAEgASgJQhngQQL6QRMKEW1lbW9zLmFwaS52MS9NZW1vEi0KCHJlYWN0aW9uGAIgASgLMhYubWVtb3MuYXBpLnYxLlJlYWN0aW9uQgPgQQIiSAoZRGVsZXRlTWVtb1JlYWN0aW9uUmVxdWVzdBIrCgRuYW1lGAEgASgJQh3gQQL6QRcKFW1lbW9zLmFwaS52MS9SZWFjdGlvbiLoAQoJTWVtb1NoYXJlEhEKBG5hbWUYASABKAlCA+BBCBI0CgtjcmVhdGVfdGltZRgCIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXBCA+BBAxI5CgtleHBpcmVfdGltZRgDIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXBCA+BBAUgAiAEBOkfqQUQKFm1lbW9zLmFwaS52MS9NZW1vU2hhcmUSG21lbW9zL3ttZW1vfS9zaGFyZXMve3NoYXJlfSoGc2hhcmVzMgVzaGFyZUIOCgxfZXhwaXJlX3RpbWUidQoWQ3JlYXRlTWVtb1NoYXJlUmVxdWVzdBIpCgZwYXJlbnQYASABKAlCGeBBAvpBEwoRbWVtb3MuYXBpLnYxL01lbW8SMAoKbWVtb19zaGFyZRgCIAEoCzIXLm1lbW9zLmFwaS52MS5NZW1vU2hhcmVCA+BBAiJCChVMaXN0TWVtb1NoYXJlc1JlcXVlc3QSKQoGcGFyZW50GAEgASgJQhngQQL6QRMKEW1lbW9zLmFwaS52MS9NZW1vIkYKFkxpc3RNZW1vU2hhcmVzUmVzcG9uc2USLAoLbWVtb19zaGFyZXMYASADKAsyFy5tZW1vcy5hcGkudjEuTWVtb1NoYXJlIkYKFkRlbGV0ZU1lbW9TaGFyZVJlcXVlc3QSLAoEbmFtZRgBIAEoCUIe4EEC+kEYChZtZW1vcy5hcGkudjEvTWVtb1NoYXJlIi4KFUdldE1lbW9CeVNoYXJlUmVxdWVzdBIVCghzaGFyZV9pZBgBIAEoCUID4EECKlAKClZpc2liaWxpdHkSGgoWVklTSUJJTElUWV9VTlNQRUNJRklFRBAAEgsKB1BSSVZBVEUQARINCglQUk9URUNURUQQAhIKCgZQVUJMSUMQAzLuEgoLTWVtb1NlcnZpY2USZQoKQ3JlYXRlTWVtbxIfLm1lbW9zLmFwaS52MS5DcmVhdGVNZW1vUmVxdWVzdBoSLm1lbW9zLmFwaS52MS5NZW1vIiLaQQRtZW1vgtPkkwIVOgRtZW1vIg0vYXBpL3YxL21lbW9zEmYKCUxpc3RNZW1vcxIeLm1lbW9zLmFwaS52MS5MaXN0TWVtb3NSZXF1ZXN0Gh8ubWVtb3MuYXBpLnYxLkxpc3RNZW1vc1Jlc3BvbnNlIhjaQQCC0+STAg8SDS9hcGkvdjEvbWVtb3MSYgoHR2V0TWVtbxIcLm1lbW9zLmFwaS52MS5HZXRNZW1vUmVxdWVzdBoSLm1lbW9zLmFwaS52MS5NZW1vIiXaQQRuYW1lgtPkkwIYEhYvYXBpL3YxL3tuYW1lPW1lbW9zLyp9En8KClVwZGF0ZU1lbW8SHy5tZW1vcy5hcGkudjEuVXBkYXRlTWVtb1JlcXVlc3QaEi5tZW1vcy5hcGkudjEuTWVtbyI82kEQbWVtbyx1cGRhdGVfbWFza4LT5JMCIzoEbWVtbzIbL2FwaS92MS97bWVtby5uYW1lPW1lbW9zLyp9EmwKCkRlbGV0ZU1lbW8SHy5tZW1vcy5hcGkudjEuRGVsZXRlTWVtb1JlcXVlc3QaFi5nb29nbGUucHJvdG9idWYuRW1wdHkiJdpBBG5hbWWC0+STAhgqFi9hcGkvdjEve25hbWU9bWVtb3MvKn0SiwEKElNldE1lbW9BdHRhY2htZW50cxInLm1lbW9zLmFwaS52MS5TZXRNZW1vQXR0YWNobWVudHNSZXF1ZXN0GhYuZ29vZ2xlLnByb3RvYnVmLkVtcHR5IjTaQQRuYW1lgtPkkwInOgEqMiIvYXBpL3YxL3tuYW1lPW1lbW9zLyp9L2F0dGFjaG1lbnRzEp0BChNMaXN0TWVtb0F0dGFjaG1lbnRzEigubWVtb3MuYXBpLnYxLkxpc3RNZW1vQXR0YWNobWVudHNSZXF1ZXN0GikubWVtb3MuYXBpLnYxLkxpc3RNZW1vQXR0YWNobWVudHNSZXNwb25zZSIx2kEEbmFtZYLT5JMCJBIiL2FwaS92MS97bmFtZT1tZW1vcy8qfS9hdHRhY2htZW50cxKFAQoQU2V0TWVtb1JlbGF0aW9ucxIlLm1lbW9zLmFwaS52MS5TZXRNZW1vUmVsYXRpb25zUmVxdWVzdBoWLmdvb2dsZS5wcm90b2J1Zi5FbXB0eSIy2kEEbmFtZYLT5JMCJToBKjIgL2FwaS92MS97bmFtZT1tZW1vcy8qfS9yZWxhdGlvbnMSlQEKEUxpc3RNZW1vUmVsYXRpb25zEiYubWVtb3MuYXBpLnYxLkxpc3RNZW1vUmVsYXRpb25zUmVxdWVzdBonLm1lbW9zLmFwaS52MS5MaXN0TWVtb1JlbGF0aW9uc1Jlc3BvbnNlIi/aQQRuYW1lgtPkkwIiEiAvYXBpL3YxL3tuYW1lPW1lbW9zLyp9L3JlbGF0aW9ucxKQAQoRQ3JlYXRlTWVtb0NvbW1lbnQSJi5tZW1vcy5hcGkudjEuQ3JlYXRlTWVtb0NvbW1lbnRSZXF1ZXN0GhIubWVtb3MuYXBpLnYxLk1lbW8iP9pBDG5hbWUsY29tbWVudILT5JMCKjoHY29tbWVudCIfL2FwaS92MS97bmFtZT1tZW1vcy8qfS9jb21tZW50cxKRAQoQTGlzdE1lbW9Db21tZW50cxIlLm1lbW9zLmFwaS52MS5MaXN0TWVtb0NvbW1lbnRzUmVxdWVzdBomLm1lbW9zLmFwaS52MS5MaXN0TWVtb0NvbW1lbnRzUmVzcG9uc2UiLtpBBG5hbWWC0+STAiESHy9hcGkvdjEve25hbWU9bWVtb3MvKn0vY29tbWVudHMSlQEKEUxpc3RNZW1vUmVhY3Rpb25zEiYubWVtb3MuYXBpLnYxLkxpc3RNZW1vUmVhY3Rpb25zUmVxdWVzdBonLm1lbW9zLmFwaS52MS5MaXN0TWVtb1JlYWN0aW9uc1Jlc3BvbnNlIi/aQQRuYW1lgtPkkwIiEiAvYXBpL3YxL3tuYW1lPW1lbW9zLyp9L3JlYWN0aW9ucxKJAQoSVXBzZXJ0TWVtb1JlYWN0aW9uEicubWVtb3MuYXBpLnYxLlVwc2VydE1lbW9SZWFjdGlvblJlcXVlc3QaFi5tZW1vcy5hcGkudjEuUmVhY3Rpb24iMtpBBG5hbWWC0+STAiU6ASoiIC9hcGkvdjEve25hbWU9bWVtb3MvKn0vcmVhY3Rpb25zEogBChJEZWxldGVNZW1vUmVhY3Rpb24SJy5tZW1vcy5hcGkudjEuRGVsZXRlTWVtb1JlYWN0aW9uUmVxdWVzdBoWLmdvb2dsZS5wcm90b2J1Zi5FbXB0eSIx2kEEbmFtZYLT5JMCJCoiL2FwaS92MS97bmFtZT1tZW1vcy8qL3JlYWN0aW9ucy8qfRKZAQoPQ3JlYXRlTWVtb1NoYXJlEiQubWVtb3MuYXBpLnYxLkNyZWF0ZU1lbW9TaGFyZVJlcXVlc3QaFy5tZW1vcy5hcGkudjEuTWVtb1NoYXJlIkfaQRFwYXJlbnQsbWVtb19zaGFyZYLT5JMCLToKbWVtb19zaGFyZSIfL2FwaS92MS97cGFyZW50PW1lbW9zLyp9L3NoYXJlcxKNAQoOTGlzdE1lbW9TaGFyZXMSIy5tZW1vcy5hcGkudjEuTGlzdE1lbW9TaGFyZXNSZXF1ZXN0GiQubWVtb3MuYXBpLnYxLkxpc3RNZW1vU2hhcmVzUmVzcG9uc2UiMNpBBnBhcmVudILT5JMCIRIfL2FwaS92MS97cGFyZW50PW1lbW9zLyp9L3NoYXJlcxJ/Cg9EZWxldGVNZW1vU2hhcmUSJC5tZW1vcy5hcGkudjEuRGVsZXRlTWVtb1NoYXJlUmVxdWVzdBoWLmdvb2dsZS5wcm90b2J1Zi5FbXB0eSIu2kEEbmFtZYLT5JMCISofL2FwaS92MS97bmFtZT1tZW1vcy8qL3NoYXJlcy8qfRJsCg5HZXRNZW1vQnlTaGFyZRIjLm1lbW9zLmFwaS52MS5HZXRNZW1vQnlTaGFyZVJlcXVlc3QaEi5tZW1vcy5hcGkudjEuTWVtbyIhgtPkkwIbEhkvYXBpL3YxL3NoYXJlcy97c2hhcmVfaWR9QqgBChBjb20ubWVtb3MuYXBpLnYxQhBNZW1vU2VydmljZVByb3RvUAFaMGdpdGh1Yi5jb20vdXNlbWVtb3MvbWVtb3MvcHJvdG8vZ2VuL2FwaS92MTthcGl2MaICA01BWKoCDE1lbW9zLkFwaS5WMcoCDE1lbW9zXEFwaVxWMeICGE1lbW9zXEFwaVxWMVxHUEJNZXRhZGF0YeoCDk1lbW9zOjpBcGk6OlYxYgZwcm90bzM", [file_api_v1_attachment_service, file_api_v1_common, file_google_api_annotations, file_google_api_client, file_google_api_field_behavior, file_google_api_resource, file_google_protobuf_empty, file_google_protobuf_field_mask, file_google_protobuf_timestamp]);
fileDesc("ChlhcGkvdjEvbWVtb19zZXJ2aWNlLnByb3RvEgxtZW1vcy5hcGkudjEipwIKCFJlYWN0aW9uEhQKBG5hbWUYASABKAlCBuBBA+BBCBIqCgdjcmVhdG9yGAIgASgJQhngQQP6QRMKEW1lbW9zLmFwaS52MS9Vc2VyEi0KCmNvbnRlbnRfaWQYAyABKAlCGeBBAvpBEwoRbWVtb3MuYXBpLnYxL01lbW8SGgoNcmVhY3Rpb25fdHlwZRgEIAEoCUID4EECEjQKC2NyZWF0ZV90aW1lGAUgASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcEID4EEDOljqQVUKFW1lbW9zLmFwaS52MS9SZWFjdGlvbhIhbWVtb3Mve21lbW99L3JlYWN0aW9ucy97cmVhY3Rpb259GgRuYW1lKglyZWFjdGlvbnMyCHJlYWN0aW9uIuoGCgRNZW1vEhEKBG5hbWUYASABKAlCA+BBCBInCgVzdGF0ZRgCIAEoDjITLm1lbW9zLmFwaS52MS5TdGF0ZUID4EECEioKB2NyZWF0b3IYAyABKAlCGeBBA/pBEwoRbWVtb3MuYXBpLnYxL1VzZXISNAoLY3JlYXRlX3RpbWUYBCABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wQgPgQQESNAoLdXBkYXRlX3RpbWUYBSABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wQgPgQQESFAoHY29udGVudBgHIAEoCUID4EECEjEKCnZpc2liaWxpdHkYCSABKA4yGC5tZW1vcy5hcGkudjEuVmlzaWJpbGl0eUID4EECEhEKBHRhZ3MYCiADKAlCA+BBAxITCgZwaW5uZWQYCyABKAhCA+BBARIyCgthdHRhY2htZW50cxgMIAMoCzIYLm1lbW9zLmFwaS52MS5BdHRhY2htZW50QgPgQQESMgoJcmVsYXRpb25zGA0gAygLMhoubWVtb3MuYXBpLnYxLk1lbW9SZWxhdGlvbkID4EEBEi4KCXJlYWN0aW9ucxgOIAMoCzIWLm1lbW9zLmFwaS52MS5SZWFjdGlvbkID4EEDEjIKCHByb3BlcnR5GA8gASgLMhsubWVtb3MuYXBpLnYxLk1lbW8uUHJvcGVydHlCA+BBAxIuCgZwYXJlbnQYECABKAlCGeBBA/pBEwoRbWVtb3MuYXBpLnYxL01lbW9IAIgBARIUCgdzbmlwcGV0GBEgASgJQgPgQQMSMgoIbG9jYXRpb24YEiABKAsyFi5tZW1vcy5hcGkudjEuTG9jYXRpb25CA+BBAUgBiAEBGnIKCFByb3BlcnR5EhAKCGhhc19saW5rGAEgASgIEhUKDWhhc190YXNrX2xpc3QYAiABKAgSEAoIaGFzX2NvZGUYAyABKAgSHAoUaGFzX2luY29tcGxldGVfdGFza3MYBCABKAgSDQoFdGl0bGUYBSABKAk6N+pBNAoRbWVtb3MuYXBpLnYxL01lbW8SDG1lbW9zL3ttZW1vfRoEbmFtZSoFbWVtb3MyBG1lbW9CCQoHX3BhcmVudEILCglfbG9jYXRpb25KBAgGEAdSDGRpc3BsYXlfdGltZSJTCghMb2NhdGlvbhIYCgtwbGFjZWhvbGRlchgBIAEoCUID4EEBEhUKCGxhdGl0dWRlGAIgASgBQgPgQQESFgoJbG9uZ2l0dWRlGAMgASgBQgPgQQEiUAoRQ3JlYXRlTWVtb1JlcXVlc3QSJQoEbWVtbxgBIAEoCzISLm1lbW9zLmFwaS52MS5NZW1vQgPgQQISFAoHbWVtb19pZBgCIAEoCUID4EEBIrMBChBMaXN0TWVtb3NSZXF1ZXN0EhYKCXBhZ2Vfc2l6ZRgBIAEoBUID4EEBEhcKCnBhZ2VfdG9rZW4YAiABKAlCA+BBARInCgVzdGF0ZRgDIAEoDjITLm1lbW9zLmFwaS52MS5TdGF0ZUID4EEBEhUKCG9yZGVyX2J5GAQgASgJQgPgQQESEwoGZmlsdGVyGAUgASgJQgPgQQESGQoMc2hvd19kZWxldGVkGAYgASgIQgPgQQEiTwoRTGlzdE1lbW9zUmVzcG9uc2USIQoFbWVtb3MYASADKAsyEi5tZW1vcy5hcGkudjEuTWVtbxIXCg9uZXh0X3BhZ2VfdG9rZW4YAiABKAkiOQoOR2V0TWVtb1JlcXVlc3QSJwoEbmFtZRgBIAEoCUIZ4EEC+kETChFtZW1vcy5hcGkudjEvTWVtbyJwChFVcGRhdGVNZW1vUmVxdWVzdBIlCgRtZW1vGAEgASgLMhIubWVtb3MuYXBpLnYxLk1lbW9CA+BBAhI0Cgt1cGRhdGVfbWFzaxgCIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5GaWVsZE1hc2tCA+BBAiJQChFEZWxldGVNZW1vUmVxdWVzdBInCgRuYW1lGAEgASgJQhngQQL6QRMKEW1lbW9zLmFwaS52MS9NZW1vEhIKBWZvcmNlGAIgASgIQgPgQQEieAoZU2V0TWVtb0F0dGFjaG1lbnRzUmVxdWVzdBInCgRuYW1lGAEgASgJQhngQQL6QRMKEW1lbW9zLmFwaS52MS9NZW1vEjIKC2F0dGFjaG1lbnRzGAIgAygLMhgubWVtb3MuYXBpLnYxLkF0dGFjaG1lbnRCA+BBAiJ2ChpMaXN0TWVtb0F0dGFjaG1lbnRzUmVxdWVzdBInCgRuYW1lGAEgASgJQhngQQL6QRMKEW1lbW9zLmFwaS52MS9NZW1vEhYKCXBhZ2Vfc2l6ZRgCIAEoBUID4EEBEhcKCnBhZ2VfdG9rZW4YAyABKAlCA+BBASJlChtMaXN0TWVtb0F0dGFjaG1lbnRzUmVzcG9uc2USLQoLYXR0YWNobWVudHMYASADKAsyGC5tZW1vcy5hcGkudjEuQXR0YWNobWVudBIXCg9uZXh0X3BhZ2VfdG9rZW4YAiABKAkiswIKDE1lbW9SZWxhdGlvbhIyCgRtZW1vGAEgASgLMh8ubWVtb3MuYXBpLnYxLk1lbW9SZWxhdGlvbi5NZW1vQgPgQQISOgoMcmVsYXRlZF9tZW1vGAIgASgLMh8ubWVtb3MuYXBpLnYxLk1lbW9SZWxhdGlvbi5NZW1vQgPgQQISMgoEdHlwZRgDIAEoDjIfLm1lbW9zLmFwaS52MS5NZW1vUmVsYXRpb24uVHlwZUID4EECGkUKBE1lbW8SJwoEbmFtZRgBIAEoCUIZ4EEC+kETChFtZW1vcy5hcGkudjEvTWVtbxIUCgdzbmlwcGV0GAIgASgJQgPgQQMiOAoEVHlwZRIUChBUWVBFX1VOU1BFQ0lGSUVEEAASDQoJUkVGRVJFTkNFEAESCwoHQ09NTUVOVBACInYKF1NldE1lbW9SZWxhdGlvbnNSZXF1ZXN0EicKBG5hbWUYASABKAlCGeBBAvpBEwoRbWVtb3MuYXBpLnYxL01lbW8SMgoJcmVsYXRpb25zGAIgAygLMhoubWVtb3MuYXBpLnYxLk1lbW9SZWxhdGlvbkID4EECInQKGExpc3RNZW1vUmVsYXRpb25zUmVxdWVzdBInCgRuYW1lGAEgASgJQhngQQL6QRMKEW1lbW9zLmFwaS52MS9NZW1vEhYKCXBhZ2Vfc2l6ZRgCIAEoBUID4EEBEhcKCnBhZ2VfdG9rZW4YAyABKAlCA+BBASJjChlMaXN0TWVtb1JlbGF0aW9uc1Jlc3BvbnNlEi0KCXJlbGF0aW9ucxgBIAMoCzIaLm1lbW9zLmFwaS52MS5NZW1vUmVsYXRpb24SFwoPbmV4dF9wYWdlX3Rva2VuGAIgASgJIoYBChhDcmVhdGVNZW1vQ29tbWVudFJlcXVlc3QSJwoEbmFtZRgBIAEoCUIZ4EEC+kETChFtZW1vcy5hcGkudjEvTWVtbxIoCgdjb21tZW50GAIgASgLMhIubWVtb3MuYXBpLnYxLk1lbW9CA+BBAhIXCgpjb21tZW50X2lkGAMgASgJQgPgQQEiigEKF0xpc3RNZW1vQ29tbWVudHNSZXF1ZXN0EicKBG5hbWUYASABKAlCGeBBAvpBEwoRbWVtb3MuYXBpLnYxL01lbW8SFgoJcGFnZV9zaXplGAIgASgFQgPgQQESFwoKcGFnZV90b2tlbhgDIAEoCUID4EEBEhUKCG9yZGVyX2J5GAQgASgJQgPgQQEiagoYTGlzdE1lbW9Db21tZW50c1Jlc3BvbnNlEiEKBW1lbW9zGAEgAygLMhIubWVtb3MuYXBpLnYxLk1lbW8SFwoPbmV4dF9wYWdlX3Rva2VuGAIgASgJEhIKCnRvdGFsX3NpemUYAyABKAUidAoYTGlzdE1lbW9SZWFjdGlvbnNSZXF1ZXN0EicKBG5hbWUYASABKAlCGeBBAvpBEwoRbWVtb3MuYXBpLnYxL01lbW8SFgoJcGFnZV9zaXplGAIgASgFQgPgQQESFwoKcGFnZV90b2tlbhgDIAEoCUID4EEBInMKGUxpc3RNZW1vUmVhY3Rpb25zUmVzcG9uc2USKQoJcmVhY3Rpb25zGAEgAygLMhYubWVtb3MuYXBpLnYxLlJlYWN0aW9uEhcKD25leHRfcGFnZV90b2tlbhgCIAEoCRISCgp0b3RhbF9zaXplGAMgASgFInMKGVVwc2VydE1lbW9SZWFjdGlvblJlcXVlc3QSJwoEbmFtZRgBIAEoCUIZ4EEC+kETChFtZW1vcy5hcGkudjEvTWVtbxItCghyZWFjdGlvbhgCIAEoCzIWLm1lbW9zLmFwaS52MS5SZWFjdGlvbkID4EECIkgKGURlbGV0ZU1lbW9SZWFjdGlvblJlcXVlc3QSKwoEbmFtZRgBIAEoCUId4EEC+kEXChVtZW1vcy5hcGkudjEvUmVhY3Rpb24i6AEKCU1lbW9TaGFyZRIRCgRuYW1lGAEgASgJQgPgQQgSNAoLY3JlYXRlX3RpbWUYAiABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wQgPgQQMSOQoLZXhwaXJlX3RpbWUYAyABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wQgPgQQFIAIgBATpH6kFEChZtZW1vcy5hcGkudjEvTWVtb1NoYXJlEhttZW1vcy97bWVtb30vc2hhcmVzL3tzaGFyZX0qBnNoYXJlczIFc2hhcmVCDgoMX2V4cGlyZV90aW1lInUKFkNyZWF0ZU1lbW9TaGFyZVJlcXVlc3QSKQoGcGFyZW50GAEgASgJQhngQQL6QRMKEW1lbW9zLmFwaS52MS9NZW1vEjAKCm1lbW9fc2hhcmUYAiABKAsyFy5tZW1vcy5hcGkudjEuTWVtb1NoYXJlQgPgQQIiQgoVTGlzdE1lbW9TaGFyZXNSZXF1ZXN0EikKBnBhcmVudBgBIAEoCUIZ4EEC+kETChFtZW1vcy5hcGkudjEvTWVtbyJGChZMaXN0TWVtb1NoYXJlc1Jlc3BvbnNlEiwKC21lbW9fc2hhcmVzGAEgAygLMhcubWVtb3MuYXBpLnYxLk1lbW9TaGFyZSJGChZEZWxldGVNZW1vU2hhcmVSZXF1ZXN0EiwKBG5hbWUYASABKAlCHuBBAvpBGAoWbWVtb3MuYXBpLnYxL01lbW9TaGFyZSIuChVHZXRNZW1vQnlTaGFyZVJlcXVlc3QSFQoIc2hhcmVfaWQYASABKAlCA+BBAipQCgpWaXNpYmlsaXR5EhoKFlZJU0lCSUxJVFlfVU5TUEVDSUZJRUQQABILCgdQUklWQVRFEAESDQoJUFJPVEVDVEVEEAISCgoGUFVCTElDEAMy7hIKC01lbW9TZXJ2aWNlEmUKCkNyZWF0ZU1lbW8SHy5tZW1vcy5hcGkudjEuQ3JlYXRlTWVtb1JlcXVlc3QaEi5tZW1vcy5hcGkudjEuTWVtbyIi2kEEbWVtb4LT5JMCFToEbWVtbyINL2FwaS92MS9tZW1vcxJmCglMaXN0TWVtb3MSHi5tZW1vcy5hcGkudjEuTGlzdE1lbW9zUmVxdWVzdBofLm1lbW9zLmFwaS52MS5MaXN0TWVtb3NSZXNwb25zZSIY2kEAgtPkkwIPEg0vYXBpL3YxL21lbW9zEmIKB0dldE1lbW8SHC5tZW1vcy5hcGkudjEuR2V0TWVtb1JlcXVlc3QaEi5tZW1vcy5hcGkudjEuTWVtbyIl2kEEbmFtZYLT5JMCGBIWL2FwaS92MS97bmFtZT1tZW1vcy8qfRJ/CgpVcGRhdGVNZW1vEh8ubWVtb3MuYXBpLnYxLlVwZGF0ZU1lbW9SZXF1ZXN0GhIubWVtb3MuYXBpLnYxLk1lbW8iPNpBEG1lbW8sdXBkYXRlX21hc2uC0+STAiM6BG1lbW8yGy9hcGkvdjEve21lbW8ubmFtZT1tZW1vcy8qfRJsCgpEZWxldGVNZW1vEh8ubWVtb3MuYXBpLnYxLkRlbGV0ZU1lbW9SZXF1ZXN0GhYuZ29vZ2xlLnByb3RvYnVmLkVtcHR5IiXaQQRuYW1lgtPkkwIYKhYvYXBpL3YxL3tuYW1lPW1lbW9zLyp9EosBChJTZXRNZW1vQXR0YWNobWVudHMSJy5tZW1vcy5hcGkudjEuU2V0TWVtb0F0dGFjaG1lbnRzUmVxdWVzdBoWLmdvb2dsZS5wcm90b2J1Zi5FbXB0eSI02kEEbmFtZYLT5JMCJzoBKjIiL2FwaS92MS97bmFtZT1tZW1vcy8qfS9hdHRhY2htZW50cxKdAQoTTGlzdE1lbW9BdHRhY2htZW50cxIoLm1lbW9zLmFwaS52MS5MaXN0TWVtb0F0dGFjaG1lbnRzUmVxdWVzdBopLm1lbW9zLmFwaS52MS5MaXN0TWVtb0F0dGFjaG1lbnRzUmVzcG9uc2UiMdpBBG5hbWWC0+STAiQSIi9hcGkvdjEve25hbWU9bWVtb3MvKn0vYXR0YWNobWVudHMShQEKEFNldE1lbW9SZWxhdGlvbnMSJS5tZW1vcy5hcGkudjEuU2V0TWVtb1JlbGF0aW9uc1JlcXVlc3QaFi5nb29nbGUucHJvdG9idWYuRW1wdHkiMtpBBG5hbWWC0+STAiU6ASoyIC9hcGkvdjEve25hbWU9bWVtb3MvKn0vcmVsYXRpb25zEpUBChFMaXN0TWVtb1JlbGF0aW9ucxImLm1lbW9zLmFwaS52MS5MaXN0TWVtb1JlbGF0aW9uc1JlcXVlc3QaJy5tZW1vcy5hcGkudjEuTGlzdE1lbW9SZWxhdGlvbnNSZXNwb25zZSIv2kEEbmFtZYLT5JMCIhIgL2FwaS92MS97bmFtZT1tZW1vcy8qfS9yZWxhdGlvbnMSkAEKEUNyZWF0ZU1lbW9Db21tZW50EiYubWVtb3MuYXBpLnYxLkNyZWF0ZU1lbW9Db21tZW50UmVxdWVzdBoSLm1lbW9zLmFwaS52MS5NZW1vIj/aQQxuYW1lLGNvbW1lbnSC0+STAio6B2NvbW1lbnQiHy9hcGkvdjEve25hbWU9bWVtb3MvKn0vY29tbWVudHMSkQEKEExpc3RNZW1vQ29tbWVudHMSJS5tZW1vcy5hcGkudjEuTGlzdE1lbW9Db21tZW50c1JlcXVlc3QaJi5tZW1vcy5hcGkudjEuTGlzdE1lbW9Db21tZW50c1Jlc3BvbnNlIi7aQQRuYW1lgtPkkwIhEh8vYXBpL3YxL3tuYW1lPW1lbW9zLyp9L2NvbW1lbnRzEpUBChFMaXN0TWVtb1JlYWN0aW9ucxImLm1lbW9zLmFwaS52MS5MaXN0TWVtb1JlYWN0aW9uc1JlcXVlc3QaJy5tZW1vcy5hcGkudjEuTGlzdE1lbW9SZWFjdGlvbnNSZXNwb25zZSIv2kEEbmFtZYLT5JMCIhIgL2FwaS92MS97bmFtZT1tZW1vcy8qfS9yZWFjdGlvbnMSiQEKElVwc2VydE1lbW9SZWFjdGlvbhInLm1lbW9zLmFwaS52MS5VcHNlcnRNZW1vUmVhY3Rpb25SZXF1ZXN0GhYubWVtb3MuYXBpLnYxLlJlYWN0aW9uIjLaQQRuYW1lgtPkkwIlOgEqIiAvYXBpL3YxL3tuYW1lPW1lbW9zLyp9L3JlYWN0aW9ucxKIAQoSRGVsZXRlTWVtb1JlYWN0aW9uEicubWVtb3MuYXBpLnYxLkRlbGV0ZU1lbW9SZWFjdGlvblJlcXVlc3QaFi5nb29nbGUucHJvdG9idWYuRW1wdHkiMdpBBG5hbWWC0+STAiQqIi9hcGkvdjEve25hbWU9bWVtb3MvKi9yZWFjdGlvbnMvKn0SmQEKD0NyZWF0ZU1lbW9TaGFyZRIkLm1lbW9zLmFwaS52MS5DcmVhdGVNZW1vU2hhcmVSZXF1ZXN0GhcubWVtb3MuYXBpLnYxLk1lbW9TaGFyZSJH2kERcGFyZW50LG1lbW9fc2hhcmWC0+STAi06Cm1lbW9fc2hhcmUiHy9hcGkvdjEve3BhcmVudD1tZW1vcy8qfS9zaGFyZXMSjQEKDkxpc3RNZW1vU2hhcmVzEiMubWVtb3MuYXBpLnYxLkxpc3RNZW1vU2hhcmVzUmVxdWVzdBokLm1lbW9zLmFwaS52MS5MaXN0TWVtb1NoYXJlc1Jlc3BvbnNlIjDaQQZwYXJlbnSC0+STAiESHy9hcGkvdjEve3BhcmVudD1tZW1vcy8qfS9zaGFyZXMSfwoPRGVsZXRlTWVtb1NoYXJlEiQubWVtb3MuYXBpLnYxLkRlbGV0ZU1lbW9TaGFyZVJlcXVlc3QaFi5nb29nbGUucHJvdG9idWYuRW1wdHkiLtpBBG5hbWWC0+STAiEqHy9hcGkvdjEve25hbWU9bWVtb3MvKi9zaGFyZXMvKn0SbAoOR2V0TWVtb0J5U2hhcmUSIy5tZW1vcy5hcGkudjEuR2V0TWVtb0J5U2hhcmVSZXF1ZXN0GhIubWVtb3MuYXBpLnYxLk1lbW8iIYLT5JMCGxIZL2FwaS92MS9zaGFyZXMve3NoYXJlX2lkfUKoAQoQY29tLm1lbW9zLmFwaS52MUIQTWVtb1NlcnZpY2VQcm90b1ABWjBnaXRodWIuY29tL3VzZW1lbW9zL21lbW9zL3Byb3RvL2dlbi9hcGkvdjE7YXBpdjGiAgNNQViqAgxNZW1vcy5BcGkuVjHKAgxNZW1vc1xBcGlcVjHiAhhNZW1vc1xBcGlcVjFcR1BCTWV0YWRhdGHqAg5NZW1vczo6QXBpOjpWMWIGcHJvdG8z", [file_api_v1_attachment_service, file_api_v1_common, file_google_api_annotations, file_google_api_client, file_google_api_field_behavior, file_google_api_resource, file_google_protobuf_empty, file_google_protobuf_field_mask, file_google_protobuf_timestamp]);
/**
* @generated from message memos.api.v1.Reaction
......@@ -63,7 +63,7 @@ export type Reaction = Message<"memos.api.v1.Reaction"> & {
*
* @generated from field: google.protobuf.Timestamp create_time = 5;
*/
createTime?: Timestamp;
createTime?: Timestamp | undefined;
};
/**
......@@ -106,7 +106,7 @@ export type Memo = Message<"memos.api.v1.Memo"> & {
*
* @generated from field: google.protobuf.Timestamp create_time = 4;
*/
createTime?: Timestamp;
createTime?: Timestamp | undefined;
/**
* The last update timestamp.
......@@ -114,14 +114,7 @@ export type Memo = Message<"memos.api.v1.Memo"> & {
*
* @generated from field: google.protobuf.Timestamp update_time = 5;
*/
updateTime?: Timestamp;
/**
* The display timestamp of the memo.
*
* @generated from field: google.protobuf.Timestamp display_time = 6;
*/
displayTime?: Timestamp;
updateTime?: Timestamp | undefined;
/**
* Required. The content of the memo in Markdown format.
......@@ -177,7 +170,7 @@ export type Memo = Message<"memos.api.v1.Memo"> & {
*
* @generated from field: memos.api.v1.Memo.Property property = 15;
*/
property?: Memo_Property;
property?: Memo_Property | undefined;
/**
* Output only. The name of the parent memo.
......@@ -185,7 +178,7 @@ export type Memo = Message<"memos.api.v1.Memo"> & {
*
* @generated from field: optional string parent = 16;
*/
parent?: string;
parent?: string | undefined;
/**
* Output only. The snippet of the memo content. Plain text only.
......@@ -199,7 +192,7 @@ export type Memo = Message<"memos.api.v1.Memo"> & {
*
* @generated from field: optional memos.api.v1.Location location = 18;
*/
location?: Location;
location?: Location | undefined;
};
/**
......@@ -292,7 +285,7 @@ export type CreateMemoRequest = Message<"memos.api.v1.CreateMemoRequest"> & {
*
* @generated from field: memos.api.v1.Memo memo = 1;
*/
memo?: Memo;
memo?: Memo | undefined;
/**
* Optional. The memo ID to use for this memo.
......@@ -342,10 +335,10 @@ export type ListMemosRequest = Message<"memos.api.v1.ListMemosRequest"> & {
/**
* Optional. The order to sort results by.
* Default to "display_time desc".
* Default to "create_time desc".
* Supports comma-separated list of fields following AIP-132.
* Example: "pinned desc, display_time desc" or "create_time asc"
* Supported fields: pinned, display_time, create_time, update_time, name
* Example: "pinned desc, create_time desc" or "update_time asc"
* Supported fields: pinned, create_time, update_time, name
*
* @generated from field: string order_by = 4;
*/
......@@ -432,14 +425,14 @@ export type UpdateMemoRequest = Message<"memos.api.v1.UpdateMemoRequest"> & {
*
* @generated from field: memos.api.v1.Memo memo = 1;
*/
memo?: Memo;
memo?: Memo | undefined;
/**
* Required. The list of fields to update.
*
* @generated from field: google.protobuf.FieldMask update_mask = 2;
*/
updateMask?: FieldMask;
updateMask?: FieldMask | undefined;
};
/**
......@@ -572,14 +565,14 @@ export type MemoRelation = Message<"memos.api.v1.MemoRelation"> & {
*
* @generated from field: memos.api.v1.MemoRelation.Memo memo = 1;
*/
memo?: MemoRelation_Memo;
memo?: MemoRelation_Memo | undefined;
/**
* The related memo.
*
* @generated from field: memos.api.v1.MemoRelation.Memo related_memo = 2;
*/
relatedMemo?: MemoRelation_Memo;
relatedMemo?: MemoRelation_Memo | undefined;
/**
* @generated from field: memos.api.v1.MemoRelation.Type type = 3;
......@@ -755,7 +748,7 @@ export type CreateMemoCommentRequest = Message<"memos.api.v1.CreateMemoCommentRe
*
* @generated from field: memos.api.v1.Memo comment = 2;
*/
comment?: Memo;
comment?: Memo | undefined;
/**
* Optional. The comment ID to use.
......@@ -930,7 +923,7 @@ export type UpsertMemoReactionRequest = Message<"memos.api.v1.UpsertMemoReaction
*
* @generated from field: memos.api.v1.Reaction reaction = 2;
*/
reaction?: Reaction;
reaction?: Reaction | undefined;
};
/**
......@@ -979,7 +972,7 @@ export type MemoShare = Message<"memos.api.v1.MemoShare"> & {
*
* @generated from field: google.protobuf.Timestamp create_time = 2;
*/
createTime?: Timestamp;
createTime?: Timestamp | undefined;
/**
* Optional. When set, the share link stops working after this time.
......@@ -987,7 +980,7 @@ export type MemoShare = Message<"memos.api.v1.MemoShare"> & {
*
* @generated from field: optional google.protobuf.Timestamp expire_time = 3;
*/
expireTime?: Timestamp;
expireTime?: Timestamp | undefined;
};
/**
......@@ -1014,7 +1007,7 @@ export type CreateMemoShareRequest = Message<"memos.api.v1.CreateMemoShareReques
*
* @generated from field: memos.api.v1.MemoShare memo_share = 2;
*/
memoShare?: MemoShare;
memoShare?: MemoShare | undefined;
};
/**
......
// @generated by protoc-gen-es v2.11.0 with parameter "target=ts"
// @generated by protoc-gen-es v2.12.0 with parameter "target=ts"
// @generated from file api/v1/shortcut_service.proto (package memos.api.v1, syntax proto3)
/* eslint-disable */
......@@ -128,7 +128,7 @@ export type CreateShortcutRequest = Message<"memos.api.v1.CreateShortcutRequest"
*
* @generated from field: memos.api.v1.Shortcut shortcut = 2;
*/
shortcut?: Shortcut;
shortcut?: Shortcut | undefined;
/**
* Optional. If set, validate the request, but do not actually create the shortcut.
......@@ -154,14 +154,14 @@ export type UpdateShortcutRequest = Message<"memos.api.v1.UpdateShortcutRequest"
*
* @generated from field: memos.api.v1.Shortcut shortcut = 1;
*/
shortcut?: Shortcut;
shortcut?: Shortcut | undefined;
/**
* Optional. The list of fields to update.
*
* @generated from field: google.protobuf.FieldMask update_mask = 2;
*/
updateMask?: FieldMask;
updateMask?: FieldMask | undefined;
};
/**
......
// @generated by protoc-gen-es v2.11.0 with parameter "target=ts"
// @generated by protoc-gen-es v2.12.0 with parameter "target=ts"
// @generated from file api/v1/user_service.proto (package memos.api.v1, syntax proto3)
/* eslint-disable */
......@@ -18,7 +18,7 @@ import type { Message } from "@bufbuild/protobuf";
* Describes the file api/v1/user_service.proto.
*/
export const file_api_v1_user_service: GenFile = /*@__PURE__*/
fileDesc("ChlhcGkvdjEvdXNlcl9zZXJ2aWNlLnByb3RvEgxtZW1vcy5hcGkudjEi1gMKBFVzZXISEQoEbmFtZRgBIAEoCUID4EEIEioKBHJvbGUYAiABKA4yFy5tZW1vcy5hcGkudjEuVXNlci5Sb2xlQgPgQQISFQoIdXNlcm5hbWUYAyABKAlCA+BBAhISCgVlbWFpbBgEIAEoCUID4EEBEhkKDGRpc3BsYXlfbmFtZRgFIAEoCUID4EEBEhcKCmF2YXRhcl91cmwYBiABKAlCA+BBARIYCgtkZXNjcmlwdGlvbhgHIAEoCUID4EEBEhUKCHBhc3N3b3JkGAggASgJQgPgQQQSJwoFc3RhdGUYCSABKA4yEy5tZW1vcy5hcGkudjEuU3RhdGVCA+BBAhI0CgtjcmVhdGVfdGltZRgKIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXBCA+BBAxI0Cgt1cGRhdGVfdGltZRgLIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXBCA+BBAyIxCgRSb2xlEhQKEFJPTEVfVU5TUEVDSUZJRUQQABIJCgVBRE1JThACEggKBFVTRVIQAzo36kE0ChFtZW1vcy5hcGkudjEvVXNlchIMdXNlcnMve3VzZXJ9GgRuYW1lKgV1c2VyczIEdXNlciJzChBMaXN0VXNlcnNSZXF1ZXN0EhYKCXBhZ2Vfc2l6ZRgBIAEoBUID4EEBEhcKCnBhZ2VfdG9rZW4YAiABKAlCA+BBARITCgZmaWx0ZXIYAyABKAlCA+BBARIZCgxzaG93X2RlbGV0ZWQYBCABKAhCA+BBASJjChFMaXN0VXNlcnNSZXNwb25zZRIhCgV1c2VycxgBIAMoCzISLm1lbW9zLmFwaS52MS5Vc2VyEhcKD25leHRfcGFnZV90b2tlbhgCIAEoCRISCgp0b3RhbF9zaXplGAMgASgFIikKFEJhdGNoR2V0VXNlcnNSZXF1ZXN0EhEKCXVzZXJuYW1lcxgBIAMoCSI6ChVCYXRjaEdldFVzZXJzUmVzcG9uc2USIQoFdXNlcnMYASADKAsyEi5tZW1vcy5hcGkudjEuVXNlciJtCg5HZXRVc2VyUmVxdWVzdBInCgRuYW1lGAEgASgJQhngQQL6QRMKEW1lbW9zLmFwaS52MS9Vc2VyEjIKCXJlYWRfbWFzaxgCIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5GaWVsZE1hc2tCA+BBASKIAQoRQ3JlYXRlVXNlclJlcXVlc3QSKAoEdXNlchgBIAEoCzISLm1lbW9zLmFwaS52MS5Vc2VyQgbgQQLgQQQSFAoHdXNlcl9pZBgCIAEoCUID4EEBEhoKDXZhbGlkYXRlX29ubHkYAyABKAhCA+BBARIXCgpyZXF1ZXN0X2lkGAQgASgJQgPgQQEijAEKEVVwZGF0ZVVzZXJSZXF1ZXN0EiUKBHVzZXIYASABKAsyEi5tZW1vcy5hcGkudjEuVXNlckID4EECEjQKC3VwZGF0ZV9tYXNrGAIgASgLMhouZ29vZ2xlLnByb3RvYnVmLkZpZWxkTWFza0ID4EECEhoKDWFsbG93X21pc3NpbmcYAyABKAhCA+BBASJQChFEZWxldGVVc2VyUmVxdWVzdBInCgRuYW1lGAEgASgJQhngQQL6QRMKEW1lbW9zLmFwaS52MS9Vc2VyEhIKBWZvcmNlGAIgASgIQgPgQQEi2AMKCVVzZXJTdGF0cxIRCgRuYW1lGAEgASgJQgPgQQgSOwoXbWVtb19kaXNwbGF5X3RpbWVzdGFtcHMYAiADKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wEj4KD21lbW9fdHlwZV9zdGF0cxgDIAEoCzIlLm1lbW9zLmFwaS52MS5Vc2VyU3RhdHMuTWVtb1R5cGVTdGF0cxI4Cgl0YWdfY291bnQYBCADKAsyJS5tZW1vcy5hcGkudjEuVXNlclN0YXRzLlRhZ0NvdW50RW50cnkSFAoMcGlubmVkX21lbW9zGAUgAygJEhgKEHRvdGFsX21lbW9fY291bnQYBiABKAUaXwoNTWVtb1R5cGVTdGF0cxISCgpsaW5rX2NvdW50GAEgASgFEhIKCmNvZGVfY291bnQYAiABKAUSEgoKdG9kb19jb3VudBgDIAEoBRISCgp1bmRvX2NvdW50GAQgASgFGi8KDVRhZ0NvdW50RW50cnkSCwoDa2V5GAEgASgJEg0KBXZhbHVlGAIgASgFOgI4ATo/6kE8ChZtZW1vcy5hcGkudjEvVXNlclN0YXRzEgx1c2Vycy97dXNlcn0qCXVzZXJTdGF0czIJdXNlclN0YXRzIj4KE0dldFVzZXJTdGF0c1JlcXVlc3QSJwoEbmFtZRgBIAEoCUIZ4EEC+kETChFtZW1vcy5hcGkudjEvVXNlciIZChdMaXN0QWxsVXNlclN0YXRzUmVxdWVzdCJCChhMaXN0QWxsVXNlclN0YXRzUmVzcG9uc2USJgoFc3RhdHMYASADKAsyFy5tZW1vcy5hcGkudjEuVXNlclN0YXRzIuQDCgtVc2VyU2V0dGluZxIRCgRuYW1lGAEgASgJQgPgQQgSQwoPZ2VuZXJhbF9zZXR0aW5nGAIgASgLMigubWVtb3MuYXBpLnYxLlVzZXJTZXR0aW5nLkdlbmVyYWxTZXR0aW5nSAASRQoQd2ViaG9va3Nfc2V0dGluZxgFIAEoCzIpLm1lbW9zLmFwaS52MS5Vc2VyU2V0dGluZy5XZWJob29rc1NldHRpbmdIABpXCg5HZW5lcmFsU2V0dGluZxITCgZsb2NhbGUYASABKAlCA+BBARIcCg9tZW1vX3Zpc2liaWxpdHkYAyABKAlCA+BBARISCgV0aGVtZRgEIAEoCUID4EEBGj4KD1dlYmhvb2tzU2V0dGluZxIrCgh3ZWJob29rcxgBIAMoCzIZLm1lbW9zLmFwaS52MS5Vc2VyV2ViaG9vayI1CgNLZXkSEwoPS0VZX1VOU1BFQ0lGSUVEEAASCwoHR0VORVJBTBABEgwKCFdFQkhPT0tTEAQ6XepBWgoYbWVtb3MuYXBpLnYxL1VzZXJTZXR0aW5nEiN1c2Vycy97dXNlcm5hbWV9L3NldHRpbmdzL3tzZXR0aW5nfSoMdXNlclNldHRpbmdzMgt1c2VyU2V0dGluZ0IHCgV2YWx1ZSJHChVHZXRVc2VyU2V0dGluZ1JlcXVlc3QSLgoEbmFtZRgBIAEoCUIg4EEC+kEaChhtZW1vcy5hcGkudjEvVXNlclNldHRpbmcigQEKGFVwZGF0ZVVzZXJTZXR0aW5nUmVxdWVzdBIvCgdzZXR0aW5nGAEgASgLMhkubWVtb3MuYXBpLnYxLlVzZXJTZXR0aW5nQgPgQQISNAoLdXBkYXRlX21hc2sYAiABKAsyGi5nb29nbGUucHJvdG9idWYuRmllbGRNYXNrQgPgQQIidQoXTGlzdFVzZXJTZXR0aW5nc1JlcXVlc3QSKQoGcGFyZW50GAEgASgJQhngQQL6QRMKEW1lbW9zLmFwaS52MS9Vc2VyEhYKCXBhZ2Vfc2l6ZRgCIAEoBUID4EEBEhcKCnBhZ2VfdG9rZW4YAyABKAlCA+BBASJ0ChhMaXN0VXNlclNldHRpbmdzUmVzcG9uc2USKwoIc2V0dGluZ3MYASADKAsyGS5tZW1vcy5hcGkudjEuVXNlclNldHRpbmcSFwoPbmV4dF9wYWdlX3Rva2VuGAIgASgJEhIKCnRvdGFsX3NpemUYAyABKAUi6gEKDkxpbmtlZElkZW50aXR5EhEKBG5hbWUYASABKAlCA+BBCBI3CghpZHBfbmFtZRgCIAEoCUIl4EED+kEfCh1tZW1vcy5hcGkudjEvSWRlbnRpdHlQcm92aWRlchIXCgpleHRlcm5fdWlkGAMgASgJQgPgQQM6c+pBcAobbWVtb3MuYXBpLnYxL0xpbmtlZElkZW50aXR5Ei91c2Vycy97dXNlcn0vbGlua2VkSWRlbnRpdGllcy97bGlua2VkX2lkZW50aXR5fSoQbGlua2VkSWRlbnRpdGllczIObGlua2VkSWRlbnRpdHkiSAobTGlzdExpbmtlZElkZW50aXRpZXNSZXF1ZXN0EikKBnBhcmVudBgBIAEoCUIZ4EEC+kETChFtZW1vcy5hcGkudjEvVXNlciJXChxMaXN0TGlua2VkSWRlbnRpdGllc1Jlc3BvbnNlEjcKEWxpbmtlZF9pZGVudGl0aWVzGAEgAygLMhwubWVtb3MuYXBpLnYxLkxpbmtlZElkZW50aXR5IssBChtDcmVhdGVMaW5rZWRJZGVudGl0eVJlcXVlc3QSKQoGcGFyZW50GAEgASgJQhngQQL6QRMKEW1lbW9zLmFwaS52MS9Vc2VyEjcKCGlkcF9uYW1lGAIgASgJQiXgQQL6QR8KHW1lbW9zLmFwaS52MS9JZGVudGl0eVByb3ZpZGVyEhEKBGNvZGUYAyABKAlCA+BBAhIZCgxyZWRpcmVjdF91cmkYBCABKAlCA+BBAhIaCg1jb2RlX3ZlcmlmaWVyGAUgASgJQgPgQQEiTQoYR2V0TGlua2VkSWRlbnRpdHlSZXF1ZXN0EjEKBG5hbWUYASABKAlCI+BBAvpBHQobbWVtb3MuYXBpLnYxL0xpbmtlZElkZW50aXR5IlAKG0RlbGV0ZUxpbmtlZElkZW50aXR5UmVxdWVzdBIxCgRuYW1lGAEgASgJQiPgQQL6QR0KG21lbW9zLmFwaS52MS9MaW5rZWRJZGVudGl0eSLyAgoTUGVyc29uYWxBY2Nlc3NUb2tlbhIRCgRuYW1lGAEgASgJQgPgQQgSGAoLZGVzY3JpcHRpb24YAiABKAlCA+BBARIzCgpjcmVhdGVkX2F0GAMgASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcEID4EEDEjMKCmV4cGlyZXNfYXQYBCABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wQgPgQQESNQoMbGFzdF91c2VkX2F0GAUgASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcEID4EEDOowB6kGIAQogbWVtb3MuYXBpLnYxL1BlcnNvbmFsQWNjZXNzVG9rZW4SOXVzZXJzL3t1c2VyfS9wZXJzb25hbEFjY2Vzc1Rva2Vucy97cGVyc29uYWxfYWNjZXNzX3Rva2VufSoUcGVyc29uYWxBY2Nlc3NUb2tlbnMyE3BlcnNvbmFsQWNjZXNzVG9rZW4ifQofTGlzdFBlcnNvbmFsQWNjZXNzVG9rZW5zUmVxdWVzdBIpCgZwYXJlbnQYASABKAlCGeBBAvpBEwoRbWVtb3MuYXBpLnYxL1VzZXISFgoJcGFnZV9zaXplGAIgASgFQgPgQQESFwoKcGFnZV90b2tlbhgDIAEoCUID4EEBIpIBCiBMaXN0UGVyc29uYWxBY2Nlc3NUb2tlbnNSZXNwb25zZRJBChZwZXJzb25hbF9hY2Nlc3NfdG9rZW5zGAEgAygLMiEubWVtb3MuYXBpLnYxLlBlcnNvbmFsQWNjZXNzVG9rZW4SFwoPbmV4dF9wYWdlX3Rva2VuGAIgASgJEhIKCnRvdGFsX3NpemUYAyABKAUihQEKIENyZWF0ZVBlcnNvbmFsQWNjZXNzVG9rZW5SZXF1ZXN0EikKBnBhcmVudBgBIAEoCUIZ4EEC+kETChFtZW1vcy5hcGkudjEvVXNlchIYCgtkZXNjcmlwdGlvbhgCIAEoCUID4EEBEhwKD2V4cGlyZXNfaW5fZGF5cxgDIAEoBUID4EEBInQKIUNyZWF0ZVBlcnNvbmFsQWNjZXNzVG9rZW5SZXNwb25zZRJAChVwZXJzb25hbF9hY2Nlc3NfdG9rZW4YASABKAsyIS5tZW1vcy5hcGkudjEuUGVyc29uYWxBY2Nlc3NUb2tlbhINCgV0b2tlbhgCIAEoCSJaCiBEZWxldGVQZXJzb25hbEFjY2Vzc1Rva2VuUmVxdWVzdBI2CgRuYW1lGAEgASgJQijgQQL6QSIKIG1lbW9zLmFwaS52MS9QZXJzb25hbEFjY2Vzc1Rva2VuIqoBCgtVc2VyV2ViaG9vaxIMCgRuYW1lGAEgASgJEgsKA3VybBgCIAEoCRIUCgxkaXNwbGF5X25hbWUYAyABKAkSNAoLY3JlYXRlX3RpbWUYBCABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wQgPgQQMSNAoLdXBkYXRlX3RpbWUYBSABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wQgPgQQMiLgoXTGlzdFVzZXJXZWJob29rc1JlcXVlc3QSEwoGcGFyZW50GAEgASgJQgPgQQIiRwoYTGlzdFVzZXJXZWJob29rc1Jlc3BvbnNlEisKCHdlYmhvb2tzGAEgAygLMhkubWVtb3MuYXBpLnYxLlVzZXJXZWJob29rImAKGENyZWF0ZVVzZXJXZWJob29rUmVxdWVzdBITCgZwYXJlbnQYASABKAlCA+BBAhIvCgd3ZWJob29rGAIgASgLMhkubWVtb3MuYXBpLnYxLlVzZXJXZWJob29rQgPgQQIifAoYVXBkYXRlVXNlcldlYmhvb2tSZXF1ZXN0Ei8KB3dlYmhvb2sYASABKAsyGS5tZW1vcy5hcGkudjEuVXNlcldlYmhvb2tCA+BBAhIvCgt1cGRhdGVfbWFzaxgCIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5GaWVsZE1hc2siLQoYRGVsZXRlVXNlcldlYmhvb2tSZXF1ZXN0EhEKBG5hbWUYASABKAlCA+BBAiKiBwoQVXNlck5vdGlmaWNhdGlvbhIUCgRuYW1lGAEgASgJQgbgQQPgQQgSKQoGc2VuZGVyGAIgASgJQhngQQP6QRMKEW1lbW9zLmFwaS52MS9Vc2VyEiwKC3NlbmRlcl91c2VyGAggASgLMhIubWVtb3MuYXBpLnYxLlVzZXJCA+BBAxI6CgZzdGF0dXMYAyABKA4yJS5tZW1vcy5hcGkudjEuVXNlck5vdGlmaWNhdGlvbi5TdGF0dXNCA+BBARI0CgtjcmVhdGVfdGltZRgEIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXBCA+BBAxI2CgR0eXBlGAUgASgOMiMubWVtb3MuYXBpLnYxLlVzZXJOb3RpZmljYXRpb24uVHlwZUID4EEDEk4KDG1lbW9fY29tbWVudBgGIAEoCzIxLm1lbW9zLmFwaS52MS5Vc2VyTm90aWZpY2F0aW9uLk1lbW9Db21tZW50UGF5bG9hZEID4EEDSAASTgoMbWVtb19tZW50aW9uGAcgASgLMjEubWVtb3MuYXBpLnYxLlVzZXJOb3RpZmljYXRpb24uTWVtb01lbnRpb25QYXlsb2FkQgPgQQNIABpsChJNZW1vQ29tbWVudFBheWxvYWQSDAoEbWVtbxgBIAEoCRIUCgxyZWxhdGVkX21lbW8YAiABKAkSFAoMbWVtb19zbmlwcGV0GAMgASgJEhwKFHJlbGF0ZWRfbWVtb19zbmlwcGV0GAQgASgJGmwKEk1lbW9NZW50aW9uUGF5bG9hZBIMCgRtZW1vGAEgASgJEhQKDHJlbGF0ZWRfbWVtbxgCIAEoCRIUCgxtZW1vX3NuaXBwZXQYAyABKAkSHAoUcmVsYXRlZF9tZW1vX3NuaXBwZXQYBCABKAkiOgoGU3RhdHVzEhYKElNUQVRVU19VTlNQRUNJRklFRBAAEgoKBlVOUkVBRBABEgwKCEFSQ0hJVkVEEAIiQAoEVHlwZRIUChBUWVBFX1VOU1BFQ0lGSUVEEAASEAoMTUVNT19DT01NRU5UEAESEAoMTUVNT19NRU5USU9OEAI6cOpBbQodbWVtb3MuYXBpLnYxL1VzZXJOb3RpZmljYXRpb24SKXVzZXJzL3t1c2VyfS9ub3RpZmljYXRpb25zL3tub3RpZmljYXRpb259GgRuYW1lKg1ub3RpZmljYXRpb25zMgxub3RpZmljYXRpb25CCQoHcGF5bG9hZCKPAQocTGlzdFVzZXJOb3RpZmljYXRpb25zUmVxdWVzdBIpCgZwYXJlbnQYASABKAlCGeBBAvpBEwoRbWVtb3MuYXBpLnYxL1VzZXISFgoJcGFnZV9zaXplGAIgASgFQgPgQQESFwoKcGFnZV90b2tlbhgDIAEoCUID4EEBEhMKBmZpbHRlchgEIAEoCUID4EEBIm8KHUxpc3RVc2VyTm90aWZpY2F0aW9uc1Jlc3BvbnNlEjUKDW5vdGlmaWNhdGlvbnMYASADKAsyHi5tZW1vcy5hcGkudjEuVXNlck5vdGlmaWNhdGlvbhIXCg9uZXh0X3BhZ2VfdG9rZW4YAiABKAkikAEKHVVwZGF0ZVVzZXJOb3RpZmljYXRpb25SZXF1ZXN0EjkKDG5vdGlmaWNhdGlvbhgBIAEoCzIeLm1lbW9zLmFwaS52MS5Vc2VyTm90aWZpY2F0aW9uQgPgQQISNAoLdXBkYXRlX21hc2sYAiABKAsyGi5nb29nbGUucHJvdG9idWYuRmllbGRNYXNrQgPgQQIiVAodRGVsZXRlVXNlck5vdGlmaWNhdGlvblJlcXVlc3QSMwoEbmFtZRgBIAEoCUIl4EEC+kEfCh1tZW1vcy5hcGkudjEvVXNlck5vdGlmaWNhdGlvbjKCHQoLVXNlclNlcnZpY2USYwoJTGlzdFVzZXJzEh4ubWVtb3MuYXBpLnYxLkxpc3RVc2Vyc1JlcXVlc3QaHy5tZW1vcy5hcGkudjEuTGlzdFVzZXJzUmVzcG9uc2UiFYLT5JMCDxINL2FwaS92MS91c2VycxJ7Cg1CYXRjaEdldFVzZXJzEiIubWVtb3MuYXBpLnYxLkJhdGNoR2V0VXNlcnNSZXF1ZXN0GiMubWVtb3MuYXBpLnYxLkJhdGNoR2V0VXNlcnNSZXNwb25zZSIhgtPkkwIbOgEqIhYvYXBpL3YxL3VzZXJzOmJhdGNoR2V0EmIKB0dldFVzZXISHC5tZW1vcy5hcGkudjEuR2V0VXNlclJlcXVlc3QaEi5tZW1vcy5hcGkudjEuVXNlciIl2kEEbmFtZYLT5JMCGBIWL2FwaS92MS97bmFtZT11c2Vycy8qfRJlCgpDcmVhdGVVc2VyEh8ubWVtb3MuYXBpLnYxLkNyZWF0ZVVzZXJSZXF1ZXN0GhIubWVtb3MuYXBpLnYxLlVzZXIiItpBBHVzZXKC0+STAhU6BHVzZXIiDS9hcGkvdjEvdXNlcnMSfwoKVXBkYXRlVXNlchIfLm1lbW9zLmFwaS52MS5VcGRhdGVVc2VyUmVxdWVzdBoSLm1lbW9zLmFwaS52MS5Vc2VyIjzaQRB1c2VyLHVwZGF0ZV9tYXNrgtPkkwIjOgR1c2VyMhsvYXBpL3YxL3t1c2VyLm5hbWU9dXNlcnMvKn0SbAoKRGVsZXRlVXNlchIfLm1lbW9zLmFwaS52MS5EZWxldGVVc2VyUmVxdWVzdBoWLmdvb2dsZS5wcm90b2J1Zi5FbXB0eSIl2kEEbmFtZYLT5JMCGCoWL2FwaS92MS97bmFtZT11c2Vycy8qfRJ+ChBMaXN0QWxsVXNlclN0YXRzEiUubWVtb3MuYXBpLnYxLkxpc3RBbGxVc2VyU3RhdHNSZXF1ZXN0GiYubWVtb3MuYXBpLnYxLkxpc3RBbGxVc2VyU3RhdHNSZXNwb25zZSIbgtPkkwIVEhMvYXBpL3YxL3VzZXJzOnN0YXRzEnoKDEdldFVzZXJTdGF0cxIhLm1lbW9zLmFwaS52MS5HZXRVc2VyU3RhdHNSZXF1ZXN0GhcubWVtb3MuYXBpLnYxLlVzZXJTdGF0cyIu2kEEbmFtZYLT5JMCIRIfL2FwaS92MS97bmFtZT11c2Vycy8qfTpnZXRTdGF0cxKCAQoOR2V0VXNlclNldHRpbmcSIy5tZW1vcy5hcGkudjEuR2V0VXNlclNldHRpbmdSZXF1ZXN0GhkubWVtb3MuYXBpLnYxLlVzZXJTZXR0aW5nIjDaQQRuYW1lgtPkkwIjEiEvYXBpL3YxL3tuYW1lPXVzZXJzLyovc2V0dGluZ3MvKn0SqAEKEVVwZGF0ZVVzZXJTZXR0aW5nEiYubWVtb3MuYXBpLnYxLlVwZGF0ZVVzZXJTZXR0aW5nUmVxdWVzdBoZLm1lbW9zLmFwaS52MS5Vc2VyU2V0dGluZyJQ2kETc2V0dGluZyx1cGRhdGVfbWFza4LT5JMCNDoHc2V0dGluZzIpL2FwaS92MS97c2V0dGluZy5uYW1lPXVzZXJzLyovc2V0dGluZ3MvKn0SlQEKEExpc3RVc2VyU2V0dGluZ3MSJS5tZW1vcy5hcGkudjEuTGlzdFVzZXJTZXR0aW5nc1JlcXVlc3QaJi5tZW1vcy5hcGkudjEuTGlzdFVzZXJTZXR0aW5nc1Jlc3BvbnNlIjLaQQZwYXJlbnSC0+STAiMSIS9hcGkvdjEve3BhcmVudD11c2Vycy8qfS9zZXR0aW5ncxKpAQoUTGlzdExpbmtlZElkZW50aXRpZXMSKS5tZW1vcy5hcGkudjEuTGlzdExpbmtlZElkZW50aXRpZXNSZXF1ZXN0GioubWVtb3MuYXBpLnYxLkxpc3RMaW5rZWRJZGVudGl0aWVzUmVzcG9uc2UiOtpBBnBhcmVudILT5JMCKxIpL2FwaS92MS97cGFyZW50PXVzZXJzLyp9L2xpbmtlZElkZW50aXRpZXMSpwEKFENyZWF0ZUxpbmtlZElkZW50aXR5EikubWVtb3MuYXBpLnYxLkNyZWF0ZUxpbmtlZElkZW50aXR5UmVxdWVzdBocLm1lbW9zLmFwaS52MS5MaW5rZWRJZGVudGl0eSJG2kEPcGFyZW50LGlkcF9uYW1lgtPkkwIuOgEqIikvYXBpL3YxL3twYXJlbnQ9dXNlcnMvKn0vbGlua2VkSWRlbnRpdGllcxKTAQoRR2V0TGlua2VkSWRlbnRpdHkSJi5tZW1vcy5hcGkudjEuR2V0TGlua2VkSWRlbnRpdHlSZXF1ZXN0GhwubWVtb3MuYXBpLnYxLkxpbmtlZElkZW50aXR5IjjaQQRuYW1lgtPkkwIrEikvYXBpL3YxL3tuYW1lPXVzZXJzLyovbGlua2VkSWRlbnRpdGllcy8qfRKTAQoURGVsZXRlTGlua2VkSWRlbnRpdHkSKS5tZW1vcy5hcGkudjEuRGVsZXRlTGlua2VkSWRlbnRpdHlSZXF1ZXN0GhYuZ29vZ2xlLnByb3RvYnVmLkVtcHR5IjjaQQRuYW1lgtPkkwIrKikvYXBpL3YxL3tuYW1lPXVzZXJzLyovbGlua2VkSWRlbnRpdGllcy8qfRK5AQoYTGlzdFBlcnNvbmFsQWNjZXNzVG9rZW5zEi0ubWVtb3MuYXBpLnYxLkxpc3RQZXJzb25hbEFjY2Vzc1Rva2Vuc1JlcXVlc3QaLi5tZW1vcy5hcGkudjEuTGlzdFBlcnNvbmFsQWNjZXNzVG9rZW5zUmVzcG9uc2UiPtpBBnBhcmVudILT5JMCLxItL2FwaS92MS97cGFyZW50PXVzZXJzLyp9L3BlcnNvbmFsQWNjZXNzVG9rZW5zErYBChlDcmVhdGVQZXJzb25hbEFjY2Vzc1Rva2VuEi4ubWVtb3MuYXBpLnYxLkNyZWF0ZVBlcnNvbmFsQWNjZXNzVG9rZW5SZXF1ZXN0Gi8ubWVtb3MuYXBpLnYxLkNyZWF0ZVBlcnNvbmFsQWNjZXNzVG9rZW5SZXNwb25zZSI4gtPkkwIyOgEqIi0vYXBpL3YxL3twYXJlbnQ9dXNlcnMvKn0vcGVyc29uYWxBY2Nlc3NUb2tlbnMSoQEKGURlbGV0ZVBlcnNvbmFsQWNjZXNzVG9rZW4SLi5tZW1vcy5hcGkudjEuRGVsZXRlUGVyc29uYWxBY2Nlc3NUb2tlblJlcXVlc3QaFi5nb29nbGUucHJvdG9idWYuRW1wdHkiPNpBBG5hbWWC0+STAi8qLS9hcGkvdjEve25hbWU9dXNlcnMvKi9wZXJzb25hbEFjY2Vzc1Rva2Vucy8qfRKVAQoQTGlzdFVzZXJXZWJob29rcxIlLm1lbW9zLmFwaS52MS5MaXN0VXNlcldlYmhvb2tzUmVxdWVzdBomLm1lbW9zLmFwaS52MS5MaXN0VXNlcldlYmhvb2tzUmVzcG9uc2UiMtpBBnBhcmVudILT5JMCIxIhL2FwaS92MS97cGFyZW50PXVzZXJzLyp9L3dlYmhvb2tzEpsBChFDcmVhdGVVc2VyV2ViaG9vaxImLm1lbW9zLmFwaS52MS5DcmVhdGVVc2VyV2ViaG9va1JlcXVlc3QaGS5tZW1vcy5hcGkudjEuVXNlcldlYmhvb2siQ9pBDnBhcmVudCx3ZWJob29rgtPkkwIsOgd3ZWJob29rIiEvYXBpL3YxL3twYXJlbnQ9dXNlcnMvKn0vd2ViaG9va3MSqAEKEVVwZGF0ZVVzZXJXZWJob29rEiYubWVtb3MuYXBpLnYxLlVwZGF0ZVVzZXJXZWJob29rUmVxdWVzdBoZLm1lbW9zLmFwaS52MS5Vc2VyV2ViaG9vayJQ2kETd2ViaG9vayx1cGRhdGVfbWFza4LT5JMCNDoHd2ViaG9vazIpL2FwaS92MS97d2ViaG9vay5uYW1lPXVzZXJzLyovd2ViaG9va3MvKn0ShQEKEURlbGV0ZVVzZXJXZWJob29rEiYubWVtb3MuYXBpLnYxLkRlbGV0ZVVzZXJXZWJob29rUmVxdWVzdBoWLmdvb2dsZS5wcm90b2J1Zi5FbXB0eSIw2kEEbmFtZYLT5JMCIyohL2FwaS92MS97bmFtZT11c2Vycy8qL3dlYmhvb2tzLyp9EqkBChVMaXN0VXNlck5vdGlmaWNhdGlvbnMSKi5tZW1vcy5hcGkudjEuTGlzdFVzZXJOb3RpZmljYXRpb25zUmVxdWVzdBorLm1lbW9zLmFwaS52MS5MaXN0VXNlck5vdGlmaWNhdGlvbnNSZXNwb25zZSI32kEGcGFyZW50gtPkkwIoEiYvYXBpL3YxL3twYXJlbnQ9dXNlcnMvKn0vbm90aWZpY2F0aW9ucxLLAQoWVXBkYXRlVXNlck5vdGlmaWNhdGlvbhIrLm1lbW9zLmFwaS52MS5VcGRhdGVVc2VyTm90aWZpY2F0aW9uUmVxdWVzdBoeLm1lbW9zLmFwaS52MS5Vc2VyTm90aWZpY2F0aW9uImTaQRhub3RpZmljYXRpb24sdXBkYXRlX21hc2uC0+STAkM6DG5vdGlmaWNhdGlvbjIzL2FwaS92MS97bm90aWZpY2F0aW9uLm5hbWU9dXNlcnMvKi9ub3RpZmljYXRpb25zLyp9EpQBChZEZWxldGVVc2VyTm90aWZpY2F0aW9uEisubWVtb3MuYXBpLnYxLkRlbGV0ZVVzZXJOb3RpZmljYXRpb25SZXF1ZXN0GhYuZ29vZ2xlLnByb3RvYnVmLkVtcHR5IjXaQQRuYW1lgtPkkwIoKiYvYXBpL3YxL3tuYW1lPXVzZXJzLyovbm90aWZpY2F0aW9ucy8qfUKoAQoQY29tLm1lbW9zLmFwaS52MUIQVXNlclNlcnZpY2VQcm90b1ABWjBnaXRodWIuY29tL3VzZW1lbW9zL21lbW9zL3Byb3RvL2dlbi9hcGkvdjE7YXBpdjGiAgNNQViqAgxNZW1vcy5BcGkuVjHKAgxNZW1vc1xBcGlcVjHiAhhNZW1vc1xBcGlcVjFcR1BCTWV0YWRhdGHqAg5NZW1vczo6QXBpOjpWMWIGcHJvdG8z", [file_api_v1_common, file_google_api_annotations, file_google_api_client, file_google_api_field_behavior, file_google_api_resource, file_google_protobuf_empty, file_google_protobuf_field_mask, file_google_protobuf_timestamp]);
fileDesc("ChlhcGkvdjEvdXNlcl9zZXJ2aWNlLnByb3RvEgxtZW1vcy5hcGkudjEi1gMKBFVzZXISEQoEbmFtZRgBIAEoCUID4EEIEioKBHJvbGUYAiABKA4yFy5tZW1vcy5hcGkudjEuVXNlci5Sb2xlQgPgQQISFQoIdXNlcm5hbWUYAyABKAlCA+BBAhISCgVlbWFpbBgEIAEoCUID4EEBEhkKDGRpc3BsYXlfbmFtZRgFIAEoCUID4EEBEhcKCmF2YXRhcl91cmwYBiABKAlCA+BBARIYCgtkZXNjcmlwdGlvbhgHIAEoCUID4EEBEhUKCHBhc3N3b3JkGAggASgJQgPgQQQSJwoFc3RhdGUYCSABKA4yEy5tZW1vcy5hcGkudjEuU3RhdGVCA+BBAhI0CgtjcmVhdGVfdGltZRgKIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXBCA+BBAxI0Cgt1cGRhdGVfdGltZRgLIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXBCA+BBAyIxCgRSb2xlEhQKEFJPTEVfVU5TUEVDSUZJRUQQABIJCgVBRE1JThACEggKBFVTRVIQAzo36kE0ChFtZW1vcy5hcGkudjEvVXNlchIMdXNlcnMve3VzZXJ9GgRuYW1lKgV1c2VyczIEdXNlciJzChBMaXN0VXNlcnNSZXF1ZXN0EhYKCXBhZ2Vfc2l6ZRgBIAEoBUID4EEBEhcKCnBhZ2VfdG9rZW4YAiABKAlCA+BBARITCgZmaWx0ZXIYAyABKAlCA+BBARIZCgxzaG93X2RlbGV0ZWQYBCABKAhCA+BBASJjChFMaXN0VXNlcnNSZXNwb25zZRIhCgV1c2VycxgBIAMoCzISLm1lbW9zLmFwaS52MS5Vc2VyEhcKD25leHRfcGFnZV90b2tlbhgCIAEoCRISCgp0b3RhbF9zaXplGAMgASgFIikKFEJhdGNoR2V0VXNlcnNSZXF1ZXN0EhEKCXVzZXJuYW1lcxgBIAMoCSI6ChVCYXRjaEdldFVzZXJzUmVzcG9uc2USIQoFdXNlcnMYASADKAsyEi5tZW1vcy5hcGkudjEuVXNlciJtCg5HZXRVc2VyUmVxdWVzdBInCgRuYW1lGAEgASgJQhngQQL6QRMKEW1lbW9zLmFwaS52MS9Vc2VyEjIKCXJlYWRfbWFzaxgCIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5GaWVsZE1hc2tCA+BBASKIAQoRQ3JlYXRlVXNlclJlcXVlc3QSKAoEdXNlchgBIAEoCzISLm1lbW9zLmFwaS52MS5Vc2VyQgbgQQLgQQQSFAoHdXNlcl9pZBgCIAEoCUID4EEBEhoKDXZhbGlkYXRlX29ubHkYAyABKAhCA+BBARIXCgpyZXF1ZXN0X2lkGAQgASgJQgPgQQEijAEKEVVwZGF0ZVVzZXJSZXF1ZXN0EiUKBHVzZXIYASABKAsyEi5tZW1vcy5hcGkudjEuVXNlckID4EECEjQKC3VwZGF0ZV9tYXNrGAIgASgLMhouZ29vZ2xlLnByb3RvYnVmLkZpZWxkTWFza0ID4EECEhoKDWFsbG93X21pc3NpbmcYAyABKAhCA+BBASJQChFEZWxldGVVc2VyUmVxdWVzdBInCgRuYW1lGAEgASgJQhngQQL6QRMKEW1lbW9zLmFwaS52MS9Vc2VyEhIKBWZvcmNlGAIgASgIQgPgQQEi9wMKCVVzZXJTdGF0cxIRCgRuYW1lGAEgASgJQgPgQQgSPgoPbWVtb190eXBlX3N0YXRzGAMgASgLMiUubWVtb3MuYXBpLnYxLlVzZXJTdGF0cy5NZW1vVHlwZVN0YXRzEjgKCXRhZ19jb3VudBgEIAMoCzIlLm1lbW9zLmFwaS52MS5Vc2VyU3RhdHMuVGFnQ291bnRFbnRyeRI7ChdtZW1vX2NyZWF0ZWRfdGltZXN0YW1wcxgHIAMoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXASFAoMcGlubmVkX21lbW9zGAUgAygJEhgKEHRvdGFsX21lbW9fY291bnQYBiABKAUaXwoNTWVtb1R5cGVTdGF0cxISCgpsaW5rX2NvdW50GAEgASgFEhIKCmNvZGVfY291bnQYAiABKAUSEgoKdG9kb19jb3VudBgDIAEoBRISCgp1bmRvX2NvdW50GAQgASgFGi8KDVRhZ0NvdW50RW50cnkSCwoDa2V5GAEgASgJEg0KBXZhbHVlGAIgASgFOgI4ATo/6kE8ChZtZW1vcy5hcGkudjEvVXNlclN0YXRzEgx1c2Vycy97dXNlcn0qCXVzZXJTdGF0czIJdXNlclN0YXRzSgQIAhADUhdtZW1vX2Rpc3BsYXlfdGltZXN0YW1wcyI+ChNHZXRVc2VyU3RhdHNSZXF1ZXN0EicKBG5hbWUYASABKAlCGeBBAvpBEwoRbWVtb3MuYXBpLnYxL1VzZXIiGQoXTGlzdEFsbFVzZXJTdGF0c1JlcXVlc3QiQgoYTGlzdEFsbFVzZXJTdGF0c1Jlc3BvbnNlEiYKBXN0YXRzGAEgAygLMhcubWVtb3MuYXBpLnYxLlVzZXJTdGF0cyLkAwoLVXNlclNldHRpbmcSEQoEbmFtZRgBIAEoCUID4EEIEkMKD2dlbmVyYWxfc2V0dGluZxgCIAEoCzIoLm1lbW9zLmFwaS52MS5Vc2VyU2V0dGluZy5HZW5lcmFsU2V0dGluZ0gAEkUKEHdlYmhvb2tzX3NldHRpbmcYBSABKAsyKS5tZW1vcy5hcGkudjEuVXNlclNldHRpbmcuV2ViaG9va3NTZXR0aW5nSAAaVwoOR2VuZXJhbFNldHRpbmcSEwoGbG9jYWxlGAEgASgJQgPgQQESHAoPbWVtb192aXNpYmlsaXR5GAMgASgJQgPgQQESEgoFdGhlbWUYBCABKAlCA+BBARo+Cg9XZWJob29rc1NldHRpbmcSKwoId2ViaG9va3MYASADKAsyGS5tZW1vcy5hcGkudjEuVXNlcldlYmhvb2siNQoDS2V5EhMKD0tFWV9VTlNQRUNJRklFRBAAEgsKB0dFTkVSQUwQARIMCghXRUJIT09LUxAEOl3qQVoKGG1lbW9zLmFwaS52MS9Vc2VyU2V0dGluZxIjdXNlcnMve3VzZXJuYW1lfS9zZXR0aW5ncy97c2V0dGluZ30qDHVzZXJTZXR0aW5nczILdXNlclNldHRpbmdCBwoFdmFsdWUiRwoVR2V0VXNlclNldHRpbmdSZXF1ZXN0Ei4KBG5hbWUYASABKAlCIOBBAvpBGgoYbWVtb3MuYXBpLnYxL1VzZXJTZXR0aW5nIoEBChhVcGRhdGVVc2VyU2V0dGluZ1JlcXVlc3QSLwoHc2V0dGluZxgBIAEoCzIZLm1lbW9zLmFwaS52MS5Vc2VyU2V0dGluZ0ID4EECEjQKC3VwZGF0ZV9tYXNrGAIgASgLMhouZ29vZ2xlLnByb3RvYnVmLkZpZWxkTWFza0ID4EECInUKF0xpc3RVc2VyU2V0dGluZ3NSZXF1ZXN0EikKBnBhcmVudBgBIAEoCUIZ4EEC+kETChFtZW1vcy5hcGkudjEvVXNlchIWCglwYWdlX3NpemUYAiABKAVCA+BBARIXCgpwYWdlX3Rva2VuGAMgASgJQgPgQQEidAoYTGlzdFVzZXJTZXR0aW5nc1Jlc3BvbnNlEisKCHNldHRpbmdzGAEgAygLMhkubWVtb3MuYXBpLnYxLlVzZXJTZXR0aW5nEhcKD25leHRfcGFnZV90b2tlbhgCIAEoCRISCgp0b3RhbF9zaXplGAMgASgFIuoBCg5MaW5rZWRJZGVudGl0eRIRCgRuYW1lGAEgASgJQgPgQQgSNwoIaWRwX25hbWUYAiABKAlCJeBBA/pBHwodbWVtb3MuYXBpLnYxL0lkZW50aXR5UHJvdmlkZXISFwoKZXh0ZXJuX3VpZBgDIAEoCUID4EEDOnPqQXAKG21lbW9zLmFwaS52MS9MaW5rZWRJZGVudGl0eRIvdXNlcnMve3VzZXJ9L2xpbmtlZElkZW50aXRpZXMve2xpbmtlZF9pZGVudGl0eX0qEGxpbmtlZElkZW50aXRpZXMyDmxpbmtlZElkZW50aXR5IkgKG0xpc3RMaW5rZWRJZGVudGl0aWVzUmVxdWVzdBIpCgZwYXJlbnQYASABKAlCGeBBAvpBEwoRbWVtb3MuYXBpLnYxL1VzZXIiVwocTGlzdExpbmtlZElkZW50aXRpZXNSZXNwb25zZRI3ChFsaW5rZWRfaWRlbnRpdGllcxgBIAMoCzIcLm1lbW9zLmFwaS52MS5MaW5rZWRJZGVudGl0eSLLAQobQ3JlYXRlTGlua2VkSWRlbnRpdHlSZXF1ZXN0EikKBnBhcmVudBgBIAEoCUIZ4EEC+kETChFtZW1vcy5hcGkudjEvVXNlchI3CghpZHBfbmFtZRgCIAEoCUIl4EEC+kEfCh1tZW1vcy5hcGkudjEvSWRlbnRpdHlQcm92aWRlchIRCgRjb2RlGAMgASgJQgPgQQISGQoMcmVkaXJlY3RfdXJpGAQgASgJQgPgQQISGgoNY29kZV92ZXJpZmllchgFIAEoCUID4EEBIk0KGEdldExpbmtlZElkZW50aXR5UmVxdWVzdBIxCgRuYW1lGAEgASgJQiPgQQL6QR0KG21lbW9zLmFwaS52MS9MaW5rZWRJZGVudGl0eSJQChtEZWxldGVMaW5rZWRJZGVudGl0eVJlcXVlc3QSMQoEbmFtZRgBIAEoCUIj4EEC+kEdChttZW1vcy5hcGkudjEvTGlua2VkSWRlbnRpdHki8gIKE1BlcnNvbmFsQWNjZXNzVG9rZW4SEQoEbmFtZRgBIAEoCUID4EEIEhgKC2Rlc2NyaXB0aW9uGAIgASgJQgPgQQESMwoKY3JlYXRlZF9hdBgDIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXBCA+BBAxIzCgpleHBpcmVzX2F0GAQgASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcEID4EEBEjUKDGxhc3RfdXNlZF9hdBgFIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXBCA+BBAzqMAepBiAEKIG1lbW9zLmFwaS52MS9QZXJzb25hbEFjY2Vzc1Rva2VuEjl1c2Vycy97dXNlcn0vcGVyc29uYWxBY2Nlc3NUb2tlbnMve3BlcnNvbmFsX2FjY2Vzc190b2tlbn0qFHBlcnNvbmFsQWNjZXNzVG9rZW5zMhNwZXJzb25hbEFjY2Vzc1Rva2VuIn0KH0xpc3RQZXJzb25hbEFjY2Vzc1Rva2Vuc1JlcXVlc3QSKQoGcGFyZW50GAEgASgJQhngQQL6QRMKEW1lbW9zLmFwaS52MS9Vc2VyEhYKCXBhZ2Vfc2l6ZRgCIAEoBUID4EEBEhcKCnBhZ2VfdG9rZW4YAyABKAlCA+BBASKSAQogTGlzdFBlcnNvbmFsQWNjZXNzVG9rZW5zUmVzcG9uc2USQQoWcGVyc29uYWxfYWNjZXNzX3Rva2VucxgBIAMoCzIhLm1lbW9zLmFwaS52MS5QZXJzb25hbEFjY2Vzc1Rva2VuEhcKD25leHRfcGFnZV90b2tlbhgCIAEoCRISCgp0b3RhbF9zaXplGAMgASgFIoUBCiBDcmVhdGVQZXJzb25hbEFjY2Vzc1Rva2VuUmVxdWVzdBIpCgZwYXJlbnQYASABKAlCGeBBAvpBEwoRbWVtb3MuYXBpLnYxL1VzZXISGAoLZGVzY3JpcHRpb24YAiABKAlCA+BBARIcCg9leHBpcmVzX2luX2RheXMYAyABKAVCA+BBASJ0CiFDcmVhdGVQZXJzb25hbEFjY2Vzc1Rva2VuUmVzcG9uc2USQAoVcGVyc29uYWxfYWNjZXNzX3Rva2VuGAEgASgLMiEubWVtb3MuYXBpLnYxLlBlcnNvbmFsQWNjZXNzVG9rZW4SDQoFdG9rZW4YAiABKAkiWgogRGVsZXRlUGVyc29uYWxBY2Nlc3NUb2tlblJlcXVlc3QSNgoEbmFtZRgBIAEoCUIo4EEC+kEiCiBtZW1vcy5hcGkudjEvUGVyc29uYWxBY2Nlc3NUb2tlbiKqAQoLVXNlcldlYmhvb2sSDAoEbmFtZRgBIAEoCRILCgN1cmwYAiABKAkSFAoMZGlzcGxheV9uYW1lGAMgASgJEjQKC2NyZWF0ZV90aW1lGAQgASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcEID4EEDEjQKC3VwZGF0ZV90aW1lGAUgASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcEID4EEDIi4KF0xpc3RVc2VyV2ViaG9va3NSZXF1ZXN0EhMKBnBhcmVudBgBIAEoCUID4EECIkcKGExpc3RVc2VyV2ViaG9va3NSZXNwb25zZRIrCgh3ZWJob29rcxgBIAMoCzIZLm1lbW9zLmFwaS52MS5Vc2VyV2ViaG9vayJgChhDcmVhdGVVc2VyV2ViaG9va1JlcXVlc3QSEwoGcGFyZW50GAEgASgJQgPgQQISLwoHd2ViaG9vaxgCIAEoCzIZLm1lbW9zLmFwaS52MS5Vc2VyV2ViaG9va0ID4EECInwKGFVwZGF0ZVVzZXJXZWJob29rUmVxdWVzdBIvCgd3ZWJob29rGAEgASgLMhkubWVtb3MuYXBpLnYxLlVzZXJXZWJob29rQgPgQQISLwoLdXBkYXRlX21hc2sYAiABKAsyGi5nb29nbGUucHJvdG9idWYuRmllbGRNYXNrIi0KGERlbGV0ZVVzZXJXZWJob29rUmVxdWVzdBIRCgRuYW1lGAEgASgJQgPgQQIiogcKEFVzZXJOb3RpZmljYXRpb24SFAoEbmFtZRgBIAEoCUIG4EED4EEIEikKBnNlbmRlchgCIAEoCUIZ4EED+kETChFtZW1vcy5hcGkudjEvVXNlchIsCgtzZW5kZXJfdXNlchgIIAEoCzISLm1lbW9zLmFwaS52MS5Vc2VyQgPgQQMSOgoGc3RhdHVzGAMgASgOMiUubWVtb3MuYXBpLnYxLlVzZXJOb3RpZmljYXRpb24uU3RhdHVzQgPgQQESNAoLY3JlYXRlX3RpbWUYBCABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wQgPgQQMSNgoEdHlwZRgFIAEoDjIjLm1lbW9zLmFwaS52MS5Vc2VyTm90aWZpY2F0aW9uLlR5cGVCA+BBAxJOCgxtZW1vX2NvbW1lbnQYBiABKAsyMS5tZW1vcy5hcGkudjEuVXNlck5vdGlmaWNhdGlvbi5NZW1vQ29tbWVudFBheWxvYWRCA+BBA0gAEk4KDG1lbW9fbWVudGlvbhgHIAEoCzIxLm1lbW9zLmFwaS52MS5Vc2VyTm90aWZpY2F0aW9uLk1lbW9NZW50aW9uUGF5bG9hZEID4EEDSAAabAoSTWVtb0NvbW1lbnRQYXlsb2FkEgwKBG1lbW8YASABKAkSFAoMcmVsYXRlZF9tZW1vGAIgASgJEhQKDG1lbW9fc25pcHBldBgDIAEoCRIcChRyZWxhdGVkX21lbW9fc25pcHBldBgEIAEoCRpsChJNZW1vTWVudGlvblBheWxvYWQSDAoEbWVtbxgBIAEoCRIUCgxyZWxhdGVkX21lbW8YAiABKAkSFAoMbWVtb19zbmlwcGV0GAMgASgJEhwKFHJlbGF0ZWRfbWVtb19zbmlwcGV0GAQgASgJIjoKBlN0YXR1cxIWChJTVEFUVVNfVU5TUEVDSUZJRUQQABIKCgZVTlJFQUQQARIMCghBUkNISVZFRBACIkAKBFR5cGUSFAoQVFlQRV9VTlNQRUNJRklFRBAAEhAKDE1FTU9fQ09NTUVOVBABEhAKDE1FTU9fTUVOVElPThACOnDqQW0KHW1lbW9zLmFwaS52MS9Vc2VyTm90aWZpY2F0aW9uEil1c2Vycy97dXNlcn0vbm90aWZpY2F0aW9ucy97bm90aWZpY2F0aW9ufRoEbmFtZSoNbm90aWZpY2F0aW9uczIMbm90aWZpY2F0aW9uQgkKB3BheWxvYWQijwEKHExpc3RVc2VyTm90aWZpY2F0aW9uc1JlcXVlc3QSKQoGcGFyZW50GAEgASgJQhngQQL6QRMKEW1lbW9zLmFwaS52MS9Vc2VyEhYKCXBhZ2Vfc2l6ZRgCIAEoBUID4EEBEhcKCnBhZ2VfdG9rZW4YAyABKAlCA+BBARITCgZmaWx0ZXIYBCABKAlCA+BBASJvCh1MaXN0VXNlck5vdGlmaWNhdGlvbnNSZXNwb25zZRI1Cg1ub3RpZmljYXRpb25zGAEgAygLMh4ubWVtb3MuYXBpLnYxLlVzZXJOb3RpZmljYXRpb24SFwoPbmV4dF9wYWdlX3Rva2VuGAIgASgJIpABCh1VcGRhdGVVc2VyTm90aWZpY2F0aW9uUmVxdWVzdBI5Cgxub3RpZmljYXRpb24YASABKAsyHi5tZW1vcy5hcGkudjEuVXNlck5vdGlmaWNhdGlvbkID4EECEjQKC3VwZGF0ZV9tYXNrGAIgASgLMhouZ29vZ2xlLnByb3RvYnVmLkZpZWxkTWFza0ID4EECIlQKHURlbGV0ZVVzZXJOb3RpZmljYXRpb25SZXF1ZXN0EjMKBG5hbWUYASABKAlCJeBBAvpBHwodbWVtb3MuYXBpLnYxL1VzZXJOb3RpZmljYXRpb24ygh0KC1VzZXJTZXJ2aWNlEmMKCUxpc3RVc2VycxIeLm1lbW9zLmFwaS52MS5MaXN0VXNlcnNSZXF1ZXN0Gh8ubWVtb3MuYXBpLnYxLkxpc3RVc2Vyc1Jlc3BvbnNlIhWC0+STAg8SDS9hcGkvdjEvdXNlcnMSewoNQmF0Y2hHZXRVc2VycxIiLm1lbW9zLmFwaS52MS5CYXRjaEdldFVzZXJzUmVxdWVzdBojLm1lbW9zLmFwaS52MS5CYXRjaEdldFVzZXJzUmVzcG9uc2UiIYLT5JMCGzoBKiIWL2FwaS92MS91c2VyczpiYXRjaEdldBJiCgdHZXRVc2VyEhwubWVtb3MuYXBpLnYxLkdldFVzZXJSZXF1ZXN0GhIubWVtb3MuYXBpLnYxLlVzZXIiJdpBBG5hbWWC0+STAhgSFi9hcGkvdjEve25hbWU9dXNlcnMvKn0SZQoKQ3JlYXRlVXNlchIfLm1lbW9zLmFwaS52MS5DcmVhdGVVc2VyUmVxdWVzdBoSLm1lbW9zLmFwaS52MS5Vc2VyIiLaQQR1c2VygtPkkwIVOgR1c2VyIg0vYXBpL3YxL3VzZXJzEn8KClVwZGF0ZVVzZXISHy5tZW1vcy5hcGkudjEuVXBkYXRlVXNlclJlcXVlc3QaEi5tZW1vcy5hcGkudjEuVXNlciI82kEQdXNlcix1cGRhdGVfbWFza4LT5JMCIzoEdXNlcjIbL2FwaS92MS97dXNlci5uYW1lPXVzZXJzLyp9EmwKCkRlbGV0ZVVzZXISHy5tZW1vcy5hcGkudjEuRGVsZXRlVXNlclJlcXVlc3QaFi5nb29nbGUucHJvdG9idWYuRW1wdHkiJdpBBG5hbWWC0+STAhgqFi9hcGkvdjEve25hbWU9dXNlcnMvKn0SfgoQTGlzdEFsbFVzZXJTdGF0cxIlLm1lbW9zLmFwaS52MS5MaXN0QWxsVXNlclN0YXRzUmVxdWVzdBomLm1lbW9zLmFwaS52MS5MaXN0QWxsVXNlclN0YXRzUmVzcG9uc2UiG4LT5JMCFRITL2FwaS92MS91c2VyczpzdGF0cxJ6CgxHZXRVc2VyU3RhdHMSIS5tZW1vcy5hcGkudjEuR2V0VXNlclN0YXRzUmVxdWVzdBoXLm1lbW9zLmFwaS52MS5Vc2VyU3RhdHMiLtpBBG5hbWWC0+STAiESHy9hcGkvdjEve25hbWU9dXNlcnMvKn06Z2V0U3RhdHMSggEKDkdldFVzZXJTZXR0aW5nEiMubWVtb3MuYXBpLnYxLkdldFVzZXJTZXR0aW5nUmVxdWVzdBoZLm1lbW9zLmFwaS52MS5Vc2VyU2V0dGluZyIw2kEEbmFtZYLT5JMCIxIhL2FwaS92MS97bmFtZT11c2Vycy8qL3NldHRpbmdzLyp9EqgBChFVcGRhdGVVc2VyU2V0dGluZxImLm1lbW9zLmFwaS52MS5VcGRhdGVVc2VyU2V0dGluZ1JlcXVlc3QaGS5tZW1vcy5hcGkudjEuVXNlclNldHRpbmciUNpBE3NldHRpbmcsdXBkYXRlX21hc2uC0+STAjQ6B3NldHRpbmcyKS9hcGkvdjEve3NldHRpbmcubmFtZT11c2Vycy8qL3NldHRpbmdzLyp9EpUBChBMaXN0VXNlclNldHRpbmdzEiUubWVtb3MuYXBpLnYxLkxpc3RVc2VyU2V0dGluZ3NSZXF1ZXN0GiYubWVtb3MuYXBpLnYxLkxpc3RVc2VyU2V0dGluZ3NSZXNwb25zZSIy2kEGcGFyZW50gtPkkwIjEiEvYXBpL3YxL3twYXJlbnQ9dXNlcnMvKn0vc2V0dGluZ3MSqQEKFExpc3RMaW5rZWRJZGVudGl0aWVzEikubWVtb3MuYXBpLnYxLkxpc3RMaW5rZWRJZGVudGl0aWVzUmVxdWVzdBoqLm1lbW9zLmFwaS52MS5MaXN0TGlua2VkSWRlbnRpdGllc1Jlc3BvbnNlIjraQQZwYXJlbnSC0+STAisSKS9hcGkvdjEve3BhcmVudD11c2Vycy8qfS9saW5rZWRJZGVudGl0aWVzEqcBChRDcmVhdGVMaW5rZWRJZGVudGl0eRIpLm1lbW9zLmFwaS52MS5DcmVhdGVMaW5rZWRJZGVudGl0eVJlcXVlc3QaHC5tZW1vcy5hcGkudjEuTGlua2VkSWRlbnRpdHkiRtpBD3BhcmVudCxpZHBfbmFtZYLT5JMCLjoBKiIpL2FwaS92MS97cGFyZW50PXVzZXJzLyp9L2xpbmtlZElkZW50aXRpZXMSkwEKEUdldExpbmtlZElkZW50aXR5EiYubWVtb3MuYXBpLnYxLkdldExpbmtlZElkZW50aXR5UmVxdWVzdBocLm1lbW9zLmFwaS52MS5MaW5rZWRJZGVudGl0eSI42kEEbmFtZYLT5JMCKxIpL2FwaS92MS97bmFtZT11c2Vycy8qL2xpbmtlZElkZW50aXRpZXMvKn0SkwEKFERlbGV0ZUxpbmtlZElkZW50aXR5EikubWVtb3MuYXBpLnYxLkRlbGV0ZUxpbmtlZElkZW50aXR5UmVxdWVzdBoWLmdvb2dsZS5wcm90b2J1Zi5FbXB0eSI42kEEbmFtZYLT5JMCKyopL2FwaS92MS97bmFtZT11c2Vycy8qL2xpbmtlZElkZW50aXRpZXMvKn0SuQEKGExpc3RQZXJzb25hbEFjY2Vzc1Rva2VucxItLm1lbW9zLmFwaS52MS5MaXN0UGVyc29uYWxBY2Nlc3NUb2tlbnNSZXF1ZXN0Gi4ubWVtb3MuYXBpLnYxLkxpc3RQZXJzb25hbEFjY2Vzc1Rva2Vuc1Jlc3BvbnNlIj7aQQZwYXJlbnSC0+STAi8SLS9hcGkvdjEve3BhcmVudD11c2Vycy8qfS9wZXJzb25hbEFjY2Vzc1Rva2VucxK2AQoZQ3JlYXRlUGVyc29uYWxBY2Nlc3NUb2tlbhIuLm1lbW9zLmFwaS52MS5DcmVhdGVQZXJzb25hbEFjY2Vzc1Rva2VuUmVxdWVzdBovLm1lbW9zLmFwaS52MS5DcmVhdGVQZXJzb25hbEFjY2Vzc1Rva2VuUmVzcG9uc2UiOILT5JMCMjoBKiItL2FwaS92MS97cGFyZW50PXVzZXJzLyp9L3BlcnNvbmFsQWNjZXNzVG9rZW5zEqEBChlEZWxldGVQZXJzb25hbEFjY2Vzc1Rva2VuEi4ubWVtb3MuYXBpLnYxLkRlbGV0ZVBlcnNvbmFsQWNjZXNzVG9rZW5SZXF1ZXN0GhYuZ29vZ2xlLnByb3RvYnVmLkVtcHR5IjzaQQRuYW1lgtPkkwIvKi0vYXBpL3YxL3tuYW1lPXVzZXJzLyovcGVyc29uYWxBY2Nlc3NUb2tlbnMvKn0SlQEKEExpc3RVc2VyV2ViaG9va3MSJS5tZW1vcy5hcGkudjEuTGlzdFVzZXJXZWJob29rc1JlcXVlc3QaJi5tZW1vcy5hcGkudjEuTGlzdFVzZXJXZWJob29rc1Jlc3BvbnNlIjLaQQZwYXJlbnSC0+STAiMSIS9hcGkvdjEve3BhcmVudD11c2Vycy8qfS93ZWJob29rcxKbAQoRQ3JlYXRlVXNlcldlYmhvb2sSJi5tZW1vcy5hcGkudjEuQ3JlYXRlVXNlcldlYmhvb2tSZXF1ZXN0GhkubWVtb3MuYXBpLnYxLlVzZXJXZWJob29rIkPaQQ5wYXJlbnQsd2ViaG9va4LT5JMCLDoHd2ViaG9vayIhL2FwaS92MS97cGFyZW50PXVzZXJzLyp9L3dlYmhvb2tzEqgBChFVcGRhdGVVc2VyV2ViaG9vaxImLm1lbW9zLmFwaS52MS5VcGRhdGVVc2VyV2ViaG9va1JlcXVlc3QaGS5tZW1vcy5hcGkudjEuVXNlcldlYmhvb2siUNpBE3dlYmhvb2ssdXBkYXRlX21hc2uC0+STAjQ6B3dlYmhvb2syKS9hcGkvdjEve3dlYmhvb2submFtZT11c2Vycy8qL3dlYmhvb2tzLyp9EoUBChFEZWxldGVVc2VyV2ViaG9vaxImLm1lbW9zLmFwaS52MS5EZWxldGVVc2VyV2ViaG9va1JlcXVlc3QaFi5nb29nbGUucHJvdG9idWYuRW1wdHkiMNpBBG5hbWWC0+STAiMqIS9hcGkvdjEve25hbWU9dXNlcnMvKi93ZWJob29rcy8qfRKpAQoVTGlzdFVzZXJOb3RpZmljYXRpb25zEioubWVtb3MuYXBpLnYxLkxpc3RVc2VyTm90aWZpY2F0aW9uc1JlcXVlc3QaKy5tZW1vcy5hcGkudjEuTGlzdFVzZXJOb3RpZmljYXRpb25zUmVzcG9uc2UiN9pBBnBhcmVudILT5JMCKBImL2FwaS92MS97cGFyZW50PXVzZXJzLyp9L25vdGlmaWNhdGlvbnMSywEKFlVwZGF0ZVVzZXJOb3RpZmljYXRpb24SKy5tZW1vcy5hcGkudjEuVXBkYXRlVXNlck5vdGlmaWNhdGlvblJlcXVlc3QaHi5tZW1vcy5hcGkudjEuVXNlck5vdGlmaWNhdGlvbiJk2kEYbm90aWZpY2F0aW9uLHVwZGF0ZV9tYXNrgtPkkwJDOgxub3RpZmljYXRpb24yMy9hcGkvdjEve25vdGlmaWNhdGlvbi5uYW1lPXVzZXJzLyovbm90aWZpY2F0aW9ucy8qfRKUAQoWRGVsZXRlVXNlck5vdGlmaWNhdGlvbhIrLm1lbW9zLmFwaS52MS5EZWxldGVVc2VyTm90aWZpY2F0aW9uUmVxdWVzdBoWLmdvb2dsZS5wcm90b2J1Zi5FbXB0eSI12kEEbmFtZYLT5JMCKComL2FwaS92MS97bmFtZT11c2Vycy8qL25vdGlmaWNhdGlvbnMvKn1CqAEKEGNvbS5tZW1vcy5hcGkudjFCEFVzZXJTZXJ2aWNlUHJvdG9QAVowZ2l0aHViLmNvbS91c2VtZW1vcy9tZW1vcy9wcm90by9nZW4vYXBpL3YxO2FwaXYxogIDTUFYqgIMTWVtb3MuQXBpLlYxygIMTWVtb3NcQXBpXFYx4gIYTWVtb3NcQXBpXFYxXEdQQk1ldGFkYXRh6gIOTWVtb3M6OkFwaTo6VjFiBnByb3RvMw", [file_api_v1_common, file_google_api_annotations, file_google_api_client, file_google_api_field_behavior, file_google_api_resource, file_google_protobuf_empty, file_google_protobuf_field_mask, file_google_protobuf_timestamp]);
/**
* @generated from message memos.api.v1.User
......@@ -93,14 +93,14 @@ export type User = Message<"memos.api.v1.User"> & {
*
* @generated from field: google.protobuf.Timestamp create_time = 10;
*/
createTime?: Timestamp;
createTime?: Timestamp | undefined;
/**
* Output only. The last update timestamp.
*
* @generated from field: google.protobuf.Timestamp update_time = 11;
*/
updateTime?: Timestamp;
updateTime?: Timestamp | undefined;
};
/**
......@@ -275,7 +275,7 @@ export type GetUserRequest = Message<"memos.api.v1.GetUserRequest"> & {
*
* @generated from field: google.protobuf.FieldMask read_mask = 2;
*/
readMask?: FieldMask;
readMask?: FieldMask | undefined;
};
/**
......@@ -294,7 +294,7 @@ export type CreateUserRequest = Message<"memos.api.v1.CreateUserRequest"> & {
*
* @generated from field: memos.api.v1.User user = 1;
*/
user?: User;
user?: User | undefined;
/**
* Optional. The user ID to use for this user.
......@@ -337,14 +337,14 @@ export type UpdateUserRequest = Message<"memos.api.v1.UpdateUserRequest"> & {
*
* @generated from field: memos.api.v1.User user = 1;
*/
user?: User;
user?: User | undefined;
/**
* Required. The list of fields to update.
*
* @generated from field: google.protobuf.FieldMask update_mask = 2;
*/
updateMask?: FieldMask;
updateMask?: FieldMask | undefined;
/**
* Optional. If set to true, allows updating sensitive fields.
......@@ -402,19 +402,12 @@ export type UserStats = Message<"memos.api.v1.UserStats"> & {
*/
name: string;
/**
* The timestamps when the memos were displayed.
*
* @generated from field: repeated google.protobuf.Timestamp memo_display_timestamps = 2;
*/
memoDisplayTimestamps: Timestamp[];
/**
* The stats of memo types.
*
* @generated from field: memos.api.v1.UserStats.MemoTypeStats memo_type_stats = 3;
*/
memoTypeStats?: UserStats_MemoTypeStats;
memoTypeStats?: UserStats_MemoTypeStats | undefined;
/**
* The count of tags.
......@@ -423,6 +416,13 @@ export type UserStats = Message<"memos.api.v1.UserStats"> & {
*/
tagCount: { [key: string]: number };
/**
* The creation timestamps of the user's memos.
*
* @generated from field: repeated google.protobuf.Timestamp memo_created_timestamps = 7;
*/
memoCreatedTimestamps: Timestamp[];
/**
* The pinned memos of the user.
*
......@@ -692,14 +692,14 @@ export type UpdateUserSettingRequest = Message<"memos.api.v1.UpdateUserSettingRe
*
* @generated from field: memos.api.v1.UserSetting setting = 1;
*/
setting?: UserSetting;
setting?: UserSetting | undefined;
/**
* Required. The list of fields to update.
*
* @generated from field: google.protobuf.FieldMask update_mask = 2;
*/
updateMask?: FieldMask;
updateMask?: FieldMask | undefined;
};
/**
......@@ -977,21 +977,21 @@ export type PersonalAccessToken = Message<"memos.api.v1.PersonalAccessToken"> &
*
* @generated from field: google.protobuf.Timestamp created_at = 3;
*/
createdAt?: Timestamp;
createdAt?: Timestamp | undefined;
/**
* Optional. The expiration timestamp.
*
* @generated from field: google.protobuf.Timestamp expires_at = 4;
*/
expiresAt?: Timestamp;
expiresAt?: Timestamp | undefined;
/**
* Output only. The last used timestamp.
*
* @generated from field: google.protobuf.Timestamp last_used_at = 5;
*/
lastUsedAt?: Timestamp;
lastUsedAt?: Timestamp | undefined;
};
/**
......@@ -1111,7 +1111,7 @@ export type CreatePersonalAccessTokenResponse = Message<"memos.api.v1.CreatePers
*
* @generated from field: memos.api.v1.PersonalAccessToken personal_access_token = 1;
*/
personalAccessToken?: PersonalAccessToken;
personalAccessToken?: PersonalAccessToken | undefined;
/**
* The actual token value - only returned on creation.
......@@ -1182,14 +1182,14 @@ export type UserWebhook = Message<"memos.api.v1.UserWebhook"> & {
*
* @generated from field: google.protobuf.Timestamp create_time = 4;
*/
createTime?: Timestamp;
createTime?: Timestamp | undefined;
/**
* The last update time of the webhook.
*
* @generated from field: google.protobuf.Timestamp update_time = 5;
*/
updateTime?: Timestamp;
updateTime?: Timestamp | undefined;
};
/**
......@@ -1255,7 +1255,7 @@ export type CreateUserWebhookRequest = Message<"memos.api.v1.CreateUserWebhookRe
*
* @generated from field: memos.api.v1.UserWebhook webhook = 2;
*/
webhook?: UserWebhook;
webhook?: UserWebhook | undefined;
};
/**
......@@ -1274,14 +1274,14 @@ export type UpdateUserWebhookRequest = Message<"memos.api.v1.UpdateUserWebhookRe
*
* @generated from field: memos.api.v1.UserWebhook webhook = 1;
*/
webhook?: UserWebhook;
webhook?: UserWebhook | undefined;
/**
* The list of fields to update.
*
* @generated from field: google.protobuf.FieldMask update_mask = 2;
*/
updateMask?: FieldMask;
updateMask?: FieldMask | undefined;
};
/**
......@@ -1336,7 +1336,7 @@ export type UserNotification = Message<"memos.api.v1.UserNotification"> & {
*
* @generated from field: memos.api.v1.User sender_user = 8;
*/
senderUser?: User;
senderUser?: User | undefined;
/**
* The status of the notification.
......@@ -1350,7 +1350,7 @@ export type UserNotification = Message<"memos.api.v1.UserNotification"> & {
*
* @generated from field: google.protobuf.Timestamp create_time = 4;
*/
createTime?: Timestamp;
createTime?: Timestamp | undefined;
/**
* The type of the notification.
......@@ -1584,12 +1584,12 @@ export type UpdateUserNotificationRequest = Message<"memos.api.v1.UpdateUserNoti
/**
* @generated from field: memos.api.v1.UserNotification notification = 1;
*/
notification?: UserNotification;
notification?: UserNotification | undefined;
/**
* @generated from field: google.protobuf.FieldMask update_mask = 2;
*/
updateMask?: FieldMask;
updateMask?: FieldMask | undefined;
};
/**
......
......@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
// @generated by protoc-gen-es v2.11.0 with parameter "target=ts"
// @generated by protoc-gen-es v2.12.0 with parameter "target=ts"
// @generated from file google/api/annotations.proto (package google.api, syntax proto3)
/* eslint-disable */
......
......@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
// @generated by protoc-gen-es v2.11.0 with parameter "target=ts"
// @generated by protoc-gen-es v2.12.0 with parameter "target=ts"
// @generated from file google/api/client.proto (package google.api, syntax proto3)
/* eslint-disable */
......@@ -57,7 +57,7 @@ export type CommonLanguageSettings = Message<"google.api.CommonLanguageSettings"
*
* @generated from field: google.api.SelectiveGapicGeneration selective_gapic_generation = 3;
*/
selectiveGapicGeneration?: SelectiveGapicGeneration;
selectiveGapicGeneration?: SelectiveGapicGeneration | undefined;
};
/**
......@@ -102,56 +102,56 @@ export type ClientLibrarySettings = Message<"google.api.ClientLibrarySettings">
*
* @generated from field: google.api.JavaSettings java_settings = 21;
*/
javaSettings?: JavaSettings;
javaSettings?: JavaSettings | undefined;
/**
* Settings for C++ client libraries.
*
* @generated from field: google.api.CppSettings cpp_settings = 22;
*/
cppSettings?: CppSettings;
cppSettings?: CppSettings | undefined;
/**
* Settings for PHP client libraries.
*
* @generated from field: google.api.PhpSettings php_settings = 23;
*/
phpSettings?: PhpSettings;
phpSettings?: PhpSettings | undefined;
/**
* Settings for Python client libraries.
*
* @generated from field: google.api.PythonSettings python_settings = 24;
*/
pythonSettings?: PythonSettings;
pythonSettings?: PythonSettings | undefined;
/**
* Settings for Node client libraries.
*
* @generated from field: google.api.NodeSettings node_settings = 25;
*/
nodeSettings?: NodeSettings;
nodeSettings?: NodeSettings | undefined;
/**
* Settings for .NET client libraries.
*
* @generated from field: google.api.DotnetSettings dotnet_settings = 26;
*/
dotnetSettings?: DotnetSettings;
dotnetSettings?: DotnetSettings | undefined;
/**
* Settings for Ruby client libraries.
*
* @generated from field: google.api.RubySettings ruby_settings = 27;
*/
rubySettings?: RubySettings;
rubySettings?: RubySettings | undefined;
/**
* Settings for Go client libraries.
*
* @generated from field: google.api.GoSettings go_settings = 28;
*/
goSettings?: GoSettings;
goSettings?: GoSettings | undefined;
};
/**
......@@ -313,7 +313,7 @@ export type JavaSettings = Message<"google.api.JavaSettings"> & {
*
* @generated from field: google.api.CommonLanguageSettings common = 3;
*/
common?: CommonLanguageSettings;
common?: CommonLanguageSettings | undefined;
};
/**
......@@ -334,7 +334,7 @@ export type CppSettings = Message<"google.api.CppSettings"> & {
*
* @generated from field: google.api.CommonLanguageSettings common = 1;
*/
common?: CommonLanguageSettings;
common?: CommonLanguageSettings | undefined;
};
/**
......@@ -355,7 +355,7 @@ export type PhpSettings = Message<"google.api.PhpSettings"> & {
*
* @generated from field: google.api.CommonLanguageSettings common = 1;
*/
common?: CommonLanguageSettings;
common?: CommonLanguageSettings | undefined;
};
/**
......@@ -376,14 +376,14 @@ export type PythonSettings = Message<"google.api.PythonSettings"> & {
*
* @generated from field: google.api.CommonLanguageSettings common = 1;
*/
common?: CommonLanguageSettings;
common?: CommonLanguageSettings | undefined;
/**
* Experimental features to be included during client library generation.
*
* @generated from field: google.api.PythonSettings.ExperimentalFeatures experimental_features = 2;
*/
experimentalFeatures?: PythonSettings_ExperimentalFeatures;
experimentalFeatures?: PythonSettings_ExperimentalFeatures | undefined;
};
/**
......@@ -450,7 +450,7 @@ export type NodeSettings = Message<"google.api.NodeSettings"> & {
*
* @generated from field: google.api.CommonLanguageSettings common = 1;
*/
common?: CommonLanguageSettings;
common?: CommonLanguageSettings | undefined;
};
/**
......@@ -471,7 +471,7 @@ export type DotnetSettings = Message<"google.api.DotnetSettings"> & {
*
* @generated from field: google.api.CommonLanguageSettings common = 1;
*/
common?: CommonLanguageSettings;
common?: CommonLanguageSettings | undefined;
/**
* Map from original service names to renamed versions.
......@@ -542,7 +542,7 @@ export type RubySettings = Message<"google.api.RubySettings"> & {
*
* @generated from field: google.api.CommonLanguageSettings common = 1;
*/
common?: CommonLanguageSettings;
common?: CommonLanguageSettings | undefined;
};
/**
......@@ -563,7 +563,7 @@ export type GoSettings = Message<"google.api.GoSettings"> & {
*
* @generated from field: google.api.CommonLanguageSettings common = 1;
*/
common?: CommonLanguageSettings;
common?: CommonLanguageSettings | undefined;
/**
* Map of service names to renamed services. Keys are the package relative
......@@ -626,7 +626,7 @@ export type MethodSettings = Message<"google.api.MethodSettings"> & {
*
* @generated from field: google.api.MethodSettings.LongRunning long_running = 2;
*/
longRunning?: MethodSettings_LongRunning;
longRunning?: MethodSettings_LongRunning | undefined;
/**
* List of top-level fields of the request message, that should be
......@@ -669,7 +669,7 @@ export type MethodSettings_LongRunning = Message<"google.api.MethodSettings.Long
*
* @generated from field: google.protobuf.Duration initial_poll_delay = 1;
*/
initialPollDelay?: Duration;
initialPollDelay?: Duration | undefined;
/**
* Multiplier to gradually increase delay between subsequent polls until it
......@@ -686,7 +686,7 @@ export type MethodSettings_LongRunning = Message<"google.api.MethodSettings.Long
*
* @generated from field: google.protobuf.Duration max_poll_delay = 3;
*/
maxPollDelay?: Duration;
maxPollDelay?: Duration | undefined;
/**
* Total polling timeout.
......@@ -694,7 +694,7 @@ export type MethodSettings_LongRunning = Message<"google.api.MethodSettings.Long
*
* @generated from field: google.protobuf.Duration total_poll_timeout = 4;
*/
totalPollTimeout?: Duration;
totalPollTimeout?: Duration | undefined;
};
/**
......
......@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
// @generated by protoc-gen-es v2.11.0 with parameter "target=ts"
// @generated by protoc-gen-es v2.12.0 with parameter "target=ts"
// @generated from file google/api/field_behavior.proto (package google.api, syntax proto3)
/* eslint-disable */
......
......@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
// @generated by protoc-gen-es v2.11.0 with parameter "target=ts"
// @generated by protoc-gen-es v2.12.0 with parameter "target=ts"
// @generated from file google/api/http.proto (package google.api, syntax proto3)
/* eslint-disable */
......
......@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
// @generated by protoc-gen-es v2.11.0 with parameter "target=ts"
// @generated by protoc-gen-es v2.12.0 with parameter "target=ts"
// @generated from file google/api/launch_stage.proto (package google.api, syntax proto3)
/* eslint-disable */
......
......@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
// @generated by protoc-gen-es v2.11.0 with parameter "target=ts"
// @generated by protoc-gen-es v2.12.0 with parameter "target=ts"
// @generated from file google/api/resource.proto (package google.api, syntax proto3)
/* eslint-disable */
......
......@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
// @generated by protoc-gen-es v2.11.0 with parameter "target=ts"
// @generated by protoc-gen-es v2.12.0 with parameter "target=ts"
// @generated from file google/type/color.proto (package google.type, syntax proto3)
/* eslint-disable */
......@@ -192,7 +192,7 @@ export type Color = Message<"google.type.Color"> & {
*
* @generated from field: google.protobuf.FloatValue alpha = 4;
*/
alpha?: number;
alpha?: number | undefined;
};
/**
......
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