add the left pane sections on main page

pull/712/head
Audric Ackermann 5 years ago
parent ea0ab2c7cc
commit c883d20bd7

@ -56,9 +56,6 @@
<div class='gutter'>
<div class='network-status-container'></div>
<div class='left-pane-placeholder'></div>
<div class='loki'>
<img src='images/loki/loki_icon_text.png' />
</div>
</div>
<div class='conversation-stack'>
<div class='conversation placeholder'>

@ -3233,8 +3233,7 @@
display: inline-flex;
flex-direction: column;
width: 300px;
width: 380px;
height: 100%;
}

@ -297,12 +297,23 @@ $session_message-container-border-radius: 5px;
}
}
.session-icon-button {
opacity: 0.4;
cursor: pointer;
display: inline-block;
transition: opacity $session-transition-duration;
&:hover {
opacity: 1;
position: relative;
svg {
transition: opacity $session-transition-duration;
opacity: 0.4;
&:hover {
opacity: 1;
}
}
&.no-opacify {
svg {
opacity: 1;
}
}
&.small.padded {
@ -316,6 +327,23 @@ $session_message-container-border-radius: 5px;
&.large.padded {
@include set-icon-margin($session-icon-size-lg);
}
.notification-count {
position: absolute;
font-size: 12px;
font-family: $session-font-family;
top: -10px;
right: -10px;
width: 20px;
height: 20px;
padding: 3px;
border-radius: 50%;
font-weight: 700;
background: red;
color: $session-color-white;
text-align: center;
opacity: 1;
}
}
.session-icon {

@ -0,0 +1,37 @@
.dark-theme {
.module-conversation-list-item {
background-color: $session-shade-4;
&:hover {
background-color: $session-shade-11;
}
}
}
.module-left-pane {
border-right: none !important;
width: 300px;
&-session {
display: flex;
}
&__sections-container {
height: -webkit-fill-available;
width: 80px;
display: inline-flex;
flex-direction: column;
background: $session-shade-2;
.module-avatar,
.session-icon-button {
margin: 30px auto 30px auto;
&:last-child {
margin: auto auto 30px auto;
}
}
}
}
.gutter {
width: 380px;
}

@ -27,6 +27,7 @@
@import 'session';
@import 'session_signin';
@import 'session_theme_dark';
@import 'session_theme_dark_left_pane';
// Installer
@import 'options';

@ -12,6 +12,8 @@ import {
} from './SearchResults';
import { LocalizerType } from '../types/Util';
import { LeftPaneSections } from './LeftPaneSections';
export interface Props {
conversations?: Array<ConversationListItemPropsType>;
friends?: Array<ConversationListItemPropsType>;
@ -45,7 +47,7 @@ type RowRendererParamsType = {
style: Object;
};
export class LeftPane extends React.Component<Props, any> {
export class LeftPane extends React.Component<Props> {
public state = {
currentTab: 'conversations',
};
@ -268,11 +270,14 @@ export class LeftPane extends React.Component<Props, any> {
const { renderMainHeader, showArchived } = this.props;
return (
<div className="module-left-pane">
<div className="module-left-pane__header">
{showArchived ? this.renderArchivedHeader() : renderMainHeader()}
<div className="module-left-pane-session">
<LeftPaneSections />
<div className="module-left-pane">
<div className="module-left-pane__header">
{showArchived ? this.renderArchivedHeader() : renderMainHeader()}
</div>
{this.renderList()}
</div>
{this.renderList()}
</div>
);
}

@ -0,0 +1,188 @@
import React from 'react';
import {
SessionIconButton,
SessionIconSize,
SessionIconType,
} from './session/icon';
import { Avatar } from './Avatar';
enum SectionType {
Profile,
Message,
People,
Globe,
Settings,
Moon,
}
interface State {
selectedSection: SectionType;
avatarPath: string;
}
const Section = ({
isSelected,
onSelect,
type,
avatarPath,
notificationCount,
}: {
isSelected: boolean;
onSelect?: (event: SectionType) => void;
type: SectionType;
avatarPath?: string;
avatarColor?: string;
notificationCount?: number;
}) => {
const handleClick = onSelect
? () => {
onSelect(type);
}
: undefined;
if (type === SectionType.Profile) {
if (!isSelected) {
return (
<Avatar
avatarPath={avatarPath}
conversationType="direct"
i18n={window.i18n}
// tslint:disable-next-line: no-backbone-get-set-outside-model
phoneNumber={window.storage.get('primaryDevicePubKey')}
size={28}
onAvatarClick={handleClick}
/>
);
} else {
return (
<Avatar
avatarPath={avatarPath}
conversationType="direct"
i18n={window.i18n}
// tslint:disable-next-line: no-backbone-get-set-outside-model
phoneNumber={window.storage.get('primaryDevicePubKey')}
size={28}
onAvatarClick={handleClick}
borderColor={'#fff'}
/>
);
}
}
let iconType: SessionIconType;
switch (type) {
case SectionType.Message:
iconType = SessionIconType.Reply;
break;
case SectionType.People:
iconType = SessionIconType.Users;
break;
case SectionType.Globe:
iconType = SessionIconType.Globe;
break;
case SectionType.Settings:
iconType = SessionIconType.Gear;
break;
case SectionType.Moon:
iconType = SessionIconType.Moon;
break;
default:
iconType = SessionIconType.Moon;
}
if (!isSelected) {
return (
<SessionIconButton
iconSize={SessionIconSize.Medium}
iconType={iconType}
notificationCount={notificationCount}
onClick={handleClick}
/>
);
} else {
return (
<SessionIconButton
iconSize={SessionIconSize.Medium}
iconType={iconType}
notificationCount={notificationCount}
onClick={handleClick}
isSelected={isSelected}
/>
);
}
};
export class LeftPaneSections extends React.Component<{}, State> {
constructor() {
super({});
this.state = {
avatarPath: '',
selectedSection: SectionType.Message,
};
}
public componentDidMount() {
// tslint:disable-next-line: no-backbone-get-set-outside-model
const ourNumber = window.storage.get('primaryDevicePubKey');
window.ConversationController.getOrCreateAndWait(ourNumber, 'private').then(
(conversation: any) => {
this.setState({
avatarPath: conversation.getAvatarPath(),
});
}
);
}
public render(): JSX.Element {
const isProfileSelected =
this.state.selectedSection === SectionType.Profile;
const isMessageSelected =
this.state.selectedSection === SectionType.Message;
const isPeopleSelected = this.state.selectedSection === SectionType.People;
const isGlobeSelected = this.state.selectedSection === SectionType.Globe;
const isSettingsSelected =
this.state.selectedSection === SectionType.Settings;
const isMoonSelected = this.state.selectedSection === SectionType.Moon;
return (
<div className="module-left-pane__sections-container">
<Section
type={SectionType.Profile}
avatarPath={this.state.avatarPath}
isSelected={isProfileSelected}
onSelect={this.handleSectionSelect}
/>
<Section
type={SectionType.Message}
isSelected={isMessageSelected}
onSelect={this.handleSectionSelect}
notificationCount={0}
/>
<Section
type={SectionType.People}
isSelected={isPeopleSelected}
onSelect={this.handleSectionSelect}
/>
<Section
type={SectionType.Globe}
isSelected={isGlobeSelected}
onSelect={this.handleSectionSelect}
/>
<Section
type={SectionType.Settings}
isSelected={isSettingsSelected}
onSelect={this.handleSectionSelect}
/>
<Section
type={SectionType.Moon}
isSelected={isMoonSelected}
onSelect={this.handleSectionSelect}
/>
</div>
);
}
private readonly handleSectionSelect = (section: SectionType): void => {
this.setState({ selectedSection: section });
};
}

@ -387,7 +387,7 @@ export class RegistrationTabs extends React.Component<{}, State> {
if (signUpMode === SignUpMode.EnterDetails) {
return (
<div className={classNames('session-registration__entry-fields')}>
{this.renderNamePasswordAndVerifyPasswordFields()};
{this.renderNamePasswordAndVerifyPasswordFields()}
</div>
);
}

@ -5,11 +5,15 @@ import { Props, SessionIcon } from '../icon';
interface SProps extends Props {
onClick: any;
notificationCount: number | undefined;
isSelected: boolean;
}
export class SessionIconButton extends React.PureComponent<SProps> {
public static readonly extendedDefaults = {
onClick: () => null,
notificationCount: undefined,
isSelected: false,
};
public static readonly defaultProps = {
...SessionIcon.defaultProps,
@ -28,14 +32,24 @@ export class SessionIconButton extends React.PureComponent<SProps> {
iconColor,
iconRotation,
iconPadded,
isSelected,
} = this.props;
let { notificationCount } = this.props;
if (notificationCount === 0) {
notificationCount = undefined;
} else if (notificationCount !== undefined && notificationCount > 9) {
notificationCount = 9;
}
return (
<div
className={classNames(
'session-icon-button',
iconSize,
iconPadded ? 'padded' : ''
iconPadded ? 'padded' : '',
isSelected ? 'no-opacify' : ''
)}
role="button"
onClick={e => {
@ -48,6 +62,9 @@ export class SessionIconButton extends React.PureComponent<SProps> {
iconColor={iconColor}
iconRotation={iconRotation}
/>
{notificationCount !== undefined && (
<span className="notification-count">{notificationCount}</span>
)}
</div>
);
}

1
ts/global.d.ts vendored

@ -16,6 +16,7 @@ interface Window {
friends: any;
generateID: any;
pushToast: any;
storage: any;
}
interface Promise<T> {

Loading…
Cancel
Save