mirror of https://github.com/usememos/memos.git
feat: add blur_content attribute to tag metadata settings (#5767)
Co-authored-by: memoclaw <265580040+memoclaw@users.noreply.github.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
parent
9e04049632
commit
45b21530d9
|
|
@ -0,0 +1,98 @@
|
|||
## Background & Context
|
||||
|
||||
Memos has a content-blur feature: when a memo's tag list contains the literal string `NSFW`
|
||||
(case-insensitive), the memo body is rendered with a `blur-lg` CSS class and a click-to-reveal
|
||||
overlay is shown. This was simplified in v0.26.x from a previous admin-configurable system
|
||||
(which had an on/off toggle and a custom-tag-list) down to a single hardcoded tag name.
|
||||
|
||||
In the same release cycle, an `InstanceTagsSetting` system was introduced that lets admins attach
|
||||
metadata (currently only `background_color`) to tag name patterns via a regex-keyed map. This
|
||||
system has its own proto definitions, store layer, API service handlers, frontend context, utility
|
||||
library, and settings UI — all independent of the blur feature.
|
||||
|
||||
A sponsor raised (orgs/usememos/discussions/5708) that the hardcoded tag name is inconvenient:
|
||||
users who organised their content under a different tag (e.g. a non-English word, a project-
|
||||
specific label, or simply a term they prefer) must re-tag all existing memos just to use the blur
|
||||
feature. Community comments echo the same concern and additionally ask for the ability to disable
|
||||
the blur globally.
|
||||
|
||||
## Issue Statement
|
||||
|
||||
The memo content-blur trigger is evaluated exclusively against the hardcoded string `"NSFW"`
|
||||
(case-insensitive) in `MemoView.tsx`, with no connection to the `InstanceTagsSetting` system,
|
||||
making it impossible for an administrator to designate any other tag name — or set of tag name
|
||||
patterns — as a blur trigger, and preventing users from re-using existing tag taxonomies to
|
||||
activate content blurring.
|
||||
|
||||
## Current State
|
||||
|
||||
**Blur detection — frontend**
|
||||
|
||||
| File | Lines | Behaviour |
|
||||
|------|-------|-----------|
|
||||
| `web/src/components/MemoView/MemoView.tsx` | 27–30 | `const nsfw = memoData.tags?.some((tag) => tag.toUpperCase() === "NSFW") ?? false;` — single hardcoded string comparison |
|
||||
| `web/src/components/MemoView/MemoViewContext.tsx` | 16–19 | Context shape exposes `nsfw: boolean`, `showNSFWContent: boolean`, `toggleNsfwVisibility` |
|
||||
| `web/src/components/MemoView/components/MemoBody.tsx` | 11–23, 37, 53 | Applies `blur-lg transition-all duration-200` when `nsfw && !showNSFWContent`; renders `NsfwOverlay` button using i18n key `memo.click-to-show-nsfw-content` |
|
||||
| `web/src/components/MemoPreview/MemoPreview.tsx` | 24–27 | Stub context value: `nsfw: false`, `showNSFWContent: false` — blur never active in preview |
|
||||
|
||||
**Localisation strings that contain the "NSFW" term**
|
||||
|
||||
| File | Keys |
|
||||
|------|------|
|
||||
| `web/src/locales/en.json` (and ~30 other locale files) | `memo.click-to-hide-nsfw-content`, `memo.click-to-show-nsfw-content`, `settings.enable-blur-nsfw-content` |
|
||||
|
||||
Note: most non-English translations already use "sensitive content" rather than "NSFW" in these
|
||||
keys; English is the outlier.
|
||||
|
||||
**Tag metadata system — proto**
|
||||
|
||||
| File | Lines | Content |
|
||||
|------|-------|---------|
|
||||
| `proto/api/v1/instance_service.proto` | 168–181 | `message TagMetadata { google.type.Color background_color = 1; }` nested inside `InstanceSetting`; `TagsSetting` is a `map<string, TagMetadata>` |
|
||||
| `proto/store/instance_setting.proto` | 113–124 | `message InstanceTagMetadata { google.type.Color background_color = 1; }` inside `InstanceTagsSetting` |
|
||||
|
||||
**Tag metadata system — backend**
|
||||
|
||||
| File | Lines | Content |
|
||||
|------|-------|---------|
|
||||
| `store/instance_setting.go` | 166–192 | `GetInstanceTagsSetting()` retrieves and caches the tags map |
|
||||
| `server/router/api/v1/instance_service.go` | 300–328 | `convertInstanceTagsSettingFromStore()` / `convertInstanceTagsSettingToStore()` convert between store and API representations, field-by-field |
|
||||
| `server/router/api/v1/instance_service.go` | 387–409 | `validateInstanceTagsSetting()` validates each key as a regex pattern and the color value |
|
||||
|
||||
**Tag metadata system — frontend**
|
||||
|
||||
| File | Lines | Content |
|
||||
|------|-------|---------|
|
||||
| `web/src/lib/tag.ts` | 28–43 | `findTagMetadata(tag, tagsSetting)` — exact-match then regex-match lookup returning `TagMetadata \| undefined` |
|
||||
| `web/src/components/MemoContent/Tag.tsx` | 23–38 | Calls `findTagMetadata()` to apply `background_color` to inline tag chips |
|
||||
| `web/src/components/Settings/TagsSection.tsx` | 36–206 | Admin settings UI for managing the tag→metadata map; currently shows only a colour picker per tag |
|
||||
| `web/src/contexts/InstanceContext.tsx` | 83–99 | `tagsSetting` selector and fetch during app initialisation |
|
||||
|
||||
## Non-Goals
|
||||
|
||||
- Redesigning or replacing the `InstanceTagsSetting` proto or store structure beyond adding one field.
|
||||
- Providing a per-user (as opposed to per-instance) blur preference.
|
||||
- Changing how background-color metadata is stored, validated, or rendered.
|
||||
- Adding a global on/off toggle for blurring (separate from per-tag configuration).
|
||||
- Modifying the blur visual effect (CSS class, animation, overlay button layout).
|
||||
- Migrating or auto-converting any existing memos that were tagged with `NSFW`.
|
||||
- Changing non-English locale strings that already use neutral terminology.
|
||||
|
||||
## Open Questions
|
||||
|
||||
1. Should the `blur_content` field in tag metadata be configurable per-tag only by admins, or also by individual users via user-level tag settings? (default: admin-only, matching the existing `InstanceTagsSetting` access model)
|
||||
|
||||
2. When a memo has multiple tags and more than one of them has `blur_content = true`, should the blur activate if _any_ matching tag has the flag set, or only if _all_ matching tags do? (default: any — OR semantics, consistent with the current single-tag check)
|
||||
|
||||
3. Should there be a migration that automatically sets `blur_content = true` for any existing `InstanceTagsSetting` entry whose key is `"NSFW"` (case-insensitive)? (default: no automatic migration; admins reconfigure manually)
|
||||
|
||||
4. What should the English-locale i18n key strings say, given that "NSFW" is to be avoided? (default: "Click to show sensitive content" / "Click to hide sensitive content")
|
||||
|
||||
## Scope
|
||||
|
||||
**M** — the change adds one `bool` field to two existing proto messages, threads it through two
|
||||
existing conversion functions in the backend, replaces one hardcoded string comparison in
|
||||
`MemoView.tsx` with a call to the already-present `findTagMetadata()` utility, adds a checkbox to
|
||||
the existing `TagsSection.tsx` settings UI, and renames three i18n keys. All required patterns
|
||||
(field addition, conversion, `findTagMetadata` lookup, settings UI checkbox) already exist in the
|
||||
codebase.
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
## Execution Log
|
||||
|
||||
### T1: Add blur_content field to proto messages
|
||||
|
||||
**Status**: Completed
|
||||
**Files Changed**: `proto/api/v1/instance_service.proto`, `proto/store/instance_setting.proto`
|
||||
**Validation**: `buf lint` — PASS
|
||||
**Path Corrections**: None
|
||||
**Deviations**: None
|
||||
|
||||
### T2: Regenerate proto code
|
||||
|
||||
**Status**: Completed
|
||||
**Files Changed**: `proto/gen/` (Go + OpenAPI), `web/src/types/proto/` (TypeScript)
|
||||
**Validation**: `grep blur_content` in generated files — PASS (field present in Go, TS, OpenAPI)
|
||||
**Path Corrections**: None
|
||||
**Deviations**: None
|
||||
|
||||
### T3: Thread blur_content through backend conversions
|
||||
|
||||
**Status**: Completed
|
||||
**Files Changed**: `server/router/api/v1/instance_service.go`
|
||||
**Validation**: `go build ./...` — PASS
|
||||
**Path Corrections**: None
|
||||
**Deviations**: None
|
||||
|
||||
### T4: Replace hardcoded NSFW check with tag metadata lookup
|
||||
|
||||
**Status**: Completed
|
||||
**Files Changed**: `web/src/components/MemoView/MemoView.tsx`, `web/src/components/MemoView/MemoViewContext.tsx`, `web/src/components/MemoView/components/MemoBody.tsx`, `web/src/components/MemoPreview/MemoPreview.tsx`
|
||||
**Validation**: `pnpm lint` — PASS
|
||||
**Path Corrections**: i18n key update (T6) was pulled forward to unblock TypeScript type checking, since the i18n key type is statically checked.
|
||||
**Deviations**: None
|
||||
|
||||
### T5: Add blur checkbox to TagsSection settings UI
|
||||
|
||||
**Status**: Completed
|
||||
**Files Changed**: `web/src/components/Settings/TagsSection.tsx`
|
||||
**Validation**: `pnpm lint` — PASS
|
||||
**Path Corrections**: None
|
||||
**Deviations**: None
|
||||
|
||||
### T6: Update English i18n keys
|
||||
|
||||
**Status**: Completed
|
||||
**Files Changed**: `web/src/locales/en.json`
|
||||
**Validation**: `grep -c "nsfw\|NSFW" en.json` — returns 0, PASS
|
||||
**Path Corrections**: Executed during T4/T5 to unblock type checking. Added `setting.tags.blur-content` key (not in original plan but required by T5's new checkbox column).
|
||||
**Deviations**: None
|
||||
|
||||
## Completion Declaration
|
||||
|
||||
**All tasks completed successfully.**
|
||||
|
||||
Summary of changes:
|
||||
- Added `bool blur_content = 2` to both API and store proto TagMetadata messages
|
||||
- Regenerated Go, TypeScript, and OpenAPI code
|
||||
- Threaded `blur_content` through `convertInstanceTagsSettingFromStore()` and `convertInstanceTagsSettingToStore()`
|
||||
- Replaced hardcoded `tag.toUpperCase() === "NSFW"` with `findTagMetadata(tag, tagsSetting)?.blurContent` lookup
|
||||
- Renamed context fields: `nsfw` → `blurred`, `showNSFWContent` → `showBlurredContent`, `toggleNsfwVisibility` → `toggleBlurVisibility`
|
||||
- Renamed `NsfwOverlay` → `BlurOverlay` component
|
||||
- Expanded TagsSection local state to track `{ color, blur }` per tag and added a "Blur content" checkbox column
|
||||
- Updated English i18n: renamed NSFW keys to "sensitive content", removed unused key, added `blur-content` setting key
|
||||
|
|
@ -0,0 +1,89 @@
|
|||
## Task List
|
||||
|
||||
T1: Add blur_content field to proto messages [S] — T2: Regenerate proto code [S] — T3: Thread blur_content through backend conversions [S] — T4: Replace hardcoded NSFW check with tag metadata lookup [M] — T5: Add blur checkbox to TagsSection settings UI [S] — T6: Update English i18n keys [S]
|
||||
|
||||
### T1: Add blur_content field to proto messages [S]
|
||||
|
||||
**Objective**: Add a `bool blur_content` field to both the API and store proto TagMetadata messages.
|
||||
**Files**: `proto/api/v1/instance_service.proto`, `proto/store/instance_setting.proto`
|
||||
**Implementation**:
|
||||
- In `proto/api/v1/instance_service.proto` (~line 171), add `bool blur_content = 2;` to `message TagMetadata` after `background_color`
|
||||
- In `proto/store/instance_setting.proto` (~line 115), add `bool blur_content = 2;` to `message InstanceTagMetadata` after `background_color`
|
||||
**Validation**: `cd proto && buf lint` — no errors
|
||||
|
||||
### T2: Regenerate proto code [S]
|
||||
|
||||
**Objective**: Regenerate Go + TypeScript + OpenAPI from updated proto definitions.
|
||||
**Files**: `proto/gen/` (generated), `web/src/types/proto/` (generated)
|
||||
**Implementation**: Run `cd proto && buf generate`
|
||||
**Dependencies**: T1
|
||||
**Validation**: `grep -r "blur_content\|blurContent" proto/gen/ web/src/types/proto/ | head -10` — shows new field in generated Go and TS files
|
||||
|
||||
### T3: Thread blur_content through backend conversion functions [S]
|
||||
|
||||
**Objective**: Pass `blur_content` through the store↔API conversion functions so the field round-trips correctly.
|
||||
**Files**: `server/router/api/v1/instance_service.go`
|
||||
**Implementation**:
|
||||
- In `convertInstanceTagsSettingFromStore()` (~line 306): add `BlurContent: metadata.GetBlurContent()` to the `InstanceSetting_TagMetadata` struct literal
|
||||
- In `convertInstanceTagsSettingToStore()` (~line 321): add `BlurContent: metadata.GetBlurContent()` to the `InstanceTagMetadata` struct literal
|
||||
**Dependencies**: T2
|
||||
**Validation**: `cd /Users/steven/Projects/usememos/memos && go build ./...` — compiles without errors
|
||||
|
||||
### T4: Replace hardcoded NSFW check with tag metadata lookup [M]
|
||||
|
||||
**Objective**: Replace the hardcoded `tag.toUpperCase() === "NSFW"` check with a lookup against `InstanceTagsSetting` via the existing `findTagMetadata()` utility, so any tag with `blur_content: true` triggers the blur.
|
||||
**Size**: M (3 files, moderate logic)
|
||||
**Files**:
|
||||
- Modify: `web/src/components/MemoView/MemoView.tsx`
|
||||
- Modify: `web/src/components/MemoView/MemoViewContext.tsx`
|
||||
- Modify: `web/src/components/MemoView/components/MemoBody.tsx`
|
||||
- Modify: `web/src/components/MemoPreview/MemoPreview.tsx`
|
||||
**Implementation**:
|
||||
1. In `MemoView.tsx`:
|
||||
- Import `useInstance` from `@/contexts/InstanceContext` and `findTagMetadata` from `@/lib/tag`
|
||||
- Replace `const nsfw = memoData.tags?.some((tag) => tag.toUpperCase() === "NSFW") ?? false;` with a check that iterates `memoData.tags` and uses `findTagMetadata(tag, tagsSetting)?.blurContent` — OR semantics (any match triggers blur)
|
||||
- Rename state/variables: `showNSFWContent` → `showBlurredContent`, `nsfw` → `blurred`, `toggleNsfwVisibility` → `toggleBlurVisibility`
|
||||
2. In `MemoViewContext.tsx`:
|
||||
- Rename interface fields: `nsfw` → `blurred`, `showNSFWContent` → `showBlurredContent`, `toggleNsfwVisibility` → `toggleBlurVisibility`
|
||||
3. In `MemoBody.tsx`:
|
||||
- Update destructured context fields to use new names (`blurred`, `showBlurredContent`, `toggleBlurVisibility`)
|
||||
- Rename `NsfwOverlay` component to `BlurOverlay`
|
||||
- Change i18n key from `memo.click-to-show-nsfw-content` to `memo.click-to-show-sensitive-content`
|
||||
4. In `MemoPreview.tsx`:
|
||||
- Update stub context to use new field names (`blurred`, `showBlurredContent`, `toggleBlurVisibility`)
|
||||
**Boundaries**: Do NOT change blur CSS classes, animation, or overlay layout
|
||||
**Dependencies**: T2
|
||||
**Validation**: `cd web && pnpm lint` — no type or lint errors
|
||||
|
||||
### T5: Add blur checkbox to TagsSection settings UI [S]
|
||||
|
||||
**Objective**: Add a "Blur content" checkbox column to the tag settings table so admins can toggle `blur_content` per tag pattern.
|
||||
**Files**: `web/src/components/Settings/TagsSection.tsx`
|
||||
**Implementation**:
|
||||
- Expand `localTags` state from `Record<string, string>` (hex only) to `Record<string, { color: string; blur: boolean }>` to track both fields
|
||||
- Update `useEffect` sync, `originalHexMap` comparison, `handleColorChange`, `handleRemoveTag`, `handleAddTag` to work with the new shape
|
||||
- Add a new `[newTagBlur, setNewTagBlur]` state for the add-tag row (default `false`)
|
||||
- In `handleSave`, pass `blurContent` when creating `InstanceSetting_TagMetadata`
|
||||
- Add a new column to `SettingTable` between "Background color" and "Actions": header `t("setting.tags.blur-content")`, renders a checkbox bound to `localTags[row.name].blur`
|
||||
- Add the i18n key `setting.tags.blur-content` to `en.json` with value `"Blur content"`
|
||||
**Dependencies**: T2
|
||||
**Validation**: `cd web && pnpm lint` — no type or lint errors
|
||||
|
||||
### T6: Update English i18n keys [S]
|
||||
|
||||
**Objective**: Rename NSFW-specific i18n keys in `en.json` to use neutral "sensitive content" terminology.
|
||||
**Files**: `web/src/locales/en.json`
|
||||
**Implementation**:
|
||||
- Change key `memo.click-to-show-nsfw-content` → `memo.click-to-show-sensitive-content` with value `"Click to show sensitive content"`
|
||||
- Change key `memo.click-to-hide-nsfw-content` → `memo.click-to-hide-sensitive-content` with value `"Click to hide sensitive content"` (dead key but renamed for consistency)
|
||||
- The key `settings.enable-blur-nsfw-content` is unused in code — remove it
|
||||
**Dependencies**: T4 (key rename must match code references)
|
||||
**Validation**: `grep -c "nsfw" web/src/locales/en.json` — returns `0`
|
||||
|
||||
## Out-of-Scope Tasks
|
||||
|
||||
- Updating non-English locale files (per non-goals: "Changing non-English locale strings that already use neutral terminology")
|
||||
- Adding automatic migration for existing NSFW tag entries
|
||||
- Per-user blur preferences
|
||||
- Global on/off toggle for blurring
|
||||
- Modifying blur visual effect (CSS, animation, overlay layout)
|
||||
|
|
@ -169,6 +169,8 @@ message InstanceSetting {
|
|||
message TagMetadata {
|
||||
// Background color for the tag label.
|
||||
google.type.Color background_color = 1;
|
||||
// Whether memos with this tag should have their content blurred.
|
||||
bool blur_content = 2;
|
||||
}
|
||||
|
||||
// Tag metadata configuration.
|
||||
|
|
|
|||
|
|
@ -761,8 +761,10 @@ type InstanceSetting_TagMetadata struct {
|
|||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
// Background color for the tag label.
|
||||
BackgroundColor *color.Color `protobuf:"bytes,1,opt,name=background_color,json=backgroundColor,proto3" json:"background_color,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
// Whether memos with this tag should have their content blurred.
|
||||
BlurContent bool `protobuf:"varint,2,opt,name=blur_content,json=blurContent,proto3" json:"blur_content,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *InstanceSetting_TagMetadata) Reset() {
|
||||
|
|
@ -802,9 +804,20 @@ func (x *InstanceSetting_TagMetadata) GetBackgroundColor() *color.Color {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (x *InstanceSetting_TagMetadata) GetBlurContent() bool {
|
||||
if x != nil {
|
||||
return x.BlurContent
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Tag metadata configuration.
|
||||
type InstanceSetting_TagsSetting struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
// Map of tag name pattern to tag metadata.
|
||||
// Each key is treated as an anchored regular expression (^pattern$),
|
||||
// so a single entry like "project/.*" matches all tags under that prefix.
|
||||
// Exact tag names are also valid (they are trivially valid regex patterns).
|
||||
Tags map[string]*InstanceSetting_TagMetadata `protobuf:"bytes,1,rep,name=tags,proto3" json:"tags,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
|
|
@ -1166,7 +1179,7 @@ const file_api_v1_instance_service_proto_rawDesc = "" +
|
|||
"\x04demo\x18\x03 \x01(\bR\x04demo\x12!\n" +
|
||||
"\finstance_url\x18\x06 \x01(\tR\vinstanceUrl\x12(\n" +
|
||||
"\x05admin\x18\a \x01(\v2\x12.memos.api.v1.UserR\x05admin\"\x1b\n" +
|
||||
"\x19GetInstanceProfileRequest\"\xe0\x15\n" +
|
||||
"\x19GetInstanceProfileRequest\"\x83\x16\n" +
|
||||
"\x0fInstanceSetting\x12\x17\n" +
|
||||
"\x04name\x18\x01 \x01(\tB\x03\xe0A\bR\x04name\x12W\n" +
|
||||
"\x0fgeneral_setting\x18\x02 \x01(\v2,.memos.api.v1.InstanceSetting.GeneralSettingH\x00R\x0egeneralSetting\x12W\n" +
|
||||
|
|
@ -1208,9 +1221,10 @@ const file_api_v1_instance_service_proto_rawDesc = "" +
|
|||
"\x18display_with_update_time\x18\x02 \x01(\bR\x15displayWithUpdateTime\x120\n" +
|
||||
"\x14content_length_limit\x18\x03 \x01(\x05R\x12contentLengthLimit\x127\n" +
|
||||
"\x18enable_double_click_edit\x18\x04 \x01(\bR\x15enableDoubleClickEdit\x12\x1c\n" +
|
||||
"\treactions\x18\a \x03(\tR\treactions\x1aL\n" +
|
||||
"\treactions\x18\a \x03(\tR\treactions\x1ao\n" +
|
||||
"\vTagMetadata\x12=\n" +
|
||||
"\x10background_color\x18\x01 \x01(\v2\x12.google.type.ColorR\x0fbackgroundColor\x1a\xba\x01\n" +
|
||||
"\x10background_color\x18\x01 \x01(\v2\x12.google.type.ColorR\x0fbackgroundColor\x12!\n" +
|
||||
"\fblur_content\x18\x02 \x01(\bR\vblurContent\x1a\xba\x01\n" +
|
||||
"\vTagsSetting\x12G\n" +
|
||||
"\x04tags\x18\x01 \x03(\v23.memos.api.v1.InstanceSetting.TagsSetting.TagsEntryR\x04tags\x1ab\n" +
|
||||
"\tTagsEntry\x12\x10\n" +
|
||||
|
|
|
|||
|
|
@ -2399,6 +2399,9 @@ components:
|
|||
allOf:
|
||||
- $ref: '#/components/schemas/Color'
|
||||
description: Background color for the tag label.
|
||||
blurContent:
|
||||
type: boolean
|
||||
description: Whether memos with this tag should have their content blurred.
|
||||
description: Metadata for a tag.
|
||||
InstanceSetting_TagsSetting:
|
||||
type: object
|
||||
|
|
@ -2407,6 +2410,11 @@ components:
|
|||
type: object
|
||||
additionalProperties:
|
||||
$ref: '#/components/schemas/InstanceSetting_TagMetadata'
|
||||
description: |-
|
||||
Map of tag name pattern to tag metadata.
|
||||
Each key is treated as an anchored regular expression (^pattern$),
|
||||
so a single entry like "project/.*" matches all tags under that prefix.
|
||||
Exact tag names are also valid (they are trivially valid regex patterns).
|
||||
description: Tag metadata configuration.
|
||||
ListAllUserStatsResponse:
|
||||
type: object
|
||||
|
|
|
|||
|
|
@ -756,8 +756,10 @@ type InstanceTagMetadata struct {
|
|||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
// Background color for the tag label.
|
||||
BackgroundColor *color.Color `protobuf:"bytes,1,opt,name=background_color,json=backgroundColor,proto3" json:"background_color,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
// Whether memos with this tag should have their content blurred.
|
||||
BlurContent bool `protobuf:"varint,2,opt,name=blur_content,json=blurContent,proto3" json:"blur_content,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *InstanceTagMetadata) Reset() {
|
||||
|
|
@ -797,8 +799,19 @@ func (x *InstanceTagMetadata) GetBackgroundColor() *color.Color {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (x *InstanceTagMetadata) GetBlurContent() bool {
|
||||
if x != nil {
|
||||
return x.BlurContent
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type InstanceTagsSetting struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
// Map of tag name pattern to tag metadata.
|
||||
// Each key is treated as an anchored regular expression (^pattern$),
|
||||
// so a single entry like "project/.*" matches all tags under that prefix.
|
||||
// Exact tag names are also valid (they are trivially valid regex patterns).
|
||||
Tags map[string]*InstanceTagMetadata `protobuf:"bytes,1,rep,name=tags,proto3" json:"tags,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
|
|
@ -1053,9 +1066,10 @@ const file_store_instance_setting_proto_rawDesc = "" +
|
|||
"\x18display_with_update_time\x18\x02 \x01(\bR\x15displayWithUpdateTime\x120\n" +
|
||||
"\x14content_length_limit\x18\x03 \x01(\x05R\x12contentLengthLimit\x127\n" +
|
||||
"\x18enable_double_click_edit\x18\x04 \x01(\bR\x15enableDoubleClickEdit\x12\x1c\n" +
|
||||
"\treactions\x18\a \x03(\tR\treactions\"T\n" +
|
||||
"\treactions\x18\a \x03(\tR\treactions\"w\n" +
|
||||
"\x13InstanceTagMetadata\x12=\n" +
|
||||
"\x10background_color\x18\x01 \x01(\v2\x12.google.type.ColorR\x0fbackgroundColor\"\xb0\x01\n" +
|
||||
"\x10background_color\x18\x01 \x01(\v2\x12.google.type.ColorR\x0fbackgroundColor\x12!\n" +
|
||||
"\fblur_content\x18\x02 \x01(\bR\vblurContent\"\xb0\x01\n" +
|
||||
"\x13InstanceTagsSetting\x12>\n" +
|
||||
"\x04tags\x18\x01 \x03(\v2*.memos.store.InstanceTagsSetting.TagsEntryR\x04tags\x1aY\n" +
|
||||
"\tTagsEntry\x12\x10\n" +
|
||||
|
|
|
|||
|
|
@ -113,6 +113,8 @@ message InstanceMemoRelatedSetting {
|
|||
message InstanceTagMetadata {
|
||||
// Background color for the tag label.
|
||||
google.type.Color background_color = 1;
|
||||
// Whether memos with this tag should have their content blurred.
|
||||
bool blur_content = 2;
|
||||
}
|
||||
|
||||
message InstanceTagsSetting {
|
||||
|
|
|
|||
|
|
@ -305,6 +305,7 @@ func convertInstanceTagsSettingFromStore(setting *storepb.InstanceTagsSetting) *
|
|||
for tag, metadata := range setting.Tags {
|
||||
tags[tag] = &v1pb.InstanceSetting_TagMetadata{
|
||||
BackgroundColor: metadata.GetBackgroundColor(),
|
||||
BlurContent: metadata.GetBlurContent(),
|
||||
}
|
||||
}
|
||||
return &v1pb.InstanceSetting_TagsSetting{
|
||||
|
|
@ -320,6 +321,7 @@ func convertInstanceTagsSettingToStore(setting *v1pb.InstanceSetting_TagsSetting
|
|||
for tag, metadata := range setting.Tags {
|
||||
tags[tag] = &storepb.InstanceTagMetadata{
|
||||
BackgroundColor: metadata.GetBackgroundColor(),
|
||||
BlurContent: metadata.GetBlurContent(),
|
||||
}
|
||||
}
|
||||
return &storepb.InstanceTagsSetting{
|
||||
|
|
|
|||
|
|
@ -21,10 +21,10 @@ const STUB_CONTEXT: MemoViewContextValue = {
|
|||
parentPage: "/",
|
||||
isArchived: false,
|
||||
readonly: true,
|
||||
showNSFWContent: false,
|
||||
nsfw: false,
|
||||
showBlurredContent: false,
|
||||
blurred: false,
|
||||
openEditor: () => {},
|
||||
toggleNsfwVisibility: () => {},
|
||||
toggleBlurVisibility: () => {},
|
||||
openPreview: () => {},
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,9 @@
|
|||
import { memo, useCallback, useMemo, useRef, useState } from "react";
|
||||
import { useLocation } from "react-router-dom";
|
||||
import { useInstance } from "@/contexts/InstanceContext";
|
||||
import useCurrentUser from "@/hooks/useCurrentUser";
|
||||
import { useUser } from "@/hooks/useUserQueries";
|
||||
import { findTagMetadata } from "@/lib/tag";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { State } from "@/types/proto/api/v1/common_pb";
|
||||
import { isSuperUser } from "@/utils/user";
|
||||
|
|
@ -19,15 +21,16 @@ const MemoView: React.FC<MemoViewProps> = (props: MemoViewProps) => {
|
|||
const [showEditor, setShowEditor] = useState(false);
|
||||
|
||||
const currentUser = useCurrentUser();
|
||||
const { tagsSetting } = useInstance();
|
||||
const creator = useUser(memoData.creator).data;
|
||||
const isArchived = memoData.state === State.ARCHIVED;
|
||||
const readonly = memoData.creator !== currentUser?.name && !isSuperUser(currentUser);
|
||||
const parentPage = parentPageProp || "/";
|
||||
|
||||
// NSFW content management: always blur content tagged with NSFW (case-insensitive)
|
||||
const [showNSFWContent, setShowNSFWContent] = useState(false);
|
||||
const nsfw = memoData.tags?.some((tag) => tag.toUpperCase() === "NSFW") ?? false;
|
||||
const toggleNsfwVisibility = useCallback(() => setShowNSFWContent((prev) => !prev), []);
|
||||
// Blur content when any tag has blur_content enabled in the instance tag settings.
|
||||
const [showBlurredContent, setShowBlurredContent] = useState(false);
|
||||
const blurred = memoData.tags?.some((tag) => findTagMetadata(tag, tagsSetting)?.blurContent) ?? false;
|
||||
const toggleBlurVisibility = useCallback(() => setShowBlurredContent((prev) => !prev), []);
|
||||
|
||||
const { previewState, openPreview, setPreviewOpen } = useImagePreview();
|
||||
|
||||
|
|
@ -46,10 +49,10 @@ const MemoView: React.FC<MemoViewProps> = (props: MemoViewProps) => {
|
|||
parentPage,
|
||||
isArchived,
|
||||
readonly,
|
||||
showNSFWContent,
|
||||
nsfw,
|
||||
showBlurredContent,
|
||||
blurred,
|
||||
openEditor,
|
||||
toggleNsfwVisibility,
|
||||
toggleBlurVisibility,
|
||||
openPreview,
|
||||
}),
|
||||
[
|
||||
|
|
@ -59,10 +62,10 @@ const MemoView: React.FC<MemoViewProps> = (props: MemoViewProps) => {
|
|||
parentPage,
|
||||
isArchived,
|
||||
readonly,
|
||||
showNSFWContent,
|
||||
nsfw,
|
||||
showBlurredContent,
|
||||
blurred,
|
||||
openEditor,
|
||||
toggleNsfwVisibility,
|
||||
toggleBlurVisibility,
|
||||
openPreview,
|
||||
],
|
||||
);
|
||||
|
|
|
|||
|
|
@ -13,10 +13,10 @@ export interface MemoViewContextValue {
|
|||
parentPage: string;
|
||||
isArchived: boolean;
|
||||
readonly: boolean;
|
||||
showNSFWContent: boolean;
|
||||
nsfw: boolean;
|
||||
showBlurredContent: boolean;
|
||||
blurred: boolean;
|
||||
openEditor: () => void;
|
||||
toggleNsfwVisibility: () => void;
|
||||
toggleBlurVisibility: () => void;
|
||||
openPreview: (urls: string | string[], index?: number) => void;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ import { useMemoHandlers } from "../hooks";
|
|||
import { useMemoViewContext } from "../MemoViewContext";
|
||||
import type { MemoBodyProps } from "../types";
|
||||
|
||||
const NsfwOverlay: React.FC<{ onClick?: () => void }> = ({ onClick }) => {
|
||||
const BlurOverlay: React.FC<{ onClick?: () => void }> = ({ onClick }) => {
|
||||
const t = useTranslate();
|
||||
return (
|
||||
<div className="absolute inset-0 z-10 pt-4 flex items-center justify-center" onClick={onClick}>
|
||||
|
|
@ -16,14 +16,14 @@ const NsfwOverlay: React.FC<{ onClick?: () => void }> = ({ onClick }) => {
|
|||
type="button"
|
||||
className="rounded-lg border border-border bg-card px-2 py-1 text-xs text-muted-foreground transition-colors hover:border-accent hover:bg-accent hover:text-foreground"
|
||||
>
|
||||
{t("memo.click-to-show-nsfw-content")}
|
||||
{t("memo.click-to-show-sensitive-content")}
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const MemoBody: React.FC<MemoBodyProps> = ({ compact }) => {
|
||||
const { memo, parentPage, showNSFWContent, nsfw, readonly, openEditor, openPreview, toggleNsfwVisibility } = useMemoViewContext();
|
||||
const { memo, parentPage, showBlurredContent, blurred, readonly, openEditor, openPreview, toggleBlurVisibility } = useMemoViewContext();
|
||||
|
||||
const { handleMemoContentClick, handleMemoContentDoubleClick } = useMemoHandlers({ readonly, openEditor, openPreview });
|
||||
|
||||
|
|
@ -34,7 +34,7 @@ const MemoBody: React.FC<MemoBodyProps> = ({ compact }) => {
|
|||
<div
|
||||
className={cn(
|
||||
"w-full flex flex-col justify-start items-start gap-2",
|
||||
nsfw && !showNSFWContent && "blur-lg transition-all duration-200",
|
||||
blurred && !showBlurredContent && "blur-lg transition-all duration-200",
|
||||
)}
|
||||
>
|
||||
<MemoContent
|
||||
|
|
@ -50,7 +50,7 @@ const MemoBody: React.FC<MemoBodyProps> = ({ compact }) => {
|
|||
<MemoReactionListView memo={memo} reactions={memo.reactions} />
|
||||
</div>
|
||||
|
||||
{nsfw && !showNSFWContent && <NsfwOverlay onClick={toggleNsfwVisibility} />}
|
||||
{blurred && !showBlurredContent && <BlurOverlay onClick={toggleBlurVisibility} />}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -33,23 +33,39 @@ const hexToColor = (hex: string) =>
|
|||
blue: parseInt(hex.slice(5, 7), 16) / 255,
|
||||
});
|
||||
|
||||
interface LocalTagMeta {
|
||||
color: string;
|
||||
blur: boolean;
|
||||
}
|
||||
|
||||
const TagsSection = () => {
|
||||
const t = useTranslate();
|
||||
const { tagsSetting: originalSetting, updateSetting, fetchSetting } = useInstance();
|
||||
const { data: tagCounts = {} } = useTagCounts(false);
|
||||
|
||||
// Local state: map of tagName → hex color string for editing.
|
||||
const [localTags, setLocalTags] = useState<Record<string, string>>(() =>
|
||||
Object.fromEntries(Object.entries(originalSetting.tags).map(([name, meta]) => [name, tagColorToHex(meta.backgroundColor)])),
|
||||
// Local state: map of tagName → { color, blur } for editing.
|
||||
const [localTags, setLocalTags] = useState<Record<string, LocalTagMeta>>(() =>
|
||||
Object.fromEntries(
|
||||
Object.entries(originalSetting.tags).map(([name, meta]) => [
|
||||
name,
|
||||
{ color: tagColorToHex(meta.backgroundColor), blur: meta.blurContent },
|
||||
]),
|
||||
),
|
||||
);
|
||||
const [newTagName, setNewTagName] = useState("");
|
||||
const [newTagColor, setNewTagColor] = useState("#ffffff");
|
||||
const [newTagBlur, setNewTagBlur] = useState(false);
|
||||
|
||||
// Sync local state when the fetched setting arrives (the fetch is async and
|
||||
// completes after mount, so localTags would be empty without this sync).
|
||||
useEffect(() => {
|
||||
setLocalTags(
|
||||
Object.fromEntries(Object.entries(originalSetting.tags).map(([name, meta]) => [name, tagColorToHex(meta.backgroundColor)])),
|
||||
Object.fromEntries(
|
||||
Object.entries(originalSetting.tags).map(([name, meta]) => [
|
||||
name,
|
||||
{ color: tagColorToHex(meta.backgroundColor), blur: meta.blurContent },
|
||||
]),
|
||||
),
|
||||
);
|
||||
}, [originalSetting.tags]);
|
||||
|
||||
|
|
@ -68,14 +84,24 @@ const TagsSection = () => {
|
|||
[localTags],
|
||||
);
|
||||
|
||||
const originalHexMap = useMemo(
|
||||
() => Object.fromEntries(Object.entries(originalSetting.tags).map(([name, meta]) => [name, tagColorToHex(meta.backgroundColor)])),
|
||||
const originalMetaMap = useMemo(
|
||||
() =>
|
||||
Object.fromEntries(
|
||||
Object.entries(originalSetting.tags).map(([name, meta]) => [
|
||||
name,
|
||||
{ color: tagColorToHex(meta.backgroundColor), blur: meta.blurContent },
|
||||
]),
|
||||
),
|
||||
[originalSetting.tags],
|
||||
);
|
||||
const hasChanges = !isEqual(localTags, originalHexMap);
|
||||
const hasChanges = !isEqual(localTags, originalMetaMap);
|
||||
|
||||
const handleColorChange = (tagName: string, hex: string) => {
|
||||
setLocalTags((prev) => ({ ...prev, [tagName]: hex }));
|
||||
setLocalTags((prev) => ({ ...prev, [tagName]: { ...prev[tagName], color: hex } }));
|
||||
};
|
||||
|
||||
const handleBlurChange = (tagName: string, blur: boolean) => {
|
||||
setLocalTags((prev) => ({ ...prev, [tagName]: { ...prev[tagName], blur } }));
|
||||
};
|
||||
|
||||
const handleRemoveTag = (tagName: string) => {
|
||||
|
|
@ -97,17 +123,18 @@ const TagsSection = () => {
|
|||
toast.error(t("setting.tags.invalid-regex"));
|
||||
return;
|
||||
}
|
||||
setLocalTags((prev) => ({ ...prev, [name]: newTagColor }));
|
||||
setLocalTags((prev) => ({ ...prev, [name]: { color: newTagColor, blur: newTagBlur } }));
|
||||
setNewTagName("");
|
||||
setNewTagColor("#ffffff");
|
||||
setNewTagBlur(false);
|
||||
};
|
||||
|
||||
const handleSave = async () => {
|
||||
try {
|
||||
const tags = Object.fromEntries(
|
||||
Object.entries(localTags).map(([name, hex]) => [
|
||||
Object.entries(localTags).map(([name, meta]) => [
|
||||
name,
|
||||
create(InstanceSetting_TagMetadataSchema, { backgroundColor: hexToColor(hex) }),
|
||||
create(InstanceSetting_TagMetadataSchema, { backgroundColor: hexToColor(meta.color), blurContent: meta.blur }),
|
||||
]),
|
||||
);
|
||||
await updateSetting(
|
||||
|
|
@ -144,12 +171,24 @@ const TagsSection = () => {
|
|||
<input
|
||||
type="color"
|
||||
className="w-8 h-8 cursor-pointer rounded border border-border bg-transparent p-0.5"
|
||||
value={localTags[row.name]}
|
||||
value={localTags[row.name].color}
|
||||
onChange={(e) => handleColorChange(row.name, e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
),
|
||||
},
|
||||
{
|
||||
key: "blur",
|
||||
header: t("setting.tags.blur-content"),
|
||||
render: (_, row: { name: string }) => (
|
||||
<input
|
||||
type="checkbox"
|
||||
className="w-4 h-4 cursor-pointer"
|
||||
checked={localTags[row.name].blur}
|
||||
onChange={(e) => handleBlurChange(row.name, e.target.checked)}
|
||||
/>
|
||||
),
|
||||
},
|
||||
{
|
||||
key: "actions",
|
||||
header: "",
|
||||
|
|
@ -188,6 +227,15 @@ const TagsSection = () => {
|
|||
value={newTagColor}
|
||||
onChange={(e) => setNewTagColor(e.target.value)}
|
||||
/>
|
||||
<label className="flex items-center gap-1.5 text-sm text-muted-foreground">
|
||||
<input
|
||||
type="checkbox"
|
||||
className="w-4 h-4 cursor-pointer"
|
||||
checked={newTagBlur}
|
||||
onChange={(e) => setNewTagBlur(e.target.checked)}
|
||||
/>
|
||||
{t("setting.tags.blur-content")}
|
||||
</label>
|
||||
<Button variant="outline" onClick={handleAddTag} disabled={!newTagName.trim()}>
|
||||
<PlusIcon className="w-4 h-4 mr-1.5" />
|
||||
{t("common.add")}
|
||||
|
|
|
|||
|
|
@ -140,8 +140,8 @@
|
|||
},
|
||||
"memo": {
|
||||
"archived-at": "تاريخ الأرشفة",
|
||||
"click-to-hide-nsfw-content": "انقر لإخفاء المحتوى الحساس",
|
||||
"click-to-show-nsfw-content": "انقر لإظهار المحتوى الحساس",
|
||||
"click-to-hide-sensitive-content": "انقر لإخفاء المحتوى الحساس",
|
||||
"click-to-show-sensitive-content": "انقر لإظهار المحتوى الحساس",
|
||||
"code": "كود",
|
||||
"comment": {
|
||||
"self": "التعليقات",
|
||||
|
|
@ -410,7 +410,7 @@
|
|||
},
|
||||
"memo": {
|
||||
"content-length-limit": "حد طول المحتوى (بايت)",
|
||||
"enable-blur-nsfw-content": "تمكين طمس المحتوى الحساس (NSFW)",
|
||||
"enable-blur-sensitive-content": "تمكين طمس المحتوى الحساس (NSFW)",
|
||||
"enable-memo-comments": "تمكين تعليقات المذكرة",
|
||||
"enable-memo-location": "تمكين موقع المذكرة",
|
||||
"reactions": "تفاعلات",
|
||||
|
|
|
|||
|
|
@ -140,8 +140,8 @@
|
|||
},
|
||||
"memo": {
|
||||
"archived-at": "Arxivat el",
|
||||
"click-to-hide-nsfw-content": "Fes clic per ocultar contingut sensible",
|
||||
"click-to-show-nsfw-content": "Fes clic per mostrar contingut sensible",
|
||||
"click-to-hide-sensitive-content": "Fes clic per ocultar contingut sensible",
|
||||
"click-to-show-sensitive-content": "Fes clic per mostrar contingut sensible",
|
||||
"code": "Codi",
|
||||
"comment": {
|
||||
"self": "Comentaris",
|
||||
|
|
@ -410,7 +410,7 @@
|
|||
},
|
||||
"memo": {
|
||||
"content-length-limit": "Límit de longitud del contingut (Bytes)",
|
||||
"enable-blur-nsfw-content": "Habilita el difuminat de contingut sensible (NSFW)",
|
||||
"enable-blur-sensitive-content": "Habilita el difuminat de contingut sensible (NSFW)",
|
||||
"enable-memo-comments": "Habilita els comentaris a les notes",
|
||||
"enable-memo-location": "Habilita la ubicació de la nota",
|
||||
"reactions": "Reaccions",
|
||||
|
|
|
|||
|
|
@ -140,8 +140,8 @@
|
|||
},
|
||||
"memo": {
|
||||
"archived-at": "Archivováno na",
|
||||
"click-to-hide-nsfw-content": "Klikněte pro skrytí citlivého obsahu",
|
||||
"click-to-show-nsfw-content": "Klikněte pro zobrazení citlivého obsahu",
|
||||
"click-to-hide-sensitive-content": "Klikněte pro skrytí citlivého obsahu",
|
||||
"click-to-show-sensitive-content": "Klikněte pro zobrazení citlivého obsahu",
|
||||
"code": "Kód",
|
||||
"comment": {
|
||||
"self": "Komentáře",
|
||||
|
|
@ -410,7 +410,7 @@
|
|||
},
|
||||
"memo": {
|
||||
"content-length-limit": "Omezení velikosti obsahu (bajty)",
|
||||
"enable-blur-nsfw-content": "Povolit rozostření citlivého obsahu",
|
||||
"enable-blur-sensitive-content": "Povolit rozostření citlivého obsahu",
|
||||
"enable-memo-comments": "Povolit komentáře k poznámkám",
|
||||
"enable-memo-location": "Povolit umístění poznámek",
|
||||
"reactions": "Reakce",
|
||||
|
|
|
|||
|
|
@ -140,8 +140,8 @@
|
|||
},
|
||||
"memo": {
|
||||
"archived-at": "Archiviert am",
|
||||
"click-to-hide-nsfw-content": "Klicken, um sensible Inhalte auszublenden",
|
||||
"click-to-show-nsfw-content": "Klicken, um sensible Inhalte anzuzeigen",
|
||||
"click-to-hide-sensitive-content": "Klicken, um sensible Inhalte auszublenden",
|
||||
"click-to-show-sensitive-content": "Klicken, um sensible Inhalte anzuzeigen",
|
||||
"code": "Code",
|
||||
"comment": {
|
||||
"self": "Kommentare",
|
||||
|
|
@ -410,7 +410,7 @@
|
|||
},
|
||||
"memo": {
|
||||
"content-length-limit": "Limitierung der Inhaltslänge (Byte)",
|
||||
"enable-blur-nsfw-content": "Unschärfe für sensible Inhalte (NSFW) aktivieren",
|
||||
"enable-blur-sensitive-content": "Unschärfe für sensible Inhalte (NSFW) aktivieren",
|
||||
"enable-memo-comments": "Kommentare für Notizen aktivieren",
|
||||
"enable-memo-location": "Notiz-Standort aktivieren",
|
||||
"reactions": "Reaktionen",
|
||||
|
|
|
|||
|
|
@ -145,8 +145,8 @@
|
|||
},
|
||||
"memo": {
|
||||
"archived-at": "Archived at",
|
||||
"click-to-hide-nsfw-content": "Click to hide NSFW content",
|
||||
"click-to-show-nsfw-content": "Click to show NSFW content",
|
||||
"click-to-hide-sensitive-content": "Click to hide sensitive content",
|
||||
"click-to-show-sensitive-content": "Click to show sensitive content",
|
||||
"code": "Code",
|
||||
"comment": {
|
||||
"self": "Comments",
|
||||
|
|
@ -342,7 +342,7 @@
|
|||
},
|
||||
"memo": {
|
||||
"content-length-limit": "Content length limit (Byte)",
|
||||
"enable-blur-nsfw-content": "Enable sensitive content (NSFW) blurring",
|
||||
"enable-blur-sensitive-content": "Enable sensitive content blurring",
|
||||
"enable-memo-comments": "Enable memo comments",
|
||||
"enable-memo-location": "Enable memo location",
|
||||
"label": "Memo",
|
||||
|
|
@ -476,6 +476,7 @@
|
|||
"title": "Tag metadata",
|
||||
"description": "Assign display colors to tags instance-wide. Tag names are treated as anchored regex patterns.",
|
||||
"background-color": "Background color",
|
||||
"blur-content": "Blur content",
|
||||
"no-tags-configured": "No tag metadata configured.",
|
||||
"tag-name": "Tag name",
|
||||
"tag-name-placeholder": "e.g. work or project/.*",
|
||||
|
|
|
|||
|
|
@ -140,8 +140,8 @@
|
|||
},
|
||||
"memo": {
|
||||
"archived-at": "Archivado en",
|
||||
"click-to-hide-nsfw-content": "Haz clic para ocultar contenido sensible",
|
||||
"click-to-show-nsfw-content": "Haz clic para mostrar contenido sensible",
|
||||
"click-to-hide-sensitive-content": "Haz clic para ocultar contenido sensible",
|
||||
"click-to-show-sensitive-content": "Haz clic para mostrar contenido sensible",
|
||||
"code": "Código",
|
||||
"comment": {
|
||||
"self": "Comentarios",
|
||||
|
|
@ -410,7 +410,7 @@
|
|||
},
|
||||
"memo": {
|
||||
"content-length-limit": "Límite de longitud de contenido (Bytes)",
|
||||
"enable-blur-nsfw-content": "Habilitar difuminado de contenido sensible (NSFW)",
|
||||
"enable-blur-sensitive-content": "Habilitar difuminado de contenido sensible (NSFW)",
|
||||
"enable-memo-comments": "Habilitar comentarios en los memos",
|
||||
"enable-memo-location": "Habilitar ubicación del memo",
|
||||
"reactions": "Reacciones",
|
||||
|
|
|
|||
|
|
@ -140,8 +140,8 @@
|
|||
},
|
||||
"memo": {
|
||||
"archived-at": "آرشیو شده در",
|
||||
"click-to-hide-nsfw-content": "برای مخفی کردن محتوای حساس کلیک کنید",
|
||||
"click-to-show-nsfw-content": "برای نمایش محتوای حساس کلیک کنید",
|
||||
"click-to-hide-sensitive-content": "برای مخفی کردن محتوای حساس کلیک کنید",
|
||||
"click-to-show-sensitive-content": "برای نمایش محتوای حساس کلیک کنید",
|
||||
"code": "کد",
|
||||
"comment": {
|
||||
"self": "نظرات",
|
||||
|
|
@ -410,7 +410,7 @@
|
|||
},
|
||||
"memo": {
|
||||
"content-length-limit": "محدودیت طول محتوا (بایت)",
|
||||
"enable-blur-nsfw-content": "فعالسازی تار کردن محتوای حساس (NSFW)",
|
||||
"enable-blur-sensitive-content": "فعالسازی تار کردن محتوای حساس (NSFW)",
|
||||
"enable-memo-comments": "فعالسازی نظرات یادداشت",
|
||||
"enable-memo-location": "فعالسازی موقعیت یادداشت",
|
||||
"reactions": "واکنشها",
|
||||
|
|
|
|||
|
|
@ -140,8 +140,8 @@
|
|||
},
|
||||
"memo": {
|
||||
"archived-at": "Archivé le",
|
||||
"click-to-hide-nsfw-content": "Cliquez pour masquer le contenu sensible",
|
||||
"click-to-show-nsfw-content": "Cliquez pour afficher le contenu sensible",
|
||||
"click-to-hide-sensitive-content": "Cliquez pour masquer le contenu sensible",
|
||||
"click-to-show-sensitive-content": "Cliquez pour afficher le contenu sensible",
|
||||
"code": "Code",
|
||||
"comment": {
|
||||
"self": "Commentaires",
|
||||
|
|
@ -410,7 +410,7 @@
|
|||
},
|
||||
"memo": {
|
||||
"content-length-limit": "Limite de longueur du contenu (octets)",
|
||||
"enable-blur-nsfw-content": "Activer le flou pour le contenu sensible (NSFW)",
|
||||
"enable-blur-sensitive-content": "Activer le flou pour le contenu sensible (NSFW)",
|
||||
"enable-memo-comments": "Activer les commentaires sur les notes",
|
||||
"enable-memo-location": "Activer la localisation des notes",
|
||||
"reactions": "Réactions",
|
||||
|
|
|
|||
|
|
@ -140,8 +140,8 @@
|
|||
},
|
||||
"memo": {
|
||||
"archived-at": "Arquivada o",
|
||||
"click-to-hide-nsfw-content": "Preme para ocultar contido NSFW",
|
||||
"click-to-show-nsfw-content": "Preme para mostrar contido NSFW",
|
||||
"click-to-hide-sensitive-content": "Preme para ocultar contido NSFW",
|
||||
"click-to-show-sensitive-content": "Preme para mostrar contido NSFW",
|
||||
"code": "Código",
|
||||
"comment": {
|
||||
"self": "Comentarios",
|
||||
|
|
@ -410,7 +410,7 @@
|
|||
},
|
||||
"memo": {
|
||||
"content-length-limit": "Límite de lonxitude do contido (Byte)",
|
||||
"enable-blur-nsfw-content": "Activar esvaecemento do contido sensible (NSFW)",
|
||||
"enable-blur-sensitive-content": "Activar esvaecemento do contido sensible (NSFW)",
|
||||
"enable-memo-comments": "Activar comentarios nas notas",
|
||||
"enable-memo-location": "Activar localización nas notas",
|
||||
"reactions": "Reaccións",
|
||||
|
|
|
|||
|
|
@ -140,8 +140,8 @@
|
|||
},
|
||||
"memo": {
|
||||
"archived-at": "संग्रहीत किया गया",
|
||||
"click-to-hide-nsfw-content": "संवेदनशील सामग्री छुपाने के लिए क्लिक करें",
|
||||
"click-to-show-nsfw-content": "संवेदनशील सामग्री दिखाने के लिए क्लिक करें",
|
||||
"click-to-hide-sensitive-content": "संवेदनशील सामग्री छुपाने के लिए क्लिक करें",
|
||||
"click-to-show-sensitive-content": "संवेदनशील सामग्री दिखाने के लिए क्लिक करें",
|
||||
"code": "कोड",
|
||||
"comment": {
|
||||
"self": "टिप्पणियाँ",
|
||||
|
|
@ -410,7 +410,7 @@
|
|||
},
|
||||
"memo": {
|
||||
"content-length-limit": "सामग्री की अधिकतम लंबाई (बाइट)",
|
||||
"enable-blur-nsfw-content": "संवेदनशील (NSFW) सामग्री धुंधला करें सक्षम करें",
|
||||
"enable-blur-sensitive-content": "संवेदनशील (NSFW) सामग्री धुंधला करें सक्षम करें",
|
||||
"enable-memo-comments": "मेमो टिप्पणियाँ सक्षम करें",
|
||||
"enable-memo-location": "मेमो स्थान सक्षम करें",
|
||||
"reactions": "प्रतिक्रियाएँ",
|
||||
|
|
|
|||
|
|
@ -140,8 +140,8 @@
|
|||
},
|
||||
"memo": {
|
||||
"archived-at": "Arhivirano u",
|
||||
"click-to-hide-nsfw-content": "Klikni za skrivanje osjetljivog sadržaja",
|
||||
"click-to-show-nsfw-content": "Klikni za prikaz osjetljivog sadržaja",
|
||||
"click-to-hide-sensitive-content": "Klikni za skrivanje osjetljivog sadržaja",
|
||||
"click-to-show-sensitive-content": "Klikni za prikaz osjetljivog sadržaja",
|
||||
"code": "Kod",
|
||||
"comment": {
|
||||
"self": "Komentari",
|
||||
|
|
@ -410,7 +410,7 @@
|
|||
},
|
||||
"memo": {
|
||||
"content-length-limit": "Ograničenje duljine sadržaja (Bajt)",
|
||||
"enable-blur-nsfw-content": "Omogući zamućenje osjetljivog sadržaja (NSFW)",
|
||||
"enable-blur-sensitive-content": "Omogući zamućenje osjetljivog sadržaja (NSFW)",
|
||||
"enable-memo-comments": "Omogući komentare na memoima",
|
||||
"enable-memo-location": "Omogući lokaciju memoa",
|
||||
"reactions": "Reakcije",
|
||||
|
|
|
|||
|
|
@ -140,8 +140,8 @@
|
|||
},
|
||||
"memo": {
|
||||
"archived-at": "Archiválva:",
|
||||
"click-to-hide-nsfw-content": "Kattints a kényes tartalom elrejtéséhez",
|
||||
"click-to-show-nsfw-content": "Kattints a kényes tartalom megjelenítéséhez",
|
||||
"click-to-hide-sensitive-content": "Kattints a kényes tartalom elrejtéséhez",
|
||||
"click-to-show-sensitive-content": "Kattints a kényes tartalom megjelenítéséhez",
|
||||
"code": "Kód",
|
||||
"comment": {
|
||||
"self": "Hozzászólások",
|
||||
|
|
@ -410,7 +410,7 @@
|
|||
},
|
||||
"memo": {
|
||||
"content-length-limit": "Tartalom hosszának korlátja (bájt)",
|
||||
"enable-blur-nsfw-content": "Érzékeny (NSFW) tartalom elhomályosításának engedélyezése",
|
||||
"enable-blur-sensitive-content": "Érzékeny (NSFW) tartalom elhomályosításának engedélyezése",
|
||||
"enable-memo-comments": "Jegyzet hozzászólások engedélyezése",
|
||||
"enable-memo-location": "Jegyzet helyének engedélyezése",
|
||||
"reactions": "Reakciók",
|
||||
|
|
|
|||
|
|
@ -140,8 +140,8 @@
|
|||
},
|
||||
"memo": {
|
||||
"archived-at": "Diarsipkan pada",
|
||||
"click-to-hide-nsfw-content": "Klik untuk menyembunyikan konten NSFW",
|
||||
"click-to-show-nsfw-content": "Klik untuk menampilkan konten NSFW",
|
||||
"click-to-hide-sensitive-content": "Klik untuk menyembunyikan konten NSFW",
|
||||
"click-to-show-sensitive-content": "Klik untuk menampilkan konten NSFW",
|
||||
"code": "Kode",
|
||||
"comment": {
|
||||
"self": "Komentar",
|
||||
|
|
@ -410,7 +410,7 @@
|
|||
},
|
||||
"memo": {
|
||||
"content-length-limit": "Batas panjang konten (Byte)",
|
||||
"enable-blur-nsfw-content": "Aktifkan pengaburan konten sensitif (NSFW)",
|
||||
"enable-blur-sensitive-content": "Aktifkan pengaburan konten sensitif (NSFW)",
|
||||
"enable-memo-comments": "Aktifkan komentar memo",
|
||||
"enable-memo-location": "Aktifkan lokasi memo",
|
||||
"reactions": "Reaksi",
|
||||
|
|
|
|||
|
|
@ -140,8 +140,8 @@
|
|||
},
|
||||
"memo": {
|
||||
"archived-at": "Archiviato il",
|
||||
"click-to-hide-nsfw-content": "Clicca per nascondere contenuti sensibili",
|
||||
"click-to-show-nsfw-content": "Clicca per mostrare contenuti sensibili",
|
||||
"click-to-hide-sensitive-content": "Clicca per nascondere contenuti sensibili",
|
||||
"click-to-show-sensitive-content": "Clicca per mostrare contenuti sensibili",
|
||||
"code": "Codice",
|
||||
"comment": {
|
||||
"self": "Commenti",
|
||||
|
|
@ -410,7 +410,7 @@
|
|||
},
|
||||
"memo": {
|
||||
"content-length-limit": "Massima lunghezza contenuto (byte)",
|
||||
"enable-blur-nsfw-content": "Abilita sfocatura contenuti sensibili (NSFW)",
|
||||
"enable-blur-sensitive-content": "Abilita sfocatura contenuti sensibili (NSFW)",
|
||||
"enable-memo-comments": "Abilita commenti memo",
|
||||
"enable-memo-location": "Abilita posizione memo",
|
||||
"reactions": "Reazioni",
|
||||
|
|
|
|||
|
|
@ -140,8 +140,8 @@
|
|||
},
|
||||
"memo": {
|
||||
"archived-at": "アーカイブ:",
|
||||
"click-to-hide-nsfw-content": "クリックしてセンシティブ内容を隠す",
|
||||
"click-to-show-nsfw-content": "クリックしてセンシティブ内容を表示",
|
||||
"click-to-hide-sensitive-content": "クリックしてセンシティブ内容を隠す",
|
||||
"click-to-show-sensitive-content": "クリックしてセンシティブ内容を表示",
|
||||
"code": "コード",
|
||||
"comment": {
|
||||
"self": "コメント",
|
||||
|
|
@ -410,7 +410,7 @@
|
|||
},
|
||||
"memo": {
|
||||
"content-length-limit": "内容の最大長(バイト)",
|
||||
"enable-blur-nsfw-content": "センシティブ(NSFW)内容のぼかしを有効化",
|
||||
"enable-blur-sensitive-content": "センシティブ(NSFW)内容のぼかしを有効化",
|
||||
"enable-memo-comments": "メモコメントを有効化",
|
||||
"enable-memo-location": "メモの位置情報を有効化",
|
||||
"reactions": "リアクション",
|
||||
|
|
|
|||
|
|
@ -140,8 +140,8 @@
|
|||
},
|
||||
"memo": {
|
||||
"archived-at": "დაარქივებულია",
|
||||
"click-to-hide-nsfw-content": "დააწკაპუნეთ NSFW კონტენტის დასამალად",
|
||||
"click-to-show-nsfw-content": "დააწკაპუნეთ NSFW კონტენტის საჩვენებლად",
|
||||
"click-to-hide-sensitive-content": "დააწკაპუნეთ NSFW კონტენტის დასამალად",
|
||||
"click-to-show-sensitive-content": "დააწკაპუნეთ NSFW კონტენტის საჩვენებლად",
|
||||
"code": "კოდი",
|
||||
"comment": {
|
||||
"self": "კომენტარები",
|
||||
|
|
@ -410,7 +410,7 @@
|
|||
},
|
||||
"memo": {
|
||||
"content-length-limit": "კონტენტის სიგრძის ლიმიტი (ბაიტი)",
|
||||
"enable-blur-nsfw-content": "NSFW კონტენტის დაბუნდოვანების ჩართვა",
|
||||
"enable-blur-sensitive-content": "NSFW კონტენტის დაბუნდოვანების ჩართვა",
|
||||
"enable-memo-comments": "მემოზე კომენტარების ჩართვა",
|
||||
"enable-memo-location": "მემოს მდებარეობის ჩართვა",
|
||||
"reactions": "რეაქციები",
|
||||
|
|
|
|||
|
|
@ -140,8 +140,8 @@
|
|||
},
|
||||
"memo": {
|
||||
"archived-at": "보관된 날짜",
|
||||
"click-to-hide-nsfw-content": "민감한(성인) 콘텐츠 숨기기",
|
||||
"click-to-show-nsfw-content": "민감한(성인) 콘텐츠 보기",
|
||||
"click-to-hide-sensitive-content": "민감한(성인) 콘텐츠 숨기기",
|
||||
"click-to-show-sensitive-content": "민감한(성인) 콘텐츠 보기",
|
||||
"code": "코드",
|
||||
"comment": {
|
||||
"self": "댓글",
|
||||
|
|
@ -410,7 +410,7 @@
|
|||
},
|
||||
"memo": {
|
||||
"content-length-limit": "내용 길이 제한 (바이트)",
|
||||
"enable-blur-nsfw-content": "민감한(성인) 콘텐츠 블러 처리 활성화",
|
||||
"enable-blur-sensitive-content": "민감한(성인) 콘텐츠 블러 처리 활성화",
|
||||
"enable-memo-comments": "메모 댓글 활성화",
|
||||
"enable-memo-location": "메모 위치 활성화",
|
||||
"reactions": "반응",
|
||||
|
|
|
|||
|
|
@ -140,8 +140,8 @@
|
|||
},
|
||||
"memo": {
|
||||
"archived-at": "येथे संग्रहित",
|
||||
"click-to-hide-nsfw-content": "संवेदनशील सामग्री लपवण्यासाठी क्लिक करा",
|
||||
"click-to-show-nsfw-content": "संवेदनशील सामग्री दाखवण्यासाठी क्लिक करा",
|
||||
"click-to-hide-sensitive-content": "संवेदनशील सामग्री लपवण्यासाठी क्लिक करा",
|
||||
"click-to-show-sensitive-content": "संवेदनशील सामग्री दाखवण्यासाठी क्लिक करा",
|
||||
"code": "कोड",
|
||||
"comment": {
|
||||
"self": "टिप्पण्या",
|
||||
|
|
@ -410,7 +410,7 @@
|
|||
},
|
||||
"memo": {
|
||||
"content-length-limit": "सामग्रीची कमाल लांबी (बाइट)",
|
||||
"enable-blur-nsfw-content": "संवेदनशील (NSFW) सामग्री ब्लर करा सक्षम करा",
|
||||
"enable-blur-sensitive-content": "संवेदनशील (NSFW) सामग्री ब्लर करा सक्षम करा",
|
||||
"enable-memo-comments": "मेमो टिप्पण्या सक्षम करा",
|
||||
"enable-memo-location": "मेमो स्थान सक्षम करा",
|
||||
"reactions": "प्रतिक्रिया",
|
||||
|
|
|
|||
|
|
@ -140,8 +140,8 @@
|
|||
},
|
||||
"memo": {
|
||||
"archived-at": "Arkivert",
|
||||
"click-to-hide-nsfw-content": "Klikk for å skjule NSFW-innhold",
|
||||
"click-to-show-nsfw-content": "Klikk for å vise NSFW-innhold",
|
||||
"click-to-hide-sensitive-content": "Klikk for å skjule NSFW-innhold",
|
||||
"click-to-show-sensitive-content": "Klikk for å vise NSFW-innhold",
|
||||
"code": "Kode",
|
||||
"comment": {
|
||||
"self": "Kommentarer",
|
||||
|
|
@ -410,7 +410,7 @@
|
|||
},
|
||||
"memo": {
|
||||
"content-length-limit": "Maksimal innholdslengde (Byte)",
|
||||
"enable-blur-nsfw-content": "Slå på sløring av NSFW-innhold (legg til NSFW-tagger nedenfor)",
|
||||
"enable-blur-sensitive-content": "Slå på sløring av NSFW-innhold (legg til NSFW-tagger nedenfor)",
|
||||
"enable-memo-comments": "Slå på kommentarer for memoer",
|
||||
"enable-memo-location": "Slå på lokasjon for memoer",
|
||||
"reactions": "Reaksjoner",
|
||||
|
|
|
|||
|
|
@ -140,8 +140,8 @@
|
|||
},
|
||||
"memo": {
|
||||
"archived-at": "Gearchiveerd op",
|
||||
"click-to-hide-nsfw-content": "Klik om NSFW-inhoud te verbergen",
|
||||
"click-to-show-nsfw-content": "Klik om NSFW-inhoud te tonen",
|
||||
"click-to-hide-sensitive-content": "Klik om NSFW-inhoud te verbergen",
|
||||
"click-to-show-sensitive-content": "Klik om NSFW-inhoud te tonen",
|
||||
"code": "Code",
|
||||
"comment": {
|
||||
"self": "Opmerkingen",
|
||||
|
|
@ -410,7 +410,7 @@
|
|||
},
|
||||
"memo": {
|
||||
"content-length-limit": "Maximale inhoudslengte (Byte)",
|
||||
"enable-blur-nsfw-content": "NSFW-inhoud vervagen inschakelen",
|
||||
"enable-blur-sensitive-content": "NSFW-inhoud vervagen inschakelen",
|
||||
"enable-memo-comments": "Memo-opmerkingen inschakelen",
|
||||
"enable-memo-location": "Memo-locatie inschakelen",
|
||||
"reactions": "Reacties",
|
||||
|
|
|
|||
|
|
@ -141,8 +141,8 @@
|
|||
},
|
||||
"memo": {
|
||||
"archived-at": "Zarchiwizowano w dniu",
|
||||
"click-to-hide-nsfw-content": "Kliknij, aby ukryć treści NSFW",
|
||||
"click-to-show-nsfw-content": "Kliknij, aby pokazać treści NSFW",
|
||||
"click-to-hide-sensitive-content": "Kliknij, aby ukryć treści NSFW",
|
||||
"click-to-show-sensitive-content": "Kliknij, aby pokazać treści NSFW",
|
||||
"code": "Kod",
|
||||
"comment": {
|
||||
"self": "Komentarze",
|
||||
|
|
@ -411,7 +411,7 @@
|
|||
},
|
||||
"memo": {
|
||||
"content-length-limit": "Limit długości treści (Bajty)",
|
||||
"enable-blur-nsfw-content": "Włącz rozmycie treści NSFW",
|
||||
"enable-blur-sensitive-content": "Włącz rozmycie treści NSFW",
|
||||
"enable-memo-comments": "Włącz komentarze do notatek",
|
||||
"enable-memo-location": "Włącz lokalizację notatek",
|
||||
"reactions": "Reakcje",
|
||||
|
|
|
|||
|
|
@ -140,8 +140,8 @@
|
|||
},
|
||||
"memo": {
|
||||
"archived-at": "Arquivado em",
|
||||
"click-to-hide-nsfw-content": "Ocultar conteúdo impróprio",
|
||||
"click-to-show-nsfw-content": "Mostrar conteúdo impróprio",
|
||||
"click-to-hide-sensitive-content": "Ocultar conteúdo impróprio",
|
||||
"click-to-show-sensitive-content": "Mostrar conteúdo impróprio",
|
||||
"code": "Código",
|
||||
"comment": {
|
||||
"self": "Comentários",
|
||||
|
|
@ -410,7 +410,7 @@
|
|||
},
|
||||
"memo": {
|
||||
"content-length-limit": "Limite de tamanho do conteúdo (Bytes)",
|
||||
"enable-blur-nsfw-content": "Desfocar conteúdo impróprio (adicione as tags abaixo)",
|
||||
"enable-blur-sensitive-content": "Desfocar conteúdo impróprio (adicione as tags abaixo)",
|
||||
"enable-memo-comments": "Comentários nos memos",
|
||||
"enable-memo-location": "Marcador de localização",
|
||||
"reactions": "Reações",
|
||||
|
|
|
|||
|
|
@ -140,8 +140,8 @@
|
|||
},
|
||||
"memo": {
|
||||
"archived-at": "Arquivado em",
|
||||
"click-to-hide-nsfw-content": "Clique para ocultar conteúdo NSFW",
|
||||
"click-to-show-nsfw-content": "Clique para mostrar conteúdo NSFW",
|
||||
"click-to-hide-sensitive-content": "Clique para ocultar conteúdo NSFW",
|
||||
"click-to-show-sensitive-content": "Clique para mostrar conteúdo NSFW",
|
||||
"code": "Código",
|
||||
"comment": {
|
||||
"self": "Comentários",
|
||||
|
|
@ -410,7 +410,7 @@
|
|||
},
|
||||
"memo": {
|
||||
"content-length-limit": "Limite de comprimento do conteúdo (Bytes)",
|
||||
"enable-blur-nsfw-content": "Ativar desfoque de conteúdo sensível (NSFW)",
|
||||
"enable-blur-sensitive-content": "Ativar desfoque de conteúdo sensível (NSFW)",
|
||||
"enable-memo-comments": "Ativar comentários em memos",
|
||||
"enable-memo-location": "Ativar localização em memos",
|
||||
"reactions": "Reações",
|
||||
|
|
|
|||
|
|
@ -140,8 +140,8 @@
|
|||
},
|
||||
"memo": {
|
||||
"archived-at": "В архиве",
|
||||
"click-to-hide-nsfw-content": "Нажмите, чтобы скрыть контент 18+",
|
||||
"click-to-show-nsfw-content": "Нажмите, чтобы посмотреть",
|
||||
"click-to-hide-sensitive-content": "Нажмите, чтобы скрыть контент 18+",
|
||||
"click-to-show-sensitive-content": "Нажмите, чтобы посмотреть",
|
||||
"code": "Код",
|
||||
"comment": {
|
||||
"self": "Комментарии",
|
||||
|
|
@ -410,7 +410,7 @@
|
|||
},
|
||||
"memo": {
|
||||
"content-length-limit": "Макс. длина заметки (байт)",
|
||||
"enable-blur-nsfw-content": "\"Размывать\" заметки с тегами",
|
||||
"enable-blur-sensitive-content": "\"Размывать\" заметки с тегами",
|
||||
"enable-memo-comments": "Комментарии",
|
||||
"enable-memo-location": "Геометки",
|
||||
"reactions": "Реакции",
|
||||
|
|
|
|||
|
|
@ -141,8 +141,8 @@
|
|||
},
|
||||
"memo": {
|
||||
"archived-at": "Arhivirano ob",
|
||||
"click-to-hide-nsfw-content": "Kliknite za skrivanje NSFW vsebine",
|
||||
"click-to-show-nsfw-content": "Kliknite za prikaz NSFW vsebine",
|
||||
"click-to-hide-sensitive-content": "Kliknite za skrivanje NSFW vsebine",
|
||||
"click-to-show-sensitive-content": "Kliknite za prikaz NSFW vsebine",
|
||||
"code": "Koda",
|
||||
"comment": {
|
||||
"self": "Komentarji",
|
||||
|
|
@ -411,7 +411,7 @@
|
|||
},
|
||||
"memo": {
|
||||
"content-length-limit": "Omejitev dolžine vsebine (bajt)",
|
||||
"enable-blur-nsfw-content": "Omogoči zameglitev občutljive vsebine (NSFW)",
|
||||
"enable-blur-sensitive-content": "Omogoči zameglitev občutljive vsebine (NSFW)",
|
||||
"enable-memo-comments": "Omogoči komentarje na beležkah",
|
||||
"enable-memo-location": "Omogoči lokacijo beležk",
|
||||
"reactions": "Odzivi",
|
||||
|
|
|
|||
|
|
@ -140,8 +140,8 @@
|
|||
},
|
||||
"memo": {
|
||||
"archived-at": "Arkiverad",
|
||||
"click-to-hide-nsfw-content": "Klicka för att dölja känsligt innehåll (NSFW)",
|
||||
"click-to-show-nsfw-content": "Klicka för att visa känsligt innehåll (NSFW)",
|
||||
"click-to-hide-sensitive-content": "Klicka för att dölja känsligt innehåll (NSFW)",
|
||||
"click-to-show-sensitive-content": "Klicka för att visa känsligt innehåll (NSFW)",
|
||||
"code": "Kod",
|
||||
"comment": {
|
||||
"self": "Kommentarer",
|
||||
|
|
@ -410,7 +410,7 @@
|
|||
},
|
||||
"memo": {
|
||||
"content-length-limit": "Innehållslängdsgräns (Byte)",
|
||||
"enable-blur-nsfw-content": "Aktivera suddighet för känsligt innehåll (NSFW)",
|
||||
"enable-blur-sensitive-content": "Aktivera suddighet för känsligt innehåll (NSFW)",
|
||||
"enable-memo-comments": "Aktivera kommentarer på anteckningar",
|
||||
"enable-memo-location": "Aktivera plats för anteckning",
|
||||
"reactions": "Reaktioner",
|
||||
|
|
|
|||
|
|
@ -140,8 +140,8 @@
|
|||
},
|
||||
"memo": {
|
||||
"archived-at": "เก็บถาวรไว้ที่",
|
||||
"click-to-hide-nsfw-content": "คลิกเพื่อซ่อนเนื้อหาไม่เหมาะสม (NSFW)",
|
||||
"click-to-show-nsfw-content": "คลิกเพื่อแสดงเนื้อหาไม่เหมาะสม (NSFW)",
|
||||
"click-to-hide-sensitive-content": "คลิกเพื่อซ่อนเนื้อหาไม่เหมาะสม (NSFW)",
|
||||
"click-to-show-sensitive-content": "คลิกเพื่อแสดงเนื้อหาไม่เหมาะสม (NSFW)",
|
||||
"code": "โค้ด",
|
||||
"comment": {
|
||||
"self": "ความคิดเห็น",
|
||||
|
|
@ -410,7 +410,7 @@
|
|||
},
|
||||
"memo": {
|
||||
"content-length-limit": "จำกัดความยาวเนื้อหา (ไบต์)",
|
||||
"enable-blur-nsfw-content": "เปิดใช้งานการเบลอเนื้อหาไม่เหมาะสม (NSFW)",
|
||||
"enable-blur-sensitive-content": "เปิดใช้งานการเบลอเนื้อหาไม่เหมาะสม (NSFW)",
|
||||
"enable-memo-comments": "เปิดใช้งานความคิดเห็นในบันทึก",
|
||||
"enable-memo-location": "เปิดใช้งานตำแหน่งในบันทึก",
|
||||
"reactions": "ปฏิกิริยา",
|
||||
|
|
|
|||
|
|
@ -140,8 +140,8 @@
|
|||
},
|
||||
"memo": {
|
||||
"archived-at": "Arşivlenme tarihi",
|
||||
"click-to-hide-nsfw-content": "NSFW içeriği gizlemek için tıklayın",
|
||||
"click-to-show-nsfw-content": "NSFW içeriği göstermek için tıklayın",
|
||||
"click-to-hide-sensitive-content": "NSFW içeriği gizlemek için tıklayın",
|
||||
"click-to-show-sensitive-content": "NSFW içeriği göstermek için tıklayın",
|
||||
"code": "Kod",
|
||||
"comment": {
|
||||
"self": "Yorumlar",
|
||||
|
|
@ -410,7 +410,7 @@
|
|||
},
|
||||
"memo": {
|
||||
"content-length-limit": "İçerik uzunluğu sınırı (Bayt)",
|
||||
"enable-blur-nsfw-content": "NSFW içeriği bulanıklaştırmayı etkinleştir",
|
||||
"enable-blur-sensitive-content": "NSFW içeriği bulanıklaştırmayı etkinleştir",
|
||||
"enable-memo-comments": "Not yorumlarını etkinleştir",
|
||||
"enable-memo-location": "Not konumunu etkinleştir",
|
||||
"reactions": "Tepkiler",
|
||||
|
|
|
|||
|
|
@ -140,8 +140,8 @@
|
|||
},
|
||||
"memo": {
|
||||
"archived-at": "Архівовано о",
|
||||
"click-to-hide-nsfw-content": "Натисніть, щоб приховати NSFW-контент",
|
||||
"click-to-show-nsfw-content": "Натисніть, щоб показати NSFW-контент",
|
||||
"click-to-hide-sensitive-content": "Натисніть, щоб приховати NSFW-контент",
|
||||
"click-to-show-sensitive-content": "Натисніть, щоб показати NSFW-контент",
|
||||
"code": "Код",
|
||||
"comment": {
|
||||
"self": "Коментарі",
|
||||
|
|
@ -410,7 +410,7 @@
|
|||
},
|
||||
"memo": {
|
||||
"content-length-limit": "Обмеження довжини вмісту (байт)",
|
||||
"enable-blur-nsfw-content": "Увімкнути розмиття чутливого контенту (NSFW)",
|
||||
"enable-blur-sensitive-content": "Увімкнути розмиття чутливого контенту (NSFW)",
|
||||
"enable-memo-comments": "Увімкнути коментарі до нотаток",
|
||||
"enable-memo-location": "Увімкнути місцезнаходження нотаток",
|
||||
"reactions": "Реакції",
|
||||
|
|
|
|||
|
|
@ -140,8 +140,8 @@
|
|||
},
|
||||
"memo": {
|
||||
"archived-at": "Đã lưu trữ lúc",
|
||||
"click-to-hide-nsfw-content": "Nhấp để ẩn nội dung nhạy cảm",
|
||||
"click-to-show-nsfw-content": "Nhấp để hiện nội dung nhạy cảm",
|
||||
"click-to-hide-sensitive-content": "Nhấp để ẩn nội dung nhạy cảm",
|
||||
"click-to-show-sensitive-content": "Nhấp để hiện nội dung nhạy cảm",
|
||||
"code": "Mã",
|
||||
"comment": {
|
||||
"self": "Bình luận",
|
||||
|
|
@ -410,7 +410,7 @@
|
|||
},
|
||||
"memo": {
|
||||
"content-length-limit": "Giới hạn độ dài nội dung (Byte)",
|
||||
"enable-blur-nsfw-content": "Bật làm mờ nội dung nhạy cảm (NSFW)",
|
||||
"enable-blur-sensitive-content": "Bật làm mờ nội dung nhạy cảm (NSFW)",
|
||||
"enable-memo-comments": "Bật bình luận ghi chú",
|
||||
"enable-memo-location": "Bật vị trí ghi chú",
|
||||
"reactions": "Phản ứng",
|
||||
|
|
|
|||
|
|
@ -140,8 +140,8 @@
|
|||
},
|
||||
"memo": {
|
||||
"archived-at": "归档于",
|
||||
"click-to-hide-nsfw-content": "点击隐藏 NSFW 内容",
|
||||
"click-to-show-nsfw-content": "点击显示 NSFW 内容",
|
||||
"click-to-hide-sensitive-content": "点击隐藏 NSFW 内容",
|
||||
"click-to-show-sensitive-content": "点击显示 NSFW 内容",
|
||||
"code": "代码",
|
||||
"comment": {
|
||||
"self": "评论",
|
||||
|
|
@ -410,7 +410,7 @@
|
|||
},
|
||||
"memo": {
|
||||
"content-length-limit": "内容长度限制(字节)",
|
||||
"enable-blur-nsfw-content": "启用 NSFW 内容模糊处理(在下方添加 NSFW 标签)",
|
||||
"enable-blur-sensitive-content": "启用 NSFW 内容模糊处理(在下方添加 NSFW 标签)",
|
||||
"enable-memo-comments": "启用备忘录评论",
|
||||
"enable-memo-location": "启用备忘录定位",
|
||||
"reactions": "表态",
|
||||
|
|
|
|||
|
|
@ -140,8 +140,8 @@
|
|||
},
|
||||
"memo": {
|
||||
"archived-at": "封存於",
|
||||
"click-to-hide-nsfw-content": "點擊隱藏 NSFW 內容",
|
||||
"click-to-show-nsfw-content": "點擊顯示 NSFW 內容",
|
||||
"click-to-hide-sensitive-content": "點擊隱藏 NSFW 內容",
|
||||
"click-to-show-sensitive-content": "點擊顯示 NSFW 內容",
|
||||
"code": "程式碼",
|
||||
"comment": {
|
||||
"self": "評論",
|
||||
|
|
@ -410,7 +410,7 @@
|
|||
},
|
||||
"memo": {
|
||||
"content-length-limit": "內容長度限制(位元組)",
|
||||
"enable-blur-nsfw-content": "啟用 NSFW 內容模糊化(在下方添加 NSFW 標籤)",
|
||||
"enable-blur-sensitive-content": "啟用 NSFW 內容模糊化(在下方添加 NSFW 標籤)",
|
||||
"enable-memo-comments": "啟用備忘錄評論",
|
||||
"enable-memo-location": "啟用備忘錄定位",
|
||||
"reactions": "表情回應",
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ import type { Message } from "@bufbuild/protobuf";
|
|||
* Describes the file api/v1/instance_service.proto.
|
||||
*/
|
||||
export const file_api_v1_instance_service: GenFile = /*@__PURE__*/
|
||||
fileDesc("Ch1hcGkvdjEvaW5zdGFuY2Vfc2VydmljZS5wcm90bxIMbWVtb3MuYXBpLnYxImkKD0luc3RhbmNlUHJvZmlsZRIPCgd2ZXJzaW9uGAIgASgJEgwKBGRlbW8YAyABKAgSFAoMaW5zdGFuY2VfdXJsGAYgASgJEiEKBWFkbWluGAcgASgLMhIubWVtb3MuYXBpLnYxLlVzZXIiGwoZR2V0SW5zdGFuY2VQcm9maWxlUmVxdWVzdCLhEAoPSW5zdGFuY2VTZXR0aW5nEhEKBG5hbWUYASABKAlCA+BBCBJHCg9nZW5lcmFsX3NldHRpbmcYAiABKAsyLC5tZW1vcy5hcGkudjEuSW5zdGFuY2VTZXR0aW5nLkdlbmVyYWxTZXR0aW5nSAASRwoPc3RvcmFnZV9zZXR0aW5nGAMgASgLMiwubWVtb3MuYXBpLnYxLkluc3RhbmNlU2V0dGluZy5TdG9yYWdlU2V0dGluZ0gAElAKFG1lbW9fcmVsYXRlZF9zZXR0aW5nGAQgASgLMjAubWVtb3MuYXBpLnYxLkluc3RhbmNlU2V0dGluZy5NZW1vUmVsYXRlZFNldHRpbmdIABJBCgx0YWdzX3NldHRpbmcYBSABKAsyKS5tZW1vcy5hcGkudjEuSW5zdGFuY2VTZXR0aW5nLlRhZ3NTZXR0aW5nSAASUQoUbm90aWZpY2F0aW9uX3NldHRpbmcYBiABKAsyMS5tZW1vcy5hcGkudjEuSW5zdGFuY2VTZXR0aW5nLk5vdGlmaWNhdGlvblNldHRpbmdIABqHAwoOR2VuZXJhbFNldHRpbmcSIgoaZGlzYWxsb3dfdXNlcl9yZWdpc3RyYXRpb24YAiABKAgSHgoWZGlzYWxsb3dfcGFzc3dvcmRfYXV0aBgDIAEoCBIZChFhZGRpdGlvbmFsX3NjcmlwdBgEIAEoCRIYChBhZGRpdGlvbmFsX3N0eWxlGAUgASgJElIKDmN1c3RvbV9wcm9maWxlGAYgASgLMjoubWVtb3MuYXBpLnYxLkluc3RhbmNlU2V0dGluZy5HZW5lcmFsU2V0dGluZy5DdXN0b21Qcm9maWxlEh0KFXdlZWtfc3RhcnRfZGF5X29mZnNldBgHIAEoBRIgChhkaXNhbGxvd19jaGFuZ2VfdXNlcm5hbWUYCCABKAgSIAoYZGlzYWxsb3dfY2hhbmdlX25pY2tuYW1lGAkgASgIGkUKDUN1c3RvbVByb2ZpbGUSDQoFdGl0bGUYASABKAkSEwoLZGVzY3JpcHRpb24YAiABKAkSEAoIbG9nb191cmwYAyABKAkaugMKDlN0b3JhZ2VTZXR0aW5nEk4KDHN0b3JhZ2VfdHlwZRgBIAEoDjI4Lm1lbW9zLmFwaS52MS5JbnN0YW5jZVNldHRpbmcuU3RvcmFnZVNldHRpbmcuU3RvcmFnZVR5cGUSGQoRZmlsZXBhdGhfdGVtcGxhdGUYAiABKAkSHAoUdXBsb2FkX3NpemVfbGltaXRfbWIYAyABKAMSSAoJczNfY29uZmlnGAQgASgLMjUubWVtb3MuYXBpLnYxLkluc3RhbmNlU2V0dGluZy5TdG9yYWdlU2V0dGluZy5TM0NvbmZpZxqGAQoIUzNDb25maWcSFQoNYWNjZXNzX2tleV9pZBgBIAEoCRIZChFhY2Nlc3Nfa2V5X3NlY3JldBgCIAEoCRIQCghlbmRwb2ludBgDIAEoCRIOCgZyZWdpb24YBCABKAkSDgoGYnVja2V0GAUgASgJEhYKDnVzZV9wYXRoX3N0eWxlGAYgASgIIkwKC1N0b3JhZ2VUeXBlEhwKGFNUT1JBR0VfVFlQRV9VTlNQRUNJRklFRBAAEgwKCERBVEFCQVNFEAESCQoFTE9DQUwQAhIGCgJTMxADGokBChJNZW1vUmVsYXRlZFNldHRpbmcSIAoYZGlzcGxheV93aXRoX3VwZGF0ZV90aW1lGAIgASgIEhwKFGNvbnRlbnRfbGVuZ3RoX2xpbWl0GAMgASgFEiAKGGVuYWJsZV9kb3VibGVfY2xpY2tfZWRpdBgEIAEoCBIRCglyZWFjdGlvbnMYByADKAkaOwoLVGFnTWV0YWRhdGESLAoQYmFja2dyb3VuZF9jb2xvchgBIAEoCzISLmdvb2dsZS50eXBlLkNvbG9yGqgBCgtUYWdzU2V0dGluZxJBCgR0YWdzGAEgAygLMjMubWVtb3MuYXBpLnYxLkluc3RhbmNlU2V0dGluZy5UYWdzU2V0dGluZy5UYWdzRW50cnkaVgoJVGFnc0VudHJ5EgsKA2tleRgBIAEoCRI4CgV2YWx1ZRgCIAEoCzIpLm1lbW9zLmFwaS52MS5JbnN0YW5jZVNldHRpbmcuVGFnTWV0YWRhdGE6AjgBGrUCChNOb3RpZmljYXRpb25TZXR0aW5nEk0KBWVtYWlsGAEgASgLMj4ubWVtb3MuYXBpLnYxLkluc3RhbmNlU2V0dGluZy5Ob3RpZmljYXRpb25TZXR0aW5nLkVtYWlsU2V0dGluZxrOAQoMRW1haWxTZXR0aW5nEg8KB2VuYWJsZWQYASABKAgSEQoJc210cF9ob3N0GAIgASgJEhEKCXNtdHBfcG9ydBgDIAEoBRIVCg1zbXRwX3VzZXJuYW1lGAQgASgJEhUKDXNtdHBfcGFzc3dvcmQYBSABKAkSEgoKZnJvbV9lbWFpbBgGIAEoCRIRCglmcm9tX25hbWUYByABKAkSEAoIcmVwbHlfdG8YCCABKAkSDwoHdXNlX3RscxgJIAEoCBIPCgd1c2Vfc3NsGAogASgIImIKA0tleRITCg9LRVlfVU5TUEVDSUZJRUQQABILCgdHRU5FUkFMEAESCwoHU1RPUkFHRRACEhAKDE1FTU9fUkVMQVRFRBADEggKBFRBR1MQBBIQCgxOT1RJRklDQVRJT04QBTph6kFeChxtZW1vcy5hcGkudjEvSW5zdGFuY2VTZXR0aW5nEhtpbnN0YW5jZS9zZXR0aW5ncy97c2V0dGluZ30qEGluc3RhbmNlU2V0dGluZ3MyD2luc3RhbmNlU2V0dGluZ0IHCgV2YWx1ZSJPChlHZXRJbnN0YW5jZVNldHRpbmdSZXF1ZXN0EjIKBG5hbWUYASABKAlCJOBBAvpBHgocbWVtb3MuYXBpLnYxL0luc3RhbmNlU2V0dGluZyKJAQocVXBkYXRlSW5zdGFuY2VTZXR0aW5nUmVxdWVzdBIzCgdzZXR0aW5nGAEgASgLMh0ubWVtb3MuYXBpLnYxLkluc3RhbmNlU2V0dGluZ0ID4EECEjQKC3VwZGF0ZV9tYXNrGAIgASgLMhouZ29vZ2xlLnByb3RvYnVmLkZpZWxkTWFza0ID4EEBMtsDCg9JbnN0YW5jZVNlcnZpY2USfgoSR2V0SW5zdGFuY2VQcm9maWxlEicubWVtb3MuYXBpLnYxLkdldEluc3RhbmNlUHJvZmlsZVJlcXVlc3QaHS5tZW1vcy5hcGkudjEuSW5zdGFuY2VQcm9maWxlIiCC0+STAhoSGC9hcGkvdjEvaW5zdGFuY2UvcHJvZmlsZRKPAQoSR2V0SW5zdGFuY2VTZXR0aW5nEicubWVtb3MuYXBpLnYxLkdldEluc3RhbmNlU2V0dGluZ1JlcXVlc3QaHS5tZW1vcy5hcGkudjEuSW5zdGFuY2VTZXR0aW5nIjHaQQRuYW1lgtPkkwIkEiIvYXBpL3YxL3tuYW1lPWluc3RhbmNlL3NldHRpbmdzLyp9ErUBChVVcGRhdGVJbnN0YW5jZVNldHRpbmcSKi5tZW1vcy5hcGkudjEuVXBkYXRlSW5zdGFuY2VTZXR0aW5nUmVxdWVzdBodLm1lbW9zLmFwaS52MS5JbnN0YW5jZVNldHRpbmciUdpBE3NldHRpbmcsdXBkYXRlX21hc2uC0+STAjU6B3NldHRpbmcyKi9hcGkvdjEve3NldHRpbmcubmFtZT1pbnN0YW5jZS9zZXR0aW5ncy8qfUKsAQoQY29tLm1lbW9zLmFwaS52MUIUSW5zdGFuY2VTZXJ2aWNlUHJvdG9QAVowZ2l0aHViLmNvbS91c2VtZW1vcy9tZW1vcy9wcm90by9nZW4vYXBpL3YxO2FwaXYxogIDTUFYqgIMTWVtb3MuQXBpLlYxygIMTWVtb3NcQXBpXFYx4gIYTWVtb3NcQXBpXFYxXEdQQk1ldGFkYXRh6gIOTWVtb3M6OkFwaTo6VjFiBnByb3RvMw", [file_api_v1_user_service, file_google_api_annotations, file_google_api_client, file_google_api_field_behavior, file_google_api_resource, file_google_protobuf_field_mask, file_google_type_color]);
|
||||
fileDesc("Ch1hcGkvdjEvaW5zdGFuY2Vfc2VydmljZS5wcm90bxIMbWVtb3MuYXBpLnYxImkKD0luc3RhbmNlUHJvZmlsZRIPCgd2ZXJzaW9uGAIgASgJEgwKBGRlbW8YAyABKAgSFAoMaW5zdGFuY2VfdXJsGAYgASgJEiEKBWFkbWluGAcgASgLMhIubWVtb3MuYXBpLnYxLlVzZXIiGwoZR2V0SW5zdGFuY2VQcm9maWxlUmVxdWVzdCL3EAoPSW5zdGFuY2VTZXR0aW5nEhEKBG5hbWUYASABKAlCA+BBCBJHCg9nZW5lcmFsX3NldHRpbmcYAiABKAsyLC5tZW1vcy5hcGkudjEuSW5zdGFuY2VTZXR0aW5nLkdlbmVyYWxTZXR0aW5nSAASRwoPc3RvcmFnZV9zZXR0aW5nGAMgASgLMiwubWVtb3MuYXBpLnYxLkluc3RhbmNlU2V0dGluZy5TdG9yYWdlU2V0dGluZ0gAElAKFG1lbW9fcmVsYXRlZF9zZXR0aW5nGAQgASgLMjAubWVtb3MuYXBpLnYxLkluc3RhbmNlU2V0dGluZy5NZW1vUmVsYXRlZFNldHRpbmdIABJBCgx0YWdzX3NldHRpbmcYBSABKAsyKS5tZW1vcy5hcGkudjEuSW5zdGFuY2VTZXR0aW5nLlRhZ3NTZXR0aW5nSAASUQoUbm90aWZpY2F0aW9uX3NldHRpbmcYBiABKAsyMS5tZW1vcy5hcGkudjEuSW5zdGFuY2VTZXR0aW5nLk5vdGlmaWNhdGlvblNldHRpbmdIABqHAwoOR2VuZXJhbFNldHRpbmcSIgoaZGlzYWxsb3dfdXNlcl9yZWdpc3RyYXRpb24YAiABKAgSHgoWZGlzYWxsb3dfcGFzc3dvcmRfYXV0aBgDIAEoCBIZChFhZGRpdGlvbmFsX3NjcmlwdBgEIAEoCRIYChBhZGRpdGlvbmFsX3N0eWxlGAUgASgJElIKDmN1c3RvbV9wcm9maWxlGAYgASgLMjoubWVtb3MuYXBpLnYxLkluc3RhbmNlU2V0dGluZy5HZW5lcmFsU2V0dGluZy5DdXN0b21Qcm9maWxlEh0KFXdlZWtfc3RhcnRfZGF5X29mZnNldBgHIAEoBRIgChhkaXNhbGxvd19jaGFuZ2VfdXNlcm5hbWUYCCABKAgSIAoYZGlzYWxsb3dfY2hhbmdlX25pY2tuYW1lGAkgASgIGkUKDUN1c3RvbVByb2ZpbGUSDQoFdGl0bGUYASABKAkSEwoLZGVzY3JpcHRpb24YAiABKAkSEAoIbG9nb191cmwYAyABKAkaugMKDlN0b3JhZ2VTZXR0aW5nEk4KDHN0b3JhZ2VfdHlwZRgBIAEoDjI4Lm1lbW9zLmFwaS52MS5JbnN0YW5jZVNldHRpbmcuU3RvcmFnZVNldHRpbmcuU3RvcmFnZVR5cGUSGQoRZmlsZXBhdGhfdGVtcGxhdGUYAiABKAkSHAoUdXBsb2FkX3NpemVfbGltaXRfbWIYAyABKAMSSAoJczNfY29uZmlnGAQgASgLMjUubWVtb3MuYXBpLnYxLkluc3RhbmNlU2V0dGluZy5TdG9yYWdlU2V0dGluZy5TM0NvbmZpZxqGAQoIUzNDb25maWcSFQoNYWNjZXNzX2tleV9pZBgBIAEoCRIZChFhY2Nlc3Nfa2V5X3NlY3JldBgCIAEoCRIQCghlbmRwb2ludBgDIAEoCRIOCgZyZWdpb24YBCABKAkSDgoGYnVja2V0GAUgASgJEhYKDnVzZV9wYXRoX3N0eWxlGAYgASgIIkwKC1N0b3JhZ2VUeXBlEhwKGFNUT1JBR0VfVFlQRV9VTlNQRUNJRklFRBAAEgwKCERBVEFCQVNFEAESCQoFTE9DQUwQAhIGCgJTMxADGokBChJNZW1vUmVsYXRlZFNldHRpbmcSIAoYZGlzcGxheV93aXRoX3VwZGF0ZV90aW1lGAIgASgIEhwKFGNvbnRlbnRfbGVuZ3RoX2xpbWl0GAMgASgFEiAKGGVuYWJsZV9kb3VibGVfY2xpY2tfZWRpdBgEIAEoCBIRCglyZWFjdGlvbnMYByADKAkaUQoLVGFnTWV0YWRhdGESLAoQYmFja2dyb3VuZF9jb2xvchgBIAEoCzISLmdvb2dsZS50eXBlLkNvbG9yEhQKDGJsdXJfY29udGVudBgCIAEoCBqoAQoLVGFnc1NldHRpbmcSQQoEdGFncxgBIAMoCzIzLm1lbW9zLmFwaS52MS5JbnN0YW5jZVNldHRpbmcuVGFnc1NldHRpbmcuVGFnc0VudHJ5GlYKCVRhZ3NFbnRyeRILCgNrZXkYASABKAkSOAoFdmFsdWUYAiABKAsyKS5tZW1vcy5hcGkudjEuSW5zdGFuY2VTZXR0aW5nLlRhZ01ldGFkYXRhOgI4ARq1AgoTTm90aWZpY2F0aW9uU2V0dGluZxJNCgVlbWFpbBgBIAEoCzI+Lm1lbW9zLmFwaS52MS5JbnN0YW5jZVNldHRpbmcuTm90aWZpY2F0aW9uU2V0dGluZy5FbWFpbFNldHRpbmcazgEKDEVtYWlsU2V0dGluZxIPCgdlbmFibGVkGAEgASgIEhEKCXNtdHBfaG9zdBgCIAEoCRIRCglzbXRwX3BvcnQYAyABKAUSFQoNc210cF91c2VybmFtZRgEIAEoCRIVCg1zbXRwX3Bhc3N3b3JkGAUgASgJEhIKCmZyb21fZW1haWwYBiABKAkSEQoJZnJvbV9uYW1lGAcgASgJEhAKCHJlcGx5X3RvGAggASgJEg8KB3VzZV90bHMYCSABKAgSDwoHdXNlX3NzbBgKIAEoCCJiCgNLZXkSEwoPS0VZX1VOU1BFQ0lGSUVEEAASCwoHR0VORVJBTBABEgsKB1NUT1JBR0UQAhIQCgxNRU1PX1JFTEFURUQQAxIICgRUQUdTEAQSEAoMTk9USUZJQ0FUSU9OEAU6YepBXgocbWVtb3MuYXBpLnYxL0luc3RhbmNlU2V0dGluZxIbaW5zdGFuY2Uvc2V0dGluZ3Mve3NldHRpbmd9KhBpbnN0YW5jZVNldHRpbmdzMg9pbnN0YW5jZVNldHRpbmdCBwoFdmFsdWUiTwoZR2V0SW5zdGFuY2VTZXR0aW5nUmVxdWVzdBIyCgRuYW1lGAEgASgJQiTgQQL6QR4KHG1lbW9zLmFwaS52MS9JbnN0YW5jZVNldHRpbmciiQEKHFVwZGF0ZUluc3RhbmNlU2V0dGluZ1JlcXVlc3QSMwoHc2V0dGluZxgBIAEoCzIdLm1lbW9zLmFwaS52MS5JbnN0YW5jZVNldHRpbmdCA+BBAhI0Cgt1cGRhdGVfbWFzaxgCIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5GaWVsZE1hc2tCA+BBATLbAwoPSW5zdGFuY2VTZXJ2aWNlEn4KEkdldEluc3RhbmNlUHJvZmlsZRInLm1lbW9zLmFwaS52MS5HZXRJbnN0YW5jZVByb2ZpbGVSZXF1ZXN0Gh0ubWVtb3MuYXBpLnYxLkluc3RhbmNlUHJvZmlsZSIggtPkkwIaEhgvYXBpL3YxL2luc3RhbmNlL3Byb2ZpbGUSjwEKEkdldEluc3RhbmNlU2V0dGluZxInLm1lbW9zLmFwaS52MS5HZXRJbnN0YW5jZVNldHRpbmdSZXF1ZXN0Gh0ubWVtb3MuYXBpLnYxLkluc3RhbmNlU2V0dGluZyIx2kEEbmFtZYLT5JMCJBIiL2FwaS92MS97bmFtZT1pbnN0YW5jZS9zZXR0aW5ncy8qfRK1AQoVVXBkYXRlSW5zdGFuY2VTZXR0aW5nEioubWVtb3MuYXBpLnYxLlVwZGF0ZUluc3RhbmNlU2V0dGluZ1JlcXVlc3QaHS5tZW1vcy5hcGkudjEuSW5zdGFuY2VTZXR0aW5nIlHaQRNzZXR0aW5nLHVwZGF0ZV9tYXNrgtPkkwI1OgdzZXR0aW5nMiovYXBpL3YxL3tzZXR0aW5nLm5hbWU9aW5zdGFuY2Uvc2V0dGluZ3MvKn1CrAEKEGNvbS5tZW1vcy5hcGkudjFCFEluc3RhbmNlU2VydmljZVByb3RvUAFaMGdpdGh1Yi5jb20vdXNlbWVtb3MvbWVtb3MvcHJvdG8vZ2VuL2FwaS92MTthcGl2MaICA01BWKoCDE1lbW9zLkFwaS5WMcoCDE1lbW9zXEFwaVxWMeICGE1lbW9zXEFwaVxWMVxHUEJNZXRhZGF0YeoCDk1lbW9zOjpBcGk6OlYxYgZwcm90bzM", [file_api_v1_user_service, file_google_api_annotations, file_google_api_client, file_google_api_field_behavior, file_google_api_resource, file_google_protobuf_field_mask, file_google_type_color]);
|
||||
|
||||
/**
|
||||
* Instance profile message containing basic instance information.
|
||||
|
|
@ -419,6 +419,13 @@ export type InstanceSetting_TagMetadata = Message<"memos.api.v1.InstanceSetting.
|
|||
* @generated from field: google.type.Color background_color = 1;
|
||||
*/
|
||||
backgroundColor?: Color;
|
||||
|
||||
/**
|
||||
* Whether memos with this tag should have their content blurred.
|
||||
*
|
||||
* @generated from field: bool blur_content = 2;
|
||||
*/
|
||||
blurContent: boolean;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -435,6 +442,11 @@ export const InstanceSetting_TagMetadataSchema: GenMessage<InstanceSetting_TagMe
|
|||
*/
|
||||
export type InstanceSetting_TagsSetting = Message<"memos.api.v1.InstanceSetting.TagsSetting"> & {
|
||||
/**
|
||||
* Map of tag name pattern to tag metadata.
|
||||
* Each key is treated as an anchored regular expression (^pattern$),
|
||||
* so a single entry like "project/.*" matches all tags under that prefix.
|
||||
* Exact tag names are also valid (they are trivially valid regex patterns).
|
||||
*
|
||||
* @generated from field: map<string, memos.api.v1.InstanceSetting.TagMetadata> tags = 1;
|
||||
*/
|
||||
tags: { [key: string]: InstanceSetting_TagMetadata };
|
||||
|
|
|
|||
Loading…
Reference in New Issue