diff --git a/apps/syndie/java/src/net/i2p/syndie/NewestEntryFirstComparator.java b/apps/syndie/java/src/net/i2p/syndie/NewestEntryFirstComparator.java new file mode 100644 index 0000000000000000000000000000000000000000..21304ef7a412baf6a8aa8ddbbb39d31b08ee168c --- /dev/null +++ b/apps/syndie/java/src/net/i2p/syndie/NewestEntryFirstComparator.java @@ -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; + } + } +} diff --git a/apps/syndie/java/src/net/i2p/syndie/NewestNodeFirstComparator.java b/apps/syndie/java/src/net/i2p/syndie/NewestNodeFirstComparator.java new file mode 100644 index 0000000000000000000000000000000000000000..6046bf0c7fb8c9494ce299e5ed59fae27590d6b1 --- /dev/null +++ b/apps/syndie/java/src/net/i2p/syndie/NewestNodeFirstComparator.java @@ -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; + } + } +} diff --git a/apps/syndie/java/src/net/i2p/syndie/ThreadNodeImpl.java b/apps/syndie/java/src/net/i2p/syndie/ThreadNodeImpl.java index 891d1f5b612e8fe2eca6d2d1410c9f6ea8f94d55..406ca10e4e63a0c5f91210c061cbcf3a30b95cf7 100644 --- a/apps/syndie/java/src/net/i2p/syndie/ThreadNodeImpl.java +++ b/apps/syndie/java/src/net/i2p/syndie/ThreadNodeImpl.java @@ -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); diff --git a/apps/syndie/java/src/net/i2p/syndie/WritableThreadIndex.java b/apps/syndie/java/src/net/i2p/syndie/WritableThreadIndex.java index 224e03710b538e532c93cc556368e7d1c67a8796..06ffc8e35f67d0b1f49f1ae1d441bbb557b891df 100644 --- a/apps/syndie/java/src/net/i2p/syndie/WritableThreadIndex.java +++ b/apps/syndie/java/src/net/i2p/syndie/WritableThreadIndex.java @@ -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; - } - } - } } diff --git a/apps/syndie/java/src/net/i2p/syndie/data/FilteredThreadIndex.java b/apps/syndie/java/src/net/i2p/syndie/data/FilteredThreadIndex.java index fb9dde971684a7f3bcbffb0a43164a4d73313002..eeaa9ee8008bfe8afd32854c6001b06b7bc76272 100644 --- a/apps/syndie/java/src/net/i2p/syndie/data/FilteredThreadIndex.java +++ b/apps/syndie/java/src/net/i2p/syndie/data/FilteredThreadIndex.java @@ -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; } } diff --git a/apps/syndie/java/src/net/i2p/syndie/sml/ThreadedHTMLRenderer.java b/apps/syndie/java/src/net/i2p/syndie/sml/ThreadedHTMLRenderer.java index ad21c196b097c44f3e62efcede4c5640ecd9f213..f981214eaa734e93e51ddb7aa11ccb02d8b12dad 100644 --- a/apps/syndie/java/src/net/i2p/syndie/sml/ThreadedHTMLRenderer.java +++ b/apps/syndie/java/src/net/i2p/syndie/sml/ThreadedHTMLRenderer.java @@ -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"); diff --git a/apps/syndie/java/src/net/i2p/syndie/web/BaseServlet.java b/apps/syndie/java/src/net/i2p/syndie/web/BaseServlet.java index 8c5c809914fde1daa37d44c992b6bfde36ff3064..65e7e078e155f808fd2028ff39a9e7c4388cfc51 100644 --- a/apps/syndie/java/src/net/i2p/syndie/web/BaseServlet.java +++ b/apps/syndie/java/src/net/i2p/syndie/web/BaseServlet.java @@ -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(); diff --git a/apps/syndie/java/src/net/i2p/syndie/web/ProfileServlet.java b/apps/syndie/java/src/net/i2p/syndie/web/ProfileServlet.java index 0432298d35957698959d7c6ceac61a19a83dd831..2e82b6fb71c6e2095acb5a9045187f0766b29974 100644 --- a/apps/syndie/java/src/net/i2p/syndie/web/ProfileServlet.java +++ b/apps/syndie/java/src/net/i2p/syndie/web/ProfileServlet.java @@ -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"); diff --git a/apps/syndie/java/src/net/i2p/syndie/web/RSSServlet.java b/apps/syndie/java/src/net/i2p/syndie/web/RSSServlet.java index d0e1940103a7bce8f8a42082b21f332ff320da7d..12e9ccf62c845ce9dbdb1cc7310820b2ba5a1957 100644 --- a/apps/syndie/java/src/net/i2p/syndie/web/RSSServlet.java +++ b/apps/syndie/java/src/net/i2p/syndie/web/RSSServlet.java @@ -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++) { diff --git a/apps/syndie/java/src/net/i2p/syndie/web/ViewBlogsServlet.java b/apps/syndie/java/src/net/i2p/syndie/web/ViewBlogsServlet.java new file mode 100644 index 0000000000000000000000000000000000000000..571e54314e54b441182268e5d48039c0906b99bf --- /dev/null +++ b/apps/syndie/java/src/net/i2p/syndie/web/ViewBlogsServlet.java @@ -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"; } +} diff --git a/apps/syndie/java/src/net/i2p/syndie/web/ViewThreadedServlet.java b/apps/syndie/java/src/net/i2p/syndie/web/ViewThreadedServlet.java index ce6c3c86d90e47ccd11514ecc44a33589f59c352..23b4ea0d2a80f33d013e624365ca34a78fb6d88d 100644 --- a/apps/syndie/java/src/net/i2p/syndie/web/ViewThreadedServlet.java +++ b/apps/syndie/java/src/net/i2p/syndie/web/ViewThreadedServlet.java @@ -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); } } diff --git a/apps/syndie/jsp/web.xml b/apps/syndie/jsp/web.xml index d4d7ea68e9820792500627cab47933f963418026..6a57e60a383d2684fa15ec9278c3a7f1796277e1 100644 --- a/apps/syndie/jsp/web.xml +++ b/apps/syndie/jsp/web.xml @@ -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> diff --git a/history.txt b/history.txt index 4225774f77a75fa5cf4a1477b9c5b3fa49e85cd3..22ea816add44057df3037a0e27da5f2a8edd6319 100644 --- a/history.txt +++ b/history.txt @@ -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