Network server and Library + nikiroo-utils update
authorNiki Roo <niki@nikiroo.be>
Sat, 1 Jul 2017 23:04:44 +0000 (01:04 +0200)
committerNiki Roo <niki@nikiroo.be>
Sat, 1 Jul 2017 23:04:44 +0000 (01:04 +0200)
17 files changed:
README.md
changelog.md
libs/nikiroo-utils-1.6.1-sources.jar [moved from libs/nikiroo-utils-1.6.0-sources.jar with 85% similarity]
src/be/nikiroo/fanfix/Instance.java
src/be/nikiroo/fanfix/Library.java
src/be/nikiroo/fanfix/Main.java
src/be/nikiroo/fanfix/RemoteLibrary.java [new file with mode: 0644]
src/be/nikiroo/fanfix/RemoteLibraryServer.java [new file with mode: 0644]
src/be/nikiroo/fanfix/data/Chapter.java
src/be/nikiroo/fanfix/data/Paragraph.java
src/be/nikiroo/fanfix/reader/BasicReader.java
src/be/nikiroo/fanfix/reader/CliReader.java
src/be/nikiroo/fanfix/reader/LocalReader.java
src/be/nikiroo/fanfix/reader/LocalReaderFrame.java
src/be/nikiroo/fanfix/reader/TuiReader.java
src/be/nikiroo/fanfix/reader/TuiReaderApplication.java
src/be/nikiroo/fanfix/reader/TuiReaderStoryWindow.java

index 826aacb2acf5b971db72964d9a823cbe15300211..d80d3c5cb7f64afa88bba49195ae1d950d610395 100644 (file)
--- a/README.md
+++ b/README.md
@@ -4,6 +4,8 @@ Fanfix is a small Java program that can download stories from some supported web
 
 (If you are interested in the recent changes, please check the [Changelog](changelog.md) -- note that starting from version 1.4.0, the changelog is checked at startup (unless the option is disabled))
 
+TODO: new screenshots + TUI screenshots
+
 ![Main GUI](screenshots/fanfix-1.3.2.png?raw=true "Main GUI")
 
 It will convert from a (supported) URL to an .epub file for stories or a .cbz file for comics (a few other output types are also available, like Plain Text, LaTeX, HTML...).
@@ -60,7 +62,9 @@ The following arguments are also allowed:
 - ```--read [id] ([chapter number])```: read the given story denoted by ID from the library
 - ```--read-url [URL] ([chapter number])```: convert on the fly and read the story denoted by ID, without saving it
 - ```--list```: list the stories present in the library and their associated IDs
-- ```--set-reader [reader type]```: set the reader type to CLI or LOCAL for this command (must be the first option)
+- ```--set-reader [reader type]```: set the reader type to CLI, TUI or GUI for this command
+- ```--server [port]```: start a story server on this port
+- ```--remote [host] [port]```: contact this server instead of the usual library
 - ```--help```: display the available options
 
 ### Environment variables
