os-js / osjs-client

OS.js Client Module
https://manual.os-js.org/
Other
31 stars 31 forks source link

Getting Tray list. #133

Closed miladhashemi closed 3 years ago

miladhashemi commented 3 years ago

Hi, How can I get tray list defined in Tray.js? I want create create tray in application. If the tray exists, i dont want create it.

andersevenrud commented 3 years ago

Here's the contract for the tray service provider:

https://github.com/os-js/osjs-client/blob/master/src/providers/core.js#L504

So you can get the list with core.make('osjs/tray').list().

You can probably implement it like this:

const createTrayEntry = (core, proc) => {
  const name = `_${proc.metadata.name}`
  const exists = core.make('osjs/tray')
    .list()
    .find(item => item[name] === true)

  if (!exists) 
    const tray = core.make('osjs/tray', {
      [name]: true,
      title: 'Hello World',
      onclick: () => {}
    })

    proc.on('destroy', () => tray.destroy())
  }
}

// ...

const register = (core, args, options, metadata) => {
  const proc = core.make('osjs/application', {args, options, metadata})
  createTrayEntry(core, proc)
}

// ...

Hold on with this, I'm adding some new stuff to the API to simplify this

andersevenrud commented 3 years ago

By the way, if you make your application a singleton type application then you don't have to do these kinds of checks because there's only one instance running at any time. This requires you to manage main window(s) manually, but maybe something worth looking into :)

const mainWindowFactory = proc => proc.createWindow({
    title: proc.metadata.title.en_EN
})

const register = (core, args, options, metadata) => {
  const proc = core.make('osjs/application', {args, options, metadata})

  // Create a window factory
  const createMainWindow = mainWindowFactory(proc)

  // The "attention" signal is when user launches app when it's already open
  proc.on('attention', (newArgs) => createMainWindow())

  // Create a new window immediately
  createMainWindow()

  // Create a new tray entry
  const tray = core.make('osjs/tray', {
    title: 'Hello World',
    onclick: () => {}
  })

  proc.on('destroy', () => tray.destroy())

  return proc
}
andersevenrud commented 3 years ago

Hold on with this, I'm adding some new stuff to the API to simplify this

I've published a new version of osjs-client that adds keys to the tray entries, so you can do the following instead:

const createTrayEntry = (core, proc) => {
  const exists = core.make('osjs/tray')
    .has(proc.metadata.name)

  if (!exists) 
    const tray = core.make('osjs/tray', {
      key: proc.metadata.name,
      title: 'Hello World',
      onclick: () => {}
    })

    proc.on('destroy', () => tray.destroy())
  }
}
andersevenrud commented 3 years ago

Correction: Now I've published it....

miladhashemi commented 3 years ago

I've published a new version of osjs-client that adds keys to the tray entries, so you can do the following instead:

Thank U. exactly I'm looking for this. I tested OSjs.make('osjs/tray').list() in brwoser but it doesn't returned tray list. :( Application is singlepoint, but I want when applications is closed, just hide the window, and tray staying on traybar. when click on tray icon make window visible(or storing state on setting and create window again). and destroy proc only I destroy tray.

andersevenrud commented 3 years ago

I tested OSjs.make('osjs/tray').list() in brwoser but it doesn't returned tray list. :(

This definitely works. I have unit tests on this -- and I cannot reproduce no result in my browser setup :thinking:

Application is singlepoint

If it is (singleton in metadata), then you don't have to get a tray list or anything like that. You can just implement it like this, which does the following:

  1. Spawns only one main window
  2. The main window is created on demand if it does not exist
  3. If it already exists it will be shown and focused
  4. Activating the tray icon will do either 2) or 3) above
const mainWindowFactory = proc => {
  const id = 'MyWindowId'
  const exists = proc.windows.find(win => win.id === id)

  if (exists) {
    exists.restore()
    exists.focus()

    return exists
  }

  const win = proc.createWindow({
    id,
    title: proc.metadata.title.en_EN
  })

  return win
}

const register = (core, args, options, metadata) => {
  const proc = core.make('osjs/application', {args, options, metadata})

  // Create a window factory
  const createMainWindow = mainWindowFactory(proc)

  // The "attention" signal is when user launches app when it's already open
  proc.on('attention', (newArgs) => createMainWindow())

  // Create a new window immediately
  createMainWindow()

  // Create a new tray entry
  const tray = core.make('osjs/tray', {
    title: 'Hello World',
    onclick: () => createMainWindow()
  })

  proc.on('destroy', () => tray.destroy())

  return proc
}

