diff options
-rw-r--r-- | RemoteFolder/src/com/android/launcher3/RemoteFolderManager.java | 28 | ||||
-rw-r--r-- | RemoteFolder/src/com/android/launcher3/RemoteFolderUpdater.java | 83 | ||||
-rw-r--r-- | res/layout/app_drawer_item.xml | 33 | ||||
-rw-r--r-- | res/layout/app_drawer_item_custom_header.xml | 3 | ||||
-rw-r--r-- | res/values/dimens.xml | 21 | ||||
-rw-r--r-- | src/com/android/launcher3/AppDrawerIconView.java | 1 | ||||
-rw-r--r-- | src/com/android/launcher3/AppDrawerListAdapter.java | 64 | ||||
-rw-r--r-- | src/com/android/launcher3/AppInfo.java | 8 | ||||
-rw-r--r-- | src/com/android/launcher3/Folder.java | 126 | ||||
-rw-r--r-- | src/com/android/launcher3/FolderIcon.java | 18 | ||||
-rw-r--r-- | src/com/android/launcher3/Launcher.java | 17 | ||||
-rw-r--r-- | src/com/android/launcher3/LauncherApplication.java | 2 | ||||
-rw-r--r-- | src/com/android/launcher3/LauncherModel.java | 43 | ||||
-rw-r--r-- | src/com/android/launcher3/RemoteFolder.java | 229 | ||||
-rw-r--r-- | src/com/android/launcher3/ShortcutInfo.java | 11 | ||||
-rw-r--r-- | src/com/android/launcher3/stats/LauncherStats.java | 35 | ||||
-rw-r--r-- | src/com/android/launcher3/stats/internal/model/TrackingEvent.java | 8 |
17 files changed, 161 insertions, 569 deletions
diff --git a/RemoteFolder/src/com/android/launcher3/RemoteFolderManager.java b/RemoteFolder/src/com/android/launcher3/RemoteFolderManager.java index c93b8338b..61a003399 100644 --- a/RemoteFolder/src/com/android/launcher3/RemoteFolderManager.java +++ b/RemoteFolder/src/com/android/launcher3/RemoteFolderManager.java @@ -1,5 +1,7 @@ package com.android.launcher3; +import java.util.ArrayList; + /** * Manages adding and removing the remote folder from the workspace. */ @@ -7,7 +9,12 @@ public class RemoteFolderManager { public RemoteFolderManager(final Launcher launcher) { } - public void setRemoteFolder(final FolderIcon remoteFolder) { } + /** + * Create a remote folder view. + * @param icon folder icon view on the workspace. + * @return a view for the remote folder. + */ + public Folder createRemoteFolder(final FolderIcon icon) { return null; } /** * Called when Launcher finishes binding items from the model. @@ -31,7 +38,26 @@ public class RemoteFolderManager { public void onAppDrawerOpened() { } /** + * Called when new apps are added to launcher. + * @param apps list of added apps. + */ + public void onBindAddApps(ArrayList<AppInfo> apps) { } + + /** * Called when the info icon is clicked */ public void onInfoIconClicked() { } + + /** + * Called when the view holder is created for the remote header. + * @param holder remote view holder. + */ + public void onCreateViewHolder(final AppDrawerListAdapter.ViewHolder holder) { } + /** + * Called when the view holder is bound for the remote header. + * @param holder remote view holder. + * @param indexedInfo header info. + */ + public void onBindViewHolder(final AppDrawerListAdapter.ViewHolder holder, + final AppDrawerListAdapter.AppItemIndexedInfo indexedInfo) { } } diff --git a/RemoteFolder/src/com/android/launcher3/RemoteFolderUpdater.java b/RemoteFolder/src/com/android/launcher3/RemoteFolderUpdater.java deleted file mode 100644 index 954595e1f..000000000 --- a/RemoteFolder/src/com/android/launcher3/RemoteFolderUpdater.java +++ /dev/null @@ -1,83 +0,0 @@ -package com.android.launcher3; - -import android.content.Context; -import android.content.Intent; -import android.graphics.Bitmap; -import android.view.View; -import java.util.List; -import android.util.Log; - -public class RemoteFolderUpdater { - - private static final String TAG = "RemoteFolderUpdater"; - - private static final Object sLock = new Object(); - private static RemoteFolderUpdater sInstance; - - public interface RemoteFolderUpdateListener { - void onSuccess(List<RemoteFolderInfo> remoteFolderInfoList); - void onFailure(String error); - } - - public static RemoteFolderUpdater getInstance() { - synchronized (sLock) { - if (sInstance == null) { - sInstance = new RemoteFolderUpdater(); - } - - return sInstance; - } - } - - private RemoteFolderUpdater() { } - - /** - * Requests data needed by remote folders. - * @param context - * @param size - * @param listener - */ - public synchronized void requestSync(Context context, final int size, final RemoteFolderUpdateListener listener) { - if (listener != null) { - listener.onFailure("RemoteFolderUpdater may not have been properly setup"); - } - } - - /** - * Register a callback to track clicks on our individual Remote Folder items. Make sure the - * intent associated with each item has a unique ID. - * - * @param view The individual item the user may click (or just clicked) - * @param intent The intent associated with the ShortcutInfo that belongs to our view - */ - public void registerViewForInteraction(View view, Intent intent) { - Log.e(TAG, "Couldn't register view for user interaction, RemoteFolderUpdater may not have been properly setup"); - } - - /** - * Holds important information that the launcher will need for each item in the remote folder. - */ - public class RemoteFolderInfo { - - public void setRecommendationData(View view) { - return; - } - - public String getTitle() { - return null; - } - - public Bitmap getIcon() { - return null; - } - - public String getIconUrl() { - return null; - } - - public Intent getIntent() { - return null; - } - } - -} diff --git a/res/layout/app_drawer_item.xml b/res/layout/app_drawer_item.xml index d8b3eb43e..03ca60a00 100644 --- a/res/layout/app_drawer_item.xml +++ b/res/layout/app_drawer_item.xml @@ -30,28 +30,9 @@ android:layout_alignBottom="@+id/drawer_item_flow" android:background="@color/app_drawer_drag_background" /> - <TextView - android:id="@+id/custom_title" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:textColor="@android:color/white" - android:textSize="@dimen/drawer_custom_title_text_size" - android:layout_marginStart="@dimen/drawer_custom_title_margin_start" - android:layout_marginTop="@dimen/drawer_custom_title_margin_top" - android:includeFontPadding="false" - android:fontFamily="roboto-light" - android:text="@string/recommendations_title" - android:visibility="gone" /> - - <ImageView - android:id="@+id/custom_title_icon" - android:layout_width="@dimen/drawer_custom_icon_size" - android:layout_height="@dimen/drawer_custom_icon_size" - android:layout_marginEnd="@dimen/drawer_custom_icon_margin_end" - android:layout_marginTop="@dimen/drawer_custom_icon_margin_top" - android:layout_alignParentEnd="true" - android:src="@drawable/triangle_icon" - android:visibility="gone" /> + <include + android:id="@+id/custom_header_layout" + layout="@layout/app_drawer_item_custom_header" /> <LinearLayout android:id="@+id/drawer_item_flow" @@ -59,7 +40,7 @@ android:layout_toEndOf="@+id/drawer_item_title" android:layout_width="match_parent" android:layout_height="wrap_content" - android:layout_below="@id/custom_title" + android:layout_below="@id/custom_header_layout" android:orientation="horizontal" /> <View @@ -75,17 +56,17 @@ android:id="@id/drawer_item_title" android:layout_width="@dimen/drawer_header_text_char_width" android:layout_height="wrap_content" - android:layout_marginTop="@dimen/drawer_header_text_margin_top_default" + android:layout_marginTop="@dimen/drawer_header_text_margin_top" android:layout_marginBottom="@dimen/drawer_header_text_margin_bottom" android:layout_marginStart="@dimen/drawer_header_text_margin_start" - android:layout_alignTop="@id/custom_title" + android:layout_alignTop="@id/custom_header_layout" android:layout_alignWithParentIfMissing="true" android:layout_alignBottom="@id/drawer_item_flow" android:includeFontPadding="false" android:gravity="center" android:singleLine="true" autofit:minTextSize="@dimen/drawer_header_text_min_text_size" - android:textSize="@dimen/drawer_header_text_size_default" + android:textSize="@dimen/drawer_header_text_size" android:fontFamily="sans-serif-light" android:textColor="@android:color/white" android:shadowRadius="@dimen/drawer_header_text_shadow_radius" diff --git a/res/layout/app_drawer_item_custom_header.xml b/res/layout/app_drawer_item_custom_header.xml new file mode 100644 index 000000000..14c171ee6 --- /dev/null +++ b/res/layout/app_drawer_item_custom_header.xml @@ -0,0 +1,3 @@ +<?xml version="1.0" encoding="utf-8"?> +<merge xmlns:android="http://schemas.android.com/apk/res/android"> +</merge>
\ No newline at end of file diff --git a/res/values/dimens.xml b/res/values/dimens.xml index f6459a5da..088640f89 100644 --- a/res/values/dimens.xml +++ b/res/values/dimens.xml @@ -136,28 +136,11 @@ <dimen name="drawer_header_text_min_text_size">8sp</dimen> <dimen name="drawer_header_text_margin_bottom">24dp</dimen> <dimen name="drawer_header_text_margin_start">6dp</dimen> + <dimen name="drawer_header_text_margin_top">6dp</dimen> + <dimen name="drawer_header_text_size">20sp</dimen> <item name="drawer_header_text_shadow_radius" format="float" type="dimen">4</item> <item name="drawer_header_text_shadow_dy" format="float" type="dimen">2</item> - <!-- Custom/default variances --> - <dimen name="drawer_header_text_size_default">20sp</dimen> - <dimen name="drawer_header_text_margin_top_default">6dp</dimen> - <dimen name="drawer_item_flow_padding_bottom_default">0dp</dimen> - <dimen name="drawer_container_bottom_margin_default">0dp</dimen> - - <dimen name="drawer_header_text_size_custom">16sp</dimen> - <dimen name="drawer_header_text_margin_top_custom">-2dp</dimen> - <dimen name="drawer_item_flow_padding_bottom_custom">15dp</dimen> - <dimen name="drawer_container_bottom_margin_custom">20dp</dimen> - - <!-- Custom header --> - <dimen name="drawer_custom_title_text_size">16sp</dimen> - <dimen name="drawer_custom_title_margin_start">50dp</dimen> - <dimen name="drawer_custom_title_margin_top">15dp</dimen> - <dimen name="drawer_custom_icon_margin_top">20dp</dimen> - <dimen name="drawer_custom_icon_margin_end">14dp</dimen> - <dimen name="drawer_custom_icon_size">12dp</dimen> - <!-- Folder open animation --> <integer name="folder_translate_y_dist">300</integer> <integer name="folder_icon_translate_y_dist">100</integer> diff --git a/src/com/android/launcher3/AppDrawerIconView.java b/src/com/android/launcher3/AppDrawerIconView.java index 94b5e93f4..d8564b6ed 100644 --- a/src/com/android/launcher3/AppDrawerIconView.java +++ b/src/com/android/launcher3/AppDrawerIconView.java @@ -33,7 +33,6 @@ public class AppDrawerIconView extends LinearLayout { TextView mLabel; ImageView mIcon; - boolean mDraggable = true; public AppDrawerIconView(Context context) { super(context); diff --git a/src/com/android/launcher3/AppDrawerListAdapter.java b/src/com/android/launcher3/AppDrawerListAdapter.java index fb47eb816..b3001e527 100644 --- a/src/com/android/launcher3/AppDrawerListAdapter.java +++ b/src/com/android/launcher3/AppDrawerListAdapter.java @@ -53,7 +53,7 @@ import java.util.LinkedHashMap; * AppDrawerListAdapter - list adapter for the vertical app drawer */ public class AppDrawerListAdapter extends RecyclerView.Adapter<AppDrawerListAdapter.ViewHolder> - implements View.OnLongClickListener, View.OnClickListener, DragSource, SectionIndexer { + implements View.OnLongClickListener, DragSource, SectionIndexer { public static final String REMOTE_HEADER = "☆"; public static final String REMOTE_SCRUBBER = "★"; @@ -87,7 +87,7 @@ public class AppDrawerListAdapter extends RecyclerView.Adapter<AppDrawerListAdap } private static Bucket getBucketForApp(AppInfo app) { - if (app.isRemote()) { + if (app.hasFlag(AppInfo.REMOTE_APP_FLAG)) { return new Bucket(Integer.MIN_VALUE, REMOTE_HEADER); } else { LocaleUtils localeUtils = LocaleUtils.getInstance(); @@ -101,6 +101,8 @@ public class AppDrawerListAdapter extends RecyclerView.Adapter<AppDrawerListAdap } } + private final RemoteFolderManager mRemoteFolderManager; + private HashSet<AppInfo> mAllApps; private ArrayList<AppItemIndexedInfo> mHeaderList; private LayoutInflater mLayoutInflater; @@ -147,8 +149,6 @@ public class AppDrawerListAdapter extends RecyclerView.Adapter<AppDrawerListAdap public static int TYPE_NORMAL = 0; public static int TYPE_CUSTOM = 1; - public TextView mCustomTitleTextView; - public ImageView mCustomImageView; public AutoFitTextView mHeaderTextView; public ViewGroup mIconLayout; public View mContainerView; @@ -161,8 +161,6 @@ public class AppDrawerListAdapter extends RecyclerView.Adapter<AppDrawerListAdap mFadingBackgroundFrontView = itemView.findViewById(R.id.fading_background_front); mHeaderTextView = (AutoFitTextView) itemView.findViewById(R.id.drawer_item_title); mHeaderTextView.bringToFront(); - mCustomTitleTextView = (TextView) itemView.findViewById(R.id.custom_title); - mCustomImageView = (ImageView) itemView.findViewById(R.id.custom_title_icon); mIconLayout = (ViewGroup) itemView.findViewById(R.id.drawer_item_flow); } } @@ -411,6 +409,8 @@ public class AppDrawerListAdapter extends RecyclerView.Adapter<AppDrawerListAdap mAllApps = new HashSet<AppInfo>(); mLayoutInflater = LayoutInflater.from(launcher); + mRemoteFolderManager = mLauncher.getRemoteFolderManager(); + mLocaleSetManager = new LocaleSetManager(mLauncher); mLocaleSetManager.updateLocaleSet(mLocaleSetManager.getSystemLocaleSet()); mItemAnimatorSet = new ItemAnimatorSet(launcher); @@ -600,8 +600,7 @@ public class AppDrawerListAdapter extends RecyclerView.Adapter<AppDrawerListAdap } if (viewType == ViewHolder.TYPE_CUSTOM) { - applyCustomStyle(holder); - holder.mCustomImageView.setOnClickListener(this); + mRemoteFolderManager.onCreateViewHolder(holder); } return holder; @@ -686,20 +685,18 @@ public class AppDrawerListAdapter extends RecyclerView.Adapter<AppDrawerListAdap mDeviceProfile.iconDrawablePaddingPx); icon.mLabel.setText(info.title); icon.mLabel.setVisibility(mHideIconLabels ? View.INVISIBLE : View.VISIBLE); - - if (info.isRemote()) { - RemoteFolderUpdater.getInstance() - .registerViewForInteraction(icon, info.getIntent()); - icon.mDraggable = false; - } } } holder.itemView.setTag(indexedInfo); + + if (indexedInfo.isRemote()) { + mRemoteFolderManager.onBindViewHolder(holder, indexedInfo); + } } @Override public boolean onLongClick(View v) { - if (v instanceof AppDrawerIconView && ((AppDrawerIconView) v).mDraggable) { + if (v instanceof AppDrawerIconView) { beginDraggingApplication(v); mLauncher.enterSpringLoadedDragMode(); } @@ -707,13 +704,6 @@ public class AppDrawerListAdapter extends RecyclerView.Adapter<AppDrawerListAdap } @Override - public void onClick(View v) { - if (v.getId() == R.id.custom_title_icon) { - mLauncher.getRemoteFolderManager().onInfoIconClicked(); - } - } - - @Override public void onDropCompleted(View target, DropTarget.DragObject d, boolean isFlingToDelete, boolean success) { // Return early and wait for onFlingToDeleteCompleted if this was the result of a fling @@ -829,6 +819,10 @@ public class AppDrawerListAdapter extends RecyclerView.Adapter<AppDrawerListAdap public boolean isRemote() { return mStartString == REMOTE_HEADER; } + + public ArrayList<AppInfo> getInfo() { + return mInfo; + } } @Override @@ -893,30 +887,4 @@ public class AppDrawerListAdapter extends RecyclerView.Adapter<AppDrawerListAdap } } } - - /** - * Remote header uses a custom styled view. Apply it here. - * @param holder view which needs a custom style. - */ - private void applyCustomStyle(final ViewHolder holder) { - Resources res = mLauncher.getResources(); - RelativeLayout.LayoutParams lp = - (RelativeLayout.LayoutParams) holder.mHeaderTextView.getLayoutParams(); - lp.removeRule(RelativeLayout.ALIGN_BOTTOM); - lp.topMargin = res.getDimensionPixelOffset(R.dimen.drawer_header_text_margin_top_custom); - - holder.mContainerView.setBackgroundColor( - res.getColor(R.color.drawer_container_background_custom)); - holder.mCustomTitleTextView.setVisibility(View.VISIBLE); - holder.mCustomImageView.setVisibility(View.VISIBLE); - holder.mHeaderTextView.setTextSize( - res.getDimension(R.dimen.drawer_header_text_size_custom)); - holder.mIconLayout.setPadding(0, 0, 0, - res.getDimensionPixelOffset(R.dimen.drawer_item_flow_padding_bottom_custom)); - - RecyclerView.LayoutParams containerLP = - (RecyclerView.LayoutParams) holder.mContainerView.getLayoutParams(); - containerLP.bottomMargin = - res.getDimensionPixelOffset(R.dimen.drawer_container_bottom_margin_custom); - } } diff --git a/src/com/android/launcher3/AppInfo.java b/src/com/android/launcher3/AppInfo.java index e8767e67e..907b42cd9 100644 --- a/src/com/android/launcher3/AppInfo.java +++ b/src/com/android/launcher3/AppInfo.java @@ -142,10 +142,12 @@ public class AppInfo extends ItemInfo { } /** - * @return true if this info represents a remote app, false otherwise + * Check if this app has a specific flag. + * @param flag flag to check. + * @return true if the flag is present, false otherwise. */ - public boolean isRemote() { - return (flags & REMOTE_APP_FLAG) != 0; + public boolean hasFlag(int flag) { + return (flags & flag) != 0; } @Override diff --git a/src/com/android/launcher3/Folder.java b/src/com/android/launcher3/Folder.java index 2bd656565..b3b690042 100644 --- a/src/com/android/launcher3/Folder.java +++ b/src/com/android/launcher3/Folder.java @@ -62,7 +62,6 @@ import android.widget.ScrollView; import android.widget.TextView; import com.android.launcher3.FolderInfo.FolderListener; -import com.android.launcher3.compat.UserHandleCompat; import com.android.launcher3.settings.SettingsProvider; import java.util.ArrayList; @@ -485,69 +484,36 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList mInfo = info; final ArrayList<ShortcutInfo> children = info.contents; - if (info.isRemote() && children.isEmpty()) { - final int count = 6; - RemoteFolderUpdater updater = RemoteFolderUpdater.getInstance(); - updater.requestSync(getContext(), count, new RemoteFolderUpdater.RemoteFolderUpdateListener() { - @Override - public void onSuccess(List<RemoteFolderUpdater.RemoteFolderInfo> remoteFolderInfoList) { - children.clear(); - for (RemoteFolderUpdater.RemoteFolderInfo remoteFolderInfo : remoteFolderInfoList) { - ShortcutInfo shortcutInfo = new ShortcutInfo(remoteFolderInfo.getIntent(), - remoteFolderInfo.getTitle(), - remoteFolderInfo.getTitle(), - remoteFolderInfo.getIcon(), - UserHandleCompat.myUserHandle()); - children.add(shortcutInfo); - - View child = mLauncher.createShortcut(R.layout.application, mContent, - shortcutInfo); - remoteFolderInfo.setRecommendationData(child); - LauncherModel.addOrMoveItemInDatabase(mLauncher, shortcutInfo, info.container, - info.screenId, info.cellX, info.cellY); - } - info.contents = children; - bind(info); - } - - @Override - public void onFailure(String error) { - Log.e(TAG, "Failed to sync data for the remote folder's shortcuts. Reason: " + error); - setupContentForNumItems(count); - } - }); - } else { - ArrayList<ShortcutInfo> overflow = new ArrayList<ShortcutInfo>(); - setupContentForNumItems(children.size()); - placeInReadingOrder(children); - int count = 0; - for (int i = 0; i < children.size(); i++) { - ShortcutInfo child = (ShortcutInfo) children.get(i); - if (createAndAddShortcut(child) == null) { - overflow.add(child); - } else { - count++; - } + ArrayList<ShortcutInfo> overflow = new ArrayList<ShortcutInfo>(); + setupContentForNumItems(children.size()); + placeInReadingOrder(children); + int count = 0; + for (int i = 0; i < children.size(); i++) { + ShortcutInfo child = (ShortcutInfo) children.get(i); + if (createAndAddShortcut(child) == null) { + overflow.add(child); + } else { + count++; } + } - // We rearrange the items in case there are any empty gaps - setupContentForNumItems(count); + // We rearrange the items in case there are any empty gaps + setupContentForNumItems(count); - // If our folder has too many items we prune them from the list. This is an issue - // when upgrading from the old Folders implementation which could contain an unlimited - // number of items. - for (ShortcutInfo item: overflow) { - mInfo.remove(item); - LauncherModel.deleteItemFromDatabase(mLauncher, item); - } + // If our folder has too many items we prune them from the list. This is an issue + // when upgrading from the old Folders implementation which could contain an unlimited + // number of items. + for (ShortcutInfo item: overflow) { + mInfo.remove(item); + LauncherModel.deleteItemFromDatabase(mLauncher, item); + } - mItemsInvalidated = true; - updateTextViewFocus(); - mInfo.addListener(this); + mItemsInvalidated = true; + updateTextViewFocus(); + mInfo.addListener(this); - setFolderName(); - updateItemLocationsInDatabase(); - } + setFolderName(); + updateItemLocationsInDatabase(); } public void setFolderName() { @@ -1264,7 +1230,16 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList // Do nothing } + /** + * @return true if contents should persist their status to the database. + */ + protected boolean shouldUpdateContentsInDatabase() { + return true; + } + private void updateItemLocationsInDatabase() { + if (!shouldUpdateContentsInDatabase()) return; + ArrayList<View> list = getItemsInReadingOrder(); for (int i = 0; i < list.size(); i++) { View v = list.get(i); @@ -1275,6 +1250,8 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList } private void updateItemLocationsInDatabaseBatch() { + if (!shouldUpdateContentsInDatabase()) return; + ArrayList<View> list = getItemsInReadingOrder(); ArrayList<ItemInfo> items = new ArrayList<ItemInfo>(); for (int i = 0; i < list.size(); i++) { @@ -1287,6 +1264,8 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList } public void addItemLocationsInDatabase() { + if (!shouldUpdateContentsInDatabase()) return; + ArrayList<View> list = getItemsInReadingOrder(); for (int i = 0; i < list.size(); i++) { View v = list.get(i); @@ -1475,8 +1454,11 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList if (info.cellX != vacant[0] || info.cellY != vacant[1]) { info.cellX = vacant[0]; info.cellY = vacant[1]; - LauncherModel.addOrMoveItemInDatabase(mLauncher, info, mInfo.id, 0, - info.cellX, info.cellY); + + if (shouldUpdateContentsInDatabase()) { + LauncherModel.addOrMoveItemInDatabase(mLauncher, info, mInfo.id, 0, + info.cellX, info.cellY); + } } boolean insert = false; mContent.addViewToCellLayout(v, insert ? 0 : -1, (int)info.id, lp, true); @@ -1515,11 +1497,7 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList mSuppressFolderDeletion = false; } - private void replaceFolderWithFinalItem() { - if (mInfo.isRemote()) { - return; - } - + protected void replaceFolderWithFinalItem() { if (mInfo.hidden && getItemCount() >= 1) { return; } @@ -1609,8 +1587,10 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList // Actually move the item in the database if it was an external drag. Call this // before creating the view, so that ShortcutInfo is updated appropriately. - LauncherModel.addOrMoveItemInDatabase( - mLauncher, si, mInfo.id, 0, si.cellX, si.cellY); + if (shouldUpdateContentsInDatabase()) { + LauncherModel.addOrMoveItemInDatabase( + mLauncher, si, mInfo.id, 0, si.cellX, si.cellY); + } // We only need to update the locations if it doesn't get handled in #onDropCompleted. if (d.dragSource != this) { @@ -1676,15 +1656,11 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList findAndSetEmptyCells(item); } createAndAddShortcut(item); - LauncherModel.addOrMoveItemInDatabase( - mLauncher, item, mInfo.id, 0, item.cellX, item.cellY); - // If this is a Remote Folder, we need to register each view with our updater for click handling. - if (mInfo.isRemote()) { - RemoteFolderUpdater updater = RemoteFolderUpdater.getInstance(); - updater.registerViewForInteraction(getViewForInfo(item), item.getIntent()); + if (shouldUpdateContentsInDatabase()) { + LauncherModel.addOrMoveItemInDatabase( + mLauncher, item, mInfo.id, 0, item.cellX, item.cellY); } - } public void onRemove(ShortcutInfo item) { diff --git a/src/com/android/launcher3/FolderIcon.java b/src/com/android/launcher3/FolderIcon.java index 33787ab35..17ea4899d 100644 --- a/src/com/android/launcher3/FolderIcon.java +++ b/src/com/android/launcher3/FolderIcon.java @@ -170,19 +170,17 @@ public class FolderIcon extends FrameLayout implements FolderListener { icon.mLauncher = launcher; icon.setContentDescription(String.format(launcher.getString(R.string.folder_name_format), folderInfo.title)); + Folder folder; if (folderInfo.isRemote()) { - RemoteFolder folder = RemoteFolder.fromXml(launcher); - folder.setDragController(launcher.getDragController()); - folder.setFolderIcon(icon); - folder.bind(folderInfo); - icon.mFolder = folder; + folder = launcher.getRemoteFolderManager().createRemoteFolder(icon); } else { - Folder folder = Folder.fromXml(launcher); - folder.setDragController(launcher.getDragController()); - folder.setFolderIcon(icon); - folder.bind(folderInfo); - icon.mFolder = folder; + folder = Folder.fromXml(launcher); } + folder.setDragController(launcher.getDragController()); + folder.setFolderIcon(icon); + folder.bind(folderInfo); + icon.mFolder = folder; + icon.mFolderRingAnimator = new FolderRingAnimator(launcher, icon); folderInfo.addListener(icon); diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java index ff59dce08..7fc373061 100644 --- a/src/com/android/launcher3/Launcher.java +++ b/src/com/android/launcher3/Launcher.java @@ -2984,14 +2984,6 @@ public class Launcher extends Activity onClickAllAppsButton(v); } else if (tag instanceof AppInfo) { AppInfo info = (AppInfo) tag; - - // Remote apps do not exist in package manager, so they should be launched - // directly by intent. - if (info.isRemote()) { - startActivity(info.intent); - return; - } - startAppShortcutOrInfoActivity(v); LauncherApplication.getLauncherStats().sendAppLaunchEvent( LauncherStats.ORIGIN_APPDRAWER, info.componentName.getPackageName()); @@ -3242,10 +3234,6 @@ public class Launcher extends Activity closeFolder(); // Open the requested folder openFolder(folderIcon, folderTouchXYOffset); - - if (info.isRemote()) { - mModel.syncRemoteFolder(info, this); - } } else { // Find the open folder... int folderScreen; @@ -4882,6 +4870,7 @@ public class Launcher extends Activity addedApps != null && mAppsCustomizeContent != null) { mAppsCustomizeContent.addApps(addedApps); mAppDrawerAdapter.addApps(addedApps); + mRemoteFolderManager.onBindAddApps(addedApps); } } @@ -4962,10 +4951,6 @@ public class Launcher extends Activity newFolder.setTextVisible(!mHideIconLabels); workspace.addInScreenFromBind(newFolder, item.container, item.screenId, item.cellX, item.cellY, 1, 1); - - if (((FolderInfo) item).isRemote()) { - mRemoteFolderManager.setRemoteFolder(newFolder); - } break; default: throw new RuntimeException("Invalid Item Type"); diff --git a/src/com/android/launcher3/LauncherApplication.java b/src/com/android/launcher3/LauncherApplication.java index eab9861bd..3facb3c21 100644 --- a/src/com/android/launcher3/LauncherApplication.java +++ b/src/com/android/launcher3/LauncherApplication.java @@ -66,7 +66,7 @@ public class LauncherApplication extends Application { if (getResources().getBoolean(R.bool.config_launcher_stkAppRename)) { registerAppNameChangeReceiver(); } - sLauncherStats = LauncherStats.createInstance(this); + sLauncherStats = LauncherStats.getInstance(this); AggregationIntentService.scheduleService(this); } diff --git a/src/com/android/launcher3/LauncherModel.java b/src/com/android/launcher3/LauncherModel.java index 050c1f759..78630afea 100644 --- a/src/com/android/launcher3/LauncherModel.java +++ b/src/com/android/launcher3/LauncherModel.java @@ -2387,11 +2387,6 @@ public class LauncherModel extends BroadcastReceiver sBgItemsIdMap.put(folderInfo.id, folderInfo); sBgFolders.put(folderInfo.id, folderInfo); - - if (folderInfo.isRemote()) { - syncRemoteFolder(folderInfo, mContext); - } - break; case LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET: @@ -4253,42 +4248,4 @@ public class LauncherModel extends BroadcastReceiver public Callbacks getCallback() { return mCallbacks != null ? mCallbacks.get() : null; } - - protected synchronized void syncRemoteFolder(final FolderInfo folderInfo, final Context context) { - RemoteFolderUpdater updater = RemoteFolderUpdater.getInstance(); - final int count = 6; - - updater.requestSync(context, count, new RemoteFolderUpdater.RemoteFolderUpdateListener() { - @Override - public void onSuccess(List<RemoteFolderUpdater.RemoteFolderInfo> remoteFolderInfoList) { - - synchronized (mLock) { - - // Clear contents to prevent any duplicates - if (folderInfo.contents != null && !folderInfo.contents.isEmpty()) { - deleteItemsFromDatabase(context, folderInfo.contents); - folderInfo.contents.clear(); - } - - // Add each remote folder item, update the DB, and notify listeners - for (RemoteFolderUpdater.RemoteFolderInfo remoteFolderInfo : remoteFolderInfoList) { - ShortcutInfo shortcutInfo = new ShortcutInfo(remoteFolderInfo.getIntent(), - remoteFolderInfo.getTitle(), - remoteFolderInfo.getTitle(), - remoteFolderInfo.getIcon(), - UserHandleCompat.myUserHandle()); - folderInfo.add(shortcutInfo); - } - - updateItemInDatabase(context, folderInfo); - folderInfo.itemsChanged(); - } - } - - @Override - public void onFailure(String error) { - Log.e(TAG, "Failed to sync data for the remote folder's shortcuts. Reason: " + error); - } - }); - } } diff --git a/src/com/android/launcher3/RemoteFolder.java b/src/com/android/launcher3/RemoteFolder.java deleted file mode 100644 index 136489466..000000000 --- a/src/com/android/launcher3/RemoteFolder.java +++ /dev/null @@ -1,229 +0,0 @@ -package com.android.launcher3; - -import android.content.Context; -import android.content.SharedPreferences; -import android.text.TextUtils; -import android.util.AttributeSet; -import android.util.DisplayMetrics; -import android.util.Log; -import android.view.LayoutInflater; -import android.view.View; -import android.widget.Button; -import android.widget.ImageView; -import android.widget.ScrollView; -import android.widget.TextView; - -/** - * Created by tmiller on 11/24/15. - */ -public class RemoteFolder extends Folder { - - public static final String TAG = "RemoteFolder"; - public static final String REMOTE_FOLDER_ENABLED = "remote_folder_enabled"; - private ScrollView mContentScrollView; - private ImageView mFolderInfo; - private TextView mFolderHelpText; - private Button mCloseInfoButton; - private View mFolderInfoContainer; - - private int mFolderInfoContainerHeight; - private int mHelpTextHeight; - private int mHelpTextWidth; - private int mButtonHeight; - private int mFolderInfoIconHeight; - /** - * Used to inflate the Workspace from XML. - * - * @param context The application's context. - * @param attrs The attribtues set containing the Workspace's customization values. - */ - public RemoteFolder(Context context, AttributeSet attrs) { - super(context, attrs); - } - - /** - * Creates a new UserFolder, inflated from R.layout.remote_folder. - * - * @param context The application's context. - * - * @return A new UserFolder. - */ - static RemoteFolder fromXml(Context context) { - return (RemoteFolder) LayoutInflater.from(context).inflate(R.layout.remote_folder, null); - } - - @Override - protected void onFinishInflate() { - super.onFinishInflate(); - int measureSpec = MeasureSpec.UNSPECIFIED; - - mContentScrollView = (ScrollView) findViewById(R.id.scroll_view); - - mFolderInfoContainer = findViewById(R.id.folder_info_container); - mFolderInfoContainer.measure(measureSpec, measureSpec); - mFolderInfoContainerHeight = mFolderInfoContainer.getMeasuredHeight(); - - mFolderInfo = (ImageView) findViewById(R.id.folder_info); - mFolderInfo.measure(measureSpec, measureSpec); - mFolderInfoIconHeight = mFolderInfo.getMeasuredHeight(); - mFolderInfo.setOnClickListener(this); - - mFolderHelpText = (TextView) findViewById(R.id.help_text_view); - mFolderHelpText.setText(getResources().getString(R.string.recommendations_help_text)); - mFolderHelpText.measure(measureSpec, measureSpec); - mHelpTextHeight = (mFolderHelpText.getLineHeight() * mFolderHelpText.getLineCount()) + - mFolderHelpText.getPaddingTop() + mFolderHelpText.getPaddingBottom(); - mHelpTextWidth = mFolderHelpText.getMeasuredWidth(); - mFolderHelpText.setVisibility(GONE); - - mCloseInfoButton = (Button) findViewById(R.id.close_info_button); - mCloseInfoButton.setText(getResources().getString(R.string.close)); - mCloseInfoButton.measure(measureSpec, measureSpec); - mButtonHeight = mCloseInfoButton.getMeasuredHeight(); - mCloseInfoButton.setOnClickListener(this); - } - - protected int getFolderHeight() { - if (mFolderHelpText.getVisibility() == VISIBLE) { - mHelpTextHeight = (mFolderHelpText.getLineHeight() * mFolderHelpText.getLineCount()) + - mFolderHelpText.getPaddingTop() + mFolderHelpText.getPaddingBottom(); - - int height = getPaddingTop() + getPaddingBottom() + mFolderInfoIconHeight - + mHelpTextHeight + mButtonHeight; - return height; - } else { - int height = getPaddingTop() + getPaddingBottom() + mFolderInfoIconHeight - + getContentAreaHeight(); - return height; - - } - } - - private int getFolderWidth() { - if (mFolderHelpText.getVisibility() == VISIBLE) { - DisplayMetrics displayMetrics = this.getResources().getDisplayMetrics(); - int screenWidth = displayMetrics.widthPixels; - int width = Math.min(mHelpTextWidth, screenWidth - getPaddingLeft() - getPaddingRight()); - return width; - } else { - int width = getPaddingLeft() + getPaddingRight() + mContent.getDesiredWidth(); - return width; - } - } - - @Override - protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - // TODO (Tyson): clean this up before merging into main CM branch - int width = getFolderWidth(); - int height = getFolderHeight(); - int contentAreaWidthSpec = MeasureSpec.makeMeasureSpec(getContentAreaWidth(), - MeasureSpec.EXACTLY); - int contentAreaHeightSpec = MeasureSpec.makeMeasureSpec(getContentAreaHeight(), - MeasureSpec.EXACTLY); - - if (LauncherAppState.isDisableAllApps()) { - // Don't cap the height of the content to allow scrolling. - mContent.setFixedSize(getContentAreaWidth(), mContent.getDesiredHeight()); - } else { - mContent.setFixedSize(getContentAreaWidth(), getContentAreaHeight()); - } - mContentScrollView.measure(contentAreaWidthSpec, contentAreaHeightSpec); - - if (mFolderHelpText.getVisibility() == VISIBLE) { - mHelpTextHeight = (mFolderHelpText.getLineHeight() * mFolderHelpText.getLineCount()) + - mFolderHelpText.getPaddingTop() + mFolderHelpText.getPaddingBottom(); - - mFolderHelpText.measure(contentAreaWidthSpec, MeasureSpec.makeMeasureSpec( - mHelpTextHeight, MeasureSpec.EXACTLY)); - mFolderInfoContainer.measure(contentAreaWidthSpec, - MeasureSpec.makeMeasureSpec( - mFolderInfoIconHeight + mHelpTextHeight + mButtonHeight, MeasureSpec.EXACTLY)); - mCloseInfoButton.measure(contentAreaWidthSpec, - MeasureSpec.makeMeasureSpec(mButtonHeight, MeasureSpec.EXACTLY)); - } else { - mHelpTextHeight = 0; - mFolderHelpText.measure(contentAreaWidthSpec, MeasureSpec.makeMeasureSpec( - mHelpTextHeight, MeasureSpec.EXACTLY)); - mFolderInfoContainer.measure(contentAreaWidthSpec, - MeasureSpec.makeMeasureSpec(mFolderInfoIconHeight, MeasureSpec.EXACTLY)); - mCloseInfoButton.measure(contentAreaWidthSpec, - MeasureSpec.makeMeasureSpec(0, MeasureSpec.EXACTLY)); - } - - Log.e(TAG, "onMeasure(), width: " + width + ", height:" + height); - - setMeasuredDimension(width, height); - } - - public void onClick(View v) { - Object tag = v.getTag(); - if (tag instanceof ShortcutInfo) { - mLauncher.onClick(v); - } - - switch (v.getId()) { - case R.id.folder_info: - toggleInfoPane(); - break; - case R.id.close_info_button: - mLauncher.closeFolder(); - break; - default: - break; - } - } - - @Override - public boolean onLongClick(View v) { - // Eat the event without doing anything. We do not allow users to remove items. - return true; - } - - private void toggleInfoPane() { - if (mFolderHelpText.getVisibility() == VISIBLE) { - // info ImageView becomes a close "X" when the help text is showing, handle accordingly - mContentScrollView.setVisibility(VISIBLE); - mContent.setVisibility(VISIBLE); - - mFolderHelpText.setVisibility(GONE); - - mCloseInfoButton.setVisibility(GONE); - - mFolderInfo.setImageDrawable(getResources().getDrawable(R.drawable.ic_launcher_info_normal_holo)); - - } else { - // show the info to the user about remote folders, including the option to disable it - mContentScrollView.setVisibility(GONE); - mContent.setVisibility(GONE); - - mFolderHelpText.setVisibility(VISIBLE); - - mCloseInfoButton.setVisibility(VISIBLE); - - mFolderInfo.setImageDrawable(getResources().getDrawable(R.drawable.ic_launcher_clear_normal_holo)); - } - this.invalidate(); - } - - @Override - public void animateClosed(boolean animate) { - super.animateClosed(animate); - mFolderHelpText.setVisibility(GONE); - mCloseInfoButton.setVisibility(GONE); - mContentScrollView.setVisibility(VISIBLE); - mFolderInfo.setImageDrawable(getResources().getDrawable(R.drawable.ic_launcher_info_normal_holo)); - } - - @Override - public void animateOpen(Workspace workspace, int[] folderTouch) { - super.animateOpen(workspace, folderTouch); - - mFolderHelpText.setText(getResources().getString(R.string.recommendations_help_text)); - mFolderHelpText.setVisibility(GONE); - mCloseInfoButton.setVisibility(GONE); - mContentScrollView.setVisibility(VISIBLE); - mContent.setVisibility(VISIBLE); - mFolderInfo.setImageDrawable(getResources().getDrawable(R.drawable.ic_launcher_info_normal_holo)); - this.invalidate(); - } -} diff --git a/src/com/android/launcher3/ShortcutInfo.java b/src/com/android/launcher3/ShortcutInfo.java index 01f79314e..0a762849c 100644 --- a/src/com/android/launcher3/ShortcutInfo.java +++ b/src/com/android/launcher3/ShortcutInfo.java @@ -59,6 +59,9 @@ public class ShortcutInfo extends ItemInfo { */ public static final int FLAG_RESTORE_STARTED = 8; + /** Indicates that this shortcut is part of the remote folder **/ + public static final int FLAG_REMOTE = 16; + /** * The intent used to start the application. */ @@ -243,6 +246,14 @@ public class ShortcutInfo extends ItemInfo { return (status & flag) != 0; } + /** + * Check if this shortcut has a specific flag. + * @param flag flag to check. + * @return true if the flag is present, false otherwise. + */ + public boolean hasFlag(int flag) { + return (flags & flag) != 0; + } public final boolean isPromise() { return hasStatusFlag(FLAG_RESTORED_ICON | FLAG_AUTOINTALL_ICON); diff --git a/src/com/android/launcher3/stats/LauncherStats.java b/src/com/android/launcher3/stats/LauncherStats.java index e1dd1bbc6..5e8cb83d5 100644 --- a/src/com/android/launcher3/stats/LauncherStats.java +++ b/src/com/android/launcher3/stats/LauncherStats.java @@ -16,12 +16,12 @@ package com.android.launcher3.stats; +import android.content.Context; import android.os.Handler; import android.os.HandlerThread; import android.os.Message; import android.text.TextUtils; import android.util.Log; -import com.android.launcher3.LauncherApplication; import com.android.launcher3.stats.internal.db.DatabaseHelper; import com.android.launcher3.stats.internal.model.TrackingEvent; @@ -41,6 +41,9 @@ public class LauncherStats { public static final String ORIGIN_APPDRAWER = "appdrawer"; public static final String ORIGIN_TREB_LONGPRESS = "trebuchet_longpress"; public static final String ORIGIN_CHOOSER = "theme_chooser"; + public static final String ORIGIN_SETTINGS = "settings"; + public static final String ORIGIN_DRAG_DROP = "drag_drop"; + public static final String ORIGIN_FOLDER = "folder"; private static void log(String msg) throws IllegalArgumentException { if (TextUtils.isEmpty(msg)) { @@ -101,17 +104,16 @@ public class LauncherStats { private static LauncherStats sInstance = null; // Members - private static WriteHandlerThread sHandlerThread = new WriteHandlerThread(); + private static WriteHandlerThread sHandlerThread; private static WriteHandler sWriteHandler; private static DatabaseHelper sDatabaseHelper; - private LauncherApplication mApplication; /** * Send a message to the handler to store event data * * @param trackingEvent {@link TrackingEvent} */ - private void sendStoreEventMessage(TrackingEvent trackingEvent) { + protected void sendStoreEventMessage(TrackingEvent trackingEvent) { log("Sending tracking event to handler: " + trackingEvent); Message msg = new Message(); msg.what = MSG_STORE_EVENT; @@ -134,32 +136,37 @@ public class LauncherStats { } /** + * Used only for overlay extensions + */ + protected LauncherStats() { } + + /** * Constructor * - * @param application {@link LauncherApplication} not null! + * @param context {@link Context} not null! * @throws IllegalArgumentException {@link IllegalArgumentException} */ - private LauncherStats(LauncherApplication application) throws IllegalArgumentException { - if (application == null) { - throw new IllegalArgumentException("'application' cannot be null!"); + private LauncherStats(Context context) throws IllegalArgumentException { + if (context == null) { + throw new IllegalArgumentException("'context' cannot be null!"); } - mApplication = application; - sDatabaseHelper = new DatabaseHelper(application); + sDatabaseHelper = new DatabaseHelper(context); + sHandlerThread = new WriteHandlerThread(); sHandlerThread.start(); sWriteHandler = new WriteHandler(); } /** - * Creates a singleton instance of the stats utility + * Gets a singleton instance of the stats utility * - * @param application {@link LauncherApplication} not null! + * @param context {@link Context} not null! * @return {@link LauncherStats} * @throws IllegalArgumentException {@link IllegalArgumentException} */ - public static LauncherStats createInstance(LauncherApplication application) + public static LauncherStats getInstance(Context context) throws IllegalArgumentException { if (sInstance == null) { - sInstance = new LauncherStats(application); + sInstance = new LauncherStats(context); } return sInstance; } diff --git a/src/com/android/launcher3/stats/internal/model/TrackingEvent.java b/src/com/android/launcher3/stats/internal/model/TrackingEvent.java index 91a9017be..a44d3f148 100644 --- a/src/com/android/launcher3/stats/internal/model/TrackingEvent.java +++ b/src/com/android/launcher3/stats/internal/model/TrackingEvent.java @@ -51,6 +51,14 @@ public class TrackingEvent { WALLPAPER_CHANGE, HOMESCREEN_PAGE, WIDGET, + + // Remote folder specific + REMOTE_FOLDER_DISABLED, + REMOTE_FOLDER_OPENED, + REMOTE_FOLDER_INFO_OPENED, + REMOTE_APP_OPENED, + REMOTE_APP_INSTALLED, + REMOTE_SYNC_TIME } public static final String KEY_ORIGIN = TrackingBundle.KEY_METADATA_ORIGIN; |