Skip to content

Commit

Permalink
Merge pull request #10458 from pedrobmarin/avatar-image
Browse files Browse the repository at this point in the history
Support for avatar images
  • Loading branch information
antobinary committed Sep 21, 2020
2 parents 7df1750 + e2adf24 commit d5450af
Show file tree
Hide file tree
Showing 21 changed files with 89 additions and 23 deletions.
Expand Up @@ -56,7 +56,7 @@ trait RegisterUserReqMsgHdlr {
val g = GuestApprovedVO(regUser.id, GuestStatus.ALLOW)
UsersApp.approveOrRejectGuest(liveMeeting, outGW, g, SystemUser.ID)
case GuestStatus.WAIT =>
val guest = GuestWaiting(regUser.id, regUser.name, regUser.role, regUser.guest, regUser.authed)
val guest = GuestWaiting(regUser.id, regUser.name, regUser.role, regUser.guest, regUser.avatarURL, regUser.authed)
addGuestToWaitingForApproval(guest, liveMeeting.guestsWaiting)
notifyModeratorsOfGuestWaiting(Vector(guest), liveMeeting.users2x, liveMeeting.props.meetingProp.intId)
case GuestStatus.DENY =>
Expand Down
Expand Up @@ -51,7 +51,7 @@ class GuestsWaiting {
def setGuestPolicy(policy: GuestPolicy) = guestPolicy = policy
}

case class GuestWaiting(intId: String, name: String, role: String, guest: Boolean, authenticated: Boolean)
case class GuestWaiting(intId: String, name: String, role: String, guest: Boolean, avatar: String, authenticated: Boolean)
case class GuestPolicy(policy: String, setBy: String)

object GuestPolicyType {
Expand Down
Expand Up @@ -44,7 +44,7 @@ object MsgBuilder {
val envelope = BbbCoreEnvelope(GetGuestsWaitingApprovalRespMsg.NAME, routing)
val header = BbbClientMsgHeader(GetGuestsWaitingApprovalRespMsg.NAME, meetingId, userId)

val guestsWaiting = guests.map(g => GuestWaitingVO(g.intId, g.name, g.role, g.guest, g.authenticated))
val guestsWaiting = guests.map(g => GuestWaitingVO(g.intId, g.name, g.role, g.guest, g.avatar, g.authenticated))
val body = GetGuestsWaitingApprovalRespMsgBody(guestsWaiting)
val event = GetGuestsWaitingApprovalRespMsg(header, body)

Expand All @@ -56,7 +56,7 @@ object MsgBuilder {
val envelope = BbbCoreEnvelope(GuestsWaitingForApprovalEvtMsg.NAME, routing)
val header = BbbClientMsgHeader(GuestsWaitingForApprovalEvtMsg.NAME, meetingId, userId)

val guestsWaiting = guests.map(g => GuestWaitingVO(g.intId, g.name, g.role, g.guest, g.authenticated))
val guestsWaiting = guests.map(g => GuestWaitingVO(g.intId, g.name, g.role, g.guest, g.avatar, g.authenticated))
val body = GuestsWaitingForApprovalEvtMsgBody(guestsWaiting)
val event = GuestsWaitingForApprovalEvtMsg(header, body)

Expand Down
Expand Up @@ -20,13 +20,13 @@ trait FakeTestData {
val guest1 = createUserVoiceAndCam(liveMeeting, Roles.VIEWER_ROLE, guest = true, authed = true, CallingWith.WEBRTC, muted = false,
talking = false, listenOnly = false)
Users2x.add(liveMeeting.users2x, guest1)
val guestWait1 = GuestWaiting(guest1.intId, guest1.name, guest1.role, guest1.guest, guest1.authed)
val guestWait1 = GuestWaiting(guest1.intId, guest1.name, guest1.role, guest1.guest, "", guest1.authed)
GuestsWaiting.add(liveMeeting.guestsWaiting, guestWait1)

val guest2 = createUserVoiceAndCam(liveMeeting, Roles.VIEWER_ROLE, guest = true, authed = true, CallingWith.FLASH, muted = false,
talking = false, listenOnly = false)
Users2x.add(liveMeeting.users2x, guest2)
val guestWait2 = GuestWaiting(guest2.intId, guest2.name, guest2.role, guest2.guest, guest2.authed)
val guestWait2 = GuestWaiting(guest2.intId, guest2.name, guest2.role, guest2.guest, "", guest2.authed)
GuestsWaiting.add(liveMeeting.guestsWaiting, guestWait2)

val vu1 = FakeUserGenerator.createFakeVoiceOnlyUser(CallingWith.PHONE, muted = false, talking = false, listenOnly = false)
Expand Down
Expand Up @@ -19,7 +19,7 @@ case class GetGuestsWaitingApprovalRespMsg(
body: GetGuestsWaitingApprovalRespMsgBody
) extends BbbCoreMsg
case class GetGuestsWaitingApprovalRespMsgBody(guests: Vector[GuestWaitingVO])
case class GuestWaitingVO(intId: String, name: String, role: String, guest: Boolean, authenticated: Boolean)
case class GuestWaitingVO(intId: String, name: String, role: String, guest: Boolean, avatar: String, authenticated: Boolean)

/**
* Message sent to client for list of guest waiting for approval. This is sent when
Expand Down
Expand Up @@ -923,7 +923,7 @@ public void userJoinedVoice(UserJoinedVoice message) {
} else {
if (message.userId.startsWith("v_")) {
// A dial-in user joined the meeting. Dial-in users by convention has userId that starts with "v_".
User vuser = new User(message.userId, message.userId, message.name, "DIAL-IN-USER", "no-avatar-url",
User vuser = new User(message.userId, message.userId, message.name, "DIAL-IN-USER", "",
true, GuestPolicy.ALLOW, "DIAL-IN");
vuser.setVoiceJoined(true);
m.userJoined(vuser);
Expand Down
Expand Up @@ -78,6 +78,7 @@ public class ParamsProcessorUtil {
private Boolean moderatorsJoinViaHTML5Client;
private Boolean attendeesJoinViaHTML5Client;
private Boolean allowRequestsWithoutSession;
private Boolean useDefaultAvatar = false;
private String defaultAvatarURL;
private String defaultConfigURL;
private String defaultGuestPolicy;
Expand Down Expand Up @@ -464,6 +465,8 @@ boolean record = processRecordMeeting(params.get(ApiParams.RECORD));
externalMeetingId = externalHash + "-" + timeStamp;
}

String avatarURL = useDefaultAvatar ? defaultAvatarURL : "";

// Create the meeting with all passed in parameters.
Meeting meeting = new Meeting.Builder(externalMeetingId,
internalMeetingId, createTime).withName(meetingName)
Expand All @@ -474,7 +477,7 @@ boolean record = processRecordMeeting(params.get(ApiParams.RECORD));
.withBannerText(bannerText).withBannerColor(bannerColor)
.withTelVoice(telVoice).withWebVoice(webVoice)
.withDialNumber(dialNumber)
.withDefaultAvatarURL(defaultAvatarURL)
.withDefaultAvatarURL(avatarURL)
.withAutoStartRecording(autoStartRec)
.withAllowStartStopRecording(allowStartStoptRec)
.withWebcamsOnlyForModerator(webcamsOnlyForMod)
Expand Down Expand Up @@ -952,6 +955,10 @@ public void setWebcamsOnlyForModerator(boolean webcamsOnlyForModerator) {
this.webcamsOnlyForModerator = webcamsOnlyForModerator;
}

public void setUseDefaultAvatar(Boolean value) {
this.useDefaultAvatar = value;
}

public void setdefaultAvatarURL(String url) {
this.defaultAvatarURL = url;
}
Expand Down
Expand Up @@ -126,6 +126,7 @@ class MessageListItem extends Component {
className={styles.avatar}
color={user.color}
moderator={user.isModerator}
avatar={user.avatar}
>
{user.name.toLowerCase().slice(0, 2)}
</UserAvatar>
Expand Down
8 changes: 7 additions & 1 deletion bigbluebutton-html5/imports/ui/components/chat/service.js
Expand Up @@ -50,20 +50,26 @@ const mapGroupMessage = (message) => {
const sender = Users.findOne({ userId: message.sender },
{
fields: {
color: 1, role: 1, name: 1, connectionStatus: 1,
color: 1,
role: 1,
name: 1,
avatar: 1,
connectionStatus: 1,
},
});
const {
color,
role,
name,
avatar,
connectionStatus,
} = sender;

const mappedSender = {
color,
isModerator: role === ROLE_MODERATOR,
name,
avatar,
isOnline: connectionStatus === CONNECTION_STATUS_ONLINE,
};

Expand Down
Expand Up @@ -84,8 +84,9 @@ class ConnectionStatusComponent extends PureComponent {
<div className={styles.left}>
<div className={styles.avatar}>
<UserAvatar
className={styles.icon}
className={cx({ [styles.initials]: conn.avatar.length === 0 })}
you={conn.you}
avatar={conn.avatar}
moderator={conn.moderator}
color={conn.color}
>
Expand Down
Expand Up @@ -82,7 +82,7 @@
justify-content: center;
align-items: center;

.icon {
.initials {
min-width: 2.25rem;
height: 2.25rem;
}
Expand Down
Expand Up @@ -87,6 +87,7 @@ const getConnectionStatus = () => {
userId: 1,
name: 1,
role: 1,
avatar: 1,
color: 1,
connectionStatus: 1,
},
Expand All @@ -96,6 +97,7 @@ const getConnectionStatus = () => {
userId,
name,
role,
avatar,
color,
connectionStatus: userStatus,
} = user;
Expand All @@ -105,6 +107,7 @@ const getConnectionStatus = () => {
if (status) {
result.push({
name,
avatar,
offline: userStatus === 'offline',
you: Auth.userID === userId,
moderator: role === ROLE_MODERATOR,
Expand Down
Expand Up @@ -14,6 +14,8 @@ const propTypes = {
voice: PropTypes.bool,
noVoice: PropTypes.bool,
color: PropTypes.string,
emoji: PropTypes.bool,
avatar: PropTypes.string,
className: PropTypes.string,
};

Expand All @@ -26,6 +28,8 @@ const defaultProps = {
voice: false,
noVoice: false,
color: '#000',
emoji: false,
avatar: '',
className: null,
};

Expand All @@ -38,6 +42,8 @@ const UserAvatar = ({
listenOnly,
color,
voice,
emoji,
avatar,
noVoice,
className,
}) => (
Expand All @@ -60,14 +66,27 @@ const UserAvatar = ({
>

<div className={cx({
[styles.talking]: (talking && !muted),
[styles.talking]: (talking && !muted && avatar.length === 0),
})}
/>


<div className={styles.content}>
{children}
</div>
{avatar.length !== 0 && !emoji
? (
<div className={styles.image}>
<img
className={cx(styles.img, {
[styles.circle]: !moderator,
[styles.square]: moderator,
})}
src={avatar}
/>
</div>
) : (
<div className={styles.content}>
{children}
</div>
)
}
</div>
);

Expand Down
Expand Up @@ -13,7 +13,8 @@

.avatar {
position: relative;
padding-bottom: 2rem;
height: 2.25rem;
min-width: 2.25rem;
border-radius: 50%;
text-align: center;
font-size: .85rem;
Expand Down Expand Up @@ -166,6 +167,25 @@
@include indicatorStyles();
}

.image {
display: flex;
height: 2rem;
width: 2rem;

.img {
object-fit: cover;
overflow: hidden;
}

.circle {
border-radius: 50%;
}

.square {
border-radius: 3px;
}
}

.content {
color: var(--user-avatar-text);
top: 50%;
Expand Down
Expand Up @@ -12,11 +12,14 @@ const defaultProps = {
};

const ChatAvatar = (props) => {
const { color, name, isModerator } = props;
const {
color, name, avatar, isModerator,
} = props;
return (

<UserAvatar
moderator={isModerator}
avatar={avatar}
color={color}
>
{name.toLowerCase().slice(0, 2)}
Expand Down
Expand Up @@ -96,6 +96,7 @@ const ChatListItem = (props) => {
<ChatAvatar
isModerator={chat.isModerator}
color={chat.color}
avatar={chat.avatar}
name={chat.name.toLowerCase().slice(0, 2)}
/>
)}
Expand Down
Expand Up @@ -256,6 +256,7 @@ const getActiveChats = (chatID) => {
const activeChat = op;
activeChat.unreadCounter = UnreadMessages.count(op.userId);
activeChat.name = op.name;
activeChat.avatar = op.avatar;
activeChat.isModerator = op.role === ROLE_MODERATOR;
activeChat.lastActivity = idsWithTimeStamp[`${op.userId}`];
return activeChat;
Expand Down
Expand Up @@ -538,6 +538,8 @@ class UserDropdown extends PureComponent {
voice={voiceUser.isVoiceUser}
noVoice={!voiceUser.isVoiceUser}
color={user.color}
emoji={user.emoji !== 'none'}
avatar={user.avatar}
>
{
userInBreakout
Expand Down
Expand Up @@ -66,13 +66,14 @@ const getNameInitials = (name) => {
return nameInitials.replace(/^\w/, c => c.toUpperCase());
}

const renderGuestUserItem = (name, color, handleAccept, handleDeny, role, sequence, userId, intl) => (
const renderGuestUserItem = (name, color, handleAccept, handleDeny, role, sequence, userId, avatar, intl) => (
<div key={`userlist-item-${userId}`} className={styles.listItem}>
<div key={`user-content-container-${userId}`} className={styles.userContentContainer}>
<div key={`user-avatar-container-${userId}`} className={styles.userAvatar}>
<UserAvatar
key={`user-avatar-${userId}`}
moderator={role === 'MODERATOR'}
avatar={avatar}
color={color}
>
{getNameInitials(name)}
Expand Down Expand Up @@ -123,6 +124,7 @@ const renderPendingUsers = (message, usersArray, action, intl) => {
user.role,
idx + 1,
user.intId,
user.avatar,
intl,
))}
</div>
Expand Down
5 changes: 2 additions & 3 deletions bigbluebutton-web/grails-app/conf/bigbluebutton.properties
Expand Up @@ -254,9 +254,8 @@ html5ClientUrl=${bigbluebutton.web.serverURL}/html5client/join
# The url for where the guest will poll if approved to join or not.
defaultGuestWaitURL=${bigbluebutton.web.serverURL}/client/guest-wait.html

# The default avatar image to display if nothing is passed on the JOIN API (avatarURL)
# call. This avatar is displayed if the user isn't sharing the webcam and
# the option (displayAvatar) is enabled in config.xml
# The default avatar image to display.
useDefaultAvatar=false
defaultAvatarURL=${bigbluebutton.web.serverURL}/client/avatar.png

# The URL of the default configuration
Expand Down
1 change: 1 addition & 0 deletions bigbluebutton-web/grails-app/conf/spring/resources.xml
Expand Up @@ -133,6 +133,7 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
<property name="autoStartRecording" value="${autoStartRecording}"/>
<property name="allowStartStopRecording" value="${allowStartStopRecording}"/>
<property name="webcamsOnlyForModerator" value="${webcamsOnlyForModerator}"/>
<property name="useDefaultAvatar" value="${useDefaultAvatar}"/>
<property name="defaultAvatarURL" value="${defaultAvatarURL}"/>
<property name="defaultConfigURL" value="${defaultConfigURL}"/>
<property name="defaultGuestPolicy" value="${defaultGuestPolicy}"/>
Expand Down

0 comments on commit d5450af

Please sign in to comment.