jenkins-bot has submitted this change and it was merged. ( 
https://gerrit.wikimedia.org/r/367400 )

Change subject: Update permissions logic for compilations.
......................................................................


Update permissions logic for compilations.

This restricts the request for Read permissions to the CompilationActivity,
and removes the request from the Feed and from PageActivity.

Note: this leaves the framework for asking for the Read permission in
BaseActivity, in case we need to bring back the automatic permission logic
when launching other activities.

This also detects whether the user selected "Never ask again" in the
permission dialog, by making use of the
shouldShowRequestPermissionRationale() method, which returns false if the
user selects "Never ask again."  Unfortunately this method also returns
false if we've never asked for the permission before.  Therefore we need
to persist an additional variable ourselves that tracks whether we've
asked for the permission at least once.

Change-Id: I57012d752df0c4f55106487a37d4516a10252091
---
M app/src/main/java/org/wikipedia/activity/BaseActivity.java
M app/src/main/java/org/wikipedia/feed/FeedFragment.java
M app/src/main/java/org/wikipedia/main/MainActivity.java
M app/src/main/java/org/wikipedia/main/MainFragment.java
M app/src/main/java/org/wikipedia/offline/LocalCompilationsActivity.java
M app/src/main/java/org/wikipedia/offline/LocalCompilationsFragment.java
M app/src/main/java/org/wikipedia/page/PageActivity.java
M app/src/main/java/org/wikipedia/settings/Prefs.java
M app/src/main/java/org/wikipedia/util/PermissionUtil.java
M app/src/main/res/layout/fragment_local_compilations.xml
M app/src/main/res/values-qq/strings.xml
M app/src/main/res/values/preference_keys.xml
M app/src/main/res/values/strings.xml
13 files changed, 74 insertions(+), 31 deletions(-)

Approvals:
  jenkins-bot: Verified
  Mholloway: Looks good to me, approved



diff --git a/app/src/main/java/org/wikipedia/activity/BaseActivity.java 
b/app/src/main/java/org/wikipedia/activity/BaseActivity.java
index 1de62c6..5f9cce6 100644
--- a/app/src/main/java/org/wikipedia/activity/BaseActivity.java
+++ b/app/src/main/java/org/wikipedia/activity/BaseActivity.java
@@ -54,10 +54,6 @@
         }
     }
 
-    public void updateOfflineCompilations() {
-        searchOfflineCompilationsWithPermission(true);
-    }
-
     protected void requestFullUserOrientation() {
         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
             setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_FULL_USER);
@@ -86,10 +82,13 @@
         switch (requestCode) {
             case 
Constants.ACTIVITY_REQUEST_READ_EXTERNAL_STORAGE_PERMISSION_OFFLINE:
                 if (PermissionUtil.isPermitted(grantResults)) {
-                    searchOfflineCompilations(false);
+                    searchOfflineCompilations(true);
                 } else {
                     L.i("Read permission was denied by user");
-                    showReadPermissionSnackbar();
+                    onOfflineCompilationsError(new 
RuntimeException(getString(R.string.offline_read_permission_error)));
+                    if 
(PermissionUtil.shouldShowReadPermissionRationale(this)) {
+                        showReadPermissionSnackbar();
+                    }
                 }
                 break;
             default:
@@ -139,9 +138,12 @@
             // TODO: enable when ready for production.
             return;
         }
-        if (!(PermissionUtil.hasReadExternalStoragePermission(this))) {
-            PermissionUtil.requestReadStorageRuntimePermissions(this,
-                    
Constants.ACTIVITY_REQUEST_READ_EXTERNAL_STORAGE_PERMISSION_OFFLINE);
+        if (!PermissionUtil.hasReadExternalStoragePermission(this)) {
+            if (PermissionUtil.shouldShowReadPermissionRationale(this)) {
+                requestReadPermission();
+            } else {
+                onOfflineCompilationsError(new 
RuntimeException(getString(R.string.offline_read_permission_error)));
+            }
         } else {
             searchOfflineCompilations(force);
         }
@@ -168,13 +170,18 @@
         }
     }
 
