Migrated navtab module from Java to Kotlin (#5965)

* Rename .java to .kt

* Migrated navtab module from Java to Kotlin

* Migrated navtab module from Java to Kotlin
This commit is contained in:
Saifuddin Adenwala 2024-11-27 19:28:46 +05:30 committed by GitHub
parent 381f9eca0c
commit 238023056f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
12 changed files with 620 additions and 633 deletions

View file

@ -1,238 +0,0 @@
package fr.free.nrw.commons.navtab;
import android.accounts.Account;
import android.accounts.AccountManager;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import com.google.android.material.bottomsheet.BottomSheetDialogFragment;
import fr.free.nrw.commons.AboutActivity;
import fr.free.nrw.commons.BuildConfig;
import fr.free.nrw.commons.CommonsApplication;
import fr.free.nrw.commons.CommonsApplication.ActivityLogoutListener;
import fr.free.nrw.commons.R;
import fr.free.nrw.commons.WelcomeActivity;
import fr.free.nrw.commons.actions.PageEditClient;
import fr.free.nrw.commons.databinding.FragmentMoreBottomSheetBinding;
import fr.free.nrw.commons.di.ApplicationlessInjection;
import fr.free.nrw.commons.feedback.FeedbackContentCreator;
import fr.free.nrw.commons.feedback.model.Feedback;
import fr.free.nrw.commons.feedback.FeedbackDialog;
import fr.free.nrw.commons.kvstore.BasicKvStore;
import fr.free.nrw.commons.kvstore.JsonKvStore;
import fr.free.nrw.commons.logging.CommonsLogSender;
import fr.free.nrw.commons.profile.ProfileActivity;
import fr.free.nrw.commons.review.ReviewActivity;
import fr.free.nrw.commons.settings.SettingsActivity;
import io.reactivex.Single;
import io.reactivex.SingleSource;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.schedulers.Schedulers;
import java.util.concurrent.Callable;
import javax.inject.Inject;
import javax.inject.Named;
public class MoreBottomSheetFragment extends BottomSheetDialogFragment {
@Inject
CommonsLogSender commonsLogSender;
private TextView moreProfile;
@Inject @Named("default_preferences")
JsonKvStore store;
@Inject
@Named("commons-page-edit")
PageEditClient pageEditClient;
private static final String GITHUB_ISSUES_URL = "https://github.com/commons-app/apps-android-commons/issues";
@Nullable
@Override
public View onCreateView(@NonNull final LayoutInflater inflater,
@Nullable final ViewGroup container, @Nullable final Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
final @NonNull FragmentMoreBottomSheetBinding binding =
FragmentMoreBottomSheetBinding.inflate(inflater, container, false);
moreProfile = binding.moreProfile;
if(store.getBoolean(CommonsApplication.IS_LIMITED_CONNECTION_MODE_ENABLED)){
binding.morePeerReview.setVisibility(View.GONE);
}
binding.moreLogout.setOnClickListener(v -> onLogoutClicked());
binding.moreFeedback.setOnClickListener(v -> onFeedbackClicked());
binding.moreAbout.setOnClickListener(v -> onAboutClicked());
binding.moreTutorial.setOnClickListener(v -> onTutorialClicked());
binding.moreSettings.setOnClickListener(v -> onSettingsClicked());
binding.moreProfile.setOnClickListener(v -> onProfileClicked());
binding.morePeerReview.setOnClickListener(v -> onPeerReviewClicked());
binding.moreFeedbackGithub.setOnClickListener(v -> onFeedbackGithubClicked());
setUserName();
return binding.getRoot();
}
private void onFeedbackGithubClicked() {
final Intent intent;
intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse(GITHUB_ISSUES_URL));
startActivity(intent);
}
@Override
public void onAttach(@NonNull final Context context) {
super.onAttach(context);
ApplicationlessInjection
.getInstance(requireActivity().getApplicationContext())
.getCommonsApplicationComponent()
.inject(this);
}
/**
* Set the username and user achievements level (if available) in navigationHeader.
*/
private void setUserName() {
BasicKvStore store = new BasicKvStore(this.getContext(), getUserName());
String level = store.getString("userAchievementsLevel","0");
if (level.equals("0")) {
moreProfile.setText(getUserName() + " (" + getString(R.string.see_your_achievements) + ")");
}
else {
moreProfile.setText(getUserName() + " (" + getString(R.string.level) + " " + level + ")");
}
}
private String getUserName(){
final AccountManager accountManager = AccountManager.get(getActivity());
final Account[] allAccounts = accountManager.getAccountsByType(BuildConfig.ACCOUNT_TYPE);
if (allAccounts.length != 0) {
return allAccounts[0].name;
}
return "";
}
protected void onLogoutClicked() {
new AlertDialog.Builder(requireActivity())
.setMessage(R.string.logout_verification)
.setCancelable(false)
.setPositiveButton(R.string.yes, (dialog, which) -> {
final CommonsApplication app = (CommonsApplication)
requireContext().getApplicationContext();
app.clearApplicationData(requireContext(), new ActivityLogoutListener(requireActivity(), getContext()));
})
.setNegativeButton(R.string.no, (dialog, which) -> dialog.cancel())
.show();
}
protected void onFeedbackClicked() {
showFeedbackDialog();
}
/**
* Creates and shows a dialog asking feedback from users
*/
private void showFeedbackDialog() {
new FeedbackDialog(getContext(), this::uploadFeedback).show();
}
/**
* uploads feedback data on the server
*/
void uploadFeedback(final Feedback feedback) {
final FeedbackContentCreator feedbackContentCreator = new FeedbackContentCreator(getContext(), feedback);
final Single<Boolean> single =
pageEditClient.createNewSection(
"Commons:Mobile_app/Feedback",
feedbackContentCreator.getSectionTitle(),
feedbackContentCreator.getSectionText(),
"New feedback on version " + feedback.getVersion() + " of the app"
)
.flatMapSingle(Single::just)
.firstOrError();
Single.defer((Callable<SingleSource<Boolean>>) () -> single)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(aBoolean -> {
if (aBoolean) {
Toast.makeText(getContext(), getString(R.string.thanks_feedback), Toast.LENGTH_SHORT)
.show();
} else {
Toast.makeText(getContext(), getString(R.string.error_feedback),
Toast.LENGTH_SHORT).show();
}
});
}
/**
* This method shows the alert dialog when a user wants to send feedback about the app.
*/
private void showAlertDialog() {
new AlertDialog.Builder(requireActivity())
.setMessage(R.string.feedback_sharing_data_alert)
.setCancelable(false)
.setPositiveButton(R.string.ok, (dialog, which) -> sendFeedback())
.show();
}
/**
* This method collects the feedback message and starts the activity with implicit intent
* to available email client.
*/
private void sendFeedback() {
final String technicalInfo = commonsLogSender.getExtraInfo();
final Intent feedbackIntent = new Intent(Intent.ACTION_SENDTO);
feedbackIntent.setType("message/rfc822");
feedbackIntent.setData(Uri.parse("mailto:"));
feedbackIntent.putExtra(Intent.EXTRA_EMAIL,
new String[]{CommonsApplication.FEEDBACK_EMAIL});
feedbackIntent.putExtra(Intent.EXTRA_SUBJECT,
CommonsApplication.FEEDBACK_EMAIL_SUBJECT);
feedbackIntent.putExtra(Intent.EXTRA_TEXT, String.format(
"\n\n%s\n%s", CommonsApplication.FEEDBACK_EMAIL_TEMPLATE_HEADER, technicalInfo));
try {
startActivity(feedbackIntent);
} catch (final ActivityNotFoundException e) {
Toast.makeText(getActivity(), R.string.no_email_client, Toast.LENGTH_SHORT).show();
}
}
protected void onAboutClicked() {
final Intent intent = new Intent(getActivity(), AboutActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT | Intent.FLAG_ACTIVITY_SINGLE_TOP);
requireActivity().startActivity(intent);
}
protected void onTutorialClicked() {
WelcomeActivity.startYourself(getActivity());
}
protected void onSettingsClicked() {
final Intent intent = new Intent(getActivity(), SettingsActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT | Intent.FLAG_ACTIVITY_SINGLE_TOP);
requireActivity().startActivity(intent);
}
protected void onProfileClicked() {
ProfileActivity.startYourself(getActivity(), getUserName(), false);
}
protected void onPeerReviewClicked() {
ReviewActivity.Companion.startYourself(getActivity(), getString(R.string.title_activity_review));
}
}

