feat: change main language to english

This commit is contained in:
email 2022-02-04 22:48:22 +08:00
parent 321183db52
commit 226e9c156a
32 changed files with 161 additions and 158 deletions

View File

@ -13,7 +13,7 @@ const AboutSiteDialog: React.FC<Props> = ({ destroy }: Props) => {
<>
<div className="dialog-header-container">
<p className="title-text">
<span className="icon-text">🤠</span> <b>Memos</b>
<span className="icon-text">🤠</span>About <b>Memos</b>
</p>
<button className="btn close-btn" onClick={handleCloseBtnClick}>
<img className="icon-img" src="/icons/close.svg" />
@ -21,9 +21,9 @@ const AboutSiteDialog: React.FC<Props> = ({ destroy }: Props) => {
</div>
<div className="dialog-content-container">
<p>
<a href="https://flomoapp.com">flomo</a>
Memos is an open source, self-hosted alternative to <a href="https://flomoapp.com">flomo</a>.
</p>
<p></p>
<p>Built with `Golang` and `React`.</p>
<br />
<p>
🏗 This project is working in progress, <br /> and very pleasure to welcome your{" "}

View File

@ -44,19 +44,19 @@ const ChangePasswordDialog: React.FC<Props> = ({ destroy }: Props) => {
const handleSaveBtnClick = async () => {
if (oldPassword === "" || newPassword === "" || newPasswordAgain === "") {
toastHelper.error("密码不能为空");
toastHelper.error("Please fill in all fields.");
return;
}
if (newPassword !== newPasswordAgain) {
toastHelper.error("新密码两次输入不一致");
toastHelper.error("New passwords do not match.");
setNewPasswordAgain("");
return;
}
const passwordValidResult = validate(newPassword, validateConfig);
if (!passwordValidResult.result) {
toastHelper.error("密码 " + passwordValidResult.reason);
toastHelper.error("Password " + passwordValidResult.reason);
return;
}
@ -64,13 +64,13 @@ const ChangePasswordDialog: React.FC<Props> = ({ destroy }: Props) => {
const isValid = await userService.checkPasswordValid(oldPassword);
if (!isValid) {
toastHelper.error("旧密码不匹配");
toastHelper.error("Old password is invalid.");
setOldPassword("");
return;
}
await userService.updatePassword(newPassword);
toastHelper.info("密码修改成功!");
toastHelper.info("Password changed.");
handleCloseBtnClick();
} catch (error: any) {
toastHelper.error(error);
@ -80,30 +80,30 @@ const ChangePasswordDialog: React.FC<Props> = ({ destroy }: Props) => {
return (
<>
<div className="dialog-header-container">
<p className="title-text"></p>
<p className="title-text">Change Password</p>
<button className="btn close-btn" onClick={handleCloseBtnClick}>
<img className="icon-img" src="/icons/close.svg" />
</button>
</div>
<div className="dialog-content-container">
<label className="form-label input-form-label">
<span className={"normal-text " + (oldPassword === "" ? "" : "not-null")}></span>
<span className={"normal-text " + (oldPassword === "" ? "" : "not-null")}>Old password</span>
<input type="password" value={oldPassword} onChange={handleOldPasswordChanged} />
</label>
<label className="form-label input-form-label">
<span className={"normal-text " + (newPassword === "" ? "" : "not-null")}></span>
<span className={"normal-text " + (newPassword === "" ? "" : "not-null")}>New passworld</span>
<input type="password" value={newPassword} onChange={handleNewPasswordChanged} />
</label>
<label className="form-label input-form-label">
<span className={"normal-text " + (newPasswordAgain === "" ? "" : "not-null")}></span>
<span className={"normal-text " + (newPasswordAgain === "" ? "" : "not-null")}>New password again</span>
<input type="password" value={newPasswordAgain} onChange={handleNewPasswordAgainChanged} />
</label>
<div className="btns-container">
<span className="btn cancel-btn" onClick={handleCloseBtnClick}>
Cancel
</span>
<span className="btn confirm-btn" onClick={handleSaveBtnClick}>
Save
</span>
</div>
</div>

View File

@ -27,29 +27,31 @@ const ConfirmResetOpenIdDialog: React.FC<Props> = ({ destroy }: Props) => {
try {
await userService.resetOpenId();
} catch (error) {
toastHelper.error("请求重置 Open API 失败");
toastHelper.error("Request reset open API failed.");
return;
}
toastHelper.success("重置成功!");
toastHelper.success("Reset open API succeeded.");
handleCloseBtnClick();
};
return (
<>
<div className="dialog-header-container">
<p className="title-text"> Open API</p>
<p className="title-text">Reset Open API</p>
<button className="btn close-btn" onClick={handleCloseBtnClick}>
<img className="icon-img" src="/icons/close.svg" />
</button>
</div>
<div className="dialog-content-container">
<p className="warn-text"> API API?</p>
<p className="warn-text">
The existing API will be invalidated and a new one will be generated, are you sure you want to reset?
</p>
<div className="btns-container">
<span className="btn cancel-btn" onClick={handleCloseBtnClick}>
Cancel
</span>
<span className={`btn confirm-btn ${resetBtnClickLoadingState.isLoading ? "loading" : ""}`} onClick={handleConfirmBtnClick}>
Reset!
</span>
</div>
</div>

View File

@ -40,7 +40,7 @@ const CreateShortcutDialog: React.FC<Props> = (props: Props) => {
const handleSaveBtnClick = async () => {
if (!title) {
toastHelper.error("标题不能为空!");
toastHelper.error("Title is required");
return;
}
@ -62,7 +62,7 @@ const CreateShortcutDialog: React.FC<Props> = (props: Props) => {
if (filters.length > 0) {
const lastFilter = filters[filters.length - 1];
if (lastFilter.value.value === "") {
toastHelper.info("先完善上一个过滤器吧");
toastHelper.info("Please fill in previous filter value");
return;
}
}
@ -90,7 +90,7 @@ const CreateShortcutDialog: React.FC<Props> = (props: Props) => {
<div className="dialog-header-container">
<p className="title-text">
<span className="icon-text">🔖</span>
{shortcutId ? "编辑检索" : "创建检索"}
{shortcutId ? "Edit Shortcut" : "Create Shortcut"}
</p>
<button className="btn close-btn" onClick={destroy}>
<img className="icon-img" src="/icons/close.svg" />
@ -98,11 +98,11 @@ const CreateShortcutDialog: React.FC<Props> = (props: Props) => {
</div>
<div className="dialog-content-container">
<div className="form-item-container input-form-container">
<span className="normal-text"></span>
<span className="normal-text">Title</span>
<input className="title-input" type="text" value={title} onChange={handleTitleInputChange} />
</div>
<div className="form-item-container filter-form-container">
<span className="normal-text"></span>
<span className="normal-text">Filter</span>
<div className="filters-wrapper">
{filters.map((f, index) => {
return (
@ -116,7 +116,7 @@ const CreateShortcutDialog: React.FC<Props> = (props: Props) => {
);
})}
<div className="create-filter-btn" onClick={handleAddFilterBenClick}>
New Filter
</div>
</div>
</div>
@ -125,10 +125,10 @@ const CreateShortcutDialog: React.FC<Props> = (props: Props) => {
<div></div>
<div className="btns-container">
<span className={`tip-text ${filters.length === 0 && "hidden"}`}>
Memo <strong>{shownMemoLength}</strong>
<strong>{shownMemoLength}</strong> eligible memo
</span>
<button className={`btn save-btn ${requestState.isLoading ? "requesting" : ""}`} onClick={handleSaveBtnClick}>
Save
</button>
</div>
</div>

View File

@ -106,11 +106,11 @@ const DailyMemoDiaryDialog: React.FC<Props> = (props: Props) => {
/>
{loadingState.isLoading ? (
<div className="tip-container">
<p className="tip-text">...</p>
<p className="tip-text">Loading...</p>
</div>
) : memos.length === 0 ? (
<div className="tip-container">
<p className="tip-text"></p>
<p className="tip-text">Oops, there is nothing.</p>
</div>
) : (
<div className="dailymemos-wrapper">

View File

@ -40,7 +40,7 @@ const DeletedMemo: React.FC<Props> = (props: Props) => {
try {
await memoService.restoreMemoById(memo.id);
handleDeletedMemoAction(memo.id);
toastHelper.info("恢复成功");
toastHelper.info("Restored successfully");
} catch (error: any) {
toastHelper.error(error.message);
}
@ -55,7 +55,7 @@ const DeletedMemo: React.FC<Props> = (props: Props) => {
return (
<div className={`memo-wrapper ${"memos-" + memo.id}`} onMouseLeave={handleMouseLeaveMemoWrapper}>
<div className="memo-top-wrapper">
<span className="time-text"> {memo.deletedAtStr}</span>
<span className="time-text">Deleted at {memo.deletedAtStr}</span>
<div className="btns-container">
<span className="btn more-action-btn">
<img className="icon-img" src="/icons/more.svg" />
@ -63,10 +63,10 @@ const DeletedMemo: React.FC<Props> = (props: Props) => {
<div className="more-action-btns-wrapper">
<div className="more-action-btns-container">
<span className="btn restore-btn" onClick={handleRestoreMemoClick}>
Restore
</span>
<span className={`btn delete-btn ${showConfirmDeleteBtn ? "final-confirm" : ""}`} onClick={handleDeleteMemoClick}>
{showConfirmDeleteBtn ? "确定删除!" : "完全删除"}
{showConfirmDeleteBtn ? "Delete!" : "Delete"}
</span>
</div>
</div>

View File

@ -176,12 +176,12 @@ const Editor = forwardRef((props: EditorProps, ref: React.ForwardedRef<EditorRef
<div className="btns-container">
<Only when={showCancelBtn}>
<button className="action-btn cancel-btn" onClick={handleCommonCancelBtnClick}>
Cancel editting
</button>
</Only>
<Only when={showConfirmBtn}>
<button className="action-btn confirm-btn" disabled={!editorRef.current?.value} onClick={handleCommonConfirmBtnClick}>
<span className="icon-text"></span>
Save <span className="icon-text"></span>
</button>
</Only>
</div>

View File

@ -93,19 +93,19 @@ const Memo: React.FC<Props> = (props: Props) => {
<div className="more-action-btns-wrapper">
<div className="more-action-btns-container">
<span className="btn" onClick={handleShowMemoStoryDialog}>
View Story
</span>
<span className="btn" onClick={handleMarkMemoClick}>
Mark
</span>
<span className="btn" onClick={handleGenMemoImageBtnClick}>
Share
</span>
<span className="btn" onClick={handleEditMemoClick}>
Edit
</span>
<span className={`btn delete-btn ${showConfirmDeleteBtn ? "final-confirm" : ""}`} onClick={handleDeleteMemoClick}>
{showConfirmDeleteBtn ? "确定删除!" : "删除"}
{showConfirmDeleteBtn ? "Delete!" : "Delete"}
</span>
</div>
</div>
@ -151,7 +151,7 @@ export function formatMemoContent(content: string) {
.replace(LINK_REG, "<a class='link' target='_blank' rel='noreferrer' href='$1'>$1</a>")
.replace(MEMO_LINK_REG, "<span class='memo-link-text' data-value='$2'>$1</span>");
// 中英文之间加空格
// Add space in english and chinese
if (shouldSplitMemoWord) {
content = content
.replace(/([\u4e00-\u9fa5])([A-Za-z0-9?.,;[\]]+)/g, "$1 $2")

View File

@ -148,7 +148,7 @@ const MemoCardDialog: React.FC<Props> = (props: Props) => {
</div>
{linkMemos.length > 0 ? (
<div className="linked-memos-wrapper">
<p className="normal-text"> {linkMemos.length} MEMO</p>
<p className="normal-text">{linkMemos.length} related MEMO</p>
{linkMemos.map((m) => {
const rawtext = parseHtmlToRawText(formatMemoContent(m.content)).replaceAll("\n", " ");
return (
@ -162,7 +162,7 @@ const MemoCardDialog: React.FC<Props> = (props: Props) => {
) : null}
{linkedMemos.length > 0 ? (
<div className="linked-memos-wrapper">
<p className="normal-text">{linkedMemos.length} MEMO</p>
<p className="normal-text">{linkedMemos.length} linked MEMO</p>
{linkedMemos.map((m) => {
const rawtext = parseHtmlToRawText(formatMemoContent(m.content)).replaceAll("\n", " ");
return (

View File

@ -140,7 +140,7 @@ const MemoEditor: React.FC<Props> = () => {
const handleSaveBtnClick = useCallback(async (content: string) => {
if (content === "") {
toastHelper.error("内容不能为空呀");
toastHelper.error("Content can't be empty");
return;
}
@ -270,7 +270,7 @@ const MemoEditor: React.FC<Props> = () => {
() => ({
className: "memo-editor",
initialContent: getEditorContentCache(),
placeholder: "现在的想法是...",
placeholder: "Any thoughts...",
showConfirmBtn: true,
showCancelBtn: showEditStatus,
onConfirmBtnClick: handleSaveBtnClick,
@ -282,7 +282,7 @@ const MemoEditor: React.FC<Props> = () => {
return (
<div className={"memo-editor-wrapper " + (showEditStatus ? "edit-ing" : "")}>
<p className={"tip-text " + (showEditStatus ? "" : "hidden")}>...</p>
<p className={"tip-text " + (showEditStatus ? "" : "hidden")}>Editting...</p>
<Editor
ref={editorRef}
{...editorConfig}

View File

@ -18,7 +18,7 @@ const MemoFilter: React.FC<FilterProps> = () => {
return (
<div className={`filter-query-container ${showFilter ? "" : "hidden"}`}>
<span className="tip-text"></span>
<span className="tip-text">Filter:</span>
<div
className={"filter-item-container " + (queryFilter ? "" : "hidden")}
onClick={() => {

View File

@ -83,7 +83,7 @@ const MemoList: React.FC<Props> = () => {
setFetchStatus(false);
})
.catch(() => {
toastHelper.error("😭 请求数据失败了");
toastHelper.error("😭 Refresh failed, please try again later.");
});
}, []);
@ -111,7 +111,13 @@ const MemoList: React.FC<Props> = () => {
))}
<div className="status-text-container">
<p className="status-text">
{isFetching ? "努力请求数据中..." : shownMemos.length === 0 ? "空空如也" : showMemoFilter ? "" : "所有数据加载完啦 🎉"}
{isFetching
? "Fetching data..."
: shownMemos.length === 0
? "Oops, there is nothing"
: showMemoFilter
? ""
: "Fetching completed 🎉"}
</p>
</div>
</div>

View File

@ -49,16 +49,16 @@ const MenuBtnsPopup: React.FC<Props> = (props: Props) => {
return (
<div className={`menu-btns-popup ${shownStatus ? "" : "hidden"}`} ref={popupElRef}>
<button className="btn action-btn" onClick={handleMyAccountBtnClick}>
<span className="icon">👤</span>
<span className="icon">👤</span> Settings
</button>
<button className="btn action-btn" onClick={handleMemosTrashBtnClick}>
<span className="icon">🗑</span>
<span className="icon">🗑</span> Recycle Bin
</button>
<button className="btn action-btn" onClick={handleAboutBtnClick}>
<span className="icon">🤠</span>
<span className="icon">🤠</span> About
</button>
<button className="btn action-btn" onClick={handleSignOutBtnClick}>
<span className="icon">👋</span> 退
<span className="icon">👋</span> Sign out
</button>
</div>
);

View File

@ -30,7 +30,7 @@ const MyAccountSection: React.FC<Props> = () => {
const handleConfirmEditUsernameBtnClick = async () => {
if (user.name === "guest") {
toastHelper.info("🈲 不要修改我的用户名");
toastHelper.info("Do not change my username");
return;
}
@ -40,7 +40,7 @@ const MyAccountSection: React.FC<Props> = () => {
const usernameValidResult = validate(username, validateConfig);
if (!usernameValidResult.result) {
toastHelper.error("用户名 " + usernameValidResult.reason);
toastHelper.error("Username " + usernameValidResult.reason);
return;
}
@ -48,13 +48,13 @@ const MyAccountSection: React.FC<Props> = () => {
const isUsable = await userService.checkUsernameUsable(username);
if (!isUsable) {
toastHelper.error("用户名无法使用");
toastHelper.error("Username is not available");
return;
}
await userService.updateUsername(username);
await userService.doSignIn();
toastHelper.info("修改成功~");
toastHelper.info("Username changed");
} catch (error: any) {
toastHelper.error(error.message);
}
@ -62,7 +62,7 @@ const MyAccountSection: React.FC<Props> = () => {
const handleChangePasswordBtnClick = () => {
if (user.name === "guest") {
toastHelper.info("🈲 不要修改我的密码");
toastHelper.info("Do not change my password");
return;
}
@ -81,21 +81,21 @@ const MyAccountSection: React.FC<Props> = () => {
return (
<>
<div className="section-container account-section-container">
<p className="title-text"></p>
<p className="title-text">Account Information</p>
<label className="form-label input-form-label">
<span className="normal-text">ID</span>
<span className="normal-text">ID:</span>
<span className="normal-text">{user.id}</span>
</label>
<label className="form-label input-form-label">
<span className="normal-text"></span>
<span className="normal-text">Created at:</span>
<span className="normal-text">{utils.getDateString(user.createdAt)}</span>
</label>
<label className="form-label input-form-label username-label">
<span className="normal-text"></span>
<span className="normal-text">Username:</span>
<input type="text" value={username} onChange={handleUsernameChanged} />
<div className={`btns-container ${username === user.name ? "hidden" : ""}`} onClick={handlePreventDefault}>
<span className="btn confirm-btn" onClick={handleConfirmEditUsernameBtnClick}>
Save
</span>
<span
className="btn cancel-btn"
@ -103,25 +103,25 @@ const MyAccountSection: React.FC<Props> = () => {
setUsername(user.name);
}}
>
Cancel
</span>
</div>
</label>
<label className="form-label password-label">
<span className="normal-text"></span>
<span className="normal-text">Password:</span>
<span className="btn" onClick={handleChangePasswordBtnClick}>
Change It
</span>
</label>
</div>
<div className="section-container openapi-section-container">
<p className="title-text">Open API</p>
<p className="title-text">Open API (Experimental feature)</p>
<p className="value-text">{openAPIRoute}</p>
<span className="reset-btn" onClick={handleResetOpenIdBtnClick}>
API
Reset API
</span>
<div className="usage-guide-container">
<p className="title-text">使</p>
<p className="title-text">Usage guide:</p>
<pre>{`POST ${openAPIRoute}\nContent-type: application/json\n{\n "content": "Hello, #memos ${window.location.origin}"\n}`}</pre>
</div>
</div>

View File

@ -11,7 +11,7 @@ const PreferencesSection: React.FC<Props> = () => {
const { globalState } = useContext(appContext);
const { useTinyUndoHistoryCache, shouldHideImageUrl, shouldSplitMemoWord, shouldUseMarkdownParser } = globalState;
const demoMemoContent = "👋 你好呀欢迎使用memos!\n* ✨ **开源项目**\n* 😋 精美且细节的视觉样式;\n* 📑 体验优良的交互逻辑;";
const demoMemoContent = "👋 Hiya, welcome to memos!\n* ✨ **Open source project**;\n* 😋 What do you think;\n* 📑 Tell me something plz;";
const handleOpenTinyUndoChanged = () => {
globalStateService.setAppSetting({
@ -65,29 +65,29 @@ const PreferencesSection: React.FC<Props> = () => {
return (
<>
<div className="section-container preferences-section-container">
<p className="title-text">Memo </p>
<p className="title-text">Memo Display</p>
<div
className="demo-content-container memo-content-text"
dangerouslySetInnerHTML={{ __html: formatMemoContent(demoMemoContent) }}
></div>
<label className="form-label checkbox-form-label" onClick={handleSplitWordsValueChanged}>
<span className="normal-text"></span>
<label className="form-label checkbox-form-label hidden" onClick={handleSplitWordsValueChanged}>
<span className="normal-text">Auto-space in English and Chinese</span>
<img className="icon-img" src={shouldSplitMemoWord ? "/icons/checkbox-active.svg" : "/icons/checkbox.svg"} />
</label>
<label className="form-label checkbox-form-label" onClick={handleUseMarkdownParserChanged}>
<span className="normal-text"> markdown </span>
<span className="normal-text">Partial markdown format parsing</span>
<img className="icon-img" src={shouldUseMarkdownParser ? "/icons/checkbox-active.svg" : "/icons/checkbox.svg"} />
</label>
<label className="form-label checkbox-form-label" onClick={handleHideImageUrlValueChanged}>
<span className="normal-text"></span>
<span className="normal-text">Hide image url</span>
<img className="icon-img" src={shouldHideImageUrl ? "/icons/checkbox-active.svg" : "/icons/checkbox.svg"} />
</label>
</div>
<div className="section-container preferences-section-container">
<p className="title-text"></p>
<p className="title-text">Editor Extensions</p>
<label className="form-label checkbox-form-label" onClick={handleOpenTinyUndoChanged}>
<span className="normal-text">
{" "}
Use{" "}
<a target="_blank" href="https://github.com/boojack/tiny-undo" onClick={(e) => e.stopPropagation()} rel="noreferrer">
tiny-undo
</a>
@ -96,13 +96,13 @@ const PreferencesSection: React.FC<Props> = () => {
</label>
</div>
<div className="section-container">
<p className="title-text"></p>
<p className="title-text">Others</p>
<div className="w-full flex flex-row justify-start items-center">
<button className="px-2 py-1 border rounded text-base hover:opacity-80" onClick={handleExportBtnClick}>
(JSON)
Export data as JSON
</button>
<button className="btn format-btn hidden" onClick={handleFormatMemosBtnClick}>
Format Data
</button>
</div>
</div>

View File

@ -43,8 +43,8 @@ const PreviewImageDialog: React.FC<Props> = ({ destroy, imgUrl }: Props) => {
<div className="img-container">
<img className={imgWidth <= 0 ? "hidden" : ""} ref={imgRef} width={imgWidth + "%"} src={imgUrl} />
<span className={"loading-text " + (imgWidth === -1 ? "" : "hidden")}>...</span>
<span className={"loading-text " + (imgWidth === 0 ? "" : "hidden")}>😟 </span>
<span className={"loading-text " + (imgWidth === -1 ? "" : "hidden")}>Loading image...</span>
<span className={"loading-text " + (imgWidth === 0 ? "" : "hidden")}>😟 Failed to load image</span>
</div>
<div className="action-btns-container">

View File

@ -36,7 +36,7 @@ const SearchBar: React.FC<Props> = () => {
<div className="quickly-action-container">
<p className="title-text">QUICKLY FILTER</p>
<div className="section-container types-container">
<span className="section-text">:</span>
<span className="section-text">Type:</span>
<div className="values-container">
{memoSpecialTypes.map((t, idx) => {
return (

View File

@ -65,7 +65,7 @@ const ShareMemoImageDialog: React.FC<Props> = (props: Props) => {
<>
<div className="dialog-header-container">
<p className="title-text">
<span className="icon-text">🥰</span> Memo
<span className="icon-text">🥰</span>Share Memo
</p>
<button className="btn close-btn" onClick={handleCloseBtnClick}>
<img className="icon-img" src="/icons/close.svg" />
@ -73,7 +73,7 @@ const ShareMemoImageDialog: React.FC<Props> = (props: Props) => {
</div>
<div className="dialog-content-container">
<div className={`tip-words-container ${shortcutImgUrl ? "finish" : "loading"}`}>
<p className="tip-text">{shortcutImgUrl ? "右键或长按即可保存图片 👇" : "图片生成中..."}</p>
<p className="tip-text">{shortcutImgUrl ? "Right click or long press to save image 👇" : "Generating the screenshot..."}</p>
</div>
<div className="memo-container" ref={memoElRef}>
<Only when={shortcutImgUrl !== ""}>

View File

@ -37,7 +37,7 @@ const ShortcutList: React.FC<Props> = () => {
return (
<div className="shortcuts-wrapper">
<p className="title-text">
<span className="normal-text"></span>
<span className="normal-text">Shortcuts</span>
<span className="btn" onClick={() => showCreateQueryDialog()}>
+
</span>
@ -45,7 +45,7 @@ const ShortcutList: React.FC<Props> = () => {
<Only when={loadingState.isSucceed && sortedShortcuts.length === 0}>
<div className="create-shortcut-btn-container">
<span className="btn" onClick={() => showCreateQueryDialog()}>
New shortcut
</span>
</div>
</Only>
@ -147,17 +147,17 @@ const ShortcutContainer: React.FC<ShortcutContainerProps> = (props: ShortcutCont
<div className={`action-btns-wrapper ${showActionBtns ? "" : "hidden"}`} onMouseLeave={handleActionBtnContainerMouseLeave}>
<div className="action-btns-container">
<span className="btn" onClick={handlePinQueryBtnClick}>
{shortcut.rowStatus === "ARCHIVED" ? "取消置顶" : "置顶"}
{shortcut.rowStatus === "ARCHIVED" ? "Unpin" : "Pin"}
</span>
<span className="btn" onClick={handleEditQueryBtnClick}>
Edit
</span>
<span
className={`btn delete-btn ${showConfirmDeleteBtn ? "final-confirm" : ""}`}
onClick={handleDeleteMemoClick}
onMouseLeave={handleDeleteBtnMouseLeave}
>
{showConfirmDeleteBtn ? "确定删除!" : "删除"}
{showConfirmDeleteBtn ? "Delete!" : "Delete"}
</span>
</div>
</div>

View File

@ -70,14 +70,14 @@ const TagList: React.FC<Props> = () => {
return (
<div className="tags-wrapper">
<p className="title-text"></p>
<p className="title-text">Tags</p>
<div className="tags-container">
{tags.map((t, idx) => (
<TagItemContainer key={t.text + "-" + idx} tag={t} tagQuery={tagQuery} />
))}
<Only when={tags.length < 5 && memoService.initialized}>
<p className="tag-tip-container">
<span className="code-text"># Tag </span>~
Enter <span className="code-text"># Tag </span> to create a tag
</p>
</Only>
</div>

View File

@ -58,7 +58,7 @@ const DatePicker: React.FC<DatePickerProps> = (props: DatePickerProps) => {
<img className="icon-img" src="/icons/arrow-left.svg" />
</span>
<span className="normal-text">
{firstDate.getFullYear()} {firstDate.getMonth() + 1}
{firstDate.getFullYear()}/{firstDate.getMonth() + 1}
</span>
<span className="btn-text" onClick={() => handleChangeMonthBtnClick(1)}>
<img className="icon-img" src="/icons/arrow-right.svg" />
@ -66,13 +66,13 @@ const DatePicker: React.FC<DatePickerProps> = (props: DatePickerProps) => {
</div>
<div className="date-picker-day-container">
<div className="date-picker-day-header">
<span className="day-item"></span>
<span className="day-item"></span>
<span className="day-item"></span>
<span className="day-item"></span>
<span className="day-item"></span>
<span className="day-item"></span>
<span className="day-item"></span>
<span className="day-item">Mon</span>
<span className="day-item">Tue</span>
<span className="day-item">Web</span>
<span className="day-item">Thu</span>
<span className="day-item">Fri</span>
<span className="day-item">Sat</span>
<span className="day-item">Sun</span>
</div>
{dayList.map((d) => {

View File

@ -15,7 +15,7 @@ interface Props {
}
const nullItem = {
text: "请选择",
text: "Select",
value: "",
};

View File

@ -1,23 +1,23 @@
// 移动端样式适配额外类名
// mobile style addtion classname
export const SHOW_SIDERBAR_MOBILE_CLASSNAME = "mobile-show-sidebar";
// 默认动画持续时长
// default animation duration
export const ANIMATION_DURATION = 200;
// toast 动画持续时长
// toast animation duration
export const TOAST_ANIMATION_DURATION = 400;
// 一天的毫秒数
// millisecond in a day
export const DAILY_TIMESTAMP = 3600 * 24 * 1000;
// 标签 正则
// tag regex
export const TAG_REG = /#\s?(.+?)\s/g;
// URL 正则
// URL regex
export const LINK_REG = /(https?:\/\/[^\s<\\*>']+)/g;
// 图片 正则
// image regex
export const IMAGE_URL_REG = /([^\s<\\*>']+\.(jpeg|jpg|gif|png|svg))/g;
// memo 关联正则
// linked memo regex
export const MEMO_LINK_REG = /\[@(.+?)\]\((.+?)\)/g;

View File

@ -1,68 +1,68 @@
import { IMAGE_URL_REG, LINK_REG, MEMO_LINK_REG, TAG_REG } from "./consts";
export const relationConsts = [
{ text: "", value: "AND" },
{ text: "", value: "OR" },
{ text: "And", value: "AND" },
{ text: "Or", value: "OR" },
];
export const filterConsts = {
TAG: {
text: "Tag",
value: "TAG",
text: "标签",
operators: [
{
text: "包括",
text: "Contains",
value: "CONTAIN",
},
{
text: "排除",
text: "Does not contain",
value: "NOT_CONTAIN",
},
],
},
TYPE: {
text: "Type",
value: "TYPE",
text: "类型",
operators: [
{
text: "Is",
value: "IS",
text: "是",
},
{
text: "Is not",
value: "IS_NOT",
text: "不是",
},
],
values: [
{
text: "Connected",
value: "CONNECTED",
text: "有关联",
},
{
text: "No tags",
value: "NOT_TAGGED",
text: "无标签",
},
{
text: "Has links",
value: "LINKED",
text: "有超链接",
},
{
text: "Has images",
value: "IMAGED",
text: "有图片",
},
],
},
TEXT: {
text: "Text",
value: "TEXT",
text: "文本",
operators: [
{
text: "Contain",
value: "CONTAIN",
text: "包括",
},
{
text: "Does not contain",
value: "NOT_CONTAIN",
text: "排除",
},
],
},

View File

@ -4,13 +4,10 @@ import { InputAction } from "tiny-undo";
* Define storage data type
*/
interface StorageData {
// 编辑器输入缓存内容
// Editor content cache
editorContentCache: string;
// 分词开关
shouldSplitMemoWord: boolean;
// 是否隐藏图片链接地址
shouldHideImageUrl: boolean;
// markdown 解析开关
shouldUseMarkdownParser: boolean;
// Editor setting

View File

@ -1,15 +1,15 @@
// 验证器
// * 主要用于验证表单
// Validator
// * use for validating form data
const chineseReg = /[\u3000\u3400-\u4DBF\u4E00-\u9FFF]/;
export interface ValidatorConfig {
// 最小长度
// min length
minLength: number;
// 最大长度
// max length
maxLength: number;
// 无空格
// no space
noSpace: boolean;
// 无中文
// no chinese
noChinese: boolean;
}
@ -18,7 +18,7 @@ export function validate(text: string, config: Partial<ValidatorConfig>): { resu
if (text.length < config.minLength) {
return {
result: false,
reason: "长度过短",
reason: "Too short",
};
}
}
@ -27,7 +27,7 @@ export function validate(text: string, config: Partial<ValidatorConfig>): { resu
if (text.length > config.maxLength) {
return {
result: false,
reason: "长度超出",
reason: "Too long",
};
}
}
@ -35,14 +35,14 @@ export function validate(text: string, config: Partial<ValidatorConfig>): { resu
if (config.noSpace && text.includes(" ")) {
return {
result: false,
reason: "不应含有空格",
reason: "Don't allow space",
};
}
if (config.noChinese && chineseReg.test(text)) {
return {
result: false,
reason: "不应含有中文字符",
reason: "Don't allow chinese",
};
}

View File

@ -15,8 +15,8 @@ export interface Store<S extends State, A extends Action> {
}
/**
* Redux
* @param preloadedState state
* Toy-Redux
* @param preloadedState initial state
* @param reducer reducer pure function
* @returns store
*/

View File

@ -114,13 +114,13 @@ const MemoTrash: React.FC<Props> = () => {
<img className="icon-img" src="/icons/menu.svg" alt="menu" />
</button>
</Only>
<span className="normal-text"></span>
<span className="normal-text">Recycle Bin</span>
</div>
</div>
<MemoFilter />
{loadingState.isLoading ? (
<div className="tip-text-container">
<p className="tip-text">...</p>
<p className="tip-text">fetching data...</p>
</div>
) : deletedMemos.length === 0 ? (
<div className="tip-text-container">

View File

@ -30,7 +30,7 @@ const Setting: React.FC<Props> = () => {
<img className="icon-img" src="/icons/menu.svg" alt="menu" />
</button>
</Only>
<span className="normal-text"></span>
<span className="normal-text">Settings</span>
</div>
</div>

View File

@ -55,13 +55,13 @@ const Signin: React.FC<Props> = () => {
const usernameValidResult = validate(username, validateConfig);
if (!usernameValidResult.result) {
toastHelper.error("用户名 " + usernameValidResult.reason);
toastHelper.error("Username: " + usernameValidResult.reason);
return;
}
const passwordValidResult = validate(password, validateConfig);
if (!passwordValidResult.result) {
toastHelper.error("密码 " + passwordValidResult.reason);
toastHelper.error("Password: " + passwordValidResult.reason);
return;
}
@ -77,7 +77,7 @@ const Signin: React.FC<Props> = () => {
if (user) {
locationService.replaceHistory("/");
} else {
toastHelper.error("😟 登录失败");
toastHelper.error("😟 Login failed");
}
} catch (error: any) {
console.error(error);
@ -107,7 +107,7 @@ const Signin: React.FC<Props> = () => {
if (user) {
locationService.replaceHistory("/");
} else {
toastHelper.error("😟 登录失败");
toastHelper.error("😟 Login failed");
}
} catch (error: any) {
console.error(error);
@ -121,7 +121,7 @@ const Signin: React.FC<Props> = () => {
<div className="page-container">
<div className="page-header-container">
<p className="title-text">
Memos <span className="icon-text"></span>
Login to Memos <span className="icon-text"></span>
</p>
</div>
{showAutoSigninAsGuest ? (
@ -132,13 +132,13 @@ const Signin: React.FC<Props> = () => {
className={`btn guest-signin ${signinBtnsClickLoadingState.isLoading ? "requesting" : ""}`}
onClick={handleAutoSigninAsGuestBtnClick}
>
👉
👉 Login as Guest quickly
</div>
<div
className={`btn ${signinBtnsClickLoadingState.isLoading ? "requesting" : ""}`}
onClick={handleSwitchAccountSigninBtnClick}
>
I have an account
</div>
</div>
</>
@ -146,11 +146,11 @@ const Signin: React.FC<Props> = () => {
<>
<div className="page-content-container">
<div className="form-item-container input-form-container">
<span className={"normal-text " + (username === "" ? "" : "not-null")}></span>
<span className={"normal-text " + (username === "" ? "" : "not-null")}>Usernmae</span>
<input type="text" autoComplete="off" value={username} onChange={handleUsernameInputChanged} />
</div>
<div className="form-item-container input-form-container">
<span className={"normal-text " + (password === "" ? "" : "not-null")}></span>
<span className={"normal-text " + (password === "" ? "" : "not-null")}>Password</span>
<input type="password" autoComplete="off" value={password} onChange={handlePasswordInputChanged} />
</div>
</div>
@ -161,14 +161,14 @@ const Signin: React.FC<Props> = () => {
className={`btn ${signinBtnsClickLoadingState.isLoading ? "requesting" : ""}`}
onClick={handleAutoSigninAsGuestBtnClick}
>
Login as Guest
</button>
<span className="split-text">/</span>
<button
className={`btn signin-btn ${signinBtnsClickLoadingState.isLoading ? "requesting" : ""}`}
onClick={() => handleSigninBtnsClick("signup")}
>
Sign up
</button>
<span className="split-text">/</span>
<button
@ -176,7 +176,7 @@ const Signin: React.FC<Props> = () => {
className={`btn signin-btn ${signinBtnsClickLoadingState.isLoading ? "requesting" : ""}`}
onClick={() => handleSigninBtnsClick("signin")}
>
Login
</button>
</div>
</div>

View File

@ -10,7 +10,7 @@ class ResourceService {
const { name: filename, size } = file;
if (size > 5 << 20) {
return Promise.reject("超过最大文件大小 5Mb");
return Promise.reject("overload max size: 5Mb");
}
const formData = new FormData();

View File

@ -1,9 +1,7 @@
type BasicType = undefined | null | boolean | number | string | Record<string, unknown> | Array<BasicType>;
// 日期戳
type DateStamp = number;
// 时间戳
type TimeStamp = number;
type FunctionType = (...args: unknown[]) => unknown;