From 262c6a7841cb575f93e7bc8f17d472b9ad84bf97 Mon Sep 17 00:00:00 2001 From: Andrey Yepin Date: Wed, 12 Mar 2025 10:37:36 -0700 Subject: Avoid drawer offset calculation if app targets are not yet processed. Fix: 338229069 Test: manual testing Flag: com.android.intentresolver.delay_drawer_offset_calculation Change-Id: Ie18ccfa044f5067e769219359e6507615566be78 --- aconfig/FeatureFlags.aconfig | 10 +++++++ .../android/intentresolver/ChooserActivity.java | 18 +++++------ .../android/intentresolver/ChooserListAdapter.java | 35 +++++++++++++++++++++- 3 files changed, 52 insertions(+), 11 deletions(-) diff --git a/aconfig/FeatureFlags.aconfig b/aconfig/FeatureFlags.aconfig index fe0dcffc..a5509b22 100644 --- a/aconfig/FeatureFlags.aconfig +++ b/aconfig/FeatureFlags.aconfig @@ -25,6 +25,16 @@ flag { } } +flag { + name: "delay_drawer_offset_calculation" + namespace: "intentresolver" + description: "Do not update the drawer offset until app targets are ready." + bug: "338229069" + metadata { + purpose: PURPOSE_BUGFIX + } +} + flag { name: "individual_metadata_title_read" namespace: "intentresolver" diff --git a/java/src/com/android/intentresolver/ChooserActivity.java b/java/src/com/android/intentresolver/ChooserActivity.java index d4cf82ff..aff34580 100644 --- a/java/src/com/android/intentresolver/ChooserActivity.java +++ b/java/src/com/android/intentresolver/ChooserActivity.java @@ -23,6 +23,7 @@ import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTE import static androidx.lifecycle.LifecycleKt.getCoroutineScope; import static com.android.intentresolver.ChooserActionFactory.EDIT_SOURCE; +import static com.android.intentresolver.Flags.delayDrawerOffsetCalculation; import static com.android.intentresolver.Flags.fixShortcutsFlashingFixed; import static com.android.intentresolver.Flags.interactiveSession; import static com.android.intentresolver.Flags.keyboardNavigationFix; @@ -2353,6 +2354,9 @@ public class ChooserActivity extends Hilt_ChooserActivity implements || recyclerView.computeVerticalScrollOffset() != 0) { return; } + if (delayDrawerOffsetCalculation() && !gridAdapter.getListAdapter().areAppTargetsReady()) { + return; + } final int availableWidth = right - left - v.getPaddingLeft() - v.getPaddingRight(); final int maxChooserWidth = getResources().getDimensionPixelSize(R.dimen.chooser_width); @@ -2381,7 +2385,7 @@ public class ChooserActivity extends Hilt_ChooserActivity implements } getMainThreadHandler().post(() -> { - if (mResolverDrawerLayout == null || gridAdapter == null) { + if (mResolverDrawerLayout == null) { return; } int offset = calculateDrawerOffset(top, bottom, recyclerView, gridAdapter); @@ -2482,15 +2486,9 @@ public class ChooserActivity extends Hilt_ChooserActivity implements //TODO: move this block inside ChooserListAdapter (should be called when // ResolverListAdapter#mPostListReadyRunnable is executed. - if (chooserListAdapter.getDisplayResolveInfoCount() == 0) { - Log.d(TAG, "getDisplayResolveInfoCount() == 0"); - if (rebuildComplete) { - onAppTargetsLoaded(listAdapter); - } - chooserListAdapter.notifyDataSetChanged(); - } else { - chooserListAdapter.updateAlphabeticalList(() -> onAppTargetsLoaded(listAdapter)); - } + chooserListAdapter.updateAlphabeticalList( + rebuildComplete, + () -> onAppTargetsLoaded(listAdapter)); if (rebuildComplete) { long duration = Tracer.INSTANCE.endAppTargetLoadingSection(listProfileUserHandle); diff --git a/java/src/com/android/intentresolver/ChooserListAdapter.java b/java/src/com/android/intentresolver/ChooserListAdapter.java index d743f859..7e5de74b 100644 --- a/java/src/com/android/intentresolver/ChooserListAdapter.java +++ b/java/src/com/android/intentresolver/ChooserListAdapter.java @@ -124,6 +124,21 @@ public class ChooserListAdapter extends ResolverListAdapter { private final ItemRevealAnimationTracker mAnimationTracker = new ItemRevealAnimationTracker(); + /** + * Indicates whether the app targets are ready. The flag is reset in + * {@link #rebuildList(boolean)} and set to true in {@link #updateAlphabeticalList(Runnable)}'s + * onPostExecute. + * There's one nuance though, {@link #updateAlphabeticalList(Runnable)} is called by the + * {@link ChooserActivity} only when {@link #rebuildList(boolean)} was called with {@code true} + * It is called with {@code false} only for inactive tabs in the + * MultiProfilePagerAdapter.rebuildTabs which, in turn, is called from either + * {@link ChooserActivity#recreatePagerAdapter} or {@link ChooserActivity#configureContentView} + * and, in both cases, there are no inactive pages in the MultiProfilePagerAdapter and + * {@link #rebuildList(boolean)} will be called with true upon navigation to the missing page. + * Yeah. + */ + private boolean mAppTargetsReady = false; + // For pinned direct share labels, if the text spans multiple lines, the TextView will consume // the full width, even if the characters actually take up less than that. Measure the actual // line widths and constrain the View's width based upon that so that the pin doesn't end up @@ -311,6 +326,13 @@ public class ChooserListAdapter extends ResolverListAdapter { } } + /** + * @return {@code true} if the app targets are ready. + */ + public final boolean areAppTargetsReady() { + return mAppTargetsReady; + } + /** * Set the enabled state for all targets. */ @@ -354,6 +376,7 @@ public class ChooserListAdapter extends ResolverListAdapter { public boolean rebuildList(boolean doPostProcessing) { mAnimationTracker.reset(); mSortedList.clear(); + mAppTargetsReady = false; boolean result = super.rebuildList(doPostProcessing); notifyDataSetChanged(); return result; @@ -518,7 +541,16 @@ public class ChooserListAdapter extends ResolverListAdapter { /** * Group application targets */ - public void updateAlphabeticalList(Runnable onCompleted) { + public void updateAlphabeticalList(boolean rebuildComplete, Runnable onCompleted) { + if (getDisplayResolveInfoCount() == 0) { + Log.d(TAG, "getDisplayResolveInfoCount() == 0"); + if (rebuildComplete) { + mAppTargetsReady = true; + onCompleted.run(); + } + notifyDataSetChanged(); + return; + } final DisplayResolveInfoAzInfoComparator comparator = new DisplayResolveInfoAzInfoComparator(mContext); ImmutableList displayList = getTargetsInCurrentDisplayList(); @@ -582,6 +614,7 @@ public class ChooserListAdapter extends ResolverListAdapter { protected void onPostExecute(List newList) { mSortedList.clear(); mSortedList.addAll(newList); + mAppTargetsReady = true; notifyDataSetChanged(); onCompleted.run(); } -- cgit v1.2.3-59-g8ed1b From 7267e8137f53bfed26969d4f7f2e4ee9b4988160 Mon Sep 17 00:00:00 2001 From: Bill Yi Date: Thu, 13 Mar 2025 19:31:04 -0700 Subject: Import translations. DO NOT MERGE ANYWHERE Auto-generated-cl: translation import Change-Id: I1e372ae6833d0b715f76cbb2e7191a136a6af910 --- java/res/values-bn/strings.xml | 2 +- java/res/values-ca/strings.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java/res/values-bn/strings.xml b/java/res/values-bn/strings.xml index 544f57de..69cbed55 100644 --- a/java/res/values-bn/strings.xml +++ b/java/res/values-bn/strings.xml @@ -56,7 +56,7 @@ "{count,plural, =1{আরও #টি ফাইল}one{আরও #টি ফাইল}other{আরও #টি ফাইল}}" "{count,plural, =1{আরও #টি ফাইল}one{আরও #টি ফাইল}other{আরও #টি ফাইল}}" "টেক্সট শেয়ার করা হচ্ছে" - "শেয়ার করার জন্য লিঙ্ক" + "লিঙ্ক শেয়ার করা হচ্ছে" "{count,plural, =1{ছবি শেয়ার করা হচ্ছে}one{#টি ছবি শেয়ার করা হচ্ছে}other{#টি ছবি শেয়ার করা হচ্ছে}}" "{count,plural, =1{ভিডিও শেয়ার করা হচ্ছে}one{#টি ভিডিও শেয়ার করা হচ্ছে}other{#টি ভিডিও শেয়ার করা হচ্ছে}}" "{count,plural, =1{#টি ফাইল শেয়ার করা হচ্ছে}one{#টি ফাইল শেয়ার করা হচ্ছে}other{#টি ফাইল শেয়ার করা হচ্ছে}}" diff --git a/java/res/values-ca/strings.xml b/java/res/values-ca/strings.xml index 23ae264b..dd003124 100644 --- a/java/res/values-ca/strings.xml +++ b/java/res/values-ca/strings.xml @@ -57,7 +57,7 @@ "{count,plural, =1{# fitxer més}many{# de fitxers més}other{# fitxers més}}" "S\'està compartint text" "S\'està compartint un enllaç" - "{count,plural, =1{]S\'està compartint una imatge}many{S\'estan compartint # d\'imatges}other{S\'estan compartint # imatges}}" + "{count,plural, =1{S\'està compartint una imatge}many{S\'estan compartint # d\'imatges}other{S\'estan compartint # imatges}}" "{count,plural, =1{S\'està compartint un vídeo}many{S\'estan compartint # de vídeos}other{S\'estan compartint # vídeos}}" "{count,plural, =1{S\'està compartint # fitxer}many{S\'estan compartint # de fitxers}other{S\'estan compartint # fitxers}}" "Selecciona els elements que vols compartir" -- cgit v1.2.3-59-g8ed1b