diff --git a/css/apps/files.scss b/css/apps/files.scss index 631ef4b..8cecee0 100644 --- a/css/apps/files.scss +++ b/css/apps/files.scss @@ -421,8 +421,17 @@ table.files-filestable { .files-list__header { margin-block: 15px; margin-inline: 3rem 1.5rem; + display: flex; + align-items: center; + + // NC33 renders "New" as a direct header child; push it to the right. + > div:has(> .files-list__header-upload-button) { + order: 2; + margin-left: auto; + } .files-list__header-grid-button { + order: 3; border: 1px solid var(--color-main-text); border-radius: 50%; width: 40px !important; @@ -576,9 +585,107 @@ table.files-filestable { padding-inline-end: 1rem; } + // Chip styling for the NC33 filters; nmcfiles.ts relocates them here. + [data-test-id="files-list-filters"] { + display: flex; + align-items: center; + gap: 0.5rem; + + // Hide the People filter (absent in the legacy layout). + > div:nth-child(3) { + display: none; + } + + button.button-vue { + background-color: var(--nmc-ods-blue-primary); + color: var(--nmc-color-text-and-icon-black); + border: none; + border-radius: var(--border-radius-small); + height: 28px; + min-height: 28px; + min-width: unset; + padding: 0 10px; + font-weight: normal; + + &:hover { + background-color: var(--nmc-ods-blue-hover); + } + + &:active, + &[aria-expanded="true"] { + background-color: var(--nmc-ods-blue-active); + } + + // Hide the leading icon; replace with a trailing caret like the chips. + .button-vue__icon { + display: none; + } + + .button-vue__text { + color: var(--nmc-color-text-and-icon-black); + } + + .button-vue__wrapper::after { + content: ''; + display: inline-block; + width: 6px; + height: 6px; + border-left: 1.5px solid var(--nmc-color-text-and-icon-black); + border-bottom: 1.5px solid var(--nmc-color-text-and-icon-black); + transform: rotate(-45deg); + margin-left: 8px; + margin-bottom: 2px; + transition: transform 0.2s ease; + } + + &[aria-expanded="true"] .button-vue__wrapper::after { + transform: rotate(135deg); + margin-bottom: -2px; + } + } + } + .files-list__filters { padding-block: 1rem; padding-inline: 4rem 1rem; + display: flex; + align-items: center; + justify-content: flex-start; + gap: 0.5rem; + + // NC33 renders the toggles after the chips; show them first (left) and + // cap their container so it can't stretch and push the chips off-screen. + > [data-test-id="files-list-filters"] { + order: -1; + flex: 0 0 auto; + width: max-content; + max-width: max-content; + } + + > ul[aria-label="Active filters"] { + flex: 0 0 auto; + display: flex; + align-items: center; + gap: 0.5rem; + list-style: none; + margin: 0; + padding: 0; + } + + // Divider anchored as the toggles' last flex item so it sits a fixed gap + // after "Modified"; only shown when filters are active. + &:has(> ul[aria-label="Active filters"] li) { + gap: 0.25rem; + + > [data-test-id="files-list-filters"]::after { + content: ""; + flex: 0 0 auto; + width: 1px; + height: 1.5rem; + margin-inline-start: -0.25rem; + background-color: var(--color-border); + } + } .file-list-filters { display: flex; diff --git a/css/components/ncactions.scss b/css/components/ncactions.scss index f7bc1eb..4ca7ae0 100644 --- a/css/components/ncactions.scss +++ b/css/components/ncactions.scss @@ -59,6 +59,81 @@ padding: 1rem; } + // NC33 file-type filter uses NcButton items (no ul/li); reshape the + // popover to match the legacy action menu below. + files-file-list-filter-type .icon-vue svg path { + fill: var(--color-main-text); + } + + &:has(files-file-list-filter-type) { + width: fit-content; + min-width: 213px; + max-height: min(312px, 60vh); + overflow-y: auto; + + > div, + > div > div, + files-file-list-filter-type, + files-file-list-filter-type > div, + .button-vue { + min-width: 0; + } + + > div, + > div > div { + padding: 0; + } + + files-file-list-filter-type > div { + display: flex; + flex-direction: column; + gap: 0; + padding: 0; + } + + .button-vue { + margin: 0; + border-radius: var(--border-radius); + padding-inline: 4px 16px; + + // Grey on hover only, not the first item's focus-on-open. + &:hover, + &:focus-visible { + background-color: var(--color-background-hover); + } + + .button-vue__text { + font-weight: normal; + } + + // Selected: strip NcButton's magenta pressed fill, keep a dark + // label and add a checkmark like the legacy menu. + &[aria-pressed="true"] { + color: var(--color-main-text); + + &:not(:hover):not(:focus-visible) { + background-color: transparent; + } + + .button-vue__text { + color: var(--color-main-text); + } + + .button-vue__wrapper::after { + content: ""; + display: inline-block; + flex: 0 0 auto; + width: 16px; + height: 16px; + margin-inline-start: auto; + background-color: currentColor; + -webkit-mask: var(--icon-check-dark) no-repeat center / contain; + mask: var(--icon-check-dark) no-repeat center / contain; + } + } + } + } + ul { display: flex; flex-direction: column; diff --git a/css/components/ncappnavigation.scss b/css/components/ncappnavigation.scss index 54400a7..0ede619 100644 --- a/css/components/ncappnavigation.scss +++ b/css/components/ncappnavigation.scss @@ -115,6 +115,11 @@ // default navbar link styling #app-navigation-vue .app-navigation-entry-wrapper { + // Cancel the framework's margin-top:auto so "Deleted files" isn't pinned to the bottom. + &.app-navigation-entry--pinned { + margin-top: 0; + } + .app-navigation-entry { position: relative; border-radius: var(--border-radius-large); diff --git a/css/components/ncusermenu.scss b/css/components/ncusermenu.scss index 86ff68f..376c697 100644 --- a/css/components/ncusermenu.scss +++ b/css/components/ncusermenu.scss @@ -24,7 +24,11 @@ order: 1; } - li#profile { + li:has(a#logout) { + order: 3; + } + + li:has(a#profile) { display: none; } @@ -150,6 +154,18 @@ background-image: var(--icon-logout-dark); } + > a#admin_settings::after { + background-image: var(--icon-admin-dark); + } + + > a#core_apps::after { + background-image: var(--icon-apps-dark); + } + + > a#core_users::after { + background-image: var(--icon-users-dark); + } + > a#nmc_welcome_popup-about { .loading-icon { diff --git a/lib/JSResourceLocatorExtension.php b/lib/JSResourceLocatorExtension.php index 70ec292..74d9133 100644 --- a/lib/JSResourceLocatorExtension.php +++ b/lib/JSResourceLocatorExtension.php @@ -17,6 +17,7 @@ use OC\Template\JSResourceLocator; use OCP\IConfig; use OCP\App\IAppManager; +use OCP\IConfig; use Psr\Log\LoggerInterface; class JSResourceLocatorExtension extends JSResourceLocator { @@ -29,14 +30,17 @@ class JSResourceLocatorExtension extends JSResourceLocator { * so we try to handle different backports in this constructor. * */ - public function __construct( - LoggerInterface $logger, - IConfig $config, - protected JSCombiner $jsCombiner, - protected IAppManager $appManager, - ) { + public function __construct(LoggerInterface $logger, IConfig $config, JSCombiner $jsCombiner, IAppManager $appManager) { $this->ownAppManager = $appManager; + // V33 + try { + parent::__construct($logger, $config, $jsCombiner, $appManager); + return; + } catch (\Throwable $eWrongConstructNC33) { + // ignore the exception, try another constructor + } + // later try { parent::__construct($logger, $config, $jsCombiner, $appManager); diff --git a/src/js/filessettings.js b/src/js/filessettings.js index fcc5d38..85395b9 100644 --- a/src/js/filessettings.js +++ b/src/js/filessettings.js @@ -11,30 +11,51 @@ const View = new StorageQuotaView({ pinia, }) -window.addEventListener('DOMContentLoaded', () => { - // Select the