diff --git a/images/icons/v2/refresh-24.svg b/images/icons/v2/refresh-24.svg new file mode 100644 index 0000000000..65a19cf6c4 --- /dev/null +++ b/images/icons/v2/refresh-24.svg @@ -0,0 +1,4 @@ + + + + diff --git a/stylesheets/_modules.scss b/stylesheets/_modules.scss index 6f6d8b1783..14bc179e03 100644 --- a/stylesheets/_modules.scss +++ b/stylesheets/_modules.scss @@ -2924,6 +2924,12 @@ $timer-icons: '55', '50', '45', '40', '35', '30', '25', '20', '15', '10', '05', .module-conversation-header__title-clickable { cursor: pointer; + + &:focus { + @include mouse-mode { + outline: none; + } + } } .module-conversation-header__note-to-self { @@ -3189,7 +3195,7 @@ button.module-conversation-details__action-button { } &__title { - @include font-body-1-bold; + @include font-title-1; padding-top: 12px; padding-bottom: 8px; } @@ -3205,6 +3211,14 @@ button.module-conversation-details__action-button { } } + &__leave-group { + color: $color-accent-red; + } + + &__block-group { + color: $color-accent-red; + } + &__tabs { display: flex; justify-content: space-around; @@ -3342,8 +3356,7 @@ button.module-conversation-details__action-button { &--reset { &::after { - transform: scaleX(-1); - -webkit-mask: url(../images/icons/v2/undo-24.svg) no-repeat center; + -webkit-mask: url(../images/icons/v2/refresh-24.svg) no-repeat center; @include light-theme { background-color: $color-gray-75; @@ -3430,6 +3443,7 @@ button.module-conversation-details__action-button { display: flex; justify-content: center; padding: 0 20px; + padding-bottom: 24px; .module-media-grid-item { border-radius: 4px; @@ -3458,6 +3472,13 @@ button.module-conversation-details__action-button { background: none; border: none; padding: 0; + + @include light-theme { + color: $color-gray-95; + } + @include dark-theme { + color: $color-gray-05; + } } } diff --git a/ts/components/conversation/ConversationHeader.tsx b/ts/components/conversation/ConversationHeader.tsx index ad5028fb2c..c515539d04 100644 --- a/ts/components/conversation/ConversationHeader.tsx +++ b/ts/components/conversation/ConversationHeader.tsx @@ -487,13 +487,15 @@ export class ConversationHeader extends React.Component { private renderHeader(): JSX.Element { const { conversationTitle, + groupVersion, id, isMe, onShowContactModal, + onShowConversationDetails, type, } = this.props; - if (conversationTitle) { + if (conversationTitle !== undefined) { return (
@@ -503,6 +505,35 @@ export class ConversationHeader extends React.Component { ); } + const hasGV2AdminEnabled = + groupVersion === 2 && + window.Signal.RemoteConfig.isEnabled('desktop.gv2Admin'); + + if (type === 'group' && hasGV2AdminEnabled) { + const onHeaderClick = () => onShowConversationDetails(); + const onKeyDown = (e: React.KeyboardEvent): void => { + if (e.key === 'Enter' || e.key === ' ') { + e.stopPropagation(); + e.preventDefault(); + + onShowConversationDetails(); + } + }; + + return ( +
+ {this.renderAvatar()} + {this.renderTitle()} +
+ ); + } + if (type === 'group' || isMe) { return (
diff --git a/ts/components/conversation/conversation-details/ConversationDetailsActions.tsx b/ts/components/conversation/conversation-details/ConversationDetailsActions.tsx index 5b09d07e02..707682a2cf 100644 --- a/ts/components/conversation/conversation-details/ConversationDetailsActions.tsx +++ b/ts/components/conversation/conversation-details/ConversationDetailsActions.tsx @@ -37,7 +37,11 @@ export const ConversationDetailsActions: React.ComponentType = ({ icon="leave" /> } - label={i18n('ConversationDetailsActions--leave-group')} + label={ +
+ {i18n('ConversationDetailsActions--leave-group')} +
+ } /> setConfirmingBlock(true)} @@ -47,7 +51,11 @@ export const ConversationDetailsActions: React.ComponentType = ({ icon="block" /> } - label={i18n('ConversationDetailsActions--block-group')} + label={ +
+ {i18n('ConversationDetailsActions--block-group')} +
+ } /> diff --git a/ts/components/conversation/conversation-details/ConversationDetailsMembershipList.stories.tsx b/ts/components/conversation/conversation-details/ConversationDetailsMembershipList.stories.tsx index fda68f5ada..8a4a58fad6 100644 --- a/ts/components/conversation/conversation-details/ConversationDetailsMembershipList.stories.tsx +++ b/ts/components/conversation/conversation-details/ConversationDetailsMembershipList.stories.tsx @@ -45,16 +45,32 @@ const createProps = (overrideProps: Partial): Props => ({ memberships: overrideProps.memberships || [], }); -story.add('Basic', () => { - const memberships = createMemberships(10); +story.add('Few', () => { + const memberships = createMemberships(3); const props = createProps({ memberships }); return ; }); -story.add('Few', () => { - const memberships = createMemberships(3); +story.add('Limit', () => { + const memberships = createMemberships(5); + + const props = createProps({ memberships }); + + return ; +}); + +story.add('Limit +1', () => { + const memberships = createMemberships(6); + + const props = createProps({ memberships }); + + return ; +}); + +story.add('Limit +2', () => { + const memberships = createMemberships(7); const props = createProps({ memberships }); diff --git a/ts/components/conversation/conversation-details/ConversationDetailsMembershipList.tsx b/ts/components/conversation/conversation-details/ConversationDetailsMembershipList.tsx index 0115823b21..01c191040e 100644 --- a/ts/components/conversation/conversation-details/ConversationDetailsMembershipList.tsx +++ b/ts/components/conversation/conversation-details/ConversationDetailsMembershipList.tsx @@ -24,7 +24,7 @@ export type Props = { i18n: LocalizerType; }; -const INITIAL_MEMBER_COUNT = 5; +const MAX_MEMBER_COUNT = 5; export const ConversationDetailsMembershipList: React.ComponentType = ({ memberships, @@ -33,44 +33,47 @@ export const ConversationDetailsMembershipList: React.ComponentType = ({ }) => { const [showAllMembers, setShowAllMembers] = React.useState(false); + const shouldHideRestMembers = memberships.length - MAX_MEMBER_COUNT > 1; + const membersToShow = + shouldHideRestMembers && !showAllMembers + ? MAX_MEMBER_COUNT + : memberships.length; + return ( - {memberships - .slice(0, showAllMembers ? undefined : INITIAL_MEMBER_COUNT) - .map(({ isAdmin, member }) => ( - showContactModal(member.id)} - icon={ - - } - label={member.title} - right={isAdmin ? i18n('GroupV2--admin') : ''} - /> - ))} - {showAllMembers === false && - memberships.length > INITIAL_MEMBER_COUNT && ( - - } - onClick={() => setShowAllMembers(true)} - label={i18n('ConversationDetailsMembershipList--show-all')} - /> - )} + {memberships.slice(0, membersToShow).map(({ isAdmin, member }) => ( + showContactModal(member.id)} + icon={ + + } + label={member.title} + right={isAdmin ? i18n('GroupV2--admin') : ''} + /> + ))} + {showAllMembers === false && shouldHideRestMembers && ( + + } + onClick={() => setShowAllMembers(true)} + label={i18n('ConversationDetailsMembershipList--show-all')} + /> + )} ); }; diff --git a/ts/components/conversation/conversation-details/PanelRow.stories.tsx b/ts/components/conversation/conversation-details/PanelRow.stories.tsx index d6be023525..0533a0dc27 100644 --- a/ts/components/conversation/conversation-details/PanelRow.stories.tsx +++ b/ts/components/conversation/conversation-details/PanelRow.stories.tsx @@ -19,7 +19,7 @@ const createProps = (overrideProps: Partial = {}): Props => ({ icon: boolean('with icon', overrideProps.icon !== undefined) ? ( ) : null, - label: text('label', overrideProps.label || ''), + label: text('label', (overrideProps.label as string) || ''), info: text('info', overrideProps.info || ''), right: text('right', (overrideProps.right as string) || ''), actions: boolean('with action', overrideProps.actions !== undefined) ? ( diff --git a/ts/components/conversation/conversation-details/PanelRow.tsx b/ts/components/conversation/conversation-details/PanelRow.tsx index 81347c531c..06550b923b 100644 --- a/ts/components/conversation/conversation-details/PanelRow.tsx +++ b/ts/components/conversation/conversation-details/PanelRow.tsx @@ -9,7 +9,7 @@ export type Props = { alwaysShowActions?: boolean; className?: string; icon?: React.ReactNode; - label: string; + label: string | React.ReactNode; info?: string; right?: string | React.ReactNode; actions?: React.ReactNode; @@ -30,15 +30,15 @@ export const PanelRow: React.ComponentType = ({ }) => { const content = ( <> - {icon &&
{icon}
} + {icon !== undefined ?
{icon}
: null}
{label}
- {info &&
{info}
} + {info !== undefined ?
{info}
: null}
- {right &&
{right}
} - {actions && ( + {right !== undefined ?
{right}
: null} + {actions !== undefined ? (
{actions}
- )} + ) : null} ); diff --git a/ts/groups.ts b/ts/groups.ts index ad3ee6dc9f..e7d56c4870 100644 --- a/ts/groups.ts +++ b/ts/groups.ts @@ -274,7 +274,7 @@ export function buildGroupLink(conversation: ConversationModel): string { const bytes = proto.toArrayBuffer(); const hash = toWebSafeBase64(window.Signal.Crypto.arrayBufferToBase64(bytes)); - return `sgnl://signal.group/#${hash}`; + return `https://signal.group/#${hash}`; } export function parseGroupLink(