diff --git a/ui/src/main/java/io/xeres/ui/controller/chat/ChatViewController.java b/ui/src/main/java/io/xeres/ui/controller/chat/ChatViewController.java
index bad44f9b..fcebd90a 100644
--- a/ui/src/main/java/io/xeres/ui/controller/chat/ChatViewController.java
+++ b/ui/src/main/java/io/xeres/ui/controller/chat/ChatViewController.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019-2023 by David Gerber - https://zapek.com
+ * Copyright (c) 2019-2025 by David Gerber - https://zapek.com
  *
  * This file is part of Xeres.
  *
@@ -54,6 +54,7 @@
 import javafx.fxml.FXMLLoader;
 import javafx.scene.Node;
 import javafx.scene.control.*;
+import javafx.scene.image.Image;
 import javafx.scene.image.ImageView;
 import javafx.scene.input.KeyCode;
 import javafx.scene.input.KeyCodeCombination;
@@ -204,10 +205,15 @@ public ChatViewController(MessageClient messageClient, ChatClient chatClient, Pr
 	}
 
 	@Override
-	public void initialize() throws IOException
+	public void initialize()
 	{
-		profileClient.getOwn().doOnSuccess(profile -> nickname = profile.getName()) // XXX: we shouldn't go further until nickname is set. maybe it should be a parameter
+		profileClient.getOwn().doOnSuccess(profile -> Platform.runLater(() -> initializeReally(profile.getName())))
 				.subscribe();
+	}
+
+	private void initializeReally(String nickname)
+	{
+		this.nickname = nickname;
 
 		var root = new TreeItem<>(new RoomHolder());
 		//noinspection unchecked
@@ -253,7 +259,14 @@ public void initialize() throws IOException
 		});
 
 		var loader = new FXMLLoader(getClass().getResource("/view/chat/chat_roominfo.fxml"), bundle);
-		roomInfoView = loader.load();
+		try
+		{
+			roomInfoView = loader.load();
+		}
+		catch (IOException e)
+		{
+			throw new RuntimeException(e);
+		}
 		chatRoomInfoController = loader.getController();
 
 		lastTypingTimeline = new Timeline(new KeyFrame(javafx.util.Duration.seconds(TYPING_NOTIFICATION_DELAY.getSeconds())));
@@ -268,7 +281,7 @@ public void initialize() throws IOException
 		previewCancel.setOnAction(event -> cancelImage());
 
 		send.addEventHandler(KeyEvent.KEY_PRESSED, this::handleInputKeys);
-		TextInputControlUtils.addEnhancedInputContextMenu(send, locationClient);
+		TextInputControlUtils.addEnhancedInputContextMenu(send, locationClient, this::handlePaste);
 
 		invite.setOnAction(event -> windowManager.openInvite(selectedRoom.getId()));
 
@@ -688,14 +701,8 @@ private void handleInputKeys(KeyEvent event)
 
 		if (PASTE_KEY.match(event))
 		{
-			var image = ClipboardUtils.getImageFromClipboard();
-			if (image != null)
+			if (handlePaste(send))
 			{
-				imagePreview.setImage(image);
-
-				ImageUtils.limitMaximumImageSize(imagePreview, PREVIEW_IMAGE_WIDTH_MAX * PREVIEW_IMAGE_HEIGHT_MAX);
-
-				setPreviewGroupVisibility(true);
 				event.consume();
 			}
 		}
@@ -711,6 +718,29 @@ else if (BACKSPACE_KEY.match(event) && imagePreview.getImage() != null)
 		}
 	}
 
