pstream is dead; long live pstream taciturnaxolotl.github.io/pstream-ng/
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Add nickname to user account settings

Introduces a nickname field to user accounts, updates the backend user interface, and extends the settings UI to allow users to view and edit their nickname. Localization strings and state management have been updated accordingly to support this new field.

Pas 067b6e43 5842af70

+69 -21
+3
src/assets/locales/en.json
··· 947 947 }, 948 948 "account": { 949 949 "accountDetails": { 950 + "nicknameLabel": "Nickname", 951 + "nicknamePlaceholder": "Enter your nickname", 950 952 "deviceNameLabel": "Device name", 951 953 "deviceNamePlaceholder": "Personal phone", 952 954 "editProfile": "Edit", ··· 1144 1146 "backendVersion": "Backend version", 1145 1147 "hostname": "Hostname", 1146 1148 "insecure": "Insecure", 1149 + "nickname": "Nickname", 1147 1150 "notLoggedIn": "You are not logged in", 1148 1151 "secure": "Secure", 1149 1152 "title": "App stats",
+3 -3
src/backend/accounts/user.ts
··· 8 8 export interface UserResponse { 9 9 id: string; 10 10 namespace: string; 11 - name: string; 12 - roles: string[]; 13 - createdAt: string; 11 + nickname: string; 12 + permissions: string[]; 14 13 profile: { 15 14 colorA: string; 16 15 colorB: string; ··· 24 23 colorB: string; 25 24 icon: string; 26 25 }; 26 + nickname?: string; 27 27 } 28 28 29 29 export interface BookmarkResponse {
+1
src/hooks/auth/useAuthData.ts
··· 101 101 sessionId: loginResponse.session.id, 102 102 deviceName: session.device, 103 103 profile: user.profile, 104 + nickname: user.nickname, 104 105 seed, 105 106 }; 106 107 setAccount(account);
+10
src/hooks/useSettingsState.ts
··· 42 42 appLanguage: string, 43 43 subtitleStyling: SubtitleStyling, 44 44 deviceName: string, 45 + nickname: string, 45 46 proxyUrls: string[] | null, 46 47 backendUrl: string | null, 47 48 febboxKey: string | null, ··· 110 111 resetDeviceName, 111 112 deviceNameChanged, 112 113 ] = useDerived(deviceName); 114 + const [nicknameState, setNicknameState, resetNickname, nicknameChanged] = 115 + useDerived(nickname); 113 116 const [profileState, setProfileState, resetProfile, profileChanged] = 114 117 useDerived(profile); 115 118 const [ ··· 263 266 resetFebboxKey(); 264 267 resetRealDebridKey(); 265 268 resetDeviceName(); 269 + resetNickname(); 266 270 resetProfile(); 267 271 resetEnableThumbnails(); 268 272 resetEnableAutoplay(); ··· 295 299 appLanguageChanged || 296 300 subStylingChanged || 297 301 deviceNameChanged || 302 + nicknameChanged || 298 303 backendUrlChanged || 299 304 proxyUrlsChanged || 300 305 febboxKeyChanged || ··· 347 352 state: deviceNameState, 348 353 set: setDeviceNameState, 349 354 changed: deviceNameChanged, 355 + }, 356 + nickname: { 357 + state: nicknameState, 358 + set: setNicknameState, 359 + changed: nicknameChanged, 350 360 }, 351 361 proxyUrls: { 352 362 state: proxyUrlsState,
+17
src/pages/Settings.tsx
··· 114 114 account: AccountWithToken; 115 115 deviceName: string; 116 116 setDeviceName: (s: string) => void; 117 + nickname: string; 118 + setNickname: (s: string) => void; 117 119 colorA: string; 118 120 setColorA: (s: string) => void; 119 121 colorB: string; ··· 136 138 <AccountEditPart 137 139 deviceName={props.deviceName} 138 140 setDeviceName={props.setDeviceName} 141 + nickname={props.nickname} 142 + setNickname={props.setNickname} 139 143 colorA={props.colorA} 140 144 setColorA={props.setColorA} 141 145 colorB={props.colorB} ··· 481 485 ); 482 486 483 487 const account = useAuthStore((s) => s.account); 488 + const setAccount = useAuthStore((s) => s.setAccount); 484 489 const updateProfile = useAuthStore((s) => s.setAccountProfile); 485 490 const updateDeviceName = useAuthStore((s) => s.updateDeviceName); 486 491 const decryptedName = useMemo(() => { ··· 513 518 appLanguage, 514 519 subStyling, 515 520 decryptedName, 521 + account?.nickname || "", 516 522 proxySet, 517 523 backendUrlSetting, 518 524 febboxKey, ··· 646 652 }); 647 653 updateDeviceName(newDeviceName); 648 654 } 655 + if (state.nickname.changed) { 656 + await editUser(backendUrl, account, { 657 + nickname: state.nickname.state, 658 + }); 659 + // Update the account in the store 660 + const updatedAccount = { ...account, nickname: state.nickname.state }; 661 + setAccount(updatedAccount); 662 + } 649 663 if (state.profile.changed) { 650 664 await editUser(backendUrl, account, { 651 665 profile: state.profile.state, ··· 720 734 setProxySet, 721 735 updateDeviceName, 722 736 updateProfile, 737 + setAccount, 723 738 logout, 724 739 setBackendUrl, 725 740 setProxyTmdb, ··· 754 769 account={user.account} 755 770 deviceName={state.deviceName.state} 756 771 setDeviceName={state.deviceName.set} 772 + nickname={state.nickname.state} 773 + setNickname={state.nickname.set} 757 774 colorA={state.profile.state.colorA} 758 775 setColorA={(v) => { 759 776 state.profile.set((s) =>
+33 -17
src/pages/parts/settings/AccountEditPart.tsx
··· 13 13 export function AccountEditPart(props: { 14 14 deviceName: string; 15 15 setDeviceName: (s: string) => void; 16 + nickname: string; 17 + setNickname: (s: string) => void; 16 18 colorA: string; 17 19 setColorA: (s: string) => void; 18 20 colorB: string; ··· 59 61 /> 60 62 </div> 61 63 <div> 62 - <div className="space-y-8 max-w-xs"> 63 - <AuthInputBox 64 - label={ 65 - t("settings.account.accountDetails.deviceNameLabel") ?? 66 - undefined 67 - } 68 - placeholder={ 69 - t("settings.account.accountDetails.deviceNamePlaceholder") ?? 70 - undefined 71 - } 72 - value={props.deviceName} 73 - onChange={(value) => props.setDeviceName(value)} 74 - /> 75 - <div className="flex space-x-3"> 76 - <Button className="logout-button" theme="danger" onClick={logout}> 77 - {t("settings.account.accountDetails.logoutButton")} 78 - </Button> 64 + <div className="flex flex-col md:flex-row md:gap-4 gap-4"> 65 + <div className="w-full"> 66 + <AuthInputBox 67 + label={t("settings.account.accountDetails.nicknameLabel")} 68 + placeholder={t( 69 + "settings.account.accountDetails.nicknamePlaceholder", 70 + )} 71 + value={props.nickname} 72 + onChange={(value) => props.setNickname(value)} 73 + className="w-full" 74 + /> 79 75 </div> 76 + <div className="w-full"> 77 + <AuthInputBox 78 + label={ 79 + t("settings.account.accountDetails.deviceNameLabel") ?? 80 + undefined 81 + } 82 + placeholder={ 83 + t("settings.account.accountDetails.deviceNamePlaceholder") ?? 84 + undefined 85 + } 86 + value={props.deviceName} 87 + onChange={(value) => props.setDeviceName(value)} 88 + className="w-full" 89 + /> 90 + </div> 91 + </div> 92 + <div className="flex space-x-3 mt-4"> 93 + <Button className="logout-button" theme="danger" onClick={logout}> 94 + {t("settings.account.accountDetails.logoutButton")} 95 + </Button> 80 96 </div> 81 97 </div> 82 98 </div>
+2 -1
src/stores/auth/index.ts
··· 8 8 colorB: string; 9 9 icon: string; 10 10 }; 11 + nickname: string; 11 12 } 12 13 13 14 export type AccountWithToken = Account & { ··· 25 26 removeAccount(): void; 26 27 setAccount(acc: AccountWithToken): void; 27 28 updateDeviceName(deviceName: string): void; 28 - updateAccount(acc: Account): void; 29 + updateAccount(acc: Partial<Account>): void; 29 30 setAccountProfile(acc: Account["profile"]): void; 30 31 setBackendUrl(url: null | string): void; 31 32 setProxySet(urls: null | string[]): void;