Skip to content

Dynamic splash image (take 2) #9935

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 15 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions app/build.xml
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@
<copy todir="test-bin" overwrite="true" verbose="true">
<fileset dir="test" includes="**/*.zip" />
<fileset dir="test" includes="**/*.txt" />
<fileset dir="test" includes="**/*.txt.asc" />
<fileset dir="test" includes="**/*.properties" />
<fileset dir="test" includes="**/*.ino" />
<fileset dir="test" includes="**/*.json*" />
Expand Down
21 changes: 20 additions & 1 deletion app/src/cc/arduino/view/SplashScreenHelper.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,18 @@

package cc.arduino.view;

import java.awt.*;
import java.awt.Color;
import java.awt.FontMetrics;
import java.awt.Graphics2D;
import java.awt.SplashScreen;
import java.awt.Toolkit;
import java.awt.geom.Rectangle2D;
import java.io.File;
import java.io.IOException;
import java.util.Map;

import processing.app.Theme;
import processing.app.UpdateCheck;

public class SplashScreenHelper {

Expand All @@ -54,6 +61,10 @@ public SplashScreenHelper(SplashScreen splash) {
if (splash != null) {
Toolkit tk = Toolkit.getDefaultToolkit();
desktopHints = (Map) tk.getDesktopProperty("awt.font.desktophints");
File image = UpdateCheck.getUpdatedSplashImageFile();
if (image != null) {
splashImage(image);
}
} else {
desktopHints = null;
}
Expand Down Expand Up @@ -120,4 +131,12 @@ private void printText(String str) {
System.err.println(str);
}

public void splashImage(File f) {
try {
splash.setImageURL(f.toURI().toURL());
} catch (NullPointerException | IllegalStateException | IOException e) {
e.printStackTrace();
}
}

}
14 changes: 11 additions & 3 deletions app/src/processing/app/Base.java
Original file line number Diff line number Diff line change
Expand Up @@ -296,7 +296,7 @@ public Base(String[] args) throws Exception {
pdeKeywords = new PdeKeywords();
pdeKeywords.reload();

final GPGDetachedSignatureVerifier gpgDetachedSignatureVerifier = new GPGDetachedSignatureVerifier();
final SignatureVerifier gpgDetachedSignatureVerifier = new SignatureVerifier();
contributionInstaller = new ContributionInstaller(BaseNoGui.getPlatform(), gpgDetachedSignatureVerifier);
libraryInstaller = new LibraryInstaller(BaseNoGui.getPlatform(), gpgDetachedSignatureVerifier);

Expand Down Expand Up @@ -1886,8 +1886,16 @@ static public String[] headerListFromIncludePath(File path) throws IOException {
*/
@SuppressWarnings("serial")
public void handleAbout() {
final Image image = Theme.getLibImage("about", activeEditor,
Theme.scale(475), Theme.scale(300));
Image image;
File f = UpdateCheck.getUpdatedSplashImageFile();
if (f != null) {
Toolkit tk = Toolkit.getDefaultToolkit();
Image unscaled = tk.getImage(f.getAbsolutePath());
image = Theme.scale(unscaled, activeEditor);
} else {
image = Theme.getLibImage("about", activeEditor, //
Theme.scale(475), Theme.scale(300));
}
final Window window = new Window(activeEditor) {
public void paint(Graphics graphics) {
Graphics2D g = Theme.setupGraphics2D(graphics);
Expand Down
35 changes: 27 additions & 8 deletions app/src/processing/app/Theme.java
Original file line number Diff line number Diff line change
Expand Up @@ -575,23 +575,42 @@ static public Image getLibImage(String filename, Component who, int width,
image = tk.getImage(imageFile.getUrl());
}

image = rescaleImage(image, who, width, height);

return image;
}

public static Image rescaleImage(Image image, Component who, int width, int height) {
MediaTracker tracker = new MediaTracker(who);
try {
tracker.addImage(image, 0);
tracker.waitForAll();
} catch (InterruptedException e) {
}
if (image.getWidth(null) == width && image.getHeight(null) == height) {
return image;
}

if (image.getWidth(null) != width || image.getHeight(null) != height) {
image = image.getScaledInstance(width, height, Image.SCALE_SMOOTH);
try {
tracker.addImage(image, 1);
tracker.waitForAll();
} catch (InterruptedException e) {
}
Image rescaled = image.getScaledInstance(width, height, Image.SCALE_SMOOTH);
try {
tracker.addImage(rescaled, 1);
tracker.waitForAll();
} catch (InterruptedException e) {
}
return rescaled;
}

return image;
public static Image scale(Image image, Component who) {
MediaTracker tracker = new MediaTracker(who);
try {
tracker.addImage(image, 0);
tracker.waitForAll();
} catch (InterruptedException e) {
}

int w = image.getWidth(null);
int h = image.getHeight(null);
return rescaleImage(image, who, scale(w), scale(h));
}

/**
Expand Down
151 changes: 115 additions & 36 deletions app/src/processing/app/UpdateCheck.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,18 +22,29 @@

package processing.app;

import org.apache.commons.compress.utils.IOUtils;
import processing.app.legacy.PApplet;
import static processing.app.I18n.tr;

import javax.swing.*;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLEncoder;
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;
import java.util.List;
import java.util.Random;
import java.util.stream.Collectors;

import static processing.app.I18n.tr;
import javax.swing.JOptionPane;

import org.apache.commons.compress.utils.IOUtils;

import cc.arduino.contributions.SignatureVerifier;
import cc.arduino.utils.FileHash;
import processing.app.legacy.PApplet;


/**
Expand All @@ -51,32 +62,88 @@
*/
public class UpdateCheck implements Runnable {
Base base;
String downloadURL = tr("https://www.arduino.cc/latest.txt");

static final long ONE_DAY = 24 * 60 * 60 * 1000;


public UpdateCheck(Base base) {
Thread thread = new Thread(this);
this.base = base;
thread.start();
}

final long ONE_DAY = 24 * 60 * 60 * 1000;

public void run() {
//System.out.println("checking for updates...");
// Ensure updates-check are made only once per day
Long when = PreferencesData.getLong("update.last");
long now = System.currentTimeMillis();
if (when != null && (now - when) < ONE_DAY) {
// don't annoy the shit outta people
return;
}
PreferencesData.setLong("update.last", now);

checkForIDEUpdates();

long id;
String idString = PreferencesData.get("update.id");
if (idString != null) {
id = Long.parseLong(idString);
} else {
checkForSplashImageUpdates();
}

private void checkForSplashImageUpdates() {
File tmp = null;
try {
tmp = File.createTempFile("arduino_splash_update", ".txt.asc");
// Check for updates of the splash screen
downloadFileFromURL("https://go.bug.st/latest_splash.txt.asc", tmp);
SignatureVerifier verifier = new SignatureVerifier();
if (!verifier.verifyCleartextSignature(tmp)) {
return;
}
String[] lines = verifier.extractTextFromCleartextSignature(tmp);
if (lines.length < 2) {
return;
}
String newSplashUrl = lines[0];
String checksum = lines[1];

// if the splash image has been changed download the new file
String oldSplashUrl = PreferencesData.get("splash.imageurl");
if (!newSplashUrl.equals(oldSplashUrl)) {
File tmpFile = BaseNoGui.getSettingsFile("splash.png.tmp");
downloadFileFromURL(newSplashUrl, tmpFile);

String algo = checksum.split(":")[0];
String crc = FileHash.hash(tmpFile, algo);
if (!crc.equalsIgnoreCase(checksum)) {
return;
}

File destFile = BaseNoGui.getSettingsFile("splash.png");
Files.move(tmpFile.toPath(), destFile.toPath(),
StandardCopyOption.REPLACE_EXISTING);
PreferencesData.set("splash.imageurl", newSplashUrl);
}

// extend expiration by 24h
long now = System.currentTimeMillis();
PreferencesData.setLong("splash.expire", now + ONE_DAY);
} catch (Exception e) {
// e.printStackTrace();
} finally {
if (tmp != null) {
tmp.delete();
}
}
}

private void checkForIDEUpdates() {
// Set update id
Long id = PreferencesData.getLong("update.id");
if (id == null) {
// generate a random id in case none exists yet
Random r = new Random();
id = r.nextLong();
PreferencesData.set("update.id", String.valueOf(id));
PreferencesData.setLong("update.id", id);
}

// Check for updates of the IDE
try {
String info;
info = URLEncoder.encode(id + "\t" +
Expand All @@ -87,18 +154,7 @@ public void run() {
System.getProperty("os.version") + "\t" +
System.getProperty("os.arch"), "UTF-8");

int latest = readInt(downloadURL + "?" + info);

String lastString = PreferencesData.get("update.last");
long now = System.currentTimeMillis();
if (lastString != null) {
long when = Long.parseLong(lastString);
if (now - when < ONE_DAY) {
// don't annoy the shit outta people
return;
}
}
PreferencesData.set("update.last", String.valueOf(now));
int latest = readIntFromURL("https://www.arduino.cc/latest.txt?" + info);

String prompt =
tr("A new version of Arduino is available,\n" +
Expand All @@ -116,7 +172,7 @@ public void run() {
options,
options[0]);
if (result == JOptionPane.YES_OPTION) {
Base.openURL(tr("https://www.arduino.cc/en/Main/Software"));
Base.openURL("https://www.arduino.cc/en/Main/Software");
}
}
}
Expand All @@ -126,15 +182,38 @@ public void run() {
}
}

public static File getUpdatedSplashImageFile() {
if (PreferencesData.has("splash.expire")) {
Long expire = PreferencesData.getLong("splash.expire");
long now = System.currentTimeMillis();
if (expire != null && now < expire) {
File f = BaseNoGui.getSettingsFile("splash.png");
if (f.isFile()) {
return f;
}
}
}
return null;
}

protected int readInt(String filename) throws IOException {
URL url = new URL(filename);
BufferedReader reader = null;
try {
reader = new BufferedReader(new InputStreamReader(url.openStream()));
return Integer.parseInt(reader.readLine());
} finally {
IOUtils.closeQuietly(reader);
protected int readIntFromURL(String _url) throws Exception {
List<String> lines = readFileFromURL(_url);
return Integer.parseInt(lines.get(0));
}

protected List<String> readFileFromURL(String _url) throws IOException {
URL url = new URL(_url);
try (BufferedReader in = new BufferedReader(new InputStreamReader(url.openStream()));) {
return in.lines().collect(Collectors.toList());
}
}

protected void downloadFileFromURL(String _url, File dest) throws IOException {
URL url = new URL(_url);
try (InputStream in = url.openStream()) {
try (FileOutputStream out = new FileOutputStream(dest)) {
IOUtils.copy(in, out);
}
}
}
}
Loading