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

fix(FilePicker): Fix exported typings and cleanup file picker files #907

Merged
merged 1 commit into from Aug 17, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
8 changes: 4 additions & 4 deletions l10n/messages.pot
Expand Up @@ -30,11 +30,11 @@ msgstr ""
msgid "Copy"
msgstr ""

#: lib/components/FilePicker/FilePicker.vue:214
#: lib/components/FilePicker/FilePicker.vue:210
msgid "Could not create the new folder"
msgstr ""

#: lib/components/FilePicker/FilePicker.vue:137
#: lib/components/FilePicker/FilePicker.vue:133
#: lib/components/FilePicker/FilePickerNavigation.vue:65
msgid "Favorites"
msgstr ""
Expand All @@ -55,7 +55,7 @@ msgstr ""
msgid "Name"
msgstr ""

#: lib/components/FilePicker/FilePicker.vue:137
#: lib/components/FilePicker/FilePicker.vue:133
#: lib/components/FilePicker/FilePickerNavigation.vue:61
msgid "Recent"
msgstr ""
Expand All @@ -78,7 +78,7 @@ msgstr ""
msgid "Size"
msgstr ""

#: lib/toast.ts:228
#: lib/toast.ts:229
msgid "Undo"
msgstr ""

Expand Down
18 changes: 10 additions & 8 deletions lib/components/DialogButton.vue
Expand Up @@ -8,17 +8,19 @@
</template>

<script setup lang="ts">
import type { AsyncComponent, Component } from 'vue'
import type { IDialogButton } from './types'
import { NcButton } from '@nextcloud/vue'

export interface IDialogButton {
label: string,
icon?: Component | AsyncComponent,
callback: () => void,
type?: 'primary' | 'secondary' | 'error' | 'warning' | 'success'
}
// with vue 3.3:
// const props = defineProps<IDialogButton>()

const props = defineProps<{
callback: IDialogButton['callback'],
label: IDialogButton['label'],
icon: IDialogButton['icon'],
type: IDialogButton['type'],
}>()

const props = defineProps<IDialogButton>()
const emit = defineEmits<(e: 'click', event: MouseEvent) => void>()

