some cleaning

NTFY_avoid_429
Thomas 11 months ago
parent e6b34dd622
commit 0d949f8dd6

@ -44,6 +44,7 @@ import android.view.WindowManager;
import android.widget.LinearLayout;
import android.widget.Toast;
import androidx.activity.OnBackPressedCallback;
import androidx.annotation.NonNull;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AlertDialog;
@ -158,31 +159,21 @@ public class ComposeActivity extends BaseActivity implements ComposeAdapter.Mana
private String editMessageId;
private static int visibilityToNumber(String visibility) {
switch (visibility) {
case "public":
return 3;
case "unlisted":
return 2;
case "private":
return 1;
case "direct":
return 0;
}
return 3;
return switch (visibility) {
case "unlisted" -> 2;
case "private" -> 1;
case "direct" -> 0;
default -> 3;
};
}
private static String visibilityToString(int visibility) {
switch (visibility) {
case 3:
return "public";
case 2:
return "unlisted";
case 1:
return "private";
case 0:
return "direct";
}
return "public";
return switch (visibility) {
case 2 -> "unlisted";
case 1 -> "private";
case 0 -> "direct";
default -> "public";
};
}
public static String getVisibility(BaseAccount account, String defaultVisibility) {
@ -208,13 +199,6 @@ public class ComposeActivity extends BaseActivity implements ComposeAdapter.Mana
}
@Override
public void onBackPressed() {
if (binding.recyclerView.getVisibility() == View.VISIBLE) {
storeDraftWarning();
}
super.onBackPressed();
}
private void storeDraftWarning() {
if (statusDraft == null) {
@ -778,6 +762,15 @@ public class ComposeActivity extends BaseActivity implements ComposeAdapter.Mana
composeAdapter.addSharing(null, null, sharedDescription, null, sharedContent, null);
}
}
getOnBackPressedDispatcher().addCallback(new OnBackPressedCallback(true) {
@Override
public void handleOnBackPressed() {
if (binding.recyclerView.getVisibility() == View.VISIBLE) {
storeDraftWarning();
}
}
});
}
@Override
@ -1032,7 +1025,7 @@ public class ComposeActivity extends BaseActivity implements ComposeAdapter.Mana
.into(binding.mediaPreview);
if (attachment.description != null) {
binding.mediaDescription.setText(attachment.description);
binding.mediaDescription.setSelection(binding.mediaDescription.getText().length());
binding.mediaDescription.setSelection(Objects.requireNonNull(binding.mediaDescription.getText()).length());
}
binding.mediaDescription.setFilters(new InputFilter[]{new InputFilter.LengthFilter(1500)});
binding.mediaDescription.requestFocus();
@ -1043,13 +1036,13 @@ public class ComposeActivity extends BaseActivity implements ComposeAdapter.Mana
binding.description.setVisibility(View.GONE);
actionBar.show();
binding.recyclerView.setVisibility(View.VISIBLE);
composeAdapter.openDescriptionActivity(true, binding.mediaDescription.getText().toString().trim(), holder, attachment, messagePosition, mediaPosition);
composeAdapter.openDescriptionActivity(true, Objects.requireNonNull(binding.mediaDescription.getText()).toString().trim(), holder, attachment, messagePosition, mediaPosition);
});
binding.mediaCancel.setOnClickListener(v -> {
binding.description.setVisibility(View.GONE);
actionBar.show();
binding.recyclerView.setVisibility(View.VISIBLE);
composeAdapter.openDescriptionActivity(false, binding.mediaDescription.getText().toString().trim(), holder, attachment, messagePosition, mediaPosition);
composeAdapter.openDescriptionActivity(false, Objects.requireNonNull(binding.mediaDescription.getText()).toString().trim(), holder, attachment, messagePosition, mediaPosition);
});
}

