fixing alignment issues with long user and topic names
This commit is contained in:
+23
-9
@@ -586,9 +586,7 @@ div.trusted-badge {
|
|||||||
.in-place-edit {
|
.in-place-edit {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
font-family: inherit;
|
font-family: inherit;
|
||||||
font-size: 1.1rem;
|
font-size: 1rem;
|
||||||
height: 2.5rem;
|
|
||||||
line-height: 2.25;
|
|
||||||
margin: 0.25rem 0.125rem 0 0.125rem;
|
margin: 0.25rem 0.125rem 0 0.125rem;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
vertical-align: baseline;
|
vertical-align: baseline;
|
||||||
@@ -596,6 +594,12 @@ div.trusted-badge {
|
|||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.in-place-edit.short {
|
||||||
|
font-size: 1.1rem;
|
||||||
|
height: 2.5rem;
|
||||||
|
line-height: 2.25;
|
||||||
|
}
|
||||||
|
|
||||||
.in-place-edit.disabled {
|
.in-place-edit.disabled {
|
||||||
border-bottom: none;
|
border-bottom: none;
|
||||||
cursor: default;
|
cursor: default;
|
||||||
@@ -605,11 +609,15 @@ div.trusted-badge {
|
|||||||
color: #bbb;
|
color: #bbb;
|
||||||
}
|
}
|
||||||
|
|
||||||
.in-place-edit .content {
|
.in-place-edit span {
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.in-place-edit.short span {
|
||||||
display: block;
|
display: block;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
overflow: hidden
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
/* END of InPlaceEdit styles */
|
/* END of InPlaceEdit styles */
|
||||||
|
|
||||||
@@ -842,6 +850,7 @@ i.search {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.scrollable-panel {
|
.scrollable-panel {
|
||||||
|
overflow-x: hidden;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
margin-top: 0.25rem;
|
margin-top: 0.25rem;
|
||||||
margin-bottom: auto;
|
margin-bottom: auto;
|
||||||
@@ -887,7 +896,8 @@ i.search {
|
|||||||
.contact-box .contact-title {
|
.contact-box .contact-title {
|
||||||
font-size: 1.05rem;
|
font-size: 1.05rem;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
overflow: hidden
|
overflow-x: hidden;
|
||||||
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
.contact-box .contact-comment {
|
.contact-box .contact-comment {
|
||||||
@@ -934,6 +944,11 @@ i.search {
|
|||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
justify-content: space-around;
|
justify-content: space-around;
|
||||||
}
|
}
|
||||||
|
.contact-box .text-box > div {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
.contact-box .action-text {
|
.contact-box .action-text {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
@@ -1023,13 +1038,12 @@ i.search {
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
flex-grow: 0;
|
flex-grow: 0;
|
||||||
flex-shrink: 0;
|
|
||||||
padding: 0.5rem 0.75rem;
|
padding: 0.5rem 0.75rem;
|
||||||
line-height: 1.5;
|
line-height: 1.5;
|
||||||
|
overflow-x: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Make sure padding is only applied at
|
/* Make sure padding is only applied at the top level panel */
|
||||||
the top level panel */
|
|
||||||
.panel-form-row > .panel-form-column,
|
.panel-form-row > .panel-form-column,
|
||||||
.panel-form-column > .panel-form-column {
|
.panel-form-column > .panel-form-column {
|
||||||
padding: 0!important;
|
padding: 0!important;
|
||||||
|
|||||||
Vendored
+1
-1
File diff suppressed because one or more lines are too long
@@ -84,6 +84,8 @@ export const MAX_ONLINE_IN_TOPIC = 4;
|
|||||||
|
|
||||||
// Maximum length of user name, topic title, and private comment.
|
// Maximum length of user name, topic title, and private comment.
|
||||||
export const MAX_TITLE_LENGTH = 60;
|
export const MAX_TITLE_LENGTH = 60;
|
||||||
|
// Maximum length of topic description.
|
||||||
|
export const MAX_TOPIC_DESCRIPTION_LENGTH = 360;
|
||||||
|
|
||||||
// Length of message previews in chat list, in characters.
|
// Length of message previews in chat list, in characters.
|
||||||
export const MESSAGE_PREVIEW_LENGTH = 80;
|
export const MESSAGE_PREVIEW_LENGTH = 80;
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ export const MIME_EXTENSIONS = ['jpg', 'gif', 'png',
|
|||||||
|
|
||||||
// Get an URL from a theCard photo: either create a data: URL or return reference URL.
|
// Get an URL from a theCard photo: either create a data: URL or return reference URL.
|
||||||
export function makeImageUrl(photo) {
|
export function makeImageUrl(photo) {
|
||||||
if (photo) {
|
if (typeof photo == 'object') {
|
||||||
if (photo.data && photo.type) {
|
if (photo.data && photo.type) {
|
||||||
const mime = photo.type.startsWith('image/') ? photo.type : ('image/' + photo.type);
|
const mime = photo.type.startsWith('image/') ? photo.type : ('image/' + photo.type);
|
||||||
return 'data:' + mime + ';base64,' + photo.data;
|
return 'data:' + mime + ';base64,' + photo.data;
|
||||||
|
|||||||
+7
-1
@@ -20,9 +20,10 @@ export function updateFavicon(count) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Create theCard which represents user's or topic's "public" info.
|
// Create theCard which represents user's or topic's "public" info.
|
||||||
export function theCard(fn, imageUrl, imageMimeType) {
|
export function theCard(fn, imageUrl, imageMimeType, note) {
|
||||||
let card = null;
|
let card = null;
|
||||||
fn = fn && fn.trim();
|
fn = fn && fn.trim();
|
||||||
|
note = note && note.trim();
|
||||||
|
|
||||||
if (fn) {
|
if (fn) {
|
||||||
card = {
|
card = {
|
||||||
@@ -30,6 +31,11 @@ export function theCard(fn, imageUrl, imageMimeType) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (typeof note == 'string') {
|
||||||
|
card = card || {};
|
||||||
|
card.note = note ? note : Tinode.DEL_CHAR;
|
||||||
|
}
|
||||||
|
|
||||||
if (imageUrl) {
|
if (imageUrl) {
|
||||||
card = card || {};
|
card = card || {};
|
||||||
let mimeType = imageMimeType;
|
let mimeType = imageMimeType;
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ export default class AccountSettingsView extends React.Component {
|
|||||||
<div>
|
<div>
|
||||||
<label className="small"><FormattedMessage id="label_user_id" defaultMessage="ID:"
|
<label className="small"><FormattedMessage id="label_user_id" defaultMessage="ID:"
|
||||||
description="Label for user address (ID)" /></label>
|
description="Label for user address (ID)" /></label>
|
||||||
<tt>{this.props.myUserId}</tt>
|
<tt style={{whiteSpace: 'nowrap'}}>{this.props.myUserId}</tt>
|
||||||
</div>
|
</div>
|
||||||
<BadgeList trustedBadges={this.props.trustedBadges} />
|
<BadgeList trustedBadges={this.props.trustedBadges} />
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ export default class InPlaceEdit extends React.Component {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.setState({active: false});
|
this.setState({active: false});
|
||||||
let value = this.state.value.trim();
|
const value = this.state.value.trim();
|
||||||
if ((value || this.props.value) && (value !== this.props.value)) {
|
if ((value || this.props.value) && (value !== this.props.value)) {
|
||||||
this.props.onFinished(value);
|
this.props.onFinished(value);
|
||||||
}
|
}
|
||||||
@@ -86,17 +86,18 @@ export default class InPlaceEdit extends React.Component {
|
|||||||
spanText = this.props.placeholder;
|
spanText = this.props.placeholder;
|
||||||
spanClass += ' placeholder';
|
spanClass += ' placeholder';
|
||||||
}
|
}
|
||||||
if (spanText.length > 20) {
|
if (!this.props.multiline || this.props.multiline == 1) {
|
||||||
// FIXME: this is wrong for RTL languages.
|
spanClass += ' short';
|
||||||
spanText = spanText.substring(0, 19) + '...';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return (<span className={spanClass} onClick={this.handleStartEditing}>
|
return (<span className={spanClass} onClick={this.handleStartEditing}>
|
||||||
<span className="content">{spanText}</span>
|
<span>{spanText}</span>
|
||||||
</span>);
|
</span>);
|
||||||
}
|
}
|
||||||
|
|
||||||
let element;
|
let element;
|
||||||
let attr = {};
|
const attr = {};
|
||||||
|
let value = null;
|
||||||
if (this.props.type == 'password') {
|
if (this.props.type == 'password') {
|
||||||
element = VisiblePassword;
|
element = VisiblePassword;
|
||||||
attr.onFinished = this.handlePasswordFinished;
|
attr.onFinished = this.handlePasswordFinished;
|
||||||
@@ -105,9 +106,11 @@ export default class InPlaceEdit extends React.Component {
|
|||||||
element = 'textarea';
|
element = 'textarea';
|
||||||
attr.rows = this.props.multiline;
|
attr.rows = this.props.multiline;
|
||||||
attr.className = 'inplace-edit';
|
attr.className = 'inplace-edit';
|
||||||
|
value = this.state.value;
|
||||||
} else {
|
} else {
|
||||||
element = 'input';
|
element = 'input';
|
||||||
attr.type = this.props.type || 'text';
|
attr.type = this.props.type || 'text';
|
||||||
|
attr.value = this.state.value;
|
||||||
}
|
}
|
||||||
attr.onChange = this.handeTextChange;
|
attr.onChange = this.handeTextChange;
|
||||||
attr.onKeyDown = this.handleKeyDown;
|
attr.onKeyDown = this.handleKeyDown;
|
||||||
@@ -119,6 +122,6 @@ export default class InPlaceEdit extends React.Component {
|
|||||||
attr.autoFocus = true;
|
attr.autoFocus = true;
|
||||||
attr.ref = this.selfRef;
|
attr.ref = this.selfRef;
|
||||||
|
|
||||||
return React.createElement(element, attr, null);
|
return React.createElement(element, attr, value);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import InPlaceEdit from './in-place-edit.jsx';
|
|||||||
import TagManager from './tag-manager.jsx';
|
import TagManager from './tag-manager.jsx';
|
||||||
|
|
||||||
import { AVATAR_SIZE, MAX_AVATAR_BYTES, MAX_EXTERN_ATTACHMENT_SIZE,
|
import { AVATAR_SIZE, MAX_AVATAR_BYTES, MAX_EXTERN_ATTACHMENT_SIZE,
|
||||||
MAX_INBAND_ATTACHMENT_SIZE, MAX_TITLE_LENGTH } from '../config.js';
|
MAX_INBAND_ATTACHMENT_SIZE, MAX_TITLE_LENGTH, MAX_TOPIC_DESCRIPTION_LENGTH } from '../config.js';
|
||||||
import { imageScaled, blobToBase64, makeImageUrl } from '../lib/blob-helpers.js';
|
import { imageScaled, blobToBase64, makeImageUrl } from '../lib/blob-helpers.js';
|
||||||
import { arrayEqual, theCard } from '../lib/utils.js';
|
import { arrayEqual, theCard } from '../lib/utils.js';
|
||||||
|
|
||||||
@@ -25,6 +25,8 @@ export default class TopicDescEdit extends React.Component {
|
|||||||
isMe: Tinode.isMeTopicName(this.props.topic),
|
isMe: Tinode.isMeTopicName(this.props.topic),
|
||||||
owner: acs && acs.isOwner(),
|
owner: acs && acs.isOwner(),
|
||||||
fullName: topic.public ? topic.public.fn : undefined,
|
fullName: topic.public ? topic.public.fn : undefined,
|
||||||
|
private: topic.private ? topic.private.comment : null,
|
||||||
|
description: topic.public ? topic.public.note : undefined,
|
||||||
avatar: makeImageUrl(topic.public ? topic.public.photo : null),
|
avatar: makeImageUrl(topic.public ? topic.public.photo : null),
|
||||||
tags: topic.tags(),
|
tags: topic.tags(),
|
||||||
newAvatar: null,
|
newAvatar: null,
|
||||||
@@ -36,6 +38,8 @@ export default class TopicDescEdit extends React.Component {
|
|||||||
this.handleFullNameUpdate = this.handleFullNameUpdate.bind(this);
|
this.handleFullNameUpdate = this.handleFullNameUpdate.bind(this);
|
||||||
this.handleImageUpdated = this.handleImageUpdated.bind(this);
|
this.handleImageUpdated = this.handleImageUpdated.bind(this);
|
||||||
this.handleAvatarCropped = this.handleAvatarCropped.bind(this);
|
this.handleAvatarCropped = this.handleAvatarCropped.bind(this);
|
||||||
|
this.handlePrivateUpdate = this.handlePrivateUpdate.bind(this);
|
||||||
|
this.handleDescriptionUpdate = this.handleDescriptionUpdate.bind(this);
|
||||||
this.uploadAvatar = this.uploadAvatar.bind(this);
|
this.uploadAvatar = this.uploadAvatar.bind(this);
|
||||||
this.handleAvatarCropCancel = this.handleAvatarCropCancel.bind(this);
|
this.handleAvatarCropCancel = this.handleAvatarCropCancel.bind(this);
|
||||||
this.handleTagsUpdated = this.handleTagsUpdated.bind(this);
|
this.handleTagsUpdated = this.handleTagsUpdated.bind(this);
|
||||||
@@ -57,12 +61,28 @@ export default class TopicDescEdit extends React.Component {
|
|||||||
|
|
||||||
handleFullNameUpdate(fn) {
|
handleFullNameUpdate(fn) {
|
||||||
fn = fn.trim().substring(0, MAX_TITLE_LENGTH);
|
fn = fn.trim().substring(0, MAX_TITLE_LENGTH);
|
||||||
if (fn) {
|
if (fn && this.state.fullName !== fn) {
|
||||||
this.setState({fullName: fn});
|
this.setState({fullName: fn});
|
||||||
this.props.onUpdateTopicDesc(this.props.topic, theCard(fn, null));
|
this.props.onUpdateTopicDesc(this.props.topic, theCard(fn, null));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handlePrivateUpdate(comment) {
|
||||||
|
comment = comment.trim().substring(0, MAX_TITLE_LENGTH);
|
||||||
|
if (this.state.private !== comment) {
|
||||||
|
this.setState({private: comment});
|
||||||
|
this.props.onTopicDescUpdate(this.props.topic, null, comment || Tinode.DEL_CHAR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
handleDescriptionUpdate(desc) {
|
||||||
|
desc = desc.trim().substring(0, MAX_TOPIC_DESCRIPTION_LENGTH);
|
||||||
|
if (desc) {
|
||||||
|
this.setState({description: desc});
|
||||||
|
this.props.onUpdateTopicDesc(this.props.topic, theCard(null, null, null, desc));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// AvatarUpload widget has changed the avatar: received a new file or deleted the avatar.
|
// AvatarUpload widget has changed the avatar: received a new file or deleted the avatar.
|
||||||
handleImageUpdated(mime, img) {
|
handleImageUpdated(mime, img) {
|
||||||
// This will show the AvatarCropView is img is not null.
|
// This will show the AvatarCropView is img is not null.
|
||||||
@@ -153,59 +173,59 @@ export default class TopicDescEdit extends React.Component {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="panel-form-row">
|
|
||||||
<div className="panel-form-column">
|
|
||||||
{this.state.isMe ? <>
|
|
||||||
<label className="small">
|
|
||||||
<FormattedMessage id="label_your_name" defaultMessage="Your name"
|
|
||||||
description="Label for full name editing" />
|
|
||||||
</label>
|
|
||||||
<div><FormattedMessage id="full_name_prompt" defaultMessage="Full name, e.g. John Doe"
|
|
||||||
description="Input placeholder for person's full name">{
|
|
||||||
(full_name_placeholder) => <InPlaceEdit
|
|
||||||
placeholder={full_name_placeholder}
|
|
||||||
value={this.state.fullName}
|
|
||||||
required={true}
|
|
||||||
onFinished={this.handleFullNameUpdate} />
|
|
||||||
}</FormattedMessage></div>
|
|
||||||
</> : <>
|
|
||||||
<div><label className="small">
|
|
||||||
<FormattedMessage id="label_topic_name" defaultMessage="Name"
|
|
||||||
description="Label for editing topic name" />
|
|
||||||
</label></div>
|
|
||||||
<div><InPlaceEdit
|
|
||||||
placeholder={this.state.groupTopic ? "Group name" : <i>Unknown</i>}
|
|
||||||
readOnly={!this.state.owner}
|
|
||||||
value={this.state.fullName}
|
|
||||||
required={true}
|
|
||||||
onFinished={this.handleFullNameUpdate} /></div>
|
|
||||||
<div><label className="small">
|
|
||||||
<FormattedMessage id="label_private" defaultMessage="Private comment"
|
|
||||||
description="Label for editing 'private'" />
|
|
||||||
</label></div>
|
|
||||||
<div>
|
|
||||||
<FormattedMessage id="private_editing_placeholder"
|
|
||||||
defaultMessage="Visible to you only"
|
|
||||||
description="Placeholder for editing 'private'">{
|
|
||||||
(private_placeholder) => <InPlaceEdit
|
|
||||||
placeholder={private_placeholder}
|
|
||||||
value={this.state.private}
|
|
||||||
onFinished={this.handlePrivateUpdate} />
|
|
||||||
}</FormattedMessage>
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
<AvatarUpload
|
|
||||||
tinode={this.props.tinode}
|
|
||||||
avatar={this.state.avatar}
|
|
||||||
readOnly={!editable}
|
|
||||||
uid={this.props.topic}
|
|
||||||
title={this.state.fullName}
|
|
||||||
onImageUpdated={this.handleImageUpdated}
|
|
||||||
onError={this.props.onError} />
|
|
||||||
</div>
|
|
||||||
<div className="panel-form-column">
|
<div className="panel-form-column">
|
||||||
|
<div className="panel-form-row">
|
||||||
|
<div className="panel-form-column">
|
||||||
|
{this.state.isMe ? <>
|
||||||
|
<label className="small">
|
||||||
|
<FormattedMessage id="label_your_name" defaultMessage="Your name"
|
||||||
|
description="Label for full name editing" />
|
||||||
|
</label>
|
||||||
|
<div><FormattedMessage id="full_name_prompt" defaultMessage="Full name, e.g. John Doe"
|
||||||
|
description="Input placeholder for person's full name">{
|
||||||
|
(full_name_placeholder) => <InPlaceEdit
|
||||||
|
placeholder={full_name_placeholder}
|
||||||
|
value={this.state.fullName}
|
||||||
|
required={true}
|
||||||
|
onFinished={this.handleFullNameUpdate} />
|
||||||
|
}</FormattedMessage></div>
|
||||||
|
</> : <>
|
||||||
|
<div><label className="small">
|
||||||
|
<FormattedMessage id="label_topic_name" defaultMessage="Name"
|
||||||
|
description="Label for editing topic name" />
|
||||||
|
</label></div>
|
||||||
|
<div><InPlaceEdit
|
||||||
|
placeholder={this.state.groupTopic ? "Group name" : <i>Unknown</i>}
|
||||||
|
readOnly={!this.state.owner}
|
||||||
|
value={this.state.fullName}
|
||||||
|
required={true}
|
||||||
|
onFinished={this.handleFullNameUpdate} /></div>
|
||||||
|
<div><label className="small">
|
||||||
|
<FormattedMessage id="label_private" defaultMessage="Private comment"
|
||||||
|
description="Label for editing 'private'" />
|
||||||
|
</label></div>
|
||||||
|
<div>
|
||||||
|
<FormattedMessage id="private_editing_placeholder"
|
||||||
|
defaultMessage="Visible to you only"
|
||||||
|
description="Placeholder for editing 'private'">{
|
||||||
|
(private_placeholder) => <InPlaceEdit
|
||||||
|
placeholder={private_placeholder}
|
||||||
|
value={this.state.private}
|
||||||
|
onFinished={this.handlePrivateUpdate} />
|
||||||
|
}</FormattedMessage>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
<AvatarUpload
|
||||||
|
tinode={this.props.tinode}
|
||||||
|
avatar={this.state.avatar}
|
||||||
|
readOnly={!editable}
|
||||||
|
uid={this.props.topic}
|
||||||
|
title={this.state.fullName}
|
||||||
|
onImageUpdated={this.handleImageUpdated}
|
||||||
|
onError={this.props.onError} />
|
||||||
|
</div>
|
||||||
<div><label className="small">
|
<div><label className="small">
|
||||||
<FormattedMessage id="label_description" defaultMessage="Description"
|
<FormattedMessage id="label_description" defaultMessage="Description"
|
||||||
description="Label for editing topic description" />
|
description="Label for editing topic description" />
|
||||||
|
|||||||
+54
-15
@@ -37,6 +37,7 @@ __webpack_require__.r(__webpack_exports__);
|
|||||||
/* harmony export */ "IMAGE_PREVIEW_DIM": () => (/* binding */ IMAGE_PREVIEW_DIM),
|
/* harmony export */ "IMAGE_PREVIEW_DIM": () => (/* binding */ IMAGE_PREVIEW_DIM),
|
||||||
/* harmony export */ "MAX_ONLINE_IN_TOPIC": () => (/* binding */ MAX_ONLINE_IN_TOPIC),
|
/* harmony export */ "MAX_ONLINE_IN_TOPIC": () => (/* binding */ MAX_ONLINE_IN_TOPIC),
|
||||||
/* harmony export */ "MAX_TITLE_LENGTH": () => (/* binding */ MAX_TITLE_LENGTH),
|
/* harmony export */ "MAX_TITLE_LENGTH": () => (/* binding */ MAX_TITLE_LENGTH),
|
||||||
|
/* harmony export */ "MAX_TOPIC_DESCRIPTION_LENGTH": () => (/* binding */ MAX_TOPIC_DESCRIPTION_LENGTH),
|
||||||
/* harmony export */ "MESSAGE_PREVIEW_LENGTH": () => (/* binding */ MESSAGE_PREVIEW_LENGTH),
|
/* harmony export */ "MESSAGE_PREVIEW_LENGTH": () => (/* binding */ MESSAGE_PREVIEW_LENGTH),
|
||||||
/* harmony export */ "LINK_CONTACT_US": () => (/* binding */ LINK_CONTACT_US),
|
/* harmony export */ "LINK_CONTACT_US": () => (/* binding */ LINK_CONTACT_US),
|
||||||
/* harmony export */ "LINK_PRIVACY_POLICY": () => (/* binding */ LINK_PRIVACY_POLICY),
|
/* harmony export */ "LINK_PRIVACY_POLICY": () => (/* binding */ LINK_PRIVACY_POLICY),
|
||||||
@@ -74,6 +75,7 @@ const MAX_IMAGE_DIM = 1024;
|
|||||||
const IMAGE_PREVIEW_DIM = 64;
|
const IMAGE_PREVIEW_DIM = 64;
|
||||||
const MAX_ONLINE_IN_TOPIC = 4;
|
const MAX_ONLINE_IN_TOPIC = 4;
|
||||||
const MAX_TITLE_LENGTH = 60;
|
const MAX_TITLE_LENGTH = 60;
|
||||||
|
const MAX_TOPIC_DESCRIPTION_LENGTH = 360;
|
||||||
const MESSAGE_PREVIEW_LENGTH = 80;
|
const MESSAGE_PREVIEW_LENGTH = 80;
|
||||||
const LINK_CONTACT_US = 'email:support@tinode.co';
|
const LINK_CONTACT_US = 'email:support@tinode.co';
|
||||||
const LINK_PRIVACY_POLICY = 'https://tinode.co/privacy.html';
|
const LINK_PRIVACY_POLICY = 'https://tinode.co/privacy.html';
|
||||||
@@ -111,7 +113,7 @@ __webpack_require__.r(__webpack_exports__);
|
|||||||
const SUPPORTED_IMAGE_FORMATS = ['image/jpeg', 'image/gif', 'image/png', 'image/svg', 'image/svg+xml'];
|
const SUPPORTED_IMAGE_FORMATS = ['image/jpeg', 'image/gif', 'image/png', 'image/svg', 'image/svg+xml'];
|
||||||
const MIME_EXTENSIONS = ['jpg', 'gif', 'png', 'svg', 'svg'];
|
const MIME_EXTENSIONS = ['jpg', 'gif', 'png', 'svg', 'svg'];
|
||||||
function makeImageUrl(photo) {
|
function makeImageUrl(photo) {
|
||||||
if (photo) {
|
if (typeof photo == 'object') {
|
||||||
if (photo.data && photo.type) {
|
if (photo.data && photo.type) {
|
||||||
const mime = photo.type.startsWith('image/') ? photo.type : 'image/' + photo.type;
|
const mime = photo.type.startsWith('image/') ? photo.type : 'image/' + photo.type;
|
||||||
return 'data:' + mime + ';base64,' + photo.data;
|
return 'data:' + mime + ';base64,' + photo.data;
|
||||||
@@ -592,9 +594,10 @@ function updateFavicon(count) {
|
|||||||
head.appendChild(newIcon);
|
head.appendChild(newIcon);
|
||||||
document.title = (count > 0 ? '(' + count + ') ' : '') + 'Tinode';
|
document.title = (count > 0 ? '(' + count + ') ' : '') + 'Tinode';
|
||||||
}
|
}
|
||||||
function theCard(fn, imageUrl, imageMimeType) {
|
function theCard(fn, imageUrl, imageMimeType, note) {
|
||||||
let card = null;
|
let card = null;
|
||||||
fn = fn && fn.trim();
|
fn = fn && fn.trim();
|
||||||
|
note = note && note.trim();
|
||||||
|
|
||||||
if (fn) {
|
if (fn) {
|
||||||
card = {
|
card = {
|
||||||
@@ -602,6 +605,11 @@ function theCard(fn, imageUrl, imageMimeType) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (typeof note == 'string') {
|
||||||
|
card = card || {};
|
||||||
|
card.note = note ? note : (tinode_sdk__WEBPACK_IMPORTED_MODULE_0___default().DEL_CHAR);
|
||||||
|
}
|
||||||
|
|
||||||
if (imageUrl) {
|
if (imageUrl) {
|
||||||
card = card || {};
|
card = card || {};
|
||||||
let mimeType = imageMimeType;
|
let mimeType = imageMimeType;
|
||||||
@@ -1249,7 +1257,11 @@ class AccountSettingsView extends (react__WEBPACK_IMPORTED_MODULE_0___default().
|
|||||||
"type": 0,
|
"type": 0,
|
||||||
"value": "ID:"
|
"value": "ID:"
|
||||||
}]
|
}]
|
||||||
})), "\xA0", react__WEBPACK_IMPORTED_MODULE_0___default().createElement("tt", null, this.props.myUserId)), react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_widgets_badge_list_jsx__WEBPACK_IMPORTED_MODULE_3__.default, {
|
})), "\xA0", react__WEBPACK_IMPORTED_MODULE_0___default().createElement("tt", {
|
||||||
|
style: {
|
||||||
|
whiteSpace: 'nowrap'
|
||||||
|
}
|
||||||
|
}, this.props.myUserId)), react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_widgets_badge_list_jsx__WEBPACK_IMPORTED_MODULE_3__.default, {
|
||||||
trustedBadges: this.props.trustedBadges
|
trustedBadges: this.props.trustedBadges
|
||||||
})), react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_widgets_avatar_upload_jsx__WEBPACK_IMPORTED_MODULE_2__.default, {
|
})), react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_widgets_avatar_upload_jsx__WEBPACK_IMPORTED_MODULE_2__.default, {
|
||||||
tinode: this.props.tinode,
|
tinode: this.props.tinode,
|
||||||
@@ -9859,7 +9871,7 @@ class InPlaceEdit extends (react__WEBPACK_IMPORTED_MODULE_0___default().Componen
|
|||||||
this.setState({
|
this.setState({
|
||||||
active: false
|
active: false
|
||||||
});
|
});
|
||||||
let value = this.state.value.trim();
|
const value = this.state.value.trim();
|
||||||
|
|
||||||
if ((value || this.props.value) && value !== this.props.value) {
|
if ((value || this.props.value) && value !== this.props.value) {
|
||||||
this.props.onFinished(value);
|
this.props.onFinished(value);
|
||||||
@@ -9886,20 +9898,19 @@ class InPlaceEdit extends (react__WEBPACK_IMPORTED_MODULE_0___default().Componen
|
|||||||
spanClass += ' placeholder';
|
spanClass += ' placeholder';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (spanText.length > 20) {
|
if (!this.props.multiline || this.props.multiline == 1) {
|
||||||
spanText = spanText.substring(0, 19) + '...';
|
spanClass += ' short';
|
||||||
}
|
}
|
||||||
|
|
||||||
return react__WEBPACK_IMPORTED_MODULE_0___default().createElement("span", {
|
return react__WEBPACK_IMPORTED_MODULE_0___default().createElement("span", {
|
||||||
className: spanClass,
|
className: spanClass,
|
||||||
onClick: this.handleStartEditing
|
onClick: this.handleStartEditing
|
||||||
}, react__WEBPACK_IMPORTED_MODULE_0___default().createElement("span", {
|
}, react__WEBPACK_IMPORTED_MODULE_0___default().createElement("span", null, spanText));
|
||||||
className: "content"
|
|
||||||
}, spanText));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let element;
|
let element;
|
||||||
let attr = {};
|
const attr = {};
|
||||||
|
let value = null;
|
||||||
|
|
||||||
if (this.props.type == 'password') {
|
if (this.props.type == 'password') {
|
||||||
element = _visible_password_jsx__WEBPACK_IMPORTED_MODULE_1__.default;
|
element = _visible_password_jsx__WEBPACK_IMPORTED_MODULE_1__.default;
|
||||||
@@ -9909,9 +9920,11 @@ class InPlaceEdit extends (react__WEBPACK_IMPORTED_MODULE_0___default().Componen
|
|||||||
element = 'textarea';
|
element = 'textarea';
|
||||||
attr.rows = this.props.multiline;
|
attr.rows = this.props.multiline;
|
||||||
attr.className = 'inplace-edit';
|
attr.className = 'inplace-edit';
|
||||||
|
value = this.state.value;
|
||||||
} else {
|
} else {
|
||||||
element = 'input';
|
element = 'input';
|
||||||
attr.type = this.props.type || 'text';
|
attr.type = this.props.type || 'text';
|
||||||
|
attr.value = this.state.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
attr.onChange = this.handeTextChange;
|
attr.onChange = this.handeTextChange;
|
||||||
@@ -9924,7 +9937,7 @@ class InPlaceEdit extends (react__WEBPACK_IMPORTED_MODULE_0___default().Componen
|
|||||||
attr.autoComplete = this.props.autoComplete;
|
attr.autoComplete = this.props.autoComplete;
|
||||||
attr.autoFocus = true;
|
attr.autoFocus = true;
|
||||||
attr.ref = this.selfRef;
|
attr.ref = this.selfRef;
|
||||||
return react__WEBPACK_IMPORTED_MODULE_0___default().createElement(element, attr, null);
|
return react__WEBPACK_IMPORTED_MODULE_0___default().createElement(element, attr, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -11600,6 +11613,8 @@ class TopicDescEdit extends (react__WEBPACK_IMPORTED_MODULE_0___default().Compon
|
|||||||
isMe: tinode_sdk__WEBPACK_IMPORTED_MODULE_2___default().isMeTopicName(this.props.topic),
|
isMe: tinode_sdk__WEBPACK_IMPORTED_MODULE_2___default().isMeTopicName(this.props.topic),
|
||||||
owner: acs && acs.isOwner(),
|
owner: acs && acs.isOwner(),
|
||||||
fullName: topic.public ? topic.public.fn : undefined,
|
fullName: topic.public ? topic.public.fn : undefined,
|
||||||
|
private: topic.private ? topic.private.comment : null,
|
||||||
|
description: topic.public ? topic.public.note : undefined,
|
||||||
avatar: (0,_lib_blob_helpers_js__WEBPACK_IMPORTED_MODULE_8__.makeImageUrl)(topic.public ? topic.public.photo : null),
|
avatar: (0,_lib_blob_helpers_js__WEBPACK_IMPORTED_MODULE_8__.makeImageUrl)(topic.public ? topic.public.photo : null),
|
||||||
tags: topic.tags(),
|
tags: topic.tags(),
|
||||||
newAvatar: null,
|
newAvatar: null,
|
||||||
@@ -11610,6 +11625,8 @@ class TopicDescEdit extends (react__WEBPACK_IMPORTED_MODULE_0___default().Compon
|
|||||||
this.handleFullNameUpdate = this.handleFullNameUpdate.bind(this);
|
this.handleFullNameUpdate = this.handleFullNameUpdate.bind(this);
|
||||||
this.handleImageUpdated = this.handleImageUpdated.bind(this);
|
this.handleImageUpdated = this.handleImageUpdated.bind(this);
|
||||||
this.handleAvatarCropped = this.handleAvatarCropped.bind(this);
|
this.handleAvatarCropped = this.handleAvatarCropped.bind(this);
|
||||||
|
this.handlePrivateUpdate = this.handlePrivateUpdate.bind(this);
|
||||||
|
this.handleDescriptionUpdate = this.handleDescriptionUpdate.bind(this);
|
||||||
this.uploadAvatar = this.uploadAvatar.bind(this);
|
this.uploadAvatar = this.uploadAvatar.bind(this);
|
||||||
this.handleAvatarCropCancel = this.handleAvatarCropCancel.bind(this);
|
this.handleAvatarCropCancel = this.handleAvatarCropCancel.bind(this);
|
||||||
this.handleTagsUpdated = this.handleTagsUpdated.bind(this);
|
this.handleTagsUpdated = this.handleTagsUpdated.bind(this);
|
||||||
@@ -11634,7 +11651,7 @@ class TopicDescEdit extends (react__WEBPACK_IMPORTED_MODULE_0___default().Compon
|
|||||||
handleFullNameUpdate(fn) {
|
handleFullNameUpdate(fn) {
|
||||||
fn = fn.trim().substring(0, _config_js__WEBPACK_IMPORTED_MODULE_7__.MAX_TITLE_LENGTH);
|
fn = fn.trim().substring(0, _config_js__WEBPACK_IMPORTED_MODULE_7__.MAX_TITLE_LENGTH);
|
||||||
|
|
||||||
if (fn) {
|
if (fn && this.state.fullName !== fn) {
|
||||||
this.setState({
|
this.setState({
|
||||||
fullName: fn
|
fullName: fn
|
||||||
});
|
});
|
||||||
@@ -11642,6 +11659,28 @@ class TopicDescEdit extends (react__WEBPACK_IMPORTED_MODULE_0___default().Compon
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handlePrivateUpdate(comment) {
|
||||||
|
comment = comment.trim().substring(0, _config_js__WEBPACK_IMPORTED_MODULE_7__.MAX_TITLE_LENGTH);
|
||||||
|
|
||||||
|
if (this.state.private !== comment) {
|
||||||
|
this.setState({
|
||||||
|
private: comment
|
||||||
|
});
|
||||||
|
this.props.onTopicDescUpdate(this.props.topic, null, comment || (tinode_sdk__WEBPACK_IMPORTED_MODULE_2___default().DEL_CHAR));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
handleDescriptionUpdate(desc) {
|
||||||
|
desc = desc.trim().substring(0, _config_js__WEBPACK_IMPORTED_MODULE_7__.MAX_TOPIC_DESCRIPTION_LENGTH);
|
||||||
|
|
||||||
|
if (desc) {
|
||||||
|
this.setState({
|
||||||
|
description: desc
|
||||||
|
});
|
||||||
|
this.props.onUpdateTopicDesc(this.props.topic, (0,_lib_utils_js__WEBPACK_IMPORTED_MODULE_9__.theCard)(null, null, null, desc));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
handleImageUpdated(mime, img) {
|
handleImageUpdated(mime, img) {
|
||||||
this.setState({
|
this.setState({
|
||||||
newAvatar: img,
|
newAvatar: img,
|
||||||
@@ -11739,6 +11778,8 @@ class TopicDescEdit extends (react__WEBPACK_IMPORTED_MODULE_0___default().Compon
|
|||||||
|
|
||||||
const editable = this.state.isMe || this.state.owner;
|
const editable = this.state.isMe || this.state.owner;
|
||||||
return react__WEBPACK_IMPORTED_MODULE_0___default().createElement((react__WEBPACK_IMPORTED_MODULE_0___default().Fragment), null, react__WEBPACK_IMPORTED_MODULE_0___default().createElement("div", {
|
return react__WEBPACK_IMPORTED_MODULE_0___default().createElement((react__WEBPACK_IMPORTED_MODULE_0___default().Fragment), null, react__WEBPACK_IMPORTED_MODULE_0___default().createElement("div", {
|
||||||
|
className: "panel-form-column"
|
||||||
|
}, react__WEBPACK_IMPORTED_MODULE_0___default().createElement("div", {
|
||||||
className: "panel-form-row"
|
className: "panel-form-row"
|
||||||
}, react__WEBPACK_IMPORTED_MODULE_0___default().createElement("div", {
|
}, react__WEBPACK_IMPORTED_MODULE_0___default().createElement("div", {
|
||||||
className: "panel-form-column"
|
className: "panel-form-column"
|
||||||
@@ -11801,9 +11842,7 @@ class TopicDescEdit extends (react__WEBPACK_IMPORTED_MODULE_0___default().Compon
|
|||||||
title: this.state.fullName,
|
title: this.state.fullName,
|
||||||
onImageUpdated: this.handleImageUpdated,
|
onImageUpdated: this.handleImageUpdated,
|
||||||
onError: this.props.onError
|
onError: this.props.onError
|
||||||
})), react__WEBPACK_IMPORTED_MODULE_0___default().createElement("div", {
|
})), react__WEBPACK_IMPORTED_MODULE_0___default().createElement("div", null, react__WEBPACK_IMPORTED_MODULE_0___default().createElement("label", {
|
||||||
className: "panel-form-column"
|
|
||||||
}, react__WEBPACK_IMPORTED_MODULE_0___default().createElement("div", null, react__WEBPACK_IMPORTED_MODULE_0___default().createElement("label", {
|
|
||||||
className: "small"
|
className: "small"
|
||||||
}, react__WEBPACK_IMPORTED_MODULE_0___default().createElement(react_intl__WEBPACK_IMPORTED_MODULE_1__.FormattedMessage, {
|
}, react__WEBPACK_IMPORTED_MODULE_0___default().createElement(react_intl__WEBPACK_IMPORTED_MODULE_1__.FormattedMessage, {
|
||||||
id: "label_description",
|
id: "label_description",
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user