Skip to content

Commit 06b3bd3

Browse files
Initial commit
1 parent 8c65bbf commit 06b3bd3

File tree

4 files changed

+116
-2
lines changed

4 files changed

+116
-2
lines changed

examples/vite/src/App.tsx

+79-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
1-
import { ChannelFilters, ChannelOptions, ChannelSort } from 'stream-chat';
1+
import {
2+
ChannelFilters,
3+
ChannelOptions,
4+
ChannelSort,
5+
LiveLocationManagerConstructorParameters,
6+
} from 'stream-chat';
27
import {
38
AIStateIndicator,
49
Channel,
@@ -13,6 +18,9 @@ import {
1318
useCreateChatClient,
1419
ThreadList,
1520
ChatView,
21+
useChatContext,
22+
useLiveLocationSharingManager,
23+
Attachment,
1624
} from 'stream-chat-react';
1725
import 'stream-chat-react/css/v2/index.css';
1826

@@ -64,13 +72,67 @@ type StreamChatGenerics = {
6472
userType: LocalUserType;
6573
};
6674

75+
const ShareLiveLocation = () => {
76+
const { channel } = useChatContext();
77+
78+
return (
79+
<button
80+
onClick={() => {
81+
console.log('trying to fetch location');
82+
navigator.geolocation.getCurrentPosition(
83+
(position) => {
84+
const { latitude, longitude } = position.coords;
85+
console.log('got location ', position);
86+
channel?.startLiveLocationSharing({
87+
latitude,
88+
longitude,
89+
end_time: new Date(Date.now() + 1 * 1000 * 3600 * 24).toISOString(),
90+
});
91+
},
92+
console.warn,
93+
{ timeout: 200 },
94+
);
95+
}}
96+
>
97+
location
98+
</button>
99+
);
100+
};
101+
102+
const watchLocationNormal: LiveLocationManagerConstructorParameters['watchLocation'] = (
103+
watcher,
104+
) => {
105+
const watch = navigator.geolocation.watchPosition((position) => {
106+
watcher({ latitude: position.coords.latitude, longitude: position.coords.longitude });
107+
});
108+
109+
return () => navigator.geolocation.clearWatch(watch);
110+
};
111+
112+
const watchLocationTimed: LiveLocationManagerConstructorParameters['watchLocation'] = (watcher) => {
113+
const timer = setInterval(() => {
114+
navigator.geolocation.getCurrentPosition((position) => {
115+
watcher({ latitude: position.coords.latitude, longitude: position.coords.longitude });
116+
});
117+
}, 5000);
118+
119+
return () => clearInterval(timer);
120+
};
121+
67122
const App = () => {
68123
const chatClient = useCreateChatClient<StreamChatGenerics>({
69124
apiKey,
70125
tokenOrProvider: userToken,
71126
userData: { id: userId },
72127
});
73128

129+
const manager = useLiveLocationSharingManager({
130+
client: chatClient ?? undefined,
131+
watchLocation: watchLocationTimed,
132+
});
133+
134+
// const s = useStateStore(manager?.state)
135+
74136
if (!chatClient) return <>Loading...</>;
75137

76138
return (
@@ -86,12 +148,27 @@ const App = () => {
86148
showChannelSearch
87149
additionalChannelSearchProps={{ searchForChannels: true }}
88150
/>
89-
<Channel>
151+
<Channel
152+
Attachment={(props) => {
153+
const [attachment] = props.attachments ?? [];
154+
155+
if (attachment?.type === 'live_location') {
156+
return (
157+
<div style={{ padding: 25 }}>
158+
lat: {attachment.latitude}, lng: {attachment.longitude}
159+
</div>
160+
);
161+
}
162+
163+
return <Attachment {...props} />;
164+
}}
165+
>
90166
<Window>
91167
<ChannelHeader Avatar={ChannelAvatar} />
92168
<MessageList returnAllReadData />
93169
<AIStateIndicator />
94170
<MessageInput focus />
171+
<ShareLiveLocation />
95172
</Window>
96173
<Thread virtualized />
97174
</Channel>

src/components/Attachment/Attachment.tsx

+1
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ const CONTAINER_MAP = {
4141
media: MediaContainer,
4242
unsupported: UnsupportedAttachmentContainer,
4343
voiceRecording: VoiceRecordingContainer,
44+
// geolocation: () => <div></div>,
4445
} as const;
4546

4647
export const ATTACHMENT_GROUPS_ORDER = [
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import { LiveLocationManager } from 'stream-chat';
2+
import type { LiveLocationManagerConstructorParameters } from 'stream-chat';
3+
import { useEffect, useMemo } from 'react';
4+
5+
type PartialKeys<T, K extends keyof T> = {
6+
[L in keyof T]: L extends K ? T[L] | undefined : T[L];
7+
};
8+
9+
export const useLiveLocationSharingManager = ({
10+
client,
11+
retrieveAndDeserialize,
12+
serializeAndStore,
13+
watchLocation,
14+
}: PartialKeys<LiveLocationManagerConstructorParameters, 'client'>) => {
15+
const manager = useMemo(() => {
16+
if (!client) return null;
17+
18+
return new LiveLocationManager({
19+
client,
20+
retrieveAndDeserialize,
21+
serializeAndStore,
22+
watchLocation,
23+
});
24+
}, [client, retrieveAndDeserialize, serializeAndStore, watchLocation]);
25+
26+
useEffect(() => {
27+
if (!manager) return;
28+
29+
manager.registerSubscriptions();
30+
31+
return () => manager.unregisterSubscriptions();
32+
}, [manager]);
33+
34+
return manager;
35+
};

src/components/Attachment/index.ts

+1
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,4 @@ export * from './components';
88
export * from './UnsupportedAttachment';
99
export * from './FileAttachment';
1010
export * from './utils';
11+
export * from './hooks/useLiveLocationSharingManager';

0 commit comments

Comments
 (0)