bug fix, cleanup

This commit is contained in:
nuclearfog 2023-10-26 20:18:01 +02:00
parent 410ed0d998
commit 34adfca115
No known key found for this signature in database
GPG Key ID: 03488A185C476379
21 changed files with 366 additions and 219 deletions

View File

@ -8,10 +8,9 @@ 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.lists.Domains;
/**
* background executor to load/block domains
* background executor to block/unblock domains
*
* @author nuclearfog
*/
@ -31,23 +30,19 @@ public class DomainAction extends AsyncExecutor<DomainAction.Param, DomainAction
protected Result doInBackground(@NonNull Param param) {
try {
switch (param.mode) {
case Param.MODE_LOAD:
Domains result = connection.getDomainBlocks(param.cursor);
return new Result(Result.MODE_LOAD, param.index, result, param.domain, null);
case Param.MODE_BLOCK:
connection.blockDomain(param.domain);
return new Result(Result.MODE_BLOCK, param.index, null, param.domain, null);
return new Result(Result.MODE_BLOCK, param.domain, null);
case Param.MODE_UNBLOCK:
connection.unblockDomain(param.domain);
return new Result(Result.MODE_UNBLOCK, param.index, null, param.domain, null);
return new Result(Result.MODE_UNBLOCK, param.domain, null);
default:
return null;
}
} catch (ConnectionException exception) {
return new Result(Result.ERROR, param.index, null, param.domain, exception);
return new Result(Result.ERROR, param.domain, exception);
}
}
@ -56,22 +51,15 @@ public class DomainAction extends AsyncExecutor<DomainAction.Param, DomainAction
*/
public static class Param {
public static final int MODE_LOAD = 1;
public static final int MODE_BLOCK = 2;
public static final int MODE_UNBLOCK = 3;
public static final long NO_CURSOR = 0L;
final String domain;
final long cursor;
final int mode;
final int index;
public Param(int mode, int index, long cursor, String domain) {
public Param(int mode, String domain) {
this.mode = mode;
this.cursor = cursor;
this.domain = domain;
this.index = index;
}
}
@ -81,25 +69,19 @@ public class DomainAction extends AsyncExecutor<DomainAction.Param, DomainAction
public static class Result {
public static final int ERROR = -1;
public static final int MODE_LOAD = 4;
public static final int MODE_BLOCK = 5;
public static final int MODE_UNBLOCK = 6;
public final int mode;
public final int index;
@Nullable
public final Domains domains;
@Nullable
public final ConnectionException exception;
@Nullable
public final String domain;
Result(int mode, int index, @Nullable Domains domains, @Nullable String domain, @Nullable ConnectionException exception) {
this.domains = domains;
Result(int mode, @Nullable String domain, @Nullable ConnectionException exception) {
this.domain = domain;
this.exception = exception;
this.mode = mode;
this.index = index;
}
}
}

View File

@ -0,0 +1,73 @@
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.lists.Domains;
/**
* Async loader class to load blocked domains
*
* @author nuclearfog
*/
public class DomainLoader extends AsyncExecutor<DomainLoader.Param, DomainLoader.Result> {
private Connection connection;
/**
*
*/
public DomainLoader(Context context) {
connection = ConnectionManager.getDefaultConnection(context);
}
@Override
protected Result doInBackground(@NonNull Param param) {
try {
Domains domains = connection.getDomainBlocks(param.cursor);
return new Result(domains, param.index, null);
} catch (ConnectionException exception) {
return new Result(null, param.index, exception);
}
}
/**
*
*/
public static class Param {
public static final long NO_CURSOR = 0L;
final long cursor;
final int index;
public Param(long cursor, int index) {
this.cursor = cursor;
this.index = index;
}
}
/**
*
*/
public static class Result {
public final int index;
@Nullable
public final Domains domains;
@Nullable
public final ConnectionException exception;
Result(@Nullable Domains domains, int index, @Nullable ConnectionException exception) {
this.domains = domains;
this.index = index;
this.exception = exception;
}
}
}

View File

@ -10,7 +10,6 @@ import org.nuclearfog.twidda.backend.api.ConnectionException;
import org.nuclearfog.twidda.backend.api.ConnectionManager;
import org.nuclearfog.twidda.backend.helper.ConnectionResult;
import org.nuclearfog.twidda.backend.helper.update.ConnectionUpdate;
import org.nuclearfog.twidda.backend.helper.update.PushUpdate;
import org.nuclearfog.twidda.config.Configuration;
import org.nuclearfog.twidda.config.GlobalSettings;
import org.nuclearfog.twidda.database.AppDatabase;
@ -66,14 +65,9 @@ public class LoginAction extends AsyncExecutor<LoginAction.Param, LoginAction.Re
database.saveLogin(account);
// save instance information
database.saveInstance(instance);
// transfer push configuration
if (settings.pushEnabled()) {
try {
connection.updatePush(new PushUpdate(settings.getWebPush()));
} catch (ConnectionException exception) {
settings.setPushEnabled(false);
}
}
// disable push for new login
settings.setPushEnabled(false);
settings.setWebPush(null);
return new Result(Result.MODE_LOGIN, account, null, null);
default:

View File

@ -24,12 +24,10 @@ public class ErrorUtils {
*
* @param exception connection exception
*/
public static void showErrorMessage(Context context, @Nullable ConnectionException exception) {
if (context != null) {
String errorMessage = getErrorMessage(context, exception);
if (!errorMessage.isEmpty()) {
Toast.makeText(context.getApplicationContext(), errorMessage, Toast.LENGTH_SHORT).show();
}
public static void showErrorMessage(@NonNull Context context, @Nullable ConnectionException exception) {
String errorMessage = getErrorMessage(context, exception);
if (!errorMessage.isEmpty()) {
Toast.makeText(context.getApplicationContext(), errorMessage, Toast.LENGTH_SHORT).show();
}
}

View File

@ -581,25 +581,38 @@ public class GlobalSettings {
/**
* save web push configuration
*
* @param webPush web push information
* @param webPush web push information or null to remove existing configuration
*/
public void setWebPush(WebPush webPush) {
Editor edit = settings.edit();
edit.putLong(PUSH_ID, webPush.getId());
edit.putString(PUSH_SERVER_KEY, webPush.getServerKey());
edit.putString(PUSH_SERVER_HOST, webPush.getHost());
edit.putString(PUSH_PUBLIC_KEY, webPush.getPublicKey());
edit.putString(PUSH_PRIVATE_KEY, webPush.getPrivateKey());
edit.putString(PUSH_AUTH_KEY, webPush.getAuthSecret());
edit.putBoolean(PUSH_ALERT_MENTION, webPush.alertMentionEnabled());
edit.putBoolean(PUSH_ALERT_REPOST, webPush.alertRepostEnabled());
edit.putBoolean(PUSH_ALERT_FAVORITE, webPush.alertFavoriteEnabled());
edit.putBoolean(PUSH_ALERT_FOLLOWING, webPush.alertFollowingEnabled());
edit.putBoolean(PUSH_ALERT_REQUEST_FOLLOW, webPush.alertFollowRequestEnabled());
edit.putBoolean(PUSH_ALERT_STATUS_POST, webPush.alertNewStatusEnabled());
edit.putBoolean(PUSH_ALERT_STATUS_EDIT, webPush.alertStatusChangeEnabled());
edit.putBoolean(PUSH_ALERT_POLL, webPush.alertPollEnabled());
edit.apply();
public void setWebPush(@Nullable WebPush webPush) {
if (webPush != null) {
this.webPush = new ConfigPush(webPush);
Editor edit = settings.edit();
edit.putLong(PUSH_ID, webPush.getId());
edit.putString(PUSH_SERVER_KEY, webPush.getServerKey());
edit.putString(PUSH_SERVER_HOST, webPush.getHost());
edit.putString(PUSH_PUBLIC_KEY, webPush.getPublicKey());
edit.putString(PUSH_PRIVATE_KEY, webPush.getPrivateKey());
edit.putString(PUSH_AUTH_KEY, webPush.getAuthSecret());
edit.putBoolean(PUSH_ALERT_MENTION, webPush.alertMentionEnabled());
edit.putBoolean(PUSH_ALERT_REPOST, webPush.alertRepostEnabled());
edit.putBoolean(PUSH_ALERT_FAVORITE, webPush.alertFavoriteEnabled());
edit.putBoolean(PUSH_ALERT_FOLLOWING, webPush.alertFollowingEnabled());
edit.putBoolean(PUSH_ALERT_REQUEST_FOLLOW, webPush.alertFollowRequestEnabled());
edit.putBoolean(PUSH_ALERT_STATUS_POST, webPush.alertNewStatusEnabled());
edit.putBoolean(PUSH_ALERT_STATUS_EDIT, webPush.alertStatusChangeEnabled());
edit.putBoolean(PUSH_ALERT_POLL, webPush.alertPollEnabled());
edit.apply();
} else {
this.webPush.clear();
Editor edit = settings.edit();
edit.remove(PUSH_ID);
edit.remove(PUSH_SERVER_KEY);
edit.remove(PUSH_SERVER_HOST);
edit.remove(PUSH_PUBLIC_KEY);
edit.remove(PUSH_PRIVATE_KEY);
edit.remove(PUSH_AUTH_KEY);
edit.apply();
}
}
/**
@ -1028,15 +1041,7 @@ public class GlobalSettings {
proxyPort = settings.getString(PROXY_PORT, "");
proxyUser = settings.getString(PROXY_USER, "");
proxyPass = settings.getString(PROXY_PASS, "");
// login informations
initLogin();
initWebpush();
}
/**
* initialize login information
*/
private void initLogin() {
// init login information
String oauthToken = settings.getString(OAUTH_TOKEN, "");
String oauthSecret = settings.getString(OAUTH_SECRET, "");
String consumerToken = settings.getString(CONSUMER_TOKEN, "");
@ -1046,12 +1051,7 @@ public class GlobalSettings {
int apiId = settings.getInt(CURRENT_API, 0);
long userId = settings.getLong(CURRENT_ID, 0L);
login = new ConfigAccount(userId, oauthToken, oauthSecret, consumerToken, consumerSecret, bearerToken, hostname, apiId);
}
/**
*
*/
private void initWebpush() {
// init web push information
long pushID = settings.getLong(PUSH_ID, 0L);
String pushServerKey = settings.getString(PUSH_SERVER_KEY, "");
String pushServerHost = settings.getString(PUSH_SERVER_HOST, "");

View File

@ -166,4 +166,16 @@ public class ConfigPush implements WebPush {
WebPush push = (WebPush) obj;
return getId() == push.getId() && getHost().equals(push.getHost());
}
/**
* clear user related information
*/
public void clear() {
id = 0L;
host = "";
serverKey = "";
publicKey = "";
privateKey = "";
authKey = "";
}
}

View File

@ -18,11 +18,11 @@ import org.nuclearfog.twidda.database.DatabaseAdapter.LocationTable;
import org.nuclearfog.twidda.database.DatabaseAdapter.MediaTable;
import org.nuclearfog.twidda.database.DatabaseAdapter.NotificationTable;
import org.nuclearfog.twidda.database.DatabaseAdapter.PollTable;
import org.nuclearfog.twidda.database.DatabaseAdapter.PushTable;
import org.nuclearfog.twidda.database.DatabaseAdapter.StatusRegisterTable;
import org.nuclearfog.twidda.database.DatabaseAdapter.StatusTable;
import org.nuclearfog.twidda.database.DatabaseAdapter.UserRegisterTable;
import org.nuclearfog.twidda.database.DatabaseAdapter.UserTable;
import org.nuclearfog.twidda.database.DatabaseAdapter.PushTable;
import org.nuclearfog.twidda.database.impl.DatabaseAccount;
import org.nuclearfog.twidda.database.impl.DatabaseEmoji;
import org.nuclearfog.twidda.database.impl.DatabaseHashtag;

View File

@ -516,7 +516,7 @@ public class ProfileActivity extends AppCompatActivity implements OnClickListene
// confirmed domain block
else if (type == ConfirmDialog.DOMAIN_BLOCK_ADD) {
String url = Uri.parse(user.getProfileUrl()).getHost();
DomainAction.Param param = new DomainAction.Param(DomainAction.Param.MODE_BLOCK, 0, DomainAction.Param.NO_CURSOR, url);
DomainAction.Param param = new DomainAction.Param(DomainAction.Param.MODE_BLOCK, url);
domainAction.execute(param, domainCallback);
}
}

View File

@ -1,5 +1,7 @@
package org.nuclearfog.twidda.ui.fragments;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
@ -39,6 +41,7 @@ public class AccountFragment extends ListFragment implements OnAccountClickListe
private AccountLoader accountLoader;
private AccountAction accountAction;
private GlobalSettings settings;
private AccountAdapter adapter;
private ConfirmDialog dialog;
@ -81,6 +84,7 @@ public class AccountFragment extends ListFragment implements OnAccountClickListe
@Override
public void onDestroy() {
accountLoader.cancel();
accountAction.cancel();
super.onDestroy();
}
@ -93,10 +97,11 @@ public class AccountFragment extends ListFragment implements OnAccountClickListe
@Override
protected void onReset() {
setRefresh(true);
adapter.clear();
accountLoader = new AccountLoader(requireContext());
accountAction = new AccountAction(requireContext());
load();
setRefresh(true);
}
@ -150,17 +155,24 @@ public class AccountFragment extends ListFragment implements OnAccountClickListe
if (result.mode == AccountAction.Result.REMOVE) {
adapter.removeItem(result.account);
} else if (result.mode == AccountAction.Result.SELECT) {
if (settings.pushEnabled()) {
PushSubscription.subscripe(requireContext());
}
if (result.account.getUser() != null) {
String message = getString(R.string.info_account_selected, result.account.getUser().getScreenname());
Toast.makeText(requireContext(), message, Toast.LENGTH_SHORT).show();
Context context = getContext();
if (context != null) {
if (settings.pushEnabled()) {
PushSubscription.subscripe(context);
}
if (result.account.getUser() != null) {
String message = getString(R.string.info_account_selected, result.account.getUser().getScreenname());
Toast.makeText(context, message, Toast.LENGTH_SHORT).show();
}
}
// set result to the parent activity
Intent intent = new Intent();
intent.putExtra(AccountActivity.RETURN_ACCOUNT, result.account);
requireActivity().setResult(AccountActivity.RETURN_ACCOUNT_CHANGED, intent);
Activity activity = getActivity();
if (activity != null) {
Intent intent = new Intent();
intent.putExtra(AccountActivity.RETURN_ACCOUNT, result.account);
activity.setResult(AccountActivity.RETURN_ACCOUNT_CHANGED, intent);
activity.finish();
}
}
}
}

View File

@ -1,5 +1,6 @@
package org.nuclearfog.twidda.ui.fragments;
import android.content.Context;
import android.os.Bundle;
import android.view.View;
import android.widget.Toast;
@ -10,8 +11,7 @@ import androidx.annotation.Nullable;
import org.nuclearfog.twidda.R;
import org.nuclearfog.twidda.backend.async.AsyncExecutor.AsyncCallback;
import org.nuclearfog.twidda.backend.async.DomainAction;
import org.nuclearfog.twidda.backend.async.DomainAction.Param;
import org.nuclearfog.twidda.backend.async.DomainAction.Result;
import org.nuclearfog.twidda.backend.async.DomainLoader;
import org.nuclearfog.twidda.backend.utils.ErrorUtils;
import org.nuclearfog.twidda.model.lists.Domains;
import org.nuclearfog.twidda.ui.adapter.recyclerview.DomainAdapter;
@ -26,20 +26,26 @@ import java.io.Serializable;
*
* @author nuclearfog
*/
public class DomainFragment extends ListFragment implements OnDomainClickListener, OnConfirmListener, AsyncCallback<Result> {
public class DomainFragment extends ListFragment implements OnDomainClickListener, OnConfirmListener {
private static final String KEY_DATA = "domain-data";
private DomainAction domainAction;
private DomainLoader domainLoader;
private DomainAdapter adapter;
private ConfirmDialog dialog;
private AsyncCallback<DomainLoader.Result> domainLoad = this::onDomainLoaded;
private AsyncCallback<DomainAction.Result> domainResult = this::onDomainResult;
private String selectedDomain = "";
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
domainAction = new DomainAction(requireContext());
domainLoader = new DomainLoader(requireContext());
dialog = new ConfirmDialog(requireActivity(), this);
adapter = new DomainAdapter(this);
setAdapter(adapter);
@ -51,7 +57,7 @@ public class DomainFragment extends ListFragment implements OnDomainClickListene
return;
}
}
load(DomainAdapter.NO_INDEX, Param.NO_CURSOR);
load(DomainAdapter.NO_INDEX, DomainLoader.Param.NO_CURSOR);
setRefresh(true);
}
@ -66,28 +72,30 @@ public class DomainFragment extends ListFragment implements OnDomainClickListene
@Override
public void onDestroy() {
domainAction.cancel();
domainLoader.cancel();
super.onDestroy();
}
@Override
protected void onReload() {
load(DomainAdapter.NO_INDEX, Param.NO_CURSOR);
load(DomainAdapter.NO_INDEX, DomainLoader.Param.NO_CURSOR);
}
@Override
protected void onReset() {
adapter.clear();
domainLoader = new DomainLoader(requireContext());
domainAction = new DomainAction(requireContext());
load(DomainAdapter.NO_INDEX, Param.NO_CURSOR);
load(DomainAdapter.NO_INDEX, DomainLoader.Param.NO_CURSOR);
setRefresh(true);
}
@Override
public void onDomainRemove(String domain) {
if (!isRefreshing() && !dialog.isShowing()) {
if (!isRefreshing() && domainAction.isIdle() && !dialog.isShowing() && domainAction.isIdle()) {
dialog.show(ConfirmDialog.DOMAIN_BLOCK_REMOVE);
selectedDomain = domain;
}
@ -96,7 +104,7 @@ public class DomainFragment extends ListFragment implements OnDomainClickListene
@Override
public boolean onPlaceholderClick(int index, long cursor) {
if (!isRefreshing()) {
if (!isRefreshing() && domainLoader.isIdle()) {
load(index, cursor);
return true;
}
@ -104,32 +112,11 @@ public class DomainFragment extends ListFragment implements OnDomainClickListene
}
@Override
public void onResult(@NonNull Result result) {
setRefresh(false);
if (result.mode == Result.MODE_LOAD) {
if (result.domains != null) {
adapter.addItems(result.domains, result.index);
}
} else if (result.mode == Result.MODE_UNBLOCK) {
if (result.domain != null) {
adapter.removeItem(result.domain);
Toast.makeText(requireContext(), R.string.info_domain_removed, Toast.LENGTH_SHORT).show();
}
} else if (result.mode == Result.ERROR) {
if (getContext() != null) {
ErrorUtils.showErrorMessage(getContext(), result.exception);
}
adapter.disableLoading();
}
}
@Override
public void onConfirm(int type, boolean remember) {
if (type == ConfirmDialog.DOMAIN_BLOCK_REMOVE) {
Param param = new Param(Param.MODE_UNBLOCK, DomainAdapter.NO_INDEX, Param.NO_CURSOR, selectedDomain);
domainAction.execute(param, this);
DomainAction.Param param = new DomainAction.Param(DomainAction.Param.MODE_UNBLOCK, selectedDomain);
domainAction.execute(param, domainResult);
}
}
@ -140,7 +127,41 @@ public class DomainFragment extends ListFragment implements OnDomainClickListene
* @param cursor cursor used to page through results
*/
private void load(int index, long cursor) {
Param param = new Param(Param.MODE_LOAD, index, cursor, null);
domainAction.execute(param, this);
DomainLoader.Param param = new DomainLoader.Param(cursor, index);
domainLoader.execute(param, domainLoad);
}
/**
*
*/
private void onDomainLoaded(DomainLoader.Result result) {
setRefresh(false);
if (result.domains != null) {
adapter.addItems(result.domains, result.index);
} else {
Context context = getContext();
if (context != null) {
ErrorUtils.showErrorMessage(context, result.exception);
}
}
}
/**
*
*/
private void onDomainResult(DomainAction.Result result) {
if (result.mode == DomainAction.Result.MODE_UNBLOCK) {
Context context = getContext();
if (result.domain != null && context != null) {
adapter.removeItem(result.domain);
Toast.makeText(context, R.string.info_domain_removed, Toast.LENGTH_SHORT).show();
}
} else if (result.mode == DomainAction.Result.ERROR) {
adapter.disableLoading();
Context context = getContext();
if (context != null) {
ErrorUtils.showErrorMessage(context, result.exception);
}
}
}
}

View File

@ -1,5 +1,6 @@
package org.nuclearfog.twidda.ui.fragments;
import android.content.Context;
import android.os.Bundle;
import android.view.View;
@ -74,7 +75,9 @@ public class EditHistoryFragment extends ListFragment implements AsyncCallback<E
@Override
protected void onReset() {
adapter.clear();
historyLoader = new EditHistoryLoader(requireContext());
historyLoader.execute(id, this);
setRefresh(true);
}
@ -83,7 +86,10 @@ public class EditHistoryFragment extends ListFragment implements AsyncCallback<E
if (result.history != null) {
adapter.setItems(result.history);
} else {
ErrorUtils.showErrorMessage(requireContext(), result.exception);
Context context = getContext();
if (context != null) {
ErrorUtils.showErrorMessage(context, result.exception);
}
}
setRefresh(false);
}

View File

@ -1,5 +1,7 @@
package org.nuclearfog.twidda.ui.fragments;
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.view.View;
@ -69,7 +71,12 @@ public class FieldFragment extends ListFragment implements OnLinkClickListener,
@Override
public void onLinkClick(String url) {
LinkUtils.openLink(requireActivity(), url);
if (!isRefreshing()) {
Activity activity = getActivity();
if (activity != null) {
LinkUtils.openLink(activity, url);
}
}
}
@ -83,9 +90,9 @@ public class FieldFragment extends ListFragment implements OnLinkClickListener,
protected void onReset() {
// reload adapter items
adapter.clear();
setRefresh(true);
userLoader = new UserLoader(requireContext());
load();
setRefresh(true);
}
@ -99,7 +106,10 @@ public class FieldFragment extends ListFragment implements OnLinkClickListener,
adapter.clear();
}
} else if (result.mode == UserLoader.Result.ERROR) {
ErrorUtils.showErrorMessage(requireContext(), result.exception);
Context context = getContext();
if (context != null) {
ErrorUtils.showErrorMessage(context, result.exception);
}
}
setRefresh(false);
}

View File

@ -1,5 +1,6 @@
package org.nuclearfog.twidda.ui.fragments;
import android.content.Context;
import android.os.Bundle;
import android.view.View;
import android.widget.Toast;
@ -81,13 +82,15 @@ public class FilterFragment extends ListFragment implements OnFilterClickListene
@Override
public void onFilterClick(Filter filter) {
filterDialog.show(filter);
if (!isRefreshing()) {
filterDialog.show(filter);
}
}
@Override
public void onFilterRemove(Filter filter) {
if (!confirmDialog.isShowing()) {
if (!isRefreshing() && !confirmDialog.isShowing() && filterAction.isIdle()) {
selection = filter;
confirmDialog.show(ConfirmDialog.FILTER_REMOVE);
}
@ -106,8 +109,9 @@ public class FilterFragment extends ListFragment implements OnFilterClickListene
@Override
public void onFilterUpdated(Filter filter) {
adapter.updateItem(filter);
if (getContext() != null) {
Toast.makeText(requireContext(), R.string.info_filter_updated, Toast.LENGTH_SHORT).show();
Context context = getContext();
if (context != null) {
Toast.makeText(context, R.string.info_filter_updated, Toast.LENGTH_SHORT).show();
}
}
@ -117,8 +121,11 @@ public class FilterFragment extends ListFragment implements OnFilterClickListene
private void onFilterLoaded(StatusFilterLoader.Result result) {
if (result.filters != null) {
adapter.replaceItems(result.filters);
} else if (result.exception != null && getContext() != null) {
ErrorUtils.showErrorMessage(requireContext(), result.exception);
} else if (result.exception != null) {
Context context = getContext();
if (context != null) {
ErrorUtils.showErrorMessage(context, result.exception);
}
}
setRefresh(false);
}
@ -129,12 +136,14 @@ public class FilterFragment extends ListFragment implements OnFilterClickListene
private void onFilterRemoved(StatusFilterAction.Result result) {
if (result.mode == StatusFilterAction.Result.DELETE) {
adapter.removeItem(result.id);
if (getContext() != null) {
Toast.makeText(requireContext(), R.string.info_filter_removed, Toast.LENGTH_SHORT).show();
Context context = getContext();
if (context != null) {
Toast.makeText(context, R.string.info_filter_removed, Toast.LENGTH_SHORT).show();
}
} else if (result.mode == StatusFilterAction.Result.ERROR) {
if (getContext() != null) {
ErrorUtils.showErrorMessage(requireContext(), result.exception);
Context context = getContext();
if (context != null) {
ErrorUtils.showErrorMessage(context, result.exception);
}
}
}

View File

@ -1,5 +1,6 @@
package org.nuclearfog.twidda.ui.fragments;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
@ -84,6 +85,7 @@ public class HashtagFragment extends ListFragment implements OnHashtagClickListe
private HashtagLoader hashtagLoader;
private HashtagAction hashtagAction;
private HashtagAdapter adapter;
private ConfirmDialog confirmDialog;
@ -171,25 +173,27 @@ public class HashtagFragment extends ListFragment implements OnHashtagClickListe
@Override
public void onHashtagClick(Hashtag hashtag, int action) {
if (action == OnHashtagClickListener.SELECT) {
if (!isRefreshing()) {
Intent intent = new Intent(requireContext(), SearchActivity.class);
String name = hashtag.getName();
if (!name.startsWith("#") && !name.startsWith("\"") && !name.endsWith("\"")) {
name = "\"" + name + "\"";
intent.putExtra(SearchActivity.KEY_QUERY, name);
} else {
intent.putExtra(SearchActivity.KEY_DATA, hashtag);
if (!isRefreshing()) {
if (action == OnHashtagClickListener.SELECT) {
if (!isRefreshing()) {
Intent intent = new Intent(requireContext(), SearchActivity.class);
String name = hashtag.getName();
if (!name.startsWith("#") && !name.startsWith("\"") && !name.endsWith("\"")) {
name = "\"" + name + "\"";
intent.putExtra(SearchActivity.KEY_QUERY, name);
} else {
intent.putExtra(SearchActivity.KEY_DATA, hashtag);
}
activityResultLauncher.launch(intent);
}
activityResultLauncher.launch(intent);
}
} else if (action == OnHashtagClickListener.REMOVE) {
if (!confirmDialog.isShowing()) {
selection = hashtag;
if (mode == MODE_FEATURE) {
confirmDialog.show(ConfirmDialog.UNFEATURE_HASHTAG);
} else if (mode == MODE_FOLLOW) {
confirmDialog.show(ConfirmDialog.UNFOLLOW_HASHTAG);
} else if (action == OnHashtagClickListener.REMOVE) {
if (hashtagAction.isIdle() && !confirmDialog.isShowing()) {
selection = hashtag;
if (mode == MODE_FEATURE) {
confirmDialog.show(ConfirmDialog.UNFEATURE_HASHTAG);
} else if (mode == MODE_FOLLOW) {
confirmDialog.show(ConfirmDialog.UNFOLLOW_HASHTAG);
}
}
}
}
@ -198,7 +202,7 @@ public class HashtagFragment extends ListFragment implements OnHashtagClickListe
@Override
public boolean onPlaceholderClick(long cursor, int index) {
if (hashtagLoader.isIdle()) {
if (!isRefreshing() && hashtagLoader.isIdle()) {
load(cursor, index);
return true;
}
@ -223,14 +227,17 @@ public class HashtagFragment extends ListFragment implements OnHashtagClickListe
* callback for {@link HashtagAction}
*/
private void onHashtagActionResult(@NonNull HashtagAction.Result result) {
if (result.mode == HashtagAction.Result.UNFEATURE) {
Toast.makeText(requireContext(), R.string.info_hashtag_unfeatured, Toast.LENGTH_SHORT).show();
adapter.removeItem(result.hashtag);
} else if (result.mode == HashtagAction.Result.UNFOLLOW) {
Toast.makeText(requireContext(), R.string.info_hashtag_unfollowed, Toast.LENGTH_SHORT).show();
adapter.removeItem(result.hashtag);
} else if (result.mode == HashtagAction.Result.ERROR) {
ErrorUtils.showErrorMessage(requireContext(), result.exception);
Context context = getContext();
if (context != null) {
if (result.mode == HashtagAction.Result.UNFEATURE) {
Toast.makeText(context, R.string.info_hashtag_unfeatured, Toast.LENGTH_SHORT).show();
adapter.removeItem(result.hashtag);
} else if (result.mode == HashtagAction.Result.UNFOLLOW) {
Toast.makeText(context, R.string.info_hashtag_unfollowed, Toast.LENGTH_SHORT).show();
adapter.removeItem(result.hashtag);
} else if (result.mode == HashtagAction.Result.ERROR) {
ErrorUtils.showErrorMessage(context, result.exception);
}
}
}
@ -239,8 +246,9 @@ public class HashtagFragment extends ListFragment implements OnHashtagClickListe
*/
private void onHashtagLoaderResult(@NonNull HashtagLoader.Result result) {
if (result.mode == HashtagLoader.Result.ERROR) {
if (getContext() != null) {
ErrorUtils.showErrorMessage(getContext(), result.exception);
Context context = getContext();
if (context != null) {
ErrorUtils.showErrorMessage(context, result.exception);
}
adapter.disableLoading();
} else {

View File

@ -1,5 +1,6 @@
package org.nuclearfog.twidda.ui.fragments;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
@ -126,7 +127,7 @@ public class NotificationFragment extends ListFragment implements OnNotification
break;
case OnNotificationClickListener.NOTIFICATION_DISMISS:
if (!confirmDialog.isShowing()) {
if (!confirmDialog.isShowing() && notificationAction.isIdle()) {
confirmDialog.show(ConfirmDialog.NOTIFICATION_DISMISS);
select = notification;
}
@ -151,7 +152,7 @@ public class NotificationFragment extends ListFragment implements OnNotification
@Override
public boolean onPlaceholderClick(long sinceId, long maxId, int position) {
if (notificationLoader.isIdle()) {
if (!isRefreshing() && notificationLoader.isIdle()) {
load(sinceId, maxId, position);
return true;
}
@ -203,8 +204,9 @@ public class NotificationFragment extends ListFragment implements OnNotification
if (result.notifications != null) {
adapter.addItems(result.notifications, result.position);
} else {
if (getContext() != null) {
ErrorUtils.showErrorMessage(getContext(), result.exception);
Context context = getContext();
if (context != null) {
ErrorUtils.showErrorMessage(context, result.exception);
}
adapter.disableLoading();
}
@ -215,11 +217,14 @@ public class NotificationFragment extends ListFragment implements OnNotification
* used by {@link FollowRequestAction} to accept a follow request
*/
private void onFollowRequestResult(FollowRequestAction.Result result) {
if (result.mode == FollowRequestAction.Result.ACCEPT) {
Toast.makeText(requireContext(), R.string.info_follow_request_accepted, Toast.LENGTH_SHORT).show();
adapter.removeItem(result.notification_id);
} else if (result.mode == FollowRequestAction.Result.ERROR) {
ErrorUtils.showErrorMessage(requireContext(), result.exception);
Context context = getContext();
if (context != null) {
if (result.mode == FollowRequestAction.Result.ACCEPT) {
Toast.makeText(context, R.string.info_follow_request_accepted, Toast.LENGTH_SHORT).show();
adapter.removeItem(result.notification_id);
} else if (result.mode == FollowRequestAction.Result.ERROR) {
ErrorUtils.showErrorMessage(context, result.exception);
}
}
}
@ -230,8 +235,9 @@ public class NotificationFragment extends ListFragment implements OnNotification
if (result.mode == NotificationAction.Result.DISMISS) {
adapter.removeItem(result.id);
} else if (result.mode == NotificationAction.Result.ERROR) {
if (getContext() != null) {
ErrorUtils.showErrorMessage(getContext(), result.exception);
Context context = getContext();
if (context != null) {
ErrorUtils.showErrorMessage(context, result.exception);
}
if (result.exception != null && result.exception.getErrorCode() == ConnectionException.RESOURCE_NOT_FOUND) {
adapter.removeItem(result.id);

View File

@ -1,5 +1,6 @@
package org.nuclearfog.twidda.ui.fragments;
import android.content.Context;
import android.os.Bundle;
import android.view.View;
import android.widget.Toast;
@ -97,15 +98,17 @@ public class ScheduleFragment extends ListFragment implements OnScheduleClickLis
@Override
public void onScheduleClick(ScheduledStatus status, int type) {
if (type == OnScheduleClickListener.SELECT) {
if (!timepicker.isShowing() && scheduleAction.isIdle()) {
selection = status;
timepicker.show(status.getPublishTime());
}
} else if (type == OnScheduleClickListener.REMOVE) {
if (!confirm.isShowing() && scheduleAction.isIdle()) {
selection = status;
confirm.show(ConfirmDialog.SCHEDULE_REMOVE);
if (!isRefreshing()) {
if (type == OnScheduleClickListener.SELECT) {
if (!timepicker.isShowing() && scheduleAction.isIdle()) {
selection = status;
timepicker.show(status.getPublishTime());
}
} else if (type == OnScheduleClickListener.REMOVE) {
if (!confirm.isShowing() && scheduleAction.isIdle()) {
selection = status;
confirm.show(ConfirmDialog.SCHEDULE_REMOVE);
}
}
}
}
@ -113,7 +116,7 @@ public class ScheduleFragment extends ListFragment implements OnScheduleClickLis
@Override
public boolean onPlaceholderClick(long min_id, long max_id, int position) {
if (scheduleLoader.isIdle()) {
if (!isRefreshing() && scheduleLoader.isIdle()) {
load(min_id, max_id, position);
return true;
}
@ -151,7 +154,10 @@ public class ScheduleFragment extends ListFragment implements OnScheduleClickLis
adapter.addItems(result.statuses, result.index);
}
} else {
ErrorUtils.showErrorMessage(requireContext(), result.exception);
Context context = getContext();
if (context != null) {
ErrorUtils.showErrorMessage(context, result.exception);
}
}
setRefresh(false);
}
@ -160,16 +166,19 @@ public class ScheduleFragment extends ListFragment implements OnScheduleClickLis
*
*/
private void onActionResult(ScheduleAction.Result result) {
if (result.mode == ScheduleAction.Result.REMOVE) {
adapter.removeItem(result.id);
Toast.makeText(requireContext(), R.string.info_schedule_removed, Toast.LENGTH_SHORT).show();
} else if (result.mode == ScheduleAction.Result.UPDATE) {
if (result.status != null) {
adapter.updateItem(result.status);
Toast.makeText(requireContext(), R.string.info_schedule_updated, Toast.LENGTH_SHORT).show();
Context context = getContext();
if (context != null) {
if (result.mode == ScheduleAction.Result.REMOVE) {
adapter.removeItem(result.id);
Toast.makeText(context, R.string.info_schedule_removed, Toast.LENGTH_SHORT).show();
} else if (result.mode == ScheduleAction.Result.UPDATE) {
if (result.status != null) {
adapter.updateItem(result.status);
Toast.makeText(context, R.string.info_schedule_updated, Toast.LENGTH_SHORT).show();
}
} else if (result.mode == ScheduleAction.Result.ERROR) {
ErrorUtils.showErrorMessage(context, result.exception);
}
} else if (result.mode == ScheduleAction.Result.ERROR) {
ErrorUtils.showErrorMessage(requireContext(), result.exception);
}
}

View File

@ -1,5 +1,6 @@
package org.nuclearfog.twidda.ui.fragments;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
@ -209,7 +210,7 @@ public class StatusFragment extends ListFragment implements StatusSelectListener
@Override
public boolean onPlaceholderClick(long minId, long maxId, int pos) {
if (statusLoader.isIdle()) {
if (!isRefreshing() && statusLoader.isIdle()) {
load(minId, maxId, pos);
return true;
}
@ -226,8 +227,9 @@ public class StatusFragment extends ListFragment implements StatusSelectListener
adapter.addItems(result.statuses, result.position);
}
} else {
if (getContext() != null) {
ErrorUtils.showErrorMessage(getContext(), result.exception);
Context context = getContext();
if (context != null) {
ErrorUtils.showErrorMessage(context, result.exception);
}
adapter.disableLoading();
}

View File

@ -1,5 +1,6 @@
package org.nuclearfog.twidda.ui.fragments;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
@ -198,6 +199,7 @@ public class UserFragment extends ListFragment implements UserClickListener, OnC
@Override
public void onDestroy() {
userLoader.cancel();
userlistManager.cancel();
super.onDestroy();
}
@ -243,7 +245,7 @@ public class UserFragment extends ListFragment implements UserClickListener, OnC
@Override
public boolean onPlaceholderClick(long cursor, int index) {
if (userLoader.isIdle()) {
if (!isRefreshing() && userLoader.isIdle()) {
load(cursor, index);
return true;
}
@ -253,7 +255,7 @@ public class UserFragment extends ListFragment implements UserClickListener, OnC
@Override
public void onDelete(User user) {
if (!confirmDialog.isShowing()) {
if (userlistManager.isIdle() && !confirmDialog.isShowing()) {
confirmDialog.show(ConfirmDialog.LIST_REMOVE_USER);
this.selectedUser = user;
}
@ -265,8 +267,9 @@ public class UserFragment extends ListFragment implements UserClickListener, OnC
if (result.users != null) {
adapter.addItems(result.users, result.index);
} else {
if (getContext() != null) {
ErrorUtils.showErrorMessage(getContext(), result.exception);
Context context = getContext();
if (context != null) {
ErrorUtils.showErrorMessage(context, result.exception);
}
adapter.disableLoading();
}
@ -278,7 +281,7 @@ public class UserFragment extends ListFragment implements UserClickListener, OnC
public void onConfirm(int type, boolean remember) {
// remove user from list
if (type == ConfirmDialog.LIST_REMOVE_USER) {
if (userlistManager.isIdle() && selectedUser != null) {
if (selectedUser != null) {
UserlistManager.Param param = new UserlistManager.Param(UserlistManager.Param.REMOVE, id, selectedUser.getScreenname());
userlistManager.execute(param, userlistUpdate);
}
@ -290,9 +293,10 @@ public class UserFragment extends ListFragment implements UserClickListener, OnC
*/
private void updateUsers(UserlistManager.Result result) {
if (result.mode == UserlistManager.Result.DEL_USER) {
if (selectedUser != null) {
Context context = getContext();
if (selectedUser != null && context != null) {
String info = getString(R.string.info_user_removed, selectedUser.getScreenname());
Toast.makeText(requireContext(), info, Toast.LENGTH_SHORT).show();
Toast.makeText(context, info, Toast.LENGTH_SHORT).show();
adapter.removeItem(selectedUser);
}
}

View File

@ -1,5 +1,6 @@
package org.nuclearfog.twidda.ui.fragments;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
@ -147,15 +148,17 @@ public class UserListFragment extends ListFragment implements ListClickListener,
@Override
public void onListClick(UserList listItem) {
Intent listIntent = new Intent(requireContext(), UserlistActivity.class);
listIntent.putExtra(UserlistActivity.KEY_DATA, listItem);
activityResultLauncher.launch(listIntent);
if (!isRefreshing()) {
Intent listIntent = new Intent(requireContext(), UserlistActivity.class);
listIntent.putExtra(UserlistActivity.KEY_DATA, listItem);
activityResultLauncher.launch(listIntent);
}
}
@Override
public boolean onPlaceholderClick(long cursor, int index) {
if (userlistLoader.isIdle()) {
if (!isRefreshing() && userlistLoader.isIdle()) {
load(cursor, index);
return true;
}
@ -174,8 +177,9 @@ public class UserListFragment extends ListFragment implements ListClickListener,
break;
case UserlistLoader.Result.ERROR:
if (getContext() != null) {
ErrorUtils.showErrorMessage(getContext(), result.exception);
Context context = getContext();
if (context != null) {
ErrorUtils.showErrorMessage(context, result.exception);
}
adapter.disableLoading();
break;
@ -187,19 +191,16 @@ public class UserListFragment extends ListFragment implements ListClickListener,
* load content into the list
*/
private void load(long cursor, int index) {
UserlistLoader.Param param;
switch (type) {
case MODE_OWNERSHIP:
param = new UserlistLoader.Param(UserlistLoader.Param.OWNERSHIP, index, id, cursor);
UserlistLoader.Param param = new UserlistLoader.Param(UserlistLoader.Param.OWNERSHIP, index, id, cursor);
userlistLoader.execute(param, this);
break;
case MODE_MEMBERSHIP:
param = new UserlistLoader.Param(UserlistLoader.Param.MEMBERSHIP, index, id, cursor);
userlistLoader.execute(param, this);
break;
default:
return;
}
userlistLoader.execute(param, this);
}
}

View File

@ -16,9 +16,9 @@
</string-array>
<string-array name="push_policy">
<item>erlaube alle Nachrichten</item>
<item>nur Nachrichten von gefolgten Nutzern</item>
<item>nur Nachrichten von Followern</item>
<item>alle Nachrichten erlauben</item>
<item>nur Nachrichten von Followings erlauben</item>
<item>nur Nachrichten von Followern erlauben</item>
</string-array>
<string-array name="scales">

View File

@ -84,9 +84,9 @@
</string-array>
<string-array name="push_policy">
<item>all notifications</item>
<item>notifications from following only</item>
<item>notifications from followers only</item>
<item>allow all notifications</item>
<item>allow notifications from following only</item>
<item>allow notifications from followers only</item>
</string-array>
<string-array name="visibility">