Add a showUserDetails modal to display user's details

Relates #655
This commit is contained in:
Audric Ackermann 2019-11-27 15:09:16 +11:00
parent af58d52b0f
commit 9992a3da1d
8 changed files with 190 additions and 0 deletions

View file

@ -821,6 +821,7 @@
<script type='text/javascript' src='js/views/create_group_dialog_view.js'></script>
<script type='text/javascript' src='js/views/edit_profile_dialog_view.js'></script>
<script type='text/javascript' src='js/views/invite_friends_dialog_view.js'></script>
<script type='text/javascript' src='js/views/user_details_dialog_view.js'></script>
<script type='text/javascript' src='js/wall_clock_listener.js'></script>
<script type='text/javascript' src='js/rotate_signed_prekey_listener.js'></script>

View file

@ -978,6 +978,30 @@
}
});
Whisper.events.on('onShowUserDetails', async ({ userPubKey }) => {
const conversation = await ConversationController.getOrCreateAndWait(
userPubKey,
'private'
);
const avatarPath = conversation.getAvatarPath();
const profile = conversation.getLokiProfile();
const displayName = profile && profile.displayName;
if (appView) {
appView.showUserDetailsDialog({
profileName: displayName,
pubkey: userPubKey,
avatarPath,
avatarColor: conversation.getColor(),
onOk: async () => {},
onStartConversation: async () => {
window.Whisper.events.trigger('showConversation', userPubKey);
},
});
}
});
Whisper.events.on('showToast', options => {
if (
appView &&

View file

@ -706,6 +706,10 @@
message: this,
isDangerous,
}),
onShowUserDetails: pubkey =>
window.Whisper.events.trigger('onShowUserDetails', {
userPubKey: pubkey,
}),
};
},
createNonBreakingLastSeparator(text) {

View file

@ -49,6 +49,8 @@ const {
CreateGroupDialog,
} = require('../../ts/components/conversation/CreateGroupDialog');
const { EditProfileDialog } = require('../../ts/components/EditProfileDialog');
const { UserDetailsDialog } = require('../../ts/components/UserDetailsDialog');
const {
UpdateGroupDialog,
} = require('../../ts/components/conversation/UpdateGroupDialog');
@ -236,6 +238,7 @@ exports.setup = (options = {}) => {
MemberList,
CreateGroupDialog,
EditProfileDialog,
UserDetailsDialog,
ConfirmDialog,
UpdateGroupDialog,
InviteFriendsDialog,

View file

@ -180,6 +180,10 @@
const dialog = new Whisper.EditProfileDialogView(options);
this.el.append(dialog.el);
},
showUserDetailsDialog(options) {
const dialog = new Whisper.UserDetailsDialogView(options);
this.el.append(dialog.el);
},
showNicknameDialog({ pubKey, title, message, nickname, onOk, onCancel }) {
const _title = title || `Change nickname for ${pubKey}`;
const dialog = new Whisper.NicknameDialogView({

View file

@ -0,0 +1,53 @@
/* global i18n, Whisper */
// eslint-disable-next-line func-names
(function() {
'use strict';
window.Whisper = window.Whisper || {};
Whisper.UserDetailsDialogView = Whisper.View.extend({
className: 'loki-dialog modal',
initialize({
profileName,
avatarPath,
avatarColor,
pubkey,
onOk,
onStartConversation,
}) {
this.close = this.close.bind(this);
this.profileName = profileName;
this.pubkey = pubkey;
this.avatarPath = avatarPath;
this.avatarColor = avatarColor;
this.onOk = onOk;
this.onStartConversation = onStartConversation;
this.$el.focus();
this.render();
},
render() {
this.dialogView = new Whisper.ReactWrapperView({
className: 'edit-profile-dialog',
Component: window.Signal.Components.UserDetailsDialog,
props: {
onOk: this.onOk,
onClose: this.close,
onStartConversation: this.onStartConversation,
profileName: this.profileName,
pubkey: this.pubkey,
avatarPath: this.avatarPath,
i18n,
},
});
this.$el.append(this.dialogView.el);
return this;
},
close() {
this.remove();
},
});
})();

View file

@ -0,0 +1,99 @@
import React from 'react';
import { Avatar } from './Avatar';
declare global {
interface Window {
displayNameRegex: any;
}
}
interface Props {
i18n: any;
profileName: string;
avatarPath: string;
avatarColor: string;
pubkey: string;
onClose: any;
onStartConversation: any;
}
export class UserDetailsDialog extends React.Component<Props> {
constructor(props: any) {
super(props);
this.closeDialog = this.closeDialog.bind(this);
this.onKeyUp = this.onKeyUp.bind(this);
this.onClickStartConversation = this.onClickStartConversation.bind(this);
window.addEventListener('keyup', this.onKeyUp);
}
public render() {
const i18n = this.props.i18n;
const cancelText = i18n('cancel');
const startConversation = i18n('startConversation');
return (
<div className="content">
{this.renderAvatar()}
<span className="profile-name">{this.props.profileName}</span>
<div className="message">{this.props.pubkey}</div>
<div className="buttons">
<button className="cancel" tabIndex={0} onClick={this.closeDialog}>
{cancelText}
</button>
<button
className="ok"
tabIndex={0}
onClick={this.onClickStartConversation}
>
{startConversation}
</button>
</div>
</div>
);
}
private renderAvatar() {
const avatarPath = this.props.avatarPath;
const color = this.props.avatarColor;
return (
<Avatar
avatarPath={avatarPath}
color={color}
conversationType="direct"
i18n={this.props.i18n}
name={this.props.profileName}
phoneNumber={this.props.pubkey}
profileName={this.props.profileName}
size={80}
/>
);
}
private onKeyUp(event: any) {
switch (event.key) {
case 'Enter':
this.onClickStartConversation();
break;
case 'Esc':
case 'Escape':
this.closeDialog();
break;
default:
}
}
private closeDialog() {
window.removeEventListener('keyup', this.onKeyUp);
this.props.onClose();
}
private onClickStartConversation() {
this.props.onStartConversation();
this.closeDialog();
}
}

View file

@ -113,6 +113,7 @@ export interface Props {
onDelete?: () => void;
onCopyPubKey?: () => void;
onShowDetail: () => void;
onShowUserDetails: (userPubKey: string) => void;
}
interface State {
@ -660,6 +661,7 @@ export class Message extends React.PureComponent<Props, State> {
conversationType,
direction,
i18n,
onShowUserDetails,
} = this.props;
if (