add QR code display

This commit is contained in:
or-else
2024-02-02 16:26:49 -08:00
parent f932b973f8
commit 9eaa172030
65 changed files with 399 additions and 86 deletions
+3
View File
@@ -129,3 +129,6 @@ export const IMMEDIATE_P2P_SUBSCRIPTION = false;
// URL schemes permitted to appear in links (i.e. no javascript: scheme).
export const CLICKABLE_URL_SCHEMES = ['http', 'https', 'ftp', 'ftps'];
// Size of the QR code in the app.
export const QRCODE_SIZE = 128;
+1 -1
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+1 -1
View File
File diff suppressed because one or more lines are too long
+7
View File
@@ -1640,5 +1640,12 @@
"description": "Notification message that the password was successfully reset.",
"missing": false,
"obsolete": false
},
"scan_qr_code": {
"translation": "QR-Code scannen",
"defaultMessage": "Scan QR Code",
"description": "Title for scanning QR code",
"missing": false,
"obsolete": false
}
}
+7
View File
@@ -1640,5 +1640,12 @@
"description": "Notification message that the password was successfully reset.",
"missing": false,
"obsolete": false
},
"scan_qr_code": {
"translation": "Scan QR Code",
"defaultMessage": "Scan QR Code",
"description": "Title for scanning QR code",
"missing": false,
"obsolete": false
}
}
+7
View File
@@ -1640,5 +1640,12 @@
"description": "Notification message that the password was successfully reset.",
"missing": false,
"obsolete": false
},
"scan_qr_code": {
"translation": "Escanear código QR",
"defaultMessage": "Scan QR Code",
"description": "Title for scanning QR code",
"missing": false,
"obsolete": false
}
}
+4
View File
@@ -796,6 +796,10 @@
"defaultMessage": "save",
"description": "Call to save an attachment"
},
"scan_qr_code": {
"defaultMessage": "Scan QR Code",
"description": "Title for scanning QR code"
},
"search_for_contacts": {
"defaultMessage": "Use search to find contacts",
"description": "Text shown in contacts view when user entered no search query."
+7
View File
@@ -1640,5 +1640,12 @@
"description": "Notification message that the password was successfully reset.",
"missing": false,
"obsolete": false
},
"scan_qr_code": {
"translation": "Scanner le code QR",
"defaultMessage": "Scan QR Code",
"description": "Title for scanning QR code",
"missing": false,
"obsolete": false
}
}
+7
View File
@@ -1640,5 +1640,12 @@
"description": "Notification message that the password was successfully reset.",
"missing": false,
"obsolete": false
},
"scan_qr_code": {
"translation": "QR 코드 스캔",
"defaultMessage": "Scan QR Code",
"description": "Title for scanning QR code",
"missing": false,
"obsolete": false
}
}
+7
View File
@@ -1640,5 +1640,12 @@
"description": "Notification message that the password was successfully reset.",
"missing": false,
"obsolete": false
},
"scan_qr_code": {
"translation": "Scanați codul QR",
"defaultMessage": "Scan QR Code",
"description": "Title for scanning QR code",
"missing": false,
"obsolete": false
}
}
+7
View File
@@ -1640,5 +1640,12 @@
"description": "Notification message that the password was successfully reset.",
"missing": false,
"obsolete": false
},
"scan_qr_code": {
"translation": "Отсканируйте QR код",
"defaultMessage": "Scan QR Code",
"description": "Title for scanning QR code",
"missing": false,
"obsolete": false
}
}
+7
View File
@@ -1640,5 +1640,12 @@
"description": "Notification message that the password was successfully reset.",
"missing": false,
"obsolete": false
},
"scan_qr_code": {
"translation": "สแกนรหัส QR",
"defaultMessage": "Scan QR Code",
"description": "Title for scanning QR code",
"missing": false,
"obsolete": false
}
}
+7
View File
@@ -1640,5 +1640,12 @@
"description": "Notification message that the password was successfully reset.",
"missing": false,
"obsolete": false
},
"scan_qr_code": {
"translation": "Відскануйте QR-код",
"defaultMessage": "Scan QR Code",
"description": "Title for scanning QR code",
"missing": false,
"obsolete": false
}
}
+7
View File
@@ -1640,5 +1640,12 @@
"description": "Notification message that the password was successfully reset.",
"missing": false,
"obsolete": false
},
"scan_qr_code": {
"translation": "掃描二維碼",
"defaultMessage": "Scan QR Code",
"description": "Title for scanning QR code",
"missing": false,
"obsolete": false
}
}
+7
View File
@@ -1640,5 +1640,12 @@
"description": "Notification message that the password was successfully reset.",
"missing": false,
"obsolete": false
},
"scan_qr_code": {
"translation": "扫描二维码",
"defaultMessage": "Scan QR Code",
"description": "Title for scanning QR code",
"missing": false,
"obsolete": false
}
}
+37 -4
View File
@@ -12,6 +12,7 @@ import ErrorPanel from '../widgets/error-panel.jsx';
import GroupManager from '../widgets/group-manager.jsx';
import MenuCancel from '../widgets/menu-cancel.jsx';
import PermissionsEditor from '../widgets/permissions-editor.jsx';
import ShowQRCode from '../widgets/show-qrcode.jsx';
import TopicCommonView from './topic-common-view.jsx';
import TopicSecurity from '../widgets/topic-security.jsx';
@@ -76,6 +77,11 @@ const messages = defineMessages({
defaultMessage: 'Edit permissions',
description: 'Menu item [Edit permissions]'
},
qrcode: {
id: 'scan_qr_code',
defaultMessage: 'Scan QR Code',
description: 'Title for scanning QR code'
},
});
class InfoView extends React.Component {
@@ -120,6 +126,8 @@ class InfoView extends React.Component {
this.handleUnarchive = this.handleUnarchive.bind(this);
this.handlePermissionsChanged = this.handlePermissionsChanged.bind(this);
this.handleLaunchPermissionsEditor = this.handleLaunchPermissionsEditor.bind(this);
this.handleCopyID = this.handleCopyID.bind(this);
this.handleShowQRCode = this.handleShowQRCode.bind(this);
this.handleShowAddMembers = this.handleShowAddMembers.bind(this);
this.handleMemberUpdateRequest = this.handleMemberUpdateRequest.bind(this);
this.handleMemberSelected = this.handleMemberSelected.bind(this);
@@ -368,6 +376,16 @@ class InfoView extends React.Component {
this.props.onNavigate(`perm/${which}`);
}
handleCopyID(e) {
e.preventDefault();
navigator.clipboard.writeText(this.props.myUserId);
}
handleShowQRCode(e) {
e.preventDefault();
this.props.onNavigate('qrcode');
}
handleShowAddMembers(e) {
e.preventDefault();
this.props.onInitFind();
@@ -514,6 +532,11 @@ class InfoView extends React.Component {
onLaunchPermissionsEditor={this.handleLaunchPermissionsEditor}
onNavigate={this.props.onNavigate} />
:
view == 'qrcode' ?
<ShowQRCode
uri={Tinode.URI_TOPIC_ID_PREFIX + this.props.tinode.myUserId}
onCancel={this.handleBackNavigate} />
:
<div id="info-view-content" className="scrollable-panel">
<div className="panel-form-column">
<a href="#" className="flat-button float-right" onClick={(e) => {e.preventDefault(); this.props.onNavigate('general');}}>
@@ -546,10 +569,20 @@ class InfoView extends React.Component {
</div>
: null
}
<div className="group">
<label className="small"><FormattedMessage id="label_user_id" defaultMessage="ID:"
description="Label for user address (ID)" /></label>&nbsp;
<tt>{this.state.address}</tt>
<div className="panel-form-row">
<div>
<label className="small"><FormattedMessage id="label_user_id" defaultMessage="ID:"
description="Label for user address (ID)" /></label>&nbsp;
<tt>{this.state.address}</tt>
</div>
<div style={{marginLeft: 'auto'}}>
&nbsp;<a href="#" onClick={this.handleCopyID}>
<i className="material-icons">content_copy</i>
</a>&nbsp;
&nbsp;<a href="#" onClick={this.handleShowQRCode}>
<i className="material-icons">qr_code</i>
</a>&nbsp;
</div>
</div>
<div className="group">
<BadgeList trustedBadges={this.state.trustedBadges} />
+1
View File
@@ -113,6 +113,7 @@ class NewTopicView extends React.Component {
onError={this.props.onError} /> :
this.state.tabSelected === 'byid' ?
<NewTopicById
myURI={Tinode.URI_TOPIC_ID_PREFIX + this.props.tinode.getCurrentUserID()}
onSubmit={this.handleGroupByID}
onError={this.props.onError} /> :
<div className="flex-column">
+20 -2
View File
@@ -1,6 +1,9 @@
import QRCode from 'qrcodejs';
import React from 'react';
import { FormattedMessage, defineMessages, injectIntl } from 'react-intl';
import { QRCODE_SIZE } from '../config';
const messages = defineMessages({
invalid_id: {
id: 'error_invalid_id',
@@ -13,6 +16,8 @@ class NewTopicById extends React.PureComponent {
constructor(props) {
super(props);
this.qrCodeRef = React.createRef();
this.state = {
groupId: '',
};
@@ -22,6 +27,14 @@ class NewTopicById extends React.PureComponent {
this.handleSubmit = this.handleSubmit.bind(this);
}
componentDidMount() {
new QRCode(this.qrCodeRef.current, {
text: this.props.myURI,
width: QRCODE_SIZE,
height: QRCODE_SIZE,
});
}
handleChange(e) {
this.setState({groupId: e.target.value});
}
@@ -36,7 +49,7 @@ class NewTopicById extends React.PureComponent {
e.preventDefault();
if (this.state.groupId) {
const name = this.state.groupId.trim();
const prefix = name.substr(0, 3);
const prefix = name.substring(0, 3);
if (name.length > 3 && ['usr', 'grp', 'chn'].includes(prefix)) {
this.props.onSubmit(name);
} else {
@@ -53,7 +66,7 @@ class NewTopicById extends React.PureComponent {
description="Prompt for entering user or group ID">{
(prompt) => <input type="text" placeholder={prompt}
value={this.state.groupId} onChange={this.handleChange}
onKeyPress={this.handleKeyPress} required autoFocus />
onKeyDown={this.handleKeyPress} required autoFocus />
}</FormattedMessage>
</div>
<div className="dialog-buttons">
@@ -62,6 +75,11 @@ class NewTopicById extends React.PureComponent {
description="Button [Subscribe]" />
</button>
</div>
<br />
<div className="panel-form-column">
<label className="small">Scan my ID:</label>
<div className="qr-code" ref={this.qrCodeRef} />
</div>
</div>
);
}
+34
View File
@@ -0,0 +1,34 @@
import QRCode from 'qrcodejs';
import React from 'react';
import { FormattedMessage } from 'react-intl';
import { QRCODE_SIZE } from '../config';
export default class ShowQRCode extends React.PureComponent {
constructor(props) {
super(props);
this.qrCodeRef = React.createRef();
}
componentDidMount() {
new QRCode(this.qrCodeRef.current, {
text: this.props.uri,
width: QRCODE_SIZE,
height: QRCODE_SIZE,
});
}
render() {
return (
<div className="panel-form-column">
<br />
<div className="qr-code" ref={this.qrCodeRef} />
<div className="dialog-buttons">
<button className="outline" onClick={this.props.onCancel}>
<FormattedMessage id="button_ok" defaultMessage="OK" description="Button [OK]" />
</button>
</div>
</div>
);
}
};