View file

@ -0,0 +1,242 @@
package fr.free.nrw.commons.navtab
import android.accounts.AccountManager
import android.annotation.SuppressLint
import android.content.ActivityNotFoundException
import android.content.Context
import android.content.Intent
import android.net.Uri
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import android.widget.Toast
import androidx.appcompat.app.AlertDialog
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
import fr.free.nrw.commons.AboutActivity
import fr.free.nrw.commons.BuildConfig
import fr.free.nrw.commons.CommonsApplication
import fr.free.nrw.commons.CommonsApplication.ActivityLogoutListener
import fr.free.nrw.commons.R
import fr.free.nrw.commons.WelcomeActivity
import fr.free.nrw.commons.actions.PageEditClient
import fr.free.nrw.commons.databinding.FragmentMoreBottomSheetBinding
import fr.free.nrw.commons.di.ApplicationlessInjection
import fr.free.nrw.commons.feedback.FeedbackContentCreator
import fr.free.nrw.commons.feedback.FeedbackDialog
import fr.free.nrw.commons.feedback.model.Feedback
import fr.free.nrw.commons.kvstore.BasicKvStore
import fr.free.nrw.commons.kvstore.JsonKvStore
import fr.free.nrw.commons.logging.CommonsLogSender
import fr.free.nrw.commons.profile.ProfileActivity
import fr.free.nrw.commons.review.ReviewActivity
import fr.free.nrw.commons.settings.SettingsActivity
import io.reactivex.Single
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.schedulers.Schedulers
import javax.inject.Inject
import javax.inject.Named
class MoreBottomSheetFragment : BottomSheetDialogFragment() {
@Inject
lateinit var commonsLogSender: CommonsLogSender
@Inject
@field: Named("default_preferences")
lateinit var store: JsonKvStore
@Inject
@field: Named("commons-page-edit")
lateinit var pageEditClient: PageEditClient
companion object {
private const val GITHUB_ISSUES_URL =
"https://github.com/commons-app/apps-android-commons/issues"
}
private var binding: FragmentMoreBottomSheetBinding? = null
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
binding = FragmentMoreBottomSheetBinding.inflate(inflater, container, false)
if (store.getBoolean(CommonsApplication.IS_LIMITED_CONNECTION_MODE_ENABLED)) {
binding?.morePeerReview?.visibility = View.GONE
}
binding?.apply {
moreLogout.setOnClickListener { onLogoutClicked() }
moreFeedback.setOnClickListener { onFeedbackClicked() }
moreAbout.setOnClickListener { onAboutClicked() }
moreTutorial.setOnClickListener { onTutorialClicked() }
moreSettings.setOnClickListener { onSettingsClicked() }
moreProfile.setOnClickListener { onProfileClicked() }
morePeerReview.setOnClickListener { onPeerReviewClicked() }
moreFeedbackGithub.setOnClickListener { onFeedbackGithubClicked() }
}
setUserName()
return binding?.root
}
private fun onFeedbackGithubClicked() {
val intent = Intent(Intent.ACTION_VIEW).apply {
data = Uri.parse(GITHUB_ISSUES_URL)
}
startActivity(intent)
}
override fun onAttach(context: Context) {
super.onAttach(context)
ApplicationlessInjection
.getInstance(requireActivity().applicationContext)
.commonsApplicationComponent
.inject(this)
}
override fun onDestroyView() {
super.onDestroyView()
binding = null
}
/**
* Set the username and user achievements level (if available) in navigationHeader.
*/
private fun setUserName() {
val store = BasicKvStore(requireContext(), getUserName())
val level = store.getString("userAchievementsLevel", "0")
binding?.moreProfile?.text = if (level == "0") {
"${getUserName()} (${getString(R.string.see_your_achievements)})"
} else {
"${getUserName()} (${getString(R.string.level)} $level)"
}
}
private fun getUserName(): String {
val accountManager = AccountManager.get(requireActivity())
val allAccounts = accountManager.getAccountsByType(BuildConfig.ACCOUNT_TYPE)
return if (allAccounts.isNotEmpty()) {
allAccounts[0].name
} else {
""
}
}
fun onLogoutClicked() {
AlertDialog.Builder(requireActivity())
.setMessage(R.string.logout_verification)
.setCancelable(false)
.setPositiveButton(R.string.yes) { _, _ ->
val app = requireContext().applicationContext as CommonsApplication
app.clearApplicationData(requireContext(), ActivityLogoutListener(requireActivity(), requireContext()))
}
.setNegativeButton(R.string.no) { dialog, _ -> dialog.cancel() }
.show()
}
fun onFeedbackClicked() {
showFeedbackDialog()
}
/**
* Creates and shows a dialog asking feedback from users
*/
private fun showFeedbackDialog() {
FeedbackDialog(requireContext()) { uploadFeedback(it) }.show()
}
/**
* Uploads feedback data on the server
*/
@SuppressLint("CheckResult")
fun uploadFeedback(feedback: Feedback) {
val feedbackContentCreator = FeedbackContentCreator(requireContext(), feedback)
val single = pageEditClient.createNewSection(
"Commons:Mobile_app/Feedback",
feedbackContentCreator.sectionTitle,
feedbackContentCreator.sectionText,
"New feedback on version ${feedback.version} of the app"
)
.flatMapSingle { Single.just(it) }
.firstOrError()
Single.defer { single }
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe { success ->
val messageResId = if (success) {
R.string.thanks_feedback
} else {
R.string.error_feedback
}
Toast.makeText(requireContext(), getString(messageResId), Toast.LENGTH_SHORT).show()
}
}
/**
* This method shows the alert dialog when a user wants to send feedback about the app.
*/
private fun showAlertDialog() {
AlertDialog.Builder(requireActivity())
.setMessage(R.string.feedback_sharing_data_alert)
.setCancelable(false)
.setPositiveButton(R.string.ok) { _, _ -> sendFeedback() }
.show()
}
/**
* This method collects the feedback message and starts the activity with implicit intent
* to the available email client.
*/
@SuppressLint("IntentReset")
private fun sendFeedback() {
val technicalInfo = commonsLogSender.getExtraInfo()
val feedbackIntent = Intent(Intent.ACTION_SENDTO).apply {
type = "message/rfc822"
data = Uri.parse("mailto:")
putExtra(Intent.EXTRA_EMAIL, arrayOf(CommonsApplication.FEEDBACK_EMAIL))
putExtra(Intent.EXTRA_SUBJECT, CommonsApplication.FEEDBACK_EMAIL_SUBJECT)
putExtra(Intent.EXTRA_TEXT, "\n\n${CommonsApplication.FEEDBACK_EMAIL_TEMPLATE_HEADER}\n$technicalInfo")
}
try {
startActivity(feedbackIntent)
} catch (e: ActivityNotFoundException) {
Toast.makeText(activity, R.string.no_email_client, Toast.LENGTH_SHORT).show()
}
}
fun onAboutClicked() {
val intent = Intent(activity, AboutActivity::class.java).apply {
addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT or Intent.FLAG_ACTIVITY_SINGLE_TOP)
}
requireActivity().startActivity(intent)
}
fun onTutorialClicked() {
WelcomeActivity.startYourself(requireActivity())
}
fun onSettingsClicked() {
val intent = Intent(activity, SettingsActivity::class.java).apply {
addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT or Intent.FLAG_ACTIVITY_SINGLE_TOP)
}
requireActivity().startActivity(intent)
}
fun onProfileClicked() {
ProfileActivity.startYourself(requireActivity(), getUserName(), false)
}
fun onPeerReviewClicked() {
ReviewActivity.startYourself(requireActivity(), getString(R.string.title_activity_review))
}
}

