Show your preferred badge in the left pane and avatar popup
This commit is contained in:
parent
f02b1ebce2
commit
7de340a104
6 changed files with 59 additions and 3 deletions
7
ts/badges/isBadgeVisible.ts
Normal file
7
ts/badges/isBadgeVisible.ts
Normal 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;
|
|
@ -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;
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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}
|
||||
|
|
|
@ -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),
|
||||
};
|
||||
};
|
||||
|
|
31
ts/test-both/badges/isBadgeVisible_test.ts
Normal file
31
ts/test-both/badges/isBadgeVisible_test.ts
Normal 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)));
|
||||
});
|
||||
});
|
Loading…
Reference in a new issue