HackerOne users: Testing against this community violates our program's Terms of Service and will result in your bounty being denied.

Categories keep showing as unread when everything is read

So my users are still having issues that they will mark a category as read and there are no new posts in the category and all of a sudden it shows there are unread posts in this category with a * beside the category and also i am using the unread icon to denote this.

I am having the same issue also with my account. Ill look in the category and nothing has changed.

Any clues to what to look for what might be causing this?

Comments

  • Sorry just to note i am using the plugin "CategoryUnreadPhoto"


    When looking at the code it seems to use this code to determine if the category is read or not

        public function categoriesController_render_before($sender) {
            foreach ($sender->data('CategoryTree', []) as $id => $category) {
                if (!$category['Read'] && $category['UnreadPhoto']) {
                    $sender->setData(
                        'CategoryTree.'.$id.'.PhotoUrl',
                        Gdn_Upload::url($category['UnreadPhoto'])
                    );
                }
            }
        }
    

    So I would assume that it is figuring out if it is read from the variable $category['Read'] that is either 0 or 1. Basically the code is saying is it unread and you have set a category photo set PhotoUrl to the unread photo.. This make sense but how does it determine the ['Read'] value?

    So if I look at \applications\vanilla\models\class.categorymodel.php there is code in there

                // Calculate the read field.
                if (strcasecmp($category['DisplayAs'], 'heading') === 0) {
                    $category['Read'] = false;
                } elseif ($dateMarkedRead) {
                    if ($lastDateInserted = ($category['LastDateInserted'] ?? false)) {
                        $category['Read'] = Gdn_Format::toTimestamp($dateMarkedRead) >= Gdn_Format::toTimestamp($lastDateInserted);
                    } else {
                        $category['Read'] = true;
                    }
                } else {
                    $category['Read'] = false;
                }
    


    So this gets me closer to the function that is returning the wrong data. But need some help to understand this logic.


    The very first line does a string comparison case insensitive to see if $category['DisplayAs'] is === heading and if so set Read as false... why?

  • NM that's incase it's a header it just sets that value to false its only for heading so all good.. I am doing some debugging with the values below that now to see why it thinks a forum is not read when it is

  • MrCaspanMrCaspan
    edited August 2020

    Okay so maybe I am not understanding this properly... It seems that it uses the datemarkedread and comparing it to the LastDateInserted for the category. So based on this logic I have to manually mark each category as read.? By reading any new threads it will never trigger this, what real use is this feature if you always have to manually trigger it haha? Imagine needing to manually trigger that you have read a post.. Is there a reason for this. I can imagine in some forums that there could be a lot of children under the category and needing to check if each child is read could be a lot of over head? If so why not store a value for this so it can be referenced not calculated each time?


    Then next to this I think instead of rewriting this function to return the proper thing I should do is create a plugin that gets this value for me based on all the children of that category. This seems so wrong this is setup this way!

  • This is probably the code you are looking for:

    Essentially when a discussion is marked as read, the last 2 pages of the containing category are checked. If they are read, the category is then marked as read.

    There has been a PR to disable this feature by default, meaning you would actually have to mark a category as read manually. I have voiced my concerns about this, but I don't know if this has been dropped or implemented in the private repository.

  • Very interesting.. So this does check to see if there are any unread comments in the first 2 pages.. Humm...


    I will have to do some digging with this information to see what it thinks there are unread comments in the first 2 pages even though there is not! This feature is like the backbone of forums to let a user know what posts have happened since they last were here!

  • MrCaspanMrCaspan
    edited August 2020

    So I think this is what the issue is. I mark a category as read. This set the DateMarkedRead on the category to today's date and time. There might be 10 unread posts inside that category but because the DateMarkedRead is newer then them it no longer matters and the Category shows Read. Then someone posts something inside the read category which triggers this event that you linked to which checks to see if there is any unread posts in the last 100 max posts, it sees that there are unread posts so it marks it the Category Unread.


    So this logic does not work as reading any posts inside the category will trigger a lookup of the last 100 max posts to see if there is anything unread.


    I think that marking a category as read should be triggering a date change on the DateMarkedRead value as well as it should be setting the first 100 max posts under that category as read also! If not you are going to go in circles!!! Am I right on this?

  • Just to add to that if I mark a category as read and lets say there are 10 unread posts in there and then I go open the category It will still show unread posts under it and in discussion view those posts still show up as unread so this is a very confusing system here. If I mark a category as read I would assume it should mark all children as read so that it does not show then as unread in discussion view also when you filter you view to show all unread posts they shoudl no longer show up there either!

    Next to using a very intensive process to go to all children posts to mark them as read it should be using a combination of the Posts DateMarkedRead  and the Categories DateMarkedRead and if either of them are after the date of the latest post it should show as read.. I think right now a Post will only check to see if it is unread based on the users last visit to that post and the time of most recent post it does not check to see the category DateMarkedRead value that I can see.

  • MrCaspanMrCaspan
    edited August 2020

    So I have this straight for everyone and sorry for the many posts!!

    If a user posts to an existing discussion or posts a new discussion the system will update the field LastDateInserted on the Category. When a user loads the Category view the system looks to see if DateMarkedRead >= LastDateInserted to see if there is any new posts/threads. This makes sense and logic seems solid.

    When a user marks the category as read it only updates the DateMarkedRead filed for the category making DateMarkedRead >= LastDateInserted so it will show no unread posts. So this seems right but in actual fact if you look under that category you will see unread posts notifications on threads. The reason is the system check to see when was the last time the user you visited this discussion and compare it to LastDateInserted on the discussion to see if there are any unread posts in that discussion. And really it should be checking to see what one is newer "The time you last visited the discussion" OR the "DateMarkedRead" on the category then compare that higher value against the LastDateInserted on the dicussion. Because without that logic it will cause a read, unread loop every time someone posts inside hat category.


    No discussion under a category should show unread posts if a category is marked as read that's the point of marking it as read IN my opinion. Then I don't believe there would be a need to Fuzzy check to see of there are unread posts under the category by visiting a post you update the datelastviewed on the discussion and no need to ever care if there are older posts..

  • Interesting, thanks for the wrap up.

    No discussion under a category should show unread posts if a category is marked as read that's the point of marking it as read IN my opinion. Then I don't believe there would be a need to Fuzzy check to see of there are unread posts under the category by visiting a post you update the datelastviewed on the discussion and no need to ever care if there are older posts..

    That would still require the user to mark each category as read manually. Reading every (new) discussion should automatically mark a category as read in my opinion.

    And really it should be checking to see what one is newer "The time you last visited the discussion" OR the "DateMarkedRead" on the category then compare that higher value against the LastDateInserted on the dicussion. Because without that logic it will cause a read, unread loop every time someone posts inside hat category.

    It looks like this actually happens here (master branch):

    But as far as I understand that doesn't seem to work in your case (3.3)? I just tried it out in this forum and marking a category as read actually displays all discussions as read.

    That feature was also refactored recently, so it may be already fixed in the next version:


  • MrCaspanMrCaspan
    edited September 2020

    So should this be posted to the GitHub page.. this kind of seems like a bug... is it not? I am just curious what others think as it is super annoying to go to the forum and a category shows and unread and all the posts inside are read!

    Sorry for the long pause Summer was crazy busy!

Sign In or Register to comment.