+	private boolean handlePaste(TextInputControl textInputControl)
+	{
+		var object = ClipboardUtils.getSupportedObjectFromClipboard();
+		return switch (object)
+		{
+			case Image image ->
+			{
+				imagePreview.setImage(image);
+
+				ImageUtils.limitMaximumImageSize(imagePreview, PREVIEW_IMAGE_WIDTH_MAX * PREVIEW_IMAGE_HEIGHT_MAX);
+
+				setPreviewGroupVisibility(true);
+				yield true;
+			}
+			case String string ->
+			{
+				textInputControl.insertText(textInputControl.getCaretPosition(), string);
+				yield true;
+			}
+			default -> false;
+		};
+	}
+
 	private void sendImage()
 	{
 		sendChatMessage("<img src=\"" + ImageUtils.writeImageAsJpegData(imagePreview.getImage(), MESSAGE_MAXIMUM_SIZE) + "\"/>");
diff --git a/ui/src/main/java/io/xeres/ui/controller/contact/ContactViewController.java b/ui/src/main/java/io/xeres/ui/controller/contact/ContactViewController.java
index c1bded04..1de58b56 100644
--- a/ui/src/main/java/io/xeres/ui/controller/contact/ContactViewController.java
+++ b/ui/src/main/java/io/xeres/ui/controller/contact/ContactViewController.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2024 by David Gerber - https://zapek.com
+ * Copyright (c) 2024-2025 by David Gerber - https://zapek.com
  *
  * This file is part of Xeres.
  *
@@ -358,7 +358,7 @@ private void setupContactSearch()
 		searchClear.setCursor(Cursor.HAND);
 		searchClear.setOnMouseClicked(event -> searchTextField.clear());
 
-		TextInputControlUtils.addEnhancedInputContextMenu(searchTextField, null);
+		TextInputControlUtils.addEnhancedInputContextMenu(searchTextField, null, null);
 		searchTextField.textProperty().addListener((observable, oldValue, newValue) -> contactFilter.setNameFilter(newValue));
 		searchTextField.lengthProperty().addListener((observable, oldValue, newValue) -> {
 			if (newValue.intValue() > 0)
diff --git a/ui/src/main/java/io/xeres/ui/controller/file/FileSearchViewController.java b/ui/src/main/java/io/xeres/ui/controller/file/FileSearchViewController.java
index ffca0cac..650723b8 100644
--- a/ui/src/main/java/io/xeres/ui/controller/file/FileSearchViewController.java
+++ b/ui/src/main/java/io/xeres/ui/controller/file/FileSearchViewController.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2024 by David Gerber - https://zapek.com
+ * Copyright (c) 2024-2025 by David Gerber - https://zapek.com
  *
  * This file is part of Xeres.
  *
@@ -80,7 +80,7 @@ public FileSearchViewController(FileClient fileClient, NotificationClient notifi
 	@Override
 	public void initialize()
 	{
-		TextInputControlUtils.addEnhancedInputContextMenu(search, null);
+		TextInputControlUtils.addEnhancedInputContextMenu(search, null, null);
 		search.setOnKeyPressed(event -> {
 			if (event.getCode() == KeyCode.ENTER)
 			{
diff --git a/ui/src/main/java/io/xeres/ui/controller/id/AddRsIdWindowController.java b/ui/src/main/java/io/xeres/ui/controller/id/AddRsIdWindowController.java
index f5567f43..4015bda8 100644
--- a/ui/src/main/java/io/xeres/ui/controller/id/AddRsIdWindowController.java
+++ b/ui/src/main/java/io/xeres/ui/controller/id/AddRsIdWindowController.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019-2023 by David Gerber - https://zapek.com
+ * Copyright (c) 2019-2025 by David Gerber - https://zapek.com
  *
  * This file is part of Xeres.
  *
@@ -128,7 +128,7 @@ public void initialize()
 			debouncer.setOnFinished(event -> checkRsId(newValue));
 			debouncer.playFromStart();
 		});
-		TextInputControlUtils.addEnhancedInputContextMenu(rsIdTextArea, null);
+		TextInputControlUtils.addEnhancedInputContextMenu(rsIdTextArea, null, null);
 
 		profileClient.getOwn()
 				.doOnSuccess(profile -> ownProfile = profile)
diff --git a/ui/src/main/java/io/xeres/ui/controller/messaging/MessagingWindowController.java b/ui/src/main/java/io/xeres/ui/controller/messaging/MessagingWindowController.java
index 4551e5e5..cd108c22 100644
--- a/ui/src/main/java/io/xeres/ui/controller/messaging/MessagingWindowController.java
+++ b/ui/src/main/java/io/xeres/ui/controller/messaging/MessagingWindowController.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019-2023 by David Gerber - https://zapek.com
+ * Copyright (c) 2019-2025 by David Gerber - https://zapek.com
  *
  * This file is part of Xeres.
  *
@@ -55,6 +55,7 @@
 import javafx.scene.control.Alert;
 import javafx.scene.control.Button;
 import javafx.scene.control.TextArea;
+import javafx.scene.control.TextInputControl;
 import javafx.scene.image.Image;
 import javafx.scene.image.ImageView;
 import javafx.scene.input.*;
@@ -161,7 +162,7 @@ public void initialize()
 				.subscribe();
 
 		send.addEventHandler(KeyEvent.KEY_PRESSED, this::handleInputKeys);
-		TextInputControlUtils.addEnhancedInputContextMenu(send, null);
+		TextInputControlUtils.addEnhancedInputContextMenu(send, null, this::handlePaste);
 
 		addImage.setOnAction(event -> {
 			var fileChooser = new FileChooser();
@@ -389,10 +390,8 @@ private void handleInputKeys(KeyEvent event)
 	{
 		if (PASTE_KEY.match(event))
 		{
-			var image = ClipboardUtils.getImageFromClipboard();
-			if (image != null)
+			if (handlePaste(send))
 			{
-				sendImageViewToMessage(new ImageView(image));
 				event.consume();
 			}
 		}
@@ -417,6 +416,25 @@ else if (event.getCode() == KeyCode.ENTER)
 		}
 	}
 
+	private boolean handlePaste(TextInputControl textInputControl)
+	{
+		var object = ClipboardUtils.getSupportedObjectFromClipboard();
+		return switch (object)
+		{
+			case Image image ->
+			{
+				sendImageViewToMessage(new ImageView(image));
+				yield true;
+			}
+			case String string ->
+			{
+				textInputControl.insertText(textInputControl.getCaretPosition(), string);
+				yield true;
+			}
+			default -> false;
+		};
+	}
+
 	private void sendImageViewToMessage(ImageView imageView)
 	{
 		ImageUtils.limitMaximumImageSize(imageView, IMAGE_WIDTH_MAX * IMAGE_HEIGHT_MAX);
diff --git a/ui/src/main/java/io/xeres/ui/custom/EditorView.java b/ui/src/main/java/io/xeres/ui/custom/EditorView.java
index 0900f808..7596025f 100644
--- a/ui/src/main/java/io/xeres/ui/custom/EditorView.java
+++ b/ui/src/main/java/io/xeres/ui/custom/EditorView.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2023 by David Gerber - https://zapek.com
+ * Copyright (c) 2023-2025 by David Gerber - https://zapek.com
  *
  * This file is part of Xeres.
  *
@@ -31,6 +31,7 @@
 import javafx.fxml.FXML;
 import javafx.fxml.FXMLLoader;
 import javafx.scene.control.*;
+import javafx.scene.image.Image;
 import javafx.scene.image.ImageView;
 import javafx.scene.input.KeyCode;
 import javafx.scene.input.KeyCodeCombination;
@@ -208,7 +209,7 @@ public void setReply(String reply)
 
 	public void setInputContextMenu(LocationClient locationClient)
 	{
-		TextInputControlUtils.addEnhancedInputContextMenu(editor, locationClient);
+		TextInputControlUtils.addEnhancedInputContextMenu(editor, locationClient, this::handlePaste);
 	}
 
 	public boolean isModified()
@@ -396,15 +397,8 @@ private void handleInputKeys(KeyEvent event)
 
 		if (PASTE_KEY.match(event))
 		{
-			var image = ClipboardUtils.getImageFromClipboard();
-			if (image != null)
+			if (handlePaste(editor))
 			{
-				var imageView = new ImageView(image);
-				ImageUtils.limitMaximumImageSize(imageView, IMAGE_WIDTH_MAX * IMAGE_HEIGHT_MAX);
-
-				var imgData = ImageUtils.writeImageAsJpegData(imageView.getImage(), IMAGE_MAXIMUM_SIZE);
-				editor.insertText(editor.getCaretPosition(), "![](" + imgData + ")");
-
 				event.consume();
 			}
 		}
@@ -414,6 +408,30 @@ else if (ENTER_INSERT_KEY.match(event))
 		}
 	}
 
+	private boolean handlePaste(TextInputControl textInputControl)
+	{
+		var object = ClipboardUtils.getSupportedObjectFromClipboard();
+		return switch (object)
+		{
+			case Image image ->
+			{
+				var imageView = new ImageView(image);
+				ImageUtils.limitMaximumImageSize(imageView, IMAGE_WIDTH_MAX * IMAGE_HEIGHT_MAX);
+
+				var imgData = ImageUtils.writeImageAsJpegData(imageView.getImage(), IMAGE_MAXIMUM_SIZE);
+				textInputControl.insertText(textInputControl.getCaretPosition(), "![](" + imgData + ")");
+
+				yield true;
+			}
+			case String string ->
+			{
+				textInputControl.insertText(textInputControl.getCaretPosition(), string);
+				yield true;
+			}
+			default -> false;
+		};
+	}
+
 	/**
 	 * Inserts a new line without cutting the current line.
 	 */
diff --git a/ui/src/main/java/io/xeres/ui/support/clipboard/ClipboardUtils.java b/ui/src/main/java/io/xeres/ui/support/clipboard/ClipboardUtils.java
index 98e77a35..60043e64 100644
--- a/ui/src/main/java/io/xeres/ui/support/clipboard/ClipboardUtils.java
+++ b/ui/src/main/java/io/xeres/ui/support/clipboard/ClipboardUtils.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2024 by David Gerber - https://zapek.com
+ * Copyright (c) 2024-2025 by David Gerber - https://zapek.com
  *
  * This file is part of Xeres.
  *
@@ -31,11 +31,14 @@
 
 /**
  * Utility class to use the clipboard. This implementation uses AWT because the clipboard support of JavaFX is, quite frankly, a
- * royal piece of shit.
+ * royal piece of shit:
+ * <ul>
+ *     <li>it fails to work with some bitmaps (for example from Telegram, Windows 10 and print screen, Chrome, ...).
+ * <li>it fails with data URIs because it tries to find out if the image is a supported format and even though it is, the URL is "wrong" for it.
+ * </ul>
  * <p>
- * Fails to work with some bitmaps (for example from Telegram, Windows 10 and print screen, Chrome, ...).
- * <p>
- * Fails with data URIs because it tries to find out if the image is a supported format and even though it is, the URL is "wrong" for it.
+ * This one just works. Note that there still might be some warnings printed out because of the DataFlavor system that isn't compatible
+ * with everything. It's harmless though.
  */
 public final class ClipboardUtils
 {
@@ -44,6 +47,26 @@ private ClipboardUtils()
 		throw new UnsupportedOperationException("Utility class");
 	}
 
+	/**
+	 * Gets whatever is in the clipboard and supported, currently: string and JavaFX images.
+	 *
+	 * @return a string or an image
+	 */
+	public static Object getSupportedObjectFromClipboard()
+	{
+		Object object = getImageFromClipboard();
+		if (object == null)
+		{
+			object = getStringFromClipboard();
+		}
+		return object;
+	}
+
+	/**
+	 * Gets an image from the clipboard
+	 *
+	 * @return the image, or null if the clipboard is empty, or it doesn't contain an image
+	 */
 	public static Image getImageFromClipboard()
 	{
 		var transferable = Toolkit.getDefaultToolkit().getSystemClipboard().getContents(null);
@@ -63,11 +86,45 @@ public static Image getImageFromClipboard()
 		return null;
 	}
 
+	/**
+	 * Copies an image to the clipboard.
+	 *
+	 * @param image the image to copy to the clipboard
+	 */
 	public static void copyImageToClipboard(Image image)
 	{
 		Toolkit.getDefaultToolkit().getSystemClipboard().setContents(new ImageSelection(SwingFXUtils.fromFXImage(image, null)), null);
 	}
 
+	/**
+	 * Gets a string from the clipboard.
+	 *
+	 * @return a string, or null if the clipboard is empty, or it doesn't contain a string
+	 */
+	public static String getStringFromClipboard()
+	{
+		var transferable = Toolkit.getDefaultToolkit().getSystemClipboard().getContents(null);
+		if (transferable != null && transferable.isDataFlavorSupported(DataFlavor.stringFlavor))
+		{
+			String string;
+			try
+			{
+				string = (String) transferable.getTransferData(DataFlavor.stringFlavor);
+			}
+			catch (UnsupportedFlavorException | IOException e)
+			{
+				throw new RuntimeException(e);
+			}
+			return string;
+		}
+		return null;
+	}
+
+	/**
+	 * Copies a string to the clipboard.
+	 *
+	 * @param text the string to copy to the clipboard
+	 */
 	public static void copyTextToClipboard(String text)
 	{
 		Toolkit.getDefaultToolkit().getSystemClipboard().setContents(new StringSelection(text), null);
diff --git a/ui/src/main/java/io/xeres/ui/support/util/TextInputControlUtils.java b/ui/src/main/java/io/xeres/ui/support/util/TextInputControlUtils.java
index 0c71b061..da313831 100644
--- a/ui/src/main/java/io/xeres/ui/support/util/TextInputControlUtils.java
+++ b/ui/src/main/java/io/xeres/ui/support/util/TextInputControlUtils.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2023 by David Gerber - https://zapek.com
+ * Copyright (c) 2023-2025 by David Gerber - https://zapek.com
  *
  * This file is part of Xeres.
  *
@@ -35,6 +35,7 @@
 
 import java.util.List;
 import java.util.ResourceBundle;
+import java.util.function.Consumer;
 
 import static io.xeres.common.dto.location.LocationConstants.OWN_LOCATION_ID;
 
@@ -54,11 +55,11 @@ private TextInputControlUtils()
 	 * @param textInputControl the text input control
 	 * @param locationClient   the location client, if null, then there will be no "Paste own ID" menu item
 	 */
-	public static void addEnhancedInputContextMenu(TextInputControl textInputControl, LocationClient locationClient)
+	public static void addEnhancedInputContextMenu(TextInputControl textInputControl, LocationClient locationClient, Consumer<TextInputControl> pasteAction)
 	{
 		var contextMenu = new ContextMenu();
 
-		contextMenu.getItems().addAll(createDefaultChatInputMenuItems(textInputControl));
+		contextMenu.getItems().addAll(createDefaultChatInputMenuItems(textInputControl, pasteAction));
 		if (locationClient != null)
 		{
 			var pasteId = new MenuItem(bundle.getString("paste-id"));
@@ -81,7 +82,7 @@ private static String buildRetroshareUrl(RSIdResponse rsIdResponse)
 		return CertificateUriFactory.generate(cleanCert, rsIdResponse.name(), rsIdResponse.location());
 	}
 
-	private static List<MenuItem> createDefaultChatInputMenuItems(TextInputControl textInputControl)
+	private static List<MenuItem> createDefaultChatInputMenuItems(TextInputControl textInputControl, Consumer<TextInputControl> pasteAction)
 	{
 		var undo = new MenuItem(bundle.getString("undo"));
 		undo.setGraphic(new FontIcon(MaterialDesignU.UNDO_VARIANT));
@@ -101,7 +102,16 @@ private static List<MenuItem> createDefaultChatInputMenuItems(TextInputControl t
 
 		var paste = new MenuItem(bundle.getString("paste"));
 		paste.setGraphic(new FontIcon(MaterialDesignC.CONTENT_PASTE));
-		paste.setOnAction(event -> textInputControl.paste());
+		paste.setOnAction(event -> {
+			if (pasteAction != null)
+			{
+				pasteAction.accept(textInputControl);
+			}
+			else
+			{
+				textInputControl.paste();
+			}
+		});
 
 		var delete = new MenuItem(bundle.getString("delete"));
 		delete.setGraphic(new FontIcon(MaterialDesignT.TRASH_CAN));