View file

@ -1,142 +0,0 @@
package fr.free.nrw.commons.navtab;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import com.google.android.material.bottomsheet.BottomSheetDialogFragment;
import fr.free.nrw.commons.AboutActivity;
import fr.free.nrw.commons.CommonsApplication;
import fr.free.nrw.commons.R;
import fr.free.nrw.commons.auth.LoginActivity;
import fr.free.nrw.commons.databinding.FragmentMoreBottomSheetLoggedOutBinding;
import fr.free.nrw.commons.di.ApplicationlessInjection;
import fr.free.nrw.commons.kvstore.JsonKvStore;
import fr.free.nrw.commons.logging.CommonsLogSender;
import fr.free.nrw.commons.settings.SettingsActivity;
import javax.inject.Inject;
import javax.inject.Named;
import timber.log.Timber;
public class MoreBottomSheetLoggedOutFragment extends BottomSheetDialogFragment {
private FragmentMoreBottomSheetLoggedOutBinding binding;
@Inject
CommonsLogSender commonsLogSender;
@Inject
@Named("default_preferences")
JsonKvStore applicationKvStore;
@Nullable
@Override
public View onCreateView(@NonNull final LayoutInflater inflater,
@Nullable final ViewGroup container, @Nullable final Bundle savedInstanceState) {
binding = FragmentMoreBottomSheetLoggedOutBinding.inflate(inflater, container, false);
return binding.getRoot();
}
@Override
public void onViewCreated(@NonNull final View view, @Nullable final Bundle savedInstanceState) {
binding.moreLogin.setOnClickListener(v -> onLogoutClicked());
binding.moreFeedback.setOnClickListener(v -> onFeedbackClicked());
binding.moreAbout.setOnClickListener(v -> onAboutClicked());
binding.moreSettings.setOnClickListener(v -> onSettingsClicked());
}
@Override
public void onDestroyView() {
super.onDestroyView();
binding = null;
}
@Override
public void onAttach(@NonNull final Context context) {
super.onAttach(context);
ApplicationlessInjection
.getInstance(requireActivity().getApplicationContext())
.getCommonsApplicationComponent()
.inject(this);
}
public void onLogoutClicked() {
applicationKvStore.putBoolean("login_skipped", false);
final Intent intent = new Intent(getContext(), LoginActivity.class);
requireActivity().finish(); //Kill the activity from which you will go to next activity
startActivity(intent);
}
public void onFeedbackClicked() {
showAlertDialog();
}
/**
* This method shows the alert dialog when a user wants to send feedback about the app.
*/
private void showAlertDialog() {
new AlertDialog.Builder(requireActivity())
.setMessage(R.string.feedback_sharing_data_alert)
.setCancelable(false)
.setPositiveButton(R.string.ok, (dialog, which) -> {
sendFeedback();
})
.show();
}
/**
* This method collects the feedback message and starts and activity with implicit intent to
* available email client.
*/
private void sendFeedback() {
final String technicalInfo = commonsLogSender.getExtraInfo();
final Intent feedbackIntent = new Intent(Intent.ACTION_SENDTO);
feedbackIntent.setType("message/rfc822");
feedbackIntent.setData(Uri.parse("mailto:"));
feedbackIntent.putExtra(Intent.EXTRA_EMAIL,
new String[]{CommonsApplication.FEEDBACK_EMAIL});
feedbackIntent.putExtra(Intent.EXTRA_SUBJECT,
CommonsApplication.FEEDBACK_EMAIL_SUBJECT);
feedbackIntent.putExtra(Intent.EXTRA_TEXT, String.format(
"\n\n%s\n%s", CommonsApplication.FEEDBACK_EMAIL_TEMPLATE_HEADER, technicalInfo));
try {
startActivity(feedbackIntent);
} catch (final ActivityNotFoundException e) {
Toast.makeText(getActivity(), R.string.no_email_client, Toast.LENGTH_SHORT).show();
}
}
public void onAboutClicked() {
final Intent intent = new Intent(getActivity(), AboutActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT | Intent.FLAG_ACTIVITY_SINGLE_TOP);
requireActivity().startActivity(intent);
}
public void onSettingsClicked() {
final Intent intent = new Intent(getActivity(), SettingsActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT | Intent.FLAG_ACTIVITY_SINGLE_TOP);
requireActivity().startActivity(intent);
}
private class BaseLogoutListener implements CommonsApplication.LogoutListener {
@Override
public void onLogoutComplete() {
Timber.d("Logout complete callback received.");
final Intent nearbyIntent = new Intent(
getContext(), LoginActivity.class);
nearbyIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
nearbyIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(nearbyIntent);
requireActivity().finish();
}
}
}

