Animate in-conversation panels on show/hide

This commit is contained in:
Ken Powers 2019-07-25 12:24:03 -04:00 committed by Scott Nonnenberg
parent c952d628c1
commit 464361b2eb
6 changed files with 112 additions and 37 deletions

View File

@ -16,6 +16,7 @@
initialize(options) {
this.ourNumber = textsecure.storage.user.getNumber();
this.listenBack = options.listenBack;
this.loading = false;
this.listenTo(this.model, 'change', this.render);
},
@ -39,19 +40,28 @@
profileName: this.model.getProfileName(),
verified: this.model.isVerified(),
onClick: this.showIdentity.bind(this),
disabled: this.loading,
},
});
this.$el.append(this.contactView.el);
return this;
},
showIdentity() {
if (this.model.id === this.ourNumber) {
if (this.model.id === this.ourNumber || this.loading) {
return;
}
this.loading = true;
this.render();
const view = new Whisper.KeyVerificationPanelView({
model: this.model,
onLoad: () => {
this.loading = false;
this.listenBack(view);
this.render();
},
});
this.listenBack(view);
},
}),
});

View File

@ -954,7 +954,7 @@
};
const view = new Whisper.ReactWrapperView({
className: 'panel-wrapper',
className: 'panel',
Component: Signal.Components.MediaGallery,
props: await getProps(),
onClose: () => {
@ -1537,7 +1537,7 @@
const props = message.getPropsForMessageDetail();
const view = new Whisper.ReactWrapperView({
className: 'message-detail-wrapper',
className: 'panel message-detail-wrapper',
Component: Signal.Components.MessageDetail,
props,
onClose,
@ -1597,11 +1597,11 @@
listenBack(view) {
this.panels = this.panels || [];
if (this.panels.length > 0) {
this.panels[0].$el.hide();
}
this.panels.unshift(view);
view.$el.insertBefore(this.$('.panel').first());
view.$el.insertAfter(this.$('.panel').last());
view.$el.one('animationend', () => {
view.$el.addClass('panel--static');
});
},
resetPanel() {
if (!this.panels || !this.panels.length) {
@ -1611,14 +1611,15 @@
const view = this.panels.shift();
if (this.panels.length > 0) {
this.panels[0].$el.show();
}
view.remove();
if (this.panels.length === 0) {
// Make sure poppers are positioned properly
window.dispatchEvent(new Event('resize'));
this.panels[0].$el.fadeIn(250);
}
view.$el.addClass('panel--remove').one('transitionend', () => {
view.remove();
if (this.panels.length === 0) {
// Make sure poppers are positioned properly
window.dispatchEvent(new Event('resize'));
}
});
},
endSession() {

View File

@ -22,6 +22,9 @@
this.loadKeys().then(() => {
this.listenTo(this.model, 'change', this.render);
if (options.onLoad) {
options.onLoad();
}
});
},
loadKeys() {

View File

@ -1,15 +1,56 @@
@import './mixins';
@keyframes panel--in {
from {
transform: translateX(500px);
opacity: 0;
}
to {
transform: translateX(0);
opacity: 1;
}
}
.conversation {
background-color: $color-white;
height: 100%;
position: relative;
.panel,
.panel-wrapper {
.panel {
height: calc(100% - #{$header-height});
overflow-y: scroll;
z-index: 1;
position: absolute;
left: 0;
top: 48px;
width: 100%;
height: calc(100% - 48px);
@include light-theme() {
background-color: $color-white;
}
@include dark-theme() {
background-color: $color-black;
}
}
.panel {
&:not(.main) {
animation: panel--in 250ms ease-out;
}
&--static {
animation: none;
}
&--remove {
transform: translateX(500px);
opacity: 0;
transition: all 250ms ease-out;
}
.container {
padding-top: 20px;
max-width: 750px;
@ -18,8 +59,7 @@
}
}
.main.panel,
.panel-wrapper {
.main.panel {
display: flex;
flex-direction: column;
overflow: initial;

View File

@ -1512,7 +1512,17 @@
height: 35px;
min-width: 35px;
vertical-align: text-bottom;
cursor: pointer;
border: none;
opacity: 0;
transition: opacity 250ms ease-out;
&:disabled {
cursor: default;
}
&--show {
opacity: 1;
}
}
.module-conversation-header__title-container {
@ -1595,7 +1605,17 @@
height: 20px;
width: 20px;
margin-left: 4px;
cursor: pointer;
border: none;
opacity: 0;
transition: opacity 250ms ease-out;
&:disabled {
cursor: default;
}
&--show {
opacity: 1;
}
}
// Module: Message Detail

View File

@ -1,4 +1,5 @@
import React from 'react';
import classnames from 'classnames';
import { Emojify } from './Emojify';
import { Avatar } from '../Avatar';
@ -49,7 +50,7 @@ interface Props {
}
export class ConversationHeader extends React.Component<Props> {
public showMenuBound: (event: React.MouseEvent<HTMLDivElement>) => void;
public showMenuBound: (event: React.MouseEvent<HTMLButtonElement>) => void;
public menuTriggerRef: React.RefObject<any>;
public constructor(props: Props) {
@ -59,7 +60,7 @@ export class ConversationHeader extends React.Component<Props> {
this.showMenuBound = this.showMenu.bind(this);
}
public showMenu(event: React.MouseEvent<HTMLDivElement>) {
public showMenu(event: React.MouseEvent<HTMLButtonElement>) {
if (this.menuTriggerRef.current) {
this.menuTriggerRef.current.handleContextClick(event);
}
@ -68,15 +69,14 @@ export class ConversationHeader extends React.Component<Props> {
public renderBackButton() {
const { onGoBack, showBackButton } = this.props;
if (!showBackButton) {
return null;
}
return (
<div
<button
onClick={onGoBack}
role="button"
className="module-conversation-header__back-icon"
className={classnames(
'module-conversation-header__back-icon',
showBackButton ? 'module-conversation-header__back-icon--show' : null
)}
disabled={!showBackButton}
/>
);
}
@ -171,16 +171,17 @@ export class ConversationHeader extends React.Component<Props> {
public renderGear(triggerId: string) {
const { showBackButton } = this.props;
if (showBackButton) {
return null;
}
return (
<ContextMenuTrigger id={triggerId} ref={this.menuTriggerRef}>
<div
role="button"
<button
onClick={this.showMenuBound}
className="module-conversation-header__gear-icon"
className={classnames(
'module-conversation-header__gear-icon',
showBackButton
? null
: 'module-conversation-header__gear-icon--show'
)}
disabled={showBackButton}
/>
</ContextMenuTrigger>
);