-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(android): implement Shortcut proxy #11759
Merged
Merged
Changes from 13 commits
Commits
Show all changes
19 commits
Select commit
Hold shift + click to select a range
6e69c90
feat(android): implement Shortcut proxy
garymathews 3d783ab
docs: update documentation
garymathews 563d38e
test: include Shortcut tests
garymathews 9a26f87
test(android): limit to android
garymathews ff38e13
Merge branch 'master' of github.com:appcelerator/titanium_mobile into…
garymathews ce41c18
docs: minor fixes
garymathews 2f80c02
test: improve Ti.UI.Shortcut tests
garymathews 9f5509a
Merge branch 'master' of github.com:appcelerator/titanium_mobile into…
garymathews 57bdec0
fix(android): implement Ti.UI.Shortcut click event
garymathews 1d85d6c
test: simplify ShortcutItem test
garymathews 8062212
Merge branch 'master' into TIMOB-27889
garymathews ba245fe
docs: include click event
garymathews c5ca4ec
docs: update example
garymathews dd0721d
fix(android): validate max shortcuts
garymathews 27612d0
Merge branch 'master' into TIMOB-27889
garymathews b0f1149
Merge branch 'master' into TIMOB-27889
ssaddique 2e65e66
Merge branch 'master' into TIMOB-27889
garymathews f54f188
fix(android): include missing getById() method
garymathews 0f3d3da
Merge branch 'TIMOB-27889' of github.com:garymathews/titanium_mobile …
garymathews File filter
Filter by extension
Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
31 changes: 31 additions & 0 deletions
31
android/modules/ui/src/java/ti/modules/titanium/ui/ShortcutModule.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
/** | ||
* Appcelerator Titanium Mobile | ||
* Copyright (c) 2020 by Axway, Inc. All Rights Reserved. | ||
* Licensed under the terms of the Apache Public License | ||
* Please see the LICENSE included with this distribution for details. | ||
*/ | ||
package ti.modules.titanium.ui; | ||
|
||
import org.appcelerator.kroll.KrollModule; | ||
import org.appcelerator.kroll.annotations.Kroll; | ||
|
||
/** | ||
* This module exist so `Ti.UI.Shortcut.addEventListener()` is defined. | ||
* `Ti.UI.createShortcut` is manually defined in `UIModule`. | ||
*/ | ||
@Kroll.module(parentModule = UIModule.class) | ||
public class ShortcutModule extends KrollModule | ||
{ | ||
private static final String TAG = "ShortcutModule"; | ||
|
||
public ShortcutModule() | ||
{ | ||
super("Shortcut"); | ||
} | ||
|
||
@Override | ||
public String getApiName() | ||
{ | ||
return "Ti.UI.Shortcut"; | ||
} | ||
} |
210 changes: 210 additions & 0 deletions
210
android/modules/ui/src/java/ti/modules/titanium/ui/ShortcutProxy.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,210 @@ | ||
/** | ||
* Appcelerator Titanium Mobile | ||
* Copyright (c) 2020 by Axway, Inc. All Rights Reserved. | ||
* Licensed under the terms of the Apache Public License | ||
* Please see the LICENSE included with this distribution for details. | ||
*/ | ||
package ti.modules.titanium.ui; | ||
|
||
import android.content.Context; | ||
import android.content.Intent; | ||
import android.content.pm.ShortcutInfo; | ||
import android.content.pm.ShortcutManager; | ||
import android.graphics.drawable.Icon; | ||
import android.os.Build; | ||
import android.os.PersistableBundle; | ||
|
||
import androidx.annotation.RequiresApi; | ||
|
||
import org.appcelerator.kroll.KrollDict; | ||
import org.appcelerator.kroll.KrollProxy; | ||
import org.appcelerator.kroll.annotations.Kroll; | ||
import org.appcelerator.kroll.common.Log; | ||
import org.appcelerator.titanium.TiApplication; | ||
import org.appcelerator.titanium.TiC; | ||
import org.appcelerator.titanium.util.TiUIHelper; | ||
import org.json.JSONException; | ||
import org.json.JSONObject; | ||
|
||
import java.util.ArrayList; | ||
import java.util.List; | ||
|
||
@Kroll.proxy( | ||
// Rename to not override `ShortcutModule` definition. | ||
name = "_Shortcut" | ||
) | ||
public class ShortcutProxy extends KrollProxy | ||
{ | ||
private static final String TAG = "ShortcutProxy"; | ||
|
||
// Only supported on Android 7.1 and above. | ||
private static final boolean shortcutCapability = Build.VERSION.SDK_INT >= Build.VERSION_CODES.N_MR1; | ||
|
||
private static ShortcutManager shortcutManager = null; | ||
|
||
public ShortcutProxy() | ||
{ | ||
super(); | ||
|
||
if (!shortcutCapability) { | ||
return; | ||
} | ||
|
||
// Obtain `ShortcutManager` instance. | ||
if (shortcutManager == null) { | ||
final Context context = TiApplication.getInstance(); | ||
shortcutManager = (ShortcutManager) context.getSystemService(Context.SHORTCUT_SERVICE); | ||
} | ||
} | ||
|
||
/** | ||
* Create a `ShortcutItemProxy` array from a `ShortcutInfo` list. | ||
* @param shortcuts List of `ShortcutInfo` objects. | ||
* @return Array of `ShortcutItemProxy` objects. | ||
*/ | ||
@RequiresApi(api = Build.VERSION_CODES.N_MR1) | ||
private ShortcutItemProxy[] toShortcutItems(List<ShortcutInfo> shortcuts) | ||
{ | ||
final List<ShortcutItemProxy> items = new ArrayList<>(); | ||
|
||
for (ShortcutInfo shortcut : shortcuts) { | ||
final ShortcutItemProxy shortcutItemProxy = new ShortcutItemProxy(); | ||
final KrollDict creationDict = new KrollDict(); | ||
|
||
// Translate into ShortcutItemProxy. | ||
creationDict.put(TiC.PROPERTY_ID, shortcut.getId()); | ||
creationDict.put(TiC.PROPERTY_TITLE, shortcut.getShortLabel()); | ||
creationDict.put(TiC.PROPERTY_DESCRIPTION, shortcut.getLongLabel()); | ||
|
||
// Obtain additional stored data. | ||
if (shortcut.getExtras() != null) { | ||
final PersistableBundle bundle = shortcut.getExtras(); | ||
|
||
if (bundle.containsKey(TiC.PROPERTY_ICON)) { | ||
creationDict.put(TiC.PROPERTY_ICON, bundle.get(TiC.PROPERTY_ICON)); | ||
} | ||
if (bundle.containsKey(TiC.PROPERTY_DATA)) { | ||
try { | ||
final KrollDict data = new KrollDict(new JSONObject(bundle.getString(TiC.PROPERTY_DATA))); | ||
creationDict.put(TiC.PROPERTY_DATA, data); | ||
} catch (JSONException e) { | ||
Log.w(TAG, "Could not parse bundle data property."); | ||
} | ||
} | ||
} | ||
|
||
// Initialize ShortcutItemProxy. | ||
shortcutItemProxy.handleCreationDict(creationDict); | ||
items.add(shortcutItemProxy); | ||
} | ||
|
||
return items.toArray(new ShortcutItemProxy[items.size()]); | ||
} | ||
|
||
/** | ||
* Obtain array of current active shortcuts. | ||
* @return Array of `ShortcutItemProxy` objects. | ||
*/ | ||
@Kroll.getProperty | ||
garymathews marked this conversation as resolved.
Show resolved
Hide resolved
|
||
public ShortcutItemProxy[] items() | ||
{ | ||
if (!shortcutCapability || shortcutManager == null) { | ||
return null; | ||
} | ||
|
||
final List<ShortcutInfo> shortcuts = shortcutManager.getDynamicShortcuts(); | ||
return toShortcutItems(shortcuts); | ||
} | ||
|
||
/** | ||
* Obtain array of current active static shortcuts. | ||
* @return Array of `ShortcutItemProxy` objects. | ||
*/ | ||
@Kroll.getProperty | ||
public ShortcutItemProxy[] staticItems() | ||
garymathews marked this conversation as resolved.
Show resolved
Hide resolved
|
||
{ | ||
if (!shortcutCapability || shortcutManager == null) { | ||
return null; | ||
} | ||
|
||
return toShortcutItems(shortcutManager.getPinnedShortcuts()); | ||
} | ||
|
||
/** | ||
* Add `ShortcutItemProxy` instance. | ||
*/ | ||
@Kroll.method | ||
public void add(ShortcutItemProxy shortcut) | ||
{ | ||
if (!shortcutCapability) { | ||
return; | ||
} | ||
|
||
// NOTE: Create the `ShortcutInfo` instance here, as the creation of `ShortcutInfo` | ||
// in `ShortcutItemProxy.handleCreationDict()` will soon be deprecated a removed. | ||
final Context context = TiApplication.getInstance(); | ||
final ShortcutInfo.Builder shortcutBuilder = new ShortcutInfo.Builder(context, shortcut.getId()); | ||
|
||
// Create shortcut intent. | ||
final Intent intent = new Intent(TiApplication.getAppRootOrCurrentActivity().getIntent()); | ||
intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_NEW_TASK); | ||
intent.setAction(Intent.ACTION_VIEW); | ||
intent.putExtra("shortcut", shortcut.getId()); | ||
intent.putExtra("properties", shortcut.getProperties().toString()); | ||
shortcutBuilder.setIntent(intent); | ||
|
||
shortcutBuilder.setShortLabel(shortcut.getTitle()); | ||
shortcutBuilder.setLongLabel(shortcut.getDescription()); | ||
|
||
// Handle shortcut icon. | ||
final Object icon = shortcut.getIcon(); | ||
if (icon instanceof Number) { | ||
int resId = ((Number) icon).intValue(); | ||
shortcutBuilder.setIcon(Icon.createWithResource(context, resId)); | ||
} else if (icon instanceof String) { | ||
String uri = resolveUrl(null, (String) icon); | ||
shortcutBuilder.setIcon(Icon.createWithResource(context, TiUIHelper.getResourceId(uri))); | ||
} | ||
|
||
// Add shortcut. | ||
final List<ShortcutInfo> shortcuts = new ArrayList<>(); | ||
shortcuts.add(shortcutBuilder.build()); | ||
shortcutManager.addDynamicShortcuts(shortcuts); | ||
} | ||
|
||
/** | ||
* Remove `ShortcutItemProxy` instance. | ||
*/ | ||
@Kroll.method | ||
public void remove(ShortcutItemProxy shortcut) | ||
{ | ||
if (!shortcutCapability) { | ||
return; | ||
} | ||
|
||
// Remove shortcut. | ||
final List<String> ids = new ArrayList<>(); | ||
ids.add(shortcut.getId()); | ||
shortcutManager.removeDynamicShortcuts(ids); | ||
} | ||
|
||
/** | ||
* Remove all active shortcuts. | ||
*/ | ||
@Kroll.method | ||
public void removeAll() | ||
{ | ||
if (!shortcutCapability) { | ||
return; | ||
} | ||
|
||
// Remove all shortcuts. | ||
shortcutManager.removeAllDynamicShortcuts(); | ||
} | ||
|
||
@Override | ||
public String getApiName() | ||
{ | ||
return "Ti.UI.Shortcut"; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Feels a bit odd to have this module stub so we can hang event listeners. Looks like we also always fire the event at the same time to Ti.App
shortcutitemclick
event - so you could probably hack this pretty easily in a js extension (basically add a dumb Ti.UI.Shortcut add/removeEventListener that registers for Ti.App event and forwards it)