mirror of
https://github.com/oxen-io/session-desktop.git
synced 2023-12-14 02:12:57 +01:00
Fixed examples in Quote.md, rough Android visuals
This commit is contained in:
parent
6653123671
commit
21bf02c94d
15 changed files with 408 additions and 59 deletions
|
@ -428,6 +428,18 @@
|
|||
"selectAContact": {
|
||||
"message": "Select a contact or group to start chatting."
|
||||
},
|
||||
"audio": {
|
||||
"message": "Audio",
|
||||
"description": "Shown in a quotation of a message containing an audio attachment if no text was originally provided with that attachment"
|
||||
},
|
||||
"video": {
|
||||
"message": "Video",
|
||||
"description": "Shown in a quotation of a message containing a video if no text was originally provided with that video"
|
||||
},
|
||||
"photo": {
|
||||
"message": "Photo",
|
||||
"description": "Shown in a quotation of a message containing a photo if no text was originally provided with that image"
|
||||
},
|
||||
"ok": {
|
||||
"message": "OK"
|
||||
},
|
||||
|
|
|
@ -278,6 +278,7 @@
|
|||
{{ /profileName }}
|
||||
</div>
|
||||
<div class='inner-bubble {{ innerBubbleClasses }}'>
|
||||
<div class='quote-wrapper'></div>
|
||||
<div class='attachments'></div>
|
||||
<p class='content' dir='auto'>
|
||||
{{ #message }}<div class='body'>{{ message }}</div>{{ /message }}
|
||||
|
|
1
images/play.svg
Normal file
1
images/play.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="24" height="24" viewBox="0 0 24 24"><path d="M8,5.14V19.14L19,12.14L8,5.14Z" /></svg>
|
After Width: | Height: | Size: 325 B |
|
@ -1,2 +1,10 @@
|
|||
exports.isJPEG = mimeType =>
|
||||
mimeType === 'image/jpeg';
|
||||
|
||||
exports.isVideo = mimeType =>
|
||||
mimeType.startsWith('video/') && mimeType !== 'video/wmv';
|
||||
|
||||
exports.isImage = mimeType =>
|
||||
mimeType.startsWith('image/') && mimeType !== 'image/tiff';
|
||||
|
||||
exports.isAudio = mimeType => mimeType.startsWith('audio/');
|
||||
|
|
|
@ -136,7 +136,8 @@
|
|||
return this.model.contentType.startsWith('audio/');
|
||||
},
|
||||
isVideo() {
|
||||
return this.model.contentType.startsWith('video/');
|
||||
const type = this.model.contentType;
|
||||
return type.startsWith('video/') && type !== 'image/wmv';
|
||||
},
|
||||
isImage() {
|
||||
const type = this.model.contentType;
|
||||
|
|
|
@ -235,7 +235,6 @@
|
|||
// Failsafe: if in the background, animation events don't fire
|
||||
setTimeout(this.remove.bind(this), 1000);
|
||||
},
|
||||
/* jshint ignore:start */
|
||||
onUnload() {
|
||||
if (this.avatarView) {
|
||||
this.avatarView.remove();
|
||||
|
@ -252,6 +251,9 @@
|
|||
if (this.timeStampView) {
|
||||
this.timeStampView.remove();
|
||||
}
|
||||
if (this.replyView) {
|
||||
this.replyView.remove();
|
||||
}
|
||||
|
||||
// NOTE: We have to do this in the background (`then` instead of `await`)
|
||||
// as our tests rely on `onUnload` synchronously removing the view from
|
||||
|
@ -265,7 +267,6 @@
|
|||
|
||||
this.remove();
|
||||
},
|
||||
/* jshint ignore:end */
|
||||
onDestroy() {
|
||||
if (this.$el.hasClass('expired')) {
|
||||
return;
|
||||
|
@ -359,6 +360,53 @@
|
|||
this.timerView.setElement(this.$('.timer'));
|
||||
this.timerView.update();
|
||||
},
|
||||
renderReply() {
|
||||
const VOICE_MESSAGE_FLAG =
|
||||
textsecure.protobuf.AttachmentPointer.Flags.VOICE_MESSAGE;
|
||||
function addVoiceMessageFlag(attachment) {
|
||||
return Object.assign({}, attachment, {
|
||||
// eslint-disable-next-line no-bitwise
|
||||
isVoiceMessage: attachment.flags & VOICE_MESSAGE_FLAG,
|
||||
});
|
||||
}
|
||||
function getObjectUrl(attachment) {
|
||||
if (!attachment || attachment.objectUrl) {
|
||||
return attachment;
|
||||
}
|
||||
|
||||
const blob = new Blob([attachment.data], {
|
||||
type: attachment.contentType,
|
||||
});
|
||||
return Object.assign({}, attachment, {
|
||||
objectUrl: URL.createObjectURL(blob),
|
||||
});
|
||||
}
|
||||
function processAttachment(attachment) {
|
||||
return getObjectUrl(addVoiceMessageFlag(attachment));
|
||||
}
|
||||
|
||||
const quote = this.model.get('quote');
|
||||
if (!quote) {
|
||||
return;
|
||||
}
|
||||
|
||||
const props = {
|
||||
authorName: 'someone',
|
||||
authorColor: 'indigo',
|
||||
text: quote.text,
|
||||
attachments: quote.attachments && quote.attachments.map(processAttachment),
|
||||
};
|
||||
|
||||
if (!this.replyView) {
|
||||
this.replyView = new Whisper.ReactWrapperView({
|
||||
el: this.$('.quote-wrapper'),
|
||||
Component: window.Signal.Components.Quote,
|
||||
props,
|
||||
});
|
||||
} else {
|
||||
this.replyView.update(props);
|
||||
}
|
||||
},
|
||||
isImageWithoutCaption() {
|
||||
const attachments = this.model.get('attachments');
|
||||
const body = this.model.get('body');
|
||||
|
@ -406,6 +454,7 @@
|
|||
this.renderRead();
|
||||
this.renderErrors();
|
||||
this.renderExpiring();
|
||||
this.renderReply();
|
||||
|
||||
|
||||
// NOTE: We have to do this in the background (`then` instead of `await`)
|
||||
|
|
|
@ -94,6 +94,7 @@
|
|||
},
|
||||
"devDependencies": {
|
||||
"@types/chai": "^4.1.2",
|
||||
"@types/classnames": "^2.2.3",
|
||||
"@types/lodash": "^4.14.106",
|
||||
"@types/mocha": "^5.0.0",
|
||||
"@types/qs": "^6.5.1",
|
||||
|
|
|
@ -450,6 +450,75 @@ span.status {
|
|||
max-width: calc(100% - 45px - #{$error-icon-size}); // avatar size + padding + error-icon size
|
||||
}
|
||||
|
||||
.quote {
|
||||
@include message-replies-colors;
|
||||
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: stretch;
|
||||
|
||||
border-radius: 2px;
|
||||
background-color: #eee;
|
||||
position: relative;
|
||||
|
||||
margin-top: $android-bubble-quote-padding - $android-bubble-padding-vertical;
|
||||
margin-right: $android-bubble-quote-padding - $android-bubble-padding-horizontal;
|
||||
margin-left: $android-bubble-quote-padding - $android-bubble-padding-horizontal;
|
||||
margin-bottom: 0.5em;
|
||||
|
||||
// Accent color border:
|
||||
border-left-width: 3;
|
||||
border-left-style: solid;
|
||||
|
||||
.primary {
|
||||
flex-grow: 1;
|
||||
padding-left: 10px;
|
||||
padding-right: 10px;
|
||||
padding-top: 6px;
|
||||
padding-bottom: 6px;
|
||||
|
||||
.author {
|
||||
font-weight: bold;
|
||||
margin-bottom: 0.3em;
|
||||
}
|
||||
|
||||
.text {
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
|
||||
.type-label {
|
||||
font-style: italic;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.filename-label {
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
.icon-container {
|
||||
flex: initial;
|
||||
min-width: 48px;
|
||||
@include aspect-ratio(1, 1);
|
||||
|
||||
.inner {
|
||||
border: 1px red solid;
|
||||
max-height: 48px;
|
||||
max-width: 48px;
|
||||
|
||||
&.file {
|
||||
@include color-svg('../images/file.svg', $grey_d);
|
||||
}
|
||||
&.microphone {
|
||||
@include color-svg('../images/microphone.svg', $grey_d);
|
||||
}
|
||||
&.play {
|
||||
@include color-svg('../images/play.svg', $grey_d);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.body {
|
||||
margin-top: 0.5em;
|
||||
white-space: pre-wrap;
|
||||
|
|
|
@ -1,3 +1,20 @@
|
|||
@mixin aspect-ratio($width, $height) {
|
||||
position: relative;
|
||||
&:before {
|
||||
display: block;
|
||||
content: "";
|
||||
width: 100%;
|
||||
padding-top: ($height / $width) * 100%;
|
||||
}
|
||||
> .inner {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@mixin color-svg($svg, $color) {
|
||||
-webkit-mask: url($svg) no-repeat center;
|
||||
-webkit-mask-size: 100%;
|
||||
|
@ -53,6 +70,47 @@
|
|||
&.grey { background-color: #666666 ; }
|
||||
&.default { background-color: $blue ; }
|
||||
}
|
||||
|
||||
// TODO: Deduplicate these! Can SASS functions generate property names?
|
||||
@mixin message-replies-colors {
|
||||
&.red { border-left-color: $material_red ; }
|
||||
&.pink { border-left-color: $material_pink ; }
|
||||
&.purple { border-left-color: $material_purple ; }
|
||||
&.deep_purple { border-left-color: $material_deep_purple ; }
|
||||
&.indigo { border-left-color: $material_indigo ; }
|
||||
&.blue { border-left-color: $material_blue ; }
|
||||
&.light_blue { border-left-color: $material_light_blue ; }
|
||||
&.cyan { border-left-color: $material_cyan ; }
|
||||
&.teal { border-left-color: $material_teal ; }
|
||||
&.green { border-left-color: $material_green ; }
|
||||
&.light_green { border-left-color: $material_light_green ; }
|
||||
&.orange { border-left-color: $material_orange ; }
|
||||
&.deep_orange { border-left-color: $material_deep_orange ; }
|
||||
&.amber { border-left-color: $material_amber ; }
|
||||
&.blue_grey { border-left-color: $material_blue_grey ; }
|
||||
&.grey { border-left-color: #999999 ; }
|
||||
&.default { border-left-color: $blue ; }
|
||||
}
|
||||
@mixin dark-message-replies-colors {
|
||||
&.red { border-left-color: $dark_material_red ; }
|
||||
&.pink { border-left-color: $dark_material_pink ; }
|
||||
&.purple { border-left-color: $dark_material_purple ; }
|
||||
&.deep_purple { border-left-color: $dark_material_deep_purple ; }
|
||||
&.indigo { border-left-color: $dark_material_indigo ; }
|
||||
&.blue { border-left-color: $dark_material_blue ; }
|
||||
&.light_blue { border-left-color: $dark_material_light_blue ; }
|
||||
&.cyan { border-left-color: $dark_material_cyan ; }
|
||||
&.teal { border-left-color: $dark_material_teal ; }
|
||||
&.green { border-left-color: $dark_material_green ; }
|
||||
&.light_green { border-left-color: $dark_material_light_green ; }
|
||||
&.orange { border-left-color: $dark_material_orange ; }
|
||||
&.deep_orange { border-left-color: $dark_material_deep_orange ; }
|
||||
&.amber { border-left-color: $dark_material_amber ; }
|
||||
&.blue_grey { border-left-color: $dark_material_blue_grey ; }
|
||||
&.grey { border-left-color: #666666 ; }
|
||||
&.default { border-left-color: $blue ; }
|
||||
}
|
||||
|
||||
@mixin invert-text-color {
|
||||
color: white;
|
||||
|
||||
|
|
|
@ -82,3 +82,8 @@ $dark_material_orange: #F57C00;
|
|||
$dark_material_deep_orange: #E64A19;
|
||||
$dark_material_amber: #FFA000;
|
||||
$dark_material_blue_grey: #455A64;
|
||||
|
||||
// Android
|
||||
$android-bubble-padding-horizontal: 12px;
|
||||
$android-bubble-padding-vertical: 9px;
|
||||
$android-bubble-quote-padding: 4px;
|
||||
|
|
|
@ -213,6 +213,7 @@
|
|||
{{ /profileName }}
|
||||
</div>
|
||||
<div class='inner-bubble {{ innerBubbleClasses }}'>
|
||||
<div class='quote-wrapper'></div>
|
||||
<div class='attachments'></div>
|
||||
<p class='content' dir='auto'>
|
||||
{{ #message }}<div class='body'>{{ message }}</div>{{ /message }}
|
||||
|
|
|
@ -33,6 +33,7 @@ window.Whisper.View.Templates = {
|
|||
{{ /profileName }}
|
||||
</div>
|
||||
<div class='inner-bubble {{ innerBubbleClasses }}'>
|
||||
<div class='quote-wrapper'></div>
|
||||
<div class='attachments'></div>
|
||||
<p class='content' dir='auto'>
|
||||
{{ #message }}<div class='body'>{{ message }}</div>{{ /message }}
|
||||
|
|
|
@ -45,14 +45,16 @@ const outgoing = new Whisper.Message({
|
|||
text: 'I am pretty confused about Pi.',
|
||||
author: '+12025550100',
|
||||
id: Date.now() - 1000,
|
||||
attachments: {
|
||||
contentType: 'image/gif',
|
||||
fileName: 'pi.gif',
|
||||
thumbnail: {
|
||||
attachments: [
|
||||
{
|
||||
contentType: 'image/gif',
|
||||
data: util.gif,
|
||||
}
|
||||
}
|
||||
fileName: 'pi.gif',
|
||||
thumbnail: {
|
||||
contentType: 'image/gif',
|
||||
data: util.gif,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
const incoming = new Whisper.Message(Object.assign({}, outgoing.attributes, {
|
||||
|
@ -85,14 +87,16 @@ const outgoing = new Whisper.Message({
|
|||
quote: {
|
||||
author: '+12025550100',
|
||||
id: Date.now() - 1000,
|
||||
attachments: {
|
||||
contentType: 'image/gif',
|
||||
fileName: 'pi.gif',
|
||||
thumbnail: {
|
||||
attachments: [
|
||||
{
|
||||
contentType: 'image/gif',
|
||||
data: util.gif,
|
||||
}
|
||||
}
|
||||
fileName: 'pi.gif',
|
||||
thumbnail: {
|
||||
contentType: 'image/gif',
|
||||
data: util.gif,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
const incoming = new Whisper.Message(Object.assign({}, outgoing.attributes, {
|
||||
|
@ -126,14 +130,16 @@ const outgoing = new Whisper.Message({
|
|||
author: '+12025550100',
|
||||
text: 'Check out this video I found!',
|
||||
id: Date.now() - 1000,
|
||||
attachments: {
|
||||
contentType: 'video/mp4',
|
||||
fileName: 'freezing_bubble.mp4',
|
||||
thumbnail: {
|
||||
contentType: 'image/gif',
|
||||
data: util.gif,
|
||||
}
|
||||
}
|
||||
attachments: [
|
||||
{
|
||||
contentType: 'video/mp4',
|
||||
fileName: 'freezing_bubble.mp4',
|
||||
thumbnail: {
|
||||
contentType: 'image/gif',
|
||||
data: util.gif,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
const incoming = new Whisper.Message(Object.assign({}, outgoing.attributes, {
|
||||
|
@ -166,14 +172,16 @@ const outgoing = new Whisper.Message({
|
|||
quote: {
|
||||
author: '+12025550100',
|
||||
id: Date.now() - 1000,
|
||||
attachments: {
|
||||
contentType: 'video/mp4',
|
||||
fileName: 'freezing_bubble.mp4',
|
||||
thumbnail: {
|
||||
contentType: 'image/gif',
|
||||
data: util.gif,
|
||||
}
|
||||
}
|
||||
attachments: [
|
||||
{
|
||||
contentType: 'video/mp4',
|
||||
fileName: 'freezing_bubble.mp4',
|
||||
thumbnail: {
|
||||
contentType: 'image/gif',
|
||||
data: util.gif,
|
||||
}
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
const incoming = new Whisper.Message(Object.assign({}, outgoing.attributes, {
|
||||
|
@ -207,10 +215,12 @@ const outgoing = new Whisper.Message({
|
|||
author: '+12025550100',
|
||||
text: 'Check out this beautiful song!',
|
||||
id: Date.now() - 1000,
|
||||
attachments: {
|
||||
contentType: 'audio/mp3',
|
||||
fileName: 'agnus_dei.mp4',
|
||||
}
|
||||
attachments: [
|
||||
{
|
||||
contentType: 'audio/mp3',
|
||||
fileName: 'agnus_dei.mp4',
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
const incoming = new Whisper.Message(Object.assign({}, outgoing.attributes, {
|
||||
|
@ -243,10 +253,12 @@ const outgoing = new Whisper.Message({
|
|||
quote: {
|
||||
author: '+12025550100',
|
||||
id: Date.now() - 1000,
|
||||
attachments: {
|
||||
contentType: 'audio/mp3',
|
||||
fileName: 'agnus_dei.mp4',
|
||||
}
|
||||
attachments: [
|
||||
{
|
||||
contentType: 'audio/mp3',
|
||||
fileName: 'agnus_dei.mp4',
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
const incoming = new Whisper.Message(Object.assign({}, outgoing.attributes, {
|
||||
|
@ -279,12 +291,14 @@ const outgoing = new Whisper.Message({
|
|||
quote: {
|
||||
author: '+12025550100',
|
||||
id: Date.now() - 1000,
|
||||
attachments: {
|
||||
// proposed as of afternoon of 4/6 in Quoted Replies group
|
||||
flags: textsecure.protobuf.AttachmentPointer.Flags.VOICE_MESSAGE,
|
||||
contentType: 'audio/mp3',
|
||||
fileName: 'agnus_dei.mp4',
|
||||
}
|
||||
attachments: [
|
||||
{
|
||||
// proposed as of afternoon of 4/6 in Quoted Replies group
|
||||
flags: textsecure.protobuf.AttachmentPointer.Flags.VOICE_MESSAGE,
|
||||
contentType: 'audio/mp3',
|
||||
fileName: 'agnus_dei.mp4',
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
const incoming = new Whisper.Message(Object.assign({}, outgoing.attributes, {
|
||||
|
@ -318,10 +332,12 @@ const outgoing = new Whisper.Message({
|
|||
author: '+12025550100',
|
||||
text: 'This is my manifesto. Tell me what you think!',
|
||||
id: Date.now() - 1000,
|
||||
attachments: {
|
||||
contentType: 'text/plain',
|
||||
fileName: 'lorum_ipsum.txt',
|
||||
}
|
||||
attachments: [
|
||||
{
|
||||
contentType: 'text/plain',
|
||||
fileName: 'lorum_ipsum.txt',
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
const incoming = new Whisper.Message(Object.assign({}, outgoing.attributes, {
|
||||
|
@ -354,10 +370,12 @@ const outgoing = new Whisper.Message({
|
|||
quote: {
|
||||
author: '+12025550100',
|
||||
id: Date.now() - 1000,
|
||||
attachments: {
|
||||
contentType: 'text/plain',
|
||||
fileName: 'lorum_ipsum.txt',
|
||||
}
|
||||
attachments: [
|
||||
{
|
||||
contentType: 'text/plain',
|
||||
fileName: 'lorum_ipsum.txt',
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
const incoming = new Whisper.Message(Object.assign({}, outgoing.attributes, {
|
||||
|
|
|
@ -1,14 +1,134 @@
|
|||
import React from 'react';
|
||||
import classnames from 'classnames';
|
||||
|
||||
// @ts-ignore
|
||||
import Mime from '../../../js/modules/types/mime';
|
||||
|
||||
|
||||
interface Props { name: string; }
|
||||
interface Props {
|
||||
i18n: (key: string, values?: Array<string>) => string;
|
||||
authorName: string;
|
||||
authorColor: string;
|
||||
attachments: Array<QuotedAttachment>;
|
||||
text: string;
|
||||
}
|
||||
|
||||
interface State { count: number; }
|
||||
interface QuotedAttachment {
|
||||
fileName: string;
|
||||
contentType: string;
|
||||
isVoiceMessage: boolean;
|
||||
objectUrl: string;
|
||||
thumbnail: {
|
||||
contentType: string;
|
||||
data: ArrayBuffer;
|
||||
}
|
||||
}
|
||||
|
||||
function validateQuote(quote: Props): boolean {
|
||||
if (quote.text) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (quote.attachments && quote.attachments.length > 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function getContentType(attachments: Array<QuotedAttachment>): string | null {
|
||||
if (!attachments || attachments.length === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const first = attachments[0];
|
||||
return first.contentType;
|
||||
}
|
||||
|
||||
export class Quote extends React.Component<Props, {}> {
|
||||
public renderIcon(first: QuotedAttachment) {
|
||||
const contentType = first.contentType;
|
||||
const objectUrl = first.objectUrl;
|
||||
|
||||
if (Mime.isVideo(contentType)) {
|
||||
// Render play icon on top of thumbnail
|
||||
// We'd have to generate our own thumbnail from a local video??
|
||||
return <div className='inner play'>Video</div>;
|
||||
} else if (Mime.isImage(contentType)) {
|
||||
if (objectUrl) {
|
||||
return <div className='inner'><img src={objectUrl} /></div>;
|
||||
} else {
|
||||
return <div className='inner'>Loading Widget</div>
|
||||
}
|
||||
} else if (Mime.isAudio(contentType)) {
|
||||
// Show microphone inner in circle
|
||||
return <div className='inner microphone'>Audio</div>;
|
||||
} else {
|
||||
// Show file icon
|
||||
return <div className='inner file'>File</div>;
|
||||
}
|
||||
}
|
||||
|
||||
public renderIconContainer() {
|
||||
const { attachments } = this.props;
|
||||
|
||||
if (!attachments || attachments.length === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const first = attachments[0];
|
||||
|
||||
return <div className='icon-container'>
|
||||
{this.renderIcon(first)}
|
||||
</div>
|
||||
}
|
||||
|
||||
public renderText() {
|
||||
const { i18n, text, attachments } = this.props;
|
||||
|
||||
if (text) {
|
||||
return <div className='text'>{text}</div>;
|
||||
}
|
||||
|
||||
if (!attachments || attachments.length === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const contentType = getContentType(attachments);
|
||||
const first = attachments[0];
|
||||
const fileName = first.fileName;
|
||||
|
||||
console.log(contentType);
|
||||
|
||||
if (Mime.isVideo(contentType)) {
|
||||
return <div className='type-label'>{i18n('video')}</div>;
|
||||
} else if (Mime.isImage(contentType)) {
|
||||
return <div className='type-label'>{i18n('photo')}</div>;
|
||||
} else if (Mime.isAudio(contentType) && first.isVoiceMessage) {
|
||||
return <div className='type-label'>{i18n('voiceMessage')}</div>;
|
||||
} else if (Mime.isAudio(contentType)) {
|
||||
console.log(first);
|
||||
return <div className='type-label'>{i18n('audio')}</div>;
|
||||
}
|
||||
|
||||
return <div className='filename-label'>{fileName}</div>;
|
||||
}
|
||||
|
||||
export class Reply extends React.Component<Props, State> {
|
||||
public render() {
|
||||
const { authorName, authorColor } = this.props;
|
||||
|
||||
if (!validateQuote(this.props)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<div>Placeholder</div>
|
||||
<div className={classnames(authorColor, 'quote')} >
|
||||
<div className="primary">
|
||||
<div className="author">{authorName}</div>
|
||||
{this.renderText()}
|
||||
</div>
|
||||
{this.renderIconContainer()}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -40,6 +40,10 @@
|
|||
version "4.1.2"
|
||||
resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.1.2.tgz#f1af664769cfb50af805431c407425ed619daa21"
|
||||
|
||||
"@types/classnames@^2.2.3":
|
||||
version "2.2.3"
|
||||
resolved "https://registry.yarnpkg.com/@types/classnames/-/classnames-2.2.3.tgz#3f0ff6873da793870e20a260cada55982f38a9e5"
|
||||
|
||||
"@types/lodash@^4.14.106":
|
||||
version "4.14.106"
|
||||
resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.106.tgz#6093e9a02aa567ddecfe9afadca89e53e5dce4dd"
|
||||
|
|
Loading…
Reference in a new issue