MOBILE-2327 settings: Implement settings list

main
Pau Ferrer Ocaña 2018-02-26 17:41:04 +01:00
parent b9c0bb5653
commit 29809e8dbc
14 changed files with 404 additions and 17 deletions

View File

@ -7,6 +7,7 @@
"errorwhileretrievingmessages": "Error while retrieving messages from the server.",
"messagenotsent": "The message was not sent. Please try again later.",
"message": "Message",
"messagepreferences": "Message preferences",
"messages": "Messages",
"newmessage": "New message",
"newmessages": "New messages",

View File

@ -18,19 +18,21 @@ import { AddonMessagesProvider } from './providers/messages';
import { AddonMessagesOfflineProvider } from './providers/messages-offline';
import { AddonMessagesSyncProvider } from './providers/sync';
import { AddonMessagesMainMenuHandler } from './providers/mainmenu-handler';
import { CoreMainMenuDelegate } from '../../core/mainmenu/providers/delegate';
import { CoreContentLinksDelegate } from '../../core/contentlinks/providers/delegate';
import { CoreUserDelegate } from '../../core/user/providers/user-delegate';
import { CoreCronDelegate } from '../../providers/cron';
import { CoreMainMenuDelegate } from '@core/mainmenu/providers/delegate';
import { CoreContentLinksDelegate } from '@core/contentlinks/providers/delegate';
import { CoreUserDelegate } from '@core/user/providers/user-delegate';
import { CoreCronDelegate } from '@providers/cron';
import { AddonMessagesSendMessageUserHandler } from './providers/user-send-message-handler';
import { AddonMessagesDiscussionLinkHandler } from './providers/discussion-link-handler';
import { AddonMessagesIndexLinkHandler } from './providers/index-link-handler';
import { AddonMessagesSyncCronHandler } from './providers/sync-cron-handler';
import { CoreEventsProvider } from '../../providers/events';
import { CoreAppProvider } from '../../providers/app';
import { CoreSitesProvider } from '../../providers/sites';
import { CoreLocalNotificationsProvider } from '../../providers/local-notifications';
import { CoreContentLinksHelperProvider } from '../../core/contentlinks/providers/helper';
import { CoreEventsProvider } from '@providers/events';
import { CoreAppProvider } from '@providers/app';
import { CoreSitesProvider } from '@providers/sites';
import { CoreLocalNotificationsProvider } from '@providers/local-notifications';
import { CoreContentLinksHelperProvider } from '@core/contentlinks/providers/helper';
import { CoreSettingsDelegate } from '@core/settings/providers/delegate';
import { AddonMessagesSettingsHandler } from './providers/settings-handler';
@NgModule({
declarations: [
@ -45,7 +47,8 @@ import { CoreContentLinksHelperProvider } from '../../core/contentlinks/provider
AddonMessagesSendMessageUserHandler,
AddonMessagesDiscussionLinkHandler,
AddonMessagesIndexLinkHandler,
AddonMessagesSyncCronHandler
AddonMessagesSyncCronHandler,
AddonMessagesSettingsHandler
]
})
export class AddonMessagesModule {
@ -55,7 +58,8 @@ export class AddonMessagesModule {
userDelegate: CoreUserDelegate, cronDelegate: CoreCronDelegate, syncHandler: AddonMessagesSyncCronHandler,
network: Network, messagesSync: AddonMessagesSyncProvider, appProvider: CoreAppProvider,
localNotifications: CoreLocalNotificationsProvider, messagesProvider: AddonMessagesProvider,
sitesProvider: CoreSitesProvider, linkHelper: CoreContentLinksHelperProvider) {
sitesProvider: CoreSitesProvider, linkHelper: CoreContentLinksHelperProvider,
settingsHandler: AddonMessagesSettingsHandler, settingsDelegate: CoreSettingsDelegate) {
// Register handlers.
mainMenuDelegate.registerHandler(mainmenuHandler);
contentLinksDelegate.registerHandler(indexLinkHandler);
@ -63,6 +67,7 @@ export class AddonMessagesModule {
userDelegate.registerHandler(sendMessageHandler);
cronDelegate.register(syncHandler);
cronDelegate.register(mainmenuHandler);
settingsDelegate.registerHandler(settingsHandler);
// Sync some discussions when device goes online.
network.onConnect().subscribe(() => {

View File

@ -535,6 +535,16 @@ export class AddonMessagesProvider {
return this.sitesProvider.wsAvailableInCurrentSite('core_message_get_unread_conversations_count');
}
/**
* Returns whether or not the message preferences are enabled for the current site.
*
* @return {boolean} True if enabled, false otherwise.
* @since 3.2
*/
isMessagePreferencesEnabled(): boolean {
return this.sitesProvider.wsAvailableInCurrentSite('core_message_get_user_message_preferences');
}
/**
* Returns whether or not messaging is enabled for a certain site.
*

View File

@ -0,0 +1,54 @@
// (C) Copyright 2015 Martin Dougiamas
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import { Injectable, Inject } from '@angular/core';
import { AddonMessagesProvider } from './messages';
import { CoreSettingsHandler, CoreSettingsHandlerData } from '@core/settings/providers/delegate';
import { CoreSitesProvider } from '@providers/sites';
/**
* Message settings handler.
*/
@Injectable()
export class AddonMessagesSettingsHandler implements CoreSettingsHandler {
name = 'AddonMessages';
priority = 600;
constructor(private messagesProvider: AddonMessagesProvider, private sitesProvider: CoreSitesProvider) {
}
/**
* Check if the handler is enabled on a site level.
*
* @return {boolean} Whether or not the handler is enabled on a site level.
*/
isEnabled(): boolean | Promise<boolean> {
return this.messagesProvider.isMessagePreferencesEnabled();
}
/**
* Returns the data needed to render the handler.
*
* @return {CoreSettingsHandlerData} Data needed to render the handler.
*/
getDisplayData(): CoreSettingsHandlerData {
return {
icon: 'chatbubbles',
title: 'addon.messages.messagepreferences',
page: 'AddonMessagesSettingsPage',
class: 'addon-messages-settings-handler'
};
}
}

View File

@ -63,6 +63,7 @@ import { CoreSiteHomeModule } from '@core/sitehome/sitehome.module';
import { CoreContentLinksModule } from '@core/contentlinks/contentlinks.module';
import { CoreUserModule } from '@core/user/user.module';
import { CoreGradesModule } from '@core/grades/grades.module';
import { CoreSettingsModule } from '@core/settings/settings.module';
// Addon modules.
import { AddonCalendarModule } from '@addon/calendar/calendar.module';
@ -109,6 +110,7 @@ export function createTranslateLoader(http: HttpClient): TranslateHttpLoader {
CoreContentLinksModule,
CoreUserModule,
CoreGradesModule,
CoreSettingsModule,
AddonCalendarModule,
AddonUserProfileFieldModule,
AddonFilesModule,

View File

@ -50,7 +50,7 @@
}
}
@include media-breakpoint-down(md) {
@include media-breakpoint-down(sm) {
.hidden-phone {
display: none !important;
opacity: 0 !important;

View File

@ -0,0 +1,10 @@
{
"about": "About",
"general": "General",
"loggedin": "Online",
"loggedoff": "Offline",
"settings": "Settings",
"sites": "Sites",
"spaceusage": "Space usage",
"synchronization": "Synchronisation"
}

View File

@ -0,0 +1,37 @@
<ion-header>
<ion-navbar>
<ion-title>{{ 'core.settings.settings' | translate}}</ion-title>
</ion-navbar>
</ion-header>
<core-split-view>
<ion-content>
<ion-list>
<a ion-item (click)="openHandler('CoreSettingsGeneralPage')" [title]="'core.settings.general' | translate" [class.core-split-item-selected]="'CoreSettingsGeneralPage' == selectedPage">
<ion-icon name="construct" item-start></ion-icon>
<p>{{ 'core.settings.general' | translate }}</p>
</a>
<a ion-item (click)="openHandler('CoreSettingsSpaceUsagePage')" [title]="'core.settings.spaceusage' | translate" [class.core-split-item-selected]="'CoreSettingsSpaceUsagePage' == selectedPage">
<ion-icon name="stats" item-start></ion-icon>
<p>{{ 'core.settings.spaceusage' | translate }}</p>
</a>
<a ion-item (click)="openHandler('CoreSettingSynchronizationPage')" [title]="'core.settings.synchronization' | translate" [class.core-split-item-selected]="'CoreSettingSynchronizationPage' == selectedPage">
<ion-icon name="sync" item-start></ion-icon>
<p>{{ 'core.settings.synchronization' | translate }}</p>
</a>
<a ion-item *ngIf="isIOS" (click)="openHandler('CoreSharedFilesListPage', {manage: true})" [title]="'core.sharedfiles.sharedfiles' | translate" [class.core-split-item-selected]="'CoreSharedFilesListPage' == selectedPage">
<ion-icon name="folder" item-start></ion-icon>
<p>{{ 'core.sharedfiles.sharedfiles' | translate }}</p>
</a>
<ion-item *ngFor="let handler of handlers" [ngClass]="['core-settings-handler', handler.class]" (click)="openHandler(handler.page, handler.params)" [title]="handler.title | translate" detail-push [class.core-split-item-selected]="handler.page == selectedPage">
<ion-icon [name]="handler.icon" item-start *ngIf="handler.icon"></ion-icon>
<p>{{ handler.title | translate}}</p>
</ion-item>
<a ion-item (click)="openHandler('CoreSettingsAboutPage')" [title]="'core.settings.about' | translate" [class.core-split-item-selected]="'CoreSettingsAboutPage' == selectedPage">
<ion-icon name="contacts" item-start></ion-icon>
<p>{{ 'core.settings.about' | translate }}</p>
</a>
</ion-list>
</ion-content>
</core-split-view>

View File

@ -0,0 +1,33 @@
// (C) Copyright 2015 Martin Dougiamas
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import { NgModule } from '@angular/core';
import { IonicPageModule } from 'ionic-angular';
import { TranslateModule } from '@ngx-translate/core';
import { CoreSettingsListPage } from './list';
import { CoreComponentsModule } from '../../../../components/components.module';
import { CoreDirectivesModule } from '../../../../directives/directives.module';
@NgModule({
declarations: [
CoreSettingsListPage
],
imports: [
CoreComponentsModule,
CoreDirectivesModule,
IonicPageModule.forChild(CoreSettingsListPage),
TranslateModule.forChild()
],
})
export class CoreSettingsListPageModule {}

View File

@ -0,0 +1,67 @@
// (C) Copyright 2015 Martin Dougiamas
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import { Component, ViewChild } from '@angular/core';
import { IonicPage, NavController, NavParams, Platform } from 'ionic-angular';
import { CoreSettingsDelegate, CoreSettingsHandlerData } from '../../providers/delegate';
import { CoreSplitViewComponent } from '@components/split-view/split-view';
/**
* Page that displays the list of settings pages.
*/
@IonicPage({segment: 'core-settings-list'})
@Component({
selector: 'page-core-settings-list',
templateUrl: 'list.html',
})
export class CoreSettingsListPage {
@ViewChild(CoreSplitViewComponent) splitviewCtrl: CoreSplitViewComponent;
handlers: CoreSettingsHandlerData[];
areHandlersLoaded: Function;
isIOS: boolean;
selectedPage: string;
constructor(private settingsDelegate: CoreSettingsDelegate, private navCtrl: NavController, platorm: Platform,
navParams: NavParams) {
this.isIOS = platorm.is('ios');
this.selectedPage = navParams.get('page') || false;
}
/**
* View loaded.
*/
ionViewDidLoad(): void {
this.handlers = this.settingsDelegate.getHandlers();
if (this.selectedPage) {
this.openHandler(this.selectedPage);
} else if (this.splitviewCtrl.isOn()) {
this.openHandler('CoreSettingsGeneralPage');
}
}
/**
* Open a handler.
*
* @param {string} page Page to open.
* @param {any} params Params of the page to open.
*/
openHandler(page: string, params?: any): void {
this.selectedPage = page;
this.navCtrl.push(page, params);
}
}

View File

@ -0,0 +1,135 @@
// (C) Copyright 2015 Martin Dougiamas
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import { Injectable } from '@angular/core';
import { CoreDelegate, CoreDelegateHandler } from '@classes/delegate';
import { CoreEventsProvider } from '@providers/events';
import { CoreLoggerProvider } from '@providers/logger';
import { CoreSitesProvider } from '@providers/sites';
import { CoreUtilsProvider } from '@providers/utils/utils';
/**
* Interface that all settings handlers must implement.
*/
export interface CoreSettingsHandler extends CoreDelegateHandler {
/**
* The highest priority is displayed first.
* @type {number}
*/
priority: number;
/**
* Returns the data needed to render the handler.
*
* @return {CoreSettingsHandlerData} Data.
*/
getDisplayData(): CoreSettingsHandlerData;
}
/**
* Data needed to render a setting handler. It's returned by the handler.
*/
export interface CoreSettingsHandlerData {
/**
* Name of the page to load for the handler.
* @type {string}
*/
page: string;
/**
* Params list of the page to load for the handler.
* @type {any}
*/
params?: any;
/**
* Title to display for the handler.
* @type {string}
*/
title: string;
/**
* Name of the icon to display for the handler.
* @type {string}
*/
icon?: string; // Name of the icon to display in the menu.
/**
* Class to add to the displayed handler.
* @type {string}
*/
class?: string;
}
/**
* Service to interact with addons to be shown in app settings. Provides functions to register a plugin
* and notify an update in the data.
*/
@Injectable()
export class CoreSettingsDelegate extends CoreDelegate {
protected handlers: { [s: string]: CoreSettingsHandler } = {};
protected enabledHandlers: { [s: string]: CoreSettingsHandler } = {};
protected siteHandlers: CoreSettingsHandlerData[] = []; // Handlers to return.
constructor(protected loggerProvider: CoreLoggerProvider, protected sitesProvider: CoreSitesProvider,
protected eventsProvider: CoreEventsProvider, protected utils: CoreUtilsProvider) {
super('CoreSettingsDelegate', loggerProvider, sitesProvider, eventsProvider);
eventsProvider.on(CoreEventsProvider.LOGOUT, this.clearSiteHandlers.bind(this));
}
/**
* Clear current site handlers. Reserved for core use.
*/
clearSiteHandlers(): void {
this.siteHandlers = [];
}
/**
* Get the handlers for the current site.
*
* @return {CoreSettingsHandlerData[]}
*/
getHandlers(): CoreSettingsHandlerData[] {
return this.siteHandlers;
}
/**
* Update handlers Data.
*/
updateData(): void {
const handlersData: any[] = [];
for (const name in this.enabledHandlers) {
const handler = this.enabledHandlers[name],
data = handler.getDisplayData();
handlersData.push({
data: data,
priority: handler.priority
});
}
// Sort them by priority.
handlersData.sort((a, b) => {
return b.priority - a.priority;
});
// Return only the display data.
this.siteHandlers = handlersData.map((item) => {
return item.data;
});
}
}

View File

@ -0,0 +1,27 @@
// (C) Copyright 2015 Martin Dougiamas
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import { NgModule } from '@angular/core';
import { CoreSettingsDelegate } from './providers/delegate';
@NgModule({
declarations: [
],
imports: [
],
providers: [
CoreSettingsDelegate
]
})
export class CoreSettingsModule {}

View File

@ -22,14 +22,16 @@
</p>
</ion-item>
<ion-grid ion-item class="core-user-communication-handlers" *ngIf="(communicationHandlers && communicationHandlers.length) || isLoadingHandlers">
<ion-row no-padding align-items-center text-center>
<ion-col align-self-center *ngIf="communicationHandlers && communicationHandlers.length">
<a *ngFor="let comHandler of communicationHandlers" (click)="handlerClicked($event, comHandler)" [ngClass]="['core-user-profile-handler', comHandler.class]" title="{{comHandler.title | translate}}">
<ion-grid class="core-user-communication-handlers" *ngIf="(communicationHandlers && communicationHandlers.length) || isLoadingHandlers">
<ion-row no-padding justify-content-between *ngIf="communicationHandlers && communicationHandlers.length">
<ion-col align-self-center *ngFor="let comHandler of communicationHandlers" text-center>
<a (click)="handlerClicked($event, comHandler)" [ngClass]="['core-user-profile-handler', comHandler.class]" title="{{comHandler.title | translate}}" tappable>
<ion-icon [name]="comHandler.icon"></ion-icon>
<p>{{comHandler.title | translate}}</p>
</a>
</ion-col>
</ion-row>
<ion-row no-padding>
<ion-col text-center class="core-loading-handlers" *ngIf="isLoadingHandlers">
<ion-spinner></ion-spinner>
</ion-col>

View File

@ -6,14 +6,18 @@ page-core-user-profile {
font-size: 24px;
}
.core-user-communication-handlers {
padding: 6px 2px;
background: $list-background-color;
border-bottom: 1px solid $list-border-color;
.core-user-profile-handler {
background: $list-background-color;
border: 0;
color: $core-user-profile-communication-icons-color;
p {
margin: 0;
}
.icon {
border-radius: 50%;
width: 32px;