View file

@ -0,0 +1,151 @@
package fr.free.nrw.commons.navtab
import android.annotation.SuppressLint
import android.content.ActivityNotFoundException
import android.content.Context
import android.content.Intent
import android.net.Uri
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import androidx.appcompat.app.AlertDialog
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
import fr.free.nrw.commons.AboutActivity
import fr.free.nrw.commons.CommonsApplication
import fr.free.nrw.commons.R
import fr.free.nrw.commons.auth.LoginActivity
import fr.free.nrw.commons.databinding.FragmentMoreBottomSheetLoggedOutBinding
import fr.free.nrw.commons.di.ApplicationlessInjection
import fr.free.nrw.commons.kvstore.JsonKvStore
import fr.free.nrw.commons.logging.CommonsLogSender
import fr.free.nrw.commons.settings.SettingsActivity
import javax.inject.Inject
import javax.inject.Named
import timber.log.Timber
class MoreBottomSheetLoggedOutFragment : BottomSheetDialogFragment() {
private var binding: FragmentMoreBottomSheetLoggedOutBinding? = null
@Inject
lateinit var commonsLogSender: CommonsLogSender
@Inject
@field: Named("default_preferences")
lateinit var applicationKvStore: JsonKvStore
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
binding = FragmentMoreBottomSheetLoggedOutBinding.inflate(
inflater,
container,
false
)
return binding?.root
}
override fun onViewCreated(
view: View,
savedInstanceState: Bundle?
) {
binding?.apply {
moreLogin.setOnClickListener { onLogoutClicked() }
moreFeedback.setOnClickListener { onFeedbackClicked() }
moreAbout.setOnClickListener { onAboutClicked() }
moreSettings.setOnClickListener { onSettingsClicked() }
}
}
override fun onDestroyView() {
super.onDestroyView()
binding = null
}
override fun onAttach(context: Context) {
super.onAttach(context)
ApplicationlessInjection
.getInstance(requireActivity().applicationContext)
.commonsApplicationComponent
.inject(this)
}
fun onLogoutClicked() {
applicationKvStore.putBoolean("login_skipped", false)
val intent = Intent(context, LoginActivity::class.java)
requireActivity().finish() // Kill the activity from which you will go to next activity
startActivity(intent)
}
fun onFeedbackClicked() {
showAlertDialog()
}
/**
* This method shows the alert dialog when a user wants to send feedback about the app.
*/
private fun showAlertDialog() {
AlertDialog.Builder(requireActivity())
.setMessage(R.string.feedback_sharing_data_alert)
.setCancelable(false)
.setPositiveButton(R.string.ok) { _, _ -> sendFeedback() }
.show()
}
/**
* This method collects the feedback message and starts an activity with an implicit intent to
* the available email client.
*/
@SuppressLint("IntentReset")
private fun sendFeedback() {
val technicalInfo = commonsLogSender.getExtraInfo()
val feedbackIntent = Intent(Intent.ACTION_SENDTO).apply {
type = "message/rfc822"
data = Uri.parse("mailto:")
putExtra(Intent.EXTRA_EMAIL, arrayOf(CommonsApplication.FEEDBACK_EMAIL))
putExtra(Intent.EXTRA_SUBJECT, CommonsApplication.FEEDBACK_EMAIL_SUBJECT)
putExtra(
Intent.EXTRA_TEXT,
"\n\n${CommonsApplication.FEEDBACK_EMAIL_TEMPLATE_HEADER}\n$technicalInfo"
)
}
try {
startActivity(feedbackIntent)
} catch (e: ActivityNotFoundException) {
Toast.makeText(activity, R.string.no_email_client, Toast.LENGTH_SHORT).show()
}
}
fun onAboutClicked() {
val intent = Intent(activity, AboutActivity::class.java).apply {
addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT or Intent.FLAG_ACTIVITY_SINGLE_TOP)
}
requireActivity().startActivity(intent)
}
fun onSettingsClicked() {
val intent = Intent(activity, SettingsActivity::class.java).apply {
addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT or Intent.FLAG_ACTIVITY_SINGLE_TOP)
}
requireActivity().startActivity(intent)
}
private inner class BaseLogoutListener : CommonsApplication.LogoutListener {
override fun onLogoutComplete() {
Timber.d("Logout complete callback received.")
val nearbyIntent = Intent(context, LoginActivity::class.java).apply {
addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK or Intent.FLAG_ACTIVITY_NEW_TASK)
}
startActivity(nearbyIntent)
requireActivity().finish()
}
}
}

