Help needed with handleBrowseUri

I am trying to produce a new plugin but I am struggling with handleBrowseUri.

I have ‘lifted’ the working part from the Randomizer plugin and tried to insert it into the new plugin (named ‘tester’ for the time being).

I do not know ;
a) if there is anything wrong with the following code or

b) if there is some other code that I should have ‘borrowed’ as well.

Any advice gratefully taken on board!

tester.prototype.handleBrowseUri = function(uri) {

  switch (uri) {
    case ‘tester’: 
        break;
    case ‘tester/selection_one':
        this.call_function_one();
        break;
    default:
        return libQ.reject(`Unknown tester URI: ${uri}`)
  }


  return libQ.resolve({
    navigation: {
      prev: { uri: '/' },
      lists: [
        {
          title: this.getI18nString(‘tester’),
          'availableListViews': [ 'list', 'grid' ],
          'items': [
            {
              service: ’tester’,
              type: 'item-no-menu',
              title: ‘Item 1’,
              uri: `tester/selection_one`,
              albumart: '/albumart?sourceicon=system_hardware/tester/assets/tester.png'
            }
          ]
        }
      ]
    }
  });
}


With this code I get a slowly progressing bar across the top of the UI.

Hey @Old_Duffer,

The progress bar that never completes is a classic symptom of handleBrowseUri returning a promise that never resolves. Looking at your code, I can see a structural issue that would cause exactly this.

Your switch statement calls this.call_function_one() for the tester/selection_one case, then falls through to return the same navigation object regardless of which case matched. There are two problems here:

  1. If call_function_one throws an error or is undefined, the exception prevents the return statement from ever being reached. The caller gets a promise that never resolves - hence the endless progress bar.

  2. The navigation structure returned is the root menu in all cases. When the user taps “Item 1” (URI tester/selection_one), the UI expects a different navigation response for that sub-URI, not the same root listing again.

The standard pattern for handleBrowseUri is to return a different navigation object per URI level. Here is a corrected structure:

tester.prototype.handleBrowseUri = function(uri) {
  switch (uri) {
    case 'tester':
      return libQ.resolve({
        navigation: {
          prev: { uri: '/' },
          lists: [
            {
              title: this.getI18nString('tester'),
              availableListViews: ['list', 'grid'],
              items: [
                {
                  service: 'tester',
                  type: 'item-no-menu',
                  title: 'Item 1',
                  uri: 'tester/selection_one',
                  albumart: '/albumart?sourceicon=system_hardware/tester/assets/tester.png'
                }
              ]
            }
          ]
        }
      });

    case 'tester/selection_one':
      return this.call_function_one();

    default:
      return libQ.reject('Unknown tester URI: ' + uri);
  }
};

Key points:

  • Each case returns its own resolved promise with the appropriate navigation for that URI level.
  • call_function_one() must itself return a libQ.resolve() with a valid navigation object (or whatever response is appropriate for what that function does). If it does not return a resolved promise, you will get the same progress bar symptom.
  • The default case rejects, which tells the UI the URI is not handled.

If call_function_one is meant to trigger playback rather than return a browsable list, the return value would be different - but it still must return a resolved or rejected promise. What does call_function_one do?

Kind Regards,

Thank you for your help. Not at the machine tonight, will read again, inwardly digest and hopefully tomorrow will bring success.

The function one is a simple axios call.

I have it all working with items added to the Randomizer plugin.

I realise that I should have also included the fact that the green bar appears but there is no icon to click on.

Fingers crossed for tomorrow.