New Posts icon to remain until all new posts read

Started by roytheboy, December 20, 2005, 04:54:26 AM

Previous topic - Next topic

roytheboy

Hi. I have recently converted a busy phpBB forum to SMF and am very impressed with the way it has turned out. The number of standard features in SMF is vast, and the ease of administration is like a breath of fresh air. Well done team :)

There is, however, just one thing that is bugging me and my forum's members: the fact that the 'new posts' icons on the board index change from 'on' to 'off' immediately the board is accessed, even if there are still unread posts within. Most users do not use the 'Show unread posts since last visit' link, and there does not seem to be a 'Show all unread posts' link. So many posts are going unnoticed purely because this aspect of SMF works differently to phpBB.

The SQL in question (Sources/BoardIndex.php, line 62 onwards) is bordering on the limits of my understanding, and I don't want to experiment on a live forum, so my question is, has anybody modified this aspect of SMF, or can anyone who knows their way around the scripts, please tell me what modifications I need to make in order to show an 'on' icon if the board contains any posts that have not been read by the user. If it helps, my forum does not use child-boards.

Thanks in advance :)
Life's a b*tch and then you die!

Oldiesmann

Several people have asked about this (surprisingly), and unfortunately I have not yet found a way to do this that would not result in a huge slowdown.

As soon as you view a board, SMF marks it as read, without marking each individual topic read. SMF then looks at the latest entry in the log_boards table for that board and your user ID and compares the resulting timestamp with the "lastmodified" timestamp for that board. If the "lastmodified" timestamp is larger, then the board is considered new.

In order to do things the way phpBB does them (in terms of not marking a board read until you click on "mark as read" or you've seen every topic in there), SMF would have to determine whether or not each topic in a board was new directly from the board index, which would result in a huge slowdown due to all the extra queries needed. SMF already keeps track of which messages have and have not been read (ie viewing a board doesn't mark every topic in that board as "read"). In 1.1, you can use the "unread;all" action to see all unread posts and the "boards" parameter to specify which board(s) to show new posts from:

.../index.php?action=unread;all - shows all unread topics from every board that you can see
.../index.php?action=unread;all;boards=1(,2,3,...) - shows all unread topics from the specified board(s)

If I can find a way to do this without causing a huge slowdown, I will gladly post this code.
Michael Eshom
Christian Metal Fans

roytheboy

Thanks Oldiesmann. I'd figured out how it all works by studying the scripts, and realised that I'd have to modify the SQL string at Sources/BoardIndex.php, line 62 onwards. My initial thoughts were, as you have suggested, that the overhead would be high, but I thought I'd try it anyway and measure the impact on performance. It was at that point that I thought I'd make sure I'm not going to be reinventing the wheel, hence my post.

It doesn't surprise me that others have asked about this, as to my thinking, this is a usability flaw (the only one I have found thus far I would add). It makes far more sense to show unread topics for as long as they are unread, rather than to cancel the indicator just for looking at the message index. I'm trying to be constructive here; not critical :)

Thanks for the URL tips - that's useful to know. If no one comes up with a guide as to how to build this particular 'wheel', maybe I'll try and find time over Christmas to delve a little deeper myself.

Happy Christmas :)
Life's a b*tch and then you die!

Sheepy

IIRC, there's a show all unread post link at lower right corner in the show unread post since last visit screen.

roytheboy

Yes, you're right - thanks. But I'd still like to get the 'new post' indicators working more intuitively if I can. BTW: I remain mega-impressed with the SMF app in general.
Life's a b*tch and then you die!

Compuart

