MOBILE-2261 core: Implement first version of update manager
parent
e216341838
commit
93568a9c97
|
@ -48,6 +48,7 @@ import { CoreGroupsProvider } from '../providers/groups';
|
|||
import { CoreCronDelegate } from '../providers/cron';
|
||||
import { CoreFileSessionProvider } from '../providers/file-session';
|
||||
import { CoreFilepoolProvider } from '../providers/filepool';
|
||||
import { CoreUpdateManagerProvider } from '../providers/update-manager';
|
||||
|
||||
// For translate loader. AoT requires an exported function for factories.
|
||||
export function createTranslateLoader(http: HttpClient) {
|
||||
|
@ -103,19 +104,23 @@ export function createTranslateLoader(http: HttpClient) {
|
|||
CoreCronDelegate,
|
||||
CoreFileSessionProvider,
|
||||
CoreFilepoolProvider,
|
||||
CoreUpdateManagerProvider,
|
||||
]
|
||||
})
|
||||
export class AppModule {
|
||||
constructor(platform: Platform, initDelegate: CoreInitDelegate) {
|
||||
constructor(platform: Platform, initDelegate: CoreInitDelegate, updateManager: CoreUpdateManagerProvider) {
|
||||
// Create a handler for platform ready and register it in the init delegate.
|
||||
let handler = {
|
||||
name: 'CorePlatformReady',
|
||||
priority: initDelegate.MAX_RECOMMENDED_PRIORITY + 400,
|
||||
priority: CoreInitDelegate.MAX_RECOMMENDED_PRIORITY + 400,
|
||||
blocking: true,
|
||||
load: platform.ready
|
||||
};
|
||||
initDelegate.registerProcess(handler);
|
||||
|
||||
// Register the update manager as an init process.
|
||||
initDelegate.registerProcess(updateManager);
|
||||
|
||||
// Execute the init processes.
|
||||
initDelegate.executeInitProcesses();
|
||||
}
|
||||
|
|
|
@ -27,13 +27,11 @@ import { FileTransferErrorMock } from './file-transfer';
|
|||
@Injectable()
|
||||
export class CoreEmulatorHelper implements CoreInitHandler {
|
||||
name = 'CoreEmulator';
|
||||
priority;
|
||||
priority = CoreInitDelegate.MAX_RECOMMENDED_PRIORITY + 500;
|
||||
blocking = true;
|
||||
|
||||
constructor(private file: File, private fileProvider: CoreFileProvider, private utils: CoreUtilsProvider,
|
||||
initDelegate: CoreInitDelegate, private localNotif: LocalNotifications, private appProvider: CoreAppProvider) {
|
||||
this.priority = initDelegate.MAX_RECOMMENDED_PRIORITY + 500;
|
||||
}
|
||||
initDelegate: CoreInitDelegate, private localNotif: LocalNotifications, private appProvider: CoreAppProvider) {}
|
||||
|
||||
/**
|
||||
* Check if the app is running in a Linux environment.
|
||||
|
|
|
@ -29,8 +29,9 @@ export interface CoreInitHandler {
|
|||
*/
|
||||
@Injectable()
|
||||
export class CoreInitDelegate {
|
||||
DEFAULT_PRIORITY = 100; // Default priority for init processes.
|
||||
MAX_RECOMMENDED_PRIORITY = 600;
|
||||
public static DEFAULT_PRIORITY = 100; // Default priority for init processes.
|
||||
public static MAX_RECOMMENDED_PRIORITY = 600;
|
||||
|
||||
initProcesses = {};
|
||||
logger;
|
||||
readiness;
|
||||
|
@ -142,7 +143,7 @@ export class CoreInitDelegate {
|
|||
*/
|
||||
registerProcess(handler: CoreInitHandler) : void {
|
||||
if (typeof handler.priority == 'undefined') {
|
||||
handler.priority = this.DEFAULT_PRIORITY;
|
||||
handler.priority = CoreInitDelegate.DEFAULT_PRIORITY;
|
||||
}
|
||||
|
||||
if (typeof this.initProcesses[handler.name] != 'undefined') {
|
||||
|
|
|
@ -0,0 +1,176 @@
|
|||
// (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 { CoreConfigProvider } from './config';
|
||||
import { CoreFilepoolProvider } from './filepool';
|
||||
import { CoreInitHandler, CoreInitDelegate } from './init';
|
||||
import { CoreLocalNotificationsProvider } from './local-notifications';
|
||||
import { CoreLoggerProvider } from './logger';
|
||||
import { CoreSitesProvider } from './sites';
|
||||
import { CoreConfigConstants } from '../configconstants';
|
||||
|
||||
/**
|
||||
* Factory to handle app updates. This factory shouldn't be used outside of core.
|
||||
*
|
||||
* This service handles processes that need to be run when updating the app, like migrate Ionic 1 database data to Ionic 3.
|
||||
*/
|
||||
@Injectable()
|
||||
export class CoreUpdateManagerProvider implements CoreInitHandler {
|
||||
// Data for init delegate.
|
||||
public name = 'CoreUpdateManager';
|
||||
public priority = CoreInitDelegate.MAX_RECOMMENDED_PRIORITY + 300;
|
||||
public blocking = true;
|
||||
|
||||
protected VERSION_APPLIED = 'version_applied';
|
||||
protected logger;
|
||||
|
||||
constructor(logger: CoreLoggerProvider, private configProvider: CoreConfigProvider, private sitesProvider: CoreSitesProvider,
|
||||
private filepoolProvider: CoreFilepoolProvider, private notifProvider: CoreLocalNotificationsProvider) {
|
||||
this.logger = logger.getInstance('CoreUpdateManagerProvider');
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the app has been updated and performs the needed processes.
|
||||
* This function shouldn't be used outside of core.
|
||||
*
|
||||
* @return {Promise<any>} Promise resolved when the update process finishes.
|
||||
*/
|
||||
load() : Promise<any> {
|
||||
let promises = [],
|
||||
versionCode = CoreConfigConstants.versioncode;
|
||||
|
||||
return this.configProvider.get(this.VERSION_APPLIED, 0).then((versionApplied: number) => {
|
||||
// @todo: Migrate all data from ydn-db to SQLite if there is no versionApplied.
|
||||
|
||||
if (versionCode >= 2013 && versionApplied < 2013) {
|
||||
promises.push(this.migrateFileExtensions());
|
||||
}
|
||||
|
||||
if (versionCode >= 2017 && versionApplied < 2017) {
|
||||
promises.push(this.setCalendarDefaultNotifTime());
|
||||
promises.push(this.setSitesConfig());
|
||||
}
|
||||
|
||||
if (versionCode >= 2018 && versionApplied < 2018) {
|
||||
promises.push(this.adaptForumOfflineStores());
|
||||
}
|
||||
|
||||
return Promise.all(promises).then(() => {
|
||||
return this.configProvider.set(this.VERSION_APPLIED, versionCode);
|
||||
}).catch((error) => {
|
||||
this.logger.error(`Error applying update from ${versionApplied} to ${versionCode}`, error);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Migrates files filling extensions.
|
||||
*
|
||||
* @return {Promise<any>} Promise resolved when the site migration is finished.
|
||||
*/
|
||||
protected migrateFileExtensions() : Promise<any> {
|
||||
return this.sitesProvider.getSitesIds().then((sites) => {
|
||||
let promises = [];
|
||||
sites.forEach((siteId) => {
|
||||
promises.push(this.filepoolProvider.fillMissingExtensionInFiles(siteId));
|
||||
});
|
||||
promises.push(this.filepoolProvider.treatExtensionInQueue());
|
||||
return Promise.all(promises);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Calendar default notification time is configurable from version 3.2.1, and a new option "Default" is added.
|
||||
* All events that were configured to use the fixed default time should now be configured to use "Default" option.
|
||||
*
|
||||
* @return {Promise<any>} Promise resolved when the events are configured.
|
||||
*/
|
||||
protected setCalendarDefaultNotifTime() : Promise<any> {
|
||||
if (!this.notifProvider.isAvailable()) {
|
||||
// Local notifications not available, nothing to do.
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
// @todo: Implement it once Calendar addon is implemented.
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
/**
|
||||
* In version 3.2.1 we want the site config to be stored in each site if available.
|
||||
* Since it can be slow, we'll only block retrieving the config of current site, the rest will be in background.
|
||||
*
|
||||
* @return {Promise<any>} Promise resolved when the config is loaded for the current site (if any).
|
||||
*/
|
||||
protected setSitesConfig() : Promise<any> {
|
||||
return this.sitesProvider.getSitesIds().then((siteIds) => {
|
||||
|
||||
return this.sitesProvider.getStoredCurrentSiteId().catch(() => {
|
||||
// Error getting current site.
|
||||
}).then((currentSiteId) => {
|
||||
let promise;
|
||||
|
||||
// Load the config of current site first.
|
||||
if (currentSiteId) {
|
||||
promise = this.setSiteConfig(currentSiteId);
|
||||
} else {
|
||||
promise = Promise.resolve();
|
||||
}
|
||||
|
||||
// Load the config of rest of sites in background.
|
||||
siteIds.forEach((siteId) => {
|
||||
if (siteId != currentSiteId) {
|
||||
this.setSiteConfig(siteId);
|
||||
}
|
||||
});
|
||||
|
||||
return promise;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Store the config of a site.
|
||||
*
|
||||
* @param {String} siteId Site ID.
|
||||
* @return {Promise<any>} Promise resolved when the config is loaded for the site.
|
||||
*/
|
||||
protected setSiteConfig(siteId: string) : Promise<any> {
|
||||
return this.sitesProvider.getSite(siteId).then((site) => {
|
||||
if (site.getStoredConfig() || !site.wsAvailable('tool_mobile_get_config')) {
|
||||
// Site already has the config or it cannot be retrieved. Stop.
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the site config.
|
||||
return site.getConfig().then((config) => {
|
||||
return this.sitesProvider.addSite(
|
||||
site.getId(), site.getURL(), site.getToken(), site.getInfo(), site.getPrivateToken(), config);
|
||||
}).catch(() => {
|
||||
// Ignore errors.
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* The data stored for offline discussions and posts changed its format. Adapt the entries already stored.
|
||||
* Since it can be slow, we'll only block migrating the db of current site, the rest will be in background.
|
||||
*
|
||||
* @return {Promise<any>} Promise resolved when the db is migrated.
|
||||
*/
|
||||
protected adaptForumOfflineStores() : Promise<any> {
|
||||
// @todo: Implement it once Forum addon is implemented.
|
||||
return Promise.resolve();
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue