-
Notifications
You must be signed in to change notification settings - Fork 483
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Game Lab: S3-backed animation library #10685
Changes from 6 commits
496d850
38f54b1
fef2a8b
e34cc86
9faa59a
330e458
7510134
1d4768c
6b6ba94
4c46c48
57d7551
2c84d26
d37e904
c0fc1fd
e9c9d71
e2582bb
b9b2d77
0967a97
d2711b4
349af67
145be7f
9042f84
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,14 +1,17 @@ | ||
/** Body of the animation picker dialog */ | ||
import React from 'react'; | ||
import Radium from 'radium'; | ||
import Immutable from 'immutable'; | ||
import color from '../../color'; | ||
import gamelabMsg from '../locale'; | ||
import animationLibrary from '../animationLibrary'; | ||
import animationLibrary from '../animationLibrary.json'; | ||
import ScrollableList from '../AnimationTab/ScrollableList.jsx'; | ||
import styles from './styles'; | ||
import AnimationPickerListItem from './AnimationPickerListItem.jsx'; | ||
import AnimationPickerSearchBar from './AnimationPickerSearchBar.jsx'; | ||
|
||
const MAX_SEARCH_RESULTS = 18; | ||
|
||
const AnimationPickerBody = React.createClass({ | ||
propTypes: { | ||
is13Plus: React.PropTypes.bool, | ||
|
@@ -17,7 +20,18 @@ const AnimationPickerBody = React.createClass({ | |
onUploadClick: React.PropTypes.func.isRequired | ||
}, | ||
|
||
getInitialState() { | ||
return { | ||
searchQuery: '' | ||
}; | ||
}, | ||
|
||
onSearchQueryChange(evt) { | ||
this.setState({searchQuery: evt.target.value}); | ||
}, | ||
|
||
render() { | ||
var pageOfResults = searchAnimations(this.state.searchQuery); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why do we do this in the render function and not There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In this case, we are actually modifying the component's local There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. coolio thanks for explaining! There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Checking my understanding — There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes. It was optimistic naming on my part, since I want pagination in the future and could picture |
||
return ( | ||
<div> | ||
<h1 style={styles.title}> | ||
|
@@ -28,7 +42,10 @@ const AnimationPickerBody = React.createClass({ | |
{gamelabMsg.animationPicker_warning()} | ||
</WarningLabel> | ||
} | ||
<AnimationPickerSearchBar /> | ||
<AnimationPickerSearchBar | ||
value={this.state.searchQuery} | ||
onChange={this.onSearchQueryChange} | ||
/> | ||
<ScrollableList style={{maxHeight: 400}}> {/* TODO: Is this maxHeight appropriate? */} | ||
<AnimationPickerListItem | ||
label={gamelabMsg.animationPicker_drawYourOwn()} | ||
|
@@ -40,7 +57,7 @@ const AnimationPickerBody = React.createClass({ | |
icon="upload" | ||
onClick={this.props.onUploadClick} | ||
/> | ||
{animationLibrary.map(animationProps => | ||
{pageOfResults.map(animationProps => | ||
<AnimationPickerListItem | ||
key={animationProps.sourceUrl} | ||
label={`${animationProps.name} (${animationProps.frameCount})`} | ||
|
@@ -63,3 +80,33 @@ export const WarningLabel = ({children}) => ( | |
WarningLabel.propTypes = { | ||
children: React.PropTypes.node | ||
}; | ||
|
||
/** | ||
* Given a search query, generate a results list of animationProps objects that | ||
* can be displayed and used to add an animation to the project. | ||
* @param {string} searchQuery - text entered by the user to find an animation | ||
*/ | ||
function searchAnimations(searchQuery) { | ||
// Make sure to generate the search regex in advance, only once. | ||
// Search is case-insensitive | ||
// Match any word boundary or underscore followed by the search query. | ||
// Example: searchQuery "bar" | ||
// Will match: "barbell", "foo-bar", "foo_bar" or "foo bar" | ||
// Will not match: "foobar", "ubar" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This will be interesting to test with the animation names we will use to see if we need a different type of search. It'll also be interesting to test if kids have ideas of what to search or if we'll need to add promps or suggestions. (I just read the spec said 1,000 - 10,000 images which is a ton) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The 1000-10000 was my own ballpark, I'm not sure what the content team has in mind. I think kids will know what to search for but there is a discoverability concern - I was actually wondering how we should special-case the results when there is no search query. Right now we always display the first n animations (alphabetical) but I'm wondering if we should instead pick a random set, or highlight the newest content. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this is what Caley was getting at but just in case not — it would be awesome to somehow save out failed searches (once user backtracks when no results?) to see what graphics students wish we had (& potential mis-searches). I know of at least one coding website that has done that as a way to source graphic additions and kids loved it (really makes it feel like the website offers something for everything). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Wow! That's an awesome idea, but maybe another pull request. We're doing similar logging when we strip unexpected markup from applab design mode HTML to see what we might be mis-categorizing. I'll take a look at this. |
||
const searchRegExp = new RegExp('(?:\\b|_)' + searchQuery, 'i'); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. TODO: I suppose I should escape |
||
|
||
// Generate the set of all results associated with all matched aliases | ||
const resultSet = Object.keys(animationLibrary.aliases) | ||
.filter(alias => searchRegExp.test(alias)) | ||
.reduce((resultSet, nextAlias) => { | ||
return resultSet.union(animationLibrary.aliases[nextAlias]); | ||
}, Immutable.Set()); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm trying out Immutable.JS |
||
|
||
// Finally alphabetize the results (for stability), take only the first | ||
// MAX_SEARCH_RESULTS so we don't load too many images at once, and return | ||
// the associated metadata for each result, along with | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. unfinished comment |
||
return resultSet | ||
.sort() | ||
.slice(0, MAX_SEARCH_RESULTS) | ||
.map(result => animationLibrary.metadata[result]); | ||
} |
This file was deleted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We are limiting the number of results to a query to avoid triggering a ton of asset loading while-you-type. Long-term I'd like to add pagination to search results so you can keep stepping through animations if you'd like.