mirror of https://github.com/usememos/memos.git
Introduce setting to disable thumbnail loading and generation when images are stored in S3
This commit is contained in:
parent
d516f9aab2
commit
cb84b7bc8a
|
|
@ -169,6 +169,9 @@ message WorkspaceSetting {
|
|||
bool enable_blur_nsfw_content = 9;
|
||||
// nsfw_tags is the list of tags that mark content as NSFW for blurring.
|
||||
repeated string nsfw_tags = 10;
|
||||
// use_thumbnails_for_s3_images enables thumbnail generation for images stored in S3.
|
||||
// When false, images stored in S3 will not have thumbnails generated.
|
||||
bool use_thumbnails_for_s3_images = 11;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -428,7 +428,6 @@ type GetUserRequest struct {
|
|||
// Supports both numeric IDs and username strings:
|
||||
// - users/{id} (e.g., users/101)
|
||||
// - users/{username} (e.g., users/steven)
|
||||
//
|
||||
// Format: users/{id_or_username}
|
||||
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
|
||||
// Optional. The fields to return in the response.
|
||||
|
|
|
|||
|
|
@ -672,9 +672,12 @@ type WorkspaceSetting_MemoRelatedSetting struct {
|
|||
// enable_blur_nsfw_content enables blurring of content marked as not safe for work (NSFW).
|
||||
EnableBlurNsfwContent bool `protobuf:"varint,9,opt,name=enable_blur_nsfw_content,json=enableBlurNsfwContent,proto3" json:"enable_blur_nsfw_content,omitempty"`
|
||||
// nsfw_tags is the list of tags that mark content as NSFW for blurring.
|
||||
NsfwTags []string `protobuf:"bytes,10,rep,name=nsfw_tags,json=nsfwTags,proto3" json:"nsfw_tags,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
NsfwTags []string `protobuf:"bytes,10,rep,name=nsfw_tags,json=nsfwTags,proto3" json:"nsfw_tags,omitempty"`
|
||||
// use_thumbnails_for_s3_images enables thumbnail generation for images stored in S3.
|
||||
// When false, images stored in S3 will not have thumbnails generated.
|
||||
UseThumbnailsForS3Images bool `protobuf:"varint,11,opt,name=use_thumbnails_for_s3_images,json=useThumbnailsForS3Images,proto3" json:"use_thumbnails_for_s3_images,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *WorkspaceSetting_MemoRelatedSetting) Reset() {
|
||||
|
|
@ -770,6 +773,13 @@ func (x *WorkspaceSetting_MemoRelatedSetting) GetNsfwTags() []string {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (x *WorkspaceSetting_MemoRelatedSetting) GetUseThumbnailsForS3Images() bool {
|
||||
if x != nil {
|
||||
return x.UseThumbnailsForS3Images
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Custom profile configuration for workspace branding.
|
||||
type WorkspaceSetting_GeneralSetting_CustomProfile struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
|
|
@ -935,7 +945,7 @@ const file_api_v1_workspace_service_proto_rawDesc = "" +
|
|||
"\aversion\x18\x02 \x01(\tR\aversion\x12\x12\n" +
|
||||
"\x04mode\x18\x03 \x01(\tR\x04mode\x12!\n" +
|
||||
"\finstance_url\x18\x06 \x01(\tR\vinstanceUrl\"\x1c\n" +
|
||||
"\x1aGetWorkspaceProfileRequest\"\x97\x11\n" +
|
||||
"\x1aGetWorkspaceProfileRequest\"\xd7\x11\n" +
|
||||
"\x10WorkspaceSetting\x12\x17\n" +
|
||||
"\x04name\x18\x01 \x01(\tB\x03\xe0A\bR\x04name\x12X\n" +
|
||||
"\x0fgeneral_setting\x18\x02 \x01(\v2-.memos.api.v1.WorkspaceSetting.GeneralSettingH\x00R\x0egeneralSetting\x12X\n" +
|
||||
|
|
@ -972,7 +982,7 @@ const file_api_v1_workspace_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\xd8\x03\n" +
|
||||
"\x02S3\x10\x03\x1a\x98\x04\n" +
|
||||
"\x12MemoRelatedSetting\x12<\n" +
|
||||
"\x1adisallow_public_visibility\x18\x01 \x01(\bR\x18disallowPublicVisibility\x127\n" +
|
||||
"\x18display_with_update_time\x18\x02 \x01(\bR\x15displayWithUpdateTime\x120\n" +
|
||||
|
|
@ -983,7 +993,8 @@ const file_api_v1_workspace_service_proto_rawDesc = "" +
|
|||
"\x1adisable_markdown_shortcuts\x18\b \x01(\bR\x18disableMarkdownShortcuts\x127\n" +
|
||||
"\x18enable_blur_nsfw_content\x18\t \x01(\bR\x15enableBlurNsfwContent\x12\x1b\n" +
|
||||
"\tnsfw_tags\x18\n" +
|
||||
" \x03(\tR\bnsfwTags\"F\n" +
|
||||
" \x03(\tR\bnsfwTags\x12>\n" +
|
||||
"\x1cuse_thumbnails_for_s3_images\x18\v \x01(\bR\x18useThumbnailsForS3Images\"F\n" +
|
||||
"\x03Key\x12\x13\n" +
|
||||
"\x0fKEY_UNSPECIFIED\x10\x00\x12\v\n" +
|
||||
"\aGENERAL\x10\x01\x12\v\n" +
|
||||
|
|
|
|||
|
|
@ -78,35 +78,23 @@ paths:
|
|||
parameters:
|
||||
- name: pageSize
|
||||
in: query
|
||||
description: |-
|
||||
Optional. The maximum number of attachments to return.
|
||||
The service may return fewer than this value.
|
||||
If unspecified, at most 50 attachments will be returned.
|
||||
The maximum value is 1000; values above 1000 will be coerced to 1000.
|
||||
description: "Optional. The maximum number of attachments to return.\r\n The service may return fewer than this value.\r\n If unspecified, at most 50 attachments will be returned.\r\n The maximum value is 1000; values above 1000 will be coerced to 1000."
|
||||
schema:
|
||||
type: integer
|
||||
format: int32
|
||||
- name: pageToken
|
||||
in: query
|
||||
description: |-
|
||||
Optional. A page token, received from a previous `ListAttachments` call.
|
||||
Provide this to retrieve the subsequent page.
|
||||
description: "Optional. A page token, received from a previous `ListAttachments` call.\r\n Provide this to retrieve the subsequent page."
|
||||
schema:
|
||||
type: string
|
||||
- name: filter
|
||||
in: query
|
||||
description: |-
|
||||
Optional. Filter to apply to the list results.
|
||||
Example: "type=image/png" or "filename:*.jpg"
|
||||
Supported operators: =, !=, <, <=, >, >=, :
|
||||
Supported fields: filename, type, size, create_time, memo
|
||||
description: "Optional. Filter to apply to the list results.\r\n Example: \"type=image/png\" or \"filename:*.jpg\"\r\n Supported operators: =, !=, <, <=, >, >=, :\r\n Supported fields: filename, type, size, create_time, memo"
|
||||
schema:
|
||||
type: string
|
||||
- name: orderBy
|
||||
in: query
|
||||
description: |-
|
||||
Optional. The order to sort results by.
|
||||
Example: "create_time desc" or "filename asc"
|
||||
description: "Optional. The order to sort results by.\r\n Example: \"create_time desc\" or \"filename asc\""
|
||||
schema:
|
||||
type: string
|
||||
responses:
|
||||
|
|
@ -130,9 +118,7 @@ paths:
|
|||
parameters:
|
||||
- name: attachmentId
|
||||
in: query
|
||||
description: |-
|
||||
Optional. The attachment ID to use for this attachment.
|
||||
If empty, a unique ID will be generated.
|
||||
description: "Optional. The attachment ID to use for this attachment.\r\n If empty, a unique ID will be generated."
|
||||
schema:
|
||||
type: string
|
||||
requestBody:
|
||||
|
|
@ -516,26 +502,18 @@ paths:
|
|||
parameters:
|
||||
- name: pageSize
|
||||
in: query
|
||||
description: |-
|
||||
Optional. The maximum number of memos to return.
|
||||
The service may return fewer than this value.
|
||||
If unspecified, at most 50 memos will be returned.
|
||||
The maximum value is 1000; values above 1000 will be coerced to 1000.
|
||||
description: "Optional. The maximum number of memos to return.\r\n The service may return fewer than this value.\r\n If unspecified, at most 50 memos will be returned.\r\n The maximum value is 1000; values above 1000 will be coerced to 1000."
|
||||
schema:
|
||||
type: integer
|
||||
format: int32
|
||||
- name: pageToken
|
||||
in: query
|
||||
description: |-
|
||||
Optional. A page token, received from a previous `ListMemos` call.
|
||||
Provide this to retrieve the subsequent page.
|
||||
description: "Optional. A page token, received from a previous `ListMemos` call.\r\n Provide this to retrieve the subsequent page."
|
||||
schema:
|
||||
type: string
|
||||
- name: state
|
||||
in: query
|
||||
description: |-
|
||||
Optional. The state of the memos to list.
|
||||
Default to `NORMAL`. Set to `ARCHIVED` to list archived memos.
|
||||
description: "Optional. The state of the memos to list.\r\n Default to `NORMAL`. Set to `ARCHIVED` to list archived memos."
|
||||
schema:
|
||||
enum:
|
||||
- STATE_UNSPECIFIED
|
||||
|
|
@ -545,20 +523,12 @@ paths:
|
|||
format: enum
|
||||
- name: orderBy
|
||||
in: query
|
||||
description: |-
|
||||
Optional. The order to sort results by.
|
||||
Default to "display_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
|
||||
description: "Optional. The order to sort results by.\r\n Default to \"display_time desc\".\r\n Supports comma-separated list of fields following AIP-132.\r\n Example: \"pinned desc, display_time desc\" or \"create_time asc\"\r\n Supported fields: pinned, display_time, create_time, update_time, name"
|
||||
schema:
|
||||
type: string
|
||||
- name: filter
|
||||
in: query
|
||||
description: |-
|
||||
Optional. Filter to apply to the list results.
|
||||
Filter is a CEL expression to filter memos.
|
||||
Refer to `Shortcut.filter`.
|
||||
description: "Optional. Filter to apply to the list results.\r\n Filter is a CEL expression to filter memos.\r\n Refer to `Shortcut.filter`."
|
||||
schema:
|
||||
type: string
|
||||
- name: showDeleted
|
||||
|
|
@ -587,9 +557,7 @@ paths:
|
|||
parameters:
|
||||
- name: memoId
|
||||
in: query
|
||||
description: |-
|
||||
Optional. The memo ID to use for this memo.
|
||||
If empty, a unique ID will be generated.
|
||||
description: "Optional. The memo ID to use for this memo.\r\n If empty, a unique ID will be generated."
|
||||
schema:
|
||||
type: string
|
||||
- name: validateOnly
|
||||
|
|
@ -636,9 +604,7 @@ paths:
|
|||
type: string
|
||||
- name: readMask
|
||||
in: query
|
||||
description: |-
|
||||
Optional. The fields to return in the response.
|
||||
If not specified, all fields are returned.
|
||||
description: "Optional. The fields to return in the response.\r\n If not specified, all fields are returned."
|
||||
schema:
|
||||
type: string
|
||||
format: field-mask
|
||||
|
|
@ -2173,9 +2139,7 @@ components:
|
|||
properties:
|
||||
name:
|
||||
type: string
|
||||
description: |-
|
||||
The name of the attachment.
|
||||
Format: attachments/{attachment}
|
||||
description: "The name of the attachment.\r\n Format: attachments/{attachment}"
|
||||
createTime:
|
||||
readOnly: true
|
||||
type: string
|
||||
|
|
@ -2201,9 +2165,7 @@ components:
|
|||
description: Output only. The size of the attachment in bytes.
|
||||
memo:
|
||||
type: string
|
||||
description: |-
|
||||
Optional. The related memo. Refer to `Memo.name`.
|
||||
Format: memos/{memo}
|
||||
description: "Optional. The related memo. Refer to `Memo.name`.\r\n Format: memos/{memo}"
|
||||
CreateSessionRequest:
|
||||
type: object
|
||||
properties:
|
||||
|
|
@ -2277,9 +2239,7 @@ components:
|
|||
properties:
|
||||
parent:
|
||||
type: string
|
||||
description: |-
|
||||
Required. The parent, who owns the tags.
|
||||
Format: memos/{memo}. Use "memos/-" to delete all tags.
|
||||
description: "Required. The parent, who owns the tags.\r\n Format: memos/{memo}. Use \"memos/-\" to delete all tags."
|
||||
tag:
|
||||
type: string
|
||||
description: Required. The tag name to delete.
|
||||
|
|
@ -2440,9 +2400,7 @@ components:
|
|||
description: The list of attachments.
|
||||
nextPageToken:
|
||||
type: string
|
||||
description: |-
|
||||
A token that can be sent as `page_token` to retrieve the next page.
|
||||
If this field is omitted, there are no subsequent pages.
|
||||
description: "A token that can be sent as `page_token` to retrieve the next page.\r\n If this field is omitted, there are no subsequent pages."
|
||||
totalSize:
|
||||
type: integer
|
||||
description: The total count of attachments (may be approximate).
|
||||
|
|
@ -2542,9 +2500,7 @@ components:
|
|||
description: The list of memos.
|
||||
nextPageToken:
|
||||
type: string
|
||||
description: |-
|
||||
A token that can be sent as `page_token` to retrieve the next page.
|
||||
If this field is omitted, there are no subsequent pages.
|
||||
description: "A token that can be sent as `page_token` to retrieve the next page.\r\n If this field is omitted, there are no subsequent pages."
|
||||
totalSize:
|
||||
type: integer
|
||||
description: The total count of memos (may be approximate).
|
||||
|
|
@ -2646,9 +2602,7 @@ components:
|
|||
properties:
|
||||
name:
|
||||
type: string
|
||||
description: |-
|
||||
The resource name of the memo.
|
||||
Format: memos/{memo}, memo is the user defined id or uuid.
|
||||
description: "The resource name of the memo.\r\n Format: memos/{memo}, memo is the user defined id or uuid."
|
||||
state:
|
||||
enum:
|
||||
- STATE_UNSPECIFIED
|
||||
|
|
@ -2660,9 +2614,7 @@ components:
|
|||
creator:
|
||||
readOnly: true
|
||||
type: string
|
||||
description: |-
|
||||
The name of the creator.
|
||||
Format: users/{user}
|
||||
description: "The name of the creator.\r\n Format: users/{user}"
|
||||
createTime:
|
||||
readOnly: true
|
||||
type: string
|
||||
|
|
@ -2722,9 +2674,7 @@ components:
|
|||
parent:
|
||||
readOnly: true
|
||||
type: string
|
||||
description: |-
|
||||
Output only. The name of the parent memo.
|
||||
Format: memos/{memo}
|
||||
description: "Output only. The name of the parent memo.\r\n Format: memos/{memo}"
|
||||
snippet:
|
||||
readOnly: true
|
||||
type: string
|
||||
|
|
@ -2762,9 +2712,7 @@ components:
|
|||
properties:
|
||||
name:
|
||||
type: string
|
||||
description: |-
|
||||
The resource name of the memo.
|
||||
Format: memos/{memo}
|
||||
description: "The resource name of the memo.\r\n Format: memos/{memo}"
|
||||
snippet:
|
||||
readOnly: true
|
||||
type: string
|
||||
|
|
@ -2810,21 +2758,14 @@ components:
|
|||
name:
|
||||
readOnly: true
|
||||
type: string
|
||||
description: |-
|
||||
The resource name of the reaction.
|
||||
Format: reactions/{reaction}
|
||||
description: "The resource name of the reaction.\r\n Format: reactions/{reaction}"
|
||||
creator:
|
||||
readOnly: true
|
||||
type: string
|
||||
description: |-
|
||||
The resource name of the creator.
|
||||
Format: users/{user}
|
||||
description: "The resource name of the creator.\r\n Format: users/{user}"
|
||||
contentId:
|
||||
type: string
|
||||
description: |-
|
||||
The resource name of the content.
|
||||
For memo reactions, this should be the memo's resource name.
|
||||
Format: memos/{memo}
|
||||
description: "The resource name of the content.\r\n For memo reactions, this should be the memo's resource name.\r\n Format: memos/{memo}"
|
||||
reactionType:
|
||||
type: string
|
||||
description: "Required. The type of reaction (e.g., \"\U0001F44D\", \"❤️\", \"\U0001F604\")."
|
||||
|
|
@ -2842,9 +2783,7 @@ components:
|
|||
properties:
|
||||
parent:
|
||||
type: string
|
||||
description: |-
|
||||
Required. The parent, who owns the tags.
|
||||
Format: memos/{memo}. Use "memos/-" to rename all tags.
|
||||
description: "Required. The parent, who owns the tags.\r\n Format: memos/{memo}. Use \"memos/-\" to rename all tags."
|
||||
oldTag:
|
||||
type: string
|
||||
description: Required. The old tag name to rename.
|
||||
|
|
@ -2859,9 +2798,7 @@ components:
|
|||
properties:
|
||||
name:
|
||||
type: string
|
||||
description: |-
|
||||
Required. The resource name of the memo.
|
||||
Format: memos/{memo}
|
||||
description: "Required. The resource name of the memo.\r\n Format: memos/{memo}"
|
||||
attachments:
|
||||
type: array
|
||||
items:
|
||||
|
|
@ -2875,9 +2812,7 @@ components:
|
|||
properties:
|
||||
name:
|
||||
type: string
|
||||
description: |-
|
||||
Required. The resource name of the memo.
|
||||
Format: memos/{memo}
|
||||
description: "Required. The resource name of the memo.\r\n Format: memos/{memo}"
|
||||
relations:
|
||||
type: array
|
||||
items:
|
||||
|
|
@ -2930,9 +2865,7 @@ components:
|
|||
type: string
|
||||
usePathStyle:
|
||||
type: boolean
|
||||
description: |-
|
||||
S3 configuration for cloud storage backend.
|
||||
Reference: https://developers.cloudflare.com/r2/examples/aws/aws-sdk-go/
|
||||
description: "S3 configuration for cloud storage backend.\r\n Reference: https://developers.cloudflare.com/r2/examples/aws/aws-sdk-go/"
|
||||
UpsertMemoReactionRequest:
|
||||
required:
|
||||
- name
|
||||
|
|
@ -2941,9 +2874,7 @@ components:
|
|||
properties:
|
||||
name:
|
||||
type: string
|
||||
description: |-
|
||||
Required. The resource name of the memo.
|
||||
Format: memos/{memo}
|
||||
description: "Required. The resource name of the memo.\r\n Format: memos/{memo}"
|
||||
reaction:
|
||||
allOf:
|
||||
- $ref: '#/components/schemas/Reaction'
|
||||
|
|
@ -3219,9 +3150,7 @@ components:
|
|||
properties:
|
||||
owner:
|
||||
type: string
|
||||
description: |-
|
||||
The name of instance owner.
|
||||
Format: users/{user}
|
||||
description: "The name of instance owner.\r\n Format: users/{user}"
|
||||
version:
|
||||
type: string
|
||||
description: Version is the current version of instance.
|
||||
|
|
@ -3237,9 +3166,7 @@ components:
|
|||
properties:
|
||||
name:
|
||||
type: string
|
||||
description: |-
|
||||
The name of the workspace setting.
|
||||
Format: workspace/settings/{setting}
|
||||
description: "The name of the workspace setting.\r\n Format: workspace/settings/{setting}"
|
||||
generalSetting:
|
||||
$ref: '#/components/schemas/WorkspaceSetting_GeneralSetting'
|
||||
storageSetting:
|
||||
|
|
@ -3252,9 +3179,7 @@ components:
|
|||
properties:
|
||||
theme:
|
||||
type: string
|
||||
description: |-
|
||||
theme is the name of the selected theme.
|
||||
This references a CSS file in the web/public/themes/ directory.
|
||||
description: "theme is the name of the selected theme.\r\n This references a CSS file in the web/public/themes/ directory."
|
||||
disallowUserRegistration:
|
||||
type: boolean
|
||||
description: disallow_user_registration disallows user registration.
|
||||
|
|
@ -3273,10 +3198,7 @@ components:
|
|||
description: custom_profile is the custom profile.
|
||||
weekStartDayOffset:
|
||||
type: integer
|
||||
description: |-
|
||||
week_start_day_offset is the week start day offset from Sunday.
|
||||
0: Sunday, 1: Monday, 2: Tuesday, 3: Wednesday, 4: Thursday, 5: Friday, 6: Saturday
|
||||
Default is Sunday.
|
||||
description: "week_start_day_offset is the week start day offset from Sunday.\r\n 0: Sunday, 1: Monday, 2: Tuesday, 3: Wednesday, 4: Thursday, 5: Friday, 6: Saturday\r\n Default is Sunday."
|
||||
format: int32
|
||||
disallowChangeUsername:
|
||||
type: boolean
|
||||
|
|
@ -3320,6 +3242,9 @@ components:
|
|||
items:
|
||||
type: string
|
||||
description: nsfw_tags is the list of tags that mark content as NSFW for blurring.
|
||||
useThumbnailsForS3Images:
|
||||
type: boolean
|
||||
description: "use_thumbnails_for_s3_images enables thumbnail generation for images stored in S3.\r\n When false, images stored in S3 will not have thumbnails generated."
|
||||
description: Memo-related workspace settings and policies.
|
||||
WorkspaceSetting_StorageSetting:
|
||||
type: object
|
||||
|
|
@ -3335,9 +3260,7 @@ components:
|
|||
format: enum
|
||||
filepathTemplate:
|
||||
type: string
|
||||
description: |-
|
||||
The template of file path.
|
||||
e.g. assets/{timestamp}_{filename}
|
||||
description: "The template of file path.\r\n e.g. assets/{timestamp}_{filename}"
|
||||
uploadSizeLimitMb:
|
||||
type: string
|
||||
description: The max upload size in megabytes.
|
||||
|
|
|
|||
|
|
@ -676,9 +676,12 @@ type WorkspaceMemoRelatedSetting struct {
|
|||
// enable_blur_nsfw_content enables blurring of content marked as not safe for work (NSFW).
|
||||
EnableBlurNsfwContent bool `protobuf:"varint,9,opt,name=enable_blur_nsfw_content,json=enableBlurNsfwContent,proto3" json:"enable_blur_nsfw_content,omitempty"`
|
||||
// nsfw_tags is the list of tags that mark content as NSFW for blurring.
|
||||
NsfwTags []string `protobuf:"bytes,10,rep,name=nsfw_tags,json=nsfwTags,proto3" json:"nsfw_tags,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
NsfwTags []string `protobuf:"bytes,10,rep,name=nsfw_tags,json=nsfwTags,proto3" json:"nsfw_tags,omitempty"`
|
||||
// use_thumbnails_for_s3_images enables thumbnail generation for images stored in S3.
|
||||
// When false, images stored in S3 will not have thumbnails generated.
|
||||
UseThumbnailsForS3Images bool `protobuf:"varint,11,opt,name=use_thumbnails_for_s3_images,json=useThumbnailsForS3Images,proto3" json:"use_thumbnails_for_s3_images,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *WorkspaceMemoRelatedSetting) Reset() {
|
||||
|
|
@ -774,6 +777,13 @@ func (x *WorkspaceMemoRelatedSetting) GetNsfwTags() []string {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (x *WorkspaceMemoRelatedSetting) GetUseThumbnailsForS3Images() bool {
|
||||
if x != nil {
|
||||
return x.UseThumbnailsForS3Images
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
var File_store_workspace_setting_proto protoreflect.FileDescriptor
|
||||
|
||||
const file_store_workspace_setting_proto_rawDesc = "" +
|
||||
|
|
@ -821,7 +831,7 @@ const file_store_workspace_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\"\xe1\x03\n" +
|
||||
"\x0euse_path_style\x18\x06 \x01(\bR\fusePathStyle\"\xa1\x04\n" +
|
||||
"\x1bWorkspaceMemoRelatedSetting\x12<\n" +
|
||||
"\x1adisallow_public_visibility\x18\x01 \x01(\bR\x18disallowPublicVisibility\x127\n" +
|
||||
"\x18display_with_update_time\x18\x02 \x01(\bR\x15displayWithUpdateTime\x120\n" +
|
||||
|
|
@ -832,7 +842,8 @@ const file_store_workspace_setting_proto_rawDesc = "" +
|
|||
"\x1adisable_markdown_shortcuts\x18\b \x01(\bR\x18disableMarkdownShortcuts\x127\n" +
|
||||
"\x18enable_blur_nsfw_content\x18\t \x01(\bR\x15enableBlurNsfwContent\x12\x1b\n" +
|
||||
"\tnsfw_tags\x18\n" +
|
||||
" \x03(\tR\bnsfwTags*s\n" +
|
||||
" \x03(\tR\bnsfwTags\x12>\n" +
|
||||
"\x1cuse_thumbnails_for_s3_images\x18\v \x01(\bR\x18useThumbnailsForS3Images*s\n" +
|
||||
"\x13WorkspaceSettingKey\x12%\n" +
|
||||
"!WORKSPACE_SETTING_KEY_UNSPECIFIED\x10\x00\x12\t\n" +
|
||||
"\x05BASIC\x10\x01\x12\v\n" +
|
||||
|
|
|
|||
|
|
@ -114,4 +114,7 @@ message WorkspaceMemoRelatedSetting {
|
|||
bool enable_blur_nsfw_content = 9;
|
||||
// nsfw_tags is the list of tags that mark content as NSFW for blurring.
|
||||
repeated string nsfw_tags = 10;
|
||||
// use_thumbnails_for_s3_images enables thumbnail generation for images stored in S3.
|
||||
// When false, images stored in S3 will not have thumbnails generated.
|
||||
bool use_thumbnails_for_s3_images = 11;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -232,16 +232,29 @@ func (s *APIV1Service) GetAttachmentBinary(ctx context.Context, request *v1pb.Ge
|
|||
}
|
||||
|
||||
if request.Thumbnail && util.HasPrefixes(attachment.Type, SupportedThumbnailMimeTypes...) {
|
||||
thumbnailBlob, err := s.getOrGenerateThumbnail(attachment)
|
||||
if err != nil {
|
||||
// thumbnail failures are logged as warnings and not cosidered critical failures as
|
||||
// a attachment image can be used in its place.
|
||||
slog.Warn("failed to get attachment thumbnail image", slog.Any("error", err))
|
||||
} else {
|
||||
return &httpbody.HttpBody{
|
||||
ContentType: attachment.Type,
|
||||
Data: thumbnailBlob,
|
||||
}, nil
|
||||
// Check if we should generate thumbnails for S3 images
|
||||
shouldGenerateThumbnail := true
|
||||
if attachment.StorageType == storepb.AttachmentStorageType_S3 {
|
||||
memoRelatedSetting, err := s.Store.GetWorkspaceMemoRelatedSetting(ctx)
|
||||
if err != nil {
|
||||
slog.Warn("failed to get workspace memo related setting", slog.Any("error", err))
|
||||
} else if !memoRelatedSetting.UseThumbnailsForS3Images {
|
||||
shouldGenerateThumbnail = false
|
||||
}
|
||||
}
|
||||
|
||||
if shouldGenerateThumbnail {
|
||||
thumbnailBlob, err := s.getOrGenerateThumbnail(attachment)
|
||||
if err != nil {
|
||||
// thumbnail failures are logged as warnings and not cosidered critical failures as
|
||||
// a attachment image can be used in its place.
|
||||
slog.Warn("failed to get attachment thumbnail image", slog.Any("error", err))
|
||||
} else {
|
||||
return &httpbody.HttpBody{
|
||||
ContentType: attachment.Type,
|
||||
Data: thumbnailBlob,
|
||||
}, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -264,6 +264,7 @@ func convertWorkspaceMemoRelatedSettingFromStore(setting *storepb.WorkspaceMemoR
|
|||
DisableMarkdownShortcuts: setting.DisableMarkdownShortcuts,
|
||||
EnableBlurNsfwContent: setting.EnableBlurNsfwContent,
|
||||
NsfwTags: setting.NsfwTags,
|
||||
UseThumbnailsForS3Images: setting.UseThumbnailsForS3Images,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -281,6 +282,7 @@ func convertWorkspaceMemoRelatedSettingToStore(setting *v1pb.WorkspaceSetting_Me
|
|||
DisableMarkdownShortcuts: setting.DisableMarkdownShortcuts,
|
||||
EnableBlurNsfwContent: setting.EnableBlurNsfwContent,
|
||||
NsfwTags: setting.NsfwTags,
|
||||
UseThumbnailsForS3Images: setting.UseThumbnailsForS3Images,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -175,6 +175,13 @@ const MemoRelatedSettings = observer(() => {
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="w-full flex flex-row justify-between items-center">
|
||||
<span>{t("setting.memo-related-settings.use-thumbnails-for-s3-images")}</span>
|
||||
<Switch
|
||||
checked={memoRelatedSetting.useThumbnailsForS3Images}
|
||||
onCheckedChange={(checked) => updatePartialSetting({ useThumbnailsForS3Images: checked })}
|
||||
/>
|
||||
</div>
|
||||
<div className="mt-2 w-full flex justify-end">
|
||||
<Button disabled={isEqual(memoRelatedSetting, originalSetting)} onClick={updateSetting}>
|
||||
{t("common.save")}
|
||||
|
|
|
|||
|
|
@ -316,7 +316,8 @@
|
|||
"enable-memo-comments": "Enable memo comments",
|
||||
"enable-memo-location": "Enable memo location",
|
||||
"reactions": "Reactions",
|
||||
"title": "Memo related settings"
|
||||
"title": "Memo related settings",
|
||||
"use-thumbnails-for-s3-images": "Generate and serve thumbnails for images stored in S3"
|
||||
},
|
||||
"my-account": "My Account",
|
||||
"preference": "Preferences",
|
||||
|
|
|
|||
|
|
@ -230,6 +230,11 @@ export interface WorkspaceSetting_MemoRelatedSetting {
|
|||
enableBlurNsfwContent: boolean;
|
||||
/** nsfw_tags is the list of tags that mark content as NSFW for blurring. */
|
||||
nsfwTags: string[];
|
||||
/**
|
||||
* use_thumbnails_for_s3_images enables thumbnail generation for images stored in S3.
|
||||
* When false, images stored in S3 will not have thumbnails generated.
|
||||
*/
|
||||
useThumbnailsForS3Images: boolean;
|
||||
}
|
||||
|
||||
/** Request message for GetWorkspaceSetting method. */
|
||||
|
|
@ -905,6 +910,7 @@ function createBaseWorkspaceSetting_MemoRelatedSetting(): WorkspaceSetting_MemoR
|
|||
disableMarkdownShortcuts: false,
|
||||
enableBlurNsfwContent: false,
|
||||
nsfwTags: [],
|
||||
useThumbnailsForS3Images: false,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -937,6 +943,9 @@ export const WorkspaceSetting_MemoRelatedSetting: MessageFns<WorkspaceSetting_Me
|
|||
for (const v of message.nsfwTags) {
|
||||
writer.uint32(82).string(v!);
|
||||
}
|
||||
if (message.useThumbnailsForS3Images !== false) {
|
||||
writer.uint32(88).bool(message.useThumbnailsForS3Images);
|
||||
}
|
||||
return writer;
|
||||
},
|
||||
|
||||
|
|
@ -1019,6 +1028,14 @@ export const WorkspaceSetting_MemoRelatedSetting: MessageFns<WorkspaceSetting_Me
|
|||
message.nsfwTags.push(reader.string());
|
||||
continue;
|
||||
}
|
||||
case 11: {
|
||||
if (tag !== 88) {
|
||||
break;
|
||||
}
|
||||
|
||||
message.useThumbnailsForS3Images = reader.bool();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if ((tag & 7) === 4 || tag === 0) {
|
||||
break;
|
||||
|
|
@ -1042,6 +1059,7 @@ export const WorkspaceSetting_MemoRelatedSetting: MessageFns<WorkspaceSetting_Me
|
|||
message.disableMarkdownShortcuts = object.disableMarkdownShortcuts ?? false;
|
||||
message.enableBlurNsfwContent = object.enableBlurNsfwContent ?? false;
|
||||
message.nsfwTags = object.nsfwTags?.map((e) => e) || [];
|
||||
message.useThumbnailsForS3Images = object.useThumbnailsForS3Images ?? false;
|
||||
return message;
|
||||
},
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import { Attachment } from "@/types/proto/api/v1/attachment_service";
|
||||
import workspaceStore from "@/store/workspace";
|
||||
|
||||
export const getAttachmentUrl = (attachment: Attachment) => {
|
||||
if (attachment.externalLink) {
|
||||
|
|
@ -9,6 +10,15 @@ export const getAttachmentUrl = (attachment: Attachment) => {
|
|||
};
|
||||
|
||||
export const getAttachmentThumbnailUrl = (attachment: Attachment) => {
|
||||
// Check if thumbnails are disabled for S3 images
|
||||
const isS3Image = !!attachment.externalLink;
|
||||
const useThumbnailsForS3Images = workspaceStore.state.memoRelatedSetting.useThumbnailsForS3Images;
|
||||
|
||||
// Don't request thumbnails for S3 images if the setting is disabled
|
||||
if (isS3Image && !useThumbnailsForS3Images) {
|
||||
return getAttachmentUrl(attachment);
|
||||
}
|
||||
|
||||
return `${window.location.origin}/file/${attachment.name}/${attachment.filename}?thumbnail=true`;
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue