06b3473c74c95f9abe7035f78852b3a1604938f4
[fanfix.git] / src / be / nikiroo / fanfix / reader / GuiReader.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.VersionCheck;
17 import be.nikiroo.fanfix.bundles.UiConfig;
18 import be.nikiroo.fanfix.data.Story;
19 import be.nikiroo.fanfix.library.LocalLibrary;
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 GuiReader extends BasicReader {
26 static private boolean nativeLookLoaded;
27
28 private LocalLibrary localLibrary;
29
30 public GuiReader() 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 public void read() throws IOException {
73 if (getStory() == null) {
74 throw new IOException("No story to read");
75 }
76
77 open(getStory().getMeta().getLuid(), null);
78 }
79
80 public void read(int chapter) throws IOException {
81 // TODO: show a special page?
82 read();
83 }
84
85 /**
86 * Import the story into the local reader library, and keep the same LUID.
87 *
88 * @param luid
89 * the Library UID
90 * @param pg
91 * the optional progress reporter
92 *
93 * @throws IOException
94 * in case of I/O error
95 */
96 public void imprt(String luid, Progress pg) throws IOException {
97 Progress pgGetStory = new Progress();
98 Progress pgSave = new Progress();
99 if (pg != null) {
100 pg.setMax(2);
101 pg.addProgress(pgGetStory, 1);
102 pg.addProgress(pgSave, 1);
103 }
104
105 try {
106 Story story = getLibrary().getStory(luid, pgGetStory);
107 if (story != null) {
108 story = localLibrary.save(story, luid, pgSave);
109 } else {
110 throw new IOException("Cannot find story in Library: " + luid);
111 }
112 } catch (IOException e) {
113 throw new IOException(
114 "Cannot import story from library to LocalReader library: "
115 + luid, e);
116 }
117 }
118
119 /**
120 * Check if the {@link Story} denoted by this Library UID is present in the
121 * {@link GuiReader} cache.
122 *
123 * @param luid
124 * the Library UID
125 *
126 * @return TRUE if it is
127 */
128 public boolean isCached(String luid) {
129 return localLibrary.getInfo(luid) != null;
130 }
131
132 public void browse(String type) {
133 // TODO: improve presentation of update message
134 final VersionCheck updates = VersionCheck.check();
135 StringBuilder builder = new StringBuilder();
136
137 final JEditorPane updateMessage = new JEditorPane("text/html", "");
138 if (updates.isNewVersionAvailable()) {
139 builder.append("A new version of the program is available at <span style='color: blue;'>https://github.com/nikiroo/fanfix/releases</span>");
140 builder.append("<br>");
141 builder.append("<br>");
142 for (Version v : updates.getNewer()) {
143 builder.append("\t<b>Version " + v + "</b>");
144 builder.append("<br>");
145 builder.append("<ul>");
146 for (String item : updates.getChanges().get(v)) {
147 builder.append("<li>" + item + "</li>");
148 }
149 builder.append("</ul>");
150 }
151
152 // html content
153 updateMessage.setText("<html><body>" //
154 + builder//
155 + "</body></html>");
156
157 // handle link events
158 updateMessage.addHyperlinkListener(new HyperlinkListener() {
159 public void hyperlinkUpdate(HyperlinkEvent e) {
160 if (e.getEventType().equals(
161 HyperlinkEvent.EventType.ACTIVATED))
162 try {
163 Desktop.getDesktop().browse(e.getURL().toURI());
164 } catch (IOException ee) {
165 Instance.syserr(ee);
166 } catch (URISyntaxException ee) {
167 Instance.syserr(ee);
168 }
169 }
170 });
171 updateMessage.setEditable(false);
172 updateMessage.setBackground(new JLabel().getBackground());
173 }
174
175 final String typeFinal = type;
176 EventQueue.invokeLater(new Runnable() {
177 public void run() {
178 if (updates.isNewVersionAvailable()) {
179 int rep = JOptionPane.showConfirmDialog(null,
180 updateMessage, "Updates available",
181 JOptionPane.OK_CANCEL_OPTION);
182 if (rep == JOptionPane.OK_OPTION) {
183 updates.ok();
184 } else {
185 updates.ignore();
186 }
187 }
188
189 new GuiReaderFrame(GuiReader.this, typeFinal).setVisible(true);
190 }
191 });
192 }
193
194 // delete from local reader library
195 void clearLocalReaderCache(String luid) {
196 try {
197 localLibrary.delete(luid);
198 } catch (IOException e) {
199 Instance.syserr(e);
200 }
201 }
202
203 // delete from main library
204 void delete(String luid) {
205 try {
206 localLibrary.delete(luid);
207 getLibrary().delete(luid);
208 } catch (IOException e) {
209 Instance.syserr(e);
210 }
211 }
212
213 // open the given book
214 void open(String luid, Progress pg) throws IOException {
215 File file = localLibrary.getFile(luid);
216 if (file == null) {
217 imprt(luid, pg);
218 file = localLibrary.getFile(luid);
219 }
220
221 open(getLibrary().getInfo(luid), file);
222 }
223
224 void changeType(String luid, String newType) {
225 try {
226 localLibrary.changeSource(luid, newType, null);
227 getLibrary().changeSource(luid, newType, null);
228 } catch (IOException e) {
229 Instance.syserr(e);
230 }
231 }
232 }