feat(message): paint non-own bubbles via --vojo-peer-bubble-bg in Stream + Channel layouts and Stream rail/day-divider via --vojo-timeline-rail
This commit is contained in:
parent
c78984a6d8
commit
45c69317ff
7 changed files with 51 additions and 3 deletions
|
|
@ -169,6 +169,10 @@ globalStyle(
|
||||||
`${ChannelRow}[data-bubble="true"][data-own="false"] ${ChannelMessageBody}`,
|
`${ChannelRow}[data-bubble="true"][data-own="false"] ${ChannelMessageBody}`,
|
||||||
{
|
{
|
||||||
borderRadius: `${config.radii.R500} ${config.radii.R500} ${config.radii.R500} ${toRem(4)}`,
|
borderRadius: `${config.radii.R500} ${config.radii.R500} ${config.radii.R500} ${toRem(4)}`,
|
||||||
|
// Peer (not-own) bubble bg — matches Stream layout's `peerBg`
|
||||||
|
// variant. Covers channels main timeline AND thread drawer
|
||||||
|
// (both pass `headerInBubble`, so `data-bubble="true"` fires).
|
||||||
|
backgroundColor: 'var(--vojo-peer-bubble-bg)',
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,10 @@ export type StreamLayoutProps = {
|
||||||
dotColor: string;
|
dotColor: string;
|
||||||
dotOpacity: number;
|
dotOpacity: number;
|
||||||
isOwn?: boolean;
|
isOwn?: boolean;
|
||||||
|
// Peer (not-own) bubble bg — caller passes `!isOwn` so every
|
||||||
|
// «чужое» сообщение reshades to `--vojo-peer-bubble-bg`. Applies
|
||||||
|
// in 1-1 DMs, groups, channels alike. No effect for own messages.
|
||||||
|
peerBg?: boolean;
|
||||||
compact?: boolean;
|
compact?: boolean;
|
||||||
header?: ReactNode;
|
header?: ReactNode;
|
||||||
railStart?: boolean;
|
railStart?: boolean;
|
||||||
|
|
@ -100,6 +104,7 @@ export const StreamLayout = as<'div', StreamLayoutProps>(
|
||||||
dotColor,
|
dotColor,
|
||||||
dotOpacity,
|
dotOpacity,
|
||||||
isOwn,
|
isOwn,
|
||||||
|
peerBg,
|
||||||
compact,
|
compact,
|
||||||
header,
|
header,
|
||||||
railStart,
|
railStart,
|
||||||
|
|
@ -169,6 +174,7 @@ export const StreamLayout = as<'div', StreamLayoutProps>(
|
||||||
className={css.StreamBubble({
|
className={css.StreamBubble({
|
||||||
own: !!isOwn,
|
own: !!isOwn,
|
||||||
compact: !!compact,
|
compact: !!compact,
|
||||||
|
peerBg: !!peerBg,
|
||||||
mediaMode: !!mediaMode,
|
mediaMode: !!mediaMode,
|
||||||
})}
|
})}
|
||||||
ref={bubbleRef}
|
ref={bubbleRef}
|
||||||
|
|
|
||||||
|
|
@ -283,7 +283,7 @@ export const StreamRail = style({
|
||||||
left: '50%',
|
left: '50%',
|
||||||
transform: 'translateX(-50%)',
|
transform: 'translateX(-50%)',
|
||||||
width: StreamRailLineWidth,
|
width: StreamRailLineWidth,
|
||||||
background: color.Surface.Container,
|
background: 'var(--vojo-timeline-rail)',
|
||||||
pointerEvents: 'none',
|
pointerEvents: 'none',
|
||||||
zIndex: 0,
|
zIndex: 0,
|
||||||
});
|
});
|
||||||
|
|
@ -452,6 +452,14 @@ export const StreamBubble = recipe({
|
||||||
paddingRight: toRem(15),
|
paddingRight: toRem(15),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
// Peer (not-own) bubble bg — differentiation between «я» and
|
||||||
|
// «не я» across every room class. Media rows neutralize this via
|
||||||
|
// the `peerBg + mediaMode` compound below (order-independent).
|
||||||
|
peerBg: {
|
||||||
|
true: {
|
||||||
|
backgroundColor: 'var(--vojo-peer-bubble-bg)',
|
||||||
|
},
|
||||||
|
},
|
||||||
// Image messages: bubble becomes a transparent shell so the
|
// Image messages: bubble becomes a transparent shell so the
|
||||||
// StreamMediaImage child supplies the visible chrome instead.
|
// StreamMediaImage child supplies the visible chrome instead.
|
||||||
// `display: block, width: 100%` (NOT fit-content) so the bubble has a
|
// `display: block, width: 100%` (NOT fit-content) so the bubble has a
|
||||||
|
|
@ -471,9 +479,21 @@ export const StreamBubble = recipe({
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
// Compound overrides — emitted after all variant classes, so they
|
||||||
|
// win the cascade regardless of variant declaration order. Keeps
|
||||||
|
// peer image / video bubbles transparent (the StreamMediaImage
|
||||||
|
// child supplies the chrome) even though `peerBg` would otherwise
|
||||||
|
// paint `--vojo-peer-bubble-bg` underneath.
|
||||||
|
compoundVariants: [
|
||||||
|
{
|
||||||
|
variants: { peerBg: true, mediaMode: true },
|
||||||
|
style: { backgroundColor: 'transparent' },
|
||||||
|
},
|
||||||
|
],
|
||||||
defaultVariants: {
|
defaultVariants: {
|
||||||
own: false,
|
own: false,
|
||||||
compact: false,
|
compact: false,
|
||||||
|
peerBg: false,
|
||||||
mediaMode: false,
|
mediaMode: false,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
@ -631,7 +651,7 @@ export const StreamDayLineWrap = style({
|
||||||
export const StreamDayLineSegment = style({
|
export const StreamDayLineSegment = style({
|
||||||
flex: 1,
|
flex: 1,
|
||||||
height: 1,
|
height: 1,
|
||||||
background: color.Surface.Container,
|
background: 'var(--vojo-timeline-rail)',
|
||||||
minWidth: toRem(8),
|
minWidth: toRem(8),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -109,6 +109,7 @@ export function CallMessage({
|
||||||
|
|
||||||
const senderId = aggregate.anchorSenderId;
|
const senderId = aggregate.anchorSenderId;
|
||||||
const isOwnMessage = !!mx.getUserId() && senderId === mx.getUserId();
|
const isOwnMessage = !!mx.getUserId() && senderId === mx.getUserId();
|
||||||
|
const peerBg = !isOwnMessage;
|
||||||
const senderName =
|
const senderName =
|
||||||
getMemberDisplayName(room, senderId) || getMxIdLocalPart(senderId) || senderId;
|
getMemberDisplayName(room, senderId) || getMxIdLocalPart(senderId) || senderId;
|
||||||
|
|
||||||
|
|
@ -220,6 +221,7 @@ export function CallMessage({
|
||||||
dotColor={dot.color}
|
dotColor={dot.color}
|
||||||
dotOpacity={dot.opacity}
|
dotOpacity={dot.opacity}
|
||||||
isOwn={isOwnMessage}
|
isOwn={isOwnMessage}
|
||||||
|
peerBg={peerBg}
|
||||||
compact={isMobile}
|
compact={isMobile}
|
||||||
railStart={streamRailStart}
|
railStart={streamRailStart}
|
||||||
railEnd={streamRailEnd}
|
railEnd={streamRailEnd}
|
||||||
|
|
|
||||||
|
|
@ -761,7 +761,7 @@ export const Message = as<'div', MessageProps>(
|
||||||
const [menuAnchor, setMenuAnchor] = useState<RectCords>();
|
const [menuAnchor, setMenuAnchor] = useState<RectCords>();
|
||||||
const [emojiBoardAnchor, setEmojiBoardAnchor] = useState<RectCords>();
|
const [emojiBoardAnchor, setEmojiBoardAnchor] = useState<RectCords>();
|
||||||
|
|
||||||
const isOwnMessage = senderId === mx.getUserId();
|
const isOwnMessage = !!mx.getUserId() && senderId === mx.getUserId();
|
||||||
const senderDisplayName =
|
const senderDisplayName =
|
||||||
getMemberDisplayName(room, senderId) ?? getMxIdLocalPart(senderId) ?? senderId;
|
getMemberDisplayName(room, senderId) ?? getMxIdLocalPart(senderId) ?? senderId;
|
||||||
|
|
||||||
|
|
@ -774,6 +774,7 @@ export const Message = as<'div', MessageProps>(
|
||||||
const dot = useDotColor(room, mEvent, true, hideReadReceipts);
|
const dot = useDotColor(room, mEvent, true, hideReadReceipts);
|
||||||
const screenSize = useScreenSizeContext();
|
const screenSize = useScreenSizeContext();
|
||||||
const isMobile = screenSize === ScreenSize.Mobile;
|
const isMobile = screenSize === ScreenSize.Mobile;
|
||||||
|
const peerBg = !isOwnMessage;
|
||||||
|
|
||||||
// msgType comes from the parent — RoomTimeline reads
|
// msgType comes from the parent — RoomTimeline reads
|
||||||
// `mEvent.getContent().msgtype` synchronously and re-evaluates inside
|
// `mEvent.getContent().msgtype` synchronously and re-evaluates inside
|
||||||
|
|
@ -1200,6 +1201,7 @@ export const Message = as<'div', MessageProps>(
|
||||||
dotColor={dot.color}
|
dotColor={dot.color}
|
||||||
dotOpacity={dot.opacity}
|
dotOpacity={dot.opacity}
|
||||||
isOwn={isOwnMessage}
|
isOwn={isOwnMessage}
|
||||||
|
peerBg={peerBg}
|
||||||
compact={isMobile}
|
compact={isMobile}
|
||||||
railStart={streamRailStart}
|
railStart={streamRailStart}
|
||||||
railEnd={streamRailEnd}
|
railEnd={streamRailEnd}
|
||||||
|
|
|
||||||
|
|
@ -58,6 +58,7 @@ export function SyslineMessage({
|
||||||
|
|
||||||
const senderId = mEvent.getSender() ?? '';
|
const senderId = mEvent.getSender() ?? '';
|
||||||
const isOwnMessage = !!mx.getUserId() && senderId === mx.getUserId();
|
const isOwnMessage = !!mx.getUserId() && senderId === mx.getUserId();
|
||||||
|
const peerBg = !isOwnMessage;
|
||||||
const senderName =
|
const senderName =
|
||||||
getMemberDisplayName(room, senderId) || getMxIdLocalPart(senderId) || senderId;
|
getMemberDisplayName(room, senderId) || getMxIdLocalPart(senderId) || senderId;
|
||||||
|
|
||||||
|
|
@ -112,6 +113,7 @@ export function SyslineMessage({
|
||||||
dotColor={dot.color}
|
dotColor={dot.color}
|
||||||
dotOpacity={dot.opacity}
|
dotOpacity={dot.opacity}
|
||||||
isOwn={isOwnMessage}
|
isOwn={isOwnMessage}
|
||||||
|
peerBg={peerBg}
|
||||||
compact={isMobile}
|
compact={isMobile}
|
||||||
railStart={streamRailStart}
|
railStart={streamRailStart}
|
||||||
railEnd={streamRailEnd}
|
railEnd={streamRailEnd}
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,15 @@
|
||||||
default is the light-theme value; `.dark-theme` overrides below. */
|
default is the light-theme value; `.dark-theme` overrides below. */
|
||||||
--vojo-horseshoe-void: #d6d6e3;
|
--vojo-horseshoe-void: #d6d6e3;
|
||||||
|
|
||||||
|
/* Peer (not-own) bubble bg — every «чужое» message reshades to
|
||||||
|
this, in 1-1 DMs, groups, channels alike. Light: slight off-white
|
||||||
|
step from #ffffff. Dark override below. */
|
||||||
|
--vojo-peer-bubble-bg: #f5f5fa;
|
||||||
|
/* Stream timeline rail (vertical line through dots) + day-divider
|
||||||
|
horizontal segments. Light: hairline cool-grey; dark overrides
|
||||||
|
below. */
|
||||||
|
--vojo-timeline-rail: #e8e8f2;
|
||||||
|
|
||||||
--font-emoji: 'Twemoji_DISABLED';
|
--font-emoji: 'Twemoji_DISABLED';
|
||||||
--font-secondary: 'InterVariable', var(--font-emoji), sans-serif;
|
--font-secondary: 'InterVariable', var(--font-emoji), sans-serif;
|
||||||
}
|
}
|
||||||
|
|
@ -39,6 +48,9 @@
|
||||||
|
|
||||||
--vojo-horseshoe-void: #090909;
|
--vojo-horseshoe-void: #090909;
|
||||||
|
|
||||||
|
--vojo-peer-bubble-bg: #090909;
|
||||||
|
--vojo-timeline-rail: #000000;
|
||||||
|
|
||||||
--font-secondary: 'InterVariable', var(--font-emoji), sans-serif;
|
--font-secondary: 'InterVariable', var(--font-emoji), sans-serif;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue