Skip to content

Commit c6af39b

Browse files
author
MargeBot
committed
Merge branch 'MEET-583' into 'main'
Improve the “link expired” error message See merge request web/clients!25267
2 parents 2413529 + 07b7146 commit c6af39b

6 files changed

Lines changed: 152 additions & 17 deletions

File tree

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
import { useHistory } from 'react-router-dom';
2+
3+
import { c } from 'ttag';
4+
5+
import { useMeetDispatch, useMeetSelector } from '@proton/meet/store/hooks';
6+
import { selectInvalidMeetingLinkModalOpen, setInvalidMeetingLinkModalOpen } from '@proton/meet/store/slices';
7+
import { isMobile } from '@proton/shared/lib/helpers/browser';
8+
import invalidLinkIcon from '@proton/styles/assets/img/meet/invalid-link.svg';
9+
10+
import { ConfirmationModal } from '../ConfirmationModal/ConfirmationModal';
11+
12+
export const InvalidMeetingLinkModal = () => {
13+
const dispatch = useMeetDispatch();
14+
const history = useHistory();
15+
const open = useMeetSelector(selectInvalidMeetingLinkModalOpen);
16+
17+
if (!open) {
18+
return null;
19+
}
20+
21+
const close = () => dispatch(setInvalidMeetingLinkModalOpen(false));
22+
23+
return (
24+
<ConfirmationModal
25+
icon={
26+
<img
27+
className="mx-auto w-custom h-custom"
28+
src={invalidLinkIcon}
29+
alt=""
30+
style={
31+
isMobile()
32+
? {
33+
'--w-custom': '3rem',
34+
'--h-custom': '3rem',
35+
}
36+
: {
37+
'--w-custom': '5rem',
38+
'--h-custom': '5rem',
39+
}
40+
}
41+
/>
42+
}
43+
title={c('Title').t`Invalid meeting link`}
44+
message={c('Info')
45+
.t`The meeting link you tried to open doesn't exist or may have expired. Make sure the link is correct, or start a new secure meeting instead.`}
46+
primaryText={c('Action').t`Start new meeting`}
47+
onPrimaryAction={() => {
48+
close();
49+
history.push({ pathname: '/join' });
50+
}}
51+
secondaryText={c('Action').t`Close`}
52+
onSecondaryAction={close}
53+
onClose={close}
54+
/>
55+
);
56+
};

applications/meet/src/app/containers/DashboardContainer/DashboardContainer.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import { useFlag } from '@proton/unleash/useFlag';
1616

1717
import { CTAModal } from '../../components/AnonymousModal/CTAModal';
1818
import { CreateRoomModal } from '../../components/CreateRoomModal/CreateRoomModal';
19+
import { InvalidMeetingLinkModal } from '../../components/InvalidMeetingLinkModal/InvalidMeetingLinkModal';
1920
import { JoinWithLinkModal } from '../../components/JoinWithLinkModal/JoinWithLinkModal';
2021
import { ScheduleMeetingModal } from '../../components/ScheduleMeetingModal/ScheduleMeetingModal';
2122
import { useDependencySetup } from '../../hooks/useDependencySetup';
@@ -152,6 +153,7 @@ export const DashboardContainer = () => {
152153
setNewlyCreatedMeetingId(id);
153154
}}
154155
/>
156+
<InvalidMeetingLinkModal />
155157
</>
156158
);
157159
};

applications/meet/src/app/containers/DashboardContainer/GuestDashboardContainer.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import { APPS } from '@proton/shared/lib/constants';
1212
import { isElectronMeet } from '@proton/shared/lib/helpers/desktop';
1313

1414
import { CTAModal } from '../../components/AnonymousModal/CTAModal';
15+
import { InvalidMeetingLinkModal } from '../../components/InvalidMeetingLinkModal/InvalidMeetingLinkModal';
1516
import { JoinWithLinkModal } from '../../components/JoinWithLinkModal/JoinWithLinkModal';
1617
import { MeetingListStatus } from '../../hooks/useMeetingList';
1718
import { DashboardContainerBody } from './DashboardContainerBody';
@@ -79,6 +80,7 @@ export const GuestDashboardContainer = () => {
7980
onClose={handleJoinWithLinkModalClose}
8081
onJoin={(meetingId, meetingPassword) => history.push(getMeetingLink(meetingId, meetingPassword))}
8182
/>
83+
<InvalidMeetingLinkModal />
8284
</>
8385
);
8486
};

applications/meet/src/app/containers/ProtonMeetContainer/ProtonMeetContainer.tsx

Lines changed: 8 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,12 @@ import { useHistory, useLocation } from 'react-router-dom';
33

44
import { RejoinReasonInfo } from '@proton-meet/proton-meet-core';
55
import { ConnectionState, DisconnectReason, type Room, RoomEvent, Track } from 'livekit-client';
6-
import { c } from 'ttag';
76

