pig-media-server 2 → 100

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) hide show
  1. checksums.yaml +4 -4
  2. data/.babelrc +3 -0
  3. data/Gemfile +1 -0
  4. data/front/application.js +71 -0
  5. data/front/components/custom.js +35 -0
  6. data/front/components/head.js +38 -0
  7. data/front/components/index.js +23 -0
  8. data/front/components/item.js +63 -0
  9. data/front/components/latest.js +32 -0
  10. data/front/components/new_flag.js +29 -0
  11. data/front/components/no_match.js +10 -0
  12. data/front/components/pager.js +38 -0
  13. data/{javascripts → front}/components/player.js +7 -11
  14. data/{javascripts → front}/components/query_list.js +6 -23
  15. data/front/components/recommend.js +41 -0
  16. data/front/components/search.js +87 -0
  17. data/front/components/search_box.js +56 -0
  18. data/{javascripts → front}/components/watch.js +8 -5
  19. data/front/controller.js +22 -0
  20. data/{javascripts/event_dispatcher.js → front/models/base.js} +1 -5
  21. data/front/models/config.js +12 -0
  22. data/front/models/custom.js +41 -0
  23. data/front/models/custom_list.js +12 -0
  24. data/front/models/latest.js +60 -0
  25. data/front/models/list.js +76 -0
  26. data/front/models/playing.js +11 -0
  27. data/front/models/recent.js +34 -0
  28. data/front/models/recommend.js +13 -0
  29. data/front/models/session.js +16 -0
  30. data/lib/pig-media-server/api.rb +35 -3
  31. data/lib/pig-media-server/backup.rb +3 -7
  32. data/lib/pig-media-server/model/comic.rb +1 -1
  33. data/lib/pig-media-server/model/data.rb +85 -81
  34. data/lib/pig-media-server/model/data_use_rdb.rb +124 -0
  35. data/lib/pig-media-server/version.rb +1 -1
  36. data/lib/pig-media-server/views/bundle.js +48 -13
  37. data/package.json +13 -18
  38. data/webpack.build.js +25 -0
  39. data/webpack.config.js +30 -0
  40. metadata +34 -19
  41. data/gulpfile.js +0 -33
  42. data/javascripts/application.js +0 -117
  43. data/javascripts/components/head.js +0 -106
  44. data/javascripts/components/list.js +0 -104
  45. data/javascripts/components/new_flag.js +0 -23
  46. data/javascripts/components/sort.js +0 -64
  47. data/javascripts/controller.js +0 -62
  48. data/javascripts/custom_list.js +0 -14
  49. data/javascripts/recent.js +0 -34
  50. data/javascripts/utils.js +0 -22
  51. data/javascripts/video.js +0 -10
  52. /data/{javascripts → front}/chromecast.js +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 03172c241d9a720259504c431a3f24d3226dae28
4
- data.tar.gz: cbd95152cf18824e2898e32562d61942d1ac525a
3
+ metadata.gz: 1450f2afe845735323e207d6ca9c4aee910c8e86
4
+ data.tar.gz: 742fd37ce519d014b1cedd7d0b6a23a80fc43c21
5
5
  SHA512:
6
- metadata.gz: 3e086f8d14b480451cd612f665b3971862601eaae32c43bf7771337befc492653b68fd1d132873e10a6408896519956145bb331f76c0c0ef8273605cb0e7cf9a
7
- data.tar.gz: a95b3789b246eff2c3a0937def42c8983793b36696eec54229d52c2cc6b37d3687b38fccbf1d776e758b4e121fa4e851b94b338698d85d6defac8723b7a021dd
6
+ metadata.gz: e722dfe919ff6bbcc51c6b6ca5f4b428e92a4ccf000ed6c052a57772eebcacba43df284c20c26f5e0374b9be3130b9fe9d65531d5b2757cf1c1d81f4c27a08aa
7
+ data.tar.gz: 75f4766423d66479199963b34d50e15ff3ed9757636c24b93da160c3dec49c6dbe65943d1860a619d0579df69b8af00547e24eb58d2126b3ac0764eb2c9a21e2
data/.babelrc ADDED
@@ -0,0 +1,3 @@
1
+ {
2
+ "presets": ["es2016-node5", "react", "es2015"]
3
+ }
data/Gemfile CHANGED
@@ -2,3 +2,4 @@ source 'https://rubygems.org'
2
2
 
