radames commited on
Commit
1d701d3
1 Parent(s): de6cf77

better API for liveblocks storage

Browse files
frontend/src/lib/App.svelte CHANGED
@@ -5,50 +5,64 @@
5
  import Menu from '$lib/Menu.svelte';
6
  import type { Room } from '@liveblocks/client';
7
  import { onDestroy } from 'svelte';
8
- import { currZoomTransform } from '$lib/store';
9
 
10
  /**
11
  * The main Liveblocks code for the example.
12
  * Check in src/routes/index.svelte to see the setup code.
13
  */
14
 
15
- export let room: Room;
16
 
17
- // Get initial values for presence and others
18
- let myPresence = room.getPresence();
19
- let others = room.getOthers();
20
 
21
- // Subscribe to further changes
22
- const unsubscribeMyPresence = room.subscribe('my-presence', (presence) => {
23
- myPresence = presence;
24
- });
25
 
26
- const unsubscribeOthers = room.subscribe('others', (otherUsers) => {
27
- others = otherUsers;
28
- });
29
 
30
- // Unsubscribe when unmounting
31
- onDestroy(() => {
32
- unsubscribeMyPresence();
33
- unsubscribeOthers();
34
- });
 
 
 
 
 
 
 
 
 
35
 
36
  // Update cursor presence to current pointer location
37
  function handlePointerMove(event: PointerEvent) {
38
  event.preventDefault();
39
- room.updatePresence({
 
 
 
 
 
40
  cursor: {
41
- x: Math.round(event.layerX),
42
- y: Math.round(event.layerY)
43
  }
44
- });
45
  }
46
 
47
  // When the pointer leaves the page, set cursor presence to null
48
  function handlePointerLeave() {
49
- room.updatePresence({
50
  cursor: null
51
- });
52
  }
53
 
54
  const COLORS = [
@@ -63,35 +77,39 @@
63
  ];
64
  </script>
65
 
66
- <div class="relative">
67
- <div class="z-0">
68
- <h3 class="text-xl">TESTS</h3>
69
- </div>
 
 
 
 
 
 
 
 
 
70
  <main class="z-10 relative">