+    private void requestReadPermission() {
+        PermissionUtil.requestReadStorageRuntimePermissions(BaseActivity.this,
+                
Constants.ACTIVITY_REQUEST_READ_EXTERNAL_STORAGE_PERMISSION_OFFLINE);
+    }
+
     private void showReadPermissionSnackbar() {
         Snackbar snackbar = FeedbackUtil.makeSnackbar(this,
                 getString(R.string.offline_read_permission_rationale), 
FeedbackUtil.LENGTH_DEFAULT);
         snackbar.setAction(R.string.page_error_retry, new 
View.OnClickListener() {
             @Override
             public void onClick(View v) {
-                searchOfflineCompilationsWithPermission(false);
+                requestReadPermission();
             }
         });
         snackbar.show();
diff --git a/app/src/main/java/org/wikipedia/feed/FeedFragment.java 
b/app/src/main/java/org/wikipedia/feed/FeedFragment.java
index 5d1276a..315c86e 100644
--- a/app/src/main/java/org/wikipedia/feed/FeedFragment.java
+++ b/app/src/main/java/org/wikipedia/feed/FeedFragment.java
@@ -20,7 +20,6 @@
 import org.wikipedia.BuildConfig;
 import org.wikipedia.R;
 import org.wikipedia.WikipediaApp;
-import org.wikipedia.activity.BaseActivity;
 import org.wikipedia.activity.FragmentUtil;
 import org.wikipedia.analytics.FeedFunnel;
 import org.wikipedia.feed.featured.FeaturedArticleCard;
@@ -36,7 +35,6 @@
 import org.wikipedia.offline.LocalCompilationsActivity;
 import org.wikipedia.settings.Prefs;
 import org.wikipedia.settings.SettingsActivity;
-import org.wikipedia.util.DeviceUtil;
 import org.wikipedia.util.FeedbackUtil;
 import org.wikipedia.util.ResourceUtil;
 import org.wikipedia.util.ThrowableUtil;
@@ -109,9 +107,6 @@
         swipeRefreshLayout.setOnRefreshListener(new 
SwipeRefreshLayout.OnRefreshListener() {
             @Override
             public void onRefresh() {
-                if (!DeviceUtil.isOnline()) {
-                    ((BaseActivity) getActivity()).updateOfflineCompilations();
-                }
                 refresh();
             }
         });
@@ -255,7 +250,7 @@
         return false;
     }
 
-    public void onOfflineCompilationsFound() {
+    public void onGoOffline() {
         refresh();
     }
 
diff --git a/app/src/main/java/org/wikipedia/main/MainActivity.java 
b/app/src/main/java/org/wikipedia/main/MainActivity.java
index 6704d91..c9403e7 100644
--- a/app/src/main/java/org/wikipedia/main/MainActivity.java
+++ b/app/src/main/java/org/wikipedia/main/MainActivity.java
@@ -85,11 +85,6 @@
     }
 
     @Override
-    protected void onOfflineCompilationsFound() {
-        getFragment().onOfflineCompilationsFound();
-    }
-
-    @Override
     protected void onNewIntent(Intent intent) {
         super.onNewIntent(intent);
         setIntent(intent);
@@ -98,7 +93,7 @@
 
     @Override
     protected void onGoOffline() {
-        searchOfflineCompilationsWithPermission(false);
+        getFragment().onGoOffline();
     }
 
     @Override
diff --git a/app/src/main/java/org/wikipedia/main/MainFragment.java 
b/app/src/main/java/org/wikipedia/main/MainFragment.java
index 5a278e3..3e53edb 100644
--- a/app/src/main/java/org/wikipedia/main/MainFragment.java
+++ b/app/src/main/java/org/wikipedia/main/MainFragment.java
@@ -428,10 +428,10 @@
         tabLayout.setVisibility(visible ? View.VISIBLE : View.GONE);
     }
 
