added Nitter support for all URLs, bug fix

This commit is contained in:
nuclearfog 2023-04-17 10:46:04 +02:00
parent 5c0aaf7ad8
commit 20079c4ec2
No known key found for this signature in database
GPG Key ID: 03488A185C476379
13 changed files with 121 additions and 120 deletions

View File

@ -113,9 +113,7 @@ public class MastodonAccount implements Account {
@NonNull
@Override
public String toString() {
if (getUser() != null)
return getUser().toString();
return "";
return "hostname=\"" + getHostname() + "\" configuration=\"" + getConfiguration().getName() + "\" " + user;
}

View File

@ -120,9 +120,7 @@ public class AccountV1 implements Account {
@NonNull
@Override
public String toString() {
if (getUser() != null)
return getUser().toString();
return "";
return "hostname=\"" + getHostname() + "\" configuration=\"" + getConfiguration().getName() + "\" " + user;
}

View File

@ -0,0 +1,95 @@
package org.nuclearfog.twidda.backend.utils;
import android.app.Activity;
import android.content.ActivityNotFoundException;
import android.content.Intent;
import android.net.Uri;
import android.widget.Toast;
import org.nuclearfog.twidda.R;
import org.nuclearfog.twidda.config.Configuration;
import org.nuclearfog.twidda.config.GlobalSettings;
import org.nuclearfog.twidda.ui.activities.StatusActivity;
import java.util.List;
import java.util.regex.Pattern;
/**
* This class provides methods to open different links, depending on app settings
*
* @author nuclearfog
*/
public class LinkUtils {
/**
* regex pattern of a status URL
*/
public static final Pattern TWITTER_LINK_PATTERN = Pattern.compile("https://twitter.com/\\w+/status/\\d+");
private LinkUtils() {}
/**
* Open a link, regarding it's content
*
* @param activity activity used to open link
* @param url url to open
*/
public static void openLink(Activity activity, String url) {
Uri link = Uri.parse(url);
GlobalSettings settings = GlobalSettings.getInstance(activity);
// check if the link points to another status
if ((settings.getLogin().getConfiguration() == Configuration.TWITTER1 || settings.getLogin().getConfiguration() == Configuration.TWITTER2)
&& TWITTER_LINK_PATTERN.matcher(link.getScheme() + "://" + link.getHost() + link.getPath()).matches()) {
List<String> segments = link.getPathSegments();
Intent intent = new Intent(activity, StatusActivity.class);
intent.putExtra(StatusActivity.KEY_STATUS_ID, Long.parseLong(segments.get(2)));
intent.putExtra(StatusActivity.KEY_STATUS_NAME, segments.get(0));
activity.startActivity(intent);
return;
}
else if (url.startsWith("https://twitter.com") && settings.twitterAltSet()) {
url = "https://nitter.net" + link.getPath();
link = Uri.parse(url);
}
// open link in a browser
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(link);
try {
activity.startActivity(intent);
} catch (ActivityNotFoundException err) {
Toast.makeText(activity.getApplicationContext(), R.string.error_connection_failed, Toast.LENGTH_SHORT).show();
}
}
/**
* open location coordinates
*
* @param activity activity used to open link
* @param coordinates coordinate string
*/
public static void openCoordinates(Activity activity, String coordinates) {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse("geo:" + coordinates + "?z=14"));
try {
activity.startActivity(intent);
} catch (ActivityNotFoundException err) {
Toast.makeText(activity.getApplicationContext(), R.string.error_no_card_app, Toast.LENGTH_SHORT).show();
}
}
/**
* open a link to a media file
*
* @param activity activity used to open link
* @param url media url
*/
public static void openMediaLink(Activity activity, Uri url) {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(url);
try {
activity.startActivity(intent);
} catch (ActivityNotFoundException err) {
Toast.makeText(activity.getApplicationContext(), R.string.error_connection_failed, Toast.LENGTH_SHORT).show();
}
}
}

View File

@ -32,6 +32,7 @@ public enum Configuration {
*/
public static final Configuration FALLBACK_CONFIG = MASTODON;
private final String name;
private final int accountType;
private final boolean userlistExtended;
private final boolean searchFilterEnabled;
@ -54,6 +55,7 @@ public enum Configuration {
switch (accountType) {
case Account.API_TWITTER_1:
case Account.API_TWITTER_2:
name = "Twitter";
userlistExtended = true;
searchFilterEnabled = true;
profileLocationEnabled = true;
@ -70,6 +72,7 @@ public enum Configuration {
default:
case Account.API_MASTODON:
name = "Mastodon";
userlistExtended = false;
searchFilterEnabled = false;
profileLocationEnabled = false;
@ -86,6 +89,13 @@ public enum Configuration {
}
}
/**
* @return network name
*/
public String getName() {
return name;
}
/**
* @return account login type, see {@link Account}
*/

View File

@ -898,14 +898,6 @@ public class GlobalSettings {
ConfigAccount account = new ConfigAccount(login);
this.account = account;
loggedIn = true;
// setup alternative Twitter host
switch (account.getConfiguration()) {
case TWITTER1:
case TWITTER2:
if (twitterAlt)
account.setHost(TWITTER_ALT_HOST);
break;
}
e.putString(HOSTNAME, account.getHostname());
e.putLong(CURRENT_ID, account.getId());
e.putString(OAUTH_TOKEN, account.getOauthToken());

View File

@ -25,7 +25,7 @@ public class ConfigAccount implements Account {
/**
*
*/
public ConfigAccount(Account account) {
public ConfigAccount(@NonNull Account account) {
id = account.getId();
oauthToken = account.getOauthToken();
tokenSecret = account.getOauthSecret();
@ -147,9 +147,7 @@ public class ConfigAccount implements Account {
@NonNull
@Override
public String toString() {
if (getUser() != null)
return getUser().toString();
return "";
return "hostname=\"" + getHostname() + "\" configuration=\"" + getConfiguration().getName() + "\"";
}

View File

@ -148,9 +148,7 @@ public class DatabaseAccount implements Account, AccountTable {
@NonNull
@Override
public String toString() {
if (getUser() != null)
return getUser().toString();
return "";
return "hostname=\"" + getHostname() + "\" configuration=\"" + getConfiguration().getName() + "\" " + user;
}

View File

@ -7,9 +7,6 @@ import static android.view.View.VISIBLE;
import static android.widget.Toast.LENGTH_SHORT;
import static org.nuclearfog.twidda.ui.activities.MessageEditor.KEY_DM_PREFIX;
import static org.nuclearfog.twidda.ui.activities.SearchActivity.KEY_SEARCH_QUERY;
import static org.nuclearfog.twidda.ui.activities.StatusActivity.KEY_STATUS_ID;
import static org.nuclearfog.twidda.ui.activities.StatusActivity.KEY_STATUS_NAME;
import static org.nuclearfog.twidda.ui.activities.StatusActivity.TWITTER_LINK_PATTERN;
import static org.nuclearfog.twidda.ui.activities.StatusEditor.KEY_STATUS_EDITOR_TEXT;
import static org.nuclearfog.twidda.ui.activities.UserlistsActivity.KEY_USERLIST_OWNER_ID;
import static org.nuclearfog.twidda.ui.activities.UsersActivity.KEY_USERS_ID;
@ -70,6 +67,7 @@ import org.nuclearfog.twidda.backend.async.UserLoader.UserResult;
import org.nuclearfog.twidda.backend.utils.AppStyles;
import org.nuclearfog.twidda.backend.utils.ErrorHandler;
import org.nuclearfog.twidda.backend.image.PicassoBuilder;
import org.nuclearfog.twidda.backend.utils.LinkUtils;
import org.nuclearfog.twidda.backend.utils.StringUtils;
import org.nuclearfog.twidda.backend.utils.EmojiUtils;
import org.nuclearfog.twidda.config.GlobalSettings;
@ -84,7 +82,6 @@ import org.nuclearfog.twidda.ui.views.TabSelector;
import org.nuclearfog.twidda.ui.views.TabSelector.OnTabSelectedListener;
import java.text.SimpleDateFormat;
import java.util.List;
import jp.wasabeef.picasso.transformations.RoundedCornersTransformation;
@ -509,24 +506,7 @@ public class ProfileActivity extends AppCompatActivity implements ActivityResult
@Override
public void onLinkClick(String tag) {
Uri link = Uri.parse(tag);
// open status link
if (TWITTER_LINK_PATTERN.matcher(link.getScheme() + "://" + link.getHost() + link.getPath()).matches()) {
List<String> segments = link.getPathSegments();
Intent intent = new Intent(this, StatusActivity.class);
intent.putExtra(KEY_STATUS_ID, Long.parseLong(segments.get(2)));
intent.putExtra(KEY_STATUS_NAME, segments.get(0));
startActivity(intent);
}
// open link in browser
else {
Intent intent = new Intent(Intent.ACTION_VIEW, link);
try {
startActivity(intent);
} catch (ActivityNotFoundException err) {
Toast.makeText(getApplicationContext(), R.string.error_connection_failed, LENGTH_SHORT).show();
}
}
LinkUtils.openLink(this, tag);
}

View File

@ -143,7 +143,6 @@ public class SettingsActivity extends AppCompatActivity implements OnClickListen
SwitchButton enableNitter = findViewById(R.id.settings_enable_twitter_alt);
SwitchButton enableLocalTl = findViewById(R.id.settings_local_timeline);
SwitchButton hideSensitive = findViewById(R.id.enable_status_hide_sensitive);
View EnableTwitterAltDescr = findViewById(R.id.settings_enable_twitter_alt_descr);
SwitchButton enableStatusIcons = findViewById(R.id.enable_status_indicators);
SeekBar listSizeSelector = findViewById(R.id.settings_list_seek);
Spinner fontSelector = findViewById(R.id.spinner_font);
@ -198,8 +197,6 @@ public class SettingsActivity extends AppCompatActivity implements OnClickListen
if (configuration != Configuration.TWITTER1 && configuration != Configuration.TWITTER2) {
enableLocalTl.setVisibility(View.VISIBLE);
enableNitter.setVisibility(View.GONE);
EnableTwitterAltDescr.setVisibility(View.GONE);
trend_card.setVisibility(View.GONE);
}
if (!settings.isLoggedIn()) {

View File

@ -70,6 +70,7 @@ import org.nuclearfog.twidda.backend.async.TranslationLoader.TranslationResult;
import org.nuclearfog.twidda.backend.utils.AppStyles;
import org.nuclearfog.twidda.backend.utils.ErrorHandler;
import org.nuclearfog.twidda.backend.image.PicassoBuilder;
import org.nuclearfog.twidda.backend.utils.LinkUtils;
import org.nuclearfog.twidda.backend.utils.StringUtils;
import org.nuclearfog.twidda.backend.utils.EmojiUtils;
import org.nuclearfog.twidda.config.Configuration;
@ -91,9 +92,7 @@ import org.nuclearfog.twidda.ui.views.LockableConstraintLayout;
import org.nuclearfog.twidda.ui.views.LockableConstraintLayout.LockCallback;
import java.text.SimpleDateFormat;
import java.util.List;
import java.util.Locale;
import java.util.regex.Pattern;
import jp.wasabeef.picasso.transformations.RoundedCornersTransformation;
@ -186,11 +185,6 @@ public class StatusActivity extends AppCompatActivity implements OnClickListener
*/
public static final String INTENT_NOTIFICATION_REMOVED_ID = "notification_removed_id";
/**
* regex pattern of a status URL
*/
public static final Pattern TWITTER_LINK_PATTERN = Pattern.compile("https://twitter.com/\\w+/status/\\d+");
/**
* scrollview position threshold to lock/unlock child scrolling
*/
@ -606,13 +600,7 @@ public class StatusActivity extends AppCompatActivity implements OnClickListener
location = status.getLocation();
}
if (location != null && !location.getCoordinates().trim().isEmpty()) {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse("geo:" + location.getCoordinates() + "?z=14"));
try {
startActivity(intent);
} catch (ActivityNotFoundException err) {
Toast.makeText(getApplicationContext(), R.string.error_no_card_app, Toast.LENGTH_SHORT).show();
}
LinkUtils.openCoordinates(this, location.getCoordinates());
}
}
// go to user reposting this status
@ -718,13 +706,7 @@ public class StatusActivity extends AppCompatActivity implements OnClickListener
@Override
public void onCardClick(Card card, int type) {
if (type == OnCardClickListener.TYPE_LINK) {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse(card.getUrl()));
try {
startActivity(intent);
} catch (ActivityNotFoundException err) {
Toast.makeText(getApplicationContext(), R.string.error_connection_failed, Toast.LENGTH_SHORT).show();
}
LinkUtils.openLink(this, card.getUrl());
} else if (type == OnCardClickListener.TYPE_IMAGE) {
String imageUrl = card.getImageUrl();
if (!imageUrl.isEmpty()) {
@ -773,26 +755,7 @@ public class StatusActivity extends AppCompatActivity implements OnClickListener
*/
@Override
public void onLinkClick(String tag) {
Uri link = Uri.parse(tag);
// check if the link points to another status
if ((settings.getLogin().getConfiguration() == Configuration.TWITTER1 || settings.getLogin().getConfiguration() == Configuration.TWITTER2)
&& TWITTER_LINK_PATTERN.matcher(link.getScheme() + "://" + link.getHost() + link.getPath()).matches()) {
List<String> segments = link.getPathSegments();
Intent intent = new Intent(this, StatusActivity.class);
intent.putExtra(KEY_STATUS_ID, Long.parseLong(segments.get(2)));
intent.putExtra(KEY_STATUS_NAME, segments.get(0));
startActivity(intent);
}
// open link in a browser
else {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(link);
try {
startActivity(intent);
} catch (ActivityNotFoundException err) {
Toast.makeText(getApplicationContext(), R.string.error_connection_failed, Toast.LENGTH_SHORT).show();
}
}
LinkUtils.openLink(this, tag);
}

View File

@ -1,8 +1,6 @@
package org.nuclearfog.twidda.ui.activities;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
import android.content.res.Configuration;
import android.graphics.Color;
import android.net.Uri;
@ -46,6 +44,7 @@ import com.google.android.exoplayer2.video.VideoRendererEventListener;
import org.nuclearfog.twidda.R;
import org.nuclearfog.twidda.backend.utils.AppStyles;
import org.nuclearfog.twidda.backend.utils.ConnectionBuilder;
import org.nuclearfog.twidda.backend.utils.LinkUtils;
import okhttp3.Call;
@ -181,13 +180,7 @@ public class VideoViewer extends AppCompatActivity implements Player.Listener {
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
if (item.getItemId() == R.id.menu_video_link) {
if (data != null) {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(data);
try {
startActivity(intent);
} catch (ActivityNotFoundException err) {
Toast.makeText(getApplicationContext(), R.string.error_connection_failed, Toast.LENGTH_SHORT).show();
}
LinkUtils.openMediaLink(this, data);
}
}
return super.onOptionsItemSelected(item);

View File

@ -4,11 +4,7 @@ import static android.widget.Toast.LENGTH_SHORT;
import static org.nuclearfog.twidda.ui.activities.MessageEditor.KEY_DM_PREFIX;
import static org.nuclearfog.twidda.ui.activities.ProfileActivity.KEY_PROFILE_USER;
import static org.nuclearfog.twidda.ui.activities.SearchActivity.KEY_SEARCH_QUERY;
import static org.nuclearfog.twidda.ui.activities.StatusActivity.KEY_STATUS_ID;
import static org.nuclearfog.twidda.ui.activities.StatusActivity.KEY_STATUS_NAME;
import static org.nuclearfog.twidda.ui.activities.StatusActivity.TWITTER_LINK_PATTERN;
import android.content.ActivityNotFoundException;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
@ -25,6 +21,7 @@ import org.nuclearfog.twidda.backend.async.MessageLoader;
import org.nuclearfog.twidda.backend.async.MessageLoader.MessageLoaderParam;
import org.nuclearfog.twidda.backend.async.MessageLoader.MessageLoaderResult;
import org.nuclearfog.twidda.backend.utils.ErrorHandler;
import org.nuclearfog.twidda.backend.utils.LinkUtils;
import org.nuclearfog.twidda.model.Message;
import org.nuclearfog.twidda.ui.activities.ImageViewer;
import org.nuclearfog.twidda.ui.activities.MessageEditor;
@ -106,25 +103,7 @@ public class MessageFragment extends ListFragment implements OnMessageClickListe
@Override
public void onLinkClick(String tag) {
Uri link = Uri.parse(tag);
// open status link
if (TWITTER_LINK_PATTERN.matcher(link.getScheme() + "://" + link.getHost() + link.getPath()).matches()) {
List<String> segments = link.getPathSegments();
Intent intent = new Intent(requireContext(), StatusActivity.class);
intent.putExtra(KEY_STATUS_ID, Long.parseLong(segments.get(2)));
intent.putExtra(KEY_STATUS_NAME, segments.get(0));
startActivity(intent);
}
// open link in browser
else {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(link);
try {
startActivity(intent);
} catch (ActivityNotFoundException err) {
Toast.makeText(requireContext(), R.string.error_connection_failed, LENGTH_SHORT).show();
}
}
LinkUtils.openLink(requireActivity(), tag);
}

View File

@ -51,7 +51,7 @@ public class AnimatedImageView extends AppCompatImageView {
public void setImageURI(@Nullable Uri uri) {
ContentResolver resolver = getContext().getContentResolver();
String mime = resolver.getType(uri);
if (mime != null && mime.contains("gif")) {
if (mime != null && mime.equals("image/gif")) {
try {
InputStream is = resolver.openInputStream(uri);
movie = Movie.decodeStream(is);