Support pinned app in dock + remove old pinned apps UI

This commit is contained in:
DanyLE 2022-12-15 17:01:16 +01:00 committed by Dany LE
parent b5863702cb
commit 3c25d8b52e
10 changed files with 250 additions and 152 deletions

48
d.ts/antos.d.ts vendored
View File

@ -4761,9 +4761,9 @@ declare namespace OS {
set text(v: string | FormattedString); set text(v: string | FormattedString);
get text(): string | FormattedString; get text(): string | FormattedString;
/** /**
* Setter: Set the text of the button * Setter: Set the text of the label
* *
* Getter: Get the current button test * Getter: Get the current label test
* *
* @memberof InputTag * @memberof InputTag
*/ */
@ -4845,7 +4845,7 @@ declare namespace OS {
*/ */
protected init(): void; protected init(): void;
/** /**
* Re-calibrate the button, do nothing in this tag * Re-calibrate, do nothing in this tag
* *
* @protected * @protected
* @memberof InputTag * @memberof InputTag
@ -4859,7 +4859,7 @@ declare namespace OS {
*/ */
reload(d?: any): void; reload(d?: any): void;
/** /**
* Button layout definition * Input layout definition
* *
* @protected * @protected
* @returns {TagLayoutType[]} * @returns {TagLayoutType[]}
@ -6401,13 +6401,6 @@ declare namespace OS {
* @memberof SystemPanelTag * @memberof SystemPanelTag
*/ */
calibrate(): void; calibrate(): void;
/**
* Refresh the pinned applications menu
*
* @private
* @memberof SystemPanelTag
*/
private RefreshPinnedApp;
/** /**
* Check if the loading tasks ended, * Check if the loading tasks ended,
* if it the case, stop the animation * if it the case, stop the animation
@ -8025,6 +8018,13 @@ declare namespace OS {
* @memberof StackMenuTag * @memberof StackMenuTag
*/ */
set onmenuselect(v: TagEventCallback<StackMenuEventData>); set onmenuselect(v: TagEventCallback<StackMenuEventData>);
/**
* Hide the current menu. This function is called
* only if the current menu is context menu
*
* @memberof StackMenuTag
*/
hide(): void;
/** /**
* Show the current menu. This function is called * Show the current menu. This function is called
* only if the current menu is a context menu * only if the current menu is a context menu
@ -8560,7 +8560,7 @@ declare namespace OS {
* @type {application.BaseApplication} * @type {application.BaseApplication}
* @memberof AppDockItemType * @memberof AppDockItemType
*/ */
app: application.BaseApplication; app?: application.BaseApplication;
/** /**
* Reference to the DOM element of * Reference to the DOM element of
* the owner dock item * the owner dock item
@ -8667,6 +8667,17 @@ declare namespace OS {
* @memberof AppDockTag * @memberof AppDockTag
*/ */
get selectedItem(): AppDockItemType; get selectedItem(): AppDockItemType;
/**
* Add a button to the dock
*
* @private
* @param {string} [name] associated application name
* @param {AppDockItemType} [item] dock item
* @param {boolean} [pinned] the button is pinned to the dock ?
* @memberof AppDockTag
*/
private add_button;
private update_button;
/** /**
* When a new application process is created, this function * When a new application process is created, this function
* will be called to add new application entry to the dock. * will be called to add new application entry to the dock.
@ -8677,6 +8688,12 @@ declare namespace OS {
* @memberof AppDockTag * @memberof AppDockTag
*/ */
addapp(item: AppDockItemType): void; addapp(item: AppDockItemType): void;
/**
* Handle the application selection action
*
* @private
* @memberof AppDockTag
*/
private handleAppSelect; private handleAppSelect;
/** /**
* Delete and application entry from the dock. * Delete and application entry from the dock.
@ -8694,6 +8711,13 @@ declare namespace OS {
* @memberof AppDockTag * @memberof AppDockTag
*/ */
protected mount(): void; protected mount(): void;
/**
* refresh the pinned application list
*
* @private
* @memberof AppDockTag
*/
private refresh_pinned_app;
} }
} }
} }

View File

