mobilizon-android-app/app/src/main/java/app/fedilab/mobilizon/MainActivity.java

428 lines
20 KiB
Java

package app.fedilab.mobilizon;
import android.Manifest;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Bundle;
import android.text.SpannableString;
import android.text.style.UnderlineSpan;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.webkit.ValueCallback;
import android.webkit.WebView;
import android.widget.EditText;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.appcompat.app.ActionBarDrawerToggle;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.SearchView;
import androidx.appcompat.widget.Toolbar;
import androidx.core.view.GravityCompat;
import androidx.drawerlayout.widget.DrawerLayout;
import com.google.android.material.navigation.NavigationView;
import com.google.android.material.snackbar.Snackbar;
import com.karumi.dexter.Dexter;
import com.karumi.dexter.listener.multi.MultiplePermissionsListener;
import com.karumi.dexter.listener.multi.SnackbarOnAnyDeniedMultiplePermissionsListener;
import java.io.File;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import app.fedilab.mobilizon.client.RetrofitMobilizonAPI;
import app.fedilab.mobilizon.client.entities.WellKnownNodeinfo;
import app.fedilab.mobilizon.helper.Helper;
import app.fedilab.mobilizon.webview.MobilizonWebChromeClient;
import app.fedilab.mobilizon.webview.MobilizonWebViewClient;
import es.dmoral.toasty.Toasty;
public class MainActivity extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener {
public static final int INPUT_FILE_REQUEST_CODE = 123;
public static boolean isAuthenticated = false;
private RelativeLayout progress;
private WebView main_webview;
private FrameLayout webview_container;
private ValueCallback<Uri[]> mFilePathCallback;
private static final int PICK_INSTANCE = 546;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
final DrawerLayout drawer = findViewById(R.id.drawer_layout);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
toggle.setDrawerIndicatorEnabled(false);
if (getSupportActionBar() != null) {
getSupportActionBar().setHomeButtonEnabled(true);
toggle = new ActionBarDrawerToggle(
this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
toggle.setDrawerIndicatorEnabled(true);
drawer.addDrawerListener(toggle);
toggle.syncState();
}
final NavigationView navigationView = findViewById(R.id.nav_view);
navigationView.setNavigationItemSelectedListener(this);
WebView.setWebContentsDebuggingEnabled(true);
drawMenu();
main_webview = findViewById(R.id.main_webview);
progress = findViewById(R.id.progress);
webview_container = findViewById(R.id.webview_container);
final ViewGroup videoLayout = findViewById(R.id.videoLayout);
String instance = Helper.getLiveInstance(MainActivity.this);
Helper.initializeWebview(MainActivity.this, main_webview, instance);
MobilizonWebChromeClient mobilizonWebChromeClient = new MobilizonWebChromeClient(MainActivity.this, main_webview, webview_container, videoLayout);
main_webview.setWebChromeClient(mobilizonWebChromeClient);
main_webview.setWebViewClient(new MobilizonWebViewClient(MainActivity.this));
showProgressDialog();
main_webview.loadUrl("https://" + instance);
MultiplePermissionsListener snackbarMultiplePermissionsListener =
SnackbarOnAnyDeniedMultiplePermissionsListener.Builder
.with(main_webview, R.string.permissions_message)
.withOpenSettingsButton(R.string.settings)
.withCallback(new Snackbar.Callback() {
@Override
public void onShown(Snackbar snackbar) {
// Event handler for when the given Snackbar is visible
}
@Override
public void onDismissed(Snackbar snackbar, int event) {
// Event handler for when the given Snackbar has been dismissed
}
})
.build();
Dexter.withContext(this)
.withPermissions(
Manifest.permission.ACCESS_COARSE_LOCATION,
Manifest.permission.ACCESS_FINE_LOCATION
)
.withListener(snackbarMultiplePermissionsListener).check();
new Thread(() -> {
try {
WellKnownNodeinfo.NodeInfo instanceNodeInfo = new RetrofitMobilizonAPI(instance).getNodeInfo();
if (instanceNodeInfo.getSoftware() != null && instanceNodeInfo.getSoftware().getName().trim().toLowerCase().compareTo("mobilizon") == 0) {
runOnUiThread(() -> {
final SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
String previousVersion = sharedpreferences.getString(Helper.PREF_VERSION+instance, null);
if( previousVersion != null && previousVersion.trim().compareTo(instanceNodeInfo.getSoftware().getVersion()) != 0) {
SharedPreferences.Editor editor = sharedpreferences.edit();
editor.putString(Helper.PREF_VERSION + instance.trim(), instanceNodeInfo.getSoftware().getVersion().trim());
editor.apply();
File dir = new File(getFilesDir().getPath()+"/" + instance);
if (dir.isDirectory()) {
String[] children = dir.list();
if( children != null) {
for (String child : children) {
//noinspection ResultOfMethodCallIgnored
new File(dir, child).delete();
}
}
}
main_webview.reload();
}else if(previousVersion == null) {
SharedPreferences.Editor editor = sharedpreferences.edit();
editor.putString(Helper.PREF_VERSION + instance.trim(), instanceNodeInfo.getSoftware().getVersion().trim());
editor.apply();
}
});
}
} catch (Exception ignored) {}
}).start();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, 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) {
try {
main_webview.loadUrl("https://" + Helper.getLiveInstance(MainActivity.this) + "/search?term=" + URLEncoder.encode(query, String.valueOf(StandardCharsets.UTF_8)));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
if (!searchView.isIconified()) {
searchView.setIconified(true);
}
myActionMenuItem.collapseActionView();
return false;
}
@Override
public boolean onQueryTextChange(String s) {
return false;
}
});
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_instance) {
showRadioButtonDialogFullInstances();
return true;
} else if (id == R.id.action_about) {
AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
LayoutInflater inflater = getLayoutInflater();
View dialogView = inflater.inflate(R.layout.popup_about, new LinearLayout(MainActivity.this), false);
TextView about = dialogView.findViewById(R.id.about);
TextView terms = dialogView.findViewById(R.id.terms);
TextView license = dialogView.findViewById(R.id.license);
TextView about_the_app = dialogView.findViewById(R.id.about_the_app);
SpannableString contentAbout = new SpannableString(about.getText().toString());
contentAbout.setSpan(new UnderlineSpan(), 0, contentAbout.length(), 0);
about.setText(contentAbout);
about.setOnClickListener(v -> {
Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("https://" + Helper.getLiveInstance(MainActivity.this) + "/about"));
startActivity(browserIntent);
});
SpannableString contentTerms = new SpannableString(terms.getText().toString());
contentTerms.setSpan(new UnderlineSpan(), 0, contentTerms.length(), 0);
terms.setText(contentTerms);
terms.setOnClickListener(v -> {
Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("https://" + Helper.getLiveInstance(MainActivity.this) + "/terms"));
startActivity(browserIntent);
});
SpannableString contentLicense = new SpannableString(license.getText().toString());
contentLicense.setSpan(new UnderlineSpan(), 0, contentLicense.length(), 0);
license.setText(contentLicense);
license.setOnClickListener(v -> {
Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("https://framagit.org/framasoft/mobilizon/blob/master/LICENSE"));
startActivity(browserIntent);
});
try {
PackageInfo pInfo = getPackageManager().getPackageInfo(getPackageName(), 0);
String version = pInfo.versionName;
about_the_app.setText(getResources().getString(R.string.about_the_app, version));
} catch (PackageManager.NameNotFoundException ignored) {
}
SpannableString contentAboutApp = new SpannableString(about_the_app.getText().toString());
contentAboutApp.setSpan(new UnderlineSpan(), 0, contentAboutApp.length(), 0);
about_the_app.setText(contentAboutApp);
about_the_app.setOnClickListener(v -> {
Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("https://framagit.org/tom79/mobilizon-android-app"));
startActivity(browserIntent);
});
builder.setView(dialogView);
builder
.setPositiveButton(R.string.close, (dialog, which) -> dialog.dismiss())
.setIcon(R.drawable.ic_baseline_info_24)
.show();
}
return super.onOptionsItemSelected(item);
}
public void showProgressDialog() {
if (progress != null) {
progress.setVisibility(View.VISIBLE);
webview_container.setVisibility(View.GONE);
}
}
public void hideProgressDialog() {
if (progress != null) {
progress.setVisibility(View.GONE);
webview_container.setVisibility(View.VISIBLE);
}
}
@Override
public void onBackPressed() {
if (main_webview.canGoBack()) {
main_webview.goBack();
} else {
super.onBackPressed();
}
}
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
int id = item.getItemId();
if (id == R.id.nav_explore) {
main_webview.loadUrl("javascript:document.querySelector('a[href=\"/search\"]').click();");
} else if (id == R.id.nav_my_event) {
main_webview.loadUrl("javascript:document.querySelector('a[href=\"/events/me\"]').click();");
} else if (id == R.id.nav_my_group) {
main_webview.loadUrl("javascript:document.querySelector('a[href=\"/groups/me\"]').click();");
} else if (id == R.id.nav_create_event) {
main_webview.loadUrl("javascript:document.querySelector('a[href=\"/events/create\"]').click();");
} else if (id == R.id.nav_login) {
main_webview.loadUrl("javascript:document.querySelector('a[href=\"/login\"]').click();");
} else if (id == R.id.nav_logout) {
Helper.clearCookies();
new java.util.Timer().schedule(
new java.util.TimerTask() {
@Override
public void run() {
runOnUiThread(() -> {
isAuthenticated = false;
drawMenu();
main_webview.loadUrl("https://" + Helper.getLiveInstance(MainActivity.this));
});
}
},
1000
);
} else if (id == R.id.nav_profile) {
main_webview.loadUrl("javascript:document.querySelector('a[href=\"/identity/update\"]').click();");
} else if (id == R.id.nav_register) {
main_webview.loadUrl("javascript:document.querySelector('a[href=\"/register/user\"]').click();");
}
DrawerLayout drawer = findViewById(R.id.drawer_layout);
drawer.closeDrawer(GravityCompat.START);
return true;
}
@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 RetrofitMobilizonAPI(newInstance).getNodeInfo();
if (instanceNodeInfo.getSoftware() != null && instanceNodeInfo.getSoftware().getName().trim().toLowerCase().compareTo("mobilizon") == 0) {
SharedPreferences.Editor editor = sharedpreferences.edit();
editor.putString(Helper.PREF_INSTANCE, newInstance);
editor.commit();
runOnUiThread(() -> {
dialog.dismiss();
main_webview.clearHistory();
main_webview.loadUrl("https://" + newInstance);
});
} else {
runOnUiThread(() -> Toasty.error(MainActivity.this, getString(R.string.not_valide_instance), Toast.LENGTH_LONG).show());
}
} catch (Exception e) {
runOnUiThread(() -> Toasty.error(MainActivity.this, getString(R.string.not_valide_instance), Toast.LENGTH_LONG).show());
e.printStackTrace();
}
}).start());
//TODO: uncomment and add support for picking instances when available
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();
}
public ValueCallback<Uri[]> getmFilePathCallback() {
return mFilePathCallback;
}
public void setmFilePathCallback(ValueCallback<Uri[]> mFilePathCallback) {
this.mFilePathCallback = mFilePathCallback;
}
@SuppressLint("ApplySharedPref")
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode != INPUT_FILE_REQUEST_CODE || mFilePathCallback == null) {
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();
}
}
super.onActivityResult(requestCode, resultCode, data);
return;
}
Uri[] results = null;
if (resultCode == Activity.RESULT_OK) {
if (data != null) {
String dataString = data.getDataString();
if (dataString != null) {
results = new Uri[]{Uri.parse(dataString)};
}
}
}
mFilePathCallback.onReceiveValue(results);
mFilePathCallback = null;
}
public void drawMenu() {
final NavigationView navigationView = findViewById(R.id.nav_view);
if (isAuthenticated) {
navigationView.getMenu().findItem(R.id.nav_create_event).setVisible(true);
navigationView.getMenu().findItem(R.id.nav_profile).setVisible(true);
navigationView.getMenu().findItem(R.id.nav_login).setVisible(false);
navigationView.getMenu().findItem(R.id.nav_logout).setVisible(true);
navigationView.getMenu().findItem(R.id.nav_register).setVisible(false);
} else {
navigationView.getMenu().findItem(R.id.nav_create_event).setVisible(false);
navigationView.getMenu().findItem(R.id.nav_profile).setVisible(false);
navigationView.getMenu().findItem(R.id.nav_login).setVisible(true);
navigationView.getMenu().findItem(R.id.nav_logout).setVisible(false);
navigationView.getMenu().findItem(R.id.nav_register).setVisible(true);
}
//navigationView.invalidate();
}
}