Feed tree state not saved correctly

Describe the problem you’re having:
On account with quite a few categories/feeds, the tree expansion state isn’t saved correctly.

Browser console shows this warning:

Cookie “feedTreeSaveStateCookie” is invalid because its size is too big. Max size is 4096 B.

If possible include steps to reproduce the problem:
31 categories, with a total of 431 feeds, expand and open most of them

tt-rss version (including git commit id):
68b78ecd3d90fb6cb35d08a96ed74b7a59470c39

Platform (i.e. Linux distro, PHP, PostgreSQL, etc) versions:
FreeBSD 12.0, PHP 7.3.18, PostgreSQL 12.3

Please provide any additional information below:
At that cookies size, it also means each requests sends over 4KB of data

this is a dojo issue. maybe its possible to serialize tree state in local storage instead of a cookie.

I noticed it saves additional state entry for each feeds I open which seems rather pointless…? I don’t understand the format and I couldn’t find where it’s being set though.

I also noticed it’s not saved server side so I guess there’s no harm moving it to local storage.

a bit more digging suggests it’s not configurable directly but must override the relevant methods; namely _saveExpandedNodes and _initState.

This patch seems working

diff --git a/js/FeedTree.js b/js/FeedTree.js
index 75a3f32a7..64ea727cf 100755
--- a/js/FeedTree.js
+++ b/js/FeedTree.js
@@ -1,9 +1,39 @@
 /* eslint-disable prefer-rest-params */
 /* global __, dojo, dijit, define, App, Feeds, CommonDialogs */
 
-define(["dojo/_base/declare", "dojo/dom-construct", "dijit/Tree", "dijit/Menu"], function (declare, domConstruct) {
+define(["dojo/_base/declare", "dojo/dom-construct", "dojo/_base/array", "dijit/Tree", "dijit/Menu"], function (declare, domConstruct, array) {
 
 	return declare("fox.FeedTree", dijit.Tree, {
+		// save state in localStorage instead of cookies
+		// reference: https://stackoverflow.com/a/27968996
+		_saveExpandedNodes: function(){
+			if(this.persist && this.cookieName){
+				var ary = [];
+				for(var id in this._openedNodes){
+					ary.push(id);
+				}
+				// Was:
+				// cookie(this.cookieName, ary.join(","), {expires: 365});
+				localStorage.setItem(this.cookieName, JSON.stringify(ary));
+			}
+		},
+		_initState: function(){
+			// summary:
+			//    Load in which nodes should be opened automatically
+			this._openedNodes = {};
+			if(this.persist && this.cookieName){
+				// Was:
+				// var oreo = cookie(this.cookieName);
+				var oreo = localStorage.getItem(this.cookieName);
+				if(oreo){
+					// Was:
+					// array.forEach(oreo.split(','), function(item){
+					array.forEach(JSON.parse(oreo), function(item){
+						this._openedNodes[item] = true;
+					}, this);
+				}
+			}
+		},
 		_onContainerKeydown: function(/* Event */ /* e */) {
 			return; // Stop dijit.Tree from interpreting keystrokes
 		},

can you register on gogs and make a PR the usual way? either that or email me the diff because idk how to get it out of discourse to apply :slight_smile:

I just registered on gogs with username nanaya.

OK, i’ve enabled your account to fork things. thanks!