mirror of https://github.com/usememos/memos
refactor: attachment service part2
parent
bb5809cae4
commit
a4920d464b
@ -1,4 +1 @@
|
||||
// Package httpgetter is using to get resources from url.
|
||||
// * Get metadata for website;
|
||||
// * Get image blob to avoid CORS;
|
||||
package httpgetter
|
||||
|
||||
@ -0,0 +1,287 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.36.6
|
||||
// protoc (unknown)
|
||||
// source: store/attachment.proto
|
||||
|
||||
package store
|
||||
|
||||
import (
|
||||
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||
timestamppb "google.golang.org/protobuf/types/known/timestamppb"
|
||||
reflect "reflect"
|
||||
sync "sync"
|
||||
unsafe "unsafe"
|
||||
)
|
||||
|
||||
const (
|
||||
// Verify that this generated code is sufficiently up-to-date.
|
||||
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
|
||||
// Verify that runtime/protoimpl is sufficiently up-to-date.
|
||||
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||
)
|
||||
|
||||
type AttachmentStorageType int32
|
||||
|
||||
const (
|
||||
AttachmentStorageType_ATTACHMENT_STORAGE_TYPE_UNSPECIFIED AttachmentStorageType = 0
|
||||
// Attachment is stored locally. AKA, local file system.
|
||||
AttachmentStorageType_LOCAL AttachmentStorageType = 1
|
||||
// Attachment is stored in S3.
|
||||
AttachmentStorageType_S3 AttachmentStorageType = 2
|
||||
// Attachment is stored in an external storage. The reference is a URL.
|
||||
AttachmentStorageType_EXTERNAL AttachmentStorageType = 3
|
||||
)
|
||||
|
||||
// Enum value maps for AttachmentStorageType.
|
||||
var (
|
||||
AttachmentStorageType_name = map[int32]string{
|
||||
0: "ATTACHMENT_STORAGE_TYPE_UNSPECIFIED",
|
||||
1: "LOCAL",
|
||||
2: "S3",
|
||||
3: "EXTERNAL",
|
||||
}
|
||||
AttachmentStorageType_value = map[string]int32{
|
||||
"ATTACHMENT_STORAGE_TYPE_UNSPECIFIED": 0,
|
||||
"LOCAL": 1,
|
||||
"S3": 2,
|
||||
"EXTERNAL": 3,
|
||||
}
|
||||
)
|
||||
|
||||
func (x AttachmentStorageType) Enum() *AttachmentStorageType {
|
||||
p := new(AttachmentStorageType)
|
||||
*p = x
|
||||
return p
|
||||
}
|
||||
|
||||
func (x AttachmentStorageType) String() string {
|
||||
return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
|
||||
}
|
||||
|
||||
func (AttachmentStorageType) Descriptor() protoreflect.EnumDescriptor {
|
||||
return file_store_attachment_proto_enumTypes[0].Descriptor()
|
||||
}
|
||||
|
||||
func (AttachmentStorageType) Type() protoreflect.EnumType {
|
||||
return &file_store_attachment_proto_enumTypes[0]
|
||||
}
|
||||
|
||||
func (x AttachmentStorageType) Number() protoreflect.EnumNumber {
|
||||
return protoreflect.EnumNumber(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use AttachmentStorageType.Descriptor instead.
|
||||
func (AttachmentStorageType) EnumDescriptor() ([]byte, []int) {
|
||||
return file_store_attachment_proto_rawDescGZIP(), []int{0}
|
||||
}
|
||||
|
||||
type AttachmentPayload struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
// Types that are valid to be assigned to Payload:
|
||||
//
|
||||
// *AttachmentPayload_S3Object_
|
||||
Payload isAttachmentPayload_Payload `protobuf_oneof:"payload"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *AttachmentPayload) Reset() {
|
||||
*x = AttachmentPayload{}
|
||||
mi := &file_store_attachment_proto_msgTypes[0]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *AttachmentPayload) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*AttachmentPayload) ProtoMessage() {}
|
||||
|
||||
func (x *AttachmentPayload) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_store_attachment_proto_msgTypes[0]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use AttachmentPayload.ProtoReflect.Descriptor instead.
|
||||
func (*AttachmentPayload) Descriptor() ([]byte, []int) {
|
||||
return file_store_attachment_proto_rawDescGZIP(), []int{0}
|
||||
}
|
||||
|
||||
func (x *AttachmentPayload) GetPayload() isAttachmentPayload_Payload {
|
||||
if x != nil {
|
||||
return x.Payload
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *AttachmentPayload) GetS3Object() *AttachmentPayload_S3Object {
|
||||
if x != nil {
|
||||
if x, ok := x.Payload.(*AttachmentPayload_S3Object_); ok {
|
||||
return x.S3Object
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type isAttachmentPayload_Payload interface {
|
||||
isAttachmentPayload_Payload()
|
||||
}
|
||||
|
||||
type AttachmentPayload_S3Object_ struct {
|
||||
S3Object *AttachmentPayload_S3Object `protobuf:"bytes,1,opt,name=s3_object,json=s3Object,proto3,oneof"`
|
||||
}
|
||||
|
||||
func (*AttachmentPayload_S3Object_) isAttachmentPayload_Payload() {}
|
||||
|
||||
type AttachmentPayload_S3Object struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
S3Config *StorageS3Config `protobuf:"bytes,1,opt,name=s3_config,json=s3Config,proto3" json:"s3_config,omitempty"`
|
||||
// key is the S3 object key.
|
||||
Key string `protobuf:"bytes,2,opt,name=key,proto3" json:"key,omitempty"`
|
||||
// last_presigned_time is the last time the object was presigned.
|
||||
// This is used to determine if the presigned URL is still valid.
|
||||
LastPresignedTime *timestamppb.Timestamp `protobuf:"bytes,3,opt,name=last_presigned_time,json=lastPresignedTime,proto3" json:"last_presigned_time,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *AttachmentPayload_S3Object) Reset() {
|
||||
*x = AttachmentPayload_S3Object{}
|
||||
mi := &file_store_attachment_proto_msgTypes[1]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *AttachmentPayload_S3Object) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*AttachmentPayload_S3Object) ProtoMessage() {}
|
||||
|
||||
func (x *AttachmentPayload_S3Object) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_store_attachment_proto_msgTypes[1]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use AttachmentPayload_S3Object.ProtoReflect.Descriptor instead.
|
||||
func (*AttachmentPayload_S3Object) Descriptor() ([]byte, []int) {
|
||||
return file_store_attachment_proto_rawDescGZIP(), []int{0, 0}
|
||||
}
|
||||
|
||||
func (x *AttachmentPayload_S3Object) GetS3Config() *StorageS3Config {
|
||||
if x != nil {
|
||||
return x.S3Config
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *AttachmentPayload_S3Object) GetKey() string {
|
||||
if x != nil {
|
||||
return x.Key
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *AttachmentPayload_S3Object) GetLastPresignedTime() *timestamppb.Timestamp {
|
||||
if x != nil {
|
||||
return x.LastPresignedTime
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
var File_store_attachment_proto protoreflect.FileDescriptor
|
||||
|
||||
const file_store_attachment_proto_rawDesc = "" +
|
||||
"\n" +
|
||||
"\x16store/attachment.proto\x12\vmemos.store\x1a\x1fgoogle/protobuf/timestamp.proto\x1a\x1dstore/workspace_setting.proto\"\x8c\x02\n" +
|
||||
"\x11AttachmentPayload\x12F\n" +
|
||||
"\ts3_object\x18\x01 \x01(\v2'.memos.store.AttachmentPayload.S3ObjectH\x00R\bs3Object\x1a\xa3\x01\n" +
|
||||
"\bS3Object\x129\n" +
|
||||
"\ts3_config\x18\x01 \x01(\v2\x1c.memos.store.StorageS3ConfigR\bs3Config\x12\x10\n" +
|
||||
"\x03key\x18\x02 \x01(\tR\x03key\x12J\n" +
|
||||
"\x13last_presigned_time\x18\x03 \x01(\v2\x1a.google.protobuf.TimestampR\x11lastPresignedTimeB\t\n" +
|
||||
"\apayload*a\n" +
|
||||
"\x15AttachmentStorageType\x12'\n" +
|
||||
"#ATTACHMENT_STORAGE_TYPE_UNSPECIFIED\x10\x00\x12\t\n" +
|
||||
"\x05LOCAL\x10\x01\x12\x06\n" +
|
||||
"\x02S3\x10\x02\x12\f\n" +
|
||||
"\bEXTERNAL\x10\x03B\x9a\x01\n" +
|
||||
"\x0fcom.memos.storeB\x0fAttachmentProtoP\x01Z)github.com/usememos/memos/proto/gen/store\xa2\x02\x03MSX\xaa\x02\vMemos.Store\xca\x02\vMemos\\Store\xe2\x02\x17Memos\\Store\\GPBMetadata\xea\x02\fMemos::Storeb\x06proto3"
|
||||
|
||||
var (
|
||||
file_store_attachment_proto_rawDescOnce sync.Once
|
||||
file_store_attachment_proto_rawDescData []byte
|
||||
)
|
||||
|
||||
func file_store_attachment_proto_rawDescGZIP() []byte {
|
||||
file_store_attachment_proto_rawDescOnce.Do(func() {
|
||||
file_store_attachment_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_store_attachment_proto_rawDesc), len(file_store_attachment_proto_rawDesc)))
|
||||
})
|
||||
return file_store_attachment_proto_rawDescData
|
||||
}
|
||||
|
||||
var file_store_attachment_proto_enumTypes = make([]protoimpl.EnumInfo, 1)
|
||||
var file_store_attachment_proto_msgTypes = make([]protoimpl.MessageInfo, 2)
|
||||
var file_store_attachment_proto_goTypes = []any{
|
||||
(AttachmentStorageType)(0), // 0: memos.store.AttachmentStorageType
|
||||
(*AttachmentPayload)(nil), // 1: memos.store.AttachmentPayload
|
||||
(*AttachmentPayload_S3Object)(nil), // 2: memos.store.AttachmentPayload.S3Object
|
||||
(*StorageS3Config)(nil), // 3: memos.store.StorageS3Config
|
||||
(*timestamppb.Timestamp)(nil), // 4: google.protobuf.Timestamp
|
||||
}
|
||||
var file_store_attachment_proto_depIdxs = []int32{
|
||||
2, // 0: memos.store.AttachmentPayload.s3_object:type_name -> memos.store.AttachmentPayload.S3Object
|
||||
3, // 1: memos.store.AttachmentPayload.S3Object.s3_config:type_name -> memos.store.StorageS3Config
|
||||
4, // 2: memos.store.AttachmentPayload.S3Object.last_presigned_time:type_name -> google.protobuf.Timestamp
|
||||
3, // [3:3] is the sub-list for method output_type
|
||||
3, // [3:3] is the sub-list for method input_type
|
||||
3, // [3:3] is the sub-list for extension type_name
|
||||
3, // [3:3] is the sub-list for extension extendee
|
||||
0, // [0:3] is the sub-list for field type_name
|
||||
}
|
||||
|
||||
func init() { file_store_attachment_proto_init() }
|
||||
func file_store_attachment_proto_init() {
|
||||
if File_store_attachment_proto != nil {
|
||||
return
|
||||
}
|
||||
file_store_workspace_setting_proto_init()
|
||||
file_store_attachment_proto_msgTypes[0].OneofWrappers = []any{
|
||||
(*AttachmentPayload_S3Object_)(nil),
|
||||
}
|
||||
type x struct{}
|
||||
out := protoimpl.TypeBuilder{
|
||||
File: protoimpl.DescBuilder{
|
||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||
RawDescriptor: unsafe.Slice(unsafe.StringData(file_store_attachment_proto_rawDesc), len(file_store_attachment_proto_rawDesc)),
|
||||
NumEnums: 1,
|
||||
NumMessages: 2,
|
||||
NumExtensions: 0,
|
||||
NumServices: 0,
|
||||
},
|
||||
GoTypes: file_store_attachment_proto_goTypes,
|
||||
DependencyIndexes: file_store_attachment_proto_depIdxs,
|
||||
EnumInfos: file_store_attachment_proto_enumTypes,
|
||||
MessageInfos: file_store_attachment_proto_msgTypes,
|
||||
}.Build()
|
||||
File_store_attachment_proto = out.File
|
||||
file_store_attachment_proto_goTypes = nil
|
||||
file_store_attachment_proto_depIdxs = nil
|
||||
}
|
||||
@ -1,287 +0,0 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.36.6
|
||||
// protoc (unknown)
|
||||
// source: store/resource.proto
|
||||
|
||||
package store
|
||||
|
||||
import (
|
||||
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||
timestamppb "google.golang.org/protobuf/types/known/timestamppb"
|
||||
reflect "reflect"
|
||||
sync "sync"
|
||||
unsafe "unsafe"
|
||||
)
|
||||
|
||||
const (
|
||||
// Verify that this generated code is sufficiently up-to-date.
|
||||
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
|
||||
// Verify that runtime/protoimpl is sufficiently up-to-date.
|
||||
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||
)
|
||||
|
||||
type ResourceStorageType int32
|
||||
|
||||
const (
|
||||
ResourceStorageType_RESOURCE_STORAGE_TYPE_UNSPECIFIED ResourceStorageType = 0
|
||||
// Resource is stored locally. AKA, local file system.
|
||||
ResourceStorageType_LOCAL ResourceStorageType = 1
|
||||
// Resource is stored in S3.
|
||||
ResourceStorageType_S3 ResourceStorageType = 2
|
||||
// Resource is stored in an external storage. The reference is a URL.
|
||||
ResourceStorageType_EXTERNAL ResourceStorageType = 3
|
||||
)
|
||||
|
||||
// Enum value maps for ResourceStorageType.
|
||||
var (
|
||||
ResourceStorageType_name = map[int32]string{
|
||||
0: "RESOURCE_STORAGE_TYPE_UNSPECIFIED",
|
||||
1: "LOCAL",
|
||||
2: "S3",
|
||||
3: "EXTERNAL",
|
||||
}
|
||||
ResourceStorageType_value = map[string]int32{
|
||||
"RESOURCE_STORAGE_TYPE_UNSPECIFIED": 0,
|
||||
"LOCAL": 1,
|
||||
"S3": 2,
|
||||
"EXTERNAL": 3,
|
||||
}
|
||||
)
|
||||
|
||||
func (x ResourceStorageType) Enum() *ResourceStorageType {
|
||||
p := new(ResourceStorageType)
|
||||
*p = x
|
||||
return p
|
||||
}
|
||||
|
||||
func (x ResourceStorageType) String() string {
|
||||
return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
|
||||
}
|
||||
|
||||
func (ResourceStorageType) Descriptor() protoreflect.EnumDescriptor {
|
||||
return file_store_resource_proto_enumTypes[0].Descriptor()
|
||||
}
|
||||
|
||||
func (ResourceStorageType) Type() protoreflect.EnumType {
|
||||
return &file_store_resource_proto_enumTypes[0]
|
||||
}
|
||||
|
||||
func (x ResourceStorageType) Number() protoreflect.EnumNumber {
|
||||
return protoreflect.EnumNumber(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use ResourceStorageType.Descriptor instead.
|
||||
func (ResourceStorageType) EnumDescriptor() ([]byte, []int) {
|
||||
return file_store_resource_proto_rawDescGZIP(), []int{0}
|
||||
}
|
||||
|
||||
type ResourcePayload struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
// Types that are valid to be assigned to Payload:
|
||||
//
|
||||
// *ResourcePayload_S3Object_
|
||||
Payload isResourcePayload_Payload `protobuf_oneof:"payload"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *ResourcePayload) Reset() {
|
||||
*x = ResourcePayload{}
|
||||
mi := &file_store_resource_proto_msgTypes[0]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *ResourcePayload) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*ResourcePayload) ProtoMessage() {}
|
||||
|
||||
func (x *ResourcePayload) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_store_resource_proto_msgTypes[0]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use ResourcePayload.ProtoReflect.Descriptor instead.
|
||||
func (*ResourcePayload) Descriptor() ([]byte, []int) {
|
||||
return file_store_resource_proto_rawDescGZIP(), []int{0}
|
||||
}
|
||||
|
||||
func (x *ResourcePayload) GetPayload() isResourcePayload_Payload {
|
||||
if x != nil {
|
||||
return x.Payload
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *ResourcePayload) GetS3Object() *ResourcePayload_S3Object {
|
||||
if x != nil {
|
||||
if x, ok := x.Payload.(*ResourcePayload_S3Object_); ok {
|
||||
return x.S3Object
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type isResourcePayload_Payload interface {
|
||||
isResourcePayload_Payload()
|
||||
}
|
||||
|
||||
type ResourcePayload_S3Object_ struct {
|
||||
S3Object *ResourcePayload_S3Object `protobuf:"bytes,1,opt,name=s3_object,json=s3Object,proto3,oneof"`
|
||||
}
|
||||
|
||||
func (*ResourcePayload_S3Object_) isResourcePayload_Payload() {}
|
||||
|
||||
type ResourcePayload_S3Object struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
S3Config *StorageS3Config `protobuf:"bytes,1,opt,name=s3_config,json=s3Config,proto3" json:"s3_config,omitempty"`
|
||||
// key is the S3 object key.
|
||||
Key string `protobuf:"bytes,2,opt,name=key,proto3" json:"key,omitempty"`
|
||||
// last_presigned_time is the last time the object was presigned.
|
||||
// This is used to determine if the presigned URL is still valid.
|
||||
LastPresignedTime *timestamppb.Timestamp `protobuf:"bytes,3,opt,name=last_presigned_time,json=lastPresignedTime,proto3" json:"last_presigned_time,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *ResourcePayload_S3Object) Reset() {
|
||||
*x = ResourcePayload_S3Object{}
|
||||
mi := &file_store_resource_proto_msgTypes[1]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *ResourcePayload_S3Object) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*ResourcePayload_S3Object) ProtoMessage() {}
|
||||
|
||||
func (x *ResourcePayload_S3Object) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_store_resource_proto_msgTypes[1]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use ResourcePayload_S3Object.ProtoReflect.Descriptor instead.
|
||||
func (*ResourcePayload_S3Object) Descriptor() ([]byte, []int) {
|
||||
return file_store_resource_proto_rawDescGZIP(), []int{0, 0}
|
||||
}
|
||||
|
||||
func (x *ResourcePayload_S3Object) GetS3Config() *StorageS3Config {
|
||||
if x != nil {
|
||||
return x.S3Config
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *ResourcePayload_S3Object) GetKey() string {
|
||||
if x != nil {
|
||||
return x.Key
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *ResourcePayload_S3Object) GetLastPresignedTime() *timestamppb.Timestamp {
|
||||
if x != nil {
|
||||
return x.LastPresignedTime
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
var File_store_resource_proto protoreflect.FileDescriptor
|
||||
|
||||
const file_store_resource_proto_rawDesc = "" +
|
||||
"\n" +
|
||||
"\x14store/resource.proto\x12\vmemos.store\x1a\x1fgoogle/protobuf/timestamp.proto\x1a\x1dstore/workspace_setting.proto\"\x88\x02\n" +
|
||||
"\x0fResourcePayload\x12D\n" +
|
||||
"\ts3_object\x18\x01 \x01(\v2%.memos.store.ResourcePayload.S3ObjectH\x00R\bs3Object\x1a\xa3\x01\n" +
|
||||
"\bS3Object\x129\n" +
|
||||
"\ts3_config\x18\x01 \x01(\v2\x1c.memos.store.StorageS3ConfigR\bs3Config\x12\x10\n" +
|
||||
"\x03key\x18\x02 \x01(\tR\x03key\x12J\n" +
|
||||
"\x13last_presigned_time\x18\x03 \x01(\v2\x1a.google.protobuf.TimestampR\x11lastPresignedTimeB\t\n" +
|
||||
"\apayload*]\n" +
|
||||
"\x13ResourceStorageType\x12%\n" +
|
||||
"!RESOURCE_STORAGE_TYPE_UNSPECIFIED\x10\x00\x12\t\n" +
|
||||
"\x05LOCAL\x10\x01\x12\x06\n" +
|
||||
"\x02S3\x10\x02\x12\f\n" +
|
||||
"\bEXTERNAL\x10\x03B\x98\x01\n" +
|
||||
"\x0fcom.memos.storeB\rResourceProtoP\x01Z)github.com/usememos/memos/proto/gen/store\xa2\x02\x03MSX\xaa\x02\vMemos.Store\xca\x02\vMemos\\Store\xe2\x02\x17Memos\\Store\\GPBMetadata\xea\x02\fMemos::Storeb\x06proto3"
|
||||
|
||||
var (
|
||||
file_store_resource_proto_rawDescOnce sync.Once
|
||||
file_store_resource_proto_rawDescData []byte
|
||||
)
|
||||
|
||||
func file_store_resource_proto_rawDescGZIP() []byte {
|
||||
file_store_resource_proto_rawDescOnce.Do(func() {
|
||||
file_store_resource_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_store_resource_proto_rawDesc), len(file_store_resource_proto_rawDesc)))
|
||||
})
|
||||
return file_store_resource_proto_rawDescData
|
||||
}
|
||||
|
||||
var file_store_resource_proto_enumTypes = make([]protoimpl.EnumInfo, 1)
|
||||
var file_store_resource_proto_msgTypes = make([]protoimpl.MessageInfo, 2)
|
||||
var file_store_resource_proto_goTypes = []any{
|
||||
(ResourceStorageType)(0), // 0: memos.store.ResourceStorageType
|
||||
(*ResourcePayload)(nil), // 1: memos.store.ResourcePayload
|
||||
(*ResourcePayload_S3Object)(nil), // 2: memos.store.ResourcePayload.S3Object
|
||||
(*StorageS3Config)(nil), // 3: memos.store.StorageS3Config
|
||||
(*timestamppb.Timestamp)(nil), // 4: google.protobuf.Timestamp
|
||||
}
|
||||
var file_store_resource_proto_depIdxs = []int32{
|
||||
2, // 0: memos.store.ResourcePayload.s3_object:type_name -> memos.store.ResourcePayload.S3Object
|
||||
3, // 1: memos.store.ResourcePayload.S3Object.s3_config:type_name -> memos.store.StorageS3Config
|
||||
4, // 2: memos.store.ResourcePayload.S3Object.last_presigned_time:type_name -> google.protobuf.Timestamp
|
||||
3, // [3:3] is the sub-list for method output_type
|
||||
3, // [3:3] is the sub-list for method input_type
|
||||
3, // [3:3] is the sub-list for extension type_name
|
||||
3, // [3:3] is the sub-list for extension extendee
|
||||
0, // [0:3] is the sub-list for field type_name
|
||||
}
|
||||
|
||||
func init() { file_store_resource_proto_init() }
|
||||
func file_store_resource_proto_init() {
|
||||
if File_store_resource_proto != nil {
|
||||
return
|
||||
}
|
||||
file_store_workspace_setting_proto_init()
|
||||
file_store_resource_proto_msgTypes[0].OneofWrappers = []any{
|
||||
(*ResourcePayload_S3Object_)(nil),
|
||||
}
|
||||
type x struct{}
|
||||
out := protoimpl.TypeBuilder{
|
||||
File: protoimpl.DescBuilder{
|
||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||
RawDescriptor: unsafe.Slice(unsafe.StringData(file_store_resource_proto_rawDesc), len(file_store_resource_proto_rawDesc)),
|
||||
NumEnums: 1,
|
||||
NumMessages: 2,
|
||||
NumExtensions: 0,
|
||||
NumServices: 0,
|
||||
},
|
||||
GoTypes: file_store_resource_proto_goTypes,
|
||||
DependencyIndexes: file_store_resource_proto_depIdxs,
|
||||
EnumInfos: file_store_resource_proto_enumTypes,
|
||||
MessageInfos: file_store_resource_proto_msgTypes,
|
||||
}.Build()
|
||||
File_store_resource_proto = out.File
|
||||
file_store_resource_proto_goTypes = nil
|
||||
file_store_resource_proto_depIdxs = nil
|
||||
}
|
||||
@ -0,0 +1,34 @@
|
||||
import { Attachment } from "@/types/proto/api/v1/attachment_service";
|
||||
import { getAttachmentUrl } from "@/utils/attachment";
|
||||
import AttachmentIcon from "./AttachmentIcon";
|
||||
|
||||
interface Props {
|
||||
attachment: Attachment;
|
||||
className?: string;
|
||||
}
|
||||
|
||||
const MemoAttachment: React.FC<Props> = (props: Props) => {
|
||||
const { className, attachment } = props;
|
||||
const attachmentUrl = getAttachmentUrl(attachment);
|
||||
|
||||
const handlePreviewBtnClick = () => {
|
||||
window.open(attachmentUrl);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={`w-auto flex flex-row justify-start items-center text-gray-500 dark:text-gray-400 hover:opacity-80 ${className}`}>
|
||||
{attachment.type.startsWith("audio") ? (
|
||||
<audio src={attachmentUrl} controls></audio>
|
||||
) : (
|
||||
<>
|
||||
<AttachmentIcon className="w-4! h-4! mr-1" attachment={attachment} />
|
||||
<span className="text-sm max-w-[256px] truncate cursor-pointer" onClick={handlePreviewBtnClick}>
|
||||
{attachment.filename}
|
||||
</span>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default MemoAttachment;
|
||||
@ -0,0 +1,92 @@
|
||||
import { Button } from "@usememos/mui";
|
||||
import { LoaderIcon, PaperclipIcon } from "lucide-react";
|
||||
import { observer } from "mobx-react-lite";
|
||||
import { useContext, useRef, useState } from "react";
|
||||
import toast from "react-hot-toast";
|
||||
import { attachmentStore } from "@/store/v2";
|
||||
import { Attachment } from "@/types/proto/api/v1/attachment_service";
|
||||
import { MemoEditorContext } from "../types";
|
||||
|
||||
interface Props {
|
||||
isUploading?: boolean;
|
||||
}
|
||||
|
||||
interface State {
|
||||
uploadingFlag: boolean;
|
||||
}
|
||||
|
||||
const UploadAttachmentButton = observer((props: Props) => {
|
||||
const context = useContext(MemoEditorContext);
|
||||
const [state, setState] = useState<State>({
|
||||
uploadingFlag: false,
|
||||
});
|
||||
const fileInputRef = useRef<HTMLInputElement>(null);
|
||||
|
||||
const handleFileInputChange = async () => {
|
||||
if (!fileInputRef.current || !fileInputRef.current.files || fileInputRef.current.files.length === 0) {
|
||||
return;
|
||||
}
|
||||
if (state.uploadingFlag) {
|
||||
return;
|
||||
}
|
||||
|
||||
setState((state) => {
|
||||
return {
|
||||
...state,
|
||||
uploadingFlag: true,
|
||||
};
|
||||
});
|
||||
|
||||
const createdAttachmentList: Attachment[] = [];
|
||||
try {
|
||||
if (!fileInputRef.current || !fileInputRef.current.files) {
|
||||
return;
|
||||
}
|
||||
for (const file of fileInputRef.current.files) {
|
||||
const { name: filename, size, type } = file;
|
||||
const buffer = new Uint8Array(await file.arrayBuffer());
|
||||
const attachment = await attachmentStore.createAttachment({
|
||||
attachment: Attachment.fromPartial({
|
||||
filename,
|
||||
size,
|
||||
type,
|
||||
content: buffer,
|
||||
}),
|
||||
attachmentId: "",
|
||||
});
|
||||
createdAttachmentList.push(attachment);
|
||||
}
|
||||
} catch (error: any) {
|
||||
console.error(error);
|
||||
toast.error(error.details);
|
||||
}
|
||||
|
||||
context.setAttachmentList([...context.attachmentList, ...createdAttachmentList]);
|
||||
setState((state) => {
|
||||
return {
|
||||
...state,
|
||||
uploadingFlag: false,
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
const isUploading = state.uploadingFlag || props.isUploading;
|
||||
|
||||
return (
|
||||
<Button className="relative p-0" variant="plain" disabled={isUploading}>
|
||||
{isUploading ? <LoaderIcon className="w-5 h-5 animate-spin" /> : <PaperclipIcon className="w-5 h-5" />}
|
||||
<input
|
||||
className="absolute inset-0 w-full h-full opacity-0 cursor-pointer"
|
||||
ref={fileInputRef}
|
||||
disabled={isUploading}
|
||||
onChange={handleFileInputChange}
|
||||
type="file"
|
||||
id="files"
|
||||
multiple={true}
|
||||
accept="*"
|
||||
/>
|
||||
</Button>
|
||||
);
|
||||
});
|
||||
|
||||
export default UploadAttachmentButton;
|
||||
@ -1,92 +0,0 @@
|
||||
import { Button } from "@usememos/mui";
|
||||
import { LoaderIcon, PaperclipIcon } from "lucide-react";
|
||||
import { observer } from "mobx-react-lite";
|
||||
import { useContext, useRef, useState } from "react";
|
||||
import toast from "react-hot-toast";
|
||||
import { attachmentStore } from "@/store/v2";
|
||||
import { Attachment } from "@/types/proto/api/v1/attachment_service";
|
||||
import { MemoEditorContext } from "../types";
|
||||
|
||||
interface Props {
|
||||
isUploadingResource?: boolean;
|
||||
}
|
||||
|
||||
interface State {
|
||||
uploadingFlag: boolean;
|
||||
}
|
||||
|
||||
const UploadResourceButton = observer((props: Props) => {
|
||||
const context = useContext(MemoEditorContext);
|
||||
const [state, setState] = useState<State>({
|
||||
uploadingFlag: false,
|
||||
});
|
||||
const fileInputRef = useRef<HTMLInputElement>(null);
|
||||
|
||||
const handleFileInputChange = async () => {
|
||||
if (!fileInputRef.current || !fileInputRef.current.files || fileInputRef.current.files.length === 0) {
|
||||
return;
|
||||
}
|
||||
if (state.uploadingFlag) {
|
||||
return;
|
||||
}
|
||||
|
||||
setState((state) => {
|
||||
return {
|
||||
...state,
|
||||
uploadingFlag: true,
|
||||
};
|
||||
});
|
||||
|
||||
const createdAttachmentList: Attachment[] = [];
|
||||
try {
|
||||
if (!fileInputRef.current || !fileInputRef.current.files) {
|
||||
return;
|
||||
}
|
||||
for (const file of fileInputRef.current.files) {
|
||||
const { name: filename, size, type } = file;
|
||||
const buffer = new Uint8Array(await file.arrayBuffer());
|
||||
const attachment = await attachmentStore.createAttachment({
|
||||
attachment: Attachment.fromPartial({
|
||||
filename,
|
||||
size,
|
||||
type,
|
||||
content: buffer,
|
||||
}),
|
||||
attachmentId: "",
|
||||
});
|
||||
createdAttachmentList.push(attachment);
|
||||
}
|
||||
} catch (error: any) {
|
||||
console.error(error);
|
||||
toast.error(error.details);
|
||||
}
|
||||
|
||||
context.setAttachmentList([...context.attachmentList, ...createdAttachmentList]);
|
||||
setState((state) => {
|
||||
return {
|
||||
...state,
|
||||
uploadingFlag: false,
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
const isUploading = state.uploadingFlag || props.isUploadingResource;
|
||||
|
||||
return (
|
||||
<Button className="relative p-0" variant="plain" disabled={isUploading}>
|
||||
{isUploading ? <LoaderIcon className="w-5 h-5 animate-spin" /> : <PaperclipIcon className="w-5 h-5" />}
|
||||
<input
|
||||
className="absolute inset-0 w-full h-full opacity-0 cursor-pointer"
|
||||
ref={fileInputRef}
|
||||
disabled={isUploading}
|
||||
onChange={handleFileInputChange}
|
||||
type="file"
|
||||
id="files"
|
||||
multiple={true}
|
||||
accept="*"
|
||||
/>
|
||||
</Button>
|
||||
);
|
||||
});
|
||||
|
||||
export default UploadResourceButton;
|
||||
@ -1,34 +0,0 @@
|
||||
import { Attachment } from "@/types/proto/api/v1/attachment_service";
|
||||
import { getAttachmentUrl } from "@/utils/attachment";
|
||||
import ResourceIcon from "./ResourceIcon";
|
||||
|
||||
interface Props {
|
||||
resource: Attachment;
|
||||
className?: string;
|
||||
}
|
||||
|
||||
const MemoResource: React.FC<Props> = (props: Props) => {
|
||||
const { className, resource } = props;
|
||||
const resourceUrl = getAttachmentUrl(resource);
|
||||
|
||||
const handlePreviewBtnClick = () => {
|
||||
window.open(resourceUrl);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={`w-auto flex flex-row justify-start items-center text-gray-500 dark:text-gray-400 hover:opacity-80 ${className}`}>
|
||||
{resource.type.startsWith("audio") ? (
|
||||
<audio src={resourceUrl} controls></audio>
|
||||
) : (
|
||||
<>
|
||||
<ResourceIcon className="w-4! h-4! mr-1" resource={resource} />
|
||||
<span className="text-sm max-w-[256px] truncate cursor-pointer" onClick={handlePreviewBtnClick}>
|
||||
{resource.filename}
|
||||
</span>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default MemoResource;
|
||||
Loading…
Reference in New Issue