View file

@ -1,95 +0,0 @@
package fr.free.nrw.commons.navtab;
import androidx.annotation.DrawableRes;
import androidx.annotation.NonNull;
import androidx.annotation.StringRes;
import androidx.fragment.app.Fragment;
import fr.free.nrw.commons.bookmarks.BookmarkFragment;
import fr.free.nrw.commons.contributions.ContributionsFragment;
import fr.free.nrw.commons.explore.ExploreFragment;
import fr.free.nrw.commons.nearby.fragments.NearbyParentFragment;
import fr.free.nrw.commons.wikidata.model.EnumCode;
import fr.free.nrw.commons.wikidata.model.EnumCodeMap;
import fr.free.nrw.commons.R;
public enum NavTab implements EnumCode {
CONTRIBUTIONS(R.string.contributions_fragment, R.drawable.ic_baseline_person_24) {
@NonNull
@Override
public Fragment newInstance() {
return ContributionsFragment.newInstance();
}
},
NEARBY(R.string.nearby_fragment, R.drawable.ic_location_on_black_24dp) {
@NonNull
@Override
public Fragment newInstance() {
return NearbyParentFragment.newInstance();
}
},
EXPLORE(R.string.navigation_item_explore, R.drawable.ic_globe) {
@NonNull
@Override
public Fragment newInstance() {
return ExploreFragment.newInstance();
}
},
BOOKMARKS(R.string.bookmarks, R.drawable.ic_round_star_border_24px) {
@NonNull
@Override
public Fragment newInstance() {
return BookmarkFragment.newInstance();
}
},
MORE(R.string.more, R.drawable.ic_menu_black_24dp) {
@NonNull
@Override
public Fragment newInstance() {
return null;
}
};
private static final EnumCodeMap<NavTab> MAP = new EnumCodeMap<>(NavTab.class);
@StringRes
private final int text;
@DrawableRes
private final int icon;
@NonNull
public static NavTab of(int code) {
return MAP.get(code);
}
public static int size() {
return MAP.size();
}
@StringRes
public int text() {
return text;
}
@DrawableRes
public int icon() {
return icon;
}
@NonNull
public abstract Fragment newInstance();
@Override
public int code() {
// This enumeration is not marshalled so tying declaration order to presentation order is
// convenient and consistent.
return ordinal();
}
NavTab(@StringRes int text, @DrawableRes int icon) {
this.text = text;
this.icon = icon;
}
}

