feat: Add Scroll-to-Top Functionality in Chapter List (Closes #1470)

[skip ci]
This commit is contained in:
Rajarshee Chatterjee
2025-10-22 16:19:27 +05:30
parent f8d4f50307
commit cc217e2b04
2 changed files with 41 additions and 14 deletions
@@ -195,20 +195,6 @@ export const PluginListItem = memo(
</View>
</View>
<View style={styles.flex} />
<Button
title={getString('browseScreen.latest')}
textColor={theme.primary}
onPress={handleLatestPress}
/>
{item.hasSettings ? (
<IconButtonV2
name="cog-outline"
size={22}
color={theme.primary}
onPress={handleSettingsPress}
theme={theme}
/>
) : null}
{item.hasUpdate || __DEV__ ? (
<IconButtonV2
name="download-outline"
@@ -218,6 +204,20 @@ export const PluginListItem = memo(
theme={theme}
/>
) : null}
{item.hasSettings ? (
<IconButtonV2
name="cog-outline"
size={22}
color={theme.primary}
onPress={handleSettingsPress}
theme={theme}
/>
) : null}
<Button
title={getString('browseScreen.latest')}
textColor={theme.primary}
onPress={handleLatestPress}
/>
</Pressable>
</Swipeable>
<ConfirmationDialog
@@ -13,6 +13,7 @@ import {
import { getString } from '@strings/translations';
import { showToast } from '@utils/showToast';
import {
Dimensions,
NativeSyntheticEvent,
NativeScrollEvent,
RefreshControl,
@@ -108,6 +109,7 @@ const NovelScreenList = ({
const { downloadQueue, downloadChapter } = useDownload();
const [isFabExtended, setIsFabExtended] = useState(true);
const [showScrollToTop, setShowScrollToTop] = useState(false);
const novelBottomSheetRef = useRef<BottomSheetModalMethods>(null);
const trackerSheetRef = useRef<BottomSheetModalMethods>(null);
@@ -122,6 +124,9 @@ const NovelScreenList = ({
if (useFabForContinueReading && lastRead) {
setIsFabExtended(currentScrollPosition <= 0);
}
const screenHeight = Dimensions.get('window').height;
setShowScrollToTop(currentScrollPosition > screenHeight / 2);
};
const onRefresh = async () => {
@@ -230,6 +235,10 @@ const NovelScreenList = ({
});
};
const scrollToTop = () => {
listRef.current?.scrollToOffset({ offset: 0, animated: true });
};
const setCustomNovelCover = async () => {
if (!novel || novel.id === 'NO_ID') {
return;
@@ -381,6 +390,20 @@ const NovelScreenList = ({
showChapterTitles={showChapterTitles}
/>
<TrackSheet bottomSheetRef={trackerSheetRef} novel={novel} />
{showScrollToTop && (
<AnimatedFAB
style={[
styles.scrollToTopFab,
{ backgroundColor: theme.surface, marginBottom: bottomInset },
]}
color={theme.primary}
icon="arrow-up"
label=""
extended={false}
onPress={scrollToTop}
visible={showScrollToTop}
/>
)}
{useFabForContinueReading && (lastRead || chapters[0]) ? (
<AnimatedFAB
style={[
@@ -429,6 +452,10 @@ const styles = StyleSheet.create({
flexDirection: 'row',
justifyContent: 'space-between',
},
scrollToTopFab: {
bottom: 16,
position: 'absolute',
},
});
export default React.memo(NovelScreenList);