finalized hashtag follow support, code cleanup

This commit is contained in:
nuclearfog 2023-05-05 23:57:46 +02:00
parent 2cafde74e1
commit 7b09ff3ac8
No known key found for this signature in database
GPG Key ID: 03488A185C476379
27 changed files with 378 additions and 245 deletions

View File

@ -20,6 +20,7 @@ import org.nuclearfog.twidda.model.Poll;
import org.nuclearfog.twidda.model.Relation;
import org.nuclearfog.twidda.model.Status;
import org.nuclearfog.twidda.model.Translation;
import org.nuclearfog.twidda.model.Trend;
import org.nuclearfog.twidda.model.User;
import org.nuclearfog.twidda.model.UserList;
@ -283,15 +284,17 @@ public interface Connection {
* follow hashtag by name
*
* @param name name of the hashtag
* @return updated hashtag information
*/
void followHashtag(String name) throws ConnectionException;
Trend followHashtag(String name) throws ConnectionException;
/**
* unfollow hashtag by name
*
* @param name name of the hashtag
* @return updated hashtag information
*/
void unfollowHashtag(String name) throws ConnectionException;
Trend unfollowHashtag(String name) throws ConnectionException;
/**
* get available locations for trends

View File

@ -46,6 +46,7 @@ import org.nuclearfog.twidda.model.Poll;
import org.nuclearfog.twidda.model.Relation;
import org.nuclearfog.twidda.model.Status;
import org.nuclearfog.twidda.model.Translation;
import org.nuclearfog.twidda.model.Trend;
import org.nuclearfog.twidda.model.User;
import org.nuclearfog.twidda.model.UserList;
@ -454,11 +455,11 @@ public class Mastodon implements Connection {
@Override
public void followHashtag(String name) throws ConnectionException {
public Trend followHashtag(String name) throws ConnectionException {
try {
if (name.startsWith("#"))
name = name.substring(1);
post(ENDPOINT_HASHTAG_GET + StringUtils.encode(name) + "/follow", new ArrayList<>());
return createTrend(post(ENDPOINT_HASHTAG_GET + StringUtils.encode(name) + "/follow", new ArrayList<>()));
} catch (IOException e) {
throw new MastodonException(e);
}
@ -466,11 +467,11 @@ public class Mastodon implements Connection {
@Override
public void unfollowHashtag(String name) throws ConnectionException {
public Trend unfollowHashtag(String name) throws ConnectionException {
try {
if (name.startsWith("#"))
name = name.substring(1);
post(ENDPOINT_HASHTAG_GET + StringUtils.encode(name) + "/unfollow", new ArrayList<>());
return createTrend(post(ENDPOINT_HASHTAG_GET + StringUtils.encode(name) + "/unfollow", new ArrayList<>()));
} catch (IOException e) {
throw new MastodonException(e);
}
@ -1303,6 +1304,25 @@ public class Mastodon implements Connection {
}
}
/**
* create trend from response
*
* @param response response from a trend endpoint
* @return trend information
*/
private Trend createTrend(Response response) throws MastodonException {
try {
ResponseBody body = response.body();
if (response.code() == 200 && body != null) {
JSONObject json = new JSONObject(body.string());
return new MastodonTrend(json);
}
throw new MastodonException(response);
} catch (IOException | JSONException e) {
throw new MastodonException(e);
}
}
/**
* send post request without return
*

View File

@ -45,6 +45,7 @@ import org.nuclearfog.twidda.model.Poll;
import org.nuclearfog.twidda.model.Relation;
import org.nuclearfog.twidda.model.Status;
import org.nuclearfog.twidda.model.Translation;
import org.nuclearfog.twidda.model.Trend;
import org.nuclearfog.twidda.model.User;
import org.nuclearfog.twidda.model.UserList;
@ -573,13 +574,13 @@ public class TwitterV1 implements Connection {
@Override
public void followHashtag(String name) throws ConnectionException {
public Trend followHashtag(String name) throws ConnectionException {
throw new TwitterException("not supported!");
}
@Override
public void unfollowHashtag(String name) throws ConnectionException {
public Trend unfollowHashtag(String name) throws ConnectionException {
throw new TwitterException("not supported!");
}

View File

@ -0,0 +1,88 @@
package org.nuclearfog.twidda.backend.async;
import android.content.Context;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import org.nuclearfog.twidda.backend.api.Connection;
import org.nuclearfog.twidda.backend.api.ConnectionException;
import org.nuclearfog.twidda.backend.api.ConnectionManager;
import org.nuclearfog.twidda.model.Trend;
/**
* Async loader for hashtag follow/unfollow action
*
* @author nuclearfog
*/
public class HashtagAction extends AsyncExecutor<HashtagAction.HashtagParam, HashtagAction.HashtagResult> {
private Connection connection;
/**
*
*/
public HashtagAction(Context context) {
connection = ConnectionManager.getDefaultConnection(context);
}
@Override
protected HashtagResult doInBackground(@NonNull HashtagParam param) {
try {
switch (param.mode) {
case HashtagParam.FOLLOW:
Trend result = connection.followHashtag(param.name);
return new HashtagResult(HashtagResult.FOLLOW, result, null);
case HashtagParam.UNFOLLOW:
result = connection.unfollowHashtag(param.name);
return new HashtagResult(HashtagResult.UNFOLLOW, result, null);
}
} catch (ConnectionException exception) {
return new HashtagResult(HashtagResult.ERROR, null, exception);
} catch (Exception exception) {
exception.printStackTrace();
}
return new HashtagResult(HashtagResult.ERROR, null, null);
}
/**
*
*/
public static class HashtagParam {
public static final int FOLLOW = 1;
public static final int UNFOLLOW = 2;
final String name;
final int mode;
public HashtagParam(String name, int mode) {
this.name = name;
this.mode = mode;
}
}
/**
*
*/
public static class HashtagResult {
public static final int ERROR = -1;
public static final int FOLLOW = 3;
public static final int UNFOLLOW = 4;
@Nullable
public final ConnectionException exception;
@Nullable
public final Trend trend;
public final int mode;
HashtagResult(int mode, @Nullable Trend trend, @Nullable ConnectionException exception) {
this.exception = exception;
this.trend = trend;
this.mode = mode;
}
}
}

View File

@ -28,7 +28,6 @@ import org.nuclearfog.zoomview.ZoomView;
import java.io.File;
/**
* Activity to show online and local images
*

View File

@ -1,10 +1,5 @@
package org.nuclearfog.twidda.ui.activities;
import static android.content.Intent.ACTION_VIEW;
import static android.widget.Toast.LENGTH_LONG;
import static android.widget.Toast.LENGTH_SHORT;
import static org.nuclearfog.twidda.ui.activities.AccountActivity.KEY_DISABLE_SELECTOR;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
@ -164,7 +159,7 @@ public class LoginActivity extends AppCompatActivity implements ActivityResultCa
// open account selector
else if (item.getItemId() == R.id.login_select_account) {
Intent accountManager = new Intent(this, AccountActivity.class);
accountManager.putExtra(KEY_DISABLE_SELECTOR, true);
accountManager.putExtra(AccountActivity.KEY_DISABLE_SELECTOR, true);
activityResultLauncher.launch(accountManager);
return true;
}
@ -196,18 +191,18 @@ public class LoginActivity extends AppCompatActivity implements ActivityResultCa
if (hostSelector.getSelectedItemId() == NetworkAdapter.ID_TWITTER) {
// use userdefined or default token keys
if (connection.useTokens() || Tokens.USE_DEFAULT_KEYS) {
Toast.makeText(getApplicationContext(), R.string.info_open_twitter_login, LENGTH_LONG).show();
Toast.makeText(getApplicationContext(), R.string.info_open_twitter_login, Toast.LENGTH_LONG).show();
LoginParam param = new LoginParam(LoginParam.MODE_REQUEST, connection.getApiType(), connection, "");
loginAsync.execute(param, this);
}
// no tokens are set, print error message
else {
Toast.makeText(getApplicationContext(), R.string.info_missing_api_keys, LENGTH_SHORT).show();
Toast.makeText(getApplicationContext(), R.string.info_missing_api_keys, Toast.LENGTH_SHORT).show();
}
}
// generate Mastodon login
else if (hostSelector.getSelectedItemId() == NetworkAdapter.ID_MASTODON) {
Toast.makeText(getApplicationContext(), R.string.info_open_mastodon_login, LENGTH_LONG).show();
Toast.makeText(getApplicationContext(), R.string.info_open_mastodon_login, Toast.LENGTH_LONG).show();
LoginParam param = new LoginParam(LoginParam.MODE_REQUEST, connection.getApiType(), connection, "");
loginAsync.execute(param, this);
}
@ -217,23 +212,23 @@ public class LoginActivity extends AppCompatActivity implements ActivityResultCa
String code = pinInput.getText().toString();
// check if user clicked on PIN button
if (loginLink == null) {
Toast.makeText(getApplicationContext(), R.string.info_get_link, LENGTH_LONG).show();
Toast.makeText(getApplicationContext(), R.string.info_get_link, Toast.LENGTH_LONG).show();
} else if (code.isEmpty()) {
pinInput.setError(getString(R.string.error_enter_code));
}
// login to Twitter
else if (hostSelector.getSelectedItemId() == NetworkAdapter.ID_TWITTER) {
if (connection.useTokens() || Tokens.USE_DEFAULT_KEYS) {
Toast.makeText(getApplicationContext(), R.string.info_login_to_twitter, LENGTH_LONG).show();
Toast.makeText(getApplicationContext(), R.string.info_login_to_twitter, Toast.LENGTH_LONG).show();
LoginParam param = new LoginParam(LoginParam.MODE_LOGIN, connection.getApiType(), connection, code);
loginAsync.execute(param, this);
} else {
Toast.makeText(getApplicationContext(), R.string.info_missing_api_keys, LENGTH_SHORT).show();
Toast.makeText(getApplicationContext(), R.string.info_missing_api_keys, Toast.LENGTH_SHORT).show();
}
}
// login to mastodon
else if (hostSelector.getSelectedItemId() == NetworkAdapter.ID_MASTODON) {
Toast.makeText(getApplicationContext(), R.string.info_login_to_mastodon, LENGTH_LONG).show();
Toast.makeText(getApplicationContext(), R.string.info_login_to_mastodon, Toast.LENGTH_LONG).show();
LoginParam param = new LoginParam(LoginParam.MODE_LOGIN, connection.getApiType(), connection, code);
loginAsync.execute(param, this);
}
@ -293,11 +288,11 @@ public class LoginActivity extends AppCompatActivity implements ActivityResultCa
* open login page
*/
private void connect() {
Intent loginIntent = new Intent(ACTION_VIEW, Uri.parse(loginLink));
Intent loginIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(loginLink));
try {
startActivity(loginIntent);
} catch (ActivityNotFoundException err) {
Toast.makeText(getApplicationContext(), R.string.error_open_link, LENGTH_SHORT).show();
Toast.makeText(getApplicationContext(), R.string.error_open_link, Toast.LENGTH_SHORT).show();
}
}
}

