Fix profile dialog

This commit is contained in:
2025-08-30 19:08:43 +03:00
Unverified
parent 5af5c98f71
commit 65c5a6d5fb
6 changed files with 26 additions and 19 deletions
+3 -2
View File
@@ -9,6 +9,7 @@ import { request, websocket } from "../websocket";
import type { FetchDMResponse, SendDMRequest, WebSocketMessage, User, DmEnvelope } from "../core/types"; import type { FetchDMResponse, SendDMRequest, WebSocketMessage, User, DmEnvelope } from "../core/types";
import type { Tabs } from "mdui/components/tabs"; import type { Tabs } from "mdui/components/tabs";
import { b64, ub64 } from "../utils/utils"; import { b64, ub64 } from "../utils/utils";
import defaultAvatar from "../resources/images/default-avatar.png";
export async function sendDm(recipientId: number, recipientPublicKeyB64: string, plaintext: string): Promise<void> { export async function sendDm(recipientId: number, recipientPublicKeyB64: string, plaintext: string): Promise<void> {
const keys = getCurrentKeys(); const keys = getCurrentKeys();
@@ -101,7 +102,7 @@ async function loadUsers() {
// Add avatar // Add avatar
const avatar = document.createElement("img"); const avatar = document.createElement("img");
avatar.src = u.profile_picture || "./src/resources/images/default-avatar.png"; avatar.src = u.profile_picture || defaultAvatar;
avatar.alt = u.username; avatar.alt = u.username;
avatar.slot = "icon"; avatar.slot = "icon";
avatar.style.width = "40px"; avatar.style.width = "40px";
@@ -111,7 +112,7 @@ async function loadUsers() {
// Handle avatar load error // Handle avatar load error
avatar.addEventListener("error", () => { avatar.addEventListener("error", () => {
avatar.src = "./src/resources/images/default-avatar.png"; avatar.src = defaultAvatar;
}); });
item.appendChild(avatar); item.appendChild(avatar);
+8
View File
@@ -224,3 +224,11 @@ export interface WebSocketCredentials {
scheme: string; scheme: string;
credentials: string; credentials: string;
} }
// -----------
// React types
// -----------
export interface DialogProps {
isOpen: boolean;
onOpenChange: (value: boolean) => void;
}
@@ -2,6 +2,8 @@ import { PRODUCT_NAME } from "../../../core/config";
import { useDialog } from "../../contexts/DialogContext"; import { useDialog } from "../../contexts/DialogContext";
import { useChat } from "../../hooks/useChat"; import { useChat } from "../../hooks/useChat";
import defaultAvatar from "../../../resources/images/default-avatar.png"; import defaultAvatar from "../../../resources/images/default-avatar.png";
import { useState } from "react";
import { ProfileDialog } from "../profile/ProfileDialog";
function BottomAppBar() { function BottomAppBar() {
const { openSettings } = useDialog(); const { openSettings } = useDialog();
@@ -70,20 +72,17 @@ function ChatTabs() {
function ChatHeader() { function ChatHeader() {
const { openProfile } = useDialog(); const [isProfileOpen, setProfileOpen] = useState(false);
const handleProfileClick = () => {
openProfile();
};
return ( return (
<header className="chat-header-left"> <header className="chat-header-left">
<div className="product-name">{PRODUCT_NAME}</div> <div className="product-name">{PRODUCT_NAME}</div>
<div className="profile"> <div className="profile">
<a href="#" id="profile-open" onClick={handleProfileClick}> <a href="#" id="profile-open" onClick={() => setProfileOpen(true)}>
<img src={defaultAvatar} alt="" id="preview1" /> <img src={defaultAvatar} alt="" id="preview1" />
</a> </a>
</div> </div>
<ProfileDialog isOpen={isProfileOpen} onOpenChange={setProfileOpen} />
</header> </header>
); );
} }
@@ -3,7 +3,7 @@ export function UserProfileDialog() {
<mdui-dialog id="user-profile-dialog" close-on-overlay-click close-on-esc> <mdui-dialog id="user-profile-dialog" close-on-overlay-click close-on-esc>
<div className="content"> <div className="content">
<div className="profile-picture-section"> <div className="profile-picture-section">
<img className="profile-picture" src="" alt="Profile Picture" /> <img className="profile-picture" alt="Profile Picture" />
</div> </div>
<div className="profile-info"> <div className="profile-info">
<div className="username-section"> <div className="username-section">
@@ -1,21 +1,21 @@
import { useState } from "react"; import { useState, type FormEvent } from "react";
import { useDialog } from "../../contexts/DialogContext";
import defaultAvatar from "../../../resources/images/default-avatar.png"; import defaultAvatar from "../../../resources/images/default-avatar.png";
import type { TextField } from "mdui/components/text-field";
import type { DialogProps } from "../../../core/types";
export function ProfileDialog() { export function ProfileDialog({ isOpen, onOpenChange }: DialogProps) {
const [username, setUsername] = useState("user123"); const [username, setUsername] = useState("user123");
const [description, setDescription] = useState(""); const [description, setDescription] = useState("");
const { isProfileOpen, closeProfile } = useDialog();
const handleSubmit = (e: React.FormEvent) => { const handleSubmit = (e: React.FormEvent) => {
e.preventDefault(); e.preventDefault();
// TODO: Implement profile update logic // TODO: Implement profile update logic
console.log("Profile update:", { username, description }); console.log("Profile update:", { username, description });
closeProfile(); onOpenChange(false);
}; };
return ( return (
<mdui-dialog id="profile-dialog" close-on-overlay-click close-on-esc open={isProfileOpen}> <mdui-dialog id="profile-dialog" close-on-overlay-click close-on-esc open={isOpen}>
<div className="content"> <div className="content">
<div className="header-top"> <div className="header-top">
<div className="profile-picture-container"> <div className="profile-picture-container">
@@ -28,7 +28,7 @@ export function ProfileDialog() {
label="Имя пользователя" label="Имя пользователя"
variant="outlined" variant="outlined"
value={username} value={username}
onChange={(e: any) => setUsername(e.target.value)} onChange={(e: FormEvent<HTMLElement & TextField>) => setUsername((e.target as TextField).value)}
autocomplete="username"> autocomplete="username">
</mdui-text-field> </mdui-text-field>
</div> </div>
@@ -39,13 +39,13 @@ export function ProfileDialog() {
label="О себе" label="О себе"
variant="outlined" variant="outlined"
value={description} value={description}
onChange={(e: any) => setDescription(e.target.value)} onChange={(e: FormEvent<HTMLElement & TextField>) => setDescription((e.target as TextField).value)}
placeholder="Расскажите о себе..." placeholder="Расскажите о себе..."
autocomplete="none"> autocomplete="none">
</mdui-text-field> </mdui-text-field>
<div className="dialog-actions"> <div className="dialog-actions">
<mdui-button type="submit" id="profile-submit">Сохранить изменения</mdui-button> <mdui-button type="submit" id="profile-submit">Сохранить изменения</mdui-button>
<mdui-button id="profile-dialog-close" variant="outlined" onClick={closeProfile}>Закрыть</mdui-button> <mdui-button id="profile-dialog-close" variant="outlined" onClick={() => onOpenChange(false)}>Закрыть</mdui-button>
</div> </div>
</form> </form>
</div> </div>
-1
View File
@@ -12,7 +12,6 @@ export default function ChatScreen() {
<> <>
<ChatInterface /> <ChatInterface />
<ProfileDialog />
<CropperDialog /> <CropperDialog />
<SettingsDialog /> <SettingsDialog />
<MessageContextMenu /> <MessageContextMenu />