Add topic modal

This commit is contained in:
Ken-Håvard Lieng 2019-01-25 03:57:58 +01:00
parent aab1ad3e99
commit 24960f23b9
11 changed files with 235 additions and 172 deletions

File diff suppressed because one or more lines are too long

View File

@ -19,6 +19,15 @@ h6 {
font-family: Montserrat, sans-serif;
}
a {
text-decoration: none;
color: #0066ff;
}
a:hover {
text-decoration: underline;
}
input {
font: 16px Roboto Mono, monospace;
border: none;
@ -504,20 +513,24 @@ input::-webkit-inner-spin-button {
display: none;
}
.editable-wrap {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.editable-wrap-editable {
cursor: pointer;
}
.chat-title {
margin-left: 10px;
padding: 0 5px;
margin-left: 15px;
font: 24px Montserrat, sans-serif;
font-weight: 700;
color: #222;
white-space: nowrap;
line-height: 50px;
}
.chat-server .chat-title {
cursor: pointer;
}
input.chat-title {
background: none;
cursor: text !important;
@ -526,7 +539,7 @@ input.chat-title {
.chat-topic-wrap {
flex: 1;
position: relative;
margin: 0 15px;
margin-left: 15px;
}
.chat-topic {
@ -535,20 +548,12 @@ input.chat-title {
top: 3px;
font-size: 16px;
color: #999;
cursor: pointer;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.chat-topic a {
color: #999;
text-decoration: none;
}
.chat-topic a:hover {
text-decoration: underline;
}
.userlist-bar {
position: absolute;
top: 0;
@ -705,15 +710,6 @@ input.chat-title {
cursor: pointer;
}
.message a {
text-decoration: none;
color: #0066ff;
}
.message a:hover {
text-decoration: underline;
}
.message-input-wrap {
position: absolute;
left: 0;
@ -751,7 +747,7 @@ input.message-input-nick.invalid {
flex: 1;
width: 100%;
height: 100%;
padding: 0 15px;
padding: 0 10px;
}
.userlist {
@ -954,6 +950,27 @@ input.message-input-nick.invalid {
margin-top: 10px;
}
.modal-header {
display: flex;
}
.modal-header h2 {
flex: 1;
}
.modal-close {
color: #999;
cursor: pointer;
}
.modal-close:hover {
color: #222;
}
.modal-content {
margin-top: 15px;
}
.modal-channel {
display: flex;
flex-direction: column;
@ -980,12 +997,6 @@ input.message-input-nick.invalid {
.modal-channel-close {
padding: 15px;
background: #fff;
color: #999;
cursor: pointer;
}
.modal-channel-close:hover {
color: #222;
}
.modal-channel-result {
@ -1057,8 +1068,12 @@ input.message-input-nick.invalid {
margin-left: 0;
}
.chat-topic {
font-size: 12px;
.chat-title-bar .editable-wrap {
flex: 1;
}
.chat-topic-wrap {
display: none;
}
.userlist-bar {

View File

@ -114,7 +114,10 @@ const AddChannel = ({ search, payload: { server }, onClose, ...props }) => {
onKeyDown={handleKey}
onChange={handleSearch}
/>
<i className="icon-cancel modal-channel-close" onClick={onClose} />
<i
className="icon-cancel modal-close modal-channel-close"
onClick={onClose}
/>
</div>
<div ref={resultsEl} className="modal-channel-results">
{search.results.map(channel => (

View File

@ -0,0 +1,19 @@
import React from 'react';
import withModal from 'components/modals/withModal';
import { linkify } from 'utils';
const Topic = ({ payload: { topic, channel }, onClose }) => {
return (
<>
<div className="modal-header">
<h2>Topic in {channel}</h2>
<i className="icon-cancel modal-close" onClick={onClose} />
</div>
<p className="modal-content">{linkify(topic)}</p>
</>
);
};
export default withModal({
name: 'topic'
})(Topic);

View File

@ -1,11 +1,13 @@
import React, { memo } from 'react';
import AddChannel from 'components/modals/AddChannel';
import Confirm from 'components/modals/Confirm';
import Topic from 'components/modals/Topic';
const Modals = () => (
<>
<AddChannel />
<Confirm />
<Topic />
</>
);

View File

@ -65,6 +65,7 @@ export default class Chat extends Component {
addFetchedMessages,
fetchMessages,
inputActions,
openModal,
runCommand,
sendMessage,
toggleSearch,
@ -86,6 +87,7 @@ export default class Chat extends Component {
status={status}
tab={tab}
title={title}
openModal={openModal}
onCloseClick={this.handleCloseClick}
onTitleChange={this.handleTitleChange}
onToggleSearch={toggleSearch}

View File

@ -2,13 +2,14 @@ import React, { memo } from 'react';
import Navicon from 'containers/Navicon';
import Editable from 'components/ui/Editable';
import { isValidServerName } from 'state/servers';
import { isChannel, linkify } from 'utils';
import { isChannel } from 'utils';
const ChatTitle = ({
status,
title,
tab,
channel,
openModal,
onTitleChange,
onToggleSearch,
onToggleUserList,
@ -44,9 +45,19 @@ const ChatTitle = ({
<span className="chat-title">{title}</span>
</Editable>
<div className="chat-topic-wrap">
<span className="chat-topic">
{channel && linkify(channel.topic)}
</span>
{channel && channel.topic && (
<span
className="chat-topic"
onClick={() =>
openModal('topic', {
topic: channel.topic,
channel: channel.name
})
}
>
{channel.topic}
</span>
)}
{serverError}
</div>
<i className="icon-search" title="Search" onClick={onToggleSearch} />

View File

@ -1,4 +1,5 @@
import React, { PureComponent, createRef } from 'react';
import cn from 'classnames';
import { stringWidth } from 'utils';
export default class Editable extends PureComponent {
@ -75,7 +76,7 @@ export default class Editable extends PureComponent {
};
render() {
const { children, className, value } = this.props;
const { children, className, editable, value } = this.props;
const style = {
width: this.state.width,
@ -86,7 +87,7 @@ export default class Editable extends PureComponent {
return this.state.editing ? (
<input
ref={this.inputEl}
className={className}
className={`editable-wrap ${className}`}
type="text"
value={value}
onBlur={this.handleBlur}
@ -97,7 +98,14 @@ export default class Editable extends PureComponent {
spellCheck={false}
/>
) : (
<div onClick={this.startEditing}>{children}</div>
<div
className={cn('editable-wrap', {
'editable-wrap-editable': editable
})}
onClick={this.startEditing}
>
{children}
</div>
);
}
}

View File

@ -22,6 +22,7 @@ import {
fetchMessages,
addFetchedMessages
} from 'state/messages';
import { openModal } from 'state/modals';
import { openPrivateChat, closePrivateChat } from 'state/privateChats';
import { getSearch, searchMessages, toggleSearch } from 'state/search';
import {
@ -58,6 +59,7 @@ const mapDispatch = dispatch => ({
closePrivateChat,
disconnect,
fetchMessages,
openModal,
openPrivateChat,
part,
runCommand,

View File

@ -61,7 +61,7 @@ function init(state, server, channel) {
state[server] = {};
}
if (channel && !state[server][channel]) {
state[server][channel] = { users: [], joined: false };
state[server][channel] = { name: channel, users: [], joined: false };
}
}
@ -135,6 +135,7 @@ export default createReducer(
[actions.socket.JOIN](state, { server, channels, user }) {
const channel = channels[0];
init(state, server, channel);
state[server][channel].name = channel;
state[server][channel].joined = true;
state[server][channel].users.push(createUser(user));
},

View File

@ -80,7 +80,7 @@ func (d *Dispatch) initFileServer() {
if cfg.Dev {
renderIndexPage(indexTemplateData{
Scripts: []string{"boot.js", "main.js"},
Scripts: []string{"/boot.js", "/main.js"},
})
} else {
bootloader := decompressedAsset(findAssetName("boot*.js"))