Skip to content

Commit 69f1f11

Browse files
authored
Merge pull request framer#320 from framer/google-sheets-menu
Google Sheets: add plugin menu
2 parents fffe0e3 + 6f9cea7 commit 69f1f11

6 files changed

Lines changed: 76 additions & 27 deletions

File tree

plugins/google-sheets/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
"dependencies": {
1414
"@tanstack/react-query": "^5.81.5",
1515
"classnames": "^2.5.1",
16-
"framer-plugin": "^3.3.2",
16+
"framer-plugin": "^3.5.2",
1717
"react": "^18.3.1",
1818
"react-dom": "^18.3.1",
1919
"react-error-boundary": "^6.0.0",

plugins/google-sheets/src/App.tsx

Lines changed: 44 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,14 @@ import { MapSheetFieldsPage } from "./pages/MapSheetFields"
88
import { Problem } from "./pages/Problem"
99
import { SelectSheetPage } from "./pages/SelectSheet"
1010
import {
11-
getPluginContext,
1211
type PluginContext,
1312
type PluginContextUpdate,
1413
syncSheet,
1514
useFetchUserInfo,
1615
useSheetQuery,
1716
useSyncSheetMutation,
1817
} from "./sheets"
18+
import { showFieldMappingUI, showLoginUI } from "./ui"
1919
import { assert, syncMethods } from "./utils"
2020

2121
interface AppProps {
@@ -64,6 +64,8 @@ export function AuthenticatedApp({ pluginContext, setContext }: AuthenticatedApp
6464

6565
const { data: sheet, isPending: isSheetPending } = useSheetQuery(spreadsheetId ?? "", sheetTitle ?? "")
6666

67+
const hasSheet = Boolean(spreadsheetId && sheetTitle)
68+
6769
const syncMutation = useSyncSheetMutation({
6870
onSuccess: result => {
6971
logSyncResult(result)
@@ -86,19 +88,45 @@ export function AuthenticatedApp({ pluginContext, setContext }: AuthenticatedApp
8688
}, [isUserInfoError, isSelectSheetError, setContext])
8789

8890
useLayoutEffect(() => {
89-
const width = sheetTitle !== null ? 360 : 320
90-
const height = sheetTitle !== null ? 425 : 345
91-
92-
void framer.showUI({
93-
width,
94-
height,
95-
minWidth: width,
96-
minHeight: height,
97-
// Only allow resizing when mapping fields as the default size could not be enough.
98-
// This will keep the given dimensions in the Select Sheet Screen.
99-
resizable: sheetTitle !== null,
100-
})
101-
}, [sheetTitle])
91+
const showUI = async () => {
92+
try {
93+
if (hasSheet) {
94+
await showFieldMappingUI()
95+
} else {
96+
await showLoginUI()
97+
}
98+
} catch (error) {
99+
console.error(error)
100+
framer.notify("Failed to open plugin. Check the logs for more details.", { variant: "error" })
101+
}
102+
}
103+
104+
void showUI()
105+
}, [sheetTitle, hasSheet, isSheetPending])
106+
107+
useEffect(() => {
108+
framer
109+
.setMenu([
110+
{
111+
label: `View ${sheetTitle ?? ""} in Google Sheets`,
112+
visible: Boolean(spreadsheetId),
113+
onAction: () => {
114+
if (!spreadsheetId) return
115+
window.open(`https://docs.google.com/spreadsheets/d/${spreadsheetId}/edit`, "_blank")
116+
},
117+
},
118+
{ type: "separator" },
119+
{
120+
label: "Log Out",
121+
onAction: () => {
122+
void auth.logout()
123+
},
124+
},
125+
])
126+
.catch((e: unknown) => {
127+
console.error(e)
128+
})
129+
}, [sheetTitle, spreadsheetId])
102130

103131
if (!spreadsheetId || sheetTitle === null) {
104132
return (
@@ -185,7 +213,7 @@ export function App({ pluginContext }: AppProps) {
185213
}),
186214
})
187215

188-
await framer.closePlugin()
216+
void framer.closePlugin()
189217
}
190218

191219
void task()
@@ -199,14 +227,7 @@ export function App({ pluginContext }: AppProps) {
199227
<p className="text-content">
200228
Your Google Account does not have access to the synced spreadsheet. Check your access and try again
201229
or{" "}
202-
<a
203-
href="#"
204-
className="text-sheets-green"
205-
onClick={() => {
206-
auth.logout()
207-
void getPluginContext().then(setContext)
208-
}}
209-
>
230+
<a href="#" className="text-sheets-green" onClick={() => void auth.logout()}>
210231
log out
211232
</a>{" "}
212233
and try a different account.

plugins/google-sheets/src/auth.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
import { framer } from "framer-plugin"
2+
import { showLoginUI } from "./ui"
3+
14
interface Tokens {
25
access_token: string
36
refresh_token?: string
@@ -33,8 +36,12 @@ class Auth {
3336
: "https://oauth.framer.wtf/google-sheets-plugin"
3437
}
3538

36-
logout() {
39+
async logout() {
3740
this.tokens.clear()
41+
await framer.setMenu([])
42+
await showLoginUI()
43+
framer.notify("Logged out of your Google account", { variant: "success" })
44+
window.location.reload()
3845
}
3946

4047
async refreshTokens() {

plugins/google-sheets/src/main.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,5 +35,5 @@ try {
3535
)
3636
} catch (e) {
3737
const message = e instanceof Error ? e.message : String(e)
38-
await framer.closePlugin(message, { variant: "error" })
38+
void framer.closePlugin(message, { variant: "error" })
3939
}

plugins/google-sheets/src/ui.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import { framer } from "framer-plugin"
2+
3+
export async function showFieldMappingUI() {
4+
await framer.showUI({
5+
width: 425,
6+
height: 425,
7+
minWidth: 360,
8+
minHeight: 425,
9+
resizable: true,
10+
})
11+
}
12+
13+
export async function showLoginUI() {
14+
await framer.showUI({
15+
width: 320,
16+
height: 345,
17+
minWidth: 320,
18+
minHeight: 345,
19+
resizable: false,
20+
})
21+
}

yarn.lock

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4811,7 +4811,7 @@ __metadata:
48114811
"@types/react": "npm:^18.3.23"
48124812
"@types/react-dom": "npm:^18.3.7"
48134813
classnames: "npm:^2.5.1"
4814-
framer-plugin: "npm:^3.3.2"
4814+
framer-plugin: "npm:^3.5.2"
48154815
react: "npm:^18.3.1"
48164816
react-dom: "npm:^18.3.1"
48174817
react-error-boundary: "npm:^6.0.0"

0 commit comments

Comments
 (0)