diff --git a/src/addon/messages/lang/en.json b/src/addon/messages/lang/en.json
index b97a0846b..e76d05634 100644
--- a/src/addon/messages/lang/en.json
+++ b/src/addon/messages/lang/en.json
@@ -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",
diff --git a/src/addon/messages/messages.module.ts b/src/addon/messages/messages.module.ts
index f1cd01549..4999b90f9 100644
--- a/src/addon/messages/messages.module.ts
+++ b/src/addon/messages/messages.module.ts
@@ -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(() => {
diff --git a/src/addon/messages/providers/messages.ts b/src/addon/messages/providers/messages.ts
index 28e10154a..6e7362f81 100644
--- a/src/addon/messages/providers/messages.ts
+++ b/src/addon/messages/providers/messages.ts
@@ -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.
*
diff --git a/src/addon/messages/providers/settings-handler.ts b/src/addon/messages/providers/settings-handler.ts
new file mode 100644
index 000000000..436eab857
--- /dev/null
+++ b/src/addon/messages/providers/settings-handler.ts
@@ -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 {
+ 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'
+ };
+ }
+
+}
diff --git a/src/app/app.module.ts b/src/app/app.module.ts
index c4f64116f..7b0be5c01 100644
--- a/src/app/app.module.ts
+++ b/src/app/app.module.ts
@@ -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,
diff --git a/src/app/app.scss b/src/app/app.scss
index 07e5352c2..d291bdec9 100644
--- a/src/app/app.scss
+++ b/src/app/app.scss
@@ -50,7 +50,7 @@
}
}
-@include media-breakpoint-down(md) {
+@include media-breakpoint-down(sm) {
.hidden-phone {
display: none !important;
opacity: 0 !important;
diff --git a/src/core/settings/lang/en.json b/src/core/settings/lang/en.json
new file mode 100644
index 000000000..6e7ad59e0
--- /dev/null
+++ b/src/core/settings/lang/en.json
@@ -0,0 +1,10 @@
+{
+ "about": "About",
+ "general": "General",
+ "loggedin": "Online",
+ "loggedoff": "Offline",
+ "settings": "Settings",
+ "sites": "Sites",
+ "spaceusage": "Space usage",
+ "synchronization": "Synchronisation"
+}
\ No newline at end of file
diff --git a/src/core/settings/pages/list/list.html b/src/core/settings/pages/list/list.html
new file mode 100644
index 000000000..724c5f9ee
--- /dev/null
+++ b/src/core/settings/pages/list/list.html
@@ -0,0 +1,37 @@
+
+
+ {{ 'core.settings.settings' | translate}}
+
+
+
+
+
+
+
+ {{ 'core.settings.general' | translate }}
+
+
+
+ {{ 'core.settings.spaceusage' | translate }}
+
+
+
+ {{ 'core.settings.synchronization' | translate }}
+
+
+
+ {{ 'core.sharedfiles.sharedfiles' | translate }}
+
+
+
+
+ {{ handler.title | translate}}
+
+
+
+
+ {{ 'core.settings.about' | translate }}
+
+
+
+
diff --git a/src/core/settings/pages/list/list.module.ts b/src/core/settings/pages/list/list.module.ts
new file mode 100644
index 000000000..6cc3bf981
--- /dev/null
+++ b/src/core/settings/pages/list/list.module.ts
@@ -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 {}
diff --git a/src/core/settings/pages/list/list.ts b/src/core/settings/pages/list/list.ts
new file mode 100644
index 000000000..6133e8e26
--- /dev/null
+++ b/src/core/settings/pages/list/list.ts
@@ -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);
+ }
+
+}
diff --git a/src/core/settings/providers/delegate.ts b/src/core/settings/providers/delegate.ts
new file mode 100644
index 000000000..df8d2e346
--- /dev/null
+++ b/src/core/settings/providers/delegate.ts
@@ -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;
+ });
+ }
+}
diff --git a/src/core/settings/settings.module.ts b/src/core/settings/settings.module.ts
new file mode 100644
index 000000000..91efeb1b1
--- /dev/null
+++ b/src/core/settings/settings.module.ts
@@ -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 {}
diff --git a/src/core/user/pages/profile/profile.html b/src/core/user/pages/profile/profile.html
index 8ea83b59f..7be3e8817 100644
--- a/src/core/user/pages/profile/profile.html
+++ b/src/core/user/pages/profile/profile.html
@@ -22,14 +22,16 @@
-
-
-
-
+
+
+
+
{{comHandler.title | translate}}
+
+
diff --git a/src/core/user/pages/profile/profile.scss b/src/core/user/pages/profile/profile.scss
index ff977a68f..c83a39afe 100644
--- a/src/core/user/pages/profile/profile.scss
+++ b/src/core/user/pages/profile/profile.scss
@@ -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;