diff --git a/apps/i2psnark/java/src/org/klomp/snark/I2PSnarkUtil.java b/apps/i2psnark/java/src/org/klomp/snark/I2PSnarkUtil.java index 7ca48f318a..77bad1339b 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/I2PSnarkUtil.java +++ b/apps/i2psnark/java/src/org/klomp/snark/I2PSnarkUtil.java @@ -65,6 +65,7 @@ public class I2PSnarkUtil { private int _maxConnections; private final File _tmpDir; private int _startupDelay; + private boolean _collapsePanels; private boolean _shouldUseOT; private boolean _shouldUseDHT; private boolean _enableRatings, _enableComments; @@ -77,6 +78,7 @@ public class I2PSnarkUtil { private static final int EEPGET_CONNECT_TIMEOUT = 45*1000; private static final int EEPGET_CONNECT_TIMEOUT_SHORT = 5*1000; public static final int DEFAULT_STARTUP_DELAY = 3; + public static final boolean DEFAULT_COLLAPSE_PANELS = true; public static final boolean DEFAULT_USE_OPENTRACKERS = true; public static final int MAX_CONNECTIONS = 24; // per torrent public static final String PROP_MAX_BW = "i2cp.outboundBytesPerSecond"; @@ -106,6 +108,7 @@ public class I2PSnarkUtil { _shouldUseOT = DEFAULT_USE_OPENTRACKERS; _openTrackers = Collections.emptyList(); _shouldUseDHT = DEFAULT_USE_DHT; + _collapsePanels = DEFAULT_COLLAPSE_PANELS; _enableRatings = _enableComments = true; _commentsName = ""; // This is used for both announce replies and .torrent file downloads, @@ -687,6 +690,16 @@ public class I2PSnarkUtil { return _enableRatings || _enableComments; } + /** @since 0.9.32 */ + public boolean collapsePanels() { + return _collapsePanels; + } + + /** @since 0.9.32 */ + public void setCollapsePanels(boolean yes) { + _collapsePanels = yes; + } + /** * Like DataHelper.toHexString but ensures no loss of leading zero bytes * @since 0.8.4 diff --git a/apps/i2psnark/java/src/org/klomp/snark/SnarkManager.java b/apps/i2psnark/java/src/org/klomp/snark/SnarkManager.java index aa35f90b42..b1a71d2017 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/SnarkManager.java +++ b/apps/i2psnark/java/src/org/klomp/snark/SnarkManager.java @@ -131,6 +131,8 @@ public class SnarkManager implements CompleteListener, ClientApp { public static final String RC_PROP_UNIVERSAL_THEMING = "routerconsole.universal.theme"; public static final String PROP_THEME = "i2psnark.theme"; public static final String DEFAULT_THEME = "ubergine"; + /** @since 0.9.32 */ + public static final String PROP_COLLAPSE_PANELS = "i2psnark.collapsePanels"; private static final String PROP_USE_OPENTRACKERS = "i2psnark.useOpentrackers"; public static final String PROP_OPENTRACKERS = "i2psnark.opentrackers"; public static final String PROP_PRIVATETRACKERS = "i2psnark.privatetrackers"; @@ -454,6 +456,17 @@ public class SnarkManager implements CompleteListener, ClientApp { return Boolean.parseBoolean(val); } + /** + * @return default true + * @since 0.9.32 + */ + public boolean isCollapsePanelsEnabled() { + String val = _config.getProperty(PROP_COLLAPSE_PANELS); + if (val == null) + return I2PSnarkUtil.DEFAULT_COLLAPSE_PANELS; + return Boolean.parseBoolean(val); + } + /**** public String linkPrefix() { return _config.getProperty(PROP_LINK_PREFIX, DEFAULT_LINK_PREFIX + getDataDir().getAbsolutePath() + File.separatorChar); @@ -798,6 +811,9 @@ public class SnarkManager implements CompleteListener, ClientApp { _config.setProperty(PROP_COMMENTS, "true"); if (!_config.containsKey(PROP_COMMENTS_NAME)) _config.setProperty(PROP_COMMENTS_NAME, ""); + if (!_config.containsKey(PROP_COLLAPSE_PANELS)) + _config.setProperty(PROP_COLLAPSE_PANELS, + Boolean.toString(I2PSnarkUtil.DEFAULT_COLLAPSE_PANELS)); updateConfig(); } @@ -871,7 +887,7 @@ public class SnarkManager implements CompleteListener, ClientApp { _util.setMaxUpBW(limits[1]); } } - + private void updateConfig() { String i2cpHost = _config.getProperty(PROP_I2CP_HOST); int i2cpPort = getInt(PROP_I2CP_PORT, 7654); @@ -908,6 +924,8 @@ public class SnarkManager implements CompleteListener, ClientApp { _util.setRatingsEnabled(Boolean.parseBoolean(_config.getProperty(PROP_RATINGS, "true"))); _util.setCommentsEnabled(Boolean.parseBoolean(_config.getProperty(PROP_COMMENTS, "true"))); _util.setCommentsName(_config.getProperty(PROP_COMMENTS_NAME, "")); + _util.setCollapsePanels(Boolean.parseBoolean(_config.getProperty(PROP_COLLAPSE_PANELS, + Boolean.toString(I2PSnarkUtil.DEFAULT_COLLAPSE_PANELS)))); File dd = getDataDir(); if (dd.isDirectory()) { if (!dd.canWrite()) @@ -918,7 +936,7 @@ public class SnarkManager implements CompleteListener, ClientApp { } initTrackerMap(); } - + private int getInt(String prop, int defaultVal) { String p = _config.getProperty(prop); try { @@ -929,29 +947,29 @@ public class SnarkManager implements CompleteListener, ClientApp { } return defaultVal; } - + /** * all params may be null or need trimming */ public void updateConfig(String dataDir, boolean filesPublic, boolean autoStart, boolean smartSort, String refreshDelay, - String startDelay, String pageSize, String seedPct, String eepHost, + String startDelay, String pageSize, String seedPct, String eepHost, String eepPort, String i2cpHost, String i2cpPort, String i2cpOpts, String upLimit, String upBW, boolean useOpenTrackers, boolean useDHT, String theme, - String lang, boolean enableRatings, boolean enableComments, String commentName) { + String lang, boolean enableRatings, boolean enableComments, String commentName, boolean collapsePanels) { synchronized(_configLock) { - locked_updateConfig(dataDir, filesPublic, autoStart, smartSort,refreshDelay, - startDelay, pageSize, seedPct, eepHost, - eepPort, i2cpHost, i2cpPort, i2cpOpts, - upLimit, upBW, useOpenTrackers, useDHT, theme, - lang, enableRatings, enableComments, commentName); + locked_updateConfig(dataDir, filesPublic, autoStart, smartSort, refreshDelay, + startDelay, pageSize, seedPct, eepHost, + eepPort, i2cpHost, i2cpPort, i2cpOpts, + upLimit, upBW, useOpenTrackers, useDHT, theme, + lang, enableRatings, enableComments, commentName, collapsePanels); } } private void locked_updateConfig(String dataDir, boolean filesPublic, boolean autoStart, boolean smartSort, String refreshDelay, - String startDelay, String pageSize, String seedPct, String eepHost, + String startDelay, String pageSize, String seedPct, String eepHost, String eepPort, String i2cpHost, String i2cpPort, String i2cpOpts, String upLimit, String upBW, boolean useOpenTrackers, boolean useDHT, String theme, - String lang, boolean enableRatings, boolean enableComments, String commentName) { + String lang, boolean enableRatings, boolean enableComments, String commentName, boolean collapsePanels) { boolean changed = false; boolean interruptMonitor = false; //if (eepHost != null) { @@ -996,7 +1014,7 @@ public class SnarkManager implements CompleteListener, ClientApp { } } } - + if (startDelay != null && _context.isRouterContext()) { int minutes = _util.getStartupDelay(); try { minutes = Integer.parseInt(startDelay.trim()); } catch (NumberFormatException nfe) {} @@ -1115,7 +1133,7 @@ public class SnarkManager implements CompleteListener, ClientApp { if (split > 0) oldOpts.put(pair.substring(0, split), pair.substring(split+1)); } - + boolean reconnect = i2cpHost != null && i2cpHost.trim().length() > 0 && port > 0 && (port != _util.getI2CPPort() || !oldI2CPHost.equals(i2cpHost)); if (reconnect || !oldOpts.equals(opts)) { @@ -1262,6 +1280,15 @@ public class SnarkManager implements CompleteListener, ClientApp { changed = true; } } + if (_util.collapsePanels() != collapsePanels) { + _config.setProperty(PROP_COLLAPSE_PANELS, Boolean.toString(collapsePanels)); + if (collapsePanels) + addMessage(_t("Collapsible panels enabled.")); + else + addMessage(_t("Collapsible panels disabled.")); + _util.setCollapsePanels(collapsePanels); + changed = true; + } if (changed) { saveConfig(); if (interruptMonitor) @@ -1485,7 +1512,7 @@ public class SnarkManager implements CompleteListener, ClientApp { fis.close(); fis = null; } catch (IOException e) {} - + // This test may be a duplicate, but not if we were called // from the DirMonitor, which only checks for dup torrent file names. Snark snark = getTorrentByInfoHash(info.getInfoHash()); diff --git a/apps/i2psnark/java/src/org/klomp/snark/web/I2PSnarkServlet.java b/apps/i2psnark/java/src/org/klomp/snark/web/I2PSnarkServlet.java index b21a8612de..a9fffb9107 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/web/I2PSnarkServlet.java +++ b/apps/i2psnark/java/src/org/klomp/snark/web/I2PSnarkServlet.java @@ -268,6 +268,9 @@ public class I2PSnarkServlet extends BasicServlet { return; } + boolean noCollapse = noCollapsePanels(req); + boolean collapsePanels = _manager.util().collapsePanels(); + setHTMLHeaders(resp); PrintWriter out = resp.getWriter(); out.write(DOCTYPE + "\n" + @@ -295,7 +298,7 @@ public class I2PSnarkServlet extends BasicServlet { String jsPfx = _context.isRouterContext() ? "" : ".resources"; String downMsg = _context.isRouterContext() ? _t("Router is down") : _t("I2PSnark has stopped"); // fallback to metarefresh when javascript is disabled - out.write("\n"); + out.write("\n"); out.write("\n" + "\n"); } } - out.write(HEADER_A + _themePath + HEADER_B + "\n"); + out.write(HEADER_A + _themePath + HEADER_B); + + // ...and inject CSS to display panels uncollapsed + if (noCollapse || !collapsePanels) { + out.write(HEADER_A + _themePath + HEADER_C); + } + out.write("\n"); + if (isConfigure || delay <= 0) out.write("
"); else @@ -381,9 +391,10 @@ public class I2PSnarkServlet extends BasicServlet { private static void setHTMLHeaders(HttpServletResponse resp) { resp.setCharacterEncoding("UTF-8"); resp.setContentType("text/html; charset=UTF-8"); - resp.setHeader("Cache-Control", "no-store, max-age=0, no-cache, must-revalidate"); + // "no-store, max-age=0" forces all our images to be reloaded on ajax refresh + resp.setHeader("Cache-Control", "max-age=86400, no-cache, must-revalidate"); resp.setHeader("Content-Security-Policy", "default-src 'self'; style-src 'self' 'unsafe-inline'; script-src 'self' 'unsafe-inline'"); - resp.setDateHeader("Expires", 0); + resp.setDateHeader("Expires", 86400); resp.setHeader("Pragma", "no-cache"); resp.setHeader("X-Frame-Options", "SAMEORIGIN"); resp.setHeader("X-XSS-Protection", "1; mode=block"); @@ -1190,10 +1201,11 @@ public class I2PSnarkServlet extends BasicServlet { boolean comments = req.getParameter("comments") != null; // commentsName is filtered in SnarkManager.updateConfig() String commentsName = req.getParameter("nofilter_commentsName"); + boolean collapsePanels = req.getParameter("collapsePanels") != null; _manager.updateConfig(dataDir, filesPublic, autoStart, smartSort, refreshDel, startupDel, pageSize, seedPct, eepHost, eepPort, i2cpHost, i2cpPort, i2cpOpts, upLimit, upBW, useOpenTrackers, useDHT, theme, - lang, ratings, comments, commentsName); + lang, ratings, comments, commentsName, collapsePanels); // update servlet try { setResourceBase(_manager.getDataDir()); @@ -2271,9 +2283,12 @@ public class I2PSnarkServlet extends BasicServlet { boolean useDHT = _manager.util().shouldUseDHT(); boolean useRatings = _manager.util().ratingsEnabled(); boolean useComments = _manager.util().commentsEnabled(); + boolean collapsePanels = _manager.util().collapsePanels(); //int seedPct = 0; - out.write("