split of css

Signed-off-by: Baptiste Lemoine <contact@cipherbliss.com>
This commit is contained in:
Baptiste Lemoine 2020-01-08 10:12:38 +01:00
parent 80751c0ca1
commit 9bef612c35
16 changed files with 325 additions and 221 deletions

View File

@ -3,7 +3,7 @@ import PropTypes from 'prop-types';
import accounts, { me } from '../../../../initial_state'; import accounts, { me } from '../../../../initial_state';
import api from '../../../../api'; import api from '../../../../api';
import ImmutablePureComponent from 'react-immutable-pure-component'; import ImmutablePureComponent from 'react-immutable-pure-component';
import { mockContactList } from './mockContactList'; import { mockContactList } from './mocks/mockContactList';
import Contact from './Contact'; import Contact from './Contact';
export default class ContactsList extends ImmutablePureComponent { export default class ContactsList extends ImmutablePureComponent {
@ -84,10 +84,10 @@ export default class ContactsList extends ImmutablePureComponent {
return ( return (
<div className='messaging-container'> <div className='messaging-container'>
<div className={classListContainer}> <div className={classListContainer}>
<div className='title column-header'> <div className='card-title '>
<i <i
role='img' role='img'
className='fa fa-envelope column-header__icon fa-fw' className='fa fa-comment column-header__icon fa-fw'
/> />
{this.state.following_count} contacts {this.state.following_count} contacts
<button <button

View File

@ -1,5 +1,4 @@
import React from 'react'; import React from 'react';
import Contact from './Contact';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import ConversationStream from './conversation-stream'; import ConversationStream from './conversation-stream';
@ -23,38 +22,57 @@ export default class ConversationItem extends React.PureComponent {
constructor(props) { constructor(props) {
super(props); super(props);
console.log('props', props);
this.state = { this.state = {
composeMessage: '', composeMessage: '',
displayed : this.props.displayed, displayed : this.props.displayed,
newMessages : this.props.newMessages,
isFocused : false,
}; };
} }
submitCompose() { submitCompose = (e) => {
console.log('submit'); e.preventDefault();
}
handleChange(e) { console.log('submit');
// e.preventDefault(); };
toggleVisibility = () => {
this.setState({ 'displayed': !this.state.displayed });
};
toggleFocused = () => {
this.setState({ 'isFocused': !this.state.isFocused });
};
handleChange = (e) => {
e.preventDefault();
console.log('e', e); console.log('e', e);
} };
render() { render() {
const hasNewClass = this.props.newMessages ? 'has-new-message' : 'nothing-new'; const hasNewClass = this.state.newMessages ? 'has-new-message' : 'nothing-new';
const isVisible = this.props.displayed ? 'displayed' : 'hidden'; const isVisible = this.state.displayed ? 'displayed' : 'hidden';
const isFocused = this.state.isFocused ? 'isFocused' : 'not-focused';
const list = ( const list = (
<li className={'conversation-item ' + hasNewClass + ' ' + isVisible}> <li className={'conversation-item ' + hasNewClass + ' ' + isVisible + ' ' + isFocused}>
<div className='top-title'> <div className='top-title'>
<i <i
role='img' role='img'
className='fa fa-envelope column-header__icon fa-fw' className='fa fa-comment-o column-header__icon fa-fw'
/> />
<Contact account={this.props.recipient} /> <span className='username'>
{this.props.newMessages && ( {this.props.recipient.username}
</span >
{/*<Contact account={this.props.recipient} />*/}
{this.props.newMessages > 0 && (
<span className='new-message-counter'> <span className='new-message-counter'>
({this.props.newMessages}) ({this.props.newMessages})
</span > </span >
)} )}
<button className='btn-small'> <button
className='btn btn-small'
onClick={this.toggleVisibility}
>
<i <i
role='img' role='img'
className='fa fa-caret-down column-header__icon fa-fw' className='fa fa-caret-down column-header__icon fa-fw'
@ -74,7 +92,8 @@ export default class ConversationItem extends React.PureComponent {
rows='3' rows='3'
className='messager-textarea' className='messager-textarea'
placeholder='allez dis nous tout' placeholder='allez dis nous tout'
value={this.state.composeMessage} onFocusCapture={this.toggleFocused}
onBlurCapture={this.toggleFocused}
onChange={this.handleChange} onChange={this.handleChange}
/> />
@ -87,7 +106,11 @@ export default class ConversationItem extends React.PureComponent {
</div > </div >
</li > </li >
); );
return list; return (
<ul >
{list}
</ul >
);
} }

View File

@ -2,6 +2,7 @@ import React from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
export default class ConversationStream extends React.PureComponent { export default class ConversationStream extends React.PureComponent {
static propTypes = { static propTypes = {
messages: PropTypes.array, messages: PropTypes.array,
}; };
@ -17,7 +18,7 @@ export default class ConversationStream extends React.PureComponent {
messagesLists = this.props.messages.map(message => { messagesLists = this.props.messages.map(message => {
return ( return (
<li className={'message ' + message.text}> <li className={'message ' + message.who}>
<p >{message.text}</p > <p >{message.text}</p >
<div className='arrow-down' /> <div className='arrow-down' />
</li > </li >
@ -27,9 +28,9 @@ export default class ConversationStream extends React.PureComponent {
} }
return ( return (
<div className='conversation-stream'> <div className='conversation-stream'>
<ul className='messages'> <div className='messages'>
{messagesLists} {messagesLists}
</ul > </div >
</div > </div >
); );
} }

View File

@ -2,7 +2,7 @@ import React from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import ConversationItem from './conversation-item'; import ConversationItem from './conversation-item';
import { mockRecipient, mockRecipient2 } from './mockConversation'; import { mockRecipient, mockRecipient2 } from './mocks/mockConversation';
export default class ConversationStack extends React.Component { export default class ConversationStack extends React.Component {
@ -19,21 +19,27 @@ export default class ConversationStack extends React.Component {
} }
render() { render() {
let list = this.props.conversations.map(conversations => let list = this.props.conversations.map(recipient => {
(
<li console.log('recipient', recipient);
className='conversation-item-wrapper' recipient = recipient[0];
key={conversations.id} return (
> <li
<ConversationItem className='conversation-item-wrapper'
recipient={mockRecipient} key={'wrapper' + recipient.id}
messages={mockRecipient.messages} >
key={conversations.id} <ConversationItem
onClick={this.openConversationWith} recipient={recipient}
/> messages={recipient.messages}
</li > key={'ConversationItem_' + recipient.id}
), onClick={this.openConversationWith}
); />
</li >
);
},
)
;
return ( return (
<ul className='stack conversations_list'> <ul className='stack conversations_list'>
{list} {list}

View File

@ -2,6 +2,9 @@ import React from 'react';
import ContactsList from './contacts-list'; import ContactsList from './contacts-list';
import ConversationStack from './conversationStack'; import ConversationStack from './conversationStack';
/**
* main component for IM, gathers contact list and list of conversations
*/
export default class InstantMessaging extends React.PureComponent { export default class InstantMessaging extends React.PureComponent {
// static propTypes = { // static propTypes = {
@ -28,7 +31,7 @@ export default class InstantMessaging extends React.PureComponent {
render() { render() {
return ( return (
<div > <div className='main-instant-messaging'>
<ContactsList /> <ContactsList />
<ConversationStack /> <ConversationStack />

View File

@ -25,7 +25,7 @@ export const mockRecipient = [
export const mockRecipient2 = [ export const mockRecipient2 = [
{ {
id : 4, id : 4,
username : 'the Bo botte', username : 'the Bo Botte',
newMessages: 0, newMessages: 0,
messages : mockMessages2, messages : mockMessages2,
}, },

View File

@ -1,177 +1 @@
$messagingBoxWidth: 20em; @import "../mastodon/messaging/main";
$messagingBoxHeight: 100%;
$conversationBoxHeight: 20em;
.fixed-box {
border: solid 1px white;
padding: 1em;
position: fixed;
bottom: 0;
}
.airmail-border {
border: 0.25em solid transparent;
border-image: 4 repeating-linear-gradient(-45deg, red 0, red 1em, white 0, white 2em,
#58a 0, #58a 3em, white 0, white 4em);
}
.status-direct,
.item-list .conversation {
@extend .airmail-border;
}
.messaging-box {
@extend .fixed-box;
right: 1em;
width: $messagingBoxWidth;
background: $ui-base-color;
height: 4em;
color: white;
z-index: 10;
&.active {
height: $messagingBoxHeight;
}
.messager-textarea {
width: 100%;
}
.title {
color: white;
}
}
.contact-list-container {
overflow-x: auto;
}
.contact-list {
display: block;
padding: 1em;
min-height: 5em;
list-style-type: none;
color: white;
.contact {
margin-bottom: 0.5rem;
}
}
.toggle-list {
float: right;
margin-left: 1em;
background: $ui-primary-color;
border: 0;
padding: .5em;
&.active {
background: $highlight-text-color;
}
}
.conversation {
.conversation__content {
padding-right: 0;
}
.conversation_reply,
.icon-button {
&:hover {
color: $ui-highlight-color;
background: mix($ui-base-color, $ui-secondary-color);
}
}
.conversation_reply,
.icon-button,
.status__action-bar-dropdown {
display: inline-block;
float: right;
width: 18em;
height: 3.2em;
text-align: center;
}
}
.conversations_list {
@extend .fixed-box;
right: $messagingBoxWidth + 2em;
bottom: 0;
width: 100%;
padding: 0.5em;
overflow-x: auto;
}
.conversation-item {
float: right;
width: 20em;
margin-left: 2em;
padding: 1em;
border-radius: 15px;
background: $classic-base-color;
&.has-new-message {
background: $ui-highlight-color;
color: $classic-primary-color;
}
}
.conversation_created-at {
margin-right: 1em;
}
.conversation_stream {
padding-top: 1em;
height: $conversationBoxHeight;
overflow: auto;
background: $ui-secondary-color;
.message {
-webkit-border-radius: 0.5rem;
-moz-border-radius: 0.5rem;
border-radius: 0.5rem;
margin-bottom: 0.5em;
padding: 0.5em 1em;
width: 80%;
}
.mine {
text-align: right;
background: $classic-primary-color;
float: right;
.arrow-down {
border-top-color: $classic-primary-color;
left: 1em;
}
}
.theirs {
text-align: left;
background: $ui-highlight-color;
float: left;
.arrow-down {
border-top-color: $ui-highlight-color;
right: 1em;
}
}
.arrow-down {
width: 0;
height: 0;
border-left: 10px solid transparent;
border-right: 20px solid transparent;
border-top: 20px solid $classic-primary-color;
position: relative;
bottom: -1em;
}
}

View File

@ -0,0 +1,3 @@
$messagingBoxWidth: 20em;
$messagingBoxHeight: 100%;
$conversationBoxHeight: 20em;

View File

@ -0,0 +1,16 @@
.contact-list-container {
overflow-x: auto;
}
.contact-list {
display: block;
padding: 1em;
min-height: 5em;
list-style-type: none;
color: white;
.contact {
margin-bottom: 0.5rem;
}
}

View File

@ -0,0 +1,16 @@
.fixed-box {
border: solid 1px white;
padding: 1em;
position: fixed;
bottom: 0;
}
.airmail-border {
border: 0.25em solid transparent;
border-image: 4 repeating-linear-gradient(-45deg, red 0, red 1em, white 0, white 2em,
#58a 0, #58a 3em, white 0, white 4em);
border-right-width: 0;
border-bottom-width: 0;
border-top-width: 0;
}

View File

@ -0,0 +1,6 @@
@import "config";
@import "helpers";
@import "messaging";
@import "contacts";
@import "messaging-conversation";
@import "messaging-stream";

View File

@ -0,0 +1,84 @@
.conversation {
.conversation__content {
padding-right: 0;
}
.conversation_reply,
.icon-button {
&:hover {
color: $ui-highlight-color;
background: mix($ui-base-color, $ui-secondary-color);
}
}
.conversation_reply,
.icon-button,
.status__action-bar-dropdown {
display: inline-block;
float: right;
width: 18em;
height: 3.2em;
text-align: center;
}
}
.conversations_list {
@extend .fixed-box;
right: $messagingBoxWidth + 2em;
bottom: 0;
width: 100%;
padding: 0.5em;
overflow-x: auto;
border: 0;
}
.conversation-item {
float: right;
width: 20em;
margin-left: 2em;
padding: 1em;
border-radius: 15px;
border: 3px solid $classic-primary-color;
-moz-border-radius-bottomleft: 0;
-moz-border-radius-bottomright: 0;
background: $classic-base-color;
&.has-new-message {
background: $ui-highlight-color;
color: $classic-primary-color;
}
&.is-focused {
border-color: $ui-base-color;
}
.username {
font-weight: bold;
}
.conversation-stream,
.conversation_input {
height: 100%;
display: block;
}
&.hidden {
.conversation-stream,
.conversation_input {
display: none;
}
}
.btn {
background: $classic-base-color;
color: $ui-base-color;
float: right;
padding: 0 1em;
margin-left: 1em;
border: 0;
}
}

View File

@ -0,0 +1,55 @@
.conversation-stream {
padding-top: 1em;
height: 5em;
overflow: auto;
width: 100%;
.message {
clear: both;
}
.messages >
.message {
-webkit-border-radius: 0.5rem;
-moz-border-radius: 0.5rem;
border-radius: 0.5rem;
margin-bottom: 0.5em;
padding: 0.5em 1em;
display: block;
}
.ours {
text-align: right;
background: $light-text-color;
float: right;
.arrow-down {
border-top-color: $light-text-color;
left: 100%;
}
}
.theirs {
text-align: left;
background: $ui-highlight-color;
float: left;
.arrow-down {
border-top-color: $ui-highlight-color;
right: 1em;
}
}
.arrow-down {
width: 0;
height: 0;
border-left: 10px solid transparent;
border-right: 20px solid transparent;
border-top: 20px solid $classic-primary-color;
position: relative;
bottom: -1em;
}
}

View File

@ -0,0 +1,54 @@
.status-direct,
.item-list .conversation {
@extend .airmail-border;
}
.main-instant-messaging {
.column-header__icon {
color: white;
}
}
.messaging-box {
@extend .fixed-box;
right: 1em;
width: $messagingBoxWidth;
background: $ui-base-color;
height: 4em;
color: white;
z-index: 10;
&.active {
height: $messagingBoxHeight;
}
.messager-textarea {
width: 100%;
}
.title {
color: white;
}
}
.toggle-list {
float: right;
margin-left: 1em;
background: $ui-primary-color;
border: 0;
padding: .5em;
width: 2em;
&.active {
background: $highlight-text-color;
}
}
.conversation_created-at {
margin-right: 1em;
}

View File

@ -1,7 +1,12 @@
# Instant messaging documentation - by Tykayn # Instant messaging documentation - by Tykayn
========= =========
here is detailed the progress and the state of wondering. here is detailed the progress and the state of wondering.
By now, the IM (Instant messaging) aims to be a simple frontend over the direct message structure. By now, **the IM (Instant messaging) aims to be a simple frontend over the direct message structure**.
Come discuss here:
[@tykayn](https://mastodon.cipherbliss.com/@tykayn)
or here
[contact@cipherbliss.com](mailto:contact@cipherbliss.com)
## what is done ## what is done
The IM is able to The IM is able to
@ -9,15 +14,23 @@ The IM is able to
* retrieving contacts from the DB * retrieving contacts from the DB
* talk one to one with an account * talk one to one with an account
* the input is a simplified compose form, it has predefined settings to have only one recipient. It uses the same mecanism than the compose form to send a private / direct message to somebody. other mentions of persons are not yet recognised. * the input is a simplified compose form, it has predefined settings to have only one recipient. It uses the same mecanism than the compose form to send a private / direct message to somebody. other mentions of persons are not yet recognised.
* components used by the IM are listed under the folder `app/javascript/mastodon/features/ui/components/messaging`
* the addition of bulma CSS enables a reliable set of css classes to have a cool layout and tooling.
* style dedicated to the IM is added in the mastodon style folder
`app/javascript/styles/mastodon/messaging/main.scss`
# TODO # TODO
## Work in progress ## Work in progress
* retrieve contacts, just like in http://localhost:3000/web/accounts/1/following
* open a new conversation when we click on an account in the contact list * open a new conversation when we click on an account in the contact list
## Research ## Research
find how it is already done to: find how it is already done to:
* retrieve contacts
* retrieve a conversation
* retrieve a conversation like http://localhost:3000/web/statuses/103356660630283894
* subscribe to the new messages of a conversation * subscribe to the new messages of a conversation
* send a direct message * send a direct message
* display a page with the routing system * display a page with the routing system