Animate in-conversation panels on show/hide
This commit is contained in:
parent
c952d628c1
commit
464361b2eb
6 changed files with 112 additions and 37 deletions
|
@ -16,6 +16,7 @@
|
||||||
initialize(options) {
|
initialize(options) {
|
||||||
this.ourNumber = textsecure.storage.user.getNumber();
|
this.ourNumber = textsecure.storage.user.getNumber();
|
||||||
this.listenBack = options.listenBack;
|
this.listenBack = options.listenBack;
|
||||||
|
this.loading = false;
|
||||||
|
|
||||||
this.listenTo(this.model, 'change', this.render);
|
this.listenTo(this.model, 'change', this.render);
|
||||||
},
|
},
|
||||||
|
@ -39,19 +40,28 @@
|
||||||
profileName: this.model.getProfileName(),
|
profileName: this.model.getProfileName(),
|
||||||
verified: this.model.isVerified(),
|
verified: this.model.isVerified(),
|
||||||
onClick: this.showIdentity.bind(this),
|
onClick: this.showIdentity.bind(this),
|
||||||
|
disabled: this.loading,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
this.$el.append(this.contactView.el);
|
this.$el.append(this.contactView.el);
|
||||||
return this;
|
return this;
|
||||||
},
|
},
|
||||||
showIdentity() {
|
showIdentity() {
|
||||||
if (this.model.id === this.ourNumber) {
|
if (this.model.id === this.ourNumber || this.loading) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.loading = true;
|
||||||
|
this.render();
|
||||||
|
|
||||||
const view = new Whisper.KeyVerificationPanelView({
|
const view = new Whisper.KeyVerificationPanelView({
|
||||||
model: this.model,
|
model: this.model,
|
||||||
|
onLoad: () => {
|
||||||
|
this.loading = false;
|
||||||
|
this.listenBack(view);
|
||||||
|
this.render();
|
||||||
|
},
|
||||||
});
|
});
|
||||||
this.listenBack(view);
|
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
|
|
|
@ -954,7 +954,7 @@
|
||||||
};
|
};
|
||||||
|
|
||||||
const view = new Whisper.ReactWrapperView({
|
const view = new Whisper.ReactWrapperView({
|
||||||
className: 'panel-wrapper',
|
className: 'panel',
|
||||||
Component: Signal.Components.MediaGallery,
|
Component: Signal.Components.MediaGallery,
|
||||||
props: await getProps(),
|
props: await getProps(),
|
||||||
onClose: () => {
|
onClose: () => {
|
||||||
|
@ -1537,7 +1537,7 @@
|
||||||
|
|
||||||
const props = message.getPropsForMessageDetail();
|
const props = message.getPropsForMessageDetail();
|
||||||
const view = new Whisper.ReactWrapperView({
|
const view = new Whisper.ReactWrapperView({
|
||||||
className: 'message-detail-wrapper',
|
className: 'panel message-detail-wrapper',
|
||||||
Component: Signal.Components.MessageDetail,
|
Component: Signal.Components.MessageDetail,
|
||||||
props,
|
props,
|
||||||
onClose,
|
onClose,
|
||||||
|
@ -1597,11 +1597,11 @@
|
||||||
|
|
||||||
listenBack(view) {
|
listenBack(view) {
|
||||||
this.panels = this.panels || [];
|
this.panels = this.panels || [];
|
||||||
if (this.panels.length > 0) {
|
|
||||||
this.panels[0].$el.hide();
|
|
||||||
}
|
|
||||||
this.panels.unshift(view);
|
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() {
|
resetPanel() {
|
||||||
if (!this.panels || !this.panels.length) {
|
if (!this.panels || !this.panels.length) {
|
||||||
|
@ -1611,14 +1611,15 @@
|
||||||
const view = this.panels.shift();
|
const view = this.panels.shift();
|
||||||
|
|
||||||
if (this.panels.length > 0) {
|
if (this.panels.length > 0) {
|
||||||
this.panels[0].$el.show();
|
this.panels[0].$el.fadeIn(250);
|
||||||
}
|
|
||||||
view.remove();
|
|
||||||
|
|
||||||
if (this.panels.length === 0) {
|
|
||||||
// Make sure poppers are positioned properly
|
|
||||||
window.dispatchEvent(new Event('resize'));
|
|
||||||
}
|
}
|
||||||
|
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() {
|
endSession() {
|
||||||
|
|
|
@ -22,6 +22,9 @@
|
||||||
|
|
||||||
this.loadKeys().then(() => {
|
this.loadKeys().then(() => {
|
||||||
this.listenTo(this.model, 'change', this.render);
|
this.listenTo(this.model, 'change', this.render);
|
||||||
|
if (options.onLoad) {
|
||||||
|
options.onLoad();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
loadKeys() {
|
loadKeys() {
|
||||||
|
|
|
@ -1,15 +1,56 @@
|
||||||
|
@import './mixins';
|
||||||
|
|
||||||
|
@keyframes panel--in {
|
||||||
|
from {
|
||||||
|
transform: translateX(500px);
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
to {
|
||||||
|
transform: translateX(0);
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.conversation {
|
.conversation {
|
||||||
background-color: $color-white;
|
background-color: $color-white;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
.panel,
|
.panel {
|
||||||
.panel-wrapper {
|
|
||||||
height: calc(100% - #{$header-height});
|
height: calc(100% - #{$header-height});
|
||||||
overflow-y: scroll;
|
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 {
|
.panel {
|
||||||
|
&:not(.main) {
|
||||||
|
animation: panel--in 250ms ease-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--static {
|
||||||
|
animation: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--remove {
|
||||||
|
transform: translateX(500px);
|
||||||
|
opacity: 0;
|
||||||
|
transition: all 250ms ease-out;
|
||||||
|
}
|
||||||
|
|
||||||
.container {
|
.container {
|
||||||
padding-top: 20px;
|
padding-top: 20px;
|
||||||
max-width: 750px;
|
max-width: 750px;
|
||||||
|
@ -18,8 +59,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.main.panel,
|
.main.panel {
|
||||||
.panel-wrapper {
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
overflow: initial;
|
overflow: initial;
|
||||||
|
|
|
@ -1512,7 +1512,17 @@
|
||||||
height: 35px;
|
height: 35px;
|
||||||
min-width: 35px;
|
min-width: 35px;
|
||||||
vertical-align: text-bottom;
|
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 {
|
.module-conversation-header__title-container {
|
||||||
|
@ -1595,7 +1605,17 @@
|
||||||
height: 20px;
|
height: 20px;
|
||||||
width: 20px;
|
width: 20px;
|
||||||
margin-left: 4px;
|
margin-left: 4px;
|
||||||
cursor: pointer;
|
border: none;
|
||||||
|
opacity: 0;
|
||||||
|
transition: opacity 250ms ease-out;
|
||||||
|
|
||||||
|
&:disabled {
|
||||||
|
cursor: default;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--show {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Module: Message Detail
|
// Module: Message Detail
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import classnames from 'classnames';
|
||||||
|
|
||||||
import { Emojify } from './Emojify';
|
import { Emojify } from './Emojify';
|
||||||
import { Avatar } from '../Avatar';
|
import { Avatar } from '../Avatar';
|
||||||
|
@ -49,7 +50,7 @@ interface Props {
|
||||||
}
|
}
|
||||||
|
|
||||||
export class ConversationHeader extends React.Component<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 menuTriggerRef: React.RefObject<any>;
|
||||||
|
|
||||||
public constructor(props: Props) {
|
public constructor(props: Props) {
|
||||||
|
@ -59,7 +60,7 @@ export class ConversationHeader extends React.Component<Props> {
|
||||||
this.showMenuBound = this.showMenu.bind(this);
|
this.showMenuBound = this.showMenu.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public showMenu(event: React.MouseEvent<HTMLDivElement>) {
|
public showMenu(event: React.MouseEvent<HTMLButtonElement>) {
|
||||||
if (this.menuTriggerRef.current) {
|
if (this.menuTriggerRef.current) {
|
||||||
this.menuTriggerRef.current.handleContextClick(event);
|
this.menuTriggerRef.current.handleContextClick(event);
|
||||||
}
|
}
|
||||||
|
@ -68,15 +69,14 @@ export class ConversationHeader extends React.Component<Props> {
|
||||||
public renderBackButton() {
|
public renderBackButton() {
|
||||||
const { onGoBack, showBackButton } = this.props;
|
const { onGoBack, showBackButton } = this.props;
|
||||||
|
|
||||||
if (!showBackButton) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<button
|
||||||
onClick={onGoBack}
|
onClick={onGoBack}
|
||||||
role="button"
|
className={classnames(
|
||||||
className="module-conversation-header__back-icon"
|
'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) {
|
public renderGear(triggerId: string) {
|
||||||
const { showBackButton } = this.props;
|
const { showBackButton } = this.props;
|
||||||
|
|
||||||
if (showBackButton) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ContextMenuTrigger id={triggerId} ref={this.menuTriggerRef}>
|
<ContextMenuTrigger id={triggerId} ref={this.menuTriggerRef}>
|
||||||
<div
|
<button
|
||||||
role="button"
|
|
||||||
onClick={this.showMenuBound}
|
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>
|
</ContextMenuTrigger>
|
||||||
);
|
);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue