Pre-release 1.4 is now available for testing (Updated 23/11/20)

Hi @laurent if I understand, this should apply to all API calls that return multiple values, right? I'm using the search endpoint, and indeed I now see the results returned under items, but I do not see the limit of 100 items, nor do I ever see cursor - I get thousands of results returned.

This is fine by me :wink: But it isn't in line with what I read above?

Edit: I see the expected result for e.g. the notes endpoint, just not search...

Yes, this end point is not yet enabled for that but I made it return an "items" property so that you can already setup your code as if it was. In other words, if there's a cursor property, you should follow it, and otherwise you have all the results.

Perfect, thanks - I've already made the update for notes and it works well, so I'll do the same for search!

In fact, I've just noticed a potential issue with the cursor approach, which would make it hard to implement a "page" parameter. This technique also doesn't quite solve some of the problems I had in mind, like reliably iterating over a feed of changing data (it handles items being deleted, but not added).

So because of this I will switch to a model similar to the Stack Exchange Paging API:

  • Paginated data may return an has_more field. If it is present, it means more pages of data can be fetched.
  • You can specify a page query parameter to get a specific page in the dataset. Page number starts and defaults to "1".
  • You can request the total number of items using the .total field property (eg. fields=.total), in which case it will be returned as the "total" property.

So the pseudo code would be changed like this:

async function fetchJson(url) {
	return (await fetch(url)).json();
}

async function fetchAllNotes() {
	let pageNum = 1;

	do {
		const response = await fetchJson('http://localhost:41184/notes?page=' + pageNum++);
		console.info('Printing notes:');
		console.info(response.items);
	} while (response.has_more)
}

I hope it doesn't mean too many changes to your code. I expect that in the loop where you fetch data, you need to remove the cursor handling and instead look at the "has_more" field, with a counter to fetch the relevant page.

If you have any questions or see any issue with this approach please let me know.

this is how django works too


Page.has_next()Ā¶

    Returns True if thereā€™s a next page.

Page.has_previous()Ā¶

    Returns True if thereā€™s a previous page.

Page.has_other_pages()Ā¶

    Returns True if thereā€™s a next or previous page.

Page.next_page_number()Ā¶

    Returns the next page number. Raises InvalidPage if next page doesnā€™t exist.

Page.previous_page_number()Ā¶

    Returns the previous page number. Raises InvalidPage if previous page doesnā€™t exist.

Page.start_index()Ā¶

    Returns the 1-based index of the first object on the page, relative to all of the objects in the paginatorā€™s list. For example, when paginating a list of 5 objects with 2 objects per page, the second pageā€™s start_index() would return 3.

Page.end_index()Ā¶

    Returns the 1-based index of the last object on the page, relative to all of the objects in the paginatorā€™s list. For example, when paginating a list of 5 objects with 2 objects per page, the second pageā€™s end_index() would return 4.

the source code

Yes I've seen that in the Dropbox or OneDrive API too, so it seems quite standard.

Well, this time I plan to wait until v1.4 is stable before testing. . .

The way I built my RPMs (github.com/taw00/joplin-rpm) in the past (Joplin 1.3) was essentially:

npm install
cd ElectronClient
yarn dist

That would trigger electron-builder and -packager to do magic javascript build-stuff and package things that I barely understand.

