[go: up one dir, main page]

Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added database for plugins #986

Merged
merged 40 commits into from
May 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
1eaf145
test
Rider21 Mar 2, 2024
6de52a7
fix
Rider21 Mar 2, 2024
b65aed2
Update pluginManager.ts
Rider21 Mar 2, 2024
72ea4d4
test
Rider21 Mar 2, 2024
31c2b2a
fix lint
Rider21 Mar 2, 2024
ebcc953
test
Rider21 Mar 2, 2024
4cfa3df
test webview
Rider21 Mar 2, 2024
d70b760
sync
Rider21 Mar 2, 2024
23eb299
/
Rider21 Mar 2, 2024
c636056
Update WebviewScreen.tsx
Rider21 Mar 2, 2024
859c314
CookieManager
Rider21 Mar 4, 2024
1769cfd
Update storage.ts
Rider21 Mar 4, 2024
454f197
Update сookie.ts
Rider21 Mar 4, 2024
4f042cb
fix title
Rider21 Mar 4, 2024
73bd975
MarqueeText...
Rider21 Mar 4, 2024
9e8ece4
Slow
Rider21 Mar 4, 2024
3101c31
Even slower
Rider21 Mar 4, 2024
015faaf
Merge remote-tracking branch 'upstream/master' into db
Rider21 Mar 5, 2024
59c1866
Squashed commit of the following:
Rider21 Mar 8, 2024
8a51a81
Merge remote-tracking branch 'upstream/master' into db
Rider21 Mar 8, 2024
64ce651
fix
Rider21 Mar 8, 2024
7ae8e53
Merge remote-tracking branch 'upstream/master' into db
Rider21 Mar 11, 2024
d5db2fd
fix
Rider21 Mar 11, 2024
a67e208
Update pluginManager.ts
Rider21 Mar 19, 2024
d7c79b2
Merge branch 'master' into db
Rider21 Mar 27, 2024
e65d43f
Merge remote-tracking branch 'upstream/master' into db
Rider21 Mar 27, 2024
320958a
test
Rider21 Mar 27, 2024
00aa7ef
fix
Rider21 Mar 29, 2024
4ea331f
fix lint
Rider21 Mar 30, 2024
8404f66
-marquee
Rider21 Apr 2, 2024
2b2bed0
Merge remote-tracking branch 'upstream/master' into db
Rider21 Apr 7, 2024
b0202c5
fix defaultCover
Rider21 Apr 7, 2024
c35d39c
Merge remote-tracking branch 'upstream/master' into db
Rider21 Apr 26, 2024
0b86a1c
test
Rider21 Apr 27, 2024
936e6f7
Merge remote-tracking branch 'upstream/master' into db
Rider21 Apr 27, 2024
9aa0649
Merge remote-tracking branch 'upstream/master' into db
Rider21 May 4, 2024
8166260
Update src/plugins/helpers/storage.ts
Rider21 May 8, 2024
497f8cb
test
Rider21 May 10, 2024
2daab50
Typescript fixes
nyagami May 22, 2024
89a1b72
private pluginID
nyagami May 22, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 18 additions & 14 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
"i18n-js": "^3.8.0",
"lodash-es": "^4.17.21",
"protobufjs": "^7.2.6",
"qs": "^6.11.2",
"qs": "^6.12.0",
"react": "18.2.0",
"react-native": "0.72.10",
"react-native-background-actions": "^3.0.1",
Expand All @@ -61,7 +61,7 @@
"react-native-tab-view": "^3.5.2",
"react-native-vector-icons": "^9.0.0",
"react-native-webview": "^13.2.2",
"sanitize-html": "^2.7.0",
"sanitize-html": "^2.13.0",
"urlencode": "^2.0.0"
},
"devDependencies": {
Expand All @@ -75,7 +75,7 @@
"@types/lodash-es": "^4.17.6",
"@types/react": "^18.0.24",
"@types/react-native-vector-icons": "^6.4.10",
"@types/sanitize-html": "^2.6.2",
"@types/sanitize-html": "^2.11.0",
"@typescript-eslint/eslint-plugin": "^5.10.2",
"@typescript-eslint/parser": "^5.10.2",
"babel-plugin-module-resolver": "^4.1.0",
Expand Down
2 changes: 1 addition & 1 deletion src/hooks/persisted/usePlugins.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ export default function usePlugins() {
*/

const installPlugin = (plugin: PluginItem) => {
return _install(plugin.url).then(_plg => {
return _install(plugin.id, plugin.url).then(_plg => {
if (_plg) {
const installedPlugins =
getMMKVObject<PluginItem[]>(INSTALLED_PLUGINS) || [];
Expand Down
2 changes: 1 addition & 1 deletion src/navigators/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ export type RootStackParamList = {
WebviewScreen: {
name: string;
url: string;
pluginId?: string;
pluginId: string;
isNovel?: boolean;
};
};
Expand Down
2 changes: 0 additions & 2 deletions src/plugins/helpers/constants.js

This file was deleted.

2 changes: 2 additions & 0 deletions src/plugins/helpers/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export const defaultCover =
'https://github.com/LNReader/lnreader-plugins/blob/master/icons/coverNotAvailable.webp?raw=true';
123 changes: 123 additions & 0 deletions src/plugins/helpers/storage.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
import { MMKV } from 'react-native-mmkv';

const store = new MMKV({ id: 'plugin_db' });

const PLUGIN_STORAGE = '_DB_';
const WEBVIEW_LOCAL_STORAGE = '_LocalStorage';
const WEBVIEW_SESSION_STORAGE = '_SessionStorage';

interface StoredItem {
created: Date;
value: any;
expires?: number; // timestamp (miliseconds)
}

class Storage {
#pluginID: string;

constructor(pluginID: string) {
this.#pluginID = pluginID;
}

/**
* Sets a key-value pair in storage.
*
* @param {string} key - The key to set.
* @param {any} value - The value to set.
* @param {Date | number} [expires] - Optional expiry date or time in milliseconds.
*/
set(key: string, value: any, expires?: Date | number): void {
const item: StoredItem = {
created: new Date(),
value,
expires: expires instanceof Date ? expires.getTime() : expires,
};
store.set(this.#pluginID + PLUGIN_STORAGE + key, JSON.stringify(item));
}

/**
* Retrieves the value for a given key from storage.
*
* @param {string} key - The key to retrieve the value for.
* @param {boolean} [raw] - Optional flag to return the raw stored item.
* @returns {any} The stored value or undefined if key is not found.
*/
get(key: string, raw?: boolean): any {
const storedItem = store.getString(this.#pluginID + PLUGIN_STORAGE + key);
if (storedItem) {
const item: StoredItem = JSON.parse(storedItem);
if (item.expires) {
if (Date.now() > item.expires) {
this.delete(key);
return undefined;
}
if (raw) {
item.expires = new Date(item.expires).getTime();
}
}
return raw ? item : item.value;
}
return undefined;
}

/**
* Deletes a key from storage.
*
* @param {string} key - The key to delete.
*/
delete(key: string): void {
store.delete(this.#pluginID + PLUGIN_STORAGE + key);
}

/**
* Clears all stored items from storage.
*/
clearAll(): void {
const keysToRemove = this.getAllKeys();
keysToRemove.forEach(key => this.delete(key));
}

/**
* Retrieves all keys set by the `set` method.
*
* @returns {string[]} An array of keys.
*/
getAllKeys(): string[] {
const keys = store
.getAllKeys()
.filter(key => key.startsWith(this.#pluginID + PLUGIN_STORAGE))
.map(key => key.replace(this.#pluginID + PLUGIN_STORAGE, ''));
return keys;
}
}

class LocalStorage {
#pluginID: string;

constructor(pluginID: string) {
this.#pluginID = pluginID;
}

get(): StoredItem['value'] | undefined {
const data = store.getString(this.#pluginID + WEBVIEW_LOCAL_STORAGE);
return data ? JSON.parse(data) : undefined;
}
}

class SessionStorage {
#pluginID: string;

constructor(pluginID: string) {
this.#pluginID = pluginID;
}

get(): StoredItem['value'] | undefined {
const data = store.getString(this.#pluginID + WEBVIEW_SESSION_STORAGE);
return data ? JSON.parse(data) : undefined;
}
}

export { Storage, LocalStorage, SessionStorage };

//to record data from the web view
export { WEBVIEW_LOCAL_STORAGE, WEBVIEW_SESSION_STORAGE, store };
44 changes: 31 additions & 13 deletions src/plugins/pluginManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import RNFS from 'react-native-fs';
import { reverse, uniqBy } from 'lodash-es';
import { PluginDownloadFolder } from '@utils/constants/download';
import { newer } from '@utils/compareVersion';
import { store } from './helpers/storage';

// packages for plugins
import { load } from 'cheerio';
Expand All @@ -12,6 +13,7 @@ import { FilterTypes } from './types/filterTypes';
import { isUrlAbsolute } from './helpers/isAbsoluteUrl';
import { fetchApi, fetchFile, fetchProto, fetchText } from './helpers/fetch';
import { defaultCover } from './helpers/constants';
import { Storage, LocalStorage, SessionStorage } from './helpers/storage';
import { encode, decode } from 'urlencode';
import { Parser } from 'htmlparser2';
import TextFile from '@native/TextFile';
Expand All @@ -33,12 +35,18 @@ const packages: Record<string, any> = {
'@libs/defaultCover': { defaultCover },
};

const _require = (packageName: string) => {
return packages[packageName];
};

const initPlugin = (rawCode: string) => {
const initPlugin = (pluginId: string, rawCode: string) => {
try {
const _require = (packageName: string) => {
if (packageName === '@libs/storage') {
return {
storage: new Storage(pluginId),
localStorage: new LocalStorage(pluginId),
sessionStorage: new SessionStorage(pluginId),
};
}
return packages[packageName];
};
/* eslint no-new-func: "off", curly: "error" */
const plugin: Plugin = Function(
'require',
Expand Down Expand Up @@ -84,26 +92,31 @@ const deserializePlugins = () => {
return TextFile.readFile(pluginsFilePath)
.then(content => {
serializedPlugins = JSON.parse(content);
for (const script of Object.values(serializedPlugins)) {
const plugin = initPlugin(script as string);
if (plugin) {
plugins[plugin.id] = plugin;
Object.entries(serializedPlugins).forEach(([pluginId, script]) => {
if (script) {
const plugin = initPlugin(pluginId, script);
if (plugin) {
plugins[plugin.id] = plugin;
}
}
}
});
})
.catch(() => {
// nothing to read
});
};

const installPlugin = async (url: string): Promise<Plugin | undefined> => {
const installPlugin = async (
pluginId: string,
url: string,
): Promise<Plugin | undefined> => {
try {
return await fetch(url, {
headers: { 'pragma': 'no-cache', 'cache-control': 'no-cache' },
})
.then(res => res.text())
.then(async rawCode => {
const plugin = initPlugin(rawCode);
const plugin = initPlugin(pluginId, rawCode);
if (!plugin) {
return undefined;
}
Expand All @@ -122,11 +135,16 @@ const installPlugin = async (url: string): Promise<Plugin | undefined> => {

const uninstallPlugin = async (_plugin: PluginItem) => {
plugins[_plugin.id] = undefined;
store.getAllKeys().forEach(key => {
if (key.startsWith(_plugin.id)) {
store.delete(key);
}
});
return serializePlugin(_plugin.id, '', false);
};

const updatePlugin = async (plugin: PluginItem) => {
return installPlugin(plugin.url);
return installPlugin(plugin.id, plugin.url);
};

const fetchPlugins = async (): Promise<PluginItem[]> => {
Expand Down
14 changes: 7 additions & 7 deletions src/plugins/types/filterTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,13 +43,13 @@ type ExcludableCheckboxFilter = {

export type Filters = Record<
string,
| { label: string } & (
| PickerFilter
| CheckboxFilter
| TextFilter
| SwitchFilter
| ExcludableCheckboxFilter
)
{ label: string } & (
| PickerFilter
| CheckboxFilter
| TextFilter
| SwitchFilter
| ExcludableCheckboxFilter
)
>;

export type FilterToValues<
Expand Down
1 change: 1 addition & 0 deletions src/plugins/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,4 +67,5 @@ export interface Plugin extends PluginItem {
searchNovels: (searchTerm: string, pageNo: number) => Promise<NovelItem[]>;
fetchImage: (url: string) => Promise<string>;
resolveUrl?: (path: string, isNovel?: boolean) => string;
webStorageUtilized?: boolean;
}
1 change: 1 addition & 0 deletions src/screens/BrowseSourceScreen/BrowseSourceScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ const BrowseSourceScreen = ({ route, navigation }: BrowseSourceScreenProps) => {
navigation.navigate('WebviewScreen', {
name: pluginName,
url: site,
pluginId,
});
};

Expand Down
Loading
Loading