diff --git a/app/components/profile_picture/profile_picture.js b/app/components/profile_picture/profile_picture.js index 869a816c62d..42668125e9d 100644 --- a/app/components/profile_picture/profile_picture.js +++ b/app/components/profile_picture/profile_picture.js @@ -48,7 +48,6 @@ export default class ProfilePicture extends PureComponent { componentWillMount() { const {edit, imageUri, user} = this.props; - this.mounted = true; if (edit && imageUri) { this.setImageURL(imageUri); @@ -61,21 +60,23 @@ export default class ProfilePicture extends PureComponent { if (!this.props.status && this.props.user) { this.props.actions.getStatusForId(this.props.user.id); } + + this.mounted = true; } - componentWillUpdate(nextProps) { + componentWillReceiveProps(nextProps) { if (this.mounted) { - const url = this.state.pictureUrl; + const url = this.props.user ? Client4.getProfilePictureUrl(this.props.user.id, this.props.user.last_picture_update) : null; const nextUrl = nextProps.user ? Client4.getProfilePictureUrl(nextProps.user.id, nextProps.user.last_picture_update) : null; if (url !== nextUrl) { this.setState({ - pictureUrl: nextUrl, + pictureUrl: null, }); if (nextUrl) { // empty function is so that promise unhandled is not triggered in dev mode - ImageCacheManager.cache('', nextUrl, this.setImageUrl).then(emptyFunction).catch(emptyFunction); + ImageCacheManager.cache('', nextUrl, this.setImageURL).then(emptyFunction).catch(emptyFunction); } } @@ -128,7 +129,8 @@ export default class ProfilePicture extends PureComponent { let source = null; if (pictureUrl) { let prefix = ''; - if (Platform.OS === 'android' && !pictureUrl.includes('content://')) { + if (Platform.OS === 'android' && !pictureUrl.startsWith('content://') && + !pictureUrl.startsWith('http://') && !pictureUrl.startsWith('https://')) { prefix = 'file://'; } diff --git a/app/utils/image_cache_manager.js b/app/utils/image_cache_manager.js index 16e3da377ee..baebc4286cd 100644 --- a/app/utils/image_cache_manager.js +++ b/app/utils/image_cache_manager.js @@ -3,7 +3,6 @@ // Based on the work done by https://github.com/wcandillon/react-native-expo-image-cache/ -import base64 from 'base-64'; import RNFetchBlob from 'react-native-fetch-blob'; import {DeviceTypes} from 'app/constants'; @@ -14,6 +13,10 @@ export default class ImageCacheManager { static listeners = {}; static cache = async (filename, uri, listener) => { + if (!listener) { + console.warn('Unable to cache image when no listener is provided'); // eslint-disable-line no-console + } + const {path, exists} = await getCacheFile(filename, uri); if (isDownloading(uri)) { addListener(uri, listener); @@ -21,9 +24,15 @@ export default class ImageCacheManager { listener(path); } else { addListener(uri, listener); + if (uri.startsWith('file://')) { + // In case the uri we are trying to cache is already a local file just notify and return + notifyAll(uri, uri); + return; + } + try { const options = { - session: base64.encode(uri), + session: uri, timeout: 10000, indicator: true, overwrite: true, @@ -48,7 +57,7 @@ export default class ImageCacheManager { export const getCacheFile = async (name, uri) => { const filename = name || uri.substring(uri.lastIndexOf('/'), uri.indexOf('?') === -1 ? uri.length : uri.indexOf('?')); const ext = filename.indexOf('.') === -1 ? '.png' : filename.substring(filename.lastIndexOf('.')); - const path = `${IMAGES_PATH}/${base64.encode(uri)}${ext}`; + const path = `${IMAGES_PATH}/${hashCode(uri)}${ext}`; try { const isDir = await RNFetchBlob.fs.isDir(IMAGES_PATH); @@ -79,3 +88,20 @@ const notifyAll = (uri, path) => { listener(path); }); }; + +// taken from https://stackoverflow.com/questions/7616461/generate-a-hash-from-string-in-javascript-jquery +const hashCode = (str) => { + let hash = 0; + let i; + let chr; + if (str.length === 0) { + return hash; + } + + for (i = 0; i < str.length; i++) { + chr = str.charCodeAt(i); + hash = ((hash << 5) - hash) + chr; + hash |= 0; // Convert to 32bit integer + } + return hash; +}; diff --git a/package.json b/package.json index 76d32a56abc..699d662fc2d 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,6 @@ "dependencies": { "analytics-react-native": "1.2.0", "babel-polyfill": "6.26.0", - "base-64": "0.1.0", "commonmark": "github:mattermost/commonmark.js#21742b9d51070b6abba82d88590a0c51ee552a47", "commonmark-react-renderer": "mattermost/commonmark-react-renderer#86fa63f898802953842526c2030f3b63c5d1ae7a", "deep-equal": "1.0.1",