Add playlist search + update lavaplayer + materialize

This commit is contained in:
Sebastien 2018-11-29 18:37:40 +02:00
parent 1a368f8f38
commit 23d098780b
10 changed files with 173 additions and 104 deletions

View File

@ -52,7 +52,7 @@ dependencies {
exclude group:"org.springframework.boot", module: "spring-boot-starter-logging" exclude group:"org.springframework.boot", module: "spring-boot-starter-logging"
} }
compile("org.springframework.boot:spring-boot-starter-log4j2") compile("org.springframework.boot:spring-boot-starter-log4j2")
compile("com.sedmelluq:lavaplayer:1.2.49") compile("com.sedmelluq:lavaplayer:1.3.10")
compile 'net.dv8tion:JDA:3.6.0_354' compile 'net.dv8tion:JDA:3.6.0_354'
compile group: 'org.json', name: 'json', version: '20160810' compile group: 'org.json', name: 'json', version: '20160810'
compile 'org.springframework.security:spring-security-web:5.0.1.RELEASE' compile 'org.springframework.security:spring-security-web:5.0.1.RELEASE'

View File

@ -31,7 +31,7 @@ public class YtSearch implements Commande {
new MessageTimeOut(MainBot.messageTimeOut, message, event.getMessage()).start(); new MessageTimeOut(MainBot.messageTimeOut, message, event.getMessage()).start();
}else { }else {
try { try {
ArrayList<SearchResult> result = youtubeT.search(args[0], 5); ArrayList<SearchResult> result = youtubeT.search(args[0], 5, false);
for(SearchResult item : result){ for(SearchResult item : result){
event.getChannel().sendMessage(EmbedMessageUtils.searchResult(item)).queue(); event.getChannel().sendMessage(EmbedMessageUtils.searchResult(item)).queue();
} }

View File

@ -200,12 +200,12 @@ public class MusicWebAPIController {
} }
@RequestMapping(value = "/search", method = RequestMethod.GET) @RequestMapping(value = "/search", method = RequestMethod.GET)
public ResponseEntity<List<SearchResult>> search(@CookieValue("token") String token, @RequestParam(value = "query") String query ){ public ResponseEntity<List<SearchResult>> search(@CookieValue("token") String token, @RequestParam(value = "query") String query, @RequestParam(value = "playlist") boolean playlist ){
if(token != null) { if(token != null) {
try { try {
UserEntity user = userUtils.getUserWithApiToken(userRepository, token); UserEntity user = userUtils.getUserWithApiToken(userRepository, token);
YoutubeTools youtubeTools = YoutubeTools.getInstance(); YoutubeTools youtubeTools = YoutubeTools.getInstance();
ArrayList<SearchResult> result = youtubeTools.search(query, 25); ArrayList<SearchResult> result = youtubeTools.search(query, 25, playlist);
return new ResponseEntity<>(result, HttpStatus.OK); return new ResponseEntity<>(result, HttpStatus.OK);
}catch (UnknownTokenException e){ }catch (UnknownTokenException e){

View File

@ -37,7 +37,7 @@ public class AudioPlayerSendHandler implements AudioSendHandler {
lastFrame = audioPlayer.provide(); lastFrame = audioPlayer.provide();
} }
byte[] data = lastFrame != null ? lastFrame.data : null; byte[] data = lastFrame != null ? lastFrame.getData() : null;
lastFrame = null; lastFrame = null;
return data; return data;

View File

@ -11,7 +11,10 @@ public class SearchResult {
public String duration; public String duration;
public SearchResult(com.google.api.services.youtube.model.SearchResult result, String duration){ public SearchResult(com.google.api.services.youtube.model.SearchResult result, String duration){
id = result.getId().getVideoId(); if(result.getId().getVideoId() == null)
id = result.getId().getPlaylistId();
else
id = result.getId().getVideoId();
title = result.getSnippet().getTitle(); title = result.getSnippet().getTitle();
description = result.getSnippet().getDescription(); description = result.getSnippet().getDescription();
publishedAt = result.getSnippet().getPublishedAt().toString(); publishedAt = result.getSnippet().getPublishedAt().toString();

View File

@ -3,10 +3,8 @@ package net.Broken.audio.Youtube;
import com.google.api.client.http.javanet.NetHttpTransport; import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.client.json.jackson2.JacksonFactory; import com.google.api.client.json.jackson2.JacksonFactory;
import com.google.api.services.youtube.YouTube; import com.google.api.services.youtube.YouTube;
import com.google.api.services.youtube.model.SearchListResponse; import com.google.api.services.youtube.model.*;
import com.google.api.services.youtube.model.SearchResult; import com.google.api.services.youtube.model.SearchResult;
import com.google.api.services.youtube.model.Video;
import com.google.api.services.youtube.model.VideoListResponse;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
@ -81,10 +79,13 @@ public class YoutubeTools {
} }
public ArrayList<net.Broken.audio.Youtube.SearchResult> search(String query, long max) throws IOException { public ArrayList<net.Broken.audio.Youtube.SearchResult> search(String query, long max, boolean playlist) throws IOException {
YouTube youTube = getYoutubeService(); YouTube youTube = getYoutubeService();
YouTube.Search.List searchList = youTube.search().list("snippet"); YouTube.Search.List searchList = youTube.search().list("snippet");
searchList.setType("video"); if(playlist)
searchList.setType("playlist");
else
searchList.setType("video");
searchList.setSafeSearch("none"); searchList.setSafeSearch("none");
searchList.setMaxResults(max); searchList.setMaxResults(max);
searchList.setQ(query); searchList.setQ(query);
@ -94,30 +95,55 @@ public class YoutubeTools {
SearchListResponse response = searchList.execute(); SearchListResponse response = searchList.execute();
StringBuilder idString = new StringBuilder(); StringBuilder idString = new StringBuilder();
for(SearchResult item : response.getItems()){
idString.append(item.getId().getVideoId()).append(",");
}
HashMap<String, Video> videoHashMap = new HashMap<>(); if(playlist){
YouTube.Videos.List video = youTube.videos().list("contentDetails"); for(SearchResult item : response.getItems()){
video.setId(idString.toString()); idString.append(item.getId().getPlaylistId()).append(",");
video.setKey(apiKey); }
VideoListResponse videoResponse = video.execute(); HashMap<String, Playlist> playlistHashMap = new HashMap<>();
for(Video item : videoResponse.getItems()){ YouTube.Playlists.List list = youTube.playlists().list("contentDetails");
videoHashMap.put(item.getId(), item); list.setId(idString.toString());
list.setKey(apiKey);
PlaylistListResponse playlistResponse = list.execute();
for( Playlist item : playlistResponse.getItems()){
playlistHashMap.put(item.getId(), item);
}
ArrayList<net.Broken.audio.Youtube.SearchResult> finalResult = new ArrayList<>();
for(SearchResult item : response.getItems()){
logger.trace(item.getSnippet().getTitle());
finalResult.add(new net.Broken.audio.Youtube.SearchResult(item, playlistHashMap.get(item.getId().getPlaylistId()).getContentDetails().getItemCount().toString()+ " Video(s)"));
}
return finalResult;
} }
ArrayList<net.Broken.audio.Youtube.SearchResult> finalResult = new ArrayList<>(); else{
for(SearchResult item : response.getItems()){ for(SearchResult item : response.getItems()){
logger.trace(item.getSnippet().getTitle()); idString.append(item.getId().getVideoId()).append(",");
finalResult.add(new net.Broken.audio.Youtube.SearchResult(item, videoHashMap.get(item.getId().getVideoId()).getContentDetails().getDuration())); }
HashMap<String, Video> videoHashMap = new HashMap<>();
YouTube.Videos.List video = youTube.videos().list("contentDetails");
video.setId(idString.toString());
video.setKey(apiKey);
VideoListResponse videoResponse = video.execute();
for(Video item : videoResponse.getItems()){
videoHashMap.put(item.getId(), item);
}
ArrayList<net.Broken.audio.Youtube.SearchResult> finalResult = new ArrayList<>();
for(SearchResult item : response.getItems()){
logger.trace(item.getSnippet().getTitle());
finalResult.add(new net.Broken.audio.Youtube.SearchResult(item, videoHashMap.get(item.getId().getVideoId()).getContentDetails().getDuration()));
}
return finalResult;
} }
return finalResult;
} }

View File

@ -1,5 +1,5 @@
/*! /*!
* Materialize v1.0.0-rc.2 (http://materializecss.com) * Materialize v1.0.0 (http://materializecss.com)
* Copyright 2014-2017 Materialize * Copyright 2014-2017 Materialize
* MIT License (https://raw.githubusercontent.com/Dogfalo/materialize/master/LICENSE) * MIT License (https://raw.githubusercontent.com/Dogfalo/materialize/master/LICENSE)
*/ */
@ -6551,7 +6551,7 @@ textarea.materialize-textarea + label:after, .select-wrapper + label:after {
transform-origin: 0 0; transform-origin: 0 0;
} }
.input-field > input[type]:-webkit-autofill:not(.browser-default) + label, .input-field > input[type]:-webkit-autofill:not(.browser-default):not([type="search"]) + label,
.input-field > input[type=date]:not(.browser-default) + label, .input-field > input[type=date]:not(.browser-default) + label,
.input-field > input[type=time]:not(.browser-default) + label { .input-field > input[type=time]:not(.browser-default) + label {
-webkit-transform: translateY(-14px) scale(0.8); -webkit-transform: translateY(-14px) scale(0.8);

View File

@ -1,5 +1,5 @@
/*! /*!
* Materialize v1.0.0-rc.2 (http://materializecss.com) * Materialize v1.0.0 (http://materializecss.com)
* Copyright 2014-2017 Materialize * Copyright 2014-2017 Materialize
* MIT License (https://raw.githubusercontent.com/Dogfalo/materialize/master/LICENSE) * MIT License (https://raw.githubusercontent.com/Dogfalo/materialize/master/LICENSE)
*/ */
@ -1084,6 +1084,8 @@ if (typeof define === 'function' && define.amd) {
exports.default = M; exports.default = M;
} }
M.version = '1.0.0';
M.keys = { M.keys = {
TAB: 9, TAB: 9,
ENTER: 13, ENTER: 13,
@ -2507,7 +2509,11 @@ $jscomp.polyfill = function (e, r, p, m) {
var $activatableElement = $(focusedElement).find('a, button').first(); var $activatableElement = $(focusedElement).find('a, button').first();
// Click a or button tag if exists, otherwise click li tag // Click a or button tag if exists, otherwise click li tag
!!$activatableElement.length ? $activatableElement[0].click() : focusedElement.click(); if (!!$activatableElement.length) {
$activatableElement[0].click();
} else if (!!focusedElement) {
focusedElement.click();
}
// Close dropdown on ESC // Close dropdown on ESC
} else if (e.which === M.keys.ESC && this.isOpen) { } else if (e.which === M.keys.ESC && this.isOpen) {
@ -2687,8 +2693,7 @@ $jscomp.polyfill = function (e, r, p, m) {
// onOpenEnd callback // onOpenEnd callback
if (typeof _this11.options.onOpenEnd === 'function') { if (typeof _this11.options.onOpenEnd === 'function') {
var elem = anim.animatables[0].target; _this11.options.onOpenEnd.call(_this11, _this11.el);
_this11.options.onOpenEnd.call(elem, _this11.el);
} }
} }
}); });
@ -2719,7 +2724,6 @@ $jscomp.polyfill = function (e, r, p, m) {
// onCloseEnd callback // onCloseEnd callback
if (typeof _this12.options.onCloseEnd === 'function') { if (typeof _this12.options.onCloseEnd === 'function') {
var elem = anim.animatables[0].target;
_this12.options.onCloseEnd.call(_this12, _this12.el); _this12.options.onCloseEnd.call(_this12, _this12.el);
} }
} }
@ -2849,7 +2853,7 @@ $jscomp.polyfill = function (e, r, p, m) {
Dropdown._dropdowns = []; Dropdown._dropdowns = [];
window.M.Dropdown = Dropdown; M.Dropdown = Dropdown;
if (M.jQueryLoaded) { if (M.jQueryLoaded) {
M.initializeJqueryWrapper(Dropdown, 'dropdown', 'M_Dropdown'); M.initializeJqueryWrapper(Dropdown, 'dropdown', 'M_Dropdown');
@ -4420,7 +4424,7 @@ $jscomp.polyfill = function (e, r, p, m) {
return Tabs; return Tabs;
}(Component); }(Component);
window.M.Tabs = Tabs; M.Tabs = Tabs;
if (M.jQueryLoaded) { if (M.jQueryLoaded) {
M.initializeJqueryWrapper(Tabs, 'tabs', 'M_Tabs'); M.initializeJqueryWrapper(Tabs, 'tabs', 'M_Tabs');
@ -6090,7 +6094,7 @@ $jscomp.polyfill = function (e, r, p, m) {
Sidenav._sidenavs = []; Sidenav._sidenavs = [];
window.M.Sidenav = Sidenav; M.Sidenav = Sidenav;
if (M.jQueryLoaded) { if (M.jQueryLoaded) {
M.initializeJqueryWrapper(Sidenav, 'sidenav', 'M_Sidenav'); M.initializeJqueryWrapper(Sidenav, 'sidenav', 'M_Sidenav');
@ -11833,10 +11837,20 @@ $jscomp.polyfill = function (e, r, p, m) {
// Add callback for centering selected option when dropdown content is scrollable // Add callback for centering selected option when dropdown content is scrollable
dropdownOptions.onOpenEnd = function (el) { dropdownOptions.onOpenEnd = function (el) {
var selectedOption = $(_this71.dropdownOptions).find('.selected').first(); var selectedOption = $(_this71.dropdownOptions).find('.selected').first();
if (_this71.dropdown.isScrollable && selectedOption.length) {
var scrollOffset = selectedOption[0].getBoundingClientRect().top - _this71.dropdownOptions.getBoundingClientRect().top; // scroll to selected option if (selectedOption.length) {
scrollOffset -= _this71.dropdownOptions.clientHeight / 2; // center in dropdown // Focus selected option in dropdown
_this71.dropdownOptions.scrollTop = scrollOffset; M.keyDown = true;
_this71.dropdown.focusedIndex = selectedOption.index();
_this71.dropdown._focusFocusedItem();
M.keyDown = false;
// Handle scrolling to selected option
if (_this71.dropdown.isScrollable) {
var scrollOffset = selectedOption[0].getBoundingClientRect().top - _this71.dropdownOptions.getBoundingClientRect().top; // scroll to selected option
scrollOffset -= _this71.dropdownOptions.clientHeight / 2; // center in dropdown
_this71.dropdownOptions.scrollTop = scrollOffset;
}
} }
}; };

View File

@ -41,6 +41,7 @@ $(document).ready(function () {
modal_loading = M.Modal.init($('#modal_loading').get(0), {dismissible: false}); modal_loading = M.Modal.init($('#modal_loading').get(0), {dismissible: false});
modal_loading.open(); modal_loading.open();
$('#tabs-swipe-demo').tabs();
$('.dropdown-button').dropdown({ $('.dropdown-button').dropdown({
@ -171,7 +172,6 @@ function getCurentMusic() {
} }
} }
clearInterval(interval);
if (savedPlaylist != null) { if (savedPlaylist != null) {
$('#playlist_list').empty(); $('#playlist_list').empty();
savedPlaylist = null; savedPlaylist = null;
@ -431,14 +431,21 @@ function search() {
load.removeClass("hide"); load.removeClass("hide");
load.addClass("scale-in"); load.addClass("scale-in");
$.get("/api/music/search?query=" + input_search.val(), (data) => { $.get("/api/music/search?query=" + input_search.val() + "&playlist=" + $("#playlistSearch").is(':checked'), (data) => {
list.empty(); list.empty();
let url;
if($("#playlistSearch").is(':checked')){
url = "https://www.youtube.com/playlist?list="
}
else
url = "https://youtube.com/watch?v=";
data.forEach((item) => { data.forEach((item) => {
let html = let html =
"<li class=\"collection-item avatar\">" + "<li class=\"collection-item avatar\">" +
" <img src=\"" + item["imageUrl"] + "\" alt=\"\" class=\"\">" + " <img src=\"" + item["imageUrl"] + "\" alt=\"\" class=\"\">" +
" <a class=\"title truncate\" href='https://youtube.com/watch?v=" + item["id"] + "' target=\"_blank\"><b>" + item["title"] + "</b></a>" + " <a class=\"title truncate\" href='" + url + item["id"] + "' target=\"_blank\"><b>" + item["title"] + "</b></a>" +
" <p class='truncate grey-text text-darken-1'>" + item["channelTittle"] + " &#9553 " + item["publishedAt"].substr(0, item["publishedAt"].indexOf('T')) + " <br>" + ytTimeToTime(item["duration"]) + " <p class='truncate grey-text text-darken-1'>" + item["channelTittle"] + " &#9553 " + item["publishedAt"].substr(0, item["publishedAt"].indexOf('T')) + " <br>" + ytTimeToTime(item["duration"]) +
" </p>" + " </p>" +
" <a href=\"#!\" class=\"secondary-content btn waves-effect waves-light green add-btn-list scale-transition\" id='" + item["id"] + "'><i class=\"material-icons \">add_circle_outline</i></a>" + " <a href=\"#!\" class=\"secondary-content btn waves-effect waves-light green add-btn-list scale-transition\" id='" + item["id"] + "'><i class=\"material-icons \">add_circle_outline</i></a>" +
@ -495,7 +502,7 @@ function addListClick(event) {
let command = { let command = {
command: "ADD", command: "ADD",
url: button.id, url: button.id,
playlistLimit: $('#limit_range').val(), playlistLimit: "300",
onHead: !$('#bottom').is(':checked') onHead: !$('#bottom').is(':checked')
}; };
sendCommand(command, false); sendCommand(command, false);
@ -507,6 +514,8 @@ function ytTimeToTime(duration) {
let seconds; let seconds;
if (duration === "PT0S") if (duration === "PT0S")
return "&#x1F534 LIVE"; return "&#x1F534 LIVE";
if(duration.endsWith("Video(s)"))
return duration;
if (duration.includes("H")) if (duration.includes("H"))
hours = parseInt(duration.match(/\d*H/)[0].replace("H", ""), 10); hours = parseInt(duration.match(/\d*H/)[0].replace("H", ""), 10);
else else

View File

@ -16,22 +16,23 @@
<meta name="theme-color" content="#263238"/> <meta name="theme-color" content="#263238"/>
<style> <style>
@media only screen and (max-width: 1200px) { @media only screen and (max-width: 1200px) {
#modalAdd{ #modalAdd {
width: 95%; width: 95%;
} }
} }
@media only screen and (min-width: 1200px) { @media only screen and (min-width: 1200px) {
#modalAdd{ #modalAdd {
width: 80%; width: 80%;
} }
} }
#modalAdd{ #modalAdd {
height: 85% !important; height: 85% !important;
max-height: 100% !important; max-height: 100% !important;
} }
.avatar>img{ .avatar > img {
position: absolute; position: absolute;
width: 80px; width: 80px;
height: auto; height: auto;
@ -40,7 +41,8 @@
display: inline-block; display: inline-block;
vertical-align: middle; vertical-align: middle;
} }
.collection-item.avatar{
.collection-item.avatar {
padding-left: 105px !important; padding-left: 105px !important;
padding-right: 75px; padding-right: 75px;
} }
@ -49,7 +51,7 @@
</head> </head>
<body class="blue-grey lighten-5" > <body class="blue-grey lighten-5">
<!--/*@thymesVar id="guild_name" type="java.lang.String"*/--> <!--/*@thymesVar id="guild_name" type="java.lang.String"*/-->
<!--/*@thymesVar id="redirect_url" type="java.lang.String"*/--> <!--/*@thymesVar id="redirect_url" type="java.lang.String"*/-->
@ -58,8 +60,9 @@
<div class="section no-pad-bot main" id="index-banner"> <div class="section no-pad-bot main" id="index-banner">
<div class="row"> <div class="row">
<div class="col l8 s12 m12"> <div class="col l8 s12 m12">
<div class="row center" > <div class="row center">
<img class="responsive-img z-depth-3" id="music_img" style="max-width: 30%" src="/img/disconnected.png"/> <img class="responsive-img z-depth-3" id="music_img" style="max-width: 30%"
src="/img/disconnected.png"/>
</div> </div>
<h4 class="center" id="music_text"></h4> <h4 class="center" id="music_text"></h4>
<div class="row center" style="margin-bottom: 0px"> <div class="row center" style="margin-bottom: 0px">
@ -68,8 +71,12 @@
</div> </div>
</div> </div>
<div class="row center"> <div class="row center">
<div class="col l2 offset-l3 m2 offset-m1 s2 offset-s1 left-align" style="padding: 0px" id="current_time">0:00</div> <div class="col l2 offset-l3 m2 offset-m1 s2 offset-s1 left-align" style="padding: 0px"
<div class="col l2 offset-l2 m2 offset-m6 s2 offset-s6 right-align " style="padding: 0px" id="total_time">0:00</div> id="current_time">0:00
</div>
<div class="col l2 offset-l2 m2 offset-m6 s2 offset-s6 right-align " style="padding: 0px"
id="total_time">0:00
</div>
</div> </div>
<div class="row center"> <div class="row center">
<div class="col l2 offset-l3 m4 s4 center"> <div class="col l2 offset-l3 m4 s4 center">
@ -91,7 +98,8 @@
<div class="row center"> <div class="row center">
<div class="col offset-l5 l2 m2 offset-m5 s2 offset-s5 center"> <div class="col offset-l5 l2 m2 offset-m5 s2 offset-s5 center">
<a class="btn black z-depth-3 waves-effect waves-light modal-trigger" href="#modal_current_info" id="btn_info"> <a class="btn black z-depth-3 waves-effect waves-light modal-trigger" href="#modal_current_info"
id="btn_info">
<i class="material-icons">info</i> <i class="material-icons">info</i>
</a> </a>
</div> </div>
@ -107,7 +115,7 @@
</div> </div>
</div> </div>
<div class="col l4 m12 s12" > <div class="col l4 m12 s12">
<table> <table>
<thead> <thead>
<tr> <tr>
@ -115,19 +123,20 @@
<div class="row center valign-wrapper" style="margin: 0px"> <div class="row center valign-wrapper" style="margin: 0px">
<div class="col l3 m5 s5 center blue-grey-text text-darken-3"><h5><b>Playlist</b></h5></div> <div class="col l3 m5 s5 center blue-grey-text text-darken-3"><h5><b>Playlist</b></h5></div>
<div class="col l3 m2 s2 center" style="padding-right: 0px; padding-left: 0px"> <div class="col l3 m2 s2 center" style="padding-right: 0px; padding-left: 0px">
<a class="waves-effect waves-light btn modal-trigger red darken-4 ctl-btn" id="flush_btn"><i class="material-icons">delete_sweep</i></a> <a class="waves-effect waves-light btn modal-trigger red darken-4 ctl-btn"
id="flush_btn"><i class="material-icons">delete_sweep</i></a>
</div> </div>
<div class="col l3 m2 s2 center" style="padding-right: 0px; padding-left: 0px"> <div class="col l3 m2 s2 center" style="padding-right: 0px; padding-left: 0px">
<!-- Modal Trigger --> <!-- Modal Trigger -->
<a class="waves-effect waves-light btn modal-trigger green darken-4" id="add_btn" href="#modalAdd"><i class="material-icons">add_circle_outline</i></a> <a class="waves-effect waves-light btn modal-trigger green darken-4" id="add_btn"
href="#modalAdd"><i class="material-icons">add_circle_outline</i></a>
</div> </div>
<div class="col l3 m2 s2 center " style="padding-left: 0px"> <div class="col l3 m2 s2 center " style="padding-left: 0px">
<div class="row switch blue-grey-text text-darken-3" style="margin-bottom: 0px"> <div class="row switch blue-grey-text text-darken-3" style="margin-bottom: 0px">
AutoFlow AutoFlow
</div> </div>
<div class="row switch tooltipped ctl-btn" data-position="bottom" data-delay="50" data-tooltip="Experimental!"> <div class="row switch tooltipped ctl-btn" data-position="bottom" data-delay="50"
data-tooltip="Experimental!">
<label> <label>
<input type="checkbox" id="autoflow"/> <input type="checkbox" id="autoflow"/>
<span class="lever"></span> <span class="lever"></span>
@ -143,7 +152,8 @@
<tbody> <tbody>
<tr> <tr>
<td> <td>
<ul id="playlist_list" class="collapsible popout" data-collapsible="accordion" style="margin: 0px"> <ul id="playlist_list" class="collapsible popout" data-collapsible="accordion"
style="margin: 0px">
</ul> </ul>
</td> </td>
@ -158,8 +168,6 @@
</div> </div>
<!-- Music --> <!-- Music -->
<div id="modal_current_info" class="modal bottom-sheet"> <div id="modal_current_info" class="modal bottom-sheet">
<div class="modal-content"> <div class="modal-content">
@ -183,46 +191,58 @@
<div class="row valign-wrapper"> <div class="row valign-wrapper">
<h3 class="col l12 m12 s12 center"> Add Music</h3> <h3 class="col l12 m12 s12 center"> Add Music</h3>
</div> </div>
<div class="row" style="margin-bottom: 0px"> <div class="row" id="musicSearch" style="margin-bottom: 0px">
<div class="row">
<form class="col l12 m12 s12"> <form class="col l12 m12 s12">
<div class="row" style="margin-bottom: 0"> <div class="row" style="margin-bottom: 0">
<div class="input-field col offset-l1 l9 m10 s10" style="padding-left: 0px; padding-right: 0px"> <div class="input-field col offset-l1 l9 m9 s7" style="padding-left: 0px; padding-right: 0px">
<!--<i class="material-icons prefix">link</i>--> <!--<i class="material-icons prefix">link</i>-->
<input id="input_search" type="text" class="validate"/> <input id="input_search" type="text" class="validate"/>
<label for="input_search">Search</label> <label for="input_search">Search</label>
</div> </div>
<div class="input-field col l2 m2 s2" style="margin-top: 22px"> <div class="input-field col l1 m2 s3" style="margin-top: 22px">
<button class="btn waves-effect waves-light green darken-4 white-text" id="btn_search" type="button"><i class="material-icons">search</i></button> <button class="btn waves-effect waves-light green darken-4 white-text" id="btn_search"
</div> type="button"><i class="material-icons">search</i></button>
</div> </div>
<div class="col l1 m1 s2 center" style="padding: 0; margin-top: 15px;">
<div class="row"> <div class="row switch blue-grey-text text-darken-3" style="margin-bottom: 0px">
<div class="col s12 m12 l12 center scale-transition scale-out hide" id="search_load" style="margin-top: 25px"> Playlist
<div class="preloader-wrapper big active"> </div>
<div class="spinner-layer spinner-blue-only"> <div class="row switch">
<div class="circle-clipper left"> <label>
<div class="circle"></div> <input type="checkbox" id="playlistSearch"/>
</div> <span class="lever"></span>
<div class="gap-patch"> </label>
<div class="circle"></div>
</div>
<div class="circle-clipper right">
<div class="circle"></div>
</div>
</div> </div>
</div> </div>
</div> </div>
<ul class="collection col l12 m12 s12 scale-transition scale-out" id="search_result" style="padding: 0">
</ul> <div class="row">
<div class="col s12 m12 l12 center scale-transition scale-out hide" id="search_load"
style="margin-top: 25px">
<div class="preloader-wrapper big active">
<div class="spinner-layer spinner-blue-only">
<div class="circle-clipper left">
<div class="circle"></div>
</div>
<div class="gap-patch">
<div class="circle"></div>
</div>
<div class="circle-clipper right">
<div class="circle"></div>
</div>
</div>
</div>
</div>
<ul class="collection col l12 m12 s12 scale-transition scale-out" id="search_result"
style="padding: 0">
</ul>
</div>
</form>
</div>
</div>
</form>
</div> </div>
</div> </div>
<div class="modal-footer"> <div class="modal-footer">
@ -234,7 +254,7 @@
</span> </span>
<span style="margin-right: 10px"> <span style="margin-right: 10px">
<label> <label>
<input name="group1" type="radio" /> <input name="group1" type="radio"/>
<span>Top</span> <span>Top</span>
</label> </label>
</span> </span>
@ -273,21 +293,20 @@
</div> </div>
</div> </div>
<div class="modal-footer"> <div class="modal-footer">
<a href="/" class="modal-action modal-close waves-effect waves-red btn-flat ">Cancel</a> <a href="/" class="modal-action modal-close waves-effect waves-red btn-flat ">Cancel</a>
<a href="#!" id="btn_ok_channel" class="modal-action modal-close waves-effect waves-green btn-flat disabled">Connect</a> <a href="#!" id="btn_ok_channel" class="modal-action modal-close waves-effect waves-green btn-flat disabled">Connect</a>
</div> </div>
</div> </div>
<!--Loading Modal--> <!--Loading Modal-->
<div id="modal_loading" class="modal valign-wrapper"> <div id="modal_loading" class="modal valign-wrapper">
<div class="modal-content" > <div class="modal-content">
<div class="row center"> <div class="row center">
<h3 class="col l12 m12 s12 center">Please wait</h3> <h3 class="col l12 m12 s12 center">Please wait</h3>
</div> </div>
<div class="row center" > <div class="row center">
<div class="preloader-wrapper big active"> <div class="preloader-wrapper big active">
<div class="spinner-layer spinner-blue"> <div class="spinner-layer spinner-blue">
<div class="circle-clipper left"> <div class="circle-clipper left">
@ -342,7 +361,6 @@
</div> </div>
<p id="radioTemplate" class="" style="visibility: hidden"> <p id="radioTemplate" class="" style="visibility: hidden">
<label> <label>
<input name="vocalRadio" class="with-gap" type="radio" value="@id" id="@id"/> <input name="vocalRadio" class="with-gap" type="radio" value="@id" id="@id"/>
@ -365,6 +383,5 @@
<script th:src="@{/js/fontawesome.js}"></script> <script th:src="@{/js/fontawesome.js}"></script>
</body> </body>
</html> </html>