@ -644,10 +644,7 @@ namespace OS {
const data = { const data = {
icon: null, icon: null,
iconclass: meta.iconclass || "", iconclass: meta.iconclass || "",
app, app
onbtclick() {
return app.toggle();
},
}; };
// TODO: this path is not good, need to create a blob of it // TODO: this path is not good, need to create a blob of it
if (meta.icon) { if (meta.icon) {

View File

@ -15,7 +15,7 @@ namespace OS {
* @type {application.BaseApplication} * @type {application.BaseApplication}
* @memberof AppDockItemType * @memberof AppDockItemType
*/ */
app: application.BaseApplication; app?: application.BaseApplication;
/** /**
* Reference to the DOM element of * Reference to the DOM element of
@ -94,9 +94,6 @@ namespace OS {
break; break;
} }
} }
if (i !== -1) {
$(this.items[i].domel).attr("tooltip", `ct:${app.title()}`);
}
} }
/** /**
@ -186,6 +183,62 @@ namespace OS {
return this._selectedItem; return this._selectedItem;
} }
/**
* Add a button to the dock
*
* @private
* @param {string} [name] associated application name
* @param {AppDockItemType} [item] dock item
* @param {boolean} [pinned] the button is pinned to the dock ?
* @memberof AppDockTag
*/
private add_button(name:string, item: AppDockItemType, pinned: boolean = false): void
{
const collection = $(this).children().filter((i, e) => {
return (e as ButtonTag).data.name == name;
});
if(collection.length > 0)
{
(collection[0] as ButtonTag).data.pinned = true;
item.domel = collection[0] as ButtonTag;
return;
}
const el = $("<afx-button>");
const bt = el[0] as ButtonTag;
el.appendTo(this);
el[0].uify(this.observable);
bt.set(item);
bt.data = {
name: name,
pinned: pinned
};
item.domel = bt;
bt.onbtclick = (e) => {
e.data.stopPropagation();
this.handleAppSelect(bt);
};
}
private update_button(el: ButtonTag): void
{
const collection = this.items.filter(it => it.app.name == el.data.name);
if(collection.length == 1)
{
$(el).removeClass("plural");
}
if(collection.length == 0)
{
if(el.data.pinned)
{
$(el).removeClass();
}
else
{
$(el).remove();
}
}
}
/** /**
* When a new application process is created, this function * When a new application process is created, this function
* will be called to add new application entry to the dock. * will be called to add new application entry to the dock.
@ -200,17 +253,7 @@ namespace OS {
let bt = undefined; let bt = undefined;
if(collection.length == 0) if(collection.length == 0)
{ {
const el = $("<afx-button>"); this.add_button(item.app.name, item);
bt = el[0] as ButtonTag;
el.appendTo(this);
el[0].uify(this.observable);
bt.set(item);
bt.data = item.app.name;
item.domel = bt;
bt.onbtclick = (e) => {
e.data.stopPropagation();
this.handleAppSelect(bt);
};
} }
else else
{ {
@ -222,40 +265,48 @@ namespace OS {
this.selectedApp = item.app; this.selectedApp = item.app;
} }
private handleAppSelect(bt: ButtonTag) /**
{ * Handle the application selection action
const name = bt.data as any as string; *
const collection = this.items.filter(it => it.app.name == name); * @private
if(collection.length == 0) * @memberof AppDockTag
*/
private handleAppSelect(bt: ButtonTag)
{ {
return; const name = bt.data.name as string;
const collection = this.items.filter(it => it.app.name == name);
const ctxmenu = $("#contextmenu")[0] as tag.StackMenuTag;
ctxmenu.hide();
if(collection.length == 0)
{
GUI.launch(name, []);
return;
}
if(collection.length == 1)
{
collection[0].app.trigger("focus");
return;
}
// show the context menu containning a list of application to select
const menu_data = collection.map(e => {
return {
text: (e.app.scheme as WindowTag).apptitle,
icon: e.icon,
iconclass: e.iconclass,
app: e.app
};
});
const offset = $(bt).offset();
ctxmenu.nodes = menu_data;
$(ctxmenu)
.css("left", offset.left)
.css("bottom", $(this).height());
ctxmenu.onmenuselect = (e) =>
{
e.data.item.data.app.show();
}
ctxmenu.show();
} }
if(collection.length == 1)
{
collection[0].app.trigger("focus");
return;
}
// show the context menu containning a list of application to select
const menu_data = collection.map(e => {
return {
text: (e.app.scheme as WindowTag).apptitle,
icon: e.icon,
iconclass: e.iconclass,
app: e.app
};
});
const ctxmenu = $("#contextmenu")[0] as tag.StackMenuTag;
const offset = $(bt).offset();
ctxmenu.nodes = menu_data;
$(ctxmenu)
.css("left", offset.left)
.css("bottom", $(this).height());
ctxmenu.onmenuselect = (e) =>
{
e.data.item.data.app.show();
}
ctxmenu.show();
}
/** /**
* Delete and application entry from the dock. * Delete and application entry from the dock.
@ -278,18 +329,10 @@ namespace OS {
if (i !== -1) { if (i !== -1) {
const appName = this.items[i].app.name; const appName = this.items[i].app.name;
const el = this.items[i].domel; const el = this.items[i].domel as ButtonTag;
delete this.items[i].app; delete this.items[i].app;
this.items.splice(i, 1); this.items.splice(i, 1);
const collection = this.items.filter(it => it.app.name == appName); this.update_button(el);
if(collection.length == 1)
{
$(el).removeClass("plural");
}
if(collection.length == 0)
{
$(el).remove();
}
} }
} }
@ -307,7 +350,7 @@ namespace OS {
const bt = ($(e.target).closest( const bt = ($(e.target).closest(
"afx-button" "afx-button"
)[0] as any) as ButtonTag; )[0] as any) as ButtonTag;
const name = bt.data as any; const name = bt.data.name as string;
const collection = this.items.filter(it => it.app.name == name); const collection = this.items.filter(it => it.app.name == name);
m.nodes = [ m.nodes = [
{ text: "__(New window)", dataid: "new" }, { text: "__(New window)", dataid: "new" },
@ -317,7 +360,7 @@ namespace OS {
m.onmenuselect = function (evt) { m.onmenuselect = function (evt) {
switch (evt.data.item.data.dataid) { switch (evt.data.item.data.dataid) {
case "new": case "new":
GUI.launch(bt.data as string, []); GUI.launch(bt.data.name as string, []);
break; break;
case "hide": case "hide":
collection.forEach((el,_) => el.app.hide()); collection.forEach((el,_) => el.app.hide());
@ -329,7 +372,11 @@ namespace OS {
break; break;
} }
}; };
return m.show(e); const offset = $(bt).offset();
$(m)
.css("left", offset.left)
.css("bottom", $(this).height());
return m.show();
}; };
announcer.trigger("sysdockloaded", undefined); announcer.trigger("sysdockloaded", undefined);
GUI.bindKey("CTRL-ALT-2", (e) =>{ GUI.bindKey("CTRL-ALT-2", (e) =>{
@ -383,6 +430,44 @@ namespace OS {
$(this).on("wheel", (evt)=>{ $(this).on("wheel", (evt)=>{
(this as any).scrollLeft += (evt.originalEvent as WheelEvent).deltaY; (this as any).scrollLeft += (evt.originalEvent as WheelEvent).deltaY;
}); });
announcer.on("app-pinned", (_) => {
this.refresh_pinned_app();
});
this.refresh_pinned_app();
}
/**
* refresh the pinned application list
*
* @private
* @memberof AppDockTag
*/
private refresh_pinned_app(): void
{
if(!setting.system.startup.pinned)
return;
// unpin all application on the dock
$(this).children().each((i,e) => {
(e as ButtonTag).data.pinned = false;
});
// pin all setting application on the dock
setting.system.startup.pinned
.filter((el) =>{
const app = setting.system.packages[el];
return app && app.app
})
.forEach((name) => {
const app = setting.system.packages[name];
const item = {
icon: app.icon,
iconclass: app.iconclass,
app: undefined
};
this.add_button(name, item, true);
});
// update to remove the button
$(this).children().each((i,e) => {
this.update_button(e as ButtonTag);
});
} }
} }
define("afx-apps-dock", AppDockTag); define("afx-apps-dock", AppDockTag);

