Fix bug when moving an unopened book in GUI
[fanfix.git] / src / be / nikiroo / fanfix / reader / GuiReader.java
CommitLineData
a6395bef
NR
1package be.nikiroo.fanfix.reader;
2
edd46289 3import java.awt.Desktop;
a6395bef
NR
4import java.awt.EventQueue;
5import java.io.File;
6import java.io.IOException;
b42117f1
NR
7import java.net.URISyntaxException;
8
9import javax.swing.JEditorPane;
10import javax.swing.JLabel;
11import javax.swing.JOptionPane;
12import javax.swing.event.HyperlinkEvent;
13import javax.swing.event.HyperlinkListener;
a6395bef
NR
14
15import be.nikiroo.fanfix.Instance;
b42117f1 16import be.nikiroo.fanfix.VersionCheck;
b4dc6ab5 17import be.nikiroo.fanfix.bundles.UiConfig;
bc2ea776 18import be.nikiroo.fanfix.data.MetaData;
a6395bef 19import be.nikiroo.fanfix.data.Story;
e42573a0 20import be.nikiroo.fanfix.library.LocalLibrary;
a6395bef 21import be.nikiroo.fanfix.output.BasicOutput.OutputType;
3b2b638f 22import be.nikiroo.utils.Progress;
b42117f1 23import be.nikiroo.utils.Version;
b0e88ebd 24import be.nikiroo.utils.ui.UIUtils;
a6395bef 25
5dd985cf 26class GuiReader extends BasicReader {
b0e88ebd
NR
27 static private boolean nativeLookLoaded;
28
68e2c6d2 29 private LocalLibrary localLibrary;
a6395bef 30
5dd985cf 31 public GuiReader() throws IOException {
b0e88ebd
NR
32 if (!nativeLookLoaded) {
33 UIUtils.setLookAndFeel();
34 nativeLookLoaded = true;
35 }
36
a6395bef
NR
37 File dir = Instance.getReaderDir();
38 dir.mkdirs();
39 if (!dir.exists()) {
40 throw new IOException(
41 "Cannote create cache directory for local reader: " + dir);
42 }
43
edd46289
NR
44 OutputType text = null;
45 OutputType images = null;
46
47 try {
48 text = OutputType.valueOfNullOkUC(Instance.getUiConfig().getString(
49 UiConfig.NON_IMAGES_DOCUMENT_TYPE));
50 if (text == null) {
51 text = OutputType.HTML;
52 }
53
54 images = OutputType.valueOfNullOkUC(Instance.getUiConfig()
55 .getString(UiConfig.IMAGES_DOCUMENT_TYPE));
56 if (images == null) {
57 images = OutputType.CBZ;
58 }
59 } catch (Exception e) {
60 UiConfig key = (text == null) ? UiConfig.NON_IMAGES_DOCUMENT_TYPE
61 : UiConfig.IMAGES_DOCUMENT_TYPE;
62 String value = Instance.getUiConfig().getString(key);
a6395bef 63
edd46289
NR
64 throw new IOException(
65 String.format(
66 "The configuration option %s is not valid: %s",
67 key, value), e);
a6395bef 68 }
a6395bef 69
68e2c6d2 70 localLibrary = new LocalLibrary(dir, text, images);
a6395bef
NR
71 }
72
211f7ddb 73 @Override
a6395bef 74 public void read() throws IOException {
bc2ea776
NR
75 MetaData meta = getMeta();
76
77 if (meta == null) {
edd46289
NR
78 throw new IOException("No story to read");
79 }
80
bc2ea776 81 read(meta.getLuid(), null);
a6395bef
NR
82 }
83
92fb0719
NR
84 /**
85 * Import the story into the local reader library, and keep the same LUID.
86 *
87 * @param luid
88 * the Library UID
89 * @param pg
90 * the optional progress reporter
91 *
92 * @throws IOException
93 * in case of I/O error
94 */
95 public void imprt(String luid, Progress pg) throws IOException {
bee7dffe
NR
96 Progress pgGetStory = new Progress();
97 Progress pgSave = new Progress();
98 if (pg != null) {
99 pg.setMax(2);
100 pg.addProgress(pgGetStory, 1);
101 pg.addProgress(pgSave, 1);
102 }
103
a6395bef 104 try {
e42573a0 105 Story story = getLibrary().getStory(luid, pgGetStory);
3d247bc3 106 if (story != null) {
b0e88ebd 107 story = localLibrary.save(story, luid, pgSave);
3d247bc3
NR
108 } else {
109 throw new IOException("Cannot find story in Library: " + luid);
110 }
a6395bef 111 } catch (IOException e) {
3d247bc3 112 throw new IOException(
a6395bef 113 "Cannot import story from library to LocalReader library: "
3d247bc3 114 + luid, e);
a6395bef 115 }
a6395bef
NR
116 }
117
9843a5e5
NR
118 /**
119 * Check if the {@link Story} denoted by this Library UID is present in the
5dd985cf 120 * {@link GuiReader} cache.
9843a5e5
NR
121 *
122 * @param luid
123 * the Library UID
124 *
125 * @return TRUE if it is
126 */
10d558d2 127 public boolean isCached(String luid) {
b0e88ebd 128 return localLibrary.getInfo(luid) != null;
10d558d2
NR
129 }
130
211f7ddb 131 @Override
b0e88ebd 132 public void browse(String type) {
b42117f1
NR
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() {
211f7ddb 159 @Override
b42117f1
NR
160 public void hyperlinkUpdate(HyperlinkEvent e) {
161 if (e.getEventType().equals(
162 HyperlinkEvent.EventType.ACTIVATED))
163 try {
164 Desktop.getDesktop().browse(e.getURL().toURI());
165 } catch (IOException ee) {
166 Instance.syserr(ee);
167 } catch (URISyntaxException ee) {
168 Instance.syserr(ee);
169 }
170 }
171 });
172 updateMessage.setEditable(false);
173 updateMessage.setBackground(new JLabel().getBackground());
174 }
175
333f0e7b 176 final String typeFinal = type;
a6395bef 177 EventQueue.invokeLater(new Runnable() {
211f7ddb 178 @Override
a6395bef 179 public void run() {
b42117f1
NR
180 if (updates.isNewVersionAvailable()) {
181 int rep = JOptionPane.showConfirmDialog(null,
182 updateMessage, "Updates available",
183 JOptionPane.OK_CANCEL_OPTION);
184 if (rep == JOptionPane.OK_OPTION) {
185 updates.ok();
186 } else {
187 updates.ignore();
188 }
189 }
190
e42573a0 191 new GuiReaderFrame(GuiReader.this, typeFinal).setVisible(true);
a6395bef
NR
192 }
193 });
194 }
10d558d2 195
754a5bc2
NR
196 // delete from local reader library
197 void clearLocalReaderCache(String luid) {
68e2c6d2
NR
198 try {
199 localLibrary.delete(luid);
200 } catch (IOException e) {
201 Instance.syserr(e);
202 }
10d558d2
NR
203 }
204
edd46289 205 // delete from main library
10d558d2 206 void delete(String luid) {
68e2c6d2
NR
207 try {
208 localLibrary.delete(luid);
e42573a0 209 getLibrary().delete(luid);
68e2c6d2
NR
210 } catch (IOException e) {
211 Instance.syserr(e);
212 }
10d558d2 213 }
edd46289
NR
214
215 // open the given book
bc2ea776 216 void read(String luid, Progress pg) throws IOException {
b0e88ebd 217 File file = localLibrary.getFile(luid);
c1873e56
NR
218 if (file == null) {
219 imprt(luid, pg);
b0e88ebd 220 file = localLibrary.getFile(luid);
edd46289
NR
221 }
222
bc2ea776 223 // TODO: show a special page for the chapter?
6322ab64 224 openExternal(getLibrary().getInfo(luid), file);
edd46289 225 }
70c9b112 226
bc2ea776 227 void changeType(String luid, String newSource) {
68e2c6d2 228 try {
34eb62fc
NR
229 if (localLibrary.getInfo(luid) != null) {
230 localLibrary.changeSource(luid, newSource, null);
231 }
bc2ea776 232 getLibrary().changeSource(luid, newSource, null);
68e2c6d2
NR
233 } catch (IOException e) {
234 Instance.syserr(e);
235 }
70c9b112 236 }
a6395bef 237}