forked from CIT/Vmeda.Online
		
	MOBILE-2329 settings: Migrate preferences
This commit is contained in:
		
							parent
							
								
									ee7808643b
								
							
						
					
					
						commit
						99af917816
					
				| @ -270,7 +270,7 @@ export class SQLiteDB { | ||||
|     deleteRecords(table: string, conditions?: object): Promise<any> { | ||||
|         if (conditions === null || typeof conditions == 'undefined') { | ||||
|             // No conditions, delete the whole table.
 | ||||
|             return this.execute(`DELETE FROM TABLE ${table}`); | ||||
|             return this.execute(`DELETE FROM ${table}`); | ||||
|         } | ||||
| 
 | ||||
|         const selectAndParams = this.whereClause(conditions); | ||||
|  | ||||
| @ -30,6 +30,7 @@ export class CoreConstants { | ||||
|     static SETTINGS_RICH_TEXT_EDITOR = 'CoreSettingsRichTextEditor'; | ||||
|     static SETTINGS_NOTIFICATION_SOUND = 'CoreSettingsNotificationSound'; | ||||
|     static SETTINGS_SYNC_ONLY_ON_WIFI = 'CoreSettingsSyncOnlyOnWifi'; | ||||
|     static SETTINGS_REPORT_IN_BACKGROUND = 'CoreSettingsReportInBackground'; | ||||
| 
 | ||||
|     // WS constants.
 | ||||
|     static WS_TIMEOUT = 30000; | ||||
|  | ||||
| @ -279,7 +279,7 @@ export class FileMock extends File { | ||||
|                     maxIterations = 10; | ||||
|                     // More accurate. Factor is 1.1.
 | ||||
|                     calculateByRequest(size, 1.1).then((size: number) => { | ||||
|                         return size / 1024; // Return size in KB.
 | ||||
|                         resolve(size / 1024); // Return size in KB.
 | ||||
|                     }); | ||||
|                 }); | ||||
| 
 | ||||
|  | ||||
| @ -45,9 +45,9 @@ export class CoreLoginSitesPage { | ||||
|      * View loaded. | ||||
|      */ | ||||
|     ionViewDidLoad(): void { | ||||
|         this.sitesProvider.getSites().then((sites) => { | ||||
|         this.sitesProvider.getSortedSites().then((sites) => { | ||||
|             // Remove protocol from the url to show more url text.
 | ||||
|             sites = sites.map((site) => { | ||||
|             this.sites = sites.map((site) => { | ||||
|                 site.siteUrl = site.siteUrl.replace(/^https?:\/\//, ''); | ||||
|                 site.badge = 0; | ||||
|                 this.pushNotificationsProvider.getSiteCounter(site.id).then((counter) => { | ||||
| @ -57,24 +57,6 @@ export class CoreLoginSitesPage { | ||||
|                 return site; | ||||
|             }); | ||||
| 
 | ||||
|             // Sort sites by url and fullname.
 | ||||
|             this.sites = sites.sort((a, b) => { | ||||
|                 // First compare by site url without the protocol.
 | ||||
|                 let compareA = a.siteUrl.toLowerCase(), | ||||
|                     compareB = b.siteUrl.toLowerCase(); | ||||
|                 const compare = compareA.localeCompare(compareB); | ||||
| 
 | ||||
|                 if (compare !== 0) { | ||||
|                     return compare; | ||||
|                 } | ||||
| 
 | ||||
|                 // If site url is the same, use fullname instead.
 | ||||
|                 compareA = a.fullName.toLowerCase().trim(); | ||||
|                 compareB = b.fullName.toLowerCase().trim(); | ||||
| 
 | ||||
|                 return compareA.localeCompare(compareB); | ||||
|             }); | ||||
| 
 | ||||
|             this.showDelete = false; | ||||
|         }).catch(() => { | ||||
|             // Shouldn't happen.
 | ||||
|  | ||||
| @ -1,12 +1,49 @@ | ||||
| { | ||||
|     "about": "About", | ||||
|     "appready": "App ready", | ||||
|     "cannotsyncoffline": "Cannot synchronise offline.", | ||||
|     "cannotsyncwithoutwifi": "Cannot synchronise because the current settings only allow to synchronise when connected to Wi-Fi. Please connect to a Wi-Fi network.", | ||||
|     "cordovadevicemodel": "Cordova device model", | ||||
|     "cordovadeviceosversion": "Cordova device OS version", | ||||
|     "cordovadeviceplatform": "Cordova device platform", | ||||
|     "cordovadeviceuuid": "Cordova device UUID", | ||||
|     "cordovaversion": "Cordova version", | ||||
|     "currentlanguage": "Current language", | ||||
|     "deletesitefiles": "Are you sure that you want to delete the downloaded files from the site '{{sitename}}'?", | ||||
|     "deletesitefilestitle": "Delete site files", | ||||
|     "deviceinfo": "Device info", | ||||
|     "deviceos": "Device OS", | ||||
|     "devicewebworkers": "Device web workers supported", | ||||
|     "disableall": "Disable notifications", | ||||
|     "disabled": "Disabled", | ||||
|     "displayformat": "Display format", | ||||
|     "enablerichtexteditor": "Enable text editor", | ||||
|     "enablerichtexteditordescription": "If enabled, a text editor will be available when entering content.", | ||||
|     "enablesyncwifi": "Allow sync only when on Wi-Fi", | ||||
|     "errordeletesitefiles": "Error deleting site files.", | ||||
|     "errorsyncsite": "Error synchronising site data. Please check your Internet connection and try again.", | ||||
|     "estimatedfreespace": "Estimated free space", | ||||
|     "filesystemroot": "File system root", | ||||
|     "general": "General", | ||||
|     "language": "Language", | ||||
|     "license": "License", | ||||
|     "localnotifavailable": "Local notifications available", | ||||
|     "locationhref": "Web view URL", | ||||
|     "loggedin": "Online", | ||||
|     "loggedoff": "Offline", | ||||
|     "navigatorlanguage": "Navigator language", | ||||
|     "navigatoruseragent": "Navigator userAgent", | ||||
|     "networkstatus": "Internet connection status", | ||||
|     "privacypolicy": "Privacy policy", | ||||
|     "reportinbackground": "Report errors automatically", | ||||
|     "settings": "Settings", | ||||
|     "sites": "Sites", | ||||
|     "spaceusage": "Space usage", | ||||
|     "synchronization": "Synchronisation" | ||||
|     "synchronization": "Synchronisation", | ||||
|     "synchronizenow": "Synchronise now", | ||||
|     "syncsettings": "Synchronisation settings", | ||||
|     "total": "Total", | ||||
|     "versioncode": "Version code", | ||||
|     "versionname": "Version name", | ||||
|     "wificonnection": "Wi-Fi connection" | ||||
| } | ||||
|  | ||||
							
								
								
									
										109
									
								
								src/core/settings/pages/about/about.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										109
									
								
								src/core/settings/pages/about/about.html
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,109 @@ | ||||
| <ion-header> | ||||
|     <ion-navbar> | ||||
|         <ion-title>{{ 'core.settings.about' | translate }}</ion-title> | ||||
|     </ion-navbar> | ||||
| </ion-header> | ||||
| <ion-content> | ||||
|     <ion-item text-wrap> | ||||
|         <h2>{{ appName }} {{ versionName }}</h2> | ||||
|     </ion-item> | ||||
|     <ion-item-group> | ||||
|         <ion-item-divider text-wrap color="light"> | ||||
|             {{ 'core.settings.license' | translate }} | ||||
|         </ion-item-divider> | ||||
|         <ion-item text-wrap> | ||||
|             <h2>Apache 2.0</h2> | ||||
|             <p><a href="http://www.apache.org/licenses/LICENSE-2.0" core-link auto-login="no">http://www.apache.org/licenses/LICENSE-2.0</a></p> | ||||
|         </ion-item> | ||||
|     </ion-item-group> | ||||
|     <ion-item-group *ngIf="privacyPolicy"> | ||||
|         <ion-item-divider text-wrap color="light"> | ||||
|             {{ 'core.settings.privacypolicy' | translate }} | ||||
|         </ion-item-divider> | ||||
|         <ion-item text-wrap> | ||||
|             <p><a [href]="privacyPolicy" core-link auto-login="no">{{ privacyPolicy }}</a></p> | ||||
|         </ion-item> | ||||
|     </ion-item-group> | ||||
|     <ion-item-group> | ||||
|         <ion-item-divider text-wrap color="light"> | ||||
|             {{ 'core.settings.deviceinfo' | translate }} | ||||
|         </ion-item-divider> | ||||
|         <ion-item text-wrap *ngIf="versionName"> | ||||
|             <h2>{{ 'core.settings.versionname' | translate}}</h2> | ||||
|             <p>{{ versionName }}</p> | ||||
|         </ion-item> | ||||
|         <ion-item text-wrap *ngIf="versionCode"> | ||||
|             <h2>{{ 'core.settings.versioncode' | translate}}</h2> | ||||
|             <p>{{ versionCode }}</p> | ||||
|         </ion-item> | ||||
|         <ion-item text-wrap *ngIf="fileSystemRoot"> | ||||
|             <h2>{{ 'core.settings.filesystemroot' | translate}}</h2> | ||||
|             <p><a *ngIf="fsClickable" [href]="fileSystemRoot" core-link auto-login="no">{{ filesystemroot }}</a></p> | ||||
|             <p *ngIf="!fsClickable">{{ fileSystemRoot }}</p> | ||||
|         </ion-item> | ||||
|         <ion-item text-wrap *ngIf="navigator && navigator.userAgent"> | ||||
|             <h2>{{ 'core.settings.navigatoruseragent' | translate}}</h2> | ||||
|             <p>{{ navigator.userAgent }}</p> | ||||
|         </ion-item> | ||||
|         <ion-item text-wrap *ngIf="navigator && navigator.language"> | ||||
|             <h2>{{ 'core.settings.navigatorlanguage' | translate}}</h2> | ||||
|             <p>{{ navigator.language }}</p> | ||||
|         </ion-item> | ||||
|         <ion-item text-wrap *ngIf="locationHref"> | ||||
|             <h2>{{ 'core.settings.locationhref' | translate}}</h2> | ||||
|             <p>{{ locationHref }}</p> | ||||
|         </ion-item> | ||||
|         <ion-item text-wrap *ngIf="appReady"> | ||||
|             <h2>{{ 'core.settings.appready' | translate}}</h2> | ||||
|             <p>{{ appReady | translate }}</p> | ||||
|         </ion-item> | ||||
|         <ion-item text-wrap *ngIf="deviceType"> | ||||
|             <h2>{{ 'core.settings.displayformat' | translate}}</h2> | ||||
|             <p>{{ deviceType | translate }}</p> | ||||
|         </ion-item> | ||||
|         <ion-item text-wrap *ngIf="deviceOs"> | ||||
|             <h2>{{ 'core.settings.deviceos' | translate}}</h2> | ||||
|             <p>{{ deviceOs | translate }}</p> | ||||
|         </ion-item> | ||||
|         <ion-item text-wrap *ngIf="currentLanguage"> | ||||
|             <h2>{{ 'core.settings.currentlanguage' | translate}}</h2> | ||||
|             <p>{{ currentLanguage }}</p> | ||||
|         </ion-item> | ||||
|         <ion-item text-wrap *ngIf="networkStatus"> | ||||
|             <h2>{{ 'core.settings.networkstatus' | translate}}</h2> | ||||
|             <p>{{ networkStatus | translate }}</p> | ||||
|         </ion-item> | ||||
|         <ion-item text-wrap *ngIf="wifiConnection"> | ||||
|             <h2>{{ 'core.settings.wificonnection' | translate}}</h2> | ||||
|             <p>{{ wifiConnection | translate }}</p> | ||||
|         </ion-item> | ||||
|         <ion-item text-wrap *ngIf="deviceWebWorkers"> | ||||
|             <h2>{{ 'core.settings.devicewebworkers' | translate}}</h2> | ||||
|             <p>{{ deviceWebWorkers | translate }}</p> | ||||
|         </ion-item> | ||||
|         <ion-item text-wrap *ngIf="device && device.cordova"> | ||||
|             <h2>{{ 'core.settings.cordovaversion' | translate}}</h2> | ||||
|             <p>{{ device.cordova }}</p> | ||||
|         </ion-item> | ||||
|         <ion-item text-wrap *ngIf="device && device.platform"> | ||||
|             <h2>{{ 'core.settings.cordovadeviceplatform' | translate}}</h2> | ||||
|             <p>{{ device.platform }}</p> | ||||
|         </ion-item> | ||||
|         <ion-item text-wrap *ngIf="device && device.version"> | ||||
|             <h2>{{ 'core.settings.cordovadeviceosversion' | translate}}</h2> | ||||
|             <p>{{ device.version }}</p> | ||||
|         </ion-item> | ||||
|         <ion-item text-wrap *ngIf="device && device.model"> | ||||
|             <h2>{{ 'core.settings.cordovadevicemodel' | translate}}</h2> | ||||
|             <p>{{ device.model }}</p> | ||||
|         </ion-item> | ||||
|         <ion-item text-wrap *ngIf="device && device.uuid"> | ||||
|             <h2>{{ 'core.settings.cordovadeviceuuid' | translate}}</h2> | ||||
|             <p>{{ device.uuid }}</p> | ||||
|         </ion-item> | ||||
|         <ion-item text-wrap *ngIf="localNotifAvailable"> | ||||
|             <h2>{{ 'core.settings.localnotifavailable' | translate}}</h2> | ||||
|             <p>{{ localNotifAvailable | translate }}</p> | ||||
|         </ion-item> | ||||
|     </ion-item-group> | ||||
| </ion-content> | ||||
							
								
								
									
										33
									
								
								src/core/settings/pages/about/about.module.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								src/core/settings/pages/about/about.module.ts
									
									
									
									
									
										Normal 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 { CoreSettingsAboutPage } from './about'; | ||||
| import { CoreComponentsModule } from '@components/components.module'; | ||||
| import { CoreDirectivesModule } from '@directives/directives.module'; | ||||
| 
 | ||||
| @NgModule({ | ||||
|     declarations: [ | ||||
|         CoreSettingsAboutPage | ||||
|     ], | ||||
|     imports: [ | ||||
|         CoreComponentsModule, | ||||
|         CoreDirectivesModule, | ||||
|         IonicPageModule.forChild(CoreSettingsAboutPage), | ||||
|         TranslateModule.forChild() | ||||
|     ], | ||||
| }) | ||||
| export class CoreSettingsAboutPageModule {} | ||||
							
								
								
									
										105
									
								
								src/core/settings/pages/about/about.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										105
									
								
								src/core/settings/pages/about/about.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,105 @@ | ||||
| // (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, } from '@angular/core'; | ||||
| import { IonicPage, Platform } from 'ionic-angular'; | ||||
| import { Device } from '@ionic-native/device'; | ||||
| import { CoreAppProvider } from '@providers/app'; | ||||
| import { CoreFileProvider } from '@providers/file'; | ||||
| import { CoreInitDelegate } from '@providers/init'; | ||||
| import { CoreLangProvider } from '@providers/lang'; | ||||
| import { CoreLocalNotificationsProvider } from '@providers/local-notifications'; | ||||
| import { CoreConfigConstants } from '../../../../configconstants'; | ||||
| 
 | ||||
| /** | ||||
|  * Page that displays the about settings. | ||||
|  */ | ||||
| @IonicPage({segment: 'core-settings-about'}) | ||||
| @Component({ | ||||
|     selector: 'page-core-settings-about', | ||||
|     templateUrl: 'about.html', | ||||
| }) | ||||
| export class CoreSettingsAboutPage { | ||||
| 
 | ||||
|     appName: string; | ||||
|     versionName: string; | ||||
|     versionCode: number; | ||||
|     privacyPolicy: string; | ||||
|     navigator: Navigator; | ||||
|     locationHref: string; | ||||
|     appReady: string; | ||||
|     deviceType: string; | ||||
|     deviceOs: string; | ||||
|     currentLanguage: string; | ||||
|     networkStatus: string; | ||||
|     wifiConnection: string; | ||||
|     deviceWebWorkers: string; | ||||
|     device: Device; | ||||
|     fileSystemRoot: string; | ||||
|     fsClickable: boolean; | ||||
|     storageType: string; | ||||
|     localNotifAvailable: string; | ||||
| 
 | ||||
|     constructor(platform: Platform, device: Device, appProvider: CoreAppProvider, fileProvider: CoreFileProvider, | ||||
|             initDelegate: CoreInitDelegate, langProvider: CoreLangProvider, | ||||
|             localNotificationsProvider: CoreLocalNotificationsProvider) { | ||||
| 
 | ||||
|         this.appName = appProvider.isDesktop() ? CoreConfigConstants.desktopappname : CoreConfigConstants.appname; | ||||
|         this.versionName = CoreConfigConstants.versionname; | ||||
|         this.versionCode = CoreConfigConstants.versioncode; | ||||
|         this.privacyPolicy = CoreConfigConstants.privacypolicy; | ||||
| 
 | ||||
|         this.navigator = window.navigator; | ||||
|         if (window.location && window.location.href) { | ||||
|             const url = window.location.href; | ||||
|             this.locationHref = url.substr(0, url.indexOf('#')); | ||||
|         } | ||||
| 
 | ||||
|         this.appReady = initDelegate.isReady() ? 'core.yes' : 'core.no'; | ||||
|         this.deviceType = platform.is('tablet') ? 'core.tablet' : 'core.phone'; | ||||
| 
 | ||||
|         if (platform.is('android')) { | ||||
|             this.deviceOs = 'core.android'; | ||||
|         } else if (platform.is('ios')) { | ||||
|             this.deviceOs = 'core.ios'; | ||||
|         } else if (platform.is('windows')) { | ||||
|             this.deviceOs = 'core.windowsphone'; | ||||
|         } else { | ||||
|             const matches = navigator.userAgent.match(/\(([^\)]*)\)/); | ||||
|             if (matches && matches.length > 1) { | ||||
|                 this.deviceOs = matches[1]; | ||||
|             } else { | ||||
|                 this.deviceOs = 'core.unknown'; | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         langProvider.getCurrentLanguage().then((lang) => { | ||||
|             this.currentLanguage = lang; | ||||
|         }); | ||||
| 
 | ||||
|         this.networkStatus = appProvider.isOnline() ? 'core.online' : 'core.offline'; | ||||
|         this.wifiConnection = appProvider.isNetworkAccessLimited() ? 'core.no' : 'core.yes'; | ||||
|         this.deviceWebWorkers = !!window['Worker'] && !!window['URL'] ? 'core.yes' : 'core.no'; | ||||
|         this.device = device; | ||||
| 
 | ||||
|         if (fileProvider.isAvailable()) { | ||||
|             fileProvider.getBasePath().then((basepath) => { | ||||
|                 this.fileSystemRoot = basepath; | ||||
|                 this.fsClickable = fileProvider.usesHTMLAPI(); | ||||
|             }); | ||||
|         } | ||||
| 
 | ||||
|         this.localNotifAvailable = localNotificationsProvider.isAvailable() ? 'core.yes' : 'core.no'; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										24
									
								
								src/core/settings/pages/general/general.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								src/core/settings/pages/general/general.html
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,24 @@ | ||||
| <ion-header> | ||||
|     <ion-navbar> | ||||
|         <ion-title>{{ 'core.settings.general' | translate }}</ion-title> | ||||
|     </ion-navbar> | ||||
| </ion-header> | ||||
| <ion-content> | ||||
|     <ion-item text-wrap> | ||||
|         <ion-label><h2>{{ 'core.settings.language' | translate }}</h2></ion-label> | ||||
|         <ion-select [(ngModel)]="selectedLanguage" (ngModelChange)="languageChanged()"> | ||||
|             <ion-option *ngFor="let code of languageCodes" [value]="code">{{ languages[code] }}</ion-option> | ||||
|         </ion-select> | ||||
|     </ion-item> | ||||
|     <ion-item text-wrap *ngIf="rteSupported"> | ||||
|         <ion-label> | ||||
|             <h2>{{ 'core.settings.enablerichtexteditor' | translate }}</h2> | ||||
|             <p>{{ 'core.settings.enablerichtexteditordescription' | translate }}</p> | ||||
|         </ion-label> | ||||
|         <ion-toggle [(ngModel)]="richTextEditor" (ngModelChange)="richTextEditorChanged()"></ion-toggle> | ||||
|     </ion-item> | ||||
|     <ion-item text-wrap *ngIf="showReport"> | ||||
|         <ion-label><h2>{{ 'core.settings.reportinbackground' | translate }}</h2></ion-label> | ||||
|         <ion-toggle [(ngModel)]="reportInBackground" (ngModelChange)="reportInBackgroundChanged()"></ion-toggle> | ||||
|     </ion-item> | ||||
| </ion-content> | ||||
							
								
								
									
										33
									
								
								src/core/settings/pages/general/general.module.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								src/core/settings/pages/general/general.module.ts
									
									
									
									
									
										Normal 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 { CoreSettingsGeneralPage } from './general'; | ||||
| import { CoreComponentsModule } from '@components/components.module'; | ||||
| import { CoreDirectivesModule } from '@directives/directives.module'; | ||||
| 
 | ||||
| @NgModule({ | ||||
|     declarations: [ | ||||
|         CoreSettingsGeneralPage | ||||
|     ], | ||||
|     imports: [ | ||||
|         CoreComponentsModule, | ||||
|         CoreDirectivesModule, | ||||
|         IonicPageModule.forChild(CoreSettingsGeneralPage), | ||||
|         TranslateModule.forChild() | ||||
|     ], | ||||
| }) | ||||
| export class CoreSettingsGeneralPageModule {} | ||||
							
								
								
									
										93
									
								
								src/core/settings/pages/general/general.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										93
									
								
								src/core/settings/pages/general/general.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,93 @@ | ||||
| // (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, } from '@angular/core'; | ||||
| import { IonicPage } from 'ionic-angular'; | ||||
| import { CoreAppProvider } from '@providers/app'; | ||||
| import { CoreConstants } from '@core/constants'; | ||||
| import { CoreConfigProvider } from '@providers/config'; | ||||
| import { CoreFileProvider } from '@providers/file'; | ||||
| import { CoreEventsProvider } from '@providers/events'; | ||||
| import { CoreLangProvider } from '@providers/lang'; | ||||
| import { CoreDomUtilsProvider } from '@providers/utils/dom'; | ||||
| import { CoreLocalNotificationsProvider } from '@providers/local-notifications'; | ||||
| import { CoreConfigConstants } from '../../../../configconstants'; | ||||
| 
 | ||||
| /** | ||||
|  * Page that displays the general settings. | ||||
|  */ | ||||
| @IonicPage({segment: 'core-settings-general'}) | ||||
| @Component({ | ||||
|     selector: 'page-core-settings-general', | ||||
|     templateUrl: 'general.html', | ||||
| }) | ||||
| export class CoreSettingsGeneralPage { | ||||
| 
 | ||||
|     languages = {}; | ||||
|     languageCodes = []; | ||||
|     selectedLanguage: string; | ||||
|     rteSupported: boolean; | ||||
|     richTextEditor: boolean; | ||||
|     showReport: boolean; | ||||
|     reportInBackground: boolean; | ||||
| 
 | ||||
|     constructor(appProvider: CoreAppProvider, private configProvider: CoreConfigProvider, fileProvider: CoreFileProvider, | ||||
|             private eventsProvider: CoreEventsProvider, private langProvider: CoreLangProvider, | ||||
|             private domUtils: CoreDomUtilsProvider, | ||||
|             localNotificationsProvider: CoreLocalNotificationsProvider) { | ||||
| 
 | ||||
|         this.languages = CoreConfigConstants.languages; | ||||
|         this.languageCodes = Object.keys(this.languages); | ||||
|         langProvider.getCurrentLanguage().then((currentLanguage) => { | ||||
|             this.selectedLanguage = currentLanguage; | ||||
|         }); | ||||
| 
 | ||||
|         this.rteSupported = this.domUtils.isRichTextEditorSupported(); | ||||
|         if (this.rteSupported) { | ||||
|             this.configProvider.get(CoreConstants.SETTINGS_RICH_TEXT_EDITOR, true).then((richTextEditorEnabled) => { | ||||
|                 this.richTextEditor = richTextEditorEnabled; | ||||
|             }); | ||||
|         } | ||||
| 
 | ||||
|         if (localStorage && localStorage.getItem && localStorage.setItem) { | ||||
|             this.showReport = true; | ||||
|             this.reportInBackground = parseInt(localStorage.getItem(CoreConstants.SETTINGS_REPORT_IN_BACKGROUND), 10) === 1; | ||||
|         } else { | ||||
|             this.showReport = false; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Called when a new language is selected. | ||||
|      */ | ||||
|     languageChanged(): void { | ||||
|         this.langProvider.changeCurrentLanguage(this.selectedLanguage).finally(() => { | ||||
|             this.eventsProvider.trigger(CoreEventsProvider.LANGUAGE_CHANGED); | ||||
|         }); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Called when the rich text editor is enabled or disabled. | ||||
|      */ | ||||
|     richTextEditorChanged(): void { | ||||
|         this.configProvider.set(CoreConstants.SETTINGS_RICH_TEXT_EDITOR, this.richTextEditor); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Called when the report in background setting is enabled or disabled. | ||||
|      */ | ||||
|     reportInBackgroundChanged(): void { | ||||
|         localStorage.setItem(CoreConstants.SETTINGS_REPORT_IN_BACKGROUND, this.reportInBackground ? '1' : '0'); | ||||
|     } | ||||
| } | ||||
| @ -16,7 +16,7 @@ | ||||
|                 <ion-icon name="stats" item-start></ion-icon> | ||||
|                 <p>{{ 'core.settings.spaceusage' | translate }}</p> | ||||
|             </ion-item> | ||||
|             <ion-item (click)="openHandler('CoreSettingSynchronizationPage')" [title]="'core.settings.synchronization' | translate" [class.core-split-item-selected]="'CoreSettingSynchronizationPage' == selectedPage" detail-push> | ||||
|             <ion-item (click)="openHandler('CoreSettingsSynchronizationPage')" [title]="'core.settings.synchronization' | translate" [class.core-split-item-selected]="'CoreSettingsSynchronizationPage' == selectedPage" detail-push> | ||||
|                 <ion-icon name="sync" item-start></ion-icon> | ||||
|                 <p>{{ 'core.settings.synchronization' | translate }}</p> | ||||
|             </ion-item> | ||||
|  | ||||
							
								
								
									
										28
									
								
								src/core/settings/pages/space-usage/space-usage.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								src/core/settings/pages/space-usage/space-usage.html
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,28 @@ | ||||
| <ion-header> | ||||
|     <ion-navbar> | ||||
|         <ion-title>{{ 'core.settings.spaceusage' | translate }}</ion-title> | ||||
|     </ion-navbar> | ||||
| </ion-header> | ||||
| <ion-content> | ||||
|     <ion-refresher [enabled]="usageLoaded" (ionRefresh)="refreshData($event)"> | ||||
|         <ion-refresher-content pullingText="{{ 'core.pulltorefresh' | translate }}"></ion-refresher-content> | ||||
|     </ion-refresher> | ||||
|     <core-loading [hideUntil]="usageLoaded"> | ||||
|         <ion-item *ngFor="let site of sites" [class.core-primary-item]="site.id == currentSiteId"> | ||||
|             <h2><core-format-text [text]="site.siteName"></core-format-text></h2> | ||||
|             <p>{{ site.fullName }}</p> | ||||
|             <p item-end>{{ site.spaceUsage | coreBytesToSize }}</p> | ||||
|             <button ion-button icon-only clear color="danger" item-end (click)="deleteSiteFiles(site)" [hidden]="!site.spaceUsage > '0'" [attr.aria-label]="'core.settings.deletesitefilestitle' | translate"> | ||||
|                 <ion-icon name="trash"></ion-icon> | ||||
|             </button> | ||||
|         </ion-item> | ||||
|         <ion-item-divider color="light"> | ||||
|             <p>{{ 'core.settings.total' | translate }}</p> | ||||
|             <p item-end>{{ totalUsage | coreBytesToSize }}</p> | ||||
|         </ion-item-divider> | ||||
|         <ion-item-divider color="light"> | ||||
|             <p>{{ 'core.settings.estimatedfreespace' | translate }}</p> | ||||
|             <p item-end>{{ freeSpace | coreBytesToSize }}</p> | ||||
|         </ion-item-divider> | ||||
|     </core-loading> | ||||
| </ion-content> | ||||
							
								
								
									
										35
									
								
								src/core/settings/pages/space-usage/space-usage.module.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								src/core/settings/pages/space-usage/space-usage.module.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,35 @@ | ||||
| // (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 { CoreSettingsSpaceUsagePage } from './space-usage'; | ||||
| import { CoreComponentsModule } from '@components/components.module'; | ||||
| import { CoreDirectivesModule } from '@directives/directives.module'; | ||||
| import { CorePipesModule } from '@pipes/pipes.module'; | ||||
| 
 | ||||
| @NgModule({ | ||||
|     declarations: [ | ||||
|         CoreSettingsSpaceUsagePage | ||||
|     ], | ||||
|     imports: [ | ||||
|         CoreComponentsModule, | ||||
|         CoreDirectivesModule, | ||||
|         CorePipesModule, | ||||
|         IonicPageModule.forChild(CoreSettingsSpaceUsagePage), | ||||
|         TranslateModule.forChild() | ||||
|     ], | ||||
| }) | ||||
| export class CoreSettingsSpaceUsagePageModule {} | ||||
							
								
								
									
										180
									
								
								src/core/settings/pages/space-usage/space-usage.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										180
									
								
								src/core/settings/pages/space-usage/space-usage.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,180 @@ | ||||
| // (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, } from '@angular/core'; | ||||
| import { IonicPage } from 'ionic-angular'; | ||||
| import { TranslateService } from '@ngx-translate/core'; | ||||
| import { CoreFileProvider } from '@providers/file'; | ||||
| import { CoreFilepoolProvider } from '@providers/filepool'; | ||||
| import { CoreSitesProvider } from '@providers/sites'; | ||||
| import { CoreTextUtilsProvider } from '@providers/utils/text'; | ||||
| import { CoreDomUtilsProvider } from '@providers/utils/dom'; | ||||
| 
 | ||||
| /** | ||||
|  * Page that displays the space usage settings. | ||||
|  */ | ||||
| @IonicPage({segment: 'core-settings-space-usage'}) | ||||
| @Component({ | ||||
|     selector: 'page-core-settings-space-usage', | ||||
|     templateUrl: 'space-usage.html', | ||||
| }) | ||||
| export class CoreSettingsSpaceUsagePage { | ||||
| 
 | ||||
|     usageLoaded = false; | ||||
|     sites = []; | ||||
|     currentSiteId = ''; | ||||
|     totalUsage = 0; | ||||
|     freeSpace = 0; | ||||
| 
 | ||||
|     constructor(private fileProvider: CoreFileProvider, private filePoolProvider: CoreFilepoolProvider, | ||||
|             private sitesProvider: CoreSitesProvider, private textUtils: CoreTextUtilsProvider, | ||||
|             private translate: TranslateService, private domUtils: CoreDomUtilsProvider) { | ||||
|         this.currentSiteId = this.sitesProvider.getCurrentSiteId(); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * View loaded. | ||||
|      */ | ||||
|     ionViewDidLoad(): void { | ||||
|         this.fetchData().finally(() => { | ||||
|             this.usageLoaded = true; | ||||
|         }); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Convenience function to calculate each site's usage, and the total usage. | ||||
|      * | ||||
|      * @return {Promise<any>} Resolved when done. | ||||
|      */ | ||||
|     protected calculateSizeUsage(): Promise<any> { | ||||
|         return this.sitesProvider.getSortedSites().then((sites) => { | ||||
|             this.sites = sites; | ||||
| 
 | ||||
|             // Get space usage.
 | ||||
|             const promises = this.sites.map((siteEntry) => { | ||||
|                 return this.sitesProvider.getSite(siteEntry.id).then((site) => { | ||||
|                     return site.getSpaceUsage().then((size) => { | ||||
|                         siteEntry.spaceUsage = size; | ||||
|                     }); | ||||
|                 }); | ||||
|             }); | ||||
| 
 | ||||
|             return Promise.all(promises); | ||||
|         }); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Convenience function to calculate total usage. | ||||
|      */ | ||||
|     protected calculateTotalUsage(): void { | ||||
|         let total = 0; | ||||
|         this.sites.forEach((site) => { | ||||
|             if (site.spaceUsage) { | ||||
|                 total += parseInt(site.spaceUsage, 10); | ||||
|             } | ||||
|         }); | ||||
|         this.totalUsage = total; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Convenience function to calculate free space in the device. | ||||
|      * | ||||
|      * @return {Promise<any>} Resolved when done. | ||||
|      */ | ||||
|     protected calculateFreeSpace(): Promise<any> { | ||||
|         if (this.fileProvider.isAvailable()) { | ||||
|             return this.fileProvider.calculateFreeSpace().then((freeSpace) => { | ||||
|                 this.freeSpace = freeSpace; | ||||
|             }).catch(() => { | ||||
|                 this.freeSpace = 0; | ||||
|             }); | ||||
|         } else { | ||||
|             this.freeSpace = 0; | ||||
| 
 | ||||
|             return Promise.resolve(null); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Convenience function to calculate space usage and free space in the device. | ||||
|      * | ||||
|      * @return {Promise<any>} Resolved when done. | ||||
|      */ | ||||
|     protected fetchData(): Promise<any> { | ||||
|         return Promise.all([ | ||||
|             this.calculateSizeUsage().then(() => this.calculateTotalUsage()), | ||||
|             this.calculateFreeSpace(), | ||||
|         ]); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Refresh the data. | ||||
|      * | ||||
|      * @param {any} refresher Refresher. | ||||
|      */ | ||||
|     refreshData(refresher: any): void { | ||||
|         this.fetchData().finally(() => { | ||||
|             refresher.complete(); | ||||
|         }); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Convenience function to update site size, along with total usage and free space. | ||||
|      * | ||||
|      * @param {any} site Site object with space usage. | ||||
|      * @param {number} newUsage New space usage of the site in bytes. | ||||
|      */ | ||||
|     protected updateSiteUsage(site: any, newUsage: number): void { | ||||
|         const oldUsage = site.spaceUsage; | ||||
|         site.spaceUsage = newUsage; | ||||
|         this.totalUsage -= oldUsage - newUsage; | ||||
|         this.freeSpace += oldUsage - newUsage; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Deletes files of a site. | ||||
|      * | ||||
|      * @param {any} siteData Site object with space usage. | ||||
|      */ | ||||
|     deleteSiteFiles(siteData: any): void { | ||||
|         this.textUtils.formatText(siteData.siteName).then((siteName) => { | ||||
|             const title = this.translate.instant('core.settings.deletesitefilestitle'); | ||||
|             const message = this.translate.instant('core.settings.deletesitefiles', {sitename: siteName}); | ||||
| 
 | ||||
|             this.domUtils.showConfirm(message, title).then(() => { | ||||
|                 return this.sitesProvider.getSite(siteData.id); | ||||
|             }).then((site) => { | ||||
|                 site.deleteFolder().then(() => { | ||||
|                     this.filePoolProvider.clearAllPackagesStatus(site.id); | ||||
|                     this.filePoolProvider.clearFilepool(site.id); | ||||
|                     this.updateSiteUsage(siteData, 0); | ||||
|                 }).catch((error) => { | ||||
|                     if (error && error.code === FileError.NOT_FOUND_ERR) { | ||||
|                         // Not found, set size 0.
 | ||||
|                         this.filePoolProvider.clearAllPackagesStatus(site.id); | ||||
|                         this.updateSiteUsage(siteData, 0); | ||||
|                     } else { | ||||
|                         // Error, recalculate the site usage.
 | ||||
|                         this.domUtils.showErrorModal('core.settings.errordeletesitefiles', true); | ||||
|                         site.getSpaceUsage().then((size) => { | ||||
|                             this.updateSiteUsage(siteData, size); | ||||
|                         }); | ||||
|                     } | ||||
|                 }); | ||||
|             }).catch(() => { | ||||
|                 // Ignore cancelled confirmation modal.
 | ||||
|             }); | ||||
|         }); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										29
									
								
								src/core/settings/pages/synchronization/synchronization.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								src/core/settings/pages/synchronization/synchronization.html
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,29 @@ | ||||
| <ion-header> | ||||
|     <ion-navbar> | ||||
|         <ion-title>{{ 'core.settings.synchronization' | translate }}</ion-title> | ||||
|     </ion-navbar> | ||||
| </ion-header> | ||||
| <ion-content> | ||||
|     <core-loading [hideUntil]="sitesLoaded"> | ||||
|         <ion-item-divider color="light"> | ||||
|             <p>{{ 'core.settings.syncsettings' | translate }}</p> | ||||
|         </ion-item-divider> | ||||
|         <ion-item> | ||||
|             <ion-label>{{ 'core.settings.enablesyncwifi' | translate }}</ion-label> | ||||
|             <ion-toggle item-end [(ngModel)]="syncOnlyOnWifi" (ngModelChange)="syncOnlyOnWifiChanged()"> | ||||
|             </ion-toggle> | ||||
|         </ion-item> | ||||
|         <ion-item-divider color="light"> | ||||
|             <p>{{ 'core.settings.sites' | translate }}</p> | ||||
|         </ion-item-divider> | ||||
|         <ion-item *ngFor="let site of sites" [class.core-primary-item]="site.id == currentSiteId"> | ||||
|             <h2><core-format-text [text]="site.siteName"></core-format-text></h2> | ||||
|             <p>{{ site.fullName }}</p> | ||||
|             <p>{{ site.siteUrl }}</p> | ||||
|             <button ion-button icon-only clear item-end *ngIf="!isSynchronizing(site.id)" (click)="synchronize(site.id)" [title]="site.siteName" [attr.aria-label]="'core.settings.synchronizenow' | translate"> | ||||
|                 <ion-icon name="sync"></ion-icon> | ||||
|             </button> | ||||
|             <ion-spinner item-end *ngIf="isSynchronizing(site.id)"></ion-spinner> | ||||
|         </ion-item> | ||||
|     </core-loading> | ||||
| </ion-content> | ||||
| @ -0,0 +1,35 @@ | ||||
| // (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 { CoreSettingsSynchronizationPage } from './synchronization'; | ||||
| import { CoreComponentsModule } from '@components/components.module'; | ||||
| import { CoreDirectivesModule } from '@directives/directives.module'; | ||||
| import { CorePipesModule } from '@pipes/pipes.module'; | ||||
| 
 | ||||
| @NgModule({ | ||||
|     declarations: [ | ||||
|         CoreSettingsSynchronizationPage | ||||
|     ], | ||||
|     imports: [ | ||||
|         CoreComponentsModule, | ||||
|         CoreDirectivesModule, | ||||
|         CorePipesModule, | ||||
|         IonicPageModule.forChild(CoreSettingsSynchronizationPage), | ||||
|         TranslateModule.forChild() | ||||
|     ], | ||||
| }) | ||||
| export class CoreSettingsSynchronizationPageModule {} | ||||
							
								
								
									
										113
									
								
								src/core/settings/pages/synchronization/synchronization.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										113
									
								
								src/core/settings/pages/synchronization/synchronization.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,113 @@ | ||||
| // (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, OnDestroy } from '@angular/core'; | ||||
| import { IonicPage } from 'ionic-angular'; | ||||
| import { CoreConstants } from '@core/constants'; | ||||
| import { CoreEventsProvider } from '@providers/events'; | ||||
| import { CoreSitesProvider, CoreSiteBasicInfo } from '@providers/sites'; | ||||
| import { CoreDomUtilsProvider } from '@providers/utils/dom'; | ||||
| import { CoreConfigProvider } from '@providers/config'; | ||||
| import { CoreSettingsHelper } from '@core/settings/providers/helper'; | ||||
| 
 | ||||
| /** | ||||
|  * Page that displays the synchronization settings. | ||||
|  */ | ||||
| @IonicPage({segment: 'core-settings-synchronization'}) | ||||
| @Component({ | ||||
|     selector: 'page-core-settings-synchronization', | ||||
|     templateUrl: 'synchronization.html', | ||||
| }) | ||||
| export class CoreSettingsSynchronizationPage implements OnDestroy { | ||||
| 
 | ||||
|     sites: CoreSiteBasicInfo[] = []; | ||||
|     sitesLoaded = false; | ||||
|     sitesObserver: any; | ||||
|     currentSiteId = ''; | ||||
|     syncOnlyOnWifi = false; | ||||
|     isDestroyed = false; | ||||
| 
 | ||||
|     constructor(private configProvider: CoreConfigProvider, private eventsProvider: CoreEventsProvider, | ||||
|             private sitesProvider: CoreSitesProvider, private domUtils: CoreDomUtilsProvider, | ||||
|             private settingsHelper: CoreSettingsHelper) { | ||||
| 
 | ||||
|         this.currentSiteId = this.sitesProvider.getCurrentSiteId(); | ||||
| 
 | ||||
|         this.sitesObserver = this.eventsProvider.on(CoreEventsProvider.SITE_UPDATED, (data) => { | ||||
|             this.sitesProvider.getSite(data.siteId).then((site) => { | ||||
|                 const siteInfo = site.getInfo(); | ||||
|                 const siteEntry = this.sites.find((siteEntry) => siteEntry.id == site.id); | ||||
|                 if (siteEntry) { | ||||
|                     siteEntry.siteUrl = siteInfo.siteurl; | ||||
|                     siteEntry.siteName = siteInfo.sitename; | ||||
|                     siteEntry.fullName = siteInfo.fullname; | ||||
|                 } | ||||
|             }); | ||||
|         }); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * View loaded. | ||||
|      */ | ||||
|     ionViewDidLoad(): void { | ||||
|         this.sitesProvider.getSortedSites().then((sites) => { | ||||
|             this.sites = sites; | ||||
|         }).finally(() => { | ||||
|             this.sitesLoaded = true; | ||||
|         }); | ||||
| 
 | ||||
|         this.configProvider.get(CoreConstants.SETTINGS_SYNC_ONLY_ON_WIFI, true).then((syncOnlyOnWifi) => { | ||||
|             this.syncOnlyOnWifi = syncOnlyOnWifi; | ||||
|         }); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Called when sync only on wifi setting is enabled or disabled. | ||||
|      */ | ||||
|     syncOnlyOnWifiChanged(): void { | ||||
|         this.configProvider.set(CoreConstants.SETTINGS_SYNC_ONLY_ON_WIFI, this.syncOnlyOnWifi); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Syncrhonizes a site. | ||||
|      * | ||||
|      * @param {string} siteId Site ID. | ||||
|      */ | ||||
|     synchronize(siteId: string): void { | ||||
|         this.settingsHelper.synchronizeSite(this.syncOnlyOnWifi, siteId).catch((error) => { | ||||
|             if (this.isDestroyed) { | ||||
|                 return; | ||||
|             } | ||||
|             this.domUtils.showErrorModalDefault(error, 'core.settings.errorsyncsite', true); | ||||
|         }); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Returns true if site is beeing synchronized. | ||||
|      * | ||||
|      * @param {string} siteId Site ID. | ||||
|      * @return {boolean} True if site is beeing synchronized, false otherwise. | ||||
|      */ | ||||
|     isSynchronizing(siteId: string): boolean { | ||||
|         return !!this.settingsHelper.getSiteSyncPromise(siteId); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Page destroyed. | ||||
|      */ | ||||
|     ngOnDestroy(): void { | ||||
|         this.isDestroyed = true; | ||||
|         this.sitesObserver && this.sitesObserver.off(); | ||||
|     } | ||||
| } | ||||
| @ -13,8 +13,14 @@ | ||||
| // limitations under the License.
 | ||||
| 
 | ||||
| import { Injectable } from '@angular/core'; | ||||
| import { CoreAppProvider } from '@providers/app'; | ||||
| import { CoreCronDelegate } from '@providers/cron'; | ||||
| import { CoreEventsProvider } from '@providers/events'; | ||||
| import { CoreFilepoolProvider } from '@providers/filepool'; | ||||
| import { CoreLoggerProvider } from '@providers/logger'; | ||||
| import { CoreSitesProvider } from '@providers/sites'; | ||||
| import { CoreUtilsProvider } from '@providers/utils/utils'; | ||||
| import { TranslateService } from '@ngx-translate/core'; | ||||
| 
 | ||||
| /** | ||||
|  * Settings helper service. | ||||
| @ -22,8 +28,11 @@ import { CoreUtilsProvider } from '@providers/utils/utils'; | ||||
| @Injectable() | ||||
| export class CoreSettingsHelper { | ||||
|     protected logger; | ||||
|     protected syncPromises = {}; | ||||
| 
 | ||||
|     constructor(loggerProvider: CoreLoggerProvider, private utils: CoreUtilsProvider) { | ||||
|     constructor(loggerProvider: CoreLoggerProvider, private appProvider: CoreAppProvider, private cronDelegate: CoreCronDelegate, | ||||
|             private eventsProvider: CoreEventsProvider, private filePoolProvider: CoreFilepoolProvider, | ||||
|             private sitesProvider: CoreSitesProvider, private utils: CoreUtilsProvider, private translate: TranslateService) { | ||||
|         this.logger = loggerProvider.getInstance('CoreSettingsHelper'); | ||||
|     } | ||||
| 
 | ||||
| @ -91,4 +100,79 @@ export class CoreSettingsHelper { | ||||
| 
 | ||||
|         return result; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Get the synchronization promise of a site. | ||||
|      * | ||||
|      * @param {string} siteId ID of the site. | ||||
|      * @return {Promise<any> | null} Sync promise or null if site is not being syncrhonized. | ||||
|      */ | ||||
|     getSiteSyncPromise(siteId: string): Promise<any> { | ||||
|         if (this.syncPromises[siteId]) { | ||||
|             return this.syncPromises[siteId]; | ||||
|         } else { | ||||
|             return null; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Synchronize a site. | ||||
|      * | ||||
|      * @param {boolean} syncOnlyOnWifi True to sync only on wifi, false otherwise. | ||||
|      * @param {string} siteId ID of the site to synchronize. | ||||
|      * @return {Promise<any>} Promise resolved when synchronized, rejected if failure. | ||||
|      */ | ||||
|     synchronizeSite(syncOnlyOnWifi: boolean, siteId: string): Promise<any> { | ||||
|         if (this.syncPromises[siteId]) { | ||||
|             // There's already a sync ongoing for this site, return the promise.
 | ||||
|             return this.syncPromises[siteId]; | ||||
|         } | ||||
| 
 | ||||
|         const promises = []; | ||||
|         const hasSyncHandlers = this.cronDelegate.hasManualSyncHandlers(); | ||||
| 
 | ||||
|         if (hasSyncHandlers && !this.appProvider.isOnline()) { | ||||
|             // We need connection to execute sync.
 | ||||
|             return Promise.reject(this.translate.instant('core.settings.cannotsyncoffline')); | ||||
|         } else if (hasSyncHandlers && syncOnlyOnWifi && this.appProvider.isNetworkAccessLimited()) { | ||||
|             return Promise.reject(this.translate.instant('core.settings.cannotsyncwithoutwifi')); | ||||
|         } | ||||
| 
 | ||||
|         // Invalidate all the site files so they are re-downloaded.
 | ||||
|         promises.push(this.filePoolProvider.invalidateAllFiles(siteId).catch(() => { | ||||
|             // Ignore errors.
 | ||||
|         })); | ||||
| 
 | ||||
|         // Get the site to invalidate data.
 | ||||
|         promises.push(this.sitesProvider.getSite(siteId).then((site) => { | ||||
|             // Invalidate the WS cache.
 | ||||
|             return site.invalidateWsCache().then(() => { | ||||
|                 const subPromises = []; | ||||
| 
 | ||||
|                 // Check if local_mobile was installed in Moodle.
 | ||||
|                 subPromises.push(site.checkIfLocalMobileInstalledAndNotUsed().then(() => { | ||||
|                     // Local mobile was added. Throw invalid session to force reconnect and create a new token.
 | ||||
|                     this.eventsProvider.trigger(CoreEventsProvider.SESSION_EXPIRED, {}, siteId); | ||||
| 
 | ||||
|                     return Promise.reject(this.translate.instant('core.lostconnection')); | ||||
|                 }, () => { | ||||
|                     // Update site info.
 | ||||
|                     return this.sitesProvider.updateSiteInfo(siteId); | ||||
|                 })); | ||||
| 
 | ||||
|                 // Execute cron if needed.
 | ||||
|                 subPromises.push(this.cronDelegate.forceSyncExecution(siteId)); | ||||
| 
 | ||||
|                 return Promise.all(subPromises); | ||||
|             }); | ||||
|         })); | ||||
| 
 | ||||
|         const syncPromise = Promise.all(promises); | ||||
|         this.syncPromises[siteId] = syncPromise; | ||||
|         syncPromise.finally(() => { | ||||
|             delete this.syncPromises[siteId]; | ||||
|         }); | ||||
| 
 | ||||
|         return syncPromise; | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -870,6 +870,36 @@ export class CoreSitesProvider { | ||||
|         }); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Get the list of sites stored, sorted by URL and full name. | ||||
|      * | ||||
|      * @param {String[]} [ids] IDs of the sites to get. If not defined, return all sites. | ||||
|      * @return {Promise<CoreSiteBasicInfo[]>} Promise resolved when the sites are retrieved. | ||||
|      */ | ||||
|     getSortedSites(ids?: string[]): Promise<CoreSiteBasicInfo[]> { | ||||
|         return this.getSites(ids).then((sites) => { | ||||
|             // Sort sites by url and ful lname.
 | ||||
|             sites.sort((a, b) => { | ||||
|                 // First compare by site url without the protocol.
 | ||||
|                 let compareA = a.siteUrl.replace(/^https?:\/\//, '').toLowerCase(), | ||||
|                     compareB = b.siteUrl.replace(/^https?:\/\//, '').toLowerCase(); | ||||
|                 const compare = compareA.localeCompare(compareB); | ||||
| 
 | ||||
|                 if (compare !== 0) { | ||||
|                     return compare; | ||||
|                 } | ||||
| 
 | ||||
|                 // If site url is the same, use fullname instead.
 | ||||
|                 compareA = a.fullName.toLowerCase().trim(); | ||||
|                 compareB = b.fullName.toLowerCase().trim(); | ||||
| 
 | ||||
|                 return compareA.localeCompare(compareB); | ||||
|             }); | ||||
| 
 | ||||
|             return sites; | ||||
|         }); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Get the list of IDs of sites stored. | ||||
|      * | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user