summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTyson Miller <tmiller@cyngn.com>2015-11-10 16:59:15 (GMT)
committerTyson Miller <tmiller@cyngn.com>2015-12-02 01:16:59 (GMT)
commit719deb83a0ac84422b68605f4d5c782865766aef (patch)
treefd3db92c9e10fa1665c2bb5c7f2e0b059ba79d5d
parentb0bc788a4fc3d6d7a86ff3f286d8524e3fa2787c (diff)
downloadandroid_packages_apps_Trebuchet-719deb83a0ac84422b68605f4d5c782865766aef.zip
android_packages_apps_Trebuchet-719deb83a0ac84422b68605f4d5c782865766aef.tar.gz
android_packages_apps_Trebuchet-719deb83a0ac84422b68605f4d5c782865766aef.tar.bz2
Trebuchet: dynamic folder type added
Issue-Id: CYNGNOS-1328 Change-Id: I09bf7bec119307f54836fedee8a1532627035d9a
-rw-r--r--Android.mk25
-rw-r--r--AndroidManifest.xml22
-rw-r--r--RemoteFolder/Android.mk1
-rw-r--r--RemoteFolder/src/com.cyngn.RemoteFolder/RemoteFolderUpdater.java64
-rw-r--r--proguard.flags28
-rw-r--r--res/layout/remote_folder.xml123
-rw-r--r--res/values/cm_strings.xml6
-rw-r--r--res/values/version.xml4
-rw-r--r--res/xml/default_workspace_4x4.xml4
-rw-r--r--res/xml/default_workspace_5x5.xml4
-rw-r--r--res/xml/default_workspace_5x6.xml4
-rw-r--r--src/com/android/launcher3/AutoInstallsLayout.java47
-rw-r--r--src/com/android/launcher3/DefaultLayoutParser.java32
-rw-r--r--src/com/android/launcher3/Folder.java134
-rw-r--r--src/com/android/launcher3/FolderIcon.java19
-rw-r--r--src/com/android/launcher3/FolderInfo.java3
-rw-r--r--src/com/android/launcher3/Launcher.java19
-rw-r--r--src/com/android/launcher3/LauncherModel.java70
-rw-r--r--src/com/android/launcher3/RemoteFolder.java260
-rw-r--r--src/com/android/launcher3/Workspace.java2
20 files changed, 819 insertions, 52 deletions
diff --git a/Android.mk b/Android.mk
index af967ac..f93af5b 100644
--- a/Android.mk
+++ b/Android.mk
@@ -27,13 +27,22 @@ LOCAL_STATIC_JAVA_LIBRARIES := android-support-v13 \
android-support-v7-recyclerview \
guava
+<<<<<<< HEAD
+REMOTE_FOLDER_UPDATER ?= $(LOCAL_PATH)/RemoteFolder
+
+
LOCAL_SRC_FILES := $(call all-java-files-under, src) \
+ $(call all-java-files-under, $(REMOTE_FOLDER_UPDATER)/src) \
+=======
+LOCAL_SRC_FILES := $(call all-java-files-under, src) \
+>>>>>>> 861f6e8... Trebuchet: Remote Folder hooks setup. Updater call still needs to be moved from Folder to LauncherModel
$(call all-java-files-under, WallpaperPicker/src) \
$(call all-renderscript-files-under, src) \
$(call all-proto-files-under, protos)
LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/WallpaperPicker/res $(LOCAL_PATH)/res
-LOCAL_AAPT_FLAGS := --auto-add-overlay
+LOCAL_AAPT_FLAGS := --auto-add-overlay \
+ --extra-packages com.cyngn.RemoteFolder
LOCAL_PROTOC_OPTIMIZE_TYPE := nano
LOCAL_PROTOC_FLAGS := --proto_path=$(LOCAL_PATH)/protos/
@@ -49,10 +58,16 @@ LOCAL_AAPT_FLAGS += --rename-manifest-package com.cyanogenmod.trebuchet
LOCAL_OVERRIDES_PACKAGES := Launcher3
LOCAL_PROGUARD_FLAG_FILES := proguard.flags
-LOCAL_PROGUARD_ENABLED := disabled
+LOCAL_PROGUARD_ENABLED := full
+
+REMOTE_FOLDER_UPDATER ?= $(LOCAL_PATH)/RemoteFolder
+include $(REMOTE_FOLDER_UPDATER)/Android.mk
include $(BUILD_PACKAGE)
+include $(CLEAR_VARS)
+include $(REMOTE_FOLDER_UPDATER)/Android.mk
+include $(BUILD_MULTI_PREBUILT)
#
# Protocol Buffer Debug Utility in Java
@@ -72,6 +87,7 @@ LOCAL_JAR_MANIFEST := util/etc/manifest.txt
include $(BUILD_HOST_JAVA_LIBRARY)
+
#
# Protocol Buffer Debug Utility Wrapper Script
#
@@ -89,4 +105,9 @@ $(LOCAL_BUILT_MODULE): $(LOCAL_PATH)/util/etc/launcher_protoutil | $(ACP)
$(copy-file-to-new-target)
$(hide) chmod 755 $@
+<<<<<<< HEAD
+include $(REMOTE_FOLDER_UPDATER)/Android.mk
+
+=======
+>>>>>>> 861f6e8... Trebuchet: Remote Folder hooks setup. Updater call still needs to be moved from Folder to LauncherModel
include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index f3425fe..b6ae5a2 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -76,6 +76,8 @@
<uses-permission android:name="com.android.launcher3.permission.RECEIVE_FIRST_LOAD_BROADCAST" />
<uses-permission android:name="cyanogenmod.permission.PROTECTED_APP" />
<uses-permission android:name="com.cyngn.stats.SEND_ANALYTICS" />
+ <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
+ <uses-permission android:name="com.google.android.gms.permission.ACTIVITY_RECOGNITION"/>
<application
android:name="com.android.launcher3.LauncherApplication"
@@ -266,5 +268,25 @@
<meta-data android:name="com.google.android.backup.api_key"
android:value="@string/backup_api_key" />
+ <meta-data android:name="com.google.android.gms.version"
+ android:value="@integer/google_play_services_version" />
+
+ <!-- For InMobi -->
+ <!--<activity android:name="com.inmobi.rendering.InMobiAdActivity"
+ android:configChanges="keyboardHidden|orientation|keyboard|smallestScreenSize|screenSize"
+ android:theme="@android:style/Theme.Translucent.NoTitleBar"
+ android:hardwareAccelerated="true" />
+
+ <service android:enabled="true" android:name="com.inmobi.commons.internal.ActivityRecognitionManager" />
+
+ <receiver
+ android:name="com.inmobi.commons.core.utilities.uid.ImIdShareBroadCastReceiver"
+ android:enabled="true"
+ android:exported="true" >
+ <intent-filter>
+ <action android:name="com.inmobi.share.id" />
+ </intent-filter>
+ </receiver>-->
+
</application>
</manifest>
diff --git a/RemoteFolder/Android.mk b/RemoteFolder/Android.mk
new file mode 100644
index 0000000..0857902
--- /dev/null
+++ b/RemoteFolder/Android.mk
@@ -0,0 +1 @@
+LOCAL_SRC_FILES += (call all-java-files-under, RemoteFolder/src) \ No newline at end of file
diff --git a/RemoteFolder/src/com.cyngn.RemoteFolder/RemoteFolderUpdater.java b/RemoteFolder/src/com.cyngn.RemoteFolder/RemoteFolderUpdater.java
new file mode 100644
index 0000000..909154c
--- /dev/null
+++ b/RemoteFolder/src/com.cyngn.RemoteFolder/RemoteFolderUpdater.java
@@ -0,0 +1,64 @@
+package com.cyngn.RemoteFolder;
+
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.Bitmap;
+import android.view.View;
+import java.util.List;
+
+public class RemoteFolderUpdater {
+
+ public interface RemoteFolderUpdateListener {
+ void onSuccess(List<RemoteFolderInfo> remoteFolderInfoList);
+ void onFailure(String error);
+ }
+
+ /**
+ * 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;
+ }
+ }
+} \ No newline at end of file
diff --git a/proguard.flags b/proguard.flags
index 0b28c0e..5eef907 100644
--- a/proguard.flags
+++ b/proguard.flags
@@ -1,3 +1,8 @@
+-keepattributes SourceFile,LineNumberTable,InnerClasses
+-keep class com.inmobi.** { *; }
+-dontwarn com.inmobi.**
+-dontwarn com.google.android.gms**
+
-keep class com.android.launcher3.Launcher {
public void previousScreen(android.view.View);
public void nextScreen(android.view.View);
@@ -57,3 +62,26 @@
public float getAnimationProgress();
public void setAnimationProgress(float);
}
+
+-keep class * extends java.util.ListResourceBundle {
+ protected Object[][] getContents();
+}
+
+-keep public class com.google.android.gms.common.internal.safeparcel.SafeParcelable {
+ public static final *** NULL;
+}
+
+-keepnames @com.google.android.gms.common.annotation.KeepName class *
+-keepclassmembernames class * {
+ @com.google.android.gms.common.annotation.KeepName *;
+}
+
+-keepnames class * implements android.os.Parcelable {
+ public static final ** CREATOR;
+}
+
+-keep class android.content.res.** { *; }
+-dontwarn android.content.res.*
+
+-keep class android.view.inputmethod.** { *; }
+-dontwarn android.view.inputmethod.*
diff --git a/res/layout/remote_folder.xml b/res/layout/remote_folder.xml
new file mode 100644
index 0000000..b185a21
--- /dev/null
+++ b/res/layout/remote_folder.xml
@@ -0,0 +1,123 @@
+<?xml version="1.0" encoding="utf-8"?>
+ <!-- Copyright (C) 2008 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+<com.android.launcher3.RemoteFolder
+xmlns:android="http://schemas.android.com/apk/res/android"
+xmlns:launcher="http://schemas.android.com/apk/res-auto"
+android:layout_width="wrap_content"
+android:layout_height="wrap_content"
+android:orientation="vertical"
+android:paddingTop="16dp"
+android:paddingStart="@dimen/folder_preview_padding"
+android:paddingEnd="@dimen/folder_preview_padding"
+android:paddingBottom="@dimen/folder_preview_padding"
+android:layout_gravity="center"
+android:background="@drawable/folder_bg">
+
+ <RelativeLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:id="@+id/folder_info_container"
+ android:background="@android:color/holo_green_dark">
+
+ <!-- TODO replace background with android:background="@android:color/transparent" -->
+ <com.android.launcher3.FolderEditText
+ android:id="@+id/folder_name"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:background="@android:color/holo_orange_dark"
+ android:fontFamily="sans-serif-condensed"
+ android:hint="@string/folder_hint_text"
+ android:imeOptions="flagNoExtractUi"
+ android:paddingBottom="@dimen/folder_name_padding"
+ android:paddingTop="@dimen/folder_name_padding"
+ android:layout_marginStart="@dimen/folder_name_padding"
+ android:layout_marginEnd="@dimen/folder_name_padding"
+ android:gravity="center_vertical"
+ android:singleLine="true"
+ android:textColor="@color/workspace_icon_text_color"
+ android:textColorHighlight="#ffCCCCCC"
+ android:textColorHint="#78ffffff"
+ android:textCursorDrawable="@null"
+ android:textSize="18sp"
+ android:layout_alignParentTop="true"
+ android:layout_alignParentLeft="true"/>
+
+
+ <ImageView
+ android:id="@+id/folder_info"
+ android:layout_width="@dimen/folder_lock_icon"
+ android:layout_height="@dimen/folder_lock_icon"
+ android:padding="@dimen/folder_name_padding"
+ android:src="@drawable/ic_launcher_info_normal_holo"
+ android:layout_alignTop="@id/folder_name"
+ android:layout_alignParentRight="true"/>
+
+ <TextView
+ android:id="@+id/help_text_view"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="@dimen/folder_name_padding"
+ android:layout_marginEnd="@dimen/folder_name_padding"
+ android:text="@string/recommendations_help_text"
+ android:fontFamily="sans-serif-condensed"
+ android:textSize="18sp"
+ android:textColor="@color/workspace_icon_text_color"
+ android:textColorHighlight="#ffCCCCCC"
+ android:textColorHint="#78ffffff"
+ android:layout_below="@id/folder_info"
+ android:background="@android:color/holo_purple"
+ />
+
+ <Button
+ android:id="@+id/close_info_button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:minHeight="@dimen/folder_lock_icon"
+ android:text="@string/close"
+ android:layout_below="@id/help_text_view"
+ android:layout_alignParentBottom="true"
+ android:layout_alignParentRight="true"
+ />
+
+ <Button
+ android:id="@+id/disable_remote_folder_button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:minHeight="@dimen/folder_lock_icon"
+ android:text="@string/disable"
+ android:layout_below="@id/help_text_view"
+ android:layout_toLeftOf="@id/close_info_button"
+ android:layout_alignParentBottom="true"
+ />
+
+ </RelativeLayout>
+
+ <ScrollView
+ android:id="@+id/scroll_view"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_horizontal"
+ android:background="@android:color/holo_red_dark">
+
+ <com.android.launcher3.CellLayout
+ android:id="@+id/folder_content"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:cacheColorHint="#ff333333"
+ android:hapticFeedbackEnabled="false"
+ android:background="@android:color/holo_blue_bright"/>
+ </ScrollView>
+</com.android.launcher3.RemoteFolder> \ No newline at end of file
diff --git a/res/values/cm_strings.xml b/res/values/cm_strings.xml
index 7602ac1..a235a2a 100644
--- a/res/values/cm_strings.xml
+++ b/res/values/cm_strings.xml
@@ -87,4 +87,10 @@
<!-- Search Manager doesn't exist -->
<string name="search_activity_not_found">A search activity could not be found!</string>
+
+ <!-- Featured Apps Strings -->
+ <string name="recommendations_title">Featured Apps</string>
+ <string name="recommendations_help_text">This is a dynamic folder that will automatically load with recommended and featured apps from us at Cyanogen Inc. If you would not like to receive these awesome offers, simply disable below and the folder will be removed.</string>
+ <string name="disable">DISABLE</string>
+ <string name="close">CLOSE</string>
</resources>
diff --git a/res/values/version.xml b/res/values/version.xml
new file mode 100644
index 0000000..d8a0e1f
--- /dev/null
+++ b/res/values/version.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <integer name="google_play_services_version">7571000</integer>
+</resources> \ No newline at end of file
diff --git a/res/xml/default_workspace_4x4.xml b/res/xml/default_workspace_4x4.xml
index 5970f12..809697e 100644
--- a/res/xml/default_workspace_4x4.xml
+++ b/res/xml/default_workspace_4x4.xml
@@ -29,6 +29,10 @@
launcher:spanX="4"
launcher:spanY="2" />
+ <!-- Recommended Folder -->
+ <remote-folder launcher:screen="1" launcher:x="0" launcher:y="2" launcher:title="@string/recommendations_title">
+ </remote-folder>
+
<!-- Google Folder -->
<folder launcher:screen="1" launcher:x="0" launcher:y="3" launcher:title="@string/google_title">
<favorite
diff --git a/res/xml/default_workspace_5x5.xml b/res/xml/default_workspace_5x5.xml
index 5839438..3577bb7 100644
--- a/res/xml/default_workspace_5x5.xml
+++ b/res/xml/default_workspace_5x5.xml
@@ -29,6 +29,10 @@
launcher:spanX="5"
launcher:spanY="2" />
+ <!-- Recommended Folder -->
+ <remote-folder launcher:screen="1" launcher:x="0" launcher:y="3" launcher:title="@string/recommendations_title">
+ </remote-folder>
+
<!-- Google Folder -->
<folder launcher:screen="1" launcher:x="0" launcher:y="4" launcher:title="@string/google_title">
<favorite
diff --git a/res/xml/default_workspace_5x6.xml b/res/xml/default_workspace_5x6.xml
index 81a1ef7..96845ae 100644
--- a/res/xml/default_workspace_5x6.xml
+++ b/res/xml/default_workspace_5x6.xml
@@ -29,6 +29,10 @@
launcher:spanX="6"
launcher:spanY="2" />
+ <!-- Recommended Folder -->
+ <remote-folder launcher:screen="1" launcher:x="0" launcher:y="3" launcher:title="@string/recommendations_title">
+ </remote-folder>
+
<!-- Google Folder -->
<folder launcher:screen="1" launcher:x="0" launcher:y="4" launcher:title="@string/google_title">
<favorite
diff --git a/src/com/android/launcher3/AutoInstallsLayout.java b/src/com/android/launcher3/AutoInstallsLayout.java
index a5d2228..b7a6d9a 100644
--- a/src/com/android/launcher3/AutoInstallsLayout.java
+++ b/src/com/android/launcher3/AutoInstallsLayout.java
@@ -82,6 +82,7 @@ public class AutoInstallsLayout {
private static final String TAG_APP_ICON = "appicon";
private static final String TAG_AUTO_INSTALL = "autoinstall";
private static final String TAG_FOLDER = "folder";
+ private static final String TAG_REMOTE_FOLDER = "remote-folder";
private static final String TAG_APPWIDGET = "appwidget";
private static final String TAG_SHORTCUT = "shortcut";
private static final String TAG_EXTRA = "extra";
@@ -257,6 +258,7 @@ public class AutoInstallsLayout {
parsers.put(TAG_APP_ICON, new AppShortcutParser());
parsers.put(TAG_AUTO_INSTALL, new AutoInstallParser());
parsers.put(TAG_FOLDER, new FolderParser());
+ parsers.put(TAG_REMOTE_FOLDER, new RemoteFolderParser());
parsers.put(TAG_APPWIDGET, new AppWidgetParser());
parsers.put(TAG_SHORTCUT, new ShortcutParser(mSourceRes));
return parsers;
@@ -269,6 +271,8 @@ public class AutoInstallsLayout {
*/
long parseAndAdd(XmlResourceParser parser)
throws XmlPullParserException, IOException;
+
+ boolean isRemoteFolder();
}
/**
@@ -311,6 +315,11 @@ public class AutoInstallsLayout {
}
}
+ @Override
+ public boolean isRemoteFolder() {
+ return false;
+ }
+
/**
* Helper method to allow extending the parser capabilities
*/
@@ -343,6 +352,11 @@ public class AutoInstallsLayout {
return addShortcut(mContext.getString(R.string.package_state_unknown), intent,
Favorites.ITEM_TYPE_APPLICATION);
}
+
+ @Override
+ public boolean isRemoteFolder() {
+ return false;
+ }
}
/**
@@ -396,6 +410,11 @@ public class AutoInstallsLayout {
}
return new Intent(Intent.ACTION_VIEW, null).setData(Uri.parse(url));
}
+
+ @Override
+ public boolean isRemoteFolder() {
+ return false;
+ }
}
/**
@@ -488,6 +507,11 @@ public class AutoInstallsLayout {
}
return insertedId;
}
+
+ @Override
+ public boolean isRemoteFolder() {
+ return false;
+ }
}
protected class FolderParser implements TagParser {
@@ -517,6 +541,11 @@ public class AutoInstallsLayout {
mValues.put(Favorites.SPANX, 1);
mValues.put(Favorites.SPANY, 1);
mValues.put(Favorites._ID, mCallback.generateNewItemId());
+
+ if (isRemoteFolder()) {
+ mValues.put("subType", 1);
+ }
+
long folderId = mCallback.insertAndCheck(mDb, mValues);
if (folderId < 0) {
if (LOGD) Log.e(TAG, "Unable to add folder");
@@ -575,6 +604,11 @@ public class AutoInstallsLayout {
}
return addedId;
}
+
+ @Override
+ public boolean isRemoteFolder() {
+ return false;
+ }
}
protected static final void beginDocument(XmlPullParser parser, String firstElementName)
@@ -630,4 +664,17 @@ public class AutoInstallsLayout {
private static void copyInteger(ContentValues from, ContentValues to, String key) {
to.put(key, from.getAsInteger(key));
}
+
+ protected class RemoteFolderParser extends FolderParser {
+
+ @Override
+ public long parseAndAdd(XmlResourceParser parser) throws XmlPullParserException, IOException {
+ return super.parseAndAdd(parser);
+ }
+
+ @Override
+ public boolean isRemoteFolder() {
+ return true;
+ }
+ }
}
diff --git a/src/com/android/launcher3/DefaultLayoutParser.java b/src/com/android/launcher3/DefaultLayoutParser.java
index e3ea40e..d9c400b 100644
--- a/src/com/android/launcher3/DefaultLayoutParser.java
+++ b/src/com/android/launcher3/DefaultLayoutParser.java
@@ -243,6 +243,11 @@ public class DefaultLayoutParser extends AutoInstallsLayout {
}
return addedId;
}
+
+ @Override
+ public boolean isRemoteFolder() {
+ return false;
+ }
}
/**
@@ -269,6 +274,11 @@ public class DefaultLayoutParser extends AutoInstallsLayout {
}
return -1;
}
+
+ @Override
+ public boolean isRemoteFolder() {
+ return false;
+ }
}
/**
@@ -287,4 +297,26 @@ public class DefaultLayoutParser extends AutoInstallsLayout {
return super.parseAndAdd(parser);
}
}
+
+ protected class RemoteFolderParser extends FolderParser {
+ public RemoteFolderParser() {
+ super();
+ }
+
+ @Override
+ public long parseAndAdd(XmlResourceParser parser) throws XmlPullParserException,
+ IOException {
+ final int resId = getAttributeResourceValue(parser, ATTR_FOLDER_ITEMS, 0);
+ if (resId != 0) {
+ parser = mSourceRes.getXml(resId);
+ beginDocument(parser, TAG_REMOTE_FOLDER);
+ }
+ return super.parseAndAdd(parser);
+ }
+
+ @Override
+ public boolean isRemoteFolder() {
+ return true;
+ }
+ }
}
diff --git a/src/com/android/launcher3/Folder.java b/src/com/android/launcher3/Folder.java
index d10be4e..4cc328c 100644
--- a/src/com/android/launcher3/Folder.java
+++ b/src/com/android/launcher3/Folder.java
@@ -62,7 +62,9 @@ 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 com.cyngn.RemoteFolder.RemoteFolderUpdater;
import java.util.ArrayList;
import java.util.Collections;
@@ -232,7 +234,7 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
mContent.setGridSize(0, 0);
mContent.getShortcutsAndWidgets().setMotionEventSplittingEnabled(false);
mContent.setInvertIfRtl(true);
- mFolderNameLockContainer = findViewById(R.id.folder_name_lock_container);
+
mFolderName = (FolderEditText) findViewById(R.id.folder_name);
mFolderName.setFolder(this);
mFolderName.setOnFocusChangeListener(this);
@@ -257,11 +259,15 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
mFolderName.setVisibility(View.GONE);
}
+ mFolderNameLockContainer = findViewById(R.id.folder_name_lock_container);
mFolderLock = (ImageView) findViewById(R.id.folder_lock);
- mFolderLock.measure(measureSpec, measureSpec);
- mFolderLock.setOnClickListener(this);
- mFolderLockHeight = mFolderLock.getMeasuredHeight();
+ // Could be null if this Folder an instance of the RemoteFolder subclass
+ if (mFolderLock != null) {
+ mFolderLock.measure(measureSpec, measureSpec);
+ mFolderLock.setOnClickListener(this);
+ mFolderLockHeight = mFolderLock.getMeasuredHeight();
+ }
DisplayMetrics displayMetrics = this.getResources().getDisplayMetrics();
mScreenWidth = displayMetrics.widthPixels;
}
@@ -476,39 +482,73 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
}
}
- void bind(FolderInfo info) {
+ void bind(final FolderInfo info) {
mInfo = info;
- ArrayList<ShortcutInfo> children = info.contents;
- 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++;
+ final ArrayList<ShortcutInfo> children = info.contents;
+
+ if (info.subType == FolderInfo.REMOTE_SUBTYPE && children.isEmpty()) {
+ final int count = 6;
+ RemoteFolderUpdater updater = mLauncher.getRemoteFolderUpdaterInstance();
+ 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++;
+ }
}
- }
- // 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() {
@@ -658,12 +698,19 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
Animator circReveal = LauncherAnimUtils.createCircularReveal(this,
circX, circY, 0, mScreenWidth);
- final View[] alphaViewSet = new View[] { mFolderNameLockContainer,
- mContent, mFolderName, mFolderLock };
+ final View[] alphaViewSet;
+ if (mInfo.subType == FolderInfo.REMOTE_SUBTYPE) {
+ alphaViewSet = new View[] { mContent, mFolderName };
+ } else {
+ alphaViewSet = new View[] { mFolderNameLockContainer,
+ mContent, mFolderName, mFolderLock };
+ }
+
for (View view : alphaViewSet) {
view.setAlpha(0f);
}
+
circReveal.setDuration(150);
circReveal.addListener(new AnimatorListenerAdapter() {
@Override
@@ -1371,15 +1418,15 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
centerAboutIcon();
}
- private int getContentAreaHeight() {
+ protected int getContentAreaHeight() {
return Math.max(mContent.getDesiredHeight(), MIN_CONTENT_DIMEN);
}
- private int getContentAreaWidth() {
+ protected int getContentAreaWidth() {
return Math.max(mContent.getDesiredWidth(), MIN_CONTENT_DIMEN);
}
- private int getFolderHeight() {
+ protected int getFolderHeight() {
int height = getPaddingTop() + getPaddingBottom() + mFolderNameHeight
+ getContentAreaHeight();
return height;
@@ -1405,8 +1452,10 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
mFolderName.measure(contentAreaWidthSpec, MeasureSpec.makeMeasureSpec(
mFolderNameHeight, MeasureSpec.EXACTLY));
}
+
mFolderNameLockContainer.measure(contentAreaWidthSpec,
- MeasureSpec.makeMeasureSpec(mFolderNameHeight,MeasureSpec.EXACTLY));
+ MeasureSpec.makeMeasureSpec(mFolderNameHeight, MeasureSpec.EXACTLY));
+
setMeasuredDimension(width, height);
}
@@ -1468,6 +1517,10 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
}
private void replaceFolderWithFinalItem() {
+ if (mInfo.subType == FolderInfo.REMOTE_SUBTYPE) {
+ return;
+ }
+
if (mInfo.hidden && getItemCount() >= 1) {
return;
}
@@ -1626,6 +1679,13 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
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.subType == FolderInfo.REMOTE_SUBTYPE) {
+ RemoteFolderUpdater updater = mLauncher.getModel().getRemoteFolderUpdaterInstance();
+ updater.registerViewForInteraction(getViewForInfo(item), item.getIntent());
+ }
+
}
public void onRemove(ShortcutInfo item) {
diff --git a/src/com/android/launcher3/FolderIcon.java b/src/com/android/launcher3/FolderIcon.java
index 214ec32..b66d5b7 100644
--- a/src/com/android/launcher3/FolderIcon.java
+++ b/src/com/android/launcher3/FolderIcon.java
@@ -170,12 +170,19 @@ 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 = Folder.fromXml(launcher);
- folder.setDragController(launcher.getDragController());
- folder.setFolderIcon(icon);
- folder.bind(folderInfo);
- icon.mFolder = folder;
-
+ if (folderInfo.subType == FolderInfo.REMOTE_SUBTYPE) {
+ RemoteFolder folder = RemoteFolder.fromXml(launcher);
+ folder.setDragController(launcher.getDragController());
+ folder.setFolderIcon(icon);
+ folder.bind(folderInfo);
+ icon.mFolder = folder;
+ } else {
+ 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/FolderInfo.java b/src/com/android/launcher3/FolderInfo.java
index 104bd6c..12b3032 100644
--- a/src/com/android/launcher3/FolderInfo.java
+++ b/src/com/android/launcher3/FolderInfo.java
@@ -28,6 +28,7 @@ import java.util.Arrays;
* Represents a folder containing shortcuts or apps.
*/
public class FolderInfo extends ItemInfo {
+ public static final int REMOTE_SUBTYPE = 1;
/**
* Whether this folder has been opened
@@ -118,7 +119,7 @@ public class FolderInfo extends ItemInfo {
@Override
public String toString() {
- return "FolderInfo(id=" + this.id + " type=" + this.itemType
+ return "FolderInfo(id=" + this.id + " type=" + this.itemType + " subtype=" + this.subType
+ " container=" + this.container + " screen=" + screenId
+ " cellX=" + cellX + " cellY=" + cellY + " spanX=" + spanX
+ " spanY=" + spanY + " dropPos=" + Arrays.toString(dropPos) + ")";
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index bada6ba..b734ad0 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -125,6 +125,7 @@ import com.android.launcher3.PagedView.TransitionEffect;
import com.android.launcher3.settings.SettingsProvider;
import com.android.launcher3.stats.LauncherStats;
import com.android.launcher3.stats.internal.service.AggregationIntentService;
+import com.cyngn.RemoteFolder.RemoteFolderUpdater;
import java.io.DataInputStream;
import java.io.DataOutputStream;
@@ -403,6 +404,9 @@ public class Launcher extends Activity
private BubbleTextView mWaitingForResume;
+ // Remote Folder Updater, used in Workspace and Folder
+ private RemoteFolderUpdater remoteFolderUpdater;
+
// Search widget
int mSearchWidgetId;
AppWidgetProviderInfo mSearchWidgetInfo;
@@ -3225,6 +3229,10 @@ public class Launcher extends Activity
closeFolder();
// Open the requested folder
openFolder(folderIcon, folderTouchXYOffset);
+
+ if (info.subType == FolderInfo.REMOTE_SUBTYPE) {
+ mModel.syncRemoteFolder(info, this);
+ }
} else {
// Find the open folder...
int folderScreen;
@@ -4883,7 +4891,7 @@ public class Launcher extends Activity
final AnimatorSet anim = LauncherAnimUtils.createAnimatorSet();
final Collection<Animator> bounceAnims = new ArrayList<Animator>();
final boolean animateIcons = forceAnimateIcons && canRunNewAppsAnimation();
- Workspace workspace = mWorkspace;
+ final Workspace workspace = mWorkspace;
long newShortcutsScreenId = -1;
for (int i = start; i < end; i++) {
final ItemInfo item = shortcuts.get(i);
@@ -4934,7 +4942,7 @@ public class Launcher extends Activity
}
break;
case LauncherSettings.Favorites.ITEM_TYPE_FOLDER:
- FolderIcon newFolder = FolderIcon.fromXml(R.layout.folder_icon, this,
+ final FolderIcon newFolder = FolderIcon.fromXml(R.layout.folder_icon, this,
(ViewGroup) workspace.getChildAt(workspace.getCurrentPage()),
(FolderInfo) item, mIconCache);
newFolder.setTextVisible(!mHideIconLabels);
@@ -5938,6 +5946,13 @@ public class Launcher extends Activity
SettingsProvider.SETTINGS_UI_HOMESCREEN_SEARCH,
R.bool.preferences_interface_homescreen_search_default);
}
+
+ public RemoteFolderUpdater getRemoteFolderUpdaterInstance() {
+ if (remoteFolderUpdater == null) {
+ remoteFolderUpdater = new RemoteFolderUpdater();
+ }
+ return remoteFolderUpdater;
+ }
}
interface LauncherTransitionable {
diff --git a/src/com/android/launcher3/LauncherModel.java b/src/com/android/launcher3/LauncherModel.java
index dae2c18..724fa32 100644
--- a/src/com/android/launcher3/LauncherModel.java
+++ b/src/com/android/launcher3/LauncherModel.java
@@ -116,6 +116,8 @@ public class LauncherModel extends BroadcastReceiver
private boolean mIsLoaderTaskRunning;
private volatile boolean mFlushingWorkerThread;
+ private static RemoteFolderUpdater remoteFolderUpdater;
+
/**
* Maintain a set of packages per user, for which we added a shortcut on the workspace.
*/
@@ -933,10 +935,10 @@ public class LauncherModel extends BroadcastReceiver
String userSerial = Long.toString(UserManagerCompat.getInstance(context)
.getSerialNumberForUser(user));
Cursor c = cr.query(LauncherSettings.Favorites.CONTENT_URI,
- new String[] { "title", "intent", "profileId" },
- "title=? and (intent=? or intent=?) and profileId=?",
- new String[] { title, intentWithPkg.toUri(0), intentWithoutPkg.toUri(0), userSerial },
- null);
+ new String[]{"title", "intent", "profileId"},
+ "title=? and (intent=? or intent=?) and profileId=?",
+ new String[]{title, intentWithPkg.toUri(0), intentWithoutPkg.toUri(0), userSerial},
+ null);
try {
return c.moveToFirst();
} finally {
@@ -2384,6 +2386,11 @@ public class LauncherModel extends BroadcastReceiver
sBgItemsIdMap.put(folderInfo.id, folderInfo);
sBgFolders.put(folderInfo.id, folderInfo);
+
+ if (folderInfo.subType == FolderInfo.REMOTE_SUBTYPE) {
+ syncRemoteFolder(folderInfo, mContext);
+ }
+
break;
case LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET:
@@ -4245,4 +4252,59 @@ public class LauncherModel extends BroadcastReceiver
public Callbacks getCallback() {
return mCallbacks != null ? mCallbacks.get() : null;
}
+
+ public static RemoteFolderUpdater getRemoteFolderUpdaterInstance() {
+ if (remoteFolderUpdater == null) {
+ remoteFolderUpdater = new RemoteFolderUpdater();
+ }
+ return remoteFolderUpdater;
+ }
+
+ protected synchronized void syncRemoteFolder(final FolderInfo folderInfo, final Context context) {
+
+ String spKey = LauncherAppState.getSharedPreferencesKey();
+ SharedPreferences sp = context.getSharedPreferences(spKey, Context.MODE_PRIVATE);
+ boolean isEnabled = sp.getBoolean(RemoteFolder.REMOTE_FOLDER_ENABLED, true);
+
+ if (!isEnabled) {
+ Log.e(TAG, "Prevented remote folder sync, since it has been explicitly disabled.");
+ return;
+ }
+
+ RemoteFolderUpdater updater = getRemoteFolderUpdaterInstance();
+ 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
new file mode 100644
index 0000000..0d33a55
--- /dev/null
+++ b/src/com/android/launcher3/RemoteFolder.java
@@ -0,0 +1,260 @@
+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 Button mDisableFolderButton;
+ 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);
+
+ mDisableFolderButton = (Button) findViewById(R.id.disable_remote_folder_button);
+ mDisableFolderButton.setText(getResources().getString(R.string.disable));
+ mDisableFolderButton.measure(measureSpec, measureSpec);
+ mDisableFolderButton.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));
+ mDisableFolderButton.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));
+ mDisableFolderButton.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;
+ case R.id.disable_remote_folder_button:
+ disableRemoteFolder();
+ break;
+ default:
+ break;
+ }
+ }
+
+ 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);
+ mDisableFolderButton.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);
+ mDisableFolderButton.setVisibility(VISIBLE);
+
+ mFolderInfo.setImageDrawable(getResources().getDrawable(R.drawable.ic_launcher_clear_normal_holo));
+ }
+ this.invalidate();
+
+ }
+
+ private void disableRemoteFolder() {
+ // close the folder UX & disable remote folders.
+ mLauncher.closeFolder();
+
+ if (mContext != null) {
+ String spKey = LauncherAppState.getSharedPreferencesKey();
+ SharedPreferences sp = mContext.getSharedPreferences(spKey, Context.MODE_PRIVATE);
+ sp.edit().putBoolean(REMOTE_FOLDER_ENABLED, false).commit();
+ Log.e(TAG, "Set preference to disable remote folder. Requesting sync to remove existing folder");
+
+ LauncherModel.deleteFolderContentsFromDatabase(mContext, mInfo);
+ LauncherModel.deleteItemFromDatabase(mContext, mInfo);
+ mLauncher.getWorkspace().removeView(this);
+ mLauncher.removeFolder(mInfo);
+
+ mLauncher.getWorkspace().refreshDrawableState();
+ }
+ }
+
+ @Override
+ public void animateClosed(boolean animate) {
+ super.animateClosed(animate);
+ mFolderHelpText.setVisibility(GONE);
+ mCloseInfoButton.setVisibility(GONE);
+ mDisableFolderButton.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);
+ mDisableFolderButton.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/Workspace.java b/src/com/android/launcher3/Workspace.java
index 71407b9..197c09a 100644
--- a/src/com/android/launcher3/Workspace.java
+++ b/src/com/android/launcher3/Workspace.java
@@ -76,11 +76,13 @@ import com.android.launcher3.compat.PackageInstallerCompat;
import com.android.launcher3.compat.PackageInstallerCompat.PackageInstallInfo;
import com.android.launcher3.compat.UserHandleCompat;
import com.android.launcher3.settings.SettingsProvider;
+import com.cyngn.RemoteFolder.RemoteFolderUpdater;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
+import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;