View File

@ -1,8 +1,5 @@
package org.nuclearfog.twidda.ui.activities;
import static org.nuclearfog.twidda.ui.activities.ProfileActivity.KEY_PROFILE_ID;
import static org.nuclearfog.twidda.ui.activities.SearchActivity.KEY_SEARCH_QUERY;
import android.app.Dialog;
import android.content.Context;
import android.content.Intent;
@ -164,7 +161,7 @@ public class MainActivity extends AppCompatActivity implements ActivityResultCal
// open home profile
if (item.getItemId() == R.id.menu_profile) {
Intent intent = new Intent(this, ProfileActivity.class);
intent.putExtra(KEY_PROFILE_ID, settings.getLogin().getId());
intent.putExtra(ProfileActivity.KEY_PROFILE_ID, settings.getLogin().getId());
startActivity(intent);
return true;
}
@ -216,7 +213,7 @@ public class MainActivity extends AppCompatActivity implements ActivityResultCal
public boolean onQueryTextSubmit(String s) {
if (s.length() <= SearchActivity.SEARCH_STR_MAX_LEN && !s.contains(":") && !s.contains("$")) {
Intent search = new Intent(this, SearchActivity.class);
search.putExtra(KEY_SEARCH_QUERY, s);
search.putExtra(SearchActivity.KEY_QUERY, s);
startActivity(search);
} else {
Toast.makeText(getApplicationContext(), R.string.error_twitter_search, Toast.LENGTH_SHORT).show();

View File

@ -6,9 +6,6 @@ import static android.Manifest.permission.READ_EXTERNAL_STORAGE;
import static android.Manifest.permission.READ_MEDIA_IMAGES;
import static android.Manifest.permission.READ_MEDIA_VIDEO;
import static android.Manifest.permission.WRITE_EXTERNAL_STORAGE;
import static android.content.Intent.ACTION_PICK;
import static android.content.Intent.EXTRA_MIME_TYPES;
import static android.content.Intent.FLAG_GRANT_READ_URI_PERMISSION;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.os.Environment.DIRECTORY_PICTURES;
import static android.provider.MediaStore.Images.Media.DATE_TAKEN;
@ -16,8 +13,6 @@ import static android.provider.MediaStore.Images.Media.DISPLAY_NAME;
import static android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
import static android.provider.MediaStore.Images.Media.MIME_TYPE;
import static android.provider.MediaStore.Images.Media.RELATIVE_PATH;
import static android.widget.Toast.LENGTH_LONG;
import static android.widget.Toast.LENGTH_SHORT;
import android.annotation.SuppressLint;
import android.content.ActivityNotFoundException;
@ -218,7 +213,7 @@ public abstract class MediaActivity extends AppCompatActivity implements Activit
private void setResult(@NonNull Boolean res) {
if (res) {
Toast.makeText(getApplicationContext(), R.string.info_image_saved, LENGTH_SHORT).show();
Toast.makeText(getApplicationContext(), R.string.info_image_saved, Toast.LENGTH_SHORT).show();
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q && destMediaFile != null) {
// start media scanner to scan for new image
MediaScannerConnection.scanFile(getApplicationContext(), new String[]{destMediaFile.getPath()}, null, null);
@ -273,7 +268,7 @@ public abstract class MediaActivity extends AppCompatActivity implements Activit
startLocating();
} else {
if (shouldShowRequestPermissionRationale(ACCESS_FINE_LOCATION)) {
Toast.makeText(getApplicationContext(), R.string.info_permission_location, LENGTH_LONG).show();
Toast.makeText(getApplicationContext(), R.string.info_permission_location, Toast.LENGTH_LONG).show();
}
requestPermissions(PERMISSION_LOCATION, REQUEST_LOCATION);
}
@ -301,7 +296,7 @@ public abstract class MediaActivity extends AppCompatActivity implements Activit
if (requiresPermission) {
for (String permission : PERMISSIONS_READ) {
if (shouldShowRequestPermissionRationale(permission)) {
Toast.makeText(getApplicationContext(), R.string.info_permission_read, LENGTH_LONG).show();
Toast.makeText(getApplicationContext(), R.string.info_permission_read, Toast.LENGTH_LONG).show();
break;
}
}
@ -328,7 +323,7 @@ public abstract class MediaActivity extends AppCompatActivity implements Activit
saveImage();
} else {
if (shouldShowRequestPermissionRationale(WRITE_EXTERNAL_STORAGE))
Toast.makeText(getApplicationContext(), R.string.info_permission_write, LENGTH_LONG).show();
Toast.makeText(getApplicationContext(), R.string.info_permission_write, Toast.LENGTH_LONG).show();
requestPermissions(PERMISSION_WRITE, REQUEST_STORE_IMG);
}
}
@ -360,13 +355,13 @@ public abstract class MediaActivity extends AppCompatActivity implements Activit
* @param requestCode type of media to fetch
*/
private void openMediaPicker(int requestCode) {
Intent mediaSelect = new Intent(ACTION_PICK);
mediaSelect.setFlags(FLAG_GRANT_READ_URI_PERMISSION);
Intent mediaSelect = new Intent(Intent.ACTION_PICK);
mediaSelect.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
switch (requestCode) {
case REQUEST_ALL:
// pick image or video
mediaSelect.setType(MIME_ALL_READ);
mediaSelect.putExtra(EXTRA_MIME_TYPES, TYPE_ALL);
mediaSelect.putExtra(Intent.EXTRA_MIME_TYPES, TYPE_ALL);
break;
case REQUEST_IMAGE:
@ -379,7 +374,7 @@ public abstract class MediaActivity extends AppCompatActivity implements Activit
activityResultLauncher.launch(mediaSelect);
this.requestCode = requestCode;
} catch (ActivityNotFoundException err) {
Toast.makeText(getApplicationContext(), R.string.error_no_media_app, LENGTH_SHORT).show();
Toast.makeText(getApplicationContext(), R.string.error_no_media_app, Toast.LENGTH_SHORT).show();
this.requestCode = 0;
}
}

View File

@ -1,16 +1,12 @@
package org.nuclearfog.twidda.ui.activities;
import static android.view.View.GONE;
import static android.view.View.OnClickListener;
import static android.view.View.VISIBLE;
import static android.widget.Toast.LENGTH_SHORT;
import android.content.Context;
import android.content.Intent;
import android.location.Location;
import android.net.Uri;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.EditText;
import android.widget.ImageButton;
@ -161,10 +157,10 @@ public class MessageEditor extends MediaActivity implements OnClickListener, OnC
protected void onMediaFetched(int resultType, @NonNull Uri uri) {
if (resultType == REQUEST_IMAGE) {
if (messageUpdate.addMedia(this, uri)) {
preview.setVisibility(VISIBLE);
media.setVisibility(GONE);
preview.setVisibility(View.VISIBLE);
media.setVisibility(View.GONE);
} else {
Toast.makeText(getApplicationContext(), R.string.error_adding_media, LENGTH_SHORT).show();
Toast.makeText(getApplicationContext(), R.string.error_adding_media, Toast.LENGTH_SHORT).show();
}
}
}
@ -225,10 +221,10 @@ public class MessageEditor extends MediaActivity implements OnClickListener, OnC
messageUpdater.execute(messageUpdate, messageResult);
loadingCircle.show();
} else {
Toast.makeText(getApplicationContext(), R.string.error_media_init, LENGTH_SHORT).show();
Toast.makeText(getApplicationContext(), R.string.error_media_init, Toast.LENGTH_SHORT).show();
}
} else {
Toast.makeText(getApplicationContext(), R.string.error_dm, LENGTH_SHORT).show();
Toast.makeText(getApplicationContext(), R.string.error_dm, Toast.LENGTH_SHORT).show();
}
}

