-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Add sample with some more features using Next JS (React + TS)
- Loading branch information
Showing
17 changed files
with
536 additions
and
295 deletions.
There are no files selected for viewing
This file contains 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 characters
This file contains 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 characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,5 @@ | ||
# Build outputs for sample Meet Add-ons | ||
addons-web-sdk/samples/package-lock.json | ||
**/dist | ||
**/node_modules | ||
**/.DS_Store |
This file contains 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 characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
# next.js | ||
/.next/ | ||
next-env.d.ts | ||
out |
This file contains 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 characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
# Pretty Colors: Next JS Add-on | ||
|
||
This is a Meet Add-on built in Next JS. This add-on displays an animation that is intended to create a simple "shimmer" effect based on the color that each call participant selects. This add-on only exists to show more features of Google Meet Add-ons than can be found at <https://github.com/googleworkspace/meet/tree/main/addons-web-sdk/samples/hello-world-next-js>. If you find anything about the configuration confusing, please see that more basic example. | ||
|
||
You can view a deployed version of this Add-on at <https://googleworkspace.github.io/meet/animation-next-js/sidepanel> and its corresponding [mainstage.html](https://googleworkspace.github.io/meet/animation-next-js/mainstage). |
This file contains 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 characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
/** @type {import('next').NextConfig} */ | ||
const nextConfig = { | ||
basePath: '/meet/animation-next-js', | ||
distDir: '../dist/animation-next-js', | ||
output: 'export', | ||
}; | ||
|
||
export default nextConfig; |
This file contains 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 characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
{ | ||
"name": "animation-next-js", | ||
"version": "0.1.0", | ||
"private": true, | ||
"scripts": { | ||
"dev": "next dev", | ||
"build": "next build", | ||
"start": "next start", | ||
"lint": "next lint" | ||
}, | ||
"dependencies": { | ||
"@googleworkspace/meet-addons": "^0.10.0", | ||
"next": "14.2.7", | ||
"react": "^18", | ||
"react-dom": "^18" | ||
}, | ||
"devDependencies": { | ||
"@types/node": "^20", | ||
"@types/react": "^18", | ||
"@types/react-dom": "^18", | ||
"typescript": "^5" | ||
} | ||
} |
56 changes: 56 additions & 0 deletions
56
addons-web-sdk/samples/animation-next-js/src/app/activitysidepanel/page.tsx
This file contains 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 characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
"use client"; | ||
|
||
import { useEffect, useState } from 'react'; | ||
import { | ||
meet, | ||
MeetSidePanelClient, | ||
} from '@googleworkspace/meet-addons/meet.addons'; | ||
import { CLOUD_PROJECT_NUMBER } from '../../shared/constants'; | ||
|
||
/** | ||
* This page displays in the Side Panel after the activity has started to allow | ||
* each call participant to modify the base color of the main stage animation. | ||
*/ | ||
export default function Page() { | ||
const [sidePanelClient, setSidePanelClient] = useState<MeetSidePanelClient>(); | ||
|
||
/** | ||
* Sends a newly chosen color to the main stage, using frame-to-frame | ||
* messaging. | ||
* @param newColor Hex code of the new color. | ||
*/ | ||
async function updateColor(newColor: string) { | ||
if (!sidePanelClient) { | ||
throw new Error("Side Panel is not yet initialized!"); | ||
} | ||
|
||
await sidePanelClient.notifyMainStage(newColor); | ||
} | ||
|
||
useEffect(() => { | ||
/** | ||
* Initializes the Add-on Side Panel Client. | ||
* https://developers.google.com/meet/add-ons/reference/websdk/addon_sdk.meetsidepanelclient | ||
*/ | ||
async function initializeSidePanelClient() { | ||
const session = await meet.addon.createAddonSession({ | ||
cloudProjectNumber: CLOUD_PROJECT_NUMBER, | ||
}); | ||
const client = await session.createSidePanelClient(); | ||
setSidePanelClient(client); | ||
} | ||
initializeSidePanelClient(); | ||
}, []); | ||
|
||
return ( | ||
<> | ||
<label htmlFor="pretty-color">Change the color. Only you will see this:</label> | ||
<input | ||
type="color" | ||
id="pretty-color" | ||
name="pretty-color" | ||
defaultValue="#00ff00" | ||
onChange={(e) => updateColor(e.target.value)} /> | ||
</> | ||
) | ||
} |
16 changes: 16 additions & 0 deletions
16
addons-web-sdk/samples/animation-next-js/src/app/layout.tsx
This file contains 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 characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
export const metadata = { | ||
title: 'Next.js', | ||
description: 'Generated by Next.js', | ||
} | ||
|
||
export default function RootLayout({ | ||
children, | ||
}: { | ||
children: React.ReactNode | ||
}) { | ||
return ( | ||
<html lang="en"> | ||
<body>{children}</body> | ||
</html> | ||
) | ||
} |
68 changes: 68 additions & 0 deletions
68
addons-web-sdk/samples/animation-next-js/src/app/mainstage/page.tsx
This file contains 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 characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
"use client"; | ||
|
||
import { useEffect, useState } from 'react'; | ||
import { | ||
meet, | ||
FrameToFrameMessage, | ||
MeetMainStageClient | ||
} from '@googleworkspace/meet-addons/meet.addons'; | ||
import { CLOUD_PROJECT_NUMBER } from '../../shared/constants'; | ||
import PrettyColors from '@/components/prettyColors'; | ||
|
||
/** | ||
* See: https://developers.google.com/meet/add-ons/guides/overview#main-stage | ||
*/ | ||
export default function Page() { | ||
const [color, setColor] = useState<string>("#00ff00"); | ||
|
||
/** | ||
* Creates a MeetMainStageClient to control the main stage of the add-on. | ||
* https://developers.google.com/meet/add-ons/reference/websdk/addon_sdk.meetmainstageclient | ||
*/ | ||
async function initializeMainStageClient(): Promise<MeetMainStageClient> { | ||
const session = await meet.addon.createAddonSession({ | ||
cloudProjectNumber: CLOUD_PROJECT_NUMBER, | ||
}); | ||
return await session.createMainStageClient(); | ||
} | ||
|
||
/** | ||
* Parses the collaboration starting state from the side panel, and updates | ||
* the color used for the main animation. | ||
*/ | ||
async function setStartingState(mainStageClient: MeetMainStageClient) { | ||
const startingState = await mainStageClient.getActivityStartingState(); | ||
const additionalData = JSON.parse(startingState.additionalData ?? '{}'); | ||
setColor(additionalData.startingColor); | ||
} | ||
|
||
/** | ||
* Listens for new frame-to-frame messages from the side panel that update | ||
* the color used for the main animation. | ||
*/ | ||
function awaitNewColor(mainStageClient: MeetMainStageClient) { | ||
mainStageClient.on('frameToFrameMessage', (message: FrameToFrameMessage) => { | ||
setColor(message.payload); | ||
}); | ||
} | ||
|
||
useEffect(() => { | ||
/** | ||
* Initialize the main stage by initializing the client, then using that | ||
* client to get the starting state (color), and observe any new colors | ||
* passed from the Side Panel. | ||
*/ | ||
async function initializeMainStage() { | ||
const client = await initializeMainStageClient(); | ||
setStartingState(client); | ||
awaitNewColor(client); | ||
} | ||
initializeMainStage(); | ||
}, []); | ||
|
||
return ( | ||
<> | ||
<PrettyColors baseColor={color}></PrettyColors> | ||
</> | ||
) | ||
} |
This file contains 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 characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
"use client"; | ||
|
||
import { useEffect } from 'react'; | ||
import { meet } from '@googleworkspace/meet-addons/meet.addons.screenshare'; | ||
import { CLOUD_PROJECT_NUMBER, SIDE_PANEL_URL } from '../shared/constants'; | ||
|
||
export default function App() { | ||
/** | ||
* Screensharing this page will prompt you to install/open this add-on. | ||
* When it is opened, it will prompt you to set up the add-on in the side | ||
* panel before starting the activity for everyone. | ||
* See: https://developers.google.com/meet/add-ons/guides/screen-sharing | ||
* | ||
* Note that in React, this must be wrapped in `useEffect`, so that `window` | ||
* is available. | ||
*/ | ||
useEffect(() => { | ||
meet.addon.screensharing.exposeToMeetWhenScreensharing( | ||
{ | ||
cloudProjectNumber: CLOUD_PROJECT_NUMBER, | ||
sidePanelUrl: SIDE_PANEL_URL, | ||
startActivityOnOpen: false, | ||
} | ||
); | ||
}) | ||
|
||
return ( | ||
<> | ||
<div>Screenshare this page to promote an add-on.</div> | ||
</> | ||
) | ||
} |
67 changes: 67 additions & 0 deletions
67
addons-web-sdk/samples/animation-next-js/src/app/sidepanel/page.tsx
This file contains 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 characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
"use client"; | ||
|
||
import { useEffect, useState } from 'react'; | ||
import { meet, MeetSidePanelClient } from '@googleworkspace/meet-addons/meet.addons'; | ||
import { | ||
ACTIVITY_SIDE_PANEL_URL, | ||
CLOUD_PROJECT_NUMBER, | ||
MAIN_STAGE_URL | ||
} from '../../shared/constants'; | ||
|
||
/** | ||
* See: https://developers.google.com/meet/add-ons/guides/overview#side-panel | ||
*/ | ||
export default function Page() { | ||
const [sidePanelClient, setSidePanelClient] = useState<MeetSidePanelClient>(); | ||
|
||
/** | ||
* Starts the add-on activity and passes the selected color to the Main Stage, | ||
* as part of the activity starting state. | ||
*/ | ||
async function startCollaboration(e: unknown) { | ||
if (!sidePanelClient) { | ||
throw new Error("Side Panel is not yet initialized!"); | ||
} | ||
|
||
const startingColor = ( | ||
document.getElementById('starting-color')! as HTMLInputElement | ||
).value; | ||
await sidePanelClient.startActivity({ | ||
mainStageUrl: MAIN_STAGE_URL, | ||
sidePanelUrl: ACTIVITY_SIDE_PANEL_URL, | ||
// Pass the selected color to customize the initial display. | ||
additionalData: `{\"startingColor\": \"${startingColor}\"}`, | ||
}); | ||
window.location.replace(ACTIVITY_SIDE_PANEL_URL + window.location.search); | ||
} | ||
|
||
useEffect(() => { | ||
/** | ||
* Initializes the Add-on Side Panel Client. | ||
* https://developers.google.com/meet/add-ons/reference/websdk/addon_sdk.meetsidepanelclient | ||
*/ | ||
async function initializeSidePanelClient() { | ||
const session = await meet.addon.createAddonSession({ | ||
cloudProjectNumber: CLOUD_PROJECT_NUMBER, | ||
}); | ||
const client = await session.createSidePanelClient(); | ||
setSidePanelClient(client); | ||
} | ||
initializeSidePanelClient(); | ||
}, []); | ||
|
||
return ( | ||
<> | ||
<div> | ||
Welcome to Pretty Colors! This is a contrived demo add-on that lets you | ||
look at an animation involving your favorite color. | ||
</div> | ||
<label htmlFor="starting-color">Pick a color you like. Everyone will see this:</label> | ||
<input type="color" id="starting-color" name="starting-color" defaultValue="#00ff00" /> | ||
<br /> | ||
<button onClick={startCollaboration}> | ||
Start the animation! | ||
</button> | ||
</> | ||
) | ||
} |
34 changes: 34 additions & 0 deletions
34
addons-web-sdk/samples/animation-next-js/src/components/prettyColors.css
This file contains 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 characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
html, body { | ||
height: 100%; | ||
margin: 0; | ||
width: 100%; | ||
} | ||
|
||
.prettyColorsContainer { | ||
height: 100%; | ||
overflow: hidden; | ||
position: relative; | ||
width: 100%; | ||
} | ||
|
||
.prettyLine { | ||
animation-name: spin; | ||
animation-direction: normal; | ||
animation-duration: 10000ms; | ||
animation-iteration-count: infinite; | ||
animation-timing-function: linear; | ||
/* border-width: 8px 0 8px 0; | ||
border-style: solid; */ | ||
height: 10px; | ||
position: absolute; | ||
width: 40%; | ||
} | ||
|
||
.prettyLine:hover { | ||
animation-direction: reverse; | ||
} | ||
|
||
@keyframes spin { | ||
from {transform:rotate(0deg);} | ||
to {transform:rotate(360deg);} | ||
} |
Oops, something went wrong.