Skip to content
This repository has been archived by the owner on Mar 12, 2020. It is now read-only.

Dynamically sized image fetching. #54

Merged
merged 4 commits into from
May 13, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 0 additions & 6 deletions Pod/Classes/Core/RCTScrollView+EnclosingScrollView.m
Original file line number Diff line number Diff line change
Expand Up @@ -51,12 +51,6 @@ - (instancetype)initWithType:(RCTScrollEventType)type
return self;
}

// TODO: For now, as I have no clue what that needs yet
- (BOOL)canCoalesce
{
return NO;
}

- (NSDictionary *)body
{
CGPoint originOffset = [__scrollView convertPoint:CGPointZero toView:_enclosingScrollView];
Expand Down
15 changes: 9 additions & 6 deletions lib/components/artist/articles/article.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,16 @@ import ImageView from '../../opaque_image_view';
class Article extends React.Component {
render() {
const article = this.props.article
// TODO The outer wrapping view is currently only there because setting `marginRight: 20` on the Article from the
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah this is a weird thing - I find that setting the style of an entire component from the parent gives mixed results. I should read up on how flexbox reconciles self-styling and styling-by-parent.

// Articles component isn’t working.
return (
<View style={{ width: 300 }}>
<ImageView style={{ height: 175, marginRight: 20 }}
aspectRatio={1.7}
imageURL={article.thumbnail_image.cropped.url} />
<Text style={styles.serifText} numberOfLines={5}>{article.title}</Text>
<Text style={styles.sansSerifText}>{article.author.name.toUpperCase()}</Text>
<View style={{ width: 320 }}>
<View style={{ width: 300 }}>
<ImageView style={{ width: 300, height: 175 }}
imageURL={article.thumbnail_image.cropped.url} />
<Text style={styles.serifText} numberOfLines={5}>{article.title}</Text>
<Text style={styles.sansSerifText}>{article.author.name.toUpperCase()}</Text>
</View>
</View>
);
}
Expand Down
8 changes: 6 additions & 2 deletions lib/components/artist/articles/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,11 @@ class Articles extends React.Component {
render() {
const articles = this.props.articles;
return (
<View style={styles.container}>
<View>
<Separator/>
<SerifText style={styles.heading}>Featured Articles</SerifText>
<ScrollView horizontal={true} style={{ overflow: 'visible', marginBottom:40 }}>
{ articles.map(article => <Article key={article.id} article={article} />) }
{ articles.map(article => <Article key={article.id} article={article} style={styles.article} />) }
</ScrollView>
</View>
);
Expand All @@ -30,6 +30,10 @@ const styles = StyleSheet.create({
heading: {
marginBottom: 20,
fontSize: 20,
},
article: {
// TODO: Why doesn’t this work? Currently working around it by making the Article internal view 20pt wider.
// marginRight: 20,
}
});

Expand Down
4 changes: 2 additions & 2 deletions lib/components/artworks/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ const artworksQuery = (artistID, page) => {
title
sale_message
image {
url
url(version: "large")
aspect_ratio
}
artist {
Expand All @@ -209,7 +209,7 @@ export default Relay.createContainer(Artworks, {
title
sale_message
image {
url
url(version: "large")
aspect_ratio
}
artist {
Expand Down
46 changes: 44 additions & 2 deletions lib/components/opaque_image_view.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,63 @@
'use strict';

import React from 'react-native';
const { PixelRatio } = React;

const GeminiHost = 'd7hftxdivxxvm.cloudfront.net';
const ImageQuality = 85;

export default class OpaqueImageView extends React.Component {
constructor(props) {
super(props);
this.state = {};
}

// Unless `aspectRatio` was not specified at all, default the ration to 1 to prevent illegal layout calculations.
aspectRatio() {
const ratio = this.props.aspectRatio;
return ratio === undefined ? undefined : (ratio || 1);
}

imageURL() {
if (this.aspectRatio()) {
return `https://${GeminiHost}/?resize_to=fit&width=${this.state.width}&height=${this.state.height}&quality=${ImageQuality}&src=${encodeURIComponent(this.props.imageURL)}`;
} else {
return this.props.imageURL;
}
}

onLayout(event) {
const { width, height } = event.nativeEvent.layout;
this.setState({
width: width * PixelRatio.get(),
height: height * PixelRatio.get(),
});
}

render() {
return <NativeOpaqueImageView {...this.props} />;
const isLaidOut = !!(this.state.width && this.state.height);
const props = Object.assign({}, this.props, {
aspectRatio: this.aspectRatio(),
imageURL: isLaidOut ? this.imageURL() : null,
onLayout: isLaidOut ? null : this.onLayout.bind(this),
});
return <NativeOpaqueImageView {...props} />;
}
}

OpaqueImageView.propTypes = {
/**
* The URL from where to fetch the image.
*/
imageURL: React.PropTypes.string.isRequired,
imageURL: React.PropTypes.string,

/**
* An aspect ratio created with: width / height.
*
* When specified:
* - The view will be sized in such a way that it maintains the aspect ratio of the image.
* - The imageURL will be modified so that it resizes the image to the exact size at which the view has been laid out,
* thus never fetching more data than absolutely necessary.
*/
aspectRatio: React.PropTypes.number,

Expand Down