mirror of
				https://github.com/usememos/memos.git
				synced 2025-06-05 22:09:59 +02:00 
			
		
		
		
	chore: tweak reaction store
This commit is contained in:
		| @@ -427,6 +427,7 @@ paths: | |||||||
|             - EYES |             - EYES | ||||||
|             - THINKING_FACE |             - THINKING_FACE | ||||||
|             - CLOWN_FACE |             - CLOWN_FACE | ||||||
|  |             - QUESTION_MARK | ||||||
|           default: TYPE_UNSPECIFIED |           default: TYPE_UNSPECIFIED | ||||||
|       tags: |       tags: | ||||||
|         - MemoService |         - MemoService | ||||||
| @@ -1557,6 +1558,7 @@ definitions: | |||||||
|       - EYES |       - EYES | ||||||
|       - THINKING_FACE |       - THINKING_FACE | ||||||
|       - CLOWN_FACE |       - CLOWN_FACE | ||||||
|  |       - QUESTION_MARK | ||||||
|     default: TYPE_UNSPECIFIED |     default: TYPE_UNSPECIFIED | ||||||
|   apiv2RowStatus: |   apiv2RowStatus: | ||||||
|     type: string |     type: string | ||||||
|   | |||||||
| @@ -24,6 +24,7 @@ message Reaction { | |||||||
|     EYES = 9; |     EYES = 9; | ||||||
|     THINKING_FACE = 10; |     THINKING_FACE = 10; | ||||||
|     CLOWN_FACE = 11; |     CLOWN_FACE = 11; | ||||||
|  |     QUESTION_MARK = 12; | ||||||
|   } |   } | ||||||
|   Type reaction_type = 4; |   Type reaction_type = 4; | ||||||
| } | } | ||||||
|   | |||||||
| @@ -1182,6 +1182,7 @@ Used internally for obfuscating the page token. | |||||||
| | EYES | 9 |  | | | EYES | 9 |  | | ||||||
| | THINKING_FACE | 10 |  | | | THINKING_FACE | 10 |  | | ||||||
| | CLOWN_FACE | 11 |  | | | CLOWN_FACE | 11 |  | | ||||||
|  | | QUESTION_MARK | 12 |  | | ||||||
|  |  | ||||||
|  |  | ||||||
|   |   | ||||||
|   | |||||||
| @@ -35,6 +35,7 @@ const ( | |||||||
| 	Reaction_EYES             Reaction_Type = 9 | 	Reaction_EYES             Reaction_Type = 9 | ||||||
| 	Reaction_THINKING_FACE    Reaction_Type = 10 | 	Reaction_THINKING_FACE    Reaction_Type = 10 | ||||||
| 	Reaction_CLOWN_FACE       Reaction_Type = 11 | 	Reaction_CLOWN_FACE       Reaction_Type = 11 | ||||||
|  | 	Reaction_QUESTION_MARK    Reaction_Type = 12 | ||||||
| ) | ) | ||||||
|  |  | ||||||
| // Enum value maps for Reaction_Type. | // Enum value maps for Reaction_Type. | ||||||
| @@ -52,6 +53,7 @@ var ( | |||||||
| 		9:  "EYES", | 		9:  "EYES", | ||||||
| 		10: "THINKING_FACE", | 		10: "THINKING_FACE", | ||||||
| 		11: "CLOWN_FACE", | 		11: "CLOWN_FACE", | ||||||
|  | 		12: "QUESTION_MARK", | ||||||
| 	} | 	} | ||||||
| 	Reaction_Type_value = map[string]int32{ | 	Reaction_Type_value = map[string]int32{ | ||||||
| 		"TYPE_UNSPECIFIED": 0, | 		"TYPE_UNSPECIFIED": 0, | ||||||
| @@ -66,6 +68,7 @@ var ( | |||||||
| 		"EYES":             9, | 		"EYES":             9, | ||||||
| 		"THINKING_FACE":    10, | 		"THINKING_FACE":    10, | ||||||
| 		"CLOWN_FACE":       11, | 		"CLOWN_FACE":       11, | ||||||
|  | 		"QUESTION_MARK":    12, | ||||||
| 	} | 	} | ||||||
| ) | ) | ||||||
|  |  | ||||||
| @@ -172,7 +175,7 @@ var File_api_v2_reaction_service_proto protoreflect.FileDescriptor | |||||||
| var file_api_v2_reaction_service_proto_rawDesc = []byte{ | var file_api_v2_reaction_service_proto_rawDesc = []byte{ | ||||||
| 	0x0a, 0x1d, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x32, 0x2f, 0x72, 0x65, 0x61, 0x63, 0x74, 0x69, 0x6f, | 	0x0a, 0x1d, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x32, 0x2f, 0x72, 0x65, 0x61, 0x63, 0x74, 0x69, 0x6f, | ||||||
| 	0x6e, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, | 	0x6e, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, | ||||||
| 	0x0c, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x22, 0xce, 0x02, | 	0x0c, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x22, 0xe1, 0x02, | ||||||
| 	0x0a, 0x08, 0x52, 0x65, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, | 	0x0a, 0x08, 0x52, 0x65, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, | ||||||
| 	0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x02, 0x69, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x72, | 	0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x02, 0x69, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x72, | ||||||
| 	0x65, 0x61, 0x74, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x72, 0x65, | 	0x65, 0x61, 0x74, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x72, 0x65, | ||||||
| @@ -182,7 +185,7 @@ var file_api_v2_reaction_service_proto_rawDesc = []byte{ | |||||||
| 	0x74, 0x79, 0x70, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1b, 0x2e, 0x6d, 0x65, 0x6d, | 	0x74, 0x79, 0x70, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1b, 0x2e, 0x6d, 0x65, 0x6d, | ||||||
| 	0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x52, 0x65, 0x61, 0x63, 0x74, 0x69, | 	0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x52, 0x65, 0x61, 0x63, 0x74, 0x69, | ||||||
| 	0x6f, 0x6e, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x52, 0x0c, 0x72, 0x65, 0x61, 0x63, 0x74, 0x69, 0x6f, | 	0x6f, 0x6e, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x52, 0x0c, 0x72, 0x65, 0x61, 0x63, 0x74, 0x69, 0x6f, | ||||||
| 	0x6e, 0x54, 0x79, 0x70, 0x65, 0x22, 0xb6, 0x01, 0x0a, 0x04, 0x54, 0x79, 0x70, 0x65, 0x12, 0x14, | 	0x6e, 0x54, 0x79, 0x70, 0x65, 0x22, 0xc9, 0x01, 0x0a, 0x04, 0x54, 0x79, 0x70, 0x65, 0x12, 0x14, | ||||||
| 	0x0a, 0x10, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, | 	0x0a, 0x10, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, | ||||||
| 	0x45, 0x44, 0x10, 0x00, 0x12, 0x0d, 0x0a, 0x09, 0x54, 0x48, 0x55, 0x4d, 0x42, 0x53, 0x5f, 0x55, | 	0x45, 0x44, 0x10, 0x00, 0x12, 0x0d, 0x0a, 0x09, 0x54, 0x48, 0x55, 0x4d, 0x42, 0x53, 0x5f, 0x55, | ||||||
| 	0x50, 0x10, 0x01, 0x12, 0x0f, 0x0a, 0x0b, 0x54, 0x48, 0x55, 0x4d, 0x42, 0x53, 0x5f, 0x44, 0x4f, | 	0x50, 0x10, 0x01, 0x12, 0x0f, 0x0a, 0x0b, 0x54, 0x48, 0x55, 0x4d, 0x42, 0x53, 0x5f, 0x44, 0x4f, | ||||||
| @@ -193,19 +196,20 @@ var file_api_v2_reaction_service_proto_rawDesc = []byte{ | |||||||
| 	0x41, 0x4e, 0x44, 0x10, 0x07, 0x12, 0x0a, 0x0a, 0x06, 0x52, 0x4f, 0x43, 0x4b, 0x45, 0x54, 0x10, | 	0x41, 0x4e, 0x44, 0x10, 0x07, 0x12, 0x0a, 0x0a, 0x06, 0x52, 0x4f, 0x43, 0x4b, 0x45, 0x54, 0x10, | ||||||
| 	0x08, 0x12, 0x08, 0x0a, 0x04, 0x45, 0x59, 0x45, 0x53, 0x10, 0x09, 0x12, 0x11, 0x0a, 0x0d, 0x54, | 	0x08, 0x12, 0x08, 0x0a, 0x04, 0x45, 0x59, 0x45, 0x53, 0x10, 0x09, 0x12, 0x11, 0x0a, 0x0d, 0x54, | ||||||
| 	0x48, 0x49, 0x4e, 0x4b, 0x49, 0x4e, 0x47, 0x5f, 0x46, 0x41, 0x43, 0x45, 0x10, 0x0a, 0x12, 0x0e, | 	0x48, 0x49, 0x4e, 0x4b, 0x49, 0x4e, 0x47, 0x5f, 0x46, 0x41, 0x43, 0x45, 0x10, 0x0a, 0x12, 0x0e, | ||||||
| 	0x0a, 0x0a, 0x43, 0x4c, 0x4f, 0x57, 0x4e, 0x5f, 0x46, 0x41, 0x43, 0x45, 0x10, 0x0b, 0x42, 0xac, | 	0x0a, 0x0a, 0x43, 0x4c, 0x4f, 0x57, 0x4e, 0x5f, 0x46, 0x41, 0x43, 0x45, 0x10, 0x0b, 0x12, 0x11, | ||||||
| 	0x01, 0x0a, 0x10, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, | 	0x0a, 0x0d, 0x51, 0x55, 0x45, 0x53, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x4d, 0x41, 0x52, 0x4b, 0x10, | ||||||
| 	0x2e, 0x76, 0x32, 0x42, 0x14, 0x52, 0x65, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x72, | 	0x0c, 0x42, 0xac, 0x01, 0x0a, 0x10, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, | ||||||
| 	0x76, 0x69, 0x63, 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x30, 0x67, 0x69, 0x74, | 	0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x42, 0x14, 0x52, 0x65, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, | ||||||
| 	0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x75, 0x73, 0x65, 0x6d, 0x65, 0x6d, 0x6f, 0x73, | 	0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x30, | ||||||
| 	0x2f, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x67, 0x65, 0x6e, | 	0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x75, 0x73, 0x65, 0x6d, 0x65, | ||||||
| 	0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x32, 0x3b, 0x61, 0x70, 0x69, 0x76, 0x32, 0xa2, 0x02, 0x03, | 	0x6d, 0x6f, 0x73, 0x2f, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, | ||||||
| 	0x4d, 0x41, 0x58, 0xaa, 0x02, 0x0c, 0x4d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x41, 0x70, 0x69, 0x2e, | 	0x67, 0x65, 0x6e, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x32, 0x3b, 0x61, 0x70, 0x69, 0x76, 0x32, | ||||||
| 	0x56, 0x32, 0xca, 0x02, 0x0c, 0x4d, 0x65, 0x6d, 0x6f, 0x73, 0x5c, 0x41, 0x70, 0x69, 0x5c, 0x56, | 	0xa2, 0x02, 0x03, 0x4d, 0x41, 0x58, 0xaa, 0x02, 0x0c, 0x4d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x41, | ||||||
| 	0x32, 0xe2, 0x02, 0x18, 0x4d, 0x65, 0x6d, 0x6f, 0x73, 0x5c, 0x41, 0x70, 0x69, 0x5c, 0x56, 0x32, | 	0x70, 0x69, 0x2e, 0x56, 0x32, 0xca, 0x02, 0x0c, 0x4d, 0x65, 0x6d, 0x6f, 0x73, 0x5c, 0x41, 0x70, | ||||||
| 	0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x0e, 0x4d, | 	0x69, 0x5c, 0x56, 0x32, 0xe2, 0x02, 0x18, 0x4d, 0x65, 0x6d, 0x6f, 0x73, 0x5c, 0x41, 0x70, 0x69, | ||||||
| 	0x65, 0x6d, 0x6f, 0x73, 0x3a, 0x3a, 0x41, 0x70, 0x69, 0x3a, 0x3a, 0x56, 0x32, 0x62, 0x06, 0x70, | 	0x5c, 0x56, 0x32, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, | ||||||
| 	0x72, 0x6f, 0x74, 0x6f, 0x33, | 	0x02, 0x0e, 0x4d, 0x65, 0x6d, 0x6f, 0x73, 0x3a, 0x3a, 0x41, 0x70, 0x69, 0x3a, 0x3a, 0x56, 0x32, | ||||||
|  | 	0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, | ||||||
| } | } | ||||||
|  |  | ||||||
| var ( | var ( | ||||||
|   | |||||||
| @@ -224,6 +224,7 @@ | |||||||
| | EYES | 9 |  | | | EYES | 9 |  | | ||||||
| | THINKING_FACE | 10 |  | | | THINKING_FACE | 10 |  | | ||||||
| | CLOWN_FACE | 11 |  | | | CLOWN_FACE | 11 |  | | ||||||
|  | | QUESTION_MARK | 12 |  | | ||||||
|  |  | ||||||
|  |  | ||||||
|   |   | ||||||
|   | |||||||
| @@ -35,6 +35,7 @@ const ( | |||||||
| 	Reaction_EYES             Reaction_Type = 9 | 	Reaction_EYES             Reaction_Type = 9 | ||||||
| 	Reaction_THINKING_FACE    Reaction_Type = 10 | 	Reaction_THINKING_FACE    Reaction_Type = 10 | ||||||
| 	Reaction_CLOWN_FACE       Reaction_Type = 11 | 	Reaction_CLOWN_FACE       Reaction_Type = 11 | ||||||
|  | 	Reaction_QUESTION_MARK    Reaction_Type = 12 | ||||||
| ) | ) | ||||||
|  |  | ||||||
| // Enum value maps for Reaction_Type. | // Enum value maps for Reaction_Type. | ||||||
| @@ -52,6 +53,7 @@ var ( | |||||||
| 		9:  "EYES", | 		9:  "EYES", | ||||||
| 		10: "THINKING_FACE", | 		10: "THINKING_FACE", | ||||||
| 		11: "CLOWN_FACE", | 		11: "CLOWN_FACE", | ||||||
|  | 		12: "QUESTION_MARK", | ||||||
| 	} | 	} | ||||||
| 	Reaction_Type_value = map[string]int32{ | 	Reaction_Type_value = map[string]int32{ | ||||||
| 		"TYPE_UNSPECIFIED": 0, | 		"TYPE_UNSPECIFIED": 0, | ||||||
| @@ -66,6 +68,7 @@ var ( | |||||||
| 		"EYES":             9, | 		"EYES":             9, | ||||||
| 		"THINKING_FACE":    10, | 		"THINKING_FACE":    10, | ||||||
| 		"CLOWN_FACE":       11, | 		"CLOWN_FACE":       11, | ||||||
|  | 		"QUESTION_MARK":    12, | ||||||
| 	} | 	} | ||||||
| ) | ) | ||||||
|  |  | ||||||
| @@ -182,7 +185,7 @@ var File_store_reaction_proto protoreflect.FileDescriptor | |||||||
| var file_store_reaction_proto_rawDesc = []byte{ | var file_store_reaction_proto_rawDesc = []byte{ | ||||||
| 	0x0a, 0x14, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x2f, 0x72, 0x65, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, | 	0x0a, 0x14, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x2f, 0x72, 0x65, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, | ||||||
| 	0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0b, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x73, 0x74, | 	0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0b, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x73, 0x74, | ||||||
| 	0x6f, 0x72, 0x65, 0x22, 0xf1, 0x02, 0x0a, 0x08, 0x52, 0x65, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, | 	0x6f, 0x72, 0x65, 0x22, 0x84, 0x03, 0x0a, 0x08, 0x52, 0x65, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, | ||||||
| 	0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x02, 0x69, 0x64, | 	0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x02, 0x69, 0x64, | ||||||
| 	0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x74, 0x73, 0x18, 0x02, | 	0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x74, 0x73, 0x18, 0x02, | ||||||
| 	0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x54, 0x73, 0x12, | 	0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x54, 0x73, 0x12, | ||||||
| @@ -193,7 +196,7 @@ var file_store_reaction_proto_rawDesc = []byte{ | |||||||
| 	0x0d, 0x72, 0x65, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x05, | 	0x0d, 0x72, 0x65, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x05, | ||||||
| 	0x20, 0x01, 0x28, 0x0e, 0x32, 0x1a, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x73, 0x74, 0x6f, | 	0x20, 0x01, 0x28, 0x0e, 0x32, 0x1a, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x73, 0x74, 0x6f, | ||||||
| 	0x72, 0x65, 0x2e, 0x52, 0x65, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x54, 0x79, 0x70, 0x65, | 	0x72, 0x65, 0x2e, 0x52, 0x65, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x54, 0x79, 0x70, 0x65, | ||||||
| 	0x52, 0x0c, 0x72, 0x65, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x22, 0xb6, | 	0x52, 0x0c, 0x72, 0x65, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x22, 0xc9, | ||||||
| 	0x01, 0x0a, 0x04, 0x54, 0x79, 0x70, 0x65, 0x12, 0x14, 0x0a, 0x10, 0x54, 0x59, 0x50, 0x45, 0x5f, | 	0x01, 0x0a, 0x04, 0x54, 0x79, 0x70, 0x65, 0x12, 0x14, 0x0a, 0x10, 0x54, 0x59, 0x50, 0x45, 0x5f, | ||||||
| 	0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0d, 0x0a, | 	0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0d, 0x0a, | ||||||
| 	0x09, 0x54, 0x48, 0x55, 0x4d, 0x42, 0x53, 0x5f, 0x55, 0x50, 0x10, 0x01, 0x12, 0x0f, 0x0a, 0x0b, | 	0x09, 0x54, 0x48, 0x55, 0x4d, 0x42, 0x53, 0x5f, 0x55, 0x50, 0x10, 0x01, 0x12, 0x0f, 0x0a, 0x0b, | ||||||
| @@ -205,17 +208,18 @@ var file_store_reaction_proto_rawDesc = []byte{ | |||||||
| 	0x0a, 0x06, 0x52, 0x4f, 0x43, 0x4b, 0x45, 0x54, 0x10, 0x08, 0x12, 0x08, 0x0a, 0x04, 0x45, 0x59, | 	0x0a, 0x06, 0x52, 0x4f, 0x43, 0x4b, 0x45, 0x54, 0x10, 0x08, 0x12, 0x08, 0x0a, 0x04, 0x45, 0x59, | ||||||
| 	0x45, 0x53, 0x10, 0x09, 0x12, 0x11, 0x0a, 0x0d, 0x54, 0x48, 0x49, 0x4e, 0x4b, 0x49, 0x4e, 0x47, | 	0x45, 0x53, 0x10, 0x09, 0x12, 0x11, 0x0a, 0x0d, 0x54, 0x48, 0x49, 0x4e, 0x4b, 0x49, 0x4e, 0x47, | ||||||
| 	0x5f, 0x46, 0x41, 0x43, 0x45, 0x10, 0x0a, 0x12, 0x0e, 0x0a, 0x0a, 0x43, 0x4c, 0x4f, 0x57, 0x4e, | 	0x5f, 0x46, 0x41, 0x43, 0x45, 0x10, 0x0a, 0x12, 0x0e, 0x0a, 0x0a, 0x43, 0x4c, 0x4f, 0x57, 0x4e, | ||||||
| 	0x5f, 0x46, 0x41, 0x43, 0x45, 0x10, 0x0b, 0x42, 0x98, 0x01, 0x0a, 0x0f, 0x63, 0x6f, 0x6d, 0x2e, | 	0x5f, 0x46, 0x41, 0x43, 0x45, 0x10, 0x0b, 0x12, 0x11, 0x0a, 0x0d, 0x51, 0x55, 0x45, 0x53, 0x54, | ||||||
| 	0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x42, 0x0d, 0x52, 0x65, 0x61, | 	0x49, 0x4f, 0x4e, 0x5f, 0x4d, 0x41, 0x52, 0x4b, 0x10, 0x0c, 0x42, 0x98, 0x01, 0x0a, 0x0f, 0x63, | ||||||
| 	0x63, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x29, 0x67, 0x69, | 	0x6f, 0x6d, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x42, 0x0d, | ||||||
| 	0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x75, 0x73, 0x65, 0x6d, 0x65, 0x6d, 0x6f, | 	0x52, 0x65, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, | ||||||
| 	0x73, 0x2f, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x67, 0x65, | 	0x29, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x75, 0x73, 0x65, 0x6d, | ||||||
| 	0x6e, 0x2f, 0x73, 0x74, 0x6f, 0x72, 0x65, 0xa2, 0x02, 0x03, 0x4d, 0x53, 0x58, 0xaa, 0x02, 0x0b, | 	0x65, 0x6d, 0x6f, 0x73, 0x2f, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, | ||||||
| 	0x4d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x53, 0x74, 0x6f, 0x72, 0x65, 0xca, 0x02, 0x0b, 0x4d, 0x65, | 	0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x73, 0x74, 0x6f, 0x72, 0x65, 0xa2, 0x02, 0x03, 0x4d, 0x53, 0x58, | ||||||
| 	0x6d, 0x6f, 0x73, 0x5c, 0x53, 0x74, 0x6f, 0x72, 0x65, 0xe2, 0x02, 0x17, 0x4d, 0x65, 0x6d, 0x6f, | 	0xaa, 0x02, 0x0b, 0x4d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x53, 0x74, 0x6f, 0x72, 0x65, 0xca, 0x02, | ||||||
| 	0x73, 0x5c, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, | 	0x0b, 0x4d, 0x65, 0x6d, 0x6f, 0x73, 0x5c, 0x53, 0x74, 0x6f, 0x72, 0x65, 0xe2, 0x02, 0x17, 0x4d, | ||||||
| 	0x61, 0x74, 0x61, 0xea, 0x02, 0x0c, 0x4d, 0x65, 0x6d, 0x6f, 0x73, 0x3a, 0x3a, 0x53, 0x74, 0x6f, | 	0x65, 0x6d, 0x6f, 0x73, 0x5c, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, | ||||||
| 	0x72, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, | 	0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x0c, 0x4d, 0x65, 0x6d, 0x6f, 0x73, 0x3a, 0x3a, | ||||||
|  | 	0x53, 0x74, 0x6f, 0x72, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, | ||||||
| } | } | ||||||
|  |  | ||||||
| var ( | var ( | ||||||
|   | |||||||
| @@ -28,6 +28,7 @@ message Reaction { | |||||||
|     EYES = 9; |     EYES = 9; | ||||||
|     THINKING_FACE = 10; |     THINKING_FACE = 10; | ||||||
|     CLOWN_FACE = 11; |     CLOWN_FACE = 11; | ||||||
|  |     QUESTION_MARK = 12; | ||||||
|   } |   } | ||||||
|   Type reaction_type = 5; |   Type reaction_type = 5; | ||||||
| } | } | ||||||
|   | |||||||
| @@ -9,10 +9,10 @@ import ( | |||||||
|  |  | ||||||
| // Version is the service current released version. | // Version is the service current released version. | ||||||
| // Semantic versioning: https://semver.org/ | // Semantic versioning: https://semver.org/ | ||||||
| var Version = "0.19.1" | var Version = "0.20.0" | ||||||
|  |  | ||||||
| // DevVersion is the service current development version. | // DevVersion is the service current development version. | ||||||
| var DevVersion = "0.19.1" | var DevVersion = "0.20.0" | ||||||
|  |  | ||||||
| func GetCurrentVersion(mode string) string { | func GetCurrentVersion(mode string) string { | ||||||
| 	if mode == "dev" || mode == "demo" { | 	if mode == "dev" || mode == "demo" { | ||||||
|   | |||||||
| @@ -131,3 +131,13 @@ CREATE TABLE `webhook` ( | |||||||
|   `name` TEXT NOT NULL, |   `name` TEXT NOT NULL, | ||||||
|   `url` TEXT NOT NULL |   `url` TEXT NOT NULL | ||||||
| ); | ); | ||||||
|  |  | ||||||
|  | -- reaction | ||||||
|  | CREATE TABLE `reaction` ( | ||||||
|  |   `id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY, | ||||||
|  |   `created_ts` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, | ||||||
|  |   `creator_id` INT NOT NULL, | ||||||
|  |   `content_id` VARCHAR(256) NOT NULL, | ||||||
|  |   `reaction_type` VARCHAR(256) NOT NULL, | ||||||
|  |   UNIQUE(`creator_id`,`content_id`,`reaction_type`)   | ||||||
|  | ); | ||||||
|   | |||||||
							
								
								
									
										9
									
								
								store/db/mysql/migration/prod/0.20/00__reaction.sql
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								store/db/mysql/migration/prod/0.20/00__reaction.sql
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,9 @@ | |||||||
|  | -- reaction | ||||||
|  | CREATE TABLE `reaction` ( | ||||||
|  |   `id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY, | ||||||
|  |   `created_ts` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, | ||||||
|  |   `creator_id` INT NOT NULL, | ||||||
|  |   `content_id` VARCHAR(256) NOT NULL, | ||||||
|  |   `reaction_type` VARCHAR(256) NOT NULL, | ||||||
|  |   UNIQUE(`creator_id`,`content_id`,`reaction_type`)   | ||||||
|  | ); | ||||||
| @@ -131,3 +131,13 @@ CREATE TABLE `webhook` ( | |||||||
|   `name` TEXT NOT NULL, |   `name` TEXT NOT NULL, | ||||||
|   `url` TEXT NOT NULL |   `url` TEXT NOT NULL | ||||||
| ); | ); | ||||||
|  |  | ||||||
|  | -- reaction | ||||||
|  | CREATE TABLE `reaction` ( | ||||||
|  |   `id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY, | ||||||
|  |   `created_ts` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, | ||||||
|  |   `creator_id` INT NOT NULL, | ||||||
|  |   `content_id` VARCHAR(256) NOT NULL, | ||||||
|  |   `reaction_type` VARCHAR(256) NOT NULL, | ||||||
|  |   UNIQUE(`creator_id`,`content_id`,`reaction_type`)   | ||||||
|  | ); | ||||||
|   | |||||||
| @@ -4,6 +4,7 @@ import ( | |||||||
| 	"context" | 	"context" | ||||||
| 	"strings" | 	"strings" | ||||||
|  |  | ||||||
|  | 	"github.com/pkg/errors" | ||||||
| 	storepb "github.com/usememos/memos/proto/gen/store" | 	storepb "github.com/usememos/memos/proto/gen/store" | ||||||
| 	"github.com/usememos/memos/store" | 	"github.com/usememos/memos/store" | ||||||
| ) | ) | ||||||
| @@ -12,15 +13,24 @@ func (d *DB) UpsertReaction(ctx context.Context, upsert *storepb.Reaction) (*sto | |||||||
| 	fields := []string{"`creator_id`", "`content_id`", "`reaction_type`"} | 	fields := []string{"`creator_id`", "`content_id`", "`reaction_type`"} | ||||||
| 	placeholder := []string{"?", "?", "?"} | 	placeholder := []string{"?", "?", "?"} | ||||||
| 	args := []interface{}{upsert.CreatorId, upsert.ContentId, upsert.ReactionType.String()} | 	args := []interface{}{upsert.CreatorId, upsert.ContentId, upsert.ReactionType.String()} | ||||||
| 	stmt := "INSERT INTO `reaction` (" + strings.Join(fields, ", ") + ") VALUES (" + strings.Join(placeholder, ", ") + ") RETURNING `id`, `created_ts`" | 	stmt := "INSERT INTO `reaction` (" + strings.Join(fields, ", ") + ") VALUES (" + strings.Join(placeholder, ", ") + ")" | ||||||
| 	if err := d.db.QueryRowContext(ctx, stmt, args...).Scan( | 	result, err := d.db.ExecContext(ctx, stmt, args...) | ||||||
| 		&upsert.Id, | 	if err != nil { | ||||||
| 		&upsert.CreatedTs, |  | ||||||
| 	); err != nil { |  | ||||||
| 		return nil, err | 		return nil, err | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	reaction := upsert | 	rawID, err := result.LastInsertId() | ||||||
|  | 	if err != nil { | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  | 	id := int32(rawID) | ||||||
|  | 	reaction, err := d.GetReaction(ctx, &store.FindReaction{ID: &id}) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  | 	if reaction == nil { | ||||||
|  | 		return nil, errors.Errorf("failed to create reaction") | ||||||
|  | 	} | ||||||
| 	return reaction, nil | 	return reaction, nil | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -39,7 +49,7 @@ func (d *DB) ListReactions(ctx context.Context, find *store.FindReaction) ([]*st | |||||||
| 	rows, err := d.db.QueryContext(ctx, ` | 	rows, err := d.db.QueryContext(ctx, ` | ||||||
| 		SELECT | 		SELECT | ||||||
| 			id, | 			id, | ||||||
| 			created_ts, | 			UNIX_TIMESTAMP(created_ts) AS created_ts, | ||||||
| 			creator_id, | 			creator_id, | ||||||
| 			content_id, | 			content_id, | ||||||
| 			reaction_type | 			reaction_type | ||||||
| @@ -77,6 +87,19 @@ func (d *DB) ListReactions(ctx context.Context, find *store.FindReaction) ([]*st | |||||||
| 	return list, nil | 	return list, nil | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func (d *DB) GetReaction(ctx context.Context, find *store.FindReaction) (*storepb.Reaction, error) { | ||||||
|  | 	list, err := d.ListReactions(ctx, find) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  | 	if len(list) == 0 { | ||||||
|  | 		return nil, nil | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	reaction := list[0] | ||||||
|  | 	return reaction, nil | ||||||
|  | } | ||||||
|  |  | ||||||
| func (d *DB) DeleteReaction(ctx context.Context, delete *store.DeleteReaction) error { | func (d *DB) DeleteReaction(ctx context.Context, delete *store.DeleteReaction) error { | ||||||
| 	_, err := d.db.ExecContext(ctx, "DELETE FROM `reaction` WHERE `id` = ?", delete.ID) | 	_, err := d.db.ExecContext(ctx, "DELETE FROM `reaction` WHERE `id` = ?", delete.ID) | ||||||
| 	return err | 	return err | ||||||
|   | |||||||
| @@ -131,3 +131,13 @@ CREATE TABLE webhook ( | |||||||
|   name TEXT NOT NULL, |   name TEXT NOT NULL, | ||||||
|   url TEXT NOT NULL |   url TEXT NOT NULL | ||||||
| ); | ); | ||||||
|  |  | ||||||
|  | -- reaction | ||||||
|  | CREATE TABLE reaction ( | ||||||
|  |   id SERIAL PRIMARY KEY, | ||||||
|  |   created_ts BIGINT NOT NULL DEFAULT EXTRACT(EPOCH FROM NOW()), | ||||||
|  |   creator_id INTEGER NOT NULL, | ||||||
|  |   content_id TEXT NOT NULL, | ||||||
|  |   reaction_type TEXT NOT NULL, | ||||||
|  |   UNIQUE(creator_id, content_id, reaction_type) | ||||||
|  | ); | ||||||
|   | |||||||
							
								
								
									
										9
									
								
								store/db/postgres/migration/prod/0.20/00_reaction.sql
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								store/db/postgres/migration/prod/0.20/00_reaction.sql
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,9 @@ | |||||||
|  | -- reaction | ||||||
|  | CREATE TABLE reaction ( | ||||||
|  |   id SERIAL PRIMARY KEY, | ||||||
|  |   created_ts BIGINT NOT NULL DEFAULT EXTRACT(EPOCH FROM NOW()), | ||||||
|  |   creator_id INTEGER NOT NULL, | ||||||
|  |   content_id TEXT NOT NULL, | ||||||
|  |   reaction_type TEXT NOT NULL, | ||||||
|  |   UNIQUE(creator_id, content_id, reaction_type) | ||||||
|  | ); | ||||||
| @@ -131,3 +131,13 @@ CREATE TABLE webhook ( | |||||||
|   name TEXT NOT NULL, |   name TEXT NOT NULL, | ||||||
|   url TEXT NOT NULL |   url TEXT NOT NULL | ||||||
| ); | ); | ||||||
|  |  | ||||||
|  | -- reaction | ||||||
|  | CREATE TABLE reaction ( | ||||||
|  |   id SERIAL PRIMARY KEY, | ||||||
|  |   created_ts BIGINT NOT NULL DEFAULT EXTRACT(EPOCH FROM NOW()), | ||||||
|  |   creator_id INTEGER NOT NULL, | ||||||
|  |   content_id TEXT NOT NULL, | ||||||
|  |   reaction_type TEXT NOT NULL, | ||||||
|  |   UNIQUE(creator_id, content_id, reaction_type) | ||||||
|  | ); | ||||||
|   | |||||||
| @@ -145,6 +145,7 @@ CREATE TABLE webhook ( | |||||||
|  |  | ||||||
| CREATE INDEX idx_webhook_creator_id ON webhook (creator_id); | CREATE INDEX idx_webhook_creator_id ON webhook (creator_id); | ||||||
|  |  | ||||||
|  | -- reaction | ||||||
| CREATE TABLE reaction ( | CREATE TABLE reaction ( | ||||||
|   id INTEGER PRIMARY KEY AUTOINCREMENT, |   id INTEGER PRIMARY KEY AUTOINCREMENT, | ||||||
|   created_ts BIGINT NOT NULL DEFAULT (strftime('%s', 'now')), |   created_ts BIGINT NOT NULL DEFAULT (strftime('%s', 'now')), | ||||||
|   | |||||||
							
								
								
									
										9
									
								
								store/db/sqlite/migration/prod/0.20/00__reaction.sql
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								store/db/sqlite/migration/prod/0.20/00__reaction.sql
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,9 @@ | |||||||
|  | -- reaction | ||||||
|  | CREATE TABLE reaction ( | ||||||
|  |   id INTEGER PRIMARY KEY AUTOINCREMENT, | ||||||
|  |   created_ts BIGINT NOT NULL DEFAULT (strftime('%s', 'now')), | ||||||
|  |   creator_id INTEGER NOT NULL, | ||||||
|  |   content_id TEXT NOT NULL, | ||||||
|  |   reaction_type TEXT NOT NULL, | ||||||
|  |   UNIQUE(creator_id, content_id, reaction_type) | ||||||
|  | ); | ||||||
| @@ -144,3 +144,13 @@ CREATE TABLE webhook ( | |||||||
| ); | ); | ||||||
|  |  | ||||||
| CREATE INDEX idx_webhook_creator_id ON webhook (creator_id); | CREATE INDEX idx_webhook_creator_id ON webhook (creator_id); | ||||||
|  |  | ||||||
|  | -- reaction | ||||||
|  | CREATE TABLE reaction ( | ||||||
|  |   id INTEGER PRIMARY KEY AUTOINCREMENT, | ||||||
|  |   created_ts BIGINT NOT NULL DEFAULT (strftime('%s', 'now')), | ||||||
|  |   creator_id INTEGER NOT NULL, | ||||||
|  |   content_id TEXT NOT NULL, | ||||||
|  |   reaction_type TEXT NOT NULL, | ||||||
|  |   UNIQUE(creator_id, content_id, reaction_type) | ||||||
|  | ); | ||||||
|   | |||||||
| @@ -45,7 +45,8 @@ func resetTestingDB(ctx context.Context, profile *profile.Profile, dbDriver stor | |||||||
| 		DROP TABLE IF EXISTS storage; | 		DROP TABLE IF EXISTS storage; | ||||||
| 		DROP TABLE IF EXISTS idp; | 		DROP TABLE IF EXISTS idp; | ||||||
| 		DROP TABLE IF EXISTS inbox; | 		DROP TABLE IF EXISTS inbox; | ||||||
| 		DROP TABLE IF EXISTS webhook;`) | 		DROP TABLE IF EXISTS webhook; | ||||||
|  | 		DROP TABLE IF EXISTS reaction;`) | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			fmt.Printf("failed to reset testing db, error: %+v\n", err) | 			fmt.Printf("failed to reset testing db, error: %+v\n", err) | ||||||
| 			panic(err) | 			panic(err) | ||||||
| @@ -65,7 +66,8 @@ func resetTestingDB(ctx context.Context, profile *profile.Profile, dbDriver stor | |||||||
| 		DROP TABLE IF EXISTS storage CASCADE; | 		DROP TABLE IF EXISTS storage CASCADE; | ||||||
| 		DROP TABLE IF EXISTS idp CASCADE; | 		DROP TABLE IF EXISTS idp CASCADE; | ||||||
| 		DROP TABLE IF EXISTS inbox CASCADE; | 		DROP TABLE IF EXISTS inbox CASCADE; | ||||||
| 		DROP TABLE IF EXISTS webhook CASCADE;`) | 		DROP TABLE IF EXISTS webhook CASCADE; | ||||||
|  | 		DROP TABLE IF EXISTS reaction CASCADE;`) | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			fmt.Printf("failed to reset testing db, error: %+v\n", err) | 			fmt.Printf("failed to reset testing db, error: %+v\n", err) | ||||||
| 			panic(err) | 			panic(err) | ||||||
|   | |||||||
| @@ -116,7 +116,7 @@ const MemoActionMenu = (props: Props) => { | |||||||
|         </MenuItem> |         </MenuItem> | ||||||
|         <Divider className="!my-1" /> |         <Divider className="!my-1" /> | ||||||
|         <div className="-mt-0.5 pl-2 pr-2 text-xs text-gray-400"> |         <div className="-mt-0.5 pl-2 pr-2 text-xs text-gray-400"> | ||||||
|           <div className="font-mono max-w-20 cursor-pointer truncate" onClick={handleCopyMemoId}> |           <div className="mt-1 font-mono max-w-20 cursor-pointer truncate" onClick={handleCopyMemoId}> | ||||||
|             ID: {memo.name} |             ID: {memo.name} | ||||||
|           </div> |           </div> | ||||||
|         </div> |         </div> | ||||||
|   | |||||||
| @@ -124,18 +124,16 @@ const MemoView: React.FC<Props> = (props: Props) => { | |||||||
|             </> |             </> | ||||||
|           )} |           )} | ||||||
|         </div> |         </div> | ||||||
|         <div className="flex flex-row justify-end items-center"> |         <div className="flex flex-row justify-end items-center select-none"> | ||||||
|           <div className="w-auto hidden group-hover:flex flex-row justify-between items-center gap-1"> |           <div className="w-auto invisible group-hover:visible flex flex-row justify-between items-center"> | ||||||
|             {props.showVisibility && memo.visibility !== Visibility.PRIVATE && ( |             {props.showVisibility && memo.visibility !== Visibility.PRIVATE && ( | ||||||
|               <> |  | ||||||
|               <Tooltip title={t(`memo.visibility.${convertVisibilityToString(memo.visibility).toLowerCase()}` as any)} placement="top"> |               <Tooltip title={t(`memo.visibility.${convertVisibilityToString(memo.visibility).toLowerCase()}` as any)} placement="top"> | ||||||
|                   <span className="h-7 w-7 flex justify-center items-center rounded-full border dark:border-zinc-700 hover:opacity-70"> |                 <span className="h-7 w-7 flex justify-center items-center hover:opacity-70"> | ||||||
|                   <VisibilityIcon visibility={memo.visibility} /> |                   <VisibilityIcon visibility={memo.visibility} /> | ||||||
|                 </span> |                 </span> | ||||||
|               </Tooltip> |               </Tooltip> | ||||||
|               </> |  | ||||||
|             )} |             )} | ||||||
|             {currentUser && memo.reactions.length === 0 && <ReactionSelector memo={memo} />} |             {currentUser && <ReactionSelector className="border-none" memo={memo} />} | ||||||
|           </div> |           </div> | ||||||
|           {!readonly && <MemoActionMenu memo={memo} showPinned={props.showPinned} />} |           {!readonly && <MemoActionMenu memo={memo} showPinned={props.showPinned} />} | ||||||
|         </div> |         </div> | ||||||
|   | |||||||
| @@ -1,8 +1,10 @@ | |||||||
| import { Dropdown, Menu, MenuButton } from "@mui/joy"; | import { Dropdown, Menu, MenuButton } from "@mui/joy"; | ||||||
|  | import classNames from "classnames"; | ||||||
| import { useRef, useState } from "react"; | import { useRef, useState } from "react"; | ||||||
| import useClickAway from "react-use/lib/useClickAway"; | import useClickAway from "react-use/lib/useClickAway"; | ||||||
| import Icon from "@/components/Icon"; | import Icon from "@/components/Icon"; | ||||||
| import { memoServiceClient } from "@/grpcweb"; | import { memoServiceClient } from "@/grpcweb"; | ||||||
|  | import useCurrentUser from "@/hooks/useCurrentUser"; | ||||||
| import { MemoNamePrefix, useMemoStore } from "@/store/v1"; | import { MemoNamePrefix, useMemoStore } from "@/store/v1"; | ||||||
| import { Memo } from "@/types/proto/api/v2/memo_service"; | import { Memo } from "@/types/proto/api/v2/memo_service"; | ||||||
| import { Reaction_Type } from "@/types/proto/api/v2/reaction_service"; | import { Reaction_Type } from "@/types/proto/api/v2/reaction_service"; | ||||||
| @@ -10,6 +12,7 @@ import { stringifyReactionType } from "./ReactionView"; | |||||||
|  |  | ||||||
| interface Props { | interface Props { | ||||||
|   memo: Memo; |   memo: Memo; | ||||||
|  |   className?: string; | ||||||
| } | } | ||||||
|  |  | ||||||
| const REACTION_TYPES = [ | const REACTION_TYPES = [ | ||||||
| @@ -24,10 +27,12 @@ const REACTION_TYPES = [ | |||||||
|   Reaction_Type.EYES, |   Reaction_Type.EYES, | ||||||
|   Reaction_Type.THINKING_FACE, |   Reaction_Type.THINKING_FACE, | ||||||
|   Reaction_Type.CLOWN_FACE, |   Reaction_Type.CLOWN_FACE, | ||||||
|  |   Reaction_Type.QUESTION_MARK, | ||||||
| ]; | ]; | ||||||
|  |  | ||||||
| const ReactionSelector = (props: Props) => { | const ReactionSelector = (props: Props) => { | ||||||
|   const { memo } = props; |   const { memo, className } = props; | ||||||
|  |   const currentUser = useCurrentUser(); | ||||||
|   const memoStore = useMemoStore(); |   const memoStore = useMemoStore(); | ||||||
|   const [open, setOpen] = useState(false); |   const [open, setOpen] = useState(false); | ||||||
|   const containerRef = useRef<HTMLDivElement>(null); |   const containerRef = useRef<HTMLDivElement>(null); | ||||||
| @@ -36,15 +41,28 @@ const ReactionSelector = (props: Props) => { | |||||||
|     setOpen(false); |     setOpen(false); | ||||||
|   }); |   }); | ||||||
|  |  | ||||||
|   const handleReactionClick = async (reaction: Reaction_Type) => { |   const hasReacted = (reactionType: Reaction_Type) => { | ||||||
|  |     return memo.reactions.some((r) => r.reactionType === reactionType && r.creator === currentUser?.name); | ||||||
|  |   }; | ||||||
|  |  | ||||||
|  |   const handleReactionClick = async (reactionType: Reaction_Type) => { | ||||||
|     try { |     try { | ||||||
|  |       if (hasReacted(reactionType)) { | ||||||
|  |         const reactions = memo.reactions.filter( | ||||||
|  |           (reaction) => reaction.reactionType === reactionType && reaction.creator === currentUser.name, | ||||||
|  |         ); | ||||||
|  |         for (const reaction of reactions) { | ||||||
|  |           await memoServiceClient.deleteMemoReaction({ id: reaction.id }); | ||||||
|  |         } | ||||||
|  |       } else { | ||||||
|         await memoServiceClient.upsertMemoReaction({ |         await memoServiceClient.upsertMemoReaction({ | ||||||
|           id: memo.id, |           id: memo.id, | ||||||
|           reaction: { |           reaction: { | ||||||
|             contentId: `${MemoNamePrefix}${memo.id}`, |             contentId: `${MemoNamePrefix}${memo.id}`, | ||||||
|           reactionType: reaction, |             reactionType: reactionType, | ||||||
|           }, |           }, | ||||||
|         }); |         }); | ||||||
|  |       } | ||||||
|       await memoStore.getOrFetchMemoById(memo.id, { |       await memoStore.getOrFetchMemoById(memo.id, { | ||||||
|         skipCache: true, |         skipCache: true, | ||||||
|       }); |       }); | ||||||
| @@ -57,7 +75,12 @@ const ReactionSelector = (props: Props) => { | |||||||
|   return ( |   return ( | ||||||
|     <Dropdown open={open} onOpenChange={(_, isOpen) => setOpen(isOpen)}> |     <Dropdown open={open} onOpenChange={(_, isOpen) => setOpen(isOpen)}> | ||||||
|       <MenuButton slots={{ root: "div" }}> |       <MenuButton slots={{ root: "div" }}> | ||||||
|         <span className="h-7 w-7 flex justify-center items-center rounded-full border dark:border-zinc-700 hover:opacity-70"> |         <span | ||||||
|  |           className={classNames( | ||||||
|  |             "h-7 w-7 flex justify-center items-center rounded-full border dark:border-zinc-700 hover:opacity-70", | ||||||
|  |             className, | ||||||
|  |           )} | ||||||
|  |         > | ||||||
|           <Icon.SmilePlus className="w-4 h-4 mx-auto text-gray-500 dark:text-gray-400" /> |           <Icon.SmilePlus className="w-4 h-4 mx-auto text-gray-500 dark:text-gray-400" /> | ||||||
|         </span> |         </span> | ||||||
|       </MenuButton> |       </MenuButton> | ||||||
| @@ -68,7 +91,10 @@ const ReactionSelector = (props: Props) => { | |||||||
|               return ( |               return ( | ||||||
|                 <span |                 <span | ||||||
|                   key={reactionType} |                   key={reactionType} | ||||||
|                   className="inline-flex w-auto cursor-pointer rounded text-lg px-1 text-gray-500 dark:text-gray-400 hover:bg-zinc-100 dark:hover:bg-zinc-800" |                   className={classNames( | ||||||
|  |                     "inline-flex w-auto cursor-pointer rounded text-lg px-1 text-gray-500 dark:text-gray-400 hover:opacity-80", | ||||||
|  |                     hasReacted(reactionType) && "bg-blue-100 dark:bg-zinc-800", | ||||||
|  |                   )} | ||||||
|                   onClick={() => handleReactionClick(reactionType)} |                   onClick={() => handleReactionClick(reactionType)} | ||||||
|                 > |                 > | ||||||
|                   {stringifyReactionType(reactionType)} |                   {stringifyReactionType(reactionType)} | ||||||
|   | |||||||
| @@ -37,6 +37,8 @@ export const stringifyReactionType = (reactionType: Reaction_Type): string => { | |||||||
|       return "🤔"; |       return "🤔"; | ||||||
|     case Reaction_Type.CLOWN_FACE: |     case Reaction_Type.CLOWN_FACE: | ||||||
|       return "🤡"; |       return "🤡"; | ||||||
|  |     case Reaction_Type.QUESTION_MARK: | ||||||
|  |       return "❓"; | ||||||
|     default: |     default: | ||||||
|       return ""; |       return ""; | ||||||
|   } |   } | ||||||
| @@ -57,16 +59,16 @@ const stringifyUsers = (users: User[]): string => { | |||||||
|  |  | ||||||
| const ReactionView = (props: Props) => { | const ReactionView = (props: Props) => { | ||||||
|   const { memo, reactionType, users } = props; |   const { memo, reactionType, users } = props; | ||||||
|   const currenUser = useCurrentUser(); |   const currentUser = useCurrentUser(); | ||||||
|   const memoStore = useMemoStore(); |   const memoStore = useMemoStore(); | ||||||
|   const hasReaction = users.some((user) => currenUser && user.username === currenUser.username); |   const hasReaction = users.some((user) => currentUser && user.username === currentUser.username); | ||||||
|  |  | ||||||
|   const handleReactionClick = async () => { |   const handleReactionClick = async () => { | ||||||
|     if (!currenUser) { |     if (!currentUser) { | ||||||
|       return; |       return; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     const index = users.findIndex((user) => user.username === currenUser.username); |     const index = users.findIndex((user) => user.username === currentUser.username); | ||||||
|     try { |     try { | ||||||
|       if (index === -1) { |       if (index === -1) { | ||||||
|         await memoServiceClient.upsertMemoReaction({ |         await memoServiceClient.upsertMemoReaction({ | ||||||
| @@ -78,7 +80,7 @@ const ReactionView = (props: Props) => { | |||||||
|         }); |         }); | ||||||
|       } else { |       } else { | ||||||
|         const reactions = memo.reactions.filter( |         const reactions = memo.reactions.filter( | ||||||
|           (reaction) => reaction.reactionType === reactionType && reaction.creator === currenUser.name, |           (reaction) => reaction.reactionType === reactionType && reaction.creator === currentUser.name, | ||||||
|         ); |         ); | ||||||
|         for (const reaction of reactions) { |         for (const reaction of reactions) { | ||||||
|           await memoServiceClient.deleteMemoReaction({ id: reaction.id }); |           await memoServiceClient.deleteMemoReaction({ id: reaction.id }); | ||||||
| @@ -95,7 +97,7 @@ const ReactionView = (props: Props) => { | |||||||
|       <div |       <div | ||||||
|         className={classNames( |         className={classNames( | ||||||
|           "h-7 border px-2 py-0.5 rounded-full font-memo flex flex-row justify-center items-center gap-1 dark:border-zinc-700", |           "h-7 border px-2 py-0.5 rounded-full font-memo flex flex-row justify-center items-center gap-1 dark:border-zinc-700", | ||||||
|           currenUser && "cursor-pointer", |           currentUser && "cursor-pointer", | ||||||
|           hasReaction && "bg-blue-100 border-blue-200 dark:bg-zinc-900", |           hasReaction && "bg-blue-100 border-blue-200 dark:bg-zinc-900", | ||||||
|         )} |         )} | ||||||
|         onClick={handleReactionClick} |         onClick={handleReactionClick} | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user