From 03ffbef8ada6850bab48d0ef8ac04e1875242c01 Mon Sep 17 00:00:00 2001 From: Vladim1r37 Date: Mon, 27 May 2019 14:25:56 +0400 Subject: [PATCH 1/3] pagination feature added --- .../client/controller/ClientController.java | 12 + .../client/controller/MessageController.java | 95 +++++--- .../client/utils/ChatStompSessionHandler.java | 1 + .../client/view/ChatViewController.java | 207 ++++++++++++------ .../database/dao/DataBaseService.java | 4 + .../messenger/database/dao/MessageDAO.java | 22 ++ src/main/resources/client/fxml/ChatView.fxml | 2 +- 7 files changed, 241 insertions(+), 102 deletions(-) diff --git a/src/main/java/ru/geekbrains/pocket/messenger/client/controller/ClientController.java b/src/main/java/ru/geekbrains/pocket/messenger/client/controller/ClientController.java index d3b6ff6f..705b3027 100644 --- a/src/main/java/ru/geekbrains/pocket/messenger/client/controller/ClientController.java +++ b/src/main/java/ru/geekbrains/pocket/messenger/client/controller/ClientController.java @@ -13,7 +13,9 @@ import ru.geekbrains.pocket.messenger.database.entity.Message; import ru.geekbrains.pocket.messenger.database.entity.User; +import java.util.HashSet; import java.util.List; +import java.util.Set; public class ClientController { static final Logger controllerLogger = LogManager.getLogger(ClientController.class); @@ -27,6 +29,7 @@ public class ClientController { List contactList; List contactListOfCards; List conversation; + Set isChatUpdated; DataBaseService dbService; @@ -44,6 +47,7 @@ private ClientController() { myUser = null; conn = null; dbService = new DataBaseService(); + isChatUpdated = new HashSet<>(); authService = new AuthController(this); contactService = new ContactController(this); groupService = new GroupController(this); @@ -185,4 +189,12 @@ public void resetWaitForConfirm() { public void saveToDBAndShowMessage(String s) { messageService.saveToDBAndShowMessage(s); } + + public void loadPreviousPageOfMessages() { + messageService.loadPreviousPageOfMessages(); + } + + public void clearIsChatUpdatedSet() { + isChatUpdated.clear(); + } } diff --git a/src/main/java/ru/geekbrains/pocket/messenger/client/controller/MessageController.java b/src/main/java/ru/geekbrains/pocket/messenger/client/controller/MessageController.java index 36e1c10a..6c43172a 100644 --- a/src/main/java/ru/geekbrains/pocket/messenger/client/controller/MessageController.java +++ b/src/main/java/ru/geekbrains/pocket/messenger/client/controller/MessageController.java @@ -4,11 +4,9 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.springframework.messaging.simp.stomp.StompSession; -import ru.geekbrains.pocket.messenger.client.model.ServerResponse; import ru.geekbrains.pocket.messenger.client.model.formatMsgWithServer.MessageFromServer; import ru.geekbrains.pocket.messenger.client.model.formatMsgWithServer.MessageListFromServer; import ru.geekbrains.pocket.messenger.client.model.formatMsgWithServer.MessageToServer; -import ru.geekbrains.pocket.messenger.client.utils.Converter; import ru.geekbrains.pocket.messenger.client.utils.HTTPSRequest; import ru.geekbrains.pocket.messenger.client.utils.Sound; import ru.geekbrains.pocket.messenger.database.entity.Message; @@ -16,6 +14,7 @@ import java.sql.Timestamp; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import static ru.geekbrains.pocket.messenger.client.controller.ClientController.token; @@ -32,13 +31,14 @@ public class MessageController { static final Logger controllerLogger = LogManager.getLogger(MessageController.class); - - ClientController clientCtrllr; + public static final int PAGE_SIZE = 50; + + ClientController cc; private StompSession session; private MessageToServer waitForConfirm; MessageController(ClientController cc) { - clientCtrllr = cc; + this.cc = cc; } public StompSession getSession() { @@ -54,33 +54,37 @@ public void resetWaitForConfirm() { } void loadChat() { - clientCtrllr.conversation = clientCtrllr.dbService.getChat(clientCtrllr.myUser, clientCtrllr.receiver); - getChatWithUser(); - clientCtrllr.chatViewController.clearMessageWebView(); - for (Message message : clientCtrllr.conversation) { - clientCtrllr.chatViewController.showMessage(message, false); + if (!cc.isChatUpdated.contains(cc.receiver.getId())) { + cc.conversation = cc.dbService.getChat(cc.myUser, cc.receiver); + getChatWithUser(); + } + cc.conversation = cc.dbService.getChat(cc.myUser, cc.receiver, 0); + Collections.reverse(cc.conversation); + cc.chatViewController.clearMessageWebView(); + for (Message message : cc.conversation) { + cc.chatViewController.showMessage(message, false); } } - void receiveMessage(MessageFromServer mfs) { + synchronized void receiveMessage(MessageFromServer mfs) { //todo: доделать логику на получение уведомлений о прочтении отправленного сообщения!? //todo: доработать логику получения сообщения из группы //Проверяем, что осообщение пришло не от клиента в списке - if (!clientCtrllr.contactList.contains(mfs.getSender())) { - User newCont = clientCtrllr.contactService.getFromServerUserById(mfs.getSender()); + if (!cc.contactList.contains(mfs.getSender())) { + User newCont = cc.contactService.getFromServerUserById(mfs.getSender()); if (newCont != null) - clientCtrllr.contactService.addContact(newCont); + cc.contactService.addContact(newCont); else controllerLogger.error("Получено сообщение от пользователя, данных которого " + "нет на сервере. Сообщение:\n" + mfs); } Message mess = mfs.toMessageWithoutUsers(); - mess.setSender(clientCtrllr.dbService.getUserById(mfs.getSender())); - mess.setReceiver(clientCtrllr.dbService.getUserById(mfs.getRecipient())); - clientCtrllr.dbService.addMessage(mess); + mess.setSender(cc.dbService.getUserById(mfs.getSender())); + mess.setReceiver(cc.dbService.getUserById(mfs.getRecipient())); + cc.dbService.addMessage(mess); //Проверяем что у нас чат именно с этим пользователем, иначе сообщение не выводится - if (clientCtrllr.receiver != null && clientCtrllr.receiver.getId().equals(mfs.getSender())) { - clientCtrllr.chatViewController.showMessage(mess, true); + if (cc.receiver != null && cc.receiver.getId().equals(mfs.getSender())) { + cc.chatViewController.showMessage(mess, true); } else { //todo: превью и счётчик непрочитанных для контакта / группы, от которых пришло сообщение } @@ -90,12 +94,12 @@ void receiveMessage(MessageFromServer mfs) { } void sendMessage(String message) { - if (clientCtrllr.receiver == null) { + if (cc.receiver == null) { showAlert("Выберите контакт для отправки сообщения", Alert.AlertType.ERROR); return; } - MessageToServer mts = new MessageToServer(message, null, clientCtrllr.receiver.getId(), null); + MessageToServer mts = new MessageToServer(message, null, cc.receiver.getId(), null); session.send("/v1/send", mts); waitForConfirm = mts; } @@ -103,29 +107,34 @@ void sendMessage(String message) { public void saveToDBAndShowMessage(String messageId) { Message mess = new Message(); mess.setId(messageId); - mess.setReceiver(clientCtrllr.receiver); - mess.setSender(clientCtrllr.myUser); + mess.setReceiver(cc.receiver); + mess.setSender(cc.myUser); mess.setText(waitForConfirm.getText()); mess.setTime(new Timestamp(System.currentTimeMillis())); - clientCtrllr.dbService.addMessage(mess); + cc.dbService.addMessage(mess); - clientCtrllr.chatViewController.showMessage(mess, false); + cc.chatViewController.showMessage(mess, false); } void clearMessagesWithUser(User contact) { - if (!clientCtrllr.dbService.getChat(clientCtrllr.myUser, contact).isEmpty()) - clientCtrllr.dbService.deleteChat(clientCtrllr.myUser, contact); + if (!cc.dbService.getChat(cc.myUser, contact).isEmpty()) + cc.dbService.deleteChat(cc.myUser, contact); } private void getChatWithUser() { try { int pageOfMessages = 0; while (true) { - ServerResponse response = HTTPSRequest.getUserMessages(token, clientCtrllr.receiver.getId(), pageOfMessages++); - if (response.getResponseCode() != 200) break; - MessageListFromServer mlfs = Converter.toJavaObject(response.getResponseJson(), MessageListFromServer.class); - if (mlfs.getData().length == 0) break; + String receiverId = cc.receiver.getId(); + int responseCode = HTTPSRequest.sendRequest("/user/" + receiverId + + "/messages?offset=" + pageOfMessages++, "GET", null, token); + if (responseCode != 200) break; + MessageListFromServer mlfs = HTTPSRequest.getResponse(MessageListFromServer.class); + if (mlfs.getData().length == 0) { + cc.isChatUpdated.add(receiverId); + break; + } synchronizeMessageListFromServ(mlfs.getData()); } } catch (Exception e) { @@ -135,17 +144,31 @@ private void getChatWithUser() { private void synchronizeMessageListFromServ(MessageFromServer[] messages) { List messageListFromDbId = new ArrayList<>(); - for (Message message : clientCtrllr.conversation) { + for (Message message : cc.conversation) { messageListFromDbId.add(message.getId()); } for (MessageFromServer entry : messages) { Message mess = entry.toMessageWithoutUsers(); if (!messageListFromDbId.contains(mess.getId())) { - mess.setSender(clientCtrllr.dbService.getUserById(entry.getSender())); - mess.setReceiver(clientCtrllr.dbService.getUserById(entry.getRecipient())); - clientCtrllr.dbService.addMessage(mess); + mess.setSender(cc.dbService.getUserById(entry.getSender())); + mess.setReceiver(cc.dbService.getUserById(entry.getRecipient())); + cc.dbService.addMessage(mess); + cc.conversation.add(mess); + } + } + } + + synchronized void loadPreviousPageOfMessages() { + int currentPageNumber = (cc.chatViewController.getIdMsg() - 1) / PAGE_SIZE; + cc.conversation = cc.dbService.getChat(cc.myUser, cc.receiver, ++currentPageNumber); + if (cc.conversation.size() == 0) { + cc.chatViewController.setTopOfConversation(true); + } else { + cc.chatViewController.removeDateOnTop(); + for (Message message : cc.conversation) { + cc.chatViewController.showMessageOnTop(message); } + cc.chatViewController.showDateOnTop(); } - clientCtrllr.conversation = clientCtrllr.dbService.getChat(clientCtrllr.myUser, clientCtrllr.receiver); } } diff --git a/src/main/java/ru/geekbrains/pocket/messenger/client/utils/ChatStompSessionHandler.java b/src/main/java/ru/geekbrains/pocket/messenger/client/utils/ChatStompSessionHandler.java index 401b661c..9e602db6 100644 --- a/src/main/java/ru/geekbrains/pocket/messenger/client/utils/ChatStompSessionHandler.java +++ b/src/main/java/ru/geekbrains/pocket/messenger/client/utils/ChatStompSessionHandler.java @@ -22,6 +22,7 @@ public ChatStompSessionHandler(ClientController clientCtrllr) { public void afterConnected(StompSession session, StompHeaders connectedHeaders) { clientCtrllr.setMessageSession(session); sessionLogger.info("websocket connection established"); + clientCtrllr.clearIsChatUpdatedSet(); session.subscribe("/user/queue/new", new StompFrameHandler() { diff --git a/src/main/java/ru/geekbrains/pocket/messenger/client/view/ChatViewController.java b/src/main/java/ru/geekbrains/pocket/messenger/client/view/ChatViewController.java index a903a16b..c5e3c0b6 100644 --- a/src/main/java/ru/geekbrains/pocket/messenger/client/view/ChatViewController.java +++ b/src/main/java/ru/geekbrains/pocket/messenger/client/view/ChatViewController.java @@ -1,5 +1,6 @@ package ru.geekbrains.pocket.messenger.client.view; +import javafx.scene.input.ScrollEvent; import ru.geekbrains.pocket.messenger.client.Main; import ru.geekbrains.pocket.messenger.client.controller.ClientController; import ru.geekbrains.pocket.messenger.client.utils.Common; @@ -157,12 +158,16 @@ public class ChatViewController implements Initializable { private Document DOMdocument; - private String tsOld; + private String tsOldOfBottom; + private String tsOldOfTop; - private int idDivMsg; + private boolean isTopOfConversation; private int idMsg; + private SimpleDateFormat dateFormatDay = initDateFormat("d MMMM"); + private SimpleDateFormat dateFormat = initDateFormat("HH:mm"); + @FXML private JFXButton btnContactSearchCancel; @@ -182,6 +187,7 @@ public class ChatViewController implements Initializable { @FXML private JFXButton btnRightMenu; + public static ChatViewController getInstance() { return instance; } @@ -204,11 +210,12 @@ public void setIdMsg(int idMsg) { this.idMsg = idMsg; } + public void setTopOfConversation(boolean isTop) { + isTopOfConversation = isTop; + } + @Override public void initialize(URL url, ResourceBundle rb) { - DOMdocument = null; - tsOld = null; //чистка даты - idMsg = 0; //присваивание ID webEngine = messageWebView.getEngine(); //инициализация WebEngine initWebView(); @@ -253,6 +260,15 @@ public void initialize(URL url, ResourceBundle rb) { // инициализация только HTML в WebView. private void initWebView() { webEngine.load(getClass().getClassLoader().getResource("client/html/Chat.html").toString()); + if (webEngine.getLoadWorker().getState() == Worker.State.SUCCEEDED) { + DOMdocument = webEngine.getDocument(); + }else { + webEngine.getLoadWorker().stateProperty().addListener((observable, oldState, newState) -> { + if (newState == Worker.State.SUCCEEDED) { + DOMdocument = webEngine.getDocument(); + } + }); + } } private void fillContactListView() { @@ -319,48 +335,52 @@ private SimpleDateFormat initDateFormat(String pattern){ * Style create in initWebView * */ - private void createMessageDiv(Message mess, String attrClass){ - - String message = mess.getText(); - String senderName = mess.getSender().getUserName(); - Timestamp timestamp = mess.getTime(); + private void showMessageDiv(Message mess, String attrClass){ //ID требуется для скрипта вставки тегов - idMsg+=1; - setIdMsg(idMsg); - //получаем аватар - //тут по идеи подбор по полу. Оставляю чтобы было понятно куда вставляется и настроить стили - String avatar = initAvatar(false); //man - String styleStr = "background-image: url(" + avatar + "); background-size: cover"; - // + idMsg++; - SimpleDateFormat dateFormatDay = initDateFormat("d MMMM"); - SimpleDateFormat dateFormat = initDateFormat("HH:mm"); + Timestamp timestamp = mess.getTime(); + boolean isNewDateHasCome = false; + if (tsOldOfBottom == null) { + tsOldOfBottom = tsOldOfTop = dateFormatDay.format(timestamp); + isNewDateHasCome = true; + } + if (!tsOldOfBottom.equals(dateFormatDay.format(timestamp))) { + tsOldOfBottom = dateFormatDay.format(timestamp); + isNewDateHasCome = true; + } - //Заменяем Enter на перенос строки, для отображения - message = message.replaceAll("\n", "
"); - //Парсим ссылки, получаем строку вида message - message = Common.urlToHyperlink(message); - message = message.replace("\\", "\\\\") - .replace("'", "\\'"); - boolean visibleDateDay=false; - if (tsOld == null) { - tsOld = dateFormatDay.format(timestamp); - visibleDateDay = true; - }else if (!tsOld.equals(dateFormatDay.format(timestamp))) { - tsOld = dateFormatDay.format(timestamp); - visibleDateDay = true; - } + String message = prepareMessageText(mess); Node body = DOMdocument.getElementsByTagName("body").item(0); - if (visibleDateDay) { + if (isNewDateHasCome) { Element divTimeDay = DOMdocument.createElement("div"); divTimeDay.setAttribute("class", "timeStampDay"); divTimeDay.setTextContent(dateFormatDay.format(timestamp)); body.appendChild(divTimeDay); } + Element messageDiv = createMessageDiv(mess, attrClass, message); + body.appendChild(messageDiv); + //Scripts + //вставляем текст с тегами + webEngine.executeScript("document.getElementById(\"" + idMsg + "\").innerHTML = '" + message +"'"); + //Сдвигаем страницу на последний элемент + webEngine.executeScript("document.body.scrollTop = document.body.scrollHeight"); + } + + private Element createMessageDiv(Message mess, String attrClass, String message) { + //получаем аватар + //тут по идеи подбор по полу. Оставляю чтобы было понятно куда вставляется и настроить стили + String avatar = initAvatar(false); //man + String styleStr = "background-image: url(" + avatar + "); background-size: cover"; + + String senderName = mess.getSender().getUserName(); + + Timestamp timestamp = mess.getTime(); + Element div = DOMdocument.createElement("div"); Element divLogo = DOMdocument.createElement("div"); Element divTxt = DOMdocument.createElement("div"); @@ -383,16 +403,25 @@ private void createMessageDiv(Message mess, String attrClass){ div.appendChild(divLogo); div.appendChild(divTxt); div.appendChild(divTime); - body.appendChild(div); - //Scripts - //вставляем текст с тегами - webEngine.executeScript("document.getElementById(\"" + idMsg + "\").innerHTML = '" + message+"'"); - //Сдвигаем страницу на последний элемент - webEngine.executeScript("document.body.scrollTop = document.body.scrollHeight"); + //Подписка на событие по открытию ссылки addListenerLinkExternalBrowser(divTxtMsg); //проверяет, есть ли у нас в сообщениях картинки addImageMessageListener(divTxtMsg); + + return div; + } + + private String prepareMessageText(Message mess) { + String message = mess.getText(); + + //Заменяем Enter на перенос строки, для отображения + message = message.replaceAll("\n", "
"); + //Парсим ссылки, получаем строку вида message + message = Common.urlToHyperlink(message); + message = message.replace("\\", "\\\\") + .replace("'", "\\'"); + return message; } public void showMessage(Message mess, boolean isNew) { @@ -400,6 +429,20 @@ public void showMessage(Message mess, boolean isNew) { Sound.playSoundNewMessage().join(); }*/ + String attrClass = getSenderUserClass(mess); + + while (DOMdocument == null) { + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + showMessageDiv(mess, attrClass); + updateLastMessageInCardsBody(mess); + } + + private String getSenderUserClass(Message mess) { String senderName = mess.getSender().getUserName(); String attrClass; @@ -408,28 +451,7 @@ public void showMessage(Message mess, boolean isNew) { } else { attrClass = "senderUserClass"; } - - //todo по хорошему надо переместить подписку на событие в другое место - //Подписка на событие загрузки документа HTML in WebView - if (DOMdocument == null) { - //если пользователь только запустил клиента и локально нет ни одного сообщения - if (webEngine.getLoadWorker().getState() == Worker.State.SUCCEEDED) { - DOMdocument = webEngine.getDocument(); - createMessageDiv(mess, attrClass); - updateLastMessageInCardsBody(mess); - }else { - webEngine.getLoadWorker().stateProperty().addListener((observable, oldState, newState) -> { - if (newState == Worker.State.SUCCEEDED) { - DOMdocument = webEngine.getDocument(); // Должен быть здесь т.к. загрузка WebEngine только произошла - createMessageDiv(mess, attrClass); - updateLastMessageInCardsBody(mess); - } - }); - } - }else { - createMessageDiv(mess, attrClass); - updateLastMessageInCardsBody(mess); - } + return attrClass; } private void updateLastMessageInCardsBody(Message mess){ @@ -626,7 +648,7 @@ public void handleSendSmile() { /** * Вызывается для чистки документа внутри WebEngine * при первом вызове чистки нет, т.к. DOMdocument == null - * так де обнуляем дату для группировки (tsOld) и ID для DIV + * также обнуляем дату для группировки (tsOldOfBottom) и ID для DIV */ public void clearMessageWebView() { if (DOMdocument != null) { @@ -639,8 +661,10 @@ public void clearMessageWebView() { } } - tsOld = null; //чистка даты - idDivMsg =0; //присваивание ID + tsOldOfBottom = null; //чистка даты + tsOldOfTop = null; //чистка даты + idMsg = 0; + isTopOfConversation = false; } //метод смены иконки @@ -859,4 +883,57 @@ public void alarmDeleteProfileExecute(){ public void alarmExitProfileExecute(){ new AlarmExitProfile(); } + + public void onScrollLoadPage(ScrollEvent event) { + int scrollTop = (Integer) webEngine.executeScript("document.body.scrollTop"); + if (idMsg != 0 && scrollTop < 10 && !isTopOfConversation) { + clientController.loadPreviousPageOfMessages(); + } + } + + public void showMessageOnTop(Message mess) { + String attrClass = getSenderUserClass(mess); + + idMsg++; + + String message = prepareMessageText(mess); + + Node body = DOMdocument.getElementsByTagName("body").item(0); + + Timestamp timestamp = mess.getTime(); + + if (!tsOldOfTop.equals(dateFormatDay.format(timestamp))) { + Element divTimeDay = getCurrentDateDiv(); + body.insertBefore(divTimeDay, body.getFirstChild()); + tsOldOfTop = dateFormatDay.format(timestamp); + } + Element messageDiv = createMessageDiv(mess, attrClass, message); + int oldScrollHeight = (Integer) webEngine.executeScript("document.body.scrollHeight"); + body.insertBefore(messageDiv, body.getFirstChild()); + + webEngine.executeScript("document.body.scrollTop += document.body.scrollHeight - " + oldScrollHeight); + webEngine.executeScript("document.getElementById(\"" + idMsg + "\").innerHTML = '" + message +"'"); + + } + + private Element getCurrentDateDiv() { + Element divTimeDay = DOMdocument.createElement("div"); + divTimeDay.setAttribute("class", "timeStampDay"); + divTimeDay.setTextContent(tsOldOfTop); + return divTimeDay; + } + + public void showDateOnTop() { + Node body = DOMdocument.getElementsByTagName("body").item(0); + Element el = (Element) body.getFirstChild(); + if (!el.getAttribute("class").equals("timeStampDay")) { + Element divTimeDay = getCurrentDateDiv(); + body.insertBefore(divTimeDay, body.getFirstChild()); + } + } + + public void removeDateOnTop() { + Node body = DOMdocument.getElementsByTagName("body").item(0); + body.removeChild(body.getFirstChild()); + } } diff --git a/src/main/java/ru/geekbrains/pocket/messenger/database/dao/DataBaseService.java b/src/main/java/ru/geekbrains/pocket/messenger/database/dao/DataBaseService.java index 1777e5a8..d34b7f48 100644 --- a/src/main/java/ru/geekbrains/pocket/messenger/database/dao/DataBaseService.java +++ b/src/main/java/ru/geekbrains/pocket/messenger/database/dao/DataBaseService.java @@ -99,6 +99,10 @@ public List getChat(User user1, User user2){ return messageDao.get(user1, user2); } + public List getChat(User user1, User user2, int pageNumber){ + return messageDao.get(user1, user2, pageNumber); + } + public void deleteChat(User user1, User user2){ messageDao.delete(user1, user2); } diff --git a/src/main/java/ru/geekbrains/pocket/messenger/database/dao/MessageDAO.java b/src/main/java/ru/geekbrains/pocket/messenger/database/dao/MessageDAO.java index 98a0df0b..2e8875d2 100644 --- a/src/main/java/ru/geekbrains/pocket/messenger/database/dao/MessageDAO.java +++ b/src/main/java/ru/geekbrains/pocket/messenger/database/dao/MessageDAO.java @@ -1,5 +1,6 @@ package ru.geekbrains.pocket.messenger.database.dao; +import ru.geekbrains.pocket.messenger.client.controller.MessageController; import ru.geekbrains.pocket.messenger.database.HibernateUtil; import ru.geekbrains.pocket.messenger.database.entity.Message; import ru.geekbrains.pocket.messenger.database.entity.User; @@ -66,6 +67,27 @@ List get(User agent1id, User agent2id){ return messages; } + List get(User agent1id, User agent2id, int pageNumber){ + Session session = HibernateUtil.getSessionFactory().getCurrentSession(); + session.getTransaction().begin(); + + Query query = session.createQuery("FROM Message m where " + + "(m.sender = :id1Param and m.receiver = :id2Param) " + + "or " + + "(m.receiver = :id1Param and m.sender = :id2Param)" + + "order by m.id desc"); + query.setParameter("id1Param", agent1id); + query.setParameter("id2Param", agent2id); + int pageSize = MessageController.PAGE_SIZE; + query.setFirstResult(pageNumber * pageSize); + query.setMaxResults(pageSize); + List messages = query.list(); + + session.getTransaction().commit(); + + return messages; + } + void delete(User agent1id, User agent2id){ Session session = HibernateUtil.getSessionFactory().getCurrentSession(); session.getTransaction().begin(); diff --git a/src/main/resources/client/fxml/ChatView.fxml b/src/main/resources/client/fxml/ChatView.fxml index 2bf89b09..147735cc 100644 --- a/src/main/resources/client/fxml/ChatView.fxml +++ b/src/main/resources/client/fxml/ChatView.fxml @@ -138,7 +138,7 @@ - + From 6c5568757929d9e3aaa5064046bf12e67b4dc39f Mon Sep 17 00:00:00 2001 From: Vladim1r37 Date: Wed, 12 Jun 2019 00:40:49 +0400 Subject: [PATCH 2/3] loadPreviousPageOfMessages() method calling modified. --- .../client/controller/MessageController.java | 1 + .../messenger/client/view/ChatViewController.java | 11 ++++++++--- src/main/resources/client/fxml/ChatView.fxml | 2 +- src/main/resources/client/html/Chat.html | 1 + src/main/resources/client/html/OnScrollHandler.js | 5 +++++ 5 files changed, 16 insertions(+), 4 deletions(-) create mode 100644 src/main/resources/client/html/OnScrollHandler.js diff --git a/src/main/java/ru/geekbrains/pocket/messenger/client/controller/MessageController.java b/src/main/java/ru/geekbrains/pocket/messenger/client/controller/MessageController.java index 6c43172a..b949dd25 100644 --- a/src/main/java/ru/geekbrains/pocket/messenger/client/controller/MessageController.java +++ b/src/main/java/ru/geekbrains/pocket/messenger/client/controller/MessageController.java @@ -64,6 +64,7 @@ void loadChat() { for (Message message : cc.conversation) { cc.chatViewController.showMessage(message, false); } + cc.chatViewController.addJSBridgeToWebView(); } synchronized void receiveMessage(MessageFromServer mfs) { diff --git a/src/main/java/ru/geekbrains/pocket/messenger/client/view/ChatViewController.java b/src/main/java/ru/geekbrains/pocket/messenger/client/view/ChatViewController.java index c5e3c0b6..c9ee4025 100644 --- a/src/main/java/ru/geekbrains/pocket/messenger/client/view/ChatViewController.java +++ b/src/main/java/ru/geekbrains/pocket/messenger/client/view/ChatViewController.java @@ -1,6 +1,7 @@ package ru.geekbrains.pocket.messenger.client.view; import javafx.scene.input.ScrollEvent; +import netscape.javascript.JSObject; import ru.geekbrains.pocket.messenger.client.Main; import ru.geekbrains.pocket.messenger.client.controller.ClientController; import ru.geekbrains.pocket.messenger.client.utils.Common; @@ -884,9 +885,8 @@ public void alarmExitProfileExecute(){ new AlarmExitProfile(); } - public void onScrollLoadPage(ScrollEvent event) { - int scrollTop = (Integer) webEngine.executeScript("document.body.scrollTop"); - if (idMsg != 0 && scrollTop < 10 && !isTopOfConversation) { + public void loadPreviousPageOfMessages() { + if (idMsg != 0 && !isTopOfConversation) { clientController.loadPreviousPageOfMessages(); } } @@ -936,4 +936,9 @@ public void removeDateOnTop() { Node body = DOMdocument.getElementsByTagName("body").item(0); body.removeChild(body.getFirstChild()); } + + public void addJSBridgeToWebView() { + JSObject window = (JSObject) webEngine.executeScript("window"); + window.setMember("chatViewController", this); + } } diff --git a/src/main/resources/client/fxml/ChatView.fxml b/src/main/resources/client/fxml/ChatView.fxml index 147735cc..2bf89b09 100644 --- a/src/main/resources/client/fxml/ChatView.fxml +++ b/src/main/resources/client/fxml/ChatView.fxml @@ -138,7 +138,7 @@ - + diff --git a/src/main/resources/client/html/Chat.html b/src/main/resources/client/html/Chat.html index 3902fc31..72b56cfa 100644 --- a/src/main/resources/client/html/Chat.html +++ b/src/main/resources/client/html/Chat.html @@ -3,6 +3,7 @@ + diff --git a/src/main/resources/client/html/OnScrollHandler.js b/src/main/resources/client/html/OnScrollHandler.js new file mode 100644 index 00000000..41392cc7 --- /dev/null +++ b/src/main/resources/client/html/OnScrollHandler.js @@ -0,0 +1,5 @@ +window.onscroll = function() { + if (document.body.scrollTop < 10) { + chatViewController.loadPreviousPageOfMessages(); + } +} \ No newline at end of file From 0835b7b122b227b1e46289dac4af9487d7b652e5 Mon Sep 17 00:00:00 2001 From: Vladim1r37 Date: Wed, 12 Jun 2019 03:30:04 +0400 Subject: [PATCH 3/3] bugfix: URL is loaded into webview instead of external browser --- .../pocket/messenger/client/Main.java | 7 ++++ .../client/controller/ClientController.java | 11 ++++++ .../client/view/ChatViewController.java | 34 ++++++++++++------- .../client/view/RootLayoutController.java | 4 +++ 4 files changed, 43 insertions(+), 13 deletions(-) diff --git a/src/main/java/ru/geekbrains/pocket/messenger/client/Main.java b/src/main/java/ru/geekbrains/pocket/messenger/client/Main.java index 88a22c09..381872cc 100644 --- a/src/main/java/ru/geekbrains/pocket/messenger/client/Main.java +++ b/src/main/java/ru/geekbrains/pocket/messenger/client/Main.java @@ -1,5 +1,7 @@ package ru.geekbrains.pocket.messenger.client; +import javafx.application.HostServices; +import ru.geekbrains.pocket.messenger.client.view.RootLayoutController; import ru.geekbrains.pocket.messenger.client.view.Tray; import javafx.application.Application; import javafx.fxml.FXMLLoader; @@ -18,10 +20,12 @@ public class Main extends Application { public static Stage primaryStage; private static BorderPane rootLayout; + private static HostServices hostServices; private static final Logger mainLogger = LogManager.getLogger(Main.class); @Override public void start(Stage stage) { + hostServices = getHostServices(); primaryStage = stage; primaryStage.setTitle("Pocket desktop ru.geekbrains.pocket.messenger.client"); primaryStage.getIcons().add(new Image(getClass().getResourceAsStream("/client/images/icon.png"))); @@ -49,6 +53,9 @@ public static void initRootLayout() { loader.setLocation(Main.class.getResource("/client/fxml/RootLayout.fxml")); rootLayout = loader.load(); + RootLayoutController rlc = loader.getController(); + rlc.getController().setHostServices(hostServices); + Scene scene = new Scene(rootLayout); Cursor cursor = Cursor.cursor("HAND"); diff --git a/src/main/java/ru/geekbrains/pocket/messenger/client/controller/ClientController.java b/src/main/java/ru/geekbrains/pocket/messenger/client/controller/ClientController.java index f70128fd..22374a56 100644 --- a/src/main/java/ru/geekbrains/pocket/messenger/client/controller/ClientController.java +++ b/src/main/java/ru/geekbrains/pocket/messenger/client/controller/ClientController.java @@ -1,6 +1,7 @@ package ru.geekbrains.pocket.messenger.client.controller; +import javafx.application.HostServices; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.springframework.messaging.simp.stomp.StompSession; @@ -38,6 +39,16 @@ public class ClientController { GroupController groupService; MessageController messageService; + private HostServices hostServices; + + public HostServices getHostServices() { + return hostServices; + } + + public void setHostServices(HostServices hostServices) { + this.hostServices = hostServices; + } + public void setChatViewController(ChatViewController chatViewController) { this.chatViewController = chatViewController; } diff --git a/src/main/java/ru/geekbrains/pocket/messenger/client/view/ChatViewController.java b/src/main/java/ru/geekbrains/pocket/messenger/client/view/ChatViewController.java index b4f9d426..abaebc8f 100644 --- a/src/main/java/ru/geekbrains/pocket/messenger/client/view/ChatViewController.java +++ b/src/main/java/ru/geekbrains/pocket/messenger/client/view/ChatViewController.java @@ -1,6 +1,5 @@ package ru.geekbrains.pocket.messenger.client.view; -import javafx.scene.input.ScrollEvent; import netscape.javascript.JSObject; import ru.geekbrains.pocket.messenger.client.Main; import ru.geekbrains.pocket.messenger.client.controller.ClientController; @@ -370,6 +369,17 @@ private void showMessageDiv(Message mess, String attrClass){ webEngine.executeScript("document.getElementById(\"" + idMsg + "\").innerHTML = '" + message +"'"); //Сдвигаем страницу на последний элемент webEngine.executeScript("document.body.scrollTop = document.body.scrollHeight"); + + addListenersToMsgDiv(); + + } + + private void addListenersToMsgDiv() { + Element divTxtMsg = DOMdocument.getElementById(String.valueOf(idMsg)); + //Подписка на событие по открытию ссылки + addListenerLinkExternalBrowser(divTxtMsg); + //проверяет, есть ли у нас в сообщениях картинки + addImageMessageListener(divTxtMsg); } private Element createMessageDiv(Message mess, String attrClass, String message) { @@ -405,11 +415,6 @@ private Element createMessageDiv(Message mess, String attrClass, String message) div.appendChild(divTxt); div.appendChild(divTime); - //Подписка на событие по открытию ссылки - addListenerLinkExternalBrowser(divTxtMsg); - //проверяет, есть ли у нас в сообщениях картинки - addImageMessageListener(divTxtMsg); - return div; } @@ -575,16 +580,18 @@ public void handleEvent(Event evt) { String domEventType = evt.getType(); if ("click".equals(domEventType)) { String href = ((Element) evt.getTarget()).getAttribute("href"); + String url = href.contains("://") ? href : "http://" + href + "/"; try { // Open URL in Browser: //ну удалил, т.к. не много не понятно пока зачем - //if (desktop.isSupported(Desktop.Action.BROWSE)) { - desktop.browse(new URI(href.contains("://") ? href : "http://" + href + "/")); - //отменяем событие, чтобы ссылка не открывалась в самом webView - evt.preventDefault(); - /*} else { - System.out.println("Could not load URL: " + href); - }*/ + if (desktop.isSupported(Desktop.Action.BROWSE)) { + desktop.browse(new URI(url)); + } else { + clientController.getHostServices().showDocument(url); + System.out.println("Desktop API is not supported. URL loaded by HostServices: " + href); + } + //отменяем событие, чтобы ссылка не открывалась в самом webView + evt.preventDefault(); } catch (IOException | URISyntaxException e) { //todo logger e.printStackTrace(); @@ -914,6 +921,7 @@ public void showMessageOnTop(Message mess) { webEngine.executeScript("document.body.scrollTop += document.body.scrollHeight - " + oldScrollHeight); webEngine.executeScript("document.getElementById(\"" + idMsg + "\").innerHTML = '" + message +"'"); + addListenersToMsgDiv(); } private Element getCurrentDateDiv() { diff --git a/src/main/java/ru/geekbrains/pocket/messenger/client/view/RootLayoutController.java b/src/main/java/ru/geekbrains/pocket/messenger/client/view/RootLayoutController.java index fe07ab8e..cc853668 100644 --- a/src/main/java/ru/geekbrains/pocket/messenger/client/view/RootLayoutController.java +++ b/src/main/java/ru/geekbrains/pocket/messenger/client/view/RootLayoutController.java @@ -11,6 +11,10 @@ public class RootLayoutController implements Initializable { private ClientController controller; + public ClientController getController() { + return controller; + } + @Override public void initialize(URL url, ResourceBundle rb) { controller = ClientController.getInstance();