Added option for sharing achievements and a back button in ProfileActivity (#4489)

* UI done

* Share added

* Minor modification

* tests added

* tests added

* tests added

* modified

* modifications

* modification

* Entered if

* Entered if

* 97% coverage

* Separate

* Minor modifications

* Minor modifications
This commit is contained in:
Ayan Sarkar 2021-07-18 05:40:32 +05:30 committed by GitHub
parent 9643d8d0b8
commit 3b7aa0376d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 189 additions and 118 deletions

View file

@ -178,10 +178,14 @@ public class Utils {
public static Bitmap getScreenShot(View view) {
View screenView = view.getRootView();
screenView.setDrawingCacheEnabled(true);
Bitmap bitmap = Bitmap.createBitmap(screenView.getDrawingCache());
Bitmap drawingCache = screenView.getDrawingCache();
if (drawingCache != null) {
Bitmap bitmap = Bitmap.createBitmap(drawingCache);
screenView.setDrawingCacheEnabled(false);
return bitmap;
}
return null;
}
/*
*Copies the content to the clipboard

View file

@ -1,8 +1,20 @@
package fr.free.nrw.commons.profile;
import android.app.AlertDialog;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.appcompat.widget.Toolbar;
import androidx.core.content.FileProvider;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.viewpager.widget.ViewPager;
@ -10,12 +22,18 @@ import butterknife.BindView;
import butterknife.ButterKnife;
import com.google.android.material.tabs.TabLayout;
import fr.free.nrw.commons.R;
import fr.free.nrw.commons.Utils;
import fr.free.nrw.commons.ViewPagerAdapter;
import fr.free.nrw.commons.auth.SessionManager;
import fr.free.nrw.commons.profile.achievements.AchievementsFragment;
import fr.free.nrw.commons.profile.leaderboard.LeaderboardFragment;
import fr.free.nrw.commons.theme.BaseActivity;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.inject.Inject;
/**
* This activity will set two tabs, achievements and
@ -31,6 +49,12 @@ public class ProfileActivity extends BaseActivity {
@BindView(R.id.tab_layout)
TabLayout tabLayout;
@BindView(R.id.toolbar)
Toolbar toolbar;
@Inject
SessionManager sessionManager;
private ViewPagerAdapter viewPagerAdapter;
private AchievementsFragment achievementsFragment;
private LeaderboardFragment leaderboardFragment;
@ -40,7 +64,9 @@ public class ProfileActivity extends BaseActivity {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_profile);
ButterKnife.bind(this);
setTitle(R.string.Profile);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
setTitle(sessionManager.getUserName());
supportFragmentManager = getSupportFragmentManager();
viewPagerAdapter = new ViewPagerAdapter(getSupportFragmentManager());
@ -49,6 +75,16 @@ public class ProfileActivity extends BaseActivity {
setTabs();
}
/**
* Navigate up event
* @return boolean
*/
@Override
public boolean onSupportNavigateUp() {
onBackPressed();
return true;
}
/**
* Creates a way to change current activity to AchievementActivity
* @param context
@ -75,10 +111,84 @@ public class ProfileActivity extends BaseActivity {
viewPagerAdapter.notifyDataSetChanged();
}
@Override
public void onDestroy() {
super.onDestroy();
compositeDisposable.clear();
}
/**
* To inflate menu
* @param menu Menu
* @return boolean
*/
@Override
public boolean onCreateOptionsMenu(final Menu menu) {
final MenuInflater menuInflater = getMenuInflater();
menuInflater.inflate(R.menu.menu_about, menu);
return super.onCreateOptionsMenu(menu);
}
/**
* To receive the id of selected item and handle further logic for that selected item
* @param item MenuItem
* @return boolean
*/
@Override
public boolean onOptionsItemSelected(final MenuItem item) {
// take screenshot in form of bitmap and show it in Alert Dialog
if (item.getItemId() == R.id.share_app_icon) {
final View rootView = getWindow().getDecorView().findViewById(android.R.id.content);
final Bitmap screenShot = Utils.getScreenShot(rootView);
showAlert(screenShot);
return true;
}
return super.onOptionsItemSelected(item);
}
/**
* It displays the alertDialog with Image of screenshot
* @param screenshot screenshot of the present screen
*/
public void showAlert(final Bitmap screenshot) {
final AlertDialog.Builder alert = new AlertDialog.Builder(this);
final LayoutInflater factory = LayoutInflater.from(this);
final View view = factory.inflate(R.layout.image_alert_layout, null);
final ImageView screenShotImage = view.findViewById(R.id.alert_image);
screenShotImage.setImageBitmap(screenshot);
final TextView shareMessage = view.findViewById(R.id.alert_text);
shareMessage.setText(R.string.achievements_share_message);
alert.setView(view);
alert.setPositiveButton(R.string.about_translate_proceed, (dialog, which) -> shareScreen(screenshot));
alert.setNegativeButton(android.R.string.cancel, (dialog, which) -> dialog.cancel());
alert.show();
}
/**
* To take bitmap and store it temporary storage and share it
* @param bitmap bitmap of screenshot
*/
void shareScreen(final Bitmap bitmap) {
try {
final File file = new File(getExternalCacheDir(), "screen.png");
final FileOutputStream fileOutputStream = new FileOutputStream(file);
bitmap.compress(Bitmap.CompressFormat.PNG, 100, fileOutputStream);
fileOutputStream.flush();
fileOutputStream.close();
file.setReadable(true, false);
final Uri fileUri = FileProvider
.getUriForFile(getApplicationContext(),
getPackageName() + ".provider", file);
grantUriPermission(getPackageName(), fileUri, Intent.FLAG_GRANT_READ_URI_PERMISSION);
final Intent intent = new Intent(android.content.Intent.ACTION_SEND);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.putExtra(Intent.EXTRA_STREAM, fileUri);
intent.setType("image/png");
startActivity(Intent.createChooser(intent, getString(R.string.share_image_via)));
} catch (final IOException e) {
e.printStackTrace();
}
}
}

View file

@ -3,14 +3,10 @@ package fr.free.nrw.commons.profile.achievements;
import android.accounts.Account;
import android.app.AlertDialog;
import android.app.AlertDialog.Builder;
import android.content.Intent;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Bundle;
import android.util.DisplayMetrics;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
@ -21,22 +17,11 @@ import android.widget.RelativeLayout;
import android.widget.TextView;
import androidx.appcompat.view.ContextThemeWrapper;
import androidx.constraintlayout.widget.ConstraintLayout;
import androidx.core.content.FileProvider;
import androidx.vectordrawable.graphics.drawable.VectorDrawableCompat;
import com.dinuscxj.progressbar.CircleProgressBar;
import org.apache.commons.lang3.StringUtils;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Objects;
import javax.inject.Inject;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
import com.dinuscxj.progressbar.CircleProgressBar;
import fr.free.nrw.commons.R;
import fr.free.nrw.commons.Utils;
import fr.free.nrw.commons.auth.SessionManager;
@ -46,6 +31,9 @@ import fr.free.nrw.commons.utils.ViewUtil;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.CompositeDisposable;
import io.reactivex.schedulers.Schedulers;
import java.util.Objects;
import javax.inject.Inject;
import org.apache.commons.lang3.StringUtils;
import timber.log.Timber;
/**
@ -174,74 +162,6 @@ public class AchievementsFragment extends CommonsDaggerSupportFragment {
return rootView;
}
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater menuInflater) {
// Inflate the menu; this adds items to the action bar if it is present.
super.onCreateOptionsMenu(menu, menuInflater);
menuInflater.inflate(R.menu.menu_about, menu);
item = menu.getItem(0);
item.setVisible(false);
}
/**
* To receive the id of selected item and handle further logic for that selected item
*/
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
// take screenshot in form of bitmap and show it in Alert Dialog
if (id == R.id.share_app_icon) {
View rootView = getActivity().getWindow().getDecorView().findViewById(android.R.id.content);
Bitmap screenShot = Utils.getScreenShot(rootView);
showAlert(screenShot);
}
return super.onOptionsItemSelected(item);
}
/**
* It displays the alertDialog with Image of screenshot
* @param screenshot
*/
public void showAlert(Bitmap screenshot){
AlertDialog.Builder alertadd = new AlertDialog.Builder(getActivity());
LayoutInflater factory = LayoutInflater.from(getActivity());
final View view = factory.inflate(R.layout.image_alert_layout, null);
ImageView screenShotImage = view.findViewById(R.id.alert_image);
screenShotImage.setImageBitmap(screenshot);
TextView shareMessage = view.findViewById(R.id.alert_text);
shareMessage.setText(R.string.achievements_share_message);
alertadd.setView(view);
alertadd.setPositiveButton(R.string.about_translate_proceed, (dialog, which) -> shareScreen(screenshot));
alertadd.setNegativeButton(android.R.string.cancel, (dialog, which) -> dialog.cancel());
alertadd.show();
}
/**
* To take bitmap and store it temporary storage and share it
* @param bitmap
*/
void shareScreen(Bitmap bitmap) {
try {
File file = new File(getActivity().getExternalCacheDir(), "screen.png");
FileOutputStream fOut = new FileOutputStream(file);
bitmap.compress(Bitmap.CompressFormat.PNG, 100, fOut);
fOut.flush();
fOut.close();
file.setReadable(true, false);
Uri fileUri = FileProvider
.getUriForFile(getActivity().getApplicationContext(), getActivity().getPackageName()+".provider", file);
getActivity().grantUriPermission(getActivity().getPackageName(), fileUri, Intent.FLAG_GRANT_READ_URI_PERMISSION);
final Intent intent = new Intent(android.content.Intent.ACTION_SEND);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.putExtra(Intent.EXTRA_STREAM, fileUri);
intent.setType("image/png");
startActivity(Intent.createChooser(intent, getString(R.string.share_image_via)));
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* To invoke the AlertDialog on clicking info button
*/

View file

@ -1,30 +1,46 @@
package fr.free.nrw.commons.profile
import android.content.Context
import android.graphics.Bitmap
import android.os.Looper
import android.view.Menu
import android.view.MenuItem
import fr.free.nrw.commons.R
import fr.free.nrw.commons.TestCommonsApplication
import org.junit.Assert
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.powermock.api.mockito.PowerMockito
import org.mockito.Mock
import org.mockito.MockitoAnnotations
import org.robolectric.Robolectric
import org.robolectric.RobolectricTestRunner
import org.robolectric.RuntimeEnvironment
import org.robolectric.Shadows
import org.robolectric.annotation.Config
import org.robolectric.fakes.RoboMenu
import org.robolectric.fakes.RoboMenuItem
import java.lang.reflect.Method
@RunWith(RobolectricTestRunner::class)
@Config(sdk = [21], application = TestCommonsApplication::class)
class ProfileActivityTest {
@Mock
private lateinit var activity: ProfileActivity
private lateinit var profileActivity: ProfileActivity
@Mock
private lateinit var mockContext: Context
@Mock
private lateinit var bitmap: Bitmap
@Before
fun setUp() {
MockitoAnnotations.initMocks(this)
activity = Robolectric.buildActivity(ProfileActivity::class.java).create().get()
mockContext = PowerMockito.mock(Context::class.java)
profileActivity = PowerMockito.mock(ProfileActivity::class.java)
mockContext = RuntimeEnvironment.application.applicationContext
}
@Test
@ -41,8 +57,53 @@ class ProfileActivityTest {
@Test
@Throws(Exception::class)
fun testStartYourself() {
ProfileActivity.startYourself(mockContext)
fun testOnCreateOptionsMenu() {
val menu: Menu = RoboMenu(mockContext)
activity.onCreateOptionsMenu(menu)
}
@Test
@Throws(Exception::class)
fun testOnOptionsItemSelected() {
val menuItem: MenuItem = RoboMenuItem(R.menu.menu_about)
Shadows.shadowOf(Looper.getMainLooper()).idle()
activity.onOptionsItemSelected(menuItem)
}
@Test
@Throws(Exception::class)
fun testOnOptionsShareItemSelected() {
val menuItemShare: MenuItem = RoboMenuItem(R.id.share_app_icon)
activity.onOptionsItemSelected(menuItemShare)
}
@Test
@Throws(Exception::class)
fun testStartYourself() {
ProfileActivity.startYourself(activity)
}
@Test
@Throws(Exception::class)
fun testShowAlert() {
Shadows.shadowOf(Looper.getMainLooper()).idle()
activity.showAlert(bitmap)
}
@Test
@Throws(Exception::class)
fun testShareScreen() {
Shadows.shadowOf(Looper.getMainLooper()).idle()
val method: Method = ProfileActivity::class.java.getDeclaredMethod(
"shareScreen", Bitmap::class.java
)
method.isAccessible = true
method.invoke(activity, bitmap)
}
@Test
@Throws(Exception::class)
fun testOnSupportNavigateUp() {
activity.onSupportNavigateUp()
}
}

View file

@ -1,7 +1,6 @@
package fr.free.nrw.commons.profile.achievements
import android.content.Context
import android.graphics.Bitmap
import android.os.Looper
import android.view.MenuItem
import android.widget.ImageView
@ -83,9 +82,6 @@ class AchievementsFragmentUnitTests {
@Mock
private lateinit var imageUploadedText: TextView
@Mock
private lateinit var bitmap: Bitmap
@Mock
private lateinit var progressBar: ProgressBar
@ -143,14 +139,6 @@ class AchievementsFragmentUnitTests {
Assert.assertNotNull(fragment)
}
@Test
@Throws(Exception::class)
fun testShowAlert() {
Shadows.shadowOf(Looper.getMainLooper()).idle()
fragment.showAlert(bitmap)
}
@Test
@Throws(Exception::class)
fun testShowInfoDialog() {
@ -329,16 +317,4 @@ class AchievementsFragmentUnitTests {
method.isAccessible = true
method.invoke(fragment)
}
@Test
@Throws(Exception::class)
fun testShareScreen() {
Shadows.shadowOf(Looper.getMainLooper()).idle()
val method: Method = AchievementsFragment::class.java.getDeclaredMethod(
"shareScreen", Bitmap::class.java
)
method.isAccessible = true
method.invoke(fragment, bitmap)
}
}