View File

@ -1,20 +1,5 @@
package org.nuclearfog.twidda.ui.activities;
import static android.content.Intent.ACTION_VIEW;
import static android.view.View.GONE;
import static android.view.View.OnClickListener;
import static android.view.View.VISIBLE;
import static android.widget.Toast.LENGTH_SHORT;
import static org.nuclearfog.twidda.ui.activities.MessageEditor.KEY_MESSAGE_PREFIX;
import static org.nuclearfog.twidda.ui.activities.SearchActivity.KEY_SEARCH_QUERY;
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;
import static org.nuclearfog.twidda.ui.activities.UsersActivity.KEY_USERS_MODE;
import static org.nuclearfog.twidda.ui.activities.UsersActivity.USERS_FOLLOWER;
import static org.nuclearfog.twidda.ui.activities.UsersActivity.USERS_FOLLOWING;
import static org.nuclearfog.twidda.ui.activities.UsersActivity.USERS_REQUESTS;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
@ -26,6 +11,7 @@ import android.text.SpannableString;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewTreeObserver.OnPreDrawListener;
import android.widget.Button;
import android.widget.ImageView;
@ -399,7 +385,7 @@ public class ProfileActivity extends AppCompatActivity implements ActivityResult
dmIcon.setVisible(true);
}
if (relation.isFollower()) {
follow_back.setVisibility(VISIBLE);
follow_back.setVisibility(View.VISIBLE);
}
result = true;
}
@ -415,7 +401,7 @@ public class ProfileActivity extends AppCompatActivity implements ActivityResult
if (user != null && !user.isCurrentUser()) {
// add username to status
String prefix = user.getScreenname() + " ";
intent.putExtra(KEY_STATUS_EDITOR_TEXT, prefix);
intent.putExtra(StatusEditor.KEY_TEXT, prefix);
}
startActivity(intent);
return true;
@ -472,7 +458,7 @@ public class ProfileActivity extends AppCompatActivity implements ActivityResult
else if (item.getItemId() == R.id.profile_message) {
Intent intent = new Intent(this, MessageEditor.class);
if (user != null && !user.isCurrentUser())
intent.putExtra(KEY_MESSAGE_PREFIX, user.getScreenname());
intent.putExtra(MessageEditor.KEY_MESSAGE_PREFIX, user.getScreenname());
startActivity(intent);
return true;
}
@ -480,7 +466,7 @@ public class ProfileActivity extends AppCompatActivity implements ActivityResult
else if (item.getItemId() == R.id.profile_lists) {
if (user != null) {
Intent intent = new Intent(this, UserlistsActivity.class);
intent.putExtra(KEY_USERLIST_OWNER_ID, user.getId());
intent.putExtra(UserlistsActivity.KEY_ID, user.getId());
startActivity(intent);
}
return true;
@ -488,7 +474,7 @@ public class ProfileActivity extends AppCompatActivity implements ActivityResult
// open request list
else if (item.getItemId() == R.id.profile_requests) {
Intent usersIntent = new Intent(this, UsersActivity.class);
usersIntent.putExtra(KEY_USERS_MODE, USERS_REQUESTS);
usersIntent.putExtra(UsersActivity.KEY_MODE, UsersActivity.USERS_REQUESTS);
startActivity(usersIntent);
return true;
}
@ -512,7 +498,7 @@ public class ProfileActivity extends AppCompatActivity implements ActivityResult
@Override
public void onTagClick(String text) {
Intent intent = new Intent(this, SearchActivity.class);
intent.putExtra(KEY_SEARCH_QUERY, text);
intent.putExtra(SearchActivity.KEY_QUERY, text);
startActivity(intent);
}
@ -530,8 +516,8 @@ public class ProfileActivity extends AppCompatActivity implements ActivityResult
// open following page
if (v.getId() == R.id.following) {
Intent intent = new Intent(this, UsersActivity.class);
intent.putExtra(KEY_USERS_ID, user.getId());
intent.putExtra(KEY_USERS_MODE, USERS_FOLLOWING);
intent.putExtra(UsersActivity.KEY_ID, user.getId());
intent.putExtra(UsersActivity.KEY_MODE, UsersActivity.USERS_FOLLOWING);
switch (settings.getLogin().getConfiguration()) {
case TWITTER1:
case TWITTER2:
@ -548,8 +534,8 @@ public class ProfileActivity extends AppCompatActivity implements ActivityResult
// open follower page
else if (v.getId() == R.id.follower) {
Intent intent = new Intent(this, UsersActivity.class);
intent.putExtra(KEY_USERS_ID, user.getId());
intent.putExtra(KEY_USERS_MODE, USERS_FOLLOWER);
intent.putExtra(UsersActivity.KEY_ID, user.getId());
intent.putExtra(UsersActivity.KEY_MODE, UsersActivity.USERS_FOLLOWER);
switch (settings.getLogin().getConfiguration()) {
case TWITTER1:
case TWITTER2:
@ -567,11 +553,11 @@ public class ProfileActivity extends AppCompatActivity implements ActivityResult
else if (v.getId() == R.id.links) {
if (!user.getProfileUrl().isEmpty()) {
String link = user.getProfileUrl();
Intent intent = new Intent(ACTION_VIEW, Uri.parse(link));
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(link));
try {
startActivity(intent);
} catch (ActivityNotFoundException err) {
Toast.makeText(getApplicationContext(), R.string.error_connection_failed, LENGTH_SHORT).show();
Toast.makeText(getApplicationContext(), R.string.error_connection_failed, Toast.LENGTH_SHORT).show();
}
}
}
@ -738,9 +724,9 @@ public class ProfileActivity extends AppCompatActivity implements ActivityResult
this.user = user;
following.setText(StringUtils.NUMBER_FORMAT.format(user.getFollowing()));
follower.setText(StringUtils.NUMBER_FORMAT.format(user.getFollower()));
following.setVisibility(VISIBLE);
follower.setVisibility(VISIBLE);
user_createdAt.setVisibility(VISIBLE);
following.setVisibility(View.VISIBLE);
follower.setVisibility(View.VISIBLE);
user_createdAt.setVisibility(View.VISIBLE);
screenName.setText(user.getScreenname());
// set status count
if (user.getStatusCount() >= 0) {
@ -775,9 +761,9 @@ public class ProfileActivity extends AppCompatActivity implements ActivityResult
descriptionSpan = EmojiUtils.removeTags(descriptionSpan);
}
description.setText(descriptionSpan);
description.setVisibility(VISIBLE);
description.setVisibility(View.VISIBLE);
} else {
description.setVisibility(GONE);
description.setVisibility(View.GONE);
}
// set user verified icon
if (user.isVerified()) {
@ -796,9 +782,9 @@ public class ProfileActivity extends AppCompatActivity implements ActivityResult
// set user location
if (!user.getLocation().isEmpty()) {
user_location.setText(user.getLocation());
user_location.setVisibility(VISIBLE);
user_location.setVisibility(View.VISIBLE);
} else {
user_location.setVisibility(GONE);
user_location.setVisibility(View.GONE);
}
// set profile url
if (!user.getProfileUrl().isEmpty()) {
@ -809,9 +795,9 @@ public class ProfileActivity extends AppCompatActivity implements ActivityResult
user_website.setText(link.substring(8));
else
user_website.setText(link);
user_website.setVisibility(VISIBLE);
user_website.setVisibility(View.VISIBLE);
} else {
user_website.setVisibility(GONE);
user_website.setVisibility(View.GONE);
}
// set profile/banner images
if (settings.imagesEnabled()) {

View File

@ -1,9 +1,5 @@
package org.nuclearfog.twidda.ui.activities;
import static android.view.View.INVISIBLE;
import static android.view.View.VISIBLE;
import static org.nuclearfog.twidda.ui.activities.ProfileActivity.TOOLBAR_TRANSPARENCY;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
@ -137,7 +133,7 @@ public class ProfileEditor extends MediaActivity implements OnClickListener, Asy
profileLocation.setVisibility(View.GONE);
profileLocationLabel.setVisibility(View.GONE);
}
toolbar.setBackgroundColor(settings.getBackgroundColor() & TOOLBAR_TRANSPARENCY);
toolbar.setBackgroundColor(settings.getBackgroundColor() & ProfileActivity.TOOLBAR_TRANSPARENCY);
profile_banner.setDrawingCacheEnabled(true);
AppStyles.setTheme(root);
picasso = PicassoBuilder.get(this);
@ -215,8 +211,8 @@ public class ProfileEditor extends MediaActivity implements OnClickListener, Asy
if (holder.setBanner(this, uri)) {
int widthPixels = Resources.getSystem().getDisplayMetrics().widthPixels;
picasso.load(uri).resize(widthPixels, widthPixels / 3).centerCrop(Gravity.TOP).into(profile_banner, this);
addBannerBtn.setVisibility(INVISIBLE);
changeBannerBtn.setVisibility(VISIBLE);
addBannerBtn.setVisibility(View.INVISIBLE);
changeBannerBtn.setVisibility(View.VISIBLE);
} else {
Toast.makeText(getApplicationContext(), R.string.error_adding_media, Toast.LENGTH_SHORT).show();
}
@ -324,11 +320,11 @@ public class ProfileEditor extends MediaActivity implements OnClickListener, Asy
}
if (!bannerImageUrl.isEmpty()) {
picasso.load(bannerImageUrl).into(profile_banner, this);
addBannerBtn.setVisibility(INVISIBLE);
changeBannerBtn.setVisibility(VISIBLE);
addBannerBtn.setVisibility(View.INVISIBLE);
changeBannerBtn.setVisibility(View.VISIBLE);
} else {
addBannerBtn.setVisibility(VISIBLE);
changeBannerBtn.setVisibility(INVISIBLE);
addBannerBtn.setVisibility(View.VISIBLE);
changeBannerBtn.setVisibility(View.INVISIBLE);
}
username.setText(user.getUsername());
profileUrl.setText(user.getProfileUrl());

View File

@ -1,7 +1,5 @@
package org.nuclearfog.twidda.ui.activities;
import static org.nuclearfog.twidda.ui.activities.StatusEditor.KEY_STATUS_EDITOR_TEXT;
import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
@ -20,34 +18,52 @@ import androidx.appcompat.widget.Toolbar;
import androidx.viewpager2.widget.ViewPager2;
import org.nuclearfog.twidda.R;
import org.nuclearfog.twidda.backend.async.AsyncExecutor.AsyncCallback;
import org.nuclearfog.twidda.backend.async.HashtagAction;
import org.nuclearfog.twidda.backend.async.HashtagAction.HashtagParam;
import org.nuclearfog.twidda.backend.async.HashtagAction.HashtagResult;
import org.nuclearfog.twidda.backend.utils.AppStyles;
import org.nuclearfog.twidda.backend.utils.ErrorHandler;
import org.nuclearfog.twidda.config.Configuration;
import org.nuclearfog.twidda.config.GlobalSettings;
import org.nuclearfog.twidda.model.Trend;
import org.nuclearfog.twidda.ui.adapter.FragmentAdapter;
import org.nuclearfog.twidda.ui.views.TabSelector;
import org.nuclearfog.twidda.ui.views.TabSelector.OnTabSelectedListener;
import java.io.Serializable;
/**
* search Activity for statuses and users
*
* @author nuclearfog
*/
public class SearchActivity extends AppCompatActivity implements OnTabSelectedListener, OnQueryTextListener {
public class SearchActivity extends AppCompatActivity implements OnTabSelectedListener, OnQueryTextListener, AsyncCallback<HashtagResult> {
/**
* Key for the search query, required
* value type is String
*/
public static final String KEY_SEARCH_QUERY = "search_query";
public static final String KEY_QUERY = "search_query";
/**
* key to add trend information to search for
* value type is {@link org.nuclearfog.twidda.model.Trend}
*/
public static final String KEY_TREND = "search_trend";
public static final int SEARCH_STR_MAX_LEN = 128;
private HashtagAction hashtagAction;
private FragmentAdapter adapter;
private GlobalSettings settings;
private ViewPager2 viewPager;
private Toolbar toolbar;
private String search = "";
@Nullable
private Trend trend;
@Override
@ -70,18 +86,23 @@ public class SearchActivity extends AppCompatActivity implements OnTabSelectedLi
settings = GlobalSettings.getInstance(this);
adapter = new FragmentAdapter(this);
hashtagAction = new HashtagAction(this);
tabSelector.addViewPager(viewPager);
tabSelector.addOnTabSelectedListener(this);
viewPager.setAdapter(adapter);
viewPager.setOffscreenPageLimit(3);
String search = getIntent().getStringExtra(KEY_SEARCH_QUERY);
if (search != null) {
this.search = search;
String query = getIntent().getStringExtra(KEY_QUERY);
Serializable data = getIntent().getSerializableExtra(KEY_TREND);
if (data instanceof Trend) {
trend = (Trend) data;
search = trend.getName();
} else if (query != null) {
search = query;
}
boolean enableHashtags = !search.startsWith("#") && settings.getLogin().getConfiguration() == Configuration.MASTODON;
adapter.setupSearchPage(search, enableHashtags);
tabSelector.addTabIcons(R.array.search_tab_icons);
}
AppStyles.setTheme(root);
}
@ -97,21 +118,44 @@ public class SearchActivity extends AppCompatActivity implements OnTabSelectedLi
@Override
public boolean onCreateOptionsMenu(@NonNull Menu m) {
getMenuInflater().inflate(R.menu.search, m);
MenuItem searchItem = m.findItem(R.id.new_search);
MenuItem searchFilter = m.findItem(R.id.search_filter);
protected void onDestroy() {
hashtagAction.cancel();
super.onDestroy();
}
@Override
public boolean onCreateOptionsMenu(@NonNull Menu menu) {
getMenuInflater().inflate(R.menu.search, menu);
MenuItem searchItem = menu.findItem(R.id.new_search);
MenuItem searchFilter = menu.findItem(R.id.search_filter);
MenuItem hashtag = menu.findItem(R.id.search_hashtag);
SearchView searchView = (SearchView) searchItem.getActionView();
hashtag.setVisible(trend != null);
boolean enableSearchFilter = settings.getLogin().getConfiguration().filterEnabled();
searchFilter.setChecked(settings.filterResults() & enableSearchFilter);
searchView.setQueryHint(search);
searchView.setOnQueryTextListener(this);
// set theme
AppStyles.setTheme(searchView, Color.TRANSPARENT);
AppStyles.setMenuIconColor(m, settings.getIconColor());
AppStyles.setMenuIconColor(menu, settings.getIconColor());
AppStyles.setOverflowIcon(toolbar, settings.getIconColor());
return super.onCreateOptionsMenu(m);
return true;
}
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
MenuItem hashtag = menu.findItem(R.id.search_hashtag);
if (trend != null) {
if (trend.following()) {
hashtag.setTitle(R.string.menu_hashtag_unfollow);
} else {
hashtag.setTitle(R.string.menu_hashtag_follow);
}
}
return super.onPrepareOptionsMenu(menu);
}
@ -121,7 +165,7 @@ public class SearchActivity extends AppCompatActivity implements OnTabSelectedLi
if (item.getItemId() == R.id.search_status) {
Intent intent = new Intent(this, StatusEditor.class);
if (search.startsWith("#"))
intent.putExtra(KEY_STATUS_EDITOR_TEXT, search + " ");
intent.putExtra(StatusEditor.KEY_TEXT, search + " ");
startActivity(intent);
return true;
}
@ -138,6 +182,17 @@ public class SearchActivity extends AppCompatActivity implements OnTabSelectedLi
item.setChecked(enable);
return true;
}
// follow/unfollow hashtag
else if (item.getItemId() == R.id.search_hashtag) {
if (trend != null && hashtagAction.isIdle()) {
HashtagParam param;
if (trend.following())
param = new HashtagParam(trend.getName(), HashtagParam.UNFOLLOW);
else
param = new HashtagParam(trend.getName(), HashtagParam.FOLLOW);
hashtagAction.execute(param, this);
}
}
return super.onOptionsItemSelected(item);
}
@ -146,7 +201,7 @@ public class SearchActivity extends AppCompatActivity implements OnTabSelectedLi
public boolean onQueryTextSubmit(String s) {
if (s.length() <= SearchActivity.SEARCH_STR_MAX_LEN && !s.contains(":") && !s.contains("$")) {
Intent search = new Intent(this, SearchActivity.class);
search.putExtra(KEY_SEARCH_QUERY, s);
search.putExtra(KEY_QUERY, s);
startActivity(search);
return true;
} else {
@ -167,4 +222,27 @@ public class SearchActivity extends AppCompatActivity implements OnTabSelectedLi
invalidateOptionsMenu();
adapter.scrollToTop(oldPosition);
}
@Override
public void onResult(@NonNull HashtagResult result) {
if (result.trend != null)
this.trend = result.trend;
switch(result.mode) {
case HashtagResult.FOLLOW:
Toast.makeText(getApplicationContext(), R.string.info_hashtag_followed, Toast.LENGTH_SHORT).show();
invalidateMenu();
break;
case HashtagResult.UNFOLLOW:
Toast.makeText(getApplicationContext(), R.string.info_hashtag_unfollowed, Toast.LENGTH_SHORT).show();
invalidateMenu();
break;
case HashtagResult.ERROR:
String message = ErrorHandler.getErrorMessage(this, result.exception);
Toast.makeText(getApplicationContext(), message, Toast.LENGTH_SHORT).show();
break;
}
}
}

View File

@ -1,17 +1,5 @@
package org.nuclearfog.twidda.ui.activities;
import static org.nuclearfog.twidda.ui.activities.SearchActivity.KEY_SEARCH_QUERY;
import static org.nuclearfog.twidda.ui.activities.StatusEditor.KEY_STATUS_EDITOR_DATA;
import static org.nuclearfog.twidda.ui.activities.StatusEditor.KEY_STATUS_EDITOR_EDIT;
import static org.nuclearfog.twidda.ui.activities.UsersActivity.KEY_USERS_ID;
import static org.nuclearfog.twidda.ui.activities.UsersActivity.KEY_USERS_MODE;
import static org.nuclearfog.twidda.ui.activities.UsersActivity.USERS_FAVORIT;
import static org.nuclearfog.twidda.ui.activities.UsersActivity.USERS_REPOST;
import static org.nuclearfog.twidda.ui.fragments.StatusFragment.KEY_ID;
import static org.nuclearfog.twidda.ui.fragments.StatusFragment.KEY_MODE;
import static org.nuclearfog.twidda.ui.fragments.StatusFragment.KEY_SEARCH;
import static org.nuclearfog.twidda.ui.fragments.StatusFragment.MODE_REPLY;
import android.content.ActivityNotFoundException;
import android.content.ClipData;
import android.content.ClipboardManager;
@ -136,34 +124,28 @@ public class StatusActivity extends AppCompatActivity implements OnClickListener
* value type is {@link Status}
* If no status object exists, {@link #KEY_STATUS_ID} and {@link #KEY_STATUS_NAME} will be used instead
*/
public static final String KEY_STATUS_DATA = "status_data";
public static final String KEY_DATA = "status_data";
/**
* key uused for notification information, containing a status
* value type is {@link Notification}
*/
public static final String KEY_NOTIFICATION_DATA = "notification_data";
/**
* key for the status ID value, alternative to {@link #KEY_STATUS_DATA}
* key for the status ID value, alternative to {@link #KEY_DATA}
* value type is Long
*/
public static final String KEY_STATUS_ID = "status_id";
/**
* key for the status author's name. alternative to {@link #KEY_STATUS_DATA}
* key for the status author's name. alternative to {@link #KEY_DATA}
* value type is String
*/
public static final String KEY_STATUS_NAME = "status_author";
/**
* key for the notification ID value, alternative to {@link #KEY_NOTIFICATION_DATA}
* key for the notification ID value
* value type is long
*/
public static final String KEY_NOTIFICATION_ID = "notification_id";
/**
* key for the (notification) status author's name. alternative to {@link #KEY_STATUS_DATA}
* key for the (notification) status author's name. alternative to {@link #KEY_DATA}
* value type is String
*/
public static final String KEY_NOTIFICATION_NAME = "notification_status_author";
@ -315,15 +297,14 @@ public class StatusActivity extends AppCompatActivity implements OnClickListener
return;
}
// get data
Serializable serializedStatus = savedInstanceState.getSerializable(KEY_STATUS_DATA);
Serializable serializedNotification = savedInstanceState.getSerializable(KEY_NOTIFICATION_DATA);
Serializable serialized = savedInstanceState.getSerializable(KEY_DATA);
long statusId = savedInstanceState.getLong(KEY_STATUS_ID, 0L);
long notificationId = savedInstanceState.getLong(KEY_NOTIFICATION_ID, 0L);
String replyUsername = "";
// set status data
if (serializedStatus instanceof Status) {
Status status = (Status) serializedStatus;
if (serialized instanceof Status) {
Status status = (Status) serialized;
Status embeddedStatus = status.getEmbeddedStatus();
setStatus(status);
StatusParam statusParam = new StatusParam(StatusParam.ONLINE, status.getId());
@ -339,8 +320,8 @@ public class StatusActivity extends AppCompatActivity implements OnClickListener
}
}
// set notification data
else if (serializedNotification instanceof Notification) {
Notification notification = (Notification) serializedNotification;
else if (serialized instanceof Notification) {
Notification notification = (Notification) serialized;
NotificationActionParam notificationParam = new NotificationActionParam(NotificationActionParam.ONLINE, notification.getId());
notificationLoader.execute(notificationParam, notificationCallback);
if (notification.getStatus() != null) {
@ -363,9 +344,9 @@ public class StatusActivity extends AppCompatActivity implements OnClickListener
}
// initialize status reply list
Bundle param = new Bundle();
param.putInt(KEY_MODE, MODE_REPLY);
param.putString(KEY_SEARCH, replyUsername);
param.putLong(KEY_ID, statusId);
param.putInt(StatusFragment.KEY_MODE, StatusFragment.MODE_REPLY);
param.putString(StatusFragment.KEY_SEARCH, replyUsername);
param.putLong(StatusFragment.KEY_ID, statusId);
FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.page_status_reply_fragment, StatusFragment.class, param);
fragmentTransaction.commit();
@ -395,8 +376,7 @@ public class StatusActivity extends AppCompatActivity implements OnClickListener
@Override
public void onSaveInstanceState(@NonNull Bundle outState) {
outState.putSerializable(KEY_STATUS_DATA, status);
outState.putSerializable(KEY_NOTIFICATION_DATA, notification);
outState.putSerializable(KEY_DATA, status);
super.onSaveInstanceState(outState);
}
@ -576,8 +556,8 @@ public class StatusActivity extends AppCompatActivity implements OnClickListener
// edit status
else if (item.getItemId() == R.id.menu_status_edit) {
Intent intent = new Intent(this, StatusEditor.class);
intent.putExtra(KEY_STATUS_EDITOR_DATA, status);
intent.putExtra(KEY_STATUS_EDITOR_EDIT, true);
intent.putExtra(StatusEditor.KEY_DATA, status);
intent.putExtra(StatusEditor.KEY_EDIT, true);
activityResultLauncher.launch(intent);
}
return super.onOptionsItemSelected(item);
@ -587,7 +567,7 @@ public class StatusActivity extends AppCompatActivity implements OnClickListener
@Override
public void onActivityResult(ActivityResult result) {
if (result.getData() != null && result.getResultCode() == StatusEditor.RETURN_STATUS_UPDATE) {
Serializable data = result.getData().getSerializableExtra(StatusEditor.RETURN_STATUS_DATA);
Serializable data = result.getData().getSerializableExtra(StatusEditor.KEY_DATA);
if (data instanceof Status) {
setStatus((Status) data);
}
@ -604,21 +584,21 @@ public class StatusActivity extends AppCompatActivity implements OnClickListener
// answer to the status
if (v.getId() == R.id.page_status_reply) {
Intent intent = new Intent(this, StatusEditor.class);
intent.putExtra(KEY_STATUS_EDITOR_DATA, status);
intent.putExtra(StatusEditor.KEY_DATA, status);
startActivity(intent);
}
// show user reposting this status
else if (v.getId() == R.id.page_status_repost) {
Intent intent = new Intent(this, UsersActivity.class);
intent.putExtra(KEY_USERS_ID, status.getId());
intent.putExtra(KEY_USERS_MODE, USERS_REPOST);
intent.putExtra(UsersActivity.KEY_ID, status.getId());
intent.putExtra(UsersActivity.KEY_MODE, UsersActivity.USERS_REPOST);
startActivity(intent);
}
// show user favoriting this status
else if (v.getId() == R.id.page_status_favorite) {
Intent intent = new Intent(this, UsersActivity.class);
intent.putExtra(KEY_USERS_ID, status.getId());
intent.putExtra(KEY_USERS_MODE, USERS_FAVORIT);
intent.putExtra(UsersActivity.KEY_ID, status.getId());
intent.putExtra(UsersActivity.KEY_MODE, UsersActivity.USERS_FAVORIT);
startActivity(intent);
}
// open profile of the status author
@ -694,7 +674,7 @@ public class StatusActivity extends AppCompatActivity implements OnClickListener
Status embeddedStatus = status.getEmbeddedStatus();
if (embeddedStatus != null) {
Intent intent = new Intent(this, StatusActivity.class);
intent.putExtra(KEY_STATUS_DATA, embeddedStatus);
intent.putExtra(KEY_DATA, embeddedStatus);
startActivity(intent);
}
return true;
@ -780,15 +760,15 @@ public class StatusActivity extends AppCompatActivity implements OnClickListener
case Media.VIDEO:
intent = new Intent(this, VideoViewer.class);
intent.putExtra(VideoViewer.VIDEO_URI, uri);
intent.putExtra(VideoViewer.ENABLE_VIDEO_CONTROLS, true);
intent.putExtra(VideoViewer.KEY_LINK, uri);
intent.putExtra(VideoViewer.KEY_CONTROLS, true);
startActivity(intent);
break;
case Media.GIF:
intent = new Intent(this, VideoViewer.class);
intent.putExtra(VideoViewer.VIDEO_URI, uri);
intent.putExtra(VideoViewer.ENABLE_VIDEO_CONTROLS, false);
intent.putExtra(VideoViewer.KEY_LINK, uri);
intent.putExtra(VideoViewer.KEY_CONTROLS, false);
startActivity(intent);
break;
}
@ -798,7 +778,7 @@ public class StatusActivity extends AppCompatActivity implements OnClickListener
@Override
public void onTagClick(String tag) {
Intent intent = new Intent(this, SearchActivity.class);
intent.putExtra(KEY_SEARCH_QUERY, tag);
intent.putExtra(SearchActivity.KEY_QUERY, tag);
startActivity(intent);
}

View File

@ -65,31 +65,25 @@ public class StatusEditor extends MediaActivity implements OnClickListener, OnPr
* key to add the status to reply
* value type is {@link Status}
*/
public static final String KEY_STATUS_EDITOR_DATA = "status_data";
public static final String KEY_DATA = "status_data";
/**
* key to edit an existing status
* value type is Boolean
*/
public static final String KEY_STATUS_EDITOR_EDIT = "status_edit";
public static final String KEY_EDIT = "status_edit";
/**
* key for the text added to the status if any
* value type is String
*/
public static final String KEY_STATUS_EDITOR_TEXT = "status_text";
/**
* key to return uploaded status information
* value type is {@link Status}
*/
public static final String RETURN_STATUS_DATA = "status_update";
public static final String KEY_TEXT = "status_text";
/**
* key for status update to restore
* value type is {@link StatusUpdate}
*/
private static final String KEY_STATUS_UPDATE = "status_update";
private static final String KEY_SAVE = "status_update";
private AsyncCallback<StatusUpdateResult> statusUpdateResult = this::onStatusUpdated;
private AsyncCallback<Instance> instanceResult = this::onInstanceResult;
@ -161,10 +155,10 @@ public class StatusEditor extends MediaActivity implements OnClickListener, OnPr
if (savedInstanceState == null)
savedInstanceState = getIntent().getExtras();
if (savedInstanceState != null) {
Serializable serializedStatus = savedInstanceState.getSerializable(KEY_STATUS_EDITOR_DATA);
Serializable serializedStatusUpdate = savedInstanceState.getSerializable(KEY_STATUS_UPDATE);
boolean editStatus = savedInstanceState.getBoolean(KEY_STATUS_EDITOR_EDIT, false);
String prefix = savedInstanceState.getString(KEY_STATUS_EDITOR_TEXT);
Serializable serializedStatus = savedInstanceState.getSerializable(KEY_DATA);
Serializable serializedStatusUpdate = savedInstanceState.getSerializable(KEY_SAVE);
boolean editStatus = savedInstanceState.getBoolean(KEY_EDIT, false);
String prefix = savedInstanceState.getString(KEY_TEXT);
if (serializedStatusUpdate instanceof StatusUpdate) {
statusUpdate = (StatusUpdate) serializedStatusUpdate;
} else if (serializedStatus instanceof Status) {
@ -224,7 +218,7 @@ public class StatusEditor extends MediaActivity implements OnClickListener, OnPr
@Override
protected void onSaveInstanceState(@NonNull Bundle outState) {
outState.putSerializable(KEY_STATUS_UPDATE, statusUpdate);
outState.putSerializable(KEY_SAVE, statusUpdate);
super.onSaveInstanceState(outState);
}
@ -384,8 +378,8 @@ public class StatusEditor extends MediaActivity implements OnClickListener, OnPr
case StatusUpdate.MEDIA_VIDEO:
intent = new Intent(this, VideoViewer.class);
intent.putExtra(VideoViewer.VIDEO_URI, uri);
intent.putExtra(VideoViewer.ENABLE_VIDEO_CONTROLS, true);
intent.putExtra(VideoViewer.KEY_LINK, uri);
intent.putExtra(VideoViewer.KEY_CONTROLS, true);
startActivity(intent);
break;
@ -458,7 +452,7 @@ public class StatusEditor extends MediaActivity implements OnClickListener, OnPr
private void onStatusUpdated(@NonNull StatusUpdateResult result) {
if (result.status != null) {
Intent intent = new Intent();
intent.putExtra(RETURN_STATUS_DATA, result.status);
intent.putExtra(KEY_DATA, result.status);
setResult(RETURN_STATUS_UPDATE, intent);
Toast.makeText(getApplicationContext(), R.string.info_status_sent, Toast.LENGTH_LONG).show();
finish();

View File

@ -1,7 +1,5 @@
package org.nuclearfog.twidda.ui.activities;
import static org.nuclearfog.twidda.ui.activities.UserlistEditor.KEY_LIST_EDITOR_DATA;
import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
@ -59,25 +57,19 @@ public class UserlistActivity extends AppCompatActivity implements ActivityResul
* key to add list information
* value type is {@link UserList}
*/
public static final String KEY_LIST_DATA = "list_data";
public static final String KEY_DATA = "list_data";
/**
* key to disable list update
* value type is boolean
*/
public static final String KEY_LIST_NO_UPDATE = "list_no_update";
public static final String KEY_DISABLE_UPDATE = "list_no_update";
/**
* result key to return the ID of a removed list
* value type is {@link UserList}
*/
public static final String RESULT_REMOVED_LIST_ID = "removed-list-id";
/**
* result key to update an user list
* value type is {@link UserList}
*/
public static final String RESULT_UPDATE_LIST = "update-user-list";
public static final String KEY_ID = "removed-list-id";
/**
* return code when an user list was deleted
@ -143,7 +135,7 @@ public class UserlistActivity extends AppCompatActivity implements ActivityResul
viewPager.setAdapter(adapter);
tabSelector.addViewPager(viewPager);
Object data = getIntent().getSerializableExtra(KEY_LIST_DATA);
Object data = getIntent().getSerializableExtra(KEY_DATA);
if (data instanceof UserList) {
userList = (UserList) data;
toolbar.setTitle(userList.getTitle());
@ -164,7 +156,7 @@ public class UserlistActivity extends AppCompatActivity implements ActivityResul
protected void onStart() {
super.onStart();
if (userList != null) {
boolean blockUpdate = getIntent().getBooleanExtra(KEY_LIST_NO_UPDATE, false);
boolean blockUpdate = getIntent().getBooleanExtra(KEY_DISABLE_UPDATE, false);
if (!blockUpdate) {
// update list information
ListActionParam param = new ListActionParam(ListActionParam.LOAD, userList.getId());
@ -225,7 +217,7 @@ public class UserlistActivity extends AppCompatActivity implements ActivityResul
// open user list editor
if (item.getItemId() == R.id.menu_list_edit) {
Intent editList = new Intent(this, UserlistEditor.class);
editList.putExtra(KEY_LIST_EDITOR_DATA, userList);
editList.putExtra(UserlistEditor.KEY_DATA, userList);
activityResultLauncher.launch(editList);
return true;
}
@ -261,7 +253,7 @@ public class UserlistActivity extends AppCompatActivity implements ActivityResul
viewPager.setCurrentItem(0);
} else {
Intent result = new Intent();
result.putExtra(RESULT_UPDATE_LIST, userList);
result.putExtra(KEY_DATA, userList);
setResult(RETURN_LIST_UPDATED, result);
super.onBackPressed();
}
@ -272,7 +264,7 @@ public class UserlistActivity extends AppCompatActivity implements ActivityResul
public void onActivityResult(ActivityResult result) {
if (result.getData() != null) {
if (result.getResultCode() == UserlistEditor.RETURN_LIST_CHANGED) {
Object data = result.getData().getSerializableExtra(UserlistEditor.KEY_USERLIST_UPDATED);
Object data = result.getData().getSerializableExtra(UserlistEditor.KEY_UPDATE);
if (data instanceof UserList) {
userList = (UserList) data;
toolbar.setTitle(userList.getTitle());
@ -413,7 +405,7 @@ public class UserlistActivity extends AppCompatActivity implements ActivityResul
case ListActionResult.DELETE:
Intent intent = new Intent();
intent.putExtra(RESULT_REMOVED_LIST_ID, result.id);
intent.putExtra(KEY_ID, result.id);
setResult(RETURN_LIST_REMOVED, intent);
Toast.makeText(getApplicationContext(), R.string.info_list_removed, Toast.LENGTH_SHORT).show();
finish();
@ -425,7 +417,7 @@ public class UserlistActivity extends AppCompatActivity implements ActivityResul
if (result.exception != null && result.exception.getErrorCode() == ConnectionException.RESOURCE_NOT_FOUND) {
// List does not exist
intent = new Intent();
intent.putExtra(RESULT_REMOVED_LIST_ID, result.id);
intent.putExtra(KEY_ID, result.id);
setResult(RETURN_LIST_REMOVED, intent);
finish();
}

View File

@ -44,19 +44,19 @@ public class UserlistEditor extends AppCompatActivity implements OnClickListener
* Key for the list ID if an existing list should be updated
* value type is Long
*/
public static final String KEY_LIST_EDITOR_DATA = "list_edit_data";
public static final String KEY_DATA = "list_edit_data";
/**
* Key for updated list information
* value type is {@link UserList}
*/
public static final String KEY_USERLIST_UPDATED = "userlist-updated";
public static final String KEY_UPDATE = "userlist-updated";
/**
* internal key used to save userlist changes
* value type is {@link UserListUpdate}
*/
private static final String KEY_USERLIST_UPDATE = "userlist-update";
private static final String KEY_SAVE = "userlist-update";
/**
* Return code used when an existing userlist was changed
@ -103,7 +103,7 @@ public class UserlistEditor extends AppCompatActivity implements OnClickListener
GlobalSettings settings = GlobalSettings.getInstance(this);
AppStyles.setEditorTheme(root, background);
Serializable serializedUserlist = getIntent().getSerializableExtra(KEY_LIST_EDITOR_DATA);
Serializable serializedUserlist = getIntent().getSerializableExtra(KEY_DATA);
if (serializedUserlist instanceof UserList) {
UserList userList = (UserList) serializedUserlist;
titleText.setText(userList.getTitle());
@ -131,7 +131,7 @@ public class UserlistEditor extends AppCompatActivity implements OnClickListener
protected void onSaveInstanceState(@NonNull Bundle outState) {
listUpdate.setTitle(titleText.getText().toString());
listUpdate.setDescription(descriptionText.getText().toString());
outState.putSerializable(KEY_USERLIST_UPDATE, listUpdate);
outState.putSerializable(KEY_SAVE, listUpdate);
super.onSaveInstanceState(outState);
}
@ -139,7 +139,7 @@ public class UserlistEditor extends AppCompatActivity implements OnClickListener
@Override
protected void onRestoreInstanceState(@NonNull Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
Serializable serializedListUpdate = savedInstanceState.getSerializable(KEY_USERLIST_UPDATE);
Serializable serializedListUpdate = savedInstanceState.getSerializable(KEY_SAVE);
if (serializedListUpdate instanceof UserListUpdate) {
listUpdate = (UserListUpdate) serializedListUpdate;
}
@ -211,7 +211,7 @@ public class UserlistEditor extends AppCompatActivity implements OnClickListener
Toast.makeText(getApplicationContext(), R.string.info_list_created, Toast.LENGTH_SHORT).show();
}
Intent intent = new Intent();
intent.putExtra(KEY_USERLIST_UPDATED, result.userlist);
intent.putExtra(KEY_UPDATE, result.userlist);
setResult(RETURN_LIST_CHANGED, intent);
finish();
} else {

View File

@ -1,8 +1,5 @@
package org.nuclearfog.twidda.ui.activities;
import static org.nuclearfog.twidda.ui.activities.UsersActivity.KEY_USERS_MODE;
import static org.nuclearfog.twidda.ui.activities.UsersActivity.USERS_EXCLUDED;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
@ -38,7 +35,7 @@ public class UserlistsActivity extends AppCompatActivity implements ActivityResu
* Key for the ID the list owner
* value type is Long
*/
public static final String KEY_USERLIST_OWNER_ID = "userlist-owner-id";
public static final String KEY_ID = "userlist-owner-id";
private ActivityResultLauncher<Intent> activityResultLauncher = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), this);
@ -71,7 +68,7 @@ public class UserlistsActivity extends AppCompatActivity implements ActivityResu
toolbar.setTitle(R.string.list_appbar);
setSupportActionBar(toolbar);
long ownerId = getIntent().getLongExtra(KEY_USERLIST_OWNER_ID, 0L);
long ownerId = getIntent().getLongExtra(KEY_ID, 0L);
isHome = ownerId == settings.getLogin().getId();
adapter.setupListPage(ownerId);
@ -125,7 +122,7 @@ public class UserlistsActivity extends AppCompatActivity implements ActivityResu
// open mute/block list
else if (item.getItemId() == R.id.list_blocklists) {
Intent usersIntent = new Intent(this, UsersActivity.class);
usersIntent.putExtra(KEY_USERS_MODE, USERS_EXCLUDED);
usersIntent.putExtra(UsersActivity.KEY_MODE, UsersActivity.USERS_EXCLUDED);
startActivity(usersIntent);
return true;
}

View File

@ -42,53 +42,53 @@ public class UsersActivity extends AppCompatActivity implements OnTabSelectedLis
* type of users to get from the source
* {@link #USERS_FOLLOWING ,#USERS_FOLLOWER ,#USERS_REPOST ,#USERLIST_FAVORIT,#USERLIST_EXCLUDED_USERS,#USERLIST_REQUESTS}
*/
public static final String KEY_USERS_MODE = "userlist_mode";
public static final String KEY_MODE = "userlist_mode";
/**
* ID of a userlist, an user or a status to get the users from
* value type is Long
*/
public static final String KEY_USERS_ID = "userlist_id";
public static final String KEY_ID = "userlist_id";
/**
* user following, requires user ID
*
* @see #KEY_USERS_MODE
* @see #KEY_MODE
*/
public static final int USERS_FOLLOWING = 0xDF893242;
/**
* follower of an user, requires user ID
*
* @see #KEY_USERS_MODE
* @see #KEY_MODE
*/
public static final int USERS_FOLLOWER = 0xA89F5968;
/**
* user reposting a status, requires status ID
*
* @see #KEY_USERS_MODE
* @see #KEY_MODE
*/
public static final int USERS_REPOST = 0x19F582E;
/**
* user favoriting/liking a status, requires status ID
*
* @see #KEY_USERS_MODE
* @see #KEY_MODE
*/
public static final int USERS_FAVORIT = 0x9bcc3f99;
/**
* setup list to show excluded (muted, blocked) users
*
* @see #KEY_USERS_MODE
* @see #KEY_MODE
*/
public static final int USERS_EXCLUDED = 0x896a786;
/**
* setup list to show incoming & outgoing follow requests
*
* @see #KEY_USERS_MODE
* @see #KEY_MODE
*/
public static final int USERS_REQUESTS = 0x0948693;
@ -128,8 +128,8 @@ public class UsersActivity extends AppCompatActivity implements OnTabSelectedLis
adapter = new FragmentAdapter(this);
viewPager.setAdapter(adapter);
mode = getIntent().getIntExtra(KEY_USERS_MODE, 0);
long id = getIntent().getLongExtra(KEY_USERS_ID, 0L);
mode = getIntent().getIntExtra(KEY_MODE, 0);
long id = getIntent().getLongExtra(KEY_ID, 0L);
switch (mode) {
case USERS_FOLLOWING:

View File

@ -56,13 +56,13 @@ public class VideoViewer extends AppCompatActivity implements Player.Listener {
* key for an Uri array with local links
* value type is {@link Uri}
*/
public static final String VIDEO_URI = "media_uri";
public static final String KEY_LINK = "media_uri";
/**
* Key to enable extra layouts for a video
* value type is Boolean
*/
public static final String ENABLE_VIDEO_CONTROLS = "enable_controls";
public static final String KEY_CONTROLS = "enable_controls";
/**
* online video cache size
@ -106,8 +106,8 @@ public class VideoViewer extends AppCompatActivity implements Player.Listener {
player = new ExoPlayer.Builder(this, renderersFactory).build();
player.addListener(this);
data = getIntent().getParcelableExtra(VIDEO_URI);
boolean enableControls = getIntent().getBooleanExtra(ENABLE_VIDEO_CONTROLS, true);
data = getIntent().getParcelableExtra(KEY_LINK);
boolean enableControls = getIntent().getBooleanExtra(KEY_CONTROLS, true);
if (!enableControls) {
playerView.setUseController(false);
player.setRepeatMode(Player.REPEAT_MODE_ONE);

View File

@ -3,7 +3,7 @@ package org.nuclearfog.twidda.ui.fragments;
import static android.widget.Toast.LENGTH_SHORT;
import static org.nuclearfog.twidda.ui.activities.MessageEditor.KEY_MESSAGE_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.SearchActivity.KEY_QUERY;
import android.content.Intent;
import android.net.Uri;
@ -108,7 +108,7 @@ public class MessageFragment extends ListFragment implements OnMessageClickListe
public void onTagClick(String tag) {
if (!isRefreshing()) {
Intent intent = new Intent(requireContext(), SearchActivity.class);
intent.putExtra(KEY_SEARCH_QUERY, tag);
intent.putExtra(KEY_QUERY, tag);
startActivity(intent);
}
}

View File

@ -116,7 +116,7 @@ public class NotificationFragment extends ListFragment implements OnNotification
switch (action) {
case OnNotificationClickListener.VIEW:
Intent intent = new Intent(requireContext(), StatusActivity.class);
intent.putExtra(StatusActivity.KEY_NOTIFICATION_DATA, notification);
intent.putExtra(StatusActivity.KEY_DATA, notification);
activityResultLauncher.launch(intent);
break;

View File

@ -1,6 +1,6 @@
package org.nuclearfog.twidda.ui.fragments;
import static org.nuclearfog.twidda.ui.activities.StatusActivity.KEY_STATUS_DATA;
import static org.nuclearfog.twidda.ui.activities.StatusActivity.KEY_DATA;
import android.content.Intent;
import android.os.Bundle;
@ -205,7 +205,7 @@ public class StatusFragment extends ListFragment implements StatusSelectListener
public void onStatusSelected(Status status) {
if (!isRefreshing()) {
Intent intent = new Intent(requireContext(), StatusActivity.class);
intent.putExtra(KEY_STATUS_DATA, status);
intent.putExtra(KEY_DATA, status);
activityResultLauncher.launch(intent);
}
}

View File

@ -1,7 +1,5 @@
package org.nuclearfog.twidda.ui.fragments;
import static org.nuclearfog.twidda.ui.activities.SearchActivity.KEY_SEARCH_QUERY;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
@ -129,9 +127,12 @@ public class TrendFragment extends ListFragment implements TrendClickListener, A
if (!isRefreshing()) {
Intent intent = new Intent(requireContext(), SearchActivity.class);
String name = trend.getName();
if (!name.startsWith("#") && !name.startsWith("\"") && !name.endsWith("\""))
if (!name.startsWith("#") && !name.startsWith("\"") && !name.endsWith("\"")) {
name = "\"" + name + "\"";
intent.putExtra(KEY_SEARCH_QUERY, name);
intent.putExtra(SearchActivity.KEY_QUERY, name);
} else {
intent.putExtra(SearchActivity.KEY_TREND, trend);
}
startActivity(intent);
}
}

View File

@ -1,7 +1,7 @@
package org.nuclearfog.twidda.ui.fragments;
import static org.nuclearfog.twidda.ui.activities.ProfileActivity.KEY_PROFILE_USER;
import static org.nuclearfog.twidda.ui.activities.UserlistActivity.KEY_LIST_DATA;
import static org.nuclearfog.twidda.ui.activities.UserlistActivity.KEY_DATA;
import android.content.Intent;
import android.os.Bundle;
@ -137,12 +137,12 @@ public class UserListFragment extends ListFragment implements ListClickListener,
if (intent != null) {
// check if userlist was removed
if (result.getResultCode() == UserlistActivity.RETURN_LIST_REMOVED) {
long removedListId = intent.getLongExtra(UserlistActivity.RESULT_REMOVED_LIST_ID, 0L);
long removedListId = intent.getLongExtra(UserlistActivity.KEY_ID, 0L);
adapter.removeItem(removedListId);
}
// check if userlist was updated
else if (result.getResultCode() == UserlistActivity.RETURN_LIST_UPDATED) {
Object object = intent.getSerializableExtra(UserlistActivity.RESULT_UPDATE_LIST);
Object object = intent.getSerializableExtra(UserlistActivity.KEY_DATA);
if (object instanceof UserList) {
UserList update = (UserList) object;
adapter.updateItem(update);
@ -155,7 +155,7 @@ public class UserListFragment extends ListFragment implements ListClickListener,
@Override
public void onListClick(UserList listItem) {
Intent listIntent = new Intent(requireContext(), UserlistActivity.class);
listIntent.putExtra(KEY_LIST_DATA, listItem);
listIntent.putExtra(KEY_DATA, listItem);
activityResultLauncher.launch(listIntent);
}

View File

@ -15,9 +15,16 @@
android:title="@string/menu_status"
app:showAsAction="ifRoom" />
<item
android:id="@+id/search_hashtag"
android:title="@string/menu_hashtag_follow"
app:showAsAction="never"
android:visible="false"/>
<item
android:id="@+id/search_filter"
android:title="@string/menu_search_filter"
android:checkable="true" />
android:checkable="true"
app:showAsAction="never" />
</menu>

View File

@ -291,4 +291,8 @@
<string name="error_duration_time_low">Dauer der Umfrage ist zu kurz!</string>
<string name="error_duration_time_high">Dauer der Umfrage ist zu lang!</string>
<string name="error_poll_option_missing">Umfrageoption darf nicht leer sein!</string>
<string name="menu_hashtag_follow">folge Hashtag</string>
<string name="menu_hashtag_unfollow">entfolge Hashtag</string>
<string name="info_hashtag_unfollowed">Hashtag entfolgt</string>
<string name="info_hashtag_followed">Hashtag gefolgt</string>
</resources>

View File

@ -65,12 +65,14 @@
<string name="info_missing_host">please enter correct hostname</string>
<string name="info_database_cleared">Database cleared</string>
<string name="info_notification_dismiss">Notification dismissed</string>
<string name="error_duration_time_low">Poll duration time too low!</string>
<string name="error_duration_time_high">Poll duration time too high!</string>
<string name="error_poll_option_missing">poll option can not be empty!</string>
<string name="info_hashtag_unfollowed">hashtag unfollowed</string>
<string name="info_hashtag_followed">hashtag followed</string>
<string name="info_error">Error</string>
<!-- toast messages for error information -->
<string name="error_duration_time_low">Poll duration time too low!</string>
<string name="error_duration_time_high">Poll duration time too high!</string>
<string name="error_poll_option_missing">poll option can not be empty!</string>
<string name="error_empty_status">Empty status!</string>
<string name="error_dm">enter username or message!</string>
<string name="error_not_found">not found!</string>
@ -116,6 +118,8 @@
<!-- menu icon strings -->
<string name="menu_status">write status</string>
<string name="menu_hashtag_follow">follow hashtag</string>
<string name="menu_hashtag_unfollow">unfollow hashtag</string>
<string name="menu_open_home_profile">open Profile</string>
<string name="menu_open_twitter_search">Search</string>
<string name="menu_open_settings">Settings</string>