@streamplace/components 0.7.21 → 0.7.26

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/dist/components/chat/chat-box.js +0 -6
  2. package/dist/components/chat/chat-message.js +9 -4
  3. package/dist/components/chat/chat.js +14 -4
  4. package/dist/components/mobile-player/ui/autoplay-button.js +1 -1
  5. package/dist/components/mobile-player/video-async.native.js +4 -4
  6. package/dist/components/mobile-player/video.js +3 -3
  7. package/dist/components/mobile-player/webrtc-diagnostics.js +67 -13
  8. package/dist/index.js +4 -1
  9. package/dist/lib/system-messages.js +1 -0
  10. package/dist/livestream-store/chat.js +11 -0
  11. package/dist/livestream-store/stream-key.js +1 -0
  12. package/dist/livestream-store/websocket-consumer.js +4 -1
  13. package/dist/player-store/player-store.js +0 -4
  14. package/dist/storage/index.js +5 -0
  15. package/dist/storage/lock.js +40 -0
  16. package/dist/storage/storage.js +14 -0
  17. package/dist/storage/storage.native.js +44 -0
  18. package/dist/storage/storage.shared.js +2 -0
  19. package/dist/streamplace-provider/index.js +1 -0
  20. package/dist/streamplace-store/stream.js +2 -0
  21. package/dist/streamplace-store/streamplace-store.js +75 -2
  22. package/dist/streamplace-store/xrpc.js +10 -1
  23. package/node-compile-cache/v22.15.0-x64-efe9a9df-0/37be0eec +0 -0
  24. package/package.json +5 -4
  25. package/src/components/chat/chat-box.tsx +0 -11
  26. package/src/components/chat/chat-message.tsx +8 -4
  27. package/src/components/chat/chat.tsx +20 -4
  28. package/src/components/mobile-player/ui/autoplay-button.tsx +2 -2
  29. package/src/components/mobile-player/video-async.native.tsx +6 -4
  30. package/src/components/mobile-player/video.tsx +6 -3
  31. package/src/components/mobile-player/webrtc-diagnostics.tsx +73 -15
  32. package/src/index.tsx +4 -0
  33. package/src/lib/system-messages.ts +1 -0
  34. package/src/livestream-store/chat.tsx +15 -0
  35. package/src/livestream-store/stream-key.tsx +1 -0
  36. package/src/livestream-store/websocket-consumer.tsx +4 -1
  37. package/src/player-store/player-state.tsx +0 -12
  38. package/src/player-store/player-store.tsx +0 -8
  39. package/src/storage/index.tsx +3 -0
  40. package/src/storage/lock.tsx +38 -0
  41. package/src/storage/storage.native.tsx +42 -0
  42. package/src/storage/storage.shared.tsx +5 -0
  43. package/src/storage/storage.tsx +15 -0
  44. package/src/streamplace-provider/index.tsx +2 -1
  45. package/src/streamplace-store/stream.tsx +2 -0
  46. package/src/streamplace-store/streamplace-store.tsx +92 -2
  47. package/src/streamplace-store/xrpc.tsx +9 -2
  48. package/tsconfig.json +2 -1
  49. package/tsconfig.tsbuildinfo +1 -1
@@ -2,6 +2,7 @@ import { SessionManager } from "@atproto/api/dist/session-manager";
2
2
  import { useContext } from "react";
3
3
  import { PlaceStreamChatProfile, PlaceStreamLivestream } from "streamplace";
4
4
  import { createStore, StoreApi, useStore } from "zustand";
5
+ import storage from "../storage";
5
6
  import { StreamplaceContext } from "../streamplace-provider/context";
6
7
 
7
8
  // there are three categories of XRPC that we need to handle:
@@ -28,9 +29,15 @@ export interface StreamplaceState {
28
29
  liveUsersRefresh: number;
29
30
  liveUsersLoading: boolean;
30
31
  liveUsersError: string | null;
31
- oauthSession: SessionManager | null;
32
+ oauthSession: SessionManager | null | undefined;
32
33
  handle: string | null;
33
34
  chatProfile: PlaceStreamChatProfile.Record | null;
35
+
36
+ // Volume state
37
+ volume: number;
38
+ muted: boolean;
39
+ setVolume: (volume: number) => void;
40
+ setMuted: (muted: boolean) => void;
34
41
  }
35
42
 
36
43
  export type StreamplaceStore = StoreApi<StreamplaceState>;
