mirror of
https://github.com/commons-app/apps-android-commons.git
synced 2025-10-26 20:33:53 +01:00
Initial commit (#2956)
* Initial commit * System Backpress activated * Removed nav drawer * Explore feed ui update * Explore list image ui update * GridView image list ui update
This commit is contained in:
parent
47047e423d
commit
9dd369e8ce
32 changed files with 1361 additions and 450 deletions
|
|
@ -7,7 +7,7 @@ apply from: 'quality.gradle'
|
|||
|
||||
def isRunningOnTravisAndIsNotPRBuild = System.getenv("CI") == "true" && file('../play.p12').exists()
|
||||
|
||||
if(isRunningOnTravisAndIsNotPRBuild) {
|
||||
if (isRunningOnTravisAndIsNotPRBuild) {
|
||||
apply plugin: 'com.github.triplet.play'
|
||||
}
|
||||
|
||||
|
|
@ -139,7 +139,7 @@ android {
|
|||
test.resources.srcDirs += 'src/main/resoures'
|
||||
}
|
||||
|
||||
signingConfigs {
|
||||
signingConfigs {
|
||||
release
|
||||
}
|
||||
|
||||
|
|
@ -148,7 +148,7 @@ android {
|
|||
minifyEnabled true
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
|
||||
testProguardFile 'test-proguard-rules.txt'
|
||||
if(isRunningOnTravisAndIsNotPRBuild) {
|
||||
if (isRunningOnTravisAndIsNotPRBuild) {
|
||||
signingConfig signingConfigs.release
|
||||
}
|
||||
}
|
||||
|
|
@ -160,7 +160,7 @@ android {
|
|||
versionNameSuffix "-debug-" + getBranchName()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (isRunningOnTravisAndIsNotPRBuild) {
|
||||
// configure keystore based on env vars in Travis for automated alpha builds
|
||||
signingConfigs.release.storeFile = file("../nr-commons.keystore")
|
||||
|
|
@ -177,7 +177,7 @@ android {
|
|||
productFlavors {
|
||||
prod {
|
||||
|
||||
applicationId 'fr.free.nrw.commons'
|
||||
applicationId 'fr.free.nrw.commons'
|
||||
|
||||
buildConfigField "String", "WIKIMEDIA_API_POTD", "\"https://commons.wikimedia.org/w/api.php?action=featuredfeed&feed=potd&feedformat=rss&language=en\""
|
||||
buildConfigField "String", "WIKIMEDIA_API_HOST", "\"https://commons.wikimedia.org/w/api.php\""
|
||||
|
|
@ -252,7 +252,7 @@ android {
|
|||
buildToolsVersion buildToolsVersion
|
||||
}
|
||||
|
||||
if(isRunningOnTravisAndIsNotPRBuild) {
|
||||
if (isRunningOnTravisAndIsNotPRBuild) {
|
||||
play {
|
||||
track = "alpha"
|
||||
userFraction = 1
|
||||
|
|
|
|||
|
|
@ -209,7 +209,8 @@ public class BookmarkPicturesFragment extends DaggerFragment {
|
|||
gridAdapter = new GridViewAdapter(
|
||||
this.getContext(),
|
||||
R.layout.layout_category_images,
|
||||
mediaList
|
||||
mediaList,
|
||||
false
|
||||
);
|
||||
gridView.setAdapter(gridAdapter);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,13 +13,14 @@ import android.widget.ProgressBar;
|
|||
import android.widget.RelativeLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
import dagger.android.support.DaggerFragment;
|
||||
|
|
@ -55,12 +56,20 @@ public class CategoryImagesListFragment extends DaggerFragment {
|
|||
private boolean hasMoreImages = true;
|
||||
private boolean isLoading = true;
|
||||
private String categoryName = null;
|
||||
private AdapterView.OnItemClickListener listener;
|
||||
|
||||
@Inject CategoryImageController controller;
|
||||
@Inject
|
||||
@Named("default_preferences")
|
||||
JsonKvStore categoryKvStore;
|
||||
|
||||
|
||||
public CategoryImagesListFragment(){
|
||||
}
|
||||
|
||||
public CategoryImagesListFragment(AdapterView.OnItemClickListener listener){
|
||||
this.listener = listener;
|
||||
}
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
View v = inflater.inflate(R.layout.fragment_category_images, container, false);
|
||||
|
|
@ -71,7 +80,7 @@ public class CategoryImagesListFragment extends DaggerFragment {
|
|||
@Override
|
||||
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
gridView.setOnItemClickListener((AdapterView.OnItemClickListener) getActivity());
|
||||
gridView.setOnItemClickListener(listener==null?((AdapterView.OnItemClickListener) getActivity()):listener);
|
||||
initViews();
|
||||
}
|
||||
|
||||
|
|
@ -169,7 +178,7 @@ public class CategoryImagesListFragment extends DaggerFragment {
|
|||
* @param mediaList List of new Media to be displayed
|
||||
*/
|
||||
private void setAdapter(List<Media> mediaList) {
|
||||
gridAdapter = new GridViewAdapter(this.getContext(), R.layout.layout_category_images, mediaList);
|
||||
gridAdapter = new GridViewAdapter(this.getContext(), R.layout.layout_category_images, mediaList, true);
|
||||
gridView.setAdapter(gridAdapter);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import android.view.LayoutInflater;
|
|||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.facebook.drawee.view.SimpleDraweeView;
|
||||
|
|
@ -23,15 +24,18 @@ import fr.free.nrw.commons.R;
|
|||
|
||||
public class GridViewAdapter extends ArrayAdapter {
|
||||
private List<Media> data;
|
||||
private boolean showSecondaryViews;
|
||||
|
||||
public GridViewAdapter(Context context, int layoutResourceId, List<Media> data) {
|
||||
public GridViewAdapter(Context context, int layoutResourceId, List<Media> data, boolean showSecondaryViews) {
|
||||
super(context, layoutResourceId, data);
|
||||
this.data = data;
|
||||
this.showSecondaryViews = showSecondaryViews;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds more item to the list
|
||||
* Its triggered on scrolling down in the list
|
||||
*
|
||||
* @param images
|
||||
*/
|
||||
public void addItems(List<Media> images) {
|
||||
|
|
@ -45,9 +49,10 @@ public class GridViewAdapter extends ArrayAdapter {
|
|||
/**
|
||||
* Check the first item in the new list with old list and returns true if they are same
|
||||
* Its triggered on successful response of the fetch images API.
|
||||
*
|
||||
* @param images
|
||||
*/
|
||||
public boolean containsAll(List<Media> images){
|
||||
public boolean containsAll(List<Media> images) {
|
||||
if (images == null || images.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
|
@ -70,6 +75,7 @@ public class GridViewAdapter extends ArrayAdapter {
|
|||
|
||||
/**
|
||||
* Sets up the UI for the category image item
|
||||
*
|
||||
* @param position
|
||||
* @param convertView
|
||||
* @param parent
|
||||
|
|
@ -86,14 +92,20 @@ public class GridViewAdapter extends ArrayAdapter {
|
|||
SimpleDraweeView imageView = convertView.findViewById(R.id.categoryImageView);
|
||||
TextView fileName = convertView.findViewById(R.id.categoryImageTitle);
|
||||
TextView author = convertView.findViewById(R.id.categoryImageAuthor);
|
||||
ImageView favoriteImage = convertView.findViewById(R.id.favorite);
|
||||
ImageView downloadImage = convertView.findViewById(R.id.download);
|
||||
favoriteImage.setVisibility(showSecondaryViews ? View.VISIBLE : View.GONE);
|
||||
downloadImage.setVisibility(showSecondaryViews ? View.VISIBLE : View.GONE);
|
||||
fileName.setText(item.getDisplayTitle());
|
||||
setAuthorView(item, author);
|
||||
imageView.setImageURI(item.getThumbUrl());
|
||||
|
||||
return convertView;
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows author information if its present
|
||||
*
|
||||
* @param item
|
||||
* @param author
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -459,7 +459,7 @@ public class ContributionsFragment
|
|||
return;
|
||||
}
|
||||
|
||||
((MainActivity)getActivity()).setNumOfUploads(uploadCount);
|
||||
// ((MainActivity)getActivity()).setNumOfUploads(uploadCount);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,572 @@
|
|||
package fr.free.nrw.commons.contributions;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.AlertDialog;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
import androidx.fragment.app.FragmentPagerAdapter;
|
||||
import androidx.viewpager.widget.ViewPager;
|
||||
|
||||
import com.google.android.material.tabs.TabLayout;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
import fr.free.nrw.commons.R;
|
||||
import fr.free.nrw.commons.auth.SessionManager;
|
||||
import fr.free.nrw.commons.di.CommonsDaggerSupportFragment;
|
||||
import fr.free.nrw.commons.location.LocationServiceManager;
|
||||
import fr.free.nrw.commons.nearby.NearbyFragment;
|
||||
import fr.free.nrw.commons.notification.Notification;
|
||||
import fr.free.nrw.commons.notification.NotificationActivity;
|
||||
import fr.free.nrw.commons.notification.NotificationController;
|
||||
import fr.free.nrw.commons.quiz.QuizChecker;
|
||||
import io.reactivex.Observable;
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
import timber.log.Timber;
|
||||
|
||||
import static fr.free.nrw.commons.location.LocationServiceManager.LOCATION_REQUEST;
|
||||
|
||||
/**
|
||||
* A simple {@link Fragment} subclass.
|
||||
* Activities that contain this fragment must implement the
|
||||
* to handle interaction events.
|
||||
*/
|
||||
public class ContributionsMainFragment extends CommonsDaggerSupportFragment implements FragmentManager.OnBackStackChangedListener {
|
||||
|
||||
|
||||
@Inject
|
||||
SessionManager sessionManager;
|
||||
@Inject
|
||||
ContributionController controller;
|
||||
@BindView(R.id.tab_layout)
|
||||
TabLayout tabLayout;
|
||||
@BindView(R.id.ContPager)
|
||||
public UnswipableViewPager viewPager;
|
||||
@Inject
|
||||
public LocationServiceManager locationManager;
|
||||
@Inject
|
||||
NotificationController notificationController;
|
||||
@Inject
|
||||
QuizChecker quizChecker;
|
||||
|
||||
|
||||
public Intent uploadServiceIntent;
|
||||
public boolean isAuthCookieAcquired = false;
|
||||
|
||||
public ContributionsActivityPagerAdapter contributionsActivityPagerAdapter;
|
||||
public final int CONTRIBUTIONS_TAB_POSITION = 0;
|
||||
public final int NEARBY_TAB_POSITION = 1;
|
||||
|
||||
public boolean isContributionsFragmentVisible = true; // False means nearby fragment is visible
|
||||
private Menu menu;
|
||||
|
||||
private boolean onOrientationChanged = false;
|
||||
|
||||
private MenuItem notificationsMenuItem;
|
||||
private TextView notificationCount;
|
||||
|
||||
public ContributionsMainFragment() {
|
||||
// Required empty public constructor
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public static ContributionsMainFragment newInstance() {
|
||||
ContributionsMainFragment fragment = new ContributionsMainFragment();
|
||||
fragment.setRetainInstance(true);
|
||||
return fragment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
|
||||
/*Todo: after
|
||||
|
||||
requestAuthToken();
|
||||
initDrawer();
|
||||
setTitle(getString(R.string.navigation_item_home)); // Should I create a new string variable with another name instead?
|
||||
|
||||
|
||||
if (savedInstanceState != null) {
|
||||
onOrientationChanged = true; // Will be used in nearby fragment to determine significant update of map
|
||||
|
||||
//If nearby map was visible, call on Tab Selected to call all nearby operations
|
||||
*//*if (savedInstanceState.getInt("viewPagerCurrentItem") == 1) {
|
||||
((NearbyFragment)contributionsActivityPagerAdapter.getItem(1)).onTabSelected(onOrientationChanged);
|
||||
}*//*
|
||||
}
|
||||
|
||||
*/
|
||||
setRetainInstance(true);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
View view = inflater.inflate(R.layout.activity_contributions, container, false);
|
||||
ButterKnife.bind(this, view);
|
||||
addTabsAndFragments();
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
/*//Todo: after might need to go to activity
|
||||
@Override
|
||||
protected void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
outState.putInt("viewPagerCurrentItem", viewPager.getCurrentItem());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onAuthCookieAcquired(String authCookie) {
|
||||
// Do a sync everytime we get here!
|
||||
requestSync(sessionManager.getCurrentAccount(), BuildConfig.CONTRIBUTION_AUTHORITY, new Bundle());
|
||||
uploadServiceIntent = new Intent(requireActivity(), UploadService.class);
|
||||
uploadServiceIntent.setAction(UploadService.ACTION_START_SERVICE);
|
||||
requireActivity().startService(uploadServiceIntent);
|
||||
|
||||
addTabsAndFragments();
|
||||
isAuthCookieAcquired = true;
|
||||
if (contributionsActivityPagerAdapter.getItem(0) != null) {
|
||||
((ContributionsFragment) contributionsActivityPagerAdapter.getItem(0)).onAuthCookieAcquired(uploadServiceIntent);
|
||||
}
|
||||
}*/
|
||||
|
||||
private void addTabsAndFragments() {
|
||||
contributionsActivityPagerAdapter = new ContributionsActivityPagerAdapter(requireActivity().getSupportFragmentManager());
|
||||
viewPager.setAdapter(contributionsActivityPagerAdapter);
|
||||
|
||||
tabLayout.addTab(tabLayout.newTab().setText(getResources().getString(R.string.contributions_fragment)));
|
||||
tabLayout.addTab(tabLayout.newTab().setText(getResources().getString(R.string.nearby_fragment)));
|
||||
|
||||
// Set custom view to add nearby info icon next to text
|
||||
View nearbyTabLinearLayout = LayoutInflater.from(requireActivity()).inflate(R.layout.custom_nearby_tab_layout, null);
|
||||
ImageView nearbyInfo = nearbyTabLinearLayout.findViewById(R.id.nearby_info_image);
|
||||
tabLayout.getTabAt(1).setCustomView(nearbyTabLinearLayout);
|
||||
|
||||
nearbyInfo.setOnClickListener(view ->
|
||||
new AlertDialog.Builder(requireActivity()).setTitle(R.string.title_activity_nearby).setMessage(R.string.showcase_view_whole_nearby_activity)
|
||||
.setCancelable(true)
|
||||
.setPositiveButton(android.R.string.ok, (dialog, id) -> dialog.cancel())
|
||||
.create()
|
||||
.show()
|
||||
);
|
||||
|
||||
if (uploadServiceIntent != null) {
|
||||
// If auth cookie already acquired notify contrib fragment so that it san operate auth required actions
|
||||
((ContributionsFragment) contributionsActivityPagerAdapter.getItem(CONTRIBUTIONS_TAB_POSITION)).onAuthCookieAcquired(uploadServiceIntent);
|
||||
}
|
||||
setTabAndViewPagerSynchronisation();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds number of uploads next to tab text "Contributions" then it will look like
|
||||
* "Contributions (NUMBER)"
|
||||
*
|
||||
* @param uploadCount
|
||||
*/
|
||||
public void setNumOfUploads(int uploadCount) {
|
||||
tabLayout.getTabAt(0).setText(getResources().getString(R.string.contributions_fragment) + " " + getResources()
|
||||
.getQuantityString(R.plurals.contributions_subtitle,
|
||||
uploadCount, uploadCount));
|
||||
}
|
||||
|
||||
/**
|
||||
* Normally tab layout and view pager has no relation, which means when you swipe view pager
|
||||
* tab won't change and vice versa. So we have to notify each of them.
|
||||
*/
|
||||
private void setTabAndViewPagerSynchronisation() {
|
||||
//viewPager.canScrollHorizontally(false);
|
||||
viewPager.setFocusableInTouchMode(true);
|
||||
|
||||
viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
|
||||
@Override
|
||||
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPageSelected(int position) {
|
||||
switch (position) {
|
||||
case CONTRIBUTIONS_TAB_POSITION:
|
||||
Timber.d("Contributions tab selected");
|
||||
tabLayout.getTabAt(CONTRIBUTIONS_TAB_POSITION).select();
|
||||
isContributionsFragmentVisible = true;
|
||||
updateMenuItem();
|
||||
|
||||
break;
|
||||
case NEARBY_TAB_POSITION:
|
||||
Timber.d("Nearby tab selected");
|
||||
tabLayout.getTabAt(NEARBY_TAB_POSITION).select();
|
||||
isContributionsFragmentVisible = false;
|
||||
updateMenuItem();
|
||||
// Do all permission and GPS related tasks on tab selected, not on create
|
||||
((NearbyFragment) contributionsActivityPagerAdapter.getItem(1)).onTabSelected(onOrientationChanged);
|
||||
break;
|
||||
default:
|
||||
tabLayout.getTabAt(CONTRIBUTIONS_TAB_POSITION).select();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPageScrollStateChanged(int state) {
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
|
||||
@Override
|
||||
public void onTabSelected(TabLayout.Tab tab) {
|
||||
viewPager.setCurrentItem(tab.getPosition());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTabUnselected(TabLayout.Tab tab) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTabReselected(TabLayout.Tab tab) {
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void hideTabs() {
|
||||
//Todo: after changeDrawerIconToBackButton();
|
||||
if (tabLayout != null) {
|
||||
tabLayout.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
public void showTabs() {
|
||||
// Todo: afterchangeDrawerIconToDefault();
|
||||
if (tabLayout != null) {
|
||||
tabLayout.setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
/* //Todo: after
|
||||
@Override
|
||||
protected void onAuthFailure() {
|
||||
|
||||
}*/
|
||||
|
||||
/* //Todo: after
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
|
||||
String contributionsFragmentTag = ((MainActivity.ContributionsActivityPagerAdapter) viewPager.getAdapter()).makeFragmentName(R.id.pager, 0);
|
||||
String nearbyFragmentTag = ((MainActivity.ContributionsActivityPagerAdapter) viewPager.getAdapter()).makeFragmentName(R.id.pager, 1);
|
||||
if (drawer.isDrawerOpen(GravityCompat.START)) {
|
||||
drawer.closeDrawer(GravityCompat.START);
|
||||
} else if (getSupportFragmentManager().findFragmentByTag(contributionsFragmentTag) != null && isContributionsFragmentVisible) {
|
||||
// Meas that contribution fragment is visible (not nearby fragment)
|
||||
ContributionsFragment contributionsFragment = (ContributionsFragment) getSupportFragmentManager().findFragmentByTag(contributionsFragmentTag);
|
||||
|
||||
if (contributionsFragment.getChildFragmentManager().findFragmentByTag(ContributionsFragment.MEDIA_DETAIL_PAGER_FRAGMENT_TAG) != null) {
|
||||
// Means that media details fragment is visible to uer instead of contributions list fragment (As chils fragment)
|
||||
// Then we want to go back to contributions list fragment on backbutton pressed from media detail fragment
|
||||
contributionsFragment.getChildFragmentManager().popBackStack();
|
||||
// Tabs were invisible when Media Details Fragment is active, make them visible again on Contrib List Fragment active
|
||||
showTabs();
|
||||
// Nearby Notification Card View was invisible when Media Details Fragment is active, make it visible again on Contrib List Fragment active, according to preferences
|
||||
if (defaultKvStore.getBoolean("displayNearbyCardView", true)) {
|
||||
if (contributionsFragment.nearbyNotificationCardView.cardViewVisibilityState == NearbyNotificationCardView.CardViewVisibilityState.READY) {
|
||||
contributionsFragment.nearbyNotificationCardView.setVisibility(View.VISIBLE);
|
||||
}
|
||||
} else {
|
||||
contributionsFragment.nearbyNotificationCardView.setVisibility(View.GONE);
|
||||
}
|
||||
} else {
|
||||
finish();
|
||||
}
|
||||
} else if (getSupportFragmentManager().findFragmentByTag(nearbyFragmentTag) != null && !isContributionsFragmentVisible) {
|
||||
// Means that nearby fragment is visible (not contributions fragment)
|
||||
NearbyFragment nearbyFragment = (NearbyFragment) contributionsActivityPagerAdapter.getItem(1);
|
||||
|
||||
if (nearbyFragment.isBottomSheetExpanded()) {
|
||||
// Back should first hide the bottom sheet if it is expanded
|
||||
nearbyFragment.listOptionMenuItemClicked();
|
||||
} else {
|
||||
// Otherwise go back to contributions fragment
|
||||
viewPager.setCurrentItem(0);
|
||||
}
|
||||
} else {
|
||||
super.onBackPressed();
|
||||
}
|
||||
}*/
|
||||
|
||||
@Override
|
||||
public void onBackStackChanged() {
|
||||
//Todo: after requireActivity().initBackButton();
|
||||
}
|
||||
|
||||
/* //Todo: afetr activity needs to do it
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
MenuInflater inflater = getMenuInflater();
|
||||
inflater.inflate(R.menu.contribution_activity_notification_menu, menu);
|
||||
|
||||
notificationsMenuItem = menu.findItem(R.id.notifications);
|
||||
final View notification = notificationsMenuItem.getActionView();
|
||||
notificationCount = notification.findViewById(R.id.notification_count_badge);
|
||||
notification.setOnClickListener(view -> {
|
||||
NotificationActivity.startYourself(MainActivity.this, "unread");
|
||||
});
|
||||
this.menu = menu;
|
||||
updateMenuItem();
|
||||
setNotificationCount();
|
||||
return true;
|
||||
}*/
|
||||
|
||||
@SuppressLint("CheckResult")
|
||||
private void setNotificationCount() {
|
||||
//Todo: afetr check the compositeDisposable instantiation
|
||||
((MainActivity) requireActivity()).compositeDisposable.add(Observable.fromCallable(() -> notificationController.getNotifications(false))
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(this::initNotificationViews,
|
||||
throwable -> Timber.e(throwable, "Error occurred while loading notifications")));
|
||||
}
|
||||
|
||||
private void initNotificationViews(List<Notification> notificationList) {
|
||||
Timber.d("Number of notifications is %d", notificationList.size());
|
||||
if (notificationList.isEmpty()) {
|
||||
notificationCount.setVisibility(View.GONE);
|
||||
} else {
|
||||
notificationCount.setVisibility(View.VISIBLE);
|
||||
notificationCount.setText(String.valueOf(notificationList.size()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Responsible with displaying required menu items according to displayed fragment.
|
||||
* Notifications icon when contributions list is visible, list sheet icon when nearby is visible
|
||||
*/
|
||||
private void updateMenuItem() {
|
||||
if (menu != null) {
|
||||
if (isContributionsFragmentVisible) {
|
||||
// Display notifications menu item
|
||||
menu.findItem(R.id.notifications).setVisible(true);
|
||||
menu.findItem(R.id.list_sheet).setVisible(false);
|
||||
Timber.d("Contributions activity notifications menu item is visible");
|
||||
} else {
|
||||
// Display bottom list menu item
|
||||
menu.findItem(R.id.notifications).setVisible(false);
|
||||
menu.findItem(R.id.list_sheet).setVisible(true);
|
||||
Timber.d("Contributions activity list sheet menu item is visible");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case R.id.notifications:
|
||||
// Starts notification activity on click to notification icon
|
||||
NotificationActivity.startYourself(requireActivity(), "unread");
|
||||
return true;
|
||||
case R.id.list_sheet:
|
||||
if (contributionsActivityPagerAdapter.getItem(1) != null) {
|
||||
((NearbyFragment) contributionsActivityPagerAdapter.getItem(1)).listOptionMenuItemClicked();
|
||||
}
|
||||
return true;
|
||||
default:
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean deviceHasCamera() {
|
||||
PackageManager pm = requireActivity().getPackageManager();
|
||||
return pm.hasSystemFeature(PackageManager.FEATURE_CAMERA) ||
|
||||
pm.hasSystemFeature(PackageManager.FEATURE_CAMERA_FRONT);
|
||||
}
|
||||
|
||||
public class ContributionsActivityPagerAdapter extends FragmentPagerAdapter {
|
||||
FragmentManager fragmentManager;
|
||||
private boolean isContributionsListFragment = true; // to know what to put in first tab, Contributions of Media Details
|
||||
|
||||
|
||||
public ContributionsActivityPagerAdapter(FragmentManager fragmentManager) {
|
||||
super(fragmentManager);
|
||||
this.fragmentManager = fragmentManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCount() {
|
||||
return 2;
|
||||
}
|
||||
|
||||
/*
|
||||
* Do not use getItem method to access fragments on pager adapter. User reference variables
|
||||
* instead.
|
||||
* */
|
||||
@Override
|
||||
public Fragment getItem(int position) {
|
||||
switch (position) {
|
||||
case 0:
|
||||
ContributionsFragment retainedContributionsFragment = getContributionsFragment(0);
|
||||
if (retainedContributionsFragment != null) {
|
||||
// ContributionsFragment is parent of ContributionsListFragment and
|
||||
// MediaDetailsFragment. If below decides which child will be visible.
|
||||
if (isContributionsListFragment) {
|
||||
retainedContributionsFragment.setContributionsListFragment();
|
||||
} else {
|
||||
retainedContributionsFragment.setMediaDetailPagerFragment();
|
||||
}
|
||||
return retainedContributionsFragment;
|
||||
} else {
|
||||
// If we reach here, retainedContributionsFragment is null
|
||||
return new ContributionsFragment();
|
||||
|
||||
}
|
||||
|
||||
case 1:
|
||||
NearbyFragment retainedNearbyFragment = getNearbyFragment(1);
|
||||
if (retainedNearbyFragment != null) {
|
||||
return retainedNearbyFragment;
|
||||
} else {
|
||||
// If we reach here, retainedNearbyFragment is null
|
||||
return new NearbyFragment();
|
||||
}
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates fragment tag with makeFragmentName method to get retained contributions fragment
|
||||
*
|
||||
* @param position index of tabs, in our case 0 or 1
|
||||
* @return
|
||||
*/
|
||||
private ContributionsFragment getContributionsFragment(int position) {
|
||||
String tag = makeFragmentName(R.id.ContPager, position);
|
||||
return (ContributionsFragment) fragmentManager.findFragmentByTag(tag);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates fragment tag with makeFragmentName method to get retained nearby fragment
|
||||
*
|
||||
* @param position index of tabs, in our case 0 or 1
|
||||
* @return
|
||||
*/
|
||||
private NearbyFragment getNearbyFragment(int position) {
|
||||
String tag = makeFragmentName(R.id.ContPager, position);
|
||||
return (NearbyFragment) fragmentManager.findFragmentByTag(tag);
|
||||
}
|
||||
|
||||
/**
|
||||
* A simple hack to use retained fragment when getID is called explicitly, if we don't use
|
||||
* this method, a new fragment will be initialized on each explicit calls of getID
|
||||
*
|
||||
* @param viewId id of view pager
|
||||
* @param index index of tabs, in our case 0 or 1
|
||||
* @return
|
||||
*/
|
||||
public String makeFragmentName(int viewId, int index) {
|
||||
return "android:switcher:" + viewId + ":" + index;
|
||||
}
|
||||
|
||||
/**
|
||||
* In first tab we can have ContributionsFragment or Media details fragment. This method
|
||||
* is responsible to update related boolean
|
||||
*
|
||||
* @param isContributionsListFragment true when contribution fragment should be visible, false
|
||||
* means user clicked to MediaDetails
|
||||
*/
|
||||
private void updateContributionFragmentTabContent(boolean isContributionsListFragment) {
|
||||
this.isContributionsListFragment = isContributionsListFragment;
|
||||
}
|
||||
}
|
||||
|
||||
/* Todo: after Activity might need to handle this
|
||||
@Override
|
||||
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
Timber.d(data != null ? data.toString() : "onActivityResult data is null");
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
controller.handleActivityResult(this, requestCode, resultCode, data);
|
||||
}*/
|
||||
|
||||
@Override
|
||||
public void onRequestPermissionsResult(int requestCode,
|
||||
String permissions[], int[] grantResults) {
|
||||
switch (requestCode) {
|
||||
case LOCATION_REQUEST: {
|
||||
// If request is cancelled, the result arrays are empty.
|
||||
if (grantResults.length > 0
|
||||
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
|
||||
Timber.d("Location permission given");
|
||||
((ContributionsFragment) contributionsActivityPagerAdapter
|
||||
.getItem(0)).locationManager.registerLocationManager();
|
||||
} else {
|
||||
// If nearby fragment is visible and location permission is not given, send user back to contrib fragment
|
||||
if (!isContributionsFragmentVisible) {
|
||||
viewPager.setCurrentItem(CONTRIBUTIONS_TAB_POSITION);
|
||||
|
||||
// TODO: If contrib fragment is visible and location permission is not given, display permission request button
|
||||
} else {
|
||||
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Todo: after might need to go into attach and detach
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
setNotificationCount();
|
||||
quizChecker.initQuizCheck(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
quizChecker.cleanup();
|
||||
locationManager.unregisterLocationManager();
|
||||
// Remove ourself from hashmap to prevent memory leaks
|
||||
locationManager = null;
|
||||
super.onDestroy();
|
||||
}*/
|
||||
|
||||
@Override
|
||||
public void onAttach(Context context) {
|
||||
super.onAttach(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDetach() {
|
||||
super.onDetach();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -1,30 +1,19 @@
|
|||
package fr.free.nrw.commons.contributions;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.AlertDialog;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
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.AdapterView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.google.android.material.tabs.TabLayout;
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import androidx.core.view.GravityCompat;
|
||||
import androidx.drawerlayout.widget.DrawerLayout;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
import androidx.fragment.app.FragmentPagerAdapter;
|
||||
import androidx.viewpager.widget.ViewPager;
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
import fr.free.nrw.commons.BuildConfig;
|
||||
|
|
@ -32,10 +21,10 @@ import fr.free.nrw.commons.R;
|
|||
import fr.free.nrw.commons.auth.AuthenticatedActivity;
|
||||
import fr.free.nrw.commons.auth.SessionManager;
|
||||
import fr.free.nrw.commons.location.LocationServiceManager;
|
||||
import fr.free.nrw.commons.nearby.NearbyFragment;
|
||||
import fr.free.nrw.commons.nearby.NearbyNotificationCardView;
|
||||
import fr.free.nrw.commons.media.MediaDetailPagerFragment;
|
||||
import fr.free.nrw.commons.navtab.NavTabFragmentPagerAdapter;
|
||||
import fr.free.nrw.commons.navtab.NavTabLayout;
|
||||
import fr.free.nrw.commons.notification.Notification;
|
||||
import fr.free.nrw.commons.notification.NotificationActivity;
|
||||
import fr.free.nrw.commons.notification.NotificationController;
|
||||
import fr.free.nrw.commons.quiz.QuizChecker;
|
||||
import fr.free.nrw.commons.upload.UploadService;
|
||||
|
|
@ -47,15 +36,20 @@ import timber.log.Timber;
|
|||
import static android.content.ContentResolver.requestSync;
|
||||
import static fr.free.nrw.commons.location.LocationServiceManager.LOCATION_REQUEST;
|
||||
|
||||
public class MainActivity extends AuthenticatedActivity implements FragmentManager.OnBackStackChangedListener {
|
||||
public class MainActivity extends AuthenticatedActivity implements FragmentManager.OnBackStackChangedListener , AdapterView.OnItemClickListener{
|
||||
|
||||
@Inject
|
||||
SessionManager sessionManager;
|
||||
@Inject ContributionController controller;
|
||||
@BindView(R.id.tab_layout)
|
||||
TabLayout tabLayout;
|
||||
@Inject
|
||||
ContributionController controller;
|
||||
@BindView(R.id.pager)
|
||||
public UnswipableViewPager viewPager;
|
||||
@BindView(R.id.fragment_main_nav_tab_layout)
|
||||
NavTabLayout tabLayout;
|
||||
private MediaDetailPagerFragment mediaDetails;
|
||||
|
||||
|
||||
|
||||
@Inject
|
||||
public LocationServiceManager locationManager;
|
||||
@Inject
|
||||
|
|
@ -67,12 +61,8 @@ public class MainActivity extends AuthenticatedActivity implements FragmentManag
|
|||
public Intent uploadServiceIntent;
|
||||
public boolean isAuthCookieAcquired = false;
|
||||
|
||||
public ContributionsActivityPagerAdapter contributionsActivityPagerAdapter;
|
||||
public final int CONTRIBUTIONS_TAB_POSITION = 0;
|
||||
public final int NEARBY_TAB_POSITION = 1;
|
||||
|
||||
public boolean isContributionsFragmentVisible = true; // False means nearby fragment is visible
|
||||
private Menu menu;
|
||||
|
||||
private boolean onOrientationChanged = false;
|
||||
|
||||
|
|
@ -81,15 +71,15 @@ public class MainActivity extends AuthenticatedActivity implements FragmentManag
|
|||
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_contributions);
|
||||
setContentView(R.layout.main);
|
||||
ButterKnife.bind(this);
|
||||
|
||||
requestAuthToken();
|
||||
initDrawer();
|
||||
setTitle(getString(R.string.navigation_item_home)); // Should I create a new string variable with another name instead?
|
||||
setUpPager();
|
||||
|
||||
|
||||
if (savedInstanceState != null ) {
|
||||
if (savedInstanceState != null) {
|
||||
onOrientationChanged = true; // Will be used in nearby fragment to determine significant update of map
|
||||
|
||||
//If nearby map was visible, call on Tab Selected to call all nearby operations
|
||||
|
|
@ -99,6 +89,17 @@ public class MainActivity extends AuthenticatedActivity implements FragmentManag
|
|||
}
|
||||
}
|
||||
|
||||
private void setUpPager() {
|
||||
viewPager.setAdapter(new NavTabFragmentPagerAdapter(getSupportFragmentManager()));
|
||||
viewPager.setOffscreenPageLimit(2);
|
||||
tabLayout.setOnNavigationItemSelectedListener(item -> {
|
||||
viewPager.setCurrentItem(item.getOrder());
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
protected void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
|
|
@ -113,126 +114,13 @@ public class MainActivity extends AuthenticatedActivity implements FragmentManag
|
|||
uploadServiceIntent.setAction(UploadService.ACTION_START_SERVICE);
|
||||
startService(uploadServiceIntent);
|
||||
|
||||
addTabsAndFragments();
|
||||
//Todo: after needs to happen at addTabsAndFragments();
|
||||
isAuthCookieAcquired = true;
|
||||
if (contributionsActivityPagerAdapter.getItem(0) != null) {
|
||||
/*if (contributionsActivityPagerAdapter.getItem(0) != null) {
|
||||
((ContributionsFragment)contributionsActivityPagerAdapter.getItem(0)).onAuthCookieAcquired(uploadServiceIntent);
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
private void addTabsAndFragments() {
|
||||
contributionsActivityPagerAdapter = new ContributionsActivityPagerAdapter(getSupportFragmentManager());
|
||||
viewPager.setAdapter(contributionsActivityPagerAdapter);
|
||||
|
||||
tabLayout.addTab(tabLayout.newTab().setText(getResources().getString(R.string.contributions_fragment)));
|
||||
tabLayout.addTab(tabLayout.newTab().setText(getResources().getString(R.string.nearby_fragment)));
|
||||
|
||||
// Set custom view to add nearby info icon next to text
|
||||
View nearbyTabLinearLayout = LayoutInflater.from(this).inflate(R.layout.custom_nearby_tab_layout, null);
|
||||
ImageView nearbyInfo = nearbyTabLinearLayout.findViewById(R.id.nearby_info_image);
|
||||
tabLayout.getTabAt(1).setCustomView(nearbyTabLinearLayout);
|
||||
|
||||
nearbyInfo.setOnClickListener(view ->
|
||||
new AlertDialog.Builder(MainActivity.this).setTitle(R.string.title_activity_nearby).setMessage(R.string.showcase_view_whole_nearby_activity)
|
||||
.setCancelable(true)
|
||||
.setPositiveButton(android.R.string.ok, (dialog, id) -> dialog.cancel())
|
||||
.create()
|
||||
.show()
|
||||
);
|
||||
|
||||
if (uploadServiceIntent != null) {
|
||||
// If auth cookie already acquired notify contrib fragment so that it san operate auth required actions
|
||||
((ContributionsFragment)contributionsActivityPagerAdapter.getItem(CONTRIBUTIONS_TAB_POSITION)).onAuthCookieAcquired(uploadServiceIntent);
|
||||
}
|
||||
setTabAndViewPagerSynchronisation();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds number of uploads next to tab text "Contributions" then it will look like
|
||||
* "Contributions (NUMBER)"
|
||||
* @param uploadCount
|
||||
*/
|
||||
public void setNumOfUploads(int uploadCount) {
|
||||
tabLayout.getTabAt(0).setText(getResources().getString(R.string.contributions_fragment) +" "+ getResources()
|
||||
.getQuantityString(R.plurals.contributions_subtitle,
|
||||
uploadCount, uploadCount));
|
||||
}
|
||||
|
||||
/**
|
||||
* Normally tab layout and view pager has no relation, which means when you swipe view pager
|
||||
* tab won't change and vice versa. So we have to notify each of them.
|
||||
*/
|
||||
private void setTabAndViewPagerSynchronisation() {
|
||||
//viewPager.canScrollHorizontally(false);
|
||||
viewPager.setFocusableInTouchMode(true);
|
||||
|
||||
viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
|
||||
@Override
|
||||
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPageSelected(int position) {
|
||||
switch (position) {
|
||||
case CONTRIBUTIONS_TAB_POSITION:
|
||||
Timber.d("Contributions tab selected");
|
||||
tabLayout.getTabAt(CONTRIBUTIONS_TAB_POSITION).select();
|
||||
isContributionsFragmentVisible = true;
|
||||
updateMenuItem();
|
||||
|
||||
break;
|
||||
case NEARBY_TAB_POSITION:
|
||||
Timber.d("Nearby tab selected");
|
||||
tabLayout.getTabAt(NEARBY_TAB_POSITION).select();
|
||||
isContributionsFragmentVisible = false;
|
||||
updateMenuItem();
|
||||
// Do all permission and GPS related tasks on tab selected, not on create
|
||||
((NearbyFragment)contributionsActivityPagerAdapter.getItem(1)).onTabSelected(onOrientationChanged);
|
||||
break;
|
||||
default:
|
||||
tabLayout.getTabAt(CONTRIBUTIONS_TAB_POSITION).select();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPageScrollStateChanged(int state) {
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
|
||||
@Override
|
||||
public void onTabSelected(TabLayout.Tab tab) {
|
||||
viewPager.setCurrentItem(tab.getPosition());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTabUnselected(TabLayout.Tab tab) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTabReselected(TabLayout.Tab tab) {
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void hideTabs() {
|
||||
changeDrawerIconToBackButton();
|
||||
if (tabLayout != null) {
|
||||
tabLayout.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
public void showTabs() {
|
||||
changeDrawerIconToDefault();
|
||||
if (tabLayout != null) {
|
||||
tabLayout.setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onAuthFailure() {
|
||||
|
|
@ -241,7 +129,8 @@ public class MainActivity extends AuthenticatedActivity implements FragmentManag
|
|||
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
|
||||
/* Todo: after stability
|
||||
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
|
||||
String contributionsFragmentTag = ((ContributionsActivityPagerAdapter) viewPager.getAdapter()).makeFragmentName(R.id.pager, 0);
|
||||
String nearbyFragmentTag = ((ContributionsActivityPagerAdapter) viewPager.getAdapter()).makeFragmentName(R.id.pager, 1);
|
||||
if (drawer.isDrawerOpen(GravityCompat.START)) {
|
||||
|
|
@ -278,9 +167,9 @@ public class MainActivity extends AuthenticatedActivity implements FragmentManag
|
|||
// Otherwise go back to contributions fragment
|
||||
viewPager.setCurrentItem(0);
|
||||
}
|
||||
} else {
|
||||
} else {*/
|
||||
super.onBackPressed();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -288,7 +177,8 @@ public class MainActivity extends AuthenticatedActivity implements FragmentManag
|
|||
initBackButton();
|
||||
}
|
||||
|
||||
@Override
|
||||
/* Todo: after set up menu
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
MenuInflater inflater = getMenuInflater();
|
||||
inflater.inflate(R.menu.contribution_activity_notification_menu, menu);
|
||||
|
|
@ -300,10 +190,10 @@ public class MainActivity extends AuthenticatedActivity implements FragmentManag
|
|||
NotificationActivity.startYourself(MainActivity.this, "unread");
|
||||
});
|
||||
this.menu = menu;
|
||||
updateMenuItem();
|
||||
//updateMenuItem();
|
||||
setNotificationCount();
|
||||
return true;
|
||||
}
|
||||
}*/
|
||||
|
||||
@SuppressLint("CheckResult")
|
||||
private void setNotificationCount() {
|
||||
|
|
@ -315,19 +205,23 @@ public class MainActivity extends AuthenticatedActivity implements FragmentManag
|
|||
}
|
||||
|
||||
private void initNotificationViews(List<Notification> notificationList) {
|
||||
Timber.d("Number of notifications is %d", notificationList.size());
|
||||
/* Timber.d("Number of notifications is %d", notificationList.size());
|
||||
if (notificationList.isEmpty()) {
|
||||
notificationCount.setVisibility(View.GONE);
|
||||
} else {
|
||||
notificationCount.setVisibility(View.VISIBLE);
|
||||
//notificationCount.setVisibility(View.VISIBLE);
|
||||
notificationCount.setText(String.valueOf(notificationList.size()));
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
/*Todo: after set up menu
|
||||
*/
|
||||
|
||||
/**
|
||||
* Responsible with displaying required menu items according to displayed fragment.
|
||||
* Notifications icon when contributions list is visible, list sheet icon when nearby is visible
|
||||
*/
|
||||
*//*
|
||||
|
||||
private void updateMenuItem() {
|
||||
if (menu != null) {
|
||||
if (isContributionsFragmentVisible) {
|
||||
|
|
@ -360,110 +254,10 @@ public class MainActivity extends AuthenticatedActivity implements FragmentManag
|
|||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean deviceHasCamera() {
|
||||
PackageManager pm = getPackageManager();
|
||||
return pm.hasSystemFeature(PackageManager.FEATURE_CAMERA) ||
|
||||
pm.hasSystemFeature(PackageManager.FEATURE_CAMERA_FRONT);
|
||||
}
|
||||
|
||||
public class ContributionsActivityPagerAdapter extends FragmentPagerAdapter {
|
||||
FragmentManager fragmentManager;
|
||||
private boolean isContributionsListFragment = true; // to know what to put in first tab, Contributions of Media Details
|
||||
|
||||
|
||||
public ContributionsActivityPagerAdapter(FragmentManager fragmentManager) {
|
||||
super(fragmentManager);
|
||||
this.fragmentManager = fragmentManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCount() {
|
||||
return 2;
|
||||
}
|
||||
|
||||
/*
|
||||
* Do not use getItem method to access fragments on pager adapter. User reference variables
|
||||
* instead.
|
||||
* */
|
||||
@Override
|
||||
public Fragment getItem(int position) {
|
||||
switch (position){
|
||||
case 0:
|
||||
ContributionsFragment retainedContributionsFragment = getContributionsFragment(0);
|
||||
if (retainedContributionsFragment != null) {
|
||||
// ContributionsFragment is parent of ContributionsListFragment and
|
||||
// MediaDetailsFragment. If below decides which child will be visible.
|
||||
if (isContributionsListFragment) {
|
||||
retainedContributionsFragment.setContributionsListFragment();
|
||||
} else {
|
||||
retainedContributionsFragment.setMediaDetailPagerFragment();
|
||||
}
|
||||
return retainedContributionsFragment;
|
||||
} else {
|
||||
// If we reach here, retainedContributionsFragment is null
|
||||
return new ContributionsFragment();
|
||||
|
||||
}
|
||||
|
||||
case 1:
|
||||
NearbyFragment retainedNearbyFragment = getNearbyFragment(1);
|
||||
if (retainedNearbyFragment != null) {
|
||||
return retainedNearbyFragment;
|
||||
} else {
|
||||
// If we reach here, retainedNearbyFragment is null
|
||||
return new NearbyFragment();
|
||||
}
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates fragment tag with makeFragmentName method to get retained contributions fragment
|
||||
* @param position index of tabs, in our case 0 or 1
|
||||
* @return
|
||||
*/
|
||||
private ContributionsFragment getContributionsFragment(int position) {
|
||||
String tag = makeFragmentName(R.id.pager, position);
|
||||
return (ContributionsFragment)fragmentManager.findFragmentByTag(tag);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates fragment tag with makeFragmentName method to get retained nearby fragment
|
||||
* @param position index of tabs, in our case 0 or 1
|
||||
* @return
|
||||
*/
|
||||
private NearbyFragment getNearbyFragment(int position) {
|
||||
String tag = makeFragmentName(R.id.pager, position);
|
||||
return (NearbyFragment)fragmentManager.findFragmentByTag(tag);
|
||||
}
|
||||
|
||||
/**
|
||||
* A simple hack to use retained fragment when getID is called explicitly, if we don't use
|
||||
* this method, a new fragment will be initialized on each explicit calls of getID
|
||||
* @param viewId id of view pager
|
||||
* @param index index of tabs, in our case 0 or 1
|
||||
* @return
|
||||
*/
|
||||
public String makeFragmentName(int viewId, int index) {
|
||||
return "android:switcher:" + viewId + ":" + index;
|
||||
}
|
||||
|
||||
/**
|
||||
* In first tab we can have ContributionsFragment or Media details fragment. This method
|
||||
* is responsible to update related boolean
|
||||
* @param isContributionsListFragment true when contribution fragment should be visible, false
|
||||
* means user clicked to MediaDetails
|
||||
*/
|
||||
private void updateContributionFragmentTabContent(boolean isContributionsListFragment) {
|
||||
this.isContributionsListFragment = isContributionsListFragment;
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
@Override
|
||||
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
Timber.d(data!=null?data.toString():"onActivityResult data is null");
|
||||
Timber.d(data != null ? data.toString() : "onActivityResult data is null");
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
controller.handleActivityResult(this, requestCode, resultCode, data);
|
||||
}
|
||||
|
|
@ -473,8 +267,9 @@ public class MainActivity extends AuthenticatedActivity implements FragmentManag
|
|||
String permissions[], int[] grantResults) {
|
||||
switch (requestCode) {
|
||||
case LOCATION_REQUEST: {
|
||||
//Todo after set this right
|
||||
// If request is cancelled, the result arrays are empty.
|
||||
if (grantResults.length > 0
|
||||
/* if (grantResults.length > 0
|
||||
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
|
||||
Timber.d("Location permission given");
|
||||
((ContributionsFragment)contributionsActivityPagerAdapter
|
||||
|
|
@ -486,7 +281,7 @@ public class MainActivity extends AuthenticatedActivity implements FragmentManag
|
|||
|
||||
// TODO: If contrib fragment is visible and location permission is not given, display permission request button
|
||||
}
|
||||
}
|
||||
}*/
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -495,6 +290,21 @@ public class MainActivity extends AuthenticatedActivity implements FragmentManag
|
|||
}
|
||||
}
|
||||
|
||||
public void hideTabs() {
|
||||
changeDrawerIconToBackButton();
|
||||
if (tabLayout != null) {
|
||||
tabLayout.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
public void showTabs() {
|
||||
changeDrawerIconToDefault();
|
||||
if (tabLayout != null) {
|
||||
tabLayout.setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
|
|
@ -510,4 +320,29 @@ public class MainActivity extends AuthenticatedActivity implements FragmentManag
|
|||
locationManager = null;
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onItemClick(AdapterView<?> parent, View view, int i, long id) {
|
||||
if (mediaDetails == null || !mediaDetails.isVisible()) {
|
||||
// set isFeaturedImage true for featured images, to include author field on media detail
|
||||
mediaDetails = new MediaDetailPagerFragment(false, true);
|
||||
FragmentManager supportFragmentManager = getSupportFragmentManager();
|
||||
supportFragmentManager
|
||||
.beginTransaction()
|
||||
.hide(supportFragmentManager.getFragments().get(supportFragmentManager.getBackStackEntryCount()))
|
||||
.add(R.id.fragmentContainer, mediaDetails)
|
||||
.addToBackStack(null)
|
||||
.commit();
|
||||
// Reason for using hide, add instead of replace is to maintain scroll position after
|
||||
// coming back to the search activity. See https://github.com/commons-app/apps-android-commons/issues/1631
|
||||
// https://stackoverflow.com/questions/11353075/how-can-i-maintain-fragment-state-when-added-to-the-back-stack/19022550#19022550 supportFragmentManager.executePendingTransactions();
|
||||
}
|
||||
mediaDetails.showImage(i);
|
||||
forceInitBackButton();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPointerCaptureChanged(boolean hasCapture) {
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,6 +9,8 @@ import fr.free.nrw.commons.category.CategoryImagesListFragment;
|
|||
import fr.free.nrw.commons.category.SubCategoryListFragment;
|
||||
import fr.free.nrw.commons.contributions.ContributionsFragment;
|
||||
import fr.free.nrw.commons.contributions.ContributionsListFragment;
|
||||
import fr.free.nrw.commons.contributions.ContributionsMainFragment;
|
||||
import fr.free.nrw.commons.explore.ExploreFragment;
|
||||
import fr.free.nrw.commons.explore.categories.SearchCategoryFragment;
|
||||
import fr.free.nrw.commons.explore.images.SearchImageFragment;
|
||||
import fr.free.nrw.commons.explore.recentsearches.RecentSearchesFragment;
|
||||
|
|
@ -27,6 +29,13 @@ public abstract class FragmentBuilderModule {
|
|||
@ContributesAndroidInjector
|
||||
abstract ContributionsListFragment bindContributionsListFragment();
|
||||
|
||||
@ContributesAndroidInjector
|
||||
abstract ExploreFragment bindExploreFragment();
|
||||
|
||||
@ContributesAndroidInjector
|
||||
abstract ContributionsMainFragment bindContributionsMainFragment();
|
||||
|
||||
|
||||
@ContributesAndroidInjector
|
||||
abstract MediaDetailFragment bindMediaDetailFragment();
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,265 @@
|
|||
package fr.free.nrw.commons.explore;
|
||||
|
||||
|
||||
import android.database.DataSetObserver;
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.FrameLayout;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
import androidx.viewpager.widget.ViewPager;
|
||||
|
||||
import com.google.android.material.tabs.TabLayout;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
import dagger.Provides;
|
||||
import fr.free.nrw.commons.Media;
|
||||
import fr.free.nrw.commons.R;
|
||||
import fr.free.nrw.commons.category.CategoryImagesListFragment;
|
||||
import fr.free.nrw.commons.di.CommonsDaggerSupportFragment;
|
||||
import fr.free.nrw.commons.media.MediaDetailPagerFragment;
|
||||
|
||||
/**
|
||||
* A simple {@link Fragment} subclass.
|
||||
*/
|
||||
public class ExploreFragment
|
||||
extends CommonsDaggerSupportFragment
|
||||
implements MediaDetailPagerFragment.MediaDetailProvider,
|
||||
AdapterView.OnItemClickListener {
|
||||
|
||||
private static final String FEATURED_IMAGES_CATEGORY = "Category:Featured_pictures_on_Wikimedia_Commons";
|
||||
private static final String MOBILE_UPLOADS_CATEGORY = "Category:Uploaded_with_Mobile/Android";
|
||||
|
||||
|
||||
@BindView(R.id.mediaContainer)
|
||||
FrameLayout mediaContainer;
|
||||
@BindView(R.id.tab_layout)
|
||||
TabLayout tabLayout;
|
||||
@BindView(R.id.viewPager)
|
||||
ViewPager viewPager;
|
||||
ViewPagerAdapter viewPagerAdapter;
|
||||
private FragmentManager supportFragmentManager;
|
||||
private MediaDetailPagerFragment mediaDetails;
|
||||
private CategoryImagesListFragment mobileImagesListFragment;
|
||||
private CategoryImagesListFragment featuredImagesListFragment;
|
||||
|
||||
public static ExploreFragment newInstance() {
|
||||
ExploreFragment fragment = new ExploreFragment();
|
||||
fragment.setRetainInstance(true);
|
||||
return fragment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(
|
||||
@NonNull LayoutInflater inflater,
|
||||
ViewGroup container,
|
||||
Bundle savedInstanceState
|
||||
) {
|
||||
View v = inflater.inflate(R.layout.activity_explore, container, false);
|
||||
ButterKnife.bind(this, v);
|
||||
viewPagerAdapter = new ViewPagerAdapter(requireActivity().getSupportFragmentManager());
|
||||
viewPager.setAdapter(viewPagerAdapter);
|
||||
tabLayout.setupWithViewPager(viewPager);
|
||||
setTabs();
|
||||
return v;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
//Todo: after setContentView(R.layout.activity_explore);
|
||||
ButterKnife.bind(requireActivity());
|
||||
//Todo:after setTitle(getString(R.string.title_activity_explore));
|
||||
supportFragmentManager = requireActivity().getSupportFragmentManager();
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the titles in the tabLayout and fragments in the viewPager
|
||||
*/
|
||||
public void setTabs() {
|
||||
List<Fragment> fragmentList = new ArrayList<>();
|
||||
List<String> titleList = new ArrayList<>();
|
||||
|
||||
featuredImagesListFragment = new CategoryImagesListFragment(this);
|
||||
Bundle featuredArguments = new Bundle();
|
||||
featuredArguments.putString("categoryName", FEATURED_IMAGES_CATEGORY);
|
||||
featuredImagesListFragment.setArguments(featuredArguments);
|
||||
fragmentList.add(featuredImagesListFragment);
|
||||
titleList.add(getString(R.string.explore_tab_title_featured));
|
||||
|
||||
mobileImagesListFragment = new CategoryImagesListFragment();
|
||||
Bundle mobileArguments = new Bundle();
|
||||
mobileArguments.putString("categoryName", MOBILE_UPLOADS_CATEGORY);
|
||||
mobileImagesListFragment.setArguments(mobileArguments);
|
||||
fragmentList.add(mobileImagesListFragment);
|
||||
titleList.add(getString(R.string.explore_tab_title_mobile));
|
||||
|
||||
viewPagerAdapter.setTabData(fragmentList, titleList);
|
||||
viewPagerAdapter.notifyDataSetChanged();
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is called mediaDetailPagerFragment. It returns the Media Object at that Index
|
||||
*
|
||||
* @param i It is the index of which media object is to be returned which is same as
|
||||
* current index of viewPager.
|
||||
* @return Media Object
|
||||
*/
|
||||
@Override
|
||||
public Media getMediaAtPosition(int i) {
|
||||
if (mobileImagesListFragment.getAdapter() != null && tabLayout.getSelectedTabPosition() == 1) {
|
||||
return (Media) mobileImagesListFragment.getAdapter().getItem(i);
|
||||
} else if (featuredImagesListFragment.getAdapter() != null && tabLayout.getSelectedTabPosition() == 0) {
|
||||
return (Media) featuredImagesListFragment.getAdapter().getItem(i);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is called on from getCount of MediaDetailPagerFragment
|
||||
* The viewpager will contain same number of media items as that of media elements in adapter.
|
||||
*
|
||||
* @return Total Media count in the adapter
|
||||
*/
|
||||
@Override
|
||||
public int getTotalMediaCount() {
|
||||
if (mobileImagesListFragment.getAdapter() != null && tabLayout.getSelectedTabPosition() == 1) {
|
||||
return mobileImagesListFragment.getAdapter().getCount();
|
||||
} else if (featuredImagesListFragment.getAdapter() != null && tabLayout.getSelectedTabPosition() == 0) {
|
||||
return featuredImagesListFragment.getAdapter().getCount();
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is never called but it was in MediaDetailProvider Interface
|
||||
* so it needs to be overrided.
|
||||
*/
|
||||
@Override
|
||||
public void notifyDatasetChanged() {
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is called on success of API call for featured images or mobile uploads.
|
||||
* The viewpager will notified that number of items have changed.
|
||||
*/
|
||||
public void viewPagerNotifyDataSetChanged() {
|
||||
if (mediaDetails != null) {
|
||||
mediaDetails.notifyDataSetChanged();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is never called but it was in MediaDetailProvider Interface
|
||||
* so it needs to be overrided.
|
||||
*/
|
||||
@Override
|
||||
public void registerDataSetObserver(DataSetObserver observer) {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is never called but it was in MediaDetailProvider Interface
|
||||
* so it needs to be overrided.
|
||||
*/
|
||||
@Override
|
||||
public void unregisterDataSetObserver(DataSetObserver observer) {
|
||||
|
||||
}
|
||||
|
||||
/** Todo: after
|
||||
* This method is called on backPressed of anyFragment in the activity.
|
||||
* If condition is called when mediaDetailFragment is opened.
|
||||
*//*
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
if (supportFragmentManager.getBackStackEntryCount() == 1) {
|
||||
tabLayout.setVisibility(View.VISIBLE);
|
||||
viewPager.setVisibility(View.VISIBLE);
|
||||
mediaContainer.setVisibility(View.GONE);
|
||||
}
|
||||
super.onBackPressed();
|
||||
}*/
|
||||
|
||||
|
||||
/**
|
||||
* This method is called when viewPager has reached its end.
|
||||
* Fetches more images and adds them to the recycler view and viewpager adapter
|
||||
*/
|
||||
public void requestMoreImages() {
|
||||
if (mobileImagesListFragment != null && tabLayout.getSelectedTabPosition() == 1) {
|
||||
mobileImagesListFragment.fetchMoreImagesViewPager();
|
||||
} else if (featuredImagesListFragment != null && tabLayout.getSelectedTabPosition() == 0) {
|
||||
featuredImagesListFragment.fetchMoreImagesViewPager();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is called onClick of media inside category featured images or mobile uploads.
|
||||
*/
|
||||
@Override
|
||||
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
|
||||
tabLayout.setVisibility(View.GONE);
|
||||
viewPager.setVisibility(View.GONE);
|
||||
mediaContainer.setVisibility(View.VISIBLE);
|
||||
if (mediaDetails == null || !mediaDetails.isVisible()) {
|
||||
// set isFeaturedImage true for featured images, to include author field on media detail
|
||||
mediaDetails = new MediaDetailPagerFragment(false, true, this);
|
||||
FragmentManager supportFragmentManager = requireActivity().getSupportFragmentManager();
|
||||
supportFragmentManager
|
||||
.beginTransaction()
|
||||
.hide(supportFragmentManager.getFragments().get(supportFragmentManager.getBackStackEntryCount()))
|
||||
.add(R.id.mediaContainer, mediaDetails)
|
||||
.addToBackStack(null)
|
||||
.commit();
|
||||
// Reason for using hide, add instead of replace is to maintain scroll position after
|
||||
// coming back to the explore activity. See https://github.com/commons-app/apps-android-commons/issues/1631
|
||||
// https://stackoverflow.com/questions/11353075/how-can-i-maintain-fragment-state-when-added-to-the-back-stack/19022550#19022550 supportFragmentManager.executePendingTransactions();
|
||||
}
|
||||
mediaDetails.showImage(i);
|
||||
//Todo: after forceInitBackButton();
|
||||
}
|
||||
|
||||
/*Todo: after
|
||||
*//**
|
||||
* This method inflates the menu in the toolbar
|
||||
*//*
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
MenuInflater inflater = requireActivity().getMenuInflater();
|
||||
inflater.inflate(R.menu.menu_search, menu);
|
||||
return super.onCreateOptionsMenu(menu);
|
||||
}
|
||||
|
||||
*//**
|
||||
* This method handles the logic on ItemSelect in toolbar menu
|
||||
* Currently only 1 choice is available to open search page of the app
|
||||
*//*
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
|
||||
// Handle item selection
|
||||
switch (item.getItemId()) {
|
||||
case R.id.action_search:
|
||||
NavigationBaseActivity.startActivityWithFlags(this, SearchActivity.class);
|
||||
return true;
|
||||
default:
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
}*/
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -16,14 +16,14 @@ import android.view.View;
|
|||
import android.view.ViewGroup;
|
||||
import android.widget.Toast;
|
||||
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
import androidx.fragment.app.FragmentStatePagerAdapter;
|
||||
import androidx.viewpager.widget.ViewPager;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
import fr.free.nrw.commons.Media;
|
||||
|
|
@ -74,6 +74,11 @@ public class MediaDetailPagerFragment extends CommonsDaggerSupportFragment imple
|
|||
this.isFeaturedImage = isFeaturedImage;
|
||||
}
|
||||
|
||||
public MediaDetailPagerFragment(Boolean editable, boolean isFeaturedImage, MediaDetailProvider provider) {
|
||||
this(editable, isFeaturedImage);
|
||||
this.provider = provider;
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater,
|
||||
ViewGroup container,
|
||||
|
|
@ -130,10 +135,12 @@ public class MediaDetailPagerFragment extends CommonsDaggerSupportFragment imple
|
|||
* or a fragment
|
||||
*/
|
||||
private void initProvider() {
|
||||
if (getParentFragment() != null) {
|
||||
provider = (MediaDetailProvider) getParentFragment();
|
||||
} else {
|
||||
provider = (MediaDetailProvider) getActivity();
|
||||
if (provider == null) {
|
||||
if (getParentFragment() != null) {
|
||||
provider = (MediaDetailProvider) getParentFragment();
|
||||
} else {
|
||||
provider = (MediaDetailProvider) getActivity();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
86
app/src/main/java/fr/free/nrw/commons/navtab/NavTab.java
Normal file
86
app/src/main/java/fr/free/nrw/commons/navtab/NavTab.java
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
package fr.free.nrw.commons.navtab;
|
||||
|
||||
import androidx.annotation.DrawableRes;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.StringRes;
|
||||
import androidx.fragment.app.Fragment;
|
||||
|
||||
import org.wikipedia.model.EnumCode;
|
||||
import org.wikipedia.model.EnumCodeMap;
|
||||
|
||||
import fr.free.nrw.commons.R;
|
||||
import fr.free.nrw.commons.bookmarks.BookmarksFragment;
|
||||
import fr.free.nrw.commons.contributions.ContributionsMainFragment;
|
||||
import fr.free.nrw.commons.explore.ExploreFragment;
|
||||
|
||||
|
||||
public enum NavTab implements EnumCode {
|
||||
CONTRIBUTIONS(R.string.contributions_fragment, R.drawable.ic_person_black_24dp) {
|
||||
@NonNull
|
||||
@Override
|
||||
public Fragment newInstance() {
|
||||
return ContributionsMainFragment.newInstance();
|
||||
}
|
||||
}, EXPLORE(R.string.navigation_item_explore, R.drawable.ic_globe) {
|
||||
@NonNull
|
||||
@Override
|
||||
public Fragment newInstance() {
|
||||
return ExploreFragment.newInstance();
|
||||
}
|
||||
},
|
||||
FAVORITES(R.string.favorites, R.drawable.ic_round_star_border_24px) {
|
||||
@NonNull
|
||||
@Override
|
||||
public Fragment newInstance() {
|
||||
return new BookmarksFragment();
|
||||
}
|
||||
},
|
||||
MORE(R.string.more, R.drawable.ic_menu_black_24dp) {
|
||||
@NonNull
|
||||
@Override
|
||||
public Fragment newInstance() {
|
||||
return ContributionsMainFragment.newInstance();
|
||||
}
|
||||
};
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
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);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
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;
|
||||
|
||||
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() {
|
||||
for (int i = 0; i < NavTab.size(); i++) {
|
||||
NavTab navTab = NavTab.of(i);
|
||||
getMenu().add(Menu.NONE, i, i, navTab.text()).setIcon(navTab.icon());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -15,7 +15,7 @@ public abstract class BaseActivity extends CommonsDaggerAppCompatActivity {
|
|||
@Named("default_preferences")
|
||||
public JsonKvStore defaultKvStore;
|
||||
|
||||
protected CompositeDisposable compositeDisposable = new CompositeDisposable();
|
||||
public CompositeDisposable compositeDisposable = new CompositeDisposable();
|
||||
protected boolean wasPreviouslyDarkTheme;
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -1,45 +1,36 @@
|
|||
package fr.free.nrw.commons.theme;
|
||||
|
||||
import android.accounts.Account;
|
||||
import android.accounts.AccountManager;
|
||||
import android.app.ActivityManager;
|
||||
import android.content.ActivityNotFoundException;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import com.google.android.material.navigation.NavigationView;
|
||||
import androidx.core.view.GravityCompat;
|
||||
import androidx.drawerlayout.widget.DrawerLayout;
|
||||
import androidx.appcompat.app.ActionBarDrawerToggle;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.google.android.material.navigation.NavigationView;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
|
||||
import butterknife.BindView;
|
||||
import fr.free.nrw.commons.AboutActivity;
|
||||
import fr.free.nrw.commons.BuildConfig;
|
||||
import fr.free.nrw.commons.CommonsApplication;
|
||||
import fr.free.nrw.commons.R;
|
||||
import fr.free.nrw.commons.WelcomeActivity;
|
||||
import fr.free.nrw.commons.achievements.AchievementsActivity;
|
||||
import fr.free.nrw.commons.auth.LoginActivity;
|
||||
import fr.free.nrw.commons.bookmarks.BookmarksActivity;
|
||||
import fr.free.nrw.commons.contributions.MainActivity;
|
||||
import fr.free.nrw.commons.explore.categories.ExploreActivity;
|
||||
import fr.free.nrw.commons.kvstore.JsonKvStore;
|
||||
import fr.free.nrw.commons.logging.CommonsLogSender;
|
||||
import fr.free.nrw.commons.notification.NotificationActivity;
|
||||
import fr.free.nrw.commons.review.ReviewActivity;
|
||||
import fr.free.nrw.commons.settings.SettingsActivity;
|
||||
import timber.log.Timber;
|
||||
|
|
@ -51,47 +42,17 @@ public abstract class NavigationBaseActivity extends BaseActivity
|
|||
|
||||
@BindView(R.id.toolbar)
|
||||
Toolbar toolbar;
|
||||
@BindView(R.id.navigation_view)
|
||||
NavigationView navigationView;
|
||||
@BindView(R.id.drawer_layout)
|
||||
DrawerLayout drawerLayout;
|
||||
@Inject
|
||||
@Named("default_preferences")
|
||||
JsonKvStore applicationKvStore;
|
||||
@Inject CommonsLogSender commonsLogSender;
|
||||
@Inject
|
||||
CommonsLogSender commonsLogSender;
|
||||
|
||||
|
||||
private ActionBarDrawerToggle toggle;
|
||||
|
||||
public void initDrawer() {
|
||||
navigationView.setNavigationItemSelectedListener(this);
|
||||
|
||||
setSupportActionBar(toolbar);
|
||||
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
||||
toggle = new ActionBarDrawerToggle(this, drawerLayout, toolbar,
|
||||
R.string.navigation_drawer_open, R.string.navigation_drawer_close);
|
||||
drawerLayout.addDrawerListener(toggle);
|
||||
toggle.setDrawerIndicatorEnabled(true);
|
||||
toggle.syncState();
|
||||
setUserName();
|
||||
Menu nav_Menu = navigationView.getMenu();
|
||||
View headerLayout = navigationView.getHeaderView(0);
|
||||
ImageView userIcon = headerLayout.findViewById(R.id.user_icon);
|
||||
if (applicationKvStore.getBoolean("login_skipped", false)) {
|
||||
userIcon.setVisibility(View.GONE);
|
||||
nav_Menu.findItem(R.id.action_login).setVisible(true);
|
||||
nav_Menu.findItem(R.id.action_home).setVisible(false);
|
||||
nav_Menu.findItem(R.id.action_settings).setVisible(true);
|
||||
nav_Menu.findItem(R.id.action_logout).setVisible(false);
|
||||
nav_Menu.findItem(R.id.action_bookmarks).setVisible(true);
|
||||
}else {
|
||||
userIcon.setVisibility(View.VISIBLE);
|
||||
nav_Menu.findItem(R.id.action_login).setVisible(false);
|
||||
nav_Menu.findItem(R.id.action_home).setVisible(true);
|
||||
nav_Menu.findItem(R.id.action_settings).setVisible(true);
|
||||
nav_Menu.findItem(R.id.action_logout).setVisible(true);
|
||||
nav_Menu.findItem(R.id.action_bookmarks).setVisible(true);
|
||||
}
|
||||
}
|
||||
|
||||
public void changeDrawerIconToBackButton() {
|
||||
|
|
@ -110,19 +71,6 @@ public abstract class NavigationBaseActivity extends BaseActivity
|
|||
* Set the username in navigationHeader.
|
||||
*/
|
||||
private void setUserName() {
|
||||
|
||||
View navHeaderView = navigationView.getHeaderView(0);
|
||||
TextView username = navHeaderView.findViewById(R.id.username);
|
||||
AccountManager accountManager = AccountManager.get(this);
|
||||
Account[] allAccounts = accountManager.getAccountsByType(BuildConfig.ACCOUNT_TYPE);
|
||||
if (allAccounts.length != 0) {
|
||||
username.setText(allAccounts[0].name);
|
||||
}
|
||||
ImageView userIcon = navHeaderView.findViewById(R.id.user_icon);
|
||||
userIcon.setOnClickListener(v -> {
|
||||
drawerLayout.closeDrawer(navigationView);
|
||||
AchievementsActivity.startYourself(NavigationBaseActivity.this);
|
||||
});
|
||||
}
|
||||
|
||||
public void initBackButton() {
|
||||
|
|
@ -151,7 +99,6 @@ public abstract class NavigationBaseActivity extends BaseActivity
|
|||
final int itemId = item.getItemId();
|
||||
switch (itemId) {
|
||||
case R.id.action_login:
|
||||
drawerLayout.closeDrawer(navigationView);
|
||||
startActivityWithFlags(
|
||||
this, LoginActivity.class, Intent.FLAG_ACTIVITY_CLEAR_TOP,
|
||||
Intent.FLAG_ACTIVITY_SINGLE_TOP);
|
||||
|
|
@ -159,27 +106,22 @@ public abstract class NavigationBaseActivity extends BaseActivity
|
|||
finish();
|
||||
return true;
|
||||
case R.id.action_home:
|
||||
drawerLayout.closeDrawer(navigationView);
|
||||
startActivityWithFlags(
|
||||
this, MainActivity.class, Intent.FLAG_ACTIVITY_CLEAR_TOP,
|
||||
Intent.FLAG_ACTIVITY_SINGLE_TOP);
|
||||
return true;
|
||||
case R.id.action_about:
|
||||
drawerLayout.closeDrawer(navigationView);
|
||||
startActivityWithFlags(this, AboutActivity.class, Intent.FLAG_ACTIVITY_REORDER_TO_FRONT,
|
||||
Intent.FLAG_ACTIVITY_SINGLE_TOP);
|
||||
return true;
|
||||
case R.id.action_settings:
|
||||
drawerLayout.closeDrawer(navigationView);
|
||||
startActivityWithFlags(this, SettingsActivity.class, Intent.FLAG_ACTIVITY_REORDER_TO_FRONT,
|
||||
Intent.FLAG_ACTIVITY_SINGLE_TOP);
|
||||
return true;
|
||||
case R.id.action_introduction:
|
||||
drawerLayout.closeDrawer(navigationView);
|
||||
WelcomeActivity.startYourself(this);
|
||||
return true;
|
||||
case R.id.action_feedback:
|
||||
drawerLayout.closeDrawer(navigationView);
|
||||
|
||||
String technicalInfo = commonsLogSender.getExtraInfo();
|
||||
|
||||
|
|
@ -211,16 +153,13 @@ public abstract class NavigationBaseActivity extends BaseActivity
|
|||
.show();
|
||||
return true;
|
||||
case R.id.action_explore:
|
||||
drawerLayout.closeDrawer(navigationView);
|
||||
ExploreActivity.startYourself(this);
|
||||
return true;
|
||||
case R.id.action_bookmarks:
|
||||
drawerLayout.closeDrawer(navigationView);
|
||||
BookmarksActivity.startYourself(this);
|
||||
return true;
|
||||
|
||||
case R.id.action_review:
|
||||
drawerLayout.closeDrawer(navigationView);
|
||||
ReviewActivity.startYourself(this, getString(R.string.title_activity_review));
|
||||
return true;
|
||||
default:
|
||||
|
|
@ -244,7 +183,7 @@ public abstract class NavigationBaseActivity extends BaseActivity
|
|||
|
||||
public static <T> void startActivityWithFlags(Context context, Class<T> cls, int... flags) {
|
||||
Intent intent = new Intent(context, cls);
|
||||
for (int flag: flags) {
|
||||
for (int flag : flags) {
|
||||
intent.addFlags(flag);
|
||||
}
|
||||
context.startActivity(intent);
|
||||
|
|
@ -257,7 +196,7 @@ public abstract class NavigationBaseActivity extends BaseActivity
|
|||
protected void onNewIntent(Intent intent) {
|
||||
super.onNewIntent(intent);
|
||||
if ((intent.getFlags() | Intent.FLAG_ACTIVITY_REORDER_TO_FRONT) > 0) {
|
||||
isRestoredToTop = true;
|
||||
isRestoredToTop = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -277,23 +216,19 @@ public abstract class NavigationBaseActivity extends BaseActivity
|
|||
|
||||
/**
|
||||
* Handles visibility of navigation base toolbar
|
||||
*
|
||||
* @param show : Used to handle visibility of toolbar
|
||||
*/
|
||||
public void setNavigationBaseToolbarVisibility(boolean show){
|
||||
if (show){
|
||||
public void setNavigationBaseToolbarVisibility(boolean show) {
|
||||
if (show) {
|
||||
toolbar.setVisibility(View.VISIBLE);
|
||||
}else {
|
||||
} else {
|
||||
toolbar.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
DrawerLayout drawer = findViewById(R.id.drawer_layout);
|
||||
if (drawer.isDrawerOpen(GravityCompat.START)) {
|
||||
drawer.closeDrawer(GravityCompat.START);
|
||||
} else {
|
||||
super.onBackPressed();
|
||||
}
|
||||
super.onBackPressed();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
5
app/src/main/res/color/color_state_nav_tab_dark.xml
Normal file
5
app/src/main/res/color/color_state_nav_tab_dark.xml
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:state_checked="true" android:color="@color/primaryDarkColor" />
|
||||
<item android:color="@color/nav_tab_icon_unselected_color" />
|
||||
</selector>
|
||||
5
app/src/main/res/color/color_state_nav_tab_light.xml
Normal file
5
app/src/main/res/color/color_state_nav_tab_light.xml
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:state_checked="true" android:color="@color/primaryDarkColor" />
|
||||
<item android:color="@color/nav_tab_icon_unselected_color" />
|
||||
</selector>
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24.0"
|
||||
android:viewportHeight="24.0">
|
||||
<path
|
||||
android:fillColor="#FFFFFFFF"
|
||||
android:pathData="M17,3H7c-1.1,0 -1.99,0.9 -1.99,2L5,21l7,-3 7,3V5c0,-1.1 -0.9,-2 -2,-2z"/>
|
||||
</vector>
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24.0"
|
||||
android:viewportHeight="24.0">
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M12,10.9c-0.61,0 -1.1,0.49 -1.1,1.1s0.49,1.1 1.1,1.1c0.61,0 1.1,-0.49 1.1,-1.1s-0.49,-1.1 -1.1,-1.1zM12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM14.19,14.19L6,18l3.81,-8.19L18,6l-3.81,8.19z"/>
|
||||
</vector>
|
||||
27
app/src/main/res/drawable-xxhdpi/ic_globe.xml
Normal file
27
app/src/main/res/drawable-xxhdpi/ic_globe.xml
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24.0"
|
||||
android:viewportHeight="24.0">
|
||||
<path
|
||||
android:pathData="M8.91,2.49a10,10 0,1 0,12.6 6.42A10,10 0,0 0,8.91 2.49ZM14.47,19.61A8,8 0,1 1,19.61 9.53,8 8,0 0,1 14.47,19.61Z"
|
||||
android:fillColor="#000000"/>
|
||||
<path
|
||||
android:pathData="M3.35,7.45s2.5,1.82 7.26,0.27 5.71,-4.49 5.71,-4.49l1.11,1.22s-1.61,3.15 -6.36,4.7 -7.91,-0.06 -7.91,-0.06Z"
|
||||
android:fillColor="#000000"/>
|
||||
<path
|
||||
android:pathData="M7.52,20.29s1,-2.94 5.71,-4.49 7.26,0.27 7.26,0.27l0.18,-1.64s-3.15,-1.61 -7.91,-0.06 -6.36,4.7 -6.36,4.7Z"
|
||||
android:fillColor="#000000"/>
|
||||
<path
|
||||
android:pathData="M3.97,13.82l15.6,-5.07l0.46,1.43l-6.81,2.21l-8.79,2.86l-0.46,-1.43z"
|
||||
android:fillColor="#000000"/>
|
||||
<path
|
||||
android:pathData="M15.8,10.76A9.77,9.77 0,0 0,9.48 4.26l1.25,-1a11.16,11.16 0,0 1,6.49 7,11.16 11.16,0 0,1 -1.12,9.51l-1.6,-0.07A9.77,9.77 0,0 0,15.8 10.76Z"
|
||||
android:fillColor="#000000"/>
|
||||
<path
|
||||
android:pathData="M8.2,13.24a9.77,9.77 0,0 1,1.29 -9l-1.6,-0.07A11.16,11.16 0,0 0,6.77 13.7a11.16,11.16 0,0 0,6.49 7l1.25,-1A9.77,9.77 0,0 1,8.2 13.24Z"
|
||||
android:fillColor="#000000"/>
|
||||
<path
|
||||
android:pathData="M8.754,4.438l1.427,-0.464l5.068,15.597l-1.427,0.464z"
|
||||
android:fillColor="#000000"/>
|
||||
</vector>
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
<vector android:height="24dp" android:tint="#FFFFFF"
|
||||
android:viewportHeight="24.0" android:viewportWidth="24.0"
|
||||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="#FF000000" android:pathData="M19,9h-4V3H9v6H5l7,7 7,-7zM5,18v2h14v-2H5z"/>
|
||||
<path android:fillColor="@color/white" android:pathData="M19,9h-4V3H9v6H5l7,7 7,-7zM5,18v2h14v-2H5z"/>
|
||||
</vector>
|
||||
|
|
|
|||
5
app/src/main/res/drawable/ic_menu_black_24dp.xml
Normal file
5
app/src/main/res/drawable/ic_menu_black_24dp.xml
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
<vector android:autoMirrored="true" android:height="24dp"
|
||||
android:viewportHeight="24.0" android:viewportWidth="24.0"
|
||||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="#FF000000" android:pathData="M3,18h18v-2L3,16v2zM3,13h18v-2L3,11v2zM3,6v2h18L21,6L3,6z"/>
|
||||
</vector>
|
||||
|
|
@ -1,9 +1,5 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:viewportWidth="30.928"
|
||||
android:viewportHeight="30.928"
|
||||
android:width="30.928dp"
|
||||
android:height="30.928dp">
|
||||
<path
|
||||
android:pathData="M24.791 4.451C24.811 3.503 24.775 2.904 24.775 2.904l-9.264 -0.007 0 0 -0.047 0 -0.047 0 0 0 -9.265 0.007c0 0 -0.035 0.599 -0.015 1.547L0 4.451 0 5.463c0 0.231 0.039 5.68 3.402 8.665 1.403 1.245 3.153 1.871 5.216 1.872 0.312 0 0.633 -0.021 0.958 -0.049 1.172 1.605 2.526 2.729 4.049 3.289l0 4.445 -4.471 0 0 2.784 -1.477 0 0 1.561 7.74 0 0.094 0 7.74 0 0 -1.56 -1.478 0 0 -2.784 -4.471 0 0 -4.445c1.522 -0.56 2.877 -1.684 4.049 -3.289 0.327 0.028 0.648 0.048 0.96 0.048 2.062 -0.002 3.812 -0.627 5.215 -1.873 3.363 -2.985 3.402 -8.434 3.402 -8.665l0 -1.011 -6.137 0zM4.752 12.619C2.831 10.919 2.263 8.009 2.095 6.475l4.158 0c0.176 1.911 0.59 4.292 1.545 6.385 0.175 0.384 0.359 0.748 0.547 1.104C6.912 13.909 5.706 13.462 4.752 12.619Zm21.424 0c-0.953 0.844 -2.16 1.29 -3.592 1.345 0.188 -0.355 0.372 -0.72 0.547 -1.104 0.955 -2.093 1.369 -4.474 1.544 -6.385l4.158 0c-0.168 1.533 -0.735 4.443 -2.657 6.144z"
|
||||
android:fillColor="#fff" />
|
||||
</vector>
|
||||
<vector android:autoMirrored="true" android:height="24dp"
|
||||
android:viewportHeight="24.0" android:viewportWidth="24.0"
|
||||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="#FF000000" android:pathData="M12,12c2.21,0 4,-1.79 4,-4s-1.79,-4 -4,-4 -4,1.79 -4,4 1.79,4 4,4zM12,14c-2.67,0 -8,1.34 -8,4v2h16v-2c0,-2.66 -5.33,-4 -8,-4z"/>
|
||||
</vector>
|
||||
|
|
|
|||
|
|
@ -1,46 +1,32 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.drawerlayout.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/drawer_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="?attr/contributionsListBackground"
|
||||
>
|
||||
android:paddingBottom="?attr/actionBarSize"
|
||||
android:gravity="center_horizontal">
|
||||
|
||||
<RelativeLayout
|
||||
<com.google.android.material.tabs.TabLayout
|
||||
android:id="@+id/tab_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?attr/tabBackground"
|
||||
app:tabIndicatorColor="?attr/tabIndicatorColor"
|
||||
app:tabMode="fixed"
|
||||
app:tabSelectedTextColor="?attr/tabSelectedTextColor"
|
||||
app:tabTextColor="?attr/tabTextColor" />
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/contributionsFragmentContainer"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center_horizontal"
|
||||
>
|
||||
<include layout="@layout/toolbar"/>
|
||||
android:layout_below="@id/tab_layout"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<com.google.android.material.tabs.TabLayout
|
||||
android:id="@+id/tab_layout"
|
||||
<fr.free.nrw.commons.contributions.UnswipableViewPager
|
||||
android:id="@+id/ContPager"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?attr/tabBackground"
|
||||
app:tabIndicatorColor="?attr/tabIndicatorColor"
|
||||
app:tabSelectedTextColor="?attr/tabSelectedTextColor"
|
||||
app:tabTextColor="?attr/tabTextColor"
|
||||
android:layout_below="@id/toolbar"
|
||||
app:tabMode="fixed" />
|
||||
android:layout_height="match_parent" />
|
||||
</FrameLayout>
|
||||
|
||||
<FrameLayout android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:id="@+id/contributionsFragmentContainer"
|
||||
android:orientation="horizontal"
|
||||
android:layout_below="@id/tab_layout">
|
||||
|
||||
<fr.free.nrw.commons.contributions.UnswipableViewPager
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/pager"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
<include layout="@layout/drawer_view" />
|
||||
|
||||
</androidx.drawerlayout.widget.DrawerLayout>
|
||||
</RelativeLayout>
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:paddingBottom="?attr/actionBarSize"
|
||||
android:orientation="vertical">
|
||||
|
||||
<com.google.android.material.tabs.TabLayout
|
||||
|
|
|
|||
|
|
@ -1,15 +1,13 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
>
|
||||
android:orientation="vertical">
|
||||
|
||||
<androidx.viewpager.widget.ViewPager
|
||||
android:id="@+id/mediaDetailsPager"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:fadingEdge="none"
|
||||
/>
|
||||
android:fadingEdge="none" />
|
||||
|
||||
</LinearLayout>
|
||||
|
|
@ -1,67 +1,90 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="2dp"
|
||||
android:paddingBottom="0dp"
|
||||
>
|
||||
android:orientation="vertical"
|
||||
android:padding="2dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/categoryImagesSequenceNumber"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textSize="98sp"
|
||||
android:textColor="#33FFFFFF"
|
||||
android:typeface="serif"
|
||||
android:layout_gravity="end|bottom"
|
||||
/>
|
||||
android:textColor="#33FFFFFF"
|
||||
android:textSize="98sp"
|
||||
android:typeface="serif"
|
||||
android:visibility="gone" />
|
||||
|
||||
<com.facebook.drawee.view.SimpleDraweeView
|
||||
android:id="@+id/categoryImageView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="240dp"
|
||||
app:actualImageScaleType="centerCrop"
|
||||
/>
|
||||
app:actualImageScaleType="centerCrop" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center|bottom"
|
||||
android:background="#AA000000"
|
||||
android:orientation="vertical"
|
||||
android:padding="@dimen/small_gap"
|
||||
>
|
||||
<ProgressBar
|
||||
android:id="@+id/categoryProgress"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
style="@style/ProgressBar"
|
||||
android:indeterminateOnly="false"
|
||||
android:max="100"
|
||||
android:visibility="gone"
|
||||
/>
|
||||
android:orientation="horizontal">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/categoryImageTitle"
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:orientation="vertical"
|
||||
android:paddingTop="8dp"
|
||||
android:paddingBottom="32dp">
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/categoryProgress"
|
||||
style="@style/ProgressBar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:indeterminateOnly="false"
|
||||
android:max="100"
|
||||
android:visibility="gone" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/categoryImageTitle"
|
||||
style="?android:textAppearanceMedium"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:paddingStart="8dp"
|
||||
android:paddingEnd="8dp"
|
||||
android:textColor="@color/black" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/categoryImageAuthor"
|
||||
style="?android:textAppearanceSmall"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:paddingStart="8dp"
|
||||
android:paddingEnd="8dp"
|
||||
android:textColor="@color/nav_tab_icon_unselected_color" />
|
||||
</LinearLayout>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/favorite"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textColor="#FFFFFFFF"
|
||||
style="?android:textAppearanceLarge"
|
||||
android:maxLines="1"
|
||||
android:ellipsize="end"
|
||||
/>
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:contentDescription="@null"
|
||||
android:tint="@color/nav_tab_icon_unselected_color"
|
||||
app:srcCompat="@drawable/ic_round_star_filled_24px" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/categoryImageAuthor"
|
||||
<ImageView
|
||||
android:id="@+id/download"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textColor="#FFFFFFFF"
|
||||
style="?android:textAppearanceMedium"
|
||||
android:maxLines="1"
|
||||
android:ellipsize="end"
|
||||
/>
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:contentDescription="@null"
|
||||
android:tint="@color/nav_tab_icon_unselected_color"
|
||||
app:srcCompat="@drawable/ic_download_white_24dp" />
|
||||
</LinearLayout>
|
||||
|
||||
</FrameLayout>
|
||||
</LinearLayout>
|
||||
39
app/src/main/res/layout/main.xml
Normal file
39
app/src/main/res/layout/main.xml
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center_horizontal">
|
||||
|
||||
<include layout="@layout/toolbar" />
|
||||
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/contributionsFragmentContainer"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_below="@id/tab_layout"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<fr.free.nrw.commons.contributions.UnswipableViewPager
|
||||
android:id="@+id/pager"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
<fr.free.nrw.commons.navtab.NavTabLayout
|
||||
android:id="@+id/fragment_main_nav_tab_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="?attr/actionBarSize"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:layout_gravity="bottom"
|
||||
android:background="@android:color/white"
|
||||
android:elevation="6dp"
|
||||
app:itemIconTint="?attr/nav_tab_item_color_state"
|
||||
app:itemTextColor="?attr/colorPrimaryDark"
|
||||
app:tabGravity="fill"
|
||||
app:tabIndicatorColor="@android:color/transparent" />
|
||||
</RelativeLayout>
|
||||
|
||||
|
|
@ -27,6 +27,7 @@
|
|||
<attr name="mainCardBackground" format="reference"/>
|
||||
<attr name="mainScreenNearbyPermissionbutton" format="reference"/>
|
||||
<attr name="icon" format="reference"/>
|
||||
<attr name="nav_tab_item_color_state" format="reference" />
|
||||
|
||||
|
||||
<declare-styleable name="CompatTextView">
|
||||
|
|
|
|||
|
|
@ -69,4 +69,5 @@
|
|||
<color name="swipe_red" tools:ignore="MissingDefaultResource">#FF0000</color>
|
||||
<color name="yes_button_color">#B22222</color>
|
||||
<color name="no_button_color">#006400</color>
|
||||
<color name="nav_tab_icon_unselected_color">#61000000</color>
|
||||
</resources>
|
||||
|
|
|
|||
|
|
@ -540,4 +540,10 @@ Upload your first media by tapping on the add button.</string>
|
|||
<string name="share_text">Upload photos to Wikimedia Commons on your phone Download the Commons app: %1$s</string>
|
||||
<string name="share_via">Share app via...</string>
|
||||
<string name="image_info">Image Info</string>
|
||||
|
||||
<!-- Hackathon-->
|
||||
|
||||
<string name="favorites">Favorites</string>
|
||||
<string name="more">More</string>
|
||||
|
||||
</resources>
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@
|
|||
<item name="textEnabled">@color/enabled_button_text_color_dark</item>
|
||||
<item name="mainCardBackground">@color/main_background_dark</item>
|
||||
<item name="mainScreenNearbyPermissionbutton">@style/DarkFlatNearbyPermissionButton</item>
|
||||
<item name="nav_tab_item_color_state">@color/color_state_nav_tab_dark</item>
|
||||
</style>
|
||||
|
||||
<style name="LightAppTheme" parent="Theme.AppCompat.Light.NoActionBar">
|
||||
|
|
@ -67,6 +68,7 @@
|
|||
<item name="textEnabled">@color/enabled_button_text_color_light</item>
|
||||
<item name="mainCardBackground">@color/primaryDarkColor</item>
|
||||
<item name="mainScreenNearbyPermissionbutton">@style/LightFlatNearbyPermissionButton</item>
|
||||
<item name="nav_tab_item_color_state">@color/color_state_nav_tab_light</item>
|
||||
</style>
|
||||
|
||||
<style name="WhiteSearchBarTheme" parent="DarkAppTheme">
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue