diff --git a/app/build.gradle b/app/build.gradle index f30ea1d65..bd46d5c69 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -9,8 +9,8 @@ android { defaultConfig { minSdk 21 targetSdk 31 - versionCode 385 - versionName "3.0.0-beta-22" + versionCode 386 + versionName "3.0.0-beta-23" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } flavorDimensions "default" @@ -71,13 +71,14 @@ allprojects { dependencies { implementation project(':autoimageslider') implementation 'androidx.appcompat:appcompat:1.4.2' - implementation 'com.google.android.material:material:1.5.0' - implementation 'androidx.constraintlayout:constraintlayout:2.1.3' + implementation 'com.google.android.material:material:1.6.1' + implementation 'androidx.constraintlayout:constraintlayout:2.1.4' implementation "com.google.code.gson:gson:2.8.6" implementation 'com.squareup.retrofit2:retrofit:2.9.0' implementation 'com.squareup.retrofit2:converter-gson:2.9.0' implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0' implementation 'androidx.preference:preference:1.2.0' + implementation "org.conscrypt:conscrypt-android:2.5.2" implementation 'com.github.evozi:Cyanea:1.0.7' implementation 'com.vanniktech:emoji-one:0.6.0' implementation 'com.github.GrenderG:Toasty:1.5.2' @@ -118,8 +119,8 @@ dependencies { implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' implementation 'androidx.lifecycle:lifecycle-livedata:2.4.1' implementation 'androidx.lifecycle:lifecycle-viewmodel:2.4.1' - implementation 'androidx.navigation:navigation-fragment:2.4.1' - implementation 'androidx.navigation:navigation-ui:2.4.1' + implementation 'androidx.navigation:navigation-fragment:2.4.2' + implementation 'androidx.navigation:navigation-ui:2.4.2' testImplementation 'junit:junit:' androidTestImplementation 'androidx.test.ext:junit:1.1.3' androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0' diff --git a/app/src/main/java/app/fedilab/android/activities/ContextActivity.java b/app/src/main/java/app/fedilab/android/activities/ContextActivity.java index 655dd9ccf..f2d12e1ac 100644 --- a/app/src/main/java/app/fedilab/android/activities/ContextActivity.java +++ b/app/src/main/java/app/fedilab/android/activities/ContextActivity.java @@ -15,6 +15,8 @@ package app.fedilab.android.activities; * see . */ +import static app.fedilab.android.ui.drawer.StatusAdapter.sendAction; + import android.content.SharedPreferences; import android.content.res.Resources; import android.graphics.drawable.ColorDrawable; @@ -28,17 +30,22 @@ import androidx.annotation.NonNull; import androidx.appcompat.app.ActionBar; import androidx.core.content.ContextCompat; import androidx.fragment.app.Fragment; +import androidx.lifecycle.ViewModelProvider; import androidx.preference.PreferenceManager; import app.fedilab.android.BaseMainActivity; import app.fedilab.android.R; import app.fedilab.android.client.entities.api.Status; +import app.fedilab.android.client.entities.app.QuickLoad; +import app.fedilab.android.client.entities.app.StatusCache; import app.fedilab.android.databinding.ActivityConversationBinding; +import app.fedilab.android.exception.DBException; import app.fedilab.android.helper.Helper; import app.fedilab.android.helper.MastodonHelper; import app.fedilab.android.helper.SpannableHelper; import app.fedilab.android.helper.ThemeHelper; import app.fedilab.android.ui.fragment.timeline.FragmentMastodonContext; +import app.fedilab.android.viewmodel.mastodon.StatusesVM; public class ContextActivity extends BaseActivity { @@ -91,6 +98,28 @@ public class ContextActivity extends BaseActivity { }; mainHandler.post(myRunnable); }).start(); + StatusesVM timelinesVM = new ViewModelProvider(ContextActivity.this).get(StatusesVM.class); + timelinesVM.getStatus(MainActivity.currentInstance, MainActivity.currentToken, focusedStatus.id).observe(ContextActivity.this, status -> { + StatusCache statusCache = new StatusCache(); + statusCache.instance = MainActivity.currentInstance; + statusCache.user_id = MainActivity.currentUserID; + statusCache.status = status; + statusCache.status_id = status.id; + //Update cache + new Thread(() -> { + try { + new StatusCache(getApplication()).updateIfExists(statusCache); + new QuickLoad(getApplication().getApplicationContext()).updateStatus(MainActivity.accountWeakReference.get(), status); + Handler mainHandler = new Handler(Looper.getMainLooper()); + //Update UI + Runnable myRunnable = () -> sendAction(ContextActivity.this, Helper.ARG_STATUS_ACTION, status, null); + mainHandler.post(myRunnable); + } catch (DBException e) { + e.printStackTrace(); + } + }).start(); + + }); } diff --git a/app/src/main/java/app/fedilab/android/activities/LoginActivity.java b/app/src/main/java/app/fedilab/android/activities/LoginActivity.java index dcf933e62..86e466500 100644 --- a/app/src/main/java/app/fedilab/android/activities/LoginActivity.java +++ b/app/src/main/java/app/fedilab/android/activities/LoginActivity.java @@ -14,16 +14,13 @@ package app.fedilab.android.activities; * You should have received a copy of the GNU General Public License along with Fedilab; if not, * see . */ -import static app.fedilab.android.BaseMainActivity.api; -import static app.fedilab.android.BaseMainActivity.client_id; -import static app.fedilab.android.BaseMainActivity.client_secret; -import static app.fedilab.android.BaseMainActivity.currentInstance; -import static app.fedilab.android.BaseMainActivity.software; + import static app.fedilab.android.helper.MastodonHelper.REDIRECT_CONTENT_WEB; import android.content.Intent; import android.content.SharedPreferences; import android.os.Bundle; +import android.util.Log; import android.view.Menu; import android.view.MenuItem; import android.widget.FrameLayout; @@ -36,7 +33,6 @@ import org.jetbrains.annotations.NotNull; import java.util.regex.Matcher; -import app.fedilab.android.BaseMainActivity; import app.fedilab.android.R; import app.fedilab.android.client.entities.app.Account; import app.fedilab.android.helper.Helper; @@ -53,7 +49,8 @@ public class LoginActivity extends BaseActivity { private final int PICK_IMPORT = 5557; private boolean requestedAdmin; - + public static Account.API apiLogin; + public static String currentInstanceLogin, client_idLogin, client_secretLogin, softwareLogin; private void manageItent(Intent intent) { if (intent != null && intent.getData() != null && intent.getData().toString().contains(REDIRECT_CONTENT_WEB + "?code=")) { @@ -65,22 +62,24 @@ public class LoginActivity extends BaseActivity { } String code = matcher.group(1); OauthVM oauthVM = new ViewModelProvider(LoginActivity.this).get(OauthVM.class); + + Log.v(Helper.TAG, "finalInstance: " + currentInstanceLogin); //We are dealing with a Mastodon API - if (api == Account.API.MASTODON) { + if (apiLogin == Account.API.MASTODON) { //API call to get the user token 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) + oauthVM.createToken(currentInstanceLogin, "authorization_code", client_idLogin, client_secretLogin, Helper.REDIRECT_CONTENT_WEB, scope, code) .observe(LoginActivity.this, tokenObj -> { Account account = new Account(); - account.client_id = BaseMainActivity.client_id; - account.client_secret = BaseMainActivity.client_secret; + account.client_id = client_idLogin; + account.client_secret = client_secretLogin; account.token = tokenObj.token_type + " " + tokenObj.access_token; - account.api = api; - account.software = software; - account.instance = currentInstance; + account.api = apiLogin; + account.software = softwareLogin; + account.instance = currentInstanceLogin; //API call to retrieve account information for the new token AccountsVM accountsVM = new ViewModelProvider(LoginActivity.this).get(AccountsVM.class); - accountsVM.getConnectedAccount(currentInstance, account.token).observe(LoginActivity.this, mastodonAccount -> { + accountsVM.getConnectedAccount(currentInstanceLogin, account.token).observe(LoginActivity.this, mastodonAccount -> { account.mastodon_account = mastodonAccount; account.user_id = mastodonAccount.id; //We check if user have really moderator rights @@ -112,8 +111,8 @@ public class LoginActivity extends BaseActivity { ThemeHelper.applyTheme(this); SharedPreferences sharedpreferences = PreferenceManager.getDefaultSharedPreferences(LoginActivity.this); setContentView(new FrameLayout(this)); - - Helper.addFragment(getSupportFragmentManager(), android.R.id.content, new FragmentLoginMain(), null, null, null); + FragmentLoginMain fragmentLoginMain = new FragmentLoginMain(); + Helper.addFragment(getSupportFragmentManager(), android.R.id.content, fragmentLoginMain, null, null, null); requestedAdmin = false; //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 @@ -185,5 +184,4 @@ public class LoginActivity extends BaseActivity { } } - } \ No newline at end of file diff --git a/app/src/main/java/app/fedilab/android/activities/WebviewConnectActivity.java b/app/src/main/java/app/fedilab/android/activities/WebviewConnectActivity.java index bdc8bb01b..3bd1f6fe4 100644 --- a/app/src/main/java/app/fedilab/android/activities/WebviewConnectActivity.java +++ b/app/src/main/java/app/fedilab/android/activities/WebviewConnectActivity.java @@ -16,9 +16,11 @@ package app.fedilab.android.activities; -import static app.fedilab.android.BaseMainActivity.api; -import static app.fedilab.android.BaseMainActivity.currentInstance; -import static app.fedilab.android.BaseMainActivity.software; +import static app.fedilab.android.activities.LoginActivity.apiLogin; +import static app.fedilab.android.activities.LoginActivity.client_idLogin; +import static app.fedilab.android.activities.LoginActivity.client_secretLogin; +import static app.fedilab.android.activities.LoginActivity.currentInstanceLogin; +import static app.fedilab.android.activities.LoginActivity.softwareLogin; import static app.fedilab.android.helper.Helper.PREF_USER_TOKEN; import android.annotation.SuppressLint; @@ -52,7 +54,6 @@ import androidx.preference.PreferenceManager; import java.util.regex.Matcher; -import app.fedilab.android.BaseMainActivity; import app.fedilab.android.R; import app.fedilab.android.client.entities.app.Account; import app.fedilab.android.databinding.ActivityWebviewConnectBinding; @@ -96,9 +97,9 @@ public class WebviewConnectActivity extends BaseActivity { //update the database new Account(activity).insertOrUpdate(account); Handler mainHandler = new Handler(Looper.getMainLooper()); - BaseMainActivity.currentToken = account.token; - BaseMainActivity.currentUserID = account.user_id; - api = Account.API.MASTODON; + MainActivity.currentToken = account.token; + MainActivity.currentUserID = account.user_id; + MainActivity.api = Account.API.MASTODON; SharedPreferences sharedpreferences = PreferenceManager.getDefaultSharedPreferences(activity); SharedPreferences.Editor editor = sharedpreferences.edit(); editor.putString(PREF_USER_TOKEN, account.token); @@ -130,7 +131,6 @@ public class WebviewConnectActivity extends BaseActivity { if (b != null) { login_url = b.getString("login_url"); requestedAdmin = b.getBoolean("requestedAdmin", false); - } if (login_url == null) finish(); @@ -223,18 +223,18 @@ public class WebviewConnectActivity extends BaseActivity { OauthVM oauthVM = new ViewModelProvider(WebviewConnectActivity.this).get(OauthVM.class); //API call to get the user token 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) + oauthVM.createToken(currentInstanceLogin, "authorization_code", client_idLogin, client_secretLogin, Helper.REDIRECT_CONTENT_WEB, scope, code) .observe(WebviewConnectActivity.this, tokenObj -> { Account account = new Account(); - account.client_id = BaseMainActivity.client_id; - account.client_secret = BaseMainActivity.client_secret; + account.client_id = client_idLogin; + account.client_secret = client_secretLogin; account.token = tokenObj.token_type + " " + tokenObj.access_token; - account.api = api; - account.software = software; - account.instance = currentInstance; + account.api = apiLogin; + account.software = softwareLogin; + account.instance = currentInstanceLogin; //API call to retrieve account information for the new token AccountsVM accountsVM = new ViewModelProvider(WebviewConnectActivity.this).get(AccountsVM.class); - accountsVM.getConnectedAccount(currentInstance, account.token).observe(WebviewConnectActivity.this, mastodonAccount -> { + accountsVM.getConnectedAccount(currentInstanceLogin, account.token).observe(WebviewConnectActivity.this, mastodonAccount -> { account.mastodon_account = mastodonAccount; account.user_id = mastodonAccount.id; //We check if user have really moderator rights diff --git a/app/src/main/java/app/fedilab/android/client/entities/app/QuickLoad.java b/app/src/main/java/app/fedilab/android/client/entities/app/QuickLoad.java index c59ec7b8e..424abbebc 100644 --- a/app/src/main/java/app/fedilab/android/client/entities/app/QuickLoad.java +++ b/app/src/main/java/app/fedilab/android/client/entities/app/QuickLoad.java @@ -198,6 +198,80 @@ public class QuickLoad { } } + + /** + * Update a status in quickload + * + * @param account {@link Account} + * @param newStatus - Status + * @throws DBException exception with database + */ + public void updateStatus(Account account, Status newStatus) throws DBException { + if (db == null) { + throw new DBException("db is null. Wrong initialization."); + } + + QuickLoad homeQuickLoad = getSavedValue(account, Timeline.TimeLineEnum.HOME, null); + QuickLoad localQuickLoad = getSavedValue(account, Timeline.TimeLineEnum.LOCAL, null); + QuickLoad publicQuickLoad = getSavedValue(account, Timeline.TimeLineEnum.PUBLIC, null); + + if (homeQuickLoad != null && homeQuickLoad.statuses != null) { + for (int i = 0; i < homeQuickLoad.statuses.size(); i++) { + if (homeQuickLoad.statuses.get(i).id.equals(newStatus.id)) { + homeQuickLoad.statuses.set(i, newStatus); + break; + } + } + ContentValues valuesHome = new ContentValues(); + valuesHome.put(Sqlite.COL_STATUSES, StatusDraft.mastodonStatusListToStringStorage(homeQuickLoad.statuses)); + //Inserts token + try { + db.update(Sqlite.TABLE_QUICK_LOAD, + valuesHome, Sqlite.COL_USER_ID + " = ? AND " + Sqlite.COL_INSTANCE + " =? AND " + Sqlite.COL_SLUG + "=?", + new String[]{homeQuickLoad.user_id, homeQuickLoad.instance, homeQuickLoad.slug}); + } catch (Exception e) { + e.printStackTrace(); + } + } + if (localQuickLoad != null && localQuickLoad.statuses != null) { + for (int i = 0; i < localQuickLoad.statuses.size(); i++) { + if (localQuickLoad.statuses.get(i).id.equals(newStatus.id)) { + localQuickLoad.statuses.set(i, newStatus); + break; + } + } + ContentValues valuesLocal = new ContentValues(); + valuesLocal.put(Sqlite.COL_STATUSES, StatusDraft.mastodonStatusListToStringStorage(localQuickLoad.statuses)); + //Inserts token + try { + db.update(Sqlite.TABLE_QUICK_LOAD, + valuesLocal, Sqlite.COL_USER_ID + " = ? AND " + Sqlite.COL_INSTANCE + " =? AND " + Sqlite.COL_SLUG + "=?", + new String[]{localQuickLoad.user_id, localQuickLoad.instance, localQuickLoad.slug}); + } catch (Exception e) { + e.printStackTrace(); + } + } + if (publicQuickLoad != null && publicQuickLoad.statuses != null) { + for (int i = 0; i < publicQuickLoad.statuses.size(); i++) { + if (publicQuickLoad.statuses.get(i).id.equals(newStatus.id)) { + publicQuickLoad.statuses.set(i, newStatus); + break; + } + } + ContentValues valuesPublic = new ContentValues(); + valuesPublic.put(Sqlite.COL_STATUSES, StatusDraft.mastodonStatusListToStringStorage(publicQuickLoad.statuses)); + //Inserts token + try { + db.update(Sqlite.TABLE_QUICK_LOAD, + valuesPublic, Sqlite.COL_USER_ID + " = ? AND " + Sqlite.COL_INSTANCE + " =? AND " + Sqlite.COL_SLUG + "=?", + new String[]{publicQuickLoad.user_id, publicQuickLoad.instance, publicQuickLoad.slug}); + } catch (Exception e) { + e.printStackTrace(); + } + } + + } + /** * Delete a status in quickload * diff --git a/app/src/main/java/app/fedilab/android/helper/Helper.java b/app/src/main/java/app/fedilab/android/helper/Helper.java index b3ab96800..1d92ef6e3 100644 --- a/app/src/main/java/app/fedilab/android/helper/Helper.java +++ b/app/src/main/java/app/fedilab/android/helper/Helper.java @@ -46,6 +46,7 @@ import android.net.NetworkInfo; import android.net.Uri; import android.os.Build; import android.os.Bundle; +import android.os.CountDownTimer; import android.os.Environment; import android.os.Handler; import android.os.Looper; @@ -93,6 +94,8 @@ import com.bumptech.glide.load.resource.bitmap.RoundedCorners; import com.bumptech.glide.request.RequestOptions; import com.jaredrummler.cyanea.Cyanea; +import org.conscrypt.Conscrypt; + import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileOutputStream; @@ -105,6 +108,7 @@ import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.PasswordAuthentication; import java.net.Proxy; +import java.security.Security; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.Collections; @@ -119,6 +123,7 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; import app.fedilab.android.BaseMainActivity; +import app.fedilab.android.MainApplication; import app.fedilab.android.R; import app.fedilab.android.activities.LoginActivity; import app.fedilab.android.activities.MainActivity; @@ -248,6 +253,7 @@ public class Helper { public static final String PREF_KEY_ID = "PREF_KEY_ID"; public static final String PREF_INSTANCE = "PREF_INSTANCE"; + public static final String SET_SECURITY_PROVIDER = "SET_SECURITY_PROVIDER"; public static final int NOTIFICATION_INTENT = 1; public static final int OPEN_NOTIFICATION = 2; @@ -433,7 +439,7 @@ public class Helper { public static void installProvider() { - /* boolean patch_provider = true; + boolean patch_provider = true; try { Context ctx = MainApplication.getApp(); SharedPreferences sharedpreferences = PreferenceManager.getDefaultSharedPreferences(ctx); @@ -445,7 +451,7 @@ public class Helper { Security.insertProviderAt(Conscrypt.newProvider(), 1); } catch (Exception ignored) { } - }*/ + } } /*** @@ -1597,4 +1603,41 @@ public class Helper { } context.deleteDatabase(OLD_DB_NAME); } + + + public static String dateDiffFull(Date dateToot) { + SimpleDateFormat df = (SimpleDateFormat) DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.MEDIUM, Locale.getDefault()); + try { + return df.format(dateToot); + } catch (Exception e) { + return ""; + } + } + + /** + * Makes the tvDate TextView field clickable, and displays the absolute date & time of a toot + * for 5 seconds. + * + * @param context Context + * @param tvDate TextView + * @param date Date + */ + + public static void absoluteDateTimeReveal(final Context context, final TextView tvDate, final Date date) { + tvDate.setOnClickListener(v -> { + + tvDate.setText(dateDiffFull(date)); + + new CountDownTimer((5 * 1000), 1000) { + + public void onTick(long millisUntilFinished) { + } + + public void onFinish() { + tvDate.setText(dateDiff(context, date)); + } + }.start(); + }); + } + } diff --git a/app/src/main/java/app/fedilab/android/ui/drawer/StatusAdapter.java b/app/src/main/java/app/fedilab/android/ui/drawer/StatusAdapter.java index 099f0d706..ed044b062 100644 --- a/app/src/main/java/app/fedilab/android/ui/drawer/StatusAdapter.java +++ b/app/src/main/java/app/fedilab/android/ui/drawer/StatusAdapter.java @@ -763,6 +763,7 @@ public class StatusAdapter extends RecyclerView.Adapter holder.binding.dateShort.setVisibility(View.VISIBLE); holder.binding.dateShort.setText(Helper.dateDiff(context, status.created_at)); holder.binding.time.setVisibility(View.GONE); + Helper.absoluteDateTimeReveal(context, holder.binding.dateShort, status.created_at); } //---- SPOILER TEXT ----- @@ -1718,6 +1719,10 @@ public class StatusAdapter extends RecyclerView.Adapter holder.timer.cancel(); holder.timer = null; } + if (holder.dateTimer != null) { + holder.dateTimer.cancel(); + holder.dateTimer = null; + } if (status.emojis != null && status.emojis.size() > 0) { holder.timer = new Timer(); holder.timer.scheduleAtFixedRate(new TimerTask() { @@ -1730,6 +1735,16 @@ public class StatusAdapter extends RecyclerView.Adapter } }, 100, 100); } + holder.dateTimer = new Timer(); + holder.dateTimer.scheduleAtFixedRate(new TimerTask() { + @Override + public void run() { + Handler mainHandler = new Handler(Looper.getMainLooper()); + Runnable myRunnable = () -> holder.binding.dateShort.setText(Helper.dateDiff(context, status.created_at)); + mainHandler.post(myRunnable); + + } + }, 100, 10000); } else if (viewHolder.getItemViewType() == STATUS_ART) { StatusViewHolder holder = (StatusViewHolder) viewHolder; MastodonHelper.loadPPMastodon(holder.bindingArt.artPp, status.account); @@ -1798,6 +1813,9 @@ public class StatusAdapter extends RecyclerView.Adapter if (holder instanceof StatusViewHolder && ((StatusViewHolder) holder).timer != null) { ((StatusViewHolder) holder).timer.cancel(); } + if (holder instanceof StatusViewHolder && ((StatusViewHolder) holder).dateTimer != null) { + ((StatusViewHolder) holder).dateTimer.cancel(); + } } public static class StatusViewHolder extends RecyclerView.ViewHolder { @@ -1808,6 +1826,7 @@ public class StatusAdapter extends RecyclerView.Adapter DrawerStatusNotificationBinding bindingNotification; DrawerStatusArtBinding bindingArt; Timer timer; + Timer dateTimer; StatusViewHolder(DrawerStatusBinding itemView) { super(itemView.getRoot()); diff --git a/app/src/main/java/app/fedilab/android/ui/fragment/login/FragmentLoginMain.java b/app/src/main/java/app/fedilab/android/ui/fragment/login/FragmentLoginMain.java index 1afde0aa8..a9045f083 100644 --- a/app/src/main/java/app/fedilab/android/ui/fragment/login/FragmentLoginMain.java +++ b/app/src/main/java/app/fedilab/android/ui/fragment/login/FragmentLoginMain.java @@ -14,10 +14,12 @@ package app.fedilab.android.ui.fragment.login; * You should have received a copy of the GNU General Public License along with Fedilab; if not, * see . */ -import static app.fedilab.android.BaseMainActivity.api; -import static app.fedilab.android.BaseMainActivity.client_id; -import static app.fedilab.android.BaseMainActivity.client_secret; -import static app.fedilab.android.BaseMainActivity.currentInstance; + +import static app.fedilab.android.activities.LoginActivity.apiLogin; +import static app.fedilab.android.activities.LoginActivity.client_idLogin; +import static app.fedilab.android.activities.LoginActivity.client_secretLogin; +import static app.fedilab.android.activities.LoginActivity.currentInstanceLogin; +import static app.fedilab.android.activities.LoginActivity.softwareLogin; import android.content.Intent; import android.content.SharedPreferences; @@ -25,6 +27,7 @@ import android.net.Uri; import android.os.Bundle; import android.text.Editable; import android.text.TextWatcher; +import android.util.Log; import android.view.ContextThemeWrapper; import android.view.LayoutInflater; import android.view.MenuInflater; @@ -135,36 +138,40 @@ public class FragmentLoginMain extends Fragment { binding.loginInstanceLayout.setErrorEnabled(true); return; } - currentInstance = binding.loginInstance.getText().toString().trim().toLowerCase(); - if (currentInstance.length() == 0) { + currentInstanceLogin = binding.loginInstance.getText().toString().trim().toLowerCase(); + if (currentInstanceLogin.length() == 0) { return; } binding.continueButton.setEnabled(false); NodeInfoVM nodeInfoVM = new ViewModelProvider(requireActivity()).get(NodeInfoVM.class); nodeInfoVM.getNodeInfo(binding.loginInstance.getText().toString()).observe(requireActivity(), nodeInfo -> { - if (nodeInfo == null) { - return; + if (nodeInfo != null) { + BaseMainActivity.software = nodeInfo.software.name.toUpperCase(); + switch (nodeInfo.software.name.toUpperCase().trim()) { + case "MASTODON": + apiLogin = Account.API.MASTODON; + break; + case "FRIENDICA": + apiLogin = Account.API.FRIENDICA; + break; + case "PIXELFED": + apiLogin = Account.API.PIXELFED; + break; + case "PLEROMA": + apiLogin = Account.API.PLEROMA; + break; + default: + apiLogin = Account.API.UNKNOWN; + break; + } + softwareLogin = nodeInfo.software.name.toUpperCase(); + } else { + apiLogin = Account.API.MASTODON; + softwareLogin = "MASTODON"; } + binding.continueButton.setEnabled(true); - BaseMainActivity.software = nodeInfo.software.name.toUpperCase(); - switch (nodeInfo.software.name.toUpperCase().trim()) { - case "MASTODON": - api = Account.API.MASTODON; - break; - case "FRIENDICA": - api = Account.API.FRIENDICA; - break; - case "PIXELFED": - api = Account.API.PIXELFED; - break; - case "PLEROMA": - api = Account.API.PLEROMA; - break; - default: - api = Account.API.UNKNOWN; - break; - } - retrievesClientId(currentInstance); + retrievesClientId(currentInstanceLogin); }); }); return root; @@ -246,20 +253,21 @@ public class FragmentLoginMain extends Fragment { } try { - currentInstance = URLEncoder.encode(host, "utf-8"); + currentInstanceLogin = URLEncoder.encode(host, "utf-8"); } catch (UnsupportedEncodingException e) { Toasty.error(requireActivity(), getString(R.string.client_error), Toast.LENGTH_LONG).show(); } String scopes = ((LoginActivity) requireActivity()).requestedAdmin() ? Helper.OAUTH_SCOPES_ADMIN : Helper.OAUTH_SCOPES; AppsVM appsVM = new ViewModelProvider(requireActivity()).get(AppsVM.class); - appsVM.createApp(currentInstance, getString(R.string.app_name), + String finalInstance = instance; + appsVM.createApp(currentInstanceLogin, 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, ((LoginActivity) requireActivity()).requestedAdmin()); + client_idLogin = app.client_id; + client_secretLogin = app.client_secret; + String redirectUrl = MastodonHelper.authorizeURL(currentInstanceLogin, client_idLogin, ((LoginActivity) requireActivity()).requestedAdmin()); SharedPreferences sharedpreferences = PreferenceManager.getDefaultSharedPreferences(requireActivity()); boolean embedded_browser = sharedpreferences.getBoolean(getString(R.string.SET_EMBEDDED_BROWSER), true); if (embedded_browser) { @@ -272,6 +280,7 @@ public class FragmentLoginMain extends Fragment { Intent intent = new Intent(Intent.ACTION_VIEW); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); intent.setData(Uri.parse(redirectUrl)); + Log.v(Helper.TAG, ">value: " + finalInstance); try { startActivity(intent); } catch (Exception e) { diff --git a/app/src/main/java/app/fedilab/android/ui/fragment/timeline/FragmentMastodonNotification.java b/app/src/main/java/app/fedilab/android/ui/fragment/timeline/FragmentMastodonNotification.java index ada5962e9..ffadc847f 100644 --- a/app/src/main/java/app/fedilab/android/ui/fragment/timeline/FragmentMastodonNotification.java +++ b/app/src/main/java/app/fedilab/android/ui/fragment/timeline/FragmentMastodonNotification.java @@ -183,7 +183,7 @@ public class FragmentMastodonNotification extends Fragment { binding.loader.setVisibility(View.GONE); binding.swipeContainer.setRefreshing(false); flagLoading = false; - if (notifications == null || notifications.notifications == null) { + if (notifications == null || notifications.notifications == null || notifications.notifications.size() == 0) { binding.noActionText.setText(R.string.no_notifications); binding.noAction.setVisibility(View.VISIBLE); binding.recyclerView.setVisibility(View.GONE); diff --git a/app/src/main/java/app/fedilab/android/ui/fragment/timeline/FragmentMastodonTimeline.java b/app/src/main/java/app/fedilab/android/ui/fragment/timeline/FragmentMastodonTimeline.java index 7f0189163..1996c0f58 100644 --- a/app/src/main/java/app/fedilab/android/ui/fragment/timeline/FragmentMastodonTimeline.java +++ b/app/src/main/java/app/fedilab/android/ui/fragment/timeline/FragmentMastodonTimeline.java @@ -377,6 +377,7 @@ public class FragmentMastodonTimeline extends Fragment implements StatusAdapter. flagLoading = false; if (statuses != null && fetched_statuses != null && fetched_statuses.statuses != null && fetched_statuses.statuses.size() > 0) { flagLoading = fetched_statuses.pagination.max_id == null; + binding.noAction.setVisibility(View.GONE); if (timelineType == Timeline.TimeLineEnum.ART) { //We have to split media in different statuses List mediaStatuses = new ArrayList<>(); diff --git a/app/src/main/java/app/fedilab/android/viewmodel/mastodon/NotificationsVM.java b/app/src/main/java/app/fedilab/android/viewmodel/mastodon/NotificationsVM.java index b72976ccc..d2df890c8 100644 --- a/app/src/main/java/app/fedilab/android/viewmodel/mastodon/NotificationsVM.java +++ b/app/src/main/java/app/fedilab/android/viewmodel/mastodon/NotificationsVM.java @@ -106,7 +106,9 @@ public class NotificationsVM extends AndroidViewModel { if (notifications.notifications != null) { for (Notification notification : notifications.notifications) { if (notification != null) { - notification.status = SpannableHelper.convertStatus(getApplication().getApplicationContext(), notification.status); + if (notification.status != null) { + notification.status = SpannableHelper.convertStatus(getApplication().getApplicationContext(), notification.status); + } } } }