Skip to content

Commit 245c071

Browse files
committed
feat: implement clipboard image upload and refactor image upload logic across versions
1 parent 618e655 commit 245c071

11 files changed

Lines changed: 198 additions & 58 deletions

File tree

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package net.azisaba.interchatmod.common.util;
2+
3+
import org.jetbrains.annotations.Nullable;
4+
5+
import javax.imageio.ImageIO;
6+
import java.awt.*;
7+
import java.awt.datatransfer.DataFlavor;
8+
import java.awt.datatransfer.Transferable;
9+
import java.awt.image.BufferedImage;
10+
import java.io.ByteArrayOutputStream;
11+
12+
public class ClipboardUtil {
13+
public static byte @Nullable [] getImageFromClipboard() {
14+
Transferable content = Toolkit.getDefaultToolkit().getSystemClipboard().getContents(null);
15+
if (content == null) return null;
16+
if (!content.isDataFlavorSupported(DataFlavor.imageFlavor)) return null;
17+
try {
18+
BufferedImage image = (BufferedImage) content.getTransferData(DataFlavor.imageFlavor);
19+
ByteArrayOutputStream os = new ByteArrayOutputStream();
20+
ImageIO.write(image, "png", os);
21+
return os.toByteArray();
22+
} catch (Exception e) {
23+
return null;
24+
}
25+
}
26+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
package net.azisaba.interchatmod.common.util.function;
2+
3+
import java.io.IOException;
4+
5+
@FunctionalInterface
6+
public interface IOSupplier<T> {
7+
T get() throws IOException;
8+
}

common/src/main/resources/assets/interchatmod/lang/en_us.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,5 +31,6 @@
3131
"generic.upload": "Upload",
3232
"generic.upload.tooltip": "Upload screenshot to the guild",
3333
"generic.upload_image_failed": "Failed to upload image: %s",
34-
"generic.uploading": "Uploading..."
34+
"generic.uploading": "Uploading...",
35+
"generic.data_is_empty": "Data is empty"
3536
}

common/src/main/resources/assets/interchatmod/lang/ja_jp.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,5 +31,6 @@
3131
"generic.upload": "アップロード",
3232
"generic.upload.tooltip": "スクリーンショットをギルドにアップロードする",
3333
"generic.upload_image_failed": "画像のアップロードに失敗しました: %s",
34-
"generic.uploading": "アップロード中..."
34+
"generic.uploading": "アップロード中...",
35+
"generic.data_is_empty": "データが空です"
3536
}

