X-Git-Url: https://git.pterodactylus.net/?p=Sone.git;a=blobdiff_plain;f=src%2Fmain%2Fjava%2Fnet%2Fpterodactylus%2Fsone%2Fweb%2FWebInterface.java;h=d4f3f5587b61eb71526a6a75d7afa9b707a0717a;hp=faba61f1dd35605a589fec60022c07dc9d72fcdf;hb=6a3f1fede0cda5cd6ed56204aa1dd37a19813cb9;hpb=d57efd02c9b81e00a94098eb6e4c9ab9cf0d449f diff --git a/src/main/java/net/pterodactylus/sone/web/WebInterface.java b/src/main/java/net/pterodactylus/sone/web/WebInterface.java index faba61f..d4f3f55 100644 --- a/src/main/java/net/pterodactylus/sone/web/WebInterface.java +++ b/src/main/java/net/pterodactylus/sone/web/WebInterface.java @@ -1,5 +1,5 @@ /* - * Sone - WebInterface.java - Copyright © 2010–2013 David Roden + * Sone - WebInterface.java - Copyright © 2010–2019 David Roden * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -17,29 +17,29 @@ package net.pterodactylus.sone.web; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.Reader; +import static com.google.common.collect.FluentIterable.from; +import static java.util.logging.Logger.getLogger; +import static net.pterodactylus.util.template.TemplateParser.parse; + import java.io.StringReader; -import java.io.UnsupportedEncodingException; -import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; -import java.util.List; import java.util.Map; import java.util.Set; +import java.util.TimeZone; import java.util.UUID; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledFuture; import java.util.concurrent.TimeUnit; -import java.util.logging.Level; import java.util.logging.Logger; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; import net.pterodactylus.sone.core.Core; +import net.pterodactylus.sone.core.ElementLoader; import net.pterodactylus.sone.core.event.ImageInsertAbortedEvent; import net.pterodactylus.sone.core.event.ImageInsertFailedEvent; import net.pterodactylus.sone.core.event.ImageInsertFinishedEvent; @@ -59,40 +59,28 @@ import net.pterodactylus.sone.core.event.SoneLockedEvent; import net.pterodactylus.sone.core.event.SoneRemovedEvent; import net.pterodactylus.sone.core.event.SoneUnlockedEvent; import net.pterodactylus.sone.core.event.UpdateFoundEvent; -import net.pterodactylus.sone.data.Album; import net.pterodactylus.sone.data.Image; import net.pterodactylus.sone.data.Post; import net.pterodactylus.sone.data.PostReply; -import net.pterodactylus.sone.data.Profile; -import net.pterodactylus.sone.data.Reply; import net.pterodactylus.sone.data.Sone; import net.pterodactylus.sone.freenet.L10nFilter; -import net.pterodactylus.sone.freenet.wot.Identity; -import net.pterodactylus.sone.freenet.wot.Trust; +import net.pterodactylus.sone.main.Loaders; +import net.pterodactylus.sone.main.PluginHomepage; +import net.pterodactylus.sone.main.PluginVersion; +import net.pterodactylus.sone.main.PluginYear; import net.pterodactylus.sone.main.SonePlugin; import net.pterodactylus.sone.notify.ListNotification; -import net.pterodactylus.sone.template.AlbumAccessor; -import net.pterodactylus.sone.template.CollectionAccessor; -import net.pterodactylus.sone.template.CssClassNameFilter; -import net.pterodactylus.sone.template.HttpRequestAccessor; -import net.pterodactylus.sone.template.IdentityAccessor; -import net.pterodactylus.sone.template.ImageAccessor; -import net.pterodactylus.sone.template.ImageLinkFilter; -import net.pterodactylus.sone.template.JavascriptFilter; +import net.pterodactylus.sone.notify.ListNotificationFilter; +import net.pterodactylus.sone.notify.PostVisibilityFilter; +import net.pterodactylus.sone.notify.ReplyVisibilityFilter; +import net.pterodactylus.sone.template.LinkedElementRenderFilter; import net.pterodactylus.sone.template.ParserFilter; -import net.pterodactylus.sone.template.PostAccessor; -import net.pterodactylus.sone.template.ProfileAccessor; -import net.pterodactylus.sone.template.ReplyAccessor; -import net.pterodactylus.sone.template.ReplyGroupFilter; -import net.pterodactylus.sone.template.RequestChangeFilter; -import net.pterodactylus.sone.template.SoneAccessor; -import net.pterodactylus.sone.template.SubstringFilter; -import net.pterodactylus.sone.template.TrustAccessor; -import net.pterodactylus.sone.template.UniqueElementFilter; -import net.pterodactylus.sone.template.UnknownDateFilter; +import net.pterodactylus.sone.template.RenderFilter; +import net.pterodactylus.sone.template.ShortenFilter; import net.pterodactylus.sone.text.Part; import net.pterodactylus.sone.text.SonePart; import net.pterodactylus.sone.text.SoneTextParser; +import net.pterodactylus.sone.text.TimeTextConverter; import net.pterodactylus.sone.web.ajax.BookmarkAjaxPage; import net.pterodactylus.sone.web.ajax.CreatePostAjaxPage; import net.pterodactylus.sone.web.ajax.CreateReplyAjaxPage; @@ -106,12 +94,13 @@ import net.pterodactylus.sone.web.ajax.EditImageAjaxPage; import net.pterodactylus.sone.web.ajax.EditProfileFieldAjaxPage; import net.pterodactylus.sone.web.ajax.FollowSoneAjaxPage; import net.pterodactylus.sone.web.ajax.GetLikesAjaxPage; +import net.pterodactylus.sone.web.ajax.GetLinkedElementAjaxPage; import net.pterodactylus.sone.web.ajax.GetNotificationsAjaxPage; import net.pterodactylus.sone.web.ajax.GetPostAjaxPage; import net.pterodactylus.sone.web.ajax.GetReplyAjaxPage; import net.pterodactylus.sone.web.ajax.GetStatusAjaxPage; import net.pterodactylus.sone.web.ajax.GetTimesAjaxPage; -import net.pterodactylus.sone.web.ajax.GetTranslationPage; +import net.pterodactylus.sone.web.ajax.GetTranslationAjaxPage; import net.pterodactylus.sone.web.ajax.LikeAjaxPage; import net.pterodactylus.sone.web.ajax.LockSoneAjaxPage; import net.pterodactylus.sone.web.ajax.MarkAsKnownAjaxPage; @@ -123,55 +112,79 @@ import net.pterodactylus.sone.web.ajax.UnlikeAjaxPage; import net.pterodactylus.sone.web.ajax.UnlockSoneAjaxPage; import net.pterodactylus.sone.web.ajax.UntrustAjaxPage; import net.pterodactylus.sone.web.page.FreenetRequest; -import net.pterodactylus.sone.web.page.PageToadlet; -import net.pterodactylus.sone.web.page.PageToadletFactory; -import net.pterodactylus.util.logging.Logging; +import net.pterodactylus.sone.web.pages.AboutPage; +import net.pterodactylus.sone.web.pages.BookmarkPage; +import net.pterodactylus.sone.web.pages.BookmarksPage; +import net.pterodactylus.sone.web.pages.CreateAlbumPage; +import net.pterodactylus.sone.web.pages.CreatePostPage; +import net.pterodactylus.sone.web.pages.CreateReplyPage; +import net.pterodactylus.sone.web.pages.CreateSonePage; +import net.pterodactylus.sone.web.pages.DeleteAlbumPage; +import net.pterodactylus.sone.web.pages.DeleteImagePage; +import net.pterodactylus.sone.web.pages.DeletePostPage; +import net.pterodactylus.sone.web.pages.DeleteProfileFieldPage; +import net.pterodactylus.sone.web.pages.DeleteReplyPage; +import net.pterodactylus.sone.web.pages.DeleteSonePage; +import net.pterodactylus.sone.web.pages.DismissNotificationPage; +import net.pterodactylus.sone.web.pages.DistrustPage; +import net.pterodactylus.sone.web.pages.EditAlbumPage; +import net.pterodactylus.sone.web.pages.EditImagePage; +import net.pterodactylus.sone.web.pages.EditProfileFieldPage; +import net.pterodactylus.sone.web.pages.EditProfilePage; +import net.pterodactylus.sone.web.pages.FollowSonePage; +import net.pterodactylus.sone.web.pages.GetImagePage; +import net.pterodactylus.sone.web.pages.ImageBrowserPage; +import net.pterodactylus.sone.web.pages.IndexPage; +import net.pterodactylus.sone.web.pages.KnownSonesPage; +import net.pterodactylus.sone.web.pages.LikePage; +import net.pterodactylus.sone.web.pages.LockSonePage; +import net.pterodactylus.sone.web.pages.LoginPage; +import net.pterodactylus.sone.web.pages.LogoutPage; +import net.pterodactylus.sone.web.pages.MarkAsKnownPage; +import net.pterodactylus.sone.web.pages.NewPage; +import net.pterodactylus.sone.web.pages.OptionsPage; +import net.pterodactylus.sone.web.pages.RescuePage; +import net.pterodactylus.sone.web.pages.SearchPage; +import net.pterodactylus.sone.web.pages.SoneTemplatePage; +import net.pterodactylus.sone.web.pages.TrustPage; +import net.pterodactylus.sone.web.pages.UnbookmarkPage; +import net.pterodactylus.sone.web.pages.UnfollowSonePage; +import net.pterodactylus.sone.web.pages.UnlikePage; +import net.pterodactylus.sone.web.pages.UnlockSonePage; +import net.pterodactylus.sone.web.pages.UntrustPage; +import net.pterodactylus.sone.web.pages.UploadImagePage; +import net.pterodactylus.sone.web.pages.ViewPostPage; +import net.pterodactylus.sone.web.pages.ViewSonePage; import net.pterodactylus.util.notify.Notification; import net.pterodactylus.util.notify.NotificationManager; import net.pterodactylus.util.notify.TemplateNotification; -import net.pterodactylus.util.template.ClassPathTemplateProvider; -import net.pterodactylus.util.template.CollectionSortFilter; -import net.pterodactylus.util.template.ContainsFilter; -import net.pterodactylus.util.template.DateFilter; -import net.pterodactylus.util.template.FormatFilter; -import net.pterodactylus.util.template.HtmlFilter; -import net.pterodactylus.util.template.MatchFilter; -import net.pterodactylus.util.template.ModFilter; -import net.pterodactylus.util.template.PaginationFilter; -import net.pterodactylus.util.template.ReflectionAccessor; -import net.pterodactylus.util.template.ReplaceFilter; -import net.pterodactylus.util.template.StoreFilter; import net.pterodactylus.util.template.Template; import net.pterodactylus.util.template.TemplateContextFactory; -import net.pterodactylus.util.template.TemplateParser; -import net.pterodactylus.util.template.TemplateProvider; -import net.pterodactylus.util.template.XmlFilter; import net.pterodactylus.util.web.RedirectPage; -import net.pterodactylus.util.web.StaticPage; import net.pterodactylus.util.web.TemplatePage; -import com.google.common.collect.Collections2; -import com.google.common.collect.ImmutableSet; -import com.google.common.eventbus.Subscribe; -import com.google.inject.Inject; - import freenet.clients.http.SessionManager; import freenet.clients.http.SessionManager.Session; -import freenet.clients.http.ToadletContainer; import freenet.clients.http.ToadletContext; import freenet.l10n.BaseL10n; -import freenet.support.api.HTTPRequest; + +import com.google.common.base.Optional; +import com.google.common.collect.Collections2; +import com.google.common.collect.ImmutableSet; +import com.google.common.eventbus.Subscribe; +import com.google.inject.Inject; /** * Bundles functionality that a web interface of a Freenet plugin needs, e.g. * references to l10n helpers. - * - * @author David ‘Bombe’ Roden */ -public class WebInterface { +public class WebInterface implements SessionProvider { /** The logger. */ - private static final Logger logger = Logging.getLogger(WebInterface.class); + private static final Logger logger = getLogger(WebInterface.class.getName()); + + /** The loaders for templates, pages, and classpath providers. */ + private final Loaders loaders; /** The notification manager. */ private final NotificationManager notificationManager = new NotificationManager(); @@ -179,9 +192,6 @@ public class WebInterface { /** The Sone plugin. */ private final SonePlugin sonePlugin; - /** The registered toadlets. */ - private final List pageToadlets = new ArrayList(); - /** The form password. */ private final String formPassword; @@ -193,6 +203,19 @@ public class WebInterface { /** The parser filter. */ private final ParserFilter parserFilter; + private final ShortenFilter shortenFilter; + private final RenderFilter renderFilter; + + private final ListNotificationFilter listNotificationFilter; + private final PostVisibilityFilter postVisibilityFilter; + private final ReplyVisibilityFilter replyVisibilityFilter; + + private final ElementLoader elementLoader; + private final LinkedElementRenderFilter linkedElementRenderFilter; + private final TimeTextConverter timeTextConverter = new TimeTextConverter(); + private final L10nFilter l10nFilter; + + private final PageToadletRegistry pageToadletRegistry; /** The “new Sone” notification. */ private final ListNotification newSoneNotification; @@ -213,7 +236,7 @@ public class WebInterface { private final ListNotification mentionNotification; /** Notifications for sone inserts. */ - private final Map soneInsertNotifications = new HashMap(); + private final Map soneInsertNotifications = new HashMap<>(); /** Sone locked notification ticker objects. */ private final Map> lockedSonesTickerObjects = Collections.synchronizedMap(new HashMap>()); @@ -236,89 +259,66 @@ public class WebInterface { /** Scheduled executor for time-based notifications. */ private final ScheduledExecutorService ticker = Executors.newScheduledThreadPool(1); - /** - * Creates a new web interface. - * - * @param sonePlugin - * The Sone plugin - */ @Inject - public WebInterface(SonePlugin sonePlugin) { + public WebInterface(SonePlugin sonePlugin, Loaders loaders, ListNotificationFilter listNotificationFilter, + PostVisibilityFilter postVisibilityFilter, ReplyVisibilityFilter replyVisibilityFilter, + ElementLoader elementLoader, TemplateContextFactory templateContextFactory, + ParserFilter parserFilter, ShortenFilter shortenFilter, + RenderFilter renderFilter, + LinkedElementRenderFilter linkedElementRenderFilter, + PageToadletRegistry pageToadletRegistry) { this.sonePlugin = sonePlugin; + this.loaders = loaders; + this.listNotificationFilter = listNotificationFilter; + this.postVisibilityFilter = postVisibilityFilter; + this.replyVisibilityFilter = replyVisibilityFilter; + this.elementLoader = elementLoader; + this.parserFilter = parserFilter; + this.shortenFilter = shortenFilter; + this.renderFilter = renderFilter; + this.linkedElementRenderFilter = linkedElementRenderFilter; + this.pageToadletRegistry = pageToadletRegistry; formPassword = sonePlugin.pluginRespirator().getToadletContainer().getFormPassword(); soneTextParser = new SoneTextParser(getCore(), getCore()); + l10nFilter = new L10nFilter(getL10n()); - templateContextFactory = new TemplateContextFactory(); - templateContextFactory.addAccessor(Object.class, new ReflectionAccessor()); - templateContextFactory.addAccessor(Collection.class, new CollectionAccessor()); - templateContextFactory.addAccessor(Sone.class, new SoneAccessor(getCore())); - templateContextFactory.addAccessor(Post.class, new PostAccessor(getCore())); - templateContextFactory.addAccessor(Reply.class, new ReplyAccessor(getCore())); - templateContextFactory.addAccessor(Album.class, new AlbumAccessor()); - templateContextFactory.addAccessor(Image.class, new ImageAccessor()); - templateContextFactory.addAccessor(Identity.class, new IdentityAccessor(getCore())); - templateContextFactory.addAccessor(Trust.class, new TrustAccessor()); - templateContextFactory.addAccessor(HTTPRequest.class, new HttpRequestAccessor()); - templateContextFactory.addAccessor(Profile.class, new ProfileAccessor(getCore())); - templateContextFactory.addFilter("date", new DateFilter()); - templateContextFactory.addFilter("html", new HtmlFilter()); - templateContextFactory.addFilter("replace", new ReplaceFilter()); - templateContextFactory.addFilter("store", new StoreFilter()); - templateContextFactory.addFilter("l10n", new L10nFilter(this)); - templateContextFactory.addFilter("substring", new SubstringFilter()); - templateContextFactory.addFilter("xml", new XmlFilter()); - templateContextFactory.addFilter("change", new RequestChangeFilter()); - templateContextFactory.addFilter("match", new MatchFilter()); - templateContextFactory.addFilter("css", new CssClassNameFilter()); - templateContextFactory.addFilter("js", new JavascriptFilter()); - templateContextFactory.addFilter("parse", parserFilter = new ParserFilter(getCore(), templateContextFactory, soneTextParser)); - templateContextFactory.addFilter("unknown", new UnknownDateFilter(getL10n(), "View.Sone.Text.UnknownDate")); - templateContextFactory.addFilter("format", new FormatFilter()); - templateContextFactory.addFilter("sort", new CollectionSortFilter()); - templateContextFactory.addFilter("image-link", new ImageLinkFilter(getCore(), templateContextFactory)); - templateContextFactory.addFilter("replyGroup", new ReplyGroupFilter()); - templateContextFactory.addFilter("in", new ContainsFilter()); - templateContextFactory.addFilter("unique", new UniqueElementFilter()); - templateContextFactory.addFilter("mod", new ModFilter()); - templateContextFactory.addFilter("paginate", new PaginationFilter()); - templateContextFactory.addProvider(TemplateProvider.TEMPLATE_CONTEXT_PROVIDER); - templateContextFactory.addProvider(new ClassPathTemplateProvider(WebInterface.class, "/templates/")); + this.templateContextFactory = templateContextFactory; templateContextFactory.addTemplateObject("webInterface", this); templateContextFactory.addTemplateObject("formPassword", formPassword); /* create notifications. */ - Template newSoneNotificationTemplate = TemplateParser.parse(createReader("/templates/notify/newSoneNotification.html")); - newSoneNotification = new ListNotification("new-sone-notification", "sones", newSoneNotificationTemplate, false); + Template newSoneNotificationTemplate = loaders.loadTemplate("/templates/notify/newSoneNotification.html"); + newSoneNotification = new ListNotification<>("new-sone-notification", "sones", newSoneNotificationTemplate, false); - Template newPostNotificationTemplate = TemplateParser.parse(createReader("/templates/notify/newPostNotification.html")); - newPostNotification = new ListNotification("new-post-notification", "posts", newPostNotificationTemplate, false); + Template newPostNotificationTemplate = loaders.loadTemplate("/templates/notify/newPostNotification.html"); + newPostNotification = new ListNotification<>("new-post-notification", "posts", newPostNotificationTemplate, false); - Template localPostNotificationTemplate = TemplateParser.parse(createReader("/templates/notify/newPostNotification.html")); - localPostNotification = new ListNotification("local-post-notification", "posts", localPostNotificationTemplate, false); + Template localPostNotificationTemplate = loaders.loadTemplate("/templates/notify/newPostNotification.html"); + localPostNotification = new ListNotification<>("local-post-notification", "posts", localPostNotificationTemplate, false); - Template newReplyNotificationTemplate = TemplateParser.parse(createReader("/templates/notify/newReplyNotification.html")); - newReplyNotification = new ListNotification("new-reply-notification", "replies", newReplyNotificationTemplate, false); + Template newReplyNotificationTemplate = loaders.loadTemplate("/templates/notify/newReplyNotification.html"); + newReplyNotification = new ListNotification<>("new-reply-notification", "replies", newReplyNotificationTemplate, false); - Template localReplyNotificationTemplate = TemplateParser.parse(createReader("/templates/notify/newReplyNotification.html")); - localReplyNotification = new ListNotification("local-reply-notification", "replies", localReplyNotificationTemplate, false); + Template localReplyNotificationTemplate = loaders.loadTemplate("/templates/notify/newReplyNotification.html"); + localReplyNotification = new ListNotification<>("local-reply-notification", "replies", localReplyNotificationTemplate, false); - Template mentionNotificationTemplate = TemplateParser.parse(createReader("/templates/notify/mentionNotification.html")); - mentionNotification = new ListNotification("mention-notification", "posts", mentionNotificationTemplate, false); + Template mentionNotificationTemplate = loaders.loadTemplate("/templates/notify/mentionNotification.html"); + mentionNotification = new ListNotification<>("mention-notification", "posts", mentionNotificationTemplate, false); - Template lockedSonesTemplate = TemplateParser.parse(createReader("/templates/notify/lockedSonesNotification.html")); - lockedSonesNotification = new ListNotification("sones-locked-notification", "sones", lockedSonesTemplate); + Template lockedSonesTemplate = loaders.loadTemplate("/templates/notify/lockedSonesNotification.html"); + lockedSonesNotification = new ListNotification<>("sones-locked-notification", "sones", lockedSonesTemplate); - Template newVersionTemplate = TemplateParser.parse(createReader("/templates/notify/newVersionNotification.html")); + Template newVersionTemplate = loaders.loadTemplate("/templates/notify/newVersionNotification.html"); newVersionNotification = new TemplateNotification("new-version-notification", newVersionTemplate); - Template insertingImagesTemplate = TemplateParser.parse(createReader("/templates/notify/inserting-images-notification.html")); - insertingImagesNotification = new ListNotification("inserting-images-notification", "images", insertingImagesTemplate); + Template insertingImagesTemplate = loaders.loadTemplate("/templates/notify/inserting-images-notification.html"); + insertingImagesNotification = new ListNotification<>("inserting-images-notification", "images", insertingImagesTemplate); - Template insertedImagesTemplate = TemplateParser.parse(createReader("/templates/notify/inserted-images-notification.html")); - insertedImagesNotification = new ListNotification("inserted-images-notification", "images", insertedImagesTemplate); + Template insertedImagesTemplate = loaders.loadTemplate("/templates/notify/inserted-images-notification.html"); + insertedImagesNotification = new ListNotification<>("inserted-images-notification", "images", insertedImagesTemplate); - Template imageInsertFailedTemplate = TemplateParser.parse(createReader("/templates/notify/image-insert-failed-notification.html")); - imageInsertFailedNotification = new ListNotification("image-insert-failed-notification", "images", imageInsertFailedTemplate); + Template imageInsertFailedTemplate = loaders.loadTemplate("/templates/notify/image-insert-failed-notification.html"); + imageInsertFailedNotification = new ListNotification<>("image-insert-failed-notification", "images", imageInsertFailedTemplate); } // @@ -330,6 +330,7 @@ public class WebInterface { * * @return The Sone core */ + @Nonnull public Core getCore() { return sonePlugin.core(); } @@ -343,68 +344,32 @@ public class WebInterface { return templateContextFactory; } - /** - * Returns the current session, creating a new session if there is no - * current session. - * - * @param toadletContenxt - * The toadlet context - * @return The current session, or {@code null} if there is no current - * session - */ - public Session getCurrentSession(ToadletContext toadletContenxt) { - return getCurrentSession(toadletContenxt, true); + private Session getCurrentSessionWithoutCreation(ToadletContext toadletContenxt) { + return getSessionManager().useSession(toadletContenxt); } - /** - * Returns the current session, creating a new session if there is no - * current session and {@code create} is {@code true}. - * - * @param toadletContenxt - * The toadlet context - * @param create - * {@code true} to create a new session if there is no current - * session, {@code false} otherwise - * @return The current session, or {@code null} if there is no current - * session - */ - public Session getCurrentSession(ToadletContext toadletContenxt, boolean create) { - Session session = getSessionManager().useSession(toadletContenxt); - if (create && (session == null)) { + private Session getOrCreateCurrentSession(ToadletContext toadletContenxt) { + Session session = getCurrentSessionWithoutCreation(toadletContenxt); + if (session == null) { session = getSessionManager().createSession(UUID.randomUUID().toString(), toadletContenxt); } return session; } - /** - * Returns the currently logged in Sone. - * - * @param toadletContext - * The toadlet context - * @return The currently logged in Sone, or {@code null} if no Sone is - * currently logged in - */ - public Sone getCurrentSone(ToadletContext toadletContext) { - return getCurrentSone(toadletContext, true); + public Sone getCurrentSoneCreatingSession(ToadletContext toadletContext) { + Collection localSones = getCore().getLocalSones(); + if (localSones.size() == 1) { + return localSones.iterator().next(); + } + return getCurrentSone(getOrCreateCurrentSession(toadletContext)); } - /** - * Returns the currently logged in Sone. - * - * @param toadletContext - * The toadlet context - * @param create - * {@code true} to create a new session if no session exists, - * {@code false} to not create a new session - * @return The currently logged in Sone, or {@code null} if no Sone is - * currently logged in - */ - public Sone getCurrentSone(ToadletContext toadletContext, boolean create) { + public Sone getCurrentSoneWithoutCreatingSession(ToadletContext toadletContext) { Collection localSones = getCore().getLocalSones(); if (localSones.size() == 1) { return localSones.iterator().next(); } - return getCurrentSone(getCurrentSession(toadletContext, create)); + return getCurrentSone(getCurrentSessionWithoutCreation(toadletContext)); } /** @@ -415,7 +380,7 @@ public class WebInterface { * @return The currently logged in Sone, or {@code null} if no Sone is * currently logged in */ - public Sone getCurrentSone(Session session) { + private Sone getCurrentSone(Session session) { if (session == null) { return null; } @@ -423,7 +388,13 @@ public class WebInterface { if (soneId == null) { return null; } - return getCore().getLocalSone(soneId, false); + return getCore().getLocalSone(soneId); + } + + @Override + @Nullable + public Sone getCurrentSone(@Nonnull ToadletContext toadletContext, boolean createSession) { + return createSession ? getCurrentSoneCreatingSession(toadletContext) : getCurrentSoneWithoutCreatingSession(toadletContext); } /** @@ -434,8 +405,9 @@ public class WebInterface { * @param sone * The Sone to set as currently logged in */ - public void setCurrentSone(ToadletContext toadletContext, Sone sone) { - Session session = getCurrentSession(toadletContext); + @Override + public void setCurrentSone(@Nonnull ToadletContext toadletContext, @Nullable Sone sone) { + Session session = getOrCreateCurrentSession(toadletContext); if (sone == null) { session.removeAttribute("Sone.CurrentSone"); } else { @@ -452,6 +424,16 @@ public class WebInterface { return notificationManager; } + @Nonnull + public Optional getNotification(@Nonnull String notificationId) { + return Optional.fromNullable(notificationManager.getNotification(notificationId)); + } + + @Nonnull + public Collection getNotifications(@Nullable Sone currentSone) { + return listNotificationFilter.filterNotifications(notificationManager.getNotifications(), currentSone); + } + /** * Returns the l10n helper of the node. * @@ -489,6 +471,15 @@ public class WebInterface { return ImmutableSet. builder().addAll(newPostNotification.getElements()).addAll(localPostNotification.getElements()).build(); } + @Nonnull + public Collection getNewPosts(@Nullable Sone currentSone) { + Set allNewPosts = ImmutableSet. builder() + .addAll(newPostNotification.getElements()) + .addAll(localPostNotification.getElements()) + .build(); + return from(allNewPosts).filter(postVisibilityFilter.isVisible(currentSone)).toSet(); + } + /** * Returns the replies that have been announced as new in the * {@link #newReplyNotification}. @@ -499,6 +490,15 @@ public class WebInterface { return ImmutableSet. builder().addAll(newReplyNotification.getElements()).addAll(localReplyNotification.getElements()).build(); } + @Nonnull + public Collection getNewReplies(@Nullable Sone currentSone) { + Set allNewReplies = ImmutableSet.builder() + .addAll(newReplyNotification.getElements()) + .addAll(localReplyNotification.getElements()) + .build(); + return from(allNewReplies).filter(replyVisibilityFilter.isVisible(currentSone)).toSet(); + } + /** * Sets whether the current start of the plugin is the first start. It is * considered a first start if the configuration file does not exist. @@ -509,7 +509,7 @@ public class WebInterface { */ public void setFirstStart(boolean firstStart) { if (firstStart) { - Template firstStartNotificationTemplate = TemplateParser.parse(createReader("/templates/notify/firstStartNotification.html")); + Template firstStartNotificationTemplate = loaders.loadTemplate("/templates/notify/firstStartNotification.html"); Notification firstStartNotification = new TemplateNotification("first-start-notification", firstStartNotificationTemplate); notificationManager.addNotification(firstStartNotification); } @@ -524,7 +524,7 @@ public class WebInterface { */ public void setNewConfig(boolean newConfig) { if (newConfig && !hasFirstStartNotification()) { - Template configNotReadNotificationTemplate = TemplateParser.parse(createReader("/templates/notify/configNotReadNotification.html")); + Template configNotReadNotificationTemplate = loaders.loadTemplate("/templates/notify/configNotReadNotification.html"); Notification configNotReadNotification = new TemplateNotification("config-not-read-notification", configNotReadNotificationTemplate); notificationManager.addNotification(configNotReadNotification); } @@ -555,7 +555,7 @@ public class WebInterface { registerToadlets(); /* notification templates. */ - Template startupNotificationTemplate = TemplateParser.parse(createReader("/templates/notify/startupNotification.html")); + Template startupNotificationTemplate = loaders.loadTemplate("/templates/notify/startupNotification.html"); final TemplateNotification startupNotification = new TemplateNotification("startup-notification", startupNotificationTemplate); notificationManager.addNotification(startupNotification); @@ -568,7 +568,7 @@ public class WebInterface { } }, 2, TimeUnit.MINUTES); - Template wotMissingNotificationTemplate = TemplateParser.parse(createReader("/templates/notify/wotMissingNotification.html")); + Template wotMissingNotificationTemplate = loaders.loadTemplate("/templates/notify/wotMissingNotification.html"); final TemplateNotification wotMissingNotification = new TemplateNotification("wot-missing-notification", wotMissingNotificationTemplate); ticker.scheduleAtFixedRate(new Runnable() { @@ -589,7 +589,7 @@ public class WebInterface { * Stops the web interface and unregisters all toadlets. */ public void stop() { - unregisterToadlets(); + pageToadletRegistry.unregisterToadlets(); ticker.shutdownNow(); } @@ -601,154 +601,122 @@ public class WebInterface { * Register all toadlets. */ private void registerToadlets() { - Template emptyTemplate = TemplateParser.parse(new StringReader("")); - Template loginTemplate = TemplateParser.parse(createReader("/templates/login.html")); - Template indexTemplate = TemplateParser.parse(createReader("/templates/index.html")); - Template newTemplate = TemplateParser.parse(createReader("/templates/new.html")); - Template knownSonesTemplate = TemplateParser.parse(createReader("/templates/knownSones.html")); - Template createSoneTemplate = TemplateParser.parse(createReader("/templates/createSone.html")); - Template createPostTemplate = TemplateParser.parse(createReader("/templates/createPost.html")); - Template createReplyTemplate = TemplateParser.parse(createReader("/templates/createReply.html")); - Template bookmarksTemplate = TemplateParser.parse(createReader("/templates/bookmarks.html")); - Template searchTemplate = TemplateParser.parse(createReader("/templates/search.html")); - Template editProfileTemplate = TemplateParser.parse(createReader("/templates/editProfile.html")); - Template editProfileFieldTemplate = TemplateParser.parse(createReader("/templates/editProfileField.html")); - Template deleteProfileFieldTemplate = TemplateParser.parse(createReader("/templates/deleteProfileField.html")); - Template viewSoneTemplate = TemplateParser.parse(createReader("/templates/viewSone.html")); - Template viewPostTemplate = TemplateParser.parse(createReader("/templates/viewPost.html")); - Template deletePostTemplate = TemplateParser.parse(createReader("/templates/deletePost.html")); - Template deleteReplyTemplate = TemplateParser.parse(createReader("/templates/deleteReply.html")); - Template deleteSoneTemplate = TemplateParser.parse(createReader("/templates/deleteSone.html")); - Template imageBrowserTemplate = TemplateParser.parse(createReader("/templates/imageBrowser.html")); - Template createAlbumTemplate = TemplateParser.parse(createReader("/templates/createAlbum.html")); - Template deleteAlbumTemplate = TemplateParser.parse(createReader("/templates/deleteAlbum.html")); - Template deleteImageTemplate = TemplateParser.parse(createReader("/templates/deleteImage.html")); - Template noPermissionTemplate = TemplateParser.parse(createReader("/templates/noPermission.html")); - Template optionsTemplate = TemplateParser.parse(createReader("/templates/options.html")); - Template rescueTemplate = TemplateParser.parse(createReader("/templates/rescue.html")); - Template aboutTemplate = TemplateParser.parse(createReader("/templates/about.html")); - Template invalidTemplate = TemplateParser.parse(createReader("/templates/invalid.html")); - Template postTemplate = TemplateParser.parse(createReader("/templates/include/viewPost.html")); - Template replyTemplate = TemplateParser.parse(createReader("/templates/include/viewReply.html")); - Template openSearchTemplate = TemplateParser.parse(createReader("/templates/xml/OpenSearch.xml")); - - PageToadletFactory pageToadletFactory = new PageToadletFactory(sonePlugin.pluginRespirator().getHLSimpleClient(), "/Sone/"); - pageToadlets.add(pageToadletFactory.createPageToadlet(new RedirectPage("", "index.html"))); - pageToadlets.add(pageToadletFactory.createPageToadlet(new IndexPage(indexTemplate, this), "Index")); - pageToadlets.add(pageToadletFactory.createPageToadlet(new NewPage(newTemplate, this), "New")); - pageToadlets.add(pageToadletFactory.createPageToadlet(new CreateSonePage(createSoneTemplate, this), "CreateSone")); - pageToadlets.add(pageToadletFactory.createPageToadlet(new KnownSonesPage(knownSonesTemplate, this), "KnownSones")); - pageToadlets.add(pageToadletFactory.createPageToadlet(new EditProfilePage(editProfileTemplate, this), "EditProfile")); - pageToadlets.add(pageToadletFactory.createPageToadlet(new EditProfileFieldPage(editProfileFieldTemplate, this))); - pageToadlets.add(pageToadletFactory.createPageToadlet(new DeleteProfileFieldPage(deleteProfileFieldTemplate, this))); - pageToadlets.add(pageToadletFactory.createPageToadlet(new CreatePostPage(createPostTemplate, this))); - pageToadlets.add(pageToadletFactory.createPageToadlet(new CreateReplyPage(createReplyTemplate, this))); - pageToadlets.add(pageToadletFactory.createPageToadlet(new ViewSonePage(viewSoneTemplate, this))); - pageToadlets.add(pageToadletFactory.createPageToadlet(new ViewPostPage(viewPostTemplate, this))); - pageToadlets.add(pageToadletFactory.createPageToadlet(new LikePage(emptyTemplate, this))); - pageToadlets.add(pageToadletFactory.createPageToadlet(new UnlikePage(emptyTemplate, this))); - pageToadlets.add(pageToadletFactory.createPageToadlet(new DeletePostPage(deletePostTemplate, this))); - pageToadlets.add(pageToadletFactory.createPageToadlet(new DeleteReplyPage(deleteReplyTemplate, this))); - pageToadlets.add(pageToadletFactory.createPageToadlet(new LockSonePage(emptyTemplate, this))); - pageToadlets.add(pageToadletFactory.createPageToadlet(new UnlockSonePage(emptyTemplate, this))); - pageToadlets.add(pageToadletFactory.createPageToadlet(new FollowSonePage(emptyTemplate, this))); - pageToadlets.add(pageToadletFactory.createPageToadlet(new UnfollowSonePage(emptyTemplate, this))); - pageToadlets.add(pageToadletFactory.createPageToadlet(new ImageBrowserPage(imageBrowserTemplate, this), "ImageBrowser")); - pageToadlets.add(pageToadletFactory.createPageToadlet(new CreateAlbumPage(createAlbumTemplate, this))); - pageToadlets.add(pageToadletFactory.createPageToadlet(new EditAlbumPage(emptyTemplate, this))); - pageToadlets.add(pageToadletFactory.createPageToadlet(new DeleteAlbumPage(deleteAlbumTemplate, this))); - pageToadlets.add(pageToadletFactory.createPageToadlet(new UploadImagePage(invalidTemplate, this))); - pageToadlets.add(pageToadletFactory.createPageToadlet(new EditImagePage(emptyTemplate, this))); - pageToadlets.add(pageToadletFactory.createPageToadlet(new DeleteImagePage(deleteImageTemplate, this))); - pageToadlets.add(pageToadletFactory.createPageToadlet(new TrustPage(emptyTemplate, this))); - pageToadlets.add(pageToadletFactory.createPageToadlet(new DistrustPage(emptyTemplate, this))); - pageToadlets.add(pageToadletFactory.createPageToadlet(new UntrustPage(emptyTemplate, this))); - pageToadlets.add(pageToadletFactory.createPageToadlet(new MarkAsKnownPage(emptyTemplate, this))); - pageToadlets.add(pageToadletFactory.createPageToadlet(new BookmarkPage(emptyTemplate, this))); - pageToadlets.add(pageToadletFactory.createPageToadlet(new UnbookmarkPage(emptyTemplate, this))); - pageToadlets.add(pageToadletFactory.createPageToadlet(new BookmarksPage(bookmarksTemplate, this), "Bookmarks")); - pageToadlets.add(pageToadletFactory.createPageToadlet(new SearchPage(searchTemplate, this))); - pageToadlets.add(pageToadletFactory.createPageToadlet(new DeleteSonePage(deleteSoneTemplate, this), "DeleteSone")); - pageToadlets.add(pageToadletFactory.createPageToadlet(new LoginPage(loginTemplate, this), "Login")); - pageToadlets.add(pageToadletFactory.createPageToadlet(new LogoutPage(emptyTemplate, this), "Logout")); - pageToadlets.add(pageToadletFactory.createPageToadlet(new OptionsPage(optionsTemplate, this), "Options")); - pageToadlets.add(pageToadletFactory.createPageToadlet(new RescuePage(rescueTemplate, this), "Rescue")); - pageToadlets.add(pageToadletFactory.createPageToadlet(new AboutPage(aboutTemplate, this, SonePlugin.VERSION), "About")); - pageToadlets.add(pageToadletFactory.createPageToadlet(new SoneTemplatePage("noPermission.html", noPermissionTemplate, "Page.NoPermission.Title", this))); - pageToadlets.add(pageToadletFactory.createPageToadlet(new DismissNotificationPage(emptyTemplate, this))); - pageToadlets.add(pageToadletFactory.createPageToadlet(new SoneTemplatePage("invalid.html", invalidTemplate, "Page.Invalid.Title", this))); - pageToadlets.add(pageToadletFactory.createPageToadlet(new StaticPage("css/", "/static/css/", "text/css"))); - pageToadlets.add(pageToadletFactory.createPageToadlet(new StaticPage("javascript/", "/static/javascript/", "text/javascript"))); - pageToadlets.add(pageToadletFactory.createPageToadlet(new StaticPage("images/", "/static/images/", "image/png"))); - pageToadlets.add(pageToadletFactory.createPageToadlet(new TemplatePage("OpenSearch.xml", "application/opensearchdescription+xml", templateContextFactory, openSearchTemplate))); - pageToadlets.add(pageToadletFactory.createPageToadlet(new GetImagePage(this))); - pageToadlets.add(pageToadletFactory.createPageToadlet(new GetTranslationPage(this))); - pageToadlets.add(pageToadletFactory.createPageToadlet(new GetStatusAjaxPage(this))); - pageToadlets.add(pageToadletFactory.createPageToadlet(new GetNotificationsAjaxPage(this))); - pageToadlets.add(pageToadletFactory.createPageToadlet(new DismissNotificationAjaxPage(this))); - pageToadlets.add(pageToadletFactory.createPageToadlet(new CreatePostAjaxPage(this))); - pageToadlets.add(pageToadletFactory.createPageToadlet(new CreateReplyAjaxPage(this))); - pageToadlets.add(pageToadletFactory.createPageToadlet(new GetReplyAjaxPage(this, replyTemplate))); - pageToadlets.add(pageToadletFactory.createPageToadlet(new GetPostAjaxPage(this, postTemplate))); - pageToadlets.add(pageToadletFactory.createPageToadlet(new GetTimesAjaxPage(this))); - pageToadlets.add(pageToadletFactory.createPageToadlet(new MarkAsKnownAjaxPage(this))); - pageToadlets.add(pageToadletFactory.createPageToadlet(new DeletePostAjaxPage(this))); - pageToadlets.add(pageToadletFactory.createPageToadlet(new DeleteReplyAjaxPage(this))); - pageToadlets.add(pageToadletFactory.createPageToadlet(new LockSoneAjaxPage(this))); - pageToadlets.add(pageToadletFactory.createPageToadlet(new UnlockSoneAjaxPage(this))); - pageToadlets.add(pageToadletFactory.createPageToadlet(new FollowSoneAjaxPage(this))); - pageToadlets.add(pageToadletFactory.createPageToadlet(new UnfollowSoneAjaxPage(this))); - pageToadlets.add(pageToadletFactory.createPageToadlet(new EditAlbumAjaxPage(this))); - pageToadlets.add(pageToadletFactory.createPageToadlet(new EditImageAjaxPage(this, parserFilter))); - pageToadlets.add(pageToadletFactory.createPageToadlet(new TrustAjaxPage(this))); - pageToadlets.add(pageToadletFactory.createPageToadlet(new DistrustAjaxPage(this))); - pageToadlets.add(pageToadletFactory.createPageToadlet(new UntrustAjaxPage(this))); - pageToadlets.add(pageToadletFactory.createPageToadlet(new LikeAjaxPage(this))); - pageToadlets.add(pageToadletFactory.createPageToadlet(new UnlikeAjaxPage(this))); - pageToadlets.add(pageToadletFactory.createPageToadlet(new GetLikesAjaxPage(this))); - pageToadlets.add(pageToadletFactory.createPageToadlet(new BookmarkAjaxPage(this))); - pageToadlets.add(pageToadletFactory.createPageToadlet(new UnbookmarkAjaxPage(this))); - pageToadlets.add(pageToadletFactory.createPageToadlet(new EditProfileFieldAjaxPage(this))); - pageToadlets.add(pageToadletFactory.createPageToadlet(new DeleteProfileFieldAjaxPage(this))); - pageToadlets.add(pageToadletFactory.createPageToadlet(new MoveProfileFieldAjaxPage(this))); - - ToadletContainer toadletContainer = sonePlugin.pluginRespirator().getToadletContainer(); - toadletContainer.getPageMaker().addNavigationCategory("/Sone/index.html", "Navigation.Menu.Sone.Name", "Navigation.Menu.Sone.Tooltip", sonePlugin); - for (PageToadlet toadlet : pageToadlets) { - String menuName = toadlet.getMenuName(); - if (menuName != null) { - toadletContainer.register(toadlet, "Navigation.Menu.Sone.Name", toadlet.path(), true, "Navigation.Menu.Sone.Item." + menuName + ".Name", "Navigation.Menu.Sone.Item." + menuName + ".Tooltip", false, toadlet); - } else { - toadletContainer.register(toadlet, null, toadlet.path(), true, false); - } - } - } - - /** - * Unregisters all toadlets. - */ - private void unregisterToadlets() { - ToadletContainer toadletContainer = sonePlugin.pluginRespirator().getToadletContainer(); - for (PageToadlet pageToadlet : pageToadlets) { - toadletContainer.unregister(pageToadlet); - } - toadletContainer.getPageMaker().removeNavigationCategory("Navigation.Menu.Sone.Name"); - } - - /** - * Creates a {@link Reader} from the {@link InputStream} for the resource - * with the given name. - * - * @param resourceName - * The name of the resource - * @return A {@link Reader} for the resource - */ - private Reader createReader(String resourceName) { - try { - return new InputStreamReader(getClass().getResourceAsStream(resourceName), "UTF-8"); - } catch (UnsupportedEncodingException uee1) { - return null; - } + Template emptyTemplate = parse(new StringReader("")); + Template loginTemplate = loaders.loadTemplate("/templates/login.html"); + Template indexTemplate = loaders.loadTemplate("/templates/index.html"); + Template newTemplate = loaders.loadTemplate("/templates/new.html"); + Template knownSonesTemplate = loaders.loadTemplate("/templates/knownSones.html"); + Template createSoneTemplate = loaders.loadTemplate("/templates/createSone.html"); + Template createPostTemplate = loaders.loadTemplate("/templates/createPost.html"); + Template createReplyTemplate = loaders.loadTemplate("/templates/createReply.html"); + Template bookmarksTemplate = loaders.loadTemplate("/templates/bookmarks.html"); + Template searchTemplate = loaders.loadTemplate("/templates/search.html"); + Template editProfileTemplate = loaders.loadTemplate("/templates/editProfile.html"); + Template editProfileFieldTemplate = loaders.loadTemplate("/templates/editProfileField.html"); + Template deleteProfileFieldTemplate = loaders.loadTemplate("/templates/deleteProfileField.html"); + Template viewSoneTemplate = loaders.loadTemplate("/templates/viewSone.html"); + Template viewPostTemplate = loaders.loadTemplate("/templates/viewPost.html"); + Template deletePostTemplate = loaders.loadTemplate("/templates/deletePost.html"); + Template deleteReplyTemplate = loaders.loadTemplate("/templates/deleteReply.html"); + Template deleteSoneTemplate = loaders.loadTemplate("/templates/deleteSone.html"); + Template imageBrowserTemplate = loaders.loadTemplate("/templates/imageBrowser.html"); + Template createAlbumTemplate = loaders.loadTemplate("/templates/createAlbum.html"); + Template deleteAlbumTemplate = loaders.loadTemplate("/templates/deleteAlbum.html"); + Template deleteImageTemplate = loaders.loadTemplate("/templates/deleteImage.html"); + Template noPermissionTemplate = loaders.loadTemplate("/templates/noPermission.html"); + Template emptyImageTitleTemplate = loaders.loadTemplate("/templates/emptyImageTitle.html"); + Template emptyAlbumTitleTemplate = loaders.loadTemplate("/templates/emptyAlbumTitle.html"); + Template optionsTemplate = loaders.loadTemplate("/templates/options.html"); + Template rescueTemplate = loaders.loadTemplate("/templates/rescue.html"); + Template aboutTemplate = loaders.loadTemplate("/templates/about.html"); + Template invalidTemplate = loaders.loadTemplate("/templates/invalid.html"); + Template postTemplate = loaders.loadTemplate("/templates/include/viewPost.html"); + Template replyTemplate = loaders.loadTemplate("/templates/include/viewReply.html"); + Template openSearchTemplate = loaders.loadTemplate("/templates/xml/OpenSearch.xml"); + + pageToadletRegistry.addPage(new RedirectPage("", "index.html")); + pageToadletRegistry.addPage(new IndexPage(indexTemplate, this, loaders, postVisibilityFilter)); + pageToadletRegistry.addPage(new NewPage(newTemplate, this, loaders)); + pageToadletRegistry.addPage(new CreateSonePage(createSoneTemplate, this, loaders)); + pageToadletRegistry.addPage(new KnownSonesPage(knownSonesTemplate, this, loaders)); + pageToadletRegistry.addPage(new EditProfilePage(editProfileTemplate, this, loaders)); + pageToadletRegistry.addPage(new EditProfileFieldPage(editProfileFieldTemplate, this, loaders)); + pageToadletRegistry.addPage(new DeleteProfileFieldPage(deleteProfileFieldTemplate, this, loaders)); + pageToadletRegistry.addPage(new CreatePostPage(createPostTemplate, this, loaders)); + pageToadletRegistry.addPage(new CreateReplyPage(createReplyTemplate, this, loaders)); + pageToadletRegistry.addPage(new ViewSonePage(viewSoneTemplate, this, loaders)); + pageToadletRegistry.addPage(new ViewPostPage(viewPostTemplate, this, loaders)); + pageToadletRegistry.addPage(new LikePage(emptyTemplate, this, loaders)); + pageToadletRegistry.addPage(new UnlikePage(emptyTemplate, this, loaders)); + pageToadletRegistry.addPage(new DeletePostPage(deletePostTemplate, this, loaders)); + pageToadletRegistry.addPage(new DeleteReplyPage(deleteReplyTemplate, this, loaders)); + pageToadletRegistry.addPage(new LockSonePage(emptyTemplate, this, loaders)); + pageToadletRegistry.addPage(new UnlockSonePage(emptyTemplate, this, loaders)); + pageToadletRegistry.addPage(new FollowSonePage(emptyTemplate, this, loaders)); + pageToadletRegistry.addPage(new UnfollowSonePage(emptyTemplate, this, loaders)); + pageToadletRegistry.addPage(new ImageBrowserPage(imageBrowserTemplate, this, loaders)); + pageToadletRegistry.addPage(new CreateAlbumPage(createAlbumTemplate, this, loaders)); + pageToadletRegistry.addPage(new EditAlbumPage(emptyTemplate, this, loaders)); + pageToadletRegistry.addPage(new DeleteAlbumPage(deleteAlbumTemplate, this, loaders)); + pageToadletRegistry.addPage(new UploadImagePage(invalidTemplate, this, loaders)); + pageToadletRegistry.addPage(new EditImagePage(emptyTemplate, this, loaders)); + pageToadletRegistry.addPage(new DeleteImagePage(deleteImageTemplate, this, loaders)); + pageToadletRegistry.addPage(new TrustPage(emptyTemplate, this, loaders)); + pageToadletRegistry.addPage(new DistrustPage(emptyTemplate, this, loaders)); + pageToadletRegistry.addPage(new UntrustPage(emptyTemplate, this, loaders)); + pageToadletRegistry.addPage(new MarkAsKnownPage(emptyTemplate, this, loaders)); + pageToadletRegistry.addPage(new BookmarkPage(emptyTemplate, this, loaders)); + pageToadletRegistry.addPage(new UnbookmarkPage(emptyTemplate, this, loaders)); + pageToadletRegistry.addPage(new BookmarksPage(bookmarksTemplate, this, loaders)); + pageToadletRegistry.addPage(new SearchPage(searchTemplate, this, loaders)); + pageToadletRegistry.addPage(new DeleteSonePage(deleteSoneTemplate, this, loaders)); + pageToadletRegistry.addPage(new LoginPage(loginTemplate, this, loaders)); + pageToadletRegistry.addPage(new LogoutPage(emptyTemplate, this, loaders)); + pageToadletRegistry.addPage(new OptionsPage(optionsTemplate, this, loaders)); + pageToadletRegistry.addPage(new RescuePage(rescueTemplate, this, loaders)); + pageToadletRegistry.addPage(new AboutPage(aboutTemplate, this, loaders, new PluginVersion(SonePlugin.getPluginVersion()), new PluginYear(sonePlugin.getYear()), new PluginHomepage(sonePlugin.getHomepage()))); + pageToadletRegistry.addPage(new SoneTemplatePage("noPermission.html", this, loaders, noPermissionTemplate, "Page.NoPermission.Title")); + pageToadletRegistry.addPage(new SoneTemplatePage("emptyImageTitle.html", this, loaders, emptyImageTitleTemplate, "Page.EmptyImageTitle.Title")); + pageToadletRegistry.addPage(new SoneTemplatePage("emptyAlbumTitle.html", this, loaders, emptyAlbumTitleTemplate, "Page.EmptyAlbumTitle.Title")); + pageToadletRegistry.addPage(new DismissNotificationPage(emptyTemplate, this, loaders)); + pageToadletRegistry.addPage(new SoneTemplatePage("invalid.html", this, loaders, invalidTemplate, "Page.Invalid.Title")); + pageToadletRegistry.addPage(loaders.loadStaticPage("css/", "/static/css/", "text/css")); + pageToadletRegistry.addPage(loaders.loadStaticPage("javascript/", "/static/javascript/", "text/javascript")); + pageToadletRegistry.addPage(loaders.loadStaticPage("images/", "/static/images/", "image/png")); + pageToadletRegistry.addPage(new TemplatePage("OpenSearch.xml", "application/opensearchdescription+xml", templateContextFactory, openSearchTemplate)); + pageToadletRegistry.addPage(new GetImagePage(this)); + pageToadletRegistry.addPage(new GetTranslationAjaxPage(this)); + pageToadletRegistry.addPage(new GetStatusAjaxPage(this, elementLoader, timeTextConverter, l10nFilter, TimeZone.getDefault())); + pageToadletRegistry.addPage(new GetNotificationsAjaxPage(this)); + pageToadletRegistry.addPage(new DismissNotificationAjaxPage(this)); + pageToadletRegistry.addPage(new CreatePostAjaxPage(this)); + pageToadletRegistry.addPage(new CreateReplyAjaxPage(this)); + pageToadletRegistry.addPage(new GetReplyAjaxPage(this, replyTemplate)); + pageToadletRegistry.addPage(new GetPostAjaxPage(this, postTemplate)); + pageToadletRegistry.addPage(new GetLinkedElementAjaxPage(this, elementLoader, linkedElementRenderFilter)); + pageToadletRegistry.addPage(new GetTimesAjaxPage(this, timeTextConverter, l10nFilter, TimeZone.getDefault())); + pageToadletRegistry.addPage(new MarkAsKnownAjaxPage(this)); + pageToadletRegistry.addPage(new DeletePostAjaxPage(this)); + pageToadletRegistry.addPage(new DeleteReplyAjaxPage(this)); + pageToadletRegistry.addPage(new LockSoneAjaxPage(this)); + pageToadletRegistry.addPage(new UnlockSoneAjaxPage(this)); + pageToadletRegistry.addPage(new FollowSoneAjaxPage(this)); + pageToadletRegistry.addPage(new UnfollowSoneAjaxPage(this)); + pageToadletRegistry.addPage(new EditAlbumAjaxPage(this)); + pageToadletRegistry.addPage(new EditImageAjaxPage(this, parserFilter, shortenFilter, renderFilter)); + pageToadletRegistry.addPage(new TrustAjaxPage(this)); + pageToadletRegistry.addPage(new DistrustAjaxPage(this)); + pageToadletRegistry.addPage(new UntrustAjaxPage(this)); + pageToadletRegistry.addPage(new LikeAjaxPage(this)); + pageToadletRegistry.addPage(new UnlikeAjaxPage(this)); + pageToadletRegistry.addPage(new GetLikesAjaxPage(this)); + pageToadletRegistry.addPage(new BookmarkAjaxPage(this)); + pageToadletRegistry.addPage(new UnbookmarkAjaxPage(this)); + pageToadletRegistry.addPage(new EditProfileFieldAjaxPage(this)); + pageToadletRegistry.addPage(new DeleteProfileFieldAjaxPage(this)); + pageToadletRegistry.addPage(new MoveProfileFieldAjaxPage(this)); + + pageToadletRegistry.registerToadlets(); } /** @@ -762,15 +730,11 @@ public class WebInterface { */ private Collection getMentionedSones(String text) { /* we need no context to find mentioned Sones. */ - Set mentionedSones = new HashSet(); - try { - for (Part part : soneTextParser.parse(null, new StringReader(text))) { - if (part instanceof SonePart) { - mentionedSones.add(((SonePart) part).getSone()); - } + Set mentionedSones = new HashSet<>(); + for (Part part : soneTextParser.parse(text, null)) { + if (part instanceof SonePart) { + mentionedSones.add(((SonePart) part).getSone()); } - } catch (IOException ioe1) { - logger.log(Level.WARNING, String.format("Could not parse post text: %s", text), ioe1); } return Collections2.filter(mentionedSones, Sone.LOCAL_SONE_FILTER); } @@ -788,7 +752,7 @@ public class WebInterface { synchronized (soneInsertNotifications) { TemplateNotification templateNotification = soneInsertNotifications.get(sone); if (templateNotification == null) { - templateNotification = new TemplateNotification(TemplateParser.parse(createReader("/templates/notify/soneInsertNotification.html"))); + templateNotification = new TemplateNotification(loaders.loadTemplate("/templates/notify/soneInsertNotification.html")); templateNotification.set("insertSone", sone); soneInsertNotifications.put(sone, templateNotification); } @@ -796,6 +760,23 @@ public class WebInterface { } } + private boolean localSoneMentionedInNewPostOrReply(Post post) { + if (!post.getSone().isLocal()) { + if (!getMentionedSones(post.getText()).isEmpty() && !post.isKnown()) { + return true; + } + } + for (PostReply postReply : getCore().getReplies(post.getId())) { + if (postReply.getSone().isLocal()) { + continue; + } + if (!getMentionedSones(postReply.getText()).isEmpty() && !postReply.isKnown()) { + return true; + } + } + return false; + } + // // EVENT HANDLERS // @@ -857,7 +838,7 @@ public class WebInterface { } if (!hasFirstStartNotification()) { notificationManager.addNotification(isLocal ? localReplyNotification : newReplyNotification); - if (!getMentionedSones(reply.getText()).isEmpty() && !isLocal && reply.getPost().isPresent() && (reply.getTime() <= System.currentTimeMillis())) { + if (reply.getPost().isPresent() && localSoneMentionedInNewPostOrReply(reply.getPost().get())) { mentionNotification.add(reply.getPost().get()); notificationManager.addNotification(mentionNotification); } @@ -877,75 +858,44 @@ public class WebInterface { newSoneNotification.remove(markSoneKnownEvent.sone()); } - /** - * Notifies the web interface that a {@link Post} was marked as known. - * - * @param markPostKnownEvent - * The event - */ @Subscribe public void markPostKnown(MarkPostKnownEvent markPostKnownEvent) { - newPostNotification.remove(markPostKnownEvent.post()); - localPostNotification.remove(markPostKnownEvent.post()); - mentionNotification.remove(markPostKnownEvent.post()); + removePost(markPostKnownEvent.post()); } - /** - * Notifies the web interface that a {@link PostReply} was marked as known. - * - * @param markPostReplyKnownEvent - * The event - */ @Subscribe public void markReplyKnown(MarkPostReplyKnownEvent markPostReplyKnownEvent) { - newReplyNotification.remove(markPostReplyKnownEvent.postReply()); - localReplyNotification.remove(markPostReplyKnownEvent.postReply()); - mentionNotification.remove(markPostReplyKnownEvent.postReply().getPost().get()); + removeReply(markPostReplyKnownEvent.postReply()); } - /** - * Notifies the web interface that a {@link Sone} was removed. - * - * @param soneRemovedEvent - * The event - */ @Subscribe public void soneRemoved(SoneRemovedEvent soneRemovedEvent) { newSoneNotification.remove(soneRemovedEvent.sone()); } - /** - * Notifies the web interface that a {@link Post} was removed. - * - * @param postRemovedEvent - * The event - */ @Subscribe public void postRemoved(PostRemovedEvent postRemovedEvent) { - newPostNotification.remove(postRemovedEvent.post()); - localPostNotification.remove(postRemovedEvent.post()); - mentionNotification.remove(postRemovedEvent.post()); + removePost(postRemovedEvent.post()); + } + + private void removePost(Post post) { + newPostNotification.remove(post); + localPostNotification.remove(post); + if (!localSoneMentionedInNewPostOrReply(post)) { + mentionNotification.remove(post); + } } - /** - * Notifies the web interface that a {@link PostReply} was removed. - * - * @param postReplyRemovedEvent - * The event - */ @Subscribe public void replyRemoved(PostReplyRemovedEvent postReplyRemovedEvent) { - PostReply reply = postReplyRemovedEvent.postReply(); + removeReply(postReplyRemovedEvent.postReply()); + } + + private void removeReply(PostReply reply) { newReplyNotification.remove(reply); localReplyNotification.remove(reply); - if (!getMentionedSones(reply.getText()).isEmpty() && reply.getPost().isPresent()) { - boolean isMentioned = false; - for (PostReply existingReply : getCore().getReplies(reply.getPost().get())) { - isMentioned |= !reply.isKnown() && !getMentionedSones(existingReply.getText()).isEmpty(); - } - if (!isMentioned) { - mentionNotification.remove(reply.getPost().get()); - } + if (reply.getPost().isPresent() && !localSoneMentionedInNewPostOrReply(reply.getPost().get())) { + mentionNotification.remove(reply.getPost().get()); } } @@ -992,7 +942,7 @@ public class WebInterface { public void soneInserting(SoneInsertingEvent soneInsertingEvent) { TemplateNotification soneInsertNotification = getSoneInsertNotification(soneInsertingEvent.sone()); soneInsertNotification.set("soneStatus", "inserting"); - if (soneInsertingEvent.sone().getOptions().getBooleanOption("EnableSoneInsertNotifications").get()) { + if (soneInsertingEvent.sone().getOptions().isSoneInsertNotificationEnabled()) { notificationManager.addNotification(soneInsertNotification); } } @@ -1008,7 +958,7 @@ public class WebInterface { TemplateNotification soneInsertNotification = getSoneInsertNotification(soneInsertedEvent.sone()); soneInsertNotification.set("soneStatus", "inserted"); soneInsertNotification.set("insertDuration", soneInsertedEvent.insertDuration() / 1000); - if (soneInsertedEvent.sone().getOptions().getBooleanOption("EnableSoneInsertNotifications").get()) { + if (soneInsertedEvent.sone().getOptions().isSoneInsertNotificationEnabled()) { notificationManager.addNotification(soneInsertNotification); } } @@ -1024,7 +974,7 @@ public class WebInterface { TemplateNotification soneInsertNotification = getSoneInsertNotification(soneInsertAbortedEvent.sone()); soneInsertNotification.set("soneStatus", "insert-aborted"); soneInsertNotification.set("insert-error", soneInsertAbortedEvent.cause()); - if (soneInsertAbortedEvent.sone().getOptions().getBooleanOption("EnableSoneInsertNotifications").get()) { + if (soneInsertAbortedEvent.sone().getOptions().isSoneInsertNotificationEnabled()) { notificationManager.addNotification(soneInsertNotification); } } @@ -1037,9 +987,10 @@ public class WebInterface { */ @Subscribe public void updateFound(UpdateFoundEvent updateFoundEvent) { - newVersionNotification.getTemplateContext().set("latestVersion", updateFoundEvent.version()); - newVersionNotification.getTemplateContext().set("latestEdition", updateFoundEvent.latestEdition()); - newVersionNotification.getTemplateContext().set("releaseTime", updateFoundEvent.releaseTime()); + newVersionNotification.set("latestVersion", updateFoundEvent.version()); + newVersionNotification.set("latestEdition", updateFoundEvent.latestEdition()); + newVersionNotification.set("releaseTime", updateFoundEvent.releaseTime()); + newVersionNotification.set("disruptive", updateFoundEvent.disruptive()); notificationManager.addNotification(newVersionNotification); }