forked from quic-issues/427e7578-d7bf-49c8-aee9-2dd999e25316
* init p2p-poll
This commit is contained in:
81
p2p-poll/composables/usePoll.ts
Normal file
81
p2p-poll/composables/usePoll.ts
Normal file
@@ -0,0 +1,81 @@
|
||||
// composables/usePoll.ts
|
||||
import { ref, onMounted, onUnmounted } from 'vue';
|
||||
import * as Y from 'yjs';
|
||||
|
||||
export const usePoll = () => {
|
||||
// Reactive Vue state to drive the UI
|
||||
const pollData = ref<Record<string, number>>({});
|
||||
const isConnected = ref(false);
|
||||
const connectedPeers = ref(1); // 1 = just you initially
|
||||
|
||||
let ydoc: Y.Doc;
|
||||
let provider: any;
|
||||
let yMap: Y.Map<number>;
|
||||
|
||||
onMounted(async () => {
|
||||
// 1. Initialize the Yjs document
|
||||
ydoc = new Y.Doc();
|
||||
|
||||
// 2. Connect via WebRTC.
|
||||
// 'nuxt-p2p-poll-demo-room' is the shared room name.
|
||||
// Anyone using this exact string will sync together.
|
||||
const { WebrtcProvider } = await import('y-webrtc');
|
||||
provider = new WebrtcProvider('nuxt-p2p-poll-demo-room', ydoc);
|
||||
|
||||
// Track connection status
|
||||
provider.on('synced', (arg: {synced: boolean}) => {
|
||||
isConnected.value = arg.synced;
|
||||
});
|
||||
|
||||
provider.on('peers', (data: any) => {
|
||||
// data.webrtcPeers contains the connected peer IDs
|
||||
connectedPeers.value = data.webrtcPeers.length + 1; // +1 for self
|
||||
});
|
||||
|
||||
// 3. Define our shared state structure. We'll use a Map
|
||||
// where the Key is the Poll Option (string) and Value is the Vote Count (number)
|
||||
yMap = ydoc.getMap<number>('shared-poll');
|
||||
|
||||
// 4. Listen for changes from other peers and update our Vue reactive state
|
||||
yMap.observe(() => {
|
||||
pollData.value = yMap.toJSON();
|
||||
});
|
||||
|
||||
// Initial load in case data already exists in the room
|
||||
pollData.value = yMap.toJSON();
|
||||
});
|
||||
|
||||
onUnmounted(() => {
|
||||
// Clean up when the component is destroyed
|
||||
if (provider) {
|
||||
provider.disconnect();
|
||||
}
|
||||
if (ydoc) {
|
||||
ydoc.destroy();
|
||||
}
|
||||
});
|
||||
|
||||
// Action: Add a new option to the poll
|
||||
const addOption = (optionName: string) => {
|
||||
const trimmedName = optionName.trim();
|
||||
if (trimmedName && !yMap.has(trimmedName)) {
|
||||
yMap.set(trimmedName, 0); // Initialize with 0 votes
|
||||
}
|
||||
};
|
||||
|
||||
// Action: Vote for an existing option
|
||||
const vote = (optionName: string) => {
|
||||
if (yMap.has(optionName)) {
|
||||
const currentVotes = yMap.get(optionName) || 0;
|
||||
yMap.set(optionName, currentVotes + 1);
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
pollData,
|
||||
isConnected,
|
||||
connectedPeers,
|
||||
addOption,
|
||||
vote
|
||||
};
|
||||
};
|
||||
Reference in New Issue
Block a user