This commit is contained in:
2025-10-20 22:08:12 +03:00
Unverified
parent 97f19ce52b
commit 27e1cf7a68
5 changed files with 26 additions and 53 deletions
+5 -6
View File
@@ -2,10 +2,10 @@ import { BrowserRouter, Routes, Route, useNavigate, matchRoutes, type RouteObjec
import { ElectronTitleBar } from "./Electron"; import { ElectronTitleBar } from "./Electron";
import { useAppState } from "./pages/chat/state"; import { useAppState } from "./pages/chat/state";
import { lazy, useEffect, useState } from "react"; import { lazy, useEffect, useState } from "react";
import { parseProfileLink } from "./core/profileLinks.ts"; import { parseProfileLink } from "./core/profileLinks";
import NotFoundPage from "./pages/not-found/NotFoundPage.tsx"; import NotFoundPage from "./pages/not-found/NotFoundPage";
import ProtectedRoute from "./pages/ProtectedRoute.tsx"; import ProtectedRoute from "./pages/ProtectedRoute";
import DownloadAppPage from "./pages/download-app/DownloadAppPage.tsx"; import DownloadAppPage from "./pages/download-app/DownloadAppPage";
// Lazy load route components // Lazy load route components
const HomePage = lazy(() => import("./pages/home/HomePage")); const HomePage = lazy(() => import("./pages/home/HomePage"));
@@ -46,8 +46,7 @@ function SmartCatchAll() {
return; return;
} }
// Check if it's a profile link const profileInfo = parseProfileLink(); // No URL specified intentionally to let it use the current URL
const profileInfo = parseProfileLink(); // no url specified intentionally to let it use the current url
if (profileInfo) { if (profileInfo) {
setShowNotFound(false); setShowNotFound(false);
+14 -38
View File
@@ -74,8 +74,7 @@ export function ProfileDialog() {
const [isSaving, setIsSaving] = useState(false); const [isSaving, setIsSaving] = useState(false);
const [errors, setErrors] = useState<{[key: string]: string}>({}); const [errors, setErrors] = useState<{[key: string]: string}>({});
const fileInputRef = useRef<HTMLInputElement>(null); const fileInputRef = useRef<HTMLInputElement>(null);
const backdropRef = useRef<HTMLDivElement>(null); const [openClass, setOpenClass] = useState(false);
const dialogRef = useRef<HTMLDivElement>(null);
// Handle dialog open/close based on state // Handle dialog open/close based on state
useEffect(() => { useEffect(() => {
@@ -84,17 +83,12 @@ export function ProfileDialog() {
fetchFreshProfileData(chat.profileDialog); fetchFreshProfileData(chat.profileDialog);
} else if (!chat.profileDialog && isOpen) { } else if (!chat.profileDialog && isOpen) {
// Start close animation // Start close animation
if (backdropRef.current && dialogRef.current) { setOpenClass(false);
backdropRef.current.classList.remove('open');
dialogRef.current.classList.remove('open');
// Wait for animation to complete before closing // Wait for animation to complete before closing
setTimeout(() => { setTimeout(() => {
setIsOpen(false); setIsOpen(false);
}, 300); // Match CSS transition duration }, 300);
} else {
setIsOpen(false);
}
} }
}, [chat.profileDialog, isOpen]); }, [chat.profileDialog, isOpen]);
@@ -132,13 +126,10 @@ export function ProfileDialog() {
useEffect(() => { useEffect(() => {
if (isOpen) { if (isOpen) {
// Small delay to ensure DOM is ready for transition // Small delay to ensure DOM is ready for transition
const timer = setTimeout(() => { const timer = requestAnimationFrame(() => {
if (backdropRef.current && dialogRef.current) { setOpenClass(true);
backdropRef.current.classList.add('open'); });
dialogRef.current.classList.add('open'); return () => cancelAnimationFrame(timer);
}
}, 10);
return () => clearTimeout(timer);
} }
}, [isOpen]); }, [isOpen]);
@@ -214,17 +205,12 @@ export function ProfileDialog() {
}; };
function triggerCloseAnimation() { function triggerCloseAnimation() {
if (backdropRef.current && dialogRef.current) { setOpenClass(false);
backdropRef.current.classList.remove('open');
dialogRef.current.classList.remove('open');
// Wait for animation to complete before closing // Wait for animation to complete before closing
setTimeout(() => { setTimeout(() => {
closeProfileDialog();
}, 300); // Match CSS transition duration
} else {
closeProfileDialog(); closeProfileDialog();
} }, 300); // Match CSS transition duration
}; };
function handleBackdropClick(e: React.MouseEvent) { function handleBackdropClick(e: React.MouseEvent) {
@@ -402,13 +388,10 @@ export function ProfileDialog() {
return createPortal( return createPortal(
<div <div
ref={backdropRef} className={`profile-dialog-backdrop ${openClass ? "open" : ""}`}
className="profile-dialog-backdrop" onClick={handleBackdropClick}>
onClick={handleBackdropClick} <div className={`profile-dialog ${openClass ? "open" : ""}`}>
>
<div ref={dialogRef} className="profile-dialog">
<div className="profile-dialog-content"> <div className="profile-dialog-content">
{/* Profile Picture */}
<div className="profile-picture-section"> <div className="profile-picture-section">
<img <img
className="profile-picture" className="profile-picture"
@@ -429,7 +412,6 @@ export function ProfileDialog() {
)} )}
</div> </div>
{/* Display Name */}
<div className={`username-section ${errors.display_name ? 'error' : ''}`}> <div className={`username-section ${errors.display_name ? 'error' : ''}`}>
<input <input
className="username-input" className="username-input"
@@ -444,7 +426,6 @@ export function ProfileDialog() {
)} )}
</div> </div>
{/* Online Status */}
{(currentData?.userId || currentData?.isOwnProfile) && ( {(currentData?.userId || currentData?.isOwnProfile) && (
<div className="online-status-section"> <div className="online-status-section">
<OnlineStatus userId={currentData.userId || user.currentUser!.id} /> <OnlineStatus userId={currentData.userId || user.currentUser!.id} />
@@ -462,8 +443,6 @@ export function ProfileDialog() {
readOnly={!currentData.isOwnProfile} readOnly={!currentData.isOwnProfile}
placeholder="username" /> placeholder="username" />
{/* Bio */}
{currentData.bio !== undefined && ( {currentData.bio !== undefined && (
<Section <Section
type="bio" type="bio"
@@ -477,7 +456,6 @@ export function ProfileDialog() {
/> />
)} )}
{/* Member Since */}
{currentData.memberSince && ( {currentData.memberSince && (
<Section <Section
type="member-since" type="member-since"
@@ -491,7 +469,6 @@ export function ProfileDialog() {
</div> </div>
</div> </div>
{/* Save FAB */}
{currentData.isOwnProfile && ( {currentData.isOwnProfile && (
<mdui-fab <mdui-fab
icon="check" icon="check"
@@ -501,7 +478,6 @@ export function ProfileDialog() {
/> />
)} )}
{/* Hidden file input */}
<input <input
ref={fileInputRef} ref={fileInputRef}
type="file" type="file"
@@ -143,7 +143,6 @@ export function ChatMessages({ messages = [], children, isDm = false, onReplySel
{children} {children}
</div> </div>
<MaterialDialog <MaterialDialog
headline="Удалить сообщение?" headline="Удалить сообщение?"
open={deleteDialogOpen} open={deleteDialogOpen}
+1 -2
View File
@@ -515,8 +515,7 @@ export function Message({ message, isAuthor, onContextMenu, onReactionClick, isD
<div <div
className={`message-content ${isEmojiMessage ? "emoji-content" : ""} ${isSingleEmojiMessage ? "single-emoji-content" : ""}`} className={`message-content ${isEmojiMessage ? "emoji-content" : ""} ${isSingleEmojiMessage ? "single-emoji-content" : ""}`}
dangerouslySetInnerHTML={formattedMessage} dangerouslySetInnerHTML={formattedMessage}
onClick={handleLinkClick} onClick={handleLinkClick} />
/>
{message.files && message.files.length > 0 && ( {message.files && message.files.length > 0 && (
<mdui-list className="message-attachments"> <mdui-list className="message-attachments">