Here is what I would suggest - I am not 100% sure when the post gets flagged as "read", however the solution should be as simple as just retrieving the list of unread threads, sorting by date and grabbing the next one off the top of the list that is NOT the post the user is viewing.
Something like this should work in C# (and easily translated to Velocity since i'm using the PublicApi) - You would need to create a velocity extension to actually call this from a widget. It also does not cover error checking and also does not check if the user is logged-in, in which case we could not display them "unread" threads. I also have not tested this code.
// You will need to include these at the top of the class
public ForumThread GetNextUnread(int groupId, int currentThreadId)
var threads = PublicApi.ForumThreads.List(new ForumThreadsListOptions
ForumThreadQueryType = "Unread",
SortOrder = "Descending",
SortBy = "date",
IncludeSubGroups = true,
GroupId = groupId
var nextThread = (from t in threads where !t.Id.Equals(currentThreadId) select t).FirstOrDefault();
if (nextThread != null)