3
3
  # Specify your gem's dependencies in pig-media-server.gemspec
4
4
  gemspec
5
+ gem 'rake'
@@ -0,0 +1,71 @@
1
+ import React from 'react';
2
+ import ReactDOM from 'react-dom';
3
+ import { Router, Route, Link, browserHistory, IndexRoute } from 'react-router'
4
+
5
+ require('./chromecast.js');
6
+
7
+ import NoMatch from './components/no_match'
8
+ import Index from './components/index'
9
+ import Player from './components/player'
10
+ import SearchBox from './components/search_box'
11
+ import Head from './components/head'
12
+ import Latest from './components/latest'
13
+ import Recommend from './components/recommend'
14
+ import Custom from './components/custom'
15
+
16
+ import Config from './models/config'
17
+ import Session from './models/session'
18
+ import Recent from './models/recent'
19
+ import Playing from './models/playing'
20
+ import CustomList from './models/custom_list'
21
+
22
+ window.config = new Config();
23
+ window.session = new Session();
24
+ window.recent = new Recent();
25
+ window.custom_list = new CustomList();
26
+
27
+ window.playing = new Playing();
28
+
29
+ config.load();
30
+ session.load();
31
+ recent.load();
32
+ custom_list.load();
33
+
34
+ class Application extends React.Component{
35
+ constructor(props){
36
+ super(props);
37
+ this.state = {}
38
+ config.addEventListener('loaded', ()=>{ this.reload() });
39
+ session.addEventListener('loaded', ()=>{ this.reload() });
40
+ recent.addEventListener('loaded', ()=>{ this.reload() });
41
+ playing.addEventListener('updated', ()=>{ this.reload() });
42
+
43
+ }
44
+ reload(){
45
+ this.setState(this.state);
46
+ }
47
+ render(){
48
+ return <div>
49
+ <Player/>
50
+ <div id='all'>
51
+ <Head />
52
+ <SearchBox/>
53
+ {this.props.children}
54
+ </div>
55
+ </div>
56
+ }
57
+ }
58
+
59
+ var route = <Router history={browserHistory}>
60
+ <Route path="/" name='app' component={Application}>
61
+ <IndexRoute component={Index} />
62
+ <Route path='/recommend' component={Recommend} />
63
+ <Route path='/custom' component={Custom} />
64
+ <Route path='/latest' component={Latest} />
65
+ </Route>
66
+ </Router>
67
+
68
+ ReactDOM.render(route, document.querySelector("#application"));
69
+
70
+
71
+
@@ -0,0 +1,35 @@
1
+ import React from 'react';
2
+ import CustomList from '../models/custom';
3
+
4
+ import Item from './item'
5
+
6
+ var custom = new CustomList();
7
+
8
+ export default class Custom extends React.Component {
9
+ constructor(props){
10
+ super(props);
11
+ custom.addEventListener('loaded', ()=>{this.reload()});
12
+ this.mounted = true;
13
+ }
14
+ reload(){ if(this.mounted){this.setState({});} }
15
+ componentDidMount(){
16
+ this.mounted = true;
17
+ $('title').text("Pig Media Server");
18
+ custom.load(this.props.location.query.name);
19
+ window.list = custom;
20
+ }
21
+ componentDidUpdate(prevProps){
22
+ if(this.props.location.query != prevProps.location.query){
23
+ custom.load(this.props.location.query.name);
24
+ }
25
+ }
26
+ componentWillUnmount(){ this.mounted = false; }
27
+ render(){
28
+ var items = custom.list.map((e)=>{
29
+ return <Item key={e.key} item={e} />
30
+ });
31
+ return <div>
32
+ <p>{items}</p>
33
+ </div>
34
+ }
35
+ }
@@ -0,0 +1,38 @@
1
+ import React from 'react';
2
+ import {Link} from 'react-router'
3
+
4
+ class LoginAs extends React.Component {
5
+ render(){
6
+ return <span>Login as {this.props.user_id}</span>
7
+ }
8
+ }
9
+
10
+ class LoginLink extends React.Component {
11
+ render(){
12
+ return <a href='/sessions'>Login</a>
13
+ }
14
+ }
15
+
16
+ class Session extends React.Component {
17
+ render(){
18
+ return <div>
19
+ {session.data.user_id ?
20
+ <LoginAs user_id={session.data.user_id} /> :
21
+ <LoginLink />
22
+ }
23
+ </div>
24
+ }
25
+ }
26
+
27
+ export default class Head extends React.Component {
28
+ render(){
29
+ return <div>
30
+ <Session/>
31
+ <h2>
32
+ <Link to='/'>{config.data.page_title}</Link>
33
+ </h2>
34
+ </div>
35
+ }
36
+ }
37
+
38
+
@@ -0,0 +1,23 @@
1
+ import React from 'react';
2
+ import Search from './search'
3
+
4
+ import QueryList from './query_list'
5
+
6
+ class Top extends React.Component {
7
+ render(){
8
+ return <div>
9
+ <QueryList query={this.props.query}/>
10
+ </div>
11
+ }
12
+ }
13
+
14
+ export default class Index extends React.Component {
15
+ is_search(){
16
+ return !!this.props.location.query.query;
17
+ }
18
+ render(){
19
+ return <div>
20
+ {this.is_search() ? <Search location={this.props.location}/> : <Top query={this.props.location.query}/> }
21
+ </div>
22
+ }
23
+ }
@@ -0,0 +1,63 @@
1
+ import React from 'react';
2
+
3
+ import NewFlag from './new_flag'
4
+ import {Watch, ChromeCast} from './watch'
5
+
6
+ class CustomLinks extends React.Component{
7
+ render(){
8
+ return <span dangerouslySetInnerHTML={{__html: this.props.item.custom_links}}/>
9
+ }
10
+ }
11
+
12
+
13
+ export default class Item extends React.Component {
14
+ mtime(){
15
+ return this.props.item.mtime;
16
+ }
17
+
18
+ size_pretty(size){
19
+ var size = parseFloat(String(size));
20
+ var result = size;
21
+ if(size < 1024){
22
+ result = `${size} Bytes`
23
+ } else if(size < 1024*1024){
24
+ result = `${this.round(size / 1024)} KB`
25
+ } else if(size < 1024*1024*1024){
26
+ result = `${this.round(size / (1024*1024))} MB`
27
+ } else if(size < 1024*1024*1024*1024){
28
+ result = `${this.round(size / (1024*1024*1024))} GB`
29
+ }
30
+ return result
31
+ }
32
+
33
+ round(i){
34
+ i = i*10;
35
+ return Math.round(i)/10
36
+ }
37
+
38
+
39
+
40
+ render(){
41
+ var item = this.props.item;
42
+ var meta = `/meta/${this.props.item.key}`;
43
+ var sub = `/sub/${this.props.item.key}`;
44
+ return <span className='main_span'>
45
+ <NewFlag
46
+ item={this.props.item}
47
+ />
48
+ <a href={item.url} className='main_link'>{item.name}</a>&nbsp;
49
+
50
+ <Watch
51
+ item={this.props.item}
52
+ />
53
+ <ChromeCast
54
+ item={this.props.item}
55
+ />
56
+ <span className='mtime'>{this.mtime()}</span>&nbsp;
57
+ <span className='size'>{this.size_pretty(item.size)}</span>&nbsp;
58
+ <a className='meta' href={meta}>Meta</a>
59
+ <a className='meta' href={sub}>Sub</a>
60
+ <CustomLinks item={this.props.item} />
61
+ </span>
62
+ }
63
+ }
@@ -0,0 +1,32 @@
1
+ import React from 'react';
2
+ import LatestList from '../models/latest';
3
+
4
+ import Item from './item'
5
+ import Pager from './pager'
6
+
7
+ var latest = new LatestList();
8
+
9
+ export default class Recommend extends React.Component {
10
+ constructor(props){
11
+ super(props);
12
+ latest.addEventListener('loaded', ()=>{this.reload()});
13
+ this.mounted = true;
14
+ }
15
+ reload(){ if(this.mounted){this.setState({});} }
16
+ componentDidMount(){
17
+ this.mounted = true;
18
+ $('title').text("Latest - Pig Media Server");
19
+ latest.load(this.props.location.query.page);
20
+ window.list = latest;
21
+ }
22
+ componentWillUnmount(){ this.mounted = false; }
23
+ render(){
24
+ var items = latest.list.map((e)=>{
25
+ return <Item key={e.key} item={e} />
26
+ });
27
+ return <div>
28
+ <p>{items}</p>
29
+ <Pager location={this.props.location} list={latest}/>
30
+ </div>
31
+ }
32
+ }
@@ -0,0 +1,29 @@
1
+ import React from 'react';
2
+
3
+ export default class NewFlag extends React.Component {
4
+ constructor(props){
5
+ super(props);
6
+ recent.addEventListener('loaded', ()=>{ this.reload()});
7
+ }
8
+ reload(){
9
+ this.setState({});
10
+ }
11
+ ext(str){ return String(str).split('.').pop().toLowerCase(); }
12
+ is_new(){
13
+ var ext = this.ext(this.props.item.name);
14
+ if(ext == 'mp4' || ext == 'flv'){
15
+ var result = true;
16
+ jQuery.each(recent.data, (k,v)=>{
17
+ if(k == `movie/${this.props.item.key}`){ result = false }
18
+ });
19
+ return result
20
+ } else {
21
+ return false;
22
+ }
23
+ }
24
+
25
+ render(){
26
+ var is_new = this.is_new();
27
+ return <span>{is_new ? <span className='new_flag' style={{color:'lime', "fontWeight":'bold'}}>New</span> : null }</span>
28
+ }
29
+ }
@@ -0,0 +1,10 @@
1
+ import React from 'react';
2
+
3
+ export default class NoMatch extends React.Component {
4
+ render(){
5
+ return <div>
6
+ <h1>404 Not Found</h1>
7
+ <p>But I return 200...</p>
8
+ </div>
9
+ }
10
+ }
@@ -0,0 +1,38 @@
1
+ import React from 'react'
2
+ import jQuery from 'jquery'
3
+ import {browserHistory} from 'react-router'
4
+
5
+ export default class Pager extends React.Component {
6
+ constructor(props){
7
+ super(props);
8
+ this.page = 1;
9
+ var page = this.props.location.query.page;
10
+ if(page){ this.page = parseInt(page)}
11
+ this.bind();
12
+ }
13
+
14
+ bind(){
15
+ //this.click();
16
+ }
17
+ prev(){
18
+ var params = this.props.location.query;
19
+ var page = this.props.location.query.page;
20
+ if(page){ this.page = parseInt(page)}
21
+ page = page - 1;
22
+ if(page < 1){page = 1}
23
+ params.page = page;
24
+ browserHistory.push("/?"+jQuery.param(params));
25
+ }
26
+ click(){
27
+ this.page ++;
28
+ var params = this.props.location.query;
29
+ params.page = this.page;
30
+ this.props.list.paginate(this.page);
31
+ history.pushState('', '', "/?"+jQuery.param(params));
32
+ }
33
+
34
+ render(){ return <span>
35
+ {(this.page > 1) ? <a href='javascript:void(0)' onClick={()=> this.prev()}>Prev</a> : null } <a href='javascript:void(0)' onClick={()=> this.click()}>Next</a>
36
+ </span>
37
+ }
38
+ }
@@ -1,12 +1,14 @@
1
- class Player extends React.Component {
1
+ import React from 'react';
2
+
3
+ export default class Player extends React.Component {
2
4
  constructor(props){
3
5
  super(props);
4
6
  this.current_url = '';
5
7
  }
6
- close(){ this.props.state.models.video.set(null); }
8
+ close(){ playing.set(null); }
7
9
  dom(){ return this.refs.video; }
8
10
 
9
- video(){ return this.props.state.models.video.item; }
11
+ video(){ return playing.item; }
10
12
 
11
13
  video_url(){
12
14
  var url = null;
@@ -28,10 +30,7 @@ class Player extends React.Component {
28
30
  }
29
31
 
30
32
  next(){
31
- var next = false;
32
- var result;
33
- var index = $.map(this.props.state.items, (e,i)=>{return e.key}).indexOf(this.props.state.models.video.item.key);
34
- this.props.state.models.video.set(this.props.state.items[index-1]);
33
+ if(!!list){ list.next() };
35
34
  }
36
35
 
37
36
  play(prev){
@@ -40,8 +39,7 @@ class Player extends React.Component {
40
39
  node.addEventListener('canplay', (e)=>{
41
40
  var target = e.target;
42
41
  target.play();
43
- this.props.state.models.recent.use(`movie/${this.video().key}`);
44
-
42
+ recent.use(`movie/${this.video().key}`);
45
43
  });
46
44
  node.addEventListener('ended', (e)=>{ this.next(); });
47
45
  node.load();
@@ -167,5 +165,3 @@ class Player extends React.Component {
167
165
  </div>
168
166
  }
169
167
  }
170
-
171
- window.Player = Player;
@@ -1,10 +1,9 @@
1
+ import React from 'react'
2
+ import {Link} from 'react-router'
3
+
1
4
  class Item extends React.Component {
2
5
  url(){ return `/?query=${encodeURIComponent(this.props.query)}` }
3
6
 
4
- click(){
5
- this.props.state.open(this.url());
6
- }
7
-
8
7
  delete_query(){
9
8
  if(confirm('Really?')){
10
9
  $.post("/api/r/delete_query_list", {query: this.props.query}).done((data)=>{
@@ -14,9 +13,7 @@ class Item extends React.Component {
14
13
  }
15
14
  render(){
16
15
  return <span className='main_span'>
17
- <a href='javascript:void(0)' onClick={()=> this.click()}>
18
- {this.props.query}
19
- </a>
16
+ <Link to={this.url()}> {this.props.query} </Link>
20
17
  <a href='javascript:void(0)' className='delete' onClick={()=> this.delete_query()}>
21
18
  Delete
22
19
  </a>
@@ -24,12 +21,11 @@ class Item extends React.Component {
24
21
  }
25
22
  }
26
23
 
27
- class QueryList extends React.Component {
24
+ export default class QueryList extends React.Component {
28
25
  constructor(props){
29
26
  super(props);
30
27
  this.state = {};
31
28
  this.state.list = [];
32
- this.controller = new Controller()
33
29
  }
34
30
 
35
31
  update_list(){
@@ -43,26 +39,13 @@ class QueryList extends React.Component {
43
39
  this.update_list();
44
40
  }
45
41
 
46
- show(){
47
- if(location.pathname == '/'){
48
- if(!this.controller.query()){
49
- return true;
50
- } else {
51
- return false;
52
- }
53
- } else {
54
- return false
55
- }
56
- }
57
-
58
42
  render(){
59
43
  var items = $.map(this.state.list, (query)=>{
60
44
  return <Item key={query} query={query} state={this.props.state} update_list={()=> this.update_list()}/>
61
45
  });
62
46
  return <div>
63
- {this.show() ? items : null}
47
+ {items}
64
48
  </div>
65
49
  }
66
50
  }
67
51
 
68
- window.QueryList = QueryList;
@@ -0,0 +1,41 @@
1
+ import React from 'react';
2
+ import RecommendList from '../models/recommend';
3
+
4
+ import Item from './item'
5
+
6
+ var recommend = new RecommendList();
7
+
8
+ export default class Recommend extends React.Component {
9
+ constructor(props){
10
+ super(props);
11
+ recommend.addEventListener('loaded', ()=>{this.reload()});
12
+ this.mounted = true;
13
+ }
14
+ reload(){ if(this.mounted){this.setState({});} }
15
+ componentDidMount(){
16
+ this.mounted = true;
17
+ $('title').text("Recommned - Pig Media Server");
18
+ recommend.load(this.props.location.query.name);
19
+ window.list = recommend;
20
+ }
21
+ componentWillUnmount(){ this.mounted = false; }
22
+ render(){
23
+ var items = recommend.list.map((e)=>{
24
+ return <Item key={e.key} item={e} />
25
+ });
26
+ return <div>
27
+ <p>{items}</p>
28
+ </div>
29
+ }
30
+
31
+ next(){
32
+ var index = this.list.map((e,i)=>{return e.key}).indexOf(playing.item.key);
33
+ var item = null
34
+ while(index > -1){
35
+ index = index - 1;
36
+ item = this.list[index];
37
+ if(item.type == 'video'){break}
38
+ }
39
+ if(item){ playing.set(item); }
40
+ }
41
+ }
@@ -0,0 +1,87 @@
1
+ import React from 'react'
2
+ import {Link} from 'react-router'
3
+ import jQuery from 'jquery'
4
+
5
+ import SearchList from '../models/list'
6
+
7
+ import Item from './item'
8
+ import Pager from './pager'
9
+
10
+ var list = new SearchList();
11
+
12
+ class QuerySave extends React.Component{
13
+ constructor(props){
14
+ super(props);
15
+ }
16
+
17
+ click(){
18
+ jQuery.post("/api/r/query_list", {query: this.props.query})
19
+ }
20
+ render(){
21
+ return <span>
22
+ <a href='javascript:void(0)' onClick={()=> this.click()}>Save Query</a>
23
+ </span>
24
+ }
25
+ }
26
+
27
+ class Sort extends React.Component{
28
+ can_change_order(){ return !!this.props.location.query.sort }
29
+ change_order(order){
30
+ var params = this.props.location.query;
31
+ params.order = order;
32
+ history.pushState('','',"/?"+jQuery.param(params));
33
+ list.search(params);
34
+ }
35
+ render(){
36
+ return <p>
37
+ <Link to={`/?query=${this.props.query}&sort=date`}>Sort By Date</Link>
38
+ <Link to={`/?query=${this.props.query}&sort=name`}>Sort By Name</Link>
39
+ {this.can_change_order() ?
40
+ <span>
41
+ <a href="javascript:void(0)" onClick={()=> this.change_order('ascending')}>Ascending</a>
42
+ <a href="javascript:void(0)" onClick={()=> this.change_order('descending')}>Descending</a>
43
+ </span>
44
+ : null
45
+ }
46
+ <QuerySave query={this.props.query} />
47
+ </p>
48
+ }
49
+
50
+ }
51
+
52
+ export default class Search extends React.Component {
53
+ constructor(props){
54
+ super(props);
55
+ this.state = {}
56
+ this.mounted = true;
57
+ list.addEventListener('loaded', ()=>{this.reload()});
58
+ }
59
+ reload(){ if(this.mounted){this.setState({});} }
60
+
61
+ search(){
62
+ list.search(this.props.location.query)
63
+ $('title').text(`${this.props.location.query.query} - Pig Media Server`);
64
+ }
65
+ componentDidMount(){
66
+ this.mounted = true;
67
+ window.list = list;
68
+ this.search();
69
+ }
70
+ componentDidUpdate(prevProps){
71
+ if(this.props.location.query != prevProps.location.query){
72
+ this.search();
73
+ }
74
+ }
75
+ componentWillUnmount(){ this.mounted = false; }
76
+
77
+ render(){
78
+ var items = list.list.map((e)=>{
79
+ return <Item key={e.key} item={e} />
80
+ });
81
+ return <div>
82
+ <Sort query={this.props.location.query.query} location={this.props.location}/>
83
+ <p>{items}</p>
84
+ <Pager location={this.props.location} list={list}/>
85
+ </div>
86
+ }
87
+ }
@@ -0,0 +1,56 @@
1
+ import React from 'react';
2
+ import {Link, browserHistory} from 'react-router'
3
+ import jQuery from 'jquery'
4
+
5
+ import Controller from '../controller'
6
+
7
+ var controller = new Controller();
8
+
9
+ class CustomList extends React.Component {
10
+ url(){ return `/custom?name=${encodeURIComponent(this.props.name)}` }
11
+ render(){
12
+ return <Link to={this.url()}>{this.props.name}</Link>
13
+ }
14
+ }
15
+
16
+ class Recommend extends React.Component {
17
+ render(){
18
+ return <span>
19
+ {!!localStorage.user_id ? <Link to={`/recommend?name=${localStorage.user_id}`}><b>Recommend</b></Link> : null}
20
+ </span>
21
+ }
22
+ }
23
+
24
+
25
+ export default class SearchBox extends React.Component {
26
+ submit(event){
27
+ event.preventDefault();
28
+ var query = this.refs.input.value;
29
+ var url = `/?query=${encodeURIComponent(query)}`;
30
+ browserHistory.push(url);
31
+ }
32
+ click(e){ this.props.state.open(e.target.dataset.url); }
33
+
34
+ componentDidUpdate(){
35
+ var query = this.query();
36
+ if(query == 'undefined' || query == 'null' || !query){query = ''}
37
+ this.refs.input.value = query;
38
+ }
39
+
40
+ change(){ }
41
+ query(){ return decodeURIComponent(controller.query()) }
42
+
43
+ render(){
44
+ var query = this.query();
45
+ if(query == 'undefined' || query == 'null' || !query){query = ''}
46
+ var c_list = jQuery.map(custom_list.data, (v,k)=>{return <CustomList key={k} name={k} state={this.props.state}/>});
47
+ return <form onSubmit={(e)=> this.submit(e)}>
48
+ <input ref='input' defaultValue={query} onChange={()=>{this.change()}}/><button>Search</button>
49
+ <Link to='/latest'>Latest</Link>
50
+ <Link to='/config'>Config</Link>
51
+ <Recommend state={this.props.state} />
52
+ <br />
53
+ {c_list}
54
+ </form>
55
+ }
56
+ }