Convert im_webapp from static mock prototypes to real backend integration
Implements all 11 product chapters (auth, messaging, contacts, groups,
files/favorites, calls, workplace/reports, settings, security) against the
real /v1/im REST API and native Tinode WS protocol, replacing the hardcoded
mock data the ba8f48ee prototype commit shipped with. Adds src/lib/im-api.js
as the REST client, plus supporting fixes across messages-view.jsx and the
attachment/upload/download pipeline (wrong SDK auth headers, group topic
naming, seq/timezone edge cases) found via live end-to-end testing against
the real backend.
Backup checkpoint before reconciling with origin/dev's parallel rewrite.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
ba8f48ee83
commit
251c9de87c
@@ -144,10 +144,13 @@ class SendMessage extends React.PureComponent {
|
||||
if (this.props.disabled) {
|
||||
return;
|
||||
}
|
||||
// onAttachImage/onAttachFile are explicitly null while forwarding a message
|
||||
// (messages-view.jsx) -- pasting a file in that state used to throw
|
||||
// "onAttachImage is not a function" instead of just not attaching anything.
|
||||
// FIXME: handle large files too.
|
||||
if (filePasted(e,
|
||||
file => { this.props.onAttachImage(file); },
|
||||
file => { this.props.onAttachFile(file); },
|
||||
file => { if (this.props.onAttachImage) { this.props.onAttachImage(file); } },
|
||||
file => { if (this.props.onAttachFile) { this.props.onAttachFile(file); } },
|
||||
this.props.onError)) {
|
||||
|
||||
// If a file was pasted, don't paste base64 data into input field.
|
||||
@@ -156,7 +159,7 @@ class SendMessage extends React.PureComponent {
|
||||
}
|
||||
|
||||
handleAttachImage(e) {
|
||||
if (e.target.files && e.target.files.length > 0) {
|
||||
if (e.target.files && e.target.files.length > 0 && this.props.onAttachImage) {
|
||||
this.props.onAttachImage(e.target.files[0]);
|
||||
}
|
||||
// Clear the value so the same file can be uploaded again.
|
||||
@@ -164,7 +167,7 @@ class SendMessage extends React.PureComponent {
|
||||
}
|
||||
|
||||
handleAttachFile(e) {
|
||||
if (e.target.files && e.target.files.length > 0) {
|
||||
if (e.target.files && e.target.files.length > 0 && this.props.onAttachFile) {
|
||||
this.props.onAttachFile(e.target.files[0]);
|
||||
}
|
||||
// Clear the value so the same file can be uploaded again.
|
||||
@@ -172,22 +175,30 @@ class SendMessage extends React.PureComponent {
|
||||
}
|
||||
|
||||
handleDropAttach(files) {
|
||||
if (files && files.length > 0) {
|
||||
if (files && files.length > 0 && this.props.onAttachFile) {
|
||||
this.props.onAttachFile(files[0]);
|
||||
}
|
||||
}
|
||||
|
||||
handleAttachAudio(url, preview, duration) {
|
||||
this.setState({audioRec: false});
|
||||
this.props.onAttachAudio(url, preview, duration);
|
||||
if (this.props.onAttachAudio) {
|
||||
this.props.onAttachAudio(url, preview, duration);
|
||||
}
|
||||
}
|
||||
|
||||
handleSend(e) {
|
||||
e.preventDefault();
|
||||
const message = this.state.message.trim();
|
||||
if (message || this.props.acceptBlank || this.props.noInput) {
|
||||
this.props.onSendMessage(message);
|
||||
this.setState({message: ''});
|
||||
const result = this.props.onSendMessage(message);
|
||||
// onSendMessage may return a promise resolving to `false` when a pre-send risk check blocked
|
||||
// or the user cancelled it -- in that case keep the composer text so nothing typed is lost.
|
||||
if (result && typeof result.then == 'function') {
|
||||
result.then(sent => { if (sent !== false) this.setState({message: ''}); });
|
||||
} else {
|
||||
this.setState({message: ''});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user