Important

The default application template does win .on('destroy', () => proc.destroy()) which you cannot use if you want the application to "stay alive" in the background. Just a note in case you created the app from template and changed it to a singleton type.

When you don't automatically close the application when main window(s) disappear you will have to make it possible to quit the application entirely. For example a menu point in the main window, or an entry in the tray contextmenu that does a proc.destroy() call.

If you don't do this and a user saves their session when they log out, the application will be running forever even though the user might not want to :)

andersevenrud commented 3 years ago

There's also another way to solve this.

Instead of creating the tray icon inside the application, you can create a new service provider and create the tray entry there and just make it spawn your application if it's not running.

This will of course make the tray entry always visible and it would sort of be detached from your application code.

Not sure if that's something you need, but thought I'd throw it out there.

miladhashemi commented 3 years ago

This definitely works. I have unit tests on this -- and I cannot reproduce no result in my browser setup 🤔

Yes, It returns tray list correctly. definitely I make a mistake before. 😕

image

The default application template does win .on('destroy', () => proc.destroy()) which you cannot use if you want the application to "stay alive" in the background. Just a note in case you created the app from template and changed it to a singleton type.

I removed it from application and added to context menu. but the context menu didn't work. I look at xterm-application source code. it has new terminal context menu but it didn't work too.

Instead of creating the tray icon inside the application, you can create a new service provider and create the tray entry there and just make it spawn your application if it's not running.

I want the tray to be shown as application has been run. and with clicking exit on context menu, destroy both proc and tray.

andersevenrud commented 3 years ago

I removed it from application and added to context menu. but the context menu didn't work. I look at xterm-application source code. it has new terminal context menu but it didn't work too.

Try doing this:

  const tray = core.make('osjs/tray').create({
    title: 'Hello World',
    onclick: () => createMainWindow()
  }, ev => {})

instead of this:

  const tray = core.make('osjs/tray', {
    title: 'Hello World',
    onclick: () => createMainWindow()
  }, ev => {})

I looked up the source and usage without the .create() call does not support the callback function and prints this warning to the console :nerd_face:

osjs/tray usage without .create() is deprecated

andersevenrud commented 3 years ago

Or an alternative to using .create() is to pass a oncontextmenu: ev => {} option. But the second argument above responds to both click and cotextmenu (onclick: ev => {} is also an option)

andersevenrud commented 3 years ago

I removed it from application and added to context menu. but the context menu didn't work. I look at xterm-application source code. it has new terminal context menu but it didn't work too.

Reading this a few more times; I'm not sure what you mean by this exactly :thinking:

miladhashemi commented 3 years ago

Reading this a few more times; I'm not sure what you mean by this exactly 🤔

At first I apologize for my English skill. :neutral_face: (Maybe it's better to help google translate before comment. Or may be it's time to bed for me 😄) My mean was that I taked your purpose.(I understand your concern about destroying proc (keep application a live) and I make application singleton through adding it to metadata.json). I said I had another issue on creating context menu. before I اhad installed xterm-application but its tray context menu didn't work. unfortunately I didn't debug more.

I hope I have expressed it better this time. :worried:

miladhashemi commented 3 years ago

I said I had another issue on creating context menu. before I اhad installed xterm-application but its tray context menu didn't work. unfortunately I didn't debug more.

maybe it was better open it as a new issue.

andersevenrud commented 3 years ago

At first I apologize for my English skill

No worries :)

maybe it was better open it in new issue.

Oh. You had issues with the tray contextmenu in the xterm application! I understand now :) It would be better as a separate issue, indeed.

unfortunately I didn't debug more.

I did and you found a bug in the client source mister! The callback function is not passed on after I did some cleanups :( Pushing a new version to fix this n

andersevenrud commented 3 years ago

Pushing a new version to fix this now

New verison of osjs-client out that fixes this :blush:

miladhashemi commented 3 years ago

New verison of osjs-client out that fixes this 😊

Real Viking, you caused, I start my morning happier tomorrow. According to Persians ( فدایی داریی). It doesn't has proper meaning in English but it nearly close to Yours sincerely. 😊

andersevenrud commented 3 years ago

Glad to hear it! :D

miladhashemi commented 3 years ago

I think this issue could be closed. 👍 Good night! 🙋🏼‍♂️

andersevenrud commented 3 years ago

Sweet! Time to go to bed here as well. Good night .)

Oh, could you please close your own issues when you think that things are OK ? That would avoid any confusion about the state of things.

miladhashemi commented 3 years ago

Oh, sure.