adding support for out of band avatars
This commit is contained in:
@@ -6,10 +6,15 @@ import { bytesToHumanSize } from './strformat.js'
|
|||||||
export const SUPPORTED_IMAGE_FORMATS = ['image/jpeg', 'image/gif', 'image/png', 'image/svg', 'image/svg+xml'];
|
export const SUPPORTED_IMAGE_FORMATS = ['image/jpeg', 'image/gif', 'image/png', 'image/svg', 'image/svg+xml'];
|
||||||
export const MIME_EXTENSIONS = ['jpg', 'gif', 'png', 'svg', 'svg'];
|
export const MIME_EXTENSIONS = ['jpg', 'gif', 'png', 'svg', 'svg'];
|
||||||
|
|
||||||
// Make a data URL from public.photo
|
// Make a data: URL from public.photo
|
||||||
export function makeImageUrl(photo) {
|
export function makeImageDataUrl(photo) {
|
||||||
return (photo && photo.type && photo.data) ?
|
if (photo) {
|
||||||
'data:image/' + photo.type + ';base64,' + photo.data : null;
|
if (photo.data && photo.type) {
|
||||||
|
return 'data:image/' + photo.type + ';base64,' + photo.data;
|
||||||
|
}
|
||||||
|
return photo.ref;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculate linear dimensions for scaling image down to fit under a certain size.
|
// Calculate linear dimensions for scaling image down to fit under a certain size.
|
||||||
|
|||||||
+26
-14
@@ -19,23 +19,35 @@ export function updateFavicon(count) {
|
|||||||
document.title = (count > 0 ? '('+count+') ' : '') + 'Tinode';
|
document.title = (count > 0 ? '('+count+') ' : '') + 'Tinode';
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create theCard which represents topic 'public' info.
|
// Create theCard which represents user's or topic's "public" info.
|
||||||
export function theCard(fn, imageDataUrl) {
|
export function theCard(fn, imageUrl, imageMimeType) {
|
||||||
let card = null;
|
let card = null;
|
||||||
|
fn = fn && fn.trim();
|
||||||
|
|
||||||
if ((fn && fn.trim()) || imageDataUrl) {
|
if (fn) {
|
||||||
card = {};
|
card = {
|
||||||
if (fn) {
|
fn: fn
|
||||||
card.fn = fn.trim();
|
};
|
||||||
}
|
|
||||||
if (imageDataUrl) {
|
|
||||||
const dataStart = imageDataUrl.indexOf(',');
|
|
||||||
card.photo = dataStart >= 0 ? {
|
|
||||||
data: imageDataUrl.substring(dataStart+1),
|
|
||||||
type: 'jpg'
|
|
||||||
} : imageDataUrl;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (imageUrl) {
|
||||||
|
card = card || {};
|
||||||
|
let mimeType = imageMimeType;
|
||||||
|
// Is this a data URL "data:[<mediatype>][;base64],<data>"?
|
||||||
|
const matches = /^data:(image\/[-a-z0-9+.]+)(;base64)?,/i.exec(imageUrl);
|
||||||
|
if (matches) {
|
||||||
|
mimeType = matches[1];
|
||||||
|
card.photo = {
|
||||||
|
data: imageUrl.substring(imageUrl.indexOf(',') + 1)
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
card.photo = {
|
||||||
|
ref: imageUrl
|
||||||
|
};
|
||||||
|
}
|
||||||
|
card.photo.type = (mimeType || 'image/jpeg').substring('image/'.length);
|
||||||
|
}
|
||||||
|
|
||||||
return card;
|
return card;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import InPlaceEdit from '../widgets/in-place-edit.jsx';
|
|||||||
import TagManager from '../widgets/tag-manager.jsx';
|
import TagManager from '../widgets/tag-manager.jsx';
|
||||||
|
|
||||||
import { MAX_TITLE_LENGTH } from '../config.js';
|
import { MAX_TITLE_LENGTH } from '../config.js';
|
||||||
import { makeImageUrl } from '../lib/blob-helpers.js';
|
import { makeImageDataUrl } from '../lib/blob-helpers.js';
|
||||||
import { arrayEqual, asEmail, asPhone, theCard } from '../lib/utils.js';
|
import { arrayEqual, asEmail, asPhone, theCard } from '../lib/utils.js';
|
||||||
|
|
||||||
export default class AccGeneralView extends React.Component {
|
export default class AccGeneralView extends React.Component {
|
||||||
@@ -19,7 +19,7 @@ export default class AccGeneralView extends React.Component {
|
|||||||
const me = this.props.tinode.getMeTopic();
|
const me = this.props.tinode.getMeTopic();
|
||||||
this.state = {
|
this.state = {
|
||||||
fullName: me.public ? me.public.fn : undefined,
|
fullName: me.public ? me.public.fn : undefined,
|
||||||
avatar: makeImageUrl(me.public ? me.public.photo : null),
|
avatar: makeImageDataUrl(me.public ? me.public.photo : null),
|
||||||
tags: me.tags(),
|
tags: me.tags(),
|
||||||
credentials: me.getCredentials() || [],
|
credentials: me.getCredentials() || [],
|
||||||
addCredActive: false,
|
addCredActive: false,
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { FormattedMessage } from 'react-intl';
|
|||||||
|
|
||||||
import AvatarUpload from '../widgets/avatar-upload.jsx';
|
import AvatarUpload from '../widgets/avatar-upload.jsx';
|
||||||
|
|
||||||
import { makeImageUrl } from '../lib/blob-helpers.js';
|
import { makeImageDataUrl } from '../lib/blob-helpers.js';
|
||||||
|
|
||||||
export default class EditAccountView extends React.Component {
|
export default class EditAccountView extends React.Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
@@ -13,7 +13,7 @@ export default class EditAccountView extends React.Component {
|
|||||||
const me = this.props.tinode.getMeTopic();
|
const me = this.props.tinode.getMeTopic();
|
||||||
this.state = {
|
this.state = {
|
||||||
fullName: me.public ? me.public.fn : undefined,
|
fullName: me.public ? me.public.fn : undefined,
|
||||||
avatar: makeImageUrl(me.public ? me.public.photo : null)
|
avatar: makeImageDataUrl(me.public ? me.public.photo : null)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ import TagManager from '../widgets/tag-manager.jsx';
|
|||||||
|
|
||||||
import { MAX_TITLE_LENGTH, NO_ACCESS_MODE } from '../config.js';
|
import { MAX_TITLE_LENGTH, NO_ACCESS_MODE } from '../config.js';
|
||||||
|
|
||||||
import { makeImageUrl } from '../lib/blob-helpers.js';
|
import { makeImageDataUrl } from '../lib/blob-helpers.js';
|
||||||
import { arrayEqual, theCard } from '../lib/utils.js';
|
import { arrayEqual, theCard } from '../lib/utils.js';
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
@@ -227,7 +227,7 @@ class InfoView extends React.Component {
|
|||||||
muted: acs && acs.isMuted(),
|
muted: acs && acs.isMuted(),
|
||||||
|
|
||||||
fullName: topic.public ? topic.public.fn : undefined,
|
fullName: topic.public ? topic.public.fn : undefined,
|
||||||
avatar: makeImageUrl(topic.public ? topic.public.photo : null),
|
avatar: makeImageDataUrl(topic.public ? topic.public.photo : null),
|
||||||
private: topic.private ? topic.private.comment : null,
|
private: topic.private ? topic.private.comment : null,
|
||||||
address: topic.name,
|
address: topic.name,
|
||||||
groupTopic: topic.isGroupType(),
|
groupTopic: topic.isGroupType(),
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ import SendMessage from '../widgets/send-message.jsx';
|
|||||||
import { DEFAULT_P2P_ACCESS_MODE, IMAGE_PREVIEW_DIM, KEYPRESS_DELAY, MESSAGES_PAGE,
|
import { DEFAULT_P2P_ACCESS_MODE, IMAGE_PREVIEW_DIM, KEYPRESS_DELAY, MESSAGES_PAGE,
|
||||||
MAX_EXTERN_ATTACHMENT_SIZE, MAX_IMAGE_DIM, MAX_INBAND_ATTACHMENT_SIZE, READ_DELAY } from '../config.js';
|
MAX_EXTERN_ATTACHMENT_SIZE, MAX_IMAGE_DIM, MAX_INBAND_ATTACHMENT_SIZE, READ_DELAY } from '../config.js';
|
||||||
import { SUPPORTED_IMAGE_FORMATS, blobToBase64, filePasted, fileToBase64,
|
import { SUPPORTED_IMAGE_FORMATS, blobToBase64, filePasted, fileToBase64,
|
||||||
imageScaled, makeImageUrl } from '../lib/blob-helpers.js';
|
imageScaled, makeImageDataUrl } from '../lib/blob-helpers.js';
|
||||||
import HashNavigation from '../lib/navigation.js';
|
import HashNavigation from '../lib/navigation.js';
|
||||||
import { bytesToHumanSize, shortDateFormat } from '../lib/strformat.js';
|
import { bytesToHumanSize, shortDateFormat } from '../lib/strformat.js';
|
||||||
|
|
||||||
@@ -261,7 +261,7 @@ class MessagesView extends React.Component {
|
|||||||
if (topic.public) {
|
if (topic.public) {
|
||||||
Object.assign(nextState, {
|
Object.assign(nextState, {
|
||||||
title: topic.public.fn,
|
title: topic.public.fn,
|
||||||
avatar: makeImageUrl(topic.public.photo)
|
avatar: makeImageDataUrl(topic.public.photo)
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
Object.assign(nextState, {
|
Object.assign(nextState, {
|
||||||
@@ -391,7 +391,7 @@ class MessagesView extends React.Component {
|
|||||||
if (desc.public) {
|
if (desc.public) {
|
||||||
this.setState({
|
this.setState({
|
||||||
title: desc.public.fn,
|
title: desc.public.fn,
|
||||||
avatar: makeImageUrl(desc.public.photo)
|
avatar: makeImageDataUrl(desc.public.photo)
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
this.setState({
|
this.setState({
|
||||||
@@ -856,7 +856,7 @@ class MessagesView extends React.Component {
|
|||||||
const user = topic.userDesc(thisFrom);
|
const user = topic.userDesc(thisFrom);
|
||||||
if (user && user.public) {
|
if (user && user.public) {
|
||||||
userName = user.public.fn;
|
userName = user.public.fn;
|
||||||
userAvatar = makeImageUrl(user.public.photo);
|
userAvatar = makeImageDataUrl(user.public.photo);
|
||||||
}
|
}
|
||||||
userFrom = thisFrom;
|
userFrom = thisFrom;
|
||||||
chatBoxClass='chat-box group';
|
chatBoxClass='chat-box group';
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ import SidepanelView from './sidepanel-view.jsx';
|
|||||||
import { API_KEY, APP_NAME, DEFAULT_P2P_ACCESS_MODE, LOGGING_ENABLED,
|
import { API_KEY, APP_NAME, DEFAULT_P2P_ACCESS_MODE, LOGGING_ENABLED,
|
||||||
MEDIA_BREAKPOINT, RECEIVED_DELAY } from '../config.js';
|
MEDIA_BREAKPOINT, RECEIVED_DELAY } from '../config.js';
|
||||||
import { PACKAGE_VERSION } from '../version.js';
|
import { PACKAGE_VERSION } from '../version.js';
|
||||||
import { base64ReEncode, makeImageUrl } from '../lib/blob-helpers.js';
|
import { base64ReEncode, makeImageDataUrl } from '../lib/blob-helpers.js';
|
||||||
import { detectServerAddress, isLocalHost, isSecureConnection } from '../lib/host-name.js';
|
import { detectServerAddress, isLocalHost, isSecureConnection } from '../lib/host-name.js';
|
||||||
import LocalStorageUtil from '../lib/local-storage.js';
|
import LocalStorageUtil from '../lib/local-storage.js';
|
||||||
import HashNavigation from '../lib/navigation.js';
|
import HashNavigation from '../lib/navigation.js';
|
||||||
@@ -641,7 +641,7 @@ class TinodeWeb extends React.Component {
|
|||||||
if (desc.public) {
|
if (desc.public) {
|
||||||
this.setState({
|
this.setState({
|
||||||
sidePanelTitle: desc.public.fn,
|
sidePanelTitle: desc.public.fn,
|
||||||
sidePanelAvatar: makeImageUrl(desc.public.photo)
|
sidePanelAvatar: makeImageDataUrl(desc.public.photo)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (desc.acs) {
|
if (desc.acs) {
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import React from 'react';
|
|||||||
import LetterTile from './letter-tile.jsx';
|
import LetterTile from './letter-tile.jsx';
|
||||||
|
|
||||||
import { AVATAR_SIZE, MAX_EXTERN_ATTACHMENT_SIZE } from '../config.js';
|
import { AVATAR_SIZE, MAX_EXTERN_ATTACHMENT_SIZE } from '../config.js';
|
||||||
import { imageScaled, blobToBase64, makeImageUrl } from '../lib/blob-helpers.js';
|
import { imageScaled, blobToBase64, makeImageDataUrl } from '../lib/blob-helpers.js';
|
||||||
|
|
||||||
export default class AvatarUpload extends React.Component {
|
export default class AvatarUpload extends React.Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
@@ -28,7 +28,7 @@ export default class AvatarUpload extends React.Component {
|
|||||||
(mime, blob) => {
|
(mime, blob) => {
|
||||||
// Convert blob to base64-encoded bits.
|
// Convert blob to base64-encoded bits.
|
||||||
blobToBase64(blob, (unused, base64bits) => {
|
blobToBase64(blob, (unused, base64bits) => {
|
||||||
const du = makeImageUrl({data: base64bits, type: mime});
|
const du = makeImageDataUrl({data: base64bits, type: mime});
|
||||||
this.setState({dataUrl: du});
|
this.setState({dataUrl: du});
|
||||||
this.props.onImageChanged(du);
|
this.props.onImageChanged(du);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import React from 'react';
|
|||||||
|
|
||||||
import Chip from './chip.jsx';
|
import Chip from './chip.jsx';
|
||||||
|
|
||||||
import { makeImageUrl } from '../lib/blob-helpers.js';
|
import { makeImageDataUrl } from '../lib/blob-helpers.js';
|
||||||
|
|
||||||
/* BEGIN ChipInput: group membership widget */
|
/* BEGIN ChipInput: group membership widget */
|
||||||
export default class ChipInput extends React.Component {
|
export default class ChipInput extends React.Component {
|
||||||
@@ -119,7 +119,7 @@ export default class ChipInput extends React.Component {
|
|||||||
chips.push(
|
chips.push(
|
||||||
<Chip
|
<Chip
|
||||||
onCancel={this.handleChipCancel}
|
onCancel={this.handleChipCancel}
|
||||||
avatar={makeImageUrl(item.public ? item.public.photo : null)}
|
avatar={makeImageDataUrl(item.public ? item.public.photo : null)}
|
||||||
title={item.public ? item.public.fn : undefined}
|
title={item.public ? item.public.fn : undefined}
|
||||||
noAvatar={this.props.avatarDisabled}
|
noAvatar={this.props.avatarDisabled}
|
||||||
topic={item.user}
|
topic={item.user}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import Tinode from 'tinode-sdk';
|
|||||||
import Contact from './contact.jsx';
|
import Contact from './contact.jsx';
|
||||||
import ContactAction from './contact-action.jsx';
|
import ContactAction from './contact-action.jsx';
|
||||||
|
|
||||||
import { makeImageUrl } from '../lib/blob-helpers.js';
|
import { makeImageDataUrl } from '../lib/blob-helpers.js';
|
||||||
|
|
||||||
import { MESSAGE_PREVIEW_LENGTH } from '../config.js';
|
import { MESSAGE_PREVIEW_LENGTH } from '../config.js';
|
||||||
|
|
||||||
@@ -90,7 +90,7 @@ class ContactList extends React.Component {
|
|||||||
contactNodes.push(
|
contactNodes.push(
|
||||||
<Contact
|
<Contact
|
||||||
title={c.public ? c.public.fn : null}
|
title={c.public ? c.public.fn : null}
|
||||||
avatar={makeImageUrl(c.public ? c.public.photo : null)}
|
avatar={makeImageDataUrl(c.public ? c.public.photo : null)}
|
||||||
comment={comment}
|
comment={comment}
|
||||||
preview={preview}
|
preview={preview}
|
||||||
received={deliveryStatus}
|
received={deliveryStatus}
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import { FormattedMessage } from 'react-intl';
|
|||||||
import { MAX_ONLINE_IN_TOPIC } from '../config.js'
|
import { MAX_ONLINE_IN_TOPIC } from '../config.js'
|
||||||
|
|
||||||
import LetterTile from './letter-tile.jsx';
|
import LetterTile from './letter-tile.jsx';
|
||||||
import { makeImageUrl } from '../lib/blob-helpers.js';
|
import { makeImageDataUrl } from '../lib/blob-helpers.js';
|
||||||
|
|
||||||
export default class GroupSubs extends React.Component {
|
export default class GroupSubs extends React.Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
@@ -23,7 +23,7 @@ export default class GroupSubs extends React.Component {
|
|||||||
<div className="avatar-box" key={sub.user}>
|
<div className="avatar-box" key={sub.user}>
|
||||||
<LetterTile
|
<LetterTile
|
||||||
topic={sub.user}
|
topic={sub.user}
|
||||||
avatar={makeImageUrl(sub.public ? sub.public.photo : null) || true}
|
avatar={makeImageDataUrl(sub.public ? sub.public.photo : null) || true}
|
||||||
title={sub.public ? sub.public.fn : null} />
|
title={sub.public ? sub.public.fn : null} />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import { FormattedMessage, defineMessages, injectIntl } from 'react-intl';
|
|||||||
import CheckBox from './checkbox.jsx';
|
import CheckBox from './checkbox.jsx';
|
||||||
import Contact from './contact.jsx';
|
import Contact from './contact.jsx';
|
||||||
|
|
||||||
import { makeImageUrl } from '../lib/blob-helpers.js';
|
import { makeImageDataUrl } from '../lib/blob-helpers.js';
|
||||||
|
|
||||||
// Translatable permission names.
|
// Translatable permission names.
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
@@ -135,7 +135,7 @@ class PermissionsEditor extends React.Component {
|
|||||||
<ul className="contact-box"><Contact
|
<ul className="contact-box"><Contact
|
||||||
item={this.props.item}
|
item={this.props.item}
|
||||||
title={this.props.userTitle}
|
title={this.props.userTitle}
|
||||||
avatar={makeImageUrl(this.props.userAvatar ? this.props.userAvatar : null)} /></ul> : null}
|
avatar={makeImageDataUrl(this.props.userAvatar ? this.props.userAvatar : null)} /></ul> : null}
|
||||||
<label className="small"><FormattedMessage id="title_permissions"
|
<label className="small"><FormattedMessage id="title_permissions"
|
||||||
defaultMessage="Permissions" description="Section title"/></label>
|
defaultMessage="Permissions" description="Section title"/></label>
|
||||||
<table className="permission-editor">
|
<table className="permission-editor">
|
||||||
|
|||||||
+55
-35
@@ -89,7 +89,7 @@ __webpack_require__.r(__webpack_exports__);
|
|||||||
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
||||||
/* harmony export */ "SUPPORTED_IMAGE_FORMATS": function() { return /* binding */ SUPPORTED_IMAGE_FORMATS; },
|
/* harmony export */ "SUPPORTED_IMAGE_FORMATS": function() { return /* binding */ SUPPORTED_IMAGE_FORMATS; },
|
||||||
/* harmony export */ "MIME_EXTENSIONS": function() { return /* binding */ MIME_EXTENSIONS; },
|
/* harmony export */ "MIME_EXTENSIONS": function() { return /* binding */ MIME_EXTENSIONS; },
|
||||||
/* harmony export */ "makeImageUrl": function() { return /* binding */ makeImageUrl; },
|
/* harmony export */ "makeImageDataUrl": function() { return /* binding */ makeImageDataUrl; },
|
||||||
/* harmony export */ "fitImageSize": function() { return /* binding */ fitImageSize; },
|
/* harmony export */ "fitImageSize": function() { return /* binding */ fitImageSize; },
|
||||||
/* harmony export */ "fileNameForMime": function() { return /* binding */ fileNameForMime; },
|
/* harmony export */ "fileNameForMime": function() { return /* binding */ fileNameForMime; },
|
||||||
/* harmony export */ "imageScaled": function() { return /* binding */ imageScaled; },
|
/* harmony export */ "imageScaled": function() { return /* binding */ imageScaled; },
|
||||||
@@ -107,8 +107,16 @@ __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 makeImageDataUrl(photo) {
|
||||||
return photo && photo.type && photo.data ? 'data:image/' + photo.type + ';base64,' + photo.data : null;
|
if (photo) {
|
||||||
|
if (photo.data && photo.type) {
|
||||||
|
return 'data:image/' + photo.type + ';base64,' + photo.data;
|
||||||
|
}
|
||||||
|
|
||||||
|
return photo.ref;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
function fitImageSize(width, height, maxWidth, maxHeight, forceSquare) {
|
function fitImageSize(width, height, maxWidth, maxHeight, forceSquare) {
|
||||||
width = width | 0;
|
width = width | 0;
|
||||||
@@ -522,7 +530,7 @@ function stringHash(value) {
|
|||||||
__webpack_require__.r(__webpack_exports__);
|
__webpack_require__.r(__webpack_exports__);
|
||||||
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
||||||
/* harmony export */ "updateFavicon": function() { return /* binding */ updateFavicon; },
|
/* harmony export */ "updateFavicon": function() { return /* binding */ updateFavicon; },
|
||||||
/* harmony export */ "vcard": function() { return /* binding */ vcard; },
|
/* harmony export */ "theCard": function() { return /* binding */ theCard; },
|
||||||
/* harmony export */ "arrayEqual": function() { return /* binding */ arrayEqual; },
|
/* harmony export */ "arrayEqual": function() { return /* binding */ arrayEqual; },
|
||||||
/* harmony export */ "asPhone": function() { return /* binding */ asPhone; },
|
/* harmony export */ "asPhone": function() { return /* binding */ asPhone; },
|
||||||
/* harmony export */ "asEmail": function() { return /* binding */ asEmail; },
|
/* harmony export */ "asEmail": function() { return /* binding */ asEmail; },
|
||||||
@@ -550,23 +558,33 @@ function updateFavicon(count) {
|
|||||||
head.appendChild(newIcon);
|
head.appendChild(newIcon);
|
||||||
document.title = (count > 0 ? '(' + count + ') ' : '') + 'Tinode';
|
document.title = (count > 0 ? '(' + count + ') ' : '') + 'Tinode';
|
||||||
}
|
}
|
||||||
function vcard(fn, imageDataUrl) {
|
function theCard(fn, imageUrl, imageMimeType) {
|
||||||
let card = null;
|
let card = null;
|
||||||
|
fn = fn && fn.trim();
|
||||||
|
|
||||||
if (fn && fn.trim() || imageDataUrl) {
|
if (fn) {
|
||||||
card = {};
|
card = {
|
||||||
|
fn: fn
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
if (fn) {
|
if (imageUrl) {
|
||||||
card.fn = fn.trim();
|
card = card || {};
|
||||||
|
let mimeType = imageMimeType;
|
||||||
|
const matches = /^data:(image\/[-a-z0-9+.]+)(;base64)?,/i.exec(imageUrl);
|
||||||
|
|
||||||
|
if (matches) {
|
||||||
|
mimeType = matches[1];
|
||||||
|
card.photo = {
|
||||||
|
data: imageUrl.substring(imageUrl.indexOf(',') + 1)
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
card.photo = {
|
||||||
|
ref: imageUrl
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (imageDataUrl) {
|
card.photo.type = (mimeType || 'image/jpeg').substring('image/'.length);
|
||||||
const dataStart = imageDataUrl.indexOf(',');
|
|
||||||
card.photo = dataStart >= 0 ? {
|
|
||||||
data: imageDataUrl.substring(dataStart + 1),
|
|
||||||
type: 'jpg'
|
|
||||||
} : imageDataUrl;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return card;
|
return card;
|
||||||
@@ -743,7 +761,7 @@ class AccGeneralView extends (react__WEBPACK_IMPORTED_MODULE_0___default().Compo
|
|||||||
const me = this.props.tinode.getMeTopic();
|
const me = this.props.tinode.getMeTopic();
|
||||||
this.state = {
|
this.state = {
|
||||||
fullName: me.public ? me.public.fn : undefined,
|
fullName: me.public ? me.public.fn : undefined,
|
||||||
avatar: (0,_lib_blob_helpers_js__WEBPACK_IMPORTED_MODULE_7__.makeImageUrl)(me.public ? me.public.photo : null),
|
avatar: (0,_lib_blob_helpers_js__WEBPACK_IMPORTED_MODULE_7__.makeImageDataUrl)(me.public ? me.public.photo : null),
|
||||||
tags: me.tags(),
|
tags: me.tags(),
|
||||||
credentials: me.getCredentials() || [],
|
credentials: me.getCredentials() || [],
|
||||||
addCredActive: false,
|
addCredActive: false,
|
||||||
@@ -792,7 +810,7 @@ class AccGeneralView extends (react__WEBPACK_IMPORTED_MODULE_0___default().Compo
|
|||||||
this.setState({
|
this.setState({
|
||||||
fullName: fn
|
fullName: fn
|
||||||
});
|
});
|
||||||
this.props.onUpdateAccount(undefined, (0,_lib_utils_js__WEBPACK_IMPORTED_MODULE_8__.vcard)(fn, null));
|
this.props.onUpdateAccount(undefined, (0,_lib_utils_js__WEBPACK_IMPORTED_MODULE_8__.theCard)(fn, null));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -800,7 +818,7 @@ class AccGeneralView extends (react__WEBPACK_IMPORTED_MODULE_0___default().Compo
|
|||||||
this.setState({
|
this.setState({
|
||||||
avatar: img
|
avatar: img
|
||||||
});
|
});
|
||||||
this.props.onUpdateAccount(undefined, (0,_lib_utils_js__WEBPACK_IMPORTED_MODULE_8__.vcard)(null, img || (tinode_sdk__WEBPACK_IMPORTED_MODULE_2___default().DEL_CHAR)));
|
this.props.onUpdateAccount(undefined, (0,_lib_utils_js__WEBPACK_IMPORTED_MODULE_8__.theCard)(null, img || (tinode_sdk__WEBPACK_IMPORTED_MODULE_2___default().DEL_CHAR)));
|
||||||
}
|
}
|
||||||
|
|
||||||
handleCredChange(e) {
|
handleCredChange(e) {
|
||||||
@@ -1640,7 +1658,7 @@ class CreateAccountView extends (react__WEBPACK_IMPORTED_MODULE_0___default().Pu
|
|||||||
this.setState({
|
this.setState({
|
||||||
errorCleared: false
|
errorCleared: false
|
||||||
});
|
});
|
||||||
this.props.onCreateAccount(this.state.login.trim(), this.state.password.trim(), (0,_lib_utils_js__WEBPACK_IMPORTED_MODULE_6__.vcard)(this.state.fn.trim().substring(0, _config_js__WEBPACK_IMPORTED_MODULE_7__.MAX_TITLE_LENGTH), this.state.imageDataUrl), {
|
this.props.onCreateAccount(this.state.login.trim(), this.state.password.trim(), (0,_lib_utils_js__WEBPACK_IMPORTED_MODULE_6__.theCard)(this.state.fn.trim().substring(0, _config_js__WEBPACK_IMPORTED_MODULE_7__.MAX_TITLE_LENGTH), this.state.imageDataUrl), {
|
||||||
'meth': 'email',
|
'meth': 'email',
|
||||||
'val': this.state.email
|
'val': this.state.email
|
||||||
});
|
});
|
||||||
@@ -1779,7 +1797,7 @@ class EditAccountView extends (react__WEBPACK_IMPORTED_MODULE_0___default().Comp
|
|||||||
const me = this.props.tinode.getMeTopic();
|
const me = this.props.tinode.getMeTopic();
|
||||||
this.state = {
|
this.state = {
|
||||||
fullName: me.public ? me.public.fn : undefined,
|
fullName: me.public ? me.public.fn : undefined,
|
||||||
avatar: (0,_lib_blob_helpers_js__WEBPACK_IMPORTED_MODULE_3__.makeImageUrl)(me.public ? me.public.photo : null)
|
avatar: (0,_lib_blob_helpers_js__WEBPACK_IMPORTED_MODULE_3__.makeImageDataUrl)(me.public ? me.public.photo : null)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2167,7 +2185,7 @@ class InfoView extends (react__WEBPACK_IMPORTED_MODULE_0___default().Component)
|
|||||||
deleter: acs && acs.isDeleter(),
|
deleter: acs && acs.isDeleter(),
|
||||||
muted: acs && acs.isMuted(),
|
muted: acs && acs.isMuted(),
|
||||||
fullName: topic.public ? topic.public.fn : undefined,
|
fullName: topic.public ? topic.public.fn : undefined,
|
||||||
avatar: (0,_lib_blob_helpers_js__WEBPACK_IMPORTED_MODULE_14__.makeImageUrl)(topic.public ? topic.public.photo : null),
|
avatar: (0,_lib_blob_helpers_js__WEBPACK_IMPORTED_MODULE_14__.makeImageDataUrl)(topic.public ? topic.public.photo : null),
|
||||||
private: topic.private ? topic.private.comment : null,
|
private: topic.private ? topic.private.comment : null,
|
||||||
address: topic.name,
|
address: topic.name,
|
||||||
groupTopic: topic.isGroupType(),
|
groupTopic: topic.isGroupType(),
|
||||||
@@ -2230,7 +2248,7 @@ class InfoView extends (react__WEBPACK_IMPORTED_MODULE_0___default().Component)
|
|||||||
this.setState({
|
this.setState({
|
||||||
fullName: fn
|
fullName: fn
|
||||||
});
|
});
|
||||||
this.props.onTopicDescUpdate(this.props.topic, (0,_lib_utils_js__WEBPACK_IMPORTED_MODULE_15__.vcard)(fn, null), null);
|
this.props.onTopicDescUpdate(this.props.topic, (0,_lib_utils_js__WEBPACK_IMPORTED_MODULE_15__.theCard)(fn, null), null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2249,7 +2267,7 @@ class InfoView extends (react__WEBPACK_IMPORTED_MODULE_0___default().Component)
|
|||||||
this.setState({
|
this.setState({
|
||||||
avatar: img
|
avatar: img
|
||||||
});
|
});
|
||||||
this.props.onTopicDescUpdate(this.props.topic, (0,_lib_utils_js__WEBPACK_IMPORTED_MODULE_15__.vcard)(null, img || (tinode_sdk__WEBPACK_IMPORTED_MODULE_2___default().DEL_CHAR)), null);
|
this.props.onTopicDescUpdate(this.props.topic, (0,_lib_utils_js__WEBPACK_IMPORTED_MODULE_15__.theCard)(null, img || (tinode_sdk__WEBPACK_IMPORTED_MODULE_2___default().DEL_CHAR)), null);
|
||||||
}
|
}
|
||||||
|
|
||||||
handleMuted(ignored, checked) {
|
handleMuted(ignored, checked) {
|
||||||
@@ -3260,7 +3278,7 @@ class MessagesView extends (react__WEBPACK_IMPORTED_MODULE_0___default().Compone
|
|||||||
if (topic.public) {
|
if (topic.public) {
|
||||||
Object.assign(nextState, {
|
Object.assign(nextState, {
|
||||||
title: topic.public.fn,
|
title: topic.public.fn,
|
||||||
avatar: (0,_lib_blob_helpers_js__WEBPACK_IMPORTED_MODULE_14__.makeImageUrl)(topic.public.photo)
|
avatar: (0,_lib_blob_helpers_js__WEBPACK_IMPORTED_MODULE_14__.makeImageDataUrl)(topic.public.photo)
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
Object.assign(nextState, {
|
Object.assign(nextState, {
|
||||||
@@ -3403,7 +3421,7 @@ class MessagesView extends (react__WEBPACK_IMPORTED_MODULE_0___default().Compone
|
|||||||
if (desc.public) {
|
if (desc.public) {
|
||||||
this.setState({
|
this.setState({
|
||||||
title: desc.public.fn,
|
title: desc.public.fn,
|
||||||
avatar: (0,_lib_blob_helpers_js__WEBPACK_IMPORTED_MODULE_14__.makeImageUrl)(desc.public.photo)
|
avatar: (0,_lib_blob_helpers_js__WEBPACK_IMPORTED_MODULE_14__.makeImageDataUrl)(desc.public.photo)
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
this.setState({
|
this.setState({
|
||||||
@@ -3881,7 +3899,7 @@ class MessagesView extends (react__WEBPACK_IMPORTED_MODULE_0___default().Compone
|
|||||||
|
|
||||||
if (user && user.public) {
|
if (user && user.public) {
|
||||||
userName = user.public.fn;
|
userName = user.public.fn;
|
||||||
userAvatar = (0,_lib_blob_helpers_js__WEBPACK_IMPORTED_MODULE_14__.makeImageUrl)(user.public.photo);
|
userAvatar = (0,_lib_blob_helpers_js__WEBPACK_IMPORTED_MODULE_14__.makeImageDataUrl)(user.public.photo);
|
||||||
}
|
}
|
||||||
|
|
||||||
userFrom = thisFrom;
|
userFrom = thisFrom;
|
||||||
@@ -4131,7 +4149,7 @@ class NewTopicView extends (react__WEBPACK_IMPORTED_MODULE_0___default().Compone
|
|||||||
|
|
||||||
handleNewGroupSubmit(name, dataUrl, priv, tags, isChannel) {
|
handleNewGroupSubmit(name, dataUrl, priv, tags, isChannel) {
|
||||||
_lib_navigation_js__WEBPACK_IMPORTED_MODULE_7__.default.navigateTo(_lib_navigation_js__WEBPACK_IMPORTED_MODULE_7__.default.removeUrlParam(window.location.hash, 'tab'));
|
_lib_navigation_js__WEBPACK_IMPORTED_MODULE_7__.default.navigateTo(_lib_navigation_js__WEBPACK_IMPORTED_MODULE_7__.default.removeUrlParam(window.location.hash, 'tab'));
|
||||||
this.props.onCreateTopic(undefined, (0,_lib_utils_js__WEBPACK_IMPORTED_MODULE_8__.vcard)(name, dataUrl), priv, tags, isChannel);
|
this.props.onCreateTopic(undefined, (0,_lib_utils_js__WEBPACK_IMPORTED_MODULE_8__.theCard)(name, dataUrl), priv, tags, isChannel);
|
||||||
}
|
}
|
||||||
|
|
||||||
handleGroupByID(topicName) {
|
handleGroupByID(topicName) {
|
||||||
@@ -5089,7 +5107,9 @@ class TinodeWeb extends (react__WEBPACK_IMPORTED_MODULE_0___default().Component)
|
|||||||
this.fbPush.onTokenRefresh(() => {
|
this.fbPush.onTokenRefresh(() => {
|
||||||
this.requestPushToken();
|
this.requestPushToken();
|
||||||
});
|
});
|
||||||
this.fbPush.onMessage(this.handlePushMessage);
|
this.fbPush.onMessage(payload => {
|
||||||
|
this.handlePushMessage(payload.data);
|
||||||
|
});
|
||||||
return reg;
|
return reg;
|
||||||
}).catch(err => {
|
}).catch(err => {
|
||||||
onError("Failed to register service worker:", err);
|
onError("Failed to register service worker:", err);
|
||||||
@@ -5418,7 +5438,7 @@ class TinodeWeb extends (react__WEBPACK_IMPORTED_MODULE_0___default().Component)
|
|||||||
if (desc.public) {
|
if (desc.public) {
|
||||||
this.setState({
|
this.setState({
|
||||||
sidePanelTitle: desc.public.fn,
|
sidePanelTitle: desc.public.fn,
|
||||||
sidePanelAvatar: (0,_lib_blob_helpers_js__WEBPACK_IMPORTED_MODULE_13__.makeImageUrl)(desc.public.photo)
|
sidePanelAvatar: (0,_lib_blob_helpers_js__WEBPACK_IMPORTED_MODULE_13__.makeImageDataUrl)(desc.public.photo)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -6839,7 +6859,7 @@ class AvatarUpload extends (react__WEBPACK_IMPORTED_MODULE_0___default().Compone
|
|||||||
handleFileUpload(e) {
|
handleFileUpload(e) {
|
||||||
(0,_lib_blob_helpers_js__WEBPACK_IMPORTED_MODULE_3__.imageScaled)(e.target.files[0], _config_js__WEBPACK_IMPORTED_MODULE_2__.AVATAR_SIZE, _config_js__WEBPACK_IMPORTED_MODULE_2__.AVATAR_SIZE, _config_js__WEBPACK_IMPORTED_MODULE_2__.MAX_EXTERN_ATTACHMENT_SIZE, true, (mime, blob) => {
|
(0,_lib_blob_helpers_js__WEBPACK_IMPORTED_MODULE_3__.imageScaled)(e.target.files[0], _config_js__WEBPACK_IMPORTED_MODULE_2__.AVATAR_SIZE, _config_js__WEBPACK_IMPORTED_MODULE_2__.AVATAR_SIZE, _config_js__WEBPACK_IMPORTED_MODULE_2__.MAX_EXTERN_ATTACHMENT_SIZE, true, (mime, blob) => {
|
||||||
(0,_lib_blob_helpers_js__WEBPACK_IMPORTED_MODULE_3__.blobToBase64)(blob, (unused, base64bits) => {
|
(0,_lib_blob_helpers_js__WEBPACK_IMPORTED_MODULE_3__.blobToBase64)(blob, (unused, base64bits) => {
|
||||||
const du = (0,_lib_blob_helpers_js__WEBPACK_IMPORTED_MODULE_3__.makeImageUrl)({
|
const du = (0,_lib_blob_helpers_js__WEBPACK_IMPORTED_MODULE_3__.makeImageDataUrl)({
|
||||||
data: base64bits,
|
data: base64bits,
|
||||||
type: mime
|
type: mime
|
||||||
});
|
});
|
||||||
@@ -7389,7 +7409,7 @@ class ChipInput extends (react__WEBPACK_IMPORTED_MODULE_0___default().Component)
|
|||||||
this.state.sortedChips.map(item => {
|
this.state.sortedChips.map(item => {
|
||||||
chips.push(react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_chip_jsx__WEBPACK_IMPORTED_MODULE_1__.default, {
|
chips.push(react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_chip_jsx__WEBPACK_IMPORTED_MODULE_1__.default, {
|
||||||
onCancel: this.handleChipCancel,
|
onCancel: this.handleChipCancel,
|
||||||
avatar: (0,_lib_blob_helpers_js__WEBPACK_IMPORTED_MODULE_2__.makeImageUrl)(item.public ? item.public.photo : null),
|
avatar: (0,_lib_blob_helpers_js__WEBPACK_IMPORTED_MODULE_2__.makeImageDataUrl)(item.public ? item.public.photo : null),
|
||||||
title: item.public ? item.public.fn : undefined,
|
title: item.public ? item.public.fn : undefined,
|
||||||
noAvatar: this.props.avatarDisabled,
|
noAvatar: this.props.avatarDisabled,
|
||||||
topic: item.user,
|
topic: item.user,
|
||||||
@@ -7680,7 +7700,7 @@ class ContactList extends (react__WEBPACK_IMPORTED_MODULE_0___default().Componen
|
|||||||
|
|
||||||
contactNodes.push(react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_contact_jsx__WEBPACK_IMPORTED_MODULE_3__.default, {
|
contactNodes.push(react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_contact_jsx__WEBPACK_IMPORTED_MODULE_3__.default, {
|
||||||
title: c.public ? c.public.fn : null,
|
title: c.public ? c.public.fn : null,
|
||||||
avatar: (0,_lib_blob_helpers_js__WEBPACK_IMPORTED_MODULE_5__.makeImageUrl)(c.public ? c.public.photo : null),
|
avatar: (0,_lib_blob_helpers_js__WEBPACK_IMPORTED_MODULE_5__.makeImageDataUrl)(c.public ? c.public.photo : null),
|
||||||
comment: comment,
|
comment: comment,
|
||||||
preview: preview,
|
preview: preview,
|
||||||
received: deliveryStatus,
|
received: deliveryStatus,
|
||||||
@@ -8942,7 +8962,7 @@ class GroupSubs extends (react__WEBPACK_IMPORTED_MODULE_0___default().Component)
|
|||||||
key: sub.user
|
key: sub.user
|
||||||
}, react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_letter_tile_jsx__WEBPACK_IMPORTED_MODULE_3__.default, {
|
}, react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_letter_tile_jsx__WEBPACK_IMPORTED_MODULE_3__.default, {
|
||||||
topic: sub.user,
|
topic: sub.user,
|
||||||
avatar: (0,_lib_blob_helpers_js__WEBPACK_IMPORTED_MODULE_4__.makeImageUrl)(sub.public ? sub.public.photo : null) || true,
|
avatar: (0,_lib_blob_helpers_js__WEBPACK_IMPORTED_MODULE_4__.makeImageDataUrl)(sub.public ? sub.public.photo : null) || true,
|
||||||
title: sub.public ? sub.public.fn : null
|
title: sub.public ? sub.public.fn : null
|
||||||
})));
|
})));
|
||||||
return usersOnline.length == countToShow;
|
return usersOnline.length == countToShow;
|
||||||
@@ -10179,7 +10199,7 @@ class PermissionsEditor extends (react__WEBPACK_IMPORTED_MODULE_0___default().Co
|
|||||||
}, react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_contact_jsx__WEBPACK_IMPORTED_MODULE_3__.default, {
|
}, react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_contact_jsx__WEBPACK_IMPORTED_MODULE_3__.default, {
|
||||||
item: this.props.item,
|
item: this.props.item,
|
||||||
title: this.props.userTitle,
|
title: this.props.userTitle,
|
||||||
avatar: (0,_lib_blob_helpers_js__WEBPACK_IMPORTED_MODULE_4__.makeImageUrl)(this.props.userAvatar ? this.props.userAvatar : null)
|
avatar: (0,_lib_blob_helpers_js__WEBPACK_IMPORTED_MODULE_4__.makeImageDataUrl)(this.props.userAvatar ? this.props.userAvatar : null)
|
||||||
})) : null, react__WEBPACK_IMPORTED_MODULE_0___default().createElement("label", {
|
})) : 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, {
|
||||||
|
|||||||
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