added invidous support for youtube queries
also added search suggestions
This commit is contained in:
parent
8dff21bc8a
commit
4b5dc1fb40
10 changed files with 324 additions and 86 deletions
|
|
@ -320,7 +320,7 @@
|
|||
<PersistentState>
|
||||
<option name="values">
|
||||
<map>
|
||||
<entry key="url" value="file:/$USER_HOME$/AppData/Local/Android/Sdk/icons/material/materialicons/file_open/baseline_file_open_24.xml" />
|
||||
<entry key="url" value="jar:file:/C:/Program%20Files/Android/Android%20Studio/plugins/android/lib/android.jar!/images/material/icons/materialicons/arrow_upward/baseline_arrow_upward_24.xml" />
|
||||
</map>
|
||||
</option>
|
||||
</PersistentState>
|
||||
|
|
@ -331,7 +331,7 @@
|
|||
<option name="values">
|
||||
<map>
|
||||
<entry key="color" value="00a6ff" />
|
||||
<entry key="outputName" value="ic_baseline_file_open_24" />
|
||||
<entry key="outputName" value="ic_arrow_up" />
|
||||
<entry key="sourceFile" value="C:\Users\denis\Desktop\adaptiveproduct_youtube_foreground_color_108 (1).svg" />
|
||||
</map>
|
||||
</option>
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@
|
|||
android:supportsRtl="true"
|
||||
android:theme="@style/AppDefaultTheme" >
|
||||
<activity android:name=".MainActivity"
|
||||
android:windowSoftInputMode="adjustResize"
|
||||
android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
|
|
|
|||
|
|
@ -228,6 +228,7 @@ public class DownloaderService extends Service {
|
|||
});
|
||||
}
|
||||
}catch (Exception ignored){}
|
||||
onDestroy();
|
||||
}
|
||||
|
||||
private void onDownloadEnd(){
|
||||
|
|
|
|||
|
|
@ -14,9 +14,13 @@ import android.os.Bundle;
|
|||
import android.os.IBinder;
|
||||
import android.provider.Settings;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.view.WindowInsets;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.core.app.ActivityCompat;
|
||||
import androidx.core.view.WindowInsetsCompat;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
|
||||
|
|
@ -134,6 +138,14 @@ public class MainActivity extends AppCompatActivity{
|
|||
return true;
|
||||
});
|
||||
|
||||
getWindow().getDecorView().setOnApplyWindowInsetsListener((view, windowInsets) -> {
|
||||
WindowInsetsCompat windowInsetsCompat = WindowInsetsCompat.toWindowInsetsCompat(windowInsets, view);
|
||||
boolean isImeVisible = windowInsetsCompat.isVisible(WindowInsetsCompat.Type.ime());
|
||||
binding.bottomNavigationView.setVisibility(isImeVisible ? View.GONE : View.VISIBLE);
|
||||
view.onApplyWindowInsets(windowInsets);
|
||||
return windowInsets;
|
||||
});
|
||||
|
||||
askPermissions();
|
||||
|
||||
Intent intent = getIntent();
|
||||
|
|
|
|||
|
|
@ -21,7 +21,12 @@ import android.view.ViewGroup;
|
|||
import android.view.Window;
|
||||
import android.widget.AutoCompleteTextView;
|
||||
import android.widget.Button;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.ScrollView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.appcompat.widget.SearchView;
|
||||
import androidx.constraintlayout.widget.ConstraintLayout;
|
||||
import androidx.coordinatorlayout.widget.CoordinatorLayout;
|
||||
import androidx.core.app.ActivityCompat;
|
||||
import androidx.fragment.app.Fragment;
|
||||
|
|
@ -44,6 +49,9 @@ import com.google.android.material.floatingactionbutton.ExtendedFloatingActionBu
|
|||
import com.google.android.material.floatingactionbutton.FloatingActionButton;
|
||||
import com.google.android.material.progressindicator.LinearProgressIndicator;
|
||||
import com.google.android.material.textfield.TextInputLayout;
|
||||
import com.google.android.material.textview.MaterialTextView;
|
||||
|
||||
import java.lang.reflect.Array;
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedList;
|
||||
import java.util.regex.Matcher;
|
||||
|
|
@ -59,6 +67,8 @@ public class HomeFragment extends Fragment implements HomeRecyclerViewAdapter.On
|
|||
private int inputQueriesLength = 0;
|
||||
private RecyclerView recyclerView;
|
||||
private HomeRecyclerViewAdapter homeRecyclerViewAdapter;
|
||||
private ScrollView searchSuggestions;
|
||||
private LinearLayout searchSuggestionsLinearLayout;
|
||||
private ShimmerFrameLayout shimmerCards;
|
||||
private CoordinatorLayout downloadFabs;
|
||||
private CoordinatorLayout downloadAllFab;
|
||||
|
|
@ -220,6 +230,8 @@ public class HomeFragment extends Fragment implements HomeRecyclerViewAdapter.On
|
|||
shimmerCards = fragmentView.findViewById(R.id.shimmer_results_framelayout);
|
||||
topAppBar = fragmentView.findViewById(R.id.home_toolbar);
|
||||
recyclerView = fragmentView.findViewById(R.id.recycler_view_home);
|
||||
searchSuggestions = fragmentView.findViewById(R.id.search_suggestions_scroll_view);
|
||||
searchSuggestionsLinearLayout = fragmentView.findViewById(R.id.search_suggestions_linear_layout);
|
||||
|
||||
homeRecyclerViewAdapter = new HomeRecyclerViewAdapter(resultObjects, this, activity);
|
||||
recyclerView.setAdapter(homeRecyclerViewAdapter);
|
||||
|
|
@ -347,6 +359,7 @@ public class HomeFragment extends Fragment implements HomeRecyclerViewAdapter.On
|
|||
public boolean onMenuItemActionExpand(MenuItem menuItem) {
|
||||
homeFabs.setVisibility(View.GONE);
|
||||
recyclerView.setVisibility(View.GONE);
|
||||
searchSuggestions.setVisibility(View.VISIBLE);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -354,6 +367,7 @@ public class HomeFragment extends Fragment implements HomeRecyclerViewAdapter.On
|
|||
public boolean onMenuItemActionCollapse(MenuItem menuItem) {
|
||||
homeFabs.setVisibility(View.VISIBLE);
|
||||
recyclerView.setVisibility(View.VISIBLE);
|
||||
searchSuggestions.setVisibility(View.GONE);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
|
@ -368,6 +382,7 @@ public class HomeFragment extends Fragment implements HomeRecyclerViewAdapter.On
|
|||
searchView.setQueryHint(getString(R.string.search_hint));
|
||||
|
||||
dbManager = new DBManager(context);
|
||||
infoUtil = new InfoUtil(context);
|
||||
|
||||
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
|
||||
@Override
|
||||
|
|
@ -394,7 +409,25 @@ public class HomeFragment extends Fragment implements HomeRecyclerViewAdapter.On
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean onQueryTextChange(String newText) { return false; }
|
||||
public boolean onQueryTextChange(String newText) {
|
||||
searchSuggestionsLinearLayout.removeAllViews();
|
||||
if (newText.isEmpty()) return false;
|
||||
Thread thread = new Thread(() -> {
|
||||
ArrayList<String> suggestions = infoUtil.getSearchSuggestions(newText);
|
||||
for (int i = 0; i < suggestions.size();i++){
|
||||
View v = LayoutInflater.from(fragmentContext).inflate(R.layout.search_suggestion_item, null);
|
||||
TextView textView = v.findViewById(R.id.suggestion_text);
|
||||
textView.setText(suggestions.get(i));
|
||||
new Handler(Looper.getMainLooper()).post(() -> searchSuggestionsLinearLayout.addView(v));
|
||||
textView.setOnClickListener(view -> onQueryTextSubmit(textView.getText().toString()));
|
||||
|
||||
MaterialButton mb = v.findViewById(R.id.set_search_query_button);
|
||||
mb.setOnClickListener(view -> searchView.setQuery(textView.getText(), false));
|
||||
}
|
||||
});
|
||||
thread.start();
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
topAppBar.setOnClickListener(view -> scrollToTop());
|
||||
|
|
|
|||
|
|
@ -28,9 +28,11 @@ import java.util.Locale;
|
|||
|
||||
public class InfoUtil {
|
||||
private static final String TAG = "API MANAGER";
|
||||
private static String countryCODE = "US";
|
||||
private static final String invidousURL = "https://invidious.baczek.me/api/v1/";
|
||||
private static String countryCODE;
|
||||
private ArrayList<Video> videos;
|
||||
private String key;
|
||||
private boolean useInvidous;
|
||||
private DBManager dbManager;
|
||||
|
||||
public InfoUtil(Context context) {
|
||||
|
|
@ -43,22 +45,33 @@ public class InfoUtil {
|
|||
JSONObject country = genericRequest("https://ipwho.is/");
|
||||
try{
|
||||
countryCODE = country.getString("country_code");
|
||||
}catch(Exception ignored){}
|
||||
}catch(Exception e){
|
||||
countryCODE = "US";
|
||||
}
|
||||
|
||||
JSONObject res = genericRequest(invidousURL + "stats");
|
||||
if(res.length() == 0) useInvidous = false;
|
||||
else useInvidous = true;
|
||||
});
|
||||
thread.start();
|
||||
thread.join();
|
||||
|
||||
}catch(Exception ignored){
|
||||
Toast.makeText(context, "Couldn't find API Key for the request", Toast.LENGTH_SHORT).show();
|
||||
}catch(Exception e){
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
videos = new ArrayList<>();
|
||||
}
|
||||
|
||||
public ArrayList<Video> search(String query) throws JSONException{
|
||||
if (key.isEmpty()) return getFromYTDL(query);
|
||||
|
||||
videos = new ArrayList<>();
|
||||
if (key.isEmpty()) {
|
||||
if(useInvidous) return searchFromInvidous(query);
|
||||
else return getFromYTDL(query);
|
||||
}
|
||||
return searchFromKey(query);
|
||||
}
|
||||
|
||||
public ArrayList<Video> searchFromKey(String query) throws JSONException{
|
||||
//short data
|
||||
JSONObject res = genericRequest("https://youtube.googleapis.com/youtube/v3/search?part=snippet&q="+query+"&maxResults=25®ionCode="+countryCODE+"&key="+key);
|
||||
if (!res.has("items")) return getFromYTDL(query);
|
||||
|
|
@ -91,7 +104,7 @@ public class InfoUtil {
|
|||
}
|
||||
|
||||
snippet.put("duration", duration);
|
||||
snippet = fixThumbnail(snippet);
|
||||
fixThumbnail(snippet);
|
||||
Video v = createVideofromJSON(snippet);
|
||||
|
||||
if(v == null || v.getThumb().isEmpty()){
|
||||
|
|
@ -105,6 +118,32 @@ public class InfoUtil {
|
|||
return videos;
|
||||
}
|
||||
|
||||
public ArrayList<Video> searchFromInvidous(String query) throws JSONException{
|
||||
JSONObject res = genericRequest(invidousURL + "search?q="+query);
|
||||
if(res.length() == 0) return getFromYTDL(query);
|
||||
JSONArray dataArray = res.getJSONArray("");
|
||||
|
||||
int j = 0;
|
||||
for(int i = 0; i < dataArray.length(); i++){
|
||||
JSONObject element = dataArray.getJSONObject(i);
|
||||
String duration = formatIntegerDuration(element.getInt("lengthSeconds"));
|
||||
if(duration.equals("0:00")){
|
||||
continue;
|
||||
}
|
||||
element.put("duration", duration);
|
||||
element.put("thumb", element.getJSONArray("videoThumbnails").getJSONObject(0).getString("url"));
|
||||
Video v = createVideofromInvidiousJSON(element);
|
||||
|
||||
if(v == null || v.getThumb().isEmpty()){
|
||||
continue;
|
||||
}
|
||||
videos.add(v);
|
||||
}
|
||||
|
||||
|
||||
return videos;
|
||||
}
|
||||
|
||||
public PlaylistTuple getPlaylist(String id, String nextPageToken) throws JSONException{
|
||||
if (key.isEmpty()) return new PlaylistTuple("", getFromYTDL("https://www.youtube.com/playlist?list="+id));
|
||||
videos = new ArrayList<>();
|
||||
|
|
@ -136,7 +175,7 @@ public class InfoUtil {
|
|||
String duration = extra.getJSONArray("items").getJSONObject(j).getJSONObject("contentDetails").getString("duration");
|
||||
duration = formatDuration(duration);
|
||||
snippet.put("duration", duration);
|
||||
snippet = fixThumbnail(snippet);
|
||||
fixThumbnail(snippet);
|
||||
Video v = createVideofromJSON(snippet);
|
||||
|
||||
if(v == null || v.getThumb().isEmpty()){
|
||||
|
|
@ -152,9 +191,16 @@ public class InfoUtil {
|
|||
return new PlaylistTuple(next, videos);
|
||||
}
|
||||
|
||||
|
||||
public Video getVideo(String id) throws JSONException {
|
||||
if (key.isEmpty()) return getFromYTDL("https://www.youtube.com/watch?v="+id).get(0);
|
||||
if (key.isEmpty()) {
|
||||
if (useInvidous){
|
||||
JSONObject res = genericRequest(invidousURL + "videos/"+id);
|
||||
if (res.length() == 0) return getFromYTDL("https://www.youtube.com/watch?v="+id).get(0);
|
||||
return createVideofromInvidiousJSON(res);
|
||||
}else{
|
||||
return getFromYTDL("https://www.youtube.com/watch?v="+id).get(0);
|
||||
}
|
||||
}
|
||||
|
||||
//short data
|
||||
JSONObject res = genericRequest("https://youtube.googleapis.com/youtube/v3/videos?part=snippet,contentDetails&id="+id+"&key="+key);
|
||||
|
|
@ -166,10 +212,9 @@ public class InfoUtil {
|
|||
|
||||
res.put("videoID", id);
|
||||
res.put("duration", duration);
|
||||
res = fixThumbnail(res);
|
||||
fixThumbnail(res);
|
||||
|
||||
Video v = createVideofromJSON(res);
|
||||
return v;
|
||||
return createVideofromJSON(res);
|
||||
}
|
||||
|
||||
private Video createVideofromJSON(JSONObject obj){
|
||||
|
|
@ -198,6 +243,31 @@ public class InfoUtil {
|
|||
return video;
|
||||
}
|
||||
|
||||
private Video createVideofromInvidiousJSON(JSONObject obj){
|
||||
Video video = null;
|
||||
try{
|
||||
String id = obj.getString("videoId");
|
||||
String title = obj.getString("title");
|
||||
title = Html.fromHtml(title).toString();
|
||||
String author = obj.getString("author");
|
||||
author = Html.fromHtml(author).toString();
|
||||
|
||||
String duration = formatIntegerDuration(obj.getInt("lengthSeconds"));
|
||||
String thumb = "https://i.ytimg.com/vi/"+id+"/hqdefault.jpg";
|
||||
|
||||
|
||||
String url = "https://www.youtube.com/watch?v=" + id;
|
||||
int downloadedAudio = dbManager.checkDownloaded(url, "audio");
|
||||
int downloadedVideo = dbManager.checkDownloaded(url, "video");
|
||||
int isPlaylist = 0;
|
||||
|
||||
video = new Video(id, url, title, author, duration, thumb, downloadedAudio, downloadedVideo, isPlaylist, "youtube", 0, 0, "");
|
||||
}catch(Exception e){
|
||||
Log.e(TAG, e.toString());
|
||||
}
|
||||
return video;
|
||||
}
|
||||
|
||||
private JSONObject genericRequest(String url){
|
||||
Log.e(TAG, url);
|
||||
|
||||
|
|
@ -231,10 +301,39 @@ public class InfoUtil {
|
|||
}catch(Exception e){
|
||||
Log.e(TAG, e.toString());
|
||||
}
|
||||
return json;
|
||||
}
|
||||
|
||||
private JSONArray genericArrayRequest(String url){
|
||||
Log.e(TAG, url);
|
||||
|
||||
BufferedReader reader;
|
||||
String line;
|
||||
StringBuilder responseContent = new StringBuilder();
|
||||
HttpURLConnection conn;
|
||||
JSONArray json = new JSONArray();
|
||||
|
||||
try{
|
||||
URL req = new URL(url);
|
||||
conn = (HttpURLConnection) req.openConnection();
|
||||
|
||||
conn.setRequestMethod("GET");
|
||||
conn.setConnectTimeout(10000);
|
||||
conn.setReadTimeout(5000);
|
||||
|
||||
if(conn.getResponseCode() < 300){
|
||||
reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
|
||||
while((line = reader.readLine()) != null){
|
||||
responseContent.append(line);
|
||||
}
|
||||
reader.close();
|
||||
|
||||
json = new JSONArray(responseContent.toString());
|
||||
}
|
||||
conn.disconnect();
|
||||
}catch(Exception e){
|
||||
Log.e(TAG, e.toString());
|
||||
}
|
||||
return json;
|
||||
}
|
||||
|
||||
|
|
@ -264,6 +363,66 @@ public class InfoUtil {
|
|||
return o;
|
||||
}
|
||||
|
||||
|
||||
public ArrayList<Video> getTrending(Context context) throws JSONException{
|
||||
videos = new ArrayList<>();
|
||||
if (key.isEmpty()) {
|
||||
if (useInvidous) return getTrendingFromInvidous(context);
|
||||
else return new ArrayList<>();
|
||||
}
|
||||
return getTrendingFromKey(context);
|
||||
}
|
||||
|
||||
public ArrayList<Video> getTrendingFromKey(Context context) throws JSONException{
|
||||
String url = "https://www.googleapis.com/youtube/v3/videos?part=snippet&chart=mostPopular&videoCategoryId=10®ionCode="+countryCODE+"&maxResults=25&key="+key;
|
||||
//short data
|
||||
JSONObject res = genericRequest(url);
|
||||
//extra data from the same videos
|
||||
JSONObject contentDetails = genericRequest("https://www.googleapis.com/youtube/v3/videos?part=contentDetails&chart=mostPopular&videoCategoryId=10®ionCode="+countryCODE+"&maxResults=25&key="+key);
|
||||
|
||||
if(!contentDetails.has("items")) return new ArrayList<>();
|
||||
|
||||
JSONArray dataArray = res.getJSONArray("items");
|
||||
JSONArray extraDataArray = contentDetails.getJSONArray("items");
|
||||
for(int i = 0; i < dataArray.length(); i++){
|
||||
JSONObject element = dataArray.getJSONObject(i);
|
||||
JSONObject snippet = element.getJSONObject("snippet");
|
||||
|
||||
String duration = extraDataArray.getJSONObject(i).getJSONObject("contentDetails").getString("duration");
|
||||
duration = formatDuration(duration);
|
||||
|
||||
snippet.put("videoID", element.getString("id"));
|
||||
snippet.put("duration", duration);
|
||||
fixThumbnail(snippet);
|
||||
|
||||
Video v = createVideofromJSON(snippet);
|
||||
if(v == null || v.getThumb().isEmpty()){
|
||||
continue;
|
||||
}
|
||||
v.setPlaylistTitle(context.getString(R.string.trendingPlaylist));
|
||||
videos.add(v);
|
||||
}
|
||||
return videos;
|
||||
}
|
||||
|
||||
public ArrayList<Video> getTrendingFromInvidous(Context context) {
|
||||
String url = invidousURL + "trending?type=music®ion="+countryCODE;
|
||||
JSONArray res = genericArrayRequest(url);
|
||||
try{
|
||||
for(int i = 0; i < res.length(); i++){
|
||||
JSONObject element = res.getJSONObject(i);
|
||||
if(!element.getString("type").equals("video")) continue;
|
||||
Video v = createVideofromInvidiousJSON(element);
|
||||
if(v == null || v.getThumb().isEmpty()) continue;
|
||||
v.setPlaylistTitle(context.getString(R.string.trendingPlaylist));
|
||||
videos.add(v);
|
||||
}
|
||||
}catch(Exception e){
|
||||
e.printStackTrace();
|
||||
}
|
||||
return videos;
|
||||
}
|
||||
|
||||
public ArrayList<Video> getFromYTDL(String query){
|
||||
videos = new ArrayList<>();
|
||||
try {
|
||||
|
|
@ -349,42 +508,26 @@ public class InfoUtil {
|
|||
return videos;
|
||||
}
|
||||
|
||||
public ArrayList<Video> getTrending(Context context) throws JSONException{
|
||||
if (key.isEmpty()) return new ArrayList<>();
|
||||
|
||||
videos = new ArrayList<>();
|
||||
|
||||
String url = "https://www.googleapis.com/youtube/v3/videos?part=snippet&chart=mostPopular&videoCategoryId=10®ionCode="+countryCODE+"&maxResults=25&key="+key;
|
||||
//short data
|
||||
public ArrayList<String> getSearchSuggestions(String query){
|
||||
if (!useInvidous) return new ArrayList<>();
|
||||
String url = invidousURL + "search/suggestions?q="+query;
|
||||
JSONObject res = genericRequest(url);
|
||||
//extra data from the same videos
|
||||
JSONObject contentDetails = genericRequest("https://www.googleapis.com/youtube/v3/videos?part=contentDetails&chart=mostPopular&videoCategoryId=10®ionCode="+countryCODE+"&maxResults=25&key="+key);
|
||||
if(res.length() == 0) return new ArrayList<>();
|
||||
|
||||
if(!contentDetails.has("items")) return new ArrayList<>();
|
||||
|
||||
JSONArray dataArray = res.getJSONArray("items");
|
||||
JSONArray extraDataArray = contentDetails.getJSONArray("items");
|
||||
for(int i = 0; i < dataArray.length(); i++){
|
||||
JSONObject element = dataArray.getJSONObject(i);
|
||||
JSONObject snippet = element.getJSONObject("snippet");
|
||||
|
||||
String duration = extraDataArray.getJSONObject(i).getJSONObject("contentDetails").getString("duration");
|
||||
duration = formatDuration(duration);
|
||||
|
||||
snippet.put("videoID", element.getString("id"));
|
||||
snippet.put("duration", duration);
|
||||
snippet = fixThumbnail(snippet);
|
||||
|
||||
Video v = createVideofromJSON(snippet);
|
||||
if(v == null || v.getThumb().isEmpty()){
|
||||
continue;
|
||||
ArrayList<String> suggestionList = new ArrayList<>();
|
||||
try{
|
||||
JSONArray suggestions = res.getJSONArray("suggestions");
|
||||
for (int i = 0; i < suggestions.length(); i++){
|
||||
suggestionList.add(suggestions.getString(i));
|
||||
}
|
||||
v.setPlaylistTitle(context.getString(R.string.trendingPlaylist));
|
||||
videos.add(v);
|
||||
}
|
||||
return videos;
|
||||
}catch(Exception ignored){}
|
||||
|
||||
return suggestionList;
|
||||
}
|
||||
|
||||
|
||||
public String formatDuration(String dur){
|
||||
if(dur.equals("P0D")){
|
||||
return "LIVE";
|
||||
|
|
@ -426,45 +569,6 @@ public class InfoUtil {
|
|||
return format;
|
||||
}
|
||||
|
||||
// public ArrayList<String> getSearchHints(String query){
|
||||
// String url = "https://google.com/complete/search?client=youtube&q="+query;
|
||||
// ArrayList<String> searchHints = new ArrayList<>();
|
||||
//
|
||||
// BufferedReader reader;
|
||||
// String line;
|
||||
// StringBuilder responseContent = new StringBuilder();
|
||||
// HttpURLConnection conn;
|
||||
// JSONArray json;
|
||||
//
|
||||
// try{
|
||||
// URL req = new URL(url);
|
||||
// conn = (HttpURLConnection) req.openConnection();
|
||||
//
|
||||
// conn.setRequestMethod("GET");
|
||||
// conn.setConnectTimeout(10000);
|
||||
// conn.setReadTimeout(5000);
|
||||
//
|
||||
// if(conn.getResponseCode() < 300){
|
||||
// reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
|
||||
// while((line = reader.readLine()) != null){
|
||||
// responseContent.append(line);
|
||||
// }
|
||||
// reader.close();
|
||||
// String content = responseContent.substring(19, responseContent.length()-1);
|
||||
//
|
||||
// json = new JSONArray(content);
|
||||
// JSONArray hints = (JSONArray) json.get(1);
|
||||
// for (int i = 0; i < hints.length(); i++){
|
||||
// searchHints.add(hints.getJSONArray(i).get(0).toString());
|
||||
// }
|
||||
// }
|
||||
// conn.disconnect();
|
||||
// }catch(Exception e){
|
||||
// Log.e(TAG, e.toString());
|
||||
// }
|
||||
// return searchHints;
|
||||
// }
|
||||
|
||||
public static class PlaylistTuple {
|
||||
String nextPageToken;
|
||||
ArrayList<Video> videos;
|
||||
|
|
|
|||
|
|
@ -78,7 +78,7 @@ public class NotificationUtil {
|
|||
.setContentIntent(pendingIntent)
|
||||
.setForegroundServiceBehavior(NotificationCompat.FOREGROUND_SERVICE_IMMEDIATE)
|
||||
.clearActions()
|
||||
//.addAction(0, context.getString(R.string.cancel), cancelNotificationPendingIntent)
|
||||
.addAction(0, context.getString(R.string.cancel), cancelNotificationPendingIntent)
|
||||
.build();
|
||||
|
||||
return notification;
|
||||
|
|
|
|||
5
app/src/main/res/drawable/ic_arrow_up.xml
Normal file
5
app/src/main/res/drawable/ic_arrow_up.xml
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
<vector android:height="24dp"
|
||||
android:viewportHeight="24" android:viewportWidth="24"
|
||||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="?android:textColorPrimary" android:pathData="M4,12l1.41,1.41L11,7.83V20h2V7.83l5.58,5.59L20,12l-8,-8 -8,8z"/>
|
||||
</vector>
|
||||
|
|
@ -27,6 +27,21 @@
|
|||
|
||||
</com.google.android.material.appbar.AppBarLayout>
|
||||
|
||||
<ScrollView
|
||||
android:id="@+id/search_suggestions_scroll_view"
|
||||
android:layout_width="match_parent"
|
||||
android:visibility="gone"
|
||||
android:layout_marginTop="?attr/actionBarSize"
|
||||
android:layout_height="wrap_content">
|
||||
<LinearLayout
|
||||
android:id="@+id/search_suggestions_linear_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<include layout="@layout/search_suggestion_item" />
|
||||
</LinearLayout>
|
||||
</ScrollView>
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:layout_width="match_parent"
|
||||
|
|
|
|||
67
app/src/main/res/layout/search_suggestion_item.xml
Normal file
67
app/src/main/res/layout/search_suggestion_item.xml
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/search_suggestions_constraintLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/downloads_relative_layout"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
app:layout_constraintDimensionRatio="H,8:1"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
android:id="@+id/downloads_card_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
app:cardBackgroundColor="@android:color/transparent"
|
||||
android:checkable="true"
|
||||
app:strokeWidth="0dp"
|
||||
app:cardPreventCornerOverlap="true"
|
||||
android:layout_margin="10dp">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
style="@style/Widget.Material3.Button.IconButton"
|
||||
android:layout_width="40dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="0.01"
|
||||
app:icon="@drawable/ic_search"
|
||||
/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/suggestion_text"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:gravity="center_vertical"
|
||||
android:paddingStart="20dp"
|
||||
android:paddingEnd="20dp"
|
||||
android:textSize="16sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
style="@style/Widget.Material3.Button.IconButton"
|
||||
android:id="@+id/set_search_query_button"
|
||||
android:layout_width="40dp"
|
||||
android:layout_height="match_parent"
|
||||
app:icon="@drawable/ic_arrow_up"
|
||||
android:layout_weight="0.01"
|
||||
/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
</RelativeLayout>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
Loading…
Reference in a new issue