Fix some crashes

This commit is contained in:
Thomas 2022-05-26 14:20:51 +02:00
parent 6c31f1f4a6
commit b884d67fbd
9 changed files with 174 additions and 153 deletions

View File

@ -14,27 +14,22 @@ package app.fedilab.android.activities;
* You should have received a copy of the GNU General Public License along with Fedilab; if not, * You should have received a copy of the GNU General Public License along with Fedilab; if not,
* see <http://www.gnu.org/licenses>. */ * see <http://www.gnu.org/licenses>. */
import static app.fedilab.android.BaseMainActivity.admin;
import static app.fedilab.android.BaseMainActivity.api; import static app.fedilab.android.BaseMainActivity.api;
import static app.fedilab.android.BaseMainActivity.client_id; import static app.fedilab.android.BaseMainActivity.client_id;
import static app.fedilab.android.BaseMainActivity.client_secret; import static app.fedilab.android.BaseMainActivity.client_secret;
import static app.fedilab.android.BaseMainActivity.currentInstance; import static app.fedilab.android.BaseMainActivity.currentInstance;
import static app.fedilab.android.BaseMainActivity.software; import static app.fedilab.android.BaseMainActivity.software;
import static app.fedilab.android.helper.Helper.PREF_USER_TOKEN;
import static app.fedilab.android.helper.MastodonHelper.REDIRECT_CONTENT_WEB; import static app.fedilab.android.helper.MastodonHelper.REDIRECT_CONTENT_WEB;
import android.content.Intent; import android.content.Intent;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.view.Menu; import android.view.Menu;
import android.view.MenuItem; import android.view.MenuItem;
import android.widget.FrameLayout; import android.widget.FrameLayout;
import android.widget.Toast; import android.widget.Toast;
import androidx.lifecycle.ViewModelProvider; import androidx.lifecycle.ViewModelProvider;
import androidx.navigation.fragment.NavHostFragment;
import androidx.preference.PreferenceManager; import androidx.preference.PreferenceManager;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@ -44,12 +39,11 @@ import java.util.regex.Matcher;
import app.fedilab.android.BaseMainActivity; import app.fedilab.android.BaseMainActivity;
import app.fedilab.android.R; import app.fedilab.android.R;
import app.fedilab.android.client.entities.app.Account; import app.fedilab.android.client.entities.app.Account;
import app.fedilab.android.client.entities.app.WellKnownNodeinfo;
import app.fedilab.android.exception.DBException;
import app.fedilab.android.helper.Helper; import app.fedilab.android.helper.Helper;
import app.fedilab.android.helper.ThemeHelper; import app.fedilab.android.helper.ThemeHelper;
import app.fedilab.android.ui.fragment.login.FragmentLoginMain; import app.fedilab.android.ui.fragment.login.FragmentLoginMain;
import app.fedilab.android.viewmodel.mastodon.AccountsVM; import app.fedilab.android.viewmodel.mastodon.AccountsVM;
import app.fedilab.android.viewmodel.mastodon.AdminVM;
import app.fedilab.android.viewmodel.mastodon.OauthVM; import app.fedilab.android.viewmodel.mastodon.OauthVM;
import es.dmoral.toasty.Toasty; import es.dmoral.toasty.Toasty;
@ -58,10 +52,7 @@ public class LoginActivity extends BaseActivity {
private final int PICK_IMPORT = 5557; private final int PICK_IMPORT = 5557;
private String oldSearch; private boolean requestedAdmin;
private String autofilledInstance;
private WellKnownNodeinfo.NodeInfo nodeInfo;
private NavHostFragment host;
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
@ -71,14 +62,7 @@ public class LoginActivity extends BaseActivity {
setContentView(new FrameLayout(this)); setContentView(new FrameLayout(this));
Helper.addFragment(getSupportFragmentManager(), android.R.id.content, new FragmentLoginMain(), null, null, null); Helper.addFragment(getSupportFragmentManager(), android.R.id.content, new FragmentLoginMain(), null, null, null);
requestedAdmin = false;
Bundle b = getIntent().getExtras();
if (b != null) {
autofilledInstance = b.getString("instance", null);
admin = b.getBoolean("admin", false);
}
//The activity handles a redirect URI, it will extract token code and will proceed to authentication //The activity handles a redirect URI, it will extract token code and will proceed to authentication
//That happens when the user wants to use an external browser //That happens when the user wants to use an external browser
if (getIntent() != null && getIntent().getData() != null && getIntent().getData().toString().contains(REDIRECT_CONTENT_WEB + "?code=")) { if (getIntent() != null && getIntent().getData() != null && getIntent().getData().toString().contains(REDIRECT_CONTENT_WEB + "?code=")) {
@ -93,7 +77,8 @@ public class LoginActivity extends BaseActivity {
//We are dealing with a Mastodon API //We are dealing with a Mastodon API
if (api == Account.API.MASTODON) { if (api == Account.API.MASTODON) {
//API call to get the user token //API call to get the user token
oauthVM.createToken(currentInstance, "authorization_code", client_id, client_secret, Helper.REDIRECT_CONTENT_WEB, Helper.OAUTH_SCOPES, code) String scope = requestedAdmin ? Helper.OAUTH_SCOPES_ADMIN : Helper.OAUTH_SCOPES;
oauthVM.createToken(currentInstance, "authorization_code", client_id, client_secret, Helper.REDIRECT_CONTENT_WEB, scope, code)
.observe(LoginActivity.this, tokenObj -> { .observe(LoginActivity.this, tokenObj -> {
Account account = new Account(); Account account = new Account();
account.client_id = BaseMainActivity.client_id; account.client_id = BaseMainActivity.client_id;
@ -106,37 +91,31 @@ public class LoginActivity extends BaseActivity {
AccountsVM accountsVM = new ViewModelProvider(LoginActivity.this).get(AccountsVM.class); AccountsVM accountsVM = new ViewModelProvider(LoginActivity.this).get(AccountsVM.class);
accountsVM.getConnectedAccount(currentInstance, account.token).observe(LoginActivity.this, mastodonAccount -> { accountsVM.getConnectedAccount(currentInstance, account.token).observe(LoginActivity.this, mastodonAccount -> {
account.mastodon_account = mastodonAccount; account.mastodon_account = mastodonAccount;
new Thread(() -> { account.user_id = mastodonAccount.id;
try { //We check if user have really moderator rights
account.user_id = mastodonAccount.id; if (requestedAdmin) {
//update the database AdminVM adminVM = new ViewModelProvider(LoginActivity.this).get(AdminVM.class);
new Account(LoginActivity.this).insertOrUpdate(account); adminVM.getAccount(account.instance, account.token, account.user_id).observe(LoginActivity.this, adminAccount -> {
account.mastodon_account.admin = adminAccount != null;
BaseMainActivity.currentToken = account.token; WebviewConnectActivity.proceedLogin(LoginActivity.this, account);
BaseMainActivity.currentUserID = account.user_id; });
api = Account.API.MASTODON; } else {
SharedPreferences.Editor editor = sharedpreferences.edit(); WebviewConnectActivity.proceedLogin(LoginActivity.this, account);
editor.putString(PREF_USER_TOKEN, account.token); }
editor.commit();
//The user is now aut
//The user is now authenticated, it will be redirected to MainActivity
Handler mainHandler = new Handler(Looper.getMainLooper());
Runnable myRunnable = () -> {
Intent mainActivity = new Intent(LoginActivity.this, MainActivity.class);
startActivity(mainActivity);
finish();
};
mainHandler.post(myRunnable);
} catch (DBException e) {
e.printStackTrace();
}
}).start();
}); });
}); });
} }
} }
} }
public boolean requestedAdmin() {
return requestedAdmin;
}
public boolean setAdmin(boolean askAdmin) {
return requestedAdmin = askAdmin;
}
@Override @Override
protected void onResume() { protected void onResume() {
super.onResume(); super.onResume();

View File

@ -17,6 +17,7 @@ package app.fedilab.android.activities;
import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.ColorDrawable;
import android.os.Bundle; import android.os.Bundle;
import android.view.MenuItem; import android.view.MenuItem;
import android.view.View;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.core.content.ContextCompat; import androidx.core.content.ContextCompat;
@ -68,6 +69,11 @@ public class SettingsActivity extends BaseActivity {
binding.setTheming.setOnClickListener(v -> displaySettings(SettingsEnum.THEMING)); binding.setTheming.setOnClickListener(v -> displaySettings(SettingsEnum.THEMING));
binding.setAdministration.setOnClickListener(v -> displaySettings(SettingsEnum.ADMINISTRATION)); binding.setAdministration.setOnClickListener(v -> displaySettings(SettingsEnum.ADMINISTRATION));
binding.setLanguage.setOnClickListener(v -> displaySettings(SettingsEnum.LANGUAGE)); binding.setLanguage.setOnClickListener(v -> displaySettings(SettingsEnum.LANGUAGE));
if (MainActivity.accountWeakReference.get().mastodon_account.admin) {
binding.setAdministration.setVisibility(View.VISIBLE);
} else {
binding.setAdministration.setVisibility(View.GONE);
}
} }
public void displaySettings(SettingsEnum settingsEnum) { public void displaySettings(SettingsEnum settingsEnum) {

View File

@ -22,6 +22,7 @@ import static app.fedilab.android.BaseMainActivity.software;
import static app.fedilab.android.helper.Helper.PREF_USER_TOKEN; import static app.fedilab.android.helper.Helper.PREF_USER_TOKEN;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.SharedPreferences; import android.content.SharedPreferences;
@ -30,6 +31,7 @@ import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler; import android.os.Handler;
import android.os.Looper; import android.os.Looper;
import android.util.Log;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
@ -59,6 +61,7 @@ import app.fedilab.android.exception.DBException;
import app.fedilab.android.helper.Helper; import app.fedilab.android.helper.Helper;
import app.fedilab.android.helper.ThemeHelper; import app.fedilab.android.helper.ThemeHelper;
import app.fedilab.android.viewmodel.mastodon.AccountsVM; import app.fedilab.android.viewmodel.mastodon.AccountsVM;
import app.fedilab.android.viewmodel.mastodon.AdminVM;
import app.fedilab.android.viewmodel.mastodon.OauthVM; import app.fedilab.android.viewmodel.mastodon.OauthVM;
@ -68,6 +71,7 @@ public class WebviewConnectActivity extends BaseActivity {
private ActivityWebviewConnectBinding binding; private ActivityWebviewConnectBinding binding;
private AlertDialog alert; private AlertDialog alert;
private String login_url; private String login_url;
private boolean requestedAdmin;
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")
public static void clearCookies(Context context) { public static void clearCookies(Context context) {
@ -86,6 +90,34 @@ public class WebviewConnectActivity extends BaseActivity {
} }
} }
@SuppressLint("ApplySharedPref")
public static void proceedLogin(Activity activity, Account account) {
new Thread(() -> {
try {
//update the database
Log.v(Helper.TAG, "account.mastodon_account.admin: " + account.mastodon_account.admin);
new Account(activity).insertOrUpdate(account);
Handler mainHandler = new Handler(Looper.getMainLooper());
BaseMainActivity.currentToken = account.token;
BaseMainActivity.currentUserID = account.user_id;
api = Account.API.MASTODON;
SharedPreferences sharedpreferences = PreferenceManager.getDefaultSharedPreferences(activity);
SharedPreferences.Editor editor = sharedpreferences.edit();
editor.putString(PREF_USER_TOKEN, account.token);
editor.commit();
//The user is now authenticated, it will be redirected to MainActivity
Runnable myRunnable = () -> {
Intent mainActivity = new Intent(activity, MainActivity.class);
activity.startActivity(mainActivity);
activity.finish();
};
mainHandler.post(myRunnable);
} catch (DBException e) {
e.printStackTrace();
}
}).start();
}
@SuppressLint("SetJavaScriptEnabled") @SuppressLint("SetJavaScriptEnabled")
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
@ -99,7 +131,10 @@ public class WebviewConnectActivity extends BaseActivity {
Bundle b = getIntent().getExtras(); Bundle b = getIntent().getExtras();
if (b != null) { if (b != null) {
login_url = b.getString("login_url"); login_url = b.getString("login_url");
requestedAdmin = b.getBoolean("requestedAdmin", false);
} }
Log.v(Helper.TAG, "requestedAdmin: " + requestedAdmin);
if (login_url == null) if (login_url == null)
finish(); finish();
ActionBar actionBar = getSupportActionBar(); ActionBar actionBar = getSupportActionBar();
@ -190,7 +225,8 @@ public class WebviewConnectActivity extends BaseActivity {
String code = matcher.group(1); String code = matcher.group(1);
OauthVM oauthVM = new ViewModelProvider(WebviewConnectActivity.this).get(OauthVM.class); OauthVM oauthVM = new ViewModelProvider(WebviewConnectActivity.this).get(OauthVM.class);
//API call to get the user token //API call to get the user token
oauthVM.createToken(currentInstance, "authorization_code", BaseMainActivity.client_id, BaseMainActivity.client_secret, Helper.REDIRECT_CONTENT_WEB, Helper.OAUTH_SCOPES, code) String scope = requestedAdmin ? Helper.OAUTH_SCOPES_ADMIN : Helper.OAUTH_SCOPES;
oauthVM.createToken(currentInstance, "authorization_code", BaseMainActivity.client_id, BaseMainActivity.client_secret, Helper.REDIRECT_CONTENT_WEB, scope, code)
.observe(WebviewConnectActivity.this, tokenObj -> { .observe(WebviewConnectActivity.this, tokenObj -> {
Account account = new Account(); Account account = new Account();
account.client_id = BaseMainActivity.client_id; account.client_id = BaseMainActivity.client_id;
@ -204,29 +240,20 @@ public class WebviewConnectActivity extends BaseActivity {
accountsVM.getConnectedAccount(currentInstance, account.token).observe(WebviewConnectActivity.this, mastodonAccount -> { accountsVM.getConnectedAccount(currentInstance, account.token).observe(WebviewConnectActivity.this, mastodonAccount -> {
account.mastodon_account = mastodonAccount; account.mastodon_account = mastodonAccount;
account.user_id = mastodonAccount.id; account.user_id = mastodonAccount.id;
new Thread(() -> { //We check if user have really moderator rights
try { if (requestedAdmin) {
//update the database AdminVM adminVM = new ViewModelProvider(WebviewConnectActivity.this).get(AdminVM.class);
new Account(WebviewConnectActivity.this).insertOrUpdate(account); Log.v(Helper.TAG, " account.instance: " + account.instance);
Handler mainHandler = new Handler(Looper.getMainLooper()); Log.v(Helper.TAG, " account.token: " + account.token);
BaseMainActivity.currentToken = account.token; Log.v(Helper.TAG, " account.user_id: " + account.user_id);
BaseMainActivity.currentUserID = account.user_id; adminVM.getAccount(account.instance, account.token, account.user_id).observe(WebviewConnectActivity.this, adminAccount -> {
api = Account.API.MASTODON; Log.v(Helper.TAG, "adminAccount: " + adminAccount);
SharedPreferences sharedpreferences = PreferenceManager.getDefaultSharedPreferences(WebviewConnectActivity.this); account.mastodon_account.admin = adminAccount != null;
SharedPreferences.Editor editor = sharedpreferences.edit(); proceedLogin(WebviewConnectActivity.this, account);
editor.putString(PREF_USER_TOKEN, account.token); });
editor.commit(); } else {
//The user is now authenticated, it will be redirected to MainActivity proceedLogin(WebviewConnectActivity.this, account);
Runnable myRunnable = () -> { }
Intent mainActivity = new Intent(WebviewConnectActivity.this, MainActivity.class);
startActivity(mainActivity);
finish();
};
mainHandler.post(myRunnable);
} catch (DBException e) {
e.printStackTrace();
}
}).start();
}); });
}); });
return true; return true;

View File

@ -73,14 +73,15 @@ public class Account implements Serializable {
public Date mute_expires_at; public Date mute_expires_at;
@SerializedName("moved") @SerializedName("moved")
public Account moved; public Account moved;
//Local var
@SerializedName("admin")
public boolean admin;
//Some extra spannable element - They will be filled automatically when fetching the account //Some extra spannable element - They will be filled automatically when fetching the account
public transient Spannable span_display_name; public transient Spannable span_display_name;
public transient Spannable span_note; public transient Spannable span_note;
public transient RelationShip relationShip; public transient RelationShip relationShip;
public static class AccountParams implements Serializable { public static class AccountParams implements Serializable {
@SerializedName("discoverable") @SerializedName("discoverable")
public boolean discoverable; public boolean discoverable;

View File

@ -431,29 +431,34 @@ public class Account implements Serializable {
account.updated_at = Helper.stringToDate(context, c.getString(c.getColumnIndexOrThrow(Sqlite.COL_UPDATED_AT))); account.updated_at = Helper.stringToDate(context, c.getString(c.getColumnIndexOrThrow(Sqlite.COL_UPDATED_AT)));
account.software = c.getString(c.getColumnIndexOrThrow(Sqlite.COL_SOFTWARE)); account.software = c.getString(c.getColumnIndexOrThrow(Sqlite.COL_SOFTWARE));
String apiStr = c.getString(c.getColumnIndexOrThrow(Sqlite.COL_API)); String apiStr = c.getString(c.getColumnIndexOrThrow(Sqlite.COL_API));
API api = null; API api;
switch (apiStr) { switch (apiStr) {
case "MASTODON": case "MASTODON":
api = API.MASTODON; api = API.MASTODON;
break; break;
case "PEERTUBE": case "FRIENDICA":
api = API.PEERTUBE; api = API.FRIENDICA;
break; break;
case "PIXELFED": case "PIXELFED":
api = API.PIXELFED; api = API.PIXELFED;
break; break;
case "PLEROMA":
api = API.PLEROMA;
break;
default:
api = API.UNKNOWN;
break;
} }
account.api = api; account.api = api;
if (api == API.MASTODON) { account.mastodon_account = restoreAccountFromString(c.getString(c.getColumnIndexOrThrow(Sqlite.COL_ACCOUNT)));
account.mastodon_account = restoreAccountFromString(c.getString(c.getColumnIndexOrThrow(Sqlite.COL_ACCOUNT)));
}
return account; return account;
} }
public enum API { public enum API {
MASTODON, MASTODON,
PEERTUBE, FRIENDICA,
PIXELFED PLEROMA,
PIXELFED,
UNKNOWN
} }
} }

View File

@ -14,7 +14,6 @@ package app.fedilab.android.ui.fragment.login;
* You should have received a copy of the GNU General Public License along with Fedilab; if not, * You should have received a copy of the GNU General Public License along with Fedilab; if not,
* see <http://www.gnu.org/licenses>. */ * see <http://www.gnu.org/licenses>. */
import static app.fedilab.android.BaseMainActivity.admin;
import static app.fedilab.android.BaseMainActivity.api; import static app.fedilab.android.BaseMainActivity.api;
import static app.fedilab.android.BaseMainActivity.client_id; import static app.fedilab.android.BaseMainActivity.client_id;
import static app.fedilab.android.BaseMainActivity.client_secret; import static app.fedilab.android.BaseMainActivity.client_secret;
@ -48,6 +47,7 @@ import java.net.URLEncoder;
import app.fedilab.android.BaseMainActivity; import app.fedilab.android.BaseMainActivity;
import app.fedilab.android.R; import app.fedilab.android.R;
import app.fedilab.android.activities.LoginActivity;
import app.fedilab.android.activities.ProxyActivity; import app.fedilab.android.activities.ProxyActivity;
import app.fedilab.android.activities.WebviewConnectActivity; import app.fedilab.android.activities.WebviewConnectActivity;
import app.fedilab.android.client.entities.app.Account; import app.fedilab.android.client.entities.app.Account;
@ -62,7 +62,6 @@ import es.dmoral.toasty.Toasty;
public class FragmentLoginMain extends Fragment { public class FragmentLoginMain extends Fragment {
private static boolean client_id_for_webview = false;
private FragmentLoginMainBinding binding; private FragmentLoginMainBinding binding;
private boolean searchInstanceRunning = false; private boolean searchInstanceRunning = false;
private String oldSearch; private String oldSearch;
@ -77,6 +76,7 @@ public class FragmentLoginMain extends Fragment {
binding.menuIcon.setOnClickListener(this::showMenu); binding.menuIcon.setOnClickListener(this::showMenu);
binding.loginInstance.setOnItemClickListener((parent, view, position, id) -> oldSearch = parent.getItemAtPosition(position).toString().trim()); binding.loginInstance.setOnItemClickListener((parent, view, position, id) -> oldSearch = parent.getItemAtPosition(position).toString().trim());
binding.adminScope.setOnCheckedChangeListener((compoundButton, checked) -> ((LoginActivity) requireActivity()).setAdmin(checked));
binding.loginInstance.addTextChangedListener(new TextWatcher() { binding.loginInstance.addTextChangedListener(new TextWatcher() {
@Override @Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) { public void beforeTextChanged(CharSequence s, int start, int count, int after) {
@ -144,29 +144,25 @@ public class FragmentLoginMain extends Fragment {
NodeInfoVM nodeInfoVM = new ViewModelProvider(requireActivity()).get(NodeInfoVM.class); NodeInfoVM nodeInfoVM = new ViewModelProvider(requireActivity()).get(NodeInfoVM.class);
nodeInfoVM.getNodeInfo(binding.loginInstance.getText().toString()).observe(requireActivity(), nodeInfo -> { nodeInfoVM.getNodeInfo(binding.loginInstance.getText().toString()).observe(requireActivity(), nodeInfo -> {
binding.continueButton.setEnabled(true); binding.continueButton.setEnabled(true);
if (nodeInfo != null && nodeInfo.software != null) { BaseMainActivity.software = nodeInfo.software.name.toUpperCase();
BaseMainActivity.software = nodeInfo.software.name.toUpperCase(); switch (nodeInfo.software.name.toUpperCase().trim()) {
if (nodeInfo.software.name.toUpperCase().trim().equals("PLEROMA") || nodeInfo.software.name.toUpperCase().trim().equals("MASTODON") || nodeInfo.software.name.toUpperCase().trim().equals("PIXELFED")) { case "MASTODON":
client_id_for_webview = true;
api = Account.API.MASTODON; api = Account.API.MASTODON;
retrievesClientId(currentInstance); break;
} else { case "FRIENDICA":
client_id_for_webview = false; api = Account.API.FRIENDICA;
if (nodeInfo.software.name.equals("PEERTUBE")) { break;
Toasty.error(requireActivity(), "Peertube is currently not supported", Toasty.LENGTH_LONG).show(); case "PIXELFED":
} else if (nodeInfo.software.name.equals("GNU")) { api = Account.API.PIXELFED;
Toasty.error(requireActivity(), "GNU is currently not supported", Toasty.LENGTH_LONG).show(); break;
} else { //Fallback to Mastodon case "PLEROMA":
client_id_for_webview = true; api = Account.API.PLEROMA;
api = Account.API.MASTODON; break;
retrievesClientId(currentInstance); default:
} api = Account.API.UNKNOWN;
} break;
} else { //Fallback to Mastodon
client_id_for_webview = true;
api = Account.API.MASTODON;
retrievesClientId(currentInstance);
} }
retrievesClientId(currentInstance);
}); });
}); });
return root; return root;
@ -217,57 +213,53 @@ public class FragmentLoginMain extends Fragment {
} }
private void retrievesClientId(String instance) { private void retrievesClientId(String instance) {
if (client_id_for_webview) { if (!instance.startsWith("http://") && !instance.startsWith("https://")) {
if (!instance.startsWith("http://") && !instance.startsWith("https://")) { instance = "https://" + instance;
instance = "https://" + instance; }
} String host = instance;
String host = instance; try {
try { URL url = new URL(instance);
URL url = new URL(instance); host = url.getHost();
host = url.getHost(); } catch (MalformedURLException e) {
} catch (MalformedURLException e) { e.printStackTrace();
e.printStackTrace(); }
}
try {
currentInstance = URLEncoder.encode(host, "utf-8");
} catch (UnsupportedEncodingException e) {
Toasty.error(requireActivity(), getString(R.string.client_error), Toast.LENGTH_LONG).show();
}
if (api == Account.API.MASTODON) {
String scopes = Helper.OAUTH_SCOPES;
if (admin) {
scopes = Helper.OAUTH_SCOPES_ADMIN;
}
AppsVM appsVM = new ViewModelProvider(requireActivity()).get(AppsVM.class);
appsVM.createApp(currentInstance, getString(R.string.app_name),
client_id_for_webview ? Helper.REDIRECT_CONTENT_WEB : Helper.REDIRECT_CONTENT,
scopes,
Helper.WEBSITE_VALUE
).observe(requireActivity(), app -> {
client_id = app.client_id;
client_secret = app.client_secret;
String redirectUrl = MastodonHelper.authorizeURL(currentInstance, client_id, admin);
SharedPreferences sharedpreferences = PreferenceManager.getDefaultSharedPreferences(requireActivity());
boolean embedded_browser = sharedpreferences.getBoolean(getString(R.string.SET_EMBEDDED_BROWSER), true);
if (embedded_browser) {
Intent i = new Intent(requireActivity(), WebviewConnectActivity.class);
i.putExtra("login_url", redirectUrl);
startActivity(i);
requireActivity().finish();
} else {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setData(Uri.parse(redirectUrl));
try {
startActivity(intent);
} catch (Exception e) {
Toasty.error(requireActivity(), getString(R.string.toast_error), Toast.LENGTH_LONG).show();
}
try {
currentInstance = URLEncoder.encode(host, "utf-8");
} catch (UnsupportedEncodingException e) {
Toasty.error(requireActivity(), getString(R.string.client_error), Toast.LENGTH_LONG).show();
}
if (api == Account.API.MASTODON) {
String scopes = binding.adminScope.isChecked() ? Helper.OAUTH_SCOPES_ADMIN : Helper.OAUTH_SCOPES;
AppsVM appsVM = new ViewModelProvider(requireActivity()).get(AppsVM.class);
appsVM.createApp(currentInstance, getString(R.string.app_name),
Helper.REDIRECT_CONTENT_WEB,
scopes,
Helper.WEBSITE_VALUE
).observe(requireActivity(), app -> {
client_id = app.client_id;
client_secret = app.client_secret;
String redirectUrl = MastodonHelper.authorizeURL(currentInstance, client_id, binding.adminScope.isChecked());
SharedPreferences sharedpreferences = PreferenceManager.getDefaultSharedPreferences(requireActivity());
boolean embedded_browser = sharedpreferences.getBoolean(getString(R.string.SET_EMBEDDED_BROWSER), true);
if (embedded_browser) {
Intent i = new Intent(requireActivity(), WebviewConnectActivity.class);
i.putExtra("login_url", redirectUrl);
i.putExtra("requestedAdmin", binding.adminScope.isChecked());
startActivity(i);
requireActivity().finish();
} else {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setData(Uri.parse(redirectUrl));
try {
startActivity(intent);
} catch (Exception e) {
Toasty.error(requireActivity(), getString(R.string.toast_error), Toast.LENGTH_LONG).show();
} }
});
} }
});
} }
} }
} }

View File

@ -60,6 +60,7 @@ public class FragmentMastodonContext extends Fragment {
private StatusesVM statusesVM; private StatusesVM statusesVM;
private List<Status> statuses; private List<Status> statuses;
private StatusAdapter statusAdapter; private StatusAdapter statusAdapter;
private RecyclerViewThreadLines recyclerViewThreadLines;
//Handle actions that can be done in other fragments //Handle actions that can be done in other fragments
private final BroadcastReceiver receive_action = new BroadcastReceiver() { private final BroadcastReceiver receive_action = new BroadcastReceiver() {
@Override @Override
@ -252,7 +253,8 @@ public class FragmentMastodonContext extends Fragment {
} }
} }
List<LineInfo> threadDecorationInfo = getThreadDecorationInfo(context, focusedStatus.id); List<LineInfo> threadDecorationInfo = getThreadDecorationInfo(context, focusedStatus.id);
binding.recyclerView.addItemDecoration(new RecyclerViewThreadLines(requireContext(), threadDecorationInfo)); recyclerViewThreadLines = new RecyclerViewThreadLines(requireContext(), threadDecorationInfo);
binding.recyclerView.addItemDecoration(recyclerViewThreadLines);
binding.swipeContainer.setRefreshing(false); binding.swipeContainer.setRefreshing(false);
binding.recyclerView.scrollToPosition(statusPosition); binding.recyclerView.scrollToPosition(statusPosition);
} }
@ -260,6 +262,7 @@ public class FragmentMastodonContext extends Fragment {
@Override @Override
public void onDestroyView() { public void onDestroyView() {
binding.recyclerView.setAdapter(null); binding.recyclerView.setAdapter(null);
binding.recyclerView.removeItemDecoration(recyclerViewThreadLines);
statusAdapter = null; statusAdapter = null;
binding = null; binding = null;
LocalBroadcastManager.getInstance(requireActivity()).unregisterReceiver(receive_action); LocalBroadcastManager.getInstance(requireActivity()).unregisterReceiver(receive_action);

View File

@ -49,6 +49,13 @@
android:inputType="textWebEmailAddress" android:inputType="textWebEmailAddress"
android:singleLine="true" /> android:singleLine="true" />
<com.google.android.material.checkbox.MaterialCheckBox
android:id="@+id/admin_scope"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/admin_scope"
app:buttonTint="@color/cyanea_accent_reference" />
</com.google.android.material.textfield.TextInputLayout> </com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.button.MaterialButton <com.google.android.material.button.MaterialButton

View File

@ -1601,6 +1601,7 @@
<string name="top_menu">Top bar menu</string> <string name="top_menu">Top bar menu</string>
<string name="also_favourite_by">"Also favourited by: "</string> <string name="also_favourite_by">"Also favourited by: "</string>
<string name="also_boosted_by">Also boosted by:</string> <string name="also_boosted_by">Also boosted by:</string>
<string name="admin_scope">I am a moderator</string>
</resources> </resources>