From 0743b3e1acab14df5aaa75befabc810ece0adf87 Mon Sep 17 00:00:00 2001 From: CrushedPixel Date: Sat, 4 Jul 2015 17:13:02 +0200 Subject: [PATCH] Added Progress Bar and Cancel Button when downloading a Replay File from Replay Center (GuiReplayDownloading) | https://trello.com/c/1ZPhwmp8/ --- .../crushedpixel/replaymod/api/ApiClient.java | 38 ++++++- .../replaymod/gui/GuiConstants.java | 1 + .../replaymod/gui/online/GuiReplayCenter.java | 13 ++- .../gui/online/GuiReplayDownloading.java | 107 ++++++++++++++++++ .../registry/DownloadedFileHandler.java | 9 +- .../assets/replaymod/lang/en_US.lang | 3 + 6 files changed, 158 insertions(+), 13 deletions(-) create mode 100644 src/main/java/eu/crushedpixel/replaymod/gui/online/GuiReplayDownloading.java diff --git a/src/main/java/eu/crushedpixel/replaymod/api/ApiClient.java b/src/main/java/eu/crushedpixel/replaymod/api/ApiClient.java index 6a3f5fab..770682d3 100755 --- a/src/main/java/eu/crushedpixel/replaymod/api/ApiClient.java +++ b/src/main/java/eu/crushedpixel/replaymod/api/ApiClient.java @@ -8,6 +8,7 @@ import com.mojang.authlib.exceptions.AuthenticationException; import eu.crushedpixel.replaymod.api.replay.ReplayModApiMethods; import eu.crushedpixel.replaymod.api.replay.SearchQuery; import eu.crushedpixel.replaymod.api.replay.holders.*; +import eu.crushedpixel.replaymod.gui.elements.listeners.ProgressUpdateListener; import eu.crushedpixel.replaymod.online.authentication.AuthenticationHash; import net.minecraft.client.Minecraft; import org.apache.commons.io.FileUtils; @@ -106,21 +107,46 @@ public class ApiClient { FileUtils.copyURLToFile(url, target); } - public void downloadFile(String auth, int file, File target) throws IOException, ApiException { + private boolean cancelDownload = false; + + public void downloadFile(String auth, int file, File target, ProgressUpdateListener listener) throws IOException, ApiException { + cancelDownload = false; + QueryBuilder builder = new QueryBuilder(ReplayModApiMethods.download_file); builder.put("auth", auth); builder.put("id", file); String url = builder.toString(); URL website = new URL(url); HttpURLConnection con = (HttpURLConnection) website.openConnection(); + + int fileSize = con.getContentLength(); + InputStream is = con.getInputStream(); if(con.getResponseCode() == 200) { - OutputStream out = new FileOutputStream(target); + BufferedInputStream bin = new BufferedInputStream(is); + FileOutputStream fout = new FileOutputStream(target); try { - IOUtils.copy(is, out); + final byte data[] = new byte[1024]; + int count; + int read = 0; + while ((count = bin.read(data, 0, 1024)) != -1) { + if(cancelDownload) { + bin.close(); + fout.close(); + + FileUtils.deleteQuietly(target); + + return; + } + + fout.write(data, 0, count); + read += count; + listener.onProgressChanged((float)(read)/fileSize); + } } finally { - out.close(); + bin.close(); + fout.close(); } } else { JsonElement element = jsonParser.parse(IOUtils.toString(is)); @@ -135,6 +161,10 @@ public class ApiClient { } } + public void cancelDownload() { + this.cancelDownload = true; + } + public void rateFile(String auth, int file, Rating.RatingType rating) throws IOException, ApiException { QueryBuilder builder = new QueryBuilder(ReplayModApiMethods.rate_file); builder.put("auth", auth); diff --git a/src/main/java/eu/crushedpixel/replaymod/gui/GuiConstants.java b/src/main/java/eu/crushedpixel/replaymod/gui/GuiConstants.java index e40ae0e5..80a4eeb2 100755 --- a/src/main/java/eu/crushedpixel/replaymod/gui/GuiConstants.java +++ b/src/main/java/eu/crushedpixel/replaymod/gui/GuiConstants.java @@ -103,4 +103,5 @@ public class GuiConstants { public static final int REPLAY_SETTINGS_CLEARCALLBACK_ID = 9014; public static final int REPLAY_EDITING_CANCEL_BUTTON = 1234; + public static final int REPLAY_DOWNLOADING_CANCEL_BUTTON = 2345; } diff --git a/src/main/java/eu/crushedpixel/replaymod/gui/online/GuiReplayCenter.java b/src/main/java/eu/crushedpixel/replaymod/gui/online/GuiReplayCenter.java index 60115565..ea101367 100755 --- a/src/main/java/eu/crushedpixel/replaymod/gui/online/GuiReplayCenter.java +++ b/src/main/java/eu/crushedpixel/replaymod/gui/online/GuiReplayCenter.java @@ -233,12 +233,13 @@ public class GuiReplayCenter extends GuiScreen implements GuiYesNoCallback { if(info != null) { File f = ReplayMod.downloadedFileHandler.getFileForID(info.getId()); if(f == null) { - f = ReplayMod.downloadedFileHandler.downloadFileForID(info.getId()); - } - try { - ReplayHandler.startReplay(f); - } catch(Exception e) { - e.printStackTrace(); + mc.displayGuiScreen(new GuiReplayDownloading(info)); + } else { + try { + ReplayHandler.startReplay(f); + } catch(Exception e) { + e.printStackTrace(); + } } } } else if(button.id == GuiConstants.CENTER_FAV_REPLAY_BUTTON) { diff --git a/src/main/java/eu/crushedpixel/replaymod/gui/online/GuiReplayDownloading.java b/src/main/java/eu/crushedpixel/replaymod/gui/online/GuiReplayDownloading.java new file mode 100644 index 00000000..2894d053 --- /dev/null +++ b/src/main/java/eu/crushedpixel/replaymod/gui/online/GuiReplayDownloading.java @@ -0,0 +1,107 @@ +package eu.crushedpixel.replaymod.gui.online; + +import com.mojang.realmsclient.gui.ChatFormatting; +import eu.crushedpixel.replaymod.ReplayMod; +import eu.crushedpixel.replaymod.api.replay.holders.FileInfo; +import eu.crushedpixel.replaymod.gui.GuiConstants; +import eu.crushedpixel.replaymod.gui.elements.GuiProgressBar; +import eu.crushedpixel.replaymod.gui.elements.listeners.ProgressUpdateListener; +import eu.crushedpixel.replaymod.replay.ReplayHandler; +import net.minecraft.client.gui.GuiButton; +import net.minecraft.client.gui.GuiScreen; +import net.minecraft.client.resources.I18n; + +import java.awt.*; +import java.io.File; +import java.io.IOException; + +public class GuiReplayDownloading extends GuiScreen implements ProgressUpdateListener { + + private String title; + private String pleaseWait; + private String cancelCallback; + + private boolean callback = false; + + private boolean initialized = false; + + private GuiProgressBar progressBar; + private GuiButton cancelButton; + + public GuiReplayDownloading(final FileInfo fileInfo) { + pleaseWait = I18n.format("replaymod.gui.viewer.download.message", ChatFormatting.UNDERLINE+fileInfo.getName()+ChatFormatting.RESET); + new Thread(new Runnable() { + @Override + public void run() { + final File replayFile = ReplayMod.downloadedFileHandler.downloadFileForID(fileInfo.getId(), GuiReplayDownloading.this); + if(replayFile.exists()) { + mc.addScheduledTask(new Runnable() { + @Override + public void run() { + try { + ReplayHandler.startReplay(replayFile); + } catch(Exception e) { + e.printStackTrace(); + } + } + }); + } + } + }).start(); + } + + @Override + public void initGui() { + if(!initialized) { + title = I18n.format("replaymod.gui.viewer.download.title"); + cancelCallback = I18n.format("replaymod.gui.rendering.cancel.callback"); + + progressBar = new GuiProgressBar(); + cancelButton = new GuiButton(GuiConstants.REPLAY_DOWNLOADING_CANCEL_BUTTON, 0, 0, I18n.format("gui.cancel")); + } + + progressBar.setBounds(10, this.height-30-20, this.width-20, 20); + + cancelButton.xPosition = this.width - 5 - 150; + cancelButton.width = 150; + cancelButton.yPosition = this.height - 5 - 20; + + buttonList.add(cancelButton); + + initialized = true; + } + + @Override + public void drawScreen(int mouseX, int mouseY, float partialTicks) { + this.drawDefaultBackground(); + super.drawScreen(mouseX, mouseY, partialTicks); + this.drawCenteredString(mc.fontRendererObj, title, this.width / 2, 20, Color.WHITE.getRGB()); + this.drawCenteredString(mc.fontRendererObj, pleaseWait, this.width / 2, 40, Color.WHITE.getRGB()); + + progressBar.drawProgressBar(); + } + + @Override + protected void actionPerformed(GuiButton button) throws IOException { + if(!button.enabled) return; + if(button.id == GuiConstants.REPLAY_DOWNLOADING_CANCEL_BUTTON) { + if(!callback) { + callback = true; + button.displayString = cancelCallback; + } else { + ReplayMod.apiClient.cancelDownload(); + mc.displayGuiScreen(new GuiReplayCenter()); + } + } + } + + @Override + public void onProgressChanged(float progress) { + if(progressBar != null) progressBar.setProgress(progress); + } + + @Override + public void onProgressChanged(float progress, String progressString) { + onProgressChanged(progress); + } +} diff --git a/src/main/java/eu/crushedpixel/replaymod/registry/DownloadedFileHandler.java b/src/main/java/eu/crushedpixel/replaymod/registry/DownloadedFileHandler.java index ce1040eb..186c3baa 100644 --- a/src/main/java/eu/crushedpixel/replaymod/registry/DownloadedFileHandler.java +++ b/src/main/java/eu/crushedpixel/replaymod/registry/DownloadedFileHandler.java @@ -1,6 +1,7 @@ package eu.crushedpixel.replaymod.registry; import eu.crushedpixel.replaymod.ReplayMod; +import eu.crushedpixel.replaymod.gui.elements.listeners.ProgressUpdateListener; import eu.crushedpixel.replaymod.online.authentication.AuthenticationHandler; import eu.crushedpixel.replaymod.utils.ReplayFile; import org.apache.commons.io.FileUtils; @@ -51,15 +52,17 @@ public class DownloadedFileHandler { return downloadedFiles.get(id); } - public File downloadFileForID(int id) { + public File downloadFileForID(int id, ProgressUpdateListener progressUpdateListener) { File f = getFileForID(id); if(f != null) return f; f = generateFileForID(id); try { - ReplayMod.apiClient.downloadFile(AuthenticationHandler.getKey(), id, f); - addToIndex(id); + ReplayMod.apiClient.downloadFile(AuthenticationHandler.getKey(), id, f, progressUpdateListener); + if(f.exists()) { + addToIndex(id); + } } catch(Exception e) { e.printStackTrace(); } diff --git a/src/main/resources/assets/replaymod/lang/en_US.lang b/src/main/resources/assets/replaymod/lang/en_US.lang index 69c59b00..5a23475d 100644 --- a/src/main/resources/assets/replaymod/lang/en_US.lang +++ b/src/main/resources/assets/replaymod/lang/en_US.lang @@ -135,6 +135,9 @@ replaymod.gui.viewer.delete.linea=Are you sure you want to delete this replay? #The Replay file name is inserted before the following string, e.g. "Some Replay will be lost forever!..." replaymod.gui.viewer.delete.lineb=will be lost forever! (a long time!) +replaymod.gui.viewer.download.title=Downloading Replay File... +replaymod.gui.viewer.download.message=Please wait while %1$s is being downloaded. + replaymod.gui.login.noacc=Don't have an account yet? #Replay Center GUI