And then I would package into RPM pretty much everything under ElectronClient/dist/linux-unpacked/*.

With 1.4.7 this breaks. The directory structure is different and I am not sure how to you generate the bits at the end and where they land. I looked through the documentation and some of the scripts and it still remains a mystery.

Can someone help me out?

Everything is in BUILD.md. If something's missing from it let me know.

An new version is out:

IMPORTANT: If you use the Clipper API, please note that there are a few breaking changes in this version. See this link for more information: https://github.com/laurent22/joplin/pull/3983


  • New: Added toolbar button to switch spell checker language
  • Improved: Api: Change pagination to has_more model
  • Fixed: Fixed inconsistent note list state when using search (#3904)
  • Fixed: Fixed text editor button tooltips
  • Fixed: Regression: Fix exporting to HTML and PDF
  • Fixed: Tags could not be selected in some cases (#3876)

@foxmask, @rxliuli, @msbentley, the updated API now has the has_more change that was discussed above and the doc has been updated too.

Sorry about this change after you've already started updating your apps, but that was unfortunately necessary as the previous model was not efficient enough to handle a "page" query parameter. If you have any question about it, please let me know.

1 Like

no problem, this is how projects progress

I have basically the same process, bar replace the yarn dist with npm run dist.

The changes to compensate for my build process were along the lines of this diff.

-      cd ElectronClient
+      cd packages/app-desktop/
       npm run dist
-      cp -r $SNAPCRAFT_PART_BUILD/ElectronClient/dist/linux-unpacked/ $SNAPCRAFT_PART_INSTALL/
+      cp -r dist/linux-unpacked/ $SNAPCRAFT_PART_INSTALL/
+      mv $SNAPCRAFT_PART_INSTALL/linux-unpacked/@joplinapp-desktop $SNAPCRAFT_PART_INSTALL/linux-unpacked/joplin

Which is to say there's 2 change of directory structure and the binary itself has also changed name, but everything else seems to work the same as before. Of course, Yarn itself might have some influence here, I'm no expert there, so you could try npm run dist rather than yarn dist to see if that influences anything.

1 Like

The npm package of the api client is being processed. The only problem at present is that I donā€™t know how to get the total number of data, I want to give the user a progress bar instead of the prompt "I'm processing"


It seems that the /notes api now only returns the three fields of id/parent_id/title by default. Is this an api change? Still a mistake?
Previous default return field

id
title
is_todo
todo_completed
parent_id
updated_time
user_updated_time
user_created_time
encryption_applied
_type

Are there other APIs that have undergone similar changes? (Folder/resource/tag)

@foxmask, I cannot replicate this, and the test for it is passing as well. Was the app by any chance built from source? Or if not, which version was it?

no I don't. I use only the provided binary

Right, now I know what's the issue is. It indeed was broken for a short time and I thought I had fixed it before the pre-release but I must have done it afterwards. So no problem then, it will work from the next version.

1 Like

@james-carroll -- thanks. I would have eventually stumbled over this process, but you saved me a tremendous amount of time.

@laurent The build.md docs are geared to a different purpose. I suppose the bits missing that I would wish for would be the finalization instructions for those who would want to build the stand-alone application (like we packagers do), whether it be an appimage or the "unpacked" variant. Also, there is nothing about how to build the cli. I have not been success with that yet.

Thanks all.

v1.4.10 is now available. From now on I will list the API breaking changes, if any, at the top to avoid any surprise. In general I don't expect many breaking changes and when there will be I will try instead to deprecate the feature, so that you have plenty of time to update your plugins.

Breaking Changes:

  • If you use the Clipper API, please note that there are a few breaking changes in this version. See this link for more information: https://github.com/laurent22/joplin/pull/3983
  • Plugins: joplin.views.dialogs.open() now returns an object instead of the button ID that was clicked. So for example instead of getting just "ok", you will get { "id": "ok" }. This is to allow adding form data to that object.

Deprecated:

  • Plugins: All create() functions under joplin.views now take a viewId as a first parameter. It will still work for now if you don't provide one, but please update your plugins.
  • Plugins: MenuItemLocation.Context is deprecated and is now an alias for MenuItemLocation.NoteListContextMenu

Plugin doc has been updated with some info about the development process.


  • New: Add {{bowm}} and {{bows}} - Beginning Of Week (Monday/Sunday) (#4023 by Helmut K. C. Tessarek)
  • New: Plugins: Add support for editor context menu
  • New: Allow customising application layout
  • Improved: Allow lowercase filters when doing search
  • Improved: Make Markdown editor selection more visible in Dark mode
  • Improved: Plugins: Allow retrieving form values from dialogs
  • Fixed: Api: Fix note and resource association end points
  • Fixed: Fix drag and drop behaviour to "copy" instead of "move" (#4031 by @CalebJohn)
  • Fixed: Fix handling of certain keys in shortcut editor (#4022 by Helmut K. C. Tessarek)
  • Fixed: Fixed issue with note being saved after word has been replaced by spell checker
  • Fixed: Plugins: Fix crash when path includes trailing slash
  • Fixed: Regression: Fix application name

  • New: Added toolbar button to switch spell checker language
  • New: Api: Added way to get the notes associated with a resource
  • New: Api: Added ability to watch resource file
  • New: API: Adds ability to paginate data (#3983)
  • New: Adds spell checker support for Rich Text editor (#3974)
  • Fixed: Fixed inconsistent note list state when using search (#3904)
  • Fixed: Fixed text editor button tooltips
  • Fixed: Regression: Fix exporting to HTML and PDF
  • Fixed: Tags could not be selected in some cases (#3876)
  • Improved: Change Markdown rendering to align with CommonMark spec (#3839)
  • Improved: Plugins: Force plugin devtool dialog to be detached
1 Like

It's in packages/tools/release-cli.js

The reason it's not documented is that it's not really supported, however you can always check .travis.yml to see how it's done. Mostly you need to run npm run dist after having done the steps listed in BUILD.md.