Fix issue #58 - Allow to search channels
This commit is contained in:
parent
550394a5e4
commit
24ad4dbc0f
|
@ -187,8 +187,10 @@ public class MainActivity extends AppCompatActivity {
|
|||
private void setTitleCustom(int titleRId) {
|
||||
Toolbar toolbar = findViewById(R.id.toolbar);
|
||||
TextView mTitle = toolbar.findViewById(R.id.toolbar_title);
|
||||
if (mTitle != null) {
|
||||
mTitle.setText(getString(titleRId));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
|
|
|
@ -16,11 +16,22 @@ package app.fedilab.fedilabtube;
|
|||
|
||||
import android.os.Bundle;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.fragment.app.FragmentTransaction;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
import androidx.fragment.app.FragmentStatePagerAdapter;
|
||||
import androidx.viewpager.widget.PagerAdapter;
|
||||
import androidx.viewpager.widget.ViewPager;
|
||||
|
||||
import com.google.android.material.tabs.TabLayout;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import app.fedilab.fedilabtube.databinding.ActivitySearchResultBinding;
|
||||
import app.fedilab.fedilabtube.fragment.DisplayChannelsFragment;
|
||||
import app.fedilab.fedilabtube.fragment.DisplayVideosFragment;
|
||||
import es.dmoral.toasty.Toasty;
|
||||
|
||||
|
@ -29,12 +40,15 @@ public class SearchActivity extends AppCompatActivity {
|
|||
|
||||
|
||||
private String search;
|
||||
private ActivitySearchResultBinding binding;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
binding = ActivitySearchResultBinding.inflate(getLayoutInflater());
|
||||
View view = binding.getRoot();
|
||||
setContentView(view);
|
||||
|
||||
setContentView(R.layout.activity_search_result);
|
||||
Bundle b = getIntent().getExtras();
|
||||
if (b != null) {
|
||||
search = b.getString("search");
|
||||
|
@ -46,15 +60,64 @@ public class SearchActivity extends AppCompatActivity {
|
|||
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
||||
setTitle(search);
|
||||
|
||||
binding.searchTabLayout.addTab(binding.searchTabLayout.newTab().setText(getString(R.string.videos)));
|
||||
binding.searchTabLayout.addTab(binding.searchTabLayout.newTab().setText(getString(R.string.channels)));
|
||||
binding.searchPager.setOffscreenPageLimit(2);
|
||||
|
||||
PagerAdapter mPagerAdapter = new ScreenSlidePagerAdapter(getSupportFragmentManager());
|
||||
binding.searchPager.setAdapter(mPagerAdapter);
|
||||
binding.searchPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
|
||||
@Override
|
||||
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
|
||||
|
||||
if (savedInstanceState == null) {
|
||||
DisplayVideosFragment displayVideosFragment = new DisplayVideosFragment();
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putString("search_peertube", search);
|
||||
displayVideosFragment.setArguments(bundle);
|
||||
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
|
||||
ft.add(R.id.container, displayVideosFragment).commit();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPageSelected(int position) {
|
||||
TabLayout.Tab tab = binding.searchTabLayout.getTabAt(position);
|
||||
if (tab != null)
|
||||
tab.select();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPageScrollStateChanged(int state) {
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
binding.searchTabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
|
||||
@Override
|
||||
public void onTabSelected(TabLayout.Tab tab) {
|
||||
binding.searchPager.setCurrentItem(tab.getPosition());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTabUnselected(TabLayout.Tab tab) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTabReselected(TabLayout.Tab tab) {
|
||||
Fragment fragment = null;
|
||||
if (binding.searchPager.getAdapter() != null)
|
||||
fragment = (Fragment) binding.searchPager.getAdapter().instantiateItem(binding.searchPager, tab.getPosition());
|
||||
switch (tab.getPosition()) {
|
||||
case 0:
|
||||
if (fragment != null) {
|
||||
DisplayVideosFragment displayVideosFragment = ((DisplayVideosFragment) fragment);
|
||||
displayVideosFragment.scrollToTop();
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
if (fragment != null) {
|
||||
DisplayChannelsFragment displayChannelsFragment = ((DisplayChannelsFragment) fragment);
|
||||
displayChannelsFragment.scrollToTop();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -67,4 +130,37 @@ public class SearchActivity extends AppCompatActivity {
|
|||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Pager adapter for the 2 fragments
|
||||
*/
|
||||
private class ScreenSlidePagerAdapter extends FragmentStatePagerAdapter {
|
||||
|
||||
ScreenSlidePagerAdapter(FragmentManager fm) {
|
||||
super(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Fragment getItem(int position) {
|
||||
Bundle bundle = new Bundle();
|
||||
if (position == 0) {
|
||||
DisplayVideosFragment displayVideosFragment = new DisplayVideosFragment();
|
||||
bundle.putString("search_peertube", search);
|
||||
displayVideosFragment.setArguments(bundle);
|
||||
return displayVideosFragment;
|
||||
}
|
||||
DisplayChannelsFragment displayChannelsFragment = new DisplayChannelsFragment();
|
||||
bundle.putString("search_peertube", search);
|
||||
displayChannelsFragment.setArguments(bundle);
|
||||
return displayChannelsFragment;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getCount() {
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -201,7 +201,7 @@ public interface PeertubeService {
|
|||
Call<String> deleteHistory(
|
||||
@Header("Authorization") String credentials);
|
||||
|
||||
//Search
|
||||
//Search videos
|
||||
@GET("search/videos")
|
||||
Call<VideoData> searchVideos(
|
||||
@Header("Authorization") String credentials,
|
||||
|
@ -209,6 +209,14 @@ public interface PeertubeService {
|
|||
@Query("start") String maxId,
|
||||
@Query("count") String count);
|
||||
|
||||
//Search channels
|
||||
@GET("search/video-channels")
|
||||
Call<ChannelData> searchChannels(
|
||||
@Header("Authorization") String credentials,
|
||||
@Query("search") String search,
|
||||
@Query("searcharget") String searchTarget,
|
||||
@Query("start") String maxId,
|
||||
@Query("count") String count);
|
||||
|
||||
//Search
|
||||
@GET("search/videos")
|
||||
|
|
|
@ -946,6 +946,34 @@ public class RetrofitPeertubeAPI {
|
|||
return apiResponse;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves channels search *synchronously*
|
||||
*
|
||||
* @param query String search
|
||||
* @return APIResponse
|
||||
*/
|
||||
public APIResponse searchChannels(String query, String max_id) {
|
||||
PeertubeService peertubeService = init();
|
||||
Call<ChannelData> searchChannelsCall = peertubeService.searchChannels(getToken(), query, "local", max_id, count);
|
||||
APIResponse apiResponse = new APIResponse();
|
||||
try {
|
||||
Response<ChannelData> response = searchChannelsCall.execute();
|
||||
if (response.isSuccessful() && response.body() != null) {
|
||||
apiResponse.setChannels(response.body().data);
|
||||
} else {
|
||||
setError(apiResponse, response.code(), response.errorBody());
|
||||
}
|
||||
} catch (IOException e) {
|
||||
Error error = new Error();
|
||||
error.setError(_context.getString(R.string.toast_error));
|
||||
apiResponse.setError(error);
|
||||
e.printStackTrace();
|
||||
}
|
||||
return apiResponse;
|
||||
}
|
||||
|
||||
|
||||
/***
|
||||
* Verifiy credential of the authenticated user *synchronously*
|
||||
* @return Account
|
||||
|
|
|
@ -182,8 +182,7 @@ public class DisplayAccountsFragment extends Fragment implements AccountsListAda
|
|||
textviewNoAction.setVisibility(View.VISIBLE);
|
||||
else
|
||||
textviewNoAction.setVisibility(View.GONE);
|
||||
|
||||
max_id = apiResponse.getMax_id();
|
||||
max_id = String.valueOf(Integer.parseInt(max_id) + 20);
|
||||
if (accounts != null && accounts.size() > 0) {
|
||||
int previousPosition = this.accounts.size();
|
||||
int currentPosition = this.accounts.size();
|
||||
|
|
|
@ -29,7 +29,6 @@ import android.view.ViewGroup;
|
|||
import android.view.WindowManager;
|
||||
import android.view.inputmethod.InputMethodManager;
|
||||
import android.widget.Button;
|
||||
import android.widget.RelativeLayout;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
@ -60,6 +59,7 @@ import app.fedilab.fedilabtube.databinding.FragmentRecyclerviewBinding;
|
|||
import app.fedilab.fedilabtube.drawer.ChannelListAdapter;
|
||||
import app.fedilab.fedilabtube.helper.Helper;
|
||||
import app.fedilab.fedilabtube.viewmodel.ChannelsVM;
|
||||
import app.fedilab.fedilabtube.viewmodel.SearchVM;
|
||||
import es.dmoral.toasty.Toasty;
|
||||
|
||||
import static app.fedilab.fedilabtube.PeertubeUploadActivity.MY_PERMISSIONS_REQUEST_READ_EXTERNAL_STORAGE;
|
||||
|
@ -71,7 +71,6 @@ public class DisplayChannelsFragment extends Fragment implements ChannelListAdap
|
|||
private static final int PICK_AVATAR = 467;
|
||||
private ChannelListAdapter channelListAdapter;
|
||||
private List<ChannelData.Channel> channels;
|
||||
private RelativeLayout mainLoader, nextElementLoader, textviewNoAction;
|
||||
private String name;
|
||||
private View rootView;
|
||||
private boolean myChannels;
|
||||
|
@ -79,6 +78,8 @@ public class DisplayChannelsFragment extends Fragment implements ChannelListAdap
|
|||
private FragmentRecyclerviewBinding binding;
|
||||
private AddChannelBinding bindingDialog;
|
||||
private Uri inputData;
|
||||
private String search_peertube;
|
||||
private String max_id;
|
||||
|
||||
@Override
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
|
@ -90,13 +91,13 @@ public class DisplayChannelsFragment extends Fragment implements ChannelListAdap
|
|||
Bundle bundle = this.getArguments();
|
||||
channels = new ArrayList<>();
|
||||
myChannels = true;
|
||||
max_id = "0";
|
||||
if (bundle != null) {
|
||||
name = bundle.getString("name", null);
|
||||
myChannels = bundle.getBoolean("myChannels", true);
|
||||
search_peertube = bundle.getString("search_peertube", null);
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (getActivity() != null) {
|
||||
action_button = getActivity().findViewById(R.id.action_button);
|
||||
if (action_button != null) {
|
||||
|
@ -106,11 +107,6 @@ public class DisplayChannelsFragment extends Fragment implements ChannelListAdap
|
|||
}
|
||||
|
||||
binding.lvElements.addItemDecoration(new DividerItemDecoration(context, DividerItemDecoration.VERTICAL));
|
||||
mainLoader = rootView.findViewById(R.id.loader);
|
||||
nextElementLoader = rootView.findViewById(R.id.loading_next);
|
||||
textviewNoAction = rootView.findViewById(R.id.no_action);
|
||||
mainLoader.setVisibility(View.VISIBLE);
|
||||
nextElementLoader.setVisibility(View.GONE);
|
||||
channelListAdapter = new ChannelListAdapter(this.channels, myChannels);
|
||||
channelListAdapter.allChannelRemoved = this;
|
||||
channelListAdapter.editAlertDialog = this;
|
||||
|
@ -121,15 +117,24 @@ public class DisplayChannelsFragment extends Fragment implements ChannelListAdap
|
|||
binding.lvElements.setLayoutManager(mLayoutManager);
|
||||
|
||||
binding.swipeContainer.setOnRefreshListener(this::pullToRefresh);
|
||||
|
||||
loadChannels(max_id);
|
||||
return rootView;
|
||||
}
|
||||
|
||||
private void loadChannels(String max_id) {
|
||||
if (search_peertube == null) {
|
||||
ChannelsVM viewModel = new ViewModelProvider(this).get(ChannelsVM.class);
|
||||
if (name != null) {
|
||||
viewModel.get(RetrofitPeertubeAPI.DataType.CHANNELS_FOR_ACCOUNT, name).observe(DisplayChannelsFragment.this.requireActivity(), this::manageViewChannels);
|
||||
} else {
|
||||
viewModel.get(RetrofitPeertubeAPI.DataType.MY_CHANNELS, null).observe(DisplayChannelsFragment.this.requireActivity(), this::manageViewChannels);
|
||||
}
|
||||
return rootView;
|
||||
} else {
|
||||
SearchVM viewModelSearch = new ViewModelProvider(this).get(SearchVM.class);
|
||||
viewModelSearch.getChannels(max_id, search_peertube).observe(this.requireActivity(), this::manageViewChannels);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
|
@ -187,19 +192,20 @@ public class DisplayChannelsFragment extends Fragment implements ChannelListAdap
|
|||
}
|
||||
|
||||
private void manageViewChannels(APIResponse apiResponse) {
|
||||
mainLoader.setVisibility(View.GONE);
|
||||
nextElementLoader.setVisibility(View.GONE);
|
||||
binding.loader.setVisibility(View.GONE);
|
||||
binding.loadingNext.setVisibility(View.GONE);
|
||||
if (apiResponse.getError() != null) {
|
||||
Toasty.error(context, apiResponse.getError().getError(), Toast.LENGTH_LONG).show();
|
||||
binding.swipeContainer.setRefreshing(false);
|
||||
return;
|
||||
}
|
||||
List<ChannelData.Channel> channels = apiResponse.getChannels();
|
||||
if ((channels == null || channels.size() == 0))
|
||||
textviewNoAction.setVisibility(View.VISIBLE);
|
||||
else
|
||||
textviewNoAction.setVisibility(View.GONE);
|
||||
|
||||
if ((channels == null || channels.size() == 0))
|
||||
binding.noAction.setVisibility(View.VISIBLE);
|
||||
else
|
||||
binding.noAction.setVisibility(View.GONE);
|
||||
max_id = String.valueOf(Integer.parseInt(max_id) + 20);
|
||||
if (channels != null && channels.size() > 0) {
|
||||
int currentPosition = this.channels.size();
|
||||
this.channels.addAll(channels);
|
||||
|
@ -217,19 +223,13 @@ public class DisplayChannelsFragment extends Fragment implements ChannelListAdap
|
|||
|
||||
public void pullToRefresh() {
|
||||
channels = new ArrayList<>();
|
||||
|
||||
binding.swipeContainer.setRefreshing(true);
|
||||
ChannelsVM viewModel = new ViewModelProvider(this).get(ChannelsVM.class);
|
||||
if (name != null) {
|
||||
viewModel.get(RetrofitPeertubeAPI.DataType.CHANNELS_FOR_ACCOUNT, name).observe(DisplayChannelsFragment.this.requireActivity(), this::manageViewChannels);
|
||||
} else {
|
||||
viewModel.get(RetrofitPeertubeAPI.DataType.MY_CHANNELS, null).observe(DisplayChannelsFragment.this.requireActivity(), this::manageViewChannels);
|
||||
}
|
||||
loadChannels("0");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAllChannelRemoved() {
|
||||
textviewNoAction.setVisibility(View.VISIBLE);
|
||||
binding.noAction.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -43,12 +43,35 @@ public class SearchVM extends AndroidViewModel {
|
|||
return apiResponseMutableLiveData;
|
||||
}
|
||||
|
||||
|
||||
public LiveData<APIResponse> getChannels(String max_id, String query) {
|
||||
apiResponseMutableLiveData = new MutableLiveData<>();
|
||||
loadChannels(max_id, query);
|
||||
return apiResponseMutableLiveData;
|
||||
}
|
||||
|
||||
public LiveData<APIResponse> searchNextVideos(List<String> tags) {
|
||||
apiResponseMutableLiveData = new MutableLiveData<>();
|
||||
loadNextVideos(tags);
|
||||
return apiResponseMutableLiveData;
|
||||
}
|
||||
|
||||
|
||||
private void loadChannels(String max_id, String query) {
|
||||
Context _mContext = getApplication().getApplicationContext();
|
||||
new Thread(() -> {
|
||||
try {
|
||||
RetrofitPeertubeAPI api = new RetrofitPeertubeAPI(_mContext);
|
||||
APIResponse apiResponse = api.searchChannels(query, max_id);
|
||||
Handler mainHandler = new Handler(Looper.getMainLooper());
|
||||
Runnable myRunnable = () -> apiResponseMutableLiveData.setValue(apiResponse);
|
||||
mainHandler.post(myRunnable);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
|
||||
private void loadVideos(String max_id, String query) {
|
||||
Context _mContext = getApplication().getApplicationContext();
|
||||
new Thread(() -> {
|
||||
|
|
|
@ -14,10 +14,34 @@
|
|||
You should have received a copy of the GNU General Public License along with TubeLab; if not,
|
||||
see <http://www.gnu.org/licenses>.
|
||||
-->
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_height="match_parent">
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:fitsSystemWindows="true"
|
||||
tools:context=".ShowChannelActivity">
|
||||
|
||||
<com.google.android.material.appbar.AppBarLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:fitsSystemWindows="true"
|
||||
app:theme="@style/ThemeOverlay.AppCompat.ActionBar">
|
||||
|
||||
<com.google.android.material.appbar.CollapsingToolbarLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:fitsSystemWindows="true"
|
||||
app:contentScrim="?attr/colorPrimary"
|
||||
app:expandedTitleMarginEnd="64dp"
|
||||
app:expandedTitleMarginStart="48dp"
|
||||
app:layout_scrollFlags="scroll|exitUntilCollapsed">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/top_banner"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="5dp">
|
||||
|
||||
<HorizontalScrollView
|
||||
android:id="@+id/history_filter"
|
||||
|
@ -71,15 +95,24 @@
|
|||
|
||||
</HorizontalScrollView>
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/container"
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</com.google.android.material.appbar.CollapsingToolbarLayout>
|
||||
|
||||
<com.google.android.material.tabs.TabLayout
|
||||
android:id="@+id/search_tabLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/history_filter">
|
||||
android:layout_height="wrap_content"
|
||||
app:tabGravity="fill"
|
||||
app:tabMode="fixed"
|
||||
app:tabSelectedTextColor="?colorAccent"
|
||||
app:tabTextColor="@android:color/white" />
|
||||
</com.google.android.material.appbar.AppBarLayout>
|
||||
|
||||
<androidx.viewpager.widget.ViewPager
|
||||
android:id="@+id/search_pager"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="5dp"
|
||||
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
|
||||
|
||||
</RelativeLayout>
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||
|
|
Loading…
Reference in New Issue