diff options
-rw-r--r-- | FrontEnd/src/http/user.ts | 27 | ||||
-rw-r--r-- | FrontEnd/src/locales/en/translation.json | 8 | ||||
-rw-r--r-- | FrontEnd/src/locales/zh/translation.json | 16 | ||||
-rw-r--r-- | FrontEnd/src/views/settings/index.tsx | 54 |
4 files changed, 94 insertions, 11 deletions
diff --git a/FrontEnd/src/http/user.ts b/FrontEnd/src/http/user.ts index 7313e484..17c4adbb 100644 --- a/FrontEnd/src/http/user.ts +++ b/FrontEnd/src/http/user.ts @@ -37,6 +37,10 @@ export interface HttpCreateUserRequest { password: string; } +export interface HttpBookmarkVisibility { + visibility: "Private" | "Register" | "Public"; +} + export class HttpChangePasswordBadCredentialError extends Error { constructor(public innerError?: AxiosError) { super(); @@ -60,6 +64,12 @@ export interface IHttpUserClient { permission: UserPermission ): Promise<void>; changePassword(req: HttpChangePasswordRequest): Promise<void>; + + getBookmarkVisibility(username: string): Promise<HttpBookmarkVisibility>; + putBookmarkVisibility( + username: string, + req: HttpBookmarkVisibility + ): Promise<void>; } export class HttpUserClient implements IHttpUserClient { @@ -136,6 +146,23 @@ export class HttpUserClient implements IHttpUserClient { } }); } + + getBookmarkVisibility(username: string): Promise<HttpBookmarkVisibility> { + return axios + .get<HttpBookmarkVisibility>( + `${apiBaseUrl}/v2/users/${username}/bookmarks/visibility` + ) + .then(extractResponseData); + } + + putBookmarkVisibility( + username: string, + req: HttpBookmarkVisibility + ): Promise<void> { + return axios + .put(`${apiBaseUrl}/v2/users/${username}/bookmarks/visibility`, req) + .then(); + } } let client: IHttpUserClient = new HttpUserClient(); diff --git a/FrontEnd/src/locales/en/translation.json b/FrontEnd/src/locales/en/translation.json index 966eddda..548dcfe1 100644 --- a/FrontEnd/src/locales/en/translation.json +++ b/FrontEnd/src/locales/en/translation.json @@ -19,6 +19,11 @@ "Disconnecting": "Disconnecting", "Reconnecting": "Reconnecting" }, + "visibility": { + "private": "Private For Me", + "register": "Only Registered Users", + "public": "Public To Everyone" + }, "serviceWorker": { "availableOffline": "Timeline is now cached in your computer and you can use it offline. 🎉🎉🎉", "upgradePrompt": "App is getting a new version!", @@ -166,6 +171,7 @@ "logout": "Log out this account.", "changeAvatar": "Change avatar.", "changeNickname": "Change nickname.", + "changeBookmarkVisibility": "Change bookmark visibility.", "dialogChangePassword": { "title": "Change Password", "prompt": "You are changing your password. You need to input the correct old password. After change, you need to login again and all old login will be invalid.", @@ -221,4 +227,4 @@ "admin": { "title": "admin" } -} +}
\ No newline at end of file diff --git a/FrontEnd/src/locales/zh/translation.json b/FrontEnd/src/locales/zh/translation.json index 2a2ae4bd..58a9b2e6 100644 --- a/FrontEnd/src/locales/zh/translation.json +++ b/FrontEnd/src/locales/zh/translation.json @@ -12,6 +12,11 @@ "network": "网络错误。", "unknown": "未知错误。" }, + "visibility": { + "private": "仅自己可见", + "register": "仅注册用户可见", + "public": "对所有人公开" + }, "connectionState": { "Connected": "已连接", "Connecting": "正在连接", @@ -162,10 +167,11 @@ }, "languagePrimary": "选择显示的语言。", "languageSecondary": "您的语言偏好将会存储在本地,下次浏览时将自动使用上次保存的语言选项。", - "changePassword": "更改账号的密码。", - "logout": "注销此账号。", - "changeAvatar": "更改头像。", - "changeNickname": "更改昵称。", + "changePassword": "更改账号的密码", + "logout": "注销此账号", + "changeAvatar": "更改头像", + "changeNickname": "更改昵称", + "changeBookmarkVisibility": "修改书签时间线可见性", "dialogChangePassword": { "title": "修改密码", "prompt": "您正在修改密码,您需要输入正确的旧密码。成功修改后您需要重新登陆,而且以前所有的登录都会失效。", @@ -221,4 +227,4 @@ "admin": { "title": "管理" } -} +}
\ No newline at end of file diff --git a/FrontEnd/src/views/settings/index.tsx b/FrontEnd/src/views/settings/index.tsx index 1f526ee0..040d604c 100644 --- a/FrontEnd/src/views/settings/index.tsx +++ b/FrontEnd/src/views/settings/index.tsx @@ -3,17 +3,19 @@ import { useNavigate } from "react-router-dom"; import { useTranslation } from "react-i18next"; import classnames from "classnames"; +import { convertI18nText, I18nText } from "@/common"; import { useUser, userService } from "@/services/user"; +import { TimelineVisibility } from "@/http/timeline"; +import ConfirmDialog from "../common/dailog/ConfirmDialog"; +import Card from "../common/Card"; +import Spinner from "../common/Spinner"; import ChangePasswordDialog from "./ChangePasswordDialog"; import ChangeAvatarDialog from "./ChangeAvatarDialog"; import ChangeNicknameDialog from "./ChangeNicknameDialog"; -import ConfirmDialog from "../common/dailog/ConfirmDialog"; -import Card from "../common/Card"; import "./index.css"; -import { convertI18nText, I18nText } from "@/common"; -import Spinner from "../common/Spinner"; +import { getHttpUserClient } from "@/http/user"; interface SettingSectionProps { title: I18nText; @@ -92,7 +94,7 @@ const SelectSettingsItem: React.FC<SelectSettingItemProps> = ({ return ( <div className={classnames("row settings-item mx-0", first && "first")}> - <div className="col col-12 col-sm-auto"> + <div className="px-0 col col-12 col-sm-auto"> <div>{convertI18nText(title, t)}</div> <small className="d-block cru-color-secondary"> {convertI18nText(subtext, t)} @@ -129,6 +131,21 @@ const SettingsPage: React.FC = (_) => { null | "changepassword" | "changeavatar" | "changenickname" | "logout" >(null); + const [bookmarkVisibility, setBookmarkVisibility] = + useState<TimelineVisibility>(); + + React.useEffect(() => { + if (user != null) { + void getHttpUserClient() + .getBookmarkVisibility(user.username) + .then(({ visibility }) => { + setBookmarkVisibility(visibility); + }); + } else { + setBookmarkVisibility(undefined); + } + }, [user]); + const language = i18n.language.slice(0, 2); return ( @@ -145,6 +162,33 @@ const SettingsPage: React.FC = (_) => { title="settings.changeNickname" onClick={() => setDialog("changenickname")} /> + <SelectSettingsItem + title="settings.changeBookmarkVisibility" + options={[ + { + value: "Private", + label: "visibility.private", + }, + { + value: "Register", + label: "visibility.register", + }, + { + value: "Public", + label: "visibility.public", + }, + ]} + value={bookmarkVisibility} + onSelect={(value) => { + void getHttpUserClient() + .putBookmarkVisibility(user.username, { + visibility: value as TimelineVisibility, + }) + .then(() => { + setBookmarkVisibility(value as TimelineVisibility); + }); + }} + /> <ButtonSettingItem title="settings.changePassword" onClick={() => setDialog("changepassword")} |