@@ -8,56 +8,52 @@ Please see LICENSE in the repository root for full details.
8
8
import { useEffect , useMemo } from "react" ;
9
9
10
10
import { setLocalStorageItem , useLocalStorage } from "../useLocalStorage" ;
11
- import { type UrlParams , getUrlParams , useUrlParams } from "../UrlParams" ;
11
+ import { getUrlParams } from "../UrlParams" ;
12
12
import { E2eeType } from "./e2eeType" ;
13
13
import { useClient } from "../ClientContext" ;
14
14
15
+ /**
16
+ * This setter will update the state for all `useRoomSharedKey` hooks
17
+ */
15
18
export function saveKeyForRoom ( roomId : string , password : string ) : void {
16
19
setLocalStorageItem ( getRoomSharedKeyLocalStorageKey ( roomId ) , password ) ;
17
20
}
18
21
19
22
const getRoomSharedKeyLocalStorageKey = ( roomId : string ) : string =>
20
23
`room-shared-key-${ roomId } ` ;
21
24
22
- const useInternalRoomSharedKey = ( roomId : string ) : string | null => {
23
- const key = getRoomSharedKeyLocalStorageKey ( roomId ) ;
24
- const [ roomSharedKey ] = useLocalStorage ( key ) ;
25
-
26
- return roomSharedKey ;
25
+ /**
26
+ * An upto-date shared key for the room. Either from local storage or the value from `setInitialValue`.
27
+ * @param roomId
28
+ * @param setInitialValue The value we get from the URL. The hook will overwrite the local storage value with this.
29
+ * @returns [roomSharedKey, setRoomSharedKey] like a react useState hook.
30
+ */
31
+ const useRoomSharedKey = (
32
+ roomId : string ,
33
+ setInitialValue ?: string ,
34
+ ) : [ string | null , setKey : ( key : string ) => void ] => {
35
+ const [ roomSharedKey , setRoomSharedKey ] = useLocalStorage (
36
+ getRoomSharedKeyLocalStorageKey ( roomId ) ,
37
+ ) ;
38
+ useEffect ( ( ) => {
39
+ // If setInitialValue is available, update the local storage (usually the password from the url).
40
+ // This will update roomSharedKey but wont update the returned value since
41
+ // that already defaults to setInitialValue.
42
+ if ( setInitialValue ) setRoomSharedKey ( setInitialValue ) ;
43
+ } , [ setInitialValue , setRoomSharedKey ] ) ;
44
+
45
+ // make sure we never return the initial null value from `useLocalStorage`
46
+ return [ setInitialValue ?? roomSharedKey , setRoomSharedKey ] ;
27
47
} ;
28
48
29
49
export function getKeyForRoom ( roomId : string ) : string | null {
30
- saveKeyFromUrlParams ( getUrlParams ( ) ) ;
31
- const key = getRoomSharedKeyLocalStorageKey ( roomId ) ;
32
- return localStorage . getItem ( key ) ;
50
+ const { roomId : urlRoomId , password } = getUrlParams ( ) ;
51
+ if ( roomId !== urlRoomId ) return null ;
52
+ return (
53
+ password ?? localStorage . getItem ( getRoomSharedKeyLocalStorageKey ( roomId ) )
54
+ ) ;
33
55
}
34
56
35
- function saveKeyFromUrlParams ( urlParams : UrlParams ) : void {
36
- if ( ! urlParams . password || ! urlParams . roomId ) return ;
37
-
38
- // Take the key from the URL and save it.
39
- // It's important to always use the room ID specified in the URL
40
- // when saving keys rather than whatever the current room ID might be,
41
- // in case we've moved to a different room but the URL hasn't changed.
42
- saveKeyForRoom ( urlParams . roomId , urlParams . password ) ;
43
- }
44
-
45
- /**
46
- * Extracts the room password from the URL if one is present, saving it in localstorage
47
- * and returning it in a tuple with the corresponding room ID from the URL.
48
- * @returns A tuple of the roomId and password from the URL if the URL has both,
49
- * otherwise [undefined, undefined]
50
- */
51
- const useKeyFromUrl = ( ) : [ string , string ] | [ undefined , undefined ] => {
52
- const urlParams = useUrlParams ( ) ;
53
-
54
- useEffect ( ( ) => saveKeyFromUrlParams ( urlParams ) , [ urlParams ] ) ;
55
-
56
- return urlParams . roomId && urlParams . password
57
- ? [ urlParams . roomId , urlParams . password ]
58
- : [ undefined , undefined ] ;
59
- } ;
60
-
61
57
export type Unencrypted = { kind : E2eeType . NONE } ;
62
58
export type SharedSecret = { kind : E2eeType . SHARED_KEY ; secret : string } ;
63
59
export type PerParticipantE2EE = { kind : E2eeType . PER_PARTICIPANT } ;
@@ -66,12 +62,11 @@ export type EncryptionSystem = Unencrypted | SharedSecret | PerParticipantE2EE;
66
62
export function useRoomEncryptionSystem ( roomId : string ) : EncryptionSystem {
67
63
const { client } = useClient ( ) ;
68
64
69
- // make sure we've extracted the key from the URL first
70
- // (and we still need to take the value it returns because
71
- // the effect won't run in time for it to save to localstorage in
72
- // time for us to read it out again).
73
- const [ urlRoomId , passwordFromUrl ] = useKeyFromUrl ( ) ;
74
- const storedPassword = useInternalRoomSharedKey ( roomId ) ;
65
+ const [ storedPassword ] = useRoomSharedKey (
66
+ getRoomSharedKeyLocalStorageKey ( roomId ) ,
67
+ getKeyForRoom ( roomId ) ?? undefined ,
68
+ ) ;
69
+
75
70
const room = client ?. getRoom ( roomId ) ;
76
71
const e2eeSystem = < EncryptionSystem > useMemo ( ( ) => {
77
72
if ( ! room ) return { kind : E2eeType . NONE } ;
@@ -80,15 +75,10 @@ export function useRoomEncryptionSystem(roomId: string): EncryptionSystem {
80
75
kind : E2eeType . SHARED_KEY ,
81
76
secret : storedPassword ,
82
77
} ;
83
- if ( urlRoomId === roomId )
84
- return {
85
- kind : E2eeType . SHARED_KEY ,
86
- secret : passwordFromUrl ,
87
- } ;
88
78
if ( room . hasEncryptionStateEvent ( ) ) {
89
79
return { kind : E2eeType . PER_PARTICIPANT } ;
90
80
}
91
81
return { kind : E2eeType . NONE } ;
92
- } , [ passwordFromUrl , room , roomId , storedPassword , urlRoomId ] ) ;
82
+ } , [ room , storedPassword ] ) ;
93
83
return e2eeSystem ;
94
84
}
0 commit comments