87
import { useUser } from '@proton/account/user/hooks';
9-
import useNotifications from '@proton/components/hooks/useNotifications';
108
import { useMeetErrorReporting } from '@proton/meet';
119
import { useCreateInstantMeeting } from '@proton/meet/hooks/useCreateInstantMeeting';
1210
import { useMeetDispatch, useMeetSelector } from '@proton/meet/store/hooks';
13-
import { setPreviousMeetingLink, setUpsellModalType } from '@proton/meet/store/slices';
11+
import { setInvalidMeetingLinkModalOpen, setPreviousMeetingLink, setUpsellModalType } from '@proton/meet/store/slices';
1412
import { resetChatAndReactions } from '@proton/meet/store/slices/chatAndReactionsSlice';
1513
import { addKeyRotationLog } from '@proton/meet/store/slices/meetingInfo';
1614
import { setMeetingLocked, toggleMeetingLockThunk } from '@proton/meet/store/slices/settings';
@@ -194,7 +192,7 @@ export const ProtonMeetContainer = ({ room, keyProvider, user = null }: ProtonMe
194192
const [reconnectionFailed, setReconnectionFailed] = useState(false);
195193
const [mlsRetrying, setMlsRetrying] = useState(false);
196194
// Stable ref to break the circular dependency between useConnectionHealthCheck and performFullReconnection
197-
const triggerFullReconnectionRef = useRef<(reason: RejoinReasonInfo) => void>(() => { });
195+
const triggerFullReconnectionRef = useRef<(reason: RejoinReasonInfo) => void>(() => {});
198196
const [prejoinParticipantCount, setPrejoinParticipantCount] = useState<number | null>(null);
199197
const [liveKitConnectionState, setLiveKitConnectionState] = useState<ConnectionState | null>(null);
200198
const [showReconnectedMessage, setShowReconnectedMessage] = useState(false);
@@ -249,8 +247,6 @@ export const ProtonMeetContainer = ({ room, keyProvider, user = null }: ProtonMe
249247
[getMeetingInfo]
250248
);
251249

252-
const notifications = useNotifications();
253-
254250
useIsRecordingInProgressReceiver(wasmApp);
255251

256252
const isGuestAdminRef = useRef(false);
@@ -322,10 +318,11 @@ export const ProtonMeetContainer = ({ room, keyProvider, user = null }: ProtonMe
322318
hasAnotherAdmin,
323319
} = isLocalParticipantAdmin(participantsMap, room.localParticipant);
324320

325-
const shareLink = `${window.location.origin}${meetingDetails.meetingId && meetingDetails.meetingPassword
326-
? getMeetingLink(meetingDetails.meetingId, meetingDetails.meetingPassword)
327-
: window.location.pathname
328-
}`;
321+
const shareLink = `${window.location.origin}${
322+
meetingDetails.meetingId && meetingDetails.meetingPassword
323+
? getMeetingLink(meetingDetails.meetingId, meetingDetails.meetingPassword)
324+
: window.location.pathname
325+
}`;
329326

330327
// Check if joining own personal meeting room
331328
const isPersonalRoom = !isGuest && personalMeeting?.MeetingLinkName === token;
@@ -424,12 +421,7 @@ export const ProtonMeetContainer = ({ room, keyProvider, user = null }: ProtonMe
424421
readyToDecrypt: true,
425422
};
426423
} catch {
427-
notifications.createNotification({
428-
type: 'error',
429-
text: c('Error').t`The meeting link you are trying to access does not exist or may have been deleted.`,
430-
expiration: 20000,
431-
});
432-
424+
dispatch(setInvalidMeetingLinkModalOpen(true));
433425
history.push('/dashboard');
434426

435427
return {};

packages/meet/store/slices/meetAppStateSlice.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,13 @@ import type { MeetState } from '../store';
77
export interface MeetAppState {
88
previousMeetingLink: string | null;
99
upsellModalType: UpsellModalTypes | null;
10+
invalidMeetingLinkModalOpen: boolean;
1011
}
1112

1213
const initialState: MeetAppState = {
1314
previousMeetingLink: null,
1415
upsellModalType: null,
16+
invalidMeetingLinkModalOpen: false,
1517
};
1618

1719
const slice = createSlice({
@@ -24,10 +26,13 @@ const slice = createSlice({
2426
setUpsellModalType: (state, action: PayloadAction<UpsellModalTypes | null>) => {
2527
state.upsellModalType = action.payload;
2628
},
29+
setInvalidMeetingLinkModalOpen: (state, action: PayloadAction<boolean>) => {
30+
state.invalidMeetingLinkModalOpen = action.payload;
31+
},
2732
},
2833
});
2934

30-
export const { setPreviousMeetingLink, setUpsellModalType } = slice.actions;
35+
export const { setPreviousMeetingLink, setUpsellModalType, setInvalidMeetingLinkModalOpen } = slice.actions;
3136

3237
export const selectPreviousMeetingLink = (state: MeetState) => {
3338
return state.meetAppState.previousMeetingLink;
@@ -37,4 +42,8 @@ export const selectUpsellModalType = (state: MeetState) => {
3742
return state.meetAppState.upsellModalType;
3843
};
3944

45+
export const selectInvalidMeetingLinkModalOpen = (state: MeetState) => {
46+
return state.meetAppState.invalidMeetingLinkModalOpen;
47+
};
48+
4049
export const meetAppStateReducer = { meetAppState: slice.reducer };
Lines changed: 74 additions & 0 deletions
Loading

0 commit comments

Comments
 (0)