mirror of
https://github.com/fromchat-messenger/web.git
synced 2026-09-22 19:15:08 +03:00
Fix reply preview
This commit is contained in:
@@ -2,24 +2,6 @@
|
|||||||
@use "../../../css/material" as *;
|
@use "../../../css/material" as *;
|
||||||
@use "sass:color";
|
@use "sass:color";
|
||||||
|
|
||||||
// Reply preview styles (shared with Message component)
|
|
||||||
.quote.contextualContent > .quoteInner {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
gap: 4px;
|
|
||||||
|
|
||||||
.replyUsername {
|
|
||||||
font-weight: 600;
|
|
||||||
color: $color-dark-on-surface;
|
|
||||||
font-size: 0.85rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.replyText {
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.chatInputWrapper {
|
.chatInputWrapper {
|
||||||
position: relative;
|
position: relative;
|
||||||
margin: 0 10px 10px 10px;
|
margin: 0 10px 10px 10px;
|
||||||
|
|||||||
@@ -2,27 +2,11 @@
|
|||||||
@use "../../../css/material" as *;
|
@use "../../../css/material" as *;
|
||||||
@use "sass:color";
|
@use "sass:color";
|
||||||
|
|
||||||
.quote.contextualContent > .quoteInner {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
gap: 4px;
|
|
||||||
|
|
||||||
.replyUsername {
|
|
||||||
font-weight: 600;
|
|
||||||
color: $color-dark-on-surface;
|
|
||||||
font-size: 0.85rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.replyText {
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.message {
|
.message {
|
||||||
$status-indicator-size: 16px;
|
$status-indicator-size: 16px;
|
||||||
|
|
||||||
margin-bottom: 1rem;
|
margin-bottom: 10px;
|
||||||
max-width: 70%;
|
max-width: 70%;
|
||||||
position: relative;
|
position: relative;
|
||||||
width: fit-content;
|
width: fit-content;
|
||||||
@@ -30,30 +14,8 @@
|
|||||||
align-items: flex-start;
|
align-items: flex-start;
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
|
|
||||||
&.received {
|
|
||||||
.messageProfilePic {
|
|
||||||
width: 40px;
|
|
||||||
height: 40px;
|
|
||||||
flex-shrink: 0;
|
|
||||||
cursor: pointer;
|
|
||||||
transition: transform 0.2s ease;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
transform: scale(1.05);
|
|
||||||
}
|
|
||||||
|
|
||||||
img {
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
border-radius: 50%;
|
|
||||||
object-fit: cover;
|
|
||||||
border: 2px solid $color-dark-outline;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.messageInner {
|
.messageInner {
|
||||||
border-radius: 12px;
|
border-radius: 20px 20px 8px 8px; // Top corners rounded, bottom corners sharper
|
||||||
position: relative;
|
position: relative;
|
||||||
word-wrap: break-word;
|
word-wrap: break-word;
|
||||||
overflow-wrap: anywhere;
|
overflow-wrap: anywhere;
|
||||||
@@ -72,6 +34,7 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 4px;
|
gap: 4px;
|
||||||
|
width: fit-content;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
transform: scale(1.05);
|
transform: scale(1.05);
|
||||||
@@ -92,9 +55,10 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.quote.replyPreview {
|
:global(.quote).replyPreview {
|
||||||
user-select: none;
|
user-select: none;
|
||||||
margin: 10px;
|
margin: 5px;
|
||||||
|
border-radius: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.messageAttachments {
|
.messageAttachments {
|
||||||
@@ -194,10 +158,31 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
&.received {
|
&.received {
|
||||||
|
.messageProfilePic {
|
||||||
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
|
flex-shrink: 0;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: transform 0.2s ease;
|
||||||
|
align-self: flex-end;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
transform: scale(1.05);
|
||||||
|
}
|
||||||
|
|
||||||
|
img {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
border-radius: 50%;
|
||||||
|
object-fit: cover;
|
||||||
|
border: 2px solid $color-dark-outline;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.messageInner {
|
.messageInner {
|
||||||
background: $color-dark-surface-container;
|
background: $color-dark-surface-container;
|
||||||
color: $color-dark-on-surface;
|
color: $color-dark-on-surface;
|
||||||
border-top-left-radius: 5px;
|
border-radius: 20px 20px 20px 8px; // Top-left: 5px, top-right: 20px, bottom: 8px
|
||||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
||||||
border: 1px solid rgba($color-dark-outline-variant, 0.4);
|
border: 1px solid rgba($color-dark-outline-variant, 0.4);
|
||||||
position: relative;
|
position: relative;
|
||||||
@@ -231,27 +216,27 @@
|
|||||||
margin-left: auto;
|
margin-left: auto;
|
||||||
flex-direction: row-reverse;
|
flex-direction: row-reverse;
|
||||||
|
|
||||||
|
:global(.quote).replyPreview {
|
||||||
|
background: linear-gradient(135deg, rgba(255, 255, 255, 0.15), rgba(255, 255, 255, 0.08));
|
||||||
|
border: 1px solid rgba(255, 255, 255, 0.2);
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
box-shadow: 0 2px 8px rgba(147, 51, 234, 0.5);
|
||||||
|
|
||||||
|
:global(.quote-inner) {
|
||||||
|
position: relative;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.messageInner {
|
.messageInner {
|
||||||
background: linear-gradient(135deg, #9333EA, #6366F1, #3B82F6);
|
background: linear-gradient(135deg, #9333EA, #6366F1, #2f68c5);
|
||||||
color: $color-dark-on-primary;
|
border-radius: 20px 20px 8px 20px; // Top-left: 20px, top-right: 5px, bottom: 8px
|
||||||
border-top-right-radius: 5px;
|
|
||||||
box-shadow: 0 0 20px rgba($color-dark-primary, 0.4);
|
box-shadow: 0 0 20px rgba($color-dark-primary, 0.4);
|
||||||
border: 1px solid rgba($color-dark-primary, 0.5);
|
border: 1px solid rgba($color-dark-primary, 0.5);
|
||||||
position: relative;
|
position: relative;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
|
||||||
&::before {
|
|
||||||
content: '';
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
bottom: 0;
|
|
||||||
background: linear-gradient(135deg, rgba(255, 255, 255, 0.15), rgba(255, 255, 255, 0.08));
|
|
||||||
pointer-events: none;
|
|
||||||
z-index: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
> * {
|
> * {
|
||||||
position: relative;
|
position: relative;
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
@@ -273,7 +258,6 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.messageTime {
|
.messageTime {
|
||||||
color: $color-dark-on-primary;
|
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,19 @@
|
|||||||
|
@use "../../../css/colors" as *;
|
||||||
|
@use "../../../css/material" as *;
|
||||||
|
|
||||||
|
:global(.quote).contextualContent > :global(.quote-inner) {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 4px;
|
||||||
|
|
||||||
|
.replyUsername {
|
||||||
|
font-weight: 600;
|
||||||
|
color: $color-dark-on-surface;
|
||||||
|
font-size: 0.85rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.replyText {
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -7,6 +7,7 @@ import { useImmer } from "use-immer";
|
|||||||
import { EmojiMenu } from "./EmojiMenu";
|
import { EmojiMenu } from "./EmojiMenu";
|
||||||
import { MaterialIcon, MaterialIconButton } from "@/utils/material";
|
import { MaterialIcon, MaterialIconButton } from "@/utils/material";
|
||||||
import styles from "@/pages/chat/css/ChatInput.module.scss";
|
import styles from "@/pages/chat/css/ChatInput.module.scss";
|
||||||
|
import replyPreviewStyles from "@/pages/chat/css/reply-preview.module.scss";
|
||||||
import { alert } from "mdui/functions/alert";
|
import { alert } from "mdui/functions/alert";
|
||||||
|
|
||||||
interface ChatInputWrapperProps {
|
interface ChatInputWrapperProps {
|
||||||
@@ -161,9 +162,9 @@ export function ChatInputWrapper(
|
|||||||
>
|
>
|
||||||
<div className={styles.contextualPreview}>
|
<div className={styles.contextualPreview}>
|
||||||
<MaterialIcon name="edit" />
|
<MaterialIcon name="edit" />
|
||||||
<Quote className={`${styles.quote} ${styles.contextualContent}`} background="surfaceContainer">
|
<Quote className={`${replyPreviewStyles.contextualContent}`} background="surfaceContainer">
|
||||||
<span className={styles.replyUsername}>{editingMessage!.username}</span>
|
<span className={replyPreviewStyles.replyUsername}>{editingMessage!.username}</span>
|
||||||
<span className={styles.replyText}>{editingMessage!.content}</span>
|
<span className={replyPreviewStyles.replyText}>{editingMessage!.content}</span>
|
||||||
</Quote>
|
</Quote>
|
||||||
<MaterialIconButton icon="close" className={styles.replyCancel} onClick={onClearEdit}></MaterialIconButton>
|
<MaterialIconButton icon="close" className={styles.replyCancel} onClick={onClearEdit}></MaterialIconButton>
|
||||||
</div>
|
</div>
|
||||||
@@ -181,9 +182,9 @@ export function ChatInputWrapper(
|
|||||||
>
|
>
|
||||||
<div className={styles.contextualPreview}>
|
<div className={styles.contextualPreview}>
|
||||||
<MaterialIcon name="reply" />
|
<MaterialIcon name="reply" />
|
||||||
<Quote className={`${styles.quote} ${styles.contextualContent}`} background="surfaceContainer">
|
<Quote className={`${replyPreviewStyles.contextualContent}`} background="surfaceContainer">
|
||||||
<span className={styles.replyUsername}>{replyTo!.username}</span>
|
<span className={replyPreviewStyles.replyUsername}>{replyTo!.username}</span>
|
||||||
<span className={styles.replyText}>{replyTo!.content}</span>
|
<span className={replyPreviewStyles.replyText}>{replyTo!.content}</span>
|
||||||
</Quote>
|
</Quote>
|
||||||
<MaterialIconButton icon="close" className={styles.replyCancel} onClick={onClearReply}></MaterialIconButton>
|
<MaterialIconButton icon="close" className={styles.replyCancel} onClick={onClearReply}></MaterialIconButton>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ import { createPortal } from "react-dom";
|
|||||||
import { parseProfileLink } from "@/core/profileLinks";
|
import { parseProfileLink } from "@/core/profileLinks";
|
||||||
import { MaterialCircularProgress, MaterialIconButton, MaterialList, MaterialListItem } from "@/utils/material";
|
import { MaterialCircularProgress, MaterialIconButton, MaterialList, MaterialListItem } from "@/utils/material";
|
||||||
import styles from "@/pages/chat/css/Message.module.scss";
|
import styles from "@/pages/chat/css/Message.module.scss";
|
||||||
|
import replyPreviewStyles from "@/pages/chat/css/reply-preview.module.scss";
|
||||||
|
|
||||||
interface MessageReactionsProps {
|
interface MessageReactionsProps {
|
||||||
reactions?: Reaction[];
|
reactions?: Reaction[];
|
||||||
@@ -483,7 +484,7 @@ export function Message({ message, isAuthor, onContextMenu, onReactionClick, isD
|
|||||||
{!isAuthor && !isDm && (
|
{!isAuthor && !isDm && (
|
||||||
<div className={styles.messageProfilePic} onClick={handleProfileClick}>
|
<div className={styles.messageProfilePic} onClick={handleProfileClick}>
|
||||||
<img
|
<img
|
||||||
src={message.username?.startsWith("Deleted User #") ? defaultAvatar : (message.profile_picture || defaultAvatar)}
|
src={message.profile_picture || defaultAvatar}
|
||||||
alt={message.username}
|
alt={message.username}
|
||||||
onError={(e) => {
|
onError={(e) => {
|
||||||
e.target.src = defaultAvatar;
|
e.target.src = defaultAvatar;
|
||||||
@@ -507,9 +508,9 @@ export function Message({ message, isAuthor, onContextMenu, onReactionClick, isD
|
|||||||
)}
|
)}
|
||||||
|
|
||||||
{message.reply_to && (
|
{message.reply_to && (
|
||||||
<Quote className={`${styles.replyPreview} ${styles.contextualContent}`} background={isAuthor ? "primaryContainer" : "surfaceContainer"}>
|
<Quote className={`${styles.replyPreview} ${replyPreviewStyles.contextualContent}`} background={isAuthor ? "primaryContainer" : "surfaceContainer"}>
|
||||||
<span className={styles.replyUsername}>{message.reply_to.username}</span>
|
<span className={replyPreviewStyles.replyUsername}>{message.reply_to.username}</span>
|
||||||
<span className={styles.replyText}>{message.reply_to.content}</span>
|
<span className={replyPreviewStyles.replyText}>{message.reply_to.content}</span>
|
||||||
</Quote>
|
</Quote>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user