chat-fe: reflow profile overlay near edges of screen

Polls for the distance between the top of the container and reflows the
overlay accordingly.
This commit is contained in:
Liam Fitzgerald 2020-04-10 14:34:48 +10:00
parent 188a1e8dcf
commit 1bca495d8a
3 changed files with 62 additions and 15 deletions

View File

@ -279,7 +279,7 @@ export class ChatScreen extends Component {
/>
</div>
<div
className="overflow-y-scroll bg-white bg-gray0-d pt3 pb2 flex flex-column-reverse"
className="overflow-y-scroll bg-white bg-gray0-d pt3 pb2 flex flex-column-reverse relative"
style={{ height: "100%", resize: "vertical" }}
onScroll={this.onScroll}>
<div

View File

@ -16,10 +16,26 @@ export class Message extends Component {
unfold: false,
copied: false,
profileClicked: false,
profileCaptured: false
profileCaptured: false,
containerOffset: 0,
containerHeight: 0,
};
this.unFoldEmbed = this.unFoldEmbed.bind(this);
this.profileToggle = this.profileToggle.bind(this);
this.containerRef = React.createRef();
this.profileCaptured = this.profileCaptured.bind(this);
this.updateContainerInterval = setInterval(this.updateContainerOffset.bind(this), 1000);
}
componentDidMount() {
this.updateContainerOffset();
}
componentWillUnmount() {
if(this.updateContainerInterval) {
clearInterval(this.updateContainerInterval);
this.updateContainerInterval = null;
}
}
unFoldEmbed(id) {
@ -47,6 +63,18 @@ export class Message extends Component {
this.setState({ profileCaptured })
}
updateContainerOffset() {
if(this.containerRef && this.containerRef.current) {
const { scrollHeight, clientHeight, scrollTop } = this.containerRef.current.offsetParent;
const offset = scrollHeight - clientHeight;
const { offsetTop, offsetHeight } = this.containerRef.current;
const normalized = offset + (offsetTop );
this.setState({ containerOffset: normalized, containerHeight: clientHeight });
}
}
renderContent() {
const { props } = this;
let letter = props.msg.letter;
@ -183,22 +211,26 @@ export class Message extends Component {
return (
<div
ref={this.containerRef}
className={
"relative w-100 f8 pl3 pt4 pr3 cf flex lh-copy " + " " + pending
"w-100 f8 pl3 pt4 pr3 cf flex lh-copy " + " " + pending
}
style={{
minHeight: "min-content"
}}>
{ (state.profileClicked || state.profileCaptured) && (
<ProfileOverlay
ship={props.msg.author}
name={contact.nickname}
color={color}
onMouseEnter={() => this.profileCaptured(true)}
onMouseLeave={() => this.profileCaptured(false)}
/>
)}
<div onClick={this.profileToggle} className="fl pr3 v-top bg-white bg-gray0-d pointer">
<div onClick={this.profileToggle} className="fl pr3 v-top bg-white bg-gray0-d pointer relative">
{ (state.profileClicked || state.profileCaptured) && (
<ProfileOverlay
ship={props.msg.author}
name={contact.nickname}
color={color}
offset={state.containerOffset}
height={state.containerHeight}
onMouseEnter={() => this.profileCaptured(true)}
onMouseLeave={() => this.profileCaptured(false)}
/>
)}
<Sigil
ship={props.msg.author}
size={24}

View File

@ -1,18 +1,33 @@
import React, { Component } from "react";
import { Sigil } from "/components/lib/icons/sigil";
const HEIGHT = 250;
export class ProfileOverlay extends Component {
constructor() {
super();
}
render() {
const { name, ship, color } = this.props;
const { name, ship, color, offset, height } = this.props;
let top, bottom;
if (offset < HEIGHT / 2) {
top = `0px`;
}
if (height - offset < HEIGHT / 1.5) {
bottom = `0px`;
}
if (!(top || bottom)) {
bottom = `-${Math.round(HEIGHT / 2) - 20}px`;
}
const containerStyle = { top, bottom, left: "100%" };
return (
<div
onMouseLeave={this.props.onMouseLeave}
onMouseEnter={this.props.onMouseEnter}
style={{ top: "-250px" }}
style={containerStyle}
className="flex-col shadow-6 br2 bg-white inter absolute z-1 f9 lh-solid"
>
<div style={{ height: "160px" }}>