mirror of
https://github.com/usememos/memos.git
synced 2024-12-24 03:33:52 +03:00
fix: visibility translation (#2429)
* fix: visibility translation * refactor: remove useless file * feat: add visibility icon
This commit is contained in:
parent
82effea070
commit
035d71e07c
@ -1,41 +0,0 @@
|
||||
import { toLower } from "lodash-es";
|
||||
import Selector from "@/components/kit/Selector";
|
||||
import { VISIBILITY_SELECTOR_ITEMS } from "@/helpers/consts";
|
||||
import { useGlobalStore } from "@/store/module";
|
||||
import { useTranslate } from "@/utils/i18n";
|
||||
|
||||
interface Props {
|
||||
value: Visibility;
|
||||
onChange: (value: Visibility) => void;
|
||||
}
|
||||
|
||||
const MemoVisibilitySelector = (props: Props) => {
|
||||
const { value, onChange } = props;
|
||||
const t = useTranslate();
|
||||
const {
|
||||
state: { systemStatus },
|
||||
} = useGlobalStore();
|
||||
const memoVisibilityOptionSelectorItems = VISIBILITY_SELECTOR_ITEMS.map((item) => {
|
||||
return {
|
||||
value: item.value,
|
||||
text: t(`memo.visibility.${toLower(item.value) as Lowercase<typeof item.value>}`),
|
||||
};
|
||||
});
|
||||
|
||||
const handleMemoVisibilityOptionChanged = async (visibility: string) => {
|
||||
onChange(visibility as Visibility);
|
||||
};
|
||||
|
||||
return (
|
||||
<Selector
|
||||
className="visibility-selector"
|
||||
disabled={systemStatus.disablePublicMemos}
|
||||
tooltipTitle={t("memo.visibility.disabled")}
|
||||
value={value}
|
||||
dataSource={memoVisibilityOptionSelectorItems}
|
||||
handleValueChanged={handleMemoVisibilityOptionChanged}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export default MemoVisibilitySelector;
|
@ -462,8 +462,8 @@ const MemoEditor = (props: Props) => {
|
||||
}}
|
||||
>
|
||||
{VISIBILITY_SELECTOR_ITEMS.map((item) => (
|
||||
<Option key={item.value} value={item.value} className="whitespace-nowrap">
|
||||
{item.text}
|
||||
<Option key={item} value={item} className="whitespace-nowrap">
|
||||
{t(`memo.visibility.${item.toLowerCase() as Lowercase<typeof item>}`)}
|
||||
</Option>
|
||||
))}
|
||||
</Select>
|
||||
|
@ -7,6 +7,7 @@ import { useTranslate } from "@/utils/i18n";
|
||||
import AppearanceSelect from "../AppearanceSelect";
|
||||
import LearnMore from "../LearnMore";
|
||||
import LocaleSelect from "../LocaleSelect";
|
||||
import VisibilityIcon from "../VisibilityIcon";
|
||||
import "@/less/settings/preferences-section.less";
|
||||
|
||||
const PreferencesSection = () => {
|
||||
@ -16,12 +17,6 @@ const PreferencesSection = () => {
|
||||
const { appearance, locale } = globalStore.state;
|
||||
const { setting, localSetting } = userStore.state.user as User;
|
||||
const [telegramUserId, setTelegramUserId] = useState<string>(setting.telegramUserId);
|
||||
const visibilitySelectorItems = VISIBILITY_SELECTOR_ITEMS.map((item) => {
|
||||
return {
|
||||
value: item.value,
|
||||
text: t(`memo.visibility.${item.value.toLowerCase() as Lowercase<typeof item.value>}`),
|
||||
};
|
||||
});
|
||||
|
||||
const dailyReviewTimeOffsetOptions: number[] = [...Array(24).keys()];
|
||||
|
||||
@ -78,15 +73,16 @@ const PreferencesSection = () => {
|
||||
<Select
|
||||
className="!min-w-fit"
|
||||
value={setting.memoVisibility}
|
||||
startDecorator={<VisibilityIcon visibility={setting.memoVisibility} />}
|
||||
onChange={(_, visibility) => {
|
||||
if (visibility) {
|
||||
handleDefaultMemoVisibilityChanged(visibility);
|
||||
}
|
||||
}}
|
||||
>
|
||||
{visibilitySelectorItems.map((item) => (
|
||||
<Option key={item.value} value={item.value}>
|
||||
{item.text}
|
||||
{VISIBILITY_SELECTOR_ITEMS.map((item) => (
|
||||
<Option key={item} value={item} className="whitespace-nowrap">
|
||||
{t(`memo.visibility.${item.toLowerCase() as Lowercase<typeof item>}`)}
|
||||
</Option>
|
||||
))}
|
||||
</Select>
|
||||
|
@ -1,113 +0,0 @@
|
||||
import { Tooltip } from "@mui/joy";
|
||||
import { memo, useEffect, useRef } from "react";
|
||||
import useToggle from "react-use/lib/useToggle";
|
||||
import { useTranslate } from "@/utils/i18n";
|
||||
import Icon from "../Icon";
|
||||
import "@/less/common/selector.less";
|
||||
|
||||
interface SelectorItem {
|
||||
text: string;
|
||||
value: string;
|
||||
}
|
||||
|
||||
interface Props {
|
||||
className?: string;
|
||||
value: string;
|
||||
dataSource: SelectorItem[];
|
||||
handleValueChanged?: (value: string) => void;
|
||||
disabled?: boolean;
|
||||
tooltipTitle?: string;
|
||||
}
|
||||
|
||||
const nullItem = {
|
||||
text: "common.select" as const,
|
||||
value: "",
|
||||
};
|
||||
|
||||
const Selector: React.FC<Props> = (props: Props) => {
|
||||
const { className, dataSource, handleValueChanged, value, disabled, tooltipTitle } = props;
|
||||
const t = useTranslate();
|
||||
const [showSelector, toggleSelectorStatus] = useToggle(false);
|
||||
|
||||
const selectorElRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
let currentItem = { text: t(nullItem.text), value: nullItem.value };
|
||||
for (const d of dataSource) {
|
||||
if (d.value === value) {
|
||||
currentItem = d;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (showSelector) {
|
||||
const handleClickOutside = (event: MouseEvent) => {
|
||||
if (!selectorElRef.current?.contains(event.target as Node)) {
|
||||
toggleSelectorStatus(false);
|
||||
}
|
||||
};
|
||||
window.addEventListener("click", handleClickOutside, {
|
||||
capture: true,
|
||||
once: true,
|
||||
});
|
||||
}
|
||||
}, [showSelector]);
|
||||
|
||||
const handleItemClick = (item: SelectorItem) => {
|
||||
if (handleValueChanged) {
|
||||
handleValueChanged(item.value);
|
||||
}
|
||||
toggleSelectorStatus(false);
|
||||
};
|
||||
|
||||
const handleCurrentValueClick = (event: React.MouseEvent) => {
|
||||
if (disabled) return;
|
||||
event.stopPropagation();
|
||||
toggleSelectorStatus();
|
||||
};
|
||||
|
||||
return (
|
||||
<Tooltip title={tooltipTitle} hidden={!disabled}>
|
||||
<div className={`selector-wrapper ${className ?? ""} `} ref={selectorElRef}>
|
||||
<div
|
||||
className={`current-value-container ${showSelector ? "active" : ""} ${disabled && "selector-disabled"}`}
|
||||
onClick={handleCurrentValueClick}
|
||||
>
|
||||
{disabled && (
|
||||
<span className="lock-text">
|
||||
<Icon.Lock className="icon-img" />
|
||||
</span>
|
||||
)}
|
||||
<span className="value-text">{currentItem.text}</span>
|
||||
{!disabled && (
|
||||
<span className="arrow-text">
|
||||
<Icon.ChevronDown className="icon-img" />
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className={`items-wrapper ${showSelector ? "" : "!hidden"}`}>
|
||||
{dataSource.length > 0 ? (
|
||||
dataSource.map((d) => {
|
||||
return (
|
||||
<div
|
||||
className={`item-container ${d.value === value ? "selected" : ""}`}
|
||||
key={d.value}
|
||||
onClick={() => {
|
||||
handleItemClick(d);
|
||||
}}
|
||||
>
|
||||
{d.text}
|
||||
</div>
|
||||
);
|
||||
})
|
||||
) : (
|
||||
<p className="tip-text">{t("common.null")}</p>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</Tooltip>
|
||||
);
|
||||
};
|
||||
|
||||
export default memo(Selector);
|
@ -7,11 +7,7 @@ export const ANIMATION_DURATION = 200;
|
||||
// millisecond in a day
|
||||
export const DAILY_TIMESTAMP = 3600 * 24 * 1000;
|
||||
|
||||
export const VISIBILITY_SELECTOR_ITEMS = [
|
||||
{ text: "Private", value: "PRIVATE" },
|
||||
{ text: "Workspace", value: "PROTECTED" },
|
||||
{ text: "Public", value: "PUBLIC" },
|
||||
] as const;
|
||||
export const VISIBILITY_SELECTOR_ITEMS = ["PRIVATE", "PROTECTED", "PUBLIC"] as const;
|
||||
|
||||
// space width for tab action in editor
|
||||
export const TAB_SPACE_WIDTH = 2;
|
||||
|
@ -1,55 +0,0 @@
|
||||
.selector-wrapper {
|
||||
@apply flex flex-col justify-start items-start relative h-8;
|
||||
|
||||
> .current-value-container {
|
||||
@apply flex flex-row justify-between items-center w-full h-full rounded px-2 pr-1 bg-white dark:bg-zinc-700 dark:border-zinc-600 border cursor-pointer select-none;
|
||||
|
||||
&:hover,
|
||||
&.active {
|
||||
@apply bg-gray-100 dark:bg-zinc-700;
|
||||
}
|
||||
|
||||
> .value-text {
|
||||
@apply text-sm mr-0 truncate dark:text-gray-300;
|
||||
width: calc(100% - 20px);
|
||||
}
|
||||
|
||||
> .lock-text {
|
||||
@apply flex flex-row justify-center items-center w-4 shrink-0 mr-1;
|
||||
}
|
||||
|
||||
> .arrow-text {
|
||||
@apply flex flex-row justify-center items-center w-4 shrink-0;
|
||||
|
||||
> .icon-img {
|
||||
@apply w-4 h-auto opacity-40 dark:text-gray-300;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
> .items-wrapper {
|
||||
@apply flex flex-col justify-start items-start absolute top-full left-0 w-auto p-1 mt-1 -ml-2 bg-white dark:bg-zinc-800 dark:border-zinc-600 rounded-md overflow-y-auto z-1 hide-scrollbar;
|
||||
min-width: calc(100% + 16px);
|
||||
max-height: 256px;
|
||||
box-shadow: 0 0 8px 0 rgb(0 0 0 / 20%);
|
||||
|
||||
> .item-container {
|
||||
@apply flex flex-col justify-start items-start w-full px-3 text-sm select-none leading-8 cursor-pointer rounded whitespace-nowrap dark:text-gray-200 hover:bg-gray-100 dark:hover:bg-zinc-600;
|
||||
|
||||
&.selected {
|
||||
@apply text-green-600;
|
||||
}
|
||||
}
|
||||
|
||||
> .tip-text {
|
||||
@apply px-3 py-1 text-sm text-gray-600;
|
||||
}
|
||||
}
|
||||
|
||||
> .selector-disabled {
|
||||
@apply cursor-not-allowed;
|
||||
@apply pointer-events-none;
|
||||
|
||||
@apply bg-gray-200 dark:bg-zinc-700 dark:border-zinc-600 text-gray-400;
|
||||
}
|
||||
}
|
@ -156,8 +156,8 @@ const MemoDetail = () => {
|
||||
}}
|
||||
>
|
||||
{VISIBILITY_SELECTOR_ITEMS.map((item) => (
|
||||
<Option key={item.value} value={item.value} className="whitespace-nowrap">
|
||||
{item.text}
|
||||
<Option key={item} value={item} className="whitespace-nowrap">
|
||||
{t(`memo.visibility.${item.toLowerCase() as Lowercase<typeof item>}`)}
|
||||
</Option>
|
||||
))}
|
||||
</Select>
|
||||
|
Loading…
Reference in New Issue
Block a user