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