Adding application icon into PanelItemNotificationArea


#1

I’m trying to add the application’s icon into the PanelItemNotificationArea but it seems not working. Maybe were I wrong somewhere in the addNotificationIcon method?

const Notification = OSjs.require('gui/notification');
const Theme = OSjs.require('core/theme');
const NotiName = '_ShieldNotification';
class ApplicationShieldWindow extends Window {
  constructor(app, metadata) {
    super('ApplicationShieldWindow', {
      icon: metadata.icon,
      title: metadata.name,
      gravity: 'center',
      width_min: 400,
      height_min: 400,
      width: 400,
      height: 400,
      allow_resize: true,
      allow_maximize: true,
    }, app);
  }

  /*
    Add its icon to the Noti Panel
  */
  addNotificationIcon(wm, app) {
    Notification.createIcon(NotiName, {
      icon: Theme.getIcon(metadata.icon, '16x16'),
      title: metadata.name,
      onClick: function () {
        console.log("Clicked on Shiled Notification Icon.")
      },
      onContextMenu: function () {
        console.log("Right-clicked on Shiled Notification Icon.")
      }
    });
  }

  init(wm, app) {
    const root = super.init(...arguments);

    this._render('ShieldWindow', require('osjs-scheme-loader!scheme.html'));
    const defaultIcon = Notification.getIcon(NotiName);
    console.log(defaultIcon);
    if (defaultIcon) {
      console.log('Shield Icon already added.')
    } else {
      this.addNotificationIcon(wm, app);
    };

    return root;
  }
}

#2

I don’t see anything obviously wrong there.

  1. Do you run in development mode ? Maybe cache is the problem
  2. Maybe the icon resolution failed and you get a “blank” icon in the bar ?
  3. Have you confirmed that your method is called ?

#3

1, I use node osjs run so i’m not in dev mode
2, Inspection doesnt show any newly inserted node in panel.
3, I added these lines to announce if we had the icon yet.

const defaultIcon = Notification.getIcon(NotiName);
console.log(defaultIcon);
if (defaultIcon) {
  console.log('Shield Icon already added.')
} else {
  this.addNotificationIcon(wm, app);
};

But no answer was found in console.


#4

You should run with osjs run --debug, and then use osjs build --debug (or osjs watch --debug).

Another tip is to have your DevTools open, and in the Network tab, select the “disable cache” checkbox. With all of this you’re guaranteed to avoid caching.

If you get nothing in the console, I’m guessing it something along these lines.


#5

Yeah, i found some messages:
WindowManager::addWindow() => Window::init() ReferenceError: metadata is not defined
at ApplicationShieldWindow.addNotificationIcon (main.js:39)
at ApplicationShieldWindow.init (main.js:55)
at CoreWM.addWindow (window-manager.js:326)
at ApplicationShield._addWindow (application.js:260)
at ApplicationShield.init (main.js:69)


#6

Oh, yeah, You’re not referencing metadata in your addNotificationIcon method.

The app instance has a reference already you can use: https://api.os-js.org/client/class/javascript/core/process.js~Process.html#instance-member-__metadata so you don’t have to put more arguments into your method.


#7

You’re right. But my piece of code still doesnt work :frowning:

relaunchApplication() {
  console.log("Clicked on Shiled Notification Icon.");
  return true;
}

showMenu() {
  console.log("Right-clicked on Shiled Notification Icon.");
  return true;
}

init(wm, app) {
    const root = super.init(...arguments);
    console.log(app.__metadata);
    this._render('ShieldWindow', require('osjs-scheme-loader!scheme.html'));
    const defaultIcon = Notification.getIcon(NotiName);
    if (defaultIcon) {
      console.log('Shield Icon already added.')
    } else {
      const shieldIcon = Notification.createIcon(NotiName, {
        icon: Theme.getIcon(app.__metadata.icon, '16x16'),
        title: app.__metadata.name,
        onClick: relaunchApplication,
        onContextMenu: showMenu
      });
      if (shieldIcon) {
        console.log("Shield icon added.");
      } else {
        console.log("Failed to add Shield icon.")
      }
    };

    return root;
  }

i tried to add directly some names instead of app.__metadata.icon and app.__metadata.name. It doesnt work either.


#8

Zip the application and upload here, and I’ll have a look.


#9

https://mega.nz/#!eV8klLiL!Ki13q_eTP4PZWqUMPw-3VSTn2vW2UyQw7Vmz7AKILO4

This slightly rewritten piece of code can run well on console, so i guess the problem may be stuck somewhere else behind the scene?

const Notification = OSjs.require('gui/notification');
const Theme = OSjs.require('core/theme');
const NotiName = '_ShieldNotification';
const Process = OSjs.require('core/process');
const Menu = OSjs.require('gui/menu');

relaunchApplication = () => {
    console.log("Clicked on Shield Notification Icon.");
    Process.create('ApplicationShield')
    return false;
  }

showMenu = (ev) => {
  /*ev.preventDefault();*/
  console.log("Right-clicked on Shield Notification Icon.");
  console.log(ev);
  return false;
}

    const defaultIcon = Notification.getIcon(NotiName);
    if (defaultIcon) {
      console.log('Shield Icon already added.')
    } else {
      console.log("Adding Shield icon.")
      const shieldIcon = Notification.createIcon(NotiName, {
        icon: Theme.getIcon("apps/shield.png", '16x16'),
        title: "Shield",
        onContextMenu: showMenu,
        onClick: relaunchApplication
      });
      if (shieldIcon) {
        console.log("Shield icon added.");
      } else {
        console.log("Failed to add Shield icon.")
      }
    };

#10

All the errors came in the console. You’re referencing undefined things.

Change these things:

      // From
      const shieldIcon = Notification.createIcon(NotiName, {
        icon: Theme.getIcon("apps/shield.png", '16x16'),
        title: "Shield",
        onClick: relaunchApplication,
        onContextMenu: showMenu
      });

      // To
      const shieldIcon = Notification.createIcon(NotiName, {
        icon: Theme.getIcon("apps/shield.png", '16x16'),
        title: "Shield",
        onClick: this.relaunchApplication, // Notice: "this"
        onContextMenu: this.showMenu // Notice: "this"
      });
 // From
            onClick:  function(ev) {
              relaunchApplication(ev);
            }

 // To:
            onClick:  (ev) => {
              this.relaunchApplication(ev);
            }

This goes way beyond OS.js support though as it is a general programming issue. You should use an editor/IDE that has the capabilities of showing you these errors (so you don’t have to reference to browser console all the time).


#11

Thank you for your kindness.

So every reference to method in a class should be preceded by this, right?


#12

Yep, that’s how JavaScript works. And if you use this inside functions, use arrow functions or self-reference (Notice how I changed that in your code!):

// 1. Arrow function`
const foo = () => {
  this.bar();
};

// 2. Self-reference
const self = this;
const foo = function() {
  self.bar();
};

This is very important because JavaScript looks for the context. You can read about this here if you like: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this


#13

That helps a lots! Basically, using const self = this would resolve the confusion between context.