-    public void onOfflineCompilationsFound() {
+    public void onGoOffline() {
         Fragment fragment = ((NavTabFragmentPagerAdapter) 
viewPager.getAdapter()).getCurrentFragment();
         if (fragment instanceof FeedFragment) {
-            ((FeedFragment) fragment).onOfflineCompilationsFound();
+            ((FeedFragment) fragment).onGoOffline();
         }
     }
 
diff --git 
a/app/src/main/java/org/wikipedia/offline/LocalCompilationsActivity.java 
b/app/src/main/java/org/wikipedia/offline/LocalCompilationsActivity.java
index 28cdc43..8be08cd 100644
--- a/app/src/main/java/org/wikipedia/offline/LocalCompilationsActivity.java
+++ b/app/src/main/java/org/wikipedia/offline/LocalCompilationsActivity.java
@@ -44,6 +44,6 @@
 
     @Override
     public void onRequestUpdateCompilations() {
-        updateOfflineCompilations();
+        searchOfflineCompilationsWithPermission(true);
     }
 }
diff --git 
a/app/src/main/java/org/wikipedia/offline/LocalCompilationsFragment.java 
b/app/src/main/java/org/wikipedia/offline/LocalCompilationsFragment.java
index 1507856..b1cc77b 100644
--- a/app/src/main/java/org/wikipedia/offline/LocalCompilationsFragment.java
+++ b/app/src/main/java/org/wikipedia/offline/LocalCompilationsFragment.java
@@ -26,6 +26,7 @@
 import org.wikipedia.views.DrawableItemDecoration;
 import org.wikipedia.views.PageItemView;
 import org.wikipedia.views.SearchEmptyView;
+import org.wikipedia.views.WikiErrorView;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -42,9 +43,11 @@
     @BindView(R.id.compilation_search_progress_bar) ProgressBar progressBar;
     @BindView(R.id.compilations_count_text) TextView countText;
     @BindView(R.id.disk_usage_view) DiskUsageView diskUsageView;
+    @BindView(R.id.compilation_search_error) WikiErrorView errorView;
     private Unbinder unbinder;
 
     private boolean updating;
+    private Throwable lastError;
     private CompilationItemAdapter adapter = new CompilationItemAdapter();
     private ItemCallback itemCallback = new ItemCallback();
 
@@ -73,6 +76,13 @@
         recyclerView.setAdapter(adapter);
         recyclerView.addItemDecoration(new DrawableItemDecoration(getContext(),
                 ResourceUtil.getThemedAttributeId(getContext(), 
R.attr.list_separator_drawable), true));
+
+        errorView.setBackClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                getActivity().finish();
+            }
+        });
 
         beginUpdate();
         return view;