View file

@ -0,0 +1,79 @@
package fr.free.nrw.commons.navtab
import androidx.annotation.DrawableRes
import androidx.annotation.StringRes
import androidx.fragment.app.Fragment
import fr.free.nrw.commons.bookmarks.BookmarkFragment
import fr.free.nrw.commons.contributions.ContributionsFragment
import fr.free.nrw.commons.explore.ExploreFragment
import fr.free.nrw.commons.nearby.fragments.NearbyParentFragment
import fr.free.nrw.commons.wikidata.model.EnumCode
import fr.free.nrw.commons.wikidata.model.EnumCodeMap
import fr.free.nrw.commons.R
enum class NavTab(
@StringRes private val text: Int,
@DrawableRes private val icon: Int
) : EnumCode {
CONTRIBUTIONS(R.string.contributions_fragment, R.drawable.ic_baseline_person_24) {
override fun newInstance(): Fragment {
return ContributionsFragment.newInstance()
}
},
NEARBY(R.string.nearby_fragment, R.drawable.ic_location_on_black_24dp) {
override fun newInstance(): Fragment {
return NearbyParentFragment.newInstance()
}
},
EXPLORE(R.string.navigation_item_explore, R.drawable.ic_globe) {
override fun newInstance(): Fragment {
return ExploreFragment.newInstance()
}
},
BOOKMARKS(R.string.bookmarks, R.drawable.ic_round_star_border_24px) {
override fun newInstance(): Fragment {
return BookmarkFragment.newInstance()
}
},
MORE(R.string.more, R.drawable.ic_menu_black_24dp) {
override fun newInstance(): Fragment? {
return null
}
};
companion object {
private val MAP: EnumCodeMap<NavTab> = EnumCodeMap(NavTab::class.java)
@JvmStatic
fun of(code: Int): NavTab {
return MAP[code]
}
@JvmStatic
fun size(): Int {
return MAP.size()
}
}
@StringRes
fun text(): Int {
return text
}
@DrawableRes
fun icon(): Int {
return icon
}
abstract fun newInstance(): Fragment?
override fun code(): Int {
// This enumeration is not marshalled so tying declaration order to presentation order is
// convenient and consistent.
return ordinal
}
}

