-
Notifications
You must be signed in to change notification settings - Fork 407
Expand file tree
/
Copy pathLiveTrackingContext.js
More file actions
109 lines (99 loc) · 4.11 KB
/
Copy pathLiveTrackingContext.js
File metadata and controls
109 lines (99 loc) · 4.11 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
import React, { useEffect, useMemo, useState } from 'react';
import { useLocation, useSearchParams } from 'react-router-dom';
import { LIVE_TRACKS_URL, MAIN_URL_WITH_SLASH } from '../manager/GlobalManager';
import {
KEY_HEX_RE,
LIVE_TRACK_KEY_SESSION,
LIVE_TRACKS_STORAGE_KEY,
NAME_PARAM,
TID_PARAM,
} from '../util/livetracks/liveTrackUtils';
import useLiveTracking from '../util/hooks/live/useLiveTracking';
const LiveTrackingContext = React.createContext();
export const LiveTrackingProvider = ({ children }) => {
const location = useLocation();
const [searchParams] = useSearchParams();
const [liveTranslations, setLiveTranslations] = useState(() => {
try {
return JSON.parse(localStorage.getItem(LIVE_TRACKS_STORAGE_KEY)) ?? [];
} catch {
return [];
}
});
const [liveParticipants, setLiveParticipants] = useState({});
const [liveViewers, setLiveViewers] = useState({});
// Pending share-permission requests shown to the owner as map notifications.
const [liveShareRequests, setLiveShareRequests] = useState([]); // [{ translationId, userId, nickname }]
// approve/deny callbacks published over websocket; wired by useLiveTracking.
const [liveShareActions, setLiveShareActions] = useState(null);
const [selectedLiveTranslation, setSelectedLiveTranslation] = useState(null);
const [followLiveLocation, setFollowLiveLocation] = useState(null);
const [myBroadcastTids, setMyBroadcastTids] = useState([]);
const livePath = MAIN_URL_WITH_SLASH + LIVE_TRACKS_URL;
const openLiveTracks = location.pathname.startsWith(livePath);
// Sync the selected translation from the URL (?tid=...#<key>), restoring the AES key the map
// stashed in sessionStorage before leaflet-hash cleared the fragment.
useEffect(() => {
if (!openLiveTracks) {
setSelectedLiveTranslation(null);
return;
}
const tid = searchParams.get(TID_PARAM);
if (!tid) {
setSelectedLiveTranslation(null);
return;
}
let key = null;
try {
const saved = sessionStorage.getItem(LIVE_TRACK_KEY_SESSION);
if (saved && KEY_HEX_RE.test(saved)) {
key = saved;
sessionStorage.removeItem(LIVE_TRACK_KEY_SESSION);
}
} catch {}
const fromList = liveTranslations.find((t) => t.id === tid);
if (fromList) {
const entry = key && !fromList.key ? { ...fromList, key } : fromList;
setSelectedLiveTranslation(entry);
} else {
const name = searchParams.get(NAME_PARAM) ?? '';
setSelectedLiveTranslation({ id: tid, name, ...(key ? { key } : {}) });
}
}, [openLiveTracks, location.search]);
const liveState = useMemo(
() => ({
liveTranslations,
setLiveTranslations,
liveParticipants,
setLiveParticipants,
liveViewers,
setLiveViewers,
liveShareRequests,
setLiveShareRequests,
liveShareActions,
setLiveShareActions,
selectedLiveTranslation,
setSelectedLiveTranslation,
followLiveLocation,
setFollowLiveLocation,
myBroadcastTids,
setMyBroadcastTids,
}),
[
liveTranslations,
liveParticipants,
liveViewers,
liveShareRequests,
liveShareActions,
selectedLiveTranslation,
followLiveLocation,
myBroadcastTids,
]
);
// Hold the WebSocket only when live tracks are in use: viewing the page, broadcasting, or having bookmarked translations
const enabled = openLiveTracks || myBroadcastTids.length > 0 || liveTranslations.length > 0;
const api = useLiveTracking(liveState, enabled);
const value = useMemo(() => ({ ...liveState, ...api, openLiveTracks }), [liveState, api, openLiveTracks]);
return <LiveTrackingContext.Provider value={value}>{children}</LiveTrackingContext.Provider>;
};
export default LiveTrackingContext;