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"> <div className="dialog-header-container">
<p className="title-text"> <p className="title-text">
<span className="icon-text">🤠</span> <b>Memos</b> <span className="icon-text">🤠</span>About <b>Memos</b>
</p> </p>
<button className="btn close-btn" onClick={handleCloseBtnClick}> <button className="btn close-btn" onClick={handleCloseBtnClick}>
<img className="icon-img" src="/icons/close.svg" /> <img className="icon-img" src="/icons/close.svg" />
@ -21,9 +21,9 @@ const AboutSiteDialog: React.FC<Props> = ({ destroy }: Props) => {
</div> </div>
<div className="dialog-content-container"> <div className="dialog-content-container">
<p> <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> <p>Built with `Golang` and `React`.</p>
<br /> <br />
<p> <p>
🏗 This project is working in progress, <br /> and very pleasure to welcome your{" "} 🏗 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 () => { const handleSaveBtnClick = async () => {
if (oldPassword === "" || newPassword === "" || newPasswordAgain === "") { if (oldPassword === "" || newPassword === "" || newPasswordAgain === "") {
toastHelper.error("密码不能为空"); toastHelper.error("Please fill in all fields.");
return; return;
} }
if (newPassword !== newPasswordAgain) { if (newPassword !== newPasswordAgain) {
toastHelper.error("新密码两次输入不一致"); toastHelper.error("New passwords do not match.");
setNewPasswordAgain(""); setNewPasswordAgain("");
return; return;
} }
const passwordValidResult = validate(newPassword, validateConfig); const passwordValidResult = validate(newPassword, validateConfig);
if (!passwordValidResult.result) { if (!passwordValidResult.result) {
toastHelper.error("密码 " + passwordValidResult.reason); toastHelper.error("Password " + passwordValidResult.reason);
return; return;
} }
@ -64,13 +64,13 @@ const ChangePasswordDialog: React.FC<Props> = ({ destroy }: Props) => {
const isValid = await userService.checkPasswordValid(oldPassword); const isValid = await userService.checkPasswordValid(oldPassword);
if (!isValid) { if (!isValid) {
toastHelper.error("旧密码不匹配"); toastHelper.error("Old password is invalid.");
setOldPassword(""); setOldPassword("");
return; return;
} }
await userService.updatePassword(newPassword); await userService.updatePassword(newPassword);
toastHelper.info("密码修改成功!"); toastHelper.info("Password changed.");
handleCloseBtnClick(); handleCloseBtnClick();
} catch (error: any) { } catch (error: any) {
toastHelper.error(error); toastHelper.error(error);
@ -80,30 +80,30 @@ const ChangePasswordDialog: React.FC<Props> = ({ destroy }: Props) => {
return ( return (
<> <>
<div className="dialog-header-container"> <div className="dialog-header-container">
<p className="title-text"></p> <p className="title-text">Change Password</p>
<button className="btn close-btn" onClick={handleCloseBtnClick}> <button className="btn close-btn" onClick={handleCloseBtnClick}>
<img className="icon-img" src="/icons/close.svg" /> <img className="icon-img" src="/icons/close.svg" />
</button> </button>
</div> </div>
<div className="dialog-content-container"> <div className="dialog-content-container">
<label className="form-label input-form-label"> <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} /> <input type="password" value={oldPassword} onChange={handleOldPasswordChanged} />
</label> </label>
<label className="form-label input-form-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} /> <input type="password" value={newPassword} onChange={handleNewPasswordChanged} />
</label> </label>
<label className="form-label input-form-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} /> <input type="password" value={newPasswordAgain} onChange={handleNewPasswordAgainChanged} />
</label> </label>
<div className="btns-container"> <div className="btns-container">
<span className="btn cancel-btn" onClick={handleCloseBtnClick}> <span className="btn cancel-btn" onClick={handleCloseBtnClick}>
Cancel
</span> </span>
<span className="btn confirm-btn" onClick={handleSaveBtnClick}> <span className="btn confirm-btn" onClick={handleSaveBtnClick}>
Save
</span> </span>
</div> </div>
</div> </div>

View File

@ -27,29 +27,31 @@ const ConfirmResetOpenIdDialog: React.FC<Props> = ({ destroy }: Props) => {
try { try {
await userService.resetOpenId(); await userService.resetOpenId();
} catch (error) { } catch (error) {
toastHelper.error("请求重置 Open API 失败"); toastHelper.error("Request reset open API failed.");
return; return;
} }
toastHelper.success("重置成功!"); toastHelper.success("Reset open API succeeded.");
handleCloseBtnClick(); handleCloseBtnClick();
}; };
return ( return (
<> <>
<div className="dialog-header-container"> <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}> <button className="btn close-btn" onClick={handleCloseBtnClick}>
<img className="icon-img" src="/icons/close.svg" /> <img className="icon-img" src="/icons/close.svg" />
</button> </button>
</div> </div>
<div className="dialog-content-container"> <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"> <div className="btns-container">
<span className="btn cancel-btn" onClick={handleCloseBtnClick}> <span className="btn cancel-btn" onClick={handleCloseBtnClick}>
Cancel
</span> </span>
<span className={`btn confirm-btn ${resetBtnClickLoadingState.isLoading ? "loading" : ""}`} onClick={handleConfirmBtnClick}> <span className={`btn confirm-btn ${resetBtnClickLoadingState.isLoading ? "loading" : ""}`} onClick={handleConfirmBtnClick}>
Reset!
</span> </span>
</div> </div>
</div> </div>

View File

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

View File

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

View File

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

View File

@ -176,12 +176,12 @@ const Editor = forwardRef((props: EditorProps, ref: React.ForwardedRef<EditorRef
<div className="btns-container"> <div className="btns-container">
<Only when={showCancelBtn}> <Only when={showCancelBtn}>
<button className="action-btn cancel-btn" onClick={handleCommonCancelBtnClick}> <button className="action-btn cancel-btn" onClick={handleCommonCancelBtnClick}>
Cancel editting
</button> </button>
</Only> </Only>
<Only when={showConfirmBtn}> <Only when={showConfirmBtn}>
<button className="action-btn confirm-btn" disabled={!editorRef.current?.value} onClick={handleCommonConfirmBtnClick}> <button className="action-btn confirm-btn" disabled={!editorRef.current?.value} onClick={handleCommonConfirmBtnClick}>
<span className="icon-text"></span> Save <span className="icon-text"></span>
</button> </button>
</Only> </Only>
</div> </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-wrapper">
<div className="more-action-btns-container"> <div className="more-action-btns-container">
<span className="btn" onClick={handleShowMemoStoryDialog}> <span className="btn" onClick={handleShowMemoStoryDialog}>
View Story
</span> </span>
<span className="btn" onClick={handleMarkMemoClick}> <span className="btn" onClick={handleMarkMemoClick}>
Mark Mark
</span> </span>
<span className="btn" onClick={handleGenMemoImageBtnClick}> <span className="btn" onClick={handleGenMemoImageBtnClick}>
Share
</span> </span>
<span className="btn" onClick={handleEditMemoClick}> <span className="btn" onClick={handleEditMemoClick}>
Edit
</span> </span>
<span className={`btn delete-btn ${showConfirmDeleteBtn ? "final-confirm" : ""}`} onClick={handleDeleteMemoClick}> <span className={`btn delete-btn ${showConfirmDeleteBtn ? "final-confirm" : ""}`} onClick={handleDeleteMemoClick}>
{showConfirmDeleteBtn ? "确定删除!" : "删除"} {showConfirmDeleteBtn ? "Delete!" : "Delete"}
</span> </span>
</div> </div>
</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(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>"); .replace(MEMO_LINK_REG, "<span class='memo-link-text' data-value='$2'>$1</span>");
// 中英文之间加空格 // Add space in english and chinese
if (shouldSplitMemoWord) { if (shouldSplitMemoWord) {
content = content content = content
.replace(/([\u4e00-\u9fa5])([A-Za-z0-9?.,;[\]]+)/g, "$1 $2") .replace(/([\u4e00-\u9fa5])([A-Za-z0-9?.,;[\]]+)/g, "$1 $2")

View File

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

View File

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

View File

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

View File

@ -83,7 +83,7 @@ const MemoList: React.FC<Props> = () => {
setFetchStatus(false); setFetchStatus(false);
}) })
.catch(() => { .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"> <div className="status-text-container">
<p className="status-text"> <p className="status-text">
{isFetching ? "努力请求数据中..." : shownMemos.length === 0 ? "空空如也" : showMemoFilter ? "" : "所有数据加载完啦 🎉"} {isFetching
? "Fetching data..."
: shownMemos.length === 0
? "Oops, there is nothing"
: showMemoFilter
? ""
: "Fetching completed 🎉"}
</p> </p>
</div> </div>
</div> </div>

View File

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

View File

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

View File

@ -11,7 +11,7 @@ const PreferencesSection: React.FC<Props> = () => {
const { globalState } = useContext(appContext); const { globalState } = useContext(appContext);
const { useTinyUndoHistoryCache, shouldHideImageUrl, shouldSplitMemoWord, shouldUseMarkdownParser } = globalState; 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 = () => { const handleOpenTinyUndoChanged = () => {
globalStateService.setAppSetting({ globalStateService.setAppSetting({
@ -65,29 +65,29 @@ const PreferencesSection: React.FC<Props> = () => {
return ( return (
<> <>
<div className="section-container preferences-section-container"> <div className="section-container preferences-section-container">
<p className="title-text">Memo </p> <p className="title-text">Memo Display</p>
<div <div
className="demo-content-container memo-content-text" className="demo-content-container memo-content-text"
dangerouslySetInnerHTML={{ __html: formatMemoContent(demoMemoContent) }} dangerouslySetInnerHTML={{ __html: formatMemoContent(demoMemoContent) }}
></div> ></div>
<label className="form-label checkbox-form-label" onClick={handleSplitWordsValueChanged}> <label className="form-label checkbox-form-label hidden" onClick={handleSplitWordsValueChanged}>
<span className="normal-text"></span> <span className="normal-text">Auto-space in English and Chinese</span>
<img className="icon-img" src={shouldSplitMemoWord ? "/icons/checkbox-active.svg" : "/icons/checkbox.svg"} /> <img className="icon-img" src={shouldSplitMemoWord ? "/icons/checkbox-active.svg" : "/icons/checkbox.svg"} />
</label> </label>
<label className="form-label checkbox-form-label" onClick={handleUseMarkdownParserChanged}> <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"} /> <img className="icon-img" src={shouldUseMarkdownParser ? "/icons/checkbox-active.svg" : "/icons/checkbox.svg"} />
</label> </label>
<label className="form-label checkbox-form-label" onClick={handleHideImageUrlValueChanged}> <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"} /> <img className="icon-img" src={shouldHideImageUrl ? "/icons/checkbox-active.svg" : "/icons/checkbox.svg"} />
</label> </label>
</div> </div>
<div className="section-container preferences-section-container"> <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}> <label className="form-label checkbox-form-label" onClick={handleOpenTinyUndoChanged}>
<span className="normal-text"> <span className="normal-text">
{" "} Use{" "}
<a target="_blank" href="https://github.com/boojack/tiny-undo" onClick={(e) => e.stopPropagation()} rel="noreferrer"> <a target="_blank" href="https://github.com/boojack/tiny-undo" onClick={(e) => e.stopPropagation()} rel="noreferrer">
tiny-undo tiny-undo
</a> </a>
@ -96,13 +96,13 @@ const PreferencesSection: React.FC<Props> = () => {
</label> </label>
</div> </div>
<div className="section-container"> <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"> <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}> <button className="px-2 py-1 border rounded text-base hover:opacity-80" onClick={handleExportBtnClick}>
(JSON) Export data as JSON
</button> </button>
<button className="btn format-btn hidden" onClick={handleFormatMemosBtnClick}> <button className="btn format-btn hidden" onClick={handleFormatMemosBtnClick}>
Format Data
</button> </button>
</div> </div>
</div> </div>

View File

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

View File

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

View File

@ -65,7 +65,7 @@ const ShareMemoImageDialog: React.FC<Props> = (props: Props) => {
<> <>
<div className="dialog-header-container"> <div className="dialog-header-container">
<p className="title-text"> <p className="title-text">
<span className="icon-text">🥰</span> Memo <span className="icon-text">🥰</span>Share Memo
</p> </p>
<button className="btn close-btn" onClick={handleCloseBtnClick}> <button className="btn close-btn" onClick={handleCloseBtnClick}>
<img className="icon-img" src="/icons/close.svg" /> <img className="icon-img" src="/icons/close.svg" />
@ -73,7 +73,7 @@ const ShareMemoImageDialog: React.FC<Props> = (props: Props) => {
</div> </div>
<div className="dialog-content-container"> <div className="dialog-content-container">
<div className={`tip-words-container ${shortcutImgUrl ? "finish" : "loading"}`}> <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>
<div className="memo-container" ref={memoElRef}> <div className="memo-container" ref={memoElRef}>
<Only when={shortcutImgUrl !== ""}> <Only when={shortcutImgUrl !== ""}>

View File

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

View File

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

View File

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

View File

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

View File

@ -1,23 +1,23 @@
// 移动端样式适配额外类名 // mobile style addtion classname
export const SHOW_SIDERBAR_MOBILE_CLASSNAME = "mobile-show-sidebar"; export const SHOW_SIDERBAR_MOBILE_CLASSNAME = "mobile-show-sidebar";
// 默认动画持续时长 // default animation duration
export const ANIMATION_DURATION = 200; export const ANIMATION_DURATION = 200;
// toast 动画持续时长 // toast animation duration
export const TOAST_ANIMATION_DURATION = 400; export const TOAST_ANIMATION_DURATION = 400;
// 一天的毫秒数 // millisecond in a day
export const DAILY_TIMESTAMP = 3600 * 24 * 1000; export const DAILY_TIMESTAMP = 3600 * 24 * 1000;
// 标签 正则 // tag regex
export const TAG_REG = /#\s?(.+?)\s/g; export const TAG_REG = /#\s?(.+?)\s/g;
// URL 正则 // URL regex
export const LINK_REG = /(https?:\/\/[^\s<\\*>']+)/g; export const LINK_REG = /(https?:\/\/[^\s<\\*>']+)/g;
// 图片 正则 // image regex
export const IMAGE_URL_REG = /([^\s<\\*>']+\.(jpeg|jpg|gif|png|svg))/g; export const IMAGE_URL_REG = /([^\s<\\*>']+\.(jpeg|jpg|gif|png|svg))/g;
// memo 关联正则 // linked memo regex
export const MEMO_LINK_REG = /\[@(.+?)\]\((.+?)\)/g; 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"; import { IMAGE_URL_REG, LINK_REG, MEMO_LINK_REG, TAG_REG } from "./consts";
export const relationConsts = [ export const relationConsts = [
{ text: "", value: "AND" }, { text: "And", value: "AND" },
{ text: "", value: "OR" }, { text: "Or", value: "OR" },
]; ];
export const filterConsts = { export const filterConsts = {
TAG: { TAG: {
text: "Tag",
value: "TAG", value: "TAG",
text: "标签",
operators: [ operators: [
{ {
text: "包括", text: "Contains",
value: "CONTAIN", value: "CONTAIN",
}, },
{ {
text: "排除", text: "Does not contain",
value: "NOT_CONTAIN", value: "NOT_CONTAIN",
}, },
], ],
}, },
TYPE: { TYPE: {
text: "Type",
value: "TYPE", value: "TYPE",
text: "类型",
operators: [ operators: [
{ {
text: "Is",
value: "IS", value: "IS",
text: "是",
}, },
{ {
text: "Is not",
value: "IS_NOT", value: "IS_NOT",
text: "不是",
}, },
], ],
values: [ values: [
{ {
text: "Connected",
value: "CONNECTED", value: "CONNECTED",
text: "有关联",
}, },
{ {
text: "No tags",
value: "NOT_TAGGED", value: "NOT_TAGGED",
text: "无标签",
}, },
{ {
text: "Has links",
value: "LINKED", value: "LINKED",
text: "有超链接",
}, },
{ {
text: "Has images",
value: "IMAGED", value: "IMAGED",
text: "有图片",
}, },
], ],
}, },
TEXT: { TEXT: {
text: "Text",
value: "TEXT", value: "TEXT",
text: "文本",
operators: [ operators: [
{ {
text: "Contain",
value: "CONTAIN", value: "CONTAIN",
text: "包括",
}, },
{ {
text: "Does not contain",
value: "NOT_CONTAIN", value: "NOT_CONTAIN",
text: "排除",
}, },
], ],
}, },

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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