Public Sans and Mono ONLY

pull/1026/head
Vincent 5 years ago
parent dd67a6b7d6
commit 83bbeeb526

@ -1,22 +1,22 @@
@font-face {
font-family: 'SpaceMono';
font-family: $session-font-mono;
src: url('../fonts/SpaceMono-Regular.ttf') format('truetype');
}
@font-face {
font-family: 'SpaceMono';
font-family: $session-font-mono;
src: url('../fonts/SpaceMono-Bold.ttf') format('truetype');
font-weight: bold;
}
@font-face {
font-family: 'SpaceMono';
font-family: $session-font-mono;
src: url('../fonts/SpaceMono-Italic.ttf') format('truetype');
font-style: italic;
}
@font-face {
font-family: 'SpaceMono';
font-family: $session-font-mono;
src: url('../fonts/SpaceMono-BoldItalic.ttf') format('truetype');
font-weight: bold;
font-style: italic;
@ -87,8 +87,11 @@
}
// Session Colors
$session-font-accent: 'Public Sans';
$session-font-default: 'Karla';
// Fonts changed to 'Public Sans' and Space Mono' as per req. Chad.
$session-font-default: 'Public Sans';
$session-font-mono: 'SpaceMono';
// $session-font-default: 'Public Sans';
// $session-font-default: 'Karla';
$session-color-green: #00f782;
$session-color-green-alt-1: #00f480;
@ -551,7 +554,7 @@ $session-element-border-green: 4px solid $session-color-green;
&-text {
@include session-color-subtle($session-color-white);
font-family: $session-font-accent;
font-family: $session-font-default;
font-weight: 300;
font-size: $session-font-xs;
line-height: $session-font-xs;
@ -802,7 +805,7 @@ label {
&__body {
padding: 0px $session-margin-lg $session-margin-lg $session-margin-lg;
font-family: $session-font-accent;
font-family: $session-font-default;
line-height: $session-font-md;
font-size: $session-font-sm;
@ -1081,7 +1084,7 @@ label {
word-break: break-all;
font-size: $session-font-md;
padding: 0px $session-margin-lg;
font-family: $session-font-accent;
font-family: $session-font-default;
font-weight: 100;
color: rgba($session-color-white, 0.8);
font-size: $session-font-md;
@ -1283,7 +1286,7 @@ label {
}
&__description {
font-family: $session-font-accent;
font-family: $session-font-default;
font-size: $session-font-sm;
font-weight: 100;
max-width: 700px;
@ -1358,7 +1361,7 @@ label {
text-align: center;
font-size: $session-font-xl;
letter-spacing: 5px;
font-family: $session-font-accent;
font-family: $session-font-default;
}
}
}
@ -1393,7 +1396,7 @@ label {
.discussion-container {
.module-message {
font-family: $session-font-accent;
font-family: $session-font-default;
border-radius: 5px;
&__text--incoming {
@ -1606,7 +1609,7 @@ input {
/* Memberlist */
.member-list-container .member {
&-item {
font-family: $session-font-accent;
font-family: $session-font-default;
padding: $session-margin-sm $session-margin-md;
background-color: $session-shade-5;
@ -1673,7 +1676,7 @@ input {
}
&-container {
font-family: $session-font-accent;
font-family: $session-font-default;
color: $session-color-white;
display: inline-flex;
flex-direction: column;
@ -1723,7 +1726,7 @@ input {
text-align: center;
font-size: 24px;
letter-spacing: 5px;
font-family: $session-font-accent;
font-family: $session-font-default;
}
}
}
@ -1757,7 +1760,7 @@ input {
height: 400px;
text-align: center;
font-family: $session-font-accent;
font-family: $session-font-default;
}
&__title h1 {
@ -1783,7 +1786,7 @@ input {
}
&--subtitle {
font-family: $session-font-accent;
font-family: $session-font-default;
font-weight: 300;
line-height: $session-font-md;
opacity: 0.8;
@ -1823,7 +1826,7 @@ input {
}
&__no-contacts {
font-family: 'SpaceMono';
font-family: $session-font-mono;
text-align: center;
padding: 20px;
}
@ -1844,7 +1847,7 @@ input {
.session-member-item {
cursor: pointer;
font-family: $session-font-accent;
font-family: $session-font-default;
padding: 0px $session-margin-sm;
height: 50px;
display: flex;

@ -302,7 +302,7 @@ $session-compose-margin: 20px;
font-size: $session-font-sm;
line-height: $session-font-h3;
margin: 0px 20px;
font-family: $session-font-accent;
font-family: $session-font-default;
}
.session-id-editable {
@ -375,7 +375,7 @@ $session-compose-margin: 20px;
border: none;
flex-grow: 1;
font-size: $session-font-sm;
font-family: $session-font-accent;
font-family: $session-font-default;
&:focus {
outline: none !important;
@ -658,7 +658,7 @@ $session-compose-margin: 20px;
border-radius: 50px;
color: $session-color-light-grey;
border: 1px solid $session-color-dark-grey;
font-family: $session-font-accent;
font-family: $session-font-default;
font-size: $session-font-sm;
}
}

@ -244,7 +244,7 @@
overflow-wrap: break-word;
padding: 0px 5px 20px 5px;
display: inline-block;
font-family: 'SpaceMono';
font-family: $session-font-mono;
user-select: all;
}
}

@ -0,0 +1,409 @@
import React from 'react';
import { debounce } from 'lodash';
import { Attachment } from '../../../types/Attachment';
import * as MIME from '../../../types/MIME';
import TextareaAutosize from 'react-autosize-textarea';
import { SessionIconButton, SessionIconSize, SessionIconType } from '../icon';
import { SessionEmojiPanel } from './SessionEmojiPanel';
import { SessionRecording } from './SessionRecording';
import { SignalService } from '../../../../ts/protobuf';
interface Props {
placeholder?: string;
sendMessage: any;
onMessageSending: any;
onMessageSuccess: any;
onMessageFailure: any;
onLoadVoiceNoteView: any;
onExitVoiceNoteView: any;
}
interface State {
message: string;
showRecordingView: boolean;
mediaSetting: boolean | null;
showEmojiPanel: boolean;
attachments: Array<Attachment>;
voiceRecording?: Blob;
}
export class SessionCompositionBox extends React.Component<Props, State> {
private readonly textarea: React.RefObject<HTMLTextAreaElement>;
private readonly fileInput: React.RefObject<HTMLInputElement>;
private emojiPanel: any;
constructor(props: any) {
super(props);
this.state = {
message: '',
attachments: [],
voiceRecording: undefined,
showRecordingView: false,
mediaSetting: null,
showEmojiPanel: false,
};
this.textarea = React.createRef();
this.fileInput = React.createRef();
// Emojis
this.emojiPanel = null;
this.toggleEmojiPanel = debounce(this.toggleEmojiPanel.bind(this), 100);
this.hideEmojiPanel = this.hideEmojiPanel.bind(this);
this.onEmojiClick = this.onEmojiClick.bind(this);
this.handleClick = this.handleClick.bind(this);
this.renderRecordingView = this.renderRecordingView.bind(this);
this.renderCompositionView = this.renderCompositionView.bind(this);
// Recording view functions
this.sendVoiceMessage = this.sendVoiceMessage.bind(this);
this.onLoadVoiceNoteView = this.onLoadVoiceNoteView.bind(this);
this.onExitVoiceNoteView = this.onExitVoiceNoteView.bind(this);
// Attachments
this.onChoseAttachment = this.onChoseAttachment.bind(this);
this.onChooseAttachment = this.onChooseAttachment.bind(this);
this.onKeyDown = this.onKeyDown.bind(this);
this.onChange = this.onChange.bind(this);
}
public componentWillReceiveProps(){
console.log(`[vince][info] Here are my composition props: `, this.props);
}
public async componentWillMount(){
const mediaSetting = await window.getSettingValue('media-permissions');
this.setState({mediaSetting});
}
public render() {
const { showRecordingView } = this.state;
return (
<div className="composition-container">
{ showRecordingView ? (
<>{this.renderRecordingView()}</>
) : (
<>{this.renderCompositionView()}</>
)}
</div>
);
}
private handleClick(e: any) {
if (this.emojiPanel && this.emojiPanel.contains(e.target)) {
return;
}
this.toggleEmojiPanel();
};
private showEmojiPanel() {
document.addEventListener('mousedown', this.handleClick, false);
this.setState({
showEmojiPanel: true,
});
}
private hideEmojiPanel() {
document.removeEventListener('mousedown', this.handleClick, false);
this.setState({
showEmojiPanel: false,
});
}
private toggleEmojiPanel() {
if (this.state.showEmojiPanel) {
this.hideEmojiPanel();
} else {
this.showEmojiPanel();
}
}
private renderRecordingView() {
return (
<SessionRecording
sendVoiceMessage={this.sendVoiceMessage}
onLoadVoiceNoteView={this.onLoadVoiceNoteView}
onExitVoiceNoteView={this.onExitVoiceNoteView}
/>
);
}
private renderCompositionView() {
const { placeholder } = this.props;
const { showEmojiPanel, message } = this.state;
return (
<>
<SessionIconButton
iconType={SessionIconType.CirclePlus}
iconSize={SessionIconSize.Large}
onClick={this.onChooseAttachment}
/>
<input
className="hidden"
multiple={true}
ref={this.fileInput}
type="file"
onChange={this.onChoseAttachment}
/>
<SessionIconButton
iconType={SessionIconType.Microphone}
iconSize={SessionIconSize.Huge}
onClick={this.onLoadVoiceNoteView}
/>
<div className="send-message-input">
<TextareaAutosize
rows={1}
maxRows={3}
ref={this.textarea}
placeholder={placeholder}
maxLength={window.CONSTANTS.MAX_MESSAGE_BODY_LENGTH}
onKeyDown={this.onKeyDown}
value={message}
onChange={this.onChange}
/>
</div>
<SessionIconButton
iconType={SessionIconType.Emoji}
iconSize={SessionIconSize.Large}
onClick={this.toggleEmojiPanel}
/>
<div className="send-message-button">
<SessionIconButton
iconType={SessionIconType.Send}
iconSize={SessionIconSize.Large}
iconColor={'#FFFFFF'}
iconRotation={90}
onClick={this.onSendMessage}
/>
</div>
<div
ref={ref => (this.emojiPanel = ref)}
onKeyDown={this.onKeyDown}
role="button"
>
<SessionEmojiPanel onEmojiClicked={this.onEmojiClick} show={showEmojiPanel}/>
</div>
</>
);
}
private onChooseAttachment() {
const fileInput = this.fileInput.current;
if(fileInput) fileInput.click();
}
private onChoseAttachment() {
// Build attachments list
const attachmentsFileList = this.fileInput.current?.files;
if (!attachmentsFileList) return;
const attachments: Array<Attachment> = [];
Array.from(attachmentsFileList).forEach(async (file: File) => {
const fileBlob = new Blob([file]);
const fileBuffer = await new Response(fileBlob).arrayBuffer();
const attachment = {
fileName: file.name,
flags: undefined,
// FIXME VINCE: Set appropriate type
contentType: MIME.AUDIO_WEBM,
size: file.size,
data: fileBuffer,
};
// Push if size is nonzero
if (attachment.data.byteLength) {
attachments.push(attachment);
}
});
this.setState({attachments});
}
private onKeyDown(event: any) {
if (event.key === 'Enter' && !event.shiftKey) {
// If shift, newline. Else send message.
event.preventDefault();
this.onSendMessage();
} else if (event.key === 'Escape' && this.state.showEmojiPanel) {
this.hideEmojiPanel();
}
}
private onSendMessage() {
const messageInput = this.textarea.current;
if (!messageInput) {
return;
}
// Verify message length
const messagePlaintext = messageInput.value;
const msgLen = messagePlaintext.length;
if (msgLen === 0 || msgLen > window.CONSTANTS.MAX_MESSAGE_BODY_LENGTH) {
return;
}
// handle Attachments
const {attachments} = this.state;
console.log(`[vince][msg] Message:`, messagePlaintext);
console.log(`[vince][msg] fileAttachments:`, attachments);
// Handle emojis
// Send message
this.props.onMessageSending();
this.props.sendMessage(
messagePlaintext,
attachments,
undefined,
undefined,
null,
{}
).then(() => {
// Message sending sucess
this.props.onMessageSuccess();
// Empty attachments
// Empty composition box
this.setState({
message: '',
attachments: [],
});
}).catch(() => {
// Message sending failed
this.props.onMessageFailure();
});
}
private async sendVoiceMessage(audioBlob: Blob) {
if (!this.state.showRecordingView) {
return;
}
const fileBuffer = await new Response(audioBlob).arrayBuffer();
const audioAttachment: Attachment = {
data: fileBuffer,
flags: SignalService.AttachmentPointer.Flags.VOICE_MESSAGE,
contentType: MIME.AUDIO_MP3,
};
const messageSuccess = this.props.sendMessage(
'',
[audioAttachment],
undefined,
undefined,
null,
{},
);
if (messageSuccess) {
// success!
}
console.log(`[compositionbox] Sending voice message:`, audioBlob);
this.onExitVoiceNoteView();
}
private onLoadVoiceNoteView() {
// Do stuff for component, then run callback to SessionConversation
const {mediaSetting} = this.state;
if (mediaSetting) {
this.setState({
showRecordingView: true,
showEmojiPanel: false,
});
this.props.onLoadVoiceNoteView();
return;
}
window.pushToast({
id: 'audioPermissionNeeded',
title: window.i18n('audioPermissionNeededTitle'),
description: window.i18n('audioPermissionNeededDescription'),
type: 'info',
});
}
private onExitVoiceNoteView() {
// Do stuff for component, then run callback to SessionConversation
this.setState({ showRecordingView: false });
this.props.onExitVoiceNoteView();
}
private onDrop() {
// On drop attachments!
// this.textarea.current?.ondrop;
// Look into react-dropzone
}
private onChange(event: any) {
this.setState({message: event.target.value});
}
private onEmojiClick({native}: any) {
const messageBox = this.textarea.current;
if (!messageBox) {
return;
}
const { message } = this.state;
const currentSelectionStart = Number(messageBox.selectionStart);
const currentSelectionEnd = Number(messageBox.selectionEnd);
const before = message.slice(0, currentSelectionStart);
const end = message.slice(currentSelectionEnd);
const newMessage = `${before}${native}${end}`;
this.setState({ message: newMessage }, () => {
// update our selection because updating text programmatically
// will put the selection at the end of the textarea
const selectionStart = currentSelectionStart + Number(native.length);
messageBox.selectionStart = selectionStart;
messageBox.selectionEnd = selectionStart;
// Sometimes, we have to repeat the set of the selection position with a timeout to be effective
setTimeout(() => {
messageBox.selectionStart = selectionStart;
messageBox.selectionEnd = selectionStart;
}, 20);
});
}
}
Loading…
Cancel
Save