mirror of
https://github.com/signalapp/Signal-Desktop.git
synced 2026-05-18 21:59:06 +01:00
Updates to release note details pane
This commit is contained in:
@@ -98,6 +98,9 @@
|
||||
|
||||
&__main {
|
||||
flex-grow: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
padding-block: 24px;
|
||||
padding-inline: 10px;
|
||||
|
||||
@@ -1,55 +0,0 @@
|
||||
// Copyright 2021 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
@use '../mixins';
|
||||
|
||||
.BadgeSustainerInstructionsDialog {
|
||||
user-select: none;
|
||||
|
||||
&__width-container {
|
||||
max-width: 420px;
|
||||
}
|
||||
|
||||
&__header {
|
||||
@include mixins.font-title-2;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
&__subheader {
|
||||
@include mixins.font-body-1;
|
||||
font-weight: normal;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
&__instructions {
|
||||
@include mixins.font-body-2;
|
||||
padding: 0;
|
||||
list-style-type: decimal;
|
||||
list-style-position: inside;
|
||||
|
||||
&::before {
|
||||
background-size: contain;
|
||||
content: '';
|
||||
display: block;
|
||||
height: 160px;
|
||||
margin-block: 24px;
|
||||
margin-inline: auto;
|
||||
width: 146px;
|
||||
|
||||
@include mixins.light-theme {
|
||||
background-image: url('../images/mobile-settings-light.svg');
|
||||
}
|
||||
@include mixins.dark-theme {
|
||||
background-image: url('../images/mobile-settings-dark.svg');
|
||||
}
|
||||
}
|
||||
|
||||
> li {
|
||||
margin-top: 1em;
|
||||
|
||||
&:first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -39,7 +39,6 @@ $is-storybook: false !default;
|
||||
@use 'components/BackupMediaDownloadProgressSettings.scss';
|
||||
@use 'components/BadgeCarouselIndex.scss';
|
||||
@use 'components/BadgeDialog.scss';
|
||||
@use 'components/BadgeSustainerInstructionsDialog.scss';
|
||||
@use 'components/BetterAvatarBubble.scss';
|
||||
@use 'components/Button.scss';
|
||||
@use 'components/CallsTab.scss';
|
||||
|
||||
@@ -134,7 +134,7 @@
|
||||
--color-legacy-signal-conversation-bg: light-dark(#F6F7FF, #2F3240);
|
||||
--color-legacy-official-chat-badge-bg: light-dark(--alpha(#4655FF / 12%), --alpha(#4952F8 / 40%));
|
||||
--color-legacy-official-chat-badge-text: light-dark(#030FFC, #C2C5FE);
|
||||
--color-legacy-signal-chat-message-bg: light-dark(#9294BC, #444664);
|
||||
--color-legacy-signal-chat-message-bg: light-dark(#8889B4, #444664);
|
||||
--color-legacy-warning-badge: light-dark(#C84118, #EB977D);
|
||||
}
|
||||
|
||||
|
||||
@@ -27,6 +27,7 @@ const defaultProps: ComponentProps<typeof BadgeDialog> = {
|
||||
firstName: 'Alice',
|
||||
i18n,
|
||||
onClose: action('onClose'),
|
||||
onDonate: action('onDonate'),
|
||||
title: 'Alice Levine',
|
||||
};
|
||||
|
||||
|
||||
@@ -13,44 +13,28 @@ import { Button, ButtonSize } from './Button.dom.tsx';
|
||||
import { BadgeDescription } from './BadgeDescription.dom.tsx';
|
||||
import { BadgeImage } from './BadgeImage.dom.tsx';
|
||||
import { BadgeCarouselIndex } from './BadgeCarouselIndex.dom.tsx';
|
||||
import { BadgeSustainerInstructionsDialog } from './BadgeSustainerInstructionsDialog.dom.tsx';
|
||||
|
||||
export type PropsType = Readonly<{
|
||||
areWeASubscriber: boolean;
|
||||
badges: ReadonlyArray<BadgeType>;
|
||||
firstName?: string;
|
||||
i18n: LocalizerType;
|
||||
onClose: () => unknown;
|
||||
onClose: () => void;
|
||||
onDonate: () => void;
|
||||
title: string;
|
||||
}>;
|
||||
|
||||
export function BadgeDialog(props: PropsType): null | React.JSX.Element {
|
||||
const { badges, i18n, onClose } = props;
|
||||
|
||||
const [isShowingInstructions, setIsShowingInstructions] = useState(false);
|
||||
const { badges, onClose } = props;
|
||||
|
||||
const hasBadges = badges.length > 0;
|
||||
useEffect(() => {
|
||||
if (!hasBadges && !isShowingInstructions) {
|
||||
if (!hasBadges) {
|
||||
onClose();
|
||||
}
|
||||
}, [hasBadges, isShowingInstructions, onClose]);
|
||||
}, [hasBadges, onClose]);
|
||||
|
||||
if (isShowingInstructions) {
|
||||
return (
|
||||
<BadgeSustainerInstructionsDialog
|
||||
i18n={i18n}
|
||||
onClose={() => setIsShowingInstructions(false)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
return hasBadges ? (
|
||||
<BadgeDialogWithBadges
|
||||
{...props}
|
||||
onShowInstructions={() => setIsShowingInstructions(true)}
|
||||
/>
|
||||
) : null;
|
||||
return hasBadges ? <BadgeDialogWithBadges {...props} /> : null;
|
||||
}
|
||||
|
||||
function BadgeDialogWithBadges({
|
||||
@@ -59,9 +43,9 @@ function BadgeDialogWithBadges({
|
||||
firstName,
|
||||
i18n,
|
||||
onClose,
|
||||
onShowInstructions,
|
||||
onDonate,
|
||||
title,
|
||||
}: PropsType & { onShowInstructions: () => unknown }): React.JSX.Element {
|
||||
}: PropsType): React.JSX.Element {
|
||||
const firstBadge = badges[0];
|
||||
strictAssert(
|
||||
firstBadge,
|
||||
@@ -125,7 +109,7 @@ function BadgeDialogWithBadges({
|
||||
currentBadge.category !== BadgeCategory.Donor &&
|
||||
'BadgeDialog__instructions-button--hidden'
|
||||
)}
|
||||
onClick={onShowInstructions}
|
||||
onClick={onDonate}
|
||||
size={ButtonSize.Large}
|
||||
>
|
||||
{i18n('icu:BadgeDialog__become-a-sustainer-button')}
|
||||
|
||||
@@ -1,34 +0,0 @@
|
||||
// Copyright 2021 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import type { ReactElement } from 'react';
|
||||
import React from 'react';
|
||||
import type { LocalizerType } from '../types/Util.std.ts';
|
||||
import { Modal } from './Modal.dom.tsx';
|
||||
|
||||
export function BadgeSustainerInstructionsDialog({
|
||||
i18n,
|
||||
onClose,
|
||||
}: Readonly<{ i18n: LocalizerType; onClose: () => unknown }>): ReactElement {
|
||||
return (
|
||||
<Modal
|
||||
modalName="BadgeSustainerInstructionsDialog"
|
||||
hasXButton
|
||||
moduleClassName="BadgeSustainerInstructionsDialog"
|
||||
i18n={i18n}
|
||||
onClose={onClose}
|
||||
>
|
||||
<h1 className="BadgeSustainerInstructionsDialog__header">
|
||||
{i18n('icu:BadgeSustainerInstructions__header')}
|
||||
</h1>
|
||||
<h2 className="BadgeSustainerInstructionsDialog__subheader">
|
||||
{i18n('icu:BadgeSustainerInstructions__subheader')}
|
||||
</h2>
|
||||
<ol className="BadgeSustainerInstructionsDialog__instructions">
|
||||
<li>{i18n('icu:BadgeSustainerInstructions__instructions__1')}</li>
|
||||
<li>{i18n('icu:BadgeSustainerInstructions__instructions__2')}</li>
|
||||
<li>{i18n('icu:BadgeSustainerInstructions__instructions__3')}</li>
|
||||
</ol>
|
||||
</Modal>
|
||||
);
|
||||
}
|
||||
@@ -71,6 +71,7 @@ type PropsActionType = {
|
||||
blockClientFromCall: (payload: RemoveClientType) => void;
|
||||
blockConversation: (id: string) => void;
|
||||
hideContactModal: () => void;
|
||||
onNavigateToDonate: () => void;
|
||||
onOpenEditNicknameAndNoteModal: () => void;
|
||||
onOutgoingAudioCallInConversation: (conversationId: string) => unknown;
|
||||
onOutgoingVideoCallInConversation: (conversationId: string) => unknown;
|
||||
@@ -127,6 +128,7 @@ export function ContactModal({
|
||||
isMuted,
|
||||
isRemoteMuteVisible,
|
||||
isRemoveFromCallVisible,
|
||||
onNavigateToDonate,
|
||||
onOpenEditNicknameAndNoteModal,
|
||||
onOutgoingAudioCallInConversation,
|
||||
onOutgoingVideoCallInConversation,
|
||||
@@ -682,6 +684,7 @@ export function ContactModal({
|
||||
firstName={contact.firstName}
|
||||
i18n={i18n}
|
||||
onClose={() => setView(ContactModalView.Default)}
|
||||
onDonate={onNavigateToDonate}
|
||||
title={contact.title}
|
||||
/>
|
||||
);
|
||||
|
||||
@@ -9,10 +9,12 @@ export function OfficialChatInlineBadge(): JSX.Element {
|
||||
return (
|
||||
<span
|
||||
className={tw(
|
||||
'relative z-0 text-color-fill-primary',
|
||||
// oxlint-disable-next-line better-tailwindcss/no-unknown-classes
|
||||
'before:content[""] before:absolute before:inset-s-1/6 before:top-1/6 before:bg-label-primary-on-color',
|
||||
'before:legacy-z-index-negative before:size-2/3 before:rounded-full'
|
||||
'relative z-0 inline-block rounded-full text-color-fill-primary',
|
||||
// Since the icon does not have a white checkmark built into the font, by making it a
|
||||
// background of the parent element we can ensure that the background is clipped
|
||||
// whenever the icon is (e.g. for overflow: ellipsis)
|
||||
'bg-linear-0 from-label-primary-on-color to-label-primary-on-color',
|
||||
'bg-size-[50%_50%] bg-center bg-no-repeat'
|
||||
)}
|
||||
>
|
||||
<AxoSymbol.InlineGlyph symbol="officialbadge-fill" label={null} />
|
||||
|
||||
@@ -105,6 +105,7 @@ const createProps = (
|
||||
memberColors,
|
||||
maxGroupSize: 1001,
|
||||
maxRecommendedGroupSize: 151,
|
||||
onNavigateToDonate: action('onNavigateToDonate'),
|
||||
pendingApprovalMemberships: times(8, () => ({
|
||||
member: getDefaultConversation(),
|
||||
})),
|
||||
|
||||
@@ -64,7 +64,6 @@ import {
|
||||
InAnotherCallTooltip,
|
||||
getTooltipContent,
|
||||
} from '../InAnotherCallTooltip.dom.tsx';
|
||||
import { BadgeSustainerInstructionsDialog } from '../../BadgeSustainerInstructionsDialog.dom.tsx';
|
||||
import type { ContactModalStateType } from '../../../types/globalModals.std.ts';
|
||||
import type { ShowToastAction } from '../../../state/ducks/toast.preload.ts';
|
||||
import { ToastType } from '../../../types/Toast.dom.tsx';
|
||||
@@ -72,7 +71,6 @@ import type { ContactNameColorType } from '../../../types/Colors.std.ts';
|
||||
|
||||
enum ModalState {
|
||||
AddingGroupMembers,
|
||||
BecomeSustainer,
|
||||
ConfirmDeleteNicknameAndNote,
|
||||
EditingGroupDescription,
|
||||
EditingGroupTitle,
|
||||
@@ -138,6 +136,7 @@ type ActionProps = {
|
||||
onConversationDeleteMessages: () => void;
|
||||
onConversationUnarchive: () => void;
|
||||
onDeleteNicknameAndNote: () => void;
|
||||
onNavigateToDonate: () => void;
|
||||
onOpenEditNicknameAndNoteModal: () => void;
|
||||
onOutgoingAudioCallInConversation: (conversationId: string) => unknown;
|
||||
onOutgoingVideoCallInConversation: (conversationId: string) => unknown;
|
||||
@@ -206,6 +205,7 @@ export function ConversationDetails({
|
||||
onConversationDeleteMessages,
|
||||
onConversationUnarchive,
|
||||
onDeleteNicknameAndNote,
|
||||
onNavigateToDonate,
|
||||
onOpenEditNicknameAndNoteModal,
|
||||
onOutgoingAudioCallInConversation,
|
||||
onOutgoingVideoCallInConversation,
|
||||
@@ -270,11 +270,6 @@ export function ConversationDetails({
|
||||
case ModalState.NothingOpen:
|
||||
modalNode = undefined;
|
||||
break;
|
||||
case ModalState.BecomeSustainer:
|
||||
modalNode = (
|
||||
<BadgeSustainerInstructionsDialog i18n={i18n} onClose={onCloseModal} />
|
||||
);
|
||||
break;
|
||||
case ModalState.EditingGroupDescription:
|
||||
case ModalState.EditingGroupTitle:
|
||||
modalNode = (
|
||||
@@ -431,6 +426,7 @@ export function ConversationDetails({
|
||||
isGroup={isGroup}
|
||||
isSignalConversation={isSignalConversation}
|
||||
membersCount={conversation.membersCount ?? null}
|
||||
onNavigateToDonate={onNavigateToDonate}
|
||||
pendingAvatarDownload={pendingAvatarDownload ?? false}
|
||||
startAvatarDownload={startAvatarDownload}
|
||||
startEditing={(isGroupTitle: boolean) => {
|
||||
@@ -486,6 +482,15 @@ export function ConversationDetails({
|
||||
<Button
|
||||
icon={isMuted ? ButtonIconType.muted : ButtonIconType.unmuted}
|
||||
onClick={() => {
|
||||
if (isSignalConversation) {
|
||||
if (isMuted) {
|
||||
setMuteExpiration(conversation.id, 0);
|
||||
} else {
|
||||
setMuteExpiration(conversation.id, Number.MAX_SAFE_INTEGER);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (isMuted) {
|
||||
setModalState(ModalState.UnmuteNotifications);
|
||||
} else {
|
||||
@@ -567,7 +572,7 @@ export function ConversationDetails({
|
||||
/>
|
||||
}
|
||||
label={i18n('icu:BadgeDialog__become-a-sustainer-button')}
|
||||
onClick={() => setModalState(ModalState.BecomeSustainer)}
|
||||
onClick={onNavigateToDonate}
|
||||
/>
|
||||
</PanelSection>
|
||||
</>
|
||||
|
||||
+1
@@ -43,6 +43,7 @@ function Wrapper(overrideProps: Partial<Props>) {
|
||||
isGroup
|
||||
isMe={false}
|
||||
isSignalConversation={false}
|
||||
onNavigateToDonate={action('onNavigateToDonate')}
|
||||
pendingAvatarDownload={false}
|
||||
startAvatarDownload={action('startAvatarDownload')}
|
||||
theme={theme}
|
||||
|
||||
@@ -31,6 +31,7 @@ export type Props = {
|
||||
isMe: boolean;
|
||||
isSignalConversation: boolean;
|
||||
membersCount: number | null;
|
||||
onNavigateToDonate: () => void;
|
||||
pendingAvatarDownload: boolean;
|
||||
startAvatarDownload: () => void;
|
||||
startEditing: (isGroupTitle: boolean) => void;
|
||||
@@ -53,6 +54,7 @@ export function ConversationDetailsHeader({
|
||||
isMe,
|
||||
isSignalConversation,
|
||||
membersCount,
|
||||
onNavigateToDonate,
|
||||
pendingAvatarDownload,
|
||||
startAvatarDownload,
|
||||
startEditing,
|
||||
@@ -155,6 +157,10 @@ export function ConversationDetailsHeader({
|
||||
onClose={() => {
|
||||
setActiveModal(undefined);
|
||||
}}
|
||||
onDonate={() => {
|
||||
setActiveModal(undefined);
|
||||
onNavigateToDonate();
|
||||
}}
|
||||
title={conversation.title}
|
||||
/>
|
||||
);
|
||||
|
||||
@@ -27,6 +27,8 @@ import { strictAssert } from '../../util/assert.std.ts';
|
||||
import { CallMode } from '../../types/CallDisposition.std.ts';
|
||||
import { isCallLinkAdmin } from '../../types/CallLink.std.ts';
|
||||
import { isFeaturedEnabledSelector } from '../../util/isFeatureEnabled.dom.ts';
|
||||
import { useNavActions } from '../ducks/nav.std.ts';
|
||||
import { NavTab, SettingsPage } from '../../types/Nav.std.ts';
|
||||
|
||||
export const SmartContactModal = memo(function SmartContactModal() {
|
||||
const i18n = useSelector(getIntl);
|
||||
@@ -105,6 +107,7 @@ export const SmartContactModal = memo(function SmartContactModal() {
|
||||
toggleGroupMemberLabelInfoModal,
|
||||
toggleSafetyNumberModal,
|
||||
} = useGlobalModalActions();
|
||||
const { changeLocation } = useNavActions();
|
||||
const {
|
||||
blockClient: blockClientFromCall,
|
||||
onOutgoingVideoCallInConversation,
|
||||
@@ -119,6 +122,16 @@ export const SmartContactModal = memo(function SmartContactModal() {
|
||||
toggleEditNicknameAndNoteModal({ conversationId: contactId });
|
||||
}, [toggleEditNicknameAndNoteModal, contactId]);
|
||||
|
||||
const onNavigateToDonate = useCallback(() => {
|
||||
hideContactModal();
|
||||
changeLocation({
|
||||
tab: NavTab.Settings,
|
||||
details: {
|
||||
page: SettingsPage.DonationsDonateFlow,
|
||||
},
|
||||
});
|
||||
}, [hideContactModal, changeLocation]);
|
||||
|
||||
return (
|
||||
<ContactModal
|
||||
areWeAdmin={areWeAdmin}
|
||||
@@ -142,6 +155,7 @@ export const SmartContactModal = memo(function SmartContactModal() {
|
||||
isRemoteMuteVisible={isRemoteMuteVisible}
|
||||
isRemoveFromCallVisible={isRemoveFromCallVisible}
|
||||
activeCallDemuxId={activeCallDemuxId}
|
||||
onNavigateToDonate={onNavigateToDonate}
|
||||
onOpenEditNicknameAndNoteModal={handleOpenEditNicknameAndNoteModal}
|
||||
onOutgoingAudioCallInConversation={onOutgoingAudioCallInConversation}
|
||||
onOutgoingVideoCallInConversation={onOutgoingVideoCallInConversation}
|
||||
|
||||
@@ -54,6 +54,7 @@ import { isFeaturedEnabledSelector } from '../../util/isFeatureEnabled.dom.ts';
|
||||
import { getCanAddLabel } from '../../types/GroupMemberLabels.std.ts';
|
||||
import { useToastActions } from '../ducks/toast.preload.ts';
|
||||
import { useNavActions } from '../ducks/nav.std.ts';
|
||||
import { NavTab, SettingsPage } from '../../types/Nav.std.ts';
|
||||
|
||||
const { sortBy } = lodash;
|
||||
|
||||
@@ -143,7 +144,7 @@ export const SmartConversationDetails = memo(function SmartConversationDetails({
|
||||
updateGroupAttributes,
|
||||
updateNicknameAndNote,
|
||||
} = useConversationsActions();
|
||||
const { pushPanelForConversation } = useNavActions();
|
||||
const { pushPanelForConversation, changeLocation } = useNavActions();
|
||||
const {
|
||||
onOutgoingAudioCallInConversation,
|
||||
onOutgoingVideoCallInConversation,
|
||||
@@ -232,6 +233,15 @@ export const SmartConversationDetails = memo(function SmartConversationDetails({
|
||||
destroyMessages(conversationId);
|
||||
}, [destroyMessages, conversationId]);
|
||||
|
||||
const onNavigateToDonate = useCallback(() => {
|
||||
changeLocation({
|
||||
tab: NavTab.Settings,
|
||||
details: {
|
||||
page: SettingsPage.DonationsDonateFlow,
|
||||
},
|
||||
});
|
||||
}, [changeLocation]);
|
||||
|
||||
const [hasMedia, setHasMedia] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
@@ -286,6 +296,7 @@ export const SmartConversationDetails = memo(function SmartConversationDetails({
|
||||
onConversationDeleteMessages={onConversationDeleteMessages}
|
||||
onConversationUnarchive={onConversationUnarchive}
|
||||
onDeleteNicknameAndNote={handleDeleteNicknameAndNote}
|
||||
onNavigateToDonate={onNavigateToDonate}
|
||||
onOpenEditNicknameAndNoteModal={handleOpenEditNicknameAndNoteModal}
|
||||
onOutgoingAudioCallInConversation={onOutgoingAudioCallInConversation}
|
||||
onOutgoingVideoCallInConversation={onOutgoingVideoCallInConversation}
|
||||
|
||||
Reference in New Issue
Block a user