Inital dropdown, modal and toggle

pull/710/head
Vincent 5 years ago
parent 649c8c9be5
commit 12011a30d4

@ -701,6 +701,7 @@
<script type='text/javascript' src='js/views/scroll_down_button_view.js'></script>
<script type='text/javascript' src='js/views/toast_view.js'></script>
<script type='text/javascript' src='js/views/session_toast_view.js'></script>
<script type='text/javascript' src='js/views/session_toggle_view.js'></script>
<script type='text/javascript' src='js/views/file_input_view.js'></script>
<script type='text/javascript' src='js/views/list_view.js'></script>
<script type='text/javascript' src='js/views/contact_list_view.js'></script>

@ -802,6 +802,9 @@
appView.openConversation(groupId, {});
};
window.generateID = () => Math.random().toString(36).substring(3);
window.toasts = new Map();
window.pushToast = options => {
// Setting toasts with the same ID can be used to prevent identical
@ -811,10 +814,7 @@
const params = {
title: options.title,
id:
options.id ||
Math.random()
.toString(36)
.substring(3),
options.id || window.generateID(),
description: options.description || '',
type: options.type || '',
};
@ -825,7 +825,6 @@
if (toast) {
window.toasts.get(toastID).update(params);
} else {
// Make new Toast
window.toasts.set(
toastID,

@ -51,6 +51,8 @@ const {
const { EditProfileDialog } = require('../../ts/components/EditProfileDialog');
const { UserDetailsDialog } = require('../../ts/components/UserDetailsDialog');
const { SessionToast } = require('../../ts/components/session/SessionToast');
const { SessionToggle } = require('../../ts/components/session/SessionToggle');
const { SessionModal } = require('../../ts/components/session/SessionModal');
const {
SessionRegistrationView,
} = require('../../ts/components/session/SessionRegistrationView');
@ -250,6 +252,8 @@ exports.setup = (options = {}) => {
GroupInvitation,
BulkEdit,
SessionToast,
SessionToggle,
SessionModal,
MediaGallery,
Message,
MessageBody,

@ -0,0 +1,31 @@
/* global Whisper */
// eslint-disable-next-line func-names
(function() {
'use strict';
window.Whisper = window.Whisper || {};
Whisper.SessionToastView = Whisper.View.extend({
initialize(options) {
this.props = {
active: options.active,
};
},
render() {
this.toggleView = new Whisper.ReactWrapperView({
className: 'session-toggle-wrapper',
Component: window.Signal.Components.SessionToast,
props: this.props,
});
this.$el.append(this.toggleView.el);
},
toggle() {
this.props.active = !this.props.active;
this.toggleView.update(this.props);
},
});
})();

@ -60,7 +60,7 @@ $session-opaque-dark-3: rgba(0, 0, 0, 0.5);
$session-color-white: #fff;
$session-color-dark-grey: #353535;
$session-color-black: #000;
$session-color-danger: #ff4538;
$session-color-danger: #FF453A;
$session-color-primary: $session-shade-13;
$session-color-secondary: $session-shade-16;
@ -489,3 +489,119 @@ label {
@include set-toast-theme($session-color-error);
}
}
.session-modal {
z-index: 150;
position: fixed;
top: 50%;
left: 50%;
box-sizing: border-box;
height: 529px;
width: 345px;
background-color: $session-shade-4;
border: 1px solid $session-shade-8;
.header {
display: flex;
flex-direction: row;
justify-content: space-between;
padding: $session-margin-lg;
font-family: 'Wasa';
text-align: center;
line-height: 18px;
font-size: 15px;
font-weight: 700;
.close,
.icons {
width: 70px;
}
.close > div {
float: left;
}
.icons > div {
float: right;
}
}
}
.session-toggle {
width: 51px;
height: 31px;
border: 1.5px solid #e5e5ea;
border-radius: 16px;
position: relative;
cursor: pointer;
background-color: rgba(0, 0, 0, 0);
.knob {
position: absolute;
top: 0.5px;
left: 0.5px;
height: 27px;
width: 27px;
border-radius: 28px;
background-color: $session-color-white;
box-shadow: 0 0 3px 1px rgba(0, 0, 0, 0.05), 0 3px 1px 0 rgba(0, 0, 0, 0.05),
0 2px 2px 0 rgba(0, 0, 0, 0.1), 0 3px 3px 0 rgba(0, 0, 0, 0.05);
transition: transform 0.25s ease, background-color 0.25s ease;
}
&.active {
background-color: $session-color-green;
border-color: $session-color-green;
.knob {
transform: translateX(20px);
}
}
}
.session-dropdown{
display: inline-block;
ul {
display: block;
list-style: none;
padding: 0px;
margin: 0px;
li {
cursor: pointer;
height: 25px;
padding-right: 7px;
background-color: #1B1B1B;
color: $session-color-white;
font-family: 'Wasa';
font-size: 12px;
line-height: $session-icon-size-sm;
font-weight: 700;
display: flex;
align-items: center;
.session-icon {
margin-left: 6px;
}
.item-content {
margin-left: 6px;
}
&.active, &:hover{
background-color: $session-shade-7;
}
&.danger {
color: $session-color-danger;
}
}
}
}

@ -1,6 +1,9 @@
import React from 'react';
import { Avatar } from './Avatar';
import { SessionDropdown, SessionDropDownType } from './session/SessionDropdown';
import { SessionIconType } from './session/icon';
declare global {
interface Window {
displayNameRegex: any;
@ -33,8 +36,40 @@ export class UserDetailsDialog extends React.Component<Props> {
const cancelText = i18n('cancel');
const startConversation = i18n('startConversation');
const items = [
{
id: "myid1",
content: "Copy Chat ID",
icon: SessionIconType.Eye,
type: SessionDropDownType.Default,
active: false
},
{
id: "myid1",
content: "Invite Friends",
icon: null,
type: SessionDropDownType.Default,
active: false
},
{
id: "myid1",
content: "Clear Chat History",
icon: SessionIconType.Check,
type: SessionDropDownType.Default,
active: true
},
{
id: "myid1",
content: "Leave Group",
icon: SessionIconType.Check,
type: SessionDropDownType.Danger,
active: false
},
];
return (
<div className="content">
<SessionDropdown items={items} />
<div className="avatar-center">
<div className="avatar-center-inner">{this.renderAvatar()}</div>
</div>

@ -0,0 +1,45 @@
import React from 'react';
import classNames from 'classnames';
import { SessionDropdownItem, SessionDropDownItemType } from './SessionDropdownItem';
import { SessionIconType } from './icon/';
interface Props {
items: Array<{
id: string,
content: string,
icon: SessionIconType | null,
type: SessionDropDownItemType,
active: boolean,
}>,
}
export class SessionDropdown extends React.PureComponent<Props> {
public static readonly defaultProps = SessionDropdownItem.defaultProps;
constructor(props: any) {
super(props);
}
public render() {
const { items } = this.props;
return (
<div className={classNames('session-dropdown')}>
<ul>
{items.map((item: any) => <SessionDropdownItem
id={item.id}
content={item.content}
icon={item.icon}
type={item.type}
active={item.active}
/>
)}
</ul>
</div>
);
}
}

@ -0,0 +1,66 @@
import React from 'react';
import classNames from 'classnames';
import { SessionIcon, SessionIconSize, SessionIconType } from './icon/';
import { generateID } from './tools/ComponentTools';
export enum SessionDropDownItemType {
Default = 'default',
Danger = 'danger',
}
interface Props {
id: string,
content: string,
type: SessionDropDownItemType,
icon: SessionIconType | null,
active: boolean,
onClick: any,
}
export class SessionDropdownItem extends React.PureComponent<Props> {
public static defaultProps = {
id: generateID(),
type: SessionDropDownItemType.Default,
onClick: () => null,
};
constructor(props: any) {
super(props);
this.clickHandler = this.clickHandler.bind(this);
}
public render() {
const { id, content, type, icon, active } = this.props;
return (
<li
id={id}
className={classNames(active ? 'active' : '', type || '')}
onClick={this.clickHandler}
>
{ icon ? <SessionIcon
iconType = { icon }
iconSize = { SessionIconSize.Small }
/>
: ''
}
<div className="item-content">
{content}
</div>
</li>
);
}
private clickHandler(e: any){
if (this.props.onClick) {
e.stopPropagation();
this.props.onClick();
}
}
}

@ -0,0 +1,43 @@
import React from 'react';
import classNames from 'classnames';
import { SessionIconButton, SessionIconSize, SessionIconType } from './icon/';
interface Props {
title: string;
body: any;
}
export class SessionModal extends React.PureComponent<Props> {
constructor(props: any) {
super(props);
}
public render() {
const { title } = this.props;
return (
<div className={classNames('session-modal')}>
<div className="header">
<div className="close">
<SessionIconButton
iconType={SessionIconType.Exit}
iconSize={SessionIconSize.Small}
/>
</div>
<div className="title">{title}</div>
<div className="icons">
<SessionIconButton
iconType={SessionIconType.Search}
iconSize={SessionIconSize.Medium}
/>
<SessionIconButton
iconType={SessionIconType.AddUser}
iconSize={SessionIconSize.Medium}
/>
</div>
</div>
</div>
);
}
}

@ -0,0 +1,48 @@
import React from 'react';
import classNames from 'classnames';
interface Props {
active: boolean;
}
interface State {
active: boolean;
}
export class SessionToggle extends React.PureComponent<Props, State> {
public static readonly extendedDefaults = {
onClick: () => null,
};
constructor(props: any) {
super(props);
this.clickHandler = this.clickHandler.bind(this);
const { active } = this.props;
this.state = {
active: active,
};
}
public render() {
return (
<div
className={classNames(
'session-toggle',
this.state.active ? 'active' : ''
)}
role="button"
onClick={this.clickHandler}
>
<div className="knob" />
</div>
);
}
private clickHandler() {
this.setState({
active: !this.state.active,
});
}
}

@ -0,0 +1,7 @@
// This is a collection of tools which can be ued to simplify the esign and rendering process of your components.
export function generateID(){
// Generates a unique ID for your component
return Math.random().toString(36).substring(3);
}
Loading…
Cancel
Save