Skip to content

Commit

Permalink
Merge pull request #40192 from nextcloud/feat/sharing-icon-bread
Browse files Browse the repository at this point in the history
  • Loading branch information
skjnldsv authored Sep 4, 2023
2 parents e547247 + 2592568 commit fe692f2
Show file tree
Hide file tree
Showing 24 changed files with 147 additions and 49 deletions.
6 changes: 3 additions & 3 deletions apps/files/src/actions/sidebarAction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
import { Permission, type Node, View, registerFileAction, FileAction } from '@nextcloud/files'
import { Permission, type Node, View, registerFileAction, FileAction, FileType } from '@nextcloud/files'
import { translate as t } from '@nextcloud/l10n'
import InformationSvg from '@mdi/svg/svg/information-variant.svg?raw'

Expand Down Expand Up @@ -51,7 +51,7 @@ export const action = new FileAction({
return (nodes[0].root?.startsWith('/files/') && nodes[0].permissions !== Permission.NONE) ?? false
},

async exec(node: Node, view: View) {
async exec(node: Node, view: View, dir: string) {
try {
// TODO: migrate Sidebar to use a Node instead
await window.OCA.Files.Sidebar.open(node.path)
Expand All @@ -60,7 +60,7 @@ export const action = new FileAction({
window.OCP.Files.Router.goToRoute(
null,
{ view: view.id, fileid: node.fileid },
{ dir: node.dirname },
{ dir },
true,
)

Expand Down
22 changes: 12 additions & 10 deletions apps/files/src/components/FileEntry.vue
Original file line number Diff line number Diff line change
Expand Up @@ -166,12 +166,15 @@
</template>
<script lang='ts'>
import type { PropType } from 'vue'
import type { Node } from '@nextcloud/files'
import { CancelablePromise } from 'cancelable-promise'
import { debounce } from 'debounce'
import { emit } from '@nextcloud/event-bus'
import { extname } from 'path'
import { generateUrl } from '@nextcloud/router'
import { getFileActions, DefaultType, FileType, formatFileSize, Permission, NodeStatus } from '@nextcloud/files'
import { getFileActions, DefaultType, FileType, formatFileSize, Permission, Folder, File } from '@nextcloud/files'
import { showError, showSuccess } from '@nextcloud/dialogs'
import { translate } from '@nextcloud/l10n'
import { vOnClickOutside } from '@vueuse/components'
Expand All @@ -186,7 +189,7 @@ import NcLoadingIcon from '@nextcloud/vue/dist/Components/NcLoadingIcon.js'
import NcTextField from '@nextcloud/vue/dist/Components/NcTextField.js'
import Vue from 'vue'
import { ACTION_DETAILS } from '../actions/sidebarAction.ts'
import { action as sidebarAction } from '../actions/sidebarAction.ts'
import { hashCode } from '../utils/hashUtils.ts'
import { isCachedPreview } from '../services/PreviewService.ts'
import { useActionsMenuStore } from '../store/actionsmenu.ts'
Expand Down Expand Up @@ -235,15 +238,15 @@ export default Vue.extend({
default: false,
},
source: {
type: Object,
type: [Folder, File, Node] as PropType<Node>,
required: true,
},
index: {
type: Number,
required: true,
},
nodes: {
type: Array,
type: Array as PropType<Node[]>,
required: true,
},
filesListWidth: {
Expand Down Expand Up @@ -295,7 +298,7 @@ export default Vue.extend({
currentDir() {
// Remove any trailing slash but leave root slash
return (this.$route?.query?.dir || '/').replace(/^(.+)\/$/, '$1')
return (this.$route?.query?.dir?.toString() || '/').replace(/^(.+)\/$/, '$1')
},
currentFileId() {
return this.$route.params.fileid || this.$route.query.fileid || null
Expand Down Expand Up @@ -660,11 +663,10 @@ export default Vue.extend({
},
openDetailsIfAvailable(event) {
const detailsAction = this.enabledActions.find(action => action.id === ACTION_DETAILS)
if (detailsAction) {
event.preventDefault()
event.stopPropagation()
detailsAction.exec(this.source, this.currentView)
event.preventDefault()
event.stopPropagation()
if (sidebarAction?.enabled?.([this.source], this.currentView)) {
sidebarAction.exec(this.source, this.currentView, this.currentDir)
}
},
Expand Down
15 changes: 9 additions & 6 deletions apps/files/src/components/FilesListVirtual.vue
Original file line number Diff line number Diff line change
Expand Up @@ -67,11 +67,13 @@
</template>

<script lang="ts">
import type { PropType } from 'vue'
import type { Node } from '@nextcloud/files'
import { translate, translatePlural } from '@nextcloud/l10n'
import { getFileListHeaders, type Node } from '@nextcloud/files'
import { getFileListHeaders, Folder, View } from '@nextcloud/files'
import { showError } from '@nextcloud/dialogs'
import Vue from 'vue'
import VirtualList from './VirtualList.vue'
import { action as sidebarAction } from '../actions/sidebarAction.ts'
import FileEntry from './FileEntry.vue'
Expand All @@ -80,6 +82,7 @@ import FilesListTableFooter from './FilesListTableFooter.vue'
import FilesListTableHeader from './FilesListTableHeader.vue'
import filesListWidthMixin from '../mixins/filesListWidth.ts'
import logger from '../logger.js'
import VirtualList from './VirtualList.vue'
export default Vue.extend({
name: 'FilesListVirtual',
Expand All @@ -97,15 +100,15 @@ export default Vue.extend({
props: {
currentView: {
type: Object,
type: View,
required: true,
},
currentFolder: {
type: Object,
type: Folder,
required: true,
},
nodes: {
type: Array,
type: Array as PropType<Node[]>,
required: true,
},
},
Expand Down Expand Up @@ -179,7 +182,7 @@ export default Vue.extend({
const node = this.nodes.find(n => n.fileid === this.fileId) as Node
if (node && sidebarAction?.enabled?.([node], this.currentView)) {
logger.debug('Opening sidebar on file ' + node.path, { node })
sidebarAction.exec(node, this.currentView, this.currentFolder)
sidebarAction.exec(node, this.currentView, this.currentFolder.path)
}
}
},
Expand Down
2 changes: 1 addition & 1 deletion apps/files/src/newMenu/newFolder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ const entry = {
iconSvgInline: FolderPlusSvg,
async handler(context: Folder, content: Node[]) {
const contentNames = content.map((node: Node) => node.basename)
const name = getUniqueName(t('files', 'New Folder'), contentNames)
const name = getUniqueName(t('files', 'New folder'), contentNames)
const { fileid, source } = await createNewFolder(context.source, name)

// Create the folder in the store
Expand Down
84 changes: 80 additions & 4 deletions apps/files/src/views/FilesList.vue
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,20 @@
<!-- Current folder breadcrumbs -->
<BreadCrumbs :path="dir" @reload="fetchContent">
<template #actions>
<NcButton v-if="canShare"
:aria-label="shareButtonLabel"
:class="{ 'files-list__header-share-button--shared': shareButtonType }"
:title="shareButtonLabel"
class="files-list__header-share-button"
type="tertiary"
@click="openSharingSidebar">
<template #icon>
<LinkIcon v-if="shareButtonType === Type.SHARE_TYPE_LINK" />
<ShareVariantIcon v-else :size="20" />
</template>
</NcButton>
<!-- Uploader -->
<UploadPicker v-if="currentFolder"
<UploadPicker v-if="currentFolder && canUpload"
:content="dirContents"
:destination="currentFolder"
:multiple="true"
Expand Down Expand Up @@ -77,18 +89,24 @@ import type { Upload } from '@nextcloud/upload'
import type { UserConfig } from '../types.ts'
import type { View, ContentsWithRoot } from '@nextcloud/files'
import { Folder, Node } from '@nextcloud/files'
import { Folder, Node, Permission } from '@nextcloud/files'
import { getCapabilities } from '@nextcloud/capabilities'
import { join, dirname } from 'path'
import { orderBy } from 'natural-orderby'
import { translate } from '@nextcloud/l10n'
import { UploadPicker } from '@nextcloud/upload'
import { Type } from '@nextcloud/sharing'
import Vue from 'vue'
import NcAppContent from '@nextcloud/vue/dist/Components/NcAppContent.js'
import NcButton from '@nextcloud/vue/dist/Components/NcButton.js'
import NcEmptyContent from '@nextcloud/vue/dist/Components/NcEmptyContent.js'
import NcIconSvgWrapper from '@nextcloud/vue/dist/Components/NcIconSvgWrapper.js'
import NcLoadingIcon from '@nextcloud/vue/dist/Components/NcLoadingIcon.js'
import Vue from 'vue'
import LinkIcon from 'vue-material-design-icons/Link.vue'
import ShareVariantIcon from 'vue-material-design-icons/ShareVariant.vue'
import { action as sidebarAction } from '../actions/sidebarAction.ts'
import { useFilesStore } from '../store/files.ts'
import { usePathsStore } from '../store/paths.ts'
import { useSelectionStore } from '../store/selection.ts'
Expand All @@ -100,17 +118,21 @@ import FilesListVirtual from '../components/FilesListVirtual.vue'
import filesSortingMixin from '../mixins/filesSorting.ts'
import logger from '../logger.js'
const isSharingEnabled = getCapabilities()?.files_sharing !== undefined
export default Vue.extend({
name: 'FilesList',
components: {
BreadCrumbs,
FilesListVirtual,
LinkIcon,
NcAppContent,
NcButton,
NcEmptyContent,
NcIconSvgWrapper,
NcLoadingIcon,
ShareVariantIcon,
UploadPicker,
},
Expand Down Expand Up @@ -139,6 +161,7 @@ export default Vue.extend({
return {
loading: true,
promise: null,
Type,
}
},
Expand All @@ -157,7 +180,7 @@ export default Vue.extend({
*/
dir(): string {
// Remove any trailing slash but leave root slash
return (this.$route?.query?.dir || '/').replace(/^(.+)\/$/, '$1')
return (this.$route?.query?.dir?.toString() || '/').replace(/^(.+)\/$/, '$1')
},
/**
Expand Down Expand Up @@ -242,6 +265,43 @@ export default Vue.extend({
const dir = this.dir.split('/').slice(0, -1).join('/') || '/'
return { ...this.$route, query: { dir } }
},
shareAttributes(): number[]|undefined {
if (!this.currentFolder?.attributes?.['share-types']) {
return undefined
}
return Object.values(this.currentFolder?.attributes?.['share-types'] || {}).flat() as number[]
},
shareButtonLabel() {
if (!this.shareAttributes) {
return this.t('files', 'Share')
}
if (this.shareButtonType === Type.SHARE_TYPE_LINK) {
return this.t('files', 'Shared by link')
}
return this.t('files', 'Shared')
},
shareButtonType(): Type|null {
if (!this.shareAttributes) {
return null
}
// If all types are links, show the link icon
if (this.shareAttributes.some(type => type === Type.SHARE_TYPE_LINK)) {
return Type.SHARE_TYPE_LINK
}
return Type.SHARE_TYPE_USER
},
canUpload() {
return this.currentFolder && (this.currentFolder.permissions & Permission.CREATE) !== 0
},
canShare() {
return isSharingEnabled
&& this.currentFolder && (this.currentFolder.permissions & Permission.SHARE) !== 0
},
},
watch: {
Expand Down Expand Up @@ -348,6 +408,13 @@ export default Vue.extend({
}
},
openSharingSidebar() {
if (window?.OCA?.Files?.Sidebar?.setActiveTab) {
window.OCA.Files.Sidebar.setActiveTab('sharing')
}
sidebarAction.exec(this.currentFolder, this.currentView, this.currentFolder.path)
},
t: translate,
},
})
Expand Down Expand Up @@ -378,12 +445,21 @@ $navigationToggleSize: 50px;
// Only the breadcrumbs shrinks
flex: 0 0;
}
&-share-button {
opacity: .3;
&--shared {
opacity: 1;
}
}
}
&__refresh-icon {
flex: 0 0 44px;
width: 44px;
height: 44px;
}
&__loading-icon {
margin: auto;
}
Expand Down
13 changes: 11 additions & 2 deletions apps/sharebymail/lib/Capabilities.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
namespace OCA\ShareByMail;

use OCA\ShareByMail\Settings\SettingsManager;
use OCP\App\IAppManager;
use OCP\Capabilities\ICapability;
use OCP\Share\IManager;

Expand All @@ -39,10 +40,15 @@ class Capabilities implements ICapability {
/** @var SettingsManager */
private $settingsManager;

/** @var IAppManager */
private $appManager;

public function __construct(IManager $manager,
SettingsManager $settingsManager) {
SettingsManager $settingsManager,
IAppManager $appManager) {
$this->manager = $manager;
$this->settingsManager = $settingsManager;
$this->appManager = $appManager;
}

/**
Expand All @@ -64,9 +70,12 @@ public function __construct(IManager $manager,
* },
* }
* }
* }
* }|array<empty>
*/
public function getCapabilities(): array {
if (!$this->appManager->isEnabledForUser('files_sharing')) {
return [];
}
return [
'files_sharing' =>
[
Expand Down
9 changes: 8 additions & 1 deletion apps/sharebymail/tests/CapabilitiesTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@

use OCA\ShareByMail\Capabilities;
use OCA\ShareByMail\Settings\SettingsManager;
use OCP\App\IAppManager;
use OCP\Share\IManager;
use Test\TestCase;

Expand All @@ -40,13 +41,17 @@ class CapabilitiesTest extends TestCase {
/** @var IManager | \PHPUnit\Framework\MockObject\MockObject */
private $settingsManager;

/** @var IAppManager | \PHPUnit\Framework\MockObject\MockObject */
private $appManager;

protected function setUp(): void {
parent::setUp();


$this->manager = $this::createMock(IManager::class);
$this->settingsManager = $this::createMock(SettingsManager::class);
$this->capabilities = new Capabilities($this->manager, $this->settingsManager);
$this->appManager = $this::createMock(IAppManager::class);
$this->capabilities = new Capabilities($this->manager, $this->settingsManager, $this->appManager);
}

public function testGetCapabilities() {
Expand All @@ -58,6 +63,8 @@ public function testGetCapabilities() {
->willReturn(false);
$this->settingsManager->method('sendPasswordByMail')
->willReturn(true);
$this->appManager->method('isEnabledForUser')
->willReturn(true);

$capabilities = [
'files_sharing' =>
Expand Down
Loading

0 comments on commit fe692f2

Please sign in to comment.