Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FilePickerBuilder: Allow to add custom buttons and use shipped picker #896

Merged
merged 2 commits into from
Aug 15, 2023
Merged
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
274 changes: 157 additions & 117 deletions lib/filepicker.ts
Original file line number Diff line number Diff line change
@@ -1,131 +1,171 @@
/// <reference types="@nextcloud/typings" />

declare const OC: Nextcloud.v25.OC | Nextcloud.v26.OC | Nextcloud.v27.OC;

export enum FilePickerType {
Choose = 1,
Move = 2,
Copy = 3,
CopyMove = 4,
Custom = 5,
Choose = 1,
Move = 2,
Copy = 3,
CopyMove = 4,
Custom = 5,
}

export interface FilePickerButton {
text: string
type?: 'primary' | 'secondary'
/** Passed on the callback as second argument */
id: number
}

export class FilePicker {
private title: string
private multiSelect: boolean
private mimeTypeFiler: string[]
private modal: boolean
private type: FilePickerType
private directoriesAllowed: boolean
private path?: string
private filter?: Nextcloud.v24.FilePickerFilter

public constructor(title: string,
multiSelect: boolean,
mimeTypeFilter: string[],
modal: boolean,
type: FilePickerType,
directoriesAllowed: boolean,
path?: string,
filter?: Nextcloud.v24.FilePickerFilter) {
this.title = title
this.multiSelect = multiSelect
this.mimeTypeFiler = mimeTypeFilter
this.modal = modal
this.type = type
this.directoriesAllowed = directoriesAllowed
this.path = path
this.filter = filter
}

public pick(): Promise<string> {
return new Promise((res, rej) => {
OC.dialogs.filepicker(
this.title,
res,
this.multiSelect,
this.mimeTypeFiler,
this.modal,
this.type,
this.path,
{
allowDirectoryChooser: this.directoriesAllowed,
filter: this.filter,
},
)
})
}

private title: string
private multiSelect: boolean
private mimeTypeFiler: string[]
private modal: boolean
private type: FilePickerType
private directoriesAllowed: boolean
private buttons?: FilePickerButton[]
private path?: string
private filter?: Nextcloud.v24.FilePickerFilter

public constructor(title: string,
multiSelect: boolean,
mimeTypeFilter: string[],
modal: boolean,
type: FilePickerType,
directoriesAllowed: boolean,
path?: string,
filter?: Nextcloud.v24.FilePickerFilter,
buttons?: FilePickerButton[]) {
this.title = title
this.multiSelect = multiSelect
this.mimeTypeFiler = mimeTypeFilter
this.modal = modal
this.type = type
this.directoriesAllowed = directoriesAllowed
this.path = path
this.filter = filter
this.buttons = buttons
}

public async pick(): Promise<[string|string[], FilePickerType]> {
// Async import for module splitting (treeshaking)
const filepicker = (await import('./legacy')).filepicker

return new Promise((resolve) => {
const buttons = this.buttons?.map(button => ({
defaultButton: button.type === 'primary',
label: button.text,
type: button.id,
}))

filepicker(
this.title,
(path: string | string[], type: FilePickerType) => resolve([path, type]),
this.multiSelect,
this.mimeTypeFiler,
this.modal,
this.type,
this.path,
{
allowDirectoryChooser: this.directoriesAllowed,
filter: this.filter,
buttons,
},
)
})
}

}

export class FilePickerBuilder {
private title: string
private multiSelect: boolean = false
private mimeTypeFiler: string[] = []
private modal: boolean = true
private type: FilePickerType = FilePickerType.Choose
private directoriesAllowed: boolean = false
private path?: string
private filter?: Nextcloud.v24.FilePickerFilter

public constructor(title: string) {
this.title = title
}

public setMultiSelect(ms: boolean): FilePickerBuilder {
this.multiSelect = ms
return this
}

public addMimeTypeFilter(filter: string): FilePickerBuilder {
this.mimeTypeFiler.push(filter)
return this
}

public setMimeTypeFilter(filter: string[]): FilePickerBuilder {
this.mimeTypeFiler = filter
return this
}

public setModal(modal: boolean): FilePickerBuilder {
this.modal = modal
return this
}

public setType(type: FilePickerType): FilePickerBuilder {
this.type = type
return this
}

public allowDirectories(allow: boolean = true): FilePickerBuilder {
this.directoriesAllowed = allow
return this
}

public startAt(path: string): FilePickerBuilder {
this.path = path
return this
}

public setFilter(filter: Nextcloud.v24.FilePickerFilter): FilePickerBuilder {
this.filter = filter
return this
}

public build(): FilePicker {
return new FilePicker(
this.title,
this.multiSelect,
this.mimeTypeFiler,
this.modal,
this.type,
this.directoriesAllowed,
this.path,
this.filter,
)
}

private title: string
private multiSelect = false
private mimeTypeFiler: string[] = []
private modal = true
private type: FilePickerType = FilePickerType.Choose
private directoriesAllowed = false
private path?: string
private filter?: Nextcloud.v24.FilePickerFilter
private buttons: FilePickerButton[] = []

public constructor(title: string) {
this.title = title
}

public setMultiSelect(ms: boolean): FilePickerBuilder {
this.multiSelect = ms
return this
}

public addMimeTypeFilter(filter: string): FilePickerBuilder {
this.mimeTypeFiler.push(filter)
return this
}

public setMimeTypeFilter(filter: string[]): FilePickerBuilder {
this.mimeTypeFiler = filter
return this
}

public addButton(button: FilePickerButton): FilePickerBuilder {
this.buttons.push(button)
return this
}

/**
* @param modal no function
* @deprecated Does not have any effect as the dialog is always modal
*/
public setModal(modal: boolean): FilePickerBuilder {
this.modal = modal
return this
}

public setType(type: FilePickerType): FilePickerBuilder {
this.type = type
return this
}

public allowDirectories(allow = true): FilePickerBuilder {
this.directoriesAllowed = allow
return this
}

public startAt(path: string): FilePickerBuilder {
this.path = path
return this
}

public setFilter(filter: Nextcloud.v24.FilePickerFilter): FilePickerBuilder {
this.filter = filter
return this
}

public build(): FilePicker {
if (this.buttons && this.type !== FilePickerType.Custom) {
console.error('FilePickerBuilder: When adding custom buttons the `type` must be set to `FilePickerType.Custom`.')
}

return new FilePicker(
this.title,
this.multiSelect,
this.mimeTypeFiler,
this.modal,
this.type,
this.directoriesAllowed,
this.path,
this.filter,
this.buttons,
)
}

}

/**
*
* @param title Title of the file picker
*/
export function getFilePickerBuilder(title: string): FilePickerBuilder {
return new FilePickerBuilder(title)
return new FilePickerBuilder(title)
}