Youtube music and video downloader

App.jsx 3.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. import React, { Component, PropTypes } from 'react';
  2. import { Meteor } from 'meteor/meteor';
  3. import { Tracker } from 'meteor/tracker';
  4. import { createContainer } from 'meteor/react-meteor-data';
  5. import { Converted } from '../api/links';
  6. import Links from './Links';
  7. import { YouTubeSearch, YouTubeVideoInfo } from './YouTubeAPI';
  8. import Video from './Video';
  9. import Input from "./Input";
  10. import Results from "./Results";
  11. import OptionsAll from "./OptionsAll";
  12. class App extends Component {
  13. constructor(props) {
  14. super(props);
  15. this.state = { result: [], links: [], value: '' };
  16. this.options = [
  17. { type: 'MP3', handler: this.downloadAudio.bind(this) },
  18. { type: 'MP4', handler: this.downloadVideo.bind(this) },
  19. ];
  20. this.optionsAll = [
  21. { type: 'MP3', handler: this.downloadAllAudio.bind(this) },
  22. { type: 'MP4', handler: this.downloadAllVideo.bind(this) },
  23. ];
  24. }
  25. render() {
  26. return (
  27. <div className="container">
  28. <h1 className="logo">SoundWave</h1>
  29. <div className="box-container">
  30. <header>
  31. <Input value={this.state.value} change={this.inputChange.bind(this)} />
  32. <Results results={this.state.result} select={this.selectResult.bind(this)} />
  33. </header>
  34. <Links links={this.state.links} remove={this.removeLink.bind(this)} handlers={this.options}/>
  35. <OptionsAll count={this.state.links.length} handlers={this.optionsAll}
  36. links={this.state.links} converted={this.props.converted} />
  37. </div>
  38. </div>
  39. );
  40. }
  41. downloadAudio(video) {
  42. console.log('Requesting mp3 for ' + video.id);
  43. }
  44. downloadVideo(video) {
  45. console.log('Requesting mp4 for ' + video.id);
  46. }
  47. downloadAllAudio() {
  48. console.log('Requesting mp3 for all');
  49. }
  50. downloadAllVideo() {
  51. console.log('Requesting mp4 for all');
  52. }
  53. inputChange(text) {
  54. this.setState({ value: text }, this.search);
  55. }
  56. removeLink(link) {
  57. if (_.some(this.state.links, e => e.id === link.id))
  58. this.setState({ links: _.reject(this.state.links, e => e.id === link.id) });
  59. }
  60. selectResult(video) {
  61. if (_.every(this.state.links, e => e.id !== video.id)) {
  62. if (_.some(this.props.converted, e => e.id === video.id)) {
  63. video.converted = _.find(this.props.converted, e => e.id === video.id)._id;
  64. } else
  65. Meteor.call('links.add', {video, type: 'audio'}, (err, res) => {
  66. if (err)
  67. console.error(err);
  68. else
  69. video.converted = _.find(this.props.converted, e => e.id === video.id)._id;
  70. });
  71. this.setState({links: [...this.state.links, video]});
  72. }
  73. this.setState({ value: '', result: [] });
  74. }
  75. search() {
  76. if (!this.state.value) {
  77. this.setState({ result: [] });
  78. } else {
  79. YouTubeSearch(this.state.value)
  80. .then(e => e.items.map(e => new Video(e)))
  81. .then(e => { this.setState({ result: e }); return e; })
  82. .then(e => e.forEach(i => YouTubeVideoInfo(i.id)
  83. .then(r => i.update(r.items[0].statistics, r.items[0].contentDetails.duration))
  84. .then(() => this.setState({ result: e }))
  85. ));
  86. }
  87. }
  88. }
  89. App.propTypes = {
  90. converted: PropTypes.array.isRequired,
  91. };
  92. export default createContainer(() => {
  93. Meteor.subscribe('links');
  94. return {
  95. converted: Converted.find({}).fetch(),
  96. };
  97. }, App)