mirror of
https://github.com/fromchat-messenger/web.git
synced 2026-09-22 19:15:08 +03:00
Add "Download app" screen for too small screens, translate strings
# Please enter the commit message for your changes. Lines starting
This commit is contained in:
@@ -27,4 +27,6 @@ export const API_WS_BASE_URL = `${location.host || BASE_DOMAIN}/api`;
|
||||
* Application name displayed in UI and document title
|
||||
* @constant
|
||||
*/
|
||||
export const PRODUCT_NAME = "FromChat";
|
||||
export const PRODUCT_NAME = "FromChat";
|
||||
|
||||
export const MINIMUM_WIDTH = 800;
|
||||
@@ -0,0 +1,8 @@
|
||||
.download-app-screen {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
min-width: 100vw;
|
||||
min-height: 100vh;
|
||||
padding: 32px;
|
||||
}
|
||||
@@ -9,6 +9,7 @@
|
||||
@use "common/material" as *;
|
||||
@use "electron";
|
||||
@use "dialogs/reply";
|
||||
@use "download-app";
|
||||
|
||||
@use "lib/fonts/montserrat";
|
||||
@use "lib/fonts/material-symbols";
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
import { MINIMUM_WIDTH } from "../core/config";
|
||||
import { ElectronTitleBar } from "./components/Electron";
|
||||
import useWindowSize from "./hooks/useWindowSize";
|
||||
import ChatScreen from "./screen/ChatScreen";
|
||||
import DownloadAppScreen from "./screen/DownloadAppScreen";
|
||||
import LoginScreen from "./screen/LoginScreen";
|
||||
import RegisterScreen from "./screen/RegisterScreen";
|
||||
import { useAppState } from "./state";
|
||||
@@ -7,12 +10,17 @@ import { useEffect } from "react";
|
||||
|
||||
export default function App() {
|
||||
const { currentPage, restoreUserFromStorage } = useAppState();
|
||||
const { width } = useWindowSize();
|
||||
|
||||
// Restore user from localStorage on app initialization
|
||||
useEffect(() => {
|
||||
restoreUserFromStorage();
|
||||
}, [restoreUserFromStorage]);
|
||||
|
||||
if (width < MINIMUM_WIDTH) {
|
||||
return <DownloadAppScreen />
|
||||
}
|
||||
|
||||
let page = <LoginScreen />;
|
||||
|
||||
switch (currentPage) {
|
||||
|
||||
@@ -176,17 +176,17 @@ export function MessageContextMenu({
|
||||
>
|
||||
<div className="context-menu-item" onClick={() => handleAction("reply")}>
|
||||
<span className="material-symbols">reply</span>
|
||||
Reply
|
||||
Ответить
|
||||
</div>
|
||||
{isAuthor && (
|
||||
<>
|
||||
<div className="context-menu-item" onClick={() => handleAction("edit")}>
|
||||
<span className="material-symbols">edit</span>
|
||||
Edit
|
||||
Редактировать
|
||||
</div>
|
||||
<div className="context-menu-item" onClick={() => handleAction("delete")}>
|
||||
<span className="material-symbols">delete</span>
|
||||
Delete
|
||||
Удалить
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
|
||||
@@ -41,8 +41,8 @@ export function MessagePanelRenderer({ panel, isChatSwitching }: MessagePanelRen
|
||||
|
||||
// Cleanup function
|
||||
return () => {
|
||||
if (panel && (panel as any).onStateChange) {
|
||||
(panel as any).onStateChange = null;
|
||||
if (panel && panel.onStateChange) {
|
||||
panel.onStateChange = null;
|
||||
}
|
||||
};
|
||||
}, [panel]);
|
||||
@@ -72,10 +72,10 @@ export function MessagePanelRenderer({ panel, isChatSwitching }: MessagePanelRen
|
||||
<img src={defaultAvatar} alt="Avatar" className="chat-header-avatar" />
|
||||
<div className="chat-header-info">
|
||||
<div className="info-chat">
|
||||
<h4 id="chat-name">Select a chat</h4>
|
||||
<h4 id="chat-name">Выбор чата</h4>
|
||||
<p>
|
||||
<span className="online-status"></span>
|
||||
Choose a chat to start messaging
|
||||
Выберите чат, чтобы начать переписку
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -88,7 +88,7 @@ export function MessagePanelRenderer({ panel, isChatSwitching }: MessagePanelRen
|
||||
height: "100%",
|
||||
color: "var(--mdui-color-on-surface-variant)"
|
||||
}}>
|
||||
Select a chat from the sidebar to start messaging
|
||||
Выберите чат на боковой панели, чтобы начать переписку
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -128,7 +128,7 @@ export function MessagePanelRenderer({ panel, isChatSwitching }: MessagePanelRen
|
||||
height: "100%",
|
||||
color: "var(--mdui-color-on-surface-variant)"
|
||||
}}>
|
||||
Loading messages...
|
||||
Загрузка сообщений...
|
||||
</div>
|
||||
</div>
|
||||
): (
|
||||
|
||||
@@ -36,7 +36,7 @@ export function ReplyMessageDialog({ isOpen, onOpenChange, replyToMessage, onSen
|
||||
return (
|
||||
<MaterialDialog open={isOpen} onOpenChange={onOpenChange} close-on-overlay-click close-on-esc className="reply-dialog">
|
||||
<div className="dialog-content">
|
||||
<h3>Reply to Message</h3>
|
||||
<h3>Ответить на сообщение</h3>
|
||||
<div className="reply-preview-dialog">
|
||||
<div className="reply-content">
|
||||
<span className="reply-username">{replyToMessage.username}</span>
|
||||
|
||||
@@ -28,24 +28,24 @@ export function UserProfileDialog({ isOpen, onOpenChange, userProfile }: UserPro
|
||||
<div className={`online-status ${userProfile.online ? "online" : "offline"}`}>
|
||||
{userProfile.online ? (
|
||||
<>
|
||||
<span className="online-indicator"></span> Online
|
||||
<span className="online-indicator"></span> Онлайн
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<span className="offline-indicator"></span> Last seen {formatTime(userProfile.last_seen)}
|
||||
<span className="offline-indicator"></span> Последний заход {formatTime(userProfile.last_seen)}
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div className="bio-section">
|
||||
<label>Bio:</label>
|
||||
<label>О себе:</label>
|
||||
<div className="bio-display">
|
||||
{userProfile.bio || "No bio available."}
|
||||
</div>
|
||||
</div>
|
||||
<div className="profile-stats">
|
||||
<div className="stat">
|
||||
<span className="stat-label">Member since:</span>
|
||||
<span className="stat-label">Зарегистрирован:</span>
|
||||
<span className="stat-value member-since">{formatTime(userProfile.created_at)}</span>
|
||||
</div>
|
||||
<div className="stat">
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
import { useEffect, useState } from "react";
|
||||
|
||||
export interface WindowSize {
|
||||
width: number;
|
||||
height: number;
|
||||
}
|
||||
|
||||
export default function useWindowSize(): WindowSize {
|
||||
const [width, setWidth] = useState(innerWidth);
|
||||
const [height, setHeight] = useState(innerHeight);
|
||||
|
||||
useEffect(() => {
|
||||
function listener() {
|
||||
setWidth(innerWidth);
|
||||
setHeight(innerHeight);
|
||||
}
|
||||
|
||||
addEventListener("resize", listener);
|
||||
|
||||
return () => {
|
||||
removeEventListener("resize", listener);
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
width: width,
|
||||
height: height
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
export default function DownloadAppScreen() {
|
||||
return (
|
||||
<div className="download-app-screen">
|
||||
<div className="inner">
|
||||
<h1>Чтобы пользоваться мессенджером, скачайте приложение</h1>
|
||||
<p>
|
||||
Этот сайт <b>не предназначен</b> для работы на маленьких экранах, поэтому
|
||||
вам нужно скачать приложение мессенджера.
|
||||
</p>
|
||||
|
||||
<a href="https://github.com/denis0001-dev/FromChat-android/releases/latest">
|
||||
<mdui-button>Скачать на GitHub</mdui-button>
|
||||
</a>
|
||||
|
||||
<p>
|
||||
Если возникнут сложности или есть вопросы, нажмите кнопку!
|
||||
</p>
|
||||
|
||||
<a href="https://t.me/denis0001-dev">
|
||||
<mdui-button>Написать в поддержку</mdui-button>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user