@ -28,6 +28,7 @@ import android.widget.Toast;
import androidx.preference.PreferenceManager;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import app.fedilab.android.R;
@ -126,7 +127,7 @@ public class CustomSharingActivity extends BaseBarActivity implements OnCustomSh
binding.setCustomSharingSave.setOnClickListener(v -> {
// obtain title, description, keywords
title = binding.setCustomSharingTitle.getText().toString();
keywords = binding.setCustomSharingKeywords.getText().toString();
keywords = Objects.requireNonNull(binding.setCustomSharingKeywords.getText()).toString();
CharSequence comma_only = ",";
CharSequence space_only = " ";
CharSequence double_space = " ";
@ -194,38 +195,38 @@ public class CustomSharingActivity extends BaseBarActivity implements OnCustomSh
String param_value = uri.getQueryParameter(param_name);
if (param_value != null)
switch (param_value) {
case "${url}":
case "${url}" -> {
paramFound = true;
builder.appendQueryParameter(param_name, bundle_url);
break;
case "${title}":
}
case "${title}" -> {
paramFound = true;
builder.appendQueryParameter(param_name, title);
break;
case "${source}":
}
case "${source}" -> {
paramFound = true;
builder.appendQueryParameter(param_name, bundle_source);
break;
case "${id}":
}
case "${id}" -> {
paramFound = true;
builder.appendQueryParameter(param_name, bundle_id);
break;
case "${description}":
}
case "${description}" -> {
paramFound = true;
builder.appendQueryParameter(param_name, bundle_content);
break;
case "${keywords}":
}
case "${keywords}" -> {
paramFound = true;
builder.appendQueryParameter(param_name, keywords);
break;
case "${creator}":
}
case "${creator}" -> {
paramFound = true;
builder.appendQueryParameter(param_name, bundle_creator);
break;
case "${thumbnailurl}":
}
case "${thumbnailurl}" -> {
paramFound = true;
builder.appendQueryParameter(param_name, bundle_thumbnailurl);
break;
}
}
if (!paramFound) {
builder.appendQueryParameter(param_name, param_value);

@ -41,6 +41,7 @@ import com.google.android.material.textfield.TextInputEditText;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Locale;
import java.util.Objects;
import app.fedilab.android.BaseMainActivity;
import app.fedilab.android.BuildConfig;
@ -115,18 +116,10 @@ public class EditProfileActivity extends BaseBarActivity {
if (currentAccount.mastodon_account.source != null) {
binding.sensitive.setChecked(currentAccount.mastodon_account.source.sensitive);
switch (currentAccount.mastodon_account.source.privacy) {
case "public":
binding.visibilityPublic.setChecked(true);
break;
case "unlisted":
binding.visibilityUnlisted.setChecked(true);
break;
case "private":
binding.visibilityPrivate.setChecked(true);
break;
case "direct":
binding.visibilityDirect.setChecked(true);
break;
case "public" -> binding.visibilityPublic.setChecked(true);
case "unlisted" -> binding.visibilityUnlisted.setChecked(true);
case "private" -> binding.visibilityPrivate.setChecked(true);
case "direct" -> binding.visibilityDirect.setChecked(true);
}
} else {
binding.sensitive.setVisibility(View.GONE);
@ -318,8 +311,8 @@ public class EditProfileActivity extends BaseBarActivity {
LinkedHashMap<Integer, Field.FieldParams> fields = new LinkedHashMap<>();
for (int i = 0; i < binding.fieldsContainer.getChildCount(); i++) {
Field.FieldParams field = new Field.FieldParams();
field.name = ((TextInputEditText) binding.fieldsContainer.getChildAt(i).findViewById(R.id.name)).getText().toString().trim();
field.value = ((TextInputEditText) binding.fieldsContainer.getChildAt(i).findViewById(R.id.value)).getText().toString().trim();
field.name = Objects.requireNonNull(((TextInputEditText) binding.fieldsContainer.getChildAt(i).findViewById(R.id.name)).getText()).toString().trim();
field.value = Objects.requireNonNull(((TextInputEditText) binding.fieldsContainer.getChildAt(i).findViewById(R.id.value)).getText()).toString().trim();
fields.put(i, field);
}
return fields;
@ -334,8 +327,8 @@ public class EditProfileActivity extends BaseBarActivity {
accountsVM.updateCredentials(BaseMainActivity.currentInstance, BaseMainActivity.currentToken,
binding.discoverable.isChecked(),
binding.bot.isChecked(),
binding.displayName.getText().toString().trim(),
binding.bio.getText().toString(),
Objects.requireNonNull(binding.displayName.getText()).toString().trim(),
Objects.requireNonNull(binding.bio.getText()).toString(),
binding.locked.isChecked(),
getPrivacy(),
binding.sensitive.isChecked(),

@ -75,27 +75,13 @@ public class FilterActivity extends BaseBarActivity implements FilterAdapter.Del
@Override
public void onItemSelected(AdapterView<?> parent1, View view, int position1, long id) {
switch (position1) {
case 0:
expire[0] = -1;
break;
case 1:
expire[0] = 1800;
break;
case 2:
expire[0] = 3600;
break;
case 3:
expire[0] = 21600;
break;
case 4:
expire[0] = 43200;
break;
case 5:
expire[0] = 86400;
break;
case 6:
expire[0] = 604800;
break;
case 0 -> expire[0] = -1;
case 1 -> expire[0] = 1800;
case 2 -> expire[0] = 3600;
case 3 -> expire[0] = 21600;
case 4 -> expire[0] = 43200;
case 5 -> expire[0] = 86400;
case 6 -> expire[0] = 604800;
}
}
@ -128,21 +114,12 @@ public class FilterActivity extends BaseBarActivity implements FilterAdapter.Del
if (filter.context != null) {
for (String val : filter.context) {
switch (val) {
case "home":
popupAddFilterBinding.contextHome.setChecked(true);
break;
case "public":
popupAddFilterBinding.contextPublic.setChecked(true);
break;
case "notifications":
popupAddFilterBinding.contextNotification.setChecked(true);
break;
case "thread":
popupAddFilterBinding.contextConversation.setChecked(true);
break;
case "account":
popupAddFilterBinding.contextProfiles.setChecked(true);
break;
case "home" -> popupAddFilterBinding.contextHome.setChecked(true);
case "public" -> popupAddFilterBinding.contextPublic.setChecked(true);
case "notifications" ->
popupAddFilterBinding.contextNotification.setChecked(true);
case "thread" -> popupAddFilterBinding.contextConversation.setChecked(true);
case "account" -> popupAddFilterBinding.contextProfiles.setChecked(true);
}
}
}
@ -193,7 +170,7 @@ public class FilterActivity extends BaseBarActivity implements FilterAdapter.Del
canBeSent = false;
}
}
if (popupAddFilterBinding.addTitle.getText().toString().trim().isEmpty()) {
if (Objects.requireNonNull(popupAddFilterBinding.addTitle.getText()).toString().trim().isEmpty()) {
popupAddFilterBinding.addTitle.setError(context.getString(R.string.cannot_be_empty));
canBeSent = false;
}

@ -94,11 +94,8 @@ public class FollowRequestActivity extends BaseActivity {
binding.loadingNextAccounts.setVisibility(View.GONE);
if (accountList != null && accounts != null && accounts.accounts != null && accounts.accounts.size() > 0) {
int startId = 0;
//There are some statuses present in the timeline
if (accountList.size() > 0) {
startId = accountList.size();
}
int startId = accountList.size();
flagLoading = accounts.pagination.max_id == null;
accountList.addAll(accounts.accounts);
max_id = accounts.pagination.max_id;

@ -21,6 +21,7 @@ import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import androidx.activity.OnBackPressedCallback;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import androidx.fragment.app.FragmentManager;
@ -82,12 +83,27 @@ public class FollowedTagActivity extends BaseBarActivity implements FollowedTagA
binding.notContent.setVisibility(View.VISIBLE);
}
});
getOnBackPressedDispatcher().addCallback(new OnBackPressedCallback(true) {
@Override
public void handleOnBackPressed() {
if (canGoBack) {
canGoBack = false;
ThemeHelper.slideViewsToRight(binding.fragmentContainer, binding.recyclerView, () -> {
if (fragmentMastodonTimeline != null) {
fragmentMastodonTimeline.onDestroyView();
}
});
setTitle(R.string.followed_tags);
invalidateOptionsMenu();
}
}
});
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == android.R.id.home) {
onBackPressed();
getOnBackPressedDispatcher().onBackPressed();
return true;
} else if (item.getItemId() == R.id.action_unfollow && tag != null) {
AlertDialog.Builder alt_bld = new MaterialAlertDialogBuilder(FollowedTagActivity.this);
@ -170,21 +186,6 @@ public class FollowedTagActivity extends BaseBarActivity implements FollowedTagA
return true;
}
@Override
public void onBackPressed() {
if (canGoBack) {
canGoBack = false;
ThemeHelper.slideViewsToRight(binding.fragmentContainer, binding.recyclerView, () -> {
if (fragmentMastodonTimeline != null) {
fragmentMastodonTimeline.onDestroyView();
}
});
setTitle(R.string.followed_tags);
invalidateOptionsMenu();
} else {
super.onBackPressed();
}
}
@Override
public void click(Tag tag) {

@ -37,6 +37,8 @@ import androidx.preference.PreferenceManager;
import com.bumptech.glide.Glide;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import java.util.Objects;
import app.fedilab.android.BaseMainActivity;
import app.fedilab.android.R;
import app.fedilab.android.activities.MainActivity;
@ -82,7 +84,7 @@ public class InstanceActivity extends DialogFragment {
binding.maxChar.setText(String.valueOf(maxCharCustom));
}
binding.close.setOnClickListener(view -> {
String max_char = binding.maxChar.getText().toString();
String max_char = Objects.requireNonNull(binding.maxChar.getText()).toString();
SharedPreferences.Editor editor = sharedpreferences.edit();
if (!max_char.isEmpty()) {
try {

@ -15,6 +15,7 @@ package app.fedilab.android.mastodon.activities;
* see <http://www.gnu.org/licenses>. */
import android.annotation.SuppressLint;
import android.content.Intent;
import android.os.Bundle;
import android.text.Editable;
@ -25,6 +26,7 @@ import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import androidx.activity.OnBackPressedCallback;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import androidx.fragment.app.FragmentManager;
@ -39,6 +41,7 @@ import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import app.fedilab.android.BaseMainActivity;
import app.fedilab.android.BuildConfig;
@ -127,6 +130,22 @@ public class MastodonListActivity extends BaseBarActivity implements MastodonLis
}
});
});
getOnBackPressedDispatcher().addCallback(new OnBackPressedCallback(true) {
@Override
public void handleOnBackPressed() {
if (canGoBack) {
canGoBack = false;
ThemeHelper.slideViewsToRight(binding.fragmentContainer, binding.recyclerView, () -> {
if (fragmentMastodonTimeline != null) {
fragmentMastodonTimeline.onDestroyView();
}
});
setTitle(R.string.action_lists);
invalidateOptionsMenu();
}
}
});
}
@ -142,10 +161,11 @@ public class MastodonListActivity extends BaseBarActivity implements MastodonLis
invalidateOptionsMenu();
}
@SuppressLint("ClickableViewAccessibility")
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == android.R.id.home) {
onBackPressed();
getOnBackPressedDispatcher().onBackPressed();
return true;
} else if (item.getItemId() == R.id.action_user_mute_home) {
AlertDialog.Builder dialogBuilder = new MaterialAlertDialogBuilder(MastodonListActivity.this);
@ -344,7 +364,7 @@ public class MastodonListActivity extends BaseBarActivity implements MastodonLis
dialogBuilder.setView(popupAddListBinding.getRoot());
popupAddListBinding.addList.setFilters(new InputFilter[]{new InputFilter.LengthFilter(255)});
popupAddListBinding.addList.setText(mastodonList.title);
popupAddListBinding.addList.setSelection(popupAddListBinding.addList.getText().length());
popupAddListBinding.addList.setSelection(Objects.requireNonNull(popupAddListBinding.addList.getText()).length());
dialogBuilder.setPositiveButton(R.string.validate, (dialog, id) -> {
if (popupAddListBinding.addList.getText() != null && popupAddListBinding.addList.getText().toString().trim().length() > 0) {
timelinesVM.updateList(
@ -459,20 +479,4 @@ public class MastodonListActivity extends BaseBarActivity implements MastodonLis
}
return true;
}
@Override
public void onBackPressed() {
if (canGoBack) {
canGoBack = false;
ThemeHelper.slideViewsToRight(binding.fragmentContainer, binding.recyclerView, () -> {
if (fragmentMastodonTimeline != null) {
fragmentMastodonTimeline.onDestroyView();
}
});
setTitle(R.string.action_lists);
invalidateOptionsMenu();
} else {
super.onBackPressed();
}
}
}

@ -17,7 +17,6 @@ package app.fedilab.android.mastodon.activities;
import static app.fedilab.android.BaseMainActivity.currentAccount;
import android.app.DownloadManager;
import android.content.BroadcastReceiver;
import android.content.ClipData;
import android.content.ClipboardManager;
@ -28,7 +27,6 @@ import android.content.SharedPreferences;
import android.content.res.ColorStateList;
import android.graphics.drawable.Animatable;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.os.Bundle;
import android.text.SpannableString;
import android.text.Spanned;
@ -1226,20 +1224,18 @@ public class ProfileActivity extends BaseActivity {
target = account.id;
}
switch (doActionAccount) {
case BLOCK:
accountsVM.block(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, target)
.observe(ProfileActivity.this, relationShip -> {
this.relationship = relationShip;
updateAccount();
});
break;
case UNBLOCK:
accountsVM.unblock(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, target)
.observe(ProfileActivity.this, relationShip -> {
this.relationship = relationShip;
updateAccount();
});
break;
case BLOCK ->
accountsVM.block(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, target)
.observe(ProfileActivity.this, relationShip -> {
this.relationship = relationShip;
updateAccount();
});
case UNBLOCK ->
accountsVM.unblock(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, target)
.observe(ProfileActivity.this, relationShip -> {
this.relationship = relationShip;
updateAccount();
});
}
dialog.dismiss();
});

@ -28,6 +28,7 @@ import androidx.recyclerview.widget.LinearLayoutManager;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import app.fedilab.android.BaseMainActivity;
import app.fedilab.android.R;
@ -291,7 +292,7 @@ public class ReportActivity extends BaseBarActivity {
if (fragment != null) {
statusIds = fragment.getCheckedStatusesId();
}
comment = binding.reportMessage.getText().toString();
comment = Objects.requireNonNull(binding.reportMessage.getText()).toString();
binding.actionButton.setEnabled(false);
accountsVM.report(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, account.id, category, statusIds, ruleIds, comment, forward)
.observe(ReportActivity.this, report -> {

@ -145,11 +145,8 @@ public class StatusInfoActivity extends BaseActivity {
if (!checkRemotely) {
fetchRelationShip(accounts.accounts, position);
}
int startId = 0;
//There are some statuses present in the timeline
if (accountList.size() > 0) {
startId = accountList.size();
}
int startId = accountList.size();
accountList.addAll(accounts.accounts);
max_id = accounts.pagination.max_id;
flagLoading = accounts.pagination.max_id == null;

@ -71,11 +71,9 @@ public class TrendsActivity extends BaseBarActivity {
Fragment fragment;
if (binding.trendsViewpager.getAdapter() != null) {
fragment = (Fragment) binding.trendsViewpager.getAdapter().instantiateItem(binding.trendsViewpager, tab.getPosition());
if (fragment instanceof FragmentMastodonTimeline) {
FragmentMastodonTimeline fragmentMastodonTimeline = ((FragmentMastodonTimeline) fragment);
if (fragment instanceof FragmentMastodonTimeline fragmentMastodonTimeline) {
fragmentMastodonTimeline.scrollToTop();
} else if (fragment instanceof FragmentMastodonTag) {
FragmentMastodonTag fragmentMastodonTag = ((FragmentMastodonTag) fragment);
} else if (fragment instanceof FragmentMastodonTag fragmentMastodonTag) {
fragmentMastodonTag.scrollToTop();
}
}

@ -25,7 +25,7 @@ import java.util.Set;
/**
* Original work from https://stackoverflow.com/a/25873554
* Original work from <a href="https://stackoverflow.com/a/25873554">stackoverflow</a>
*/
public class NetworkStateReceiver extends BroadcastReceiver {

@ -31,18 +31,14 @@ public class ToastMessage extends BroadcastReceiver {
String content = b.getString(Helper.RECEIVE_TOAST_CONTENT, null);
if (type != null && content != null) {
switch (type) {
case Helper.RECEIVE_TOAST_TYPE_ERROR:
Toasty.error(context, content, Toasty.LENGTH_SHORT).show();
break;
case Helper.RECEIVE_TOAST_TYPE_WARNING:
Toasty.warning(context, content, Toasty.LENGTH_SHORT).show();
break;
case Helper.RECEIVE_TOAST_TYPE_INFO:
Toasty.info(context, content, Toasty.LENGTH_SHORT).show();
break;
case Helper.RECEIVE_TOAST_TYPE_SUCCESS:
Toasty.success(context, content, Toasty.LENGTH_SHORT).show();
break;
case Helper.RECEIVE_TOAST_TYPE_ERROR ->
Toasty.error(context, content, Toasty.LENGTH_SHORT).show();
case Helper.RECEIVE_TOAST_TYPE_WARNING ->
Toasty.warning(context, content, Toasty.LENGTH_SHORT).show();
case Helper.RECEIVE_TOAST_TYPE_INFO ->
Toasty.info(context, content, Toasty.LENGTH_SHORT).show();
case Helper.RECEIVE_TOAST_TYPE_SUCCESS ->
Toasty.success(context, content, Toasty.LENGTH_SHORT).show();
}
}
}

@ -14,6 +14,7 @@ package app.fedilab.android.mastodon.ui.fragment.settings;
* You should have received a copy of the GNU General Public License along with Fedilab; if not,
* see <http://www.gnu.org/licenses>. */
import android.annotation.SuppressLint;
import android.content.SharedPreferences;
import android.os.Bundle;
@ -23,6 +24,7 @@ import androidx.preference.PreferenceFragmentCompat;
import androidx.preference.PreferenceManager;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import app.fedilab.android.BaseMainActivity;
@ -37,6 +39,7 @@ public class FragmentComposeSettings extends PreferenceFragmentCompat implements
createPref();
}
@SuppressLint("ApplySharedPref")
private void createPref() {
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(requireActivity());
@ -83,7 +86,7 @@ public class FragmentComposeSettings extends PreferenceFragmentCompat implements
@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
if (key.equalsIgnoreCase(getString(R.string.SET_WATERMARK_TEXT))) {
if (Objects.requireNonNull(key).equalsIgnoreCase(getString(R.string.SET_WATERMARK_TEXT))) {
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putString(getString(R.string.SET_WATERMARK_TEXT) + BaseMainActivity.currentUserID + BaseMainActivity.currentInstance, sharedPreferences.getString(getString(R.string.SET_WATERMARK_TEXT), null));
editor.apply();
@ -94,14 +97,14 @@ public class FragmentComposeSettings extends PreferenceFragmentCompat implements
public void onResume() {
super.onResume();
getPreferenceScreen().getSharedPreferences()
Objects.requireNonNull(getPreferenceScreen().getSharedPreferences())
.registerOnSharedPreferenceChangeListener(this);
}
@Override
public void onPause() {
super.onPause();
getPreferenceScreen().getSharedPreferences()
Objects.requireNonNull(getPreferenceScreen().getSharedPreferences())
.unregisterOnSharedPreferenceChangeListener(this);
}

Loading…
Cancel
Save