comment #5 - searches

This commit is contained in:
Thomas 2020-10-09 14:54:01 +02:00
parent fb83a1927d
commit fd7632f001
9 changed files with 788 additions and 55 deletions

View File

@ -22,7 +22,6 @@ import android.content.SharedPreferences;
import android.database.sqlite.SQLiteDatabase;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.EditText;
@ -151,7 +150,6 @@ public class MainActivity extends AppCompatActivity {
overviewFragment = new DisplayOverviewFragment();
Log.v(Helper.TAG,"active: " + active);
if( active == null) {
active = overviewFragment;
}

View File

@ -16,29 +16,286 @@ package app.fedilab.fedilabtube;
import android.os.Bundle;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.RadioGroup;
import android.widget.Spinner;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.FragmentTransaction;
import androidx.constraintlayout.widget.ConstraintLayout;
import androidx.lifecycle.ViewModelProvider;
import app.fedilab.fedilabtube.fragment.DisplayVideosFragment;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import app.fedilab.fedilabtube.client.data.VideoData;
import app.fedilab.fedilabtube.client.entities.SepiaSearch;
import app.fedilab.fedilabtube.helper.Helper;
import app.fedilab.fedilabtube.viewmodel.SepiaSearchVM;
import mabbas007.tagsedittext.TagsEditText;
import static app.fedilab.fedilabtube.MainActivity.peertubeInformation;
public class SepiaSearchActivity extends AppCompatActivity {
private SepiaSearch sepiaSearchVideo;
private SepiaSearch sepiaSearchChannel;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_sepia_search);
sepiaSearchVideo = new SepiaSearch();
sepiaSearchChannel = new SepiaSearch();
if (getSupportActionBar() != null)
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
Button filter = findViewById(R.id.filter);
ConstraintLayout filter_elements = findViewById(R.id.filter_elements);
filter.setOnClickListener(view -> {
if( filter_elements.getVisibility() == View.VISIBLE) {
filter_elements.setVisibility(View.GONE);
}else{
filter_elements.setVisibility(View.VISIBLE);
}
});
RadioGroup sepia_element_nsfw = findViewById(R.id.sepia_element_nsfw);
sepia_element_nsfw.setOnCheckedChangeListener((group, checkedId) -> {
if (checkedId == R.id.sepia_element_nsfw_no) {
sepiaSearchVideo.setNsfw(false);
} else {
sepiaSearchVideo.setNsfw(true);
}
});
RadioGroup radio_date = findViewById(R.id.radio_date);
radio_date.setOnCheckedChangeListener((group, checkedId) -> {
switch(checkedId){
case R.id.sepia_element_published_date_today:
Calendar cal = GregorianCalendar.getInstance();
cal.set(Calendar.HOUR_OF_DAY, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);
sepiaSearchVideo.setStartDate(cal.getTime());
break;
case R.id.sepia_element_published_date_last_7_days:
cal = GregorianCalendar.getInstance();
cal.setTime(new Date());
cal.add(Calendar.DAY_OF_YEAR, -7);
sepiaSearchVideo.setStartDate(cal.getTime());
break;
case R.id.sepia_element_published_date_last_30_days:
cal = GregorianCalendar.getInstance();
cal.setTime(new Date());
cal.add(Calendar.DAY_OF_YEAR, -30);
sepiaSearchVideo.setStartDate(cal.getTime());
break;
case R.id.sepia_element_published_date_last_365_days:
cal = GregorianCalendar.getInstance();
cal.setTime(new Date());
cal.add(Calendar.DAY_OF_YEAR, -365);
sepiaSearchVideo.setStartDate(cal.getTime());
break;
default:
sepiaSearchVideo.setStartDate(null);
}
});
RadioGroup duration = findViewById(R.id.duration);
duration.setOnCheckedChangeListener((group, checkedId) -> {
switch(checkedId){
case R.id.sepia_element_duration_short:
sepiaSearchVideo.setDurationMin(0);
sepiaSearchVideo.setDurationMax(240);
break;
case R.id.sepia_element_duration_medium:
sepiaSearchVideo.setDurationMin(240);
sepiaSearchVideo.setDurationMax(600);
break;
case R.id.sepia_element_duration_long:
sepiaSearchVideo.setDurationMin(600);
sepiaSearchVideo.setDurationMax(999999999);
break;
default:
sepiaSearchVideo.setDurationMin(0);
sepiaSearchVideo.setDurationMax(999999999);
break;
}
});
Spinner sort_by = findViewById(R.id.sort_by);
ArrayAdapter<String> adapterSortBy = new ArrayAdapter<>(SepiaSearchActivity.this,
android.R.layout.simple_spinner_dropdown_item, getResources().getStringArray(R.array.sort_by_array));
sort_by.setAdapter(adapterSortBy);
sort_by.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
String orderby, channelOrderBy;
switch (position){
case 1:
orderby = "-publishedAt";
channelOrderBy = "-createdAt";
break;
case 2:
orderby = "publishedAt";
channelOrderBy = "createdAt";
break;
default:
orderby = "-match";
channelOrderBy = null;
}
sepiaSearchVideo.setSort(orderby);
sepiaSearchChannel.setSort(channelOrderBy);
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
Spinner sepia_element_category = findViewById(R.id.sepia_element_category);
Spinner sepia_element_license = findViewById(R.id.sepia_element_license);
Spinner sepia_element_language = findViewById(R.id.sepia_element_language);
TagsEditText sepia_element_all_of_tags = findViewById(R.id.sepia_element_all_of_tags);
TagsEditText sepia_element_one_of_tags = findViewById(R.id.sepia_element_one_of_tags);
LinkedHashMap<Integer, String> categories = new LinkedHashMap<>(peertubeInformation.getCategories());
LinkedHashMap<Integer, String> licences = new LinkedHashMap<>(peertubeInformation.getLicences());
LinkedHashMap<String, String> languages = new LinkedHashMap<>(peertubeInformation.getLanguages());
LinkedHashMap<String, String> translations = new LinkedHashMap<>(peertubeInformation.getTranslations());
//Populate catgories
String[] categoriesA = new String[categories.size()+1];
categoriesA[0] = getString(R.string.display_all_categories);
Iterator<Map.Entry<Integer, String>> it = categories.entrySet().iterator();
int i = 1;
while (it.hasNext()) {
Map.Entry<Integer, String> pair = it.next();
if (translations.size() == 0 || !translations.containsKey(pair.getValue()))
categoriesA[i] = pair.getValue();
else
categoriesA[i] = translations.get(pair.getValue());
it.remove();
i++;
}
ArrayAdapter<String> adapterCatgories = new ArrayAdapter<>(SepiaSearchActivity.this,
android.R.layout.simple_spinner_dropdown_item, categoriesA);
sepia_element_category.setAdapter(adapterCatgories);
//Populate licenses
String[] licensesA = new String[licences.size()+1];
licensesA[0] = getString(R.string.display_all_licenses);
it = licences.entrySet().iterator();
i = 1;
while (it.hasNext()) {
Map.Entry<Integer, String> pair = it.next();
if (translations.size() == 0 || !translations.containsKey(pair.getValue()))
licensesA[i] = pair.getValue();
else
licensesA[i] = translations.get(pair.getValue());
it.remove();
i++;
}
ArrayAdapter<String> adapterLicenses = new ArrayAdapter<>(SepiaSearchActivity.this,
android.R.layout.simple_spinner_dropdown_item, licensesA);
sepia_element_license.setAdapter(adapterLicenses);
//Populate languages
String[] languagesA = new String[languages.size()+1];
languagesA[0] = getString(R.string.display_all_languages);
Iterator<Map.Entry<String, String>> itl = languages.entrySet().iterator();
i = 1;
while (itl.hasNext()) {
Map.Entry<String, String> pair = itl.next();
if (translations.size() == 0 || !translations.containsKey(pair.getValue()))
languagesA[i] = pair.getValue();
else
languagesA[i] = translations.get(pair.getValue());
itl.remove();
i++;
}
ArrayAdapter<String> adapterLanguages = new ArrayAdapter<>(SepiaSearchActivity.this,
android.R.layout.simple_spinner_dropdown_item, languagesA);
sepia_element_language.setAdapter(adapterLanguages);
sepia_element_license.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
updateLicensePosition(position);
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
//Manage categories
sepia_element_category.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
updateCategoryPosition(position);
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
//Manage languages
sepia_element_language.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
updateLanguagesPosition(position);
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
Button apply_filter = findViewById(R.id.apply_filter);
apply_filter.setOnClickListener(v->{
if( sepia_element_one_of_tags.getTags().size() > 0 ) {
sepiaSearchVideo.setTagsOneOf(sepia_element_one_of_tags.getTags());
}else{
sepiaSearchVideo.setTagsOneOf(null);
}
if( sepia_element_all_of_tags.getTags().size() > 0 ) {
sepiaSearchVideo.setTagsAllOf(sepia_element_all_of_tags.getTags());
}else{
sepiaSearchVideo.setTagsAllOf(null);
}
SepiaSearchVM sepiaSearchVM = new ViewModelProvider(SepiaSearchActivity.this).get(SepiaSearchVM.class);
sepiaSearchVM.sepiaSearch(sepiaSearchVideo).observe(SepiaSearchActivity.this, this::manageVideos);
});
}
@ -51,4 +308,65 @@ public class SepiaSearchActivity extends AppCompatActivity {
return super.onOptionsItemSelected(item);
}
private void manageVideos(VideoData videoData) {
}
private void updateLanguagesPosition(int position) {
LinkedHashMap<String, String> languagesCheck = new LinkedHashMap<>(peertubeInformation.getLanguages());
Iterator<Map.Entry<String, String>> it = languagesCheck.entrySet().iterator();
int i = 0;
while (it.hasNext()) {
Map.Entry<String, String> pair = it.next();
if (i == position && position > 0) {
List<String> languages = new ArrayList<>();
languages.add(pair.getKey());
sepiaSearchVideo.setBoostLanguages(languages);
break;
}else {
sepiaSearchVideo.setBoostLanguages(null);
}
it.remove();
i++;
}
}
private void updateCategoryPosition(int position) {
LinkedHashMap<Integer, String> categoriesCheck = new LinkedHashMap<>(peertubeInformation.getCategories());
Iterator<Map.Entry<Integer, String>> it = categoriesCheck.entrySet().iterator();
int i = 0;
while (it.hasNext()) {
Map.Entry<Integer, String> pair = it.next();
if (i == position && position > 0 ) {
List<Integer> categories = new ArrayList<>();
categories.add(pair.getKey());
sepiaSearchVideo.setCategoryOneOf(categories);
break;
}else {
sepiaSearchVideo.setCategoryOneOf(null);
}
it.remove();
i++;
}
}
private void updateLicensePosition(int position) {
LinkedHashMap<Integer, String> licensesCheck = new LinkedHashMap<>(peertubeInformation.getLicences());
Iterator<Map.Entry<Integer, String>> it = licensesCheck.entrySet().iterator();
int i = 0;
while (it.hasNext()) {
Map.Entry<Integer, String> pair = it.next();
if (i == position && position > 0) {
List<Integer> licenses = new ArrayList<>();
licenses.add(pair.getKey());
sepiaSearchVideo.setLicenceOneOf(licenses);
break;
}else {
sepiaSearchVideo.setLicenceOneOf(null);
}
it.remove();
i++;
}
}
}

