deleting contacts
This commit is contained in:
+11
-1
@@ -199,12 +199,22 @@ input[type="search"]:focus {
|
|||||||
box-shadow: 0 1px 0 rgba(33, 150, 243, 0.25);
|
box-shadow: 0 1px 0 rgba(33, 150, 243, 0.25);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
textarea.invalid,
|
||||||
|
input[type="text"].invalid,
|
||||||
|
input[type="email"].invalid,
|
||||||
|
input[type="password"].invalid,
|
||||||
|
input[type="search"].invalid {
|
||||||
|
border-bottom: 1px solid #e57373;
|
||||||
|
box-shadow: 0 1px 0 rgba(229, 115, 115, 0.25);
|
||||||
|
}
|
||||||
|
|
||||||
input[type="text"]::placeholder,
|
input[type="text"]::placeholder,
|
||||||
input[type="email"]::placeholder,
|
input[type="email"]::placeholder,
|
||||||
input[type="password"]::placeholder,
|
input[type="password"]::placeholder,
|
||||||
input[type="search"]::placeholder,
|
input[type="search"]::placeholder,
|
||||||
textarea::placeholder {
|
textarea::placeholder {
|
||||||
color: #bbb;
|
color: #bbb;
|
||||||
|
font-weight: lighter;
|
||||||
}
|
}
|
||||||
|
|
||||||
input[type="text"].with-visibility,
|
input[type="text"].with-visibility,
|
||||||
@@ -321,7 +331,7 @@ li.right:hover .menuTrigger {
|
|||||||
.hr {
|
.hr {
|
||||||
display: block;
|
display: block;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 0.6rem;
|
height: 0.45rem;
|
||||||
min-height: 0.3rem;
|
min-height: 0.3rem;
|
||||||
background-color: #f0f0f0;
|
background-color: #f0f0f0;
|
||||||
box-shadow: inset 0 0.25rem 0.25rem -0.25rem rgba(0,0,0,0.15),
|
box-shadow: inset 0 0.25rem 0.25rem -0.25rem rgba(0,0,0,0.15),
|
||||||
|
|||||||
Vendored
+1
-1
File diff suppressed because one or more lines are too long
+1
-1
@@ -10,7 +10,7 @@
|
|||||||
"babel-plugin-react-intl": "^3.0.1",
|
"babel-plugin-react-intl": "^3.0.1",
|
||||||
"browserslist": "^4.4.1",
|
"browserslist": "^4.4.1",
|
||||||
"cssnano": "^4.1.10",
|
"cssnano": "^4.1.10",
|
||||||
"postcss": "^7.0.6",
|
"postcss": "^7.0.17",
|
||||||
"uglifyjs-webpack-plugin": "^2.1.2",
|
"uglifyjs-webpack-plugin": "^2.1.2",
|
||||||
"webpack": "^4.29.6",
|
"webpack": "^4.29.6",
|
||||||
"webpack-cli": "^3.2.3"
|
"webpack-cli": "^3.2.3"
|
||||||
|
|||||||
+3
-2
@@ -7,12 +7,13 @@
|
|||||||
"label_your_name": "Your name",
|
"label_your_name": "Your name",
|
||||||
"label_password": "Password",
|
"label_password": "Password",
|
||||||
"password_unchanged_prompt": "Unchanged",
|
"password_unchanged_prompt": "Unchanged",
|
||||||
"label_user_id": "Address:",
|
|
||||||
"label_default_access_mode": "Default access mode:",
|
|
||||||
"label_message_sound": "Message sound:",
|
"label_message_sound": "Message sound:",
|
||||||
"label_push_notifications": "Notification alerts:",
|
"label_push_notifications": "Notification alerts:",
|
||||||
"label_push_notifications_disabled": "Notification alerts (requires HTTPS):",
|
"label_push_notifications_disabled": "Notification alerts (requires HTTPS):",
|
||||||
"title_tag_manager": "Tags (user discovery)",
|
"title_tag_manager": "Tags (user discovery)",
|
||||||
|
"label_user_contacts": "Contacts:",
|
||||||
|
"label_user_id": "Address:",
|
||||||
|
"label_default_access_mode": "Default access mode:",
|
||||||
"button_logout": "Logout",
|
"button_logout": "Logout",
|
||||||
"requested_permissions": "Requested",
|
"requested_permissions": "Requested",
|
||||||
"granted_permissions": "Granted",
|
"granted_permissions": "Granted",
|
||||||
|
|||||||
+2
-1
@@ -132,5 +132,6 @@
|
|||||||
"chat_invitation_block": "Заблокировать",
|
"chat_invitation_block": "Заблокировать",
|
||||||
"peers_messaging_disabled": "Чат заблокирован у корреспондента.",
|
"peers_messaging_disabled": "Чат заблокирован у корреспондента.",
|
||||||
"enable_peers_messaging": "Разблокировать.",
|
"enable_peers_messaging": "Разблокировать.",
|
||||||
"more_online_members": "+еще {overflow}"
|
"more_online_members": "+еще {overflow}",
|
||||||
|
"label_user_contacts": "Конакты"
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-1
@@ -132,5 +132,6 @@
|
|||||||
"tags_not_found": "尚未定义标签。添加一些。",
|
"tags_not_found": "尚未定义标签。添加一些。",
|
||||||
"tags_editor_no_tags": "添加一些标签",
|
"tags_editor_no_tags": "添加一些标签",
|
||||||
"title_manage_tags": "管理标签",
|
"title_manage_tags": "管理标签",
|
||||||
"more_online_members": "还有{overflow}个"
|
"more_online_members": "还有{overflow}个",
|
||||||
|
"label_user_contacts": "往来"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ export function shortDateFormat(then, locale) {
|
|||||||
|
|
||||||
// Convert seconds to minutes:seconds, i.e. 156 sec -> 2:36.
|
// Convert seconds to minutes:seconds, i.e. 156 sec -> 2:36.
|
||||||
export function secondsToTime(seconds) {
|
export function secondsToTime(seconds) {
|
||||||
const min = Math.floor(seconds % 3600 / 60);
|
const min = Math.floor(seconds / 60);
|
||||||
let sec = seconds % 60;
|
let sec = seconds % 60;
|
||||||
sec = sec < 10 ? `0${sec}` : sec;
|
sec = sec < 10 ? `0${sec}` : sec;
|
||||||
return `${min}:${sec}`;
|
return `${min}:${sec}`;
|
||||||
|
|||||||
@@ -61,3 +61,22 @@ export function arrayEqual(a, b) {
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Checks (loosely) if the given string is a phone. If so, returns the phone number in a format
|
||||||
|
// as close to E.164 as possible.
|
||||||
|
export function asPhone(val) {
|
||||||
|
val = val.trim();
|
||||||
|
if (/^\s*(?:\+?(\d{1,3}))?[- (.]*(\d{3})[- ).]*(\d{3})[- .]*(\d{2})[- .]*(\d{2})?\s*$/.test(val)) {
|
||||||
|
return val.replace(/[- ().]*/, '');
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Checks (loosely) if the given string is an email. If so returns the email.
|
||||||
|
export function asEmail(val) {
|
||||||
|
val = val.trim();
|
||||||
|
if (/^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$/.test(val)) {
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|||||||
+5
-3
@@ -8,12 +8,13 @@
|
|||||||
"label_your_name": "Your name",
|
"label_your_name": "Your name",
|
||||||
"label_password": "Password",
|
"label_password": "Password",
|
||||||
"password_unchanged_prompt": "Unchanged",
|
"password_unchanged_prompt": "Unchanged",
|
||||||
"label_user_id": "Address:",
|
|
||||||
"label_default_access_mode": "Default access mode:",
|
|
||||||
"label_message_sound": "Message sound:",
|
"label_message_sound": "Message sound:",
|
||||||
"label_push_notifications": "Notification alerts:",
|
"label_push_notifications": "Notification alerts:",
|
||||||
"label_push_notifications_disabled": "Notification alerts (requires HTTPS):",
|
"label_push_notifications_disabled": "Notification alerts (requires HTTPS):",
|
||||||
"title_tag_manager": "Tags (user discovery)",
|
"title_tag_manager": "Tags (user discovery)",
|
||||||
|
"label_user_contacts": "Contacts:",
|
||||||
|
"label_user_id": "Address:",
|
||||||
|
"label_default_access_mode": "Default access mode:",
|
||||||
"button_logout": "Logout",
|
"button_logout": "Logout",
|
||||||
"requested_permissions": "Requested",
|
"requested_permissions": "Requested",
|
||||||
"granted_permissions": "Granted",
|
"granted_permissions": "Granted",
|
||||||
@@ -269,7 +270,8 @@
|
|||||||
"chat_invitation_block": "Заблокировать",
|
"chat_invitation_block": "Заблокировать",
|
||||||
"peers_messaging_disabled": "Чат заблокирован у корреспондента.",
|
"peers_messaging_disabled": "Чат заблокирован у корреспондента.",
|
||||||
"enable_peers_messaging": "Разблокировать.",
|
"enable_peers_messaging": "Разблокировать.",
|
||||||
"more_online_members": "+еще {overflow}"
|
"more_online_members": "+еще {overflow}",
|
||||||
|
"label_user_contacts": "Конакты"
|
||||||
},
|
},
|
||||||
"zh-CN": {
|
"zh-CN": {
|
||||||
"archived_contacts": "已归档联系人 ({count})",
|
"archived_contacts": "已归档联系人 ({count})",
|
||||||
|
|||||||
+121
-45
@@ -10,31 +10,38 @@ import PermissionsEditor from '../widgets/permissions-editor.jsx';
|
|||||||
import TagManager from '../widgets/tag-manager.jsx';
|
import TagManager from '../widgets/tag-manager.jsx';
|
||||||
|
|
||||||
import { makeImageUrl } from '../lib/blob-helpers.js';
|
import { makeImageUrl } from '../lib/blob-helpers.js';
|
||||||
import { arrayEqual, vcard } from '../lib/utils.js';
|
import { arrayEqual, asEmail, asPhone, vcard } from '../lib/utils.js';
|
||||||
|
|
||||||
export default class EditAccountView extends React.Component {
|
export default class EditAccountView extends React.Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
|
|
||||||
const me = this.props.tinode.getMeTopic();
|
const me = this.props.tinode.getMeTopic();
|
||||||
const defacs = me ? me.getDefaultAccess() : null;
|
const defacs = me.getDefaultAccess();
|
||||||
const fnd = this.props.tinode.getFndTopic();
|
|
||||||
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: makeImageUrl(me.public ? me.public.photo : null),
|
||||||
auth: defacs ? defacs.auth : null,
|
auth: defacs ? defacs.auth : null,
|
||||||
anon: defacs ? defacs.anon : null,
|
anon: defacs ? defacs.anon : null,
|
||||||
fndSubscribed: false,
|
tags: me.tags(),
|
||||||
tags: fnd.tags(),
|
credentials: me.getCredentials() || [],
|
||||||
|
addCredActive: false,
|
||||||
|
addCredInvalid: false,
|
||||||
|
newCred: '',
|
||||||
showPermissionEditorFor: undefined,
|
showPermissionEditorFor: undefined,
|
||||||
previousOnTags: fnd.onTagsUpdated
|
previousOnTags: me.onTagsUpdated
|
||||||
};
|
};
|
||||||
|
|
||||||
this.tnNewTags = this.tnNewTags.bind(this);
|
this.tnNewTags = this.tnNewTags.bind(this);
|
||||||
|
this.tnCredsUpdated = this.tnCredsUpdated.bind(this);
|
||||||
this.handleFullNameUpdate = this.handleFullNameUpdate.bind(this);
|
this.handleFullNameUpdate = this.handleFullNameUpdate.bind(this);
|
||||||
this.handlePasswordUpdate = this.handlePasswordUpdate.bind(this);
|
this.handlePasswordUpdate = this.handlePasswordUpdate.bind(this);
|
||||||
this.handleImageChanged = this.handleImageChanged.bind(this);
|
this.handleImageChanged = this.handleImageChanged.bind(this);
|
||||||
this.handleCheckboxClick = this.handleCheckboxClick.bind(this);
|
this.handleCheckboxClick = this.handleCheckboxClick.bind(this);
|
||||||
|
this.handleStartAddCred = this.handleStartAddCred.bind(this);
|
||||||
|
this.handleCredChange = this.handleCredChange.bind(this);
|
||||||
|
this.handleCredKeyDown = this.handleCredKeyDown.bind(this);
|
||||||
|
this.handleCredEntered = this.handleCredEntered.bind(this);
|
||||||
this.handleLaunchPermissionsEditor = this.handleLaunchPermissionsEditor.bind(this);
|
this.handleLaunchPermissionsEditor = this.handleLaunchPermissionsEditor.bind(this);
|
||||||
this.handleHidePermissionsEditor = this.handleHidePermissionsEditor.bind(this);
|
this.handleHidePermissionsEditor = this.handleHidePermissionsEditor.bind(this);
|
||||||
this.handlePermissionsChanged = this.handlePermissionsChanged.bind(this);
|
this.handlePermissionsChanged = this.handlePermissionsChanged.bind(this);
|
||||||
@@ -42,31 +49,26 @@ export default class EditAccountView extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
const fnd = this.props.tinode.getFndTopic();
|
const me = this.props.tinode.getMeTopic();
|
||||||
fnd.onTagsUpdated = this.tnNewTags;
|
me.onCredsUpdated = this.tnCredsUpdated;
|
||||||
if (!fnd.isSubscribed()) {
|
me.onTagsUpdated = this.tnNewTags;
|
||||||
fnd.subscribe(fnd.startMetaQuery().withTags().build())
|
|
||||||
.then((ctrl) => {
|
|
||||||
this.setState({fndSubscribed: true});
|
|
||||||
})
|
|
||||||
.catch((err) => {
|
|
||||||
this.props.onError(err.message, 'err');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillUnmount() {
|
componentWillUnmount() {
|
||||||
const fnd = this.props.tinode.getFndTopic();
|
const me = this.props.tinode.getMeTopic();
|
||||||
fnd.onTagsUpdated = this.state.previousOnTags;
|
me.onTagsUpdated = this.state.previousOnTags;
|
||||||
if (fnd.isSubscribed() && this.state.fndSubscribed) {
|
me.onCredsUpdated = undefined;
|
||||||
fnd.leave();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
tnNewTags(tags) {
|
tnNewTags(tags) {
|
||||||
this.setState({tags: tags});
|
this.setState({tags: tags});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tnCredsUpdated(creds) {
|
||||||
|
console.log("tnCredsUpdated", creds, new Error());
|
||||||
|
this.setState({credentials: creds || []});
|
||||||
|
}
|
||||||
|
|
||||||
handleFullNameUpdate(fn) {
|
handleFullNameUpdate(fn) {
|
||||||
this.setState({fullName: fn});
|
this.setState({fullName: fn});
|
||||||
this.props.onUpdateAccount(undefined, vcard(fn, null));
|
this.props.onUpdateAccount(undefined, vcard(fn, null));
|
||||||
@@ -90,6 +92,49 @@ export default class EditAccountView extends React.Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handleStartAddCred() {
|
||||||
|
this.setState({addCredActive: true});
|
||||||
|
}
|
||||||
|
|
||||||
|
handleCredChange(e) {
|
||||||
|
this.setState({newCred: e.target.value, addCredInvalid: false});
|
||||||
|
}
|
||||||
|
|
||||||
|
handleCredKeyDown(e) {
|
||||||
|
if (e.keyCode === 27) {
|
||||||
|
// Escape pressed
|
||||||
|
this.setState({newCred: '', addCredActive: false});
|
||||||
|
} else if (e.keyCode === 13) {
|
||||||
|
// Enter pressed
|
||||||
|
this.handleCredEntered(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
handleCredEntered(e) {
|
||||||
|
let value = this.state.newCred.trim();
|
||||||
|
if (!value) {
|
||||||
|
this.setState({addCredActive: false, addCredInvalid: false});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let val = asPhone(value);
|
||||||
|
let method;
|
||||||
|
if (val) {
|
||||||
|
method = 'tel';
|
||||||
|
} else {
|
||||||
|
val = asEmail(value);
|
||||||
|
if (val) {
|
||||||
|
method = 'email';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (method) {
|
||||||
|
this.props.onCredAdd(method, val);
|
||||||
|
this.setState({addCredActive: false, newCred: ''});
|
||||||
|
} else {
|
||||||
|
this.setState({addCredInvalid: true});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
handleLaunchPermissionsEditor(which) {
|
handleLaunchPermissionsEditor(which) {
|
||||||
this.setState({
|
this.setState({
|
||||||
showPermissionEditorFor: which,
|
showPermissionEditorFor: which,
|
||||||
@@ -120,13 +165,25 @@ export default class EditAccountView extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
var tags = [];
|
/*
|
||||||
this.state.tags.map(function(tag) {
|
let tags = [];
|
||||||
|
this.state.tags.map((tag) => {
|
||||||
tags.push(<span className="badge" key={tags.length}>{tag}</span>);
|
tags.push(<span className="badge" key={tags.length}>{tag}</span>);
|
||||||
});
|
});
|
||||||
if (tags.length == 0) {
|
if (tags.length == 0) {
|
||||||
tags = <i><FormattedMessage id="tags_not_found" /></i>;
|
tags = <i><FormattedMessage id="tags_not_found" /></i>;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
let credentials = [];
|
||||||
|
this.state.credentials.map((cred) => {
|
||||||
|
credentials.push(<div key={cred.meth + ":" + cred.val}>{cred.meth}: <tt>{cred.val}</tt>
|
||||||
|
{!cred.done ?
|
||||||
|
<a href="javascript:;"
|
||||||
|
onClick={this.props.onCredConfirm.bind(this, cred.meth, cred.val)}>confirm</a>
|
||||||
|
: null} <a href="javascript:;" onClick={this.props.onCredDelete.bind(this, cred.meth, cred.val)}><i
|
||||||
|
className="material-icons gray">delete_outline</i></a></div>);
|
||||||
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<React.Fragment>{this.state.showPermissionEditorFor ?
|
<React.Fragment>{this.state.showPermissionEditorFor ?
|
||||||
<PermissionsEditor
|
<PermissionsEditor
|
||||||
@@ -170,26 +227,6 @@ export default class EditAccountView extends React.Component {
|
|||||||
onError={this.props.onError} />
|
onError={this.props.onError} />
|
||||||
</div>
|
</div>
|
||||||
<div className="hr" />
|
<div className="hr" />
|
||||||
<div className="panel-form-column">
|
|
||||||
<div className="panel-form-row">
|
|
||||||
<label><FormattedMessage id="label_user_id" defaultMessage="Address:"
|
|
||||||
description="Label for user address (ID)" /></label>
|
|
||||||
<tt>{this.props.myUserId}</tt>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<label className="small">
|
|
||||||
<FormattedMessage id="label_default_access_mode" defaultMessage="Default access mode:"
|
|
||||||
description="Label for default access mode" />
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
<div className="quoted">
|
|
||||||
<div>Auth: <tt className="clickable"
|
|
||||||
onClick={this.handleLaunchPermissionsEditor.bind(this, 'auth')}>{this.state.auth}</tt></div>
|
|
||||||
<div>Anon: <tt className="clickable"
|
|
||||||
onClick={this.handleLaunchPermissionsEditor.bind(this, 'anon')}>{this.state.anon}</tt></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="hr" />
|
|
||||||
<div className="panel-form-row">
|
<div className="panel-form-row">
|
||||||
<label htmlFor="message-sound">
|
<label htmlFor="message-sound">
|
||||||
<FormattedMessage id="label_message_sound" defaultMessage="Message sound:"
|
<FormattedMessage id="label_message_sound" defaultMessage="Message sound:"
|
||||||
@@ -207,7 +244,7 @@ export default class EditAccountView extends React.Component {
|
|||||||
:
|
:
|
||||||
<FormattedMessage id="label_push_notifications_disabled"
|
<FormattedMessage id="label_push_notifications_disabled"
|
||||||
defaultMessage="Notification alerts (requires HTTPS):"
|
defaultMessage="Notification alerts (requires HTTPS):"
|
||||||
description="Label for push notifications switch (disabled)" />
|
description="Label for push notifications switch" />
|
||||||
}
|
}
|
||||||
</label>
|
</label>
|
||||||
<CheckBox name="alert" id="desktop-alerts"
|
<CheckBox name="alert" id="desktop-alerts"
|
||||||
@@ -224,6 +261,45 @@ export default class EditAccountView extends React.Component {
|
|||||||
onSubmit={this.handleTagsUpdated} />
|
onSubmit={this.handleTagsUpdated} />
|
||||||
}</FormattedMessage>
|
}</FormattedMessage>
|
||||||
<div className="hr" />
|
<div className="hr" />
|
||||||
|
<div className="panel-form-column">
|
||||||
|
<div>
|
||||||
|
<label className="small">
|
||||||
|
<FormattedMessage id="label_user_contacts" defaultMessage="Contacts:"
|
||||||
|
description="Label for user contacts" />
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div className="quoted">
|
||||||
|
{credentials}
|
||||||
|
{this.state.addCredActive ?
|
||||||
|
<input type="text" value={this.state.value}
|
||||||
|
className={this.state.addCredInvalid ? "invalid" : null}
|
||||||
|
placeholder="Phone number or email" required="required" autoFocus
|
||||||
|
onChange={this.handleCredChange} onKeyDown={this.handleCredKeyDown} onBlur={this.handleCredEntered} />
|
||||||
|
: null}
|
||||||
|
<div><a href="javascript:;" onClick={this.handleStartAddCred}>+ Add another</a></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="hr" />
|
||||||
|
<div className="panel-form-column">
|
||||||
|
<div className="panel-form-row">
|
||||||
|
<label className="small"><FormattedMessage id="label_user_id" defaultMessage="Address:"
|
||||||
|
description="Label for user address (ID)" /></label>
|
||||||
|
<tt>{this.props.myUserId}</tt>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label className="small">
|
||||||
|
<FormattedMessage id="label_default_access_mode" defaultMessage="Default access mode:"
|
||||||
|
description="Label for default access mode" />
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div className="quoted">
|
||||||
|
<div>Auth: <tt className="clickable"
|
||||||
|
onClick={this.handleLaunchPermissionsEditor.bind(this, 'auth')}>{this.state.auth}</tt></div>
|
||||||
|
<div>Anon: <tt className="clickable"
|
||||||
|
onClick={this.handleLaunchPermissionsEditor.bind(this, 'anon')}>{this.state.anon}</tt></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="hr" />
|
||||||
<div className="panel-form-column">
|
<div className="panel-form-column">
|
||||||
<a href="javascript:;" className="red flat-button" onClick={this.props.onLogout}>
|
<a href="javascript:;" className="red flat-button" onClick={this.props.onLogout}>
|
||||||
<i className="material-icons">exit_to_app</i> <FormattedMessage id="button_logout"
|
<i className="material-icons">exit_to_app</i> <FormattedMessage id="button_logout"
|
||||||
|
|||||||
@@ -135,6 +135,9 @@ class SidepanelView extends React.Component {
|
|||||||
onUpdateTags={this.props.onUpdateAccountTags}
|
onUpdateTags={this.props.onUpdateAccountTags}
|
||||||
onTogglePushNotifications={this.props.onTogglePushNotifications}
|
onTogglePushNotifications={this.props.onTogglePushNotifications}
|
||||||
onToggleMessageSounds={this.props.onToggleMessageSounds}
|
onToggleMessageSounds={this.props.onToggleMessageSounds}
|
||||||
|
onCredAdd={this.props.onCredAdd}
|
||||||
|
onCredDelete={this.props.onCredDelete}
|
||||||
|
onCredConfirm={this.props.onCredConfirm}
|
||||||
onLogout={this.props.onLogout}
|
onLogout={this.props.onLogout}
|
||||||
onCancel={this.props.onCancel}
|
onCancel={this.props.onCancel}
|
||||||
onError={this.props.onError} /> :
|
onError={this.props.onError} /> :
|
||||||
|
|||||||
@@ -84,6 +84,9 @@ class TinodeWeb extends React.Component {
|
|||||||
this.handleGlobalSettings = this.handleGlobalSettings.bind(this);
|
this.handleGlobalSettings = this.handleGlobalSettings.bind(this);
|
||||||
this.handleShowArchive = this.handleShowArchive.bind(this);
|
this.handleShowArchive = this.handleShowArchive.bind(this);
|
||||||
this.handleToggleMessageSounds = this.handleToggleMessageSounds.bind(this);
|
this.handleToggleMessageSounds = this.handleToggleMessageSounds.bind(this);
|
||||||
|
this.handleCredAdd = this.handleCredAdd.bind(this);
|
||||||
|
this.handleCredDelete = this.handleCredDelete.bind(this);
|
||||||
|
this.handleCredConfirm = this.handleCredConfirm.bind(this);
|
||||||
this.initDesktopAlerts = this.initDesktopAlerts.bind(this);
|
this.initDesktopAlerts = this.initDesktopAlerts.bind(this);
|
||||||
this.togglePushToken = this.togglePushToken.bind(this);
|
this.togglePushToken = this.togglePushToken.bind(this);
|
||||||
this.requestPushToken = this.requestPushToken.bind(this);
|
this.requestPushToken = this.requestPushToken.bind(this);
|
||||||
@@ -493,11 +496,14 @@ class TinodeWeb extends React.Component {
|
|||||||
credCode: undefined,
|
credCode: undefined,
|
||||||
myUserId: this.tinode.getCurrentUserID()
|
myUserId: this.tinode.getCurrentUserID()
|
||||||
});
|
});
|
||||||
|
console.log("handleLoginSuccessful");
|
||||||
// Subscribe, fetch topic desc, the list of subscriptions. Messages are not fetched.
|
// Subscribe, fetch topic desc, the list of subscriptions. Messages are not fetched.
|
||||||
me.subscribe(
|
me.subscribe(
|
||||||
me.startMetaQuery().
|
me.startMetaQuery().
|
||||||
withLaterSub().
|
withLaterSub().
|
||||||
withDesc().
|
withDesc().
|
||||||
|
withTags().
|
||||||
|
withCreds().
|
||||||
build()
|
build()
|
||||||
).catch((err) => {
|
).catch((err) => {
|
||||||
localStorage.removeItem('auth-token');
|
localStorage.removeItem('auth-token');
|
||||||
@@ -635,7 +641,7 @@ class TinodeWeb extends React.Component {
|
|||||||
if (fnd.isSubscribed()) {
|
if (fnd.isSubscribed()) {
|
||||||
this.tnFndSubsUpdated();
|
this.tnFndSubsUpdated();
|
||||||
} else {
|
} else {
|
||||||
fnd.subscribe(fnd.startMetaQuery().withSub().withTags().build()).catch((err) => {
|
fnd.subscribe(fnd.startMetaQuery().withSub().build()).catch((err) => {
|
||||||
this.handleError(err.message, 'err');
|
this.handleError(err.message, 'err');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -827,7 +833,7 @@ class TinodeWeb extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
handleUpdateAccountTagsRequest(tags) {
|
handleUpdateAccountTagsRequest(tags) {
|
||||||
this.tinode.getFndTopic().setMeta({tags: tags})
|
this.tinode.getMeTopic().setMeta({tags: tags})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
this.handleError(err.message, 'err');
|
this.handleError(err.message, 'err');
|
||||||
});
|
});
|
||||||
@@ -933,6 +939,24 @@ class TinodeWeb extends React.Component {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handleCredAdd(method, value) {
|
||||||
|
// TODO: implement
|
||||||
|
console.log("add credential", method, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
handleCredDelete(method, value) {
|
||||||
|
console.log("delete credential", method, value);
|
||||||
|
const me = this.tinode.getMeTopic();
|
||||||
|
me.delCredential(method, value).catch((err) => {
|
||||||
|
this.handleError(err.message, 'err');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
handleCredConfirm(method, response) {
|
||||||
|
// TODO: implement
|
||||||
|
console.log("confirm credential", method, response);
|
||||||
|
}
|
||||||
|
|
||||||
// User clicked Cancel button in Setting or Sign Up panel.
|
// User clicked Cancel button in Setting or Sign Up panel.
|
||||||
handleSidepanelCancel() {
|
handleSidepanelCancel() {
|
||||||
const parsed = HashNavigation.parseUrlHash(window.location.hash);
|
const parsed = HashNavigation.parseUrlHash(window.location.hash);
|
||||||
@@ -1254,6 +1278,9 @@ class TinodeWeb extends React.Component {
|
|||||||
onUpdateAccountTags={this.handleUpdateAccountTagsRequest}
|
onUpdateAccountTags={this.handleUpdateAccountTagsRequest}
|
||||||
onTogglePushNotifications={this.togglePushToken}
|
onTogglePushNotifications={this.togglePushToken}
|
||||||
onToggleMessageSounds={this.handleToggleMessageSounds}
|
onToggleMessageSounds={this.handleToggleMessageSounds}
|
||||||
|
onCredAdd={this.handleCredAdd}
|
||||||
|
onCredDelete={this.handleCredDelete}
|
||||||
|
onCredConfirm={this.handleCredConfirm}
|
||||||
onTopicSelected={this.handleTopicSelected}
|
onTopicSelected={this.handleTopicSelected}
|
||||||
onCreateTopic={this.handleNewTopicRequest}
|
onCreateTopic={this.handleNewTopicRequest}
|
||||||
onNewTopic={this.handleNewTopic}
|
onNewTopic={this.handleNewTopic}
|
||||||
|
|||||||
+210
-75
File diff suppressed because one or more lines are too long
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