71
- <!-- Show the current user's cursor location -->
72
- <div class="text">
73
- {myPresence?.cursor
74
- ? `${myPresence.cursor.x} × ${myPresence.cursor.y}`
75
- : 'Move your cursor to broadcast its position to other people in the room.'}
76
- </div>
77
- {#if myPresence?.cursor}
78
- <Frame x={myPresence.cursor.x} y={myPresence.cursor.y} transform={$currZoomTransform} />
79
  {/if}
80
 
81
  <!-- When others connected, iterate through others and show their cursors -->
82
  {#if others}
83
- {#each [...others] as { connectionId, presence } (connectionId)}
84
  {#if presence?.cursor}
 
 
85
  <Cursor
86
  color={COLORS[connectionId % COLORS.length]}
87
  x={presence.cursor.x}
88
  y={presence.cursor.y}
 
89
  />
90
- <Frame x={presence.cursor.x} y={presence.cursor.y} transform={$currZoomTransform} />
91
  {/if}
92
  {/each}
93
  {/if}
94
- <Canvas />
95
  </main>
96
  </div>
97
  <div class="fixed bottom-0 left-0 right-0 z-50 my-2">
 
5
  import Menu from '$lib/Menu.svelte';
6
  import type { Room } from '@liveblocks/client';
7
  import { onDestroy } from 'svelte';
8
+ import { currZoomTransform, myPresence, others } from '$lib/store';
9
 
10
  /**
11
  * The main Liveblocks code for the example.
12
  * Check in src/routes/index.svelte to see the setup code.
13
  */
14
 
15
+ // export let room: Room;
16
 
17
+ // // Get initial values for presence and others
18
+ // let myPresence = room.getPresence();
19
+ // let others = room.getOthers();
20
 
21
+ // // Subscribe to further changes
22
+ // const unsubscribeMyPresence = room.subscribe('my-presence', (presence) => {
23
+ // myPresence = presence;
24
+ // });
25
 
26
+ // const unsubscribeOthers = room.subscribe('others', (otherUsers) => {
27
+ // others = otherUsers;
28
+ // });
29
 
30
+ // // Unsubscribe when unmounting
31
+ // onDestroy(() => {
32
+ // unsubscribeMyPresence();
33
+ // unsubscribeOthers();
34
+ // });
35
+ $: {
36
+ console.log('myPresence', $myPresence.cursor);
37
+ // console.log('others', $others);
38
+ }
39
+ const r = 10;
40
+ function round(p, n) {
41
+ return p % n < n / 2 ? p - (p % n) : p + n - (p % n);
42
+ }
43
+ const grid = 10;
44
 
45
  // Update cursor presence to current pointer location
46
  function handlePointerMove(event: PointerEvent) {
47
  event.preventDefault();
48
+ const x = Math.round(event.layerX / grid) * grid; //round(Math.max(r, Math.min(512 * 5 - r, event.clientX)), 100);
49
+ const y = Math.round(event.layerY / grid) * grid; //round(Math.max(r, Math.min(512 * 5 - r, event.clientY)), 100);
50
+ // const x = round(Math.max(r, Math.min(512 * 5 - r, event.clientX)), grid);
51
+ // const y = round(Math.max(r, Math.min(512 * 5 - r, event.clientY)), grid);
52
+
53
+ $myPresence = {
54
  cursor: {
55
+ x,
56
+ y
57
  }
58
+ };
59
  }
60
 
61
  // When the pointer leaves the page, set cursor presence to null
62
  function handlePointerLeave() {
63
+ $myPresence = {
64
  cursor: null
65
+ };
66
  }
67
 
68
  const COLORS = [
 
77
  ];
78
  </script>
79
 
80
+ <!-- Show the current user's cursor location -->
81
+ <div class="text">
82
+ {$myPresence?.cursor
83
+ ? `${$myPresence.cursor.x} × ${$myPresence.cursor.y}`
84
+ : 'Move your cursor to broadcast its position to other people in the room.'}
85
+ </div>
86
+ <div
87
+ class="relative z-0 w-screen h-screen"
88
+ on:pointerleave={handlePointerLeave}
89
+ on:pointermove={handlePointerMove}
90
+ >
91
+ <Canvas />
92
+
93
  <main class="z-10 relative">
94
+ {#if $myPresence?.cursor}
95
+ <Frame x={$myPresence.cursor.x} y={$myPresence.cursor.y} transform={$currZoomTransform} />
 
 
 
 
 
 
96
  {/if}
97
 
98
  <!-- When others connected, iterate through others and show their cursors -->
99
  {#if others}
100
+ {#each [...$others] as { connectionId, presence } (connectionId)}
101
  {#if presence?.cursor}
102
+ <Frame x={presence.cursor.x} y={presence.cursor.y} transform={$currZoomTransform} />
103
+
104
  <Cursor
105
  color={COLORS[connectionId % COLORS.length]}
106
  x={presence.cursor.x}
107
  y={presence.cursor.y}
108
+ transform={$currZoomTransform}
109
  />
 
110
  {/if}
111
  {/each}
112
  {/if}
 
113
  </main>
114
  </div>
115
  <div class="fixed bottom-0 left-0 right-0 z-50 my-2">
frontend/src/lib/Canvas.svelte CHANGED
@@ -21,7 +21,7 @@
21
  onMount(() => {
22
  const scale = width / containerEl.clientWidth;
23
  const zoomHandler = zoom()
24
- .scaleExtent([1 / scale / 2, 2])
25
  .translateExtent([
26
  [0, 0],
27
  [width, height]
@@ -41,7 +41,7 @@
41
  canvasCtx.rect(10, 10, 160, 90);
42
  canvasCtx.fill();
43
  canvasCtx.strokeStyle = 'blue';
44
- canvasCtx.lineWidth = 5;
45
  canvasCtx.strokeRect(0, 0, width, height);
46
  });
47
 
@@ -60,7 +60,7 @@
60
 
61
  <div
62
  bind:this={containerEl}
63
- class="fixed w-screen h-screen top-0 left-0 overflow-hidden border-4 border-black"
64
  >
65
  <canvas bind:this={canvasEl} {width} {height} class="absolute top-0 left-0" />
66
  </div>
 
21
  onMount(() => {
22
  const scale = width / containerEl.clientWidth;
23
  const zoomHandler = zoom()
24
+ .scaleExtent([1 / scale, 2])
25
  .translateExtent([
26
  [0, 0],
27
  [width, height]
 
41
  canvasCtx.rect(10, 10, 160, 90);
42
  canvasCtx.fill();
43
  canvasCtx.strokeStyle = 'blue';
44
+ canvasCtx.lineWidth = 10;
45
  canvasCtx.strokeRect(0, 0, width, height);
46
  });
47
 
 
60
 
61
  <div
62
  bind:this={containerEl}
63
+ class="absolute top-0 left-0 right-0 bottom-0 overflow-hidden border-4 border-black z-0"
64
  >
65
  <canvas bind:this={canvasEl} {width} {height} class="absolute top-0 left-0" />
66
  </div>
frontend/src/lib/Cursor.svelte CHANGED
@@ -1,5 +1,8 @@
1
  <script lang="ts">
2
  import { spring } from 'svelte/motion';
 
 
 
3
 
4
  export let color = '';
5
  export let x = 0;
@@ -13,16 +16,15 @@
13
  damping: 0.35
14
  }
15
  );
16
-
17
  // Update spring when x and y change
18
  $: coords.set({ x, y });
19
  </script>
20
 
21
  <svg
22
- class="cursor"
23
  fill="none"
24
  height="36"
25
- style={`transform: translateX(${$coords.x}px) translateY(${$coords.y}px)`}
26
  viewBox="0 0 24 36"
27
  width="24"
28
  xmlns="http://www.w3.org/2000/svg"
@@ -36,5 +38,6 @@
36
  <style lang="postcss" scoped>
37
  .cursor {
38
  @apply absolute top-0 left-0;
 
39
  }
40
  </style>
 
1
  <script lang="ts">
2
  import { spring } from 'svelte/motion';
3
+ import type { ZoomTransform } from 'd3-zoom';
4
+
5
+ export let transform: ZoomTransform;
6
 
7
  export let color = '';
8
  export let x = 0;
 
16
  damping: 0.35
17
  }
18
  );
 
19
  // Update spring when x and y change
20
  $: coords.set({ x, y });
21
  </script>
22
 
23
  <svg
24
+ class="block cursor z-0"
25
  fill="none"
26
  height="36"
27
+ style={`transform: translateX(${$coords.x}px) translateY(${$coords.y}px) scale(${transform.k})`}
28
  viewBox="0 0 24 36"
29
  width="24"
30
  xmlns="http://www.w3.org/2000/svg"
 
38
  <style lang="postcss" scoped>
39
  .cursor {
40
  @apply absolute top-0 left-0;
41
+ /* transform-origin: 0 0; */
42
  }
43
  </style>
frontend/src/lib/Frame.svelte CHANGED
@@ -20,13 +20,13 @@
20
  </script>
21
 
22
  <div
23
- class="frame"
24
  style={`transform: translateX(${$coords.x}px) translateY(${$coords.y}px) scale(${transform.k})`}
25
  />
26
 
27
  <style lang="postcss" scoped>
28
  .frame {
29
- @apply absolute top-0 left-0 border-2 border-sky-500 bg-gradient-to-b from-sky-200 w-[512px] h-[512px];
30
  transform-origin: 0 0;
31
  }
32
  </style>
 
20
  </script>
21
 
22
  <div
23
+ class="frame z-0"
24
  style={`transform: translateX(${$coords.x}px) translateY(${$coords.y}px) scale(${transform.k})`}
25
  />
26
 
27
  <style lang="postcss" scoped>
28
  .frame {
29
+ @apply pointer-events-none touch-none absolute top-0 left-0 border-2 border-sky-500 bg-gradient-to-b from-sky-200 w-[512px] h-[512px];
30
  transform-origin: 0 0;
31
  }
32
  </style>
frontend/src/lib/store.ts CHANGED
@@ -1,7 +1,37 @@
1
- import { writable } from 'svelte/store';
 
 
 
2
  import { type ZoomTransform, zoomIdentity } from 'd3-zoom';
3
 
4
  export const loadingState = writable<string>('');
5
  export const isLoading = writable<boolean>(false);
6
 
7
  export const currZoomTransform = writable<ZoomTransform>(zoomIdentity);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { writable, get } from 'svelte/store';
2
+ import { onDestroy } from 'svelte';
3
+ import type { Room } from '@liveblocks/client';
4
+
5
  import { type ZoomTransform, zoomIdentity } from 'd3-zoom';
6
 
7
  export const loadingState = writable<string>('');
8
  export const isLoading = writable<boolean>(false);
9
 
10
  export const currZoomTransform = writable<ZoomTransform>(zoomIdentity);
11
+
12
+ export const myPresence = writable(null);
13
+ export const others = writable(null);
14
+
15
+ export function createPresenceStore(room: Room) {
16
+ // Get initial values for presence and others
17
+ myPresence.set(room.getPresence());
18
+ others.set(room.getOthers());
19
+
20
+ const unsubscribeMyPresence = room.subscribe('my-presence', (presence) => {
21
+ myPresence.update((_) => presence);
22
+ });
23
+
24
+ const unsubscribeOthers = room.subscribe('others', (otherUsers) => {
25
+ others.update((_) => otherUsers);
26
+ });
27
+
28
+ myPresence.set = (presence) => {
29
+ room.updatePresence(presence);
30
+ return presence;
31
+ };
32
+
33
+ return () => {
34
+ unsubscribeMyPresence();
35
+ unsubscribeOthers();
36
+ };
37
+ }
frontend/src/routes/+page.svelte CHANGED
@@ -1,6 +1,6 @@
1
  <script lang="ts">
2
  import { onMount } from 'svelte';
3
- import { isLoading, loadingState } from '$lib/store';
4
  import { PUBLIC_WS_ENDPOINT, PUBLIC_DEV_MODE } from '$env/static/public';
5
  import type { Client, Room } from '@liveblocks/client';
6
  import { createClient } from '@liveblocks/client';
@@ -17,7 +17,7 @@
17
 
18
  let client: Client;
19
  let room: Room;
20
- let roomId = 'sveltekit-live-cursors';
21
 
22
  onMount(() => {
23
  client = createClient({
@@ -30,9 +30,11 @@
30
  },
31
  initialStorage: {}
32
  });
 
33
  return () => {
34
  if (client && room) {
35
  client.leave(roomId);
 
36
  }
37
  };
38
  });
 
1
  <script lang="ts">
2
  import { onMount } from 'svelte';
3
+ import { isLoading, loadingState, createPresenceStore } from '$lib/store';
4
  import { PUBLIC_WS_ENDPOINT, PUBLIC_DEV_MODE } from '$env/static/public';
5
  import type { Client, Room } from '@liveblocks/client';
6
  import { createClient } from '@liveblocks/client';
 
17
 
18
  let client: Client;
19
  let room: Room;
20
+ let roomId = 'multiplayer-SD';
21
 
22
  onMount(() => {
23
  client = createClient({
 
30
  },
31
  initialStorage: {}
32
  });
33
+ const unsubscribePresence = createPresenceStore(room);
34
  return () => {
35
  if (client && room) {
36
  client.leave(roomId);
37
+ unsubscribePresence();
38
  }
39
  };
40
  });