mirror of
https://github.com/lxsang/antos-frontend.git
synced 2024-12-27 01:38:21 +01:00
feat: use a separated setting file for each application instead of a single system setting files
This commit is contained in:
parent
4d59b104b9
commit
add5ef77c8
53
d.ts/antos.d.ts
vendored
53
d.ts/antos.d.ts
vendored
@ -1037,8 +1037,9 @@ declare namespace OS {
|
|||||||
* @param {string} path VFS path to the scheme file
|
* @param {string} path VFS path to the scheme file
|
||||||
* @param {BaseModel} app the target application
|
* @param {BaseModel} app the target application
|
||||||
* @param {(HTMLElement | string)} parent The parent HTML element where the application is rendered.
|
* @param {(HTMLElement | string)} parent The parent HTML element where the application is rendered.
|
||||||
|
* @return {Promise<any>} a promise object
|
||||||
*/
|
*/
|
||||||
function loadScheme(path: string, app: BaseModel, parent: HTMLElement | string): void;
|
function loadScheme(path: string, app: BaseModel, parent: HTMLElement | string): Promise<any>;
|
||||||
/**
|
/**
|
||||||
* Clear the current system theme
|
* Clear the current system theme
|
||||||
*
|
*
|
||||||
@ -2289,6 +2290,19 @@ declare namespace OS {
|
|||||||
* @returns {*}
|
* @returns {*}
|
||||||
*/
|
*/
|
||||||
function switcher(...args: string[]): any;
|
function switcher(...args: string[]): any;
|
||||||
|
/**
|
||||||
|
* A watcher is a Proxy wrapper to an object
|
||||||
|
*
|
||||||
|
* It is used to automatically detect changes in the
|
||||||
|
* target object and notify the change to a callback
|
||||||
|
* handler
|
||||||
|
*
|
||||||
|
* @export
|
||||||
|
* @param {Object} target object
|
||||||
|
* @param {(obj: Object, key: string, value: any, path: any[]) => void} callback function
|
||||||
|
* @returns {Proxy} the wrapper object
|
||||||
|
*/
|
||||||
|
function watcher(target: GenericObject<any>, callback: (obj: Object, key: any, value: any, path: any[]) => void): Object;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/// <reference types="jquery" />
|
/// <reference types="jquery" />
|
||||||
@ -2311,9 +2325,19 @@ declare namespace OS {
|
|||||||
*/
|
*/
|
||||||
abstract class BaseApplication extends BaseModel {
|
abstract class BaseApplication extends BaseModel {
|
||||||
/**
|
/**
|
||||||
* Placeholder of all settings specific to the application.
|
* Watcher of all settings specific to the application.
|
||||||
* The settings stored in this object will be saved to system
|
* The settings stored in this object will be saved to application folder
|
||||||
* setting when logout and can be reused in the next login session
|
* in JSON format as .settings.json and will be loaded automatically
|
||||||
|
* when application is initialized.
|
||||||
|
*
|
||||||
|
* This object is globally acessible to all processes of the same application
|
||||||
|
*
|
||||||
|
* @type {GenericObject<any>}
|
||||||
|
* @memberof BaseApplication
|
||||||
|
*/
|
||||||
|
static setting_wdg: GenericObject<any>;
|
||||||
|
/**
|
||||||
|
* Reference to per application setting i.e. setting_wdg
|
||||||
*
|
*
|
||||||
* @type {GenericObject<any>}
|
* @type {GenericObject<any>}
|
||||||
* @memberof BaseApplication
|
* @memberof BaseApplication
|
||||||
@ -2352,16 +2376,16 @@ declare namespace OS {
|
|||||||
* @returns {void}
|
* @returns {void}
|
||||||
* @memberof BaseApplication
|
* @memberof BaseApplication
|
||||||
*/
|
*/
|
||||||
init(): void;
|
init(): Promise<any>;
|
||||||
/**
|
/**
|
||||||
* Render the application UI by first loading its scheme
|
* Render the application UI by first loading its scheme
|
||||||
* and then mount this scheme to the DOM tree
|
* and then mount this scheme to the DOM tree
|
||||||
*
|
*
|
||||||
* @protected
|
* @protected
|
||||||
* @returns {void}
|
* @returns {Promise<any>}
|
||||||
* @memberof BaseApplication
|
* @memberof BaseApplication
|
||||||
*/
|
*/
|
||||||
protected loadScheme(): void;
|
protected loadScheme(): Promise<any>;
|
||||||
/**
|
/**
|
||||||
* API function to perform an heavy task.
|
* API function to perform an heavy task.
|
||||||
* This function will create a Task that is tracked by any
|
* This function will create a Task that is tracked by any
|
||||||
@ -2420,17 +2444,6 @@ declare namespace OS {
|
|||||||
* @memberof BaseApplication
|
* @memberof BaseApplication
|
||||||
*/
|
*/
|
||||||
protected applyAllSetting(): void;
|
protected applyAllSetting(): void;
|
||||||
/**
|
|
||||||
* Set a setting value to the application setting
|
|
||||||
* registry
|
|
||||||
*
|
|
||||||
* @protected
|
|
||||||
* @param {string} k setting name
|
|
||||||
* @param {*} v setting value
|
|
||||||
* @returns {void}
|
|
||||||
* @memberof BaseApplication
|
|
||||||
*/
|
|
||||||
protected registry(k: string, v: any): void;
|
|
||||||
/**
|
/**
|
||||||
* Show the appliation
|
* Show the appliation
|
||||||
*
|
*
|
||||||
@ -2803,10 +2816,10 @@ declare namespace OS {
|
|||||||
*
|
*
|
||||||
* @protected
|
* @protected
|
||||||
* @param {string} p VFS path to the UI scheme definition
|
* @param {string} p VFS path to the UI scheme definition
|
||||||
* @returns {void}
|
* @returns {Promise<any>}
|
||||||
* @memberof BaseModel
|
* @memberof BaseModel
|
||||||
*/
|
*/
|
||||||
protected render(p: string): void;
|
protected render(p: string): Promise<any>;
|
||||||
/**
|
/**
|
||||||
* Exit the model
|
* Exit the model
|
||||||
*
|
*
|
||||||
|
@ -35,9 +35,21 @@ namespace OS {
|
|||||||
*/
|
*/
|
||||||
export abstract class BaseApplication extends BaseModel {
|
export abstract class BaseApplication extends BaseModel {
|
||||||
/**
|
/**
|
||||||
* Placeholder of all settings specific to the application.
|
* Watcher of all settings specific to the application.
|
||||||
* The settings stored in this object will be saved to system
|
* The settings stored in this object will be saved to application folder
|
||||||
* setting when logout and can be reused in the next login session
|
* in JSON format as .settings.json and will be loaded automatically
|
||||||
|
* when application is initialized.
|
||||||
|
*
|
||||||
|
* This object is globally acessible to all processes of the same application
|
||||||
|
*
|
||||||
|
* @type {GenericObject<any>}
|
||||||
|
* @memberof BaseApplication
|
||||||
|
*/
|
||||||
|
static setting_wdg: GenericObject<any>;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reference to per application setting i.e. setting_wdg
|
||||||
*
|
*
|
||||||
* @type {GenericObject<any>}
|
* @type {GenericObject<any>}
|
||||||
* @memberof BaseApplication
|
* @memberof BaseApplication
|
||||||
@ -69,10 +81,7 @@ namespace OS {
|
|||||||
*/
|
*/
|
||||||
constructor(name: string, args: AppArgumentsType[]) {
|
constructor(name: string, args: AppArgumentsType[]) {
|
||||||
super(name, args);
|
super(name, args);
|
||||||
if (!setting.applications[this.name]) {
|
this.setting = (this.constructor as any).setting_wdg;
|
||||||
setting.applications[this.name] = {};
|
|
||||||
}
|
|
||||||
this.setting = setting.applications[this.name];
|
|
||||||
this.keycomb = {};
|
this.keycomb = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -87,7 +96,9 @@ namespace OS {
|
|||||||
* @returns {void}
|
* @returns {void}
|
||||||
* @memberof BaseApplication
|
* @memberof BaseApplication
|
||||||
*/
|
*/
|
||||||
init(): void {
|
init(): Promise<any> {
|
||||||
|
return new Promise(async (ok, nok) =>{
|
||||||
|
try {
|
||||||
this.off("*");
|
this.off("*");
|
||||||
this.on("exit", () => this.quit(false));
|
this.on("exit", () => this.quit(false));
|
||||||
// first register some base event to the app
|
// first register some base event to the app
|
||||||
@ -123,7 +134,14 @@ namespace OS {
|
|||||||
});
|
});
|
||||||
|
|
||||||
this.updateLocale(this.systemsetting.system.locale);
|
this.updateLocale(this.systemsetting.system.locale);
|
||||||
return this.loadScheme();
|
await this.loadScheme();
|
||||||
|
this.applyAllSetting();
|
||||||
|
}
|
||||||
|
catch(e)
|
||||||
|
{
|
||||||
|
nok(__e(e));
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -131,10 +149,10 @@ namespace OS {
|
|||||||
* and then mount this scheme to the DOM tree
|
* and then mount this scheme to the DOM tree
|
||||||
*
|
*
|
||||||
* @protected
|
* @protected
|
||||||
* @returns {void}
|
* @returns {Promise<any>}
|
||||||
* @memberof BaseApplication
|
* @memberof BaseApplication
|
||||||
*/
|
*/
|
||||||
protected loadScheme(): void {
|
protected loadScheme(): Promise<any> {
|
||||||
//now load the scheme
|
//now load the scheme
|
||||||
const path = `${this.meta().path}/scheme.html`;
|
const path = `${this.meta().path}/scheme.html`;
|
||||||
return this.render(path);
|
return this.render(path);
|
||||||
@ -270,21 +288,6 @@ namespace OS {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Set a setting value to the application setting
|
|
||||||
* registry
|
|
||||||
*
|
|
||||||
* @protected
|
|
||||||
* @param {string} k setting name
|
|
||||||
* @param {*} v setting value
|
|
||||||
* @returns {void}
|
|
||||||
* @memberof BaseApplication
|
|
||||||
*/
|
|
||||||
protected registry(k: string, v: any): void {
|
|
||||||
this.setting[k] = v;
|
|
||||||
return this.publish("appregistry", k);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Show the appliation
|
* Show the appliation
|
||||||
*
|
*
|
||||||
|
@ -288,7 +288,7 @@ namespace OS {
|
|||||||
return GUI.htmlToScheme(this.markup, this, this.host);
|
return GUI.htmlToScheme(this.markup, this, this.host);
|
||||||
} else {
|
} else {
|
||||||
// a file handle
|
// a file handle
|
||||||
return this.render(this.markup.path);
|
this.render(this.markup.path);
|
||||||
}
|
}
|
||||||
} else if (
|
} else if (
|
||||||
this.constructor.scheme
|
this.constructor.scheme
|
||||||
|
@ -322,10 +322,10 @@ namespace OS {
|
|||||||
*
|
*
|
||||||
* @protected
|
* @protected
|
||||||
* @param {string} p VFS path to the UI scheme definition
|
* @param {string} p VFS path to the UI scheme definition
|
||||||
* @returns {void}
|
* @returns {Promise<any>}
|
||||||
* @memberof BaseModel
|
* @memberof BaseModel
|
||||||
*/
|
*/
|
||||||
protected render(p: string): void {
|
protected render(p: string): Promise<any> {
|
||||||
return GUI.loadScheme(p, this, this.host);
|
return GUI.loadScheme(p, this, this.host);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1234,8 +1234,10 @@ namespace OS {
|
|||||||
* @returns {Promise<any>} a promise on the result data
|
* @returns {Promise<any>} a promise on the result data
|
||||||
*/
|
*/
|
||||||
export function post(p: string, d: any): Promise<any> {
|
export function post(p: string, d: any): Promise<any> {
|
||||||
return API.Task(function (resolve, reject) {
|
return API.Task(async (resolve, reject) => {
|
||||||
return $.ajax({
|
try
|
||||||
|
{
|
||||||
|
$.ajax({
|
||||||
type: "POST",
|
type: "POST",
|
||||||
url: p,
|
url: p,
|
||||||
contentType: "application/json",
|
contentType: "application/json",
|
||||||
@ -1256,8 +1258,13 @@ namespace OS {
|
|||||||
return resolve(data);
|
return resolve(data);
|
||||||
})
|
})
|
||||||
.fail(function (j, s, e) {
|
.fail(function (j, s, e) {
|
||||||
return reject(API.throwe(s));
|
reject(e);
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
catch(e)
|
||||||
|
{
|
||||||
|
reject(__e(e));
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1776,5 +1783,38 @@ namespace OS {
|
|||||||
});
|
});
|
||||||
return o;
|
return o;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A watcher is a Proxy wrapper to an object
|
||||||
|
*
|
||||||
|
* It is used to automatically detect changes in the
|
||||||
|
* target object and notify the change to a callback
|
||||||
|
* handler
|
||||||
|
*
|
||||||
|
* @export
|
||||||
|
* @param {Object} target object
|
||||||
|
* @param {(obj: Object, key: string, value: any, path: any[]) => void} callback function
|
||||||
|
* @returns {Proxy} the wrapper object
|
||||||
|
*/
|
||||||
|
export function watcher(target: GenericObject<any>, callback: (obj: Object, key: any, value: any, path:any[]) => void): Object
|
||||||
|
{
|
||||||
|
const create_handle_for = (path:any[]) => {
|
||||||
|
return {
|
||||||
|
get: (obj: Object, key: any) => {
|
||||||
|
if(typeof obj[key] === "object" && obj[key] !== null) {
|
||||||
|
return new Proxy(obj[key], create_handle_for(path.concat(key)));
|
||||||
|
}
|
||||||
|
return obj[key];
|
||||||
|
},
|
||||||
|
set: (obj: Object, prop:any, value: any) => {
|
||||||
|
obj[prop] = value;
|
||||||
|
callback(obj, prop, value, path);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return new Proxy(target, create_handle_for([]));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -180,22 +180,23 @@ namespace OS {
|
|||||||
* @param {string} path VFS path to the scheme file
|
* @param {string} path VFS path to the scheme file
|
||||||
* @param {BaseModel} app the target application
|
* @param {BaseModel} app the target application
|
||||||
* @param {(HTMLElement | string)} parent The parent HTML element where the application is rendered.
|
* @param {(HTMLElement | string)} parent The parent HTML element where the application is rendered.
|
||||||
|
* @return {Promise<any>} a promise object
|
||||||
*/
|
*/
|
||||||
export function loadScheme(
|
export function loadScheme(
|
||||||
path: string,
|
path: string,
|
||||||
app: BaseModel,
|
app: BaseModel,
|
||||||
parent: HTMLElement | string
|
parent: HTMLElement | string
|
||||||
): void {
|
): Promise<any> {
|
||||||
path.asFileHandle()
|
return new Promise(async (ok,nok) =>{
|
||||||
.read()
|
try {
|
||||||
.then(function (x) {
|
const x = await path.asFileHandle().read();
|
||||||
if (!x) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
htmlToScheme(x, app, parent);
|
htmlToScheme(x, app, parent);
|
||||||
})
|
ok(true);
|
||||||
.catch((e) => {
|
}
|
||||||
announcer.oserror(__("Cannot load scheme: {0}", path), e);
|
catch(e)
|
||||||
|
{
|
||||||
|
nok(__e(e));
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -724,6 +725,45 @@ namespace OS {
|
|||||||
e);
|
e);
|
||||||
return reject(e);
|
return reject(e);
|
||||||
}
|
}
|
||||||
|
const mt = application[app].meta;
|
||||||
|
// load application setting if any
|
||||||
|
let settings = {};
|
||||||
|
try
|
||||||
|
{
|
||||||
|
console.log("load setting for", app);
|
||||||
|
if(mt.path.asFileHandle().protocol === "home")
|
||||||
|
{
|
||||||
|
settings = await `${mt.path}/.settings.json`.asFileHandle().read("json");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// system package
|
||||||
|
settings = await `home:///.antos/settings/${app}.json`.asFileHandle().read("json");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch(_)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
application[app].setting_wdg = API.watcher(settings, (o,k,v,p) => {
|
||||||
|
console.log("Changed detected", o, k,v, p);
|
||||||
|
let key = k;
|
||||||
|
if(p.length > 0)
|
||||||
|
{
|
||||||
|
key = p[0];
|
||||||
|
}
|
||||||
|
const data: API.AnnouncementDataType<any> = {} as API.AnnouncementDataType<any>;
|
||||||
|
data.icon = undefined;
|
||||||
|
if (mt && mt.icon) {
|
||||||
|
data.icon = `${mt.path}/${mt.icon}`;
|
||||||
|
}
|
||||||
|
data.id = 0;
|
||||||
|
data.name = app;
|
||||||
|
data.message = key;
|
||||||
|
data.iconclass = mt?mt.iconclass:undefined;
|
||||||
|
data.u_data = undefined;
|
||||||
|
console.log(data);
|
||||||
|
return announcer.trigger("appregistry", data);
|
||||||
|
});
|
||||||
const p = await PM.createProcess(
|
const p = await PM.createProcess(
|
||||||
app,
|
app,
|
||||||
application[app],
|
application[app],
|
||||||
|
@ -136,6 +136,25 @@ namespace OS {
|
|||||||
if (i >= 0) {
|
if (i >= 0) {
|
||||||
if (application[app.name].type === ModelType.Application) {
|
if (application[app.name].type === ModelType.Application) {
|
||||||
GUI.undock(app as application.BaseApplication);
|
GUI.undock(app as application.BaseApplication);
|
||||||
|
// save setting file if any
|
||||||
|
if(PM.processes[app.name].length == 1)
|
||||||
|
{
|
||||||
|
const app_class = application[app.name] as typeof OS.application.BaseApplication;
|
||||||
|
let file = `${app_class.meta.path}/.settings.json`.asFileHandle();
|
||||||
|
if(file.protocol !== "home")
|
||||||
|
{
|
||||||
|
file = `home:///.antos/settings/${app.name}.json`.asFileHandle();
|
||||||
|
}
|
||||||
|
file.cache = app_class.setting_wdg;
|
||||||
|
//file.cache = JSON.stringify(app_class.setting_wdg, undefined, 4);
|
||||||
|
console.log("save setting file");
|
||||||
|
file
|
||||||
|
.write("object")
|
||||||
|
.catch((e) =>{
|
||||||
|
return announcer.osinfo(
|
||||||
|
__("Unable to save settings for application {0}: {1}", app.name, e.toString()));
|
||||||
|
});
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
GUI.detachservice(app as application.BaseService);
|
GUI.detachservice(app as application.BaseService);
|
||||||
}
|
}
|
||||||
|
@ -398,7 +398,7 @@ namespace OS {
|
|||||||
*/
|
*/
|
||||||
export function resetSetting(): void {
|
export function resetSetting(): void {
|
||||||
setting.desktop = {
|
setting.desktop = {
|
||||||
path: "home://.desktop",
|
path: "home://.antos/desktop",
|
||||||
menu: [],
|
menu: [],
|
||||||
showhidden: false,
|
showhidden: false,
|
||||||
};
|
};
|
||||||
@ -476,13 +476,13 @@ namespace OS {
|
|||||||
menu: [],
|
menu: [],
|
||||||
packages: {},
|
packages: {},
|
||||||
pkgpaths: {
|
pkgpaths: {
|
||||||
user: "home://.packages",
|
user: "home://.antos/packages",
|
||||||
system: "os://packages",
|
system: "os://packages",
|
||||||
},
|
},
|
||||||
repositories: [],
|
repositories: [],
|
||||||
startup: {
|
startup: {
|
||||||
apps: [],
|
apps: [],
|
||||||
services: ["Syslog/PushNotification", "Syslog/Calendar"],
|
services: ["SystemServices/PushNotification", "SystemServices/Calendar"],
|
||||||
pinned: [],
|
pinned: [],
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -564,13 +564,13 @@ namespace OS {
|
|||||||
switch (data.dataid) {
|
switch (data.dataid) {
|
||||||
case `${this.name}-hidden`:
|
case `${this.name}-hidden`:
|
||||||
//@.view.set "showhidden", e.item.data.checked
|
//@.view.set "showhidden", e.item.data.checked
|
||||||
return this.registry("showhidden", data.checked);
|
this.setting.showhidden = data.checked;
|
||||||
//@.setting.showhidden = e.item.data.checked
|
//@.setting.showhidden = e.item.data.checked
|
||||||
case `${this.name}-refresh`:
|
case `${this.name}-refresh`:
|
||||||
this.view.path = this.currdir.path;
|
this.view.path = this.currdir.path;
|
||||||
return;
|
return;
|
||||||
case `${this.name}-nav`:
|
case `${this.name}-nav`:
|
||||||
return this.registry("nav", data.checked);
|
this.setting.nav = data.checked;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//@setting.nav = e.item.data.checked
|
//@setting.nav = e.item.data.checked
|
||||||
|
Loading…
Reference in New Issue
Block a user