Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions .changeset/calm-geese-wink.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
---
"@uppy/aws-s3": patch
"@uppy/url": patch
"@uppy/companion-client": patch
"@uppy/components": patch
"@uppy/provider-views": patch
"@uppy/react": patch
"@uppy/svelte": patch
"@uppy/vue": patch
---

Add `useGooglePicker` react hook and remove unused `RequestClient` options `name`, `pluginId` and `provider`.
2 changes: 2 additions & 0 deletions examples/react/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
"dependencies": {
"@tailwindcss/vite": "^4.1.11",
"@uppy/core": "workspace:*",
"@uppy/google-drive-picker": "workspace:*",
"@uppy/google-photos-picker": "workspace:*",
"@uppy/react": "workspace:*",
"@uppy/remote-sources": "workspace:*",
"@uppy/screen-capture": "workspace:*",
Expand Down
35 changes: 28 additions & 7 deletions examples/react/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/** biome-ignore-all lint/nursery/useUniqueElementIds: it's fine */
import Uppy from '@uppy/core'
import GoogleDrivePicker from '@uppy/google-drive-picker'
import {
Dropzone,
FilesGrid,
Expand All @@ -12,31 +13,51 @@ import UppyScreenCapture from '@uppy/screen-capture'
import Tus from '@uppy/tus'
import UppyWebcam from '@uppy/webcam'
import { useRef, useState } from 'react'
import CustomDropzone from './CustomDropzone'
import CustomDropzone, { type CustomDropzonePlugin } from './CustomDropzone'
import { RemoteSource } from './RemoteSource'
import ScreenCapture from './ScreenCapture'
import Webcam from './Webcam'

import './app.css'
import '@uppy/react/css/style.css'
import GooglePhotosPicker from '@uppy/google-photos-picker'

const companionUrl = 'http://localhost:3020'
const googlePickerClientId = '' // see GOOGLE_PICKER_CLIENT_ID in dev Dashboard
const googlePickerApiKey = '' // see GOOGLE_PICKER_API_KEY in dev Dashboard
const googlePickerAppId = '' // see GOOGLE_PICKER_APP_ID in dev Dashboard

function App() {
const [uppy] = useState(() =>
new Uppy()
new Uppy({
restrictions: {
maxNumberOfFiles: 1,
},
})
.use(Tus, {
endpoint: 'https://tusd.tusdemo.net/files/',
})
.use(GoogleDrivePicker, {
clientId: googlePickerClientId,
companionUrl,
apiKey: googlePickerApiKey,
appId: googlePickerAppId,
})
.use(GooglePhotosPicker, {
clientId: googlePickerClientId,
companionUrl,
})
.use(UppyWebcam)
.use(UppyScreenCapture)
.use(UppyRemoteSources, { companionUrl: 'http://localhost:3020' }),
.use(UppyRemoteSources, { companionUrl }),
)

const dialogRef = useRef<HTMLDialogElement>(null)
const [modalPlugin, setModalPlugin] = useState<
'webcam' | 'dropbox' | 'screen-capture' | null
>(null)
const [modalPlugin, setModalPlugin] = useState<CustomDropzonePlugin | null>(
null,
)

function openModal(plugin: 'webcam' | 'dropbox' | 'screen-capture') {
function openModal(plugin: CustomDropzonePlugin) {
setModalPlugin(plugin)
dialogRef.current?.showModal()
}
Expand Down
41 changes: 39 additions & 2 deletions examples/react/src/CustomDropzone.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,28 @@
import { ProviderIcon, useDropzone, useFileInput } from '@uppy/react'
import {
ProviderIcon,
useDropzone,
useFileInput,
useGooglePicker,
} from '@uppy/react'

export type CustomDropzonePlugin = 'webcam' | 'dropbox' | 'screen-capture'

export interface CustomDropzoneProps {
openModal: (plugin: 'webcam' | 'dropbox' | 'screen-capture') => void
openModal: (plugin: CustomDropzonePlugin) => void
}

export function CustomDropzone({ openModal }: CustomDropzoneProps) {
const { getRootProps, getInputProps } = useDropzone({ noClick: true })
const { getButtonProps, getInputProps: getFileInputProps } = useFileInput()

const googleDrivePicker = useGooglePicker({
pickerType: 'drive',
})

const googlePhotosPicker = useGooglePicker({
pickerType: 'photos',
})

return (
<div>
<input {...getInputProps()} className="hidden" />
Expand Down Expand Up @@ -59,6 +74,28 @@ export function CustomDropzone({ openModal }: CustomDropzoneProps) {
</div>
Dropbox
</button>

<button
type="button"
onClick={() => googleDrivePicker.show()}
className="hover:bg-gray-100 transition-colors p-2 rounded-md flex flex-col items-center gap-2 text-sm"
>
<div className="bg-white shadow-md rounded-md p-1">
<ProviderIcon provider="googledrive" />
</div>
Google Drive
</button>

<button
type="button"
onClick={() => googlePhotosPicker.show()}
className="hover:bg-gray-100 transition-colors p-2 rounded-md flex flex-col items-center gap-2 text-sm"
>
<div className="bg-white shadow-md rounded-md p-1">
<ProviderIcon provider="googlephotos" />
</div>
Google Photos
</button>
</div>
</div>
</div>
Expand Down
2 changes: 0 additions & 2 deletions packages/@uppy/aws-s3/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -426,8 +426,6 @@ export default class AwsS3Multipart<
}
if ('endpoint' in opts) {
this.#client = new RequestClient(this.uppy, {
pluginId: this.id,
provider: 'AWS',
companionUrl: this.opts.endpoint!,
companionHeaders: this.opts.headers,
companionCookiesRule: this.opts.cookiesRule,
Expand Down
3 changes: 3 additions & 0 deletions packages/@uppy/companion-client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@
"p-retry": "^6.1.0"
},
"devDependencies": {
"@types/gapi": "^0.0.47",
"@types/google.accounts": "^0.0.14",
"@types/google.picker": "^0.0.42",
"jsdom": "^26.1.0",
"typescript": "^5.8.3",
"vitest": "^3.2.4"
Expand Down
4 changes: 2 additions & 2 deletions packages/@uppy/companion-client/src/Provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,8 @@ export default class Provider<M extends Meta, B extends Body>
super(uppy, opts)
this.provider = opts.provider
this.id = this.provider
this.name = this.opts.name || getName(this.id)
this.pluginId = this.opts.pluginId
this.name = opts.name || getName(this.id)
this.pluginId = opts.pluginId
this.tokenKey = `companion-${this.pluginId}-auth-token`
this.companionKeysParams = this.opts.companionKeysParams
this.preAuthToken = null
Expand Down
4 changes: 0 additions & 4 deletions packages/@uppy/companion-client/src/RequestClient.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,9 @@ describe('RequestClient', () => {
it('has a hostname without trailing slash', () => {
const mockCore = { getState: () => ({}) } as any
const a = new RequestClient(mockCore, {
pluginId: 'test',
provider: 'test',
companionUrl: 'http://companion.uppy.io',
})
const b = new RequestClient(mockCore, {
pluginId: 'test2',
provider: 'test2',
companionUrl: 'http://companion.uppy.io/',
})

Expand Down
3 changes: 0 additions & 3 deletions packages/@uppy/companion-client/src/RequestClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,6 @@ import AuthError from './AuthError.js'
type CompanionHeaders = Record<string, string> | undefined

export type Opts = {
name?: string
provider: string
pluginId: string
companionUrl: string
companionCookiesRule?: 'same-origin' | 'include' | 'omit'
companionHeaders?: CompanionHeaders
Expand Down
14 changes: 11 additions & 3 deletions packages/@uppy/companion-client/src/SearchProvider.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
import type { Body, Meta, Uppy } from '@uppy/core'
import type { CompanionClientSearchProvider } from '@uppy/utils'
import RequestClient, { type Opts } from './RequestClient.js'
import RequestClient, {
type Opts as RequestClientOpts,
} from './RequestClient.js'

export interface Opts extends RequestClientOpts {
name?: string
provider: string
pluginId: string
}

const getName = (id: string): string => {
return id
Expand All @@ -25,8 +33,8 @@ export default class SearchProvider<M extends Meta, B extends Body>
super(uppy, opts)
this.provider = opts.provider
this.id = this.provider
this.name = this.opts.name || getName(this.id)
this.pluginId = this.opts.pluginId
this.name = opts.name || getName(this.id)
this.pluginId = opts.pluginId
}

fileUrl(id: string): string {
Expand Down
Loading