diff --git a/android/KMEA/app/src/main/assets/keyboard.html b/android/KMEA/app/src/main/assets/keyboard.html index 0b57d747b7..b649c92adc 100644 --- a/android/KMEA/app/src/main/assets/keyboard.html +++ b/android/KMEA/app/src/main/assets/keyboard.html @@ -235,6 +235,23 @@ } } + function suggestionPopup(obj,custom,x,y,w,h) { + if(obj != null) { + var i; + var s = JSON.stringify(obj); + var shift = false; + var pos = x.toString() + ',' + y.toString(); + var size = w.toString() + ',' + h.toString(); + + + fragmentToggle=(fragmentToggle+1) % 100; + var hash = 'suggestPopup-' + fragmentToggle + '+pos=' + pos + '+size=' + size + '+suggestion=' + s; + hash = hash + '+custom=' + custom; + + window.location.hash = hash; + } + } + function showMenu() { fragmentToggle = (fragmentToggle + 1) % 100; window.location.hash = 'globeKeyAction' + fragmentToggle; diff --git a/android/KMEA/app/src/main/java/com/tavultesoft/kmea/JSONParser.java b/android/KMEA/app/src/main/java/com/tavultesoft/kmea/JSONParser.java index 00ce496df7..04c9391e11 100644 --- a/android/KMEA/app/src/main/java/com/tavultesoft/kmea/JSONParser.java +++ b/android/KMEA/app/src/main/java/com/tavultesoft/kmea/JSONParser.java @@ -12,6 +12,7 @@ import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.InterruptedIOException; +import java.io.StringReader; import java.io.UnsupportedEncodingException; import java.net.HttpURLConnection; import java.net.URL; @@ -162,4 +163,16 @@ public final class JSONParser { public JSONObject getJSONObjectFromUrl(String urlStr) { return getJSONObjectFromUrl(urlStr, JSONObject.class); } + + public JSONObject getJSONObjectFromString(String str) { + return getJSONObjectFromReader(new BufferedReader(new StringReader(str))); + } + + public JSONObject getJSONObjectFromURIString(String str) { + try { + return getJSONObjectFromString(java.net.URLDecoder.decode(str, "UTF-8")); + } catch (UnsupportedEncodingException e) { + return null; + } + } } \ No newline at end of file diff --git a/android/KMEA/app/src/main/java/com/tavultesoft/kmea/KMManager.java b/android/KMEA/app/src/main/java/com/tavultesoft/kmea/KMManager.java index ef2fc96f46..fb10e4a2f9 100644 --- a/android/KMEA/app/src/main/java/com/tavultesoft/kmea/KMManager.java +++ b/android/KMEA/app/src/main/java/com/tavultesoft/kmea/KMManager.java @@ -1371,6 +1371,36 @@ public final class KMManager { currentBanner = (change.equals("loaded")) ? "suggestion" : "blank"; RelativeLayout.LayoutParams params = getKeyboardLayoutParams(); InAppKeyboard.setLayoutParams(params); + } else if (url.indexOf("suggestPopup") >= 0) { + int start = url.indexOf("pos=") + 4; + int end = url.indexOf("size="); + + String posData[] = url.substring(start, end).split("\\,"); + + start = end + 5; + end = url.indexOf("suggestion="); + + String sizeData[] = url.substring(start, end).split("\\,"); + + start = end + 11; + end = url.indexOf("custom="); + + String suggestionJSON = url.substring(start, end); + + start = end + 7; + + String isCustomStr = url.substring(start); + + JSONParser parser = new JSONParser(); + JSONObject obj = parser.getJSONObjectFromURIString(suggestionJSON); + + try { + Log.v("KMEA", "Suggestion display: " + obj.getString("displayAs")); + } catch (JSONException e) { + //e.printStackTrace(); + Log.v("KMEA", "JSON parsing error: " + e.getMessage()); + } + } return false; } @@ -1547,8 +1577,37 @@ public final class KMManager { currentBanner = (change.equals("loaded")) ? "suggestion" : "blank"; RelativeLayout.LayoutParams params = getKeyboardLayoutParams(); SystemKeyboard.setLayoutParams(params); - } - return false; + } else if (url.indexOf("suggestPopup") >= 0) { + int start = url.indexOf("pos=") + 4; + int end = url.indexOf("size="); + + String posData[] = url.substring(start, end).split("\\,"); + + start = end + 5; + end = url.indexOf("suggestion="); + + String sizeData[] = url.substring(start, end).split("\\,"); + + start = end + 11; + end = url.indexOf("custom="); + + String suggestionJSON = url.substring(start, end); + + start = end + 7; + + String isCustomStr = url.substring(start); + + JSONParser parser = new JSONParser(); + JSONObject obj = parser.getJSONObjectFromURIString(suggestionJSON); + + try { + Log.v("KMEA", "Suggestion display: " + obj.getString("displayAs")); + } catch (JSONException e) { + //e.printStackTrace(); + Log.v("KMEA", "JSON parsing error: " + e.getMessage()); + } + + return false; } } diff --git a/web/source/kmwembedded.ts b/web/source/kmwembedded.ts index ce7ad6c422..0536908d1f 100644 --- a/web/source/kmwembedded.ts +++ b/web/source/kmwembedded.ts @@ -186,6 +186,18 @@ namespace com.keyman.osk { return true; }; + + SuggestionManager.prototype.platformHold = function(this: SuggestionManager, suggestionObj: BannerSuggestion, isCustom: boolean) { + // Parallels VisualKeyboard.prototype.touchHold, but for predictive suggestions instead of keystrokes. + let suggestionEle = suggestionObj.div; + + // Need to know if it's a option or not! + + var xBase = dom.Utils.getAbsoluteX(suggestionEle) - dom.Utils.getAbsoluteX(suggestionEle.parentElement) + suggestionEle.offsetWidth/2, + yBase = dom.Utils.getAbsoluteY(suggestionEle) - dom.Utils.getAbsoluteY(suggestionEle.parentElement); + + window['suggestionPopup'](suggestionObj.suggestion, isCustom, xBase, yBase, suggestionEle.offsetWidth, suggestionEle.offsetHeight); + } } namespace com.keyman.text { diff --git a/web/source/osk/banner.ts b/web/source/osk/banner.ts index f4c3544853..8d6fa3b0da 100644 --- a/web/source/osk/banner.ts +++ b/web/source/osk/banner.ts @@ -407,9 +407,11 @@ namespace com.keyman.osk { } } - class SuggestionManager extends dom.UITouchHandlerBase { + export class SuggestionManager extends dom.UITouchHandlerBase { private selected: BannerSuggestion; + platformHold: (suggestion: BannerSuggestion, isCustom: boolean) => void; + //#region Touch handling implementation findTargetFrom(e: HTMLElement): HTMLDivElement { let keyman = com.keyman.singleton; @@ -459,11 +461,16 @@ namespace com.keyman.osk { //#region Long-press support protected hold(t: HTMLDivElement): void { - // Temp, pending implementation of suggestion longpress submenus - // - nothing worth doing with a hold yet - + let suggestionObj = t['suggestion'] as BannerSuggestion; - // Should have separate native + embedded mode branches. - // Embedded mode should pass any info needed to show a submenu IMMEDIATELY. + // Is this the suggestion? It's never in this.currentSuggestions, so check against that. + let isCustom = this.currentSuggestions.indexOf(suggestionObj.suggestion) == -1; + + if(this.platformHold) { + // Implemented separately for native + embedded mode branches. + // Embedded mode should pass any info needed to show a submenu IMMEDIATELY. + this.platformHold(suggestionObj, isCustom); // No implementation yet for native. + } } protected clearHolds(): void { // Temp, pending implementation of suggestion longpress submenus @@ -471,12 +478,12 @@ namespace com.keyman.osk { // only really used in native-KMW } + protected hasModalPopup(): boolean { - // Temp, pending implementation of suggestion longpress submenus - // Utilized by the mobile apps; allows them to 'take over' touch handling, // blocking it within KMW when the apps are already managing an ongoing touch-hold. - return false; + let keyman = com.keyman.singleton; + return keyman['osk'].vkbd.popupVisible; } protected dealiasSubTarget(target: HTMLDivElement): HTMLDivElement {