rs-react-native-image-gallery
Version:
React Native Image Gallery with Thumbnails
214 lines (210 loc) • 35.8 kB
JavaScript
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==