View File

@ -17,26 +17,25 @@ package app.fedilab.fedilabtube.client;
import android.content.Context;
import android.content.SharedPreferences;
import java.util.Set;
import app.fedilab.fedilabtube.R;
import java.io.IOException;
import app.fedilab.fedilabtube.client.data.VideoData;
import app.fedilab.fedilabtube.client.entities.SepiaSearch;
import app.fedilab.fedilabtube.helper.Helper;
import retrofit2.Call;
import retrofit2.Response;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
class RetrofitSepiaSearchAPI {
public class RetrofitSepiaSearchAPI {
private String finalUrl;
private Context _context;
private Set<String> selection;
private String count;
public RetrofitSepiaSearchAPI(Context context) {
_context = context;
finalUrl = "https://search.joinpeertube.org/api/v1/";
SharedPreferences sharedpreferences = _context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
count = String.valueOf(sharedpreferences.getInt(Helper.SET_VIDEOS_PER_PAGE, Helper.VIDEOS_PER_PAGE));
}
@ -45,11 +44,38 @@ class RetrofitSepiaSearchAPI {
.baseUrl(finalUrl)
.addConverterFactory(GsonConverterFactory.create())
.build();
SharedPreferences sharedpreferences = _context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
selection = sharedpreferences.getStringSet(_context.getString(R.string.set_video_language_choice), null);
return retrofit.create(SepiaSearchService.class);
}
/**
* Return videos for a sepia search
* @param sepiaSearch SepiaSearch
* @return VideoData
*/
public VideoData getVideos(SepiaSearch sepiaSearch) {
SepiaSearchService sepiaSearchService = init();
Call<VideoData> videoDataCall = sepiaSearchService.getVideos(
sepiaSearch.getStart(),
count,
sepiaSearch.getSearch(),
sepiaSearch.getDurationMax(),
sepiaSearch.getStartDate(),
sepiaSearch.getBoostLanguages(),
sepiaSearch.getCategoryOneOf(),
sepiaSearch.getLicenceOneOf(),
sepiaSearch.getTagsOneOf(),
sepiaSearch.getTagsAllOf(),
sepiaSearch.isNsfw(),
sepiaSearch.getSort());
try {
Response<VideoData> response = videoDataCall.execute();
if (response.isSuccessful() && response.body() != null) {
return response.body();
}
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}

View File

@ -33,8 +33,8 @@ interface SepiaSearchService {
@Query("durationMax") int durationMax,
@Query("startDate") Date startDate,
@Query("boostLanguages") List<String> languageOneOf,
@Query("categoryOneOf") List<String> categoryOneOf,
@Query("licenceOneOf") List<String> licenceOneOf,
@Query("categoryOneOf") List<Integer> categoryOneOf,
@Query("licenceOneOf") List<Integer> licenceOneOf,
@Query("tagsOneOf") List<String> tagsOneOf,
@Query("tagsAllOf") List<String> tagsAllOf,
@Query("nsfw") boolean nsfw,

View File

@ -19,11 +19,12 @@ import android.os.Parcelable;
import com.google.gson.annotations.SerializedName;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
@SuppressWarnings("unused")
class SepiaSearch implements Parcelable {
public class SepiaSearch implements Parcelable {
@SerializedName("start")
private String start;
@ -33,14 +34,16 @@ class SepiaSearch implements Parcelable {
private String search;
@SerializedName("durationMax")
private int durationMax;
@SerializedName("durationMin")
private int durationMin;
@SerializedName("startDate")
private Date startDate;
@SerializedName("boostLanguages")
private List<String> boostLanguages;
@SerializedName("categoryOneOf")
private List<String> categoryOneOf;
private List<Integer> categoryOneOf;
@SerializedName("licenceOneOf")
private List<String> licenceOneOf;
private List<Integer> licenceOneOf;
@SerializedName("tagsOneOf")
private List<String> tagsOneOf;
@SerializedName("tagsAllOf")
@ -84,6 +87,14 @@ class SepiaSearch implements Parcelable {
this.durationMax = durationMax;
}
public int getDurationMin() {
return durationMin;
}
public void setDurationMin(int durationMin) {
this.durationMin = durationMin;
}
public Date getStartDate() {
return startDate;
}
@ -100,19 +111,19 @@ class SepiaSearch implements Parcelable {
this.boostLanguages = boostLanguages;
}
public List<String> getCategoryOneOf() {
public List<Integer> getCategoryOneOf() {
return categoryOneOf;
}
public void setCategoryOneOf(List<String> categoryOneOf) {
public void setCategoryOneOf(List<Integer> categoryOneOf) {
this.categoryOneOf = categoryOneOf;
}
public List<String> getLicenceOneOf() {
public List<Integer> getLicenceOneOf() {
return licenceOneOf;
}
public void setLicenceOneOf(List<String> licenceOneOf) {
public void setLicenceOneOf(List<Integer> licenceOneOf) {
this.licenceOneOf = licenceOneOf;
}
@ -159,10 +170,11 @@ class SepiaSearch implements Parcelable {
dest.writeString(this.count);
dest.writeString(this.search);
dest.writeInt(this.durationMax);
dest.writeInt(this.durationMin);
dest.writeLong(this.startDate != null ? this.startDate.getTime() : -1);
dest.writeStringList(this.boostLanguages);
dest.writeStringList(this.categoryOneOf);
dest.writeStringList(this.licenceOneOf);
dest.writeList(this.categoryOneOf);
dest.writeList(this.licenceOneOf);
dest.writeStringList(this.tagsOneOf);
dest.writeStringList(this.tagsAllOf);
dest.writeByte(this.nsfw ? (byte) 1 : (byte) 0);
@ -177,18 +189,21 @@ class SepiaSearch implements Parcelable {
this.count = in.readString();
this.search = in.readString();
this.durationMax = in.readInt();
this.durationMin = in.readInt();
long tmpStartDate = in.readLong();
this.startDate = tmpStartDate == -1 ? null : new Date(tmpStartDate);
this.boostLanguages = in.createStringArrayList();
this.categoryOneOf = in.createStringArrayList();
this.licenceOneOf = in.createStringArrayList();
this.categoryOneOf = new ArrayList<>();
in.readList(this.categoryOneOf, Integer.class.getClassLoader());
this.licenceOneOf = new ArrayList<>();
in.readList(this.licenceOneOf, Integer.class.getClassLoader());
this.tagsOneOf = in.createStringArrayList();
this.tagsAllOf = in.createStringArrayList();
this.nsfw = in.readByte() != 0;
this.sort = in.readString();
}
public static final Parcelable.Creator<SepiaSearch> CREATOR = new Parcelable.Creator<SepiaSearch>() {
public static final Creator<SepiaSearch> CREATOR = new Creator<SepiaSearch>() {
@Override
public SepiaSearch createFromParcel(Parcel source) {
return new SepiaSearch(source);

View File

@ -0,0 +1,319 @@
package app.fedilab.fedilabtube.fragment;
/* Copyright 2020 Thomas Schneider
*
* This file is a part of TubeLab
*
* This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation; either version 3 of the
* License, or (at your option) any later version.
*
* TubeLab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
* Public License for more details.
*
* You should have received a copy of the GNU General Public License along with TubeLab; if not,
* see <http://www.gnu.org/licenses>. */
import android.content.Context;
import android.content.SharedPreferences;
import android.graphics.Rect;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.inputmethod.InputMethodManager;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProvider;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.List;
import app.fedilab.fedilabtube.R;
import app.fedilab.fedilabtube.client.data.VideoData;
import app.fedilab.fedilabtube.client.entities.SepiaSearch;
import app.fedilab.fedilabtube.drawer.AccountsHorizontalListAdapter;
import app.fedilab.fedilabtube.drawer.PeertubeAdapter;
import app.fedilab.fedilabtube.helper.Helper;
import app.fedilab.fedilabtube.viewmodel.SepiaSearchVM;
import es.dmoral.toasty.Toasty;
public class DisplaySepiaSearchFragment extends Fragment implements AccountsHorizontalListAdapter.EventListener {
private LinearLayoutManager mLayoutManager;
private GridLayoutManager gLayoutManager;
private boolean flag_loading;
private Context context;
private PeertubeAdapter peertubeAdapater;
private String max_id;
private List<VideoData.Video> peertubes;
private RelativeLayout mainLoader, nextElementLoader, textviewNoAction;
private boolean firstLoad;
private SwipeRefreshLayout swipeRefreshLayout;
private SharedPreferences sharedpreferences;
private TextView textviewNoActionText;
private View rootView;
private RecyclerView lv_status;
private SepiaSearchVM viewModelSearch;
public DisplaySepiaSearchFragment() {
}
private SepiaSearch sepiaSearchVideo;
@Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
rootView = inflater.inflate(R.layout.fragment_video, container, false);
peertubes = new ArrayList<>();
context = getContext();
Bundle bundle = this.getArguments();
if (bundle != null) {
sepiaSearchVideo = bundle.getParcelable("sepiaSearchVideo");
}
max_id = "0";
lv_status = rootView.findViewById(R.id.lv_status);
flag_loading = true;
firstLoad = true;
assert context != null;
sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
swipeRefreshLayout = rootView.findViewById(R.id.swipeContainer);
mainLoader = rootView.findViewById(R.id.loader);
nextElementLoader = rootView.findViewById(R.id.loading_next_status);
textviewNoAction = rootView.findViewById(R.id.no_action);
textviewNoActionText = rootView.findViewById(R.id.no_action_text);
mainLoader.setVisibility(View.VISIBLE);
nextElementLoader.setVisibility(View.GONE);
peertubeAdapater = new PeertubeAdapter(this.peertubes);
lv_status.setAdapter(peertubeAdapater);
if (!Helper.isTablet(context)) {
mLayoutManager = new LinearLayoutManager(context);
lv_status.setLayoutManager(mLayoutManager);
} else {
gLayoutManager = new GridLayoutManager(context, 2);
int spanCount = (int) Helper.convertDpToPixel(2, context);
int spacing = (int) Helper.convertDpToPixel(5, context);
lv_status.addItemDecoration(new GridSpacingItemDecoration(spanCount, spacing, true));
lv_status.setLayoutManager(gLayoutManager);
}
viewModelSearch = new ViewModelProvider(DisplaySepiaSearchFragment.this).get(SepiaSearchVM.class);
swipeRefreshLayout.setOnRefreshListener(this::pullToRefresh);
lv_status.addOnScrollListener(new RecyclerView.OnScrollListener() {
public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
if (mLayoutManager != null) {
int firstVisibleItem = mLayoutManager.findFirstVisibleItemPosition();
if (dy > 0) {
int visibleItemCount = mLayoutManager.getChildCount();
int totalItemCount = mLayoutManager.getItemCount();
if (firstVisibleItem + visibleItemCount == totalItemCount && context != null) {
if (!flag_loading) {
flag_loading = true;
loadTimeline();
nextElementLoader.setVisibility(View.VISIBLE);
}
} else {
nextElementLoader.setVisibility(View.GONE);
}
}
} else if (gLayoutManager != null) {
int firstVisibleItem = gLayoutManager.findFirstVisibleItemPosition();
if (dy > 0) {
int visibleItemCount = gLayoutManager.getChildCount();
int totalItemCount = gLayoutManager.getItemCount();
if (firstVisibleItem + visibleItemCount == totalItemCount && context != null) {
if (!flag_loading) {
flag_loading = true;
loadTimeline();
nextElementLoader.setVisibility(View.VISIBLE);
}
} else {
nextElementLoader.setVisibility(View.GONE);
}
}
}
}
});
loadTimeline();
return rootView;
}
@Override
public void onPause() {
super.onPause();
if (swipeRefreshLayout != null) {
swipeRefreshLayout.setEnabled(false);
swipeRefreshLayout.setRefreshing(false);
swipeRefreshLayout.clearAnimation();
}
if (getActivity() != null) {
InputMethodManager imm = (InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVICE);
if (imm != null && getView() != null) {
imm.hideSoftInputFromWindow(getView().getWindowToken(), 0);
}
}
}
@Override
public void onCreate(Bundle saveInstance) {
super.onCreate(saveInstance);
}
@Override
public void onAttach(@NotNull Context context) {
super.onAttach(context);
this.context = context;
}
@Override
public void onStop() {
super.onStop();
}
@Override
public void onDestroy() {
super.onDestroy();
}
private void manageVIewVideos(VideoData videoData) {
//hide loaders
mainLoader.setVisibility(View.GONE);
nextElementLoader.setVisibility(View.GONE);
//handle other API error
if (videoData == null || videoData.data == null) {
Toasty.error(context, context.getString(R.string.toast_error), Toast.LENGTH_LONG).show();
swipeRefreshLayout.setRefreshing(false);
flag_loading = false;
return;
}
int previousPosition = this.peertubes.size();
if (max_id == null)
max_id = "0";
int videoPerPage = sharedpreferences.getInt(Helper.SET_VIDEOS_PER_PAGE, Helper.VIDEOS_PER_PAGE);
max_id = String.valueOf(Integer.parseInt(max_id) + videoPerPage);
this.peertubes.addAll(videoData.data);
//If no item were inserted previously the adapter is created
if (previousPosition == 0) {
peertubeAdapater = new PeertubeAdapter(this.peertubes);
lv_status.setAdapter(peertubeAdapater);
} else
peertubeAdapater.notifyItemRangeInserted(previousPosition, videoData.data.size());
//remove handlers
swipeRefreshLayout.setRefreshing(false);
textviewNoAction.setVisibility(View.GONE);
if (firstLoad && (videoData.data== null || videoData.data.size() == 0)) {
textviewNoActionText.setText(R.string.no_video_to_display);
textviewNoAction.setVisibility(View.VISIBLE);
}
flag_loading = false;
firstLoad = false;
}
@Override
public void onDestroyView() {
if (lv_status != null) {
try {
lv_status.setAdapter(null);
} catch (Exception ignored) {
}
}
super.onDestroyView();
rootView = null;
}
@Override
public void onResume() {
super.onResume();
swipeRefreshLayout.setEnabled(true);
}
public void scrollToTop() {
if (mLayoutManager != null) {
mLayoutManager.scrollToPositionWithOffset(0, 0);
} else if (gLayoutManager != null) {
gLayoutManager.scrollToPositionWithOffset(0, 0);
}
}
public void pullToRefresh() {
int size = peertubes.size();
peertubes.clear();
peertubes = new ArrayList<>();
peertubeAdapater.notifyItemRangeRemoved(0, size);
loadTimeline();
}
@Override
public void click(String forAccount) {
pullToRefresh();
}
private void loadTimeline() {
viewModelSearch.sepiaSearch(sepiaSearchVideo).observe(this.requireActivity(), this::manageVIewVideos);
}
static class GridSpacingItemDecoration extends RecyclerView.ItemDecoration {
private int spanCount;
private int spacing;
private boolean includeEdge;
public GridSpacingItemDecoration(int spanCount, int spacing, boolean includeEdge) {
this.spanCount = spanCount;
this.spacing = spacing;
this.includeEdge = includeEdge;
}
@Override
public void getItemOffsets(@NotNull Rect outRect, @NotNull View view, RecyclerView parent, @NotNull RecyclerView.State state) {
int position = parent.getChildAdapterPosition(view);
int column = position % spanCount;
if (includeEdge) {
outRect.left = spacing - column * spacing / spanCount;
outRect.right = (column + 1) * spacing / spanCount;
if (position < spanCount) {
outRect.top = spacing;
}
outRect.bottom = spacing;
} else {
outRect.left = column * spacing / spanCount;
outRect.right = spacing - (column + 1) * spacing / spanCount;
if (position >= spanCount) {
outRect.top = spacing;
}
}
}
}
}

View File

@ -119,7 +119,6 @@ public class DisplayVideosFragment extends Fragment implements AccountsHorizonta
RecyclerView lv_accounts = rootView.findViewById(R.id.lv_accounts);
Button display_all = rootView.findViewById(R.id.display_all);
top_account_container = rootView.findViewById(R.id.top_account_container);
max_id = null;
max_id_accounts = null;
flag_loading = true;
firstLoad = true;

View File

@ -0,0 +1,58 @@
package app.fedilab.fedilabtube.viewmodel;
/* Copyright 2020 Thomas Schneider
*
* This file is a part of TubeLab
*
* This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation; either version 3 of the
* License, or (at your option) any later version.
*
* TubeLab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
* Public License for more details.
*
* You should have received a copy of the GNU General Public License along with TubeLab; if not,
* see <http://www.gnu.org/licenses>. */
import android.app.Application;
import android.content.Context;
import android.os.Handler;
import android.os.Looper;
import androidx.annotation.NonNull;
import androidx.lifecycle.AndroidViewModel;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData;
import app.fedilab.fedilabtube.client.RetrofitSepiaSearchAPI;
import app.fedilab.fedilabtube.client.data.VideoData;
import app.fedilab.fedilabtube.client.entities.SepiaSearch;
public class SepiaSearchVM extends AndroidViewModel {
private MutableLiveData<VideoData> apiResponseMutableLiveData;
public SepiaSearchVM(@NonNull Application application) {
super(application);
}
public LiveData<VideoData> sepiaSearch(SepiaSearch sepiaSearch) {
apiResponseMutableLiveData = new MutableLiveData<>();
getVideos(sepiaSearch);
return apiResponseMutableLiveData;
}
private void getVideos(SepiaSearch sepiaSearch) {
Context _mContext = getApplication().getApplicationContext();
new Thread(() -> {
try {
VideoData videoData = new RetrofitSepiaSearchAPI(_mContext).getVideos(sepiaSearch);
Handler mainHandler = new Handler(Looper.getMainLooper());
Runnable myRunnable = () -> apiResponseMutableLiveData.setValue(videoData);
mainHandler.post(myRunnable);
} catch (Exception e) {
e.printStackTrace();
}
}).start();
}
}

View File

@ -33,6 +33,7 @@
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent"
android:id="@+id/header"
android:animateLayoutChanges="true"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent">
<com.mancj.materialsearchbar.MaterialSearchBar
@ -88,6 +89,8 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/filter_elements"
android:visibility="gone"
android:animateLayoutChanges="true"
app:layout_constraintTop_toBottomOf="@+id/filter"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent">
@ -141,6 +144,7 @@
app:layout_constraintTop_toBottomOf="@+id/sepia_element_published_date_label"
app:layout_constraintStart_toStartOf="parent">
<RadioGroup
android:id="@+id/radio_date"
android:orientation="horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
@ -191,6 +195,7 @@
app:layout_constraintTop_toBottomOf="@+id/sepia_element_duration_label"
app:layout_constraintStart_toStartOf="parent">
<RadioGroup
android:id="@+id/duration"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
@ -225,53 +230,48 @@
android:text="@string/category"
app:layout_constraintTop_toBottomOf="@+id/sepia_element_duration"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toStartOf="@+id/sepia_element_license_label"
android:id="@+id/sepia_element_category_label"
/>
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:labelFor="@+id/sepia_element_license"
android:text="@string/license"
app:layout_constraintStart_toEndOf="@+id/sepia_element_category_label"
app:layout_constraintTop_toBottomOf="@+id/sepia_element_duration"
app:layout_constraintEnd_toStartOf="@+id/sepia_element_language_label"
android:id="@+id/sepia_element_license_label"
/>
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:labelFor="@+id/sepia_element_language"
android:text="@string/language"
app:layout_constraintStart_toEndOf="@+id/sepia_element_license_label"
app:layout_constraintTop_toBottomOf="@+id/sepia_element_duration"
app:layout_constraintEnd_toEndOf="parent"
android:id="@+id/sepia_element_language_label"
/>
<Spinner
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintTop_toBottomOf="@+id/sepia_element_category_label"
app:layout_constraintStart_toStartOf="@+id/sepia_element_category_label"
app:layout_constraintStart_toEndOf="@+id/sepia_element_category_label"
android:id="@+id/sepia_element_category"
/>
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:labelFor="@+id/sepia_element_license"
android:text="@string/license"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/sepia_element_category"
android:id="@+id/sepia_element_license_label"
/>
<Spinner
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/category"
app:layout_constraintTop_toBottomOf="@+id/sepia_element_license_label"
app:layout_constraintStart_toStartOf="@+id/sepia_element_license_label"
app:layout_constraintEnd_toEndOf="@+id/sepia_element_license_label"
android:id="@+id/sepia_element_license"
/>
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:labelFor="@+id/sepia_element_language"
android:text="@string/language"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/sepia_element_license"
android:id="@+id/sepia_element_language_label"
/>
<Spinner
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/category"
app:layout_constraintTop_toBottomOf="@+id/sepia_element_language_label"
app:layout_constraintStart_toStartOf="@+id/sepia_element_language_label"
app:layout_constraintEnd_toEndOf="@+id/sepia_element_language_label"
android:id="@+id/sepia_element_language"
/>
@ -281,7 +281,7 @@
android:labelFor="@+id/sepia_element_all_of_tags"
android:text="@string/all_of_these_tags"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/sepia_element_category"
app:layout_constraintTop_toBottomOf="@+id/sepia_element_language"
app:layout_constraintEnd_toEndOf="parent"
android:id="@+id/sepia_element_all_of_tags_label"
/>