-
Notifications
You must be signed in to change notification settings - Fork 197
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
Improve plugin settings, standardized captcha errors, hide chapters that no longer exist #1389
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -22,6 +22,16 @@ export const insertChapters = async ( | |
if (!chapters?.length) { | ||
return; | ||
} | ||
const existingChapters = await getPageChapters( | ||
novelId, | ||
'', | ||
'', | ||
chapters[0].page || '1', | ||
); | ||
const chaptersToHide = existingChapters.filter( | ||
c => !chapters.some(ch => ch.path === c.path), | ||
); | ||
Comment on lines
+31
to
+33
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. hide chapters if they are known but not in the list given |
||
|
||
db.transaction(tx => { | ||
chapters.forEach((chapter, index) => { | ||
tx.executeSql( | ||
|
@@ -40,8 +50,8 @@ export const insertChapters = async ( | |
tx.executeSql( | ||
` | ||
UPDATE Chapter SET | ||
page = ?, position = ? | ||
WHERE path = ? AND novelId = ? AND (page != ? OR position != ?) | ||
page = ?, position = ?, hidden = 0 | ||
WHERE path = ? AND novelId = ? AND (page != ? OR position != ? OR hidden != 0) | ||
`, | ||
[ | ||
chapter.page || '1', | ||
|
@@ -56,6 +66,12 @@ export const insertChapters = async ( | |
}, | ||
); | ||
}); | ||
chaptersToHide.forEach(chapter => { | ||
tx.executeSql( | ||
'UPDATE Chapter SET hidden = 1 WHERE path = ? AND novelId = ?', | ||
[chapter.path, novelId], | ||
); | ||
}); | ||
}); | ||
}; | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -77,6 +77,7 @@ const getLibraryWithCategoryQuery = ` | |
SUM(unread) as chaptersUnread, SUM(isDownloaded) as chaptersDownloaded, | ||
novelId, MAX(readTime) as lastReadAt, MAX(updatedTime) as lastUpdatedAt | ||
FROM Chapter | ||
WHERE hidden = 0 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Dont show hidden chapters for unread counts |
||
GROUP BY novelId | ||
) as C ON NIL.id = C.novelId | ||
) WHERE 1 = 1 | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -14,23 +14,23 @@ const getChaptersReadCountQuery = ` | |
FROM Chapter | ||
JOIN Novel | ||
ON Chapter.novelId = Novel.id | ||
WHERE Chapter.unread = 0 AND Novel.inLibrary = 1 | ||
WHERE Chapter.unread = 0 AND Novel.inLibrary = 1 AND Chapter.hidden = 0 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. dont show hidden chapters for stats |
||
`; | ||
|
||
const getChaptersTotalCountQuery = ` | ||
SELECT COUNT(*) as chaptersCount | ||
FROM Chapter | ||
JOIN Novel | ||
ON Chapter.novelId = Novel.id | ||
WHERE Novel.inLibrary = 1 | ||
WHERE Novel.inLibrary = 1 AND Chapter.hidden = 0 | ||
`; | ||
|
||
const getChaptersUnreadCountQuery = ` | ||
SELECT COUNT(*) as chaptersUnread | ||
FROM Chapter | ||
JOIN Novel | ||
ON Chapter.novelId = Novel.id | ||
WHERE Chapter.unread = 1 AND Novel.inLibrary = 1 | ||
WHERE Chapter.unread = 1 AND Novel.inLibrary = 1 AND Chapter.hidden = 0 | ||
`; | ||
|
||
const getChaptersDownloadedCountQuery = ` | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -157,6 +157,7 @@ export default function usePlugins() { | |
name: _plg.name, | ||
version: _plg.version, | ||
hasUpdate: false, | ||
hasSettings: !!_plg.pluginSettings, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. update the hasSettings value on plugin update, not only plugin installation |
||
}; | ||
if (newPlugin.id === lastUsedPlugin?.id) { | ||
setLastUsedPlugin(newPlugin); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -44,9 +44,25 @@ export const fetchApi = async ( | |
init?: FetchInit, | ||
): Promise<Response> => { | ||
init = makeInit(init); | ||
return await fetch(url, init); | ||
return await fetch(url, init).then(checkCloudflareError); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. standardized cloudflare error handling across all plugins |
||
}; | ||
|
||
async function checkCloudflareError(res: Response) { | ||
const text = await res.clone().text(); | ||
const title = text.match(/<title>(.*?)<\/title>/)?.[1]; | ||
if ( | ||
title == 'Bot Verification' || | ||
title == 'You are being redirected...' || | ||
title == 'Un instant...' || | ||
title == 'Just a moment...' || | ||
title == 'Redirecting...' | ||
) { | ||
throw new Error('Captcha error, please open in webview'); | ||
} | ||
|
||
return res; | ||
} | ||
|
||
const FILE_READER_PREFIX_LENGTH = 'data:application/octet-stream;base64,' | ||
.length; | ||
|
||
|
@@ -79,7 +95,7 @@ export const fetchText = async ( | |
): Promise<string> => { | ||
init = makeInit(init); | ||
try { | ||
const res = await fetch(url, init); | ||
const res = await fetch(url, init).then(checkCloudflareError); | ||
if (!res.ok) { | ||
throw new Error(); | ||
} | ||
|
@@ -163,6 +179,7 @@ export const fetchProto = async function ( | |
...init, | ||
body: bodyArray, | ||
} as RequestInit) | ||
.then(checkCloudflareError) | ||
.then(r => r.blob()) | ||
.then(blob => { | ||
// decode response data | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -148,12 +148,17 @@ const getPlugin = (pluginId: string) => { | |
return plugins[pluginId]; | ||
}; | ||
|
||
const unloadPlugin = (pluginId: string) => { | ||
plugins[pluginId] = undefined; | ||
}; | ||
Comment on lines
+151
to
+153
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. option to unload plugin so you dont need to restart app to apply plugin settings |
||
|
||
const LOCAL_PLUGIN_ID = 'local'; | ||
|
||
export { | ||
getPlugin, | ||
installPlugin, | ||
uninstallPlugin, | ||
unloadPlugin, | ||
updatePlugin, | ||
fetchPlugins, | ||
LOCAL_PLUGIN_ID, | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,10 +5,13 @@ import { Button } from '@components/index'; | |
import { useTheme } from '@hooks/persisted'; | ||
import { getString } from '@strings/translations'; | ||
import { Storage } from '@plugins/helpers/storage'; | ||
import { unloadPlugin } from '@plugins/pluginManager'; | ||
import { SwitchItem } from '@components'; | ||
|
||
interface PluginSetting { | ||
value: string; | ||
label: string; | ||
type?: 'Switch'; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. add switch setting type |
||
} | ||
|
||
interface PluginSettings { | ||
|
@@ -75,6 +78,7 @@ const SourceSettingsModal: React.FC<SourceSettingsModal> = ({ | |
Object.entries(formValues).forEach(([key, value]) => { | ||
storage.set(key, value); | ||
}); | ||
unloadPlugin(pluginId); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. unload plugin on settings change (itll get re-loaded when needed) as this allows re-initialization of plugin settings |
||
onDismiss(); | ||
}; | ||
|
||
|
@@ -112,20 +116,30 @@ const SourceSettingsModal: React.FC<SourceSettingsModal> = ({ | |
</Text> | ||
<Text style={[{ color: theme.onSurfaceVariant }]}>{description}</Text> | ||
|
||
{Object.entries(pluginSettings).map(([key, setting]) => ( | ||
<TextInput | ||
key={key} | ||
mode="outlined" | ||
label={setting.label} | ||
value={formValues[key] || ''} | ||
onChangeText={value => handleChange(key, value)} | ||
placeholder={`Enter ${setting.label}`} | ||
placeholderTextColor={theme.onSurfaceDisabled} | ||
underlineColor={theme.outline} | ||
style={[{ color: theme.onSurface }, styles.textInput]} | ||
theme={{ colors: { ...theme } }} | ||
/> | ||
))} | ||
{Object.entries(pluginSettings).map(([key, setting]) => | ||
setting?.type === 'Switch' ? ( | ||
<SwitchItem | ||
key={key} | ||
label={setting.label} | ||
value={!!formValues[key]} | ||
onPress={() => handleChange(key, formValues[key] ? '' : 'true')} | ||
theme={theme} | ||
/> | ||
) : ( | ||
Comment on lines
+120
to
+128
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. switch setting type (saves the values as either an empty string or the string "true" as plugin settings are all strings, and by making false falsy it will work just as well) |
||
<TextInput | ||
key={key} | ||
mode="outlined" | ||
label={setting.label} | ||
value={formValues[key] || ''} | ||
onChangeText={value => handleChange(key, value)} | ||
placeholder={`Enter ${setting.label}`} | ||
placeholderTextColor={theme.onSurfaceDisabled} | ||
underlineColor={theme.outline} | ||
style={[{ color: theme.onSurface }, styles.textInput]} | ||
theme={{ colors: { ...theme } }} | ||
/> | ||
), | ||
)} | ||
|
||
<View style={styles.customCSSButtons}> | ||
<Button | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -71,7 +71,7 @@ const Novel = ({ route, navigation }: NovelScreenProps) => { | |
lastRead, | ||
novelSettings: { | ||
sort = defaultChapterSort, | ||
filter = '', | ||
filter = 'AND hidden=0', | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. by default hide hidden chapters |
||
showChapterTitles = false, | ||
}, | ||
openPage, | ||
|
@@ -89,6 +89,7 @@ const Novel = ({ route, navigation }: NovelScreenProps) => { | |
refreshChapters, | ||
deleteChapters, | ||
} = useNovel(path, pluginId); | ||
|
||
const theme = useTheme(); | ||
const { top: topInset, bottom: bottomInset } = useSafeAreaInsets(); | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -223,7 +223,11 @@ const NovelInfoHeader = ({ | |
) : null} | ||
<IconButton | ||
icon="filter-variant" | ||
iconColor={filter ? filterColor(theme.isDark) : theme.onSurface} | ||
iconColor={ | ||
filter.trim() !== 'AND hidden=0' | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. cus |
||
? filterColor(theme.isDark) | ||
: theme.onSurface | ||
} | ||
size={24} | ||
onPress={() => novelBottomSheetRef.current?.present()} | ||
/> | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -92,6 +92,16 @@ const ChaptersSettingsSheet = ({ | |
: filterChapters(filter + ' AND bookmark=1'); | ||
}} | ||
/> | ||
<Checkbox | ||
theme={theme} | ||
label={getString('novelScreen.bottomSheet.filters.dontExist')} | ||
status={!filter.match('AND hidden=0')} | ||
onPress={() => { | ||
filter.match('AND hidden=0') | ||
? filterChapters(filter.replace(/ ?AND hidden=0/, '')) | ||
: filterChapters(filter + ' AND hidden=0'); | ||
}} | ||
/> | ||
Comment on lines
+95
to
+104
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. checkbox to remove the |
||
</View> | ||
); | ||
|
||
|
@@ -184,7 +194,7 @@ const ChaptersSettingsSheet = ({ | |
); | ||
|
||
return ( | ||
<BottomSheet snapPoints={[240]} bottomSheetRef={bottomSheetRef}> | ||
<BottomSheet snapPoints={[280]} bottomSheetRef={bottomSheetRef}> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. sheet needs to be taller cus new option |
||
<BottomSheetView | ||
style={[ | ||
styles.contentContainer, | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,6 +6,7 @@ import { NOVEL_STORAGE } from '@utils/Storages'; | |
import { downloadFile } from '@plugins/helpers/fetch'; | ||
import ServiceManager from '@services/ServiceManager'; | ||
import { db } from '@database/db'; | ||
import { getPageChapters } from '@database/queries/ChapterQueries'; | ||
|
||
const updateNovelMetadata = ( | ||
pluginId: string, | ||
|
@@ -73,13 +74,23 @@ const updateNovelTotalPages = (novelId: number, totalPages: number) => { | |
}); | ||
}; | ||
|
||
const updateNovelChapters = ( | ||
const updateNovelChapters = async ( | ||
novelName: string, | ||
novelId: number, | ||
chapters: ChapterItem[], | ||
downloadNewChapters?: boolean, | ||
page?: string, | ||
) => { | ||
const existingChapters = await getPageChapters( | ||
novelId, | ||
'', | ||
'', | ||
chapters[0].page || '1', | ||
); | ||
const chaptersToHide = existingChapters.filter( | ||
c => !chapters.some(ch => ch.path === c.path), | ||
); | ||
Comment on lines
+90
to
+92
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Another place where hiding chapters that are in db but not in response |
||
|
||
return new Promise((resolve, reject) => { | ||
db.transaction(async tx => { | ||
for (let position = 0; position < chapters.length; position++) { | ||
|
@@ -124,8 +135,8 @@ const updateNovelChapters = ( | |
tx.executeSql( | ||
` | ||
UPDATE Chapter SET | ||
name = ?, releaseTime = ?, updatedTime = datetime('now','localtime'), page = ?, position = ? | ||
WHERE path = ? AND novelId = ? AND (name != ? OR releaseTime != ? OR page != ? OR position != ?); | ||
name = ?, releaseTime = ?, updatedTime = datetime('now','localtime'), page = ?, position = ?, hidden = 0 | ||
WHERE path = ? AND novelId = ? AND (name != ? OR releaseTime != ? OR page != ? OR position != ? OR hidden != 0); | ||
`, | ||
[ | ||
name, | ||
|
@@ -153,6 +164,12 @@ const updateNovelChapters = ( | |
}, | ||
); | ||
} | ||
chaptersToHide.forEach(chapter => { | ||
tx.executeSql( | ||
'UPDATE Chapter SET hidden = 1 WHERE path = ? AND novelId = ?', | ||
[chapter.path, novelId], | ||
); | ||
}); | ||
resolve(null); | ||
}); | ||
}); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -124,7 +124,7 @@ | |
"updatedTo": "Updated to %{version}", | ||
"settings": { | ||
"title": "Plugin Settings", | ||
"description": "Fill in the plugin settings. Restart app to apply the settings." | ||
"description": "Fill in the plugin settings." | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You dont need to restart the app anymore 🔥 |
||
} | ||
}, | ||
"browseSettings": "Browse Settings", | ||
|
@@ -333,7 +333,8 @@ | |
"filters": { | ||
"bookmarked": "Bookmarked", | ||
"downloaded": "Downloaded", | ||
"unread": "Unread" | ||
"unread": "Unread", | ||
"dontExist": "Show chapters that no longer exist" | ||
}, | ||
"order": { | ||
"byChapterName": "By chapter name", | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Db migration