package app.fedilab.fedilabtube; /* 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 . */ import android.annotation.SuppressLint; import android.app.Activity; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.SharedPreferences; import android.database.sqlite.SQLiteDatabase; import android.net.Uri; import android.os.Build; import android.os.Bundle; import android.os.Handler; import android.os.Looper; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.widget.EditText; import android.widget.LinearLayout; import android.widget.TextView; import android.widget.Toast; import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.widget.SearchView; import androidx.appcompat.widget.Toolbar; import androidx.fragment.app.Fragment; import androidx.fragment.app.FragmentManager; import androidx.fragment.app.FragmentStatePagerAdapter; import androidx.localbroadcastmanager.content.LocalBroadcastManager; import androidx.viewpager.widget.PagerAdapter; import androidx.viewpager.widget.ViewPager; import com.google.android.material.bottomnavigation.BottomNavigationView; import com.kobakei.ratethisapp.RateThisApp; import org.jetbrains.annotations.NotNull; import java.io.IOException; import java.net.InetAddress; import java.net.NetworkInterface; import java.net.URL; import java.util.ArrayList; import java.util.Collections; import java.util.Enumeration; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Set; import java.util.TreeSet; import java.util.regex.Matcher; import java.util.regex.Pattern; import app.fedilab.fedilabtube.client.RetrofitPeertubeAPI; import app.fedilab.fedilabtube.client.data.AccountData.Account; import app.fedilab.fedilabtube.client.data.InstanceData; import app.fedilab.fedilabtube.client.data.VideoData; import app.fedilab.fedilabtube.client.entities.Error; import app.fedilab.fedilabtube.client.entities.OauthParams; import app.fedilab.fedilabtube.client.entities.PeertubeInformation; import app.fedilab.fedilabtube.client.entities.Token; import app.fedilab.fedilabtube.client.entities.UserMe; import app.fedilab.fedilabtube.client.entities.UserSettings; import app.fedilab.fedilabtube.client.entities.WellKnownNodeinfo; import app.fedilab.fedilabtube.databinding.ActivityMainBinding; import app.fedilab.fedilabtube.fragment.DisplayOverviewFragment; import app.fedilab.fedilabtube.fragment.DisplayVideosFragment; import app.fedilab.fedilabtube.helper.Helper; import app.fedilab.fedilabtube.helper.HelperAcadInstance; import app.fedilab.fedilabtube.helper.HelperInstance; import app.fedilab.fedilabtube.helper.PlaylistExportHelper; import app.fedilab.fedilabtube.helper.SwitchAccountHelper; import app.fedilab.fedilabtube.services.RetrieveInfoService; import app.fedilab.fedilabtube.sqlite.AccountDAO; import app.fedilab.fedilabtube.sqlite.Sqlite; import app.fedilab.fedilabtube.sqlite.StoredInstanceDAO; import app.fedilab.fedilabtube.viewmodel.TimelineVM; import es.dmoral.toasty.Toasty; import su.litvak.chromecast.api.v2.ChromeCast; import su.litvak.chromecast.api.v2.ChromeCasts; import su.litvak.chromecast.api.v2.ChromeCastsListener; import su.litvak.chromecast.api.v2.MediaStatus; import static app.fedilab.fedilabtube.MainActivity.TypeOfConnection.NORMAL; import static app.fedilab.fedilabtube.MainActivity.TypeOfConnection.SURFING; import static app.fedilab.fedilabtube.helper.Helper.isLoggedInType; import static app.fedilab.fedilabtube.helper.Helper.peertubeInformation; public class MainActivity extends AppCompatActivity implements ChromeCastsListener { public static int PICK_INSTANCE = 5641; public static int PICK_INSTANCE_SURF = 5642; public static UserMe userMe; public static InstanceData.InstanceConfig instanceConfig; public static TypeOfConnection typeOfConnection; public static List chromeCasts; public static ChromeCast chromeCast; public static boolean chromecastActivated = false; private DisplayVideosFragment recentFragment, locaFragment, trendingFragment, subscriptionFragment, mostLikedFragment; private DisplayOverviewFragment overviewFragment; private ActivityMainBinding binding; private final BottomNavigationView.OnNavigationItemSelectedListener mOnNavigationItemSelectedListener = item -> { int itemId = item.getItemId(); String type = null; if (itemId == R.id.navigation_discover) { setTitleCustom(R.string.title_discover); binding.viewpager.setCurrentItem(0); type = HelperAcadInstance.DISCOVER; } else if (itemId == R.id.navigation_subscription) { binding.viewpager.setCurrentItem(1); setTitleCustom(R.string.subscriptions); type = HelperAcadInstance.SUBSCRIPTIONS; } else if (itemId == R.id.navigation_trending) { setTitleCustom(R.string.title_trending); if (Helper.isLoggedIn(MainActivity.this)) { binding.viewpager.setCurrentItem(2); } else { binding.viewpager.setCurrentItem(1); } type = HelperAcadInstance.TRENDING; } else if (itemId == R.id.navigation_most_liked) { setTitleCustom(R.string.title_most_liked); binding.viewpager.setCurrentItem(2); type = HelperAcadInstance.MOSTLIKED; } else if (itemId == R.id.navigation_recently_added) { setTitleCustom(R.string.title_recently_added); binding.viewpager.setCurrentItem(3); type = HelperAcadInstance.RECENTLY_ADDED; } else if (itemId == R.id.navigation_local) { setTitleCustom(R.string.title_local); binding.viewpager.setCurrentItem(4); type = HelperAcadInstance.LOCAL; } if (type != null) { Matomo.sendScreen(MainActivity.this, "TIMELINE", type); } return true; }; private BroadcastReceiver manage_chromecast; private VideoData.Video castedTube; @SuppressLint("ApplySharedPref") public static void showRadioButtonDialogFullInstances(Activity activity, boolean storeInDb) { final SharedPreferences sharedpreferences = activity.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE); AlertDialog.Builder alt_bld = new AlertDialog.Builder(activity); alt_bld.setTitle(R.string.instance_choice); String instance = HelperInstance.getLiveInstance(activity); final EditText input = new EditText(activity); LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams( LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT); input.setLayoutParams(lp); alt_bld.setView(input); input.setText(instance); alt_bld.setPositiveButton(R.string.validate, (dialog, which) -> new Thread(() -> { try { String newInstance = input.getText().toString().trim(); if (!newInstance.startsWith("http")) { newInstance = "http://" + newInstance; } URL url = new URL(newInstance); newInstance = url.getHost(); WellKnownNodeinfo.NodeInfo instanceNodeInfo = new RetrofitPeertubeAPI(activity, newInstance, null).getNodeInfo(); if (instanceNodeInfo.getSoftware() != null && instanceNodeInfo.getSoftware().getName().trim().toLowerCase().compareTo("peertube") == 0) { SharedPreferences.Editor editor = sharedpreferences.edit(); editor.putString(Helper.PREF_INSTANCE, newInstance); editor.commit(); if (storeInDb) { newInstance = newInstance.trim().toLowerCase(); InstanceData.AboutInstance aboutInstance = new RetrofitPeertubeAPI(activity, newInstance, null).getAboutInstance(); SQLiteDatabase db = Sqlite.getInstance(activity.getApplicationContext(), Sqlite.DB_NAME, null, Sqlite.DB_VERSION).open(); new StoredInstanceDAO(activity, db).insertInstance(aboutInstance, newInstance); activity.runOnUiThread(() -> { dialog.dismiss(); Helper.logoutNoRemoval(activity); }); } else { activity.runOnUiThread(() -> { dialog.dismiss(); Intent intent = new Intent(activity, MainActivity.class); activity.startActivity(intent); }); } } else { activity.runOnUiThread(() -> Toasty.error(activity, activity.getString(R.string.not_valide_instance), Toast.LENGTH_LONG).show()); } } catch (Exception e) { e.printStackTrace(); } }).start()); alt_bld.setNegativeButton(R.string.cancel, (dialog, which) -> dialog.dismiss()); alt_bld.setNeutralButton(R.string.help, (dialog, which) -> { Intent intent = new Intent(activity, InstancePickerActivity.class); if (storeInDb) { activity.startActivityForResult(intent, PICK_INSTANCE_SURF); } else { activity.startActivityForResult(intent, PICK_INSTANCE); } }); AlertDialog alert = alt_bld.create(); alert.show(); } 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 public void newChromeCastDiscovered(ChromeCast chromeCast) { if (chromeCasts == null) { chromeCasts = new ArrayList<>(); chromeCasts.add(chromeCast); } else { boolean canBeAdded = true; for (ChromeCast cast : chromeCasts) { if (cast.getName().compareTo(chromeCast.getName()) == 0) { canBeAdded = false; break; } } if (canBeAdded) { chromeCasts.add(chromeCast); } } try { if (chromeCast.isAppRunning(Helper.CAST_ID) && chromeCast.getMediaStatus() != null && chromeCast.getMediaStatus().playerState != null) { if (binding.castInfo.getVisibility() == View.GONE) { binding.castInfo.setVisibility(View.VISIBLE); } } } catch (IOException e) { e.printStackTrace(); } } @Override public void chromeCastRemoved(ChromeCast chromeCast) { } @Override public void onDestroy() { super.onDestroy(); binding = null; ChromeCasts.unregisterListener(this); if (manage_chromecast != null) { LocalBroadcastManager.getInstance(MainActivity.this).unregisterReceiver(manage_chromecast); new Thread(() -> { if (chromeCasts != null && chromeCasts.size() > 0) { for (ChromeCast cast : chromeCasts) { try { cast.stopApp(); cast.disconnect(); } catch (IOException e) { e.printStackTrace(); } } } }).start(); } if (chromeCasts != null) { chromeCasts = null; } if (chromeCast != null) { chromeCast = null; } } //Method for discovering cast devices public void discoverCast() { new Thread(() -> { if (chromeCasts != null) { for (ChromeCast cast : chromeCasts) { try { cast.disconnect(); } catch (IOException e) { e.printStackTrace(); } } chromeCasts = null; } chromeCasts = new ArrayList<>(); try { List interfaces; interfaces = Collections.list(NetworkInterface.getNetworkInterfaces()); for (NetworkInterface ni : interfaces) { if ((!ni.isLoopback()) && ni.isUp() && (ni.getName().equals("wlan0"))) { Enumeration inetAddressEnumeration = ni.getInetAddresses(); while (inetAddressEnumeration.hasMoreElements()) { InetAddress inetAddress = inetAddressEnumeration.nextElement(); ChromeCasts.restartDiscovery(inetAddress); int tryFind = 0; while (ChromeCasts.get().isEmpty() && tryFind < 5) { try { //noinspection BusyWait Thread.sleep(1000); tryFind++; } catch (InterruptedException ignored) { } } } } } ChromeCasts.stopDiscovery(); Handler mainHandler = new Handler(Looper.getMainLooper()); Runnable myRunnable = this::invalidateOptionsMenu; mainHandler.post(myRunnable); } catch (IOException e) { e.printStackTrace(); } }).start(); } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); binding = ActivityMainBinding.inflate(getLayoutInflater()); View view = binding.getRoot(); setContentView(view); ChromeCastsListener chromeCastsListener = this; ChromeCasts.registerListener(chromeCastsListener); Toolbar toolbar = findViewById(R.id.toolbar); setSupportActionBar(toolbar); typeOfConnection = TypeOfConnection.UNKNOWN; binding.navView.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener); if (getSupportActionBar() != null) { getSupportActionBar().setDisplayShowTitleEnabled(false); } checkIfConnectedUsers(); recentFragment = new DisplayVideosFragment(); Bundle bundle = new Bundle(); bundle.putSerializable(Helper.TIMELINE_TYPE, TimelineVM.TimelineType.RECENT); recentFragment.setArguments(bundle); locaFragment = new DisplayVideosFragment(); bundle = new Bundle(); bundle.putSerializable(Helper.TIMELINE_TYPE, TimelineVM.TimelineType.LOCAL); locaFragment.setArguments(bundle); trendingFragment = new DisplayVideosFragment(); bundle = new Bundle(); bundle.putSerializable(Helper.TIMELINE_TYPE, TimelineVM.TimelineType.TRENDING); trendingFragment.setArguments(bundle); subscriptionFragment = new DisplayVideosFragment(); bundle = new Bundle(); bundle.putSerializable(Helper.TIMELINE_TYPE, TimelineVM.TimelineType.SUBSCRIBTIONS); subscriptionFragment.setArguments(bundle); mostLikedFragment = new DisplayVideosFragment(); bundle = new Bundle(); bundle.putSerializable(Helper.TIMELINE_TYPE, TimelineVM.TimelineType.MOST_LIKED); mostLikedFragment.setArguments(bundle); overviewFragment = new DisplayOverviewFragment(); if (!Helper.isLoggedIn(MainActivity.this)) { PagerAdapter mPagerAdapter = new ScreenSlidePagerAdapter(getSupportFragmentManager()); binding.viewpager.setAdapter(mPagerAdapter); } binding.viewpager.setOffscreenPageLimit(5); Matomo.sendEvent(MainActivity.this, "UTILISATEUR", "DEMARRAGE", HelperInstance.getLiveInstance(MainActivity.this), Helper.isLoggedIn(MainActivity.this) ? 1 : 0); binding.viewpager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() { @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { } @Override public void onPageSelected(int position) { MenuItem item = binding.navView.getMenu().getItem(position); binding.navView.setSelectedItemId(item.getItemId()); } @Override public void onPageScrollStateChanged(int state) { } }); toolbar.setOnClickListener(v -> { if (binding.viewpager.getAdapter() == null) { return; } if (binding.viewpager.getAdapter().instantiateItem(binding.viewpager, binding.viewpager.getCurrentItem()) instanceof DisplayVideosFragment) { ((DisplayVideosFragment) binding.viewpager.getAdapter().instantiateItem(binding.viewpager, binding.viewpager.getCurrentItem())).scrollToTop(); } else if (binding.viewpager.getAdapter().instantiateItem(binding.viewpager, binding.viewpager.getCurrentItem()) instanceof DisplayOverviewFragment) { ((DisplayOverviewFragment) binding.viewpager.getAdapter().instantiateItem(binding.viewpager, binding.viewpager.getCurrentItem())).scrollToTop(); } }); setTitleCustom(R.string.title_discover); if (Helper.isLoggedIn(MainActivity.this)) { binding.navView.inflateMenu(R.menu.bottom_nav_menu_connected); refreshToken(); } else { binding.navView.inflateMenu(R.menu.bottom_nav_menu); } peertubeInformation = new PeertubeInformation(); peertubeInformation.setCategories(new LinkedHashMap<>()); peertubeInformation.setLanguages(new LinkedHashMap<>()); peertubeInformation.setLicences(new LinkedHashMap<>()); peertubeInformation.setPrivacies(new LinkedHashMap<>()); peertubeInformation.setPlaylistPrivacies(new LinkedHashMap<>()); peertubeInformation.setTranslations(new LinkedHashMap<>()); startInForeground(); if (BuildConfig.google_restriction && BuildConfig.full_instances) { RateThisApp.onCreate(this); RateThisApp.showRateDialogIfNeeded(this); } if (!BuildConfig.full_instances) { PlaylistExportHelper.manageIntentUrl(MainActivity.this, getIntent()); } binding.castClose.setOnClickListener(v -> { Intent intentBC = new Intent(Helper.RECEIVE_CAST_SETTINGS); Bundle b = new Bundle(); b.putInt("displayed", 0); intentBC.putExtras(b); LocalBroadcastManager.getInstance(MainActivity.this).sendBroadcast(intentBC); }); binding.castTogglePlay.setOnClickListener(v -> { if (chromeCast != null) { new Thread(() -> { try { Handler mainHandler = new Handler(Looper.getMainLooper()); Runnable myRunnable = () -> binding.castTogglePlay.setVisibility(View.GONE); mainHandler.post(myRunnable); int icon = -1; if (chromeCast.getMediaStatus().playerState == MediaStatus.PlayerState.PLAYING) { chromeCast.pause(); icon = R.drawable.ic_baseline_play_arrow_32; } else if (chromeCast.getMediaStatus().playerState == MediaStatus.PlayerState.PAUSED) { chromeCast.play(); icon = R.drawable.ic_baseline_pause_32; } if (icon != -1) { int finalIcon = icon; myRunnable = () -> binding.castTogglePlay.setImageResource(finalIcon); mainHandler.post(myRunnable); } myRunnable = () -> binding.castTogglePlay.setVisibility(View.VISIBLE); mainHandler.post(myRunnable); } catch (IOException e) { e.printStackTrace(); } }).start(); } }); manage_chromecast = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { Bundle b = intent.getExtras(); assert b != null; int state = b.getInt("state_asked", -1); int displayed = b.getInt("displayed", -1); castedTube = b.getParcelable("castedTube"); if (state == 1) { discoverCast(); } else if (state == 0) { new Thread(() -> { try { if (chromeCast != null) { chromeCast.stopApp(); chromeCast.disconnect(); } } catch (IOException e) { e.printStackTrace(); } }).start(); } if (displayed == 1) { chromecastActivated = true; if (castedTube != null) { binding.castInfo.setVisibility(View.VISIBLE); Helper.loadGiF(MainActivity.this, castedTube.getThumbnailPath(), binding.castView); binding.castTitle.setText(castedTube.getTitle()); binding.castDescription.setText(castedTube.getDescription()); } } else if (displayed == 0) { chromecastActivated = false; binding.castInfo.setVisibility(View.GONE); new Thread(() -> { try { if (chromeCast != null) { chromeCast.stopApp(); } } catch (IOException e) { e.printStackTrace(); } }).start(); } } }; final SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE); LocalBroadcastManager.getInstance(MainActivity.this).registerReceiver(manage_chromecast, new IntentFilter(Helper.RECEIVE_CAST_SETTINGS)); int search_cast = sharedpreferences.getInt(getString(R.string.set_cast_choice), 0); if (search_cast == 1) { discoverCast(); } } public DisplayVideosFragment getSubscriptionFragment() { return subscriptionFragment; } private void startInForeground() { Intent notificationIntent = new Intent(this, RetrieveInfoService.class); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { startForegroundService(notificationIntent); } else { startService(notificationIntent); } } private void refreshToken() { new Thread(() -> { final SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE); String tokenStr = Helper.getToken(MainActivity.this); String instance = HelperInstance.getLiveInstance(MainActivity.this); SQLiteDatabase db = Sqlite.getInstance(getApplicationContext(), Sqlite.DB_NAME, null, Sqlite.DB_VERSION).open(); String instanceShar = sharedpreferences.getString(Helper.PREF_INSTANCE, null); String userIdShar = sharedpreferences.getString(Helper.PREF_KEY_ID, null); Account account = new AccountDAO(MainActivity.this, db).getAccountByToken(tokenStr); if (account == null) { account = new AccountDAO(MainActivity.this, db).getAccountByIdInstance(userIdShar, instanceShar); } if (account != null) { Account finalAccount = account; OauthParams oauthParams = new OauthParams(); oauthParams.setGrant_type("refresh_token"); oauthParams.setClient_id(account.getClient_id()); oauthParams.setClient_secret(account.getClient_secret()); oauthParams.setRefresh_token(account.getRefresh_token()); oauthParams.setAccess_token(account.getToken()); try { Token token = new RetrofitPeertubeAPI(MainActivity.this).manageToken(oauthParams); if (token == null) { return; } runOnUiThread(() -> { //To avoid a token issue with subscriptions, adding fragment is done when the token is refreshed. new Handler().post(() -> { if (Helper.isLoggedIn(MainActivity.this)) { PagerAdapter mPagerAdapter = new ScreenSlidePagerAdapter(getSupportFragmentManager()); binding.viewpager.setAdapter(mPagerAdapter); } }); }); userMe = new RetrofitPeertubeAPI(MainActivity.this, instance, token.getAccess_token()).verifyCredentials(); if (userMe != null && userMe.getAccount() != null) { new AccountDAO(MainActivity.this, db).updateAccount(userMe.getAccount()); SharedPreferences.Editor editor = sharedpreferences.edit(); editor.putString(Helper.PREF_KEY_ID, account.getId()); editor.putString(Helper.PREF_KEY_NAME, account.getUsername()); editor.putBoolean(getString(R.string.set_autoplay_choice), userMe.isAutoPlayVideo()); editor.putBoolean(getString(R.string.set_store_in_history), userMe.isVideosHistoryEnabled()); editor.putBoolean(getString(R.string.set_autoplay_next_video_choice), userMe.isAutoPlayNextVideo()); editor.putString(getString(R.string.set_video_sensitive_choice), userMe.getNsfwPolicy()); //Sync languages from server List videoLanguageServer = userMe.getVideoLanguages(); if (videoLanguageServer != null) { Set videoLanguageServerSet = new TreeSet<>(videoLanguageServer); videoLanguageServerSet.addAll(videoLanguageServer); Set videoLanguageLocal = sharedpreferences.getStringSet(getString(R.string.set_video_language_choice), null); if (videoLanguageServerSet.size() > 0 && videoLanguageLocal != null) { videoLanguageServer.addAll(videoLanguageLocal); } editor.putStringSet(getString(R.string.set_video_language_choice), videoLanguageServerSet); editor.apply(); } } instanceConfig = new RetrofitPeertubeAPI(MainActivity.this).getConfigInstance(); } catch (Error error) { runOnUiThread(() -> { AlertDialog.Builder alt_bld = new AlertDialog.Builder(this); alt_bld.setTitle(R.string.refresh_token_failed); alt_bld.setMessage(R.string.refresh_token_failed_message); alt_bld.setNegativeButton(R.string.action_logout, (dialog, id) -> { dialog.dismiss(); Helper.logoutCurrentUser(MainActivity.this, finalAccount); }); alt_bld.setPositiveButton(R.string._retry, (dialog, id) -> { dialog.dismiss(); refreshToken(); }); AlertDialog alert = alt_bld.create(); alert.show(); }); error.printStackTrace(); } } }).start(); } @Override public boolean onCreateOptionsMenu(@NotNull Menu menu) { getMenuInflater().inflate(R.menu.main_menu, menu); MenuItem myActionMenuItem = menu.findItem(R.id.action_search); SearchView searchView = (SearchView) myActionMenuItem.getActionView(); searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() { @Override public boolean onQueryTextSubmit(String query) { Pattern link = Pattern.compile("(https?://[\\da-z.-]+\\.[a-z.]{2,10})/videos/watch/(\\w{8}-\\w{4}-\\w{4}-\\w{4}-\\w{12})(\\?start=(\\d+[hH])?(\\d+[mM])?(\\d+[sS])?)?$"); Matcher matcherLink = link.matcher(query.trim()); if (matcherLink.find()) { Intent intent = new Intent(MainActivity.this, PeertubeActivity.class); intent.setData(Uri.parse(query.trim())); startActivity(intent); myActionMenuItem.collapseActionView(); return false; } Intent intent = new Intent(MainActivity.this, SearchActivity.class); Bundle b = new Bundle(); String search = query.trim(); b.putString("search", search); intent.putExtras(b); startActivity(intent); if (!searchView.isIconified()) { searchView.setIconified(true); } myActionMenuItem.collapseActionView(); return false; } @Override public boolean onQueryTextChange(String s) { return false; } }); MenuItem uploadItem = menu.findItem(R.id.action_upload); MenuItem myVideosItem = menu.findItem(R.id.action_myvideos); MenuItem playslistItem = menu.findItem(R.id.action_playlist); MenuItem historyItem = menu.findItem(R.id.action_history); MenuItem mostLikedItem = menu.findItem(R.id.action_most_liked); MenuItem settingsItem = menu.findItem(R.id.action_settings); MenuItem sepiaSearchItem = menu.findItem(R.id.action_sepia_search); MenuItem incognitoItem = menu.findItem(R.id.action_incognito); MenuItem instanceItem = menu.findItem(R.id.action_change_instance); MenuItem accountItem = menu.findItem(R.id.action_account); if (BuildConfig.surfing_mode && ((Helper.isLoggedIn(MainActivity.this) && typeOfConnection == NORMAL) || typeOfConnection == SURFING)) { binding.instances.setVisibility(View.VISIBLE); binding.instances.setOnClickListener(null); binding.instances.setOnClickListener(v -> { Intent intent = new Intent(MainActivity.this, ManageInstancesActivity.class); startActivity(intent); overridePendingTransition(R.anim.slide_in_up, R.anim.slide_out_up); }); } else { binding.instances.setVisibility(View.GONE); } switch (typeOfConnection) { case UNKNOWN: instanceItem.setVisible(false); accountItem.setVisible(false); uploadItem.setVisible(false); myVideosItem.setVisible(false); playslistItem.setVisible(false); historyItem.setVisible(false); settingsItem.setVisible(false); mostLikedItem.setVisible(false); incognitoItem.setVisible(false); break; case REMOTE_ACCOUNT: case NORMAL: accountItem.setVisible(true); if (Helper.isLoggedIn(MainActivity.this)) { instanceItem.setVisible(false); uploadItem.setVisible(true); myVideosItem.setVisible(true); playslistItem.setVisible(true); historyItem.setVisible(true); settingsItem.setVisible(false); mostLikedItem.setVisible(true); incognitoItem.setVisible(true); final SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE); boolean checked = sharedpreferences.getBoolean(getString(R.string.set_store_in_history), true); incognitoItem.setChecked(checked); } else { instanceItem.setVisible(true); uploadItem.setVisible(false); myVideosItem.setVisible(false); playslistItem.setVisible(!BuildConfig.full_instances); historyItem.setVisible(false); settingsItem.setVisible(true); mostLikedItem.setVisible(false); incognitoItem.setVisible(false); } break; case SURFING: instanceItem.setVisible(false); accountItem.setVisible(true); uploadItem.setVisible(false); myVideosItem.setVisible(false); playslistItem.setVisible(false); historyItem.setVisible(false); settingsItem.setVisible(false); mostLikedItem.setVisible(false); incognitoItem.setVisible(false); break; } if (!BuildConfig.instance_switcher) { instanceItem.setVisible(false); } if (!BuildConfig.sepia_search) { sepiaSearchItem.setVisible(false); } return true; } private void checkIfConnectedUsers() { new Thread(() -> { try { typeOfConnection = NORMAL; if (!Helper.canMakeAction(MainActivity.this)) { SQLiteDatabase db = Sqlite.getInstance(getApplicationContext(), Sqlite.DB_NAME, null, Sqlite.DB_VERSION).open(); List accounts = new AccountDAO(MainActivity.this, db).getAllAccount(); if (accounts != null && accounts.size() > 0) { //The user is not authenticated and there accounts in db. That means the user is surfing some other instances typeOfConnection = TypeOfConnection.SURFING; } } runOnUiThread(this::invalidateOptionsMenu); } catch (Exception e) { e.printStackTrace(); } }).start(); } @Override public boolean onOptionsItemSelected(MenuItem item) { String type = null; String action = "TIMELINE"; if (item.getItemId() == R.id.action_change_instance) { if (BuildConfig.full_instances) { showRadioButtonDialogFullInstances(MainActivity.this, false); } else { showRadioButtonDialog(); } action = "CHANGE_INSTANCE"; type = ""; } else if (item.getItemId() == R.id.action_settings) { Intent intent = new Intent(MainActivity.this, SettingsActivity.class); startActivity(intent); } else if (item.getItemId() == R.id.action_account) { Intent intent; if (typeOfConnection == SURFING) { SwitchAccountHelper.switchDialog(MainActivity.this, false); } else { if (Helper.canMakeAction(MainActivity.this)) { intent = new Intent(MainActivity.this, AccountActivity.class); } else { intent = new Intent(MainActivity.this, LoginActivity.class); } startActivity(intent); } } else if (item.getItemId() == R.id.action_upload) { Intent intent = new Intent(MainActivity.this, PeertubeUploadActivity.class); startActivity(intent); } else if (item.getItemId() == R.id.action_myvideos) { Intent intent = new Intent(MainActivity.this, VideosTimelineActivity.class); Bundle bundle = new Bundle(); bundle.putSerializable("type", TimelineVM.TimelineType.MY_VIDEOS); intent.putExtras(bundle); startActivity(intent); type = HelperAcadInstance.MYVIDEOS; } else if (item.getItemId() == R.id.action_history) { Intent intent = new Intent(MainActivity.this, VideosTimelineActivity.class); Bundle bundle = new Bundle(); bundle.putSerializable("type", TimelineVM.TimelineType.HISTORY); intent.putExtras(bundle); startActivity(intent); type = HelperAcadInstance.HISTORY; } else if (item.getItemId() == R.id.action_most_liked) { Intent intent = new Intent(MainActivity.this, VideosTimelineActivity.class); Bundle bundle = new Bundle(); bundle.putSerializable("type", TimelineVM.TimelineType.MOST_LIKED); intent.putExtras(bundle); startActivity(intent); type = HelperAcadInstance.MOSTLIKED; } else if (item.getItemId() == R.id.action_playlist) { Intent intent; if (Helper.isLoggedIn(MainActivity.this)) { intent = new Intent(MainActivity.this, AllPlaylistsActivity.class); } else { intent = new Intent(MainActivity.this, AllLocalPlaylistsActivity.class); } startActivity(intent); } else if (item.getItemId() == R.id.action_sepia_search) { Intent intent = new Intent(MainActivity.this, SepiaSearchActivity.class); startActivity(intent); } else if (item.getItemId() == R.id.action_about) { Intent intent = new Intent(MainActivity.this, AboutActivity.class); startActivity(intent); } else if (item.getItemId() == R.id.action_incognito) { item.setChecked(!item.isChecked()); final SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE); SharedPreferences.Editor editor = sharedpreferences.edit(); editor.putBoolean(getString(R.string.set_store_in_history), item.isChecked()); editor.apply(); new Thread(() -> { UserSettings userSettings = new UserSettings(); userSettings.setVideosHistoryEnabled(item.isChecked()); try { RetrofitPeertubeAPI api = new RetrofitPeertubeAPI(MainActivity.this); api.updateUser(userSettings); } catch (Exception | Error e) { e.printStackTrace(); } }).start(); return false; } if (type != null) { Matomo.sendScreen(MainActivity.this, action, type); } return true; } @Override protected void onNewIntent(Intent intent) { super.onNewIntent(intent); if (intent == null) return; Bundle extras = intent.getExtras(); if (extras != null && extras.containsKey(Helper.INTENT_ACTION)) { if (extras.getInt(Helper.INTENT_ACTION) == Helper.ADD_USER_INTENT) { recreate(); } } else if (!BuildConfig.full_instances) { PlaylistExportHelper.manageIntentUrl(MainActivity.this, intent); } } @SuppressLint("ApplySharedPref") private void showRadioButtonDialog() { AlertDialog.Builder alt_bld = new AlertDialog.Builder(this); alt_bld.setTitle(R.string.instance_choice); final SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE); String acad = HelperInstance.getLiveInstance(MainActivity.this); int i = 0; HashMap instancesMap = new HashMap<>(HelperAcadInstance.instances_themes); Iterator> it = instancesMap.entrySet().iterator(); String[] academiesKey = new String[HelperAcadInstance.instances_themes.size()]; String[] academiesValue = new String[HelperAcadInstance.instances_themes.size()]; int position = 0; while (it.hasNext()) { Map.Entry pair = it.next(); academiesKey[i] = pair.getKey(); academiesValue[i] = pair.getValue(); if (pair.getValue().compareTo(acad) == 0) { position = i; } it.remove(); i++; } alt_bld.setSingleChoiceItems(academiesKey, position, (dialog, item) -> { String newInstance = academiesValue[item]; SharedPreferences.Editor editor = sharedpreferences.edit(); editor.putString(Helper.PREF_INSTANCE, newInstance); editor.commit(); dialog.dismiss(); recreate(); }); alt_bld.setPositiveButton(R.string.close, (dialog, id) -> dialog.dismiss()); AlertDialog alert = alt_bld.create(); alert.show(); } @SuppressLint("ApplySharedPref") @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == PICK_INSTANCE && resultCode == Activity.RESULT_OK) { if (data != null && data.getData() != null) { final SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE); SharedPreferences.Editor editor = sharedpreferences.edit(); editor.putString(Helper.PREF_INSTANCE, String.valueOf(data.getData())); editor.commit(); recreate(); } } } public enum TypeOfConnection { UNKNOWN, NORMAL, SURFING, REMOTE_ACCOUNT } private class ScreenSlidePagerAdapter extends FragmentStatePagerAdapter { ScreenSlidePagerAdapter(FragmentManager fm) { super(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT); } @NotNull @Override public Fragment getItem(final int position) { if (Helper.isLoggedIn(MainActivity.this)) { switch (position) { case 0: return overviewFragment; case 1: return subscriptionFragment; case 2: return trendingFragment; case 3: return recentFragment; case 4: return locaFragment; } } else { switch (position) { case 0: return overviewFragment; case 1: return trendingFragment; case 2: return mostLikedFragment; case 3: return recentFragment; case 4: return locaFragment; } } return overviewFragment; } @Override public int getCount() { return 5; } } }