2005-12-07 jrandom

* Added a first pass at a blog view in Syndie
This commit is contained in:
jrandom
2005-12-08 00:50:32 +00:00
committed by zzz
parent 952bcc696a
commit 7beacff028
13 changed files with 239 additions and 72 deletions

View File

@ -0,0 +1,20 @@
package net.i2p.syndie;
import java.util.*;
import net.i2p.data.*;
import net.i2p.syndie.data.*;
/** sort BlogURI instances with the highest entryId first */
public class NewestEntryFirstComparator implements Comparator {
public int compare(Object lhs, Object rhs) {
BlogURI left = (BlogURI)lhs;
BlogURI right = (BlogURI)rhs;
if (left.getEntryId() > right.getEntryId()) {
return -1;
} else if (left.getEntryId() == right.getEntryId()) {
return DataHelper.compareTo(left.getKeyHash().getData(), right.getKeyHash().getData());
} else {
return 1;
}
}
}

View File

@ -0,0 +1,30 @@
package net.i2p.syndie;
import java.util.*;
import net.i2p.data.*;
/** sort ThreadNodeImpl instances with the highest entryId first */
public class NewestNodeFirstComparator implements Comparator {
public int compare(Object lhs, Object rhs) {
ThreadNodeImpl left = (ThreadNodeImpl)lhs;
ThreadNodeImpl right = (ThreadNodeImpl)rhs;
long l = left.getMostRecentPostDate();
long r = right.getMostRecentPostDate();
if (l > r) {
return -1;
} else if (l == r) {
// ok, the newest responses match, so lets fall back and compare the roots themselves
l = left.getEntry().getEntryId();
r = right.getEntry().getEntryId();
if (l > r) {
return -1;
} else if (l == r) {
return DataHelper.compareTo(left.getEntry().getKeyHash().getData(), right.getEntry().getKeyHash().getData());
} else {
return 1;
}
} else {
return 1;
}
}
}

View File

@ -80,7 +80,7 @@ class ThreadNodeImpl implements ThreadNode {
}
// now reorder the children
TreeSet ordered = new TreeSet(new WritableThreadIndex.NewestNodeFirstComparator());
TreeSet ordered = new TreeSet(new NewestNodeFirstComparator());
for (int i = 0; i < _children.size(); i++) {
ThreadNodeImpl kid = (ThreadNodeImpl)_children.get(i);
ordered.add(kid);

View File

@ -136,44 +136,4 @@ class WritableThreadIndex extends ThreadIndex {
buf.append("</threadIndex>\n");
return buf.toString();
}
/** sort BlogURI instances with the highest entryId first */
private class NewestEntryFirstComparator implements Comparator {
public int compare(Object lhs, Object rhs) {
BlogURI left = (BlogURI)lhs;
BlogURI right = (BlogURI)rhs;
if (left.getEntryId() > right.getEntryId()) {
return -1;
} else if (left.getEntryId() == right.getEntryId()) {
return DataHelper.compareTo(left.getKeyHash().getData(), right.getKeyHash().getData());
} else {
return 1;
}
}
}
/** sort ThreadNodeImpl instances with the highest entryId first */
public static class NewestNodeFirstComparator implements Comparator {
public int compare(Object lhs, Object rhs) {
ThreadNodeImpl left = (ThreadNodeImpl)lhs;
ThreadNodeImpl right = (ThreadNodeImpl)rhs;
long l = left.getMostRecentPostDate();
long r = right.getMostRecentPostDate();
if (l > r) {
return -1;
} else if (l == r) {
// ok, the newest responses match, so lets fall back and compare the roots themselves
l = left.getEntry().getEntryId();
r = right.getEntry().getEntryId();
if (l > r) {
return -1;
} else if (l == r) {
return DataHelper.compareTo(left.getEntry().getKeyHash().getData(), right.getEntry().getKeyHash().getData());
} else {
return 1;
}
} else {
return 1;
}
}
}
}

View File