const handleClick = (e: MouseEvent) => {
Expand Down
2 changes: 1 addition & 1 deletion lib/components/FilePicker/FileList.vue
Expand Up @@ -66,7 +66,7 @@ import type { Node } from '@nextcloud/files'
import { getCanonicalLocale } from '@nextcloud/l10n'
import { NcButton, NcCheckboxRadioSwitch } from '@nextcloud/vue'
import { join } from 'path'
import { t } from '../../l10n'
import { t } from '../../utils/l10n'
import { computed, ref, type Ref } from 'vue'

import IconSortAscending from 'vue-material-design-icons/MenuDown.vue'
Expand Down
2 changes: 1 addition & 1 deletion lib/components/FilePicker/FileListRow.vue
Expand Up @@ -27,7 +27,7 @@
import { type Node, formatFileSize } from '@nextcloud/files'
import { NcCheckboxRadioSwitch } from '@nextcloud/vue'
import { computed } from 'vue'
import { t } from '../../l10n'
import { t } from '../../utils/l10n'

import NcDatetime from './NcDatetime.vue'

Expand Down
10 changes: 3 additions & 7 deletions lib/components/FilePicker/FilePicker.vue
Expand Up @@ -28,25 +28,21 @@
</template>

<script setup lang="ts">
import type { IDialogButton } from '../DialogButton.vue'
import type { IFilePickerButton } from '../types'
import { davRootPath, type Node } from '@nextcloud/files'

import DialogBase from '../DialogBase.vue'
import FileList from './FileList.vue'
import FilePickerBreadcrumbs from './FilePickerBreadcrumbs.vue'
import FilePickerNavigation from './FilePickerNavigation.vue'

import { t } from '../../l10n'
import { t } from '../../utils/l10n'
import { join } from 'path'
import { computed, onMounted, ref, toRef } from 'vue'
import { useDAVFiles } from '../../usables/dav'
import { useMimeFilter } from '../../usables/mime'
import { showError } from '../../toast'

export interface IFilePickerButton extends Omit<IDialogButton, 'callback'> {
callback: (nodes: Node[]) => void
}

const props = withDefaults(defineProps<{
/** Buttons to be displayed */
buttons: IFilePickerButton[]
Expand All @@ -69,7 +65,7 @@ const props = withDefaults(defineProps<{
/**
* Custom filter function used to filter pickable files
*/
filterFn?: (node: Node) => boolean
filterFn?: (node: Node) => boolean

/**
* List of allowed mime types
Expand Down
2 changes: 1 addition & 1 deletion lib/components/FilePicker/FilePickerBreadcrumbs.vue
Expand Up @@ -48,7 +48,7 @@ import IconPlus from 'vue-material-design-icons/Plus.vue'

import { NcActions, NcActionInput, NcBreadcrumbs, NcBreadcrumb } from '@nextcloud/vue'
import { computed, ref } from 'vue'
import { t } from '../../l10n'
import { t } from '../../utils/l10n'

const props = defineProps<{
/** Current path to display */
Expand Down
2 changes: 1 addition & 1 deletion lib/components/FilePicker/FilePickerNavigation.vue
Expand Up @@ -48,7 +48,7 @@ import IconMagnify from 'vue-material-design-icons/Magnify.vue'
import IconStar from 'vue-material-design-icons/Star.vue'

import { NcButton, NcSelect, NcTextField } from '@nextcloud/vue'
import { t } from '../../l10n'
import { t } from '../../utils/l10n'
import { computed } from 'vue'
import { Fragment } from 'vue-frag'

Expand Down
2 changes: 1 addition & 1 deletion lib/components/FilePicker/NcDatetime.vue
Expand Up @@ -27,7 +27,7 @@

<script lang="ts">
import { getCanonicalLocale } from '@nextcloud/l10n'
import { t } from '../../l10n.js'
import { t } from '../../utils/l10n.js'
import { defineComponent, type PropType } from 'vue'

const FEW_SECONDS_AGO = {
Expand Down
29 changes: 29 additions & 0 deletions lib/components/FilePicker/index.ts
@@ -0,0 +1,29 @@
/**
* @copyright Copyright (c) 2023 Ferdinand Thiessen <opensource@fthiessen.de>
*
* @author Ferdinand Thiessen <opensource@fthiessen.de>
*
* @license AGPL-3.0-or-later
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/

import { defineAsyncComponent, type AsyncComponent } from 'vue'
import type { DefaultComputed, DefaultData, DefaultMethods } from 'vue/types/options.js'

export type IFilePicker = typeof import('./FilePicker.vue').default

// Async import for module splitting (treeshaking)
export const FilePickerVue = defineAsyncComponent(() => import('./FilePicker.vue')) as AsyncComponent<DefaultData<never>, DefaultMethods<never>, DefaultComputed, IFilePicker['props']>
35 changes: 35 additions & 0 deletions lib/components/types.ts
@@ -0,0 +1,35 @@
/**
* @copyright Copyright (c) 2023 Ferdinand Thiessen <opensource@fthiessen.de>
*
* @author Ferdinand Thiessen <opensource@fthiessen.de>
*
* @license AGPL-3.0-or-later
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/

import type { Node } from '@nextcloud/files'
import type { AsyncComponent, Component } from 'vue'

export interface IDialogButton {
label: string,
icon?: Component | AsyncComponent,
callback: () => void,
type?: 'primary' | 'secondary' | 'error' | 'warning' | 'success'
}

export interface IFilePickerButton extends Omit<IDialogButton, 'callback'> {
callback: (nodes: Node[]) => void
}
5 changes: 2 additions & 3 deletions lib/index.ts
@@ -1,8 +1,7 @@
import { defineAsyncComponent } from 'vue'

export { FilePicker, FilePickerType, FilePickerBuilder, getFilePickerBuilder } from './filepicker.js'
export { TOAST_UNDO_TIMEOUT, TOAST_DEFAULT_TIMEOUT, TOAST_PERMANENT_TIMEOUT } from './toast.js'
export { TOAST_ARIA_LIVE_OFF, TOAST_ARIA_LIVE_POLITE, TOAST_ARIA_LIVE_ASSERTIVE } from './toast.js'
export { showMessage, showSuccess, showWarning, showInfo, showError, showUndo } from './toast.js'

export const FilePickerVue = defineAsyncComponent(() => import('./components/FilePicker/FilePicker.vue'))
export { spawnDialog } from './utils/dialogs.js'
export { FilePickerVue } from './components/FilePicker/index.js'
11 changes: 0 additions & 11 deletions lib/l10n.ts

This file was deleted.

2 changes: 1 addition & 1 deletion lib/legacy.ts
Expand Up @@ -29,7 +29,7 @@ import type { IFilePickerButton } from './components/FilePicker/FilePicker.vue'
import type { Node } from '@nextcloud/files'
import type { AsyncComponent, Component } from 'vue'

import { t } from './l10n'
import { t } from './utils/l10n'
import { FilePickerVue, FilePickerType } from '.'
import DialogBase from './components/DialogBase.vue'
import Vue from 'vue'
Expand Down
3 changes: 2 additions & 1 deletion lib/toast.ts
Expand Up @@ -23,11 +23,12 @@
///<reference types="toastify-js" />

import Toastify from 'toastify-js'
import { t } from './l10n.js'
import { t } from './utils/l10n.js'

import '../styles/toast.scss'

class ToastType {

static readonly ERROR = 'toast-error';
static readonly WARNING = 'toast-warning';
static readonly INFO = 'toast-info';
Expand Down
53 changes: 53 additions & 0 deletions lib/utils/dialogs.ts
@@ -0,0 +1,53 @@
/**
* @copyright Copyright (c) 2023 Ferdinand Thiessen <opensource@fthiessen.de>
*
* @author Ferdinand Thiessen <opensource@fthiessen.de>
*
* @license AGPL-3.0-or-later
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
import type { AsyncComponent, Component } from 'vue'

import Vue from 'vue'

/**
* Helper to spawn a Vue dialog without having to mount it from a component
*
* @param dialog The dialog component to spawn
* @param props Properties to pass to the dialog
* @param onClose Callback when the dialog is closed
*/
export const spawnDialog = (dialog: Component | AsyncComponent, props: any, onClose: () => void = () => {}) => {
const el = document.createElement('div')

const container: HTMLElement = document.querySelector(props?.container) || document.body
container.appendChild(el)

const vue = new Vue({
el,
name: 'VueDialogHelper',
render: (h) =>
h(dialog, {
props,
on: {
close: () => {
onClose()
vue.$destroy()
},
},
}),
})
}
34 changes: 34 additions & 0 deletions lib/utils/l10n.ts
@@ -0,0 +1,34 @@
/**
* @copyright Copyright (c) 2023 Ferdinand Thiessen <opensource@fthiessen.de>
*
* @author Ferdinand Thiessen <opensource@fthiessen.de>
* @author John Molakvoæ <skjnldsv@protonmail.com>
*
* @license AGPL-3.0-or-later
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/

import { getGettextBuilder } from '@nextcloud/l10n/gettext'

const gtBuilder = getGettextBuilder()
.detectLocale()

__TRANSLATIONS__.map(data => gtBuilder.addTranslation(data.locale, data.json))

const gt = gtBuilder.build()

export const n = gt.ngettext.bind(gt) as typeof gt.ngettext
export const t = gt.gettext.bind(gt) as typeof gt.gettext