View file

@ -1,38 +0,0 @@
package fr.free.nrw.commons.navtab;
import android.view.ViewGroup;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentPagerAdapter;
public class NavTabFragmentPagerAdapter extends FragmentPagerAdapter {
private Fragment currentFragment;
public NavTabFragmentPagerAdapter(FragmentManager mgr) {
super(mgr);
}
@Nullable
public Fragment getCurrentFragment() {
return currentFragment;
}
@Override
public Fragment getItem(int pos) {
return NavTab.of(pos).newInstance();
}
@Override
public int getCount() {
return NavTab.size();
}
@Override
public void setPrimaryItem(ViewGroup container, int position, Object object) {
currentFragment = ((Fragment) object);
super.setPrimaryItem(container, position, object);
}
}

View file

@ -0,0 +1,36 @@
package fr.free.nrw.commons.navtab
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentManager
import androidx.fragment.app.FragmentPagerAdapter
class NavTabFragmentPagerAdapter(
mgr: FragmentManager
) : FragmentPagerAdapter(mgr, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) {
private var currentFragment: Fragment? = null
fun getCurrentFragment(): Fragment? {
return currentFragment
}
override fun getItem(pos: Int): Fragment {
return NavTab.of(pos).newInstance()!!
}
override fun getCount(): Int {
return NavTab.size()
}
override fun setPrimaryItem(
container: ViewGroup,
position: Int,
`object`: Any
) {
currentFragment = `object` as Fragment
super.setPrimaryItem(container, position, `object`)
}
}

View file

@ -1,41 +0,0 @@
package fr.free.nrw.commons.navtab;
import android.content.Context;
import android.util.AttributeSet;
import android.view.Menu;
import com.google.android.material.bottomnavigation.BottomNavigationView;
import fr.free.nrw.commons.contributions.MainActivity;
public class NavTabLayout extends BottomNavigationView {
public NavTabLayout(Context context) {
super(context);
setTabViews();
}
public NavTabLayout(Context context, AttributeSet attrs) {
super(context, attrs);
setTabViews();
}
public NavTabLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
setTabViews();
}
private void setTabViews() {
if (((MainActivity) getContext()).applicationKvStore.getBoolean("login_skipped") == true) {
for (int i = 0; i < NavTabLoggedOut.size(); i++) {
NavTabLoggedOut navTab = NavTabLoggedOut.of(i);
getMenu().add(Menu.NONE, i, i, navTab.text()).setIcon(navTab.icon());
}
} else {
for (int i = 0; i < NavTab.size(); i++) {
NavTab navTab = NavTab.of(i);
getMenu().add(Menu.NONE, i, i, navTab.text()).setIcon(navTab.icon());
}
}
}
}

View file

