Show your preferred badge in the left pane and avatar popup

This commit is contained in:
Evan Hahn 2021-11-08 10:29:54 -06:00 committed by GitHub
parent f02b1ebce2
commit 7de340a104
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 59 additions and 3 deletions

View File

@ -0,0 +1,7 @@
// Copyright 2021 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import type { BadgeType } from './types';
export const isBadgeVisible = (badge: Readonly<BadgeType>): boolean =>
'isVisible' in badge ? badge.isVisible : true;

View File

@ -22,6 +22,7 @@ import * as log from '../logging/log';
import { assert } from '../util/assert';
import { shouldBlurAvatar } from '../util/shouldBlurAvatar';
import { getBadgeImageFileLocalPath } from '../badges/getBadgeImageFileLocalPath';
import { isBadgeVisible } from '../badges/isBadgeVisible';
import { BadgeImageTheme } from '../badges/BadgeImageTheme';
export enum AvatarBlur {
@ -212,7 +213,7 @@ export const Avatar: FunctionComponent<Props> = ({
}
let badgeNode: ReactNode;
if (badge && theme && !isMe) {
if (badge && theme && !noteToSelf && isBadgeVisible(badge)) {
const badgeSize = Math.ceil(size * 0.425);
const badgeTheme =
theme === ThemeType.light ? BadgeImageTheme.Light : BadgeImageTheme.Dark;

View File

@ -11,6 +11,7 @@ import enMessages from '../../_locales/en/messages.json';
import type { PropsType } from './MainHeader';
import { MainHeader } from './MainHeader';
import { getDefaultConversation } from '../test-both/helpers/getDefaultConversation';
import { ThemeType } from '../types/Util';
const i18n = setupI18n('en', enMessages);
@ -26,6 +27,7 @@ const createProps = (overrideProps: Partial<PropsType> = {}): PropsType => ({
searchConversation: overrideProps.searchConversation,
selectedConversation: undefined,
startSearchCounter: 0,
theme: ThemeType.light,
phoneNumber: optionalText('phoneNumber', overrideProps.phoneNumber),
title: requiredText('title', overrideProps.title),

View File

@ -8,10 +8,11 @@ import { createPortal } from 'react-dom';
import { showSettings } from '../shims/Whisper';
import { Avatar } from './Avatar';
import { AvatarPopup } from './AvatarPopup';
import type { LocalizerType } from '../types/Util';
import type { LocalizerType, ThemeType } from '../types/Util';
import type { AvatarColorType } from '../types/Colors';
import type { ConversationType } from '../state/ducks/conversations';
import { LeftPaneSearchInput } from './LeftPaneSearchInput';
import type { BadgeType } from '../badges/types';
export type PropsType = {
searchTerm: string;
@ -29,7 +30,9 @@ export type PropsType = {
profileName?: string;
title: string;
avatarPath?: string;
badge?: BadgeType;
hasPendingUpdate: boolean;
theme: ThemeType;
i18n: LocalizerType;
@ -191,6 +194,7 @@ export class MainHeader extends React.Component<PropsType, StateType> {
public render(): JSX.Element {
const {
avatarPath,
badge,
color,
disabled,
hasPendingUpdate,
@ -203,6 +207,7 @@ export class MainHeader extends React.Component<PropsType, StateType> {
showArchivedConversations,
startComposing,
startUpdate,
theme,
title,
toggleProfileEditor,
} = this.props;
@ -219,6 +224,7 @@ export class MainHeader extends React.Component<PropsType, StateType> {
<Avatar
acceptedMessageRequest
avatarPath={avatarPath}
badge={badge}
className="module-main-header__avatar"
color={color}
conversationType="direct"
@ -227,6 +233,7 @@ export class MainHeader extends React.Component<PropsType, StateType> {
name={name}
phoneNumber={phoneNumber}
profileName={profileName}
theme={theme}
title={title}
// `sharedGroupNames` makes no sense for yourself, but
// `<Avatar>` needs it to determine blurring.
@ -247,6 +254,7 @@ export class MainHeader extends React.Component<PropsType, StateType> {
{({ ref, style }) => (
<AvatarPopup
acceptedMessageRequest
badge={badge}
innerRef={ref}
i18n={i18n}
isMe
@ -256,6 +264,7 @@ export class MainHeader extends React.Component<PropsType, StateType> {
name={name}
phoneNumber={phoneNumber}
profileName={profileName}
theme={theme}
title={title}
avatarPath={avatarPath}
size={28}

View File

@ -7,6 +7,7 @@ import { mapDispatchToProps } from '../actions';
import { MainHeader } from '../../components/MainHeader';
import type { StateType } from '../reducer';
import { getPreferredBadgeSelector } from '../selectors/badges';
import {
getQuery,
getSearchConversation,
@ -15,6 +16,7 @@ import {
import {
getIntl,
getRegionCode,
getTheme,
getUserConversationId,
getUserNumber,
getUserUuid,
@ -22,6 +24,8 @@ import {
import { getMe, getSelectedConversation } from '../selectors/conversations';
const mapStateToProps = (state: StateType) => {
const me = getMe(state);
return {
disabled: state.network.challengeStatus !== 'idle',
hasPendingUpdate: Boolean(state.updates.didSnooze),
@ -33,7 +37,9 @@ const mapStateToProps = (state: StateType) => {
ourConversationId: getUserConversationId(state),
ourNumber: getUserNumber(state),
ourUuid: getUserUuid(state),
...getMe(state),
...me,
badge: getPreferredBadgeSelector(state)(me.badges),
theme: getTheme(state),
i18n: getIntl(state),
};
};

View File

@ -0,0 +1,31 @@
// Copyright 2021 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import { assert } from 'chai';
import type { BadgeType } from '../../badges/types';
import { isBadgeVisible } from '../../badges/isBadgeVisible';
import { BadgeCategory } from '../../badges/BadgeCategory';
describe('isBadgeVisible', () => {
const fakeBadge = (isVisible?: boolean): BadgeType => ({
category: BadgeCategory.Donor,
descriptionTemplate: 'test',
id: 'TEST',
images: [],
name: 'test',
...(typeof isVisible === 'boolean' ? { expiresAt: 123, isVisible } : {}),
});
it("returns true if the visibility is unspecified (someone else's badge)", () => {
assert.isTrue(isBadgeVisible(fakeBadge()));
});
it('returns false if not visible', () => {
assert.isFalse(isBadgeVisible(fakeBadge(false)));
});
it('returns true if visible', () => {
assert.isTrue(isBadgeVisible(fakeBadge(true)));
});
});