If you want to make sure boards aren't marked as seen while jumping to the last topic of a board, remove:
Code (Display.php) Select
// Mark board as seen if we came using last post link from BoardIndex. (or other places...)
if (isset($_REQUEST['boardseen']))
{
db_query("
REPLACE INTO {$db_prefix}log_boards
(logTime, ID_MEMBER, ID_BOARD)
VALUES (" . time() . ", $ID_MEMBER, $board)", __FILE__, __LINE__);
}



If you also would like the boards to remain unread until mark as read has been pressed, remove:
Code (MessageIndex.php) Select
db_query("
REPLACE INTO {$db_prefix}log_boards
(logTime, ID_MEMBER, ID_BOARD)
VALUES (" . time() . ", $ID_MEMBER, $board)", __FILE__, __LINE__);
if (!empty($board_info['parent_boards']))
{
db_query("
UPDATE {$db_prefix}log_boards
SET logTime = " . time() . "
WHERE ID_MEMBER = $ID_MEMBER
AND ID_BOARD IN (" . implode(',', array_keys($board_info['parent_boards'])) . ")
LIMIT " . count($board_info['parent_boards']), __FILE__, __LINE__);

// We've seen all these boards now!
foreach ($board_info['parent_boards'] as $k => $dummy)
{
if (isset($_SESSION['topicseen_cache'][$k]))
unset($_SESSION['topicseen_cache'][$k]);
}
}



This is different from the phpBB system, since it still doesn't mark the boards as seen after leaving the forum. To do that, add after:
Code (Load.php) Select
$_SESSION['ID_MSG_LAST_VISIT'] = $user_settings['ID_MSG_LAST_VISIT'];
this query:

db_query("
REPLACE INTO {$db_prefix}log_boards
(ID_MEMBER, ID_BOARD, logTime)
SELECT $ID_MEMBER, ID_BOARD, $visitTime
FROM {$db_prefix}boards", __FILE__, __LINE__);



(please note, all of the above code is untested)
Hendrik Jan Visser
Former Lead Developer & Co-founder www.simplemachines.org
Personal Signature:
Realitynet.nl -> ExpeditieRobinson.net / PekingExpress.org / WieIsDeMol.Com

roytheboy

Compuart - thanks for taking the time to respond, and I hate to seem ungrateful, but your suggestions do not leave the forum behaving intuitively. What I want is for the board icons to remain 'on' for as long as there are unread posts within. Whether or not phpBB acts in this way, it is still the most intuitive interface action IMHO.

I am hoping to find time to have a go at recoding the SQL string that I mentioned above, so that I can measure the overhead of checking every post, every time the boardindex is loaded; but your post has prompted me to try something else. Maybe the action of triggering the icon to switch could be conditional on a check of all the posts within the board. At least this would not create an additional load when viewing the boardindex, and would cut down the db search to actions involving one board at a time.

My problem is that I have not yet been able to study the SMF scripts in detail, so I do not yet fully understand the code-flow with regards to this issue.
Life's a b*tch and then you die!

Compuart

In that case try (without the previous changes) adding before:
Code (Display.php) Select
// Have we recently cached the number of new topics in this board, and it's still a lot?
this:
$_REQUEST['topicseen'] = true;
if (isset($_REQUEST['boardseen']))
unset($_REQUEST['boardseen']);



Remove this again:
Code (MessageIndex.php) Select
db_query("
REPLACE INTO {$db_prefix}log_boards
(logTime, ID_MEMBER, ID_BOARD)
VALUES (" . time() . ", $ID_MEMBER, $board)", __FILE__, __LINE__);
if (!empty($board_info['parent_boards']))
{
db_query("
UPDATE {$db_prefix}log_boards
SET logTime = " . time() . "
WHERE ID_MEMBER = $ID_MEMBER
AND ID_BOARD IN (" . implode(',', array_keys($board_info['parent_boards'])) . ")
LIMIT " . count($board_info['parent_boards']), __FILE__, __LINE__);

// We've seen all these boards now!
foreach ($board_info['parent_boards'] as $k => $dummy)
{
if (isset($_SESSION['topicseen_cache'][$k]))
unset($_SESSION['topicseen_cache'][$k]);
}
}



I think this should result in the desired behaviour (untested though), that is, marking topics as seen instead of boards.
Hendrik Jan Visser
Former Lead Developer & Co-founder www.simplemachines.org
Personal Signature:
Realitynet.nl -> ExpeditieRobinson.net / PekingExpress.org / WieIsDeMol.Com

roytheboy

#8
Thanks again for your assistance, but I think we're at cross-purposes somewhere. I'm using the latest download of SMF - 1.0.5, with the PHP 4.4.0 and MySQL 5.0.12 updates. None of the files in my distro contain the line "Have we recently cached the number of new topics in this board, and it's still a lot?" and nowhere can I find any mention of "topicseen_cache".

However, the plot thickens because whilst searching Display.php I assumed your suggested mod was to the Display() function so I scanned through and found this at line 254:


// Mark board as seen if this is the only new topic.
if (isset($_REQUEST['topicseen']))
{
// Use the mark read tables... and the last visit to figure out if this should be read or not.
$request = db_query("
SELECT COUNT(t.ID_TOPIC)
FROM {$db_prefix}topics AS t, {$db_prefix}messages AS m
LEFT JOIN {$db_prefix}log_boards AS lb ON (lb.ID_BOARD = $board AND lb.ID_MEMBER = $ID_MEMBER)
LEFT JOIN {$db_prefix}log_topics AS lt ON (lt.ID_TOPIC = t.ID_TOPIC AND lt.ID_MEMBER = $ID_MEMBER)
WHERE t.ID_BOARD = $board
AND m.ID_MSG = t.ID_LAST_MSG
AND m.posterTime > IFNULL(lt.logTime, IFNULL(lb.logTime, 0))" . (empty($_SESSION['ID_MSG_LAST_VISIT']) ? '' : "
AND t.ID_LAST_MSG > $_SESSION[ID_MSG_LAST_VISIT]"), __FILE__, __LINE__);
list ($numNewTopics) = mysql_fetch_row($request);
mysql_free_result($request);

// If there're no real new topics in this board, mark the board as seen.
if (empty($numNewTopics))
$_REQUEST['boardseen'] = true;
}


The top comment here suggests that the board should only be marked as seen if the topic being viewed is/was the only new one. Also, the comment near the bottom suggests the same. Again, I am unable to spend time learning how this all comes together at the moment, but are you able to explain why the comments here suggest that the icons should act as I am requesting? ...have I found a bug perhaps?
Life's a b*tch and then you die!

iowamf

I have been banging my head for months with how some users can have a board full of topics with the "NEW" icon and still have the ?action=unread;all;start=0 come up empty.

Quote from: Oldiesmann on December 20, 2005, 09:10:23 AM
As soon as you view a board, SMF marks it as read, without marking each individual topic read.

This is especially confusing for TinyPortal users with a column full of "Recent" posts with "New" icons - but the "show unread" and even the "click here to try all unread" comes up with an empty list.

Would really like a work around (at least for SMF1.1 RC2) to get the ?action=unread;all;start=0 to work correctly - IMHO, this is a bug. I do understand what a challenge this may be without taking a huge performance hit.

Ah - clarity ... I've been hunting this one for too long.

roytheboy

iowamf - I think you're talking about a different problem with the 'new' icon, being that if you are reading a thread and posts come in at that time, you can read and even respond to those posts yet when you return to the forum home page, the board 'new' icon is now telling you that there are new posts. This is a separate 'interaction bug' (for want of a better description) in my opinion.

I remain very impressed with the SMF forum as a whole, but the way that the 'new' icon functions is still a pain in two important 'usability' respects.
Life's a b*tch and then you die!

iowamf

#11
I'm 100% convinced that the "show unread" is not working intuitively using the default configuration of SMF 1.1 RC2 ... I've got "unread" topics but unread;all;start=0 is not showing them. I've reinstalled a few times and can duplicate this every time.

The issue I'm talking about can be repeated by never clicking on the the "Welcome to SMF!" message that comes with the default installation and by clicking on the "General Discussion" board and then following up with trying to view all unread messages.

If a user tries to "show unread" or the "click here to try all unread topics" - the "Welcome to SMF!" message will not show up in the unread list (even though the "Welcome to SMF!" message will still have the "new" icon and the user has never read/clicked the message).

Quote from: roytheboy on March 01, 2006, 05:58:52 AM
iowamf - I think you're talking about a different problem with the 'new' icon, being that if you are reading a thread and posts come in at that time, you can read and even respond to those posts yet when you return to the forum home page, the board 'new' icon is now telling you that there are new posts. This is a separate 'interaction bug' (for want of a better description) in my opinion.

I'm not sure I understand what problem you are describing - I hope my above clarification describes what I am seeing.

Quote from: roytheboy on March 01, 2006, 05:58:52 AM
I remain very impressed with the SMF forum as a whole, but the way that the 'new' icon functions is still a pain in two important 'usability' respects.

Agreed - SMF is a fine piece of work.

iowamf

Thanks Compuart -

I tried this and so far - so good! No error messages either.

I don't know what this is going to do to performance - but I'm just testing for now and I'm more concerned with functionality than performance.

Keeping "unread" messages in the "unread list" is a good thing  ;)

Quote from: Compuart on December 21, 2005, 02:06:02 PM
In that case try (without the previous changes) adding before:
Code (Display.php) Select
// Have we recently cached the number of new topics in this board, and it's still a lot?
this:
$_REQUEST['topicseen'] = true;
if (isset($_REQUEST['boardseen']))
unset($_REQUEST['boardseen']);



Remove this again:
Code (MessageIndex.php) Select
db_query("
REPLACE INTO {$db_prefix}log_boards
(logTime, ID_MEMBER, ID_BOARD)
VALUES (" . time() . ", $ID_MEMBER, $board)", __FILE__, __LINE__);
if (!empty($board_info['parent_boards']))
{
db_query("
UPDATE {$db_prefix}log_boards
SET logTime = " . time() . "
WHERE ID_MEMBER = $ID_MEMBER
AND ID_BOARD IN (" . implode(',', array_keys($board_info['parent_boards'])) . ")
LIMIT " . count($board_info['parent_boards']), __FILE__, __LINE__);

// We've seen all these boards now!
foreach ($board_info['parent_boards'] as $k => $dummy)
{
if (isset($_SESSION['topicseen_cache'][$k]))
unset($_SESSION['topicseen_cache'][$k]);
}
}



I think this should result in the desired behaviour (untested though), that is, marking topics as seen instead of boards.

mark7144

Is this safe to do with RC2?

I have done it for my RC2 board and so far it seems fine but can you check the code i removed and confirm it was fine to do:

I removed the following from MessageIndex.php

db_query("
REPLACE INTO {$db_prefix}log_boards
(ID_MSG, ID_MEMBER, ID_BOARD)
VALUES ($modSettings[maxMsgID], $ID_MEMBER, $board)", __FILE__, __LINE__);
if (!empty($board_info['parent_boards']))
{
db_query("
UPDATE {$db_prefix}log_boards
SET ID_MSG = $modSettings[maxMsgID]
WHERE ID_MEMBER = $ID_MEMBER
AND ID_BOARD IN (" . implode(',', array_keys($board_info['parent_boards'])) . ")
LIMIT " . count($board_info['parent_boards']), __FILE__, __LINE__);

// We've seen all these boards now!
foreach ($board_info['parent_boards'] as $k => $dummy)
if (isset($_SESSION['topicseen_cache'][$k]))
unset($_SESSION['topicseen_cache'][$k]);
}

if (isset($_SESSION['topicseen_cache'][$board]))
unset($_SESSION['topicseen_cache'][$board]);

mark7144

I can now unfortunately confirm this does not work properly with RC2, maybe it can but I don't know how to adapt your instructions to work with it.

Please would someone be kind enough to tell me how to make this RC2 compatible?

iowamf

what are the symptoms?

is there a test case to duplicate it - I can try it on my site (on a private LAN).

mark7144

#16
My users complained that when they read all the new posts in a forum section, it would still show the 'new posts' image at the forum index (after a refresh to).

Sorry I have no test case for you - I'd really appreciate if you could do it on your LAN.

mark7144

I just thought of an idea why this might be happening.


After a topic with a new reply hasn't been read for several days, it will eventually move to the next page. Now most people don't view past the first page and I think this could be the problem.

Would you agree and is there a way around this?

iowamf

Quote from: mark7144 on March 16, 2006, 03:42:24 PM
My users complained that when they read all the new posts in a forum section, it would still show the 'new posts' image at the forum index (after a refresh to).

Sorry I have no test case for you - I'd really appreciate if you could do it on your LAN.

I can't duplicate the above - the problem in this thread is nearly the opposite (?)

The problem I (was) having is that posts with the 'new' icon were not showing up in the "show all unread" list.  I may have exchanged a solution to stop marking unread messages as read for a performance problem - but that is a choice I'm willing to make.  I'm hoping this gets addressed in the non-RC version of SMF.

Muldoon

Quote from: iowamf on March 04, 2006, 04:16:50 PM
Thanks Compuart -

I tried this and so far - so good! No error messages either.

I don't know what this is going to do to performance - but I'm just testing for now and I'm more concerned with functionality than performance.

Keeping "unread" messages in the "unread list" is a good thing  ;)

Quote from: Compuart on December 21, 2005, 02:06:02 PM
In that case try (without the previous changes) adding before:
Code (Display.php) Select
// Have we recently cached the number of new topics in this board, and it's still a lot?
this:
$_REQUEST['topicseen'] = true;
if (isset($_REQUEST['boardseen']))
unset($_REQUEST['boardseen']);



Remove this again:
Code (MessageIndex.php) Select
db_query("
REPLACE INTO {$db_prefix}log_boards
(logTime, ID_MEMBER, ID_BOARD)
VALUES (" . time() . ", $ID_MEMBER, $board)", __FILE__, __LINE__);
if (!empty($board_info['parent_boards']))
{
db_query("
UPDATE {$db_prefix}log_boards
SET logTime = " . time() . "
WHERE ID_MEMBER = $ID_MEMBER
AND ID_BOARD IN (" . implode(',', array_keys($board_info['parent_boards'])) . ")
LIMIT " . count($board_info['parent_boards']), __FILE__, __LINE__);

// We've seen all these boards now!
foreach ($board_info['parent_boards'] as $k => $dummy)
{
if (isset($_SESSION['topicseen_cache'][$k]))
unset($_SESSION['topicseen_cache'][$k]);
}
}



I think this should result in the desired behaviour (untested though), that is, marking topics as seen instead of boards.

iowamf...so this worked for you? I am having the same problem right now:

I recently got SMF 1.1 RC3 up along w/ TP 0.9.5 beta.

For some reason, after I finish viewing 'Show unread posts since last visit' and finish viewing all those posts, it then says:

No unread topics found since your last visit. Click here to try all unread topics.

Well, when I click on 'Click here to try all unread topics', it just comes back with: No messages... when I know this is wrong as there are still plenty of posts that are still unread. What should I do next? Any help would be much appreciated.

Advertisement: