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
@@ -116,35 +116,44 @@ export default class CallIncoming extends React.Component {
|
||||
}
|
||||
|
||||
render() {
|
||||
const isAudioOnly = !!this.props.audioOnly;
|
||||
const ringing = this.props.callState == CALL_STATE_INCOMING_RECEIVED;
|
||||
const surfaceClass = isAudioOnly ? 'call-audio-surface' : 'call-video-surface';
|
||||
const photoStyle = this.state.avatar ? {'--incoming-call-photo': `url(${this.state.avatar})`} : null;
|
||||
return (
|
||||
<div className="alert-container">
|
||||
<div className="incoming-call">
|
||||
<div className="caller-card incoming pulse">
|
||||
<div className="avatar-box">
|
||||
<LetterTile
|
||||
authorizeURL={this.props.tinode.authorizeURL}
|
||||
avatar={this.state.avatar || true}
|
||||
topic={this.props.topic}
|
||||
title={this.state.fullName} />
|
||||
</div>
|
||||
<div className="caller-name">{truncateString(this.state.fullName, MAX_PEER_TITLE_LENGTH)}
|
||||
<BadgeList short={true} trustedBadges={this.state.trustedBadges} /></div>
|
||||
</div>
|
||||
<div id="controls">
|
||||
{this.props.callState == CALL_STATE_INCOMING_RECEIVED ?
|
||||
<>
|
||||
<button className="danger" onClick={this.handleRejectCall}>
|
||||
<i className="material-icons">call_end</i>
|
||||
</button>
|
||||
<button className="positive" onClick={this.handleAcceptCall}>
|
||||
<i className="material-icons">call</i>
|
||||
</button>
|
||||
</>
|
||||
:
|
||||
null
|
||||
}
|
||||
<div className={`call-fullscreen incoming-call-overlay ${surfaceClass} incoming`}>
|
||||
<div className="call-ambient" />
|
||||
{this.state.avatar &&
|
||||
<div className="incoming-call-photo-blur" style={photoStyle} />}
|
||||
<div className="call-peer-card">
|
||||
<div className="avatar-box call-product-avatar">
|
||||
<LetterTile
|
||||
authorizeURL={this.props.tinode.authorizeURL}
|
||||
avatar={this.state.avatar || true}
|
||||
topic={this.props.topic}
|
||||
title={this.state.fullName} />
|
||||
</div>
|
||||
<h1>{truncateString(this.state.fullName, MAX_PEER_TITLE_LENGTH)}
|
||||
<BadgeList short={true} trustedBadges={this.state.trustedBadges} /></h1>
|
||||
<p>{isAudioOnly ? '对方邀请你语音通话...' : '对方邀请你视频通话...'}</p>
|
||||
{ringing && <span className="call-ringing-dots"><i /><i /><i /></span>}
|
||||
</div>
|
||||
<footer className="call-incoming-actions">
|
||||
{ringing ?
|
||||
<>
|
||||
<button type="button" className="call-control danger" onClick={this.handleRejectCall}>
|
||||
<span><i className="material-icons">call_end</i></span>
|
||||
<small>拒绝</small>
|
||||
</button>
|
||||
<button type="button" className="call-control" onClick={this.handleAcceptCall}>
|
||||
<span><i className="material-icons">{isAudioOnly ? 'call' : 'videocam'}</i></span>
|
||||
<small>接听</small>
|
||||
</button>
|
||||
</>
|
||||
:
|
||||
null
|
||||
}
|
||||
</footer>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user