@@ -119,16 +129,19 @@
 
     public void onCompilationsRefreshed() {
         updating = false;
+        lastError = null;
         update();
     }
 
     public void onCompilationsError(Throwable t) {
         updating = false;
-        // TODO: show error
+        lastError = t;
+        update();
     }
 
     private void beginUpdate() {
         updating = true;
+        lastError = null;
         if (callback() != null) {
             callback().onRequestUpdateCompilations();
         }
@@ -163,6 +176,15 @@
     }
 
     private void updateEmptyState(@Nullable String searchQuery) {
+        if (lastError != null) {
+            errorView.setError(lastError);
+            errorView.setVisibility(View.VISIBLE);
+            progressBar.setVisibility(View.GONE);
+            searchEmptyView.setVisibility(View.GONE);
+            listContainer.setVisibility(View.GONE);
+            return;
+        }
+        errorView.setVisibility(View.GONE);
         if (updating) {
             progressBar.setVisibility(View.VISIBLE);
             searchEmptyView.setVisibility(View.GONE);
diff --git a/app/src/main/java/org/wikipedia/page/PageActivity.java 
b/app/src/main/java/org/wikipedia/page/PageActivity.java
index 94f18c2..8898b84 100644
--- a/app/src/main/java/org/wikipedia/page/PageActivity.java
+++ b/app/src/main/java/org/wikipedia/page/PageActivity.java
@@ -268,11 +268,6 @@
         handleIntent(intent);
     }
 
-    @Override
-    protected void onGoOffline() {
-        searchOfflineCompilationsWithPermission(false);
-    }
-
     private void handleIntent(@NonNull Intent intent) {
         if (Intent.ACTION_VIEW.equals(intent.getAction()) && intent.getData() 
!= null) {
             WikiSite wiki = new WikiSite(intent.getData().getAuthority());
diff --git a/app/src/main/java/org/wikipedia/settings/Prefs.java 
b/app/src/main/java/org/wikipedia/settings/Prefs.java
index 67a7820..f0f35d2 100644
--- a/app/src/main/java/org/wikipedia/settings/Prefs.java
+++ b/app/src/main/java/org/wikipedia/settings/Prefs.java
@@ -513,6 +513,14 @@
         setBoolean(R.string.preference_key_initial_onboarding_enabled, 
enabled);
     }
 
+    public static boolean askedForPermissionOnce(@NonNull String permission) {
+        return getBoolean(R.string.preference_key_permission_asked + 
permission, false);
+    }
+
+    public static void setAskedForPermissionOnce(@NonNull String permission) {
+        setBoolean(R.string.preference_key_permission_asked + permission, 
true);
+    }
+
     public static void setReadingListsCurrentUser(@Nullable String userName) {
         setString(R.string.preference_key_reading_lists_current_user_hash,
                 TextUtils.isEmpty(userName) ? "" : 
StringUtil.md5string(userName));
diff --git a/app/src/main/java/org/wikipedia/util/PermissionUtil.java 
b/app/src/main/java/org/wikipedia/util/PermissionUtil.java
index d5c88f0..986f329 100644
--- a/app/src/main/java/org/wikipedia/util/PermissionUtil.java
+++ b/app/src/main/java/org/wikipedia/util/PermissionUtil.java
@@ -1,13 +1,17 @@
 package org.wikipedia.util;
 
 import android.Manifest;
+import android.annotation.TargetApi;
 import android.content.Context;
 import android.content.pm.PackageManager;
+import android.os.Build;
 import android.support.annotation.NonNull;
 import android.support.v4.app.ActivityCompat;
 import android.support.v4.app.Fragment;
 import android.support.v4.content.ContextCompat;
 import android.support.v7.app.AppCompatActivity;
+
+import org.wikipedia.settings.Prefs;
 
 /**
  * Common methods for dealing with runtime permissions.
@@ -26,10 +30,17 @@
     }
 
     public static void requestReadStorageRuntimePermissions(AppCompatActivity 
activity, int requestCode) {
+        
Prefs.setAskedForPermissionOnce(Manifest.permission.READ_EXTERNAL_STORAGE);
         ActivityCompat.requestPermissions(activity, new 
String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, requestCode);
         // once permission is granted/denied it will continue with 
onRequestPermissionsResult
     }
 
+    @TargetApi(Build.VERSION_CODES.M)
+    public static boolean shouldShowReadPermissionRationale(@NonNull 
AppCompatActivity activity) {
+        return 
!Prefs.askedForPermissionOnce(Manifest.permission.READ_EXTERNAL_STORAGE)
+                || 
activity.shouldShowRequestPermissionRationale(Manifest.permission.READ_EXTERNAL_STORAGE);
+    }
+
     public static boolean hasWriteExternalStoragePermission(@NonNull Context 
context) {
         return ContextCompat.checkSelfPermission(context,
                 Manifest.permission.WRITE_EXTERNAL_STORAGE) == 
PackageManager.PERMISSION_GRANTED;
diff --git a/app/src/main/res/layout/fragment_local_compilations.xml 
b/app/src/main/res/layout/fragment_local_compilations.xml
index d46f054..d290bbc 100644
--- a/app/src/main/res/layout/fragment_local_compilations.xml
+++ b/app/src/main/res/layout/fragment_local_compilations.xml
@@ -75,6 +75,13 @@
             android:layout_height="wrap_content"
             android:layout_gravity="center"/>
 
+        <org.wikipedia.views.WikiErrorView
+            android:id="@+id/compilation_search_error"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:orientation="vertical"
+            android:layout_gravity="center"/>
+
     </FrameLayout>
 
 </LinearLayout>
diff --git a/app/src/main/res/values-qq/strings.xml 
b/app/src/main/res/values-qq/strings.xml
index 106dd35..066d05a 100644
--- a/app/src/main/res/values-qq/strings.xml
+++ b/app/src/main/res/values-qq/strings.xml
@@ -415,6 +415,7 @@
   <string name="description_edit_revert_reason2">Reason for an edit being 
reverted, because it looks like vandalism.</string>
   <string name="description_edit_revert_history">Message that allows the user 
to go to the edit history associated with the article. (Please preserve the 
anchor tag in its exact form)</string>
   <string name="offline_read_permission_rationale">Message explaining why we 
need permission to access the device storage when reading articles in offline 
mode.</string>
+  <string name="offline_read_permission_error">Error shown when the app could 
not read from the internal or external storage of the device due to permission 
not being granted.</string>
   <string name="offline_card_text">Message shown in the Feed card that informs 
the user that they are now browsing Wikipedia in offline mode.</string>
   <string name="offline_my_compilations">Button label for the user to access 
their list of compilations.</string>
   <string name="offline_compilations_title">Title shown on the toolbar of the 
activity for managing offline compilations.</string>
diff --git a/app/src/main/res/values/preference_keys.xml 
b/app/src/main/res/values/preference_keys.xml
index 1449bd4..dd6be63 100644
--- a/app/src/main/res/values/preference_keys.xml
+++ b/app/src/main/res/values/preference_keys.xml
@@ -57,4 +57,5 @@
     <string 
name="preference_key_reading_lists_remote_delete_pending">readingListsRemoteDeletePending</string>
     <string 
name="preference_key_initial_onboarding_enabled">initialOnboardingEnabled</string>
     <string 
name="preference_key_reading_lists_current_user_hash">readingListsCurrentUserHash</string>
+    <string name="preference_key_permission_asked">permissionAsked</string>
 </resources>
diff --git a/app/src/main/res/values/strings.xml 
b/app/src/main/res/values/strings.xml
index eb0f1a1..6830b46 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -469,6 +469,7 @@
 
     <!-- Offline -->
     <string name="offline_read_permission_rationale">Permission to access 
storage on your device is required for offline browsing. Please try again, and 
grant the requested permission.</string>
+    <string name="offline_read_permission_error">Permission not granted to 
read from device storage.</string>
     <string name="offline_card_text">You are now browsing Wikipedia in offline 
mode. Please note that offline articles may not be fully up to date with the 
online version.</string>
     <string name="offline_my_compilations">My compilations</string>
     <string name="offline_compilations_title">Offline compilations</string>

-- 
To view, visit https://gerrit.wikimedia.org/r/367400
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: merged
Gerrit-Change-Id: I57012d752df0c4f55106487a37d4516a10252091
Gerrit-PatchSet: 8
Gerrit-Project: apps/android/wikipedia
Gerrit-Branch: master
Gerrit-Owner: Dbrant <[email protected]>
Gerrit-Reviewer: Brion VIBBER <[email protected]>
Gerrit-Reviewer: Dbrant <[email protected]>
Gerrit-Reviewer: Mholloway <[email protected]>
Gerrit-Reviewer: jenkins-bot <>

_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to