mirror of
https://github.com/fromchat-messenger/web.git
synced 2026-09-22 19:15:08 +03:00
Implement screenshots in features
This commit is contained in:
Binary file not shown.
|
After Width: | Height: | Size: 295 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 231 KiB |
@@ -3,6 +3,9 @@ import { useUserStore } from "@/state/user";
|
||||
import styles from "./home.module.scss";
|
||||
import useDownloadAppScreen from "@/core/hooks/useDownloadAppScreen";
|
||||
import { MaterialButton, MaterialIcon } from "@/utils/material";
|
||||
import generalChatScreenshot from "../../images/screenshots/general-chat.png";
|
||||
import dmScreenshot from "../../images/screenshots/dm.png";
|
||||
import type { ReactNode } from "react";
|
||||
|
||||
function GitHubLink({ children }: { children: React.ReactNode }) {
|
||||
return (
|
||||
@@ -16,6 +19,35 @@ function SupportLink({ children }: { children: React.ReactNode }) {
|
||||
);
|
||||
}
|
||||
|
||||
interface FeatureSectionProps {
|
||||
title: ReactNode;
|
||||
children: ReactNode;
|
||||
screenshot: string;
|
||||
right?: boolean;
|
||||
}
|
||||
|
||||
function FeatureSection({title, children, screenshot, right = false}: FeatureSectionProps) {
|
||||
const featureText = (
|
||||
<div className={styles.featureText}>
|
||||
<div className={styles.featureTitle}>{title}</div>
|
||||
<div className={styles.featureDesc}>{children}</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
const featureScreenshot = (
|
||||
<div className={styles.featureScreenshotOuter}>
|
||||
<div className={styles.featureScreenshotGlow} />
|
||||
<img src={screenshot} className={styles.featureScreenshot} />
|
||||
</div>
|
||||
)
|
||||
|
||||
return (
|
||||
<div className={`${styles.featureContainer}`}>
|
||||
{right ? <>{featureText}{featureScreenshot}</> : <>{featureScreenshot}{featureText}</>}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default function HomePage() {
|
||||
const navigate = useNavigate();
|
||||
const { user } = useUserStore();
|
||||
@@ -75,76 +107,18 @@ export default function HomePage() {
|
||||
</section>
|
||||
|
||||
<section className={styles.features}>
|
||||
<div className={styles.container}>
|
||||
<h3 className={styles.sectionTitle}>Возможности</h3>
|
||||
<div className={styles.featuresGrid}>
|
||||
<div className={styles.featureCard}>
|
||||
<div className={styles.featureIcon}>
|
||||
<MaterialIcon name="security" />
|
||||
</div>
|
||||
<h4>End-to-End Шифрование</h4>
|
||||
<p>
|
||||
Ваши личные сообщения защищены современным шифрованием X25519 + AES-GCM.
|
||||
Только вы и получатель можете прочитать сообщения.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className={styles.featureCard}>
|
||||
<div className={styles.featureIcon}>
|
||||
<MaterialIcon name="code" />
|
||||
</div>
|
||||
<h4>100% открытый код</h4>
|
||||
<p>
|
||||
Весь исходный код доступен на <GitHubLink>GitHub</GitHubLink>. Вы можете проверить безопасность,
|
||||
внести изменения или развернуть свой сервер.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className={styles.featureCard}>
|
||||
<div className={styles.featureIcon}>
|
||||
<MaterialIcon name="attach_file" />
|
||||
</div>
|
||||
<h4>Обмен Файлами</h4>
|
||||
<p>
|
||||
Отправляйте файлы до 4 ГБ. Файлы в личных сообщениях шифруются.
|
||||
В общем чате шифрования нет, так как ваши сообщения могут читать все пользователи FromChat.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className={styles.featureCard}>
|
||||
<div className={styles.featureIcon}>
|
||||
<MaterialIcon name="notifications" />
|
||||
</div>
|
||||
<h4>Уведомления</h4>
|
||||
<p>
|
||||
Получайте push-уведомления в браузере и настольном приложении.
|
||||
Никогда не пропустите важное сообщение.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className={styles.featureCard}>
|
||||
<div className={styles.featureIcon}>
|
||||
<MaterialIcon name="edit" />
|
||||
</div>
|
||||
<h4>Редактирование</h4>
|
||||
<p>
|
||||
Редактируйте и удаляйте свои сообщения. Отвечайте на сообщения
|
||||
для лучшего контекста общения.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className={styles.featureCard}>
|
||||
<div className={styles.featureIcon}>
|
||||
<MaterialIcon name="computer" />
|
||||
</div>
|
||||
<h4>Кроссплатформенность</h4>
|
||||
<p>
|
||||
Работает в браузере и как настольное приложение для Windows,
|
||||
macOS и Linux. Единый интерфейс везде.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<FeatureSection
|
||||
title={<>Общий чат</>}
|
||||
screenshot={generalChatScreenshot}
|
||||
right
|
||||
>
|
||||
Общайтесь со всеми пользователями этого сервера FromChat.
|
||||
</FeatureSection>
|
||||
<FeatureSection
|
||||
title={<>Личные сообщения</>}
|
||||
screenshot={dmScreenshot}>
|
||||
Общайтесь с одним человеком.
|
||||
</FeatureSection>
|
||||
</section>
|
||||
|
||||
<section className={styles.download}>
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
color: $color-dark-on-background;
|
||||
font-family: 'Montserrat', sans-serif;
|
||||
position: relative;
|
||||
background-color: $color-dark-surface;
|
||||
|
||||
// Container styles
|
||||
.container {
|
||||
@@ -145,98 +146,88 @@
|
||||
|
||||
// Features section
|
||||
.features {
|
||||
padding: 6rem 0;
|
||||
backdrop-filter: blur(20px);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 50px;
|
||||
|
||||
.sectionTitle {
|
||||
text-align: center;
|
||||
font-size: 2.5rem;
|
||||
.featureContainer {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
gap: 20px;
|
||||
padding: 0 16px;
|
||||
align-items: center;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
max-width: 700px;
|
||||
|
||||
.featureText {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
flex-grow: 1;
|
||||
flex-shrink: 1;
|
||||
|
||||
.featureTitle {
|
||||
font-size: 30pt;
|
||||
font-weight: 700;
|
||||
margin-bottom: 3rem;
|
||||
background: linear-gradient(45deg, $color-dark-primary, $color-dark-tertiary);
|
||||
background: linear-gradient(45deg, #9333EA, #6366F1, #3B82F6, #A855F7, #D946EF, #EC4899, #7E22CE);
|
||||
background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
background-clip: text;
|
||||
text-shadow: 0 0 20px rgba($color-dark-primary, 0.5);
|
||||
text-shadow: 0 0 20px rgba(147, 51, 234, 0.5);
|
||||
line-height: normal;
|
||||
}
|
||||
|
||||
.featuresGrid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(350px, 1fr));
|
||||
gap: 2rem;
|
||||
.featureDesc {
|
||||
text-align: left;
|
||||
font-size: 15pt;
|
||||
}
|
||||
}
|
||||
|
||||
.featureCard {
|
||||
background: rgba($color-dark-surface-container, 0.6);
|
||||
backdrop-filter: blur(20px);
|
||||
border-radius: 20px;
|
||||
padding: 2rem;
|
||||
border: 1px solid rgba($color-dark-primary, 0.3);
|
||||
transition: all 0.3s ease;
|
||||
.featureScreenshotOuter {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
|
||||
&::before {
|
||||
content: '';
|
||||
.featureScreenshotGlow {
|
||||
$size: 400px;
|
||||
|
||||
@keyframes rotateGradient {
|
||||
from {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
to {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
background: conic-gradient(
|
||||
from 0deg,
|
||||
rgba(147, 51, 234, 0.5) 0%,
|
||||
rgba(99, 102, 241, 0.6) 12.5%,
|
||||
rgba(59, 130, 246, 0.55) 25%,
|
||||
rgba(168, 85, 247, 0.5) 37.5%,
|
||||
rgba(217, 70, 239, 0.6) 50%,
|
||||
rgba(236, 72, 153, 0.55) 62.5%,
|
||||
rgba(192, 132, 252, 0.5) 75%,
|
||||
rgba(126, 34, 206, 0.6) 87.5%,
|
||||
rgba(147, 51, 234, 0.5) 100%
|
||||
);
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: linear-gradient(135deg, rgba($color-dark-primary, 0.1), rgba($color-dark-tertiary, 0.1));
|
||||
opacity: 0;
|
||||
transition: opacity 0.3s ease;
|
||||
width: $size;
|
||||
height: $size;
|
||||
top: calc(50% - ($size / 2));
|
||||
opacity: 0.6;
|
||||
left: calc(50% - ($size / 2));
|
||||
border-radius: 50%;
|
||||
filter: blur(80px);
|
||||
z-index: 0;
|
||||
will-change: transform;
|
||||
animation: rotateGradient 8s linear infinite;
|
||||
}
|
||||
|
||||
> * {
|
||||
.featureScreenshot {
|
||||
max-width: 300px;
|
||||
z-index: 50;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
transform: translateY(-5px);
|
||||
box-shadow:
|
||||
0 20px 40px rgba(0, 0, 0, 0.3),
|
||||
0 0 30px rgba($color-dark-primary, 0.2);
|
||||
border-color: rgba($color-dark-primary, 0.5);
|
||||
|
||||
&::before {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.featureIcon {
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
background: linear-gradient(135deg, rgba($color-dark-primary, 0.3), rgba($color-dark-tertiary, 0.3));
|
||||
border-radius: 15px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-bottom: 1.5rem;
|
||||
border: 1px solid rgba($color-dark-primary, 0.4);
|
||||
box-shadow: 0 0 15px rgba($color-dark-primary, 0.2);
|
||||
user-select: none;
|
||||
|
||||
mdui-icon {
|
||||
font-size: 1.5rem;
|
||||
color: $color-dark-primary;
|
||||
text-shadow: 0 0 10px rgba($color-dark-primary, 0.8);
|
||||
}
|
||||
}
|
||||
|
||||
h4 {
|
||||
font-size: 1.25rem;
|
||||
font-weight: 600;
|
||||
margin-bottom: 1rem;
|
||||
color: $color-dark-on-surface;
|
||||
text-shadow: 0 0 10px rgba($color-dark-primary, 0.3);
|
||||
}
|
||||
|
||||
p {
|
||||
line-height: 1.6;
|
||||
opacity: 0.9;
|
||||
color: $color-dark-on-surface-variant;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -280,9 +271,6 @@
|
||||
|
||||
// CTA section
|
||||
.cta {
|
||||
padding: 6rem 0;
|
||||
backdrop-filter: blur(20px);
|
||||
|
||||
.ctaContent {
|
||||
text-align: center;
|
||||
max-width: 600px;
|
||||
@@ -317,10 +305,6 @@
|
||||
|
||||
// Footer
|
||||
.homepageFooter {
|
||||
backdrop-filter: blur(20px);
|
||||
padding: 3rem 0 1rem;
|
||||
box-shadow: 0 -4px 20px rgba($color-dark-primary, 0.1);
|
||||
|
||||
.footerContent {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
|
||||
|
||||
Reference in New Issue
Block a user