@ -16,11 +16,12 @@ public class FilteredThreadIndex extends ThreadIndex {
private List _roots;
private List _ignoredAuthors;
private Collection _filteredAuthors;
private boolean _filterAuthorsByRoot;
public static final String GROUP_FAVORITE = "Favorite";
public static final String GROUP_IGNORE = "Ignore";
public FilteredThreadIndex(User user, Archive archive, Collection tags, Collection authors) {
public FilteredThreadIndex(User user, Archive archive, Collection tags, Collection authors, boolean filterAuthorsByRoot) {
super();
_user = user;
_archive = archive;
@ -31,6 +32,7 @@ public class FilteredThreadIndex extends ThreadIndex {
_filteredAuthors = authors;
if (_filteredAuthors == null)
_filteredAuthors = Collections.EMPTY_SET;
_filterAuthorsByRoot = filterAuthorsByRoot;
_ignoredAuthors = new ArrayList();
for (Iterator iter = user.getPetNameDB().iterator(); iter.hasNext(); ) {
@ -53,12 +55,12 @@ public class FilteredThreadIndex extends ThreadIndex {
_roots = new ArrayList(_baseIndex.getRootCount());
for (int i = 0; i < _baseIndex.getRootCount(); i++) {
ThreadNode node = _baseIndex.getRoot(i);
if (!isIgnored(node, _ignoredAuthors, _filteredTags, _filteredAuthors))
if (!isIgnored(node, _ignoredAuthors, _filteredTags, _filteredAuthors, _filterAuthorsByRoot))
_roots.add(node);
}
}
private boolean isIgnored(ThreadNode node, List ignoredAuthors, Collection requestedTags, Collection filteredAuthors) {
private boolean isIgnored(ThreadNode node, List ignoredAuthors, Collection requestedTags, Collection filteredAuthors, boolean filterAuthorsByRoot) {
if (filteredAuthors.size() <= 0) {
boolean allAuthorsIgnored = true;
for (Iterator iter = node.getRecursiveAuthorIterator(); iter.hasNext(); ) {
@ -75,9 +77,16 @@ public class FilteredThreadIndex extends ThreadIndex {
boolean filteredAuthorMatches = false;
for (Iterator iter = filteredAuthors.iterator(); iter.hasNext(); ) {
Hash author = (Hash)iter.next();
if (node.containsAuthor(author)) {
filteredAuthorMatches = true;
break;
if (filterAuthorsByRoot) {
if (node.getEntry().getKeyHash().equals(author)) {
filteredAuthorMatches = true;
break;
}
} else {
if (node.containsAuthor(author)) {
filteredAuthorMatches = true;
break;
}
}
}
if (!filteredAuthorMatches)
@ -107,4 +116,5 @@ public class FilteredThreadIndex extends ThreadIndex {
public ThreadNode getNode(BlogURI uri) { return _baseIndex.getNode(uri); }
public Collection getFilteredTags() { return _filteredTags; }
public Collection getFilteredAuthors() { return _filteredAuthors; }
public boolean getFilterAuthorsByRoot() { return _filterAuthorsByRoot; }
}

View File

@ -41,7 +41,10 @@ public class ThreadedHTMLRenderer extends HTMLRenderer {
/** index into the nav tree to start displaying */
public static final String PARAM_OFFSET = "offset";
public static final String PARAM_TAGS = "tags";
/** only show threads that the given author participates in */
public static final String PARAM_AUTHOR = "author";
/** only show threads started by the given author */
public static final String PARAM_THREAD_AUTHOR = "threadAuthorOnly";
/** search back through the blog for entries this many days */
public static final String PARAM_DAYS_BACK = "daysBack";
// parameters for editing one's profile
@ -94,7 +97,7 @@ public class ThreadedHTMLRenderer extends HTMLRenderer {
return buf.toString();
}
public static String getNavLink(String uri, String viewPost, String viewThread, String tags, String author, int offset) {
public static String getNavLink(String uri, String viewPost, String viewThread, String tags, String author, boolean authorOnly, int offset) {
StringBuffer buf = new StringBuffer(64);
buf.append(uri);
buf.append('?');
@ -106,8 +109,11 @@ public class ThreadedHTMLRenderer extends HTMLRenderer {
if (!empty(tags))
buf.append(PARAM_TAGS).append('=').append(tags).append('&');
if (!empty(author))
if (!empty(author)) {
buf.append(PARAM_AUTHOR).append('=').append(author).append('&');
if (authorOnly)
buf.append(PARAM_THREAD_AUTHOR).append("=true&");
}
buf.append(PARAM_OFFSET).append('=').append(offset).append('&');
@ -115,7 +121,7 @@ public class ThreadedHTMLRenderer extends HTMLRenderer {
}
public static String getViewPostLink(String uri, ThreadNode node, User user, boolean isPermalink,
String offset, String tags, String author) {
String offset, String tags, String author, boolean authorOnly) {
StringBuffer buf = new StringBuffer(64);
buf.append(uri);
if (node.getChildCount() > 0) {
@ -137,15 +143,19 @@ public class ThreadedHTMLRenderer extends HTMLRenderer {
buf.append(PARAM_OFFSET).append('=').append(offset).append('&');
if (!empty(tags))
buf.append(PARAM_TAGS).append('=').append(tags).append('&');
if (!empty(author))
buf.append(PARAM_AUTHOR).append('=').append(author).append('&');
}
if (authorOnly && !empty(author)) {
buf.append(PARAM_AUTHOR).append('=').append(author).append('&');
buf.append(PARAM_THREAD_AUTHOR).append("=true&");
} else if (!isPermalink && !empty(author))
buf.append(PARAM_AUTHOR).append('=').append(author).append('&');
return buf.toString();
}
public static String getViewPostLink(String uri, BlogURI post, User user, boolean isPermalink,
String offset, String tags, String author) {
String offset, String tags, String author, boolean authorOnly) {
StringBuffer buf = new StringBuffer(64);
buf.append(uri);
buf.append('?').append(PARAM_VISIBLE).append('=');
@ -160,8 +170,11 @@ public class ThreadedHTMLRenderer extends HTMLRenderer {
buf.append(PARAM_OFFSET).append('=').append(offset).append('&');
if (!empty(tags))
buf.append(PARAM_TAGS).append('=').append(tags).append('&');
if (!empty(author))
if (!empty(author)) {
buf.append(PARAM_AUTHOR).append('=').append(author).append('&');
if (authorOnly)
buf.append(PARAM_THREAD_AUTHOR).append("=true&");
}
}
return buf.toString();
@ -174,7 +187,7 @@ public class ThreadedHTMLRenderer extends HTMLRenderer {
*/
public void render(User user, Writer out, Archive archive, BlogURI post,
boolean inlineReply, ThreadIndex index, String baseURI, String replyHiddenFields,
String offset, String requestTags, String filteredAuthor) throws IOException {
String offset, String requestTags, String filteredAuthor, boolean authorOnly) throws IOException {
EntryContainer entry = archive.getEntry(post);
if (entry == null) return;
_entry = entry;
@ -255,7 +268,7 @@ public class ThreadedHTMLRenderer extends HTMLRenderer {
}
out.write("\n<a href=\"");
out.write(getViewPostLink(baseURI, node, user, true, offset, requestTags, filteredAuthor));
out.write(getViewPostLink(baseURI, node, user, true, offset, requestTags, filteredAuthor, authorOnly));
out.write("\" title=\"Select a shareable link directly to this post\">permalink</a>\n");

View File

@ -152,12 +152,20 @@ public abstract class BaseServlet extends HttpServlet {
FilteredThreadIndex index = (FilteredThreadIndex)req.getSession().getAttribute("threadIndex");
boolean authorOnly = Boolean.valueOf(req.getParameter(ThreadedHTMLRenderer.PARAM_THREAD_AUTHOR)).booleanValue();
if ( (index != null) && (authorOnly != index.getFilterAuthorsByRoot()) )
forceNewIndex = true;
Collection tags = getFilteredTags(req);
Collection filteredAuthors = getFilteredAuthors(req);
boolean tagsChanged = ( (index != null) && (!index.getFilteredTags().equals(tags)) );
boolean authorsChanged = ( (index != null) && (!index.getFilteredAuthors().equals(filteredAuthors)) );
if (_log.shouldLog(Log.DEBUG))
_log.debug("authorOnly=" + authorOnly + " forceNewIndex? " + forceNewIndex + " authors=" + filteredAuthors);
if (forceNewIndex || (index == null) || (tagsChanged) || (authorsChanged) ) {
index = new FilteredThreadIndex(user, BlogManager.instance().getArchive(), getFilteredTags(req), filteredAuthors);
index = new FilteredThreadIndex(user, BlogManager.instance().getArchive(), getFilteredTags(req), filteredAuthors, authorOnly);
req.getSession().setAttribute("threadIndex", index);
if (_log.shouldLog(Log.INFO))
_log.info("New filtered index created (forced? " + forceNewIndex + ", tagsChanged? " + tagsChanged + ", authorsChanged? " + authorsChanged + ")");
@ -561,7 +569,7 @@ public abstract class BaseServlet extends HttpServlet {
//out.write("<tr class=\"topNav\"><td class=\"topNav_user\" colspan=\"2\" nowrap=\"true\">\n");
out.write("<tr class=\"topNav\"><td colspan=\"3\" nowrap=\"true\"><span class=\"topNav_user\">\n");
out.write("<!-- nav bar begin -->\n");
out.write("<a href=\"threads.jsp\" title=\"Syndie home\">Home</a> ");
out.write("<a href=\"threads.jsp\" title=\"Syndie home\">Home</a> <a href=\"blogs.jsp\" title=\"Blog summary\">Blogs</a> ");
if (user.getAuthenticated() && (user.getBlog() != null) ) {
out.write("Logged in as <a href=\"" + getProfileLink(req, user.getBlog()) + "\" title=\"Edit your profile\">");
out.write(user.getUsername());
@ -933,22 +941,25 @@ public abstract class BaseServlet extends HttpServlet {
return ThreadedHTMLRenderer.getViewPostLink(req.getRequestURI(), node, user, isPermalink,
req.getParameter(ThreadedHTMLRenderer.PARAM_OFFSET),
req.getParameter(ThreadedHTMLRenderer.PARAM_TAGS),
req.getParameter(ThreadedHTMLRenderer.PARAM_AUTHOR));
req.getParameter(ThreadedHTMLRenderer.PARAM_AUTHOR),
Boolean.valueOf(req.getParameter(ThreadedHTMLRenderer.PARAM_THREAD_AUTHOR)).booleanValue());
}
protected String getViewPostLink(HttpServletRequest req, BlogURI post, User user) {
return ThreadedHTMLRenderer.getViewPostLink(req.getRequestURI(), post, user, false,
req.getParameter(ThreadedHTMLRenderer.PARAM_OFFSET),
req.getParameter(ThreadedHTMLRenderer.PARAM_TAGS),
req.getParameter(ThreadedHTMLRenderer.PARAM_AUTHOR));
req.getParameter(ThreadedHTMLRenderer.PARAM_AUTHOR),
Boolean.valueOf(req.getParameter(ThreadedHTMLRenderer.PARAM_THREAD_AUTHOR)).booleanValue());
}
protected String getViewThreadLink(HttpServletRequest req, ThreadNode node, User user) {
return getViewThreadLink(req.getRequestURI(), node, user,
req.getParameter(ThreadedHTMLRenderer.PARAM_OFFSET),
req.getParameter(ThreadedHTMLRenderer.PARAM_TAGS),
req.getParameter(ThreadedHTMLRenderer.PARAM_AUTHOR));
req.getParameter(ThreadedHTMLRenderer.PARAM_AUTHOR),
Boolean.valueOf(req.getParameter(ThreadedHTMLRenderer.PARAM_THREAD_AUTHOR)).booleanValue());
}
protected static String getViewThreadLink(String uri, ThreadNode node, User user, String offset,
String tags, String author) {
String tags, String author, boolean authorOnly) {
StringBuffer buf = new StringBuffer(64);
buf.append(uri);
BlogURI expandTo = node.getEntry();
@ -975,8 +986,11 @@ public abstract class BaseServlet extends HttpServlet {
if (!empty(tags))
buf.append(ThreadedHTMLRenderer.PARAM_TAGS).append('=').append(tags).append('&');
if (!empty(author))
if (!empty(author)) {
buf.append(ThreadedHTMLRenderer.PARAM_AUTHOR).append('=').append(author).append('&');
if (authorOnly)
buf.append(ThreadedHTMLRenderer.PARAM_THREAD_AUTHOR).append("=true&");
}
buf.append("#").append(node.getEntry().toString());
return buf.toString();
@ -990,6 +1004,7 @@ public abstract class BaseServlet extends HttpServlet {
req.getParameter(ThreadedHTMLRenderer.PARAM_VIEW_THREAD),
req.getParameter(ThreadedHTMLRenderer.PARAM_TAGS),
req.getParameter(ThreadedHTMLRenderer.PARAM_AUTHOR),
Boolean.valueOf(req.getParameter(ThreadedHTMLRenderer.PARAM_THREAD_AUTHOR)).booleanValue(),
offset);
}
@ -1014,7 +1029,13 @@ public abstract class BaseServlet extends HttpServlet {
}
protected Collection getFilteredAuthors(HttpServletRequest req) {
String authors = req.getParameter(ThreadedHTMLRenderer.PARAM_AUTHOR);
List rv = new ArrayList();
rv.addAll(getAuthors(req.getParameter(ThreadedHTMLRenderer.PARAM_AUTHOR)));
//rv.addAll(getAuthors(req.getParameter(ThreadedHTMLRenderer.PARAM_THREAD_AUTHOR)));
return rv;
}
private Collection getAuthors(String authors) {
if (authors != null) {
StringTokenizer tok = new StringTokenizer(authors, "\n\t ");
ArrayList rv = new ArrayList();

View File

@ -103,14 +103,13 @@ public class ProfileServlet extends BaseServlet {
}
private void renderProfile(User user, String baseURI, PrintWriter out, Hash author, Archive archive) throws IOException {
out.write("<tr><td colspan=\"3\">Profile for <a href=\"" + getControlTarget() + "?"
+ ThreadedHTMLRenderer.PARAM_AUTHOR + '=' + author.toBase64()
+ "\" title=\"View threads by the profiled author\">");
out.write("<tr><td colspan=\"3\">Profile for ");
PetName pn = user.getPetNameDB().getByLocation(author.toBase64());
String name = null;
BlogInfo info = archive.getBlogInfo(author);
if (pn != null) {
out.write(pn.getName());
String name = null;
name = null;
if (info != null)
name = info.getProperty(BlogInfo.NAME);
@ -119,7 +118,6 @@ public class ProfileServlet extends BaseServlet {
out.write(" (" + name + ")");
} else {
String name = null;
if (info != null)
name = info.getProperty(BlogInfo.NAME);
@ -130,6 +128,12 @@ public class ProfileServlet extends BaseServlet {
out.write("</a>");
if (info != null)
out.write(" [edition " + info.getEdition() + "]");
out.write("<br />\n");
out.write("<a href=\"" + getControlTarget() + "?" + ThreadedHTMLRenderer.PARAM_AUTHOR
+ '=' + author.toBase64() + "&" + ThreadedHTMLRenderer.PARAM_THREAD_AUTHOR + "=true&\""
+ " title=\"View '" + HTMLRenderer.sanitizeTagParam(name) + "'s blog\">View their blog</a> or ");
out.write("<a href=\"" + getControlTarget() + "?" + ThreadedHTMLRenderer.PARAM_AUTHOR
+ '=' + author.toBase64() + "&\">threads they have participated in</a>\n");
out.write("</td></tr>\n");
out.write("<tr><td colspan=\"3\"><hr /></td></tr>\n");

View File

@ -60,7 +60,7 @@ public class RSSServlet extends HttpServlet {
if (count > 100) count = 100;
Archive archive = BlogManager.instance().getArchive();
FilteredThreadIndex index = new FilteredThreadIndex(user, archive, tagSet, null);
FilteredThreadIndex index = new FilteredThreadIndex(user, archive, tagSet, null, false);
List entries = new ArrayList();
// depth first search of the most recent threads
for (int i = 0; i < count && i < index.getRootCount(); i++) {

View File

@ -0,0 +1,95 @@
package net.i2p.syndie.web;
import java.io.*;
import java.util.*;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import net.i2p.I2PAppContext;
import net.i2p.client.naming.*;
import net.i2p.data.*;
import net.i2p.syndie.*;
import net.i2p.syndie.data.*;
import net.i2p.syndie.sml.*;
/**
* List the blogs known in the archive
*
*/
public class ViewBlogsServlet extends BaseServlet {
private static final int MAX_AUTHORS_AT_ONCE = 100;
private static final int MAX_TAGS = 50;
protected void renderServletDetails(User user, HttpServletRequest req, PrintWriter out, ThreadIndex index,
int threadOffset, BlogURI visibleEntry, Archive archive) throws IOException {
TreeSet orderedRoots = new TreeSet(new NewestEntryFirstComparator());
// The thread index is ordered by last updated date, as opposed to root posting date,
// so lets reorder things
int count = index.getRootCount();
for (int i = 0; i < count; i++) {
ThreadNode node = index.getRoot(i);
orderedRoots.add(node.getEntry());
}
TreeSet tags = new TreeSet();
List writtenAuthors = new ArrayList();
out.write("<tr><td colspan=\"3\"><b>Blogs:</b></td></tr>\n");
out.write("<tr><td colspan=\"3\">");
for (Iterator iter = orderedRoots.iterator(); iter.hasNext() && writtenAuthors.size() < MAX_AUTHORS_AT_ONCE; ) {
BlogURI uri= (BlogURI)iter.next();
String curTags[] = archive.getEntry(uri).getTags();
if (curTags != null)
for (int i = 0; i < curTags.length && tags.size() < MAX_TAGS; i++)
tags.add(curTags[i]);
if (writtenAuthors.contains(uri.getKeyHash())) {
// skip
} else {
BlogInfo info = archive.getBlogInfo(uri);
if (info == null)
continue;
String name = info.getProperty(BlogInfo.NAME);
if ( (name == null) || (name.trim().length() <= 0) )
name = uri.getKeyHash().toBase64().substring(0,8);
String desc = info.getProperty(BlogInfo.DESCRIPTION);
if ( (desc == null) || (desc.trim().length() <= 0) )
desc = name + "'s blog";
String age = null;
long dayBegin = BlogManager.instance().getDayBegin();
long postId = uri.getEntryId();
if (postId >= dayBegin) {
age = "today";
} else if (postId >= dayBegin - 24*60*60*1000) {
age = "yesterday";
} else {
int daysAgo = (int)((dayBegin - postId + 24*60*60*1000-1)/(24*60*60*1000));
age = daysAgo + " days ago";
}
out.write("<a href=\"" + getControlTarget() + "?"
+ ThreadedHTMLRenderer.PARAM_AUTHOR + '=' + uri.getKeyHash().toBase64()
+ "&" + ThreadedHTMLRenderer.PARAM_THREAD_AUTHOR + "=true&"
+ "\" title=\"Posts by " + trim(HTMLRenderer.sanitizeTagParam(name), 32)
+ ", last post " + age + "\">");
out.write(HTMLRenderer.sanitizeString(desc, 32));
out.write("</a> \n");
writtenAuthors.add(uri.getKeyHash());
}
}
out.write("</td></tr>\n");
out.write("<tr><td colspan=\"3\"><b>Topics:</b></td></tr>\n");
out.write("<tr><td colspan=\"3\">");
for (Iterator iter = tags.iterator(); iter.hasNext(); ) {
String tag = (String)iter.next();
out.write("<a href=\"" + getFilterByTagLink(req, null, user, tag, null)
+ "\" title=\"View threads flagged with the tag '" + HTMLRenderer.sanitizeTagParam(tag) + "'\">");
out.write(HTMLRenderer.sanitizeString(tag, 32));
out.write("</a> ");
}
out.write("</td></tr>\n");
}
protected String getTitle() { return "Syndie :: View blogs"; }
}

View File

@ -36,13 +36,15 @@ public class ViewThreadedServlet extends BaseServlet {
String off = req.getParameter(ThreadedHTMLRenderer.PARAM_OFFSET);
String tags = req.getParameter(ThreadedHTMLRenderer.PARAM_TAGS);
String author = req.getParameter(ThreadedHTMLRenderer.PARAM_AUTHOR);
boolean authorOnly = Boolean.valueOf(req.getParameter(ThreadedHTMLRenderer.PARAM_THREAD_AUTHOR)).booleanValue();
for (int i = 0; i < posts.size(); i++) {
BlogURI post = (BlogURI)posts.get(i);
boolean inlineReply = (posts.size() == 1);
//if (true)
// inlineReply = true;
renderer.render(user, out, archive, post, inlineReply, index, uri, getAuthActionFields(), off, tags, author);
renderer.render(user, out, archive, post, inlineReply, index, uri, getAuthActionFields(), off, tags, author, authorOnly);
}
}

View File

@ -64,6 +64,11 @@
<servlet-class>net.i2p.syndie.web.ThreadNavServlet</servlet-class>
</servlet>
<servlet>
<servlet-name>net.i2p.syndie.web.ViewBlogsServlet</servlet-name>
<servlet-class>net.i2p.syndie.web.ViewBlogsServlet</servlet-class>
</servlet>
<servlet>
<servlet-name>net.i2p.syndie.UpdaterServlet</servlet-name>
<servlet-class>net.i2p.syndie.UpdaterServlet</servlet-class>
@ -126,6 +131,10 @@
<servlet-name>net.i2p.syndie.web.ThreadNavServlet</servlet-name>
<url-pattern>/threadnav/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>net.i2p.syndie.web.ViewBlogsServlet</servlet-name>
<url-pattern>/blogs.jsp</url-pattern>
</servlet-mapping>
<session-config>
<session-timeout>

View File

@ -1,4 +1,7 @@
$Id: history.txt,v 1.348 2005/12/05 01:14:16 jrandom Exp $
$Id: history.txt,v 1.349 2005/12/07 15:19:43 jrandom Exp $
2005-12-07 jrandom
* Added a first pass at a blog view in Syndie
2005-12-07 jrandom
* Expand the thread we're viewing to its leaf