UNPKG

rs-react-native-image-gallery

Version:
214 lines (210 loc) 35.8 kB
import { FlashList } from '@shopify/flash-list'; import { useCallback, useEffect, useMemo, useRef, useState } from 'react'; import { Dimensions, Image, StyleSheet, Text, TouchableOpacity, View } from 'react-native'; import Modal from 'react-native-modal'; import { preLoadImages } from './_helpers'; import { DEFAULT_THUMB_COLOR, DEFAULT_THUMB_SIZE, THUMB_SPACING } from './constants'; import ImagePreview from './image-preview'; import SwipeContainer from './swipe-container'; // ---------------------------------------------------------------------- var _a = Dimensions.get('window'), deviceHeight = _a.height, deviceWidth = _a.width; var ImageGallery = function (_a) { var close = _a.close, _b = _a.hideThumbs, hideThumbs = _b === void 0 ? false : _b, _c = _a.images, images = _c === void 0 ? [] : _c, _d = _a.initialIndex, initialIndex = _d === void 0 ? 0 : _d, isOpen = _a.isOpen, renderCustomImage = _a.renderCustomImage, renderCustomThumb = _a.renderCustomThumb, renderFooterComponent = _a.renderFooterComponent, renderHeaderComponent = _a.renderHeaderComponent, _e = _a.resizeMode, resizeMode = _e === void 0 ? 'contain' : _e, _f = _a.thumbColor, thumbColor = _f === void 0 ? DEFAULT_THUMB_COLOR : _f, _g = _a.thumbResizeMode, thumbResizeMode = _g === void 0 ? 'cover' : _g, _h = _a.thumbSize, thumbSize = _h === void 0 ? DEFAULT_THUMB_SIZE : _h, _j = _a.disableSwipe, disableSwipe = _j === void 0 ? false : _j; var _k = useState(initialIndex), activeIndex = _k[0], setActiveIndex = _k[1]; var _l = useState(false), isDragging = _l[0], setIsDragging = _l[1]; var topRef = useRef(null); var bottomRef = useRef(null); // Memoize sizes to prevent unnecessary re-renders var mainListSize = useMemo(function () { return ({ width: deviceWidth, height: deviceHeight }); }, []); var keyExtractor = useCallback(function (item, index) { var _a, _b; return (_b = (_a = item.id) === null || _a === void 0 ? void 0 : _a.toString()) !== null && _b !== void 0 ? _b : index.toString(); }, []); var scrollToIndex = useCallback(function (index) { if (!isOpen || index < 0 || index >= images.length) return; // Update active index first setActiveIndex(index); // Create scroll options - center the item in the view var scrollOptions = { animated: true, index: index, viewPosition: 0.5 }; // Use setTimeout to ensure animations work properly with state update setTimeout(function () { try { if (topRef.current) { topRef.current.scrollToIndex(scrollOptions); } if (bottomRef.current && !hideThumbs) { bottomRef.current.scrollToIndex(scrollOptions); } } catch (error) { console.warn('Error scrolling to index:', error); } }, 0); }, [hideThumbs, isOpen, images.length]); var renderItem = useCallback(function (_a) { var item = _a.item, index = _a.index; return (<View style={{ width: deviceWidth, height: deviceHeight, flex: 1 }}> <ImagePreview index={index} isSelected={activeIndex === index} item={item} resizeMode={resizeMode} renderCustomImage={renderCustomImage}/> </View>); }, [activeIndex, resizeMode, renderCustomImage, deviceWidth, deviceHeight]); var renderThumb = function (_a) { var item = _a.item, index = _a.index; // Check active state on each render var isActive = activeIndex === index; var imageSource = item.thumbSource || item.source || { uri: item.thumbUrl || item.url }; // Create proper conditional styling that won't fail with null/undefined var thumbStyle; if (isActive) { thumbStyle = [ styles.thumb, { width: thumbSize, height: thumbSize, borderWidth: 3, borderColor: thumbColor } ]; } else { thumbStyle = [styles.thumb, { width: thumbSize, height: thumbSize }]; } return (<TouchableOpacity onPress={function () { return scrollToIndex(index); }} activeOpacity={0.8} style={{ height: thumbSize, marginRight: THUMB_SPACING, justifyContent: 'center', alignItems: 'center' }}> {renderCustomThumb ? (renderCustomThumb(item, index, isActive)) : (<Image resizeMode={thumbResizeMode} style={thumbStyle} source={imageSource} fadeDuration={100}/>)} </TouchableOpacity>); }; var onMomentumEnd = useCallback(function (e) { var x = e.nativeEvent.contentOffset.x; var newIndex = Math.round(x / deviceWidth); // Only update if different to avoid unnecessary re-renders if (newIndex !== activeIndex) { scrollToIndex(newIndex); } }, [deviceWidth, scrollToIndex, activeIndex]); useEffect(function () { // Only set the initial index when opening the gallery if (isOpen && initialIndex >= 0 && initialIndex < images.length) { setActiveIndex(initialIndex); } else if (!isOpen) { // Reset the active index when closing, but don't scroll setActiveIndex(0); } }, [isOpen, initialIndex, images.length]); // Preload image thumbnails when gallery opens useEffect(function () { if (isOpen && images.length > 0) { var urls = images.map(function (img) { return img.thumbUrl || img.url; }).filter(Boolean); preLoadImages(urls); } }, [isOpen, images]); return (<Modal isVisible={isOpen} onBackdropPress={close} onBackButtonPress={close} onSwipeComplete={close} swipeDirection={disableSwipe ? [] : ['down']} style={{ margin: 0, justifyContent: 'flex-end' }} useNativeDriverForBackdrop={true} useNativeDriver={true} hideModalContentWhileAnimating={true} propagateSwipe={true} onModalHide={function () { if (bottomRef.current) { bottomRef.current.scrollToIndex({ index: activeIndex, animated: false, viewPosition: 0.5 }); } if (topRef.current) { topRef.current.scrollToIndex({ index: activeIndex, animated: false, viewPosition: 0.5 }); } }} onModalWillShow={function () { if (bottomRef.current) { bottomRef.current.scrollToIndex({ index: activeIndex, animated: false, viewPosition: 0.5 }); } if (topRef.current) { topRef.current.scrollToIndex({ index: activeIndex, animated: false, viewPosition: 0.5 }); } }}> <View style={styles.container}> {images.length > 0 && (<> <SwipeContainer disableSwipe={disableSwipe} setIsDragging={setIsDragging} close={close}> <FlashList initialScrollIndex={initialIndex < images.length ? initialIndex : 0} estimatedItemSize={deviceWidth} data={images} horizontal keyExtractor={keyExtractor} onMomentumScrollEnd={onMomentumEnd} pagingEnabled ref={topRef} renderItem={renderItem} scrollEnabled={!isDragging} showsHorizontalScrollIndicator={false} estimatedListSize={mainListSize} drawDistance={deviceWidth} removeClippedSubviews={true}/> </SwipeContainer> {!hideThumbs && (<View style={styles.bottomFlatlist}> <FlashList initialScrollIndex={initialIndex < images.length ? initialIndex : 0} estimatedItemSize={thumbSize + THUMB_SPACING} contentContainerStyle={styles.thumbnailListContainer} data={images} horizontal keyExtractor={keyExtractor} pagingEnabled={false} ref={bottomRef} renderItem={renderThumb} showsHorizontalScrollIndicator={false} drawDistance={deviceWidth * 2} removeClippedSubviews={true} extraData={activeIndex} overrideItemLayout={function (layout, _item, _index) { layout.size = thumbSize + THUMB_SPACING; }}/> </View>)} </>)} {/* Page indicator */} {images.length > 0 && (<View style={styles.pageIndicator}> <Text style={styles.pageIndicatorText}>{"".concat(activeIndex + 1, " / ").concat(images.length)}</Text> </View>)} {renderHeaderComponent && images.length > 0 && (<View style={styles.header}>{renderHeaderComponent(images[activeIndex], activeIndex)}</View>)} {renderFooterComponent && images.length > 0 && (<View style={styles.footer}>{renderFooterComponent(images[activeIndex], activeIndex)}</View>)} </View> </Modal>); }; var styles = StyleSheet.create({ container: { alignItems: 'center', backgroundColor: 'black', flex: 1, height: deviceHeight, justifyContent: 'center', width: deviceWidth }, header: { position: 'absolute', top: 0, width: '100%' }, footer: { position: 'absolute', bottom: 0, width: '100%' }, activeThumb: { borderWidth: 3 }, thumb: { borderRadius: 12 }, thumbnailListContainer: { paddingVertical: 20, paddingHorizontal: 10 }, bottomFlatlist: { position: 'absolute', width: deviceWidth, height: DEFAULT_THUMB_SIZE * 1.5, bottom: DEFAULT_THUMB_SIZE, left: 0 }, pageIndicator: { position: 'absolute', top: 15, alignSelf: 'center', backgroundColor: 'rgba(0, 0, 0, 0.5)', padding: 8, borderRadius: 15, zIndex: 20 }, pageIndicatorText: { color: 'white', fontSize: 14, fontWeight: 'bold' } }); export default ImageGallery; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW1hZ2UtZ2FsbGVyeS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9pbWFnZS1nYWxsZXJ5LnRzeCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFDaEQsT0FBTyxFQUFFLFdBQVcsRUFBRSxTQUFTLEVBQUUsT0FBTyxFQUFFLE1BQU0sRUFBRSxRQUFRLEVBQUUsTUFBTSxPQUFPLENBQUM7QUFDMUUsT0FBTyxFQUFFLFVBQVUsRUFBRSxLQUFLLEVBQUUsVUFBVSxFQUFFLElBQUksRUFBRSxnQkFBZ0IsRUFBRSxJQUFJLEVBQUUsTUFBTSxjQUFjLENBQUM7QUFDM0YsT0FBTyxLQUFLLE1BQU0sb0JBQW9CLENBQUM7QUFDdkMsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLFlBQVksQ0FBQztBQUMzQyxPQUFPLEVBQUUsbUJBQW1CLEVBQUUsa0JBQWtCLEVBQUUsYUFBYSxFQUFFLE1BQU0sYUFBYSxDQUFDO0FBQ3JGLE9BQU8sWUFBWSxNQUFNLGlCQUFpQixDQUFDO0FBQzNDLE9BQU8sY0FBYyxNQUFNLG1CQUFtQixDQUFDO0FBRy9DLHlFQUF5RTtBQUVuRSxJQUFBLEtBQStDLFVBQVUsQ0FBQyxHQUFHLENBQUMsUUFBUSxDQUFDLEVBQTdELFlBQVksWUFBQSxFQUFTLFdBQVcsV0FBNkIsQ0FBQztBQUU5RSxJQUFNLFlBQVksR0FBMkIsVUFBQyxFQWU3QztRQWRBLEtBQUssV0FBQSxFQUNMLGtCQUFrQixFQUFsQixVQUFVLG1CQUFHLEtBQUssS0FBQSxFQUNsQixjQUFXLEVBQVgsTUFBTSxtQkFBRyxFQUFFLEtBQUEsRUFDWCxvQkFBZ0IsRUFBaEIsWUFBWSxtQkFBRyxDQUFDLEtBQUEsRUFDaEIsTUFBTSxZQUFBLEVBQ04saUJBQWlCLHVCQUFBLEVBQ2pCLGlCQUFpQix1QkFBQSxFQUNqQixxQkFBcUIsMkJBQUEsRUFDckIscUJBQXFCLDJCQUFBLEVBQ3JCLGtCQUFz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UCxTQUFTLEVBQUUsUUFBUTtRQUNuQixlQUFlLEVBQUUsb0JBQW9CO1FBQ3JDLE9BQU8sRUFBRSxDQUFDO1FBQ1YsWUFBWSxFQUFFLEVBQUU7UUFDaEIsTUFBTSxFQUFFLEVBQUU7S0FDVjtJQUNELGlCQUFpQixFQUFFO1FBQ2xCLEtBQUssRUFBRSxPQUFPO1FBQ2QsUUFBUSxFQUFFLEVBQUU7UUFDWixVQUFVLEVBQUUsTUFBTTtLQUNsQjtDQUNELENBQUMsQ0FBQztBQUVILGVBQWUsWUFBWSxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgRmxhc2hMaXN0IH0gZnJvbSAnQHNob3BpZnkvZmxhc2gtbGlzdCc7XG5pbXBvcnQgeyB1c2VDYWxsYmFjaywgdXNlRWZmZWN0LCB1c2VNZW1vLCB1c2VSZWYsIHVzZVN0YXRlIH0gZnJvbSAncmVhY3QnO1xuaW1wb3J0IHsgRGltZW5zaW9ucywgSW1hZ2UsIFN0eWxlU2hlZXQsIFRleHQsIFRvdWNoYWJsZU9wYWNpdHksIFZpZXcgfSBmcm9tICdyZWFjdC1uYXRpdmUnO1xuaW1wb3J0IE1vZGFsIGZyb20gJ3JlYWN0LW5hdGl2ZS1tb2RhbCc7XG5pbXBvcnQgeyBwcmVMb2FkSW1hZ2VzIH0gZnJvbSAnLi9faGVscGVycyc7XG5pbXBvcnQgeyBERUZBVUxUX1RIVU1CX0NPTE9SLCBERUZBVUxUX1RIVU1CX1NJWkUsIFRIVU1CX1NQQUNJTkcgfSBmcm9tICcuL2NvbnN0YW50cyc7XG5pbXBvcnQgSW1hZ2VQcmV2aWV3IGZyb20gJy4vaW1hZ2UtcHJldmlldyc7XG5pbXBvcnQgU3dpcGVDb250YWluZXIgZnJvbSAnLi9zd2lwZS1jb250YWluZXInO1xuaW1wb3J0IHR5cGUgeyBHYWxsZXJ5UHJvcHMsIEltYWdlT2JqZWN0LCBSZW5kZXJJbWFnZVByb3BzIH0gZnJvbSAnLi90eXBlcyc7XG5cbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuY29uc3QgeyBoZWlnaHQ6IGRldmljZUhlaWdodCwgd2lkdGg6IGRldmljZVdpZHRoIH0gPSBEaW1lbnNpb25zLmdldCgnd2luZG93Jyk7XG5cbmNvbnN0IEltYWdlR2FsbGVyeTogUmVhY3QuRkM8R2FsbGVyeVByb3BzPiA9ICh7XG5cdGNsb3NlLFxuXHRoaWRlVGh1bWJzID0gZmFsc2UsXG5cdGltYWdlcyA9IFtdLFxuXHRpbml0aWFsSW5kZXggPSAwLFxuXHRpc09wZW4sXG5cdHJlbmRlckN1c3RvbUltYWdlLFxuXHRyZW5kZXJDdXN0b21UaHVtYixcblx0cmVuZGVyRm9vdGVyQ29tcG9uZW50LFxuXHRyZW5kZXJIZWFkZXJDb21wb25lbnQsXG5cdHJlc2l6ZU1vZGUgPSAnY29udGFpbicsXG5cdHRodW1iQ29sb3IgPSBERUZBVUxUX1RIVU1CX0NPTE9SLFxuXHR0aHVtYlJlc2l6ZU1vZGUgPSAnY292ZXInLFxuXHR0aHVtYlNpemUgPSBERUZBVUxUX1RIVU1CX1NJWkUsXG5cdGRpc2FibGVTd2lwZSA9IGZhbHNlXG59KSA9PiB7XG5cdGNvbnN0IFthY3RpdmVJbmRleCwgc2V0QWN0aXZlSW5kZXhdID0gdXNlU3RhdGUoaW5pdGlhbEluZGV4KTtcblx0Y29uc3QgW2lzRHJhZ2dpbmcsIHNldElzRHJhZ2dpbmddID0gdXNlU3RhdGUoZmFsc2UpO1xuXG5cdGNvbnN0IHRvcFJlZiA9IHVzZVJlZjxGbGFzaExpc3Q8SW1hZ2VPYmplY3Q+PihudWxsKTtcblx0Y29uc3QgYm90dG9tUmVmID0gdXNlUmVmPEZsYXNoTGlzdDxJbWFnZU9iamVjdD4+KG51bGwpO1xuXG5cdC8vIE1lbW9pemUgc2l6ZXMgdG8gcHJldmVudCB1bm5lY2Vzc2FyeSByZS1yZW5kZXJzXG5cdGNvbnN0IG1haW5MaXN0U2l6ZSA9IHVzZU1lbW8oKCkgPT4gKHsgd2lkdGg6IGRldmljZVdpZHRoLCBoZWlnaHQ6IGRldmljZUhlaWdodCB9KSwgW10pO1xuXG5cdGNvbnN0IGtleUV4dHJhY3RvciA9IHVzZUNhbGxiYWNrKChpdGVtOiBJbWFnZU9iamVjdCwgaW5kZXg6IG51bWJlcikgPT4gaXRlbS5pZD8udG9TdHJpbmcoKSA/PyBpbmRleC50b1N0cmluZygpLCBbXSk7XG5cblx0Y29uc3Qgc2Nyb2xsVG9JbmRleCA9IHVzZUNhbGxiYWNrKFxuXHRcdChpbmRleDogbnVtYmVyKSA9PiB7XG5cdFx0XHRpZiAoIWlzT3BlbiB8fCBpbmRleCA8IDAgfHwgaW5kZXggPj0gaW1hZ2VzLmxlbmd0aCkgcmV0dXJuO1xuXG5cdFx0XHQvLyBVcGRhdGUgYWN0aXZlIGluZGV4IGZpcnN0XG5cdFx0XHRzZXRBY3RpdmVJbmRleChpbmRleCk7XG5cblx0XHRcdC8vIENyZWF0ZSBzY3JvbGwgb3B0aW9ucyAtIGNlbnRlciB0aGUgaXRlbSBpbiB0aGUgdmlld1xuXHRcdFx0Y29uc3Qgc2Nyb2xsT3B0aW9ucyA9IHtcblx0XHRcdFx0YW5pbWF0ZWQ6IHRydWUsXG5cdFx0XHRcdGluZGV4LFxuXHRcdFx0XHR2aWV3UG9zaXRpb246IDAuNVxuXHRcdFx0fTtcblxuXHRcdFx0Ly8gVXNlIHNldFRpbWVvdXQgdG8gZW5zdXJlIGFuaW1hdGlvbnMgd29yayBwcm9wZXJseSB3aXRoIHN0YXRlIHVwZGF0ZVxuXHRcdFx0c2V0VGltZW91dCgoKSA9PiB7XG5cdFx0XHRcdHRyeSB7XG5cdFx0XHRcdFx0aWYgKHRvcFJlZi5jdXJyZW50KSB7XG5cdFx0XHRcdFx0XHR0b3BSZWYuY3VycmVudC5zY3JvbGxUb0luZGV4KHNjcm9sbE9wdGlvbnMpO1xuXHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdGlmIChib3R0b21SZWYuY3VycmVudCAmJiAhaGlkZVRodW1icykge1xuXHRcdFx0XHRcdFx0Ym90dG9tUmVmLmN1cnJlbnQuc2Nyb2xsVG9JbmRleChzY3JvbGxPcHRpb25zKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH0gY2F0Y2ggKGVycm9yKSB7XG5cdFx0XHRcdFx0Y29uc29sZS53YXJuKCdFcnJvciBzY3JvbGxpbmcgdG8gaW5kZXg6JywgZXJyb3IpO1xuXHRcdFx0XHR9XG5cdFx0XHR9LCAwKTtcblx0XHR9LFxuXHRcdFtoaWRlVGh1bWJzLCBpc09wZW4sIGltYWdlcy5sZW5ndGhdXG5cdCk7XG5cblx0Y29uc3QgcmVuZGVySXRlbSA9IHVzZUNhbGxiYWNrKFxuXHRcdCh7IGl0ZW0sIGluZGV4IH06IFJlbmRlckltYWdlUHJvcHMpID0+IChcblx0XHRcdDxWaWV3IHN0eWxlPXt7IHdpZHRoOiBkZXZpY2VXaWR0aCwgaGVpZ2h0OiBkZXZpY2VIZWlnaHQsIGZsZXg6IDEgfX0+XG5cdFx0XHRcdDxJbWFnZVByZXZpZXdcblx0XHRcdFx0XHRpbmRleD17aW5kZXh9XG5cdFx0XHRcdFx0aXNTZWxlY3RlZD17YWN0aXZlSW5kZXggPT09IGluZGV4fVxuXHRcdFx0XHRcdGl0ZW09e2l0ZW19XG5cdFx0XHRcdFx0cmVzaXplTW9kZT17cmVzaXplTW9kZX1cblx0XHRcdFx0XHRyZW5kZXJDdXN0b21JbWFnZT17cmVuZGVyQ3VzdG9tSW1hZ2V9XG5cdFx0XHRcdC8+XG5cdFx0XHQ8L1ZpZXc+XG5cdFx0KSxcblx0XHRbYWN0aXZlSW5kZXgsIHJlc2l6ZU1vZGUsIHJlbmRlckN1c3RvbUltYWdlLCBkZXZpY2VXaWR0aCwgZGV2aWNlSGVpZ2h0XVxuXHQpO1xuXG5cdGNvbnN0IHJlbmRlclRodW1iID0gKHsgaXRlbSwgaW5kZXggfTogUmVuZGVySW1hZ2VQcm9wcykgPT4ge1xuXHRcdC8vIENoZWNrIGFjdGl2ZSBzdGF0ZSBvbiBlYWNoIHJlbmRlclxuXHRcdGNvbnN0IGlzQWN0aXZlID0gYWN0aXZlSW5kZXggPT09IGluZGV4O1xuXHRcdGNvbnN0IGltYWdlU291cmNlID0gaXRlbS50aHVtYlNvdXJjZSB8fCBpdGVtLnNvdXJjZSB8fCB7IHVyaTogaXRlbS50aHVtYlVybCB8fCBpdGVtLnVybCB9O1xuXG5cdFx0Ly8gQ3JlYXRlIHByb3BlciBjb25kaXRpb25hbCBzdHlsaW5nIHRoYXQgd29uJ3QgZmFpbCB3aXRoIG51bGwvdW5kZWZpbmVkXG5cdFx0bGV0IHRodW1iU3R5bGU7XG5cdFx0aWYgKGlzQWN0aXZlKSB7XG5cdFx0XHR0aHVtYlN0eWxlID0gW1xuXHRcdFx0XHRzdHlsZXMudGh1bWIsXG5cdFx0XHRcdHtcblx0XHRcdFx0XHR3aWR0aDogdGh1bWJTaXplLFxuXHRcdFx0XHRcdGhlaWdodDogdGh1bWJTaXplLFxuXHRcdFx0XHRcdGJvcmRlcldpZHRoOiAzLFxuXHRcdFx0XHRcdGJvcmRlckNvbG9yOiB0aHVtYkNvbG9yXG5cdFx0XHRcdH1cblx0XHRcdF07XG5cdFx0fSBlbHNlIHtcblx0XHRcdHRodW1iU3R5bGUgPSBbc3R5bGVzLnRodW1iLCB7IHdpZHRoOiB0aHVtYlNpemUsIGhlaWdodDogdGh1bWJTaXplIH1dO1xuXHRcdH1cblxuXHRcdHJldHVybiAoXG5cdFx0XHQ8VG91Y2hhYmxlT3BhY2l0eVxuXHRcdFx0XHRvblByZXNzPXsoKSA9PiBzY3JvbGxUb0luZGV4KGluZGV4KX1cblx0XHRcdFx0YWN0aXZlT3BhY2l0eT17MC44fVxuXHRcdFx0XHRzdHlsZT17e1xuXHRcdFx0XHRcdGhlaWdodDogdGh1bWJTaXplLFxuXHRcdFx0XHRcdG1hcmdpblJpZ2h0OiBUSFVNQl9TUEFDSU5HLFxuXHRcdFx0XHRcdGp1c3RpZnlDb250ZW50OiAnY2VudGVyJyxcblx0XHRcdFx0XHRhbGlnbkl0ZW1zOiAnY2VudGVyJ1xuXHRcdFx0XHR9fT5cblx0XHRcdFx0e3JlbmRlckN1c3RvbVRodW1iID8gKFxuXHRcdFx0XHRcdHJlbmRlckN1c3RvbVRodW1iKGl0ZW0sIGluZGV4LCBpc0FjdGl2ZSlcblx0XHRcdFx0KSA6IChcblx0XHRcdFx0XHQ8SW1hZ2UgcmVzaXplTW9kZT17dGh1bWJSZXNpemVNb2RlfSBzdHlsZT17dGh1bWJTdHlsZX0gc291cmNlPXtpbWFnZVNvdXJjZX0gZmFkZUR1cmF0aW9uPXsxMDB9IC8+XG5cdFx0XHRcdCl9XG5cdFx0XHQ8L1RvdWNoYWJsZU9wYWNpdHk+XG5cdFx0KTtcblx0fTtcblxuXHRjb25zdCBvbk1vbWVudHVtRW5kID0gdXNlQ2FsbGJhY2soXG5cdFx0KGU6IHsgbmF0aXZlRXZlbnQ6IHsgY29udGVudE9mZnNldDogeyB4OiBudW1iZXIgfSB9IH0pID0+IHtcblx0XHRcdGNvbnN0IHsgeCB9ID0gZS5uYXRpdmVFdmVudC5jb250ZW50T2Zmc2V0O1xuXHRcdFx0Y29uc3QgbmV3SW5kZXggPSBNYXRoLnJvdW5kKHggLyBkZXZpY2VXaWR0aCk7XG5cblx0XHRcdC8vIE9ubHkgdXBkYXRlIGlmIGRpZmZlcmVudCB0byBhdm9pZCB1bm5lY2Vzc2FyeSByZS1yZW5kZXJzXG5cdFx0XHRpZiAobmV3SW5kZXggIT09IGFjdGl2ZUluZGV4KSB7XG5cdFx0XHRcdHNjcm9sbFRvSW5kZXgobmV3SW5kZXgpO1xuXHRcdFx0fVxuXHRcdH0sXG5cdFx0W2RldmljZVdpZHRoLCBzY3JvbGxUb0luZGV4LCBhY3RpdmVJbmRleF1cblx0KTtcblxuXHR1c2VFZmZlY3QoKCkgPT4ge1xuXHRcdC8vIE9ubHkgc2V0IHRoZSBpbml0aWFsIGluZGV4IHdoZW4gb3BlbmluZyB0aGUgZ2FsbGVyeVxuXHRcdGlmIChpc09wZW4gJiYgaW5pdGlhbEluZGV4ID49IDAgJiYgaW5pdGlhbEluZGV4IDwgaW1hZ2VzLmxlbmd0aCkge1xuXHRcdFx0c2V0QWN0aXZlSW5kZXgoaW5pdGlhbEluZGV4KTtcblx0XHR9IGVsc2UgaWYgKCFpc09wZW4pIHtcblx0XHRcdC8vIFJlc2V0IHRoZSBhY3RpdmUgaW5kZXggd2hlbiBjbG9zaW5nLCBidXQgZG9uJ3Qgc2Nyb2xsXG5cdFx0XHRzZXRBY3RpdmVJbmRleCgwKTtcblx0XHR9XG5cdH0sIFtpc09wZW4sIGluaXRpYWxJbmRleCwgaW1hZ2VzLmxlbmd0aF0pO1xuXG5cdC8vIFByZWxvYWQgaW1hZ2UgdGh1bWJuYWlscyB3aGVuIGdhbGxlcnkgb3BlbnNcblx0dXNlRWZmZWN0KCgpID0+IHtcblx0XHRpZiAoaXNPcGVuICYmIGltYWdlcy5sZW5ndGggPiAwKSB7XG5cdFx0XHRjb25zdCB1cmxzID0gaW1hZ2VzLm1hcCgoaW1nKSA9PiBpbWcudGh1bWJVcmwgfHwgaW1nLnVybCkuZmlsdGVyKEJvb2xlYW4pO1xuXHRcdFx0cHJlTG9hZEltYWdlcyh1cmxzKTtcblx0XHR9XG5cdH0sIFtpc09wZW4sIGltYWdlc10pO1xuXG5cdHJldHVybiAoXG5cdFx0PE1vZGFsXG5cdFx0XHRpc1Zpc2libGU9e2lzT3Blbn1cblx0XHRcdG9uQmFja2Ryb3BQcmVzcz17Y2xvc2V9XG5cdFx0XHRvbkJhY2tCdXR0b25QcmVzcz17Y2xvc2V9XG5cdFx0XHRvblN3aXBlQ29tcGxldGU9e2Nsb3NlfVxuXHRcdFx0c3dpcGVEaXJlY3Rpb249e2Rpc2FibGVTd2lwZSA/IFtdIDogWydkb3duJ119XG5cdFx0XHRzdHlsZT17eyBtYXJnaW46IDAsIGp1c3RpZnlDb250ZW50OiAnZmxleC1lbmQnIH19XG5cdFx0XHR1c2VOYXRpdmVEcml2ZXJGb3JCYWNrZHJvcD17dHJ1ZX1cblx0XHRcdHVzZU5hdGl2ZURyaXZlcj17dHJ1ZX1cblx0XHRcdGhpZGVNb2RhbENvbnRlbnRXaGlsZUFuaW1hdGluZz17dHJ1ZX1cblx0XHRcdHByb3BhZ2F0ZVN3aXBlPXt0cnVlfVxuXHRcdFx0b25Nb2RhbEhpZGU9eygpID0+IHtcblx0XHRcdFx0aWYgKGJvdHRvbVJlZi5jdXJyZW50KSB7XG5cdFx0XHRcdFx0Ym90dG9tUmVmLmN1cnJlbnQuc2Nyb2xsVG9JbmRleCh7XG5cdFx0XHRcdFx0XHRpbmRleDogYWN0aXZlSW5kZXgsXG5cdFx0XHRcdFx0XHRhbmltYXRlZDogZmFsc2UsXG5cdFx0XHRcdFx0XHR2aWV3UG9zaXRpb246IDAuNVxuXHRcdFx0XHRcdH0pO1xuXHRcdFx0XHR9XG5cdFx0XHRcdGlmICh0b3BSZWYuY3VycmVudCkge1xuXHRcdFx0XHRcdHRvcFJlZi5jdXJyZW50LnNjcm9sbFRvSW5kZXgoe1xuXHRcdFx0XHRcdFx0aW5kZXg6IGFjdGl2ZUluZGV4LFxuXHRcdFx0XHRcdFx0YW5pbWF0ZWQ6IGZhbHNlLFxuXHRcdFx0XHRcdFx0dmlld1Bvc2l0aW9uOiAwLjVcblx0XHRcdFx0XHR9KTtcblx0XHRcdFx0fVxuXHRcdFx0fX1cblx0XHRcdG9uTW9kYWxXaWxsU2hvdz17KCkgPT4ge1xuXHRcdFx0XHRpZiAoYm90dG9tUmVmLmN1cnJlbnQpIHtcblx0XHRcdFx0XHRib3R0b21SZWYuY3VycmVudC5zY3JvbGxUb0luZGV4KHtcblx0XHRcdFx0XHRcdGluZGV4OiBhY3RpdmVJbmRleCxcblx0XHRcdFx0XHRcdGFuaW1hdGVkOiBmYWxzZSxcblx0XHRcdFx0XHRcdHZpZXdQb3NpdGlvbjogMC41XG5cdFx0XHRcdFx0fSk7XG5cdFx0XHRcdH1cblx0XHRcdFx0aWYgKHRvcFJlZi5jdXJyZW50KSB7XG5cdFx0XHRcdFx0dG9wUmVmLmN1cnJlbnQuc2Nyb2xsVG9JbmRleCh7XG5cdFx0XHRcdFx0XHRpbmRleDogYWN0aXZlSW5kZXgsXG5cdFx0XHRcdFx0XHRhbmltYXRlZDogZmFsc2UsXG5cdFx0XHRcdFx0XHR2aWV3UG9zaXRpb246IDAuNVxuXHRcdFx0XHRcdH0pO1xuXHRcdFx0XHR9XG5cdFx0XHR9fT5cblx0XHRcdDxWaWV3IHN0eWxlPXtzdHlsZXMuY29udGFpbmVyfT5cblx0XHRcdFx0e2ltYWdlcy5sZW5ndGggPiAwICYmIChcblx0XHRcdFx0XHQ8PlxuXHRcdFx0XHRcdFx0PFN3aXBlQ29udGFpbmVyIGRpc2FibGVTd2lwZT17ZGlzYWJsZVN3aXBlfSBzZXRJc0RyYWdnaW5nPXtzZXRJc0RyYWdnaW5nfSBjbG9zZT17Y2xvc2V9PlxuXHRcdFx0XHRcdFx0XHQ8Rmxhc2hMaXN0XG5cdFx0XHRcdFx0XHRcdFx0aW5pdGlhbFNjcm9sbEluZGV4PXtpbml0aWFsSW5kZXggPCBpbWFnZXMubGVuZ3RoID8gaW5pdGlhbEluZGV4IDogMH1cblx0XHRcdFx0XHRcdFx0XHRlc3RpbWF0ZWRJdGVtU2l6ZT17ZGV2aWNlV2lkdGh9XG5cdFx0XHRcdFx0XHRcdFx0ZGF0YT17aW1hZ2VzfVxuXHRcdFx0XHRcdFx0XHRcdGhvcml6b250YWxcblx0XHRcdFx0XHRcdFx0XHRrZXlFeHRyYWN0b3I9e2tleUV4dHJhY3Rvcn1cblx0XHRcdFx0XHRcdFx0XHRvbk1vbWVudHVtU2Nyb2xsRW5kPXtvbk1vbWVudHVtRW5kfVxuXHRcdFx0XHRcdFx0XHRcdHBhZ2luZ0VuYWJsZWRcblx0XHRcdFx0XHRcdFx0XHRyZWY9e3RvcFJlZn1cblx0XHRcdFx0XHRcdFx0XHRyZW5kZXJJdGVtPXtyZW5kZXJJdGVtfVxuXHRcdFx0XHRcdFx0XHRcdHNjcm9sbEVuYWJsZWQ9eyFpc0RyYWdnaW5nfVxuXHRcdFx0XHRcdFx0XHRcdHNob3dzSG9yaXpvbnRhbFNjcm9sbEluZGljYXRvcj17ZmFsc2V9XG5cdFx0XHRcdFx0XHRcdFx0ZXN0aW1hdGVkTGlzdFNpemU9e21haW5MaXN0U2l6ZX1cblx0XHRcdFx0XHRcdFx0XHRkcmF3RGlzdGFuY2U9e2RldmljZVdpZHRofVxuXHRcdFx0XHRcdFx0XHRcdHJlbW92ZUNsaXBwZWRTdWJ2aWV3cz17dHJ1ZX1cblx0XHRcdFx0XHRcdFx0Lz5cblx0XHRcdFx0XHRcdDwvU3dpcGVDb250YWluZXI+XG5cblx0XHRcdFx0XHRcdHshaGlkZVRodW1icyAmJiAoXG5cdFx0XHRcdFx0XHRcdDxWaWV3IHN0eWxlPXtzdHlsZXMuYm90dG9tRmxhdGxpc3R9PlxuXHRcdFx0XHRcdFx0XHRcdDxGbGFzaExpc3Rcblx0XHRcdFx0XHRcdFx0XHRcdGluaXRpYWxTY3JvbGxJbmRleD17aW5pdGlhbEluZGV4IDwgaW1hZ2VzLmxlbmd0aCA/IGluaXRpYWxJbmRleCA6IDB9XG5cdFx0XHRcdFx0XHRcdFx0XHRlc3RpbWF0ZWRJdGVtU2l6ZT17dGh1bWJTaXplICsgVEhVTUJfU1BBQ0lOR31cblx0XHRcdFx0XHRcdFx0XHRcdGNvbnRlbnRDb250YWluZXJTdHlsZT17c3R5bGVzLnRodW1ibmFpbExpc3RDb250YWluZXJ9XG5cdFx0XHRcdFx0XHRcdFx0XHRkYXRhPXtpbWFnZXN9XG5cdFx0XHRcdFx0XHRcdFx0XHRob3Jpem9udGFsXG5cdFx0XHRcdFx0XHRcdFx0XHRrZXlFeHRyYWN0b3I9e2tleUV4dHJhY3Rvcn1cblx0XHRcdFx0XHRcdFx0XHRcdHBhZ2luZ0VuYWJsZWQ9e2ZhbHNlfVxuXHRcdFx0XHRcdFx0XHRcdFx0cmVmPXtib3R0b21SZWZ9XG5cdFx0XHRcdFx0XHRcdFx0XHRyZW5kZXJJdGVtPXtyZW5kZXJUaHVtYn1cblx0XHRcdFx0XHRcdFx0XHRcdHNob3dzSG9yaXpvbnRhbFNjcm9sbEluZGljYXRvcj17ZmFsc2V9XG5cdFx0XHRcdFx0XHRcdFx0XHRkcmF3RGlzdGFuY2U9e2RldmljZVdpZHRoICogMn1cblx0XHRcdFx0XHRcdFx0XHRcdHJlbW92ZUNsaXBwZWRTdWJ2aWV3cz17dHJ1ZX1cblx0XHRcdFx0XHRcdFx0XHRcdGV4dHJhRGF0YT17YWN0aXZlSW5kZXh9XG5cdFx0XHRcdFx0XHRcdFx0XHRvdmVycmlkZUl0ZW1MYXlvdXQ9eyhsYXlvdXQsIF9pdGVtLCBfaW5kZXgpID0+IHtcblx0XHRcdFx0XHRcdFx0XHRcdFx0bGF5b3V0LnNpemUgPSB0aHVtYlNpemUgKyBUSFVNQl9TUEFDSU5HO1xuXHRcdFx0XHRcdFx0XHRcdFx0fX1cblx0XHRcdFx0XHRcdFx0XHQvPlxuXHRcdFx0XHRcdFx0XHQ8L1ZpZXc+XG5cdFx0XHRcdFx0XHQpfVxuXHRcdFx0XHRcdDwvPlxuXHRcdFx0XHQpfVxuXG5cdFx0XHRcdHsvKiBQYWdlIGluZGljYXRvciAqL31cblx0XHRcdFx0e2ltYWdlcy5sZW5ndGggPiAwICYmIChcblx0XHRcdFx0XHQ8VmlldyBzdHlsZT17c3R5bGVzLnBhZ2VJbmRpY2F0b3J9PlxuXHRcdFx0XHRcdFx0PFRleHQgc3R5bGU9e3N0eWxlcy5wYWdlSW5kaWNhdG9yVGV4dH0+e2Ake2FjdGl2ZUluZGV4ICsgMX0gLyAke2ltYWdlcy5sZW5ndGh9YH08L1RleHQ+XG5cdFx0XHRcdFx0PC9WaWV3PlxuXHRcdFx0XHQpfVxuXG5cdFx0XHRcdHtyZW5kZXJIZWFkZXJDb21wb25lbnQgJiYgaW1hZ2VzLmxlbmd0aCA+IDAgJiYgKFxuXHRcdFx0XHRcdDxWaWV3IHN0eWxlPXtzdHlsZXMuaGVhZGVyfT57cmVuZGVySGVhZGVyQ29tcG9uZW50KGltYWdlc1thY3RpdmVJbmRleF0sIGFjdGl2ZUluZGV4KX08L1ZpZXc+XG5cdFx0XHRcdCl9XG5cblx0XHRcdFx0e3JlbmRlckZvb3RlckNvbXBvbmVudCAmJiBpbWFnZXMubGVuZ3RoID4gMCAmJiAoXG5cdFx0XHRcdFx0PFZpZXcgc3R5bGU9e3N0eWxlcy5mb290ZXJ9PntyZW5kZXJGb290ZXJDb21wb25lbnQoaW1hZ2VzW2FjdGl2ZUluZGV4XSwgYWN0aXZlSW5kZXgpfTwvVmlldz5cblx0XHRcdFx0KX1cblx0XHRcdDwvVmlldz5cblx0XHQ8L01vZGFsPlxuXHQpO1xufTtcblxuY29uc3Qgc3R5bGVzID0gU3R5bGVTaGVldC5jcmVhdGUoe1xuXHRjb250YWluZXI6IHtcblx0XHRhbGlnbkl0ZW1zOiAnY2VudGVyJyxcblx0XHRiYWNrZ3JvdW5kQ29sb3I6ICdibGFjaycsXG5cdFx0ZmxleDogMSxcblx0XHRoZWlnaHQ6IGRldmljZUhlaWdodCxcblx0XHRqdXN0aWZ5Q29udGVudDogJ2NlbnRlcicsXG5cdFx0d2lkdGg6IGRldmljZVdpZHRoXG5cdH0sXG5cdGhlYWRlcjoge1xuXHRcdHBvc2l0aW9uOiAnYWJzb2x1dGUnLFxuXHRcdHRvcDogMCxcblx0XHR3aWR0aDogJzEwMCUnXG5cdH0sXG5cdGZvb3Rlcjoge1xuXHRcdHBvc2l0aW9uOiAnYWJzb2x1dGUnLFxuXHRcdGJvdHRvbTogMCxcblx0XHR3aWR0aDogJzEwMCUnXG5cdH0sXG5cdGFjdGl2ZVRodW1iOiB7XG5cdFx0Ym9yZGVyV2lkdGg6IDNcblx0fSxcblx0dGh1bWI6IHtcblx0XHRib3JkZXJSYWRpdXM6IDEyXG5cdH0sXG5cdHRodW1ibmFpbExpc3RDb250YWluZXI6IHtcblx0XHRwYWRkaW5nVmVydGljYWw6IDIwLFxuXHRcdHBhZGRpbmdIb3Jpem9udGFsOiAxMFxuXHR9LFxuXHRib3R0b21GbGF0bGlzdDoge1xuXHRcdHBvc2l0aW9uOiAnYWJzb2x1dGUnLFxuXHRcdHdpZHRoOiBkZXZpY2VXaWR0aCxcblx0XHRoZWlnaHQ6IERFRkFVTFRfVEhVTUJfU0laRSAqIDEuNSxcblx0XHRib3R0b206IERFRkFVTFRfVEhVTUJfU0laRSxcblx0XHRsZWZ0OiAwXG5cdH0sXG5cdHBhZ2VJbmRpY2F0b3I6IHtcblx0XHRwb3NpdGlvbjogJ2Fic29sdXRlJyxcblx0XHR0b3A6IDE1LFxuXHRcdGFsaWduU2VsZjogJ2NlbnRlcicsXG5cdFx0YmFja2dyb3VuZENvbG9yOiAncmdiYSgwLCAwLCAwLCAwLjUpJyxcblx0XHRwYWRkaW5nOiA4LFxuXHRcdGJvcmRlclJhZGl1czogMTUsXG5cdFx0ekluZGV4OiAyMFxuXHR9LFxuXHRwYWdlSW5kaWNhdG9yVGV4dDoge1xuXHRcdGNvbG9yOiAnd2hpdGUnLFxuXHRcdGZvbnRTaXplOiAxNCxcblx0XHRmb250V2VpZ2h0OiAnYm9sZCdcblx0fVxufSk7XG5cbmV4cG9ydCBkZWZhdWx0IEltYWdlR2FsbGVyeTtcbiJdfQ==