refactor: Remove Ununsed Files and Dependencies
This commit is contained in:
@@ -84,7 +84,6 @@ project.ext.react = [
|
||||
apply from: '../../node_modules/react-native-unimodules/gradle.groovy'
|
||||
apply from: "../../node_modules/react-native/react.gradle"
|
||||
apply from: "../../node_modules/expo-constants/scripts/get-app-config-android.gradle"
|
||||
apply from: "../../node_modules/expo-updates/scripts/create-manifest-android.gradle"
|
||||
|
||||
/**
|
||||
* Set this to true to create two separate APKs instead of one:
|
||||
|
||||
@@ -30,26 +30,6 @@
|
||||
android:allowBackup="true"
|
||||
android:theme="@style/AppTheme"
|
||||
android:usesCleartextTraffic="true">
|
||||
|
||||
<meta-data
|
||||
android:name="expo.modules.updates.EXPO_UPDATE_URL"
|
||||
android:value="https://exp.host/@rajarsheechatterjee/LNReader"/>
|
||||
|
||||
<meta-data
|
||||
android:name="expo.modules.updates.EXPO_SDK_VERSION"
|
||||
android:value="41.0.0"/>
|
||||
|
||||
<meta-data
|
||||
android:name="expo.modules.updates.ENABLED"
|
||||
android:value="false"/>
|
||||
|
||||
<meta-data
|
||||
android:name="expo.modules.updates.EXPO_UPDATES_CHECK_ON_LAUNCH"
|
||||
android:value="ALWAYS"/>
|
||||
|
||||
<meta-data
|
||||
android:name="expo.modules.updates.EXPO_UPDATES_LAUNCH_WAIT_MS"
|
||||
android:value="0"/>
|
||||
|
||||
<meta-data
|
||||
android:name="expo.modules.notifications.default_notification_icon"
|
||||
|
||||
@@ -2,7 +2,6 @@ package com.rajarsheechatterjee.LNReader;
|
||||
|
||||
import android.app.Application;
|
||||
import android.content.Context;
|
||||
import android.net.Uri;
|
||||
|
||||
import com.facebook.react.PackageList;
|
||||
import com.facebook.react.ReactApplication;
|
||||
@@ -21,7 +20,6 @@ import org.unimodules.core.interfaces.SingletonModule;
|
||||
import expo.modules.constants.ConstantsPackage;
|
||||
import expo.modules.permissions.PermissionsPackage;
|
||||
import expo.modules.filesystem.FileSystemPackage;
|
||||
import expo.modules.updates.UpdatesController;
|
||||
|
||||
import com.facebook.react.bridge.JSIModulePackage;
|
||||
import com.swmansion.reanimated.ReanimatedJSIModulePackage;
|
||||
@@ -29,7 +27,6 @@ import com.swmansion.reanimated.ReanimatedJSIModulePackage;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class MainApplication extends Application implements ReactApplication {
|
||||
private final ReactModuleRegistryProvider mModuleRegistryProvider = new ReactModuleRegistryProvider(
|
||||
@@ -59,24 +56,6 @@ public class MainApplication extends Application implements ReactApplication {
|
||||
protected JSIModulePackage getJSIModulePackage() {
|
||||
return new ReanimatedJSIModulePackage();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @Nullable String getJSBundleFile() {
|
||||
if (BuildConfig.DEBUG) {
|
||||
return super.getJSBundleFile();
|
||||
} else {
|
||||
return UpdatesController.getInstance().getLaunchAssetFile();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @Nullable String getBundleAssetName() {
|
||||
if (BuildConfig.DEBUG) {
|
||||
return super.getBundleAssetName();
|
||||
} else {
|
||||
return UpdatesController.getInstance().getBundleAssetName();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
@@ -89,10 +68,6 @@ public class MainApplication extends Application implements ReactApplication {
|
||||
super.onCreate();
|
||||
SoLoader.init(this, /* native exopackage */ false);
|
||||
|
||||
if (!BuildConfig.DEBUG) {
|
||||
UpdatesController.initialize(this);
|
||||
}
|
||||
|
||||
initializeFlipper(this, getReactNativeHost().getReactInstanceManager());
|
||||
}
|
||||
|
||||
|
||||
-1
@@ -22,7 +22,6 @@ public class BasePackageList {
|
||||
new expo.modules.permissions.PermissionsPackage(),
|
||||
new expo.modules.splashscreen.SplashScreenPackage(),
|
||||
new expo.modules.sqlite.SQLitePackage(),
|
||||
new expo.modules.updates.UpdatesPackage(),
|
||||
new expo.modules.webbrowser.WebBrowserPackage()
|
||||
);
|
||||
}
|
||||
|
||||
Generated
+5
-219
@@ -10,18 +10,15 @@
|
||||
"dependencies": {
|
||||
"@react-native-async-storage/async-storage": "^1.15.11",
|
||||
"@react-native-community/masked-view": "^0.1.11",
|
||||
"@react-native-community/netinfo": "^7.1.1",
|
||||
"@react-native-community/slider": "^4.1.12",
|
||||
"@react-navigation/material-bottom-tabs": "^6.0.9",
|
||||
"@react-navigation/native": "^6.0.6",
|
||||
"@react-navigation/stack": "^6.0.11",
|
||||
"@reduxjs/toolkit": "^1.7.2",
|
||||
"@types/react-native-vector-icons": "^6.4.10",
|
||||
"cheerio": "^1.0.0-rc.10",
|
||||
"expo": "^41.0.1",
|
||||
"expo-document-picker": "^9.2.4",
|
||||
"expo-file-system": "~11.0.2",
|
||||
"expo-font": "~9.1.0",
|
||||
"expo-haptics": "~10.0.0",
|
||||
"expo-keep-awake": "~9.1.2",
|
||||
"expo-linear-gradient": "~9.1.0",
|
||||
@@ -30,7 +27,6 @@
|
||||
"expo-notifications": "~0.11.6",
|
||||
"expo-splash-screen": "^0.11.4",
|
||||
"expo-sqlite": "~9.1.0",
|
||||
"expo-updates": "~0.5.4",
|
||||
"expo-web-browser": "~9.1.0",
|
||||
"i18n-js": "^3.8.0",
|
||||
"lodash": "^4.17.21",
|
||||
@@ -51,18 +47,15 @@
|
||||
"react-native-render-html": "^6.3.4",
|
||||
"react-native-safe-area-context": "^3.2.0",
|
||||
"react-native-screens": "^3.9.0",
|
||||
"react-native-skeleton-placeholder": "^5.0.0",
|
||||
"react-native-swipe-gestures": "^1.0.5",
|
||||
"react-native-tab-view": "^3.1.1",
|
||||
"react-native-tts": "^4.1.0",
|
||||
"react-native-unimodules": "^0.13.3",
|
||||
"react-native-vector-icons": "^9.0.0",
|
||||
"react-native-web": "^0.17.5",
|
||||
"react-native-webview": "^11.14.3",
|
||||
"react-redux": "^7.2.6",
|
||||
"redux": "^4.1.2",
|
||||
"redux-persist": "^6.0.0",
|
||||
"redux-thunk": "^2.4.0",
|
||||
"rn-sliding-up-panel": "^2.4.4",
|
||||
"sanitize-html": "^2.7.0"
|
||||
},
|
||||
@@ -73,6 +66,7 @@
|
||||
"@types/jest": "^27.4.0",
|
||||
"@types/lodash": "^4.14.179",
|
||||
"@types/react-native": "^0.66.15",
|
||||
"@types/react-native-vector-icons": "^6.4.10",
|
||||
"@types/react-test-renderer": "^17.0.1",
|
||||
"@types/sanitize-html": "^2.6.2",
|
||||
"@typescript-eslint/eslint-plugin": "^5.10.2",
|
||||
@@ -3781,14 +3775,6 @@
|
||||
"react-native": ">=0.57"
|
||||
}
|
||||
},
|
||||
"node_modules/@react-native-community/netinfo": {
|
||||
"version": "7.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@react-native-community/netinfo/-/netinfo-7.1.1.tgz",
|
||||
"integrity": "sha512-i8mSbp4JqIH0nEpHJGlVyr4Xb2/jtkK2YZbtiVU+gOih3FvhK2MzRLaEaDGr/DW8DTSKCo0QupUaiqrA3Lvcqg==",
|
||||
"peerDependencies": {
|
||||
"react-native": ">=0.59"
|
||||
}
|
||||
},
|
||||
"node_modules/@react-native-community/slider": {
|
||||
"version": "4.1.12",
|
||||
"resolved": "https://registry.npmjs.org/@react-native-community/slider/-/slider-4.1.12.tgz",
|
||||
@@ -4076,6 +4062,7 @@
|
||||
"version": "0.66.15",
|
||||
"resolved": "https://registry.npmjs.org/@types/react-native/-/react-native-0.66.15.tgz",
|
||||
"integrity": "sha512-qNK3LZhNpSd2Hdr0OFdvQ/VOb1qcjNhmw96LsOtxIN+1RtXHO/1dVzxYUlWnKMCtV+E5WSaWM703c9Q7gG9tyg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/react": "*"
|
||||
}
|
||||
@@ -4084,6 +4071,7 @@
|
||||
"version": "6.4.10",
|
||||
"resolved": "https://registry.npmjs.org/@types/react-native-vector-icons/-/react-native-vector-icons-6.4.10.tgz",
|
||||
"integrity": "sha512-z4sexbuZ7nmYsp7Z9YB5fSQoN3KFn6nZA3QsCkQLOYnVmVlxX4U22v/bM9Xx/6dOA1vClxoRZo2CFDX16uryXQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/react": "*",
|
||||
"@types/react-native": "*"
|
||||
@@ -4864,14 +4852,6 @@
|
||||
"resolved": "https://registry.npmjs.org/array-filter/-/array-filter-1.0.0.tgz",
|
||||
"integrity": "sha1-uveeYubvTCpMC4MSMtr/7CUfnYM="
|
||||
},
|
||||
"node_modules/array-find-index": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz",
|
||||
"integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/array-includes": {
|
||||
"version": "3.1.4",
|
||||
"resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.4.tgz",
|
||||
@@ -6192,15 +6172,6 @@
|
||||
"js-yaml": "bin/js-yaml.js"
|
||||
}
|
||||
},
|
||||
"node_modules/create-react-class": {
|
||||
"version": "15.7.0",
|
||||
"resolved": "https://registry.npmjs.org/create-react-class/-/create-react-class-15.7.0.tgz",
|
||||
"integrity": "sha512-QZv4sFWG9S5RUvkTYWbflxeZX+JG7Cz0Tn33rQBJ+WFQTqTfUTjMjiv9tnfXazjsO5r0KhPs+AqCjyrQX6h2ng==",
|
||||
"dependencies": {
|
||||
"loose-envify": "^1.3.1",
|
||||
"object-assign": "^4.1.1"
|
||||
}
|
||||
},
|
||||
"node_modules/cross-fetch": {
|
||||
"version": "3.1.5",
|
||||
"resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.5.tgz",
|
||||
@@ -6248,15 +6219,6 @@
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/css-in-js-utils": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/css-in-js-utils/-/css-in-js-utils-2.0.1.tgz",
|
||||
"integrity": "sha512-PJF0SpJT+WdbVVt0AOYp9C8GnuruRlL/UFW7932nLWmFLQTaWEzTBQEx7/hn4BuV+WON75iAViSUJLiU3PKbpA==",
|
||||
"dependencies": {
|
||||
"hyphenate-style-name": "^1.0.2",
|
||||
"isobject": "^3.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/css-to-react-native": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/css-to-react-native/-/css-to-react-native-3.0.0.tgz",
|
||||
@@ -7754,24 +7716,6 @@
|
||||
"lodash": "^4.17.15"
|
||||
}
|
||||
},
|
||||
"node_modules/expo-structured-headers": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/expo-structured-headers/-/expo-structured-headers-1.0.1.tgz",
|
||||
"integrity": "sha512-U4frE8rT5x1LqZv5Ru/9CtzY8gh0wp1MfwTu5hetPydnwxXfWchuXvKgWRjEHglFU2X/29kYFY/J1UkPvCN8xg=="
|
||||
},
|
||||
"node_modules/expo-updates": {
|
||||
"version": "0.5.5",
|
||||
"resolved": "https://registry.npmjs.org/expo-updates/-/expo-updates-0.5.5.tgz",
|
||||
"integrity": "sha512-1R8EKkT3GoDjMRQnDaTYv31gIYIaYQGHOrjHJfwq8ai9f1W1AHux6KAH2/H6sc2o9a7roWVwjDn2kKwCm9AeHg==",
|
||||
"dependencies": {
|
||||
"@expo/config-plugins": "^1.0.18",
|
||||
"@expo/metro-config": "^0.1.59",
|
||||
"expo-structured-headers": "~1.0.1",
|
||||
"fbemitter": "^2.1.1",
|
||||
"resolve-from": "^5.0.0",
|
||||
"uuid": "^3.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/expo-web-browser": {
|
||||
"version": "9.1.0",
|
||||
"resolved": "https://registry.npmjs.org/expo-web-browser/-/expo-web-browser-9.1.0.tgz",
|
||||
@@ -8626,11 +8570,6 @@
|
||||
"url": "https://github.com/sponsors/typicode"
|
||||
}
|
||||
},
|
||||
"node_modules/hyphenate-style-name": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/hyphenate-style-name/-/hyphenate-style-name-1.0.4.tgz",
|
||||
"integrity": "sha512-ygGZLjmXfPHj+ZWh6LwbC37l43MhfztxetbFCoYTM2VjkIUpeHgSNn7QIyVFj7YQ1Wl9Cbw5sholVJPzWvC2MQ=="
|
||||
},
|
||||
"node_modules/i18n-js": {
|
||||
"version": "3.8.0",
|
||||
"resolved": "https://registry.npmjs.org/i18n-js/-/i18n-js-3.8.0.tgz",
|
||||
@@ -8751,14 +8690,6 @@
|
||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
|
||||
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
|
||||
},
|
||||
"node_modules/inline-style-prefixer": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/inline-style-prefixer/-/inline-style-prefixer-6.0.0.tgz",
|
||||
"integrity": "sha512-XTHvRUS4ZJNzC1GixJRmOlWSS45fSt+DJoyQC9ytj0WxQfcgofQtDtyKKYxHUqEsWCs+LIWftPF1ie7+i012Fg==",
|
||||
"dependencies": {
|
||||
"css-in-js-utils": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/internal-slot": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz",
|
||||
@@ -11577,11 +11508,6 @@
|
||||
"resolved": "https://registry.npmjs.org/noop-fn/-/noop-fn-1.0.0.tgz",
|
||||
"integrity": "sha1-XzPUfxPSFQ35PgywNmmemC94/78="
|
||||
},
|
||||
"node_modules/normalize-css-color": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/normalize-css-color/-/normalize-css-color-1.0.2.tgz",
|
||||
"integrity": "sha1-Apkel8zOxmI/5XOvu/Deah8+n40="
|
||||
},
|
||||
"node_modules/normalize-path": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
|
||||
@@ -12955,17 +12881,6 @@
|
||||
"react": "^17.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/react-native-skeleton-placeholder": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/react-native-skeleton-placeholder/-/react-native-skeleton-placeholder-5.0.0.tgz",
|
||||
"integrity": "sha512-7sdG+Y2ENEVcxFC9XlpCgHy59XKkxaUyVqDwuAb66hvl7lwFr25uA5kHJ+JuDJ84ptVil5UEowW/2avwhsfoYg==",
|
||||
"peerDependencies": {
|
||||
"@react-native-masked-view/masked-view": "^0.2.3",
|
||||
"react": ">=0.14.8",
|
||||
"react-native": ">=0.50.1",
|
||||
"react-native-linear-gradient": "^2.5.6"
|
||||
}
|
||||
},
|
||||
"node_modules/react-native-swipe-gestures": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/react-native-swipe-gestures/-/react-native-swipe-gestures-1.0.5.tgz",
|
||||
@@ -13154,38 +13069,6 @@
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/react-native-web": {
|
||||
"version": "0.17.5",
|
||||
"resolved": "https://registry.npmjs.org/react-native-web/-/react-native-web-0.17.5.tgz",
|
||||
"integrity": "sha512-pdieIZi2/YeVTaOuIaeaLC6FMkk8h3pvPNruedH+6cWiE15Oz6BGjJ+5IafdXEyiipb1Y0+QuecW81fa3DVM4g==",
|
||||
"dependencies": {
|
||||
"array-find-index": "^1.0.2",
|
||||
"create-react-class": "^15.7.0",
|
||||
"fbjs": "^3.0.0",
|
||||
"hyphenate-style-name": "^1.0.4",
|
||||
"inline-style-prefixer": "^6.0.0",
|
||||
"normalize-css-color": "^1.0.2",
|
||||
"prop-types": "^15.6.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": ">=17.0.1",
|
||||
"react-dom": ">=17.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/react-native-web/node_modules/fbjs": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/fbjs/-/fbjs-3.0.0.tgz",
|
||||
"integrity": "sha512-dJd4PiDOFuhe7vk4F80Mba83Vr2QuK86FoxtgPmzBqEJahncp+13YCmfoa53KHCo6OnlXLG7eeMWPfB5CrpVKg==",
|
||||
"dependencies": {
|
||||
"cross-fetch": "^3.0.4",
|
||||
"fbjs-css-vars": "^1.0.0",
|
||||
"loose-envify": "^1.0.0",
|
||||
"object-assign": "^4.1.0",
|
||||
"promise": "^7.1.1",
|
||||
"setimmediate": "^1.0.5",
|
||||
"ua-parser-js": "^0.7.18"
|
||||
}
|
||||
},
|
||||
"node_modules/react-native-webview": {
|
||||
"version": "11.14.3",
|
||||
"resolved": "https://registry.npmjs.org/react-native-webview/-/react-native-webview-11.14.3.tgz",
|
||||
@@ -18933,11 +18816,6 @@
|
||||
"resolved": "https://registry.npmjs.org/@react-native-community/masked-view/-/masked-view-0.1.11.tgz",
|
||||
"integrity": "sha512-rQfMIGSR/1r/SyN87+VD8xHHzDYeHaJq6elOSCAD+0iLagXkSI2pfA0LmSXP21uw5i3em7GkkRjfJ8wpqWXZNw=="
|
||||
},
|
||||
"@react-native-community/netinfo": {
|
||||
"version": "7.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@react-native-community/netinfo/-/netinfo-7.1.1.tgz",
|
||||
"integrity": "sha512-i8mSbp4JqIH0nEpHJGlVyr4Xb2/jtkK2YZbtiVU+gOih3FvhK2MzRLaEaDGr/DW8DTSKCo0QupUaiqrA3Lvcqg=="
|
||||
},
|
||||
"@react-native-community/slider": {
|
||||
"version": "4.1.12",
|
||||
"resolved": "https://registry.npmjs.org/@react-native-community/slider/-/slider-4.1.12.tgz",
|
||||
@@ -19175,6 +19053,7 @@
|
||||
"version": "0.66.15",
|
||||
"resolved": "https://registry.npmjs.org/@types/react-native/-/react-native-0.66.15.tgz",
|
||||
"integrity": "sha512-qNK3LZhNpSd2Hdr0OFdvQ/VOb1qcjNhmw96LsOtxIN+1RtXHO/1dVzxYUlWnKMCtV+E5WSaWM703c9Q7gG9tyg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/react": "*"
|
||||
}
|
||||
@@ -19183,6 +19062,7 @@
|
||||
"version": "6.4.10",
|
||||
"resolved": "https://registry.npmjs.org/@types/react-native-vector-icons/-/react-native-vector-icons-6.4.10.tgz",
|
||||
"integrity": "sha512-z4sexbuZ7nmYsp7Z9YB5fSQoN3KFn6nZA3QsCkQLOYnVmVlxX4U22v/bM9Xx/6dOA1vClxoRZo2CFDX16uryXQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/react": "*",
|
||||
"@types/react-native": "*"
|
||||
@@ -19696,11 +19576,6 @@
|
||||
"resolved": "https://registry.npmjs.org/array-filter/-/array-filter-1.0.0.tgz",
|
||||
"integrity": "sha1-uveeYubvTCpMC4MSMtr/7CUfnYM="
|
||||
},
|
||||
"array-find-index": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz",
|
||||
"integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E="
|
||||
},
|
||||
"array-includes": {
|
||||
"version": "3.1.4",
|
||||
"resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.4.tgz",
|
||||
@@ -20700,15 +20575,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"create-react-class": {
|
||||
"version": "15.7.0",
|
||||
"resolved": "https://registry.npmjs.org/create-react-class/-/create-react-class-15.7.0.tgz",
|
||||
"integrity": "sha512-QZv4sFWG9S5RUvkTYWbflxeZX+JG7Cz0Tn33rQBJ+WFQTqTfUTjMjiv9tnfXazjsO5r0KhPs+AqCjyrQX6h2ng==",
|
||||
"requires": {
|
||||
"loose-envify": "^1.3.1",
|
||||
"object-assign": "^4.1.1"
|
||||
}
|
||||
},
|
||||
"cross-fetch": {
|
||||
"version": "3.1.5",
|
||||
"resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.5.tgz",
|
||||
@@ -20746,15 +20612,6 @@
|
||||
"resolved": "https://registry.npmjs.org/css-color-keywords/-/css-color-keywords-1.0.0.tgz",
|
||||
"integrity": "sha1-/qJhbcZ2spYmhrOvjb2+GAskTgU="
|
||||
},
|
||||
"css-in-js-utils": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/css-in-js-utils/-/css-in-js-utils-2.0.1.tgz",
|
||||
"integrity": "sha512-PJF0SpJT+WdbVVt0AOYp9C8GnuruRlL/UFW7932nLWmFLQTaWEzTBQEx7/hn4BuV+WON75iAViSUJLiU3PKbpA==",
|
||||
"requires": {
|
||||
"hyphenate-style-name": "^1.0.2",
|
||||
"isobject": "^3.0.1"
|
||||
}
|
||||
},
|
||||
"css-to-react-native": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/css-to-react-native/-/css-to-react-native-3.0.0.tgz",
|
||||
@@ -21932,24 +21789,6 @@
|
||||
"lodash": "^4.17.15"
|
||||
}
|
||||
},
|
||||
"expo-structured-headers": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/expo-structured-headers/-/expo-structured-headers-1.0.1.tgz",
|
||||
"integrity": "sha512-U4frE8rT5x1LqZv5Ru/9CtzY8gh0wp1MfwTu5hetPydnwxXfWchuXvKgWRjEHglFU2X/29kYFY/J1UkPvCN8xg=="
|
||||
},
|
||||
"expo-updates": {
|
||||
"version": "0.5.5",
|
||||
"resolved": "https://registry.npmjs.org/expo-updates/-/expo-updates-0.5.5.tgz",
|
||||
"integrity": "sha512-1R8EKkT3GoDjMRQnDaTYv31gIYIaYQGHOrjHJfwq8ai9f1W1AHux6KAH2/H6sc2o9a7roWVwjDn2kKwCm9AeHg==",
|
||||
"requires": {
|
||||
"@expo/config-plugins": "^1.0.18",
|
||||
"@expo/metro-config": "^0.1.59",
|
||||
"expo-structured-headers": "~1.0.1",
|
||||
"fbemitter": "^2.1.1",
|
||||
"resolve-from": "^5.0.0",
|
||||
"uuid": "^3.4.0"
|
||||
}
|
||||
},
|
||||
"expo-web-browser": {
|
||||
"version": "9.1.0",
|
||||
"resolved": "https://registry.npmjs.org/expo-web-browser/-/expo-web-browser-9.1.0.tgz",
|
||||
@@ -22602,11 +22441,6 @@
|
||||
"integrity": "sha512-vbaCKN2QLtP/vD4yvs6iz6hBEo6wkSzs8HpRah1Z6aGmF2KW5PdYuAd7uX5a+OyBZHBhd+TFLqgjUgytQr4RvQ==",
|
||||
"dev": true
|
||||
},
|
||||
"hyphenate-style-name": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/hyphenate-style-name/-/hyphenate-style-name-1.0.4.tgz",
|
||||
"integrity": "sha512-ygGZLjmXfPHj+ZWh6LwbC37l43MhfztxetbFCoYTM2VjkIUpeHgSNn7QIyVFj7YQ1Wl9Cbw5sholVJPzWvC2MQ=="
|
||||
},
|
||||
"i18n-js": {
|
||||
"version": "3.8.0",
|
||||
"resolved": "https://registry.npmjs.org/i18n-js/-/i18n-js-3.8.0.tgz",
|
||||
@@ -22687,14 +22521,6 @@
|
||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
|
||||
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
|
||||
},
|
||||
"inline-style-prefixer": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/inline-style-prefixer/-/inline-style-prefixer-6.0.0.tgz",
|
||||
"integrity": "sha512-XTHvRUS4ZJNzC1GixJRmOlWSS45fSt+DJoyQC9ytj0WxQfcgofQtDtyKKYxHUqEsWCs+LIWftPF1ie7+i012Fg==",
|
||||
"requires": {
|
||||
"css-in-js-utils": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"internal-slot": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz",
|
||||
@@ -24876,11 +24702,6 @@
|
||||
"resolved": "https://registry.npmjs.org/noop-fn/-/noop-fn-1.0.0.tgz",
|
||||
"integrity": "sha1-XzPUfxPSFQ35PgywNmmemC94/78="
|
||||
},
|
||||
"normalize-css-color": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/normalize-css-color/-/normalize-css-color-1.0.2.tgz",
|
||||
"integrity": "sha1-Apkel8zOxmI/5XOvu/Deah8+n40="
|
||||
},
|
||||
"normalize-path": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
|
||||
@@ -26170,11 +25991,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"react-native-skeleton-placeholder": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/react-native-skeleton-placeholder/-/react-native-skeleton-placeholder-5.0.0.tgz",
|
||||
"integrity": "sha512-7sdG+Y2ENEVcxFC9XlpCgHy59XKkxaUyVqDwuAb66hvl7lwFr25uA5kHJ+JuDJ84ptVil5UEowW/2avwhsfoYg=="
|
||||
},
|
||||
"react-native-swipe-gestures": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/react-native-swipe-gestures/-/react-native-swipe-gestures-1.0.5.tgz",
|
||||
@@ -26324,36 +26140,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"react-native-web": {
|
||||
"version": "0.17.5",
|
||||
"resolved": "https://registry.npmjs.org/react-native-web/-/react-native-web-0.17.5.tgz",
|
||||
"integrity": "sha512-pdieIZi2/YeVTaOuIaeaLC6FMkk8h3pvPNruedH+6cWiE15Oz6BGjJ+5IafdXEyiipb1Y0+QuecW81fa3DVM4g==",
|
||||
"requires": {
|
||||
"array-find-index": "^1.0.2",
|
||||
"create-react-class": "^15.7.0",
|
||||
"fbjs": "^3.0.0",
|
||||
"hyphenate-style-name": "^1.0.4",
|
||||
"inline-style-prefixer": "^6.0.0",
|
||||
"normalize-css-color": "^1.0.2",
|
||||
"prop-types": "^15.6.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"fbjs": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/fbjs/-/fbjs-3.0.0.tgz",
|
||||
"integrity": "sha512-dJd4PiDOFuhe7vk4F80Mba83Vr2QuK86FoxtgPmzBqEJahncp+13YCmfoa53KHCo6OnlXLG7eeMWPfB5CrpVKg==",
|
||||
"requires": {
|
||||
"cross-fetch": "^3.0.4",
|
||||
"fbjs-css-vars": "^1.0.0",
|
||||
"loose-envify": "^1.0.0",
|
||||
"object-assign": "^4.1.0",
|
||||
"promise": "^7.1.1",
|
||||
"setimmediate": "^1.0.5",
|
||||
"ua-parser-js": "^0.7.18"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"react-native-webview": {
|
||||
"version": "11.14.3",
|
||||
"resolved": "https://registry.npmjs.org/react-native-webview/-/react-native-webview-11.14.3.tgz",
|
||||
|
||||
+1
-7
@@ -17,18 +17,15 @@
|
||||
"dependencies": {
|
||||
"@react-native-async-storage/async-storage": "^1.15.11",
|
||||
"@react-native-community/masked-view": "^0.1.11",
|
||||
"@react-native-community/netinfo": "^7.1.1",
|
||||
"@react-native-community/slider": "^4.1.12",
|
||||
"@react-navigation/material-bottom-tabs": "^6.0.9",
|
||||
"@react-navigation/native": "^6.0.6",
|
||||
"@react-navigation/stack": "^6.0.11",
|
||||
"@reduxjs/toolkit": "^1.7.2",
|
||||
"@types/react-native-vector-icons": "^6.4.10",
|
||||
"cheerio": "^1.0.0-rc.10",
|
||||
"expo": "^41.0.1",
|
||||
"expo-document-picker": "^9.2.4",
|
||||
"expo-file-system": "~11.0.2",
|
||||
"expo-font": "~9.1.0",
|
||||
"expo-haptics": "~10.0.0",
|
||||
"expo-keep-awake": "~9.1.2",
|
||||
"expo-linear-gradient": "~9.1.0",
|
||||
@@ -37,7 +34,6 @@
|
||||
"expo-notifications": "~0.11.6",
|
||||
"expo-splash-screen": "^0.11.4",
|
||||
"expo-sqlite": "~9.1.0",
|
||||
"expo-updates": "~0.5.4",
|
||||
"expo-web-browser": "~9.1.0",
|
||||
"i18n-js": "^3.8.0",
|
||||
"lodash": "^4.17.21",
|
||||
@@ -58,18 +54,15 @@
|
||||
"react-native-render-html": "^6.3.4",
|
||||
"react-native-safe-area-context": "^3.2.0",
|
||||
"react-native-screens": "^3.9.0",
|
||||
"react-native-skeleton-placeholder": "^5.0.0",
|
||||
"react-native-swipe-gestures": "^1.0.5",
|
||||
"react-native-tab-view": "^3.1.1",
|
||||
"react-native-tts": "^4.1.0",
|
||||
"react-native-unimodules": "^0.13.3",
|
||||
"react-native-vector-icons": "^9.0.0",
|
||||
"react-native-web": "^0.17.5",
|
||||
"react-native-webview": "^11.14.3",
|
||||
"react-redux": "^7.2.6",
|
||||
"redux": "^4.1.2",
|
||||
"redux-persist": "^6.0.0",
|
||||
"redux-thunk": "^2.4.0",
|
||||
"rn-sliding-up-panel": "^2.4.4",
|
||||
"sanitize-html": "^2.7.0"
|
||||
},
|
||||
@@ -80,6 +73,7 @@
|
||||
"@types/jest": "^27.4.0",
|
||||
"@types/lodash": "^4.14.179",
|
||||
"@types/react-native": "^0.66.15",
|
||||
"@types/react-native-vector-icons": "^6.4.10",
|
||||
"@types/react-test-renderer": "^17.0.1",
|
||||
"@types/sanitize-html": "^2.6.2",
|
||||
"@typescript-eslint/eslint-plugin": "^5.10.2",
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
/* eslint-disable no-unused-vars */
|
||||
|
||||
import React from 'react';
|
||||
import { StyleSheet } from 'react-native';
|
||||
|
||||
export const Dialog = ({ visible, theme }) => {};
|
||||
|
||||
const styles = StyleSheet.create({});
|
||||
@@ -1,28 +0,0 @@
|
||||
import React from 'react';
|
||||
import { Text, View } from 'react-native';
|
||||
|
||||
import { IconButton } from 'react-native-paper';
|
||||
// import {Row} from './Common';
|
||||
|
||||
import EmptyView from './EmptyView';
|
||||
|
||||
const ErrorView = ({ theme, onRetry, error, openWebView }) => (
|
||||
<View style={{ flex: 1, justifyContent: 'center' }}>
|
||||
<EmptyView
|
||||
icon="(; ̄Д ̄)"
|
||||
description={error}
|
||||
style={{ color: theme.textColorSecondary }}
|
||||
>
|
||||
<IconButton
|
||||
icon="reload"
|
||||
size={25}
|
||||
style={{ margin: 0, marginTop: 24 }}
|
||||
color={theme.text}
|
||||
onPress={onRetry}
|
||||
/>
|
||||
<Text style={{ color: theme.textColorPrimary }}>Retry</Text>
|
||||
</EmptyView>
|
||||
</View>
|
||||
);
|
||||
|
||||
export default ErrorView;
|
||||
@@ -14,7 +14,6 @@ import ListView from './ListView';
|
||||
|
||||
import { useDeviceOrientation } from '../services/utils/helpers';
|
||||
import { useSettings } from '../hooks/reduxHooks';
|
||||
import { defaultCoverUri } from '../sources/helpers/constants';
|
||||
import { coverPlaceholderColor } from '../theme/colors';
|
||||
|
||||
const NovelCover = ({
|
||||
|
||||
@@ -1,180 +0,0 @@
|
||||
import React from 'react';
|
||||
import {
|
||||
Pressable,
|
||||
PressableProps,
|
||||
StyleSheet,
|
||||
Text,
|
||||
View,
|
||||
} from 'react-native';
|
||||
import FastImage from 'react-native-fast-image';
|
||||
import { useAppearanceSettings, useLibrarySettings } from '../../redux/hooks';
|
||||
|
||||
import { LibraryNovelInfo, NovelInfo } from '../../database/types';
|
||||
import { SourceNovelItem } from '../../sources/types';
|
||||
import { ThemeType } from '../../theme/types';
|
||||
import {
|
||||
UnreadBadge,
|
||||
DownloadsBadge,
|
||||
InLibraryBadge,
|
||||
} from './NovelCoverBadges';
|
||||
import { DisplayModes } from '../../redux/settings/settingsSlice';
|
||||
import { LinearGradient } from 'expo-linear-gradient';
|
||||
import { useDeviceOrientation, useNovelCoverHeight } from '../../hooks';
|
||||
import { DeviceOrientation } from '../../hooks/useDeviceOrientation';
|
||||
|
||||
interface Props extends PressableProps {
|
||||
item: LibraryNovelInfo | SourceNovelItem | NovelInfo;
|
||||
isSelected: boolean;
|
||||
theme: ThemeType;
|
||||
showInLibraryBadge?: boolean;
|
||||
}
|
||||
|
||||
const NovelItem: React.FC<Props> = props => {
|
||||
const { item, showInLibraryBadge = false, theme, isSelected = false } = props;
|
||||
|
||||
const { displayMode } = useAppearanceSettings();
|
||||
const { novelsPerRowLandscape, novelsPerRowPotrait } =
|
||||
useAppearanceSettings();
|
||||
const { showUnreadBadge, showDownloadsBadge } = useLibrarySettings();
|
||||
|
||||
const orientation = useDeviceOrientation();
|
||||
|
||||
const coverHeight = useNovelCoverHeight();
|
||||
|
||||
const coverSelectedStyle = {
|
||||
backgroundColor: theme.primary,
|
||||
opacity: 0.8,
|
||||
};
|
||||
|
||||
return (
|
||||
<View
|
||||
style={[
|
||||
{
|
||||
flex:
|
||||
1 /
|
||||
(orientation === DeviceOrientation.POTRAIT
|
||||
? novelsPerRowPotrait
|
||||
: novelsPerRowLandscape),
|
||||
},
|
||||
styles.container,
|
||||
isSelected && coverSelectedStyle,
|
||||
]}
|
||||
>
|
||||
<Pressable
|
||||
style={styles.pressable}
|
||||
android_ripple={{ color: theme.rippleColor }}
|
||||
{...props}
|
||||
>
|
||||
<View style={styles.badgeContainer}>
|
||||
{'chaptersDownloaded' in item &&
|
||||
item.chaptersDownloaded &&
|
||||
showDownloadsBadge ? (
|
||||
<DownloadsBadge
|
||||
unreadCount={item.chaptersUnread}
|
||||
downloadCount={item.chaptersDownloaded}
|
||||
showUnreadBadge={showUnreadBadge}
|
||||
theme={theme}
|
||||
/>
|
||||
) : null}
|
||||
{'chaptersUnread' in item &&
|
||||
item.chaptersUnread &&
|
||||
showUnreadBadge ? (
|
||||
<UnreadBadge
|
||||
unreadCount={item.chaptersUnread}
|
||||
downloadCount={item.chaptersDownloaded}
|
||||
showDownloadsBadge={showDownloadsBadge}
|
||||
theme={theme}
|
||||
/>
|
||||
) : null}
|
||||
</View>
|
||||
{showInLibraryBadge ? <InLibraryBadge theme={theme} /> : null}
|
||||
<FastImage
|
||||
source={{ uri: item.novelCover }}
|
||||
style={[
|
||||
{ height: coverHeight },
|
||||
styles.image,
|
||||
showInLibraryBadge && styles.inLibrary,
|
||||
]}
|
||||
>
|
||||
{displayMode === DisplayModes.Compact ? (
|
||||
<CompactTitle name={item.novelName} />
|
||||
) : null}
|
||||
</FastImage>
|
||||
{displayMode === DisplayModes.Comfortable ? (
|
||||
<Text
|
||||
numberOfLines={2}
|
||||
style={[{ color: theme.textColorPrimary }, styles.title]}
|
||||
>
|
||||
{item.novelName}
|
||||
</Text>
|
||||
) : null}
|
||||
</Pressable>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
export default NovelItem;
|
||||
|
||||
const CompactTitle = ({ name }: { name: string }) => (
|
||||
<View style={styles.compactTitleContainer}>
|
||||
<LinearGradient
|
||||
colors={['transparent', 'rgba(0,0,0,0.7)']}
|
||||
style={styles.linearGradient}
|
||||
>
|
||||
<Text numberOfLines={2} style={[styles.title, styles.compactTitle]}>
|
||||
{name}
|
||||
</Text>
|
||||
</LinearGradient>
|
||||
</View>
|
||||
);
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
overflow: 'hidden',
|
||||
borderRadius: 6,
|
||||
margin: 2,
|
||||
},
|
||||
pressable: {
|
||||
flex: 1,
|
||||
padding: 4,
|
||||
},
|
||||
badgeContainer: {
|
||||
position: 'absolute',
|
||||
zIndex: 1,
|
||||
top: 12,
|
||||
left: 12,
|
||||
flexDirection: 'row',
|
||||
},
|
||||
image: {
|
||||
borderRadius: 4,
|
||||
},
|
||||
inLibrary: {
|
||||
opacity: 0.5,
|
||||
},
|
||||
title: {
|
||||
padding: 4,
|
||||
fontSize: 12,
|
||||
},
|
||||
compactTitleContainer: {
|
||||
position: 'absolute',
|
||||
bottom: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
flex: 1,
|
||||
borderRadius: 4,
|
||||
},
|
||||
linearGradient: {
|
||||
borderRadius: 4,
|
||||
padding: 4,
|
||||
paddingTop: 16,
|
||||
},
|
||||
compactTitle: {
|
||||
color: 'rgba(255,255,255,1)',
|
||||
textShadowColor: 'rgba(0, 0, 0, 0.75)',
|
||||
textShadowOffset: {
|
||||
width: -1,
|
||||
height: 1,
|
||||
},
|
||||
textShadowRadius: 10,
|
||||
},
|
||||
});
|
||||
@@ -1,104 +0,0 @@
|
||||
import React from 'react';
|
||||
import { StyleSheet, Text } from 'react-native';
|
||||
|
||||
import { ThemeType } from '../../theme/types';
|
||||
|
||||
interface UnreadBadgeProps {
|
||||
unreadCount: number;
|
||||
downloadCount: number;
|
||||
showDownloadsBadge: boolean;
|
||||
theme: ThemeType;
|
||||
}
|
||||
|
||||
const UnreadBadge: React.FC<UnreadBadgeProps> = ({
|
||||
unreadCount,
|
||||
downloadCount,
|
||||
showDownloadsBadge,
|
||||
theme,
|
||||
}) => (
|
||||
<Text
|
||||
style={[
|
||||
styles.unreadBadge,
|
||||
(!downloadCount || !showDownloadsBadge) && styles.borderLeftRadius,
|
||||
{ backgroundColor: theme.primary, color: theme.onPrimary },
|
||||
]}
|
||||
>
|
||||
{unreadCount}
|
||||
</Text>
|
||||
);
|
||||
|
||||
interface DownloadsBadgeProps {
|
||||
unreadCount: number;
|
||||
downloadCount: number;
|
||||
showUnreadBadge: boolean;
|
||||
theme: ThemeType;
|
||||
}
|
||||
|
||||
const DownloadsBadge: React.FC<DownloadsBadgeProps> = ({
|
||||
unreadCount,
|
||||
downloadCount,
|
||||
showUnreadBadge,
|
||||
theme,
|
||||
}) => (
|
||||
<Text
|
||||
style={[
|
||||
styles.downloadBadge,
|
||||
(!unreadCount || !showUnreadBadge) && styles.borderRightRadius,
|
||||
{ backgroundColor: theme.tertiary, color: theme.onTertiary },
|
||||
]}
|
||||
>
|
||||
{downloadCount}
|
||||
</Text>
|
||||
);
|
||||
|
||||
interface InLibraryBadgeProps {
|
||||
theme: ThemeType;
|
||||
}
|
||||
|
||||
const InLibraryBadge: React.FC<InLibraryBadgeProps> = ({ theme }) => (
|
||||
<Text
|
||||
style={[
|
||||
styles.inLibraryBadge,
|
||||
{ backgroundColor: theme.primary, color: theme.onPrimary },
|
||||
]}
|
||||
>
|
||||
In library
|
||||
</Text>
|
||||
);
|
||||
|
||||
export { UnreadBadge, DownloadsBadge, InLibraryBadge };
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
borderLeftRadius: {
|
||||
borderTopLeftRadius: 4,
|
||||
borderBottomLeftRadius: 4,
|
||||
},
|
||||
borderRightRadius: {
|
||||
borderTopRightRadius: 4,
|
||||
borderBottomRightRadius: 4,
|
||||
},
|
||||
unreadBadge: {
|
||||
borderTopRightRadius: 4,
|
||||
borderBottomRightRadius: 4,
|
||||
paddingVertical: 2,
|
||||
paddingHorizontal: 4,
|
||||
fontSize: 12,
|
||||
},
|
||||
downloadBadge: {
|
||||
borderTopLeftRadius: 4,
|
||||
borderBottomLeftRadius: 4,
|
||||
paddingVertical: 2,
|
||||
paddingHorizontal: 4,
|
||||
fontSize: 12,
|
||||
},
|
||||
inLibraryBadge: {
|
||||
position: 'absolute',
|
||||
top: 12,
|
||||
right: 12,
|
||||
borderRadius: 4,
|
||||
paddingVertical: 2,
|
||||
paddingHorizontal: 4,
|
||||
fontSize: 12,
|
||||
zIndex: 2,
|
||||
},
|
||||
});
|
||||
@@ -1,20 +0,0 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { Text as NativeText, TextPropTypes } from 'react-native';
|
||||
|
||||
const Text = ({ type, children, style, theme }) => {
|
||||
const color =
|
||||
type === 'primary'
|
||||
? theme.textColorPrimary
|
||||
: type === 'secondary'
|
||||
? theme.textColorSecondary
|
||||
: theme.textColorHint;
|
||||
|
||||
return <NativeText style={[style, { color }]}>{children}</NativeText>;
|
||||
};
|
||||
|
||||
Text.propType = {
|
||||
style: TextPropTypes.style,
|
||||
type: PropTypes.oneOf(['primary', 'secondary', 'hint']),
|
||||
theme: PropTypes.object.isRequired,
|
||||
};
|
||||
@@ -1,65 +0,0 @@
|
||||
import { useEffect, useRef, useState } from 'react';
|
||||
|
||||
import { useAppDispatch, useSavedChapterData } from '../redux/hooks';
|
||||
import { saveChapterProgress } from '../redux/localStorage/localStorageSlice';
|
||||
|
||||
export const useChapterProgress = (chapterId: number, readerRef: any) => {
|
||||
const dispatch = useAppDispatch();
|
||||
const { progressPercentage = 0, progressLocation = 0 } =
|
||||
useSavedChapterData(chapterId);
|
||||
|
||||
const [percentage, setPercentage] = useState(progressPercentage);
|
||||
const [location, setLocation] = useState(progressLocation);
|
||||
|
||||
const percentageRef = useRef(0);
|
||||
percentageRef.current = percentage;
|
||||
|
||||
const locationRef = useRef(0);
|
||||
locationRef.current = location;
|
||||
|
||||
const setProgress = ({ nativeEvent }: { nativeEvent: any }) => {
|
||||
const currentOffsetY = nativeEvent.contentOffset.y;
|
||||
const currentPosition =
|
||||
nativeEvent.contentOffset.y + nativeEvent.layoutMeasurement.height;
|
||||
|
||||
const currentProgressPercentage = Math.round(
|
||||
(currentPosition / nativeEvent.contentSize.height) * 100,
|
||||
);
|
||||
|
||||
setPercentage(currentProgressPercentage);
|
||||
setLocation(currentOffsetY);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
dispatch(
|
||||
saveChapterProgress({
|
||||
chapterId,
|
||||
progressLocation: locationRef.current,
|
||||
progressPercentage: percentageRef.current,
|
||||
}),
|
||||
);
|
||||
};
|
||||
}, []);
|
||||
|
||||
const [firstLayout, setFirstLayout] = useState(true);
|
||||
|
||||
const scrollToSavedProgress = () => {
|
||||
if (firstLayout) {
|
||||
percentage < 100 &&
|
||||
readerRef.current.scrollTo({
|
||||
x: 0,
|
||||
y: location,
|
||||
animated: false,
|
||||
});
|
||||
setFirstLayout(false);
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
progressLocation,
|
||||
progressPercentage: percentage,
|
||||
setProgress,
|
||||
scrollToSavedProgress,
|
||||
};
|
||||
};
|
||||
@@ -1,61 +0,0 @@
|
||||
import { useCallback, useState } from 'react';
|
||||
import { useFocusEffect } from '@react-navigation/native';
|
||||
|
||||
import { LibraryNovelInfo } from '../database/types';
|
||||
import { getLibraryNovelsFromDb } from '../database/queries/LibraryQueries';
|
||||
import { useLibrarySettings } from '../redux/hooks';
|
||||
|
||||
const useLibrary = () => {
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
const [novels, setNovels] = useState<LibraryNovelInfo[]>([]);
|
||||
const [error, setError] = useState<string>();
|
||||
|
||||
const { filters, sort } = useLibrarySettings();
|
||||
|
||||
const getLibraryNovels = useCallback(async () => {
|
||||
try {
|
||||
const res = await getLibraryNovelsFromDb(filters, sort);
|
||||
setNovels(res);
|
||||
} catch (err) {
|
||||
if (err instanceof Error) {
|
||||
setError(err.message);
|
||||
}
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
}, [filters, sort]);
|
||||
|
||||
const getLibrarySearchResults = useCallback(
|
||||
async (searchText: string) => {
|
||||
try {
|
||||
const res = await getLibraryNovelsFromDb(filters, sort, searchText);
|
||||
setNovels(res);
|
||||
} catch (err) {
|
||||
if (err instanceof Error) {
|
||||
setError(err.message);
|
||||
}
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
},
|
||||
[filters, sort],
|
||||
);
|
||||
|
||||
const clearSearchResults = () => getLibraryNovels();
|
||||
|
||||
useFocusEffect(
|
||||
useCallback(() => {
|
||||
getLibraryNovels();
|
||||
}, [getLibraryNovels]),
|
||||
);
|
||||
return {
|
||||
isLoading,
|
||||
novels,
|
||||
error,
|
||||
getLibrarySearchResults,
|
||||
clearSearchResults,
|
||||
getLibraryNovels,
|
||||
};
|
||||
};
|
||||
|
||||
export default useLibrary;
|
||||
@@ -1,68 +1,13 @@
|
||||
import { createSlice, PayloadAction } from '@reduxjs/toolkit';
|
||||
|
||||
// import { defaultDarkTheme } from '../../theme/dark';
|
||||
import { BrowseSettingsMap } from './types';
|
||||
|
||||
export enum DisplayModes {
|
||||
Compact = 'compact',
|
||||
Comfortable = 'comfortable',
|
||||
NoTitle = 'no title',
|
||||
List = 'list',
|
||||
}
|
||||
|
||||
export enum TextAlignments {
|
||||
Left = 'left',
|
||||
Center = 'center',
|
||||
Justify = 'justfy',
|
||||
Right = 'right',
|
||||
}
|
||||
|
||||
// interface ReaderTheme {
|
||||
// backgroundColor: string;
|
||||
// textColor: string;
|
||||
// }
|
||||
|
||||
interface SettingsState {
|
||||
appearance: {
|
||||
// theme: ThemeType;
|
||||
displayMode: DisplayModes;
|
||||
novelsPerRowPotrait: number;
|
||||
novelsPerRowLandscape: number;
|
||||
showLabelsInNav: boolean;
|
||||
showHistoryTab: boolean;
|
||||
showUpdatesTab: boolean;
|
||||
};
|
||||
reader: {
|
||||
fontFamily: string | null;
|
||||
fontSize: number;
|
||||
lineHeight: number;
|
||||
textAlign: TextAlignments;
|
||||
backgroundColor: string;
|
||||
textColor: string;
|
||||
paddingHorizontal: number;
|
||||
customCSS: string | null;
|
||||
fullScreenMode: boolean;
|
||||
useWebViewReader: boolean;
|
||||
showProgressPercentage: boolean;
|
||||
useSwipeGestures: boolean;
|
||||
};
|
||||
library: {
|
||||
filters: string[];
|
||||
sort: string;
|
||||
showDownloadsBadge: boolean;
|
||||
showUnreadBadge: boolean;
|
||||
updateLibraryOnLaunch: boolean;
|
||||
};
|
||||
updates: {
|
||||
lastUpdateTime: Date | null;
|
||||
onlyUpdateOngoingNovels: boolean;
|
||||
updateNovelMetadata: boolean;
|
||||
showLastUpdateTime: boolean;
|
||||
};
|
||||
app: {
|
||||
incognitoMode: boolean;
|
||||
downloadOnlyMode: boolean;
|
||||
};
|
||||
appearance: {};
|
||||
reader: {};
|
||||
library: {};
|
||||
updates: {};
|
||||
app: {};
|
||||
browse: {
|
||||
onlyShowPinnedSources: boolean;
|
||||
showMyAnimeList: boolean;
|
||||
@@ -71,46 +16,11 @@ interface SettingsState {
|
||||
}
|
||||
|
||||
const initialState: SettingsState = {
|
||||
appearance: {
|
||||
// theme: defaultDarkTheme,
|
||||
displayMode: DisplayModes.Compact,
|
||||
novelsPerRowPotrait: 3,
|
||||
novelsPerRowLandscape: 6,
|
||||
showLabelsInNav: true,
|
||||
showHistoryTab: true,
|
||||
showUpdatesTab: true,
|
||||
},
|
||||
reader: {
|
||||
fontFamily: '',
|
||||
fontSize: 16,
|
||||
lineHeight: 1.5,
|
||||
textAlign: TextAlignments.Left,
|
||||
backgroundColor: '#000000',
|
||||
textColor: 'rgba(255,255,255,0.7)',
|
||||
paddingHorizontal: 5,
|
||||
customCSS: null,
|
||||
fullScreenMode: true,
|
||||
useWebViewReader: false,
|
||||
showProgressPercentage: false,
|
||||
useSwipeGestures: false,
|
||||
},
|
||||
library: {
|
||||
filters: [],
|
||||
sort: 'novelId DESC',
|
||||
showDownloadsBadge: true,
|
||||
showUnreadBadge: true,
|
||||
updateLibraryOnLaunch: false,
|
||||
},
|
||||
updates: {
|
||||
lastUpdateTime: null,
|
||||
onlyUpdateOngoingNovels: false,
|
||||
updateNovelMetadata: false,
|
||||
showLastUpdateTime: false,
|
||||
},
|
||||
app: {
|
||||
incognitoMode: false,
|
||||
downloadOnlyMode: false,
|
||||
},
|
||||
appearance: {},
|
||||
reader: {},
|
||||
library: {},
|
||||
updates: {},
|
||||
app: {},
|
||||
browse: {
|
||||
onlyShowPinnedSources: false,
|
||||
showMyAnimeList: true,
|
||||
|
||||
@@ -1,35 +1,3 @@
|
||||
// export interface SettingsMap {
|
||||
// 'app.downloadOnlyMode': 'string';
|
||||
// 'app.incognitoMode': 'string';
|
||||
// 'appearance.displayMode': 'string';
|
||||
// 'appearance.novelsPerRowLandscape': 'string';
|
||||
// 'appearance.novelsPerRowPotrait': 'string';
|
||||
// 'appearance.showHistoryTab': 'string';
|
||||
// 'appearance.showLabelsInNav': 'string';
|
||||
// 'appearance.showUpdatesTab': 'string';
|
||||
// 'appearance.theme': 'string';
|
||||
// 'library.showDownloadsBadge': 'string';
|
||||
// 'library.showUnreadBadge': 'string';
|
||||
// 'library.sort': 'string';
|
||||
// 'library.updateLibraryOnLaunch': 'string';
|
||||
// 'reader.backgroundColor': 'string';
|
||||
// 'reader.customCSS': 'string';
|
||||
// 'reader.fontFamily': 'string';
|
||||
// 'reader.fontSize': 'string';
|
||||
// 'reader.fullScreenMode': 'string';
|
||||
// 'reader.lineHeight': 'string';
|
||||
// 'reader.paddingHorizontal': 'string';
|
||||
// 'reader.showProgressPercentage': 'string';
|
||||
// 'reader.textAlign': 'string';
|
||||
// 'reader.textColor': 'string';
|
||||
// 'reader.useSwipeGestures': 'string';
|
||||
// 'reader.useWebViewReader': 'string';
|
||||
// 'updates.lastUpdateTime': 'string';
|
||||
// 'updates.onlyUpdateOngoingNovels': 'string';
|
||||
// 'updates.showLastUpdateTime': 'string';
|
||||
// 'updates.updateNovelMetadata': 'string';
|
||||
// }
|
||||
|
||||
export interface BrowseSettingsMap {
|
||||
onlyShowPinnedSources: 'string';
|
||||
searchAllSources: 'string';
|
||||
|
||||
@@ -1,57 +0,0 @@
|
||||
import {
|
||||
ENABLE_DISCOVER,
|
||||
FILTER_LANGUAGE,
|
||||
GET_SOURCES,
|
||||
PIN_SOURCES,
|
||||
SEARCH_SOURCES,
|
||||
} from './source.types';
|
||||
import { showToast } from '../../hooks/showToast';
|
||||
import sources from '../../sources/sources.json';
|
||||
|
||||
export const getSourcesAction = () => async dispatch => {
|
||||
try {
|
||||
/**
|
||||
* Sort sources aplhabetically
|
||||
*/
|
||||
let sortedSources = sources.sort((a, b) =>
|
||||
a.sourceName.localeCompare(b.sourceName),
|
||||
);
|
||||
|
||||
dispatch({
|
||||
type: GET_SOURCES,
|
||||
payload: sortedSources,
|
||||
});
|
||||
} catch (error) {
|
||||
showToast(error.message);
|
||||
}
|
||||
};
|
||||
|
||||
export const searchSourcesAction = searchText => async dispatch => {
|
||||
const res = searchText.toLowerCase();
|
||||
|
||||
dispatch({
|
||||
type: SEARCH_SOURCES,
|
||||
payload: res,
|
||||
});
|
||||
};
|
||||
|
||||
export const pinSourceAction = sourceId => async dispatch => {
|
||||
dispatch({
|
||||
type: PIN_SOURCES,
|
||||
payload: sourceId,
|
||||
});
|
||||
};
|
||||
|
||||
export const filterLanguage = language => async dispatch => {
|
||||
dispatch({
|
||||
type: FILTER_LANGUAGE,
|
||||
payload: language,
|
||||
});
|
||||
};
|
||||
|
||||
export const enableDiscover = key => async dispatch => {
|
||||
dispatch({
|
||||
type: ENABLE_DISCOVER,
|
||||
payload: key,
|
||||
});
|
||||
};
|
||||
@@ -1,149 +0,0 @@
|
||||
import React, { useCallback } from 'react';
|
||||
import { Pressable, StyleSheet, View, Text } from 'react-native';
|
||||
|
||||
import moment from 'moment';
|
||||
import FastImage from 'react-native-fast-image';
|
||||
|
||||
import { parseChapterNumber } from '../../../services/utils/helpers';
|
||||
import { setNovel } from '../../../redux/novel/novel.actions';
|
||||
import { defaultCoverUri } from '../../../sources/helpers/constants';
|
||||
import { IconButton } from '../../../components/IconButton/IconButton';
|
||||
|
||||
const HistoryItem = ({
|
||||
history,
|
||||
theme,
|
||||
dispatch,
|
||||
navigation,
|
||||
deleteHistory,
|
||||
}) => {
|
||||
const {
|
||||
historyId,
|
||||
historyTimeRead,
|
||||
historyChapterId,
|
||||
sourceId,
|
||||
novelId,
|
||||
novelUrl,
|
||||
novelName,
|
||||
novelCover,
|
||||
chapterName,
|
||||
chapterUrl,
|
||||
bookmark,
|
||||
} = history;
|
||||
|
||||
const getChapterNumber = useCallback(
|
||||
() =>
|
||||
`Chapter ${parseChapterNumber(chapterName)} • ${moment(historyTimeRead)
|
||||
.format('h:mm a')
|
||||
.toUpperCase()}`,
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
[],
|
||||
);
|
||||
|
||||
const navigateToNovel = () => {
|
||||
navigation.navigate('Novel', history);
|
||||
dispatch(setNovel(history));
|
||||
};
|
||||
|
||||
const navigateToChapter = () =>
|
||||
navigation.navigate('Chapter', {
|
||||
chapterId: historyChapterId,
|
||||
chapterUrl,
|
||||
sourceId,
|
||||
novelUrl,
|
||||
novelId,
|
||||
chapterName,
|
||||
novelName,
|
||||
bookmark,
|
||||
});
|
||||
|
||||
const uri =
|
||||
novelCover && !novelCover.startsWith('/') ? novelCover : defaultCoverUri;
|
||||
|
||||
return (
|
||||
<Pressable
|
||||
onPress={navigateToNovel}
|
||||
android_ripple={{ color: theme.rippleColor }}
|
||||
>
|
||||
<View style={styles.content}>
|
||||
<View style={styles.container}>
|
||||
<View>
|
||||
<FastImage source={{ uri }} style={styles.novelCover} />
|
||||
</View>
|
||||
<View style={styles.textContainer}>
|
||||
<Text
|
||||
style={[{ color: theme.textColorPrimary }, styles.chapterTitle]}
|
||||
numberOfLines={2}
|
||||
>
|
||||
{novelName}
|
||||
</Text>
|
||||
<Text
|
||||
style={[
|
||||
{ color: theme.textColorSecondary },
|
||||
styles.chapterNumber,
|
||||
]}
|
||||
numberOfLines={1}
|
||||
>
|
||||
{getChapterNumber()}
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
<View style={styles.buttons}>
|
||||
<IconButton
|
||||
icon="delete-outline"
|
||||
size={24}
|
||||
color={theme.textColorPrimary}
|
||||
onPress={() => deleteHistory(historyId)}
|
||||
containerStyle={{ marginLeft: 12 }}
|
||||
theme={theme}
|
||||
/>
|
||||
<IconButton
|
||||
icon="play"
|
||||
size={24}
|
||||
color={theme.textColorPrimary}
|
||||
onPress={navigateToChapter}
|
||||
containerStyle={{ marginLeft: 12 }}
|
||||
theme={theme}
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
</Pressable>
|
||||
);
|
||||
};
|
||||
|
||||
export default HistoryItem;
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
content: {
|
||||
paddingVertical: 8,
|
||||
paddingHorizontal: 16,
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'space-between',
|
||||
},
|
||||
container: {
|
||||
flex: 1,
|
||||
flexDirection: 'row',
|
||||
overflow: 'hidden',
|
||||
},
|
||||
novelCover: {
|
||||
height: 80,
|
||||
width: 56,
|
||||
borderRadius: 4,
|
||||
},
|
||||
textContainer: {
|
||||
flexShrink: 1,
|
||||
marginLeft: 16,
|
||||
justifyContent: 'center',
|
||||
},
|
||||
chapterTitle: {
|
||||
fontSize: 15,
|
||||
flexWrap: 'wrap',
|
||||
},
|
||||
buttons: {
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
},
|
||||
chapterNumber: {
|
||||
marginTop: 4,
|
||||
},
|
||||
});
|
||||
@@ -1,58 +0,0 @@
|
||||
// import React from 'react';
|
||||
|
||||
// import { Menu } from 'react-native-paper';
|
||||
// import {
|
||||
// ChapterDownloadingButton,
|
||||
// DeleteChapterButton,
|
||||
// DownloadChapterButton,
|
||||
// } from '../../novel/components/Chapter/ChapterDownloadButtons';
|
||||
|
||||
// export const DownloadButton = ({
|
||||
// downloadQueue,
|
||||
// theme,
|
||||
// chapter,
|
||||
// downloadChapter,
|
||||
// deleteChapter,
|
||||
// deleteChapterMenu,
|
||||
// showDeleteChapterMenu,
|
||||
// hideDeleteChapterMenu,
|
||||
// }) => {
|
||||
// if (downloadQueue.some(chap => chap.chapterId === chapter.chapterId)) {
|
||||
// return <ChapterDownloadingButton theme={theme} />;
|
||||
// } else if (chapter.downloaded === 1) {
|
||||
// return (
|
||||
// <Menu
|
||||
// visible={deleteChapterMenu}
|
||||
// onDismiss={hideDeleteChapterMenu}
|
||||
// anchor={
|
||||
// <DeleteChapterButton theme={theme} onPress={showDeleteChapterMenu} />
|
||||
// }
|
||||
// contentStyle={{ backgroundColor: theme.menuColor }}
|
||||
// >
|
||||
// <Menu.Item
|
||||
// onPress={() => {
|
||||
// deleteChapter(chapter.chapterId, chapter.chapterName);
|
||||
// hideDeleteChapterMenu();
|
||||
// }}
|
||||
// title="Delete"
|
||||
// titleStyle={{ color: theme.textColorPrimary }}
|
||||
// />
|
||||
// </Menu>
|
||||
// );
|
||||
// } else {
|
||||
// return (
|
||||
// <DownloadChapterButton
|
||||
// theme={theme}
|
||||
// onPress={() =>
|
||||
// downloadChapter(
|
||||
// chapter.sourceId,
|
||||
// chapter.novelUrl,
|
||||
// chapter.chapterUrl,
|
||||
// chapter.chapterName,
|
||||
// chapter.chapterId,
|
||||
// )
|
||||
// }
|
||||
// />
|
||||
// );
|
||||
// }
|
||||
// };
|
||||
@@ -1,149 +0,0 @@
|
||||
import * as SQLite from 'expo-sqlite';
|
||||
const db = SQLite.openDatabase('lnreader.db');
|
||||
|
||||
const getLibraryNovelsQuery = 'SELECT * FROM novels WHERE followed = 1';
|
||||
|
||||
const getLibraryNovels = () => {
|
||||
return new Promise((resolve, reject) =>
|
||||
db.transaction(tx => {
|
||||
tx.executeSql(
|
||||
getLibraryNovelsQuery,
|
||||
null,
|
||||
(txObj, { rows: { _array } }) => resolve(_array),
|
||||
(txObj, error) => {
|
||||
// console.log('Error ', error)
|
||||
},
|
||||
);
|
||||
}),
|
||||
);
|
||||
};
|
||||
|
||||
const getLibraryChaptersQuery =
|
||||
'SELECT chapters.* FROM chapters JOIN novels ON chapters.novelId = novels.novelId WHERE novels.followed = 1';
|
||||
|
||||
const getLibraryChapters = () => {
|
||||
return new Promise((resolve, reject) =>
|
||||
db.transaction(tx => {
|
||||
tx.executeSql(
|
||||
getLibraryChaptersQuery,
|
||||
null,
|
||||
(txObj, { rows: { _array } }) => resolve(_array),
|
||||
(txObj, error) => {
|
||||
// console.log('Error ', error)
|
||||
},
|
||||
);
|
||||
}),
|
||||
);
|
||||
};
|
||||
|
||||
const getLibraryDownloadsQuery =
|
||||
'SELECT downloads.* FROM downloads JOIN chapters ON downloads.downloadChapterId = chapters.chapterId JOIN novels ON chapters.novelId = novels.novelId WHERE novels.followed = 1';
|
||||
|
||||
const getLibraryDownloads = () => {
|
||||
return new Promise((resolve, reject) =>
|
||||
db.transaction(tx => {
|
||||
tx.executeSql(
|
||||
getLibraryDownloadsQuery,
|
||||
null,
|
||||
(txObj, { rows: { _array } }) => resolve(_array),
|
||||
(txObj, error) => {
|
||||
// console.log('Error ', error)
|
||||
},
|
||||
);
|
||||
}),
|
||||
);
|
||||
};
|
||||
|
||||
const restoreNovelsQuery =
|
||||
'INSERT OR REPLACE INTO novels (novelId, novelUrl, sourceUrl, sourceId, source, novelName, novelCover, novelSummary, author, artist, status, genre, followed, unread) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)';
|
||||
|
||||
const restoreNovels = async novel => {
|
||||
db.transaction(tx =>
|
||||
tx.executeSql(
|
||||
restoreNovelsQuery,
|
||||
[
|
||||
novel.novelId,
|
||||
novel.novelUrl,
|
||||
novel.sourceUrl,
|
||||
novel.sourceId,
|
||||
novel.source,
|
||||
novel.novelName,
|
||||
novel.novelCover,
|
||||
novel.novelSummary,
|
||||
novel.author,
|
||||
novel.artist,
|
||||
novel.status,
|
||||
novel.genre,
|
||||
novel.followed,
|
||||
novel.unread,
|
||||
],
|
||||
(txObj, res) => {},
|
||||
(txObj, error) => {
|
||||
// console.log('Error ', error)
|
||||
},
|
||||
),
|
||||
);
|
||||
};
|
||||
|
||||
const restoreChaptersQuery =
|
||||
'INSERT OR IGNORE INTO chapters (novelId, chapterId, chapterUrl, chapterName, releaseDate, bookmark, `read`, downloaded) VALUES (?, ?, ?, ?, ?, ?, ?, ?)';
|
||||
|
||||
const restoreChapters = async chapter => {
|
||||
const {
|
||||
novelId,
|
||||
chapterId,
|
||||
chapterUrl,
|
||||
chapterName,
|
||||
releaseDate,
|
||||
bookmark,
|
||||
read,
|
||||
downloaded,
|
||||
} = chapter;
|
||||
|
||||
db.transaction(tx =>
|
||||
tx.executeSql(
|
||||
restoreChaptersQuery,
|
||||
[
|
||||
novelId,
|
||||
chapterId,
|
||||
chapterUrl,
|
||||
chapterName,
|
||||
releaseDate,
|
||||
bookmark,
|
||||
read,
|
||||
downloaded,
|
||||
],
|
||||
(txObj, res) => {},
|
||||
(txObj, error) => {
|
||||
// console.log('Error ', error)
|
||||
},
|
||||
),
|
||||
);
|
||||
};
|
||||
|
||||
const restoreDownloadsQuery =
|
||||
'INSERT OR IGNORE INTO downloads (downloadChapterId, chapterName, chapterText) VALUES (?, ?, ?)';
|
||||
|
||||
const restoreDownloads = async chapter => {
|
||||
const { downloadChapterId, chapterName, chapterText } = chapter;
|
||||
|
||||
db.transaction(tx =>
|
||||
tx.executeSql(
|
||||
restoreDownloadsQuery,
|
||||
[downloadChapterId, chapterName, chapterText],
|
||||
(txObj, res) => {},
|
||||
(txObj, error) => {
|
||||
// console.log('Error ', error)
|
||||
},
|
||||
),
|
||||
);
|
||||
};
|
||||
|
||||
export {
|
||||
getLibraryNovels,
|
||||
getLibraryChapters,
|
||||
getLibraryDownloads,
|
||||
restoreNovels,
|
||||
restoreChapters,
|
||||
restoreDownloads,
|
||||
};
|
||||
@@ -1,71 +0,0 @@
|
||||
import * as DocumentPicker from 'expo-document-picker';
|
||||
import { StorageAccessFramework } from 'expo-file-system';
|
||||
import moment from 'moment';
|
||||
|
||||
import { showToast } from '../../hooks/showToast';
|
||||
|
||||
import {
|
||||
getLibraryChapters,
|
||||
getLibraryDownloads,
|
||||
getLibraryNovels,
|
||||
restoreChapters,
|
||||
restoreDownloads,
|
||||
restoreNovels,
|
||||
} from './BackupQueries';
|
||||
|
||||
const createFullBackup = async () => {
|
||||
const novels = await getLibraryNovels();
|
||||
const chapters = await getLibraryChapters();
|
||||
const downloads = await getLibraryDownloads();
|
||||
|
||||
const backup = { novels, chapters, downloads };
|
||||
|
||||
/**
|
||||
* Request permissions
|
||||
*/
|
||||
const permissions =
|
||||
await StorageAccessFramework.requestDirectoryPermissionsAsync();
|
||||
if (!permissions.granted) {
|
||||
return;
|
||||
}
|
||||
|
||||
const uri = permissions.directoryUri;
|
||||
|
||||
const date = moment().format('YYYY-MM-DD');
|
||||
|
||||
const fileName = 'lnreader_backup_' + date;
|
||||
|
||||
if (uri) {
|
||||
const fileUri = await StorageAccessFramework.createFileAsync(
|
||||
uri,
|
||||
fileName,
|
||||
'application/json',
|
||||
);
|
||||
|
||||
await StorageAccessFramework.writeAsStringAsync(
|
||||
fileUri,
|
||||
JSON.stringify(backup),
|
||||
);
|
||||
|
||||
showToast('Backup created.');
|
||||
}
|
||||
};
|
||||
|
||||
const restoreFullBackup = async () => {
|
||||
const backup = await DocumentPicker.getDocumentAsync();
|
||||
|
||||
if (backup.uri) {
|
||||
let data = await StorageAccessFramework.readAsStringAsync(backup.uri);
|
||||
data = JSON.parse(data);
|
||||
|
||||
const { novels, chapters, downloads } = data;
|
||||
|
||||
novels.map(novel => restoreNovels(novel));
|
||||
chapters.map(chapter => restoreChapters(chapter));
|
||||
downloads.map(chapter => restoreDownloads(chapter));
|
||||
}
|
||||
|
||||
showToast('Backup restored.');
|
||||
};
|
||||
|
||||
export { createFullBackup, restoreFullBackup };
|
||||
@@ -1,191 +0,0 @@
|
||||
import * as cheerio from 'cheerio';
|
||||
const baseUrl = 'https://boxnovel.com/novel';
|
||||
const searchUrl = 'https://boxnovel.com/';
|
||||
|
||||
const sourceId = 1;
|
||||
|
||||
const popularNovels = async page => {
|
||||
let url = `${baseUrl}/page/${page}/?m_orderby=rating`;
|
||||
let totalPages = 73;
|
||||
|
||||
const result = await fetch(url);
|
||||
const body = await result.text();
|
||||
|
||||
const loadedCheerio = cheerio.load(body);
|
||||
|
||||
let novels = [];
|
||||
|
||||
loadedCheerio('.page-item-detail').each(function () {
|
||||
const novelName = loadedCheerio(this).find('h3 > a').text();
|
||||
const novelCover = loadedCheerio(this).find('img').attr('src');
|
||||
|
||||
let novelUrl = loadedCheerio(this).find('h3 > a').attr('href');
|
||||
novelUrl = novelUrl.replace(`${baseUrl}/`, '');
|
||||
|
||||
const novel = {
|
||||
sourceId,
|
||||
novelName,
|
||||
novelCover,
|
||||
novelUrl,
|
||||
};
|
||||
|
||||
novels.push(novel);
|
||||
});
|
||||
|
||||
return { totalPages, novels };
|
||||
};
|
||||
|
||||
const parseNovelAndChapters = async novelUrl => {
|
||||
const url = `${baseUrl}/${novelUrl}`;
|
||||
|
||||
const result = await fetch(url);
|
||||
const body = await result.text();
|
||||
|
||||
let loadedCheerio = cheerio.load(body);
|
||||
|
||||
let novel = {};
|
||||
|
||||
loadedCheerio('.post-title > h3 > span').remove();
|
||||
|
||||
novel.sourceId = 1;
|
||||
|
||||
novel.sourceName = 'BoxNovel';
|
||||
|
||||
novel.url = url;
|
||||
|
||||
novel.novelUrl = novelUrl;
|
||||
|
||||
novel.novelName = loadedCheerio('.post-title > h3')
|
||||
.text()
|
||||
.replace(/[\t\n]/g, '')
|
||||
.trim();
|
||||
|
||||
novel.novelCover = loadedCheerio('.summary_image > a > img').attr('src');
|
||||
|
||||
loadedCheerio('.post-content_item').each(function () {
|
||||
const detailName = loadedCheerio(this)
|
||||
.find('.summary-heading > h5')
|
||||
.text()
|
||||
.replace(/[\t\n]/g, '')
|
||||
.trim();
|
||||
const detail = loadedCheerio(this)
|
||||
.find('.summary-content')
|
||||
.text()
|
||||
.replace(/[\t\n]/g, '')
|
||||
.trim();
|
||||
|
||||
switch (detailName) {
|
||||
case 'Genre(s)':
|
||||
novel.genre = detail.trim().replace(/[\t\n]/g, ',');
|
||||
break;
|
||||
case 'Author(s)':
|
||||
novel.author = detail.trim();
|
||||
break;
|
||||
case 'Artist(s)':
|
||||
novel.status = detail.trim();
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
loadedCheerio('.description-summary > div.summary__content')
|
||||
.find('em')
|
||||
.remove();
|
||||
|
||||
novel.summary = loadedCheerio('.description-summary > div.summary__content')
|
||||
.text()
|
||||
.replace(/[\t\n]|Description|Summary/g, '');
|
||||
|
||||
let novelChapters = [];
|
||||
|
||||
const data = await fetch(`${url}ajax/chapters/`, { method: 'POST' });
|
||||
const text = await data.text();
|
||||
|
||||
loadedCheerio = cheerio.load(text);
|
||||
|
||||
loadedCheerio('.wp-manga-chapter').each(function () {
|
||||
const chapterName = loadedCheerio(this)
|
||||
.find('a')
|
||||
.text()
|
||||
.replace(/[\t\n]/g, '')
|
||||
.trim();
|
||||
|
||||
const releaseDate = loadedCheerio(this)
|
||||
.find('span')
|
||||
.text()
|
||||
.replace(/[\t\n]/g, '')
|
||||
.trim();
|
||||
|
||||
const chapterUrl = loadedCheerio(this)
|
||||
.find('a')
|
||||
.attr('href')
|
||||
.replace(url, '');
|
||||
|
||||
const chapter = { chapterName, releaseDate, chapterUrl };
|
||||
|
||||
novelChapters.push(chapter);
|
||||
});
|
||||
|
||||
novel.chapters = novelChapters.reverse();
|
||||
|
||||
return novel;
|
||||
};
|
||||
|
||||
const parseChapter = async (novelUrl, chapterUrl) => {
|
||||
const url = `${baseUrl}/${novelUrl}/${chapterUrl}`;
|
||||
|
||||
const result = await fetch(url);
|
||||
const body = await result.text();
|
||||
|
||||
const loadedCheerio = cheerio.load(body);
|
||||
|
||||
const chapterName = loadedCheerio('div.text-left > h3').text();
|
||||
let chapterText = loadedCheerio('.reading-content').html();
|
||||
const chapter = {
|
||||
sourceId,
|
||||
novelUrl,
|
||||
chapterUrl,
|
||||
chapterName,
|
||||
chapterText,
|
||||
};
|
||||
|
||||
return chapter;
|
||||
};
|
||||
|
||||
const searchNovels = async searchTerm => {
|
||||
const url = `${searchUrl}?s=${searchTerm}&post_type=wp-manga&m_orderby=rating`;
|
||||
|
||||
const result = await fetch(url);
|
||||
const body = await result.text();
|
||||
|
||||
const loadedCheerio = cheerio.load(body);
|
||||
|
||||
let novels = [];
|
||||
|
||||
loadedCheerio('.c-tabs-item__content').each(function () {
|
||||
const novelName = loadedCheerio(this).find('h4 > a').text();
|
||||
const novelCover = loadedCheerio(this).find('img').attr('src');
|
||||
|
||||
let novelUrl = loadedCheerio(this).find('h4 > a').attr('href');
|
||||
novelUrl = novelUrl.replace(`${baseUrl}/`, '');
|
||||
|
||||
const novel = {
|
||||
sourceId,
|
||||
novelName,
|
||||
novelCover,
|
||||
novelUrl,
|
||||
};
|
||||
|
||||
novels.push(novel);
|
||||
});
|
||||
|
||||
return novels;
|
||||
};
|
||||
|
||||
const BoxNovelScraper = {
|
||||
popularNovels,
|
||||
parseNovelAndChapters,
|
||||
parseChapter,
|
||||
searchNovels,
|
||||
};
|
||||
|
||||
export default BoxNovelScraper;
|
||||
@@ -1,36 +0,0 @@
|
||||
export const cleanHtml = html => {
|
||||
let text = html;
|
||||
|
||||
if (!text) {
|
||||
return "Chapter is empty.\n\nReport if it's available in webview.";
|
||||
}
|
||||
|
||||
text = text
|
||||
/**
|
||||
* Remove inline styles
|
||||
*/
|
||||
.replace(
|
||||
/style="((?:font-family|line-height|font-size|text-align).*?)"/gi,
|
||||
'',
|
||||
)
|
||||
.replace(/class=".*?"/gi, '')
|
||||
.replace(/id=".*?"/gi, '')
|
||||
|
||||
/**
|
||||
* Remove comments
|
||||
*/
|
||||
.replace(/<!--.*?-->/gim, '')
|
||||
.replace(/<\s*script[^>]*>[\s\S]*?<\/script>/gim, '')
|
||||
.replace(/<\s*noscript[^>]*>[\s\S]*?<\/noscript>/gim, '')
|
||||
.replace(/<\s*form[^>]*>[\s\S]*?<\/form>/gim, '')
|
||||
/**
|
||||
* Remove relative links
|
||||
*/
|
||||
.replace(
|
||||
/<\s*a[^>]*href=['"](\/.*?)['"][^>]*>([\s\S]*?)<\/\s*a\s*>/gi,
|
||||
'$2',
|
||||
)
|
||||
.trim();
|
||||
|
||||
return text;
|
||||
};
|
||||
@@ -1,3 +1,5 @@
|
||||
export const coverPlaceholderColor = '#8888881F';
|
||||
|
||||
const AccentColors = {
|
||||
default: '#2979FF',
|
||||
defaultDark: '#3399FF',
|
||||
@@ -1,30 +0,0 @@
|
||||
import { NativeModules, Platform } from 'react-native';
|
||||
|
||||
const { NavigationBarColor } = NativeModules;
|
||||
|
||||
const changeNavigationBarColor = (
|
||||
color = String,
|
||||
light = false,
|
||||
animated = true,
|
||||
) => {
|
||||
if (Platform.OS === 'android') {
|
||||
const LightNav = light ? true : false;
|
||||
NavigationBarColor.changeNavigationBarColor(color, LightNav, animated);
|
||||
}
|
||||
};
|
||||
const hideNavigationBar = () => {
|
||||
if (Platform.OS === 'android') {
|
||||
return NavigationBarColor.hideNavigationBar();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
const showNavigationBar = () => {
|
||||
if (Platform.OS === 'android') {
|
||||
NavigationBarColor.showNavigationBar();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
export { changeNavigationBarColor, hideNavigationBar, showNavigationBar };
|
||||
@@ -1,4 +0,0 @@
|
||||
import { ColorScheme, ThemeType } from '../types';
|
||||
|
||||
export const getFilterColor = (theme: ThemeType): string =>
|
||||
theme.type === ColorScheme.DARK ? '#FFEB3B' : '#FFC107';
|
||||
@@ -1,7 +0,0 @@
|
||||
import { StatusBar } from 'react-native';
|
||||
import { ColorScheme, ThemeType } from '../types';
|
||||
|
||||
export const setStatusBarColor = (theme: ThemeType) =>
|
||||
StatusBar.setBarStyle(
|
||||
theme.type === ColorScheme.DARK ? 'light-content' : 'dark-content',
|
||||
);
|
||||
Reference in New Issue
Block a user