Loading app/build.gradle +4 −2 Original line number Diff line number Diff line Loading @@ -13,8 +13,8 @@ android { defaultConfig { minSdk 21 targetSdk 31 versionCode 423 versionName "3.6.2" versionCode 424 versionName "3.6.3" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } flavorDimensions "default" Loading Loading @@ -95,6 +95,8 @@ dependencies { implementation "com.github.bumptech.glide:glide:4.12.0" implementation "com.github.bumptech.glide:okhttp3-integration:4.12.0" implementation "org.jsoup:jsoup:1.15.1" implementation 'com.github.mergehez:ArgPlayer:v3.1' implementation project(path: ':mytransl') implementation project(path: ':ratethisapp') Loading app/src/main/assets/release_notes/notes.json +5 −0 Original line number Diff line number Diff line [ { "version": "3.6.3", "code": "424", "note": "Fixed:\n- Issue with messages/notifications not correctly displayed\n- Friendica: issues with mentions and tags (open browser)\n- Improve sharing behaviour\n" }, { "version": "3.6.2", "code": "423", Loading app/src/main/java/app/fedilab/android/BaseMainActivity.java +102 −95 Original line number Diff line number Diff line Loading @@ -79,6 +79,10 @@ import com.google.android.material.snackbar.Snackbar; import com.google.android.material.tabs.TabLayout; import com.jaredrummler.cyanea.Cyanea; import org.jsoup.Jsoup; import org.jsoup.nodes.Document; import org.jsoup.nodes.Element; import java.io.File; import java.io.IOException; import java.util.ArrayList; Loading Loading @@ -852,15 +856,9 @@ public abstract class BaseMainActivity extends BaseActivity implements NetworkSt boolean fetchSharedMedia = sharedpreferences.getBoolean(getString(R.string.SET_RETRIEVE_METADATA_IF_URL_FROM_EXTERAL), true); boolean fetchShareContent = sharedpreferences.getBoolean(getString(R.string.SET_SHARE_DETAILS), true); if (url[0] != null && count == 1 && (fetchShareContent || fetchSharedMedia)) { if (!url[0].trim().equalsIgnoreCase(sharedText.trim())) { Bundle b = new Bundle(); b.putString(Helper.ARG_SHARE_TITLE, sharedSubject); b.putString(Helper.ARG_SHARE_DESCRIPTION, sharedText); CrossActionHelper.doCrossShare(BaseMainActivity.this, b); } else { String originalUrl = url[0]; new Thread(() -> { if (url[0].startsWith("www.")) url[0] = "http://" + url[0]; if (!url[0].matches("^https?://.*")) url[0] = "http://" + url[0]; Matcher matcherPattern = Patterns.WEB_URL.matcher(url[0]); String potentialUrl = null; while (matcherPattern.find()) { Loading @@ -871,9 +869,7 @@ public abstract class BaseMainActivity extends BaseActivity implements NetworkSt } // If we actually have a URL then make use of it. if (potentialUrl != null && potentialUrl.length() > 0) { Pattern titlePattern = Pattern.compile("<meta [^>]*property=[\"']og:title[\"'] [^>]*content=[\"']([^'^\"]+?)[\"'][^>]*>"); Pattern descriptionPattern = Pattern.compile("<meta [^>]*property=[\"']og:description[\"'] [^>]*content=[\"']([^'^\"]+?)[\"'][^>]*>"); Pattern imagePattern = Pattern.compile("<meta [^>]*property=[\"']og:image[\"'] [^>]*content=[\"']([^'^\"]+?)[\"'][^>]*>"); try { OkHttpClient client = new OkHttpClient.Builder() Loading @@ -896,40 +892,53 @@ public abstract class BaseMainActivity extends BaseActivity implements NetworkSt if (response.isSuccessful()) { try { String data = response.body().string(); Matcher matcherTitle; matcherTitle = titlePattern.matcher(data); Matcher matcherDescription = descriptionPattern.matcher(data); Matcher matcherImage = imagePattern.matcher(data); String titleEncoded = null; String descriptionEncoded = null; if (fetchShareContent) { while (matcherTitle.find()) titleEncoded = matcherTitle.group(1); while (matcherDescription.find()) descriptionEncoded = matcherDescription.group(1); } String image = null; if (fetchSharedMedia) { while (matcherImage.find()) image = matcherImage.group(1); } String title = null; String description = null; Document html = Jsoup.parse(data); Element titleEl = html.selectFirst("meta[property='og:title']"); Element descriptionEl = html.selectFirst("meta[property='og:description']"); Element imageUrlEl = html.selectFirst("meta[property='og:image']"); String title = ""; String description = ""; if(titleEl != null) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { if (titleEncoded != null) title = Html.fromHtml(titleEncoded, Html.FROM_HTML_MODE_LEGACY).toString(); if (descriptionEncoded != null) description = Html.fromHtml(descriptionEncoded, Html.FROM_HTML_MODE_LEGACY).toString(); title = Html.fromHtml(titleEl.attr("content"), Html.FROM_HTML_MODE_LEGACY).toString(); } else { if (titleEncoded != null) title = Html.fromHtml(titleEncoded).toString(); if (descriptionEncoded != null) description = Html.fromHtml(descriptionEncoded).toString(); title = Html.fromHtml(titleEl.attr("content")).toString(); } } String finalImage = image; String finalTitle = title; String finalDescription = description; if(descriptionEl != null) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { description = Html.fromHtml(descriptionEl.attr("content"), Html.FROM_HTML_MODE_LEGACY).toString(); } else { description = Html.fromHtml(descriptionEl.attr("content")).toString(); } } String imageUrl = ""; if(imageUrlEl != null) { imageUrl = imageUrlEl.attr("content"); } StringBuilder titleBuilder = new StringBuilder(); if(!originalUrl.trim().equalsIgnoreCase(sharedText.trim())) { // If the shared text is not just the URL, add it to the top String toAppend = sharedText.replaceAll("\\s*" + Pattern.quote(originalUrl) + "\\s*", ""); titleBuilder.append(toAppend); } if (title.length() > 0) { // OG title fetched from source if(titleBuilder.length() > 0) titleBuilder.append("\n\n"); titleBuilder.append(title); } String finalImage = imageUrl; String finalTitle = titleBuilder.toString(); String finalDescription = description; runOnUiThread(() -> { Bundle b = new Bundle(); Loading @@ -955,8 +964,6 @@ public abstract class BaseMainActivity extends BaseActivity implements NetworkSt } }).start(); } } else { Bundle b = new Bundle(); b.putString(Helper.ARG_SHARE_TITLE, sharedSubject); Loading app/src/main/java/app/fedilab/android/activities/InstanceProfileActivity.java +1 −41 Original line number Diff line number Diff line Loading @@ -15,34 +15,21 @@ package app.fedilab.android.activities; * see <http://www.gnu.org/licenses>. */ import static androidx.core.text.HtmlCompat.FROM_HTML_MODE_LEGACY; import android.os.Build; import android.os.Bundle; import android.text.Html; import android.text.SpannableString; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.widget.Button; import android.widget.TextView; import android.widget.Toast; import androidx.lifecycle.ViewModelProvider; import androidx.recyclerview.widget.LinearLayoutManager; import java.util.ArrayList; import java.util.List; import app.fedilab.android.BaseMainActivity; import app.fedilab.android.R; import app.fedilab.android.client.entities.api.Account; import app.fedilab.android.databinding.ActivityInstanceProfileBinding; import app.fedilab.android.helper.Helper; import app.fedilab.android.helper.ThemeHelper; import app.fedilab.android.ui.drawer.AccountAdapter; import app.fedilab.android.viewmodel.mastodon.NodeInfoVM; import app.fedilab.android.viewmodel.mastodon.SearchVM; import es.dmoral.toasty.Toasty; public class InstanceProfileActivity extends BaseActivity { Loading Loading @@ -75,40 +62,13 @@ public class InstanceProfileActivity extends BaseActivity { finish(); return; } binding.name.setText(nodeInfo.metadata != null ? nodeInfo.metadata.nodeName : instance); binding.name.setText(instance); SpannableString descriptionSpan; if (nodeInfo.metadata != null && nodeInfo.metadata.nodeDescription != null) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) descriptionSpan = new SpannableString(Html.fromHtml(nodeInfo.metadata.nodeDescription, FROM_HTML_MODE_LEGACY)); else descriptionSpan = new SpannableString(Html.fromHtml(nodeInfo.metadata.nodeDescription)); binding.description.setText(descriptionSpan, TextView.BufferType.SPANNABLE); } binding.userCount.setText(Helper.withSuffix((nodeInfo.usage.users.total))); binding.statusCount.setText(Helper.withSuffix(((nodeInfo.usage.localPosts)))); String softwareStr = nodeInfo.software.name + " - "; binding.software.setText(softwareStr); binding.version.setText(nodeInfo.software.version); if (nodeInfo.metadata != null && nodeInfo.metadata.staffAccounts != null && nodeInfo.metadata.staffAccounts.size() > 0) { SearchVM searchVM = new ViewModelProvider(InstanceProfileActivity.this).get(SearchVM.class); List<Account> accounts = new ArrayList<>(); for (String accountURL : nodeInfo.metadata.staffAccounts) { searchVM.search(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, accountURL, null, "accounts", false, true, false, 0, null, null, 1) .observe(InstanceProfileActivity.this, results -> { if (results.accounts != null && results.accounts.size() > 0) { accounts.add(results.accounts.get(0)); } if (accounts.size() == nodeInfo.metadata.staffAccounts.size()) { AccountAdapter accountsListAdapter = new AccountAdapter(accounts); binding.lvAccounts.setAdapter(accountsListAdapter); final LinearLayoutManager mLayoutManager; mLayoutManager = new LinearLayoutManager(InstanceProfileActivity.this); binding.lvAccounts.setLayoutManager(mLayoutManager); } }); } } binding.instanceContainer.setVisibility(View.VISIBLE); binding.loader.setVisibility(View.GONE); }); Loading app/src/main/java/app/fedilab/android/client/entities/api/Tag.java +12 −0 Original line number Diff line number Diff line Loading @@ -27,4 +27,16 @@ public class Tag implements Serializable { public String url; @SerializedName("history") public List<History> history; public int getWeight() { int weight = 0; for (History h : history) { try { weight += Integer.parseInt(h.accounts); } catch (Exception ignored) { } } return weight; } } Loading
app/build.gradle +4 −2 Original line number Diff line number Diff line Loading @@ -13,8 +13,8 @@ android { defaultConfig { minSdk 21 targetSdk 31 versionCode 423 versionName "3.6.2" versionCode 424 versionName "3.6.3" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } flavorDimensions "default" Loading Loading @@ -95,6 +95,8 @@ dependencies { implementation "com.github.bumptech.glide:glide:4.12.0" implementation "com.github.bumptech.glide:okhttp3-integration:4.12.0" implementation "org.jsoup:jsoup:1.15.1" implementation 'com.github.mergehez:ArgPlayer:v3.1' implementation project(path: ':mytransl') implementation project(path: ':ratethisapp') Loading
app/src/main/assets/release_notes/notes.json +5 −0 Original line number Diff line number Diff line [ { "version": "3.6.3", "code": "424", "note": "Fixed:\n- Issue with messages/notifications not correctly displayed\n- Friendica: issues with mentions and tags (open browser)\n- Improve sharing behaviour\n" }, { "version": "3.6.2", "code": "423", Loading
app/src/main/java/app/fedilab/android/BaseMainActivity.java +102 −95 Original line number Diff line number Diff line Loading @@ -79,6 +79,10 @@ import com.google.android.material.snackbar.Snackbar; import com.google.android.material.tabs.TabLayout; import com.jaredrummler.cyanea.Cyanea; import org.jsoup.Jsoup; import org.jsoup.nodes.Document; import org.jsoup.nodes.Element; import java.io.File; import java.io.IOException; import java.util.ArrayList; Loading Loading @@ -852,15 +856,9 @@ public abstract class BaseMainActivity extends BaseActivity implements NetworkSt boolean fetchSharedMedia = sharedpreferences.getBoolean(getString(R.string.SET_RETRIEVE_METADATA_IF_URL_FROM_EXTERAL), true); boolean fetchShareContent = sharedpreferences.getBoolean(getString(R.string.SET_SHARE_DETAILS), true); if (url[0] != null && count == 1 && (fetchShareContent || fetchSharedMedia)) { if (!url[0].trim().equalsIgnoreCase(sharedText.trim())) { Bundle b = new Bundle(); b.putString(Helper.ARG_SHARE_TITLE, sharedSubject); b.putString(Helper.ARG_SHARE_DESCRIPTION, sharedText); CrossActionHelper.doCrossShare(BaseMainActivity.this, b); } else { String originalUrl = url[0]; new Thread(() -> { if (url[0].startsWith("www.")) url[0] = "http://" + url[0]; if (!url[0].matches("^https?://.*")) url[0] = "http://" + url[0]; Matcher matcherPattern = Patterns.WEB_URL.matcher(url[0]); String potentialUrl = null; while (matcherPattern.find()) { Loading @@ -871,9 +869,7 @@ public abstract class BaseMainActivity extends BaseActivity implements NetworkSt } // If we actually have a URL then make use of it. if (potentialUrl != null && potentialUrl.length() > 0) { Pattern titlePattern = Pattern.compile("<meta [^>]*property=[\"']og:title[\"'] [^>]*content=[\"']([^'^\"]+?)[\"'][^>]*>"); Pattern descriptionPattern = Pattern.compile("<meta [^>]*property=[\"']og:description[\"'] [^>]*content=[\"']([^'^\"]+?)[\"'][^>]*>"); Pattern imagePattern = Pattern.compile("<meta [^>]*property=[\"']og:image[\"'] [^>]*content=[\"']([^'^\"]+?)[\"'][^>]*>"); try { OkHttpClient client = new OkHttpClient.Builder() Loading @@ -896,40 +892,53 @@ public abstract class BaseMainActivity extends BaseActivity implements NetworkSt if (response.isSuccessful()) { try { String data = response.body().string(); Matcher matcherTitle; matcherTitle = titlePattern.matcher(data); Matcher matcherDescription = descriptionPattern.matcher(data); Matcher matcherImage = imagePattern.matcher(data); String titleEncoded = null; String descriptionEncoded = null; if (fetchShareContent) { while (matcherTitle.find()) titleEncoded = matcherTitle.group(1); while (matcherDescription.find()) descriptionEncoded = matcherDescription.group(1); } String image = null; if (fetchSharedMedia) { while (matcherImage.find()) image = matcherImage.group(1); } String title = null; String description = null; Document html = Jsoup.parse(data); Element titleEl = html.selectFirst("meta[property='og:title']"); Element descriptionEl = html.selectFirst("meta[property='og:description']"); Element imageUrlEl = html.selectFirst("meta[property='og:image']"); String title = ""; String description = ""; if(titleEl != null) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { if (titleEncoded != null) title = Html.fromHtml(titleEncoded, Html.FROM_HTML_MODE_LEGACY).toString(); if (descriptionEncoded != null) description = Html.fromHtml(descriptionEncoded, Html.FROM_HTML_MODE_LEGACY).toString(); title = Html.fromHtml(titleEl.attr("content"), Html.FROM_HTML_MODE_LEGACY).toString(); } else { if (titleEncoded != null) title = Html.fromHtml(titleEncoded).toString(); if (descriptionEncoded != null) description = Html.fromHtml(descriptionEncoded).toString(); title = Html.fromHtml(titleEl.attr("content")).toString(); } } String finalImage = image; String finalTitle = title; String finalDescription = description; if(descriptionEl != null) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { description = Html.fromHtml(descriptionEl.attr("content"), Html.FROM_HTML_MODE_LEGACY).toString(); } else { description = Html.fromHtml(descriptionEl.attr("content")).toString(); } } String imageUrl = ""; if(imageUrlEl != null) { imageUrl = imageUrlEl.attr("content"); } StringBuilder titleBuilder = new StringBuilder(); if(!originalUrl.trim().equalsIgnoreCase(sharedText.trim())) { // If the shared text is not just the URL, add it to the top String toAppend = sharedText.replaceAll("\\s*" + Pattern.quote(originalUrl) + "\\s*", ""); titleBuilder.append(toAppend); } if (title.length() > 0) { // OG title fetched from source if(titleBuilder.length() > 0) titleBuilder.append("\n\n"); titleBuilder.append(title); } String finalImage = imageUrl; String finalTitle = titleBuilder.toString(); String finalDescription = description; runOnUiThread(() -> { Bundle b = new Bundle(); Loading @@ -955,8 +964,6 @@ public abstract class BaseMainActivity extends BaseActivity implements NetworkSt } }).start(); } } else { Bundle b = new Bundle(); b.putString(Helper.ARG_SHARE_TITLE, sharedSubject); Loading
app/src/main/java/app/fedilab/android/activities/InstanceProfileActivity.java +1 −41 Original line number Diff line number Diff line Loading @@ -15,34 +15,21 @@ package app.fedilab.android.activities; * see <http://www.gnu.org/licenses>. */ import static androidx.core.text.HtmlCompat.FROM_HTML_MODE_LEGACY; import android.os.Build; import android.os.Bundle; import android.text.Html; import android.text.SpannableString; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.widget.Button; import android.widget.TextView; import android.widget.Toast; import androidx.lifecycle.ViewModelProvider; import androidx.recyclerview.widget.LinearLayoutManager; import java.util.ArrayList; import java.util.List; import app.fedilab.android.BaseMainActivity; import app.fedilab.android.R; import app.fedilab.android.client.entities.api.Account; import app.fedilab.android.databinding.ActivityInstanceProfileBinding; import app.fedilab.android.helper.Helper; import app.fedilab.android.helper.ThemeHelper; import app.fedilab.android.ui.drawer.AccountAdapter; import app.fedilab.android.viewmodel.mastodon.NodeInfoVM; import app.fedilab.android.viewmodel.mastodon.SearchVM; import es.dmoral.toasty.Toasty; public class InstanceProfileActivity extends BaseActivity { Loading Loading @@ -75,40 +62,13 @@ public class InstanceProfileActivity extends BaseActivity { finish(); return; } binding.name.setText(nodeInfo.metadata != null ? nodeInfo.metadata.nodeName : instance); binding.name.setText(instance); SpannableString descriptionSpan; if (nodeInfo.metadata != null && nodeInfo.metadata.nodeDescription != null) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) descriptionSpan = new SpannableString(Html.fromHtml(nodeInfo.metadata.nodeDescription, FROM_HTML_MODE_LEGACY)); else descriptionSpan = new SpannableString(Html.fromHtml(nodeInfo.metadata.nodeDescription)); binding.description.setText(descriptionSpan, TextView.BufferType.SPANNABLE); } binding.userCount.setText(Helper.withSuffix((nodeInfo.usage.users.total))); binding.statusCount.setText(Helper.withSuffix(((nodeInfo.usage.localPosts)))); String softwareStr = nodeInfo.software.name + " - "; binding.software.setText(softwareStr); binding.version.setText(nodeInfo.software.version); if (nodeInfo.metadata != null && nodeInfo.metadata.staffAccounts != null && nodeInfo.metadata.staffAccounts.size() > 0) { SearchVM searchVM = new ViewModelProvider(InstanceProfileActivity.this).get(SearchVM.class); List<Account> accounts = new ArrayList<>(); for (String accountURL : nodeInfo.metadata.staffAccounts) { searchVM.search(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, accountURL, null, "accounts", false, true, false, 0, null, null, 1) .observe(InstanceProfileActivity.this, results -> { if (results.accounts != null && results.accounts.size() > 0) { accounts.add(results.accounts.get(0)); } if (accounts.size() == nodeInfo.metadata.staffAccounts.size()) { AccountAdapter accountsListAdapter = new AccountAdapter(accounts); binding.lvAccounts.setAdapter(accountsListAdapter); final LinearLayoutManager mLayoutManager; mLayoutManager = new LinearLayoutManager(InstanceProfileActivity.this); binding.lvAccounts.setLayoutManager(mLayoutManager); } }); } } binding.instanceContainer.setVisibility(View.VISIBLE); binding.loader.setVisibility(View.GONE); }); Loading
app/src/main/java/app/fedilab/android/client/entities/api/Tag.java +12 −0 Original line number Diff line number Diff line Loading @@ -27,4 +27,16 @@ public class Tag implements Serializable { public String url; @SerializedName("history") public List<History> history; public int getWeight() { int weight = 0; for (History h : history) { try { weight += Integer.parseInt(h.accounts); } catch (Exception ignored) { } } return weight; } }