@ -0,0 +1,47 @@
package fr.free.nrw.commons.navtab
import android.content.Context
import android.util.AttributeSet
import android.view.Menu
import com.google.android.material.bottomnavigation.BottomNavigationView
import fr.free.nrw.commons.contributions.MainActivity
class NavTabLayout : BottomNavigationView {
constructor(context: Context) : super(context) {
setTabViews()
}
constructor(
context: Context,
attrs: AttributeSet?
) : super(context, attrs) {
setTabViews()
}
constructor(
context: Context,
attrs: AttributeSet?,
defStyleAttr: Int
) : super(context, attrs, defStyleAttr) {
setTabViews()
}
private fun setTabViews() {
val isLoginSkipped = (context as MainActivity)
.applicationKvStore.getBoolean("login_skipped")
if (isLoginSkipped) {
for (i in 0 until NavTabLoggedOut.size()) {
val navTab = NavTabLoggedOut.of(i)
menu.add(Menu.NONE, i, i, navTab.text()).setIcon(navTab.icon())
}
} else {
for (i in 0 until NavTab.size()) {
val navTab = NavTab.of(i)
menu.add(Menu.NONE, i, i, navTab.text()).setIcon(navTab.icon())
}
}
}
}

View file

@ -1,79 +0,0 @@
package fr.free.nrw.commons.navtab;
import androidx.annotation.DrawableRes;
import androidx.annotation.NonNull;
import androidx.annotation.StringRes;
import androidx.fragment.app.Fragment;
import fr.free.nrw.commons.R;
import fr.free.nrw.commons.bookmarks.BookmarkFragment;
import fr.free.nrw.commons.explore.ExploreFragment;
import fr.free.nrw.commons.wikidata.model.EnumCode;
import fr.free.nrw.commons.wikidata.model.EnumCodeMap;
public enum NavTabLoggedOut implements EnumCode {
EXPLORE(R.string.navigation_item_explore, R.drawable.ic_globe) {
@NonNull
@Override
public Fragment newInstance() {
return ExploreFragment.newInstance();
}
},
BOOKMARKS(R.string.bookmarks, R.drawable.ic_round_star_border_24px) {
@NonNull
@Override
public Fragment newInstance() {
return BookmarkFragment.newInstance();
}
},
MORE(R.string.more, R.drawable.ic_menu_black_24dp) {
@NonNull
@Override
public Fragment newInstance() {
return null;
}
};
private static final EnumCodeMap<NavTabLoggedOut> MAP = new EnumCodeMap<>(
NavTabLoggedOut.class);
@StringRes
private final int text;
@DrawableRes
private final int icon;
@NonNull
public static NavTabLoggedOut of(int code) {
return MAP.get(code);
}
public static int size() {
return MAP.size();
}
@StringRes
public int text() {
return text;
}
@DrawableRes
public int icon() {
return icon;
}
@NonNull
public abstract Fragment newInstance();
@Override
public int code() {
// This enumeration is not marshalled so tying declaration order to presentation order is
// convenient and consistent.
return ordinal();
}
NavTabLoggedOut(@StringRes int text, @DrawableRes int icon) {
this.text = text;
this.icon = icon;
}
}

View file

@ -0,0 +1,65 @@
package fr.free.nrw.commons.navtab
import androidx.annotation.DrawableRes
import androidx.annotation.StringRes
import androidx.fragment.app.Fragment
import fr.free.nrw.commons.R
import fr.free.nrw.commons.bookmarks.BookmarkFragment
import fr.free.nrw.commons.explore.ExploreFragment
import fr.free.nrw.commons.wikidata.model.EnumCode
import fr.free.nrw.commons.wikidata.model.EnumCodeMap
enum class NavTabLoggedOut(
@StringRes private val text: Int,
@DrawableRes private val icon: Int
) : EnumCode {
EXPLORE(R.string.navigation_item_explore, R.drawable.ic_globe) {
override fun newInstance(): Fragment {
return ExploreFragment.newInstance()
}
},
BOOKMARKS(R.string.bookmarks, R.drawable.ic_round_star_border_24px) {
override fun newInstance(): Fragment {
return BookmarkFragment.newInstance()
}
},
MORE(R.string.more, R.drawable.ic_menu_black_24dp) {
override fun newInstance(): Fragment? {
return null
}
};
companion object {
private val MAP: EnumCodeMap<NavTabLoggedOut> = EnumCodeMap(NavTabLoggedOut::class.java)
@JvmStatic
fun of(code: Int): NavTabLoggedOut {
return MAP[code]
}
@JvmStatic
fun size(): Int {
return MAP.size()
}
}
@StringRes
fun text(): Int {
return text
}
@DrawableRes
fun icon(): Int {
return icon
}
abstract fun newInstance(): Fragment?
override fun code(): Int {
// This enumeration is not marshalled so tying declaration order to presentation order is
// convenient and consistent.
return ordinal
}
}