fabric-1.16/src/main/java/net/azisaba/interchatmod/fabric/Commands.java

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@
66
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
77
import net.azisaba.interchatmod.common.model.Guild;
88
import net.azisaba.interchatmod.common.model.GuildMember;
9+
import net.azisaba.interchatmod.common.util.ClipboardUtil;
910
import net.azisaba.interchatmod.common.util.Constants;
11+
import net.azisaba.interchatmod.common.util.function.IOSupplier;
1012
import net.fabricmc.fabric.api.client.command.v1.ClientCommandManager;
1113
import net.fabricmc.fabric.api.client.command.v1.FabricClientCommandSource;
1214
import net.minecraft.client.MinecraftClient;
@@ -205,7 +207,7 @@ public static LiteralArgumentBuilder<FabricClientCommandSource> builderGuild() {
205207
)
206208
)
207209
)
208-
.then(literal("upload_image")
210+
.then(literal("uploadimage")
209211
.then(argument("uuid", StringArgumentType.string())
210212
.executes(ctx -> executeUploadImage(ctx.getSource(), StringArgumentType.getString(ctx, "uuid")))
211213
)
@@ -306,18 +308,18 @@ private static int executeChat(FabricClientCommandSource source, String guildNam
306308
return 1;
307309
}
308310

309-
private static int executeUploadImage(FabricClientCommandSource source, String uuid) {
310-
File image = Mod.images.get(UUID.fromString(uuid));
311-
if (image == null) {
312-
return 0;
313-
}
311+
private static void uploadImage(FabricClientCommandSource source, IOSupplier<byte[]> dataSupplier) {
314312
source.sendFeedback(new TranslatableText("generic.uploading").formatted(Formatting.GRAY));
315313
Thread thread = new Thread(() -> {
316314
try {
317-
byte[] data = Files.readAllBytes(image.toPath());
315+
byte[] data = dataSupplier.get();
316+
if (data == null) {
317+
MinecraftClient.getInstance().execute(() -> source.sendError(new TranslatableText("generic.upload_image_failed", new TranslatableText("generic.data_is_empty")).formatted(Formatting.RED)));
318+
return;
319+
}
318320
JsonObject obj = GSON.fromJson(Mod.uploadImage(data), JsonObject.class);
319321
if (!obj.has("uuid")) {
320-
MinecraftClient.getInstance().execute(() -> source.sendError(new TranslatableText("generic.upload_image_failed", new LiteralText(obj.toString()).formatted(Formatting.RED))));
322+
MinecraftClient.getInstance().execute(() -> source.sendError(new TranslatableText("generic.upload_image_failed", new LiteralText(obj.toString())).formatted(Formatting.RED)));
321323
return;
322324
}
323325
String imageUuid = obj.get("uuid").getAsString();
@@ -328,6 +330,18 @@ private static int executeUploadImage(FabricClientCommandSource source, String u
328330
});
329331
thread.setName("InterChat Upload Image Thread");
330332
thread.start();
333+
}
334+
335+
private static int executeUploadImage(FabricClientCommandSource source, String uuid) {
336+
if (uuid == null) {
337+
uploadImage(source, ClipboardUtil::getImageFromClipboard);
338+
return 1;
339+
}
340+
File image = Mod.images.get(UUID.fromString(uuid));
341+
if (image == null) {
342+
return 0;
343+
}
344+
uploadImage(source, () -> Files.readAllBytes(image.toPath()));
331345
return 1;
332346
}
333347

fabric-1.17/src/main/java/net/azisaba/interchatmod/fabric/Commands.java

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@
66
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
77
import net.azisaba.interchatmod.common.model.Guild;
88
import net.azisaba.interchatmod.common.model.GuildMember;
9+
import net.azisaba.interchatmod.common.util.ClipboardUtil;
910
import net.azisaba.interchatmod.common.util.Constants;
11+
import net.azisaba.interchatmod.common.util.function.IOSupplier;
1012
import net.fabricmc.fabric.api.client.command.v1.FabricClientCommandSource;
1113
import net.minecraft.client.MinecraftClient;
1214
import net.minecraft.command.CommandSource;
@@ -203,10 +205,11 @@ public static LiteralArgumentBuilder<FabricClientCommandSource> builderGuild() {
203205
)
204206
)
205207
)
206-
.then(literal("upload_image")
208+
.then(literal("uploadimage")
207209
.then(argument("uuid", StringArgumentType.string())
208210
.executes(ctx -> executeUploadImage(ctx.getSource(), StringArgumentType.getString(ctx, "uuid")))
209211
)
212+
.executes(ctx -> executeUploadImage(ctx.getSource(), null))
210213
)
211214
;
212215
}
@@ -304,18 +307,18 @@ private static int executeChat(FabricClientCommandSource source, String guildNam
304307
return 1;
305308
}
306309

307-
private static int executeUploadImage(FabricClientCommandSource source, String uuid) {
308-
File image = Mod.images.get(UUID.fromString(uuid));
309-
if (image == null) {
310-
return 0;
311-
}
310+
private static void uploadImage(FabricClientCommandSource source, IOSupplier<byte[]> dataSupplier) {
312311
source.sendFeedback(new TranslatableText("generic.uploading").formatted(Formatting.GRAY));
313312
Thread thread = new Thread(() -> {
314313
try {
315-
byte[] data = Files.readAllBytes(image.toPath());
314+
byte[] data = dataSupplier.get();
315+
if (data == null) {
316+
MinecraftClient.getInstance().execute(() -> source.sendError(new TranslatableText("generic.upload_image_failed", new TranslatableText("generic.data_is_empty")).formatted(Formatting.RED)));
317+
return;
318+
}
316319
JsonObject obj = GSON.fromJson(Mod.uploadImage(data), JsonObject.class);
317320
if (!obj.has("uuid")) {
318-
MinecraftClient.getInstance().execute(() -> source.sendError(new TranslatableText("generic.upload_image_failed", new LiteralText(obj.toString()).formatted(Formatting.RED))));
321+
MinecraftClient.getInstance().execute(() -> source.sendError(new TranslatableText("generic.upload_image_failed", new LiteralText(obj.toString())).formatted(Formatting.RED)));
319322
return;
320323
}
321324
String imageUuid = obj.get("uuid").getAsString();
@@ -326,6 +329,18 @@ private static int executeUploadImage(FabricClientCommandSource source, String u
326329
});
327330
thread.setName("InterChat Upload Image Thread");
328331
thread.start();
332+
}
333+
334+
private static int executeUploadImage(FabricClientCommandSource source, String uuid) {
335+
if (uuid == null) {
336+
uploadImage(source, ClipboardUtil::getImageFromClipboard);
337+
return 1;
338+
}
339+
File image = Mod.images.get(UUID.fromString(uuid));
340+
if (image == null) {
341+
return 0;
342+
}
343+
uploadImage(source, () -> Files.readAllBytes(image.toPath()));
329344
return 1;
330345
}
331346

fabric-1.18/src/main/java/net/azisaba/interchatmod/fabric/Commands.java

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@
66
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
77
import net.azisaba.interchatmod.common.model.Guild;
88
import net.azisaba.interchatmod.common.model.GuildMember;
9+
import net.azisaba.interchatmod.common.util.ClipboardUtil;
910
import net.azisaba.interchatmod.common.util.Constants;
11+
import net.azisaba.interchatmod.common.util.function.IOSupplier;
1012
import net.fabricmc.fabric.api.client.command.v1.FabricClientCommandSource;
1113
import net.minecraft.client.MinecraftClient;
1214
import net.minecraft.command.CommandSource;
@@ -203,10 +205,11 @@ public static LiteralArgumentBuilder<FabricClientCommandSource> builderGuild() {
203205
)
204206
)
205207
)
206-
.then(literal("upload_image")
208+
.then(literal("uploadimage")
207209
.then(argument("uuid", StringArgumentType.string())
208210
.executes(ctx -> executeUploadImage(ctx.getSource(), StringArgumentType.getString(ctx, "uuid")))
209211
)
212+
.executes(ctx -> executeUploadImage(ctx.getSource(), null))
210213
)
211214
;
212215
}
@@ -304,18 +307,18 @@ private static int executeChat(FabricClientCommandSource source, String guildNam
304307
return 1;
305308
}
306309

307-
private static int executeUploadImage(FabricClientCommandSource source, String uuid) {
308-
File image = Mod.images.get(UUID.fromString(uuid));
309-
if (image == null) {
310-
return 0;
311-
}
310+
private static void uploadImage(FabricClientCommandSource source, IOSupplier<byte[]> dataSupplier) {
312311
source.sendFeedback(new TranslatableText("generic.uploading").formatted(Formatting.GRAY));
313312
Thread thread = new Thread(() -> {
314313
try {
315-
byte[] data = Files.readAllBytes(image.toPath());
314+
byte[] data = dataSupplier.get();
315+
if (data == null) {
316+
MinecraftClient.getInstance().execute(() -> source.sendError(new TranslatableText("generic.upload_image_failed", new TranslatableText("generic.data_is_empty")).formatted(Formatting.RED)));
317+
return;
318+
}
316319
JsonObject obj = GSON.fromJson(Mod.uploadImage(data), JsonObject.class);
317320
if (!obj.has("uuid")) {
318-
MinecraftClient.getInstance().execute(() -> source.sendError(new TranslatableText("generic.upload_image_failed", new LiteralText(obj.toString()).formatted(Formatting.RED))));
321+
MinecraftClient.getInstance().execute(() -> source.sendError(new TranslatableText("generic.upload_image_failed", new LiteralText(obj.toString())).formatted(Formatting.RED)));
319322
return;
320323
}
321324
String imageUuid = obj.get("uuid").getAsString();
@@ -326,6 +329,18 @@ private static int executeUploadImage(FabricClientCommandSource source, String u
326329
});
327330
thread.setName("InterChat Upload Image Thread");
328331
thread.start();
332+
}
333+
334+
private static int executeUploadImage(FabricClientCommandSource source, String uuid) {
335+
if (uuid == null) {
336+
uploadImage(source, ClipboardUtil::getImageFromClipboard);
337+
return 1;
338+
}
339+
File image = Mod.images.get(UUID.fromString(uuid));
340+
if (image == null) {
341+
return 0;
342+
}
343+
uploadImage(source, () -> Files.readAllBytes(image.toPath()));
329344
return 1;
330345
}
331346

fabric-1.19/src/main/java/net/azisaba/interchatmod/fabric/Commands.java

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@
66
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
77
import net.azisaba.interchatmod.common.model.Guild;
88
import net.azisaba.interchatmod.common.model.GuildMember;
9+
import net.azisaba.interchatmod.common.util.ClipboardUtil;
910
import net.azisaba.interchatmod.common.util.Constants;
11+
import net.azisaba.interchatmod.common.util.function.IOSupplier;
1012
import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource;
1113
import net.minecraft.client.MinecraftClient;
1214
import net.minecraft.command.CommandSource;
@@ -206,10 +208,11 @@ public static LiteralArgumentBuilder<FabricClientCommandSource> builderGuild() {
206208
)
207209
)
208210
)
209-
.then(literal("upload_image")
211+
.then(literal("uploadimage")
210212
.then(argument("uuid", StringArgumentType.string())
211213
.executes(ctx -> executeUploadImage(ctx.getSource(), StringArgumentType.getString(ctx, "uuid")))
212214
)
215+
.executes(ctx -> executeUploadImage(ctx.getSource(), null))
213216
)
214217
;
215218
}
@@ -307,18 +310,18 @@ private static int executeChat(FabricClientCommandSource source, String guildNam
307310
return 1;
308311
}
309312

310-
private static int executeUploadImage(FabricClientCommandSource source, String uuid) {
311-
File image = Mod.images.get(UUID.fromString(uuid));
312-
if (image == null) {
313-
return 0;
314-
}
313+
private static void uploadImage(FabricClientCommandSource source, IOSupplier<byte[]> dataSupplier) {
315314
source.sendFeedback(Text.translatable("generic.uploading").formatted(Formatting.GRAY));
316315
Thread thread = new Thread(() -> {
317316
try {
318-
byte[] data = Files.readAllBytes(image.toPath());
317+
byte[] data = dataSupplier.get();
318+
if (data == null) {
319+
MinecraftClient.getInstance().execute(() -> source.sendError(Text.translatable("generic.upload_image_failed", Text.translatable("generic.data_is_empty")).formatted(Formatting.RED)));
320+
return;
321+
}
319322
JsonObject obj = GSON.fromJson(Mod.uploadImage(data), JsonObject.class);
320323
if (!obj.has("uuid")) {
321-
MinecraftClient.getInstance().execute(() -> source.sendError(Text.translatable("generic.upload_image_failed", Text.literal(obj.toString()).formatted(Formatting.RED))));
324+
MinecraftClient.getInstance().execute(() -> source.sendError(Text.translatable("generic.upload_image_failed", Text.literal(obj.toString())).formatted(Formatting.RED)));
322325
return;
323326
}
324327
String imageUuid = obj.get("uuid").getAsString();
@@ -329,6 +332,18 @@ private static int executeUploadImage(FabricClientCommandSource source, String u
329332
});
330333
thread.setName("InterChat Upload Image Thread");
331334
thread.start();
335+
}
336+
337+
private static int executeUploadImage(FabricClientCommandSource source, String uuid) {
338+
if (uuid == null) {
339+
uploadImage(source, ClipboardUtil::getImageFromClipboard);
340+
return 1;
341+
}
342+
File image = Mod.images.get(UUID.fromString(uuid));
343+
if (image == null) {
344+
return 0;
345+
}
346+
uploadImage(source, () -> Files.readAllBytes(image.toPath()));
332347
return 1;
333348
}
334349

fabric-1.20/src/main/java/net/azisaba/interchatmod/fabric/Commands.java

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@
66
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
77
import net.azisaba.interchatmod.common.model.Guild;
88
import net.azisaba.interchatmod.common.model.GuildMember;
9+
import net.azisaba.interchatmod.common.util.ClipboardUtil;
910
import net.azisaba.interchatmod.common.util.Constants;
11+
import net.azisaba.interchatmod.common.util.function.IOSupplier;
1012
import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource;
1113
import net.minecraft.client.MinecraftClient;
1214
import net.minecraft.command.CommandSource;
@@ -206,10 +208,11 @@ public static LiteralArgumentBuilder<FabricClientCommandSource> builderGuild() {
206208
)
207209
)
208210
)
209-
.then(literal("upload_image")
211+
.then(literal("uploadimage")
210212
.then(argument("uuid", StringArgumentType.string())
211213
.executes(ctx -> executeUploadImage(ctx.getSource(), StringArgumentType.getString(ctx, "uuid")))
212214
)
215+
.executes(ctx -> executeUploadImage(ctx.getSource(), null))
213216
)
214217
;
215218
}
@@ -307,18 +310,18 @@ private static int executeChat(FabricClientCommandSource source, String guildNam
307310
return 1;
308311
}
309312

310-
private static int executeUploadImage(FabricClientCommandSource source, String uuid) {
311-
File image = Mod.images.get(UUID.fromString(uuid));
312-
if (image == null) {
313-
return 0;
314-
}
313+
private static void uploadImage(FabricClientCommandSource source, IOSupplier<byte[]> dataSupplier) {
315314
source.sendFeedback(Text.translatable("generic.uploading").formatted(Formatting.GRAY));
316315
Thread thread = new Thread(() -> {
317316
try {
318-
byte[] data = Files.readAllBytes(image.toPath());
317+
byte[] data = dataSupplier.get();
318+
if (data == null) {
319+
MinecraftClient.getInstance().execute(() -> source.sendError(Text.translatable("generic.upload_image_failed", Text.translatable("generic.data_is_empty")).formatted(Formatting.RED)));
320+
return;
321+
}
319322
JsonObject obj = GSON.fromJson(Mod.uploadImage(data), JsonObject.class);
320323
if (!obj.has("uuid")) {
321-
MinecraftClient.getInstance().execute(() -> source.sendError(Text.translatable("generic.upload_image_failed", Text.literal(obj.toString()).formatted(Formatting.RED))));
324+
MinecraftClient.getInstance().execute(() -> source.sendError(Text.translatable("generic.upload_image_failed", Text.literal(obj.toString())).formatted(Formatting.RED)));
322325
return;
323326
}
324327
String imageUuid = obj.get("uuid").getAsString();
@@ -329,6 +332,18 @@ private static int executeUploadImage(FabricClientCommandSource source, String u
329332
});
330333
thread.setName("InterChat Upload Image Thread");
331334
thread.start();
335+
}
336+
337+
private static int executeUploadImage(FabricClientCommandSource source, String uuid) {
338+
if (uuid == null) {
339+
uploadImage(source, ClipboardUtil::getImageFromClipboard);
340+
return 1;
341+
}
342+
File image = Mod.images.get(UUID.fromString(uuid));
343+
if (image == null) {
344+
return 0;
345+
}
346+
uploadImage(source, () -> Files.readAllBytes(image.toPath()));
332347
return 1;
333348
}
334349

0 commit comments

Comments
 (0)