fix: visibility translation (#2429)

* fix: visibility translation

* refactor: remove useless file

* feat: add visibility icon
This commit is contained in:
Zexi 2023-10-23 08:06:59 +08:00 committed by GitHub
parent 82effea070
commit 035d71e07c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 10 additions and 227 deletions

View File

@ -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;

View File

@ -462,8 +462,8 @@ const MemoEditor = (props: Props) => {
}} }}
> >
{VISIBILITY_SELECTOR_ITEMS.map((item) => ( {VISIBILITY_SELECTOR_ITEMS.map((item) => (
<Option key={item.value} value={item.value} className="whitespace-nowrap"> <Option key={item} value={item} className="whitespace-nowrap">
{item.text} {t(`memo.visibility.${item.toLowerCase() as Lowercase<typeof item>}`)}
</Option> </Option>
))} ))}
</Select> </Select>

View File

@ -7,6 +7,7 @@ import { useTranslate } from "@/utils/i18n";
import AppearanceSelect from "../AppearanceSelect"; import AppearanceSelect from "../AppearanceSelect";
import LearnMore from "../LearnMore"; import LearnMore from "../LearnMore";
import LocaleSelect from "../LocaleSelect"; import LocaleSelect from "../LocaleSelect";
import VisibilityIcon from "../VisibilityIcon";
import "@/less/settings/preferences-section.less"; import "@/less/settings/preferences-section.less";
const PreferencesSection = () => { const PreferencesSection = () => {
@ -16,12 +17,6 @@ const PreferencesSection = () => {
const { appearance, locale } = globalStore.state; const { appearance, locale } = globalStore.state;
const { setting, localSetting } = userStore.state.user as User; const { setting, localSetting } = userStore.state.user as User;
const [telegramUserId, setTelegramUserId] = useState<string>(setting.telegramUserId); 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()]; const dailyReviewTimeOffsetOptions: number[] = [...Array(24).keys()];
@ -78,15 +73,16 @@ const PreferencesSection = () => {
<Select <Select
className="!min-w-fit" className="!min-w-fit"
value={setting.memoVisibility} value={setting.memoVisibility}
startDecorator={<VisibilityIcon visibility={setting.memoVisibility} />}
onChange={(_, visibility) => { onChange={(_, visibility) => {
if (visibility) { if (visibility) {
handleDefaultMemoVisibilityChanged(visibility); handleDefaultMemoVisibilityChanged(visibility);
} }
}} }}
> >
{visibilitySelectorItems.map((item) => ( {VISIBILITY_SELECTOR_ITEMS.map((item) => (
<Option key={item.value} value={item.value}> <Option key={item} value={item} className="whitespace-nowrap">
{item.text} {t(`memo.visibility.${item.toLowerCase() as Lowercase<typeof item>}`)}
</Option> </Option>
))} ))}
</Select> </Select>

View File

@ -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);

View File

@ -7,11 +7,7 @@ export const ANIMATION_DURATION = 200;
// millisecond in a day // millisecond in a day
export const DAILY_TIMESTAMP = 3600 * 24 * 1000; export const DAILY_TIMESTAMP = 3600 * 24 * 1000;
export const VISIBILITY_SELECTOR_ITEMS = [ export const VISIBILITY_SELECTOR_ITEMS = ["PRIVATE", "PROTECTED", "PUBLIC"] as const;
{ text: "Private", value: "PRIVATE" },
{ text: "Workspace", value: "PROTECTED" },
{ text: "Public", value: "PUBLIC" },
] as const;
// space width for tab action in editor // space width for tab action in editor
export const TAB_SPACE_WIDTH = 2; export const TAB_SPACE_WIDTH = 2;

View File

@ -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;
}
}

View File

@ -156,8 +156,8 @@ const MemoDetail = () => {
}} }}
> >
{VISIBILITY_SELECTOR_ITEMS.map((item) => ( {VISIBILITY_SELECTOR_ITEMS.map((item) => (
<Option key={item.value} value={item.value} className="whitespace-nowrap"> <Option key={item} value={item} className="whitespace-nowrap">
{item.text} {t(`memo.visibility.${item.toLowerCase() as Lowercase<typeof item>}`)}
</Option> </Option>
))} ))}
</Select> </Select>