@@ -85,6 +89,7 @@ There are some unit tests you can run, too:
 
 - libs/nikiroo-utils-sources.jar: some shared utility functions I also use elsewhere
 - [libs/unbescape-sources.jar](https://github.com/unbescape/unbescape): a nice library to escape/unescape a lot of text formats; I only use it for HTML
+- [libs/jexer-sources.jar](https://github.com/klamonte/jexer): a small library that offers TUI widgets
 
 Nothing else but Java 1.6+.
 
@@ -115,8 +120,16 @@ Currently missing, but either in progress or planned:
   - [x] Implement it from --set-reader to the actual window
   - [x] List the stories
   - [ ] Fix the UI layout
-  - [ ] Status bar and real menus
-  - [ ] Open a story in the reader and/or natively
+  - [x] Status bar
+  - [ ] Real menus
+  - [x] Open a story in the reader and/or natively
+  - [ ] Update the screenshots
+- [ ] Network support
+  - [x] A server that can send the stories
+  - [x] A network implementation of the Library
+  - [ ] Write access to the library (?)
+  - [ ] Access rights (?)
+  - [ ] More tests, especially with the GUI
 - [ ] Check if it can work on Android
   - [x] First checks: it should work, but with changes
   - [ ] Adapt work on images :(
index 89b6b00d44b23dca262852414a71a8be831f2559..a27f9c8f27286e5c03fa16eda04c0dc65c77baec 100644 (file)
@@ -2,6 +2,8 @@
 
 ## Version WIP
 - New reader type: TUI (a text user interface with windows and menus)
+- A server option to offer stories on the network
+- A remote library to get said stories from the network
 
 ## Version 1.5.3
 - FimFiction: Fix tags and chapter handling for some stories
similarity index 85%
rename from libs/nikiroo-utils-1.6.0-sources.jar
rename to libs/nikiroo-utils-1.6.1-sources.jar
index 1ec2951b17dc08ac7051355d62f75c9813b28aac..f3b1578e33be4dce4635d0b11b11efd27c51ce98 100644 (file)
Binary files a/libs/nikiroo-utils-1.6.0-sources.jar and b/libs/nikiroo-utils-1.6.1-sources.jar differ
index 28849b325510ccec2b17b813de99d8fef9036650..42e141e60bcc2dda445c55a77abc26dcd27a7e05 100644 (file)
@@ -27,6 +27,7 @@ public class Instance {
        private static boolean debug;
        private static File coverDir;
        private static File readerTmp;
+       private static File remoteDir;
        private static String configDir;
 
        static {
@@ -84,6 +85,7 @@ public class Instance {
                coverDir = getFile(Config.DEFAULT_COVERS_DIR);
                File tmp = getFile(Config.CACHE_DIR);
                readerTmp = getFile(UiConfig.CACHE_DIR_LOCAL_READER);
+               remoteDir = new File(getFile(Config.LIBRARY_DIR), "remote");
 
                if (checkEnv("NOUTF")) {
                        trans.setUnicode(false);
@@ -185,6 +187,25 @@ public class Instance {
                return readerTmp;
        }
 
+       /**
+        * Return the directory where to store temporary files for the remote
+        * {@link Library}.
+        * 
+        * @param host
+        *            the remote for this host
+        * 
+        * @return the directory
+        */
+       public static File getRemoteDir(String host) {
+               remoteDir.mkdirs();
+
+               if (host != null) {
+                       return new File(remoteDir, host);
+               }
+
+               return remoteDir;
+       }
+
        /**
         * Check if we need to check that a new version of Fanfix is available.
         * 
index 8a3895ad8c82a5c3e8e8754f3202f9da48e3edf8..3868bd3fee03d946214db55f8594f14bf34a5887 100644 (file)
@@ -38,8 +38,8 @@ import be.nikiroo.utils.Progress;
 public class Library {
        protected File baseDir;
        protected boolean localSpeed;
+       protected Map<MetaData, File> stories;
 
-       private Map<MetaData, File> stories;
        private int lastId;
        private OutputType text;
        private OutputType image;
@@ -156,17 +156,12 @@ public class Library {
         * 
         * @return the stories
         */
-       public synchronized List<MetaData> getListByType(String type) {
-               if (type != null) {
-                       // convert the type to dir name
-                       type = getExpectedDir(type).getName();
-               }
-
+       public synchronized List<MetaData> getListBySource(String type) {
                List<MetaData> list = new ArrayList<MetaData>();
-               for (Entry<MetaData, File> entry : getStories(null).entrySet()) {
-                       String storyType = entry.getValue().getParentFile().getName();
+               for (MetaData meta : getStories(null).keySet()) {
+                       String storyType = meta.getSource();
                        if (type == null || type.equalsIgnoreCase(storyType)) {
-                               list.add(entry.getKey());
+                               list.add(meta);
                        }
                }
 
index 5cd3313897317d7fb5a03c73c17557ff421ae890..38f58af3814fcc484f966112af59ec4f96618129 100644 (file)
@@ -16,7 +16,7 @@ import be.nikiroo.fanfix.supported.BasicSupport;
 import be.nikiroo.fanfix.supported.BasicSupport.SupportType;
 import be.nikiroo.utils.Progress;
 import be.nikiroo.utils.Version;
-import be.nikiroo.utils.ui.UIUtils;
+import be.nikiroo.utils.serial.Server;
 
 /**
  * Main program entry point.
@@ -25,7 +25,7 @@ import be.nikiroo.utils.ui.UIUtils;
  */
 public class Main {
        private enum MainAction {
-               IMPORT, EXPORT, CONVERT, READ, READ_URL, LIST, HELP, SET_READER, START, VERSION,
+               IMPORT, EXPORT, CONVERT, READ, READ_URL, LIST, HELP, SET_READER, START, VERSION, SERVER, REMOTE,
        }
 
        /**
@@ -55,6 +55,8 @@ public class Main {
         * <li>--set-reader [reader type]: set the reader type to CLI, TUI or LOCAL
         * for this command</li>
         * <li>--version: get the version of the program</li>
+        * <li>--server [port]: start a server on this port</li>
+        * <li>--remote [host] [port]: use a the given remote library</li>
         * </ul>
         * 
         * @param args
@@ -63,11 +65,13 @@ public class Main {
        public static void main(String[] args) {
                String urlString = null;
                String luid = null;
-               String typeString = null;
+               String sourceString = null;
                String chapString = null;
                String target = null;
                MainAction action = MainAction.START;
                Boolean plusInfo = null;
+               String host = null;
+               Integer port = null;
 
                boolean noMoreActions = false;
 
@@ -102,8 +106,8 @@ public class Main {
                        case EXPORT:
                                if (luid == null) {
                                        luid = args[i];
-                               } else if (typeString == null) {
-                                       typeString = args[i];
+                               } else if (sourceString == null) {
+                                       sourceString = args[i];
                                } else if (target == null) {
                                        target = args[i];
                                } else {
@@ -113,8 +117,8 @@ public class Main {
                        case CONVERT:
                                if (urlString == null) {
                                        urlString = args[i];
-                               } else if (typeString == null) {
-                                       typeString = args[i];
+                               } else if (sourceString == null) {
+                                       sourceString = args[i];
                                } else if (target == null) {
                                        target = args[i];
                                } else if (plusInfo == null) {
@@ -128,8 +132,8 @@ public class Main {
                                }
                                break;
                        case LIST:
-                               if (typeString == null) {
-                                       typeString = args[i];
+                               if (sourceString == null) {
+                                       sourceString = args[i];
                                } else {
                                        exitCode = 255;
                                }
@@ -164,6 +168,30 @@ public class Main {
                                break;
                        case VERSION:
                                exitCode = 255; // no arguments for this option
+                               break;
+                       case SERVER:
+                               if (port == null) {
+                                       port = Integer.parseInt(args[i]);
+                               } else {
+                                       exitCode = 255;
+                               }
+                               break;
+                       case REMOTE:
+                               if (host == null) {
+                                       host = args[i];
+                               } else if (port == null) {
+                                       port = Integer.parseInt(args[i]);
+                                       try {
+                                               BasicReader.setDefaultLibrary(new RemoteLibrary(host,
+                                                               port));
+                                       } catch (IOException e) {
+                                               Instance.syserr(e);
+                                       }
+                                       action = MainAction.START;
+                               } else {
+                                       exitCode = 255;
+                               }
+                               break;
                        }
                }
 
@@ -215,16 +243,16 @@ public class Main {
                                updates.ok(); // we consider it read
                                break;
                        case EXPORT:
-                               exitCode = export(luid, typeString, target, pg);
+                               exitCode = export(luid, sourceString, target, pg);
                                updates.ok(); // we consider it read
                                break;
                        case CONVERT:
-                               exitCode = convert(urlString, typeString, target,
+                               exitCode = convert(urlString, sourceString, target,
                                                plusInfo == null ? false : plusInfo, pg);
                                updates.ok(); // we consider it read
                                break;
                        case LIST:
-                               exitCode = list(typeString);
+                               exitCode = list(sourceString);
                                break;
                        case READ:
                                exitCode = read(luid, chapString, true);
@@ -237,6 +265,7 @@ public class Main {
                                exitCode = 0;
                                break;
                        case SET_READER:
+                               exitCode = 255;
                                break;
                        case VERSION:
                                System.out
@@ -247,8 +276,23 @@ public class Main {
                                updates.ok(); // we consider it read
                                break;
                        case START:
-                               //BasicReader.setDefaultReaderType(ReaderType.LOCAL);
-                               BasicReader.getReader().start(null);
+                               BasicReader.getReader().browse(null);
+                               break;
+                       case SERVER:
+                               if (port == null) {
+                                       exitCode = 255;
+                                       break;
+                               }
+                               try {
+                                       Server server = new RemoteLibraryServer(port);
+                                       server.start();
+                                       System.out.println("Remote server started on: " + port);
+                               } catch (IOException e) {
+                                       Instance.syserr(e);
+                               }
+                               return;
+                       case REMOTE:
+                               exitCode = 255;
                                break;
                        }
                }
@@ -320,17 +364,17 @@ public class Main {
        }
 
        /**
-        * List the stories of the given type from the {@link Library} (unless NULL
-        * is passed, in which case all stories will be listed).
+        * List the stories of the given source from the {@link Library} (unless
+        * NULL is passed, in which case all stories will be listed).
         * 
-        * @param type
-        *            the type to list the known stories of, or NULL to list all
+        * @param source
+        *            the source to list the known stories of, or NULL to list all
         *            stories
         * 
         * @return the exit return code (0 = success)
         */
-       private static int list(String type) {
-               BasicReader.getReader().start(type);
+       private static int list(String source) {
+               BasicReader.getReader().browse(source);
                return 0;
        }
 
diff --git a/src/be/nikiroo/fanfix/RemoteLibrary.java b/src/be/nikiroo/fanfix/RemoteLibrary.java
new file mode 100644 (file)
index 0000000..cc78be9
--- /dev/null
@@ -0,0 +1,109 @@
+package be.nikiroo.fanfix;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Map;
+
+import be.nikiroo.fanfix.data.MetaData;
+import be.nikiroo.fanfix.data.Story;
+import be.nikiroo.fanfix.output.BasicOutput.OutputType;
+import be.nikiroo.utils.Progress;
+import be.nikiroo.utils.Version;
+import be.nikiroo.utils.serial.ConnectActionClient;
+
+public class RemoteLibrary extends Library {
+       private String host;
+       private int port;
+
+       private Library lib;
+
+       public RemoteLibrary(String host, int port) throws IOException {
+               this.host = host;
+               this.port = port;
+
+               this.localSpeed = false;
+               this.baseDir = Instance.getRemoteDir(host);
+               this.baseDir.mkdirs();
+
+               this.lib = new Library(baseDir, OutputType.INFO_TEXT, OutputType.CBZ);
+       }
+
+       @Override
+       public synchronized Story save(Story story, String luid, Progress pg)
+                       throws IOException {
+               throw new java.lang.InternalError(
+                               "No write support allowed on remote Libraries");
+       }
+
+       @Override
+       public synchronized boolean delete(String luid) {
+               throw new java.lang.InternalError(
+                               "No write support allowed on remote Libraries");
+       }
+
+       @Override
+       public synchronized boolean changeType(String luid, String newType) {
+               throw new java.lang.InternalError(
+                               "No write support allowed on remote Libraries");
+       }
+
+       @Override
+       protected synchronized Map<MetaData, File> getStories(Progress pg) {
+               // TODO: progress
+               if (stories.isEmpty()) {
+                       try {
+                               new ConnectActionClient(host, port, true, null) {
+                                       public void action(Version serverVersion) throws Exception {
+                                               try {
+                                                       Object rep = send("GET_METADATA *");
+                                                       for (MetaData meta : (MetaData[]) rep) {
+                                                               stories.put(meta, null);
+                                                       }
+                                               } catch (Exception e) {
+                                                       e.printStackTrace();
+                                               }
+                                       }
+                               }.connect();
+                       } catch (IOException e) {
+                               Instance.syserr(e);
+                       }
+               }
+
+               return stories;
+       }
+
+       @Override
+       public synchronized File getFile(final String luid) {
+               File file = lib.getFile(luid);
+               if (file == null) {
+                       final File[] tmp = new File[1];
+                       try {
+                               new ConnectActionClient(host, port, true, null) {
+                                       public void action(Version serverVersion) throws Exception {
+                                               try {
+                                                       Object rep = send("GET_STORY " + luid);
+                                                       Story story = (Story) rep;
+                                                       if (story != null) {
+                                                               lib.save(story, luid, null);
+                                                               tmp[0] = lib.getFile(luid);
+                                                       }
+                                               } catch (Exception e) {
+                                                       Instance.syserr(e);
+                                               }
+                                       }
+                               }.connect();
+                       } catch (IOException e) {
+                               Instance.syserr(e);
+                       }
+
+                       file = tmp[0];
+               }
+
+               if (file != null) {
+                       MetaData meta = getInfo(luid);
+                       stories.put(meta, file);
+               }
+
+               return file;
+       }
+}
diff --git a/src/be/nikiroo/fanfix/RemoteLibraryServer.java b/src/be/nikiroo/fanfix/RemoteLibraryServer.java
new file mode 100644 (file)
index 0000000..9ecbc41
--- /dev/null
@@ -0,0 +1,51 @@
+package be.nikiroo.fanfix;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Map;
+
+import be.nikiroo.fanfix.data.MetaData;
+import be.nikiroo.utils.Version;
+import be.nikiroo.utils.serial.ConnectActionServer;
+import be.nikiroo.utils.serial.Server;
+
+public class RemoteLibraryServer extends Server {
+
+       public RemoteLibraryServer(int port) throws IOException {
+               super(Version.getCurrentVersion(), port, true);
+       }
+
+       @Override
+       protected Object onRequest(ConnectActionServer action,
+                       Version clientVersion, Object data) throws Exception {
+               String command = null;
+               String args = null;
+               if (data instanceof String) {
+                       command = (String) data;
+                       int pos = command.indexOf(" ");
+                       if (pos >= 0) {
+                               args = command.substring(pos + 1);
+                               command = command.substring(0, pos);
+                       }
+               }
+
+               System.out.println(String.format("COMMAND: [%s], ARGS: [%s]", command,
+                               args));
+
+               if (command != null) {
+                       if (command.equals("GET_METADATA")) {
+                               if (args != null && args.equals("*")) {
+                                       Map<MetaData, File> stories = Instance.getLibrary()
+                                                       .getStories(null);
+                                       return stories.keySet().toArray(new MetaData[] {});
+                               }
+                       } else if (command.equals("GET_STORY")) {
+                               if (args != null) {
+                                       return Instance.getLibrary().getStory(args, null);
+                               }
+                       }
+               }
+
+               return null;
+       }
+}
index 7d0a51b306b62bfc7f821065a0c10e358be82075..d9f285f96762ce135b8046578f0df9d75d31b819 100644 (file)
@@ -16,6 +16,13 @@ public class Chapter implements Iterable<Paragraph> {
        private List<Paragraph> empty = new ArrayList<Paragraph>();
        private long words;
 
+       /**
+        * Empty constructor, not to use.
+        */
+       private Chapter() {
+               // for serialisation purposes
+       }
+
        /**
         * Create a new {@link Chapter} with the given information.
         * 
index e4c94d45710bdb2f8b1cd9cd7f655f8ef490f861..8a9130bf83fdcc8342a796f125a64a1aa994ea4c 100644 (file)
@@ -30,6 +30,13 @@ public class Paragraph {
        private String content;
        private long words;
 
+       /**
+        * Empty constructor, not to use.
+        */
+       private Paragraph() {
+               // for serialisation purposes
+       }
+
        /**
         * Create a new {@link Paragraph} with the given image.
         * 
index 7b9c98c2a6c1f0239bb460fc2fc8b7938a36a9fb..05e3e3df1124b6eae858e536e5b57adec2db78e2 100644 (file)
@@ -14,7 +14,6 @@ import be.nikiroo.fanfix.data.MetaData;
 import be.nikiroo.fanfix.data.Story;
 import be.nikiroo.fanfix.supported.BasicSupport;
 import be.nikiroo.utils.Progress;
-import be.nikiroo.utils.ui.UIUtils;
 import be.nikiroo.utils.serial.SerialUtils;
 
 /**
@@ -32,22 +31,28 @@ public abstract class BasicReader {
                GUI,
                /** A text (UTF-8) reader with menu and text windows */
                TUI,
-               
+
                ;
-               
+
                public String getTypeName() {
                        String pkg = "be.nikiroo.fanfix.reader.";
                        switch (this) {
-                               case CLI: return pkg + "CliReader";
-                               case TUI: return pkg + "TuiReader";
-                               case GUI: return pkg + "LocalReader";
+                       case CLI:
+                               return pkg + "CliReader";
+                       case TUI:
+                               return pkg + "TuiReader";
+                       case GUI:
+                               return pkg + "LocalReader";
                        }
-                       
+
                        return null;
                }
        }
 
+       private static Library defaultLibrary = Instance.getLibrary();
        private static ReaderType defaultType = ReaderType.GUI;
+
+       private Library lib;
        private Story story;
        private ReaderType type;
 
@@ -95,9 +100,34 @@ public abstract class BasicReader {
                return story;
        }
 
+       /**
+        * The {@link Library} to load the stories from (by default, takes the
+        * default {@link Library}).
+        * 
+        * @return the {@link Library}
+        */
+       public Library getLibrary() {
+               if (lib == null) {
+                       lib = defaultLibrary;
+               }
+
+               return lib;
+       }
+
+       /**
+        * Change the {@link Library} that will be managed by this
+        * {@link BasicReader}.
+        * 
+        * @param lib
+        *            the new {@link Library}
+        */
+       public void setLibrary(Library lib) {
+               this.lib = lib;
+       }
+
        /**
         * Create a new {@link BasicReader} for a {@link Story} in the
-        * {@link Library} .
+        * {@link Library}.
         * 
         * @param luid
         *            the {@link Story} ID
@@ -108,7 +138,7 @@ public abstract class BasicReader {
         *             in case of I/O error
         */
        public void setStory(String luid, Progress pg) throws IOException {
-               story = Instance.getLibrary().getStory(luid, pg);
+               story = lib.getStory(luid, pg);
                if (story == null) {
                        throw new IOException("Cannot retrieve story from library: " + luid);
                }
@@ -162,14 +192,17 @@ public abstract class BasicReader {
        public abstract void read(int chapter) throws IOException;
 
        /**
-        * Start the reader in browse mode for the given type (or pass NULL for all
-        * types).
+        * Start the reader in browse mode for the given source (or pass NULL for
+        * all sources).
         * 
-        * @param type
+        * @param library
+        *            the library to browse
+        * 
+        * @param source
         *            the type of {@link Story} to take into account, or NULL for
         *            all
         */
-       public abstract void start(String type);
+       public abstract void browse(String source);
 
        /**
         * Return a new {@link BasicReader} ready for use if one is configured.
@@ -181,8 +214,8 @@ public abstract class BasicReader {
        public static BasicReader getReader() {
                try {
                        if (defaultType != null) {
-                               return ((BasicReader)SerialUtils.createObject
-                                       (defaultType.getTypeName())).setType(defaultType);
+                               return ((BasicReader) SerialUtils.createObject(defaultType
+                                               .getTypeName())).setType(defaultType);
                        }
                } catch (Exception e) {
                        Instance.syserr(new Exception("Cannot create a reader of type: "
@@ -213,6 +246,16 @@ public abstract class BasicReader {
                BasicReader.defaultType = defaultType;
        }
 
+       /**
+        * Change the default {@link Library} to open with the {@link BasicReader}s.
+        * 
+        * @param lib
+        *            the new {@link Library}
+        */
+       public static void setDefaultLibrary(Library lib) {
+               BasicReader.defaultLibrary = lib;
+       }
+
        /**
         * Return an {@link URL} from this {@link String}, be it a file path or an
         * actual {@link URL}.
@@ -242,9 +285,9 @@ public abstract class BasicReader {
        }
 
        // open with external player the related file
-       public static void open(String luid) throws IOException {
-               MetaData meta = Instance.getLibrary().getInfo(luid);
-               File target = Instance.getLibrary().getFile(luid);
+       public static void open(Library lib, String luid) throws IOException {
+               MetaData meta = lib.getInfo(luid);
+               File target = lib.getFile(luid);
 
                open(meta, target);
        }
index a57de34a8e3beb403d7f2fdec1052d225aafd617..7ac69e85d7ce0e14d8b0c045569f7c7fbeeb0a52 100644 (file)
@@ -78,9 +78,9 @@ class CliReader extends BasicReader {
        }
 
        @Override
-       public void start(String type) {
+       public void browse(String source) {
                List<MetaData> stories;
-               stories = Instance.getLibrary().getListByType(type);
+               stories = getLibrary().getListBySource(source);
 
                for (MetaData story : stories) {
                        String author = "";
index 2b92e721db959fc52aa46af7ebb7799daa4afec5..6c6150318b38917958579a4fbaf87a5f1489ff05 100644 (file)
@@ -20,11 +20,19 @@ import be.nikiroo.fanfix.data.Story;
 import be.nikiroo.fanfix.output.BasicOutput.OutputType;
 import be.nikiroo.utils.Progress;
 import be.nikiroo.utils.Version;
+import be.nikiroo.utils.ui.UIUtils;
 
 class LocalReader extends BasicReader {
-       private Library lib;
+       static private boolean nativeLookLoaded;
+
+       private Library localLibrary;
 
        public LocalReader() throws IOException {
+               if (!nativeLookLoaded) {
+                       UIUtils.setLookAndFeel();
+                       nativeLookLoaded = true;
+               }
+
                File dir = Instance.getReaderDir();
                dir.mkdirs();
                if (!dir.exists()) {
@@ -58,7 +66,7 @@ class LocalReader extends BasicReader {
                                                        key, value), e);
                }
 
-               lib = new Library(dir, text, images);
+               localLibrary = new Library(dir, text, images);
        }
 
        @Override
@@ -99,7 +107,7 @@ class LocalReader extends BasicReader {
                try {
                        Story story = Instance.getLibrary().getStory(luid, pgGetStory);
                        if (story != null) {
-                               story = lib.save(story, luid, pgSave);
+                               story = localLibrary.save(story, luid, pgSave);
                        } else {
                                throw new IOException("Cannot find story in Library: " + luid);
                        }
@@ -120,11 +128,11 @@ class LocalReader extends BasicReader {
         * @return TRUE if it is
         */
        public boolean isCached(String luid) {
-               return lib.getInfo(luid) != null;
+               return localLibrary.getInfo(luid) != null;
        }
 
        @Override
-       public void start(String type) {
+       public void browse(String type) {
                // TODO: improve presentation of update message
                final VersionCheck updates = VersionCheck.check();
                StringBuilder builder = new StringBuilder();
@@ -189,28 +197,28 @@ class LocalReader extends BasicReader {
 
        // delete from local reader library
        void clearLocalReaderCache(String luid) {
-               lib.delete(luid);
+               localLibrary.delete(luid);
        }
 
        // delete from main library
        void delete(String luid) {
-               lib.delete(luid);
+               localLibrary.delete(luid);
                Instance.getLibrary().delete(luid);
        }
 
        // open the given book
        void open(String luid, Progress pg) throws IOException {
-               File file = lib.getFile(luid);
+               File file = localLibrary.getFile(luid);
                if (file == null) {
                        imprt(luid, pg);
-                       file = lib.getFile(luid);
+                       file = localLibrary.getFile(luid);
                }
 
-               open(Instance.getLibrary().getInfo(luid), file);
+               open(getLibrary().getInfo(luid), file);
        }
 
        void changeType(String luid, String newType) {
-               lib.changeType(luid, newType);
+               localLibrary.changeType(luid, newType);
                Instance.getLibrary().changeType(luid, newType);
        }
 }
index 03df7fbdf5cf133d86ac5d11634392e7edb61632..edd1fb60e598d1954b21bfb6f00b6317aeed5757 100644 (file)
@@ -220,7 +220,7 @@ class LocalReaderFrame extends JFrame {
         */
        private void refreshBooks() {
                for (LocalReaderGroup group : booksByType.keySet()) {
-                       List<MetaData> stories = Instance.getLibrary().getListByType(
+                       List<MetaData> stories = Instance.getLibrary().getListBySource(
                                        booksByType.get(group));
                        group.refreshBooks(stories, words);
                }
index d18436f67a9497b4ec42e0a6514036e29447a9dd..d00bbc29079b906e0ecbeae5e45b21bca8ac7d0e 100644 (file)
@@ -4,6 +4,7 @@ import java.io.IOException;
 import java.util.List;
 
 import be.nikiroo.fanfix.Instance;
+import be.nikiroo.fanfix.Library;
 import be.nikiroo.fanfix.data.MetaData;
 
 class TuiReader extends BasicReader {
@@ -13,7 +14,7 @@ class TuiReader extends BasicReader {
                        throw new IOException("No story to read");
                }
 
-               open(getStory().getMeta().getLuid());
+               open(getLibrary(), getStory().getMeta().getLuid());
        }
 
        @Override
@@ -23,8 +24,8 @@ class TuiReader extends BasicReader {
        }
 
        @Override
-       public void start(String type) {
-               List<MetaData> stories = Instance.getLibrary().getListByType(type);
+       public void browse(String source) {
+               List<MetaData> stories = getLibrary().getListBySource(source);
                try {
                        TuiReaderApplication app = new TuiReaderApplication(stories, this);
                        new Thread(app).start();
index 94ecfd52104b636e6ad2a4af5bd6c77541403afb..9a534983f3f25068ea7fd9f2b6b31909775abb39 100644 (file)
@@ -5,7 +5,6 @@ import java.util.List;
 
 import jexer.TApplication;
 import jexer.TMessageBox;
-import be.nikiroo.fanfix.Instance;
 import be.nikiroo.fanfix.data.MetaData;
 
 public class TuiReaderApplication extends TApplication {
@@ -55,21 +54,15 @@ public class TuiReaderApplication extends TApplication {
 
        public void open(MetaData meta) {
                // TODO: open in editor + external option
-               if (true) {
-                       if (!meta.isImageDocument()) {
-                               new TuiReaderStoryWindow(this, meta);
-                       } else {
+               if (!meta.isImageDocument()) {
+                       new TuiReaderStoryWindow(this, reader.getLibrary(), meta);
+               } else {
+                       try {
+                               BasicReader.open(reader.getLibrary(), meta.getLuid());
+                       } catch (IOException e) {
                                messageBox("Error when trying to open the story",
-                                               "Images document not yet supported.",
-                                               TMessageBox.Type.OK);
+                                               e.getMessage(), TMessageBox.Type.OK);
                        }
-                       return;
-               }
-               try {
-                       reader.open(meta.getLuid());
-               } catch (IOException e) {
-                       messageBox("Error when trying to open the story", e.getMessage(),
-                                       TMessageBox.Type.OK);
                }
        }
 }
index 7eb592fd4686666a6237d4787243e2dd55ab1711..0d47cde4a680cae672b04346194ab0b112ffd406 100644 (file)
@@ -13,12 +13,14 @@ import jexer.TText;
 import jexer.TWindow;
 import jexer.event.TResizeEvent;
 import be.nikiroo.fanfix.Instance;
+import be.nikiroo.fanfix.Library;
 import be.nikiroo.fanfix.data.Chapter;
 import be.nikiroo.fanfix.data.MetaData;
 import be.nikiroo.fanfix.data.Paragraph;
 import be.nikiroo.fanfix.data.Story;
 
 public class TuiReaderStoryWindow extends TWindow {
+       private Library lib;
        private MetaData meta;
        private Story story;
        private TText textField;
@@ -26,12 +28,15 @@ public class TuiReaderStoryWindow extends TWindow {
        private List<TButton> navigationButtons;
        private TLabel chapterName;
 
-       public TuiReaderStoryWindow(TApplication app, MetaData meta) {
-               this(app, meta, 0);
+       public TuiReaderStoryWindow(TApplication app, Library lib, MetaData meta) {
+               this(app, lib, meta, 0);
        }
 
-       public TuiReaderStoryWindow(TApplication app, MetaData meta, int chapter) {
+       public TuiReaderStoryWindow(TApplication app, Library lib, MetaData meta,
+                       int chapter) {
                super(app, desc(meta), 0, 0, 60, 18, CENTERED | RESIZABLE);
+               
+               this.lib = lib;
                this.meta = meta;
 
                // TODO: show all meta info before?
@@ -46,7 +51,10 @@ public class TuiReaderStoryWindow extends TWindow {
                // -3 because 0-based and 2 for borders
                int row = getHeight() - 3;
 
-               navigationButtons.add(addButton(" ", 0, row, null)); // for bg colour when << button is pressed
+               navigationButtons.add(addButton(" ", 0, row, null)); // for bg colour
+                                                                                                                               // when <<
+                                                                                                                               // button is
+                                                                                                                               // pressed
                navigationButtons.add(addButton("<<  ", 0, row, new TAction() {
                        public void DO() {
                                setChapter(0);
@@ -67,7 +75,7 @@ public class TuiReaderStoryWindow extends TWindow {
                                setChapter(getStory().getChapters().size());
                        }
                }));
-               
+
                navigationButtons.get(0).setEnabled(false);
                navigationButtons.get(1).setEnabled(false);
                navigationButtons.get(2).setEnabled(false);
@@ -113,14 +121,14 @@ public class TuiReaderStoryWindow extends TWindow {
 
                if (chapter != this.chapter) {
                        this.chapter = chapter;
-                       
+
                        int max = getStory().getChapters().size();
                        navigationButtons.get(0).setEnabled(chapter > 0);
                        navigationButtons.get(1).setEnabled(chapter > 0);
                        navigationButtons.get(2).setEnabled(chapter > 0);
                        navigationButtons.get(3).setEnabled(chapter < max);
                        navigationButtons.get(4).setEnabled(chapter < max);
-                       
+
                        Chapter chap;
                        String name;
                        if (chapter == 0) {
@@ -128,7 +136,8 @@ public class TuiReaderStoryWindow extends TWindow {
                                name = String.format(" %s", chap.getName());
                        } else {
                                chap = getStory().getChapters().get(chapter - 1);
-                               name = String.format(" %d/%d: %s", chapter, max, chap.getName());
+                               name = String
+                                               .format(" %d/%d: %s", chapter, max, chap.getName());
                        }
 
                        while (name.length() < getWidth() - chapterName.getX()) {
@@ -157,7 +166,7 @@ public class TuiReaderStoryWindow extends TWindow {
        private Story getStory() {
                if (story == null) {
                        // TODO: progress bar?
-                       story = Instance.getLibrary().getStory(meta.getLuid(), null);
+                       story = lib.getStory(meta.getLuid(), null);
                }
                return story;
        }