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 api from '../../../../api';
import ImmutablePureComponent from 'react-immutable-pure-component';
import { mockContactList } from './mockContactList';
import { mockContactList } from './mocks/mockContactList';
import Contact from './Contact';
export default class ContactsList extends ImmutablePureComponent {
@ -84,10 +84,10 @@ export default class ContactsList extends ImmutablePureComponent {
return (
<div className='messaging-container'>
<div className={classListContainer}>
<div className='title column-header'>
<div className='card-title '>
<i
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
<button

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,177 +1 @@
$messagingBoxWidth: 20em;
$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;
}
}
@import "../mastodon/messaging/main";

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
=========
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
The IM is able to
@ -9,15 +14,23 @@ The IM is able to
* retrieving contacts from the DB
* 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.
* 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
## 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
## Research
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
* send a direct message
* display a page with the routing system