@@ -40,7 +47,10 @@ export const makeStreamplaceStore = ({
40
47
  }: {
41
48
  url: string;
42
49
  }): StoreApi<StreamplaceState> => {
43
- return createStore<StreamplaceState>()((set) => ({
50
+ const VOLUME_STORAGE_KEY = "globalVolume";
51
+ const MUTED_STORAGE_KEY = "globalMuted";
52
+
53
+ const store = createStore<StreamplaceState>()((set) => ({
44
54
  url,
45
55
  liveUsers: null,
46
56
  setLiveUsers: (opts: {
@@ -59,7 +69,73 @@ export const makeStreamplaceStore = ({
59
69
  oauthSession: null,
60
70
  handle: null,
61
71
  chatProfile: null,
72
+
73
+ // Volume state - start with defaults
74
+ volume: 1.0,
75
+ muted: false,
76
+
77
+ setVolume: (volume: number) => {
78
+ // Ensure the value is finite and within bounds
79
+ if (!Number.isFinite(volume)) {
80
+ console.warn("Invalid volume value:", volume, "- using 1.0");
81
+ volume = 1.0;
82
+ }
83
+ const clampedVolume = Math.max(0, Math.min(1, volume));
84
+
85
+ set({ volume: clampedVolume });
86
+
87
+ // Auto-unmute if volume > 0
88
+ if (clampedVolume > 0) {
89
+ set({ muted: false });
90
+ storage.setItem(MUTED_STORAGE_KEY, "false").catch(console.error);
91
+ }
92
+
93
+ storage
94
+ .setItem(VOLUME_STORAGE_KEY, clampedVolume.toString())
95
+ .catch(console.error);
96
+ },
97
+
98
+ setMuted: (muted: boolean) => {
99
+ set({ muted });
100
+ storage.setItem(MUTED_STORAGE_KEY, muted.toString()).catch(console.error);
101
+ },
62
102
  }));
103
+
104
+ // Load initial volume state from storage asynchronously
105
+ (async () => {
106
+ try {
107
+ const storedVolume = await storage.getItem(VOLUME_STORAGE_KEY);
108
+ const storedMuted = await storage.getItem(MUTED_STORAGE_KEY);
109
+
110
+ let initialVolume = 1.0;
111
+ let initialMuted = false;
112
+
113
+ if (storedVolume) {
114
+ const parsedVolume = parseFloat(storedVolume);
115
+ if (
116
+ Number.isFinite(parsedVolume) &&
117
+ parsedVolume >= 0 &&
118
+ parsedVolume <= 1
119
+ ) {
120
+ initialVolume = parsedVolume;
121
+ }
122
+ }
123
+
124
+ if (storedMuted) {
125
+ initialMuted = storedMuted === "true";
126
+ }
127
+
128
+ // Update the store with loaded values
129
+ store.setState({
130
+ volume: initialVolume,
131
+ muted: initialMuted,
132
+ });
133
+ } catch (e) {
134
+ console.warn("Failed to load volume settings from storage:", e);
135
+ }
136
+ })();
137
+
138
+ return store;
63
139
  };
64
140
 
65
141
  export function getStreamplaceStoreFromContext(): StreamplaceStore {
@@ -87,3 +163,17 @@ export const useSetHandle = (): ((handle: string) => void) => {
87
163
  const store = getStreamplaceStoreFromContext();
88
164
  return (handle: string) => store.setState({ handle });
89
165
  };
166
+
167
+ // Volume convenience hooks
168
+ export const useVolume = () => useStreamplaceStore((x) => x.volume);
169
+ export const useMuted = () => useStreamplaceStore((x) => x.muted);
170
+ export const useSetVolume = () => useStreamplaceStore((x) => x.setVolume);
171
+ export const useSetMuted = () => useStreamplaceStore((x) => x.setMuted);
172
+
173
+ // Composite hook for effective volume (0 if muted) - used by video components
174
+ export const useEffectiveVolume = () =>
175
+ useStreamplaceStore((state) => {
176
+ const effectiveVolume = state.muted ? 0 : state.volume;
177
+ // Ensure we always return a finite number for HTMLMediaElement.volume
178
+ return Number.isFinite(effectiveVolume) ? effectiveVolume : 1.0;
179
+ });
@@ -4,10 +4,17 @@ import { useStreamplaceStore } from ".";
4
4
 
5
5
  export function usePDSAgent(): StreamplaceAgent | null {
6
6
  const oauthSession = useStreamplaceStore((state) => state.oauthSession);
7
-
7
+ // oauthsession is
8
+ // - undefined when loading
9
+ // - null when logged out, and
10
+ // - SessionManager when logged in
8
11
  return useMemo(() => {
9
12
  if (!oauthSession) {
10
- return null;
13
+ if (oauthSession === undefined) return null;
14
+ // TODO: change once we allow unauthed requests + profile indexing
15
+ // it's bluesky's AppView b/c otherwise we'd have goosewithpipe.jpg
16
+ // showing up everywhere
17
+ return new StreamplaceAgent("https://public.api.bsky.app"); // nodeUrl);
11
18
  }
12
19
 
13
20
  return new StreamplaceAgent(oauthSession);
package/tsconfig.json CHANGED
@@ -4,7 +4,8 @@
4
4
  "rootDir": "./src",
5
5
  "outDir": "./dist",
6
6
  "jsx": "react-jsx",
7
- "module": "commonjs"
7
+ "module": "commonjs",
8
+ "skipLibCheck": true
8
9
  },
9
10
  "include": ["./src"]
10
11
  }