mirror of
https://github.com/maxkratz/lectureStudio.git
synced 2024-05-18 20:00:16 +00:00
Compare commits
10 commits
da11e75393
...
b9701a91d4
Author | SHA1 | Date | |
---|---|---|---|
b9701a91d4 | |||
6fc39584f2 | |||
3017e56d38 | |||
3670addb1b | |||
159f46a59c | |||
9bfe08f8f3 | |||
5381908205 | |||
af1ed754ee | |||
9a31df9413 | |||
af82092ccb |
|
@ -28,7 +28,6 @@ import java.util.ArrayList;
|
|||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.lecturestudio.core.geometry.Dimension2D;
|
||||
import org.lecturestudio.core.geometry.Rectangle2D;
|
||||
|
@ -758,8 +757,8 @@ public class Document {
|
|||
pages.clear();
|
||||
|
||||
int pageCount = pdfDocument.getPageCount();
|
||||
String[] prevSplitPageText = new String[2];
|
||||
String[] splitPageText;
|
||||
|
||||
List<String> lastPageTextLines = List.of();
|
||||
|
||||
for (int number = 0; number < pageCount; number++) {
|
||||
Page page = new Page(this, number);
|
||||
|
@ -772,26 +771,24 @@ public class Document {
|
|||
}
|
||||
}
|
||||
|
||||
splitPageText = page.getPageText().split("\n");
|
||||
List<String> pageTextLines = pdfDocument.getPageTextLines(number, 2);
|
||||
|
||||
if (splitPageText.length >= 2 && prevSplitPageText.length >= 2 &&
|
||||
Stream.of(prevSplitPageText[0], prevSplitPageText[1], splitPageText[0], splitPageText[1])
|
||||
.allMatch(Objects::nonNull)) {
|
||||
if (prevSplitPageText[0].equals(splitPageText[0]) && prevSplitPageText[1].equals(splitPageText[1])) {
|
||||
page.setOverlay(true);
|
||||
List<String> finalLastPageTextLines = lastPageTextLines;
|
||||
List<String> differences = pageTextLines.stream()
|
||||
.filter(element -> !finalLastPageTextLines.contains(element)).toList();
|
||||
|
||||
if (number > 0) {
|
||||
Page prevPage = pages.get(number - 1);
|
||||
prevPage.setOverlay(true);
|
||||
}
|
||||
}
|
||||
else {
|
||||
prevSplitPageText = splitPageText;
|
||||
// The pages have equal content, thus mark them as overlay pages.
|
||||
if (differences.isEmpty()) {
|
||||
page.setOverlay(true);
|
||||
|
||||
if (number > 0) {
|
||||
Page prevPage = pages.get(number - 1);
|
||||
prevPage.setOverlay(true);
|
||||
}
|
||||
}
|
||||
else {
|
||||
prevSplitPageText = splitPageText;
|
||||
}
|
||||
|
||||
lastPageTextLines = pageTextLines;
|
||||
|
||||
pages.add(page);
|
||||
}
|
||||
|
||||
|
|
|
@ -130,6 +130,16 @@ public interface DocumentAdapter {
|
|||
*/
|
||||
String getPageText(int pageNumber) throws IOException;
|
||||
|
||||
/**
|
||||
* Get the text of the page as a list where each list entry represents a text line in the page.
|
||||
*
|
||||
* @param pageNumber The page number.
|
||||
* @param maxLines The maximum number of lines to retrieve.
|
||||
*
|
||||
* @return the text of the page as a list of text lines in the page.
|
||||
*/
|
||||
List<String> getPageTextLines(int pageNumber, int maxLines);
|
||||
|
||||
/**
|
||||
* Get the word bounds of the page that has the specified page number.
|
||||
*
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* Copyright (C) 2020 TU Darmstadt, Department of Computer Science,
|
||||
* Embedded Systems and Applications Group.
|
||||
*
|
||||
* 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
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.lecturestudio.core.pdf;
|
||||
|
||||
public interface DocumentPlatformQueue {
|
||||
|
||||
void runInPlatformQueue(Runnable runnable);
|
||||
|
||||
}
|
|
@ -0,0 +1,83 @@
|
|||
/*
|
||||
* Copyright (C) 2020 TU Darmstadt, Department of Computer Science,
|
||||
* Embedded Systems and Applications Group.
|
||||
*
|
||||
* 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
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.lecturestudio.core.pdf;
|
||||
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
|
||||
public class DocumentWorker {
|
||||
|
||||
private final DocumentPlatformQueue eventQueue;
|
||||
|
||||
protected LinkedBlockingQueue<DocumentWorkerTask> queue;
|
||||
|
||||
protected boolean alive;
|
||||
|
||||
protected Thread thread;
|
||||
|
||||
|
||||
public DocumentWorker(DocumentPlatformQueue eventQueue) {
|
||||
this.eventQueue = eventQueue;
|
||||
|
||||
queue = new LinkedBlockingQueue<>();
|
||||
thread = new Thread(this::run);
|
||||
}
|
||||
|
||||
public void start() {
|
||||
alive = true;
|
||||
|
||||
thread.start();
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
alive = false;
|
||||
|
||||
thread.interrupt();
|
||||
}
|
||||
|
||||
public void add(DocumentWorkerTask task) {
|
||||
try {
|
||||
queue.put(task);
|
||||
}
|
||||
catch (InterruptedException x) {
|
||||
// Ignore
|
||||
}
|
||||
}
|
||||
|
||||
public void run() {
|
||||
while (alive) {
|
||||
final DocumentWorkerTask task;
|
||||
|
||||
try {
|
||||
task = queue.take();
|
||||
}
|
||||
catch (InterruptedException x) {
|
||||
break;
|
||||
}
|
||||
|
||||
try {
|
||||
task.runInBackground();
|
||||
|
||||
eventQueue.runInPlatformQueue(task);
|
||||
}
|
||||
catch (final Throwable t) {
|
||||
eventQueue.runInPlatformQueue(() -> task.exception(t));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* Copyright (C) 2020 TU Darmstadt, Department of Computer Science,
|
||||
* Embedded Systems and Applications Group.
|
||||
*
|
||||
* 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
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.lecturestudio.core.pdf;
|
||||
|
||||
public abstract class DocumentWorkerTask implements Runnable {
|
||||
|
||||
/**
|
||||
* This method will be executed on the background thread.
|
||||
*/
|
||||
public void runInBackground() {
|
||||
}
|
||||
|
||||
/**
|
||||
* This method will be executed on the UI thread if work() did not throw any exception.
|
||||
*/
|
||||
public void run() {
|
||||
}
|
||||
|
||||
/**
|
||||
* This method will be executed on the UI thread if work() throws an exception.
|
||||
*
|
||||
* @param t The throwable containing the error.
|
||||
*/
|
||||
public void exception(final Throwable t) {
|
||||
}
|
||||
|
||||
}
|
|
@ -317,6 +317,18 @@ public class PdfDocument {
|
|||
return muPDFDocument.getPageText(pageNumber);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the text of the page as a list where each list entry represents a text line in the page.
|
||||
*
|
||||
* @param pageNumber The page number.
|
||||
* @param maxLines The maximum number of lines to retrieve.
|
||||
*
|
||||
* @return the text of the page as a list of text lines in the page.
|
||||
*/
|
||||
public List<String> getPageTextLines(int pageNumber, int maxLines) {
|
||||
return muPDFDocument.getPageTextLines(pageNumber, maxLines);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the word bounds of the page that has the specified page number.
|
||||
*
|
||||
|
|
|
@ -41,14 +41,9 @@ import java.io.IOException;
|
|||
import java.io.OutputStream;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.net.URI;
|
||||
import java.util.AbstractMap;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.lecturestudio.core.geometry.Rectangle2D;
|
||||
import org.lecturestudio.core.io.BitConverter;
|
||||
|
@ -201,7 +196,6 @@ public class MuPDFDocument implements DocumentAdapter {
|
|||
Page page = getPage(pageNumber);
|
||||
|
||||
SimpleTextWalker textWalker = new SimpleTextWalker(page.getBounds());
|
||||
|
||||
StructuredText structuredText = displayList.toStructuredText();
|
||||
structuredText.walk(textWalker);
|
||||
|
||||
|
@ -496,6 +490,62 @@ public class MuPDFDocument implements DocumentAdapter {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getPageTextLines(int pageNumber, int maxLines) {
|
||||
synchronized (mutex) {
|
||||
List<String> lines = new ArrayList<>();
|
||||
DisplayList displayList = getDisplayList(pageNumber);
|
||||
StructuredText structuredText = displayList.toStructuredText();
|
||||
|
||||
// Sort page text blocks, so that the page text is chronologically ordered (top-down).
|
||||
var sorted = Arrays.stream(structuredText.getBlocks())
|
||||
.sorted((o1, o2) -> o1.bbox.y0 < o2.bbox.y0 ? -1 : 1)
|
||||
.toList();
|
||||
|
||||
// Last text block y-position.
|
||||
double lastY0 = Double.MAX_VALUE;
|
||||
double lastY1 = Double.MAX_VALUE;
|
||||
|
||||
// Read text lines from each block.
|
||||
for (var block : sorted) {
|
||||
// Check if the blocks intersect each other.
|
||||
boolean intersects = (block.bbox.y0 >= lastY0 && block.bbox.y0 <= lastY1)
|
||||
|| (block.bbox.y1 >= lastY0 && block.bbox.y1 <= lastY1);
|
||||
|
||||
if (block.lines.length > 0) {
|
||||
StructuredText.TextLine textLine = block.lines[0];
|
||||
|
||||
if (textLine.chars.length > 0) {
|
||||
// Convert individual chars into lines of strings.
|
||||
var text = Arrays.stream(textLine.chars)
|
||||
.map(textChar -> Character.toString(textChar.c))
|
||||
.collect(Collectors.joining(""));
|
||||
|
||||
// If the blocks intersect, merge the text into a single line.
|
||||
if (intersects) {
|
||||
// Get last line text.
|
||||
int index = lines.size() - 1;
|
||||
String lastLine = lines.get(index) + text;
|
||||
lines.set(index, lastLine);
|
||||
}
|
||||
else {
|
||||
lines.add(text);
|
||||
}
|
||||
|
||||
if (lines.size() >= maxLines) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lastY0 = block.bbox.y0;
|
||||
lastY1 = block.bbox.y1;
|
||||
}
|
||||
|
||||
return lines;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the display list of the {@link PageEntry} that is mapped to the specified page number.
|
||||
*
|
||||
|
|
|
@ -605,6 +605,11 @@ public class PDFBoxDocument implements DocumentAdapter {
|
|||
return shapes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getPageTextLines(int pageNumber, int maxLines) {
|
||||
return List.of();
|
||||
}
|
||||
|
||||
private void loadOutline(PDDocumentCatalog catalog, PDOutlineItem item,
|
||||
DocumentOutlineItem outline) {
|
||||
if (isNull(item)) {
|
||||
|
|
|
@ -125,7 +125,7 @@ public class DocumentService {
|
|||
final File file = new File(nonNull(templatePath) ? templatePath : "");
|
||||
|
||||
return CompletableFuture.supplyAsync(() -> {
|
||||
// Search for a opened whiteboard.
|
||||
// Search for an opened whiteboard.
|
||||
Document whiteboard = documents.getFirstWhiteboard();
|
||||
|
||||
// If there isn't any whiteboard, then create one.
|
||||
|
|
|
@ -22,6 +22,9 @@ button.download = Herunterladen
|
|||
button.update = Aktualisieren
|
||||
button.record = Aufzeichnen
|
||||
|
||||
label.reply = antwortet
|
||||
label.edited = Bearbeitet
|
||||
|
||||
file.description.pdf = PDF-Folien
|
||||
file.description.recording = Vorlesungsaufzeichnung
|
||||
file.description.wav = Wave Sound
|
||||
|
|
|
@ -22,6 +22,9 @@ button.download = Download
|
|||
button.update = Update
|
||||
button.record = Record
|
||||
|
||||
label.reply = replies
|
||||
label.edited = Edited
|
||||
|
||||
file.description.pdf = PDF Slides
|
||||
file.description.recording = Lecture Recording
|
||||
file.description.wav = Wave Sound
|
||||
|
|
125
lect-player-web/src/main/frontend/package-lock.json
generated
125
lect-player-web/src/main/frontend/package-lock.json
generated
|
@ -2129,43 +2129,6 @@
|
|||
"integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==",
|
||||
"dev": true
|
||||
},
|
||||
"body-parser": {
|
||||
"version": "1.20.1",
|
||||
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz",
|
||||
"integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"bytes": "3.1.2",
|
||||
"content-type": "~1.0.4",
|
||||
"debug": "2.6.9",
|
||||
"depd": "2.0.0",
|
||||
"destroy": "1.2.0",
|
||||
"http-errors": "2.0.0",
|
||||
"iconv-lite": "0.4.24",
|
||||
"on-finished": "2.4.1",
|
||||
"qs": "6.11.0",
|
||||
"raw-body": "2.5.1",
|
||||
"type-is": "~1.6.18",
|
||||
"unpipe": "1.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"debug": {
|
||||
"version": "2.6.9",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
|
||||
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ms": "2.0.0"
|
||||
}
|
||||
},
|
||||
"ms": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
|
||||
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"bonjour-service": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/bonjour-service/-/bonjour-service-1.1.0.tgz",
|
||||
|
@ -2595,12 +2558,6 @@
|
|||
"integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==",
|
||||
"dev": true
|
||||
},
|
||||
"cookie": {
|
||||
"version": "0.5.0",
|
||||
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz",
|
||||
"integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==",
|
||||
"dev": true
|
||||
},
|
||||
"cookie-signature": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
|
||||
|
@ -3161,17 +3118,17 @@
|
|||
}
|
||||
},
|
||||
"express": {
|
||||
"version": "4.18.2",
|
||||
"resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz",
|
||||
"integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==",
|
||||
"version": "4.19.2",
|
||||
"resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz",
|
||||
"integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"accepts": "~1.3.8",
|
||||
"array-flatten": "1.1.1",
|
||||
"body-parser": "1.20.1",
|
||||
"body-parser": "1.20.2",
|
||||
"content-disposition": "0.5.4",
|
||||
"content-type": "~1.0.4",
|
||||
"cookie": "0.5.0",
|
||||
"cookie": "0.6.0",
|
||||
"cookie-signature": "1.0.6",
|
||||
"debug": "2.6.9",
|
||||
"depd": "2.0.0",
|
||||
|
@ -3205,6 +3162,32 @@
|
|||
"integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==",
|
||||
"dev": true
|
||||
},
|
||||
"body-parser": {
|
||||
"version": "1.20.2",
|
||||
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz",
|
||||
"integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"bytes": "3.1.2",
|
||||
"content-type": "~1.0.5",
|
||||
"debug": "2.6.9",
|
||||
"depd": "2.0.0",
|
||||
"destroy": "1.2.0",
|
||||
"http-errors": "2.0.0",
|
||||
"iconv-lite": "0.4.24",
|
||||
"on-finished": "2.4.1",
|
||||
"qs": "6.11.0",
|
||||
"raw-body": "2.5.2",
|
||||
"type-is": "~1.6.18",
|
||||
"unpipe": "1.0.0"
|
||||
}
|
||||
},
|
||||
"cookie": {
|
||||
"version": "0.6.0",
|
||||
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz",
|
||||
"integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==",
|
||||
"dev": true
|
||||
},
|
||||
"debug": {
|
||||
"version": "2.6.9",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
|
||||
|
@ -3219,6 +3202,18 @@
|
|||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
|
||||
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
|
||||
"dev": true
|
||||
},
|
||||
"raw-body": {
|
||||
"version": "2.5.2",
|
||||
"resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz",
|
||||
"integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"bytes": "3.1.2",
|
||||
"http-errors": "2.0.0",
|
||||
"iconv-lite": "0.4.24",
|
||||
"unpipe": "1.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -3345,9 +3340,9 @@
|
|||
}
|
||||
},
|
||||
"follow-redirects": {
|
||||
"version": "1.15.2",
|
||||
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz",
|
||||
"integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==",
|
||||
"version": "1.15.6",
|
||||
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz",
|
||||
"integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==",
|
||||
"dev": true
|
||||
},
|
||||
"for-each": {
|
||||
|
@ -4993,18 +4988,6 @@
|
|||
"integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==",
|
||||
"dev": true
|
||||
},
|
||||
"raw-body": {
|
||||
"version": "2.5.1",
|
||||
"resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz",
|
||||
"integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"bytes": "3.1.2",
|
||||
"http-errors": "2.0.0",
|
||||
"iconv-lite": "0.4.24",
|
||||
"unpipe": "1.0.0"
|
||||
}
|
||||
},
|
||||
"readable-stream": {
|
||||
"version": "3.6.0",
|
||||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
|
||||
|
@ -6336,9 +6319,9 @@
|
|||
}
|
||||
},
|
||||
"webpack-dev-middleware": {
|
||||
"version": "5.3.3",
|
||||
"resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-5.3.3.tgz",
|
||||
"integrity": "sha512-hj5CYrY0bZLB+eTO+x/j67Pkrquiy7kWepMHmUMoPsmcUaeEnQJqFzHJOyxgWlq746/wUuA64p9ta34Kyb01pA==",
|
||||
"version": "5.3.4",
|
||||
"resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-5.3.4.tgz",
|
||||
"integrity": "sha512-BVdTqhhs+0IfoeAf7EoH5WE+exCmqGerHfDM0IL096Px60Tq2Mn9MAbnaGUe6HiMa41KMCYF19gyzZmBcq/o4Q==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"colorette": "^2.0.10",
|
||||
|
@ -6376,15 +6359,15 @@
|
|||
"dev": true
|
||||
},
|
||||
"schema-utils": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.0.0.tgz",
|
||||
"integrity": "sha512-1edyXKgh6XnJsJSQ8mKWXnN/BVaIbFMLpouRUrXgVq7WYne5kw3MW7UPhO44uRXQSIpTSXoJbmrR2X0w9kUTyg==",
|
||||
"version": "4.2.0",
|
||||
"resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz",
|
||||
"integrity": "sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/json-schema": "^7.0.9",
|
||||
"ajv": "^8.8.0",
|
||||
"ajv": "^8.9.0",
|
||||
"ajv-formats": "^2.1.1",
|
||||
"ajv-keywords": "^5.0.0"
|
||||
"ajv-keywords": "^5.1.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@ package org.lecturestudio.presenter.api.context;
|
|||
import static java.util.Objects.isNull;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
|
@ -68,6 +69,8 @@ public class PresenterContext extends ApplicationContext {
|
|||
|
||||
private final ObservableList<MessengerMessage> messengerMessages = new ObservableArrayList<>();
|
||||
|
||||
private final List<MessengerMessage> allReceivedMessengerMessages = new ArrayList<>();
|
||||
|
||||
private final IntegerProperty messageCount = new IntegerProperty();
|
||||
|
||||
private final ObservableList<SpeechRequestMessage> speechRequests = new ObservableArrayList<>();
|
||||
|
@ -187,6 +190,10 @@ public class PresenterContext extends ApplicationContext {
|
|||
return messengerMessages;
|
||||
}
|
||||
|
||||
public List<MessengerMessage> getAllReceivedMessengerMessages() {
|
||||
return allReceivedMessengerMessages;
|
||||
}
|
||||
|
||||
public List<SpeechRequestMessage> getSpeechRequests() {
|
||||
return speechRequests;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package org.lecturestudio.presenter.api.event;
|
||||
|
||||
public class ExternalMessagesViewEvent extends ExternalViewEvent {
|
||||
|
||||
public ExternalMessagesViewEvent(boolean enabled) {
|
||||
super(enabled);
|
||||
}
|
||||
|
|
|
@ -120,10 +120,10 @@ public abstract class CefStreamPresenter<T extends View> extends Presenter<T> {
|
|||
|
||||
// Open the running course url.
|
||||
StreamConfiguration streamConfig = ctx.getConfiguration().getStreamConfig();
|
||||
long courseId = ctx.getCourse().getId();
|
||||
String accessLink = ctx.getCourse().getDefaultAccessLink();
|
||||
String serverName = streamConfig.getServerName();
|
||||
String serverUrl = String.format("https://%s", serverName);
|
||||
String courseApiUrl = String.format("%s/course/api/%d", serverUrl, courseId);
|
||||
String courseApiUrl = String.format("%s/course/api/%s", serverUrl, accessLink);
|
||||
|
||||
browser = client.createBrowser(courseApiUrl, false, false);
|
||||
}
|
||||
|
|
|
@ -95,9 +95,11 @@ import org.lecturestudio.presenter.api.service.ScreenSourceService;
|
|||
import org.lecturestudio.presenter.api.service.StreamService;
|
||||
import org.lecturestudio.presenter.api.handler.shutdown.SaveDocumentsHandler;
|
||||
import org.lecturestudio.presenter.api.handler.shutdown.SaveRecordingHandler;
|
||||
import org.lecturestudio.presenter.api.service.WebService;
|
||||
import org.lecturestudio.presenter.api.util.ScreenDocumentCreator;
|
||||
import org.lecturestudio.presenter.api.view.MainView;
|
||||
import org.lecturestudio.web.api.exception.StreamMediaException;
|
||||
import org.lecturestudio.web.api.message.StopStreamEnvironmentMessage;
|
||||
|
||||
public class MainPresenter extends org.lecturestudio.core.presenter.MainPresenter<MainView> implements ViewHandler {
|
||||
|
||||
|
@ -131,6 +133,8 @@ public class MainPresenter extends org.lecturestudio.core.presenter.MainPresente
|
|||
|
||||
private final ScreenShareService screenShareService;
|
||||
|
||||
private final WebService webService;
|
||||
|
||||
private SlidesPresenter slidesPresenter;
|
||||
|
||||
/** The waiting notification. */
|
||||
|
@ -147,7 +151,8 @@ public class MainPresenter extends org.lecturestudio.core.presenter.MainPresente
|
|||
BookmarkService bookmarkService,
|
||||
RecordingService recordingService,
|
||||
StreamService streamService,
|
||||
ScreenShareService screenShareService) {
|
||||
ScreenShareService screenShareService,
|
||||
WebService webService) {
|
||||
super(context, view);
|
||||
|
||||
this.audioSystemProvider = audioSystemProvider;
|
||||
|
@ -160,6 +165,7 @@ public class MainPresenter extends org.lecturestudio.core.presenter.MainPresente
|
|||
this.streamService = streamService;
|
||||
this.screenSourceService = new ScreenSourceService();
|
||||
this.screenShareService = screenShareService;
|
||||
this.webService = webService;
|
||||
this.viewMap = new ObservableHashMap<>();
|
||||
this.shortcutMap = new HashMap<>();
|
||||
this.contexts = new ArrayList<>();
|
||||
|
@ -336,6 +342,7 @@ public class MainPresenter extends org.lecturestudio.core.presenter.MainPresente
|
|||
if (state == ExecutableState.Stopped) {
|
||||
PresenterContext presenterContext = (PresenterContext) context;
|
||||
presenterContext.getMessengerMessages().clear();
|
||||
presenterContext.getAllReceivedMessengerMessages().clear();
|
||||
|
||||
// destroyHandler(MessengerWindowPresenter.class);
|
||||
}
|
||||
|
@ -455,6 +462,33 @@ public class MainPresenter extends org.lecturestudio.core.presenter.MainPresente
|
|||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onEvent(StopStreamEnvironmentMessage event) {
|
||||
//This method tries to force the stop of all stream components (stream, messenger, quiz) even if they might be inactive from this side
|
||||
|
||||
final String initiator = String.format("%s %s", event.getFirstName(), event.getFamilyName());
|
||||
|
||||
try {
|
||||
webService.stopQuiz();
|
||||
}
|
||||
catch (Exception exception) {
|
||||
logException(exception, "Stop quiz failed");
|
||||
}
|
||||
try {
|
||||
webService.stopMessenger();
|
||||
}
|
||||
catch (Exception exception) {
|
||||
logException(exception, "Stop messenger failed");
|
||||
}
|
||||
|
||||
((PresenterContext) context).setStreamStarted(false);
|
||||
|
||||
context.showNotification(NotificationType.WARNING,
|
||||
"stream.environment.stopped.by.message.title",
|
||||
"stream.environment.stopped.by.message",
|
||||
initiator);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addShutdownHandler(ShutdownHandler handler) {
|
||||
requireNonNull(handler, "ShutdownHandler must not be null.");
|
||||
|
|
|
@ -28,9 +28,11 @@ import org.lecturestudio.core.app.ApplicationContext;
|
|||
import org.lecturestudio.core.app.configuration.Configuration;
|
||||
import org.lecturestudio.core.presenter.Presenter;
|
||||
import org.lecturestudio.core.view.ViewLayer;
|
||||
import org.lecturestudio.presenter.api.context.PresenterContext;
|
||||
import org.lecturestudio.presenter.api.view.MessengerWindow;
|
||||
import org.lecturestudio.web.api.message.MessengerMessage;
|
||||
import org.lecturestudio.web.api.message.SpeechRequestMessage;
|
||||
import org.lecturestudio.web.api.message.util.MessageUtil;
|
||||
|
||||
public class MessengerWindowPresenter extends Presenter<MessengerWindow> {
|
||||
|
||||
|
@ -81,6 +83,26 @@ public class MessengerWindowPresenter extends Presenter<MessengerWindow> {
|
|||
requireNonNull(message);
|
||||
|
||||
view.setMessengerMessage(message);
|
||||
|
||||
if(message.isDeleted()) {
|
||||
view.removeMessengerMessage(message.getMessageId());
|
||||
return;
|
||||
}
|
||||
|
||||
if(message.isEdited()) {
|
||||
view.setModifiedMessengerMessage(message);
|
||||
return;
|
||||
}
|
||||
|
||||
if(MessageUtil.isReply(message)) {
|
||||
final MessengerMessage messageToReplyTo = MessageUtil.findMessageToReplyTo(
|
||||
((PresenterContext) context).getAllReceivedMessengerMessages(),
|
||||
message);
|
||||
view.setMessengerMessageAsReply(message, messageToReplyTo);
|
||||
}
|
||||
else {
|
||||
view.setMessengerMessage(message);
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
|
|
|
@ -124,6 +124,7 @@ import org.lecturestudio.web.api.message.MessengerMessage;
|
|||
import org.lecturestudio.web.api.message.SpeechBaseMessage;
|
||||
import org.lecturestudio.web.api.message.SpeechCancelMessage;
|
||||
import org.lecturestudio.web.api.message.SpeechRequestMessage;
|
||||
import org.lecturestudio.web.api.message.util.MessageUtil;
|
||||
import org.lecturestudio.web.api.model.Message;
|
||||
import org.lecturestudio.web.api.model.ScreenSource;
|
||||
import org.lecturestudio.web.api.service.ServiceParameters;
|
||||
|
@ -166,6 +167,8 @@ public class SlidesPresenter extends Presenter<SlidesView> {
|
|||
|
||||
private final RecordingService recordingService;
|
||||
|
||||
private final UserPrivilegeService userPrivilegeService;
|
||||
|
||||
private StylusHandler stylusHandler;
|
||||
|
||||
private PageEditedListener pageEditedListener;
|
||||
|
@ -184,8 +187,6 @@ public class SlidesPresenter extends Presenter<SlidesView> {
|
|||
|
||||
private SelectionIdleTimer idleTimer;
|
||||
|
||||
private final UserPrivilegeService userPrivilegeService;
|
||||
|
||||
|
||||
@Inject
|
||||
SlidesPresenter(ApplicationContext context, SlidesView view,
|
||||
|
@ -197,10 +198,10 @@ public class SlidesPresenter extends Presenter<SlidesView> {
|
|||
DocumentService documentService,
|
||||
DocumentRecorder documentRecorder,
|
||||
RecordingService recordingService,
|
||||
UserPrivilegeService userPrivilegeService,
|
||||
WebService webService,
|
||||
WebServiceInfo webServiceInfo,
|
||||
WebRtcStreamService streamService,
|
||||
UserPrivilegeService userPrivilegeService) {
|
||||
WebRtcStreamService streamService) {
|
||||
super(context, view);
|
||||
|
||||
this.viewFactory = viewFactory;
|
||||
|
@ -211,6 +212,7 @@ public class SlidesPresenter extends Presenter<SlidesView> {
|
|||
this.bookmarkService = bookmarkService;
|
||||
this.documentService = documentService;
|
||||
this.recordingService = recordingService;
|
||||
this.userPrivilegeService = userPrivilegeService;
|
||||
this.webService = webService;
|
||||
this.webServiceInfo = webServiceInfo;
|
||||
this.streamService = streamService;
|
||||
|
@ -219,7 +221,6 @@ public class SlidesPresenter extends Presenter<SlidesView> {
|
|||
this.pageObjectRegistry = new PageObjectRegistry();
|
||||
this.documentChangeListener = new DocumentChangeHandler();
|
||||
this.screenViewContext = new ScreenPresentationViewContext();
|
||||
this.userPrivilegeService = userPrivilegeService;
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
|
@ -356,9 +357,32 @@ public class SlidesPresenter extends Presenter<SlidesView> {
|
|||
requireNonNull(message);
|
||||
|
||||
PresenterContext presenterContext = (PresenterContext) context;
|
||||
presenterContext.getMessengerMessages().add(message);
|
||||
|
||||
view.setMessengerMessage(message);
|
||||
if (message.isDeleted()) {
|
||||
onDiscardMessage(message);
|
||||
view.removeMessengerMessage(message.getMessageId());
|
||||
return;
|
||||
}
|
||||
|
||||
if (message.isEdited()) {
|
||||
view.setModifiedMessengerMessage(message);
|
||||
MessageUtil.updateOutdatedMessage(presenterContext.getMessengerMessages(), message);
|
||||
MessageUtil.updateOutdatedMessage(presenterContext.getAllReceivedMessengerMessages(), message);
|
||||
return;
|
||||
}
|
||||
|
||||
presenterContext.getMessengerMessages().add(message);
|
||||
presenterContext.getAllReceivedMessengerMessages().add(message);
|
||||
|
||||
if (MessageUtil.isReply(message)) {
|
||||
final MessengerMessage messageToReplyTo = MessageUtil.findMessageToReplyTo(
|
||||
((PresenterContext) context).getAllReceivedMessengerMessages(),
|
||||
message);
|
||||
view.setMessengerMessageAsReply(message, messageToReplyTo);
|
||||
}
|
||||
else {
|
||||
view.setMessengerMessage(message);
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
|
@ -1467,7 +1491,9 @@ public class SlidesPresenter extends Presenter<SlidesView> {
|
|||
return;
|
||||
}
|
||||
|
||||
action.accept(config.isEnabled(), checkIfScreenInList(list, config.getScreen()));
|
||||
checkScreenExists(config);
|
||||
|
||||
action.accept(config.isEnabled(), true);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -1502,9 +1528,9 @@ public class SlidesPresenter extends Presenter<SlidesView> {
|
|||
}
|
||||
|
||||
private void showExternalScreen(ExternalWindowConfiguration config, BiConsumer<Boolean, Boolean> action) {
|
||||
final ObservableList<Screen> screens = presentationController.getScreens();
|
||||
checkScreenExists(config);
|
||||
|
||||
action.accept(config.isEnabled(), checkIfScreenInList(screens, config.getScreen()));
|
||||
action.accept(config.isEnabled(), true);
|
||||
}
|
||||
|
||||
private void hideExternalScreens() {
|
||||
|
@ -1513,6 +1539,14 @@ public class SlidesPresenter extends Presenter<SlidesView> {
|
|||
view.hideExternalSpeech();
|
||||
}
|
||||
|
||||
private void checkScreenExists(ExternalWindowConfiguration config) {
|
||||
final ObservableList<Screen> screens = presentationController.getScreens();
|
||||
|
||||
if (!checkIfScreenInList(screens, config.getScreen())) {
|
||||
config.setScreen(null);
|
||||
}
|
||||
}
|
||||
|
||||
private void viewShowExternalMessages(boolean persistent) {
|
||||
final ExternalWindowConfiguration config = getExternalMessagesConfig();
|
||||
|
||||
|
@ -1520,6 +1554,8 @@ public class SlidesPresenter extends Presenter<SlidesView> {
|
|||
config.setEnabled(true);
|
||||
}
|
||||
|
||||
checkScreenExists(config);
|
||||
|
||||
view.showExternalMessages(config.getScreen(), config.getPosition(), config.getSize());
|
||||
}
|
||||
|
||||
|
@ -1540,6 +1576,8 @@ public class SlidesPresenter extends Presenter<SlidesView> {
|
|||
config.setEnabled(true);
|
||||
}
|
||||
|
||||
checkScreenExists(config);
|
||||
|
||||
view.showExternalParticipants(config.getScreen(), config.getPosition(), config.getSize());
|
||||
}
|
||||
|
||||
|
@ -1560,6 +1598,8 @@ public class SlidesPresenter extends Presenter<SlidesView> {
|
|||
config.setEnabled(true);
|
||||
}
|
||||
|
||||
checkScreenExists(config);
|
||||
|
||||
view.showExternalSlidePreview(config.getScreen(), config.getPosition(), config.getSize());
|
||||
}
|
||||
|
||||
|
@ -1580,6 +1620,8 @@ public class SlidesPresenter extends Presenter<SlidesView> {
|
|||
config.setEnabled(true);
|
||||
}
|
||||
|
||||
checkScreenExists(config);
|
||||
|
||||
view.showExternalSpeech(config.getScreen(), config.getPosition(), config.getSize());
|
||||
}
|
||||
|
||||
|
@ -1600,6 +1642,8 @@ public class SlidesPresenter extends Presenter<SlidesView> {
|
|||
config.setEnabled(true);
|
||||
}
|
||||
|
||||
checkScreenExists(config);
|
||||
|
||||
view.showExternalNotes(config.getScreen(), config.getPosition(), config.getSize());
|
||||
}
|
||||
|
||||
|
@ -1620,6 +1664,8 @@ public class SlidesPresenter extends Presenter<SlidesView> {
|
|||
config.setEnabled(true);
|
||||
}
|
||||
|
||||
checkScreenExists(config);
|
||||
|
||||
view.showExternalSlideNotes(config.getScreen(), config.getPosition(), config.getSize());
|
||||
}
|
||||
|
||||
|
@ -1637,7 +1683,7 @@ public class SlidesPresenter extends Presenter<SlidesView> {
|
|||
if (screen == null) {
|
||||
return true;
|
||||
}
|
||||
return screens.stream().anyMatch(scrn -> scrn.equals(screen));
|
||||
return screens.stream().anyMatch(s -> s.equals(screen));
|
||||
}
|
||||
|
||||
private void recordPage(Page page) {
|
||||
|
|
|
@ -310,7 +310,7 @@ public class ToolbarPresenter extends Presenter<ToolbarView> {
|
|||
String template = config.getTemplateConfig()
|
||||
.getWhiteboardTemplateConfig().getTemplatePath();
|
||||
|
||||
documentService.openWhiteboard(template).join();
|
||||
documentService.openWhiteboard(template);
|
||||
}
|
||||
else {
|
||||
documentService.selectDocument(documents.getLastNonWhiteboard());
|
||||
|
|
|
@ -38,6 +38,7 @@ import org.lecturestudio.presenter.api.event.MessengerStateEvent;
|
|||
import org.lecturestudio.presenter.api.event.QuizStateEvent;
|
||||
import org.lecturestudio.presenter.api.net.LocalBroadcaster;
|
||||
import org.lecturestudio.web.api.client.TokenProvider;
|
||||
import org.lecturestudio.web.api.message.StopStreamEnvironmentMessage;
|
||||
import org.lecturestudio.web.api.message.CoursePresenceMessage;
|
||||
import org.lecturestudio.web.api.message.MessageTransport;
|
||||
import org.lecturestudio.web.api.message.SpeechBaseMessage;
|
||||
|
@ -364,6 +365,9 @@ public class WebService extends ExecutableBase {
|
|||
messageTransport.addListener(SpeechBaseMessage.class, message -> {
|
||||
context.getEventBus().post(message);
|
||||
});
|
||||
messageTransport.addListener(StopStreamEnvironmentMessage.class, message -> {
|
||||
context.getEventBus().post(message);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -27,6 +27,12 @@ public interface MessengerWindow extends View {
|
|||
|
||||
void setMessengerMessage(MessengerMessage message);
|
||||
|
||||
void setMessengerMessageAsReply(MessengerMessage message, MessengerMessage messageToReplyTo);
|
||||
|
||||
void setModifiedMessengerMessage(MessengerMessage modifiedMessage);
|
||||
|
||||
void removeMessengerMessage(String messageId);
|
||||
|
||||
void setSpeechRequestMessage(SpeechRequestMessage message);
|
||||
|
||||
void setTextSize(double size);
|
||||
|
|
|
@ -102,6 +102,12 @@ public interface SlidesView extends View {
|
|||
|
||||
void setMessengerMessage(MessengerMessage message);
|
||||
|
||||
void removeMessengerMessage(String messageId);
|
||||
|
||||
void setMessengerMessageAsReply(MessengerMessage message, MessengerMessage messageToReplyTo);
|
||||
|
||||
void setModifiedMessengerMessage(MessengerMessage modifiedMessage);
|
||||
|
||||
void addSpeechRequest(SpeechBaseMessage message);
|
||||
|
||||
void removeSpeechRequest(SpeechBaseMessage message);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
audio.device.connected = Audiogerät verbunden
|
||||
audio.device.disconnected = Audiogerät getrennt
|
||||
audio.device.connected = Audioger\u00e4t verbunden
|
||||
audio.device.disconnected = Audioger\u00e4t getrennt
|
||||
|
||||
bookmark.assign.warning = Lesezeichen konnte nicht erstellt werden
|
||||
bookmark.delete.error = Lesezeichen konnte nicht gel\u00f6scht werden
|
||||
|
@ -16,7 +16,7 @@ document.save.lecture = Vorlesung
|
|||
error = Fehler
|
||||
generic.error = Bitte kontaktieren Sie Ihren Systemadministrator. Vollst\u00e4ndige Details finden Sie im Anwendungsprotokoll.
|
||||
|
||||
please.wait = Einen Moment bitte...
|
||||
please.wait = Einen Moment bitte ...
|
||||
|
||||
messenger.starting = Der Messenger wird gestartet
|
||||
messenger.start.error = Messenger konnte nicht gestartet werden
|
||||
|
@ -76,6 +76,7 @@ text.message = Nachricht
|
|||
text.message.time = Datum / Uhrzeit
|
||||
text.messages = Textnachrichten
|
||||
text.message.me = Ich
|
||||
text.message.me.dative = Mir
|
||||
text.message.privately = Privat
|
||||
text.message.recipient = {0} an {1}
|
||||
text.message.to.me = mich
|
||||
|
@ -144,4 +145,7 @@ shortcut.color.one = Farbe 1
|
|||
shortcut.color.two = Farbe 2
|
||||
shortcut.color.three = Farbe 3
|
||||
shortcut.color.four = Farbe 4
|
||||
shortcut.color.five = Farbe 5
|
||||
shortcut.color.five = Farbe 5
|
||||
|
||||
stream.environment.stopped.by.message.title = Stream-Umgebung stoppen
|
||||
stream.environment.stopped.by.message = Stoppen der Stream-Umgebung bestehend aus Quiz, Messenger und Stream wurde initiiert. Initiator: {0}
|
|
@ -16,7 +16,7 @@ document.save.lecture = Lecture
|
|||
error = Error
|
||||
generic.error = Please contact your system administrator. For complete details, see the application log.
|
||||
|
||||
please.wait = One moment please...
|
||||
please.wait = One moment please ...
|
||||
|
||||
messenger.starting = Starting Messenger
|
||||
messenger.start.error = Messenger could not be started
|
||||
|
@ -76,6 +76,7 @@ text.message = Message
|
|||
text.message.time = Date / Time
|
||||
text.messages = Text Messages
|
||||
text.message.me = Me
|
||||
text.message.dative = Me
|
||||
text.message.privately = Privately
|
||||
text.message.recipient = {0} to {1}
|
||||
text.message.to.me = me
|
||||
|
@ -144,4 +145,7 @@ shortcut.color.one = Color 1
|
|||
shortcut.color.two = Color 2
|
||||
shortcut.color.three = Color 3
|
||||
shortcut.color.four = Color 4
|
||||
shortcut.color.five = Color 5
|
||||
shortcut.color.five = Color 5
|
||||
|
||||
stream.environment.stopped.by.message.title = Stream-environment stopped
|
||||
stream.environment.stopped.by.message = Stop of Stream-environment consisting of quiz, messenger and stream was initiated. Initiator: {0}
|
|
@ -65,7 +65,11 @@ import org.lecturestudio.presenter.api.context.PresenterContext;
|
|||
import org.lecturestudio.presenter.api.input.Shortcut;
|
||||
import org.lecturestudio.presenter.api.net.LocalBroadcaster;
|
||||
import org.lecturestudio.presenter.api.recording.FileLectureRecorder;
|
||||
import org.lecturestudio.presenter.api.service.*;
|
||||
import org.lecturestudio.presenter.api.service.BookmarkService;
|
||||
import org.lecturestudio.presenter.api.service.RecordingService;
|
||||
import org.lecturestudio.presenter.api.service.WebRtcStreamService;
|
||||
import org.lecturestudio.presenter.api.service.WebService;
|
||||
import org.lecturestudio.presenter.api.service.WebServiceInfo;
|
||||
import org.lecturestudio.presenter.api.view.MainView;
|
||||
import org.lecturestudio.presenter.api.view.QuitRecordingView;
|
||||
import org.lecturestudio.presenter.api.view.RestoreRecordingView;
|
||||
|
@ -196,7 +200,7 @@ class MainPresenterTest extends PresenterTest {
|
|||
public <T> T getInstance(Class<T> cls) {
|
||||
if (cls == SlidesPresenter.class) {
|
||||
ToolController toolController = new ToolController(context, documentService);
|
||||
return (T) new SlidesPresenter(context, createProxy(SlidesView.class), null, toolController, presentationController, null, bookmarkService, documentService, documentRecorder, recordingService, webService, webServiceInfo, streamService, null);
|
||||
return (T) new SlidesPresenter(context, createProxy(SlidesView.class), null, toolController, presentationController, null, bookmarkService, documentService, documentRecorder, recordingService, null, webService, webServiceInfo, streamService);
|
||||
}
|
||||
else if (cls == SettingsPresenter.class) {
|
||||
return (T) new SettingsPresenter(context, createProxy(SettingsView.class));
|
||||
|
@ -232,7 +236,7 @@ class MainPresenterTest extends PresenterTest {
|
|||
|
||||
MainPresenter presenter = new MainPresenter(context, view,
|
||||
audioSystemProvider, presentationController, null, viewFactory,
|
||||
documentService, bookmarkService, recordingService, null, null);
|
||||
documentService, bookmarkService, recordingService, null, null, null);
|
||||
presenter.initialize();
|
||||
presenter.showView(testView, ViewLayer.Content);
|
||||
}
|
||||
|
@ -270,7 +274,7 @@ class MainPresenterTest extends PresenterTest {
|
|||
|
||||
MainPresenter presenter = new MainPresenter(context, view,
|
||||
audioSystemProvider, presentationController, null, viewFactory,
|
||||
documentService, bookmarkService, recordingService, null, null);
|
||||
documentService, bookmarkService, recordingService, null, null, null);
|
||||
presenter.initialize();
|
||||
presenter.display(new TestPresenter(context, new TestView()));
|
||||
|
||||
|
@ -321,7 +325,7 @@ class MainPresenterTest extends PresenterTest {
|
|||
|
||||
MainPresenter presenter = new MainPresenter(context, view,
|
||||
audioSystemProvider, presentationController, null, viewFactory,
|
||||
documentService, bookmarkService, recordingService, null, null);
|
||||
documentService, bookmarkService, recordingService, null, null, null);
|
||||
presenter.initialize();
|
||||
presenter.display(new TestPresenter(context, new TestView()));
|
||||
|
||||
|
@ -367,7 +371,7 @@ class MainPresenterTest extends PresenterTest {
|
|||
|
||||
MainPresenter presenter = new MainPresenter(context, view,
|
||||
audioSystemProvider, presentationController, null, viewFactory,
|
||||
documentService, bookmarkService, recordingService, null, null);
|
||||
documentService, bookmarkService, recordingService, null, null, null);
|
||||
presenter.initialize();
|
||||
presenter.display(testPresenter);
|
||||
presenter.destroy(testPresenter);
|
||||
|
@ -414,7 +418,7 @@ class MainPresenterTest extends PresenterTest {
|
|||
|
||||
MainPresenter presenter = new MainPresenter(context, view,
|
||||
audioSystemProvider, presentationController, null, viewFactory,
|
||||
documentService, bookmarkService, recordingService, null, null);
|
||||
documentService, bookmarkService, recordingService, null, null, null);
|
||||
presenter.initialize();
|
||||
presenter.display(testPresenter);
|
||||
presenter.destroy(testPresenter);
|
||||
|
@ -436,7 +440,7 @@ class MainPresenterTest extends PresenterTest {
|
|||
|
||||
MainPresenter presenter = new MainPresenter(context, view,
|
||||
audioSystemProvider, presentationController, null, viewFactory,
|
||||
documentService, bookmarkService, recordingService, null, null);
|
||||
documentService, bookmarkService, recordingService, null, null, null);
|
||||
presenter.initialize();
|
||||
presenter.setFullscreen(true);
|
||||
|
||||
|
@ -474,7 +478,7 @@ class MainPresenterTest extends PresenterTest {
|
|||
|
||||
MainPresenter presenter = new MainPresenter(context, view,
|
||||
audioSystemProvider, presentationController, null, viewFactory,
|
||||
documentService, bookmarkService, recordingService, null, null);
|
||||
documentService, bookmarkService, recordingService, null, null, null);
|
||||
presenter.initialize();
|
||||
|
||||
view.shownAction.execute();
|
||||
|
@ -496,7 +500,7 @@ class MainPresenterTest extends PresenterTest {
|
|||
|
||||
MainPresenter presenter = new MainPresenter(context, view,
|
||||
audioSystemProvider, presentationController, null, viewFactory,
|
||||
documentService, bookmarkService, recordingService, null, null);
|
||||
documentService, bookmarkService, recordingService, null, null, null);
|
||||
presenter.initialize();
|
||||
presenter.addShutdownHandler(new ShutdownHandler() {
|
||||
|
||||
|
@ -538,7 +542,7 @@ class MainPresenterTest extends PresenterTest {
|
|||
|
||||
MainPresenter presenter = new MainPresenter(context, view,
|
||||
audioSystemProvider, presentationController, null, viewFactory,
|
||||
documentService, bookmarkService, recordingService, null, null);
|
||||
documentService, bookmarkService, recordingService, null, null, null);
|
||||
presenter.initialize();
|
||||
presenter.display(new TestPresenter(context, new TestView()));
|
||||
|
||||
|
@ -565,7 +569,7 @@ class MainPresenterTest extends PresenterTest {
|
|||
|
||||
MainPresenter presenter = new MainPresenter(context, view,
|
||||
audioSystemProvider, presentationController, null, viewFactory,
|
||||
documentService, bookmarkService, recordingService, null, null);
|
||||
documentService, bookmarkService, recordingService, null, null, null);
|
||||
presenter.initialize();
|
||||
|
||||
recordingService.start();
|
||||
|
@ -601,7 +605,7 @@ class MainPresenterTest extends PresenterTest {
|
|||
|
||||
MainPresenter presenter = new MainPresenter(context, view,
|
||||
audioSystemProvider, presentationController, null, viewFactory,
|
||||
documentService, bookmarkService, recordingService, null, null);
|
||||
documentService, bookmarkService, recordingService, null, null, null);
|
||||
presenter.initialize();
|
||||
|
||||
ToolController toolController = new ToolController(context, documentService);
|
||||
|
|
|
@ -106,6 +106,21 @@ class MessengerWindowPresenterTest extends PresenterTest {
|
|||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMessengerMessageAsReply(MessengerMessage message, MessengerMessage messageToReplyTo) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setModifiedMessengerMessage(MessengerMessage modifiedMessage) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeMessengerMessage(String messageId) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSpeechRequestMessage(SpeechRequestMessage message) {
|
||||
|
||||
|
|
|
@ -24,6 +24,7 @@ import org.lecturestudio.core.app.dictionary.Dictionary;
|
|||
import org.lecturestudio.swing.components.MessagePanel;
|
||||
import org.lecturestudio.swing.components.NotesPanel;
|
||||
import org.lecturestudio.web.api.message.UserMessage;
|
||||
import org.lecturestudio.web.api.message.util.MessageUtil;
|
||||
import org.lecturestudio.web.api.model.UserInfo;
|
||||
|
||||
public class ViewUtil {
|
||||
|
@ -43,21 +44,7 @@ public class ViewUtil {
|
|||
*/
|
||||
public static <T extends MessagePanel> T createMessageView(Class<T> c,
|
||||
UserInfo userInfo, UserMessage message, Dictionary dict) {
|
||||
String myId = userInfo.getUserId();
|
||||
boolean byMe = Objects.equals(message.getUserId(), myId);
|
||||
String sender;
|
||||
|
||||
if (byMe) {
|
||||
sender = dict.get("text.message.me");
|
||||
}
|
||||
else {
|
||||
String nameFull = message.getFirstName() + " " + message.getFamilyName();
|
||||
String[] nameParts = nameFull.split(" ");
|
||||
String firstName = nameParts.length > 0 ? nameParts[0] : "";
|
||||
String lastName = nameParts.length > 1 ? nameParts[nameParts.length - 1] : "";
|
||||
|
||||
sender = String.format("%s %s", firstName, lastName);
|
||||
}
|
||||
String sender = MessageUtil.evaluateSender(message, userInfo, dict);
|
||||
|
||||
try {
|
||||
T view = c.getDeclaredConstructor(Dictionary.class)
|
||||
|
@ -71,6 +58,7 @@ public class ViewUtil {
|
|||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a concrete NotesPanel specified by the provided class
|
||||
* parameter.
|
||||
|
@ -91,5 +79,4 @@ public class ViewUtil {
|
|||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@ import java.awt.Component;
|
|||
import java.awt.Container;
|
||||
import java.awt.event.WindowAdapter;
|
||||
import java.awt.event.WindowEvent;
|
||||
import java.util.Optional;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.swing.JFrame;
|
||||
|
@ -31,13 +32,14 @@ import org.lecturestudio.core.view.Action;
|
|||
import org.lecturestudio.presenter.api.service.UserPrivilegeService;
|
||||
import org.lecturestudio.presenter.api.view.MessengerWindow;
|
||||
import org.lecturestudio.presenter.swing.utils.ViewUtil;
|
||||
import org.lecturestudio.swing.components.MessageAsReplyView;
|
||||
import org.lecturestudio.swing.components.MessageView;
|
||||
import org.lecturestudio.swing.components.SpeechRequestView;
|
||||
import org.lecturestudio.swing.util.SwingUtils;
|
||||
import org.lecturestudio.swing.view.SwingView;
|
||||
import org.lecturestudio.web.api.message.MessengerDirectMessage;
|
||||
import org.lecturestudio.web.api.message.MessengerMessage;
|
||||
import org.lecturestudio.web.api.message.SpeechRequestMessage;
|
||||
import org.lecturestudio.web.api.message.util.MessageUtil;
|
||||
import org.lecturestudio.web.api.model.UserInfo;
|
||||
|
||||
@SwingView(name = "messenger-window")
|
||||
|
@ -65,23 +67,11 @@ public class SwingMessengerWindow extends JFrame implements MessengerWindow {
|
|||
UserInfo userInfo = userPrivilegeService.getUserInfo();
|
||||
|
||||
MessageView messageView = ViewUtil.createMessageView(MessageView.class, userInfo, message, dict);
|
||||
messageView.setMessage(message.getMessage().getText());
|
||||
messageView.setMessage(message, userInfo);
|
||||
messageView.setOnDiscard(() -> {
|
||||
removeMessageView(messageView);
|
||||
});
|
||||
|
||||
if (message instanceof MessengerDirectMessage) {
|
||||
MessengerDirectMessage directMessage = (MessengerDirectMessage) message;
|
||||
String recipient = directMessage.getRecipientId();
|
||||
|
||||
if (recipient.equals("organisers")) {
|
||||
messageView.setPrivateText(dict.get("text.message.to.organisators"));
|
||||
}
|
||||
else {
|
||||
messageView.setPrivateText(dict.get("text.message.privately"));
|
||||
}
|
||||
}
|
||||
|
||||
messageView.pack();
|
||||
|
||||
messageViewContainer.add(messageView);
|
||||
|
@ -89,6 +79,49 @@ public class SwingMessengerWindow extends JFrame implements MessengerWindow {
|
|||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMessengerMessageAsReply(MessengerMessage message, MessengerMessage messageToReplyTo) {
|
||||
SwingUtils.invoke(() -> {
|
||||
UserInfo userInfo = userPrivilegeService.getUserInfo();
|
||||
|
||||
MessageAsReplyView messageView = ViewUtil.createMessageView(MessageAsReplyView.class, userInfo, message, dict);
|
||||
messageView.setMessage(message, userInfo);
|
||||
|
||||
final String userToReplyTo = MessageUtil.evaluateSenderOfMessageToReplyTo(messageToReplyTo, userInfo, dict);
|
||||
messageView.setUserToReplyTo(userToReplyTo);
|
||||
|
||||
messageView.setOnDiscard(() -> {
|
||||
removeMessageView(messageView);
|
||||
});
|
||||
|
||||
messageView.pack();
|
||||
|
||||
messageViewContainer.add(messageView);
|
||||
messageViewContainer.revalidate();
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setModifiedMessengerMessage(MessengerMessage modifiedMessage) {
|
||||
SwingUtils.invoke(() -> {
|
||||
final Optional<MessageView> toModify = findCorrespondingMessageView(modifiedMessage.getMessageId());
|
||||
|
||||
if (toModify.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
UserInfo userInfo = userPrivilegeService.getUserInfo();
|
||||
|
||||
toModify.get().setMessage(modifiedMessage, userInfo);
|
||||
toModify.get().setIsEdited();
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeMessengerMessage(String messageId) {
|
||||
removeMessageView(messageId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSpeechRequestMessage(SpeechRequestMessage message) {
|
||||
SwingUtils.invoke(() -> {
|
||||
|
@ -148,4 +181,28 @@ public class SwingMessengerWindow extends JFrame implements MessengerWindow {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void removeMessageView(final String messageId) {
|
||||
for(Component component : messageViewContainer.getComponents()) {
|
||||
if((component instanceof MessageView messageView) &&
|
||||
messageView.getMessageId().equals(messageId)) {
|
||||
|
||||
messageViewContainer.remove(component);
|
||||
messageViewContainer.validate();
|
||||
messageViewContainer.repaint();
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Optional<MessageView> findCorrespondingMessageView(final String messageId) {
|
||||
for (Component component : messageViewContainer.getComponents()) {
|
||||
if ((component instanceof MessageView messageView) &&
|
||||
messageView.getMessageId().equals(messageId)) {
|
||||
return Optional.of(messageView);
|
||||
}
|
||||
}
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -50,12 +50,12 @@ import java.awt.event.ComponentEvent;
|
|||
import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.text.MessageFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Enumeration;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.IntSupplier;
|
||||
|
@ -87,6 +87,7 @@ import org.lecturestudio.presenter.swing.utils.ViewUtil;
|
|||
import org.lecturestudio.stylus.awt.AwtStylusManager;
|
||||
import org.lecturestudio.swing.components.AdaptiveTabbedPane;
|
||||
import org.lecturestudio.swing.components.ExternalFrame;
|
||||
import org.lecturestudio.swing.components.MessageAsReplyView;
|
||||
import org.lecturestudio.swing.components.MessagePanel;
|
||||
import org.lecturestudio.swing.components.MessageView;
|
||||
import org.lecturestudio.swing.components.NotesView;
|
||||
|
@ -113,9 +114,9 @@ import org.lecturestudio.swing.view.SwingView;
|
|||
import org.lecturestudio.swing.view.ViewPostConstruct;
|
||||
import org.lecturestudio.web.api.event.PeerStateEvent;
|
||||
import org.lecturestudio.web.api.event.RemoteVideoFrameEvent;
|
||||
import org.lecturestudio.web.api.message.MessengerDirectMessage;
|
||||
import org.lecturestudio.web.api.message.MessengerMessage;
|
||||
import org.lecturestudio.web.api.message.SpeechBaseMessage;
|
||||
import org.lecturestudio.web.api.message.util.MessageUtil;
|
||||
import org.lecturestudio.web.api.model.UserInfo;
|
||||
import org.lecturestudio.web.api.stream.model.CourseParticipant;
|
||||
|
||||
|
@ -744,10 +745,37 @@ public class SwingSlidesView extends JPanel implements SlidesView {
|
|||
public void setMessengerMessage(MessengerMessage message) {
|
||||
SwingUtils.invoke(() -> {
|
||||
UserInfo userInfo = userPrivilegeService.getUserInfo();
|
||||
String myId = userInfo.getUserId();
|
||||
|
||||
MessageView messageView = ViewUtil.createMessageView(MessageView.class, userInfo, message, dict);
|
||||
messageView.setMessage(message.getMessage().getText());
|
||||
messageView.setMessage(message, userInfo);
|
||||
messageView.setOnDiscard(() -> {
|
||||
executeAction(discardMessageAction, messageView.getMessage());
|
||||
|
||||
removeMessageView(messageView);
|
||||
});
|
||||
messageView.setOnCreateSlide(() -> {
|
||||
createMessageSlideAction.execute(messageView.getMessage());
|
||||
|
||||
removeMessageView(messageView);
|
||||
});
|
||||
|
||||
messageView.pack();
|
||||
|
||||
addMessageView(messageView);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMessengerMessageAsReply(MessengerMessage message, MessengerMessage messageToReplyTo) {
|
||||
SwingUtils.invoke(() -> {
|
||||
UserInfo userInfo = userPrivilegeService.getUserInfo();
|
||||
|
||||
MessageAsReplyView messageView = ViewUtil.createMessageView(MessageAsReplyView.class, userInfo, message, dict);
|
||||
messageView.setMessage(message, userInfo);
|
||||
|
||||
final String userToReplyTo = MessageUtil.evaluateSenderOfMessageToReplyTo(messageToReplyTo, userInfo, dict);
|
||||
messageView.setUserToReplyTo(userToReplyTo);
|
||||
|
||||
messageView.setOnDiscard(() -> {
|
||||
executeAction(discardMessageAction, message);
|
||||
|
||||
|
@ -759,32 +787,37 @@ public class SwingSlidesView extends JPanel implements SlidesView {
|
|||
removeMessageView(messageView);
|
||||
});
|
||||
|
||||
if (message instanceof MessengerDirectMessage directMessage) {
|
||||
String recipientId = directMessage.getRecipientId();
|
||||
boolean byMe = Objects.equals(message.getUserId(), myId);
|
||||
boolean toMe = Objects.equals(recipientId, myId);
|
||||
boolean toOrganisers = Objects.equals(recipientId, "organisers");
|
||||
|
||||
String sender = byMe
|
||||
? dict.get("text.message.me")
|
||||
: String.format("%s %s", message.getFirstName(), message.getFamilyName());
|
||||
|
||||
String recipient = toMe
|
||||
? dict.get("text.message.to.me")
|
||||
: toOrganisers
|
||||
? dict.get("text.message.to.organisators.short")
|
||||
: String.format("%s %s", directMessage.getRecipientFirstName(), directMessage.getRecipientFamilyName());
|
||||
|
||||
messageView.setUserName(MessageFormat.format(dict.get("text.message.recipient"), sender, ""));
|
||||
messageView.setPrivateText(recipient);
|
||||
}
|
||||
|
||||
messageView.pack();
|
||||
|
||||
addMessageView(messageView);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setModifiedMessengerMessage(MessengerMessage modifiedMessage) {
|
||||
SwingUtils.invoke(() -> {
|
||||
final Optional<MessageView> toModify = findCorrespondingMessageView(modifiedMessage.getMessageId());
|
||||
|
||||
if (toModify.isEmpty()){
|
||||
return;
|
||||
}
|
||||
|
||||
UserInfo userInfo = userPrivilegeService.getUserInfo();
|
||||
|
||||
toModify.get().setMessage(modifiedMessage, userInfo);
|
||||
toModify.get().setIsEdited();
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeMessengerMessage(String messageId) {
|
||||
final Optional<MessageView> toRemove = findCorrespondingMessageView(messageId);
|
||||
|
||||
if(toRemove.isEmpty()) return;
|
||||
|
||||
removeMessageView(toRemove.get());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addSpeechRequest(SpeechBaseMessage message) {
|
||||
SwingUtils.invoke(() -> {
|
||||
|
@ -2411,6 +2444,16 @@ public class SwingSlidesView extends JPanel implements SlidesView {
|
|||
}
|
||||
}
|
||||
|
||||
private Optional<MessageView> findCorrespondingMessageView(final String messageId) {
|
||||
for(Component component : messageViewContainer.getComponents()) {
|
||||
if((component instanceof MessageView messageView) &&
|
||||
messageView.getMessageId().equals(messageId)) {
|
||||
return Optional.of(messageView);
|
||||
}
|
||||
}
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all notes from the View
|
||||
*/
|
||||
|
|
|
@ -17,6 +17,7 @@ import java.util.List;
|
|||
import java.util.stream.IntStream;
|
||||
|
||||
public class AdaptiveTabbedPane extends JComponent {
|
||||
|
||||
public static final int TAB_SIZE_OFFSET = UIScale.scale(1);
|
||||
|
||||
private AdaptiveTabType defaultTabType = AdaptiveTabType.NORMAL;
|
||||
|
@ -44,8 +45,12 @@ public class AdaptiveTabbedPane extends JComponent {
|
|||
public AdaptiveTabbedPane(int tabPlacement) {
|
||||
setBorder(new EmptyBorder(0, 0, 0, 0));
|
||||
setLayout(new BorderLayout());
|
||||
|
||||
tabbedPane.setFocusable(false);
|
||||
tabbedPane.setTabPlacement(tabPlacement);
|
||||
|
||||
add(tabbedPane);
|
||||
|
||||
tabbedPane.addMouseListener(new MouseAdapter() {
|
||||
@Override
|
||||
public void mousePressed(MouseEvent e) {
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
package org.lecturestudio.swing.components;
|
||||
|
||||
import org.lecturestudio.core.app.dictionary.Dictionary;
|
||||
|
||||
import java.awt.Font;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.Box;
|
||||
|
||||
public class MessageAsReplyView extends MessageView {
|
||||
|
||||
private JLabel userToReplyToLabel;
|
||||
|
||||
private JLabel replyToLabel;
|
||||
|
||||
|
||||
public MessageAsReplyView(Dictionary dict) {
|
||||
super(dict);
|
||||
}
|
||||
|
||||
public void setUserToReplyTo(final String userToReplyTo) {
|
||||
userToReplyToLabel.setText(userToReplyTo);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Box createUserPanel() {
|
||||
final Box userPanel = Box.createHorizontalBox();
|
||||
|
||||
userPanel.setOpaque(false);
|
||||
userPanel.add(userLabel);
|
||||
userPanel.add(Box.createHorizontalStrut(20));
|
||||
userPanel.add(replyToLabel);
|
||||
userPanel.add(Box.createHorizontalStrut(20));
|
||||
userPanel.add(userToReplyToLabel);
|
||||
userPanel.add(privateLabel);
|
||||
userPanel.add(Box.createHorizontalGlue());
|
||||
|
||||
return userPanel;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initComponents() {
|
||||
super.initComponents();
|
||||
|
||||
userToReplyToLabel = new JLabel();
|
||||
|
||||
replyToLabel = new JLabel(dict.get("label.reply"));
|
||||
replyToLabel.setFont(replyToLabel.getFont().deriveFont(Font.ITALIC));
|
||||
}
|
||||
}
|
|
@ -49,6 +49,8 @@ public abstract class MessagePanel extends JPanel {
|
|||
|
||||
protected JLabel privateLabel;
|
||||
|
||||
protected JLabel editedLabel;
|
||||
|
||||
|
||||
abstract protected void createContent(JPanel content);
|
||||
|
||||
|
@ -118,6 +120,11 @@ public abstract class MessagePanel extends JPanel {
|
|||
privateLabel.setForeground(Color.RED);
|
||||
privateLabel.setVisible(false);
|
||||
|
||||
editedLabel = new JLabel();
|
||||
editedLabel.setText(dict.get("label.edited"));
|
||||
editedLabel.setFont(editedLabel.getFont().deriveFont(Font.BOLD));
|
||||
editedLabel.setVisible(false);
|
||||
|
||||
createContent(content);
|
||||
|
||||
add(content);
|
||||
|
|
|
@ -23,6 +23,8 @@ import java.awt.Dimension;
|
|||
import java.awt.Insets;
|
||||
import java.awt.event.ComponentAdapter;
|
||||
import java.awt.event.ComponentEvent;
|
||||
import java.text.MessageFormat;
|
||||
import java.util.Objects;
|
||||
|
||||
import javax.swing.BorderFactory;
|
||||
import javax.swing.Box;
|
||||
|
@ -34,22 +36,80 @@ import org.lecturestudio.core.app.dictionary.Dictionary;
|
|||
import org.lecturestudio.core.view.Action;
|
||||
import org.lecturestudio.swing.AwtResourceLoader;
|
||||
import org.lecturestudio.swing.util.SwingUtils;
|
||||
import org.lecturestudio.web.api.message.MessengerDirectMessage;
|
||||
import org.lecturestudio.web.api.message.MessengerDirectMessageAsReply;
|
||||
import org.lecturestudio.web.api.message.MessengerMessage;
|
||||
import org.lecturestudio.web.api.model.UserInfo;
|
||||
|
||||
public class MessageView extends MessagePanel {
|
||||
|
||||
private MessengerMessage message;
|
||||
|
||||
private JButton discardButton;
|
||||
|
||||
private JTextArea textArea;
|
||||
|
||||
private JButton createSlideButton;
|
||||
|
||||
private String messageId;
|
||||
|
||||
protected JTextArea textArea;
|
||||
|
||||
|
||||
public MessageView(Dictionary dict) {
|
||||
super(dict);
|
||||
}
|
||||
|
||||
public void setMessage(String message) {
|
||||
textArea.setText(message);
|
||||
public MessengerMessage getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
public void setMessage(MessengerMessage message, UserInfo userInfo) {
|
||||
this.message = message;
|
||||
|
||||
textArea.setText(message.getMessage().getText());
|
||||
messageId = message.getMessageId();
|
||||
|
||||
if (message instanceof MessengerDirectMessage directMessage) {
|
||||
String myId = userInfo.getUserId();
|
||||
String recipientId = directMessage.getRecipientId();
|
||||
|
||||
boolean byMe = Objects.equals(message.getUserId(), myId);
|
||||
boolean toMe = Objects.equals(recipientId, myId);
|
||||
boolean toOrganisers = Objects.equals(recipientId, "organisers");
|
||||
|
||||
String sender = byMe
|
||||
? dict.get("text.message.me")
|
||||
: String.format("%s %s", message.getFirstName(), message.getFamilyName());
|
||||
|
||||
String recipient = toMe
|
||||
? dict.get("text.message.to.me")
|
||||
: toOrganisers
|
||||
? dict.get("text.message.to.organisators.short")
|
||||
: String.format("%s %s", directMessage.getRecipientFirstName(), directMessage.getRecipientFamilyName());
|
||||
|
||||
setUserName(MessageFormat.format(dict.get("text.message.recipient"), sender, ""));
|
||||
setPrivateText(recipient);
|
||||
}
|
||||
if (message instanceof MessengerDirectMessageAsReply directMessageAsReply) {
|
||||
String myId = userInfo.getUserId();
|
||||
String recipientId = directMessageAsReply.getRecipientId();
|
||||
|
||||
boolean byMe = Objects.equals(message.getUserId(), myId);
|
||||
boolean toMe = Objects.equals(recipientId, myId);
|
||||
boolean toOrganisers = Objects.equals(recipientId, "organisers");
|
||||
|
||||
String sender = byMe
|
||||
? dict.get("text.message.me")
|
||||
: String.format("%s %s", message.getFirstName(), message.getFamilyName());
|
||||
|
||||
String recipient = toMe
|
||||
? dict.get("text.message.to.me")
|
||||
: toOrganisers
|
||||
? dict.get("text.message.to.organisators.short")
|
||||
: String.format("%s %s", directMessageAsReply.getRecipientFirstName(), directMessageAsReply.getRecipientFamilyName());
|
||||
|
||||
setUserName(MessageFormat.format(dict.get("text.message.recipient"), sender, ""));
|
||||
setPrivateText(recipient);
|
||||
}
|
||||
}
|
||||
|
||||
public void setPrivateText(String text) {
|
||||
|
@ -65,29 +125,32 @@ public class MessageView extends MessagePanel {
|
|||
SwingUtils.bindAction(createSlideButton, action);
|
||||
}
|
||||
|
||||
public String getMessageId() {
|
||||
return messageId;
|
||||
}
|
||||
|
||||
public void setIsEdited() {
|
||||
editedLabel.setVisible(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void createContent(JPanel content) {
|
||||
discardButton = new JButton(AwtResourceLoader.getIcon("message-check.svg", 18));
|
||||
discardButton.setToolTipText(dict.get("button.processed"));
|
||||
createSlideButton = new JButton(AwtResourceLoader.getIcon("message-slide.svg", 18));
|
||||
createSlideButton.setToolTipText(dict.get("button.create.slide"));
|
||||
initComponents();
|
||||
|
||||
Box userPanel = Box.createHorizontalBox();
|
||||
userPanel.setOpaque(false);
|
||||
userPanel.add(userLabel);
|
||||
userPanel.add(privateLabel);
|
||||
userPanel.add(Box.createHorizontalGlue());
|
||||
Box userPanel = createUserPanel();
|
||||
|
||||
Box timePanel = Box.createHorizontalBox();
|
||||
timePanel.setOpaque(false);
|
||||
timePanel.add(timeLabel);
|
||||
timePanel.add(Box.createHorizontalGlue());
|
||||
Box timeEditedPanel = Box.createHorizontalBox();
|
||||
timeEditedPanel.setOpaque(false);
|
||||
timeEditedPanel.add(timeLabel);
|
||||
timeEditedPanel.add(Box.createHorizontalStrut(10));
|
||||
timeEditedPanel.add(editedLabel);
|
||||
timeEditedPanel.add(Box.createHorizontalGlue());
|
||||
|
||||
Box userTimePanel = Box.createVerticalBox();
|
||||
userTimePanel.setBorder(BorderFactory.createEmptyBorder());
|
||||
userTimePanel.setOpaque(false);
|
||||
userTimePanel.add(userPanel);
|
||||
userTimePanel.add(timePanel);
|
||||
userTimePanel.add(timeEditedPanel);
|
||||
|
||||
Box controlPanel = Box.createHorizontalBox();
|
||||
controlPanel.setBorder(BorderFactory.createEmptyBorder(2, 5, 2, 5));
|
||||
|
@ -133,4 +196,23 @@ public class MessageView extends MessagePanel {
|
|||
}
|
||||
});
|
||||
}
|
||||
|
||||
protected Box createUserPanel() {
|
||||
final Box userPanel = Box.createHorizontalBox();
|
||||
|
||||
userPanel.setOpaque(false);
|
||||
userPanel.add(userLabel);
|
||||
userPanel.add(privateLabel);
|
||||
userPanel.add(Box.createHorizontalGlue());
|
||||
|
||||
return userPanel;
|
||||
}
|
||||
|
||||
protected void initComponents() {
|
||||
discardButton = new JButton(AwtResourceLoader.getIcon("message-check.svg", 18));
|
||||
createSlideButton = new JButton(AwtResourceLoader.getIcon("message-slide.svg", 18));
|
||||
|
||||
discardButton.setToolTipText(dict.get("button.processed"));
|
||||
createSlideButton.setToolTipText(dict.get("button.create.slide"));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -62,13 +62,13 @@ public class ParticipantList extends JPanel {
|
|||
@Inject
|
||||
public ParticipantList(ResourceBundle bundle) {
|
||||
super();
|
||||
actionMap = new HashMap<>();
|
||||
|
||||
setLayout(new BorderLayout());
|
||||
setFocusable(false);
|
||||
setIgnoreRepaint(true);
|
||||
|
||||
listModel = new SortedListModel();
|
||||
actionMap = new HashMap<>();
|
||||
|
||||
popupMenuBanItem = new JMenuItem("Ban");
|
||||
popupMenuBanItem.addActionListener(e -> {
|
||||
|
|
|
@ -455,7 +455,8 @@ public class ThumbPanel extends JPanel {
|
|||
if (selected) {
|
||||
g2d.setColor(Color.BLUE);
|
||||
g2d.fillRect(0, 0, getWidth(), getHeight());
|
||||
}else if(page.isOverlay()){
|
||||
}
|
||||
else if (page.isOverlay()) {
|
||||
g2d.setColor(Color.GRAY);
|
||||
g2d.fillRect(0, 0, getWidth(), getHeight());
|
||||
}
|
||||
|
|
|
@ -175,7 +175,7 @@
|
|||
<dependency>
|
||||
<groupId>org.apache.tomcat.embed</groupId>
|
||||
<artifactId>tomcat-embed-websocket</artifactId>
|
||||
<version>10.1.10</version>
|
||||
<version>10.1.19</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
|
|
|
@ -27,7 +27,9 @@ import javax.json.JsonValue;
|
|||
import javax.json.bind.adapter.JsonbAdapter;
|
||||
|
||||
import org.lecturestudio.web.api.message.MessengerDirectMessage;
|
||||
import org.lecturestudio.web.api.message.MessengerDirectMessageAsReply;
|
||||
import org.lecturestudio.web.api.message.MessengerMessage;
|
||||
import org.lecturestudio.web.api.message.MessengerMessageAsReply;
|
||||
import org.lecturestudio.web.api.model.Message;
|
||||
|
||||
public class MessengerMessageAdapter implements JsonbAdapter<MessengerMessage, JsonObject> {
|
||||
|
@ -43,12 +45,20 @@ public class MessengerMessageAdapter implements JsonbAdapter<MessengerMessage, J
|
|||
builder.add("date", message.getDate().toString());
|
||||
builder.add("messageId", message.getMessageId());
|
||||
|
||||
if(message instanceof MessengerMessageAsReply messageAsReply) {
|
||||
builder.add("msgIdToReplyTo", messageAsReply.getMsgIdToReplyTo());
|
||||
}
|
||||
|
||||
if (message instanceof MessengerDirectMessage directMessage) {
|
||||
builder.add("recipientId", directMessage.getRecipientId());
|
||||
builder.add("recipientFirstName", directMessage.getRecipientFirstName());
|
||||
builder.add("recipientFamilyName", directMessage.getRecipientFamilyName());
|
||||
}
|
||||
|
||||
if(message instanceof MessengerDirectMessageAsReply directMessageAsReply) {
|
||||
builder.add("msgIdToReplyTo", directMessageAsReply.getMsgIdToReplyTo());
|
||||
}
|
||||
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
|
@ -58,21 +68,45 @@ public class MessengerMessageAdapter implements JsonbAdapter<MessengerMessage, J
|
|||
|
||||
MessengerMessage message;
|
||||
|
||||
if (type.equals("MessengerDirectMessage")) {
|
||||
MessengerDirectMessage directMessage = new MessengerDirectMessage();
|
||||
directMessage.setRecipientId(jsonObject.getString("recipientId"));
|
||||
switch (type) {
|
||||
case "MessengerDirectMessage" -> {
|
||||
MessengerDirectMessage directMessage = new MessengerDirectMessage();
|
||||
|
||||
if (!jsonObject.isNull("recipientFirstName")) {
|
||||
directMessage.setRecipientFirstName(jsonObject.getString("recipientFirstName"));
|
||||
}
|
||||
if (!jsonObject.isNull("recipientFamilyName")) {
|
||||
directMessage.setRecipientFamilyName(jsonObject.getString("recipientFamilyName"));
|
||||
directMessage.setRecipientId(jsonObject.getString("recipientId"));
|
||||
if (!jsonObject.isNull("recipientFirstName")) {
|
||||
directMessage.setRecipientFirstName(jsonObject.getString("recipientFirstName"));
|
||||
}
|
||||
if (!jsonObject.isNull("recipientFamilyName")) {
|
||||
directMessage.setRecipientFamilyName(jsonObject.getString("recipientFamilyName"));
|
||||
}
|
||||
message = directMessage;
|
||||
}
|
||||
case "MessengerDirectMessageAsReply" -> {
|
||||
MessengerDirectMessageAsReply directMessageAsReply = new MessengerDirectMessageAsReply();
|
||||
|
||||
message = directMessage;
|
||||
}
|
||||
else {
|
||||
message = new MessengerMessage();
|
||||
directMessageAsReply.setRecipientId(jsonObject.getString("recipientId"));
|
||||
if (!jsonObject.isNull("recipientFirstName")) {
|
||||
directMessageAsReply.setRecipientFirstName(jsonObject.getString("recipientFirstName"));
|
||||
}
|
||||
if (!jsonObject.isNull("recipientFamilyName")) {
|
||||
directMessageAsReply.setRecipientFamilyName(jsonObject.getString("recipientFamilyName"));
|
||||
}
|
||||
if (!jsonObject.isNull("messageIdToReplyTo")) {
|
||||
directMessageAsReply.setMsgIdToReplyTo(jsonObject.getString("msgIdToReplyTo"));
|
||||
}
|
||||
|
||||
message = directMessageAsReply;
|
||||
}
|
||||
case "MessengerMessageAsReply" -> {
|
||||
MessengerMessageAsReply messageAsReply = new MessengerMessageAsReply();
|
||||
|
||||
if (!jsonObject.isNull("msgIdToReplyTo")) {
|
||||
messageAsReply.setMsgIdToReplyTo(jsonObject.getString("msgIdToReplyTo"));
|
||||
}
|
||||
|
||||
message = messageAsReply;
|
||||
}
|
||||
default -> message = new MessengerMessage();
|
||||
}
|
||||
|
||||
if (jsonObject.get("text").getValueType() != JsonValue.ValueType.NULL) {
|
||||
|
@ -96,6 +130,12 @@ public class MessengerMessageAdapter implements JsonbAdapter<MessengerMessage, J
|
|||
if (jsonObject.get("messageId").getValueType() != JsonValue.ValueType.NULL) {
|
||||
message.setMessageId(jsonObject.getString("messageId"));
|
||||
}
|
||||
if (jsonObject.get("deleted").getValueType() != JsonValue.ValueType.NULL) {
|
||||
message.setDeleted(jsonObject.getBoolean("deleted"));
|
||||
}
|
||||
if (jsonObject.get("edited").getValueType() != JsonValue.ValueType.NULL) {
|
||||
message.setEdited(jsonObject.getBoolean("edited"));
|
||||
}
|
||||
|
||||
return message;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
package org.lecturestudio.web.api.data.bind;
|
||||
|
||||
import static java.util.Objects.nonNull;
|
||||
|
||||
import javax.json.Json;
|
||||
import javax.json.JsonObject;
|
||||
import javax.json.JsonObjectBuilder;
|
||||
import javax.json.bind.adapter.JsonbAdapter;
|
||||
|
||||
import org.lecturestudio.web.api.message.StopStreamEnvironmentMessage;
|
||||
|
||||
import java.time.ZonedDateTime;
|
||||
|
||||
public class StopStreamEnvironmentMessageAdapter implements JsonbAdapter<StopStreamEnvironmentMessage, JsonObject> {
|
||||
|
||||
@Override
|
||||
public JsonObject adaptToJson(StopStreamEnvironmentMessage stopStreamEnvironmentMessage) throws Exception {
|
||||
JsonObjectBuilder builder = Json.createObjectBuilder();
|
||||
|
||||
builder.add("type", stopStreamEnvironmentMessage.getClass().getSimpleName());
|
||||
|
||||
if (nonNull(stopStreamEnvironmentMessage.getMessageId())) {
|
||||
builder.add("messageId", stopStreamEnvironmentMessage.getMessageId());
|
||||
}
|
||||
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public org.lecturestudio.web.api.message.StopStreamEnvironmentMessage adaptFromJson(JsonObject jsonObject) throws Exception {
|
||||
String typeStr = jsonObject.getString("type");
|
||||
String className = StopStreamEnvironmentMessage.class.getPackageName() + "." + typeStr;
|
||||
Class<?> cls = Class.forName(className);
|
||||
|
||||
StopStreamEnvironmentMessage message = (StopStreamEnvironmentMessage) cls.getConstructor().newInstance();
|
||||
|
||||
message.setMessageId(jsonObject.getString("messageId"));
|
||||
message.setDate(ZonedDateTime.parse(jsonObject.getString("time")));
|
||||
message.setUserId(jsonObject.getString("userId"));
|
||||
message.setFirstName(jsonObject.getString("firstName"));
|
||||
message.setFamilyName(jsonObject.getString("familyName"));
|
||||
|
||||
return message;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
package org.lecturestudio.web.api.message;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@NoArgsConstructor
|
||||
public class MessengerDirectMessageAsReply extends MessengerDirectMessage {
|
||||
|
||||
private String msgIdToReplyTo;
|
||||
|
||||
}
|
|
@ -31,4 +31,7 @@ public class MessengerMessage extends UserMessage {
|
|||
|
||||
private Message message;
|
||||
|
||||
private boolean deleted;
|
||||
|
||||
private boolean edited;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
package org.lecturestudio.web.api.message;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@NoArgsConstructor
|
||||
public class MessengerMessageAsReply extends MessengerMessage {
|
||||
|
||||
private String msgIdToReplyTo;
|
||||
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
package org.lecturestudio.web.api.message;
|
||||
|
||||
public class StopStreamEnvironmentMessage extends UserMessage {
|
||||
|
||||
}
|
|
@ -33,4 +33,12 @@ public abstract class WebMessage {
|
|||
|
||||
private ZonedDateTime date;
|
||||
|
||||
|
||||
@Override
|
||||
public boolean equals(final Object obj) {
|
||||
if(!(obj instanceof WebMessage webMessage)) return false;
|
||||
|
||||
return this == webMessage || this.messageId.equals(webMessage.getMessageId());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -96,7 +96,8 @@ public class WebSocketStompTransport extends ExecutableBase implements MessageTr
|
|||
new CoursePresenceMessageAdapter(),
|
||||
new MessengerMessageAdapter(),
|
||||
new QuizAnswerMessageAdapter(),
|
||||
new SpeechMessageAdapter()
|
||||
new SpeechMessageAdapter(),
|
||||
new StopStreamEnvironmentMessageAdapter()
|
||||
);
|
||||
|
||||
jsonb = JsonbBuilder.create(jsonbConfig);
|
||||
|
@ -255,6 +256,9 @@ public class WebSocketStompTransport extends ExecutableBase implements MessageTr
|
|||
|
||||
subscribe(stompSession, "/topic/course/event/{id}/presence");
|
||||
subscribe(stompSession, "/topic/course/{id}/chat");
|
||||
subscribe(stompSession, "/topic/course/{id}/chat/deletion");
|
||||
subscribe(stompSession, "/topic/course/{id}/chat/edit");
|
||||
subscribe(stompSession, "/topic/course/{id}/stopStreamEnvironment");
|
||||
subscribe(stompSession, "/user/queue/course/{id}/chat");
|
||||
subscribe(stompSession, "/user/queue/course/{id}/presence");
|
||||
subscribe(stompSession, "/user/queue/course/{id}/speech");
|
||||
|
|
|
@ -0,0 +1,72 @@
|
|||
package org.lecturestudio.web.api.message.util;
|
||||
|
||||
import org.lecturestudio.core.app.dictionary.Dictionary;
|
||||
import org.lecturestudio.web.api.message.MessengerDirectMessageAsReply;
|
||||
import org.lecturestudio.web.api.message.MessengerMessage;
|
||||
import org.lecturestudio.web.api.message.MessengerMessageAsReply;
|
||||
import org.lecturestudio.web.api.message.UserMessage;
|
||||
import org.lecturestudio.web.api.model.UserInfo;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
public class MessageUtil {
|
||||
|
||||
public static boolean isReply(final UserMessage message) {
|
||||
return message instanceof MessengerMessageAsReply || message instanceof MessengerDirectMessageAsReply;
|
||||
}
|
||||
|
||||
public static String evaluateSender(final UserMessage message, final UserInfo userInfo, final Dictionary dictionary) {
|
||||
final boolean byMe = sentByMe(message, userInfo);
|
||||
|
||||
if (byMe) return dictionary.get("text.message.me");
|
||||
else {
|
||||
String nameFull = message.getFirstName() + " " + message.getFamilyName();
|
||||
String[] nameParts = nameFull.split(" ");
|
||||
String firstName = nameParts.length > 0 ? nameParts[0] : "";
|
||||
String lastName = nameParts.length > 1 ? nameParts[nameParts.length - 1] : "";
|
||||
|
||||
return String.format("%s %s", firstName, lastName);
|
||||
}
|
||||
}
|
||||
|
||||
public static String evaluateSenderOfMessageToReplyTo(final UserMessage messageToReplyTo, final UserInfo userInfo, final Dictionary dictionary) {
|
||||
final boolean byMe = sentByMe(messageToReplyTo, userInfo);
|
||||
|
||||
if(byMe) return dictionary.get("text.message.me.dative");
|
||||
|
||||
return evaluateSender(messageToReplyTo, userInfo, dictionary);
|
||||
}
|
||||
|
||||
public static MessengerMessage findMessageToReplyTo(final List<MessengerMessage> messages, final MessengerMessage message) {
|
||||
if(message instanceof MessengerMessageAsReply messageAsReply) {
|
||||
return messages.stream()
|
||||
.filter(messengerMessage -> messengerMessage.getMessageId().equals(messageAsReply.getMsgIdToReplyTo()))
|
||||
.findAny()
|
||||
.orElseThrow(() -> new IllegalArgumentException("Given ID of message to reply to couldn't be found"));
|
||||
}
|
||||
|
||||
if(message instanceof MessengerDirectMessageAsReply directMessageAsReply) {
|
||||
return messages.stream()
|
||||
.filter(messengerMessage -> messengerMessage.getMessageId().equals(directMessageAsReply.getMsgIdToReplyTo()))
|
||||
.findAny()
|
||||
.orElseThrow(() -> new IllegalArgumentException("Given ID of message to reply to couldn't be found"));
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static void updateOutdatedMessage(final List<MessengerMessage> messages, final MessengerMessage newMessage) {
|
||||
for (MessengerMessage message : messages) {
|
||||
if (message.getMessageId().equals(newMessage.getMessageId())) {
|
||||
messages.remove(message);
|
||||
messages.add(newMessage);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean sentByMe(final UserMessage message, final UserInfo userInfo) {
|
||||
final String myId = userInfo.getUserId();
|
||||
return Objects.equals(message.getUserId(), myId);
|
||||
}
|
||||
}
|
|
@ -39,6 +39,14 @@ public class Message extends ServiceModel {
|
|||
this.text = text;
|
||||
}
|
||||
|
||||
public boolean isReply() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public String getMsgIdToReplyTo() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getClass().getSimpleName() + ": " + text;
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
package org.lecturestudio.web.api.model;
|
||||
|
||||
public class MessageAsReply extends Message {
|
||||
|
||||
private String msgIdToReplyTo;
|
||||
|
||||
|
||||
public MessageAsReply() {
|
||||
this(null);
|
||||
}
|
||||
|
||||
public MessageAsReply(String msgIdToReplyTo) {
|
||||
setMsgIdToReplyTo(msgIdToReplyTo);
|
||||
}
|
||||
|
||||
public String getMsgIdToReplyTo() {
|
||||
return msgIdToReplyTo;
|
||||
}
|
||||
|
||||
public void setMsgIdToReplyTo(final String msgIdToReplyTo) {
|
||||
this.msgIdToReplyTo = msgIdToReplyTo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isReply() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getClass().getSimpleName() + ": " + msgIdToReplyTo;
|
||||
}
|
||||
}
|
|
@ -25,6 +25,8 @@ public class Course {
|
|||
|
||||
private Long id;
|
||||
|
||||
private String defaultAccessLink;
|
||||
|
||||
private String roomId;
|
||||
|
||||
private String title;
|
||||
|
@ -36,6 +38,10 @@ public class Course {
|
|||
return id;
|
||||
}
|
||||
|
||||
public String getDefaultAccessLink() {
|
||||
return defaultAccessLink;
|
||||
}
|
||||
|
||||
public String getRoomId() {
|
||||
return roomId;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue