Last active
          January 29, 2025 07:39 
        
      - 
      
 - 
        
Save sudkumar/c84be58dd644730fd3ce0ebae98a56db to your computer and use it in GitHub Desktop.  
Revisions
- 
        
sudkumar revised this gist
May 22, 2020 . No changes.There are no files selected for viewing
 - 
        
sudkumar revised this gist
May 22, 2020 . 2 changed files with 11 additions and 8 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -8,7 +8,9 @@ import Pusher from "pusher-js" const pusherConfig = { key: '<your_pusher_key_here>', cluster: '<pusher_cluster>', // auth endpoint for private channels // e.g. for Laravel https://example.com/api/broadcasting/auth authEndpoint: '<auth_endpoint_for_private_channels>' } This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -4,9 +4,9 @@ import { ChannelsProvider, usePrivateChannels } from "./channels" // FIRST: we will wrap our application with the `ChannelsProvider` function App () { // get the user and the access token SOMEHOW! const user = getUser() // via context or any other way const token = getToken() // via local storage or any other ways return <ChannelsProvider authUser={user} authToken={token}> <Notifications authUserId={user.id} /> </ChannelsProvider> @@ -29,14 +29,15 @@ interface INotification { /** * Our notification channel which notif */ function useNotificationChannel ( authUserId: integer, onChange: (notification: INotification) => void ) { const channels = usePrivateChannels(authUserId) useEffect(() => { if (channels) { channels.listen(NOTIFICATION_EVENT, onChange) // same as channels.notification(onChange) return () => { channels.stopListening(NOTIFICATION_EVENT) }  - 
        
sudkumar revised this gist
May 22, 2020 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -67,7 +67,7 @@ export function usePrivateChannels (authUserId: any) { } /** * Get the channels */ function getChannels(pusherConfig: typeof pusherConfig, authToken?: string) { const client = new Pusher(pusherConfig.key, {  - 
        
sudkumar revised this gist
May 22, 2020 . 2 changed files with 89 additions and 16 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,4 +1,4 @@ import React, { useEffect, useState, useMemo } from "react" import Echo from "laravel-echo" import Pusher from "pusher-js" @@ -10,32 +10,36 @@ const pusherConfig = { cluster: '<pusher_cluster>', authEndpoint: '<auth_endpoint_for_private_channels>' // for example https://example.com/api/broadcasting/auth } /** * Context for Channels */ type TChannels = Echo | undefined const ChannelsContext = React.createContext<TChannels>(undefined) /** * Channel Context Provider */ export function ChannelsProvider({ children, authUser, authToken }: { children: React.ReactNode, authUser?: any authToken?: string }) { const [channels, setChannels] = useState<TChannels>(undefined) useEffect(() => { const channels = getChannels(pusherConfig, authToken); setChannels(channels) return () => { // disconnect from server and reset the channels channels.disconnect() setChannels(undefined) } }, [authUser, authToken]) return ( <ChannelContext.Provider value={channels}> {children} @@ -47,24 +51,35 @@ export function ChannelContextProvider({ * Hook to use the channels provided via context */ export function useChannels() { const channels = React.useContext(ChannelsContext) return channels } /** * Use private channels * It simple return the useChannels with authenticated user bindings */ export function usePrivateChannels (authUserId: any) { const channels = useChannels() return useMemo(() => { return channels && channels.private("users." + authUserId) }, [channels, authUserId]) } /** * Get the pusher channels */ function getChannels(pusherConfig: typeof pusherConfig, authToken?: string) { const client = new Pusher(pusherConfig.key, { cluster: pusherConfig.cluster, forceTLS: true, authEndpoint: pusherConfig.authEndpoint, auth: authToken ? { headers: { // pass the authorization token when using private channels Authorization: `Bearer ${authToken}`, }, }: undefined, }) const channels = new Echo({ This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,58 @@ import React, { useEffect } from 'react' import { ChannelsProvider, usePrivateChannels } from "./channels" // FIRST: we will wrap our application with the `ChannelsProvider` function App () { // get the user and the access token const user = getUser() const token = getToken() return <ChannelsProvider authUser={user} authToken={token}> <Notifications authUserId={user.id} /> </ChannelsProvider> } // Next, we will listen to a private channel for an event // and update the data on events // A channel listens to a particular event // Here is an example event from Laravel when sending notifications const NOTIFICATION_EVENT = ".Illuminate\\Notifications\\Events\\BroadcastNotificationCreated" interface INotification { id: number, content: string } /** * Our notification channel which notif */ function useNotificationChannel (authUserId: integer, onChange: (notification: INotification) => void) { const channels = usePrivateChannels(authUserId) useEffect(() => { if (channels) { channels.listen(NOTIFICATION_EVENT, onChange) // NOTE: Laravel echo provides .notification method to listen to notification // which internally calls the listen method with the notification event // e.g notificationsChannel.notification(onChange) return () => { channels.stopListening(NOTIFICATION_EVENT) } } }, [channels, onChange]) } export function Notifications({ authUserId }: { authUserId: integer }) { const [notifications, setNotifications] = useState<Array<INotification>>([]) const handleNotificationsEvent = useCallback((notification: INotification) => { setNotifications( existingNotifications => ([notification].concat(existingNotifications)) ) }) useNotificationChannel(authUserId, handleNotificationsEvent) return <ol> {notifications.map(n => <li key={n.id}>{n.content}</li>} </ol> }  - 
        
sudkumar revised this gist
May 22, 2020 . 1 changed file with 38 additions and 42 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,57 +1,38 @@ import React, { useEffect, useState } from "react" import Echo from "laravel-echo" import Pusher from "pusher-js" /** * Pusher configuration */ const pusherConfig = { key: '<your_pusher_key_here>', cluster: '<pusher_cluster>', authEndpoint: '<auth_endpoint_for_private_channels>' // for example https://example.com/api/broadcasting/auth } type TChannels = Echo | undefined /** * Context for Channels */ export const ChannelContext = React.createContext<TChannels>(undefined) export type ChannelProps = { channels: TChannels } /** * Channel Context Provider */ export function ChannelContextProvider({ children, authUser, }: { children: React.ReactNode, authUser?: any }) { const [channels, setChannels] = useState<TChannels>(undefined) useEffect(() => { if (config.appEnv === "production" && authUser) { setChannels(getChannels()) } }, [user]) @@ -69,11 +50,26 @@ export function useChannels() { const channels = React.useContext(ChannelContext) return channels } /** * Get the pusher channels */ export function getChannels() { const client = new Pusher(pusherConfig.key, { cluster: pusherConfig.cluster, forceTLS: true, authEndpoint: pusherConfig.authEndpoint, auth: { headers: { // pass the authorization token when using private channels Authorization: `Bearer ${window.localStorage.getItem("access_token")}`, }, }, }) const channels = new Echo({ broadcaster: "pusher", client: client, }) return channels }  - 
        
sudkumar created this gist
May 22, 2020 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,79 @@ import React, { useEffect, useState } from "react" import Echo from "laravel-echo" import Pusher from "pusher-js" import { $PropertyType } from "utility-types" import config from "./config" import { withContext } from "./utils" import { useAuthUser } from "./Auth" export function getChannels() { const client = new Pusher(config.pusher.key, { cluster: config.pusher.cluster, forceTLS: true, authEndpoint: config.pusher.authEndpoint, auth: { headers: { Authorization: `Bearer ${getAuthorizationToken()}`, }, }, }) const channels = new Echo({ broadcaster: "pusher", client: client, }) return channels } /** * Context for Channels * * Usage: Wrap a component with withXHR (dont forget to extends the XHRProps in the swapped components) */ export const ChannelContext = React.createContext<Echo | undefined>(undefined) export const withChannels = withContext<Echo | undefined, "channels">( ChannelContext, "channels" ) export type ChannelProps = { channels: Echo | undefined } /** * Channel Context Provider */ export function ChannelContextProvider({ children, }: { children: React.ReactNode }) { const { user } = useAuthUser() const [channels, setChannels] = useState< $PropertyType<ChannelProps, "channels"> >(undefined) useEffect(() => { if (config.appEnv === "production" && user) { setChannels(getChannels()) } }, [user]) return ( <ChannelContext.Provider value={channels}> {children} </ChannelContext.Provider> ) } /** * Hook to use the channels provided via context */ export function useChannels() { const channels = React.useContext(ChannelContext) return channels } /** * Assuming we are storing the auth token in local storage */ export function getAuthorizationToken() { return localStorage.getItem("access_token") }