MOBILE-3631 core: Add splitview placeholder page

main
Pau Ferrer Ocaña 2021-01-26 12:21:40 +01:00
parent 18cb43aa5e
commit 001048fc9a
7 changed files with 110 additions and 52 deletions

View File

@ -1,5 +1,7 @@
<ion-content class="menu"> <ion-content class="menu">
<ng-content></ng-content> <ng-content></ng-content>
</ion-content> </ion-content>
<ion-router-outlet class="content"></ion-router-outlet> <ion-router-outlet class="content-outlet"></ion-router-outlet>
<!-- @todo placeholder --> <core-empty-box class="content-placeholder" icon="fas-arrow-circle-left" [message]="placeholderText | translate"
[flipIconRtl]="true">
</core-empty-box>

View File

@ -1,11 +1,13 @@
// @todo RTL layout
:host { :host {
--menu-min-width: 270px; --menu-min-width: 270px;
--menu-max-width: 28%; --menu-max-width: 28%;
--menu-box-shadow: var(--core-menu-box-shadow-end);
--menu-z: 2;
--menu-border-width: 1;
--menu-display: flex; --menu-display: flex;
--content-display: block; --content-display: block;
--border-width: 1; --content-outlet-display: none;
--content-placeholder-display: var(--content-display);
top: 0; top: 0;
right: 0; right: 0;
@ -17,58 +19,74 @@
flex-direction: row; flex-direction: row;
flex-wrap: nowrap; flex-wrap: nowrap;
contain: strict; contain: strict;
}
:host(.menu-only) { .menu,
--menu-min-width: 0; .content-outlet {
--menu-max-width: 100%;
--content-display: none;
--border-width: 0;
}
:host(.content-only) {
--menu-display: none;
--border-width: 0;
}
:host-context(ion-app.md) {
--border: calc(var(--border-width) * 1px) solid var(--ion-item-border-color, var(--ion-border-color, var(--ion-color-step-150, rgba(0, 0, 0, .13))));
}
:host-context(ion-app.ios) {
--border: calc(var(--border-width) * .55px) solid var(--ion-item-border-color, var(--ion-border-color, var(--ion-color-step-250, #c8c7cc)));
}
.menu,
.content {
top: 0; top: 0;
right: 0; right: 0;
bottom: 0; bottom: 0;
left: 0; left: 0;
position: relative; position: relative;
box-shadow: none !important; box-shadow: none;
z-index: 0; z-index: 0;
} }
.menu { .menu {
box-shadow: var(--menu-box-shadow);
z-index: var(--menu-z);
display: var(--menu-display); display: var(--menu-display);
flex-shrink: 0; flex-shrink: 0;
order: -1; order: -1;
border-left: unset; width: 100%;
border-right: unset;
border-inline-start: 0; border-inline-start: 0;
border-inline-end: var(--border); border-inline-end: var(--border);
min-width: var(--menu-min-width); min-width: var(--menu-min-width);
max-width: var(--menu-max-width); max-width: var(--menu-max-width);
width: 100%; }
}
.content { .content-outlet {
display: var(--content-display); display: var(--content-outlet-display);
flex: 1; flex: 1;
::ng-deep ion-header { ::ng-deep ion-header {
display: none; display: none;
} }
}
.content-placeholder {
display: var(--content-placeholder-display);
flex: 1;
position: relative;
background-color: var(--ion-background);
}
}
:host(.menu-only) {
--menu-min-width: 0;
--menu-max-width: 100%;
--content-display: none;
--menu-border-width: 0;
--menu-box-shadow: none;
--menu-z: 0;
--selected-item-border-width: 0;
}
:host(.content-only) {
--menu-display: none;
--menu-border-width: 0;
}
:host(.outlet-activated) {
--content-placeholder-display: none;
--content-outlet-display: var(--content-display);
}
:host-context(ion-app.md) {
--border: calc(var(--menu-border-width) * 1px) solid var(--ion-item-border-color, var(--ion-border-color, var(--ion-color-step-150, rgba(0, 0, 0, .13))));
}
:host-context(ion-app.ios) {
--border: calc(var(--menu-border-width) * .55px) solid var(--ion-item-border-color, var(--ion-border-color, var(--ion-color-step-250, #c8c7cc)));
} }

View File

@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
import { AfterViewInit, Component, ElementRef, HostBinding, OnDestroy, ViewChild } from '@angular/core'; import { AfterViewInit, Component, ElementRef, HostBinding, Input, OnDestroy, ViewChild } from '@angular/core';
import { IonRouterOutlet } from '@ionic/angular'; import { IonRouterOutlet } from '@ionic/angular';
import { CoreScreen } from '@services/screen'; import { CoreScreen } from '@services/screen';
import { Subscription } from 'rxjs'; import { Subscription } from 'rxjs';
@ -32,6 +32,7 @@ export class CoreSplitViewComponent implements AfterViewInit, OnDestroy {
@ViewChild(IonRouterOutlet) outlet!: IonRouterOutlet; @ViewChild(IonRouterOutlet) outlet!: IonRouterOutlet;
@HostBinding('class') classes = ''; @HostBinding('class') classes = '';
@Input() placeholderText = 'core.emptysplit';
isNested = false; isNested = false;
private subscriptions?: Subscription[]; private subscriptions?: Subscription[];
@ -65,6 +66,10 @@ export class CoreSplitViewComponent implements AfterViewInit, OnDestroy {
private updateClasses(): void { private updateClasses(): void {
const classes: string[] = [this.getCurrentMode()]; const classes: string[] = [this.getCurrentMode()];
if (this.outlet.isActivated) {
classes.push('outlet-activated');
}
if (this.isNested) { if (this.isNested) {
classes.push('nested'); classes.push('nested');
} }
@ -92,4 +97,13 @@ export class CoreSplitViewComponent implements AfterViewInit, OnDestroy {
return CoreSplitViewMode.MenuAndContent; return CoreSplitViewMode.MenuAndContent;
} }
/**
* Check if both panels are shown. It depends on screen width.
*
* @return If split view is enabled.
*/
isOn(): boolean {
return this.outlet.isActivated;
}
} }

View File

@ -1,4 +1,6 @@
:host { :host {
--side-blocks-box-shadow: var(--core-menu-box-shadow-start);
&.core-no-blocks .core-course-blocks-content { &.core-no-blocks .core-course-blocks-content {
height: auto; height: auto;
} }
@ -20,7 +22,7 @@
div.core-course-blocks-side { div.core-course-blocks-side {
max-width: var(--side-blocks-max-width); max-width: var(--side-blocks-max-width);
min-width: var(--side-blocks-min-width); min-width: var(--side-blocks-min-width);
box-shadow: -4px 0px 16px rgba(0, 0, 0, 0.18); box-shadow: var(--side-blocks-box-shadow);
z-index: 2; z-index: 2;
// @todo @include core-split-area-end(); // @todo @include core-split-area-end();
} }
@ -53,7 +55,7 @@
:host-context([dir="rtl"]).core-has-blocks { :host-context([dir="rtl"]).core-has-blocks {
@media (min-width: 768px) { @media (min-width: 768px) {
div.core-course-blocks-side { div.core-course-blocks-side {
box-shadow: 4px 0px 16px rgba(0, 0, 0, 0.18); box-shadow: var(--side-blocks-box-shadow);
} }
} }
} }

View File

@ -91,6 +91,21 @@ export class CoreNavigatorService {
return matches?.[1] ?? null; return matches?.[1] ?? null;
} }
/**
* Returns if a section is loaded on the split view (tablet mode).
*
* @param path Path, can be a glob pattern.
* @return Whether the active route is using the given path.
*/
isCurrentPathInTablet(path: string): boolean {
if (CoreScreen.instance.isMobile) {
// Split view is off.
return false;
}
return this.isCurrent(path);
}
/** /**
* Navigate to a new path. * Navigate to a new path.
* *
@ -213,6 +228,8 @@ export class CoreNavigatorService {
* @return Previous path. * @return Previous path.
*/ */
getPreviousPath(): string { getPreviousPath(): string {
// @todo: Remove this method and the used attributes.
// This is a quick workarround to avoid loops. Ie, in messages we can navigate to user profile and there to messages.
return CoreUrlUtils.instance.removeUrlParams(this.previousPath || ''); return CoreUrlUtils.instance.removeUrlParams(this.previousPath || '');
} }

View File

@ -69,6 +69,10 @@ ion-icon {
} }
} }
[dir=rtl] ion-icon.icon-flip-rtl {
transform: scaleX(-1);
}
// Ionic alert. // Ionic alert.
ion-alert.core-alert-network-error .alert-head { ion-alert.core-alert-network-error .alert-head {
position: relative; position: relative;

View File

@ -106,6 +106,7 @@
--color: var(--custom-bottom-tabs-color, var(--white)); --color: var(--custom-bottom-tabs-color, var(--white));
} }
--core-toolbar-button-image-width: var(--custom-toolbar-button-image-width, 32px);
--ion-statusbar-background: var(--custom-toolbar-background, var(--ion-color-primary)); --ion-statusbar-background: var(--custom-toolbar-background, var(--ion-color-primary));
ion-toolbar { ion-toolbar {
--color: var(--custom-toolbar-color, var(--ion-color-primary-contrast)); --color: var(--custom-toolbar-color, var(--ion-color-primary-contrast));
@ -170,8 +171,6 @@
--selected-item-color: var(--custom-selected-item-color, var(--core-color)); --selected-item-color: var(--custom-selected-item-color, var(--core-color));
--selected-item-border-width: var(--custom-selected-item-border-width, 5px); --selected-item-border-width: var(--custom-selected-item-border-width, 5px);
--drop-shadow: var(--custom-drop-shadow, 0, 0, 0, 0.2);
--core-login-background: var(--custom-login-background, var(--white)); --core-login-background: var(--custom-login-background, var(--white));
--core-login-text-color: var(--custom-login-text-color, var(--black)); --core-login-text-color: var(--custom-login-text-color, var(--black));
@ -188,11 +187,8 @@
--core-star-color: var(--custom-star-color, var(--core-color)); --core-star-color: var(--custom-star-color, var(--core-color));
--core-large-avatar-size: var(--custom-large-avatar-size, 90px); --core-large-avatar-size: var(--custom-large-avatar-size, 90px);
--core-avatar-size: var(--custom-avatar-size, 40px); --core-avatar-size: var(--custom-avatar-size, 40px);
--core-toolbar-button-image-width: var(--custom-toolbar-button-image-width, 32px);
--core-send-message-input-background: var(--custom-send-message-input-background, var(--gray)); --core-send-message-input-background: var(--custom-send-message-input-background, var(--gray));
--core-send-message-input-color: var(--custom-send-message-input-color, var(--black)); --core-send-message-input-color: var(--custom-send-message-input-color, var(--black));
@ -214,6 +210,11 @@
--addon-messages-avatar-size: var(--custom-messages-avatar-size, 30px); --addon-messages-avatar-size: var(--custom-messages-avatar-size, 30px);
--addon-messages-discussion-badge: var(--custom-messages-discussion-badge, var(--core-color)); --addon-messages-discussion-badge: var(--custom-messages-discussion-badge, var(--core-color));
--addon-messages-discussion-badge-text: var(--custom-messages-discussion-badge-text, var(--white)); --addon-messages-discussion-badge-text: var(--custom-messages-discussion-badge-text, var(--white));
--drop-shadow: var(--custom-drop-shadow, 0, 0, 0, 0.2);
--core-menu-box-shadow-end: var(--custom-menu-box-shadow-end, -4px 0px 16px rgba(0, 0, 0, 0.18));
--core-menu-box-shadow-start: var(--custom-menu-box-shadow-start, 4px 0px 16px rgba(0, 0, 0, 0.18));
} }
/* /*