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

Shortcut url followup #9908

Merged
merged 25 commits into from
Nov 8, 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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions changelog/unreleased/enhancement-create-shortcuts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
Enhancement: Create shortcuts

We've added a new functionality to add to shortcuts to web, those can be created via the "+ New" context menu.
Users can enter URLs or pick a file via the drop down menu and create a '.url' file.

'.url' files can be opened via web or downloaded and opened on the desktop.

https://github.com/owncloud/web/pull/9890
https://github.com/owncloud/web/pull/9908
https://github.com/owncloud/web/issues/9796
https://github.com/owncloud/web/issues/9887
https://github.com/owncloud/web/issues/9850
3 changes: 2 additions & 1 deletion packages/web-app-files/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
"vuex": "4.1.0",
"web-app-files": "workspace:*",
"web-app-search": "workspace:*",
"web-runtime": "workspace:*"
"web-runtime": "workspace:*",
"dompurify": "^3.0.6"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -170,9 +170,12 @@

<script lang="ts">
import { mapActions, mapGetters } from 'vuex'

import { useFileActions, useFileActionsCreateNewShortcut } from '@ownclouders/web-pkg'
import { isLocationPublicActive, isLocationSpacesActive } from '@ownclouders/web-pkg'
import {
isLocationPublicActive,
isLocationSpacesActive,
useFileActions,
useFileActionsCreateNewShortcut
} from '@ownclouders/web-pkg'
import { useActiveLocation } from '@ownclouders/web-pkg'
import {
useFileActionsCreateNewFile,
Expand Down
8 changes: 3 additions & 5 deletions packages/web-app-files/src/extensions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,23 @@ import {
Extension,
useStore,
useRouter,
useClientService,
useConfigurationManager
useSearch
} from '@ownclouders/web-pkg'
import { computed } from 'vue'
import { SDKSearch } from './search'

export const extensions = ({ applicationConfig }: ApplicationSetupOptions) => {
const store = useStore()
const router = useRouter()
const clientService = useClientService()
const configurationManager = useConfigurationManager()
const { search: searchFunction } = useSearch()

return computed(
() =>
[
{
id: 'com.github.owncloud.web.files.search',
type: 'search',
searchProvider: new SDKSearch(store, router, clientService, configurationManager)
searchProvider: new SDKSearch(store, router, searchFunction)
}
] satisfies Extension[]
)
Expand Down
20 changes: 5 additions & 15 deletions packages/web-app-files/src/search/sdk/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,34 +2,24 @@ import Preview from './preview'
import List from './list'
import { Store } from 'vuex'
import { Router } from 'vue-router'
import {
ClientService,
ConfigurationManager,
SearchList,
SearchPreview,
SearchProvider
} from '@ownclouders/web-pkg'
import { SearchFunction, SearchList, SearchPreview, SearchProvider } from '@ownclouders/web-pkg'

function $gettext(msg) {
return msg
}

export default class Provider implements SearchProvider {
public readonly id: string
public readonly displayName: string
public readonly previewSearch: SearchPreview
public readonly listSearch: SearchList
private readonly store: Store<any>

constructor(
store: Store<any>,
router: Router,
clientService: ClientService,
configurationManager: ConfigurationManager
) {
constructor(store: Store<any>, router: Router, searchFunction: SearchFunction) {
this.id = 'files.sdk'
this.displayName = $gettext('Files')
this.previewSearch = new Preview(store, router, clientService, configurationManager)
this.listSearch = new List(store, clientService, configurationManager)
this.previewSearch = new Preview(router, searchFunction)
this.listSearch = new List(searchFunction)
this.store = store
}

Expand Down
69 changes: 7 additions & 62 deletions packages/web-app-files/src/search/sdk/list.ts
Original file line number Diff line number Diff line change
@@ -1,74 +1,19 @@
import ListComponent from '../../components/Search/List.vue'
import { ClientService, SearchList, SearchResult } from '@ownclouders/web-pkg'
import { ProjectSpaceResource, isProjectSpaceResource } from '@ownclouders/web-client/src/helpers'
import { Component, computed, Ref, unref } from 'vue'
import { DavProperties } from '@ownclouders/web-client/src/webdav/constants'
import { Store } from 'vuex'
import { ConfigurationManager } from '@ownclouders/web-pkg'
import { urlJoin } from '@ownclouders/web-client/src/utils'
import { SearchFunction, SearchList, SearchResult } from '@ownclouders/web-pkg'
import { Component } from 'vue'

export const searchLimit = 200

export default class List implements SearchList {
public readonly component: Component
private readonly store: Store<any>
private readonly clientService: ClientService
private readonly configurationManager: ConfigurationManager
private readonly projectSpaces: Ref<ProjectSpaceResource[]>
private readonly searchFunction: SearchFunction

constructor(
store: Store<any>,
clientService: ClientService,
configurationManager: ConfigurationManager
) {
constructor(searchFunction: SearchFunction) {
this.component = ListComponent
this.store = store
this.clientService = clientService
this.configurationManager = configurationManager
this.projectSpaces = computed(() =>
this.store.getters['runtime/spaces/spaces'].filter((s) => isProjectSpaceResource(s))
)
this.searchFunction = searchFunction
}

getProjectSpace(id): ProjectSpaceResource {
return unref(this.projectSpaces).find((s) => s.id === id)
}

async search(term: string): Promise<SearchResult> {
if (this.configurationManager.options.routing.fullShareOwnerPaths) {
await this.store.dispatch('runtime/spaces/loadMountPoints', {
graphClient: this.clientService.graphAuthenticated
})
}

if (!term) {
return {
totalResults: null,
values: []
}
}

const { resources, totalResults } = await this.clientService.webdav.search(term, {
searchLimit,
davProperties: DavProperties.Default
})

return {
totalResults,
values: resources.map((resource) => {
const matchingSpace = this.getProjectSpace(resource.parentFolderId)
const data = matchingSpace ? matchingSpace : resource

// info: in oc10 we have no storageId in resources. All resources are mounted into the personal space.
if (!data.storageId) {
data.storageId = this.store.getters.user.id
}
if (this.configurationManager.options.routing.fullShareOwnerPaths && data.shareRoot) {
data.path = urlJoin(data.shareRoot, data.path)
}

return { id: data.id, data }
})
}
public async search(term: string): Promise<SearchResult> {
return this.searchFunction(term, searchLimit)
}
}
83 changes: 7 additions & 76 deletions packages/web-app-files/src/search/sdk/preview.ts
Original file line number Diff line number Diff line change
@@ -1,92 +1,23 @@
import { ClientService, Cache, SearchPreview, SearchResult } from '@ownclouders/web-pkg'
import { ProjectSpaceResource, isProjectSpaceResource } from '@ownclouders/web-client/src/helpers'
import { Component, computed, Ref, unref } from 'vue'
import { SearchFunction, SearchPreview, SearchResult } from '@ownclouders/web-pkg'
import { Component, unref } from 'vue'
import { Router } from 'vue-router'
import { DavProperties } from '@ownclouders/web-client/src/webdav/constants'
import { Store } from 'vuex'
import { ConfigurationManager, ResourcePreview } from '@ownclouders/web-pkg'
import { urlJoin } from '@ownclouders/web-client/src/utils'
import { ResourcePreview } from '@ownclouders/web-pkg'

export const previewSearchLimit = 8

export default class Preview implements SearchPreview {
public readonly component: Component
private readonly cache: Cache<string, SearchResult>
private readonly router: Router
private readonly store: Store<any>
private readonly clientService: ClientService
private readonly configurationManager: ConfigurationManager
private readonly projectSpaces: Ref<ProjectSpaceResource[]>
private readonly searchFunction: SearchFunction

constructor(
store: Store<any>,
router: Router,
clientService: ClientService,
configurationManager: ConfigurationManager
) {
constructor(router: Router, searchFunction: SearchFunction) {
this.component = ResourcePreview
this.router = router
this.store = store
// define how long the cache should be valid, maybe conf option?
this.cache = new Cache({ ttl: 10000, capacity: 100 })
this.clientService = clientService
this.configurationManager = configurationManager
this.projectSpaces = computed(() =>
this.store.getters['runtime/spaces/spaces'].filter((s) => isProjectSpaceResource(s))
)
}

getProjectSpace(id): ProjectSpaceResource {
return unref(this.projectSpaces).find((s) => s.id === id)
this.searchFunction = searchFunction
}

public async search(term: string): Promise<SearchResult> {
if (!term) {
return {
totalResults: null,
values: []
}
}

if (this.configurationManager.options.routing.fullShareOwnerPaths) {
await this.store.dispatch('runtime/spaces/loadMountPoints', {
graphClient: this.clientService.graphAuthenticated
})
}

if (this.cache.has(term)) {
return this.cache.get(term)
}

const areHiddenFilesShown = this.store.state.Files?.areHiddenFilesShown

const { resources, totalResults } = await this.clientService.webdav.search(term, {
searchLimit: previewSearchLimit,
davProperties: DavProperties.Default
})

return {
totalResults,
values: resources
.map((resource) => {
const matchingSpace = this.getProjectSpace(resource.parentFolderId)
const data = matchingSpace ? matchingSpace : resource

// info: in oc10 we have no storageId in resources. All resources are mounted into the personal space.
if (!data.storageId) {
data.storageId = this.store.getters.user.id
}
if (this.configurationManager.options.routing.fullShareOwnerPaths && data.shareRoot) {
data.path = urlJoin(data.shareRoot, data.path)
}

return { id: data.id, data }
})
.filter(({ data }) => {
// filter results if hidden files shouldn't be shown due to settings
return !data.name.startsWith('.') || areHiddenFilesShown
})
}
return this.searchFunction(term, previewSearchLimit)
}

public get available(): boolean {
Expand Down
Loading