Dependency fix + Local/Remote Library support
[fanfix.git] / src / be / nikiroo / fanfix / reader / LocalReader.java
1 package be.nikiroo.fanfix.reader;
2
3 import java.awt.Desktop;
4 import java.awt.EventQueue;
5 import java.io.File;
6 import java.io.IOException;
7 import java.net.URISyntaxException;
8
9 import javax.swing.JEditorPane;
10 import javax.swing.JLabel;
11 import javax.swing.JOptionPane;
12 import javax.swing.event.HyperlinkEvent;
13 import javax.swing.event.HyperlinkListener;
14
15 import be.nikiroo.fanfix.Instance;
16 import be.nikiroo.fanfix.LocalLibrary;
17 import be.nikiroo.fanfix.VersionCheck;
18 import be.nikiroo.fanfix.bundles.UiConfig;
19 import be.nikiroo.fanfix.data.Story;
20 import be.nikiroo.fanfix.output.BasicOutput.OutputType;
21 import be.nikiroo.utils.Progress;
22 import be.nikiroo.utils.Version;
23 import be.nikiroo.utils.ui.UIUtils;
24
25 class LocalReader extends BasicReader {
26 static private boolean nativeLookLoaded;
27
28 private LocalLibrary localLibrary;
29
30 public LocalReader() throws IOException {
31 if (!nativeLookLoaded) {
32 UIUtils.setLookAndFeel();
33 nativeLookLoaded = true;
34 }
35
36 File dir = Instance.getReaderDir();
37 dir.mkdirs();
38 if (!dir.exists()) {
39 throw new IOException(
40 "Cannote create cache directory for local reader: " + dir);
41 }
42
43 OutputType text = null;
44 OutputType images = null;
45
46 try {
47 text = OutputType.valueOfNullOkUC(Instance.getUiConfig().getString(
48 UiConfig.NON_IMAGES_DOCUMENT_TYPE));
49 if (text == null) {
50 text = OutputType.HTML;
51 }
52
53 images = OutputType.valueOfNullOkUC(Instance.getUiConfig()
54 .getString(UiConfig.IMAGES_DOCUMENT_TYPE));
55 if (images == null) {
56 images = OutputType.CBZ;
57 }
58 } catch (Exception e) {
59 UiConfig key = (text == null) ? UiConfig.NON_IMAGES_DOCUMENT_TYPE
60 : UiConfig.IMAGES_DOCUMENT_TYPE;
61 String value = Instance.getUiConfig().getString(key);
62
63 throw new IOException(
64 String.format(
65 "The configuration option %s is not valid: %s",
66 key, value), e);
67 }
68
69 localLibrary = new LocalLibrary(dir, text, images);
70 }
71
72 @Override
73 public void read() throws IOException {
74 if (getStory() == null) {
75 throw new IOException("No story to read");
76 }
77
78 open(getStory().getMeta().getLuid(), null);
79 }
80
81 @Override
82 public void read(int chapter) throws IOException {
83 // TODO: show a special page?
84 read();
85 }
86
87 /**
88 * Import the story into the local reader library, and keep the same LUID.
89 *
90 * @param luid
91 * the Library UID
92 * @param pg
93 * the optional progress reporter
94 *
95 * @throws IOException
96 * in case of I/O error
97 */
98 public void imprt(String luid, Progress pg) throws IOException {
99 Progress pgGetStory = new Progress();
100 Progress pgSave = new Progress();
101 if (pg != null) {
102 pg.setMax(2);
103 pg.addProgress(pgGetStory, 1);
104 pg.addProgress(pgSave, 1);
105 }
106
107 try {
108 Story story = Instance.getLibrary().getStory(luid, pgGetStory);
109 if (story != null) {
110 story = localLibrary.save(story, luid, pgSave);
111 } else {
112 throw new IOException("Cannot find story in Library: " + luid);
113 }
114 } catch (IOException e) {
115 throw new IOException(
116 "Cannot import story from library to LocalReader library: "
117 + luid, e);
118 }
119 }
120
121 /**
122 * Check if the {@link Story} denoted by this Library UID is present in the
123 * {@link LocalReader} cache.
124 *
125 * @param luid
126 * the Library UID
127 *
128 * @return TRUE if it is
129 */
130 public boolean isCached(String luid) {
131 return localLibrary.getInfo(luid) != null;
132 }
133
134 @Override
135 public void browse(String type) {
136 // TODO: improve presentation of update message
137 final VersionCheck updates = VersionCheck.check();
138 StringBuilder builder = new StringBuilder();
139
140 final JEditorPane updateMessage = new JEditorPane("text/html", "");
141 if (updates.isNewVersionAvailable()) {
142 builder.append("A new version of the program is available at <span style='color: blue;'>https://github.com/nikiroo/fanfix/releases</span>");
143 builder.append("<br>");
144 builder.append("<br>");
145 for (Version v : updates.getNewer()) {
146 builder.append("\t<b>Version " + v + "</b>");
147 builder.append("<br>");
148 builder.append("<ul>");
149 for (String item : updates.getChanges().get(v)) {
150 builder.append("<li>" + item + "</li>");
151 }
152 builder.append("</ul>");
153 }
154
155 // html content
156 updateMessage.setText("<html><body>" //
157 + builder//
158 + "</body></html>");
159
160 // handle link events
161 updateMessage.addHyperlinkListener(new HyperlinkListener() {
162 public void hyperlinkUpdate(HyperlinkEvent e) {
163 if (e.getEventType().equals(
164 HyperlinkEvent.EventType.ACTIVATED))
165 try {
166 Desktop.getDesktop().browse(e.getURL().toURI());
167 } catch (IOException ee) {
168 Instance.syserr(ee);
169 } catch (URISyntaxException ee) {
170 Instance.syserr(ee);
171 }
172 }
173 });
174 updateMessage.setEditable(false);
175 updateMessage.setBackground(new JLabel().getBackground());
176 }
177
178 final String typeFinal = type;
179 EventQueue.invokeLater(new Runnable() {
180 public void run() {
181 if (updates.isNewVersionAvailable()) {
182 int rep = JOptionPane.showConfirmDialog(null,
183 updateMessage, "Updates available",
184 JOptionPane.OK_CANCEL_OPTION);
185 if (rep == JOptionPane.OK_OPTION) {
186 updates.ok();
187 } else {
188 updates.ignore();
189 }
190 }
191
192 new LocalReaderFrame(LocalReader.this, typeFinal)
193 .setVisible(true);
194 }
195 });
196 }
197
198 // delete from local reader library
199 void clearLocalReaderCache(String luid) {
200 try {
201 localLibrary.delete(luid);
202 } catch (IOException e) {
203 Instance.syserr(e);
204 }
205 }
206
207 // delete from main library
208 void delete(String luid) {
209 try {
210 localLibrary.delete(luid);
211 Instance.getLibrary().delete(luid);
212 } catch (IOException e) {
213 Instance.syserr(e);
214 }
215 }
216
217 // open the given book
218 void open(String luid, Progress pg) throws IOException {
219 File file = localLibrary.getFile(luid);
220 if (file == null) {
221 imprt(luid, pg);
222 file = localLibrary.getFile(luid);
223 }
224
225 open(getLibrary().getInfo(luid), file);
226 }
227
228 void changeType(String luid, String newType) {
229 try {
230 localLibrary.changeSource(luid, newType, null);
231 Instance.getLibrary().changeSource(luid, newType, null);
232 } catch (IOException e) {
233 Instance.syserr(e);
234 }
235 }
236 }