From ba1ce95aa203c3c41f6f0a3de6e0d5de545f85c6 Mon Sep 17 00:00:00 2001 From: MewX Date: Tue, 24 Jul 2018 14:53:06 +0800 Subject: [PATCH 1/9] #32 Added unit tests for LightCache class --- .../LightNovelLibrary/app/build.gradle | 4 +- .../activity/ViewImageDetailActivity.java | 4 +- .../java/org/mewx/wenku8/util/LightCache.java | 301 ++++++++---------- .../org/mewx/wenku8/util/LightCacheTest.java | 172 ++++++++++ 4 files changed, 305 insertions(+), 176 deletions(-) create mode 100644 studio-android/LightNovelLibrary/app/src/test/java/org/mewx/wenku8/util/LightCacheTest.java diff --git a/studio-android/LightNovelLibrary/app/build.gradle b/studio-android/LightNovelLibrary/app/build.gradle index d4611fc5..68a0d08d 100644 --- a/studio-android/LightNovelLibrary/app/build.gradle +++ b/studio-android/LightNovelLibrary/app/build.gradle @@ -90,8 +90,8 @@ dependencies { androidTestImplementation 'com.android.support.test:rules:1.0.2' androidTestImplementation 'junit:junit:4.12' androidTestImplementation 'org.mockito:mockito-core:1.10.19' - androidTestCompile 'com.google.dexmaker:dexmaker:1.2' - androidTestCompile 'com.google.dexmaker:dexmaker-mockito:1.2' + androidTestImplementation 'com.google.dexmaker:dexmaker:1.2' + androidTestImplementation 'com.google.dexmaker:dexmaker-mockito:1.2' testImplementation 'junit:junit:4.12' testImplementation 'org.mockito:mockito-all:1.10.19' diff --git a/studio-android/LightNovelLibrary/app/src/main/java/org/mewx/wenku8/activity/ViewImageDetailActivity.java b/studio-android/LightNovelLibrary/app/src/main/java/org/mewx/wenku8/activity/ViewImageDetailActivity.java index 5f851391..2cc89d6d 100644 --- a/studio-android/LightNovelLibrary/app/src/main/java/org/mewx/wenku8/activity/ViewImageDetailActivity.java +++ b/studio-android/LightNovelLibrary/app/src/main/java/org/mewx/wenku8/activity/ViewImageDetailActivity.java @@ -199,7 +199,7 @@ public void onInput(@NonNull MaterialDialog dialog, final CharSequence input) { @Override public void onPositive(MaterialDialog dialog) { // copy file from 'path' to 'uri + File.separator + input + ".jpg"' - LightCache.copyfile(path, newuri + File.separator + input + ".jpg", true); + LightCache.copyFile(path, newuri + File.separator + input + ".jpg", true); Toast.makeText(ViewImageDetailActivity.this, "已保存:" + newuri + File.separator + input + ".jpg", Toast.LENGTH_SHORT).show(); } @@ -224,7 +224,7 @@ public void onNegative(MaterialDialog dialog) { } else { // copy file from 'path' to 'uri + File.separator + input + ".jpg"' - LightCache.copyfile(path, newuri + File.separator + input + ".jpg", true); + LightCache.copyFile(path, newuri + File.separator + input + ".jpg", true); Toast.makeText(ViewImageDetailActivity.this, "已保存:" + newuri + File.separator + input + ".jpg", Toast.LENGTH_SHORT).show(); } } diff --git a/studio-android/LightNovelLibrary/app/src/main/java/org/mewx/wenku8/util/LightCache.java b/studio-android/LightNovelLibrary/app/src/main/java/org/mewx/wenku8/util/LightCache.java index 39a85d31..f67a2c3b 100644 --- a/studio-android/LightNovelLibrary/app/src/main/java/org/mewx/wenku8/util/LightCache.java +++ b/studio-android/LightNovelLibrary/app/src/main/java/org/mewx/wenku8/util/LightCache.java @@ -1,187 +1,144 @@ -/** - * Light Cache - ** - * This class provide straight file operation functions. - * Easy save file, read file and delete file. - **/ - package org.mewx.wenku8.util; -import java.io.BufferedReader; +import android.util.Log; + import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.File; import java.io.FileInputStream; -import java.io.FileNotFoundException; import java.io.FileOutputStream; -import java.io.FileReader; import java.io.IOException; -import android.util.Log; - +/** + * Light Cache + * * + * This class provide straight file operation functions. + * Easy save file, read file and delete file. + */ public class LightCache { - public static boolean testFileExist(String path) { - File file = new File(path); - if(file.exists()) { - if(file.length() == 0) - deleteFile(path); // delete empty file + private static final String TAG = LightCache.class.getSimpleName(); + + /** + * Test whether file exists + * + * @param path the full file path + * @return true if file exist and not empty; + * otherwise false, and if the file exists but it's empty, it will get removed + */ + public static boolean testFileExist(String path) { + File file = new File(path); + if (file.exists()) { + if (file.length() == 0) + deleteFile(path); // delete empty file and return false else return true; } return false; - } - - public static byte[] loadFile(String path) { - // if file not exist, then return null - File file = new File(path); - if (file.exists() && file.isFile()) { - // load existing file - int fileSize = (int) file.length(); // get file size - try { - FileInputStream in = new FileInputStream(file); - DataInputStream dis = new DataInputStream(in); - - // read all - byte[] bs = new byte[fileSize]; - if(dis.read(bs, 0, fileSize) == -1) - return null; - - dis.close(); - in.close(); - return bs; - } catch (IOException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } - return null; - } - - public static boolean saveFile(String path, String fileName, byte[] bs, boolean forceUpdate) { - // if forceUpdate == true then update the file - File file = new File(path); - file.mkdirs(); - - file = new File(path + (path.charAt(path.length() - 1) != File.separatorChar ? File.separator : "") + fileName); - Log.v("MewX-File", - "Path: " + path + (path.charAt(path.length() - 1) != File.separatorChar ? File.separator : "") + fileName); - if (!file.exists() || forceUpdate) { - if (file.exists() && !file.isFile()) { - Log.v("MewX-File", "Write failed0"); - return false; // is not a file - } - - try { - file.createNewFile(); // create file - - FileOutputStream out = new FileOutputStream(file); // trunc - DataOutputStream dos = new DataOutputStream(out); - - // write all - dos.write(bs); - - dos.close(); - out.close(); - Log.v("MewX-File", "Write successfully"); - return true; - } catch (IOException e) { - e.printStackTrace(); - return false; - } - - } - return true; // say it successful - } - - public static boolean saveFile(String filepath, byte[] bs, boolean forceUpdate) { - // if forceUpdate == true then update the file - File file = new File(filepath); - Log.v("MewX-File", "Path: " + filepath); - if (!file.exists() || forceUpdate) { - if (file.exists() && !file.isFile()) { - Log.v("MewX-File", "Write failed0"); - return false; // is not a file - } - - try { - file.createNewFile(); // create file - - FileOutputStream out = new FileOutputStream(file); // trunc - if (out == null) { - Log.v("MewX-File", "Write failed1"); - return false; - } - DataOutputStream dos = new DataOutputStream(out); - if (dos == null) { - Log.v("MewX-File", "Write failed2"); - return false; - } - - // write all - dos.write(bs); - - dos.close(); - out.close(); - Log.v("MewX-File", "Write successfully"); - return true; - } catch (IOException e) { - e.printStackTrace(); - return false; - } - - } - return true; // say it successful - } - - public static boolean deleteFile(String path, String fileName) { - Log.v("MewX-File", - "Path: " - + path - + (path.charAt(path.length() - 1) != File.separatorChar ? File.separator - : "") + fileName); - File file = new File( - path - + (path.charAt(path.length() - 1) != File.separatorChar ? File.separator - : "") + fileName); - - if (file.delete()) { - Log.v("MewX-File", "Delete successfully"); - return true; - } else - return false; - } - - public static boolean deleteFile(String filepath) { - Log.v("MewX-File", "Path: " + filepath); - File file = new File(filepath); - - if (file.delete()) { - Log.v("MewX-File", "Delete successfully"); - return true; - } else - return false; - } - - public static void copyfile(String from, String to, Boolean forceWrite ) { - File fromFile = new File(from); - File toFile = new File(to); - if (!fromFile.exists() || !fromFile.isFile() || !fromFile.canRead()) - return; - - if (!toFile.getParentFile().exists()) toFile.getParentFile().mkdirs(); - if (toFile.exists() && forceWrite) toFile.delete(); - - try { - java.io.FileInputStream fosfrom = new java.io.FileInputStream(fromFile); - java.io.FileOutputStream fosto = new FileOutputStream(toFile); - - byte bt[] = new byte[1024]; - int c; - while ((c = fosfrom.read(bt)) > 0) fosto.write(bt, 0, c); - fosfrom.close(); - fosto.close(); - } catch (Exception ex) { - ex.printStackTrace(); - } - } + } + + /** + * load file content + * @param path full file path (can be relative) + * @return null if the file does not exist; otherwise the file content string, can be empty + */ + public static byte[] loadFile(String path) { + // if file not exist, then return null + File file = new File(path); + if (file.exists() && file.isFile()) { + // load existing file + int fileSize = (int) file.length(); // get file size + try { + FileInputStream in = new FileInputStream(file); + DataInputStream dis = new DataInputStream(in); + + // read all + byte[] bs = new byte[fileSize]; + if (dis.read(bs, 0, fileSize) == -1) + return null; // error + + dis.close(); + in.close(); + return bs; + } catch (IOException e) { + e.printStackTrace(); + } + } + return null; + } + + public static boolean saveFile(String path, String fileName, byte[] bs, boolean forceUpdate) { + final String fullPath = path + (path.charAt(path.length() - 1) != File.separatorChar ? File.separator : "") + fileName; + return saveFile(fullPath, bs, forceUpdate); + } + + public static boolean saveFile(String filepath, byte[] bs, boolean forceUpdate) { + // create parent folder first when applicable + File file = new File(filepath); + if (file.getParentFile() != null && !file.getParentFile().exists() && !file.getParentFile().mkdirs()) + Log.d(TAG, "Failed to create dir: " + filepath); + + // if forceUpdate == true then update the file + Log.d(TAG, "Path: " + filepath); + if (!file.exists() || forceUpdate) { + if (file.exists() && !file.isFile()) { + Log.d(TAG, "Failed to write, which may caused by file is not a file"); + return false; // is not a file + } + + try { + // create file + if (!file.createNewFile()) + Log.d(TAG, "File existed or failed to create file: " + filepath); + + FileOutputStream out = new FileOutputStream(file); // truncate + DataOutputStream dos = new DataOutputStream(out); + + // write all + dos.write(bs); + + dos.close(); + out.close(); + Log.d(TAG, "Write successfully"); + } catch (IOException e) { + e.printStackTrace(); + return false; + } + } + return true; // say it successful + } + + public static boolean deleteFile(String path, String fileName) { + final String fullPath = path + (path.charAt(path.length() - 1) != File.separatorChar ? File.separator : "") + fileName; + return deleteFile(fullPath); + } + + public static boolean deleteFile(String filepath) { + Log.d(TAG, "Deleting: " + filepath); + return new File(filepath).delete(); + } + + public static void copyFile(String from, String to, Boolean forceWrite) { + File fromFile = new File(from); + File toFile = new File(to); + if (!fromFile.exists() || !fromFile.isFile() || !fromFile.canRead() || toFile.exists() && !forceWrite) + return; + + if (!toFile.getParentFile().exists() && !toFile.getParentFile().mkdirs()) + Log.d(TAG, "Failed to create parent dirs for target file: " + to); + if (toFile.exists() && forceWrite && !toFile.delete()) + Log.d(TAG, "Failed to create or delete target file: " + to); + + try { + java.io.FileInputStream fosFrom = new java.io.FileInputStream(fromFile); + java.io.FileOutputStream fosTo = new FileOutputStream(toFile); + + byte bt[] = new byte[1024]; + int c; + while ((c = fosFrom.read(bt)) > 0) fosTo.write(bt, 0, c); + fosFrom.close(); + fosTo.close(); + } catch (Exception ex) { + ex.printStackTrace(); + } + } } diff --git a/studio-android/LightNovelLibrary/app/src/test/java/org/mewx/wenku8/util/LightCacheTest.java b/studio-android/LightNovelLibrary/app/src/test/java/org/mewx/wenku8/util/LightCacheTest.java new file mode 100644 index 00000000..551e0fc8 --- /dev/null +++ b/studio-android/LightNovelLibrary/app/src/test/java/org/mewx/wenku8/util/LightCacheTest.java @@ -0,0 +1,172 @@ +package org.mewx.wenku8.util; + +import android.util.Log; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.powermock.api.mockito.PowerMockito; +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.modules.junit4.PowerMockRunner; + +import java.io.File; + +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +@RunWith(PowerMockRunner.class) +@PrepareForTest({Log.class}) +public class LightCacheTest { + private static final String TEMP_FILE_PATH = "test/path"; + private static final String TEMP_FILE_NAME = "test.temp"; + private static final String TEMP_FILE_FULL_NAME_PATH = TEMP_FILE_PATH + File.separator + TEMP_FILE_NAME; + + @Before + public void setUp() { + // mock at the very beginning + PowerMockito.mockStatic(Log.class); + PowerMockito.doReturn(0).when(Log.class); // do nothing + + // reset test environment + LightCache.deleteFile(TEMP_FILE_NAME); // single file + LightCache.deleteFile(TEMP_FILE_FULL_NAME_PATH); // file with path + LightCache.deleteFile(TEMP_FILE_PATH); + LightCache.deleteFile("test"); + } + + /** + * when file exists, return true + */ + @Test + public void testFileExist() { + assertFalse(LightCache.testFileExist(TEMP_FILE_NAME)); + + // create file + LightCache.saveFile(TEMP_FILE_NAME, new byte[]{'a'}, false); + + assertTrue(LightCache.testFileExist(TEMP_FILE_NAME)); + } + + /** + * when file exists but the file is empty, return false + */ + @Test + public void testFileExistEmpty() { + assertFalse(LightCache.testFileExist(TEMP_FILE_NAME)); + + // create file + LightCache.saveFile(TEMP_FILE_NAME, new byte[]{}, false); + + assertFalse(LightCache.testFileExist(TEMP_FILE_NAME)); + } + + @Test + public void loadFileNoFile() { + assertNull(LightCache.loadFile(TEMP_FILE_FULL_NAME_PATH)); + } + + @Test + public void loadFileEmptyFile() { + LightCache.saveFile(TEMP_FILE_NAME, new byte[]{}, false); + assertArrayEquals(new byte[0], LightCache.loadFile(TEMP_FILE_NAME)); + } + + @Test + public void loadFileNormalFile() { + LightCache.saveFile(TEMP_FILE_NAME, new byte[]{'a', 'b', 'c'}, false); + assertArrayEquals(new byte[]{'a', 'b', 'c'}, LightCache.loadFile(TEMP_FILE_NAME)); + } + + @Test + public void saveFilePathAndFileName() { + LightCache.saveFile(TEMP_FILE_PATH, TEMP_FILE_NAME, new byte[]{'a', 'b', 'c'}, false); + assertArrayEquals(new byte[]{'a', 'b', 'c'}, LightCache.loadFile(TEMP_FILE_FULL_NAME_PATH)); + } + + @Test + public void saveFileFullPath() { + LightCache.saveFile(TEMP_FILE_FULL_NAME_PATH, new byte[]{'a', 'b', 'c'}, false); + assertArrayEquals(new byte[]{'a', 'b', 'c'}, LightCache.loadFile(TEMP_FILE_FULL_NAME_PATH)); + } + + @Test + public void saveFileNoUpdate() { + LightCache.saveFile(TEMP_FILE_FULL_NAME_PATH, new byte[]{'a', 'b', 'c'}, false); + LightCache.saveFile(TEMP_FILE_FULL_NAME_PATH, new byte[]{'d', 'e', 'f'}, false); + assertArrayEquals(new byte[]{'a', 'b', 'c'}, LightCache.loadFile(TEMP_FILE_FULL_NAME_PATH)); + } + + @Test + public void saveFileForceUpdate() { + LightCache.saveFile(TEMP_FILE_FULL_NAME_PATH, new byte[]{'a', 'b', 'c'}, false); + LightCache.saveFile(TEMP_FILE_FULL_NAME_PATH, new byte[]{'d', 'e', 'f'}, true); + assertArrayEquals(new byte[]{'d', 'e', 'f'}, LightCache.loadFile(TEMP_FILE_FULL_NAME_PATH)); + } + + /** + * Target file is actually is a folder + */ + @Test + public void saveFileExistingFolder() { + assertTrue(new File(TEMP_FILE_FULL_NAME_PATH).mkdirs()); // create as folder + assertFalse(LightCache.saveFile(TEMP_FILE_FULL_NAME_PATH, new byte[]{'d', 'e', 'f'}, true)); + } + + @Test + public void deleteFileNoFile() { + assertFalse(LightCache.deleteFile(TEMP_FILE_PATH, TEMP_FILE_NAME)); + } + + @Test + public void deleteFileNormal() { + assertTrue(LightCache.saveFile(TEMP_FILE_FULL_NAME_PATH, new byte[]{'a', 'b', 'c'}, false)); + assertTrue(LightCache.deleteFile(TEMP_FILE_PATH, TEMP_FILE_NAME)); + } + + @Test + public void deleteFolder() { + assertTrue(new File(TEMP_FILE_FULL_NAME_PATH).mkdirs()); + assertTrue(LightCache.deleteFile(TEMP_FILE_FULL_NAME_PATH)); + } + + @Test + public void deleteFolderNotEmpty() { + assertTrue(new File(TEMP_FILE_FULL_NAME_PATH).mkdirs()); + assertFalse(LightCache.deleteFile(TEMP_FILE_PATH)); + } + + @Test + public void copyFileNoSourceFile() { + LightCache.copyFile(TEMP_FILE_NAME, TEMP_FILE_FULL_NAME_PATH, false); + assertFalse(LightCache.testFileExist(TEMP_FILE_FULL_NAME_PATH)); + } + + @Test + public void copyFileNormal() { + assertTrue(LightCache.saveFile(TEMP_FILE_NAME, new byte[]{'a', 'b', 'c'}, false)); + LightCache.copyFile(TEMP_FILE_NAME, TEMP_FILE_FULL_NAME_PATH, false); + assertTrue(LightCache.testFileExist(TEMP_FILE_FULL_NAME_PATH)); + assertTrue(LightCache.testFileExist(TEMP_FILE_NAME)); // original file still exists + } + + @Test + public void copyFileExistingNoForce() { + assertTrue(LightCache.saveFile(TEMP_FILE_NAME, new byte[]{'a', 'b', 'c'}, false)); + assertTrue(LightCache.saveFile(TEMP_FILE_FULL_NAME_PATH, new byte[]{'d', 'e', 'f'}, false)); + LightCache.copyFile(TEMP_FILE_NAME, TEMP_FILE_FULL_NAME_PATH, false); + assertTrue(LightCache.testFileExist(TEMP_FILE_FULL_NAME_PATH)); + assertArrayEquals(new byte[]{'d', 'e', 'f'}, LightCache.loadFile(TEMP_FILE_FULL_NAME_PATH)); + } + + @Test + public void copyFileExistingForce() { + assertTrue(LightCache.saveFile(TEMP_FILE_NAME, new byte[]{'a', 'b', 'c'}, false)); + assertTrue(LightCache.saveFile(TEMP_FILE_FULL_NAME_PATH, new byte[]{'d', 'e', 'f'}, false)); + LightCache.copyFile(TEMP_FILE_NAME, TEMP_FILE_FULL_NAME_PATH, true); + assertTrue(LightCache.testFileExist(TEMP_FILE_FULL_NAME_PATH)); + assertArrayEquals(new byte[]{'a', 'b', 'c'}, LightCache.loadFile(TEMP_FILE_FULL_NAME_PATH)); + } + +} From 8ddb3cbdfcefdce3bc59bdf1fab9e5e7fe801880 Mon Sep 17 00:00:00 2001 From: MewX Date: Tue, 24 Jul 2018 15:02:10 +0800 Subject: [PATCH 2/9] Closes #38 Fixed crash issue on clicking the latest chapter while loading --- .../wenku8/activity/NovelInfoActivity.java | 41 +++++++++---------- 1 file changed, 20 insertions(+), 21 deletions(-) diff --git a/studio-android/LightNovelLibrary/app/src/main/java/org/mewx/wenku8/activity/NovelInfoActivity.java b/studio-android/LightNovelLibrary/app/src/main/java/org/mewx/wenku8/activity/NovelInfoActivity.java index 0d903972..9bd4ef27 100644 --- a/studio-android/LightNovelLibrary/app/src/main/java/org/mewx/wenku8/activity/NovelInfoActivity.java +++ b/studio-android/LightNovelLibrary/app/src/main/java/org/mewx/wenku8/activity/NovelInfoActivity.java @@ -194,10 +194,7 @@ public void onMenuCollapsed() { tvLatestChapter.setBackground(getResources().getDrawable(R.drawable.btn_menu_item)); } tvNovelTitle.setOnClickListener(v -> { - if(isLoading) { - Toast.makeText(NovelInfoActivity.this, getResources().getString(R.string.system_loading_please_wait), Toast.LENGTH_SHORT).show(); - return; - } + if (runLoadingChecker()) return; // show aid: title new MaterialDialog.Builder(NovelInfoActivity.this) @@ -213,10 +210,7 @@ public void onMenuCollapsed() { .show(); }); tvNovelAuthor.setOnClickListener(v -> { - if(isLoading) { - Toast.makeText(NovelInfoActivity.this, getResources().getString(R.string.system_loading_please_wait), Toast.LENGTH_SHORT).show(); - return; - } + if (runLoadingChecker()) return; new MaterialDialog.Builder(NovelInfoActivity.this) .theme(Theme.LIGHT) @@ -234,10 +228,7 @@ public void onMenuCollapsed() { .show(); }); fabFavorite.setOnClickListener(v -> { - if(isLoading) { - Toast.makeText(NovelInfoActivity.this, getResources().getString(R.string.system_loading_please_wait), Toast.LENGTH_SHORT).show(); - return; - } + if (runLoadingChecker()) return; // add to favorite if(GlobalConfig.testInLocalBookshelf(aid)) { @@ -273,11 +264,9 @@ public void onMenuCollapsed() { } }); fabDownload.setOnClickListener(v -> { - if(isLoading) { - Toast.makeText(NovelInfoActivity.this, getResources().getString(R.string.system_loading_please_wait), Toast.LENGTH_SHORT).show(); - return; - } - else if(!GlobalConfig.testInLocalBookshelf(aid)) { + if (runLoadingChecker()) return; + + if(!GlobalConfig.testInLocalBookshelf(aid)) { Toast.makeText(NovelInfoActivity.this, getResources().getString(R.string.system_fav_it_first), Toast.LENGTH_SHORT).show(); return; } @@ -321,6 +310,8 @@ else if(!GlobalConfig.testInLocalBookshelf(aid)) { .show(); }); tvLatestChapter.setOnClickListener(view -> { + if (runLoadingChecker()) return; + // no sufficient info if (mNovelItemMeta != null && mNovelItemMeta.latestSectionCid != 0) showDirectJumpToReaderDialog( mNovelItemMeta.latestSectionCid); @@ -329,6 +320,17 @@ else if(!GlobalConfig.testInLocalBookshelf(aid)) { }); } + /** + * run loading checker + * @return true if loading; otherwise false + */ + private boolean runLoadingChecker() { + if (isLoading) { + Toast.makeText(NovelInfoActivity.this, getResources().getString(R.string.system_loading_please_wait), Toast.LENGTH_SHORT).show(); + } + return isLoading; + } + /** * 0 检查更新 */ @@ -516,10 +518,7 @@ public boolean onOptionsItemSelected(MenuItem menuItem) { finishAfterTransition(); // end directly } else if (menuItem.getItemId() == R.id.action_continue_read_progress) { - if(isLoading) { - Toast.makeText(NovelInfoActivity.this, getResources().getString(R.string.system_loading_please_wait), Toast.LENGTH_SHORT).show(); - return true; - } + if (runLoadingChecker()) return true; // show dialog, jump to last read position final GlobalConfig.ReadSavesV1 rs = GlobalConfig.getReadSavesRecordV1(aid); From 465ccb96e47238500ea955b673954c83b27176a7 Mon Sep 17 00:00:00 2001 From: MewX Date: Tue, 24 Jul 2018 19:22:19 +0800 Subject: [PATCH 3/9] #32 Moved LightCache test to androidTest for the code coverage report --- .travis.yml | 2 +- .../org/mewx/wenku8/util/LightCacheTest.java | 190 ++++++++++++++++++ .../org/mewx/wenku8/global/api/Wenku8API.java | 2 +- .../java/org/mewx/wenku8/util/LightCache.java | 9 + .../org/mewx/wenku8/util/LightCacheTest.java | 172 ---------------- 5 files changed, 201 insertions(+), 174 deletions(-) create mode 100644 studio-android/LightNovelLibrary/app/src/androidTest/java/org/mewx/wenku8/util/LightCacheTest.java delete mode 100644 studio-android/LightNovelLibrary/app/src/test/java/org/mewx/wenku8/util/LightCacheTest.java diff --git a/.travis.yml b/.travis.yml index 6a516a78..4be9eecf 100644 --- a/.travis.yml +++ b/.travis.yml @@ -35,5 +35,5 @@ before_install: - android-wait-for-emulator - adb shell input keyevent 82 & -script: ./gradlew build connectedCheck coveralls +script: ./gradlew build connectedAlphaDebugAndroidTest coveralls diff --git a/studio-android/LightNovelLibrary/app/src/androidTest/java/org/mewx/wenku8/util/LightCacheTest.java b/studio-android/LightNovelLibrary/app/src/androidTest/java/org/mewx/wenku8/util/LightCacheTest.java new file mode 100644 index 00000000..5dfce8ad --- /dev/null +++ b/studio-android/LightNovelLibrary/app/src/androidTest/java/org/mewx/wenku8/util/LightCacheTest.java @@ -0,0 +1,190 @@ +package org.mewx.wenku8.util; + +import android.content.Context; +import android.support.test.InstrumentationRegistry; +import android.support.test.filters.SmallTest; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import java.io.File; + +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +@SmallTest +public class LightCacheTest { + private static final String TEMP_FILE_NAME = "test.temp"; + + private static String BASE = ""; + private static String BASE_TEMP_FILE_PATH; + private static String BASE_TEMP_FILE_NAME; + private static String BASE_TEMP_FILE_FULL_NAME_PATH; + + @Before + public void setUp() { + final String TEMP_FILE_PATH = "test/path"; + final String TEMP_FILE_FULL_NAME_PATH = TEMP_FILE_PATH + File.separator + TEMP_FILE_NAME; + + Context instrumentationCtx = InstrumentationRegistry.getTargetContext(); + BASE = instrumentationCtx.getFilesDir().getAbsolutePath() + File.separator; + BASE_TEMP_FILE_PATH = BASE + TEMP_FILE_PATH; + BASE_TEMP_FILE_NAME = BASE + TEMP_FILE_NAME; + BASE_TEMP_FILE_FULL_NAME_PATH = BASE + TEMP_FILE_FULL_NAME_PATH; + } + + @After + public void cleanUp() { + // reset test environment + LightCache.deleteFile(BASE_TEMP_FILE_NAME); // single file + LightCache.deleteFile(BASE_TEMP_FILE_FULL_NAME_PATH); // file with path + LightCache.deleteFile(BASE_TEMP_FILE_PATH); + LightCache.deleteFile(BASE + "test"); + } + + /** + * when file exists, return true + */ + @Test + public void testFileExist() { + assertFalse(LightCache.testFileExist(BASE_TEMP_FILE_NAME)); + + // create file + LightCache.saveFile(BASE_TEMP_FILE_NAME, new byte[]{'a'}, false); + + assertTrue(LightCache.testFileExist(BASE_TEMP_FILE_NAME)); + } + + /** + * when file exists but the file is empty, return false + */ + @Test + public void testFileExistEmpty() { + assertFalse(LightCache.testFileExist(BASE_TEMP_FILE_NAME)); + + // create file + LightCache.saveFile(BASE_TEMP_FILE_NAME, new byte[]{}, false); + + assertFalse(LightCache.testFileExist(BASE_TEMP_FILE_NAME)); + } + + @Test + public void loadFileNoFile() { + assertNull(LightCache.loadFile(BASE_TEMP_FILE_FULL_NAME_PATH)); + } + + @Test + public void loadFileEmptyFile() { + LightCache.saveFile(BASE_TEMP_FILE_NAME, new byte[]{}, false); + assertArrayEquals(new byte[0], LightCache.loadFile(BASE_TEMP_FILE_NAME)); + } + + @Test + public void loadFileNormalFile() { + LightCache.saveFile(BASE_TEMP_FILE_NAME, new byte[]{'a', 'b', 'c'}, false); + assertArrayEquals(new byte[]{'a', 'b', 'c'}, LightCache.loadFile(BASE_TEMP_FILE_NAME)); + } + + @Test + public void saveFilePathAndFileName() { + LightCache.saveFile(BASE_TEMP_FILE_PATH, TEMP_FILE_NAME, new byte[]{'a', 'b', 'c'}, false); + assertArrayEquals(new byte[]{'a', 'b', 'c'}, LightCache.loadFile(BASE_TEMP_FILE_FULL_NAME_PATH)); + } + + @Test + public void saveFileFullPath() { + LightCache.saveFile(BASE_TEMP_FILE_FULL_NAME_PATH, new byte[]{'a', 'b', 'c'}, false); + assertArrayEquals(new byte[]{'a', 'b', 'c'}, LightCache.loadFile(BASE_TEMP_FILE_FULL_NAME_PATH)); + } + + @Test + public void saveFileNoUpdate() { + LightCache.saveFile(BASE_TEMP_FILE_FULL_NAME_PATH, new byte[]{'a', 'b', 'c'}, false); + LightCache.saveFile(BASE_TEMP_FILE_FULL_NAME_PATH, new byte[]{'d', 'e', 'f'}, false); + assertArrayEquals(new byte[]{'a', 'b', 'c'}, LightCache.loadFile(BASE_TEMP_FILE_FULL_NAME_PATH)); + } + + @Test + public void saveFileForceUpdate() { + LightCache.saveFile(BASE_TEMP_FILE_FULL_NAME_PATH, new byte[]{'a', 'b', 'c'}, false); + LightCache.saveFile(BASE_TEMP_FILE_FULL_NAME_PATH, new byte[]{'d', 'e', 'f'}, true); + assertArrayEquals(new byte[]{'d', 'e', 'f'}, LightCache.loadFile(BASE_TEMP_FILE_FULL_NAME_PATH)); + } + + /** + * Target file is actually is a folder + */ + @Test + public void saveFileExistingFolder() { + assertTrue(new File(BASE_TEMP_FILE_FULL_NAME_PATH).mkdirs()); // create as folder + assertFalse(LightCache.saveFile(BASE_TEMP_FILE_FULL_NAME_PATH, new byte[]{'d', 'e', 'f'}, true)); + } + + @Test + public void deleteFileNoFile() { + assertFalse(LightCache.deleteFile(BASE_TEMP_FILE_PATH, TEMP_FILE_NAME)); + } + + @Test + public void deleteFileNormal() { + assertTrue(LightCache.saveFile(BASE_TEMP_FILE_FULL_NAME_PATH, new byte[]{'a', 'b', 'c'}, false)); + assertTrue(LightCache.deleteFile(BASE_TEMP_FILE_PATH, TEMP_FILE_NAME)); + } + + @Test + public void deleteFolder() { + assertTrue(new File(BASE_TEMP_FILE_FULL_NAME_PATH).mkdirs()); + assertTrue(LightCache.deleteFile(BASE_TEMP_FILE_FULL_NAME_PATH)); + } + + @Test + public void deleteFolderNotEmpty() { + assertTrue(new File(BASE_TEMP_FILE_FULL_NAME_PATH).mkdirs()); + assertFalse(LightCache.deleteFile(BASE_TEMP_FILE_PATH)); + } + + @Test + public void copyFileNoSourceFile() { + LightCache.copyFile(BASE_TEMP_FILE_NAME, BASE_TEMP_FILE_FULL_NAME_PATH, false); + assertFalse(LightCache.testFileExist(BASE_TEMP_FILE_FULL_NAME_PATH)); + } + + @Test + public void copyFileNoTargetFileParentFolder() { + assertTrue(LightCache.saveFile(BASE_TEMP_FILE_NAME, new byte[]{'a', 'b', 'c'}, false)); + LightCache.copyFile(BASE_TEMP_FILE_NAME, BASE_TEMP_FILE_FULL_NAME_PATH, false); + assertTrue(LightCache.testFileExist(BASE_TEMP_FILE_FULL_NAME_PATH)); + assertTrue(LightCache.testFileExist(BASE_TEMP_FILE_NAME)); // original file still exists + } + + @Test + public void copyFileNormal() { + assertTrue(new File(BASE_TEMP_FILE_PATH).mkdirs()); + assertTrue(LightCache.saveFile(BASE_TEMP_FILE_NAME, new byte[]{'a', 'b', 'c'}, false)); + LightCache.copyFile(BASE_TEMP_FILE_NAME, BASE_TEMP_FILE_FULL_NAME_PATH, false); + assertTrue(LightCache.testFileExist(BASE_TEMP_FILE_FULL_NAME_PATH)); + assertTrue(LightCache.testFileExist(BASE_TEMP_FILE_NAME)); // original file still exists + } + + @Test + public void copyFileExistingNoForce() { + assertTrue(LightCache.saveFile(BASE_TEMP_FILE_NAME, new byte[]{'a', 'b', 'c'}, false)); + assertTrue(LightCache.saveFile(BASE_TEMP_FILE_FULL_NAME_PATH, new byte[]{'d', 'e', 'f'}, false)); + LightCache.copyFile(BASE_TEMP_FILE_NAME, BASE_TEMP_FILE_FULL_NAME_PATH, false); + assertTrue(LightCache.testFileExist(BASE_TEMP_FILE_FULL_NAME_PATH)); + assertArrayEquals(new byte[]{'d', 'e', 'f'}, LightCache.loadFile(BASE_TEMP_FILE_FULL_NAME_PATH)); + } + + @Test + public void copyFileExistingForce() { + assertTrue(LightCache.saveFile(BASE_TEMP_FILE_NAME, new byte[]{'a', 'b', 'c'}, false)); + assertTrue(LightCache.saveFile(BASE_TEMP_FILE_FULL_NAME_PATH, new byte[]{'d', 'e', 'f'}, false)); + LightCache.copyFile(BASE_TEMP_FILE_NAME, BASE_TEMP_FILE_FULL_NAME_PATH, true); + assertTrue(LightCache.testFileExist(BASE_TEMP_FILE_FULL_NAME_PATH)); + assertArrayEquals(new byte[]{'a', 'b', 'c'}, LightCache.loadFile(BASE_TEMP_FILE_FULL_NAME_PATH)); + } + +} diff --git a/studio-android/LightNovelLibrary/app/src/main/java/org/mewx/wenku8/global/api/Wenku8API.java b/studio-android/LightNovelLibrary/app/src/main/java/org/mewx/wenku8/global/api/Wenku8API.java index f4426370..f929e8fe 100644 --- a/studio-android/LightNovelLibrary/app/src/main/java/org/mewx/wenku8/global/api/Wenku8API.java +++ b/studio-android/LightNovelLibrary/app/src/main/java/org/mewx/wenku8/global/api/Wenku8API.java @@ -31,7 +31,7 @@ public static String getCoverURL(int aid) { // this only prevents good boys from doing bad things, and it's what we all know :-) // and I know the mixed use for both simplified and traditional do not work in this case public static final int MIN_REPLY_TEXT = 7; - public static final String[] badWords = { + private static final String[] badWords = { // Simplified "共产党", "政府", "毛泽东", "邓小平", "江泽民", "胡锦涛", "温家宝", "习近平", "李克强", "台独", "藏独", "反日", "反共", "反中", "达赖", "刘晓波", "毛主席", "愤青", diff --git a/studio-android/LightNovelLibrary/app/src/main/java/org/mewx/wenku8/util/LightCache.java b/studio-android/LightNovelLibrary/app/src/main/java/org/mewx/wenku8/util/LightCache.java index f67a2c3b..d7f9afeb 100644 --- a/studio-android/LightNovelLibrary/app/src/main/java/org/mewx/wenku8/util/LightCache.java +++ b/studio-android/LightNovelLibrary/app/src/main/java/org/mewx/wenku8/util/LightCache.java @@ -38,6 +38,7 @@ public static boolean testFileExist(String path) { /** * load file content + * * @param path full file path (can be relative) * @return null if the file does not exist; otherwise the file content string, can be empty */ @@ -117,6 +118,14 @@ public static boolean deleteFile(String filepath) { return new File(filepath).delete(); } + /** + * Copy file from one place to another place, + * if target parent path does not exist, then create them + * + * @param from full path + * @param to full path + * @param forceWrite true if wanting to override + */ public static void copyFile(String from, String to, Boolean forceWrite) { File fromFile = new File(from); File toFile = new File(to); diff --git a/studio-android/LightNovelLibrary/app/src/test/java/org/mewx/wenku8/util/LightCacheTest.java b/studio-android/LightNovelLibrary/app/src/test/java/org/mewx/wenku8/util/LightCacheTest.java deleted file mode 100644 index 551e0fc8..00000000 --- a/studio-android/LightNovelLibrary/app/src/test/java/org/mewx/wenku8/util/LightCacheTest.java +++ /dev/null @@ -1,172 +0,0 @@ -package org.mewx.wenku8.util; - -import android.util.Log; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.powermock.api.mockito.PowerMockito; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.modules.junit4.PowerMockRunner; - -import java.io.File; - -import static org.junit.Assert.assertArrayEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; - -@RunWith(PowerMockRunner.class) -@PrepareForTest({Log.class}) -public class LightCacheTest { - private static final String TEMP_FILE_PATH = "test/path"; - private static final String TEMP_FILE_NAME = "test.temp"; - private static final String TEMP_FILE_FULL_NAME_PATH = TEMP_FILE_PATH + File.separator + TEMP_FILE_NAME; - - @Before - public void setUp() { - // mock at the very beginning - PowerMockito.mockStatic(Log.class); - PowerMockito.doReturn(0).when(Log.class); // do nothing - - // reset test environment - LightCache.deleteFile(TEMP_FILE_NAME); // single file - LightCache.deleteFile(TEMP_FILE_FULL_NAME_PATH); // file with path - LightCache.deleteFile(TEMP_FILE_PATH); - LightCache.deleteFile("test"); - } - - /** - * when file exists, return true - */ - @Test - public void testFileExist() { - assertFalse(LightCache.testFileExist(TEMP_FILE_NAME)); - - // create file - LightCache.saveFile(TEMP_FILE_NAME, new byte[]{'a'}, false); - - assertTrue(LightCache.testFileExist(TEMP_FILE_NAME)); - } - - /** - * when file exists but the file is empty, return false - */ - @Test - public void testFileExistEmpty() { - assertFalse(LightCache.testFileExist(TEMP_FILE_NAME)); - - // create file - LightCache.saveFile(TEMP_FILE_NAME, new byte[]{}, false); - - assertFalse(LightCache.testFileExist(TEMP_FILE_NAME)); - } - - @Test - public void loadFileNoFile() { - assertNull(LightCache.loadFile(TEMP_FILE_FULL_NAME_PATH)); - } - - @Test - public void loadFileEmptyFile() { - LightCache.saveFile(TEMP_FILE_NAME, new byte[]{}, false); - assertArrayEquals(new byte[0], LightCache.loadFile(TEMP_FILE_NAME)); - } - - @Test - public void loadFileNormalFile() { - LightCache.saveFile(TEMP_FILE_NAME, new byte[]{'a', 'b', 'c'}, false); - assertArrayEquals(new byte[]{'a', 'b', 'c'}, LightCache.loadFile(TEMP_FILE_NAME)); - } - - @Test - public void saveFilePathAndFileName() { - LightCache.saveFile(TEMP_FILE_PATH, TEMP_FILE_NAME, new byte[]{'a', 'b', 'c'}, false); - assertArrayEquals(new byte[]{'a', 'b', 'c'}, LightCache.loadFile(TEMP_FILE_FULL_NAME_PATH)); - } - - @Test - public void saveFileFullPath() { - LightCache.saveFile(TEMP_FILE_FULL_NAME_PATH, new byte[]{'a', 'b', 'c'}, false); - assertArrayEquals(new byte[]{'a', 'b', 'c'}, LightCache.loadFile(TEMP_FILE_FULL_NAME_PATH)); - } - - @Test - public void saveFileNoUpdate() { - LightCache.saveFile(TEMP_FILE_FULL_NAME_PATH, new byte[]{'a', 'b', 'c'}, false); - LightCache.saveFile(TEMP_FILE_FULL_NAME_PATH, new byte[]{'d', 'e', 'f'}, false); - assertArrayEquals(new byte[]{'a', 'b', 'c'}, LightCache.loadFile(TEMP_FILE_FULL_NAME_PATH)); - } - - @Test - public void saveFileForceUpdate() { - LightCache.saveFile(TEMP_FILE_FULL_NAME_PATH, new byte[]{'a', 'b', 'c'}, false); - LightCache.saveFile(TEMP_FILE_FULL_NAME_PATH, new byte[]{'d', 'e', 'f'}, true); - assertArrayEquals(new byte[]{'d', 'e', 'f'}, LightCache.loadFile(TEMP_FILE_FULL_NAME_PATH)); - } - - /** - * Target file is actually is a folder - */ - @Test - public void saveFileExistingFolder() { - assertTrue(new File(TEMP_FILE_FULL_NAME_PATH).mkdirs()); // create as folder - assertFalse(LightCache.saveFile(TEMP_FILE_FULL_NAME_PATH, new byte[]{'d', 'e', 'f'}, true)); - } - - @Test - public void deleteFileNoFile() { - assertFalse(LightCache.deleteFile(TEMP_FILE_PATH, TEMP_FILE_NAME)); - } - - @Test - public void deleteFileNormal() { - assertTrue(LightCache.saveFile(TEMP_FILE_FULL_NAME_PATH, new byte[]{'a', 'b', 'c'}, false)); - assertTrue(LightCache.deleteFile(TEMP_FILE_PATH, TEMP_FILE_NAME)); - } - - @Test - public void deleteFolder() { - assertTrue(new File(TEMP_FILE_FULL_NAME_PATH).mkdirs()); - assertTrue(LightCache.deleteFile(TEMP_FILE_FULL_NAME_PATH)); - } - - @Test - public void deleteFolderNotEmpty() { - assertTrue(new File(TEMP_FILE_FULL_NAME_PATH).mkdirs()); - assertFalse(LightCache.deleteFile(TEMP_FILE_PATH)); - } - - @Test - public void copyFileNoSourceFile() { - LightCache.copyFile(TEMP_FILE_NAME, TEMP_FILE_FULL_NAME_PATH, false); - assertFalse(LightCache.testFileExist(TEMP_FILE_FULL_NAME_PATH)); - } - - @Test - public void copyFileNormal() { - assertTrue(LightCache.saveFile(TEMP_FILE_NAME, new byte[]{'a', 'b', 'c'}, false)); - LightCache.copyFile(TEMP_FILE_NAME, TEMP_FILE_FULL_NAME_PATH, false); - assertTrue(LightCache.testFileExist(TEMP_FILE_FULL_NAME_PATH)); - assertTrue(LightCache.testFileExist(TEMP_FILE_NAME)); // original file still exists - } - - @Test - public void copyFileExistingNoForce() { - assertTrue(LightCache.saveFile(TEMP_FILE_NAME, new byte[]{'a', 'b', 'c'}, false)); - assertTrue(LightCache.saveFile(TEMP_FILE_FULL_NAME_PATH, new byte[]{'d', 'e', 'f'}, false)); - LightCache.copyFile(TEMP_FILE_NAME, TEMP_FILE_FULL_NAME_PATH, false); - assertTrue(LightCache.testFileExist(TEMP_FILE_FULL_NAME_PATH)); - assertArrayEquals(new byte[]{'d', 'e', 'f'}, LightCache.loadFile(TEMP_FILE_FULL_NAME_PATH)); - } - - @Test - public void copyFileExistingForce() { - assertTrue(LightCache.saveFile(TEMP_FILE_NAME, new byte[]{'a', 'b', 'c'}, false)); - assertTrue(LightCache.saveFile(TEMP_FILE_FULL_NAME_PATH, new byte[]{'d', 'e', 'f'}, false)); - LightCache.copyFile(TEMP_FILE_NAME, TEMP_FILE_FULL_NAME_PATH, true); - assertTrue(LightCache.testFileExist(TEMP_FILE_FULL_NAME_PATH)); - assertArrayEquals(new byte[]{'a', 'b', 'c'}, LightCache.loadFile(TEMP_FILE_FULL_NAME_PATH)); - } - -} From c99adfc29fb0afbef1d7131fb9641f0f59ee88f5 Mon Sep 17 00:00:00 2001 From: MewX Date: Tue, 24 Jul 2018 20:48:15 +0800 Subject: [PATCH 4/9] #32 Added unit tests for OldNovelContentParser and UserInfo --- .travis.yml | 2 +- .../global/api/OldNovelContentParserTest.java | 57 +++++++++++++++++++ .../mewx/wenku8/global/api/UserInfoTest.java | 36 ++++++++++++ .../wenku8/activity/NovelInfoActivity.java | 9 ++- .../wenku8/activity/UserInfoActivity.java | 18 +++--- .../activity/VerticalReaderActivity.java | 4 +- .../global/api/OldNovelContentParser.java | 38 +++++++------ .../org/mewx/wenku8/global/api/UserInfo.java | 23 ++++---- .../mewx/wenku8/global/api/VolumeList.java | 11 ++-- .../reader/loader/WenkuReaderLoaderXML.java | 17 +++--- .../org/mewx/wenku8/util/LightNetwork.java | 8 --- 11 files changed, 154 insertions(+), 69 deletions(-) create mode 100644 studio-android/LightNovelLibrary/app/src/androidTest/java/org/mewx/wenku8/global/api/OldNovelContentParserTest.java create mode 100644 studio-android/LightNovelLibrary/app/src/androidTest/java/org/mewx/wenku8/global/api/UserInfoTest.java diff --git a/.travis.yml b/.travis.yml index 4be9eecf..6211b21f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -35,5 +35,5 @@ before_install: - android-wait-for-emulator - adb shell input keyevent 82 & -script: ./gradlew build connectedAlphaDebugAndroidTest coveralls +script: ./gradlew assembleAlpha connectedAlphaDebugAndroidTest coveralls diff --git a/studio-android/LightNovelLibrary/app/src/androidTest/java/org/mewx/wenku8/global/api/OldNovelContentParserTest.java b/studio-android/LightNovelLibrary/app/src/androidTest/java/org/mewx/wenku8/global/api/OldNovelContentParserTest.java new file mode 100644 index 00000000..a41e7a29 --- /dev/null +++ b/studio-android/LightNovelLibrary/app/src/androidTest/java/org/mewx/wenku8/global/api/OldNovelContentParserTest.java @@ -0,0 +1,57 @@ +package org.mewx.wenku8.global.api; + +import org.junit.Test; + +import java.util.List; + +import static org.mewx.wenku8.global.api.OldNovelContentParser.NovelContentType.*; + +import static org.junit.Assert.assertEquals; + +public class OldNovelContentParserTest { + private static final String NOVEL_CONTENT = "line 1\r\n" + + " http://bbbbb.com/pictures/1/1339/90903/107724.jpg \r\n" + + " line 2 \r\n\r\n" + + "http://bbbbb.com/pictures/1/1339/90903/107725.jpg\r\n" + + "line 3\r\n"; + + @Test + public void parseNovelContent() { + List contents = OldNovelContentParser.parseNovelContent(NOVEL_CONTENT, null); + assertEquals(5, contents.size()); + + OldNovelContentParser.NovelContent tempContent = contents.get(0); + assertEquals(TEXT, tempContent.type); + assertEquals("line 1", tempContent.content); + + tempContent = contents.get(1); + assertEquals(IMAGE, tempContent.type); + assertEquals("http://bbbbb.com/pictures/1/1339/90903/107724.jpg", tempContent.content); + + tempContent = contents.get(2); + assertEquals(TEXT, tempContent.type); + assertEquals("line 2", tempContent.content); + + tempContent = contents.get(3); + assertEquals(IMAGE, tempContent.type); + assertEquals("http://bbbbb.com/pictures/1/1339/90903/107725.jpg", tempContent.content); + + tempContent = contents.get(4); + assertEquals(TEXT, tempContent.type); + assertEquals("line 3", tempContent.content); + } + + @Test + public void novelContentParser_onlyImage() { + List contents = OldNovelContentParser.NovelContentParser_onlyImage(NOVEL_CONTENT); + assertEquals(2, contents.size()); + + OldNovelContentParser.NovelContent tempContent = contents.get(0); + assertEquals(IMAGE, tempContent.type); + assertEquals("http://bbbbb.com/pictures/1/1339/90903/107724.jpg", tempContent.content); + + tempContent = contents.get(1); + assertEquals(IMAGE, tempContent.type); + assertEquals("http://bbbbb.com/pictures/1/1339/90903/107725.jpg", tempContent.content); + } +} \ No newline at end of file diff --git a/studio-android/LightNovelLibrary/app/src/androidTest/java/org/mewx/wenku8/global/api/UserInfoTest.java b/studio-android/LightNovelLibrary/app/src/androidTest/java/org/mewx/wenku8/global/api/UserInfoTest.java new file mode 100644 index 00000000..e1d2d058 --- /dev/null +++ b/studio-android/LightNovelLibrary/app/src/androidTest/java/org/mewx/wenku8/global/api/UserInfoTest.java @@ -0,0 +1,36 @@ +package org.mewx.wenku8.global.api; + +import android.support.test.filters.SmallTest; + +import org.junit.Test; + +import static org.junit.Assert.*; + +@SmallTest +public class UserInfoTest { + private static final String USER_INFO_XML = "\n" + + "\n" + + "\n" + + "\n" + + "100\n" + + "10\n" + + "\n" + + ""; + + @Test + public void parseUserInfo() { + UserInfo ui = UserInfo.parseUserInfo(USER_INFO_XML); + assertNotNull(ui); + assertEquals("apptest", ui.username); + assertEquals("apptest nick", ui.nickyname); + assertEquals(10, ui.experience); + assertEquals(100, ui.score); + assertEquals("新手上路", ui.rank); + } + + @Test + public void parseInvalidUserInfo() { + UserInfo ui = UserInfo.parseUserInfo("adfsdfasdfasdf"); + assertNull(ui); + } +} \ No newline at end of file diff --git a/studio-android/LightNovelLibrary/app/src/main/java/org/mewx/wenku8/activity/NovelInfoActivity.java b/studio-android/LightNovelLibrary/app/src/main/java/org/mewx/wenku8/activity/NovelInfoActivity.java index 9bd4ef27..2a04ded0 100644 --- a/studio-android/LightNovelLibrary/app/src/main/java/org/mewx/wenku8/activity/NovelInfoActivity.java +++ b/studio-android/LightNovelLibrary/app/src/main/java/org/mewx/wenku8/activity/NovelInfoActivity.java @@ -37,6 +37,7 @@ import org.mewx.wenku8.global.api.ChapterInfo; import org.mewx.wenku8.global.api.NovelItemMeta; import org.mewx.wenku8.global.api.OldNovelContentParser; +import org.mewx.wenku8.global.api.OldNovelContentParser.NovelContentType; import org.mewx.wenku8.global.api.VolumeList; import org.mewx.wenku8.global.api.Wenku8API; import org.mewx.wenku8.global.api.Wenku8Error; @@ -861,10 +862,9 @@ protected Wenku8Error.ErrorCode doInBackground(Integer... params) { // cache image if (GlobalConfig.doCacheImage()) { List nc = OldNovelContentParser.NovelContentParser_onlyImage(xml); - if (nc == null) return Wenku8Error.ErrorCode.NETWORK_ERROR; for (int i = 0; i < nc.size(); i++) { - if (nc.get(i).type == 'i') { + if (nc.get(i).type == NovelContentType.IMAGE) { pDialog.setMaxProgress(++size_a); // save this images, judge exist first @@ -972,7 +972,7 @@ protected Wenku8Error.ErrorCode doInBackground(Integer... params) { String result; try { result = new String(bytes, "UTF-8"); - Log.e("MewX", result); + Log.d("MewX", result); if (!LightTool.isInteger(result)) return Wenku8Error.ErrorCode.RETURNED_VALUE_EXCEPTION; if(Wenku8Error.getSystemDefinedErrorCode(Integer.parseInt(result)) != Wenku8Error.ErrorCode.SYSTEM_1_SUCCEEDED @@ -1075,10 +1075,9 @@ protected Wenku8Error.ErrorCode doInBackground(Integer[]... params) { // cache image if (GlobalConfig.doCacheImage()) { List nc = OldNovelContentParser.NovelContentParser_onlyImage(xml); - if (nc == null) return Wenku8Error.ErrorCode.NETWORK_ERROR; for (int i = 0; i < nc.size(); i++) { - if (nc.get(i).type == 'i') { + if (nc.get(i).type == NovelContentType.IMAGE) { size_a ++; // save this images, judge exist first diff --git a/studio-android/LightNovelLibrary/app/src/main/java/org/mewx/wenku8/activity/UserInfoActivity.java b/studio-android/LightNovelLibrary/app/src/main/java/org/mewx/wenku8/activity/UserInfoActivity.java index 482b1b0c..aa1c4a1a 100644 --- a/studio-android/LightNovelLibrary/app/src/main/java/org/mewx/wenku8/activity/UserInfoActivity.java +++ b/studio-android/LightNovelLibrary/app/src/main/java/org/mewx/wenku8/activity/UserInfoActivity.java @@ -55,7 +55,7 @@ protected void onCreate(Bundle savedInstanceState) { setContentView(R.layout.layout_account_info); // set indicator enable - Toolbar mToolbar = (Toolbar) findViewById(R.id.toolbar_actionbar); + Toolbar mToolbar = findViewById(R.id.toolbar_actionbar); setSupportActionBar(mToolbar); if(getSupportActionBar() != null) { getSupportActionBar().setDisplayHomeAsUpEnabled(true); @@ -85,13 +85,13 @@ protected void onCreate(Bundle savedInstanceState) { } // get views - rivAvatar = (RoundedImageView)findViewById(R.id.user_avatar); - tvUserName = (TextView)findViewById(R.id.username); - tvNickyName = (TextView)findViewById(R.id.nickname); - tvScore = (TextView)findViewById(R.id.score); - tvExperience = (TextView)findViewById(R.id.experience); - tvRank = (TextView)findViewById(R.id.rank); - tvLogout = (TextView)findViewById(R.id.btn_logout); + rivAvatar = findViewById(R.id.user_avatar); + tvUserName = findViewById(R.id.username); + tvNickyName = findViewById(R.id.nickname); + tvScore = findViewById(R.id.score); + tvExperience = findViewById(R.id.experience); + tvRank = findViewById(R.id.rank); + tvLogout = findViewById(R.id.btn_logout); // sync get info agui = new AsyncGetUserInfo(); @@ -154,7 +154,7 @@ else if(Wenku8Error.getSystemDefinedErrorCode(Integer.valueOf(new String(b))) == } Log.e("MewX", xml); - ui = UserInfo.parseUserInfo(new UserInfo(), xml); + ui = UserInfo.parseUserInfo(xml); if(ui == null) return Wenku8Error.ErrorCode.XML_PARSE_FAILED; return Wenku8Error.ErrorCode.SYSTEM_1_SUCCEEDED; diff --git a/studio-android/LightNovelLibrary/app/src/main/java/org/mewx/wenku8/activity/VerticalReaderActivity.java b/studio-android/LightNovelLibrary/app/src/main/java/org/mewx/wenku8/activity/VerticalReaderActivity.java index 1fd66c6d..716a90e9 100644 --- a/studio-android/LightNovelLibrary/app/src/main/java/org/mewx/wenku8/activity/VerticalReaderActivity.java +++ b/studio-android/LightNovelLibrary/app/src/main/java/org/mewx/wenku8/activity/VerticalReaderActivity.java @@ -242,7 +242,7 @@ protected void onPostExecute(Integer result) { pDialog.setProgress(i); switch (nc.get(i).type) { - case 't': + case TEXT: TextView tempTV = new TextView(VerticalReaderActivity.this); if (i == 0) { tempTV.setTextSize(TypedValue.COMPLEX_UNIT_SP, @@ -264,7 +264,7 @@ protected void onPostExecute(Integer result) { TextListLayout.addView(tempTV); break; - case 'i': + case IMAGE: final ImageView tempIV = new ImageView(VerticalReaderActivity.this); tempIV.setClickable(true); tempIV.setAdjustViewBounds(true); diff --git a/studio-android/LightNovelLibrary/app/src/main/java/org/mewx/wenku8/global/api/OldNovelContentParser.java b/studio-android/LightNovelLibrary/app/src/main/java/org/mewx/wenku8/global/api/OldNovelContentParser.java index 9b07f378..eaba5bcf 100644 --- a/studio-android/LightNovelLibrary/app/src/main/java/org/mewx/wenku8/global/api/OldNovelContentParser.java +++ b/studio-android/LightNovelLibrary/app/src/main/java/org/mewx/wenku8/global/api/OldNovelContentParser.java @@ -1,12 +1,11 @@ package org.mewx.wenku8.global.api; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; import android.util.Log; -import android.widget.Toast; import com.afollestad.materialdialogs.MaterialDialog; -import org.mewx.wenku8.MyApp; - import java.util.ArrayList; import java.util.List; @@ -15,12 +14,19 @@ * Old Novel Content Parser. */ public class OldNovelContentParser { + private static final String TAG = OldNovelContentParser.class.getSimpleName(); + + public enum NovelContentType { + TEXT, IMAGE + } + public static class NovelContent { - public char type = 't'; // 't' - text (default); 'i' - img + public NovelContentType type = NovelContentType.TEXT; public String content = ""; } - public static List parseNovelContent(String raw, MaterialDialog pDialog) { + @NonNull + public static List parseNovelContent(@NonNull String raw, @Nullable MaterialDialog pDialog) { List result = new ArrayList<>(); // use split @@ -42,7 +48,7 @@ public static List parseNovelContent(String raw, MaterialDialog pD temp = t.indexOf("", 0); if (temp == -1) { NovelContent nc = new NovelContent(); - nc.type = 't'; + nc.type = NovelContentType.TEXT; nc.content = t.trim(); //.replaceAll("[ | ]", " ").trim(); result.add(nc); @@ -50,7 +56,7 @@ public static List parseNovelContent(String raw, MaterialDialog pD if (pDialog != null) pDialog.setMaxProgress(result.size()); } else { - Log.v("MewX", "img index = " + temp); + Log.d(TAG, "img index = " + temp); // nc.content = nc.content.substring(temp + 12, // nc.content.indexOf("", temp + 12)); @@ -64,16 +70,15 @@ public static List parseNovelContent(String raw, MaterialDialog pD NovelContent nc2 = new NovelContent(); int t2 = t.indexOf("", temp + 12); if (t2 < 0) { - Log.v("MewX", "Breaked in parseNovelContent, t2 = " - + t2); + Log.d(TAG, "Broke in parseNovelContent, t2 = " + t2); NovelContent nc = new NovelContent(); - nc.type = 't'; + nc.type = NovelContentType.TEXT; nc.content = t; result.add(nc); break; } nc2.content = t.substring(temp + 12, t2); - nc2.type = 'i'; + nc2.type = NovelContentType.IMAGE; result.add(nc2); temp = t2 + 12; @@ -89,7 +94,8 @@ public static List parseNovelContent(String raw, MaterialDialog pD } - public static List NovelContentParser_onlyImage(String raw) { + @NonNull + public static List NovelContentParser_onlyImage(@NonNull String raw) { List result = new ArrayList<>(); // use split @@ -99,7 +105,7 @@ public static List NovelContentParser_onlyImage(String raw) { // test temp = t.indexOf("", 0); if (temp != -1) { - Log.v("MewX", "img index = " + temp); + Log.d(TAG, "img index = " + temp); // nc.content = nc.content.substring(temp + 12, // nc.content.indexOf("", temp + 12)); @@ -113,13 +119,11 @@ public static List NovelContentParser_onlyImage(String raw) { NovelContent nc2 = new NovelContent(); int t2 = t.indexOf("", temp + 12); if (t2 < 0) { - Log.v("MewX", - "Breaked in NovelContentParser_onlyImage, t2 = " - + t2); + Log.d(TAG, "Breaked in NovelContentParser_onlyImage, t2 = " + t2); break; } nc2.content = t.substring(temp + 12, t2); - nc2.type = 'i'; + nc2.type = NovelContentType.IMAGE; result.add(nc2); temp = t2 + 12; diff --git a/studio-android/LightNovelLibrary/app/src/main/java/org/mewx/wenku8/global/api/UserInfo.java b/studio-android/LightNovelLibrary/app/src/main/java/org/mewx/wenku8/global/api/UserInfo.java index 174e384a..dfd32b23 100644 --- a/studio-android/LightNovelLibrary/app/src/main/java/org/mewx/wenku8/global/api/UserInfo.java +++ b/studio-android/LightNovelLibrary/app/src/main/java/org/mewx/wenku8/global/api/UserInfo.java @@ -1,5 +1,7 @@ package org.mewx.wenku8.global.api; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; import android.util.Log; import org.mewx.wenku8.global.GlobalConfig; @@ -13,7 +15,7 @@ * User Info. */ public class UserInfo { - /** + /* * * * @@ -30,9 +32,10 @@ public class UserInfo { public int experience; // 经验值 public String rank; - public static UserInfo parseUserInfo(UserInfo ui, String xml) { - + @Nullable + public static UserInfo parseUserInfo(@NonNull String xml) { try { + UserInfo ui = new UserInfo(); XmlPullParserFactory factory = XmlPullParserFactory.newInstance(); XmlPullParser xmlPullParser = factory.newPullParser(); xmlPullParser.setInput(new StringReader(xml)); @@ -48,23 +51,19 @@ public static UserInfo parseUserInfo(UserInfo ui, String xml) { // root tag break; } else if ("item".equals(xmlPullParser.getName())) { - if("uname".equals(xmlPullParser.getAttributeValue(0))) { + if ("uname".equals(xmlPullParser.getAttributeValue(0))) { ui.username = xmlPullParser.nextText(); Log.e("MewX", ui.username.length() == 0 ? GlobalConfig.UNKNOWN : ui.username); - } - else if("nickname".equals(xmlPullParser.getAttributeValue(0))) { + } else if ("nickname".equals(xmlPullParser.getAttributeValue(0))) { ui.nickyname = xmlPullParser.nextText(); Log.e("MewX", ui.nickyname.length() == 0 ? GlobalConfig.UNKNOWN : ui.nickyname); - } - else if("score".equals(xmlPullParser.getAttributeValue(0))) { + } else if ("score".equals(xmlPullParser.getAttributeValue(0))) { ui.score = Integer.valueOf(xmlPullParser.nextText()); Log.e("MewX", "score:" + ui.score); - } - else if("experience".equals(xmlPullParser.getAttributeValue(0))) { + } else if ("experience".equals(xmlPullParser.getAttributeValue(0))) { ui.experience = Integer.valueOf(xmlPullParser.nextText()); Log.e("MewX", "experience:" + ui.experience); - } - else if("rank".equals(xmlPullParser.getAttributeValue(0))) { + } else if ("rank".equals(xmlPullParser.getAttributeValue(0))) { ui.rank = xmlPullParser.nextText(); Log.e("MewX", ui.rank.length() == 0 ? GlobalConfig.UNKNOWN : ui.rank); } diff --git a/studio-android/LightNovelLibrary/app/src/main/java/org/mewx/wenku8/global/api/VolumeList.java b/studio-android/LightNovelLibrary/app/src/main/java/org/mewx/wenku8/global/api/VolumeList.java index 231a1c34..48fb4892 100644 --- a/studio-android/LightNovelLibrary/app/src/main/java/org/mewx/wenku8/global/api/VolumeList.java +++ b/studio-android/LightNovelLibrary/app/src/main/java/org/mewx/wenku8/global/api/VolumeList.java @@ -2,11 +2,9 @@ import org.mewx.wenku8.global.GlobalConfig; import org.mewx.wenku8.util.LightCache; -import org.mewx.wenku8.util.LightNetwork; import java.io.File; import java.io.Serializable; -import java.io.UnsupportedEncodingException; import java.util.ArrayList; import java.util.List; @@ -23,19 +21,18 @@ public class VolumeList implements Serializable { public void cleanLocalCache() { for (ChapterInfo tempCi : this.chapterList) { String xml = GlobalConfig.loadFullFileFromSaveFolder("novel", tempCi.cid + ".xml"); - if (xml == null || xml.length() == 0) { + if (xml.length() == 0) { return; } List nc = OldNovelContentParser.NovelContentParser_onlyImage(xml); - if (nc == null) return; for (int i = 0; i < nc.size(); i++) { - if (nc.get(i).type == 'i'){ + if (nc.get(i).type == OldNovelContentParser.NovelContentType.IMAGE) { String imgFileName = GlobalConfig.generateImageFileNameByURL(nc.get(i).content); LightCache.deleteFile( - GlobalConfig.getFirstFullSaveFilePath()+ + GlobalConfig.getFirstFullSaveFilePath() + GlobalConfig.imgsSaveFolderName + File.separator + imgFileName); LightCache.deleteFile( - GlobalConfig.getSecondFullSaveFilePath()+ + GlobalConfig.getSecondFullSaveFilePath() + GlobalConfig.imgsSaveFolderName + File.separator + imgFileName); } } diff --git a/studio-android/LightNovelLibrary/app/src/main/java/org/mewx/wenku8/reader/loader/WenkuReaderLoaderXML.java b/studio-android/LightNovelLibrary/app/src/main/java/org/mewx/wenku8/reader/loader/WenkuReaderLoaderXML.java index 14701455..164513c3 100644 --- a/studio-android/LightNovelLibrary/app/src/main/java/org/mewx/wenku8/reader/loader/WenkuReaderLoaderXML.java +++ b/studio-android/LightNovelLibrary/app/src/main/java/org/mewx/wenku8/reader/loader/WenkuReaderLoaderXML.java @@ -5,6 +5,7 @@ import org.mewx.wenku8.global.GlobalConfig; import org.mewx.wenku8.global.api.OldNovelContentParser; +import org.mewx.wenku8.global.api.OldNovelContentParser.NovelContentType; import java.util.List; @@ -43,11 +44,11 @@ public boolean hasNext(int wordIndex) { } else { // last one - if(nc.get(currentIndex).type == 't' && wordIndex + 1 < nc.get(currentIndex).content.length()) { + if(nc.get(currentIndex).type == NovelContentType.TEXT && wordIndex + 1 < nc.get(currentIndex).content.length()) { // text but not last word return true; } - else if(nc.get(currentIndex).type != 't' && wordIndex == 0) { + else if(nc.get(currentIndex).type != NovelContentType.TEXT && wordIndex == 0) { // image return true; } @@ -66,11 +67,11 @@ public boolean hasPrevious(int wordIndex) { } else { // first one - if(nc.get(currentIndex).type == 't' && wordIndex - 1 >= 0) { + if(nc.get(currentIndex).type == NovelContentType.TEXT && wordIndex - 1 >= 0) { // one more word ahead return true; } - else if(nc.get(currentIndex).type != 't' && wordIndex == nc.get(currentIndex).content.length() - 1) + else if(nc.get(currentIndex).type != NovelContentType.TEXT && wordIndex == nc.get(currentIndex).content.length() - 1) // image previous use index last return true; } @@ -232,10 +233,10 @@ public void closeLoader() { nc = null; } - private ElementType intepreteOldSign(char s) { - switch (s) { - case 't': return ElementType.TEXT; - case 'i': return ElementType.IMAGE_DEPENDENT; + private ElementType intepreteOldSign(NovelContentType type) { + switch (type) { + case TEXT: return ElementType.TEXT; + case IMAGE: return ElementType.IMAGE_DEPENDENT; default: return ElementType.TEXT; } } diff --git a/studio-android/LightNovelLibrary/app/src/main/java/org/mewx/wenku8/util/LightNetwork.java b/studio-android/LightNovelLibrary/app/src/main/java/org/mewx/wenku8/util/LightNetwork.java index 786b41d4..d16d60b7 100644 --- a/studio-android/LightNovelLibrary/app/src/main/java/org/mewx/wenku8/util/LightNetwork.java +++ b/studio-android/LightNovelLibrary/app/src/main/java/org/mewx/wenku8/util/LightNetwork.java @@ -55,11 +55,6 @@ public static String encodeToHttp(String str) { */ @Nullable public static byte[] LightHttpPostConnection(String u, ContentValues values) { - - // a replacer -// u = u.replace(fromEle, toEle); -// long start = System.currentTimeMillis(); - // new API, initial URL url; HttpURLConnection http; @@ -116,9 +111,6 @@ public static byte[] LightHttpPostConnection(String u, ContentValues values) { outStream.close(); inStream.close(); -// long elapsed = System.currentTimeMillis() - start; -// Log.e("MewX-Net", "page fetched in " + elapsed + "ms"); - return data; // return value } catch (IOException e) { From 6fe878d72602c8d319be077a9d2148f9a6e8681e Mon Sep 17 00:00:00 2001 From: MewX Date: Tue, 24 Jul 2018 23:18:08 +0800 Subject: [PATCH 5/9] #32 Added unit tests for NovelItemInfoUpdate and NovelListWithInfoParser --- .../global/api/NovelItemInfoUpdateTest.java | 64 ++++++++ .../api/NovelListWithInfoParserTest.java | 69 +++++++++ .../global/api/OldNovelContentParserTest.java | 31 ++++ .../wenku8/global/api/Wenku8ParserTest.java | 13 ++ .../mewx/wenku8/fragment/LatestFragment.java | 2 +- .../global/api/NovelItemInfoUpdate.java | 39 ++--- .../mewx/wenku8/global/api/NovelItemList.java | 125 ---------------- .../global/api/NovelListWithInfoParser.java | 10 +- .../global/api/OldNovelContentParser.java | 4 +- .../mewx/wenku8/global/api/ReviewList.java | 22 +-- .../wenku8/global/api/ReviewReplyList.java | 8 +- .../activity/Wenku8ReaderActivityV1.java | 139 ++++++++---------- .../reader/loader/WenkuReaderLoaderXML.java | 5 +- .../reader/view/WenkuReaderPageView.java | 53 +++---- 14 files changed, 305 insertions(+), 279 deletions(-) create mode 100644 studio-android/LightNovelLibrary/app/src/androidTest/java/org/mewx/wenku8/global/api/NovelItemInfoUpdateTest.java create mode 100644 studio-android/LightNovelLibrary/app/src/androidTest/java/org/mewx/wenku8/global/api/NovelListWithInfoParserTest.java delete mode 100644 studio-android/LightNovelLibrary/app/src/main/java/org/mewx/wenku8/global/api/NovelItemList.java diff --git a/studio-android/LightNovelLibrary/app/src/androidTest/java/org/mewx/wenku8/global/api/NovelItemInfoUpdateTest.java b/studio-android/LightNovelLibrary/app/src/androidTest/java/org/mewx/wenku8/global/api/NovelItemInfoUpdateTest.java new file mode 100644 index 00000000..1c0c9244 --- /dev/null +++ b/studio-android/LightNovelLibrary/app/src/androidTest/java/org/mewx/wenku8/global/api/NovelItemInfoUpdateTest.java @@ -0,0 +1,64 @@ +package org.mewx.wenku8.global.api; + +import org.junit.Test; + +import static org.junit.Assert.*; + +public class NovelItemInfoUpdateTest { + + @Test + public void convertFromMeta() { + final String META_XML = "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + ""; + NovelItemMeta meta = Wenku8Parser.parseNovelFullMeta(META_XML); + assertNotNull(meta); + + NovelItemInfoUpdate info = NovelItemInfoUpdate.convertFromMeta(meta); + assertEquals("向森之魔物献上花束(向森林的魔兽少女献花)", info.title); + assertEquals(1306, info.aid); + assertEquals("小木君人", info.author); + assertEquals("已完成", info.status); + assertEquals("2012-11-02", info.update); + assertEquals("第一卷 插图", info.latest_chapter); + } + + @Test + public void parseNovelItemInfoUpdate() { + final String XML = "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + ""; + NovelItemInfoUpdate info = NovelItemInfoUpdate.parse(XML); + assertNotNull(info); + + assertEquals("绝对双刃absolute duo", info.title); + assertEquals(1305, info.aid); + assertEquals("柊★巧", info.author); + assertEquals("连载中", info.status); + assertEquals("2014-10-01", info.update); + assertEquals("「焰牙」——那是藉由超化之后的精神力将自身灵...", info.intro_short); + } + + @Test + public void parseNovelItemInfoUpdateInvalid() { + NovelItemInfoUpdate info = NovelItemInfoUpdate.parse("1234"); + assertNull(info); + } +} \ No newline at end of file diff --git a/studio-android/LightNovelLibrary/app/src/androidTest/java/org/mewx/wenku8/global/api/NovelListWithInfoParserTest.java b/studio-android/LightNovelLibrary/app/src/androidTest/java/org/mewx/wenku8/global/api/NovelListWithInfoParserTest.java new file mode 100644 index 00000000..5f1e40c0 --- /dev/null +++ b/studio-android/LightNovelLibrary/app/src/androidTest/java/org/mewx/wenku8/global/api/NovelListWithInfoParserTest.java @@ -0,0 +1,69 @@ +package org.mewx.wenku8.global.api; + +import org.junit.Test; + +import java.util.List; + +import static org.junit.Assert.*; + +public class NovelListWithInfoParserTest { + private static final String XML = "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + ""; + + @Test + public void getNovelListWithInfoPageNum() { + assertEquals(166, NovelListWithInfoParser.getNovelListWithInfoPageNum(XML)); + } + + + @Test + public void getNovelListWithInfoInvalid() { + List list = NovelListWithInfoParser.getNovelListWithInfo("1234"); + assertTrue(list.isEmpty()); + } + + @Test + public void getNovelListWithInfo() { + List list = NovelListWithInfoParser.getNovelListWithInfo(XML); + assertEquals(2, list.size()); + + NovelListWithInfoParser.NovelListWithInfo info = list.get(0); + assertEquals(1034, info.aid); + assertEquals(14416, info.fav); + assertEquals(2316361, info.hit); + assertEquals(153422, info.push); + assertEquals("恶魔高校DxD(High School DxD)", info.name); + + info = list.get(1); + assertEquals(1035, info.aid); + assertEquals(789, info.fav); + assertEquals(1234, info.hit); + assertEquals(4567, info.push); + assertEquals("High School DxD", info.name); + } +} \ No newline at end of file diff --git a/studio-android/LightNovelLibrary/app/src/androidTest/java/org/mewx/wenku8/global/api/OldNovelContentParserTest.java b/studio-android/LightNovelLibrary/app/src/androidTest/java/org/mewx/wenku8/global/api/OldNovelContentParserTest.java index a41e7a29..29564282 100644 --- a/studio-android/LightNovelLibrary/app/src/androidTest/java/org/mewx/wenku8/global/api/OldNovelContentParserTest.java +++ b/studio-android/LightNovelLibrary/app/src/androidTest/java/org/mewx/wenku8/global/api/OldNovelContentParserTest.java @@ -41,6 +41,37 @@ public void parseNovelContent() { assertEquals("line 3", tempContent.content); } + @Test + public void parseNovelContentWithIncompleteImageTag() { + final String BROKEN_XML = "line 1\r\n" + + " http://bbbbb.com/pictures/1/1339/90903/107724.jpg \r\n" + + " line 2 \r\n\r\n" + + " http://bbbbb.com/pictures/1/1339/90903/107725.jpg \r\n" + + "line 3\r\n"; + List contents = OldNovelContentParser.parseNovelContent(BROKEN_XML, null); + assertEquals(5, contents.size()); + + OldNovelContentParser.NovelContent tempContent = contents.get(0); + assertEquals(TEXT, tempContent.type); + assertEquals("line 1", tempContent.content); + + tempContent = contents.get(1); + assertEquals(IMAGE, tempContent.type); + assertEquals("http://bbbbb.com/pictures/1/1339/90903/107724.jpg", tempContent.content); + + tempContent = contents.get(2); + assertEquals(TEXT, tempContent.type); + assertEquals("line 2", tempContent.content); + + tempContent = contents.get(3); + assertEquals(TEXT, tempContent.type); + assertEquals("http://bbbbb.com/pictures/1/1339/90903/107725.jpg", tempContent.content); + + tempContent = contents.get(4); + assertEquals(TEXT, tempContent.type); + assertEquals("line 3", tempContent.content); + } + @Test public void novelContentParser_onlyImage() { List contents = OldNovelContentParser.NovelContentParser_onlyImage(NOVEL_CONTENT); diff --git a/studio-android/LightNovelLibrary/app/src/androidTest/java/org/mewx/wenku8/global/api/Wenku8ParserTest.java b/studio-android/LightNovelLibrary/app/src/androidTest/java/org/mewx/wenku8/global/api/Wenku8ParserTest.java index 4500ebab..561c808f 100644 --- a/studio-android/LightNovelLibrary/app/src/androidTest/java/org/mewx/wenku8/global/api/Wenku8ParserTest.java +++ b/studio-android/LightNovelLibrary/app/src/androidTest/java/org/mewx/wenku8/global/api/Wenku8ParserTest.java @@ -74,6 +74,12 @@ public void testParseReviewList() { Assert.assertEquals(review.getTitle(), "有种神曲奏界的既视感"); } + @Test + public void testParseReviewListInvalid() { + ReviewList reviewList = new ReviewList(); + Wenku8Parser.parseReviewList(reviewList, "1324"); + Assert.assertTrue(reviewList.getList().isEmpty()); + } @Test public void testParseReviewListPageTwo() { @@ -170,6 +176,13 @@ public void testParseReviewReplyList() { Assert.assertEquals(reviewReply.getContent(), "滑稽✧(`ῧ′)机智"); } + @Test + public void testParseReviewReplyListInvalid() { + ReviewReplyList reviewReplyList = new ReviewReplyList(); + Wenku8Parser.parseReviewReplyList(reviewReplyList, "1234"); + Assert.assertTrue(reviewReplyList.getList().isEmpty()); + } + @Test public void testParseReviewReplyListPage2() { final String REVIEW_REPLY_LIST_XML_PAGE_2 = "\n" + diff --git a/studio-android/LightNovelLibrary/app/src/main/java/org/mewx/wenku8/fragment/LatestFragment.java b/studio-android/LightNovelLibrary/app/src/main/java/org/mewx/wenku8/fragment/LatestFragment.java index b07219ae..82bca947 100644 --- a/studio-android/LightNovelLibrary/app/src/main/java/org/mewx/wenku8/fragment/LatestFragment.java +++ b/studio-android/LightNovelLibrary/app/src/main/java/org/mewx/wenku8/fragment/LatestFragment.java @@ -209,7 +209,7 @@ protected Integer doInBackground(ContentValues... params) { String xml = new String(tempXml, "UTF-8"); totalPage = NovelListWithInfoParser.getNovelListWithInfoPageNum(xml); List l = NovelListWithInfoParser.getNovelListWithInfo(xml); - if (l == null) + if (l.isEmpty()) return -100; // network error if (listNovelItemInfo == null) diff --git a/studio-android/LightNovelLibrary/app/src/main/java/org/mewx/wenku8/global/api/NovelItemInfoUpdate.java b/studio-android/LightNovelLibrary/app/src/main/java/org/mewx/wenku8/global/api/NovelItemInfoUpdate.java index a14f7755..8c84d2ea 100644 --- a/studio-android/LightNovelLibrary/app/src/main/java/org/mewx/wenku8/global/api/NovelItemInfoUpdate.java +++ b/studio-android/LightNovelLibrary/app/src/main/java/org/mewx/wenku8/global/api/NovelItemInfoUpdate.java @@ -1,5 +1,8 @@ package org.mewx.wenku8.global.api; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; + import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserFactory; @@ -10,27 +13,23 @@ * The updated version of novel item info. */ public class NovelItemInfoUpdate { - private final String LoadingString = "Loading..."; + private static final String LOADING_STRING = "Loading..."; // Variables - public int aid = 0; - public String title = LoadingString; - public String author = LoadingString; - public String status = LoadingString; - public String update = LoadingString; // last update time - public String intro_short = LoadingString; - public String latest_chapter = LoadingString; // only used in bookshelf - public boolean isLoading = false; - - public String intro_full = ""; // not necessary - public boolean imageReady = false; // image + public int aid; + public String title; + public String author = LOADING_STRING; + public String status = LOADING_STRING; + public String update = LOADING_STRING; // last update time + public String intro_short = LOADING_STRING; + public String latest_chapter = LOADING_STRING; // only used in bookshelf // static function - public static NovelItemInfoUpdate convertFromMeta(NovelItemMeta nim) { + @NonNull + public static NovelItemInfoUpdate convertFromMeta(@NonNull NovelItemMeta nim) { NovelItemInfoUpdate niiu = new NovelItemInfoUpdate(0); niiu.title = nim.title; niiu.aid = nim.aid; - niiu.title = nim.title; niiu.author = nim.author; niiu.status = nim.bookStatus; niiu.update = nim.lastUpdate; @@ -39,9 +38,10 @@ public static NovelItemInfoUpdate convertFromMeta(NovelItemMeta nim) { return niiu; } - public static NovelItemInfoUpdate parse(String xml) { - NovelItemInfoUpdate niiu = new NovelItemInfoUpdate(0); + @Nullable + public static NovelItemInfoUpdate parse(@NonNull String xml) { try { + NovelItemInfoUpdate niiu = new NovelItemInfoUpdate(0); XmlPullParserFactory factory = XmlPullParserFactory.newInstance(); XmlPullParser xmlPullParser = factory.newPullParser(); xmlPullParser.setInput(new StringReader(xml)); @@ -62,7 +62,6 @@ public static NovelItemInfoUpdate parse(String xml) { niiu.status = ""; niiu.update = ""; niiu.intro_short = ""; - niiu.intro_full = ""; niiu.latest_chapter = ""; } else if ("data".equals(xmlPullParser.getName())) { @@ -101,10 +100,4 @@ public NovelItemInfoUpdate(int aid) { this.title = Integer.toString(aid); } - /** - * "get" functions - */ - public void setIntroFull(String str) { - intro_full = str; - } } diff --git a/studio-android/LightNovelLibrary/app/src/main/java/org/mewx/wenku8/global/api/NovelItemList.java b/studio-android/LightNovelLibrary/app/src/main/java/org/mewx/wenku8/global/api/NovelItemList.java deleted file mode 100644 index 5952f554..00000000 --- a/studio-android/LightNovelLibrary/app/src/main/java/org/mewx/wenku8/global/api/NovelItemList.java +++ /dev/null @@ -1,125 +0,0 @@ -package org.mewx.wenku8.global.api; - -import android.util.Log; - -import org.mewx.wenku8.global.GlobalConfig; -import org.mewx.wenku8.util.LightTool; - -import java.util.ArrayList; -import java.util.List; - -/** - * Created by MewX on 2015/1/21. - * Novel Item List. - */ -public class NovelItemList { - - - List l; - int currentPage; - int totalPage; - int lastRecord; // this save the last add number for reversing operation - - // Variables - private boolean parseStatus; // default false - - /** - * Init the whole struct with the received XML string - * - * @param str only str[0] is available, because I use array for pass by reference - */ - public NovelItemList(String[] str, int page) { - setNovelItemList(str, page); - } - - public NovelItemList() { - // init all values - parseStatus = false; - currentPage = 1; - totalPage = 1; - } - - public void setNovelItemList(String[] str, int page) { - parseStatus = parseNovelItemList(str, page); - } - - /** - * get parse status - * - * @return true - parsed, else failed. - */ - public boolean getParseStatus() { - return parseStatus; - } - - public int getTotalPage() { - return totalPage; - } - - public int getCurrentPage() { - return currentPage; - } - - public List getNovelItemList() { - return l; - } - - private boolean parseNovelItemList(String[] str, int page) { - // - // - // - // - // - // - // - // - // - // - // - // - // - // - - final char SEPERATOR = '\''; // seperator - //if( page > totalPage ) return true; - currentPage = page; - if(l!=null) { - lastRecord = l.size()==0?0:l.size()/10*10; // save last size - Log.i("MewX","set lastRecord: "+Integer.toString(lastRecord)); - } - else - lastRecord = 0; - - // get total page - int beg, temp; - beg = str[0].indexOf(SEPERATOR); - temp = str[0].indexOf(SEPERATOR, beg + 1); - if (beg == -1 || temp == -1) return false; // this is an exception - if(LightTool.isInteger(str[0].substring(beg + 1, temp))) - totalPage = Integer.parseInt(str[0].substring(beg + 1, temp)); - Log.v("MewX", "TotalPage = " + totalPage + "; CurrentPage = " + currentPage + "."); - beg = temp + 1; // prepare for loop - - // init array - if(l==null) - l = new ArrayList<>(); - while (true) { - beg = str[0].indexOf(SEPERATOR, beg); - temp = str[0].indexOf(SEPERATOR, beg + 1); - if (beg == -1 || temp == -1) break; - - if(LightTool.isInteger(str[0].substring(beg + 1, temp))) - l.add(Integer.parseInt(str[0].substring(beg + 1, temp))); - Log.v("MewX", "Add novel aid: " + l.get(l.size() - 1)); - - beg = temp + 1; // prepare for next round - } - - return true; - } - - public void requestForReverse(){ - for( int i = lastRecord; i < l.size(); i ++ ) - l.remove(lastRecord); - } -} diff --git a/studio-android/LightNovelLibrary/app/src/main/java/org/mewx/wenku8/global/api/NovelListWithInfoParser.java b/studio-android/LightNovelLibrary/app/src/main/java/org/mewx/wenku8/global/api/NovelListWithInfoParser.java index 24189cdc..0ee60d7e 100644 --- a/studio-android/LightNovelLibrary/app/src/main/java/org/mewx/wenku8/global/api/NovelListWithInfoParser.java +++ b/studio-android/LightNovelLibrary/app/src/main/java/org/mewx/wenku8/global/api/NovelListWithInfoParser.java @@ -1,5 +1,6 @@ package org.mewx.wenku8.global.api; +import android.support.annotation.NonNull; import android.util.Log; import org.xmlpull.v1.XmlPullParser; @@ -7,6 +8,7 @@ import java.io.StringReader; import java.util.ArrayList; +import java.util.List; /** Novel List With Info for improve loading speed. * Created by MewX on 2015/10/20. @@ -46,11 +48,12 @@ static public int getNovelListWithInfoPageNum(String xml) { return 0; // default } - static public ArrayList getNovelListWithInfo(String xml) { + @NonNull + static public List getNovelListWithInfo(String xml) { + List l = new ArrayList<>(); try { XmlPullParserFactory factory = XmlPullParserFactory.newInstance(); XmlPullParser xmlPullParser = factory.newPullParser(); - ArrayList l = new ArrayList<>(); NovelListWithInfo n = new NovelListWithInfo(); xmlPullParser.setInput(new StringReader(xml)); int eventType = xmlPullParser.getEventType(); @@ -84,10 +87,9 @@ static public ArrayList getNovelListWithInfo(String xml) { } eventType = xmlPullParser.next(); } - return l; } catch (Exception e) { e.printStackTrace(); - return null; } + return l; } } diff --git a/studio-android/LightNovelLibrary/app/src/main/java/org/mewx/wenku8/global/api/OldNovelContentParser.java b/studio-android/LightNovelLibrary/app/src/main/java/org/mewx/wenku8/global/api/OldNovelContentParser.java index eaba5bcf..8bc11896 100644 --- a/studio-android/LightNovelLibrary/app/src/main/java/org/mewx/wenku8/global/api/OldNovelContentParser.java +++ b/studio-android/LightNovelLibrary/app/src/main/java/org/mewx/wenku8/global/api/OldNovelContentParser.java @@ -70,10 +70,10 @@ public static List parseNovelContent(@NonNull String raw, @Nullabl NovelContent nc2 = new NovelContent(); int t2 = t.indexOf("", temp + 12); if (t2 < 0) { - Log.d(TAG, "Broke in parseNovelContent, t2 = " + t2); + Log.d(TAG, "Incomplete image pair, t2 = " + t2); NovelContent nc = new NovelContent(); nc.type = NovelContentType.TEXT; - nc.content = t; + nc.content = t.trim(); result.add(nc); break; } diff --git a/studio-android/LightNovelLibrary/app/src/main/java/org/mewx/wenku8/global/api/ReviewList.java b/studio-android/LightNovelLibrary/app/src/main/java/org/mewx/wenku8/global/api/ReviewList.java index c468f9c9..a56f0a39 100644 --- a/studio-android/LightNovelLibrary/app/src/main/java/org/mewx/wenku8/global/api/ReviewList.java +++ b/studio-android/LightNovelLibrary/app/src/main/java/org/mewx/wenku8/global/api/ReviewList.java @@ -10,21 +10,21 @@ public class ReviewList { public static class Review { private int rid; // review id - @NonNull private Date postTime; + @NonNull private Date postTime = new Date(); private int noReplies; - @NonNull private Date lastReplyTime; - @NonNull private String userName; + @NonNull private Date lastReplyTime = new Date(); + @NonNull private String userName = ""; private int uid; // post user - @NonNull private String title; // review title + @NonNull private String title = ""; // review title public Review(int rid, @NonNull Date postTime, int noReplies, @NonNull Date lastReplyTime, @NonNull String userName, int uid, @NonNull String title) { - this.rid = rid; - this.postTime = postTime; - this.noReplies = noReplies; - this.lastReplyTime = lastReplyTime; - this.userName = userName; - this.uid = uid; - this.title = title; + setRid(rid); + setPostTime(postTime); + setNoReplies(noReplies); + setLastReplyTime(lastReplyTime); + setUserName(userName); + setUid(uid); + setTitle(title); } public int getRid() { diff --git a/studio-android/LightNovelLibrary/app/src/main/java/org/mewx/wenku8/global/api/ReviewReplyList.java b/studio-android/LightNovelLibrary/app/src/main/java/org/mewx/wenku8/global/api/ReviewReplyList.java index 1af8f1ed..6c5f3e74 100644 --- a/studio-android/LightNovelLibrary/app/src/main/java/org/mewx/wenku8/global/api/ReviewReplyList.java +++ b/studio-android/LightNovelLibrary/app/src/main/java/org/mewx/wenku8/global/api/ReviewReplyList.java @@ -15,10 +15,10 @@ public static class ReviewReply { @NonNull private String content; public ReviewReply(@NonNull Date replyTime, @NonNull String userName, int uid, @NonNull String content) { - this.replyTime = replyTime; - this.userName = userName; - this.uid = uid; - this.content = content; + setReplyTime(replyTime); + setUserName(userName); + setUid(uid); + setContent(content); } @NonNull diff --git a/studio-android/LightNovelLibrary/app/src/main/java/org/mewx/wenku8/reader/activity/Wenku8ReaderActivityV1.java b/studio-android/LightNovelLibrary/app/src/main/java/org/mewx/wenku8/reader/activity/Wenku8ReaderActivityV1.java index 23f272ee..f9b9f866 100644 --- a/studio-android/LightNovelLibrary/app/src/main/java/org/mewx/wenku8/reader/activity/Wenku8ReaderActivityV1.java +++ b/studio-android/LightNovelLibrary/app/src/main/java/org/mewx/wenku8/reader/activity/Wenku8ReaderActivityV1.java @@ -68,7 +68,7 @@ public class Wenku8ReaderActivityV1 extends AppCompatActivity { private int aid, cid; private String forcejump; private VolumeList volumeList= null; - private List nc; + private List nc = new ArrayList<>(); private RelativeLayout mSliderHolder; private SlidingLayout sl; // private int tempNavBarHeight; @@ -195,12 +195,9 @@ private void showNavigationBar() { // Without this, after pressing volume buttons, the navigation bar will // show up and won't hide final View decorView = getWindow().getDecorView(); - decorView.setOnSystemUiVisibilityChangeListener(new View.OnSystemUiVisibilityChangeListener() { - @Override - public void onSystemUiVisibilityChange(int visibility) { - if((visibility & View.SYSTEM_UI_FLAG_FULLSCREEN) == 0) { - decorView.setSystemUiVisibility(flags); - } + decorView.setOnSystemUiVisibilityChangeListener(visibility -> { + if((visibility & View.SYSTEM_UI_FLAG_FULLSCREEN) == 0) { + decorView.setSystemUiVisibility(flags); } }); } @@ -416,7 +413,7 @@ protected Wenku8Error.ErrorCode doInBackground(ContentValues... params) { } nc = OldNovelContentParser.parseNovelContent(xml, null); - if (nc == null || nc.size() == 0) + if (nc.size() == 0) return xml.length() == 0 ? Wenku8Error.ErrorCode.SERVER_RETURN_NOTHING : Wenku8Error.ErrorCode.XML_PARSE_FAILED; return Wenku8Error.ErrorCode.SYSTEM_1_SUCCEEDED; @@ -696,78 +693,72 @@ public void onStopTrackingTouch(DiscreteSeekBar discreteSeekBar) { return true; }); - findViewById(R.id.text_previous).setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - // goto previous chapter - for (int i = 0; i < volumeList.chapterList.size(); i++) { - if (cid == volumeList.chapterList.get(i).cid) { - // found self - if (i == 0) { - // no more previous - Toast.makeText(Wenku8ReaderActivityV1.this, getResources().getString(R.string.reader_already_first_chapter), Toast.LENGTH_SHORT).show(); - } else { - // jump to previous - final int i_bak = i; - new MaterialDialog.Builder(Wenku8ReaderActivityV1.this) - .onPositive((dialog, which) -> { - Intent intent = new Intent(Wenku8ReaderActivityV1.this, Wenku8ReaderActivityV1.class); //VerticalReaderActivity.class); - intent.putExtra("aid", aid); - intent.putExtra("volume", volumeList); - intent.putExtra("cid", volumeList.chapterList.get(i_bak - 1).cid); - intent.putExtra("from", from); // from cloud - startActivity(intent); - overridePendingTransition(R.anim.fade_in, R.anim.hold); // fade in animation - Wenku8ReaderActivityV1.this.finish(); - }) - .theme(WenkuReaderPageView.getInDayMode() ? Theme.LIGHT : Theme.DARK) - .title(R.string.dialog_sure_to_jump_chapter) - .content(volumeList.chapterList.get(i_bak - 1).chapterName) - .contentGravity(GravityEnum.CENTER) - .positiveText(R.string.dialog_positive_yes) - .negativeText(R.string.dialog_negative_no) - .show(); - } - break; + findViewById(R.id.text_previous).setOnClickListener(v -> { + // goto previous chapter + for (int i = 0; i < volumeList.chapterList.size(); i++) { + if (cid == volumeList.chapterList.get(i).cid) { + // found self + if (i == 0) { + // no more previous + Toast.makeText(Wenku8ReaderActivityV1.this, getResources().getString(R.string.reader_already_first_chapter), Toast.LENGTH_SHORT).show(); + } else { + // jump to previous + final int i_bak = i; + new MaterialDialog.Builder(Wenku8ReaderActivityV1.this) + .onPositive((dialog, which) -> { + Intent intent = new Intent(Wenku8ReaderActivityV1.this, Wenku8ReaderActivityV1.class); //VerticalReaderActivity.class); + intent.putExtra("aid", aid); + intent.putExtra("volume", volumeList); + intent.putExtra("cid", volumeList.chapterList.get(i_bak - 1).cid); + intent.putExtra("from", from); // from cloud + startActivity(intent); + overridePendingTransition(R.anim.fade_in, R.anim.hold); // fade in animation + Wenku8ReaderActivityV1.this.finish(); + }) + .theme(WenkuReaderPageView.getInDayMode() ? Theme.LIGHT : Theme.DARK) + .title(R.string.dialog_sure_to_jump_chapter) + .content(volumeList.chapterList.get(i_bak - 1).chapterName) + .contentGravity(GravityEnum.CENTER) + .positiveText(R.string.dialog_positive_yes) + .negativeText(R.string.dialog_negative_no) + .show(); } + break; } } }); - findViewById(R.id.text_next).setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - // goto next chapter - for (int i = 0; i < volumeList.chapterList.size(); i++) { - if (cid == volumeList.chapterList.get(i).cid) { - // found self - if (i + 1 >= volumeList.chapterList.size()) { - // no more previous - Toast.makeText(Wenku8ReaderActivityV1.this, getResources().getString(R.string.reader_already_last_chapter), Toast.LENGTH_SHORT).show(); - } else { - // jump to previous - final int i_bak = i; - new MaterialDialog.Builder(Wenku8ReaderActivityV1.this) - .onPositive((dialog, which) -> { - Intent intent = new Intent(Wenku8ReaderActivityV1.this, Wenku8ReaderActivityV1.class); //VerticalReaderActivity.class); - intent.putExtra("aid", aid); - intent.putExtra("volume", volumeList); - intent.putExtra("cid", volumeList.chapterList.get(i_bak + 1).cid); - intent.putExtra("from", from); // from cloud - startActivity(intent); - overridePendingTransition(R.anim.fade_in, R.anim.hold); // fade in animation - Wenku8ReaderActivityV1.this.finish(); - }) - .theme(WenkuReaderPageView.getInDayMode() ? Theme.LIGHT : Theme.DARK) - .title(R.string.dialog_sure_to_jump_chapter) - .content(volumeList.chapterList.get(i_bak + 1).chapterName) - .contentGravity(GravityEnum.CENTER) - .positiveText(R.string.dialog_positive_yes) - .negativeText(R.string.dialog_negative_no) - .show(); - } - break; + findViewById(R.id.text_next).setOnClickListener(v -> { + // goto next chapter + for (int i = 0; i < volumeList.chapterList.size(); i++) { + if (cid == volumeList.chapterList.get(i).cid) { + // found self + if (i + 1 >= volumeList.chapterList.size()) { + // no more previous + Toast.makeText(Wenku8ReaderActivityV1.this, getResources().getString(R.string.reader_already_last_chapter), Toast.LENGTH_SHORT).show(); + } else { + // jump to previous + final int i_bak = i; + new MaterialDialog.Builder(Wenku8ReaderActivityV1.this) + .onPositive((dialog, which) -> { + Intent intent = new Intent(Wenku8ReaderActivityV1.this, Wenku8ReaderActivityV1.class); //VerticalReaderActivity.class); + intent.putExtra("aid", aid); + intent.putExtra("volume", volumeList); + intent.putExtra("cid", volumeList.chapterList.get(i_bak + 1).cid); + intent.putExtra("from", from); // from cloud + startActivity(intent); + overridePendingTransition(R.anim.fade_in, R.anim.hold); // fade in animation + Wenku8ReaderActivityV1.this.finish(); + }) + .theme(WenkuReaderPageView.getInDayMode() ? Theme.LIGHT : Theme.DARK) + .title(R.string.dialog_sure_to_jump_chapter) + .content(volumeList.chapterList.get(i_bak + 1).chapterName) + .contentGravity(GravityEnum.CENTER) + .positiveText(R.string.dialog_positive_yes) + .negativeText(R.string.dialog_negative_no) + .show(); } + break; } } }); diff --git a/studio-android/LightNovelLibrary/app/src/main/java/org/mewx/wenku8/reader/loader/WenkuReaderLoaderXML.java b/studio-android/LightNovelLibrary/app/src/main/java/org/mewx/wenku8/reader/loader/WenkuReaderLoaderXML.java index 164513c3..96caea10 100644 --- a/studio-android/LightNovelLibrary/app/src/main/java/org/mewx/wenku8/reader/loader/WenkuReaderLoaderXML.java +++ b/studio-android/LightNovelLibrary/app/src/main/java/org/mewx/wenku8/reader/loader/WenkuReaderLoaderXML.java @@ -2,6 +2,7 @@ import android.graphics.Bitmap; import android.graphics.BitmapFactory; +import android.support.annotation.NonNull; import org.mewx.wenku8.global.GlobalConfig; import org.mewx.wenku8.global.api.OldNovelContentParser; @@ -17,10 +18,10 @@ public class WenkuReaderLoaderXML extends WenkuReaderLoader { private int currentIndex = 0; - private List nc = null; // 't'-text; 'i'-image + private List nc; public String chapterName; - public WenkuReaderLoaderXML(List onc) { + public WenkuReaderLoaderXML(@NonNull List onc) { nc = onc; } diff --git a/studio-android/LightNovelLibrary/app/src/main/java/org/mewx/wenku8/reader/view/WenkuReaderPageView.java b/studio-android/LightNovelLibrary/app/src/main/java/org/mewx/wenku8/reader/view/WenkuReaderPageView.java index e7b357e0..b5c8cea2 100644 --- a/studio-android/LightNovelLibrary/app/src/main/java/org/mewx/wenku8/reader/view/WenkuReaderPageView.java +++ b/studio-android/LightNovelLibrary/app/src/main/java/org/mewx/wenku8/reader/view/WenkuReaderPageView.java @@ -8,28 +8,16 @@ import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Point; -import android.graphics.Rect; import android.graphics.Shader; import android.graphics.Typeface; import android.graphics.drawable.BitmapDrawable; -import android.media.Image; -import android.net.wifi.WifiManager; import android.os.AsyncTask; import android.os.Build; -import android.os.Handler; import android.text.TextPaint; -import android.util.AttributeSet; import android.util.Log; -import android.util.TypedValue; -import android.view.MotionEvent; import android.view.View; -import android.view.ViewGroup; -import android.widget.ImageView; -import android.widget.RelativeLayout; import android.widget.Toast; -import com.android.volley.toolbox.Volley; -import com.nostra13.universalimageloader.core.DisplayImageOptions; import com.nostra13.universalimageloader.core.ImageLoader; import com.nostra13.universalimageloader.core.assist.ImageSize; @@ -42,7 +30,6 @@ import org.mewx.wenku8.reader.setting.WenkuReaderSettingV1; import org.mewx.wenku8.util.LightTool; -import java.lang.annotation.ElementType; import java.util.ArrayList; import java.util.List; import java.util.Random; @@ -113,17 +100,17 @@ private class BitmapInfo { // useless constructs // public WenkuReaderPageView(Context context) { // super(context); -// Log.e("MewX", "-- view: construct 1"); +// Log.d("MewX", "-- view: construct 1"); // } // // public WenkuReaderPageView(Context context, AttributeSet attrs) { // super(context, attrs); -// Log.e("MewX", "-- view: construct 2"); +// Log.d("MewX", "-- view: construct 2"); // } // // public WenkuReaderPageView(Context context, AttributeSet attrs, int defStyleAttr) { // super(context, attrs, defStyleAttr); -// Log.e("MewX", "-- view: construct 3"); +// Log.d("MewX", "-- view: construct 3"); // } static public boolean getInDayMode() { @@ -226,7 +213,7 @@ static public void resetTextColor() { */ public WenkuReaderPageView(Context context, int lineIndex, int wordIndex, LOADING_DIRECTION directionForward) { super(context); - Log.e("MewX", "-- view: construct my"); + Log.d("MewX", "-- view: construct my"); lineInfoList = new ArrayList<>(); bitmapInfoList = new ArrayList<>(); mLoader.setCurrentIndex(lineIndex); @@ -251,7 +238,7 @@ else if(lineIndex + 1 < mLoader.getElementCount()){ firstWordIndex = 0; } else { - Log.e("MewX", "-- view: end construct A, just return"); + Log.d("MewX", "-- view: end construct A, just return"); return; } mLoader.setCurrentIndex(firstLineIndex); @@ -283,7 +270,7 @@ else if(lineIndex > 0) { } for(LineInfo li : lineInfoList) - Log.e("MewX", "get: " + li.text); + Log.d("MewX", "get: " + li.text); } @@ -294,15 +281,15 @@ else if(lineIndex > 0) { private void calcFromFirst() { int widthSum = 0; int heightSum = fontHeight; - String tempText = ""; + StringBuilder tempText = new StringBuilder(); - Log.e("MewX", "firstLineIndex = " + firstLineIndex + "; firstWordIndex = " + firstWordIndex); + Log.d("MewX", "firstLineIndex = " + firstLineIndex + "; firstWordIndex = " + firstWordIndex); for(int curLineIndex = firstLineIndex, curWordIndex = firstWordIndex; curLineIndex < mLoader.getElementCount(); ) { // init paragraph head vars if(curWordIndex == 0 && mLoader.getCurrentType() == WenkuReaderLoader.ElementType.TEXT) { // leading space widthSum = 2 * fontHeight; - tempText = "  "; + tempText = new StringBuilder("  "); } else if(mLoader.getCurrentType() == WenkuReaderLoader.ElementType.IMAGE_DEPENDENT) { if(lineInfoList.size() != 0) { @@ -326,7 +313,7 @@ else if(mLoader.getCurrentType() == WenkuReaderLoader.ElementType.IMAGE_DEPENDEN // get a record of line if(mLoader.getCurrentAsString() == null || mLoader.getCurrentAsString().length() == 0) { - Log.e("MewX", "empty string! in " + curLineIndex + "(" + curWordIndex + ")"); + Log.d("MewX", "empty string! in " + curLineIndex + "(" + curWordIndex + ")"); curWordIndex = 0; if(curLineIndex >= mLoader.getElementCount()) { // out of bounds @@ -343,7 +330,7 @@ else if(mLoader.getCurrentType() == WenkuReaderLoader.ElementType.IMAGE_DEPENDEN // wrap line, save line LineInfo li = new LineInfo(); li.type = WenkuReaderLoader.ElementType.TEXT; - li.text = tempText; + li.text = tempText.toString(); lineInfoList.add(li); heightSum += pxLineDistance; @@ -366,12 +353,12 @@ else if(curLineIndex > 0) { } // height acceptable - tempText = temp; + tempText = new StringBuilder(temp); widthSum = tempWidth; heightSum += fontHeight; } else { - tempText = tempText + temp; + tempText.append(temp); widthSum += tempWidth; } @@ -380,7 +367,7 @@ else if(curLineIndex > 0) { // next paragraph, wrap line LineInfo li = new LineInfo(); li.type = WenkuReaderLoader.ElementType.TEXT; - li.text = tempText; + li.text = tempText.toString(); lineInfoList.add(li); heightSum += pxParagraphDistance; @@ -394,7 +381,7 @@ else if(curLineIndex > 0) { // height acceptable heightSum += fontHeight; widthSum = 0; - tempText = ""; + tempText = new StringBuilder(); curWordIndex = 0; if(curLineIndex + 1 >= mLoader.getElementCount()) { // out of bounds @@ -428,7 +415,7 @@ private void calcFromLast() { // special to image if(curType == WenkuReaderLoader.ElementType.IMAGE_DEPENDENT && lineInfoList.size() != 0) { - Log.e("MewX", "jump 1"); + Log.d("MewX", "jump 1"); firstLineIndex = curLineIndex + 1; firstWordIndex = 0; mLoader.setCurrentIndex(firstLineIndex); @@ -516,7 +503,7 @@ else if(i == curList.size() - 1) lineInfoList.add(0, curList.get(i)); } for(LineInfo li : lineInfoList) - Log.e("MewX", "full: " + li.text); + Log.d("MewX", "full: " + li.text); // not full to continue, set curWord as last index of the string if(curLineIndex - 1 >= 0) { @@ -524,7 +511,7 @@ else if(i == curList.size() - 1) curWordIndex = mLoader.getCurrentAsString().length(); } else { - Log.e("MewX", "jump 2"); + Log.d("MewX", "jump 2"); firstLineIndex = 0; firstWordIndex = 0; mLoader.setCurrentIndex(firstLineIndex); @@ -540,7 +527,7 @@ protected void onDraw(Canvas canvas) { super.onDraw(canvas); //canvas.drawLine(0.0f, 0.0f, 320.0f, 320.0f, new Paint()); // px if(mSetting == null || mLoader == null) return; - Log.e("MewX", "onDraw()"); + Log.d("MewX", "onDraw()"); // draw background if(getInDayMode()) { @@ -588,7 +575,7 @@ protected void onDraw(Canvas canvas) { } } - Log.e("MewX", "draw: " + li.text); + Log.d("MewX", "draw: " + li.text); if(li.type == WenkuReaderLoader.ElementType.TEXT) { canvas.drawText( li.text, (float) (pxPageEdgeDistance + pxParagraphEdgeDistance), (float) heightSum, textPaint); heightSum += fontHeight; From 618a5d6e2f6dbc541b64a95e72c704249d4bca4f Mon Sep 17 00:00:00 2001 From: MewX Date: Wed, 25 Jul 2018 08:18:39 +0800 Subject: [PATCH 6/9] #32 Added unit tests for Wenku8Parser --- .../api/NovelListWithInfoParserTest.java | 5 + .../global/api/OldNovelContentParserTest.java | 23 +- .../wenku8/global/api/Wenku8ParserTest.java | 319 +++++++++++++----- .../wenku8/activity/NovelInfoActivity.java | 16 +- .../org/mewx/wenku8/fragment/FavFragment.java | 6 +- .../fragment/NovelItemListFragment.java | 15 +- .../global/api/NovelListWithInfoParser.java | 5 + .../mewx/wenku8/global/api/Wenku8Parser.java | 25 +- 8 files changed, 295 insertions(+), 119 deletions(-) diff --git a/studio-android/LightNovelLibrary/app/src/androidTest/java/org/mewx/wenku8/global/api/NovelListWithInfoParserTest.java b/studio-android/LightNovelLibrary/app/src/androidTest/java/org/mewx/wenku8/global/api/NovelListWithInfoParserTest.java index 5f1e40c0..b32ffce8 100644 --- a/studio-android/LightNovelLibrary/app/src/androidTest/java/org/mewx/wenku8/global/api/NovelListWithInfoParserTest.java +++ b/studio-android/LightNovelLibrary/app/src/androidTest/java/org/mewx/wenku8/global/api/NovelListWithInfoParserTest.java @@ -35,6 +35,11 @@ public class NovelListWithInfoParserTest { "\n" + ""; + @Test + public void getNovelListWithInfoPageNumInvalid() { + assertEquals(0, NovelListWithInfoParser.getNovelListWithInfoPageNum("1234")); + } + @Test public void getNovelListWithInfoPageNum() { assertEquals(166, NovelListWithInfoParser.getNovelListWithInfoPageNum(XML)); diff --git a/studio-android/LightNovelLibrary/app/src/androidTest/java/org/mewx/wenku8/global/api/OldNovelContentParserTest.java b/studio-android/LightNovelLibrary/app/src/androidTest/java/org/mewx/wenku8/global/api/OldNovelContentParserTest.java index 29564282..650f282a 100644 --- a/studio-android/LightNovelLibrary/app/src/androidTest/java/org/mewx/wenku8/global/api/OldNovelContentParserTest.java +++ b/studio-android/LightNovelLibrary/app/src/androidTest/java/org/mewx/wenku8/global/api/OldNovelContentParserTest.java @@ -15,6 +15,12 @@ public class OldNovelContentParserTest { "http://bbbbb.com/pictures/1/1339/90903/107725.jpg\r\n" + "line 3\r\n"; + private static final String NOVEL_CONTENt_BROKEN_IMAGE = "line 1\r\n" + + " http://bbbbb.com/pictures/1/1339/90903/107724.jpg \r\n" + + " line 2 \r\n\r\n" + + " http://bbbbb.com/pictures/1/1339/90903/107725.jpg \r\n" + + "line 3\r\n"; + @Test public void parseNovelContent() { List contents = OldNovelContentParser.parseNovelContent(NOVEL_CONTENT, null); @@ -43,12 +49,7 @@ public void parseNovelContent() { @Test public void parseNovelContentWithIncompleteImageTag() { - final String BROKEN_XML = "line 1\r\n" + - " http://bbbbb.com/pictures/1/1339/90903/107724.jpg \r\n" + - " line 2 \r\n\r\n" + - " http://bbbbb.com/pictures/1/1339/90903/107725.jpg \r\n" + - "line 3\r\n"; - List contents = OldNovelContentParser.parseNovelContent(BROKEN_XML, null); + List contents = OldNovelContentParser.parseNovelContent(NOVEL_CONTENt_BROKEN_IMAGE, null); assertEquals(5, contents.size()); OldNovelContentParser.NovelContent tempContent = contents.get(0); @@ -85,4 +86,14 @@ public void novelContentParser_onlyImage() { assertEquals(IMAGE, tempContent.type); assertEquals("http://bbbbb.com/pictures/1/1339/90903/107725.jpg", tempContent.content); } + + @Test + public void novelContentParser_onlyImageBroken() { + List contents = OldNovelContentParser.NovelContentParser_onlyImage(NOVEL_CONTENt_BROKEN_IMAGE); + assertEquals(1, contents.size()); + + OldNovelContentParser.NovelContent tempContent = contents.get(0); + assertEquals(IMAGE, tempContent.type); + assertEquals("http://bbbbb.com/pictures/1/1339/90903/107724.jpg", tempContent.content); + } } \ No newline at end of file diff --git a/studio-android/LightNovelLibrary/app/src/androidTest/java/org/mewx/wenku8/global/api/Wenku8ParserTest.java b/studio-android/LightNovelLibrary/app/src/androidTest/java/org/mewx/wenku8/global/api/Wenku8ParserTest.java index 561c808f..8d03aadb 100644 --- a/studio-android/LightNovelLibrary/app/src/androidTest/java/org/mewx/wenku8/global/api/Wenku8ParserTest.java +++ b/studio-android/LightNovelLibrary/app/src/androidTest/java/org/mewx/wenku8/global/api/Wenku8ParserTest.java @@ -2,11 +2,14 @@ import android.support.test.filters.SmallTest; -import org.junit.Assert; import org.junit.Test; +import java.util.Arrays; import java.util.Calendar; import java.util.GregorianCalendar; +import java.util.List; + +import static org.junit.Assert.*; @SmallTest public class Wenku8ParserTest { @@ -41,44 +44,196 @@ public class Wenku8ParserTest { "\n" + ""; - // TODO: more tests + @Test + public void testParseNovelItemList() { + final String XML = "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + ""; + + List list = Wenku8Parser.parseNovelItemList(XML); + assertEquals(Arrays.asList(166, 1143, 1034, 1213, 1, 1011, 1192, 433, 47, 7, 374), list); + } + + @Test + public void testParseNovelItemListInvalid() { + List list = Wenku8Parser.parseNovelItemList("1234"); + assertTrue(list.isEmpty()); + } + + @Test + public void testParseNovelFullMeta() { + final String META_XML = "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + ""; + NovelItemMeta meta = Wenku8Parser.parseNovelFullMeta(META_XML); + assertNotNull(meta); + + assertEquals(1306, meta.aid); + assertEquals("向森之魔物献上花束(向森林的魔兽少女献花)", meta.title); + assertEquals("小木君人", meta.author); + assertEquals(26, meta.dayHitsCount); + assertEquals(43984, meta.totalHitsCount); + assertEquals(1735, meta.pushCount); + assertEquals(848, meta.favCount); + assertEquals("小学馆", meta.pressId); + assertEquals("已完成", meta.bookStatus); + assertEquals(105985, meta.bookLength); + assertEquals("2012-11-02", meta.lastUpdate); + assertEquals(41897, meta.latestSectionCid); + assertEquals("第一卷 插图", meta.latestSectionName); + } + + @Test + public void testParseNovelFullMetaInvalid() { + NovelItemMeta meta = Wenku8Parser.parseNovelFullMeta("1234"); + assertNull(meta); + } + + @Test + public void testGetVolumeList() { + final String XML = "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + ""; + + List volumeLists = Wenku8Parser.getVolumeList(XML); + assertEquals(2, volumeLists.size()); + + // ---- + VolumeList vList = volumeLists.get(0); + assertEquals(41748, vList.vid); + assertEquals("第一卷 告白于苍刻之夜", vList.volumeName); + + assertEquals(11, vList.chapterList.size()); + ChapterInfo cInfo = vList.chapterList.get(0); + assertEquals(41749, cInfo.cid); + assertEquals("序章", cInfo.chapterName); + cInfo = vList.chapterList.get(1); + assertEquals(41750, cInfo.cid); + assertEquals("第一章「去对我的『楯』说吧——」", cInfo.chapterName); + cInfo = vList.chapterList.get(2); + assertEquals(41751, cInfo.cid); + assertEquals("第二章「我真的对你非常感兴趣」", cInfo.chapterName); + cInfo = vList.chapterList.get(3); + assertEquals(41752, cInfo.cid); + assertEquals("第三章「揍我吧!」", cInfo.chapterName); + cInfo = vList.chapterList.get(4); + assertEquals(41753, cInfo.cid); + assertEquals("第四章「下次,再来喝苹果茶」", cInfo.chapterName); + cInfo = vList.chapterList.get(5); + assertEquals(41754, cInfo.cid); + assertEquals("第五章「这是约定」", cInfo.chapterName); + cInfo = vList.chapterList.get(6); + assertEquals(41755, cInfo.cid); + assertEquals("第六章「你的背后——由我来守护!」", cInfo.chapterName); + cInfo = vList.chapterList.get(7); + assertEquals(41756, cInfo.cid); + assertEquals("第七章「茱莉——爱交给你!」", cInfo.chapterName); + cInfo = vList.chapterList.get(8); + assertEquals(41757, cInfo.cid); + assertEquals("尾声", cInfo.chapterName); + cInfo = vList.chapterList.get(9); + assertEquals(41758, cInfo.cid); + assertEquals("后记", cInfo.chapterName); + cInfo = vList.chapterList.get(10); + assertEquals(41759, cInfo.cid); + assertEquals("插图", cInfo.chapterName); + + + // ---- + vList = volumeLists.get(1); + assertEquals(45090, vList.vid); + assertEquals("第二卷 谎言、真相与赤红", vList.volumeName); + + assertEquals(2, vList.chapterList.size()); + cInfo = vList.chapterList.get(0); + assertEquals(45091, cInfo.cid); + assertEquals("序章", cInfo.chapterName); + cInfo = vList.chapterList.get(1); + assertEquals(45092, cInfo.cid); + assertEquals("第一章「莉莉丝·布里斯托」", cInfo.chapterName); + } + + @Test + public void testGetVolumeListInvalid() { + List volumeLists = Wenku8Parser.getVolumeList("1234"); + assertTrue(volumeLists.isEmpty()); + } @Test public void testParseReviewList() { ReviewList reviewList = new ReviewList(); Wenku8Parser.parseReviewList(reviewList, REVIEW_LIST_XML); - Assert.assertEquals(reviewList.getTotalPage(), 12); - Assert.assertEquals(reviewList.getCurrentPage(), 1); - Assert.assertEquals(reviewList.getList().size(), 2); + assertEquals(reviewList.getTotalPage(), 12); + assertEquals(reviewList.getCurrentPage(), 1); + assertEquals(reviewList.getList().size(), 2); ReviewList.Review review = reviewList.getList().get(0); - Assert.assertEquals(review.getRid(), 79800); - Assert.assertEquals(review.getPostTime().getTime(), + assertEquals(review.getRid(), 79800); + assertEquals(review.getPostTime().getTime(), new GregorianCalendar(2013, Calendar.MAY, 25, 17, 16, 31).getTime().getTime()); - Assert.assertEquals(review.getNoReplies(), 1); - Assert.assertEquals(review.getLastReplyTime().getTime(), + assertEquals(review.getNoReplies(), 1); + assertEquals(review.getLastReplyTime().getTime(), new GregorianCalendar(2013, Calendar.MAY, 28, 18, 49, 16).getTime().getTime()); - Assert.assertEquals(review.getUid(), 81669); - Assert.assertEquals(review.getUserName(), "老衲0轻音"); - Assert.assertEquals(review.getTitle(), "前排……"); + assertEquals(review.getUid(), 81669); + assertEquals(review.getUserName(), "老衲0轻音"); + assertEquals(review.getTitle(), "前排……"); review = reviewList.getList().get(1); - Assert.assertEquals(review.getRid(), 79826); - Assert.assertEquals(review.getPostTime().getTime(), + assertEquals(review.getRid(), 79826); + assertEquals(review.getPostTime().getTime(), new GregorianCalendar(2013, Calendar.MAY, 25, 23, 20, 2).getTime().getTime()); - Assert.assertEquals(review.getNoReplies(), 4); - Assert.assertEquals(review.getLastReplyTime().getTime(), + assertEquals(review.getNoReplies(), 4); + assertEquals(review.getLastReplyTime().getTime(), new GregorianCalendar(2013, Calendar.MAY, 27, 23, 42, 59).getTime().getTime()); - Assert.assertEquals(review.getUid(), 34924); - Assert.assertEquals(review.getUserName(), "冒险奏鸣"); - Assert.assertEquals(review.getTitle(), "有种神曲奏界的既视感"); + assertEquals(review.getUid(), 34924); + assertEquals(review.getUserName(), "冒险奏鸣"); + assertEquals(review.getTitle(), "有种神曲奏界的既视感"); } @Test public void testParseReviewListInvalid() { ReviewList reviewList = new ReviewList(); Wenku8Parser.parseReviewList(reviewList, "1324"); - Assert.assertTrue(reviewList.getList().isEmpty()); + assertTrue(reviewList.getList().isEmpty()); } @Test @@ -103,53 +258,53 @@ public void testParseReviewListPageTwo() { Wenku8Parser.parseReviewList(reviewList, REVIEW_LIST_XML); Wenku8Parser.parseReviewList(reviewList, REVIEW_LIST_XML_PAGE_2); - Assert.assertEquals(reviewList.getTotalPage(), 12); - Assert.assertEquals(reviewList.getCurrentPage(), 2); - Assert.assertEquals(reviewList.getList().size(), 4); + assertEquals(reviewList.getTotalPage(), 12); + assertEquals(reviewList.getCurrentPage(), 2); + assertEquals(reviewList.getList().size(), 4); ReviewList.Review review = reviewList.getList().get(0); - Assert.assertEquals(review.getRid(), 79800); - Assert.assertEquals(review.getPostTime().getTime(), + assertEquals(review.getRid(), 79800); + assertEquals(review.getPostTime().getTime(), new GregorianCalendar(2013, Calendar.MAY, 25, 17, 16, 31).getTime().getTime()); - Assert.assertEquals(review.getNoReplies(), 1); - Assert.assertEquals(review.getLastReplyTime().getTime(), + assertEquals(review.getNoReplies(), 1); + assertEquals(review.getLastReplyTime().getTime(), new GregorianCalendar(2013, Calendar.MAY, 28, 18, 49, 16).getTime().getTime()); - Assert.assertEquals(review.getUid(), 81669); - Assert.assertEquals(review.getUserName(), "老衲0轻音"); - Assert.assertEquals(review.getTitle(), "前排……"); + assertEquals(review.getUid(), 81669); + assertEquals(review.getUserName(), "老衲0轻音"); + assertEquals(review.getTitle(), "前排……"); review = reviewList.getList().get(1); - Assert.assertEquals(review.getRid(), 79826); - Assert.assertEquals(review.getPostTime().getTime(), + assertEquals(review.getRid(), 79826); + assertEquals(review.getPostTime().getTime(), new GregorianCalendar(2013, Calendar.MAY, 25, 23, 20, 2).getTime().getTime()); - Assert.assertEquals(review.getNoReplies(), 4); - Assert.assertEquals(review.getLastReplyTime().getTime(), + assertEquals(review.getNoReplies(), 4); + assertEquals(review.getLastReplyTime().getTime(), new GregorianCalendar(2013, Calendar.MAY, 27, 23, 42, 59).getTime().getTime()); - Assert.assertEquals(review.getUid(), 34924); - Assert.assertEquals(review.getUserName(), "冒险奏鸣"); - Assert.assertEquals(review.getTitle(), "有种神曲奏界的既视感"); + assertEquals(review.getUid(), 34924); + assertEquals(review.getUserName(), "冒险奏鸣"); + assertEquals(review.getTitle(), "有种神曲奏界的既视感"); review = reviewList.getList().get(2); - Assert.assertEquals(review.getRid(), 79801); - Assert.assertEquals(review.getPostTime().getTime(), + assertEquals(review.getRid(), 79801); + assertEquals(review.getPostTime().getTime(), new GregorianCalendar(2013, Calendar.MAY, 25, 17, 16, 31).getTime().getTime()); - Assert.assertEquals(review.getNoReplies(), 1); - Assert.assertEquals(review.getLastReplyTime().getTime(), + assertEquals(review.getNoReplies(), 1); + assertEquals(review.getLastReplyTime().getTime(), new GregorianCalendar(2013, Calendar.MAY, 28, 18, 49, 16).getTime().getTime()); - Assert.assertEquals(review.getUid(), 81670); - Assert.assertEquals(review.getUserName(), "老衲0轻音"); - Assert.assertEquals(review.getTitle(), "前排……"); + assertEquals(review.getUid(), 81670); + assertEquals(review.getUserName(), "老衲0轻音"); + assertEquals(review.getTitle(), "前排……"); review = reviewList.getList().get(3); - Assert.assertEquals(review.getRid(), 79827); - Assert.assertEquals(review.getPostTime().getTime(), + assertEquals(review.getRid(), 79827); + assertEquals(review.getPostTime().getTime(), new GregorianCalendar(2013, Calendar.MAY, 25, 23, 20, 2).getTime().getTime()); - Assert.assertEquals(review.getNoReplies(), 4); - Assert.assertEquals(review.getLastReplyTime().getTime(), + assertEquals(review.getNoReplies(), 4); + assertEquals(review.getLastReplyTime().getTime(), new GregorianCalendar(2013, Calendar.MAY, 27, 23, 42, 59).getTime().getTime()); - Assert.assertEquals(review.getUid(), 34925); - Assert.assertEquals(review.getUserName(), "冒险奏鸣"); - Assert.assertEquals(review.getTitle(), "有种神曲奏界的既视感"); + assertEquals(review.getUid(), 34925); + assertEquals(review.getUserName(), "冒险奏鸣"); + assertEquals(review.getTitle(), "有种神曲奏界的既视感"); } @Test @@ -157,30 +312,30 @@ public void testParseReviewReplyList() { ReviewReplyList reviewReplyList = new ReviewReplyList(); Wenku8Parser.parseReviewReplyList(reviewReplyList, REVIEW_REPLY_LIST_XML); - Assert.assertEquals(reviewReplyList.getTotalPage(), 2); - Assert.assertEquals(reviewReplyList.getCurrentPage(), 1); - Assert.assertEquals(reviewReplyList.getList().size(), 2); + assertEquals(reviewReplyList.getTotalPage(), 2); + assertEquals(reviewReplyList.getCurrentPage(), 1); + assertEquals(reviewReplyList.getList().size(), 2); ReviewReplyList.ReviewReply reviewReply = reviewReplyList.getList().get(0); - Assert.assertEquals(reviewReply.getReplyTime().getTime(), + assertEquals(reviewReply.getReplyTime().getTime(), new GregorianCalendar(2018, Calendar.JULY, 13, 10, 18, 11).getTime().getTime()); - Assert.assertEquals(reviewReply.getUid(), 233516); - Assert.assertEquals(reviewReply.getUserName(), "a1b2c3d4"); - Assert.assertEquals(reviewReply.getContent(), "嗯…………至少是一樓發完"); + assertEquals(reviewReply.getUid(), 233516); + assertEquals(reviewReply.getUserName(), "a1b2c3d4"); + assertEquals(reviewReply.getContent(), "嗯…………至少是一樓發完"); reviewReply = reviewReplyList.getList().get(1); - Assert.assertEquals(reviewReply.getReplyTime().getTime(), + assertEquals(reviewReply.getReplyTime().getTime(), new GregorianCalendar(2018, Calendar.JULY, 13, 13, 57, 35).getTime().getTime()); - Assert.assertEquals(reviewReply.getUid(), 230041); - Assert.assertEquals(reviewReply.getUserName(), "156126"); - Assert.assertEquals(reviewReply.getContent(), "滑稽✧(`ῧ′)机智"); + assertEquals(reviewReply.getUid(), 230041); + assertEquals(reviewReply.getUserName(), "156126"); + assertEquals(reviewReply.getContent(), "滑稽✧(`ῧ′)机智"); } @Test public void testParseReviewReplyListInvalid() { ReviewReplyList reviewReplyList = new ReviewReplyList(); Wenku8Parser.parseReviewReplyList(reviewReplyList, "1234"); - Assert.assertTrue(reviewReplyList.getList().isEmpty()); + assertTrue(reviewReplyList.getList().isEmpty()); } @Test @@ -204,36 +359,36 @@ public void testParseReviewReplyListPage2() { Wenku8Parser.parseReviewReplyList(reviewReplyList, REVIEW_REPLY_LIST_XML); Wenku8Parser.parseReviewReplyList(reviewReplyList, REVIEW_REPLY_LIST_XML_PAGE_2); - Assert.assertEquals(reviewReplyList.getTotalPage(), 2); - Assert.assertEquals(reviewReplyList.getCurrentPage(), 2); - Assert.assertEquals(reviewReplyList.getList().size(), 4); + assertEquals(reviewReplyList.getTotalPage(), 2); + assertEquals(reviewReplyList.getCurrentPage(), 2); + assertEquals(reviewReplyList.getList().size(), 4); ReviewReplyList.ReviewReply reviewReply = reviewReplyList.getList().get(0); - Assert.assertEquals(reviewReply.getReplyTime().getTime(), + assertEquals(reviewReply.getReplyTime().getTime(), new GregorianCalendar(2018, Calendar.JULY, 13, 10, 18, 11).getTime().getTime()); - Assert.assertEquals(reviewReply.getUid(), 233516); - Assert.assertEquals(reviewReply.getUserName(), "a1b2c3d4"); - Assert.assertEquals(reviewReply.getContent(), "嗯…………至少是一樓發完"); + assertEquals(reviewReply.getUid(), 233516); + assertEquals(reviewReply.getUserName(), "a1b2c3d4"); + assertEquals(reviewReply.getContent(), "嗯…………至少是一樓發完"); reviewReply = reviewReplyList.getList().get(1); - Assert.assertEquals(reviewReply.getReplyTime().getTime(), + assertEquals(reviewReply.getReplyTime().getTime(), new GregorianCalendar(2018, Calendar.JULY, 13, 13, 57, 35).getTime().getTime()); - Assert.assertEquals(reviewReply.getUid(), 230041); - Assert.assertEquals(reviewReply.getUserName(), "156126"); - Assert.assertEquals(reviewReply.getContent(), "滑稽✧(`ῧ′)机智"); + assertEquals(reviewReply.getUid(), 230041); + assertEquals(reviewReply.getUserName(), "156126"); + assertEquals(reviewReply.getContent(), "滑稽✧(`ῧ′)机智"); reviewReply = reviewReplyList.getList().get(2); - Assert.assertEquals(reviewReply.getReplyTime().getTime(), + assertEquals(reviewReply.getReplyTime().getTime(), new GregorianCalendar(2018, Calendar.JULY, 13, 10, 18, 11).getTime().getTime()); - Assert.assertEquals(reviewReply.getUid(), 233517); - Assert.assertEquals(reviewReply.getUserName(), "a1b2c3d4"); - Assert.assertEquals(reviewReply.getContent(), "嗯…………至少是一樓發完"); + assertEquals(reviewReply.getUid(), 233517); + assertEquals(reviewReply.getUserName(), "a1b2c3d4"); + assertEquals(reviewReply.getContent(), "嗯…………至少是一樓發完"); reviewReply = reviewReplyList.getList().get(3); - Assert.assertEquals(reviewReply.getReplyTime().getTime(), + assertEquals(reviewReply.getReplyTime().getTime(), new GregorianCalendar(2018, Calendar.JULY, 13, 13, 57, 35).getTime().getTime()); - Assert.assertEquals(reviewReply.getUid(), 230042); - Assert.assertEquals(reviewReply.getUserName(), "156126"); - Assert.assertEquals(reviewReply.getContent(), "滑稽✧(`ῧ′)机智"); + assertEquals(reviewReply.getUid(), 230042); + assertEquals(reviewReply.getUserName(), "156126"); + assertEquals(reviewReply.getContent(), "滑稽✧(`ῧ′)机智"); } } diff --git a/studio-android/LightNovelLibrary/app/src/main/java/org/mewx/wenku8/activity/NovelInfoActivity.java b/studio-android/LightNovelLibrary/app/src/main/java/org/mewx/wenku8/activity/NovelInfoActivity.java index 2a04ded0..2b76465b 100644 --- a/studio-android/LightNovelLibrary/app/src/main/java/org/mewx/wenku8/activity/NovelInfoActivity.java +++ b/studio-android/LightNovelLibrary/app/src/main/java/org/mewx/wenku8/activity/NovelInfoActivity.java @@ -670,7 +670,7 @@ protected Integer doInBackground(Integer... params) { } listVolume = Wenku8Parser.getVolumeList(novelFullVolume); - if(listVolume == null) return -1; + if(listVolume.isEmpty()) return -1; } catch (UnsupportedEncodingException e) { e.printStackTrace(); return -2; @@ -793,7 +793,7 @@ class AsyncUpdateCacheTask extends AsyncTask { - private List tempNovelList = null; + private List tempNovelList = new ArrayList<>(); @Override protected Integer doInBackground(Integer... params) { if(isLoading) @@ -263,10 +263,9 @@ protected Integer doInBackground(Integer... params) { } // judge result - if( tempNovelList == null || tempNovelList.size() == 0 ) { - String error = "in AsyncGetNovelItemList: doInBackground: tempNovelList == null || tempNovelList.size() == 0"; - } - else { + if (tempNovelList.isEmpty()) { + Log.d("MewX", "in AsyncGetNovelItemList: doInBackground: tempNovelList == null || tempNovelList.size() == 0"); + } else { totalPage = tempNovelList.get(0); tempNovelList.remove(0); } @@ -276,12 +275,12 @@ protected Integer doInBackground(Integer... params) { @Override protected void onPostExecute(Integer integer) { - if(integer == -1) { + if (integer == -1) { // network error return; } - if(tempNovelList != null && tempNovelList.size()==0) { - String error = "in AsyncGetNovelItemList: doInBackground: tempNovelList == null || tempNovelList.size() == 0"; + if (tempNovelList.isEmpty()) { + Log.d("MewX", "in AsyncGetNovelItemList: doInBackground: tempNovelList == null || tempNovelList.size() == 0"); return; } diff --git a/studio-android/LightNovelLibrary/app/src/main/java/org/mewx/wenku8/global/api/NovelListWithInfoParser.java b/studio-android/LightNovelLibrary/app/src/main/java/org/mewx/wenku8/global/api/NovelListWithInfoParser.java index 0ee60d7e..e9077d1b 100644 --- a/studio-android/LightNovelLibrary/app/src/main/java/org/mewx/wenku8/global/api/NovelListWithInfoParser.java +++ b/studio-android/LightNovelLibrary/app/src/main/java/org/mewx/wenku8/global/api/NovelListWithInfoParser.java @@ -22,6 +22,11 @@ static public class NovelListWithInfo { public int fav = 0; } + /** + * get current 'page' attributes + * @param xml input xml + * @return the page in the xml file or 0 by default + */ static public int getNovelListWithInfoPageNum(String xml) { try { XmlPullParserFactory factory = XmlPullParserFactory.newInstance(); diff --git a/studio-android/LightNovelLibrary/app/src/main/java/org/mewx/wenku8/global/api/Wenku8Parser.java b/studio-android/LightNovelLibrary/app/src/main/java/org/mewx/wenku8/global/api/Wenku8Parser.java index 78488357..96a2c5f9 100644 --- a/studio-android/LightNovelLibrary/app/src/main/java/org/mewx/wenku8/global/api/Wenku8Parser.java +++ b/studio-android/LightNovelLibrary/app/src/main/java/org/mewx/wenku8/global/api/Wenku8Parser.java @@ -1,5 +1,6 @@ package org.mewx.wenku8.global.api; +import android.support.annotation.NonNull; import android.util.Log; import org.mewx.wenku8.util.LightTool; @@ -18,7 +19,8 @@ */ public class Wenku8Parser { - public static List parseNovelItemList(String str) { + @NonNull + public static List parseNovelItemList(@NonNull String str) { List list = new ArrayList<>(); // @@ -39,21 +41,21 @@ public static List parseNovelItemList(String str) { // The returning list of this xml is: (total page, aids) // { 166, 1143, 1034, 1213, 1, 1011, 1192, 433, 47, 7, 374 } - final char SEPERATOR = '\''; // seperator + final char SEPARATOR = '\''; // seperator // get total page int beg, temp; - beg = str.indexOf(SEPERATOR); - temp = str.indexOf(SEPERATOR, beg + 1); - if (beg == -1 || temp == -1) return null; // this is an exception + beg = str.indexOf(SEPARATOR); + temp = str.indexOf(SEPARATOR, beg + 1); + if (beg == -1 || temp == -1) return list; // empty, this is an exception if(LightTool.isInteger(str.substring(beg + 1, temp))) list.add(Integer.parseInt(str.substring(beg + 1, temp))); beg = temp + 1; // prepare for loop // init array while (true) { - beg = str.indexOf(SEPERATOR, beg); - temp = str.indexOf(SEPERATOR, beg + 1); + beg = str.indexOf(SEPARATOR, beg); + temp = str.indexOf(SEPARATOR, beg + 1); if (beg == -1 || temp == -1) break; if(LightTool.isInteger(str.substring(beg + 1, temp))) @@ -151,11 +153,12 @@ static public NovelItemMeta parseNovelFullMeta(String xml) { } - static public ArrayList getVolumeList(String xml) { + @NonNull + static public ArrayList getVolumeList(@NonNull String xml) { + ArrayList l = new ArrayList<>(); try { XmlPullParserFactory factory = XmlPullParserFactory.newInstance(); XmlPullParser xmlPullParser = factory.newPullParser(); - ArrayList l = new ArrayList<>(); VolumeList vl = null; ChapterInfo ci; xmlPullParser.setInput(new StringReader(xml)); @@ -219,12 +222,10 @@ static public ArrayList getVolumeList(String xml) { } else break; } - - return l; } catch (Exception e) { e.printStackTrace(); - return null; } + return l; } /** From d88cb489735ce1fa7e4565740ae68105d9ba56fc Mon Sep 17 00:00:00 2001 From: MewX Date: Wed, 25 Jul 2018 08:59:31 +0800 Subject: [PATCH 7/9] #32 Migrated and removed NovelItemInfo --- .../mewx/wenku8/adapter/NovelItemAdapter.java | 45 +++-- .../mewx/wenku8/fragment/LatestFragment.java | 19 +- .../mewx/wenku8/global/api/NovelItemInfo.java | 180 ------------------ 3 files changed, 31 insertions(+), 213 deletions(-) delete mode 100644 studio-android/LightNovelLibrary/app/src/main/java/org/mewx/wenku8/global/api/NovelItemInfo.java diff --git a/studio-android/LightNovelLibrary/app/src/main/java/org/mewx/wenku8/adapter/NovelItemAdapter.java b/studio-android/LightNovelLibrary/app/src/main/java/org/mewx/wenku8/adapter/NovelItemAdapter.java index fdda291b..c2cff70b 100644 --- a/studio-android/LightNovelLibrary/app/src/main/java/org/mewx/wenku8/adapter/NovelItemAdapter.java +++ b/studio-android/LightNovelLibrary/app/src/main/java/org/mewx/wenku8/adapter/NovelItemAdapter.java @@ -13,7 +13,7 @@ import org.mewx.wenku8.MyApp; import org.mewx.wenku8.R; import org.mewx.wenku8.global.GlobalConfig; -import org.mewx.wenku8.global.api.NovelItemInfo; +import org.mewx.wenku8.global.api.NovelItemInfoUpdate; import org.mewx.wenku8.global.api.Wenku8API; import org.mewx.wenku8.listener.MyOptionClickListener; import org.mewx.wenku8.listener.MyItemClickListener; @@ -33,19 +33,19 @@ public class NovelItemAdapter extends RecyclerView.Adapter mDataset; + private List mDataset; // empty list, then use append method to add list elements public NovelItemAdapter() { mDataset = new ArrayList<>(); } - public NovelItemAdapter(List dataset) { + public NovelItemAdapter(List dataset) { super(); mDataset = dataset; // reference } - public void RefreshDataset(List dataset) { + public void RefreshDataset(List dataset) { mDataset = dataset; // reference } @@ -62,23 +62,23 @@ public void onBindViewHolder(@NonNull final ViewHolder viewHolder, int i) { // set text if(viewHolder.tvNovelTitle != null) - viewHolder.tvNovelTitle.setText(mDataset.get(i).getTitle()); + viewHolder.tvNovelTitle.setText(mDataset.get(i).title); if(viewHolder.tvNovelAuthor != null) - viewHolder.tvNovelAuthor.setText(mDataset.get(i).getAuthor()); + viewHolder.tvNovelAuthor.setText(mDataset.get(i).author); if(viewHolder.tvNovelStatus != null) - viewHolder.tvNovelStatus.setText(Wenku8API.getStatusBySTATUS(Wenku8API.getSTATUSByInt(mDataset.get(i).getStatus()))); + viewHolder.tvNovelStatus.setText(mDataset.get(i).status); if(viewHolder.tvNovelUpdate != null) - viewHolder.tvNovelUpdate.setText(mDataset.get(i).getUpdate()); + viewHolder.tvNovelUpdate.setText(mDataset.get(i).update); if(viewHolder.tvNovelIntro != null) - viewHolder.tvNovelIntro.setText(mDataset.get(i).getIntroShort()); + viewHolder.tvNovelIntro.setText(mDataset.get(i).intro_short); // need to solve flicking problem - if(LightCache.testFileExist(GlobalConfig.getFirstStoragePath() + "imgs" + File.separator + mDataset.get(i).getAid() + ".jpg")) - ImageLoader.getInstance().displayImage("file://" + GlobalConfig.getFirstStoragePath() + "imgs" + File.separator + mDataset.get(i).getAid() + ".jpg", viewHolder.ivNovelCover); - else if(LightCache.testFileExist(GlobalConfig.getSecondStoragePath() + "imgs" + File.separator + mDataset.get(i).getAid() + ".jpg")) - ImageLoader.getInstance().displayImage("file://" + GlobalConfig.getSecondStoragePath() + "imgs" + File.separator + mDataset.get(i).getAid() + ".jpg", viewHolder.ivNovelCover); + if(LightCache.testFileExist(GlobalConfig.getFirstStoragePath() + "imgs" + File.separator + mDataset.get(i).aid + ".jpg")) + ImageLoader.getInstance().displayImage("file://" + GlobalConfig.getFirstStoragePath() + "imgs" + File.separator + mDataset.get(i).aid + ".jpg", viewHolder.ivNovelCover); + else if(LightCache.testFileExist(GlobalConfig.getSecondStoragePath() + "imgs" + File.separator + mDataset.get(i).aid + ".jpg")) + ImageLoader.getInstance().displayImage("file://" + GlobalConfig.getSecondStoragePath() + "imgs" + File.separator + mDataset.get(i).aid + ".jpg", viewHolder.ivNovelCover); else - ImageLoader.getInstance().displayImage(Wenku8API.getCoverURL(mDataset.get(i).getAid()), viewHolder.ivNovelCover); + ImageLoader.getInstance().displayImage(Wenku8API.getCoverURL(mDataset.get(i).aid), viewHolder.ivNovelCover); } @@ -110,17 +110,16 @@ public static class ViewHolder extends RecyclerView.ViewHolder implements View.O private MyOptionClickListener mMyOptionClickListener; private MyItemLongClickListener mLongClickListener; public int position; - public boolean isLoading = false; private ImageButton ibNovelOption; - public ImageView ivNovelCover; - public TextView tvNovelTitle; - public TextView tvNovelStatus; - public TextView tvNovelAuthor; - public TextView tvNovelUpdate; - public TextView tvNovelIntro; - - public ViewHolder(View itemView, MyItemClickListener clickListener, MyOptionClickListener myOptionClickListener, MyItemLongClickListener longClickListener) { + ImageView ivNovelCover; + TextView tvNovelTitle; + TextView tvNovelStatus; + TextView tvNovelAuthor; + TextView tvNovelUpdate; + TextView tvNovelIntro; + + ViewHolder(View itemView, MyItemClickListener clickListener, MyOptionClickListener myOptionClickListener, MyItemLongClickListener longClickListener) { super(itemView); this.mClickListener = clickListener; this.mMyOptionClickListener = myOptionClickListener; diff --git a/studio-android/LightNovelLibrary/app/src/main/java/org/mewx/wenku8/fragment/LatestFragment.java b/studio-android/LightNovelLibrary/app/src/main/java/org/mewx/wenku8/fragment/LatestFragment.java index 82bca947..a7a4c182 100644 --- a/studio-android/LightNovelLibrary/app/src/main/java/org/mewx/wenku8/fragment/LatestFragment.java +++ b/studio-android/LightNovelLibrary/app/src/main/java/org/mewx/wenku8/fragment/LatestFragment.java @@ -26,7 +26,7 @@ import org.mewx.wenku8.activity.NovelInfoActivity; import org.mewx.wenku8.adapter.NovelItemAdapter; import org.mewx.wenku8.global.GlobalConfig; -import org.mewx.wenku8.global.api.NovelItemInfo; +import org.mewx.wenku8.global.api.NovelItemInfoUpdate; import org.mewx.wenku8.global.api.NovelListWithInfoParser; import org.mewx.wenku8.global.api.Wenku8API; import org.mewx.wenku8.listener.MyItemClickListener; @@ -48,7 +48,7 @@ public class LatestFragment extends Fragment implements MyItemClickListener, MyI private TextView mTextView; // Novel Item info - private List listNovelItemInfo; + private List listNovelItemInfo; private NovelItemAdapter mAdapter; private int currentPage, totalPage; // currentP stores next reading page num, TODO: fix wrong number @@ -140,9 +140,9 @@ public void onItemClick(View view, final int position) { // go to detail activity Intent intent = new Intent(getActivity(), NovelInfoActivity.class); - intent.putExtra("aid", listNovelItemInfo.get(position).getAid()); + intent.putExtra("aid", listNovelItemInfo.get(position).aid); intent.putExtra("from", "latest"); - intent.putExtra("title", listNovelItemInfo.get(position).getTitle()); + intent.putExtra("title", listNovelItemInfo.get(position).title); if(Build.VERSION.SDK_INT < 21) { startActivity(intent); } @@ -224,12 +224,11 @@ protected Integer doInBackground(ContentValues... params) { // byte[] img = LightNetwork.LightHttpPost( // Wenku8Interface.BaseURL, imgP); - NovelItemInfo ni = new NovelItemInfo(); - ni.setAid(nlwi.aid); - ni.setTitle(nlwi.name); - ni.setAuthor(nlwi.hit + ""); // hit - ni.setUpdate(nlwi.push + ""); // push - ni.setIntro_short(nlwi.fav + ""); // fav + NovelItemInfoUpdate ni = new NovelItemInfoUpdate(nlwi.aid); + ni.title = nlwi.name; + ni.author = nlwi.hit + ""; // hit + ni.update = nlwi.push + ""; // push + ni.intro_short = nlwi.fav + ""; // fav listNovelItemInfo.add(ni); } diff --git a/studio-android/LightNovelLibrary/app/src/main/java/org/mewx/wenku8/global/api/NovelItemInfo.java b/studio-android/LightNovelLibrary/app/src/main/java/org/mewx/wenku8/global/api/NovelItemInfo.java deleted file mode 100644 index e1257fa7..00000000 --- a/studio-android/LightNovelLibrary/app/src/main/java/org/mewx/wenku8/global/api/NovelItemInfo.java +++ /dev/null @@ -1,180 +0,0 @@ -package org.mewx.wenku8.global.api; - -import org.xmlpull.v1.XmlPullParser; -import org.xmlpull.v1.XmlPullParserFactory; - -import java.io.StringReader; - -/** - * Created by MewX on 2015/1/20. - * Novel item info short. - */ -public class NovelItemInfo { - - // Variables - private boolean parseStatus; // default false -// private boolean loadingStatus; - - private int aid = 0; - private String title = ""; - private String author = ""; - private int status = 0; // 0 - not; 1 - finished - private String update = ""; // last update time - private String intro_short = ""; - -// private String intro_full = ""; // not necessary - -// private boolean imageReady = false; // image - - /** - * Init the whole struct with the received XML string - * - * @param str only str[0] is available, because I use array for pass by reference - */ - public NovelItemInfo(String[] str) { - setNovelItemInfo(str); - } - - public NovelItemInfo(int aid) { - // set aid only, first loading event - this.aid = aid; - this.title = Integer.toString(aid); // use aid as title - } - - public NovelItemInfo() { - // this construct is for manually set all info - parseStatus = true; - } - - public boolean setNovelItemInfo(String[] str) { - parseStatus = parseNovelItemIntro(str); - return parseStatus; - } - -// public boolean getLoadingStatus(){ -// return loadingStatus; -// } -// -// public void setLoadingStatus(boolean b){ -// loadingStatus = b; -// } - - public boolean getParseStatus() { - return parseStatus; // true - parsed, else failed. - } - - private boolean parseNovelItemIntro(String[] str) { - // only str[0] is available - - try { - XmlPullParserFactory factory = XmlPullParserFactory.newInstance(); - XmlPullParser xmlPullParser = factory.newPullParser(); - xmlPullParser.setInput(new StringReader(str[0])); - int eventType = xmlPullParser.getEventType(); - - while (eventType != XmlPullParser.END_DOCUMENT) { - switch (eventType) { - case XmlPullParser.START_DOCUMENT:// all start - break; - - case XmlPullParser.START_TAG: - - if ("metadata".equals(xmlPullParser.getName())) { - // Init all the value - aid = 0; - title = ""; - author = ""; - status = 0; - update = ""; - intro_short = ""; - - } else if ("data".equals(xmlPullParser.getName())) { - if ("Title".equals(xmlPullParser.getAttributeValue(0))) { - aid = Integer.valueOf( - xmlPullParser.getAttributeValue(1)); - title = xmlPullParser.nextText(); - } else if ("Author".equals(xmlPullParser - .getAttributeValue(0))) { - author = xmlPullParser.getAttributeValue(1); - } else if ("BookStatus".equals(xmlPullParser - .getAttributeValue(0))) { - status = Integer.valueOf( - xmlPullParser.getAttributeValue(1)); - } else if ("LastUpdate".equals(xmlPullParser - .getAttributeValue(0))) { - update = xmlPullParser.getAttributeValue(1); - } else if ("IntroPreview".equals(xmlPullParser - .getAttributeValue(0))) { - intro_short = xmlPullParser.nextText().trim().replaceAll("\u3000",""); - } - } - break; - } - eventType = xmlPullParser.next(); - } - return true; - } catch (Exception e) { - e.printStackTrace(); - return false; - } - } - - /** - * "get" functions - */ - public int getAid() { - return aid; - } - - public String getTitle() { - return title; - } - - public String getAuthor() { - return author; - } - - public int getStatus() { - return status; - } - - public String getUpdate() { - return update; - } - - public String getIntroShort() { - return intro_short; - } - - public void setAid(int aid) { - this.aid = aid; - } - - public void setTitle(String title) { - this.title = title; - } - - public void setAuthor(String author) { - this.author = author; - } - - public void setStatus(int status) { - this.status = status; - } - - public void setUpdate(String update) { - this.update = update; - } - - public void setIntro_short(String intro_short) { - this.intro_short = intro_short; - } - - // public String getIntroFull() { -// return intro_full; -// } -// -// public void setIntroFull(String str) { -// intro_full = str; -// } -} \ No newline at end of file From 4910c04edad852020b0feeef1fbce11bdcfcdf88 Mon Sep 17 00:00:00 2001 From: MewX Date: Sun, 12 Aug 2018 16:46:40 +0930 Subject: [PATCH 8/9] #32 Upgraded gradle version to the latest --- studio-android/LightNovelLibrary/app/build.gradle | 2 +- studio-android/LightNovelLibrary/build.gradle | 2 +- studio-android/LightNovelLibrary/volley/build.gradle | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/studio-android/LightNovelLibrary/app/build.gradle b/studio-android/LightNovelLibrary/app/build.gradle index 68a0d08d..a23df6ba 100644 --- a/studio-android/LightNovelLibrary/app/build.gradle +++ b/studio-android/LightNovelLibrary/app/build.gradle @@ -89,7 +89,7 @@ dependencies { androidTestImplementation 'com.android.support.test:runner:1.0.2' androidTestImplementation 'com.android.support.test:rules:1.0.2' androidTestImplementation 'junit:junit:4.12' - androidTestImplementation 'org.mockito:mockito-core:1.10.19' + androidTestImplementation 'org.mockito:mockito-all:1.10.19' androidTestImplementation 'com.google.dexmaker:dexmaker:1.2' androidTestImplementation 'com.google.dexmaker:dexmaker-mockito:1.2' diff --git a/studio-android/LightNovelLibrary/build.gradle b/studio-android/LightNovelLibrary/build.gradle index d3b7e9d8..d03b2944 100644 --- a/studio-android/LightNovelLibrary/build.gradle +++ b/studio-android/LightNovelLibrary/build.gradle @@ -6,7 +6,7 @@ buildscript { google() } dependencies { - classpath 'com.android.tools.build:gradle:3.1.3' + classpath 'com.android.tools.build:gradle:3.1.4' classpath 'org.kt3k.gradle.plugin:coveralls-gradle-plugin:2.4.0' // NOTE: Do not place your application dependencies here; they belong diff --git a/studio-android/LightNovelLibrary/volley/build.gradle b/studio-android/LightNovelLibrary/volley/build.gradle index a6dc672c..afe63151 100644 --- a/studio-android/LightNovelLibrary/volley/build.gradle +++ b/studio-android/LightNovelLibrary/volley/build.gradle @@ -20,7 +20,7 @@ buildscript { google() } dependencies { - classpath 'com.android.tools.build:gradle:3.1.3' + classpath 'com.android.tools.build:gradle:3.1.4' } } From 78ab7c44ee61ac810106ee2c49d18728f4000c3b Mon Sep 17 00:00:00 2001 From: MewX Date: Sun, 12 Aug 2018 20:07:36 +0930 Subject: [PATCH 9/9] #32 Fixed mockito version and changed dexmaker provider to linkedin --- studio-android/LightNovelLibrary/app/build.gradle | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/studio-android/LightNovelLibrary/app/build.gradle b/studio-android/LightNovelLibrary/app/build.gradle index a23df6ba..16d05014 100644 --- a/studio-android/LightNovelLibrary/app/build.gradle +++ b/studio-android/LightNovelLibrary/app/build.gradle @@ -89,9 +89,9 @@ dependencies { androidTestImplementation 'com.android.support.test:runner:1.0.2' androidTestImplementation 'com.android.support.test:rules:1.0.2' androidTestImplementation 'junit:junit:4.12' - androidTestImplementation 'org.mockito:mockito-all:1.10.19' - androidTestImplementation 'com.google.dexmaker:dexmaker:1.2' - androidTestImplementation 'com.google.dexmaker:dexmaker-mockito:1.2' + androidTestImplementation 'org.mockito:mockito-core:2.19.0' + androidTestImplementation 'com.linkedin.dexmaker:dexmaker:2.19.1' + androidTestImplementation 'com.linkedin.dexmaker:dexmaker-mockito:2.19.1' testImplementation 'junit:junit:4.12' testImplementation 'org.mockito:mockito-all:1.10.19'