aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Vitaly Takmazov2018-04-11 21:34:14 +0300
committerGravatar Vitaly Takmazov2018-04-11 21:34:14 +0300
commitad99117a15062a3819dad1f52a072e9694a954df (patch)
tree61b47950cca3adba91ef4f7c8ce80c1a1f8a531f
parent47254ab8555162bc121c7b618fff42fc64b9454c (diff)
server: last read marker for threads
-rw-r--r--juick-common/src/main/java/com/juick/server/CommandsManager.java4
-rw-r--r--juick-common/src/main/java/com/juick/service/MessagesService.java6
-rw-r--r--juick-server-jdbc/src/main/java/com/juick/service/MessagesServiceImpl.java21
-rw-r--r--juick-server-jdbc/src/main/java/com/juick/service/SubscriptionServiceImpl.java20
-rw-r--r--juick-server-jdbc/src/main/resources/schema.sql1
-rw-r--r--juick-server/src/main/java/com/juick/server/api/Messages.java2
-rw-r--r--juick-server/src/test/java/com/juick/server/tests/ServerTests.java24
-rw-r--r--juick-www/src/main/java/com/juick/www/controllers/MessagesWWW.java2
-rw-r--r--juick-www/src/main/java/com/juick/www/controllers/NewMessage.java2
-rw-r--r--juick-www/src/test/java/com/juick/WebAppTests.java13
10 files changed, 49 insertions, 46 deletions
diff --git a/juick-common/src/main/java/com/juick/server/CommandsManager.java b/juick-common/src/main/java/com/juick/server/CommandsManager.java
index d924ac70..734d68fb 100644
--- a/juick-common/src/main/java/com/juick/server/CommandsManager.java
+++ b/juick-common/src/main/java/com/juick/server/CommandsManager.java
@@ -388,7 +388,7 @@ public class CommandsManager {
com.juick.Message msg = messagesService.getMessage(mid);
if (msg != null) {
if (showReplies) {
- List<com.juick.Message> replies = messagesService.getReplies(mid);
+ List<com.juick.Message> replies = messagesService.getReplies(user, mid);
replies.add(0, msg);
return CommandResult.fromString(String.join("\n",
replies.stream().map(PlainTextFormatter::formatPostSummary).collect(Collectors.toList())));
@@ -477,7 +477,7 @@ public class CommandsManager {
} else {
String attachmentStr = attachment.toString();
String attachmentType = StringUtils.isNotEmpty(attachmentStr) ? attachmentStr.substring(attachmentStr.length() - 3) : null;
- int newrid = messagesService.createReply(mid, rid, user.getUid(), txt, attachmentType);
+ int newrid = messagesService.createReply(mid, rid, user, txt, attachmentType);
if (StringUtils.isNotEmpty(attachmentType)) {
String attachmentFName = attachment.getScheme().equals("juick") ? attachment.getHost()
: HttpUtils.downloadImage(attachment.toURL(), tmpDir).getHost();
diff --git a/juick-common/src/main/java/com/juick/service/MessagesService.java b/juick-common/src/main/java/com/juick/service/MessagesService.java
index 2dce2806..968e64be 100644
--- a/juick-common/src/main/java/com/juick/service/MessagesService.java
+++ b/juick-common/src/main/java/com/juick/service/MessagesService.java
@@ -29,7 +29,7 @@ import java.util.List;
public interface MessagesService {
int createMessage(int uid, String txt, String attachment, Collection<com.juick.Tag> tags);
- int createReply(int mid, int rid, int uid, String txt, String attachment);
+ int createReply(int mid, int rid, User user, String txt, String attachment);
int getReplyIDIncrement(int mid);
@@ -95,7 +95,7 @@ public interface MessagesService {
List<com.juick.Message> getMessages(List<Integer> mids);
- List<com.juick.Message> getReplies(int mid);
+ List<com.juick.Message> getReplies(User user, int mid);
boolean setMessagePopular(int mid, int popular);
@@ -110,4 +110,6 @@ public interface MessagesService {
List<ResponseReply> getLastReplies(int hours);
List<Integer> getPopularCandidates();
+
+ void setLastReadComment(User user, Integer mid, Integer rid);
}
diff --git a/juick-server-jdbc/src/main/java/com/juick/service/MessagesServiceImpl.java b/juick-server-jdbc/src/main/java/com/juick/service/MessagesServiceImpl.java
index 3b73ed25..c811e300 100644
--- a/juick-server-jdbc/src/main/java/com/juick/service/MessagesServiceImpl.java
+++ b/juick-server-jdbc/src/main/java/com/juick/service/MessagesServiceImpl.java
@@ -167,7 +167,7 @@ public class MessagesServiceImpl extends BaseJdbcService implements MessagesServ
/**
* @param mid
* @param rid
- * @param uid
+ * @param user
* @param txt
* @param attachment
* @return
@@ -175,17 +175,18 @@ public class MessagesServiceImpl extends BaseJdbcService implements MessagesServ
*/
@Transactional
@Override
- public int createReply(final int mid, final int rid, final int uid, final String txt, final String attachment) {
+ public int createReply(final int mid, final int rid, final User user, final String txt, final String attachment) {
int ridnew = getReplyIDIncrement(mid);
Date ts = Date.from(Instant.now());
getJdbcTemplate().update("INSERT INTO replies(message_id, reply_id, user_id, replyto, attach, txt, ts) " +
"VALUES (?, ?, ?, ?, ?, ?, ?)",
- mid, ridnew, uid, rid, attachment, txt, ts);
+ mid, ridnew, user.getUid(), rid, attachment, txt, ts);
if (ridnew > 0) {
getJdbcTemplate().update(
"UPDATE messages SET replies = replies + 1, updated=? WHERE message_id = ?",
ts, mid);
+ setLastReadComment(user, mid, ridnew);
}
return ridnew;
}
@@ -771,8 +772,8 @@ public class MessagesServiceImpl extends BaseJdbcService implements MessagesServ
@Transactional(readOnly = true)
@Override
- public List<com.juick.Message> getReplies(final int mid) {
- return getNamedParameterJdbcTemplate().query(
+ public List<Message> getReplies(final User user, final int mid) {
+ List<Message> replies = getNamedParameterJdbcTemplate().query(
"SELECT replies.message_id as mid, replies.reply_id, replies.replyto, " +
"replies.user_id, users.nick, users.banned, " +
"TIMESTAMPDIFF(MINUTE, replies.ts, NOW()), replies.ts, " +
@@ -793,6 +794,10 @@ public class MessagesServiceImpl extends BaseJdbcService implements MessagesServ
"WHERE replies.message_id = :mid ORDER BY replies.reply_id ASC",
new MapSqlParameterSource("mid", mid),
new MessageMapper());
+ if (replies.size() > 0) {
+ setLastReadComment(user, mid, replies.stream().map(Message::getRid).max(Comparator.naturalOrder()).get());
+ }
+ return replies;
}
@Transactional
@@ -919,4 +924,10 @@ public class MessagesServiceImpl extends BaseJdbcService implements MessagesServ
"WHERE COALESCE(messages_tags.tag_id, 0) != 2 AND favorites.ts > TIMESTAMPADD(HOUR, -2, CURRENT_TIMESTAMP) " +
"AND messages.popular=0 GROUP BY messages.message_id HAVING COUNT(DISTINCT favorites.user_id) > 1;", Integer.class);
}
+ @Transactional
+ @Override
+ public void setLastReadComment(User user, Integer mid, Integer rid) {
+ jdbcTemplate.update("UPDATE subscr_messages SET last_read_rid=? WHERE message_id=? AND suser_id=?",
+ rid, mid, user.getUid());
+ }
}
diff --git a/juick-server-jdbc/src/main/java/com/juick/service/SubscriptionServiceImpl.java b/juick-server-jdbc/src/main/java/com/juick/service/SubscriptionServiceImpl.java
index 0273c1c3..d580f97a 100644
--- a/juick-server-jdbc/src/main/java/com/juick/service/SubscriptionServiceImpl.java
+++ b/juick-server-jdbc/src/main/java/com/juick/service/SubscriptionServiceImpl.java
@@ -41,22 +41,12 @@ import java.util.stream.Collectors;
*/
@Repository
public class SubscriptionServiceImpl extends BaseJdbcService implements SubscriptionService {
- private final UserService userService;
- private final MessagesService messagesService;
- private final TagService tagService;
-
@Inject
- public SubscriptionServiceImpl(UserService userService,
- MessagesService messagesService, TagService tagService) {
- Assert.notNull(userService, "UserService must be initialized");
- this.userService = userService;
-
- Assert.notNull(messagesService,"MessagesService must be initialized");
- this.messagesService = messagesService;
-
- Assert.notNull(tagService, "TagService must be initialized");
- this.tagService = tagService;
- }
+ private UserService userService;
+ @Inject
+ private MessagesService messagesService;
+ @Inject
+ private TagService tagService;
@Transactional(readOnly = true)
@Override
diff --git a/juick-server-jdbc/src/main/resources/schema.sql b/juick-server-jdbc/src/main/resources/schema.sql
index 544b4e51..66b4d7ac 100644
--- a/juick-server-jdbc/src/main/resources/schema.sql
+++ b/juick-server-jdbc/src/main/resources/schema.sql
@@ -227,6 +227,7 @@ CREATE TABLE IF NOT EXISTS `replies` (
CREATE TABLE IF NOT EXISTS `subscr_messages` (
`message_id` int(10) unsigned NOT NULL,
`suser_id` int(10) unsigned NOT NULL,
+ `last_read_rid` smallint(5) unsigned NOT NULL DEFAULT '0',
UNIQUE KEY (`message_id`,`suser_id`)
);
diff --git a/juick-server/src/main/java/com/juick/server/api/Messages.java b/juick-server/src/main/java/com/juick/server/api/Messages.java
index 86426bf6..45b8f69c 100644
--- a/juick-server/src/main/java/com/juick/server/api/Messages.java
+++ b/juick-server/src/main/java/com/juick/server/api/Messages.java
@@ -145,7 +145,7 @@ public class Messages {
if (!messagesService.canViewThread(mid, vuid)) {
return FORBIDDEN;
} else {
- List<com.juick.Message> replies = messagesService.getReplies(mid);
+ List<com.juick.Message> replies = messagesService.getReplies(visitor, mid);
replies.add(0, msg);
return ResponseEntity.ok(replies);
}
diff --git a/juick-server/src/test/java/com/juick/server/tests/ServerTests.java b/juick-server/src/test/java/com/juick/server/tests/ServerTests.java
index 2c335cb2..095566ec 100644
--- a/juick-server/src/test/java/com/juick/server/tests/ServerTests.java
+++ b/juick-server/src/test/java/com/juick/server/tests/ServerTests.java
@@ -54,22 +54,18 @@ import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.util.UriComponents;
import org.springframework.web.util.UriComponentsBuilder;
import rocks.xmpp.addr.Jid;
-import rocks.xmpp.core.stanza.model.Stanza;
import rocks.xmpp.core.stanza.model.StanzaError;
import rocks.xmpp.core.stanza.model.client.ClientMessage;
import rocks.xmpp.core.stanza.model.errors.Condition;
-import rocks.xmpp.core.stanza.model.server.ServerMessage;
import javax.inject.Inject;
import java.io.IOException;
-import java.lang.reflect.InvocationTargetException;
import java.net.URI;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.sql.Timestamp;
import java.time.Instant;
import java.util.*;
-import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.stream.IntStream;
@@ -246,18 +242,18 @@ public class ServerTests {
assertEquals("we already have ugnich", -1, userService.createUser("ugnich", "x"));
int ugnich_id = userService.createUser("hugnich", "x");
User ugnich = userService.getUserByUID(ugnich_id).orElse(new User());
- int rid = messagesService.createReply(msg2.getMid(), 0, ugnich.getUid(), "bla-bla", null);
+ int rid = messagesService.createReply(msg2.getMid(), 0, ugnich, "bla-bla", null);
assertEquals(1, rid);
assertThat(msg2.getTo(), equalTo(null));
Message reply = messagesService.getReply(msg2.getMid(), rid);
assertThat(reply.getTo().getName(), equalTo(user.getName()));
- List<Message> replies = messagesService.getReplies(msg2.getMid());
+ List<Message> replies = messagesService.getReplies(user, msg2.getMid());
assertThat(replies.size(), equalTo(1));
assertThat(replies.get(0), equalTo(reply));
- int ridToReply = messagesService.createReply(msg2.getMid(), 1, ugnich_id, "blax2", null);
+ int ridToReply = messagesService.createReply(msg2.getMid(), 1, ugnich, "blax2", null);
Message reply2 = messagesService.getReply(msg2.getMid(), ridToReply);
assertThat(reply.getTo().getName(), equalTo(user.getName()));
- List<Message> replies2 = messagesService.getReplies(msg2.getMid());
+ List<Message> replies2 = messagesService.getReplies(user, msg2.getMid());
assertThat(replies2.size(), equalTo(2));
assertThat(replies2.get(1), equalTo(reply2));
Message msg3 = messagesService.getMessage(mid2);
@@ -267,7 +263,7 @@ public class ServerTests {
assertEquals(-1, userService.checkPassword(ugnich.getName(), "xy"));
subscriptionService.subscribeMessage(msg.getMid(), user.getUid());
subscriptionService.subscribeMessage(msg.getMid(), ugnich.getUid());
- int reply_id = messagesService.createReply(msg.getMid(), 0, ugnich_id, "comment", null);
+ int reply_id = messagesService.createReply(msg.getMid(), 0, ugnich, "comment", null);
assertEquals(1, subscriptionService.getUsersSubscribedToComments(msg,
messagesService.getReply(msg.getMid(), reply_id)).size());
assertThat(messagesService.getDiscussions(ugnich.getUid(), 0L).get(0),
@@ -308,7 +304,7 @@ public class ServerTests {
Instant ts = jdbcTemplate.queryForObject("SELECT updated FROM messages WHERE message_id=?",
Timestamp.class, mid).toInstant();
Thread.sleep(1000);
- int rid = messagesService.createReply(mid, 0, ugnich_id, "people", null);
+ int rid = messagesService.createReply(mid, 0, ugnich, "people", null);
Instant rts = jdbcTemplate.queryForObject("SELECT updated FROM messages WHERE message_id=?",
Timestamp.class, mid).toInstant();
assertThat(rts, greaterThan(ts));
@@ -498,7 +494,9 @@ public class ServerTests {
public void topTest() {
int topmid = messagesService.createMessage(ugnich.getUid(), "top message", null, null);
IntStream.rangeClosed(6, 12).forEach(i -> {
- messagesService.createReply(topmid, 0, i, "yo", null);
+ User next = new User();
+ next.setUid(i);
+ messagesService.createReply(topmid, 0, next, "yo", null);
});
assertThat(messagesService.getPopularCandidates().get(0), is(topmid));
@@ -615,7 +613,7 @@ public class ServerTests {
commandsManager.processCommand(readerUser, "S #" + mid, emptyUri).getText());
assertEquals("should be favorited", "Message is added to your recommendations",
commandsManager.processCommand(readerUser, "! #" + mid, emptyUri).getText());
- int rid = messagesService.createReply(mid, 0, uid, "comment", null);
+ int rid = messagesService.createReply(mid, 0, user, "comment", null);
assertEquals("number of subscribed users should match", 1,
subscriptionService.getUsersSubscribedToComments(
messagesService.getMessage(mid),
@@ -642,7 +640,7 @@ public class ServerTests {
assertEquals("should be third reply", expectedThirdReply,
commandsManager.processCommand(user, "#" + mid + "/2 ",
URI.create("http://static.juick.com/settings/facebook.png")).getText());
- Message reply = messagesService.getReplies(mid).stream().filter(m -> m.getRid() == 3).findFirst()
+ Message reply = messagesService.getReplies(user, mid).stream().filter(m -> m.getRid() == 3).findFirst()
.orElse(new Message());
assertEquals("should be reply to second comment", 2, reply.getReplyto());
assertEquals("tags should NOT be updated", "It is not your message",
diff --git a/juick-www/src/main/java/com/juick/www/controllers/MessagesWWW.java b/juick-www/src/main/java/com/juick/www/controllers/MessagesWWW.java
index e6662c4e..5bbea56b 100644
--- a/juick-www/src/main/java/com/juick/www/controllers/MessagesWWW.java
+++ b/juick-www/src/main/java/com/juick/www/controllers/MessagesWWW.java
@@ -540,7 +540,7 @@ public class MessagesWWW {
model.addAttribute("visitorSubscribed", messagesService.isSubscribed(visitor.getUid(), msg.getMid()));
model.addAttribute("visitorInBL", userService.isInBL(msg.getUser().getUid(), visitor.getUid()));
model.addAttribute("recomm", messagesService.getMessageRecommendations(msg.getMid()));
- List<com.juick.Message> replies = messagesService.getReplies(msg.getMid());
+ List<com.juick.Message> replies = messagesService.getReplies(visitor, msg.getMid());
List<Integer> blUIDs = new ArrayList<>();
for (Message reply : replies) {
diff --git a/juick-www/src/main/java/com/juick/www/controllers/NewMessage.java b/juick-www/src/main/java/com/juick/www/controllers/NewMessage.java
index 042a1b0f..6b97c7c4 100644
--- a/juick-www/src/main/java/com/juick/www/controllers/NewMessage.java
+++ b/juick-www/src/main/java/com/juick/www/controllers/NewMessage.java
@@ -147,7 +147,7 @@ public class NewMessage {
}
String attachmentType = StringUtils.isNotEmpty(attachmentFName.toString()) ? attachmentFName.toString().substring(attachmentFName.toString().length() - 3) : null;
- int ridnew = messagesService.createReply(mid, rid, visitor.getUid(), body, attachmentType);
+ int ridnew = messagesService.createReply(mid, rid, visitor, body, attachmentType);
subscriptionService.subscribeMessage(mid, visitor.getUid());
Message xmsg = new Message();
diff --git a/juick-www/src/test/java/com/juick/WebAppTests.java b/juick-www/src/test/java/com/juick/WebAppTests.java
index e383a0a9..37798d08 100644
--- a/juick-www/src/test/java/com/juick/WebAppTests.java
+++ b/juick-www/src/test/java/com/juick/WebAppTests.java
@@ -167,7 +167,7 @@ public class WebAppTests {
public void repliesList() throws IOException {
int mid = messagesService.createMessage(ugnich.getUid(), "hello", null, null);
IntStream.range(1, 15).forEach(i ->
- messagesService.createReply(mid, i-1, freefd.getUid(), String.valueOf(i-1), null ));
+ messagesService.createReply(mid, i-1, freefd, String.valueOf(i-1), null ));
HtmlPage threadPage = webClient.getPage(String.format("http://localhost:8080/ugnich/%d", mid));
assertThat(threadPage.getWebResponse().getStatusCode(), equalTo(200));
@@ -181,7 +181,7 @@ public class WebAppTests {
@Test
public void userShouldNotSeeReplyButtonToBannedUser() throws Exception {
int mid = messagesService.createMessage(ugnich.getUid(), "freefd bl me", null, null);
- messagesService.createReply(mid, 0, ugnich.getUid(), "yo", null);
+ messagesService.createReply(mid, 0, ugnich, "yo", null);
MvcResult loginResult = mockMvc.perform(post("/login")
.param("username", freefdName)
.param("password", freefdPassword)).andReturn();
@@ -198,7 +198,8 @@ public class WebAppTests {
privacyQueriesService.blacklistUser(freefd, ugnich);
assertThat(userService.isInBLAny(freefd.getUid(), ugnich.getUid()), equalTo(true));
int renhaId = userService.createUser("renha", "secret");
- messagesService.createReply(mid, 0, renhaId, "people", null);
+ messagesService.createReply(mid, 0, userService.getUserByUID(renhaId).orElseThrow(IllegalStateException::new),
+ "people", null);
threadPage = webClient.getPage(String.format("http://localhost:8080/ugnich/%d", mid));
assertThat(threadPage.getWebResponse().getStatusCode(), equalTo(200));
assertThat(threadPage.querySelectorAll(".msg-comment-target").isEmpty(), equalTo(true));
@@ -292,7 +293,7 @@ public class WebAppTests {
.param("body", String.format("D #%d/%d", mid, 3)))
.andExpect(status().isFound());
Thread.sleep(5000);
- assertThat(messagesService.getReplies(mid).size(), equalTo(2));
+ assertThat(messagesService.getReplies(ugnich, mid).size(), equalTo(2));
}
@Test
public void hashLoginShouldNotUseSession() throws Exception {
@@ -342,7 +343,7 @@ public class WebAppTests {
discussions = (HtmlPage) discussions.refresh();
assertThat(discussions.querySelectorAll("article").size(), is(2));
assertThat(discussions.querySelectorAll("article").get(0).getAttributes().getNamedItem("data-mid").getNodeValue(), is(String.valueOf(midNew)));
- messagesService.createReply(mid, 0, freefd.getUid(), "I'm replied", null);
+ messagesService.createReply(mid, 0, freefd, "I'm replied", null);
discussions = (HtmlPage) discussions.refresh();
assertThat(discussions.querySelectorAll("article").size(), is(2));
assertThat(discussions.querySelectorAll("article").get(0).getAttributes().getNamedItem("data-mid").getNodeValue(), is(String.valueOf(mid)));
@@ -358,7 +359,7 @@ public class WebAppTests {
assertThat(discussions.querySelectorAll("article").size(), is(20));
assertThat(discussions.querySelectorAll("article")
.get(19).getAttributes().getNamedItem("data-mid").getNodeValue(), is(String.valueOf(mid)));
- messagesService.createReply(midNew, 0, freefd.getUid(), "I'm replied", null);
+ messagesService.createReply(midNew, 0, freefd, "I'm replied", null);
discussions = (HtmlPage) discussions.refresh();
assertThat(discussions.querySelectorAll("article")
.get(0).getAttributes().getNamedItem("data-mid").getNodeValue(), is(String.valueOf(midNew)));