begin template system change
authorNiki Roo <niki@nikiroo.be>
Tue, 19 May 2020 19:20:52 +0000 (21:20 +0200)
committerNiki Roo <niki@nikiroo.be>
Tue, 19 May 2020 19:20:52 +0000 (21:20 +0200)
src/be/nikiroo/fanfix/library/Template.java [new file with mode: 0644]
src/be/nikiroo/fanfix/library/WebLibraryServerHtml.java
src/be/nikiroo/fanfix/library/web/templates/WebLibraryServerTemplates.java
src/be/nikiroo/fanfix/library/web/templates/index.html [new file with mode: 0644]
src/be/nikiroo/fanfix/library/web/templates/viewer.html [new file with mode: 0644]

diff --git a/src/be/nikiroo/fanfix/library/Template.java b/src/be/nikiroo/fanfix/library/Template.java
new file mode 100644 (file)
index 0000000..e247e27
--- /dev/null
@@ -0,0 +1,113 @@
+package be.nikiroo.fanfix.library;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import be.nikiroo.utils.IOUtils;
+import be.nikiroo.utils.StringUtils;
+import be.nikiroo.utils.streams.ReplaceInputStream;
+
+public class Template {
+       private Class<?> location;
+       private String name;
+
+       private Map<String, String> values = new HashMap<String, String>();
+       private Map<String, Template> valuesTemplate = new HashMap<String, Template>();
+       private Map<String, List<Template>> valuesTemplateList = new HashMap<String, List<Template>>();
+
+       public Template(Class<?> location, String name) {
+               this.location = location;
+               this.name = name;
+       }
+
+       public synchronized InputStream read() throws IOException {
+
+               String from[] = new String[values.size() + valuesTemplate.size()
+                               + valuesTemplateList.size()];
+               String to[] = new String[from.length];
+
+               int i = 0;
+
+               for (String key : values.keySet()) {
+                       from[i] = "${" + key + "}";
+                       to[i] = values.get(key);
+
+                       i++;
+               }
+               for (String key : valuesTemplate.keySet()) {
+                       InputStream value = valuesTemplate.get(key).read();
+                       try {
+                               from[i] = "${" + key + "}";
+                               to[i] = IOUtils.readSmallStream(value);
+                       } finally {
+                               value.close();
+                       }
+
+                       i++;
+               }
+               for (String key : valuesTemplateList.keySet()) {
+                       List<Template> templates = valuesTemplateList.get(key);
+                       StringBuilder value = new StringBuilder();
+                       for (Template template : templates) {
+                               InputStream valueOne = template.read();
+                               try {
+                                       value.append(IOUtils.readSmallStream(valueOne));
+                               } finally {
+                                       valueOne.close();
+                               }
+                       }
+                       from[i] = "${" + key + "}";
+                       to[i] = value.toString();
+
+                       i++;
+               }
+
+               InputStream in = IOUtils.openResource(location, name);
+               
+               //TODO: pending fix in replace stream
+               String data = IOUtils.readSmallStream(in);
+               in.close();
+               for(i = 0 ; i < from.length;i++) {
+                       data=data.replace(from[i], to[i]);
+               }
+               
+               //in = new ReplaceInputStream(in, from, to);
+               in = new ByteArrayInputStream(StringUtils.getBytes(data));
+               // END TODO
+               
+               return in;
+       }
+
+       public synchronized Template set(String key, String value) {
+               values.put(key, value);
+               valuesTemplate.remove(key);
+               valuesTemplateList.remove(key);
+               return this;
+       }
+
+       public synchronized Template set(String key, Template value) {
+               values.remove(key);
+               valuesTemplate.put(key, value);
+               valuesTemplateList.remove(key);
+               return this;
+       }
+
+       public synchronized Template set(String key, List<Template> value) {
+               values.remove(key);
+               valuesTemplate.remove(key);
+               valuesTemplateList.put(key, value);
+               return this;
+       }
+
+       @Override
+       public String toString() {
+               return String.format(
+                               "[Template for %s with (%d,%d,%d) value(s) to replace]", name,
+                               values.size(), valuesTemplate.size(),
+                               valuesTemplateList.size());
+       }
+}
index 69d8671736d7e2e4cf8c2922ca61358803f6bd2f..f3432c38cbdbc093941b2932e3817ea227754038 100644 (file)
@@ -5,6 +5,8 @@ import java.io.FileInputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.security.KeyStore;
+import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -36,6 +38,9 @@ abstract class WebLibraryServerHtml implements Runnable {
        private NanoHTTPD server;
        protected TraceHandler tracer = new TraceHandler();
 
+       WebLibraryServerTemplates templates = WebLibraryServerTemplates
+                       .getInstance();
+
        abstract protected WLoginResult login(String who, String cookie);
 
        abstract protected WLoginResult login(String who, String key,
@@ -346,9 +351,6 @@ abstract class WebLibraryServerHtml implements Runnable {
                        WLoginResult login) throws IOException {
                BasicLibrary lib = Instance.getInstance().getLibrary();
                MetaResultList result = new MetaResultList(metas(login));
-               StringBuilder builder = new StringBuilder();
-
-               builder.append(getTemplateIndexPreBanner(true));
 
                Map<String, String> params = session.getParms();
 
@@ -372,15 +374,13 @@ abstract class WebLibraryServerHtml implements Runnable {
 
                // TODO: javascript in realtime, using visible=false + hide [submit]
 
-               StringBuilder selects = new StringBuilder();
+               List<Template> selects = new ArrayList<Template>();
                boolean sourcesSel = false;
                boolean authorsSel = false;
                boolean tagsSel = false;
 
-               String selectTemplate = getTemplate("browser.select");
-
                if (!browser.isEmpty()) {
-                       StringBuilder options = new StringBuilder();
+                       List<Template> options = new ArrayList<Template>();
 
                        if (browser.equals("sources")) {
                                sourcesSel = true;
@@ -389,8 +389,8 @@ abstract class WebLibraryServerHtml implements Runnable {
                                // TODO: if 1 group -> no group
                                Map<String, List<String>> sources = result.getSourcesGrouped();
                                for (String source : sources.keySet()) {
-                                       options.append(
-                                                       getTemplateBrowserOption(source, source, browser2));
+                                       options.add(
+                                                       templates.browserOption(source, source, browser2));
                                }
                        } else if (browser.equals("authors")) {
                                authorsSel = true;
@@ -399,28 +399,23 @@ abstract class WebLibraryServerHtml implements Runnable {
                                // TODO: if 1 group -> no group
                                Map<String, List<String>> authors = result.getAuthorsGrouped();
                                for (String author : authors.keySet()) {
-                                       options.append(
-                                                       getTemplateBrowserOption(author, author, browser2));
+                                       options.add(
+                                                       templates.browserOption(author, author, browser2));
                                }
                        } else if (browser.equals("tags")) {
                                tagsSel = true;
                                filterTag = browser2.isEmpty() ? filterTag : browser2;
 
                                for (String tag : result.getTags()) {
-                                       options.append(
-                                                       getTemplateBrowserOption(tag, tag, browser2));
+                                       options.add(templates.browserOption(tag, tag, browser2));
                                }
                        }
 
-                       selects.append(selectTemplate //
-                                       .replace("${name}", "browser2") //
-                                       .replace("${value}", browser2) //
-                                       .replace("${options}", options.toString()) //
-                       );
+                       selects.add(templates.browserSelect("browser2", browser2, options));
                }
 
                if (!browser2.isEmpty()) {
-                       StringBuilder options = new StringBuilder();
+                       List<Template> options = new ArrayList<Template>();
 
                        if (browser.equals("sources")) {
                                filterSource = browser3.isEmpty() ? filterSource : browser3;
@@ -430,7 +425,7 @@ abstract class WebLibraryServerHtml implements Runnable {
                                if (sources != null && !sources.isEmpty()) {
                                        // TODO: single empty value
                                        for (String source : sources) {
-                                               options.append(getTemplateBrowserOption(source, source,
+                                               options.add(templates.browserOption(source, source,
                                                                browser3));
                                        }
                                }
@@ -442,29 +437,16 @@ abstract class WebLibraryServerHtml implements Runnable {
                                if (authors != null && !authors.isEmpty()) {
                                        // TODO: single empty value
                                        for (String author : authors) {
-                                               options.append(getTemplateBrowserOption(author, author,
+                                               options.add(templates.browserOption(author, author,
                                                                browser3));
                                        }
                                }
                        }
 
-                       selects.append(selectTemplate //
-                                       .replace("${name}", "browser3") //
-                                       .replace("${value}", browser3) //
-                                       .replace("${options}", options.toString()) //
-                       );
+                       selects.add(templates.browserSelect("browser3", browser3, options));
                }
 
-               String sel = "selected='selected'";
-               builder.append(getTemplate("browser") //
-                               .replace("${sourcesSelected}", sourcesSel ? sel : "") //
-                               .replace("${authorsSelected}", authorsSel ? sel : "") //
-                               .replace("${tagsSelected}", tagsSel ? sel : "") //
-                               .replace("${filter}", filter) //
-                               .replace("${selects}", selects.toString()) //
-               );
-
-               builder.append("\t\t<div class='books'>\n");
+               List<Template> booklines = new ArrayList<Template>();
                for (MetaData meta : result.getMetas()) {
                        if (!filter.isEmpty() && !meta.getTitle().toLowerCase()
                                        .contains(filter.toLowerCase())) {
@@ -492,29 +474,20 @@ abstract class WebLibraryServerHtml implements Runnable {
                                author = "(" + meta.getAuthor() + ")";
                        }
 
-                       String cachedClass = "cached";
-                       String cached = "&#9673;";
-                       if (!lib.isCached(meta.getLuid())) {
-                               cachedClass = "uncached";
-                               cached = "&#9675;";
-                       }
-
-                       builder.append(getTemplate("bookline") //
-                                       .replace("${href}",
-                                                       WebLibraryUrls.getViewUrl(meta.getLuid(), null,
-                                                                       null)) //
-                                       .replace("${luid}", meta.getLuid()) //
-                                       .replace("${title}", meta.getTitle()) //
-                                       .replace("${author}", author) //
-                                       .replace("${cachedClass}", cachedClass) //
-                                       .replace("${cached}", cached) //
-                       );
+                       booklines.add(templates.bookline( //
+                                       meta.getLuid(), //
+                                       WebLibraryUrls.getViewUrl(meta.getLuid(), null, null), //
+                                       meta.getTitle(), //
+                                       author, //
+                                       lib.isCached(meta.getLuid()) //
+                       ));
                }
-               builder.append("\t\t</div>\n");
-
-               builder.append(getTemplate("index.post"));
 
-               return NanoHTTPD.newFixedLengthResponse(builder.toString());
+               // Add the browser in front of the booklines
+               booklines.add(0, templates.browser(browser, filter, selects));
+               
+               return newInputStreamResponse(NanoHTTPD.MIME_HTML,
+                               templates.index(true, booklines).read());
        }
 
        private Response getViewer(Map<String, String> cookies, String uri,
@@ -850,20 +823,6 @@ abstract class WebLibraryServerHtml implements Runnable {
                return html;
        }
 
-       private String getTemplateBrowserOption(String name, String value,
-                       String selected) throws IOException {
-               String selectedAttribute = "";
-               if (value.equals(selected)) {
-                       selectedAttribute = " selected='selected'";
-               }
-
-               return getTemplate("browser.option" //
-                               .replace("${value}", value) //
-                               .replace("${selected}", selectedAttribute) //
-                               .replace("${name}", name) //
-               );
-       }
-
        private String getTemplate(String template) throws IOException {
                // TODO: check if it is "slow" -> map cache
                InputStream in = IOUtils.openResource(WebLibraryServerTemplates.class,
index 482a1b826e12514a0714cf5cd3256531851d4166..ba4deb83f290739407822fc4933802633fb5bf0e 100644 (file)
@@ -1,4 +1,166 @@
 package be.nikiroo.fanfix.library.web.templates;
 
+import java.util.List;
+
+import be.nikiroo.fanfix.Instance;
+import be.nikiroo.fanfix.bundles.UiConfig;
+import be.nikiroo.fanfix.library.Template;
+import be.nikiroo.utils.Version;
+
 public class WebLibraryServerTemplates {
+       static private WebLibraryServerTemplates instance = new WebLibraryServerTemplates();
+
+       static public WebLibraryServerTemplates getInstance() {
+               return instance;
+       }
+
+       public Template bookline(String luid, String href, String title,
+                       String author, boolean cached) {
+
+               String cachedClass = "cached";
+               String cachedValue = "&#9673;";
+               if (!cached) {
+                       cachedClass = "uncached";
+                       cachedValue = "&#9675;";
+               }
+
+               return new Template(getClass(), "bookline.html") //
+                               .set("href", href) //
+                               .set("cachedClass", cachedClass) //
+                               .set("cached", cachedValue) //
+                               .set("luid", luid) //
+                               .set("title", title) //
+                               .set("author", author) //
+               ;
+       }
+
+       public Template browser(String selectedValue, String filter,
+                       List<Template> selects) {
+               return new Template(getClass(), "browser.html") //
+                               .set("sourcesSelected",
+                                               "sources".equals(selectedValue) ? "selected='selected'"
+                                                               : "") //
+                               .set("authorsSelected",
+                                               "authors".equals(selectedValue) ? "selected='selected'"
+                                                               : "") //
+                               .set("tagsSelected",
+                                               "tags".equals(selectedValue) ? "selected='selected'"
+                                                               : "") //
+                               .set("filter", filter) //
+                               .set("selects", selects) //
+               ;
+       }
+
+       public Template browserOption(String name, String value,
+                       String selectedValue) {
+               return new Template(getClass(), "browser.option.html") //
+                               .set("value", value) //
+                               .set("selected",
+                                               value.equals(selectedValue) ? "selected='selected'"
+                                                               : "") //
+                               .set("name", name) //
+               ;
+       }
+
+       public Template browserSelect(String name, String value,
+                       List<Template> options) {
+               return new Template(getClass(), "browser.select.html") //
+                               .set("name", name) //
+                               .set("value", value) //
+                               .set("options", options) //
+               ;
+       }
+
+       public Template index(boolean banner, List<Template> content) {
+               String favicon = "favicon.ico";
+               String icon = Instance.getInstance().getUiConfig()
+                               .getString(UiConfig.PROGRAM_ICON);
+               if (icon != null) {
+                       favicon = "icon_" + icon.replace("-", "_") + ".png";
+               }
+
+               Template index = new Template(getClass(), "index.html") //
+                               .set("title", "Fanfix") //
+                               .set("favicon", favicon) //
+                               .set("content", content) //
+               ;
+
+               if (banner) {
+                       index.set("banner", new Template(getClass(), "index.banner.html") //
+                                       .set("favicon", favicon) //
+                                       .set("version", Version.getCurrentVersion().toString()) //
+                       );
+               } else {
+                       index.set("banner", "");
+               }
+
+               return index;
+       }
+
+       public Template viewer(Template browser, List<Template> booklines) {
+               // TODO
+               return null;
+       }
+
+       public Template viewerImage(String src, String href, String zoomStyle) {
+               return new Template(getClass(), "viewer.image.html") //
+                               .set("src", src) //
+                               .set("href", href) //
+                               .set("zoomStyle", zoomStyle) //
+               ;
+       }
+
+       public Template viewerText(List<Template> desc, List<Template> content) {
+               return new Template(getClass(), "viewer.text.html") //
+                               .set("desc", desc) //
+                               .set("content", content) //
+               ;
+       }
+
+       public Template viewerLink(String name, String link, String className) {
+               return new Template(getClass(), "viewer.link.html") //
+                               .set("link", link) //
+                               .set("class", className) //
+                               .set("name", name) //
+               ;
+       }
+
+       public Template viewerNavbar(int current, List<Template> links,
+                       String hrefFirst, String hrefPrevious, String hrefNext,
+                       String hrefLast, boolean disabledFirst, boolean disabledPrevious,
+                       boolean disabledNext, boolean disabledLast) {
+               return new Template(getClass(), "viewer.navbar.html") //
+                               .set("disabledFirst",
+                                               disabledFirst ? "disabled='disabled'" : "") //
+                               .set("disabledPrevious",
+                                               disabledPrevious ? "disabled='disabled'" : "") //
+                               .set("disabledNext", disabledNext ? "disabled='disabled'" : "") //
+                               .set("disabledLast", disabledLast ? "disabled='disabled'" : "") //
+                               .set("hrefFirst", hrefFirst) //
+                               .set("hrefPrevious", hrefPrevious) //
+                               .set("hrefNext", hrefNext) //
+                               .set("hrefLast", hrefLast) //
+                               .set("current", Integer.toString(current)) //
+                               .set("links", links) //
+               ;
+       }
+
+       // numberOfButtons = 4 or 1 or the moment
+       public Template viewerOptionbar(int numberOfButtons,
+                       List<Template> buttons) {
+               return new Template(getClass(), "viewer.optionbar.html") //
+                               .set("classSize", "s" + numberOfButtons) //
+                               .set("buttons", buttons) //
+               ;
+       }
+
+       public Template viewerOptionbarButton(String value, String href,
+                       String className, boolean disabled) {
+               return new Template(getClass(), "viewer.optionbar.button.html") //
+                               .set("disabled", disabled ? "disabled='disabled'" : "") //
+                               .set("class", className) //
+                               .set("href", href) //
+                               .set("value", value) //
+               ;
+       }
 }
diff --git a/src/be/nikiroo/fanfix/library/web/templates/index.html b/src/be/nikiroo/fanfix/library/web/templates/index.html
new file mode 100644 (file)
index 0000000..29b8d2c
--- /dev/null
@@ -0,0 +1,50 @@
+<!DOCTYPE html>
+<html>
+<head>
+<!--
+       Copyright 2020 David ROULET
+       
+       This file is part of fanfix.
+       
+       fanfix is free software: you can redistribute it and/or modify
+       it under the terms of the GNU Affero General Public License as published by
+       the Free Software Foundation, either version 3 of the License, or
+       (at your option) any later version.
+       
+       fanfix is distributed in the hope that it will be useful,
+       but WITHOUT ANY WARRANTY; without even the implied warranty of
+       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+       GNU Affero General Public License for more details.
+       
+       You should have received a copy of the GNU Affero General Public License
+       along with fanfix.  If not, see <https://www.gnu.org/licenses/>.
+       ___________________________________________________________________________
+
+       This website was coded by:
+                       A kangaroo.
+                                                  _  _
+                                                 (\\( \
+                                                  `.\-.)
+                              _...._            _,-"   `-.
+\                           ,"      `-._.- -.,-"       .  \
+ \`.                      ,"                               `.
+  \ `-...__              /                           .   .:  y
+   `._     ``-...__     /                           ,"```-._/
+      `-._         ```-"                      |    /_          //
+          `.._                   _            ;   <_ \        //
+              ``-.___             `.           `-._ \ \      //
+                     `- <           `.     (\ _/)/ `.\/     //
+                         \            \     `       ^^^^^^^^^
+       ___________________________________________________________________________
+       
+       -->
+       <meta http-equiv="content-type" content="text/html; charset=utf-8">
+       <meta name="viewport" content="width=device-width, initial-scale=1.0">
+       <title>${title}</title>
+       <link rel="stylesheet" type="text/css" href="/style.css" />
+       <link rel="icon" type="image/x-icon" href="/${favicon}" />
+</head>
+<body>
+       <div class='main'>
+${banner}${content}    </div>
+</body>
diff --git a/src/be/nikiroo/fanfix/library/web/templates/viewer.html b/src/be/nikiroo/fanfix/library/web/templates/viewer.html
new file mode 100644 (file)
index 0000000..f4b4215
--- /dev/null
@@ -0,0 +1 @@
+${browser}${viewer}
\ No newline at end of file