feat: move back conversation request buttons to the bottom

because we can
pull/3281/head
Audric Ackermann 10 months ago
parent d8bc48938b
commit b1b557581b
No known key found for this signature in database

@ -15,13 +15,12 @@ import { SessionButton, SessionButtonColor } from '../basic/SessionButton';
import { import {
ConversationIncomingRequestExplanation, ConversationIncomingRequestExplanation,
ConversationOutgoingRequestExplanation, ConversationOutgoingRequestExplanation,
InvitedToGroupControlMessage,
} from './SubtleNotification'; } from './SubtleNotification';
import { NetworkTime } from '../../util/NetworkTime'; import { NetworkTime } from '../../util/NetworkTime';
const MessageRequestContainer = styled.div` const MessageRequestContainer = styled.div`
display: flex; display: flex;
flex-direction: column; flex-direction: column-reverse;
justify-content: center; justify-content: center;
padding: var(--margins-lg); padding: var(--margins-lg);
gap: var(--margins-lg); gap: var(--margins-lg);
@ -98,7 +97,6 @@ export const ConversationMessageRequestButtons = () => {
return ( return (
<MessageRequestContainer> <MessageRequestContainer>
<InvitedToGroupControlMessage />
<ConversationBannerRow> <ConversationBannerRow>
<SessionButton <SessionButton
onClick={() => { onClick={() => {

@ -58,7 +58,7 @@ import { ConversationMessageRequestButtons } from './MessageRequestButtons';
import { RightPanel, StyledRightPanelContainer } from './right-panel/RightPanel'; import { RightPanel, StyledRightPanelContainer } from './right-panel/RightPanel';
import { HTMLDirection } from '../../util/i18n/rtlSupport'; import { HTMLDirection } from '../../util/i18n/rtlSupport';
import { showLinkVisitWarningDialog } from '../dialog/OpenUrlModal'; import { showLinkVisitWarningDialog } from '../dialog/OpenUrlModal';
import { NoMessageInConversation } from './SubtleNotification'; import { InvitedToGroup, NoMessageInConversation } from './SubtleNotification';
const DEFAULT_JPEG_QUALITY = 0.85; const DEFAULT_JPEG_QUALITY = 0.85;
@ -265,7 +265,8 @@ export class SessionConversation extends Component<Props, State> {
> >
<div className="conversation-messages"> <div className="conversation-messages">
<NoMessageInConversation /> <NoMessageInConversation />
<ConversationMessageRequestButtons /> <InvitedToGroup />
<SplitViewContainer <SplitViewContainer
top={<InConversationCallContainer />} top={<InConversationCallContainer />}
bottom={ bottom={
@ -276,6 +277,8 @@ export class SessionConversation extends Component<Props, State> {
} }
disableTop={!this.props.hasOngoingCallWithFocusedConvo} disableTop={!this.props.hasOngoingCallWithFocusedConvo}
/> />
<ConversationMessageRequestButtons />
{isDraggingFile && <SessionFileDropzone />} {isDraggingFile && <SessionFileDropzone />}
</div> </div>

@ -155,7 +155,7 @@ const GroupRequestExplanation = () => {
); );
}; };
export const InvitedToGroupControlMessage = () => { const InvitedToGroupControlMessage = () => {
const selectedConversation = useSelectedConversationKey(); const selectedConversation = useSelectedConversationKey();
const isGroupV2 = useSelectedIsGroupV2(); const isGroupV2 = useSelectedIsGroupV2();
const hasMessages = useSelectedHasMessages(); const hasMessages = useSelectedHasMessages();
@ -202,6 +202,14 @@ export const InvitedToGroupControlMessage = () => {
); );
}; };
export const InvitedToGroup = () => {
return (
<Container noExtraPadding={false}>
<InvitedToGroupControlMessage />
</Container>
);
};
export const NoMessageInConversation = () => { export const NoMessageInConversation = () => {
const selectedConversation = useSelectedConversationKey(); const selectedConversation = useSelectedConversationKey();
const hasMessages = useSelectedHasMessages(); const hasMessages = useSelectedHasMessages();

@ -21,6 +21,7 @@ import { ed25519Str } from '../../session/utils/String';
import { UserGroupsWrapperActions } from '../../webworker/workers/browser/libsession_worker_interface'; import { UserGroupsWrapperActions } from '../../webworker/workers/browser/libsession_worker_interface';
import { NetworkTime } from '../../util/NetworkTime'; import { NetworkTime } from '../../util/NetworkTime';
import { MessageQueue } from '../../session/sending'; import { MessageQueue } from '../../session/sending';
import { WithLocalMessageDeletionType } from '../../session/types/with';
async function unsendMessagesForEveryone1o1AndLegacy( async function unsendMessagesForEveryone1o1AndLegacy(
conversation: ConversationModel, conversation: ConversationModel,
@ -103,7 +104,8 @@ export async function unsendMessagesForEveryoneGroupV2({
*/ */
async function unsendMessagesForEveryone( async function unsendMessagesForEveryone(
conversation: ConversationModel, conversation: ConversationModel,
msgsToDelete: Array<MessageModel> msgsToDelete: Array<MessageModel>,
{ deletionType }: WithLocalMessageDeletionType
) { ) {
window?.log?.info('Deleting messages for all users in this conversation'); window?.log?.info('Deleting messages for all users in this conversation');
const destinationId = conversation.id as string; const destinationId = conversation.id as string;
@ -134,7 +136,11 @@ async function unsendMessagesForEveryone(
allMessagesFrom: [], // currently we cannot remove all the messages from a specific pubkey but we do already handle them on the receiving side allMessagesFrom: [], // currently we cannot remove all the messages from a specific pubkey but we do already handle them on the receiving side
}); });
} }
await deleteMessagesFromSwarmAndCompletelyLocally(conversation, msgsToDelete); if (deletionType === 'complete') {
await deleteMessagesFromSwarmAndCompletelyLocally(conversation, msgsToDelete);
} else {
await deleteMessagesFromSwarmAndMarkAsDeletedLocally(conversation, msgsToDelete);
}
window.inboxStore?.dispatch(resetSelectedMessageIds()); window.inboxStore?.dispatch(resetSelectedMessageIds());
ToastUtils.pushDeleted(msgsToDelete.length); ToastUtils.pushDeleted(msgsToDelete.length);
@ -311,10 +317,9 @@ export async function deleteMessageLocallyOnly({
conversation, conversation,
message, message,
deletionType, deletionType,
}: { }: WithLocalMessageDeletionType & {
conversation: ConversationModel; conversation: ConversationModel;
message: MessageModel; message: MessageModel;
deletionType: 'complete' | 'markDeleted';
}) { }) {
if (deletionType === 'complete') { if (deletionType === 'complete') {
// remove the message from the database // remove the message from the database
@ -446,7 +451,9 @@ const doDeleteSelectedMessages = async ({
} }
} }
// if they are all ours, of not but we are an admin, we can move forward // if they are all ours, of not but we are an admin, we can move forward
await unsendMessagesForEveryone(conversation, selectedMessages); await unsendMessagesForEveryone(conversation, selectedMessages, {
deletionType: 'markDeleted', // 03 groups: mark as deleted
});
return; return;
} }
@ -455,13 +462,13 @@ const doDeleteSelectedMessages = async ({
window.inboxStore?.dispatch(resetSelectedMessageIds()); window.inboxStore?.dispatch(resetSelectedMessageIds());
return; return;
} }
await unsendMessagesForEveryone(conversation, selectedMessages); await unsendMessagesForEveryone(conversation, selectedMessages, { deletionType: 'complete' }); // not 03 group: delete completely
return; return;
} }
// delete just for me in a legacy closed group only means delete locally // delete just for me in a legacy closed group only means delete locally
if (conversation.isClosedGroup()) { if (conversation.isClosedGroup()) {
await deleteMessagesFromSwarmAndCompletelyLocally(conversation, selectedMessages); await deleteMessagesFromSwarmAndMarkAsDeletedLocally(conversation, selectedMessages);
// Update view and trigger update // Update view and trigger update
window.inboxStore?.dispatch(resetSelectedMessageIds()); window.inboxStore?.dispatch(resetSelectedMessageIds());

@ -752,7 +752,7 @@ export class MessageModel extends Backbone.Model<MessageAttributes> {
props.text = body; props.text = body;
} }
if (this.get('isDeleted')) { if (this.get('isDeleted')) {
props.isDeleted = this.get('isDeleted'); props.isDeleted = !!this.get('isDeleted');
} }
if (this.getMessageHash()) { if (this.getMessageHash()) {

@ -68,7 +68,7 @@ async function getInitializedGroupObject({
if (!found) { if (!found) {
found = { found = {
authData: null, authData: null,
joinedAtSeconds: Math.floor(Date.now()/ 1000), joinedAtSeconds: Math.floor(Date.now() / 1000),
name: groupName, name: groupName,
priority: 0, priority: 0,
pubkeyHex: groupPk, pubkeyHex: groupPk,
@ -410,7 +410,7 @@ async function handleGroupUpdateMemberLeftNotificationMessage({
}); });
} }
async function handleGroupDeleteMemberContentMessage({ async function handleGroupUpdateDeleteMemberContentMessage({
groupPk, groupPk,
signatureTimestamp, signatureTimestamp,
change, change,
@ -420,7 +420,7 @@ async function handleGroupDeleteMemberContentMessage({
if (!convo) { if (!convo) {
return; return;
} }
window.log.info(`handleGroupDeleteMemberContentMessage for ${ed25519Str(groupPk)}`); window.log.info(`handleGroupUpdateDeleteMemberContentMessage for ${ed25519Str(groupPk)}`);
/** /**
* When handling a GroupUpdateDeleteMemberContentMessage we need to do a few things. * When handling a GroupUpdateDeleteMemberContentMessage we need to do a few things.
@ -428,10 +428,8 @@ async function handleGroupDeleteMemberContentMessage({
* 1. we only delete the messageHashes which are in the change.messageHashes AND sent by that same author. * 1. we only delete the messageHashes which are in the change.messageHashes AND sent by that same author.
* When `adminSignature` is not empty and valid, * When `adminSignature` is not empty and valid,
* 2. we delete all the messages in the group sent by any of change.memberSessionIds AND * 2. we delete all the messages in the group sent by any of change.memberSessionIds AND
* 3. we delete all the messageHashes in the conversation matching the change.messageHashes (even if not from the right sender) * 3. we mark as deleted all the messageHashes in the conversation matching the change.messageHashes (even if not from the right sender)
* *
* Note: we never fully delete those messages locally, but only empty them and mark them as deleted with the
* "This message was deleted" placeholder.
* Eventually, we will be able to delete those "deleted by kept locally" messages with placeholders. * Eventually, we will be able to delete those "deleted by kept locally" messages with placeholders.
*/ */
@ -445,8 +443,8 @@ async function handleGroupDeleteMemberContentMessage({
signatureTimestamp, signatureTimestamp,
}); });
// we don't want to hang while for too long here // we don't want to hang for too long here
// processing the handleGroupDeleteMemberContentMessage itself // processing the handleGroupUpdateDeleteMemberContentMessage itself
// (we are running on the receiving pipeline here) // (we are running on the receiving pipeline here)
// so network calls are not allowed. // so network calls are not allowed.
for (let index = 0; index < messageModels.length; index++) { for (let index = 0; index < messageModels.length; index++) {
@ -456,7 +454,7 @@ async function handleGroupDeleteMemberContentMessage({
await messageModel.markAsDeleted(); await messageModel.markAsDeleted();
} catch (e) { } catch (e) {
window.log.warn( window.log.warn(
`handleGroupDeleteMemberContentMessage markAsDeleted non-admin of ${messageModel.getMessageHash()} failed with`, `handleGroupUpdateDeleteMemberContentMessage markAsDeleted non-admin of ${messageModel.getMessageHash()} failed with`,
e.message e.message
); );
} }
@ -488,6 +486,7 @@ async function handleGroupDeleteMemberContentMessage({
toRemove, toRemove,
signatureTimestamp, signatureTimestamp,
}); // this is step 2. }); // this is step 2.
const modelsByHashes = await Data.findAllMessageHashesInConversation({ const modelsByHashes = await Data.findAllMessageHashesInConversation({
groupPk, groupPk,
messageHashes: change.messageHashes, messageHashes: change.messageHashes,
@ -731,7 +730,7 @@ async function handleGroupUpdateMessage(
return; return;
} }
if (details.updateMessage.deleteMemberContent) { if (details.updateMessage.deleteMemberContent) {
await handleGroupDeleteMemberContentMessage({ await handleGroupUpdateDeleteMemberContentMessage({
change: details.updateMessage change: details.updateMessage
.deleteMemberContent as SignalService.GroupUpdateDeleteMemberContentMessage, .deleteMemberContent as SignalService.GroupUpdateDeleteMemberContentMessage,
...detailsWithContext, ...detailsWithContext,

@ -20,3 +20,5 @@ export type WithBatchMethod<T extends string> = { method: T };
export type WithConvoId = { conversationId: string }; export type WithConvoId = { conversationId: string };
export type WithMessageId = { messageId: string }; export type WithMessageId = { messageId: string };
export type WithLocalMessageDeletionType = { deletionType: 'complete' | 'markDeleted' };

@ -41,9 +41,7 @@ export const useAuthorProfileName = (messageId: string): string | null => {
const authorProfileName = senderIsUs const authorProfileName = senderIsUs
? window.i18n('you') ? window.i18n('you')
: senderProps.nickname || : senderProps.nickname || senderProps.displayNameInProfile || PubKey.shorten(sender);
senderProps.displayNameInProfile ||
PubKey.shorten(sender);
return authorProfileName || window.i18n('unknown'); return authorProfileName || window.i18n('unknown');
}; };
@ -70,7 +68,7 @@ export const useAuthorAvatarPath = (messageId: string): string | null => {
export const useMessageIsDeleted = (messageId: string): boolean => { export const useMessageIsDeleted = (messageId: string): boolean => {
const props = useMessagePropsByMessageId(messageId); const props = useMessagePropsByMessageId(messageId);
return props?.propsForMessage.isDeleted || false; return !!props?.propsForMessage.isDeleted || false;
}; };
export const useFirstMessageOfSeries = (messageId: string | undefined): boolean => { export const useFirstMessageOfSeries = (messageId: string | undefined): boolean => {

Loading…
Cancel
Save