// noPage import { ContentStyle, FlashList } from "@shopify/flash-list"; import { LibComponent } from 'esoftplay/cache/lib/component/import'; import { LibCurl } from 'esoftplay/cache/lib/curl/import'; import { LibLoading } from 'esoftplay/cache/lib/loading/import'; import { LibStyle } from 'esoftplay/cache/lib/style/import'; import { LibTextstyle } from 'esoftplay/cache/lib/textstyle/import'; import esp from 'esoftplay/esp'; import React from 'react'; import isEqual from 'react-fast-compare'; import { View } from 'react-native'; export interface LibInfiniteProps { url: string, post?: any, isDebug?: 0 | 1, initialData?: any[], injectData?: any, onRefresh?: () => void onResponseEdit?: (res: any) => any, onDataChange?: (data: any, page: number) => void onResult?: (res: any, uri: string) => void, filterData?: (item: any, index: number, array: any[]) => boolean, error?: string, LoadingView?: any, errorView?: ((msg: string) => any) | any, mainIndex?: string, stickyHeaderIndices?: number[], bounces?: boolean, customHeader?: any, staticHeight?: number, ItemSeparatorComponent?: any, ListEmptyComponent?: any, ListFooterComponent?: any, ListEndedComponent?: any, ListHeaderComponent?: any, columnWrapperStyle?: any, onScroll?: (e: any) => void, scrollEventThrottle?: number, keyboardShouldPersistTaps?: boolean | "always" | "never" | "handled", extraData?: any, getItemLayout?: (data: any, index: number) => LibListItemLayout, horizontal?: boolean, initialNumToRender?: number, initialScrollIndex?: number, keyExtractor?: (item: any, index: number) => string, legacyImplementation?: boolean, numColumns?: number, onEndReached?: (() => void) | null, onEndReachedThreshold?: number | null, pagingEnabled?: boolean, refreshEnabled?: boolean, renderFooter?: () => any, renderItem: (item: any, index: number) => any, viewabilityConfig?: any, removeClippedSubviews?: boolean, style?: ContentStyle } export interface LibInfiniteState { data: any[], error: string } /** Klik [disini](https://github.com/dev-esoftplay/mobile-docs/blob/main/modules/lib/infinite.md) untuk melihat dokumentasi*/ export default class m extends LibComponent { isStop: boolean = false page: number | undefined = 0 pages: number[] flatlist = React.createRef>() constructor(props: LibInfiniteProps) { super(props); this.state = { data: [], error: '' } this.pages = [] this.loadData = this.loadData.bind(this); this._renderItem = this._renderItem.bind(this); this._keyExtractor = this._keyExtractor.bind(this); this.scrollToIndex = this.scrollToIndex.bind(this); /* DEPRECATED */ const dp = ['onResult', 'mainIndex', 'filterData'] dp.forEach((pr) => { if (this.props.hasOwnProperty(pr)) { console.warn(`props key ${pr} from LibInfinite has been DEPRECATED`) } }) } componentDidMount(): void { super.componentDidMount() this.loadData() } loadData(page?: number): void { if (page == undefined) { this.setState((state: LibInfiniteState, props: LibInfiniteProps) => { return { isStop: false, error: '', data: [] } }) page = 0 this.pages = [] } var { url, post } = this.props if (page > 0) { url += url.includes('?') ? '&' : '?' url += 'page=' + page } if (!this.pages.includes(page)) { this.pages.push(page) new LibCurl().withHeader(this.props?.customHeader || {})(url, post, (_res, msg) => { const data = this.props.onResponseEdit ? this.props.onResponseEdit(_res) : _res if (this.props.isDebug) { esp.log(data); } this.props.onResult && this.props.onResult(data, url) const update = () => { this.props.onDataChange && this.props.onDataChange(this.state.data || [], this.page) } let mainIndex: any = this.props.mainIndex && data[this.props.mainIndex] || data if (mainIndex.list.length == 0 || data.list == '') { this.page = page this.isStop = true this.setState((state: LibInfiniteState, props: LibInfiniteProps) => { return { isStop: this.isStop, error: this.props.error || esp.lang("lib/infinite", "empty_data"), data: page == 0 ? [] : (typeof this.props?.filterData == 'function' ? state.data.filter(this.props.filterData) : state.data), } }, update) } else { this.page = page this.isStop = ([...this.state.data, ...mainIndex.list].length >= parseInt(mainIndex.total) || (this.page >= (mainIndex.pages || mainIndex.total_page) - 1)) this.setState((state: LibInfiniteState, props: LibInfiniteProps) => { const latestData = [...state.data, ...mainIndex.list] return { isStop: this.isStop, error: '', data: page == 0 ? (typeof this.props?.filterData == 'function' ? mainIndex.list.filter(this.props.filterData) : mainIndex.list) : (typeof this.props?.filterData == 'function' ? latestData.filter(this.props.filterData) : latestData), } }, update) } }, (msg) => { if (this.props.isDebug) { esp.log(msg) } this.page = page this.isStop = true this.setState({ data: [], error: msg?.message, }) }, this.props.isDebug ) } } componentDidUpdate(prevProps: LibInfiniteProps, prevState: LibInfiniteState): void { if (this.props.initialData != undefined && prevProps.initialData != this.props.initialData && this.props.initialData.length != 0 && this.state.data.length == 0) { this.setState({ data: this.props.initialData, error: "" }) } if (this.props.injectData !== undefined && !isEqual(this.props.injectData, this.state.data)) { this.setState({ data: this.props.injectData, error: "" }) } } _renderItem({ item, index }: any): any { return this.props.renderItem(item, index) } _keyExtractor(item: any, index: number): string { return item.hasOwnProperty('id') && item.id || index.toString() } scrollToIndex(x: number, anim?: boolean, viewOffset?: number, viewPosition?: number): void { if (!anim) anim = true; this.flatlist.current?.scrollToIndex({ index: x, animated: anim, viewOffset: viewOffset, viewPosition: viewPosition }) } render(): any { const { data, error } = this.state const { errorView, refreshEnabled } = this.props // const AutoLayoutViewNativeComponent = require("@shopify/flash-list/src/native/auto-layout/AutoLayoutViewNativeComponent") return ( { (!data || data.length) == 0 && !this.isStop ? this.props.LoadingView || : { this.loadData() this.props?.onRefresh?.() } : () => { }} refreshing={false} keyExtractor={this._keyExtractor} nestedScrollEnabled ListEmptyComponent={ errorView ? typeof errorView == 'function' ? errorView(error) : errorView : } showsHorizontalScrollIndicator={false} showsVerticalScrollIndicator={false} estimatedItemSize={this.props.staticHeight || 100} initialNumToRender={5} ListFooterComponent={ (!this.isStop) ? : (this.props?.ListEndedComponent || ) } onEndReachedThreshold={0.5} onEndReached={() => { if (!this.isStop) { this.loadData((this?.page || 0) + 1) } }} {...this.props} contentContainerStyle={this.props?.style} style={undefined} renderItem={this._renderItem} /> } ) } }