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.Context; import android.content.Intent; import android.content.SharedPreferences; import android.database.sqlite.SQLiteDatabase; import android.os.Build; import android.os.Bundle; import android.os.Handler; import android.view.Menu; import android.view.MenuItem; import android.widget.EditText; import android.widget.LinearLayout; 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 com.google.android.material.bottomnavigation.BottomNavigationView; import com.kobakei.ratethisapp.RateThisApp; import org.jetbrains.annotations.NotNull; import java.util.List; import java.util.Set; import java.util.TreeSet; import app.fedilab.fedilabtube.client.RetrofitPeertubeAPI; import app.fedilab.fedilabtube.client.data.AccountData.Account; 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.WellKnownNodeinfo; import app.fedilab.fedilabtube.fragment.DisplayOverviewFragment; import app.fedilab.fedilabtube.fragment.DisplayVideosFragment; import app.fedilab.fedilabtube.helper.Helper; import app.fedilab.fedilabtube.services.RetrieveInfoService; import app.fedilab.fedilabtube.sqlite.AccountDAO; import app.fedilab.fedilabtube.sqlite.Sqlite; import app.fedilab.fedilabtube.viewmodel.TimelineVM; import es.dmoral.toasty.Toasty; import static app.fedilab.fedilabtube.helper.Helper.academies; public class MainActivity extends AppCompatActivity { public static PeertubeInformation peertubeInformation; public static int PICK_INSTANCE = 5641; final FragmentManager fm = getSupportFragmentManager(); Fragment active; private DisplayVideosFragment recentFragment, locaFragment, trendingFragment, subscriptionFragment, mostLikedFragment; private DisplayOverviewFragment overviewFragment; private final BottomNavigationView.OnNavigationItemSelectedListener mOnNavigationItemSelectedListener = item -> { DisplayVideosFragment displayVideosFragment = null; int itemId = item.getItemId(); if (itemId == R.id.navigation_subscription) { displayVideosFragment = subscriptionFragment; setTitle(R.string.subscriptions); } else if (itemId == R.id.navigation_trending) { setTitle(R.string.title_trending); displayVideosFragment = trendingFragment; } else if (itemId == R.id.navigation_most_liked) { setTitle(R.string.title_most_liked); displayVideosFragment = mostLikedFragment; } else if (itemId == R.id.navigation_recently_added) { setTitle(R.string.title_recently_added); displayVideosFragment = recentFragment; } else if (itemId == R.id.navigation_local) { setTitle(R.string.title_local); displayVideosFragment = locaFragment; } else if (itemId == R.id.navigation_discover) { setTitle(R.string.title_discover); fm.beginTransaction().hide(active).show(overviewFragment).commit(); active = overviewFragment; return true; } if (displayVideosFragment != null) { fm.beginTransaction().hide(active).show(displayVideosFragment).commit(); active = displayVideosFragment; return true; } else { return false; } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Toolbar toolbar = findViewById(R.id.toolbar); setSupportActionBar(toolbar); BottomNavigationView navView = findViewById(R.id.nav_view); navView.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener); Fragment fragment = getSupportFragmentManager().findFragmentByTag("5"); if(fragment != null) getSupportFragmentManager().beginTransaction().remove(fragment).commit(); fragment = getSupportFragmentManager().findFragmentByTag("4"); if(fragment != null) getSupportFragmentManager().beginTransaction().remove(fragment).commit(); fragment = getSupportFragmentManager().findFragmentByTag("3"); if(fragment != null) getSupportFragmentManager().beginTransaction().remove(fragment).commit(); fragment = getSupportFragmentManager().findFragmentByTag("2"); if(fragment != null) getSupportFragmentManager().beginTransaction().remove(fragment).commit(); fragment = getSupportFragmentManager().findFragmentByTag("1"); if(fragment != null) getSupportFragmentManager().beginTransaction().remove(fragment).commit(); 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( active == null) { active = overviewFragment; } fm.beginTransaction().add(R.id.nav_host_fragment, locaFragment, "5").hide(locaFragment).commit(); if (!Helper.isLoggedIn(MainActivity.this)) { fm.beginTransaction().add(R.id.nav_host_fragment, recentFragment, "4").hide(recentFragment).commit(); fm.beginTransaction().add(R.id.nav_host_fragment, mostLikedFragment, "3").hide(mostLikedFragment).commit(); fm.beginTransaction().add(R.id.nav_host_fragment, trendingFragment, "2").hide(trendingFragment).commit(); fm.beginTransaction().add(R.id.nav_host_fragment, overviewFragment, "1").commit(); } toolbar.setOnClickListener(v->{ if(active instanceof DisplayVideosFragment) { ((DisplayVideosFragment) active).scrollToTop(); }else if(active instanceof DisplayOverviewFragment) { ((DisplayOverviewFragment) active).scrollToTop(); } }); setTitle(R.string.title_discover); if (Helper.isLoggedIn(MainActivity.this)) { navView.inflateMenu(R.menu.bottom_nav_menu_connected); final SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE); String tokenStr = sharedpreferences.getString(Helper.PREF_KEY_OAUTH_TOKEN, null); String instance = Helper.getLiveInstance(MainActivity.this); SQLiteDatabase db = Sqlite.getInstance(getApplicationContext(), Sqlite.DB_NAME, null, Sqlite.DB_VERSION).open(); Account account = new AccountDAO(MainActivity.this, db).getAccountByToken(tokenStr); if (account != null) { 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()); new Thread(() -> { try { Token token = new RetrofitPeertubeAPI(MainActivity.this).manageToken(oauthParams); if (token == null) { runOnUiThread(() -> Helper.logoutCurrentUser(MainActivity.this, account)); return; } runOnUiThread(() -> { //To avoid a token issue with subscriptions, adding fragment is done when the token is refreshed. new Handler().post(() -> { fm.beginTransaction().add(R.id.nav_host_fragment, recentFragment, "4").hide(recentFragment).commitAllowingStateLoss(); fm.beginTransaction().add(R.id.nav_host_fragment, trendingFragment, "3").hide(trendingFragment).commitAllowingStateLoss(); fm.beginTransaction().add(R.id.nav_host_fragment, subscriptionFragment, "2").hide(subscriptionFragment).commitAllowingStateLoss(); fm.beginTransaction().add(R.id.nav_host_fragment, overviewFragment, "1").commitAllowingStateLoss(); }); }); UserMe 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()); //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(); } } } catch (Error error) { error.printStackTrace(); } }).start(); } } else { navView.inflateMenu(R.menu.bottom_nav_menu); } startInForeground(); if(BuildConfig.google_restriction && BuildConfig.full_instances) { RateThisApp.onCreate(this); RateThisApp.showRateDialogIfNeeded(this); } } private void startInForeground() { Intent notificationIntent = new Intent(this, RetrieveInfoService.class); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { startForegroundService(notificationIntent); } else { startService(notificationIntent); } } @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) { 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 instanceItem = menu.findItem(R.id.action_change_instance); 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); 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); } else { instanceItem.setVisible(true); uploadItem.setVisible(false); myVideosItem.setVisible(false); playslistItem.setVisible(false); historyItem.setVisible(false); settingsItem.setVisible(true); mostLikedItem.setVisible(false); } if( !BuildConfig.full_instances) { sepiaSearchItem.setVisible(false); } return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { if (item.getItemId() == R.id.action_change_instance) { if (BuildConfig.full_instances) { showRadioButtonDialogFullInstances(); } else { showRadioButtonDialog(); } return true; } 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 (Helper.isLoggedIn(MainActivity.this)) { intent = new Intent(MainActivity.this, AccountActivity.class); } else { intent = new Intent(MainActivity.this, LoginActivity.class); } startActivity(intent); return true; } else if (item.getItemId() == R.id.action_upload) { Intent intent = new Intent(MainActivity.this, PeertubeUploadActivity.class); startActivity(intent); return true; } 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); return true; } 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); return true; } 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); return true; } else if (item.getItemId() == R.id.action_playlist) { Intent intent = new Intent(MainActivity.this, AllPlaylistsActivity.class); startActivity(intent); return true; }else if(item.getItemId() == R.id.action_sepia_search) { Intent intent = new Intent(MainActivity.this, SepiaSearchActivity.class); startActivity(intent); return true; }else if (item.getItemId() == R.id.action_about) { Intent intent = new Intent(MainActivity.this, AboutActivity.class); startActivity(intent); return true; } return super.onOptionsItemSelected(item); } public void setActive(DisplayVideosFragment displayVideosFragment){ this.active = displayVideosFragment; } public void setSubscriptionFragment(DisplayVideosFragment displayVideosFragment) { this.subscriptionFragment = displayVideosFragment; } @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(); } } } @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 = Helper.getLiveInstance(MainActivity.this); int i = 0; for (String item : academies) { if (Helper.getPeertubeUrl(item).compareTo(acad) == 0) { break; } i++; } alt_bld.setSingleChoiceItems(academies, i, (dialog, item) -> { String newInstance = academies[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") private void showRadioButtonDialogFullInstances() { final SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE); AlertDialog.Builder alt_bld = new AlertDialog.Builder(this); alt_bld.setTitle(R.string.instance_choice); String instance = Helper.getLiveInstance(MainActivity.this); final EditText input = new EditText(MainActivity.this); 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(); WellKnownNodeinfo.NodeInfo instanceNodeInfo = new RetrofitPeertubeAPI(MainActivity.this, 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(); runOnUiThread(() -> { dialog.dismiss(); recreate(); }); } else { runOnUiThread(() -> Toasty.error(MainActivity.this, 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(MainActivity.this, InstancePickerActivity.class); startActivityForResult(intent, PICK_INSTANCE); }); 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(); } } } }