View File

@ -482,7 +482,24 @@ namespace OS {
set onmenuselect(v: TagEventCallback<StackMenuEventData>) { set onmenuselect(v: TagEventCallback<StackMenuEventData>) {
this._onmenuselect = v; this._onmenuselect = v;
} }
/**
* Hide the current menu. This function is called
* only if the current menu is context menu
*
* @memberof StackMenuTag
*/
hide(): void
{
if (!this.context) {
return;
}
$(this)
.css("bottom", "unset")
.css("top", "unset")
.css("left", "unset")
.css("right", "unset")
.hide();
}
/** /**
* Show the current menu. This function is called * Show the current menu. This function is called
* only if the current menu is a context menu * only if the current menu is a context menu
@ -505,7 +522,9 @@ namespace OS {
$(this) $(this)
.css("top", top + "px") .css("top", top + "px")
.css("left", left + "px"); .css("left", left + "px")
.css("bottom", "unset")
.css("right", "unset");
} }
const dropoff = (e) => { const dropoff = (e) => {
@ -517,12 +536,7 @@ namespace OS {
{ {
return; return;
} }
$(this) this.hide();
.css("bottom", "unset")
.css("top", "unset")
.css("left", "unset")
.css("right", "unset")
.hide();
$(document).off("click", dropoff); $(document).off("click", dropoff);
}; };

View File

@ -206,15 +206,10 @@ namespace OS {
ref: "panel", ref: "panel",
children: [ children: [
{ {
el: "afx-menu", el: "afx-button",
ref: "osmenu", ref: "osmenu",
class: "afx-panel-os-menu", class: "afx-panel-os-menu",
}, },
{
el: "afx-menu",
ref: "pinned",
class: "afx-panel-os-pinned-app",
},
{ {
el: "afx-apps-dock", el: "afx-apps-dock",
ref: "sysdock", ref: "sysdock",
@ -382,34 +377,6 @@ namespace OS {
}px`; }px`;
} }
/**
* Refresh the pinned applications menu
*
* @private
* @memberof SystemPanelTag
*/
private RefreshPinnedApp(): void
{
if(!setting.system.startup.pinned)
return;
(this.refs.pinned as GUI.tag.MenuTag).items =
setting.system.startup.pinned
.filter((el) =>{
const app = setting.system.packages[el];
return app && app.app
})
.map((name) => {
const app = setting.system.packages[name];
return {
icon: app.icon,
iconclass: app.iconclass,
app: app.app,
tooltip: `cb:${app.name}`
};
});
}
/** /**
* Check if the loading tasks ended, * Check if the loading tasks ended,
* if it the case, stop the animation * if it the case, stop the animation
@ -434,7 +401,7 @@ namespace OS {
* @memberof SystemPanelTag * @memberof SystemPanelTag
*/ */
protected mount(): void { protected mount(): void {
(this.refs.osmenu as MenuTag).items = [this._osmenu]; (this.refs.osmenu as ButtonTag).set(this._osmenu);
this._cb = (e) => { this._cb = (e) => {
if ( if (
!$(e.target).closest($(this.refs.overlay)).length && !$(e.target).closest($(this.refs.overlay)).length &&
@ -468,7 +435,7 @@ namespace OS {
return Ant.OS.exit(); return Ant.OS.exit();
}, },
}); });
(this.refs.osmenu as MenuTag).onmenuselect = (e) => { (this.refs.osmenu as ButtonTag).onbtclick = (e) => {
if($(this.refs.overlay).is(":hidden")) if($(this.refs.overlay).is(":hidden"))
{ {
this.toggle(true); this.toggle(true);
@ -511,19 +478,9 @@ namespace OS {
}; };
$(this.refs.overlay) $(this.refs.overlay)
.hide(); .hide();
(this.refs.pinned as GUI.tag.MenuTag).onmenuselect = (e) => { this.refs.osmenu.contextmenuHandle = (e, m) => { };
const app = e.data.item.data.app; this.refs.systray.contextmenuHandle = (e, m) => { };
if(!app)
return;
GUI.launch(app, []);
};
this.refs.osmenu.contextmenuHandle = (e, m) => { }
this.refs.systray.contextmenuHandle = (e, m) => { }
this.refs.pinned.contextmenuHandle = (e, m) => { }
this.refs.panel.contextmenuHandle = (e, m) => { }; this.refs.panel.contextmenuHandle = (e, m) => { };
announcer.on("app-pinned", (_) => {
this.RefreshPinnedApp();
});
announcer.on("loading", (o: API.AnnouncementDataType<number>) => { announcer.on("loading", (o: API.AnnouncementDataType<number>) => {
if(o.u_data != 0) if(o.u_data != 0)
{ {
@ -549,7 +506,6 @@ namespace OS {
announcer.on("desktopresize", (e) => { announcer.on("desktopresize", (e) => {
this.calibrate(); this.calibrate();
}); });
this.RefreshPinnedApp();
Ant.OS.announcer.trigger("syspanelloaded", undefined); Ant.OS.announcer.trigger("syspanelloaded", undefined);
} }
} }

View File

@ -9,11 +9,18 @@ afx-apps-dock{
box-shadow: none; box-shadow: none;
} }
afx-apps-dock afx-button > button:hover {
background-color: #3f3e3e;
}
afx-apps-dock afx-button.plural > button:hover
{
border-top: 3px double #646363;
}
afx-apps-dock afx-button.selected > button { afx-apps-dock afx-button.selected > button {
background-color: #464646; background-color: #464646;
color: white; color: white;
border: 0; border: 0;
border-bottom: 3px solid #bb86fc; border-bottom: 2px solid #bb86fc;
} }
afx-apps-dock afx-button.plural.selected > button { afx-apps-dock afx-button.plural.selected > button {
border-top: 3px double #646363; border-top: 3px double #646363;

View File

@ -4,14 +4,19 @@ afx-sys-panel > div{
box-shadow: none; box-shadow: none;
} }
afx-sys-panel .afx-panel-os-menu li afx-sys-panel .afx-panel-os-menu button
{
background-color: #e7414d;
border-radius: 0;
border: 0;
}
afx-sys-panel .afx-panel-os-menu button .label-text
{ {
font-weight: bold; font-weight: bold;
background-color: #e7414d;
border-top-right-radius: 9px;
border-bottom-right-radius: 9px;
} }
afx-sys-panel .afx-panel-os-menu a {
afx-sys-panel .afx-panel-os-menu {
color: white; color: white;
} }

View File

@ -8,11 +8,18 @@ afx-apps-dock{
border-right:1px solid #a6a6a6; border-right:1px solid #a6a6a6;
box-shadow: none; box-shadow: none;
} }
afx-apps-dock afx-button > button:hover {
background-color: #cecece;
}
afx-apps-dock afx-button.plural > button:hover
{
border-top: 3px double #a6a6a6;
}
afx-apps-dock afx-button.selected > button { afx-apps-dock afx-button.selected > button {
background-color: #2786F3; background-color: #2786F3;
color: white; color: white;
border: 0; border: 0;
border-bottom: 3px solid salmon; border-bottom: 2px solid salmon;
} }
afx-apps-dock afx-button.plural.selected > button { afx-apps-dock afx-button.plural.selected > button {

View File

@ -3,15 +3,19 @@ afx-sys-panel > div{
border-top: 1px solid #9c9C9C; border-top: 1px solid #9c9C9C;
box-shadow:none; box-shadow:none;
} }
afx-sys-panel .afx-panel-os-menu button
{
background-color: #e7414d;
border-radius: 0;
border: 0;
}
afx-sys-panel .afx-panel-os-menu li afx-sys-panel .afx-panel-os-menu button .label-text
{ {
font-weight: bold; font-weight: bold;
background-color: #e7414d;
border-top-right-radius: 9px;
border-bottom-right-radius: 9px;
} }
afx-sys-panel .afx-panel-os-menu a {
afx-sys-panel .afx-panel-os-menu {
color: white; color: white;
} }
@ -96,7 +100,7 @@ afx-sys-panel div[data-id="searchicon"]:before{
} }
afx-sys-panel input{ afx-sys-panel input{
border:0; border:0;
height: 25px; height: 30px;
color:#afafaf; color:#afafaf;
font-size: 16px; font-size: 16px;
background-color: transparent; background-color: transparent;

View File

@ -15,6 +15,11 @@ afx-sys-panel > div{
height: 35px; height: 35px;
} }
afx-sys-panel afx-apps-dock
{
flex:1;
}
afx-sys-panel afx-overlay afx-sys-panel afx-overlay
{ {
bottom: 35px; bottom: 35px;
@ -68,17 +73,11 @@ afx-sys-panel > div.loading::before {
afx-sys-panel .afx-panel-os-menu { afx-sys-panel .afx-panel-os-menu {
padding:0; padding:0;
margin: 0; margin: 0;
margin-right: 5px;
} }
afx-sys-panel .afx-panel-os-stray{ afx-sys-panel .afx-panel-os-stray{
position: relative; position: relative;
} }
afx-sys-panel .afx-panel-os-pinned-app afx-menu-entry{
display: inline-block;
}
afx-sys-panel afx-menu.afx-panel-os-stray afx-menu { afx-sys-panel afx-menu.afx-panel-os-stray afx-menu {
right: 0; right: 0;
position: absolute; position: absolute;