Skip to content

Commit

Permalink
Allow updating the messenger's text while it's open #19
Browse files Browse the repository at this point in the history
  • Loading branch information
EddyVerbruggen committed Feb 2, 2017
1 parent 4fa9076 commit 9bf8688
Show file tree
Hide file tree
Showing 8 changed files with 117 additions and 27 deletions.
22 changes: 22 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,28 @@ NativeKeyboard.showMessengerKeyboard(
);
```


### `updateMessenger`
Manipulate the messenger while it's open. For instance if you want to update the text programmatically based on what the user typed (by responding to `onTextChanged` events).

|option|type|iOS|Android|description
|---|---|---|---|---
|`text`|`string`|yes|yes|Replace the messenger's text by this. The current text remains if omitted.
|`caretIndex`|`number`|yes|yes|Position the cursor anywhere in the text range. Defaults to the end of the text.
|`showKeyboard`|`boolean`|yes|yes|If `false` or omitted no changes to the keyboard state are made.

```js
NativeKeyboard.updateMessenger(
{
text: "Text updated! ", // added a space so the user can continue typing
caretIndex: 5,
showKeyboard: true
},
function() { console.log('updated ok') },
function(err) { console.log(err)}
);
```

## I like it, hook me up!
This plugin has been a BEAST to implement and its maintenance is killing me already so I need to make this a commercial offering (with a __free trial__, see below) to keep it afloat. If you have a compelling reason to not pay for an unlocked version let me know and we'll work something out.

Expand Down
46 changes: 37 additions & 9 deletions demo/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,18 @@
position: absolute;
top: 26px;
background-color: #eee;
right: 70px;
right: 44px;
font-size: 12px;
text-decoration: underline;
padding: 2px;
border-radius: 2px;
}

#header #updateMessenger {
position: absolute;
top: 26px;
background-color: #eee;
right: 86px;
font-size: 12px;
text-decoration: underline;
padding: 2px;
Expand Down Expand Up @@ -124,8 +135,9 @@

<div id="header">
<div id="title">Chatting with John</div>
<div id="toggleChat" onclick="toggleChat()">Toggle chat</div>
<div id="focusMessenger" onclick="showMessengerKeyboard()">Focus messenger</div>
<div id="toggleChat" onclick="toggleChat()">Toggle</div>
<div id="focusMessenger" onclick="showMessengerKeyboard()">Focus</div>
<div id="updateMessenger" onclick="updateMessenger()">Update</div>
</div>

<div id="messages">
Expand Down Expand Up @@ -163,6 +175,20 @@
});
}

function updateMessenger() {
var options = {
text: "This is the updated text! ",
showKeyboard: true,
caretIndex: 10 // caret is set at end of text if not specified
};

NativeKeyboard.updateMessenger(
options,
// optional success and error handlers
function(){},
function(){});
}

function showMessengerKeyboard() {
NativeKeyboard.showMessengerKeyboard(function(){}, function(){});
}
Expand All @@ -173,11 +199,13 @@
console.log("onSubmit: " + text);
appendMessage(text);
},
onKeyboardWillShow: function () {
console.log("keyboard will show");
onKeyboardWillShow: function (height) {
console.log("keyboard will show, height is: " + height);
//appendMessage("keyboard will show, height is: " + height);
},
onKeyboardDidShow: function (height) {
console.log("keyboard did show, height is: " + height);
console.log("keyboard shows, height is: " + height);
//appendMessage("keyboard shows, height is: " + height);
},
onKeyboardWillHide: function () {
console.log("keyboard will hide");
Expand All @@ -186,9 +214,10 @@
console.log("keyboard did hide");
},
onTextChanged: function(newText) {
// every keystroke will be logged
console.log("text changed to: " + newText);
//appendMessage(newText);
},
showKeyboard: true,
type: "twitter", // iOS only, default (default) | decimalpad | phonepad | numberpad | namephonepad | number | email | twitter | url | alphabet | search | ascii
appearance: "light", // iOS only, light (default) | dark
secure: false, // iOS only, default false, disables things like Emoji and Predicive text entry
Expand All @@ -197,7 +226,7 @@
autoscrollElement: document.getElementById("messages"), // default unset
keepOpenAfterSubmit: true, // default false
animated: true,
text: 'Prefilled text!',
text: "This has been prefilled",
placeholder: 'Type your message..',
placeholderColor: "#DDDDDD",
textViewBackgroundColor: "#F6F6F6",
Expand All @@ -206,7 +235,6 @@
maxChars: 140, // setting this > 0 will make the counter show up on iOS (and ignore input on Android, for now)
counterStyle: 'countdownreversed', // iOS only currently, note that 'none' still shows a counter in case maxChars is set
textColor: '#555555',
showKeyboard: true,

// this button is best suited for picking media (camera / cameraroll / last image) from an actionsheet
leftButton: {
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "cordova-plugin-native-keyboard",
"version": "1.2.1",
"version": "1.3.0",
"description": "This plugin aims to solve common keyboard problems encountered with Cordova / PhoneGap apps. The messenger component (see screenshots) is ready for production, but this plugin will have more tricks up its sleeve. I'll document those once they're ready for primetime as well.",
"cordova": {
"id": "cordova-plugin-native-keyboard",
Expand Down
2 changes: 1 addition & 1 deletion plugin.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<plugin xmlns="http://apache.org/cordova/ns/plugins/1.0"
xmlns:android="http://schemas.android.com/apk/res/android"
id="cordova-plugin-native-keyboard"
version="1.2.1">
version="1.3.0">

<name>Native Keyboard</name>

Expand Down
15 changes: 15 additions & 0 deletions src/android/NativeKeyboard.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ public class NativeKeyboard extends CordovaPlugin {

private static final String ACTION_SHOW_MESSENGER = "showMessenger";
private static final String ACTION_SHOW_MESSENGER_KEYBOARD = "showMessengerKeyboard";
private static final String ACTION_UPDATE_MESSENGER = "updateMessenger";
private static final String ACTION_HIDE_MESSENGER = "hideMessenger";

private NativeKeyboardImpl impl;
Expand Down Expand Up @@ -56,6 +57,20 @@ public void onError(String errorMessage) {
});
return true;

} else if (ACTION_UPDATE_MESSENGER.equals(action)) {
impl.updateMessenger(args.getJSONObject(0), new OnNativeKeyboardEventListener() {
@Override
public void onSuccess(JSONObject result) {
callbackContext.success();
}

@Override
public void onError(String errorMessage) {
callbackContext.error(errorMessage);
}
});
return true;

} else if (ACTION_HIDE_MESSENGER.equals(action)) {
impl.hideMessenger(args.getJSONObject(0), new OnNativeKeyboardEventListener() {
@Override
Expand Down
Binary file modified src/android/lib/nativekeyboard.jar
Binary file not shown.
55 changes: 40 additions & 15 deletions src/ios/CDVNativeKeyboard.m
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,31 @@ - (void)showMessenger:(CDVInvokedUrlCommand*)command {
}
}

- (void)updateMessenger:(CDVInvokedUrlCommand*)command {
if (tvc != nil) {
NSDictionary* options = [command argumentAtIndex:0];
if (options[@"text"]) {
tvc.textView.text = options[@"text"];
}

if ([options[@"showKeyboard"] boolValue]) {
[tvc presentKeyboard:YES];
}

if (options[@"caretIndex"] != nil) {
int caretIndex = [options[@"caretIndex"] intValue];
UITextPosition *textPosition = [tvc.textView positionFromPosition:tvc.textView.beginningOfDocument offset:caretIndex];
[tvc.textView setSelectedTextRange:[tvc.textView textRangeFromPosition:textPosition toPosition:textPosition]];
}

CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK];
[self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
} else {
CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"Call 'showMessenger' first."];
[self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
}
}

- (void)hideMessenger:(CDVInvokedUrlCommand*)command {
if (tvc != nil) {
NSDictionary* options = [command argumentAtIndex:0];
Expand Down Expand Up @@ -136,7 +161,7 @@ - (void)show:(CDVInvokedUrlCommand*)command {
textarea = [@"textarea" isEqualToString:options[@"type"]];

UIControl<NKTextInput>* field = [self getActiveTextViewOrField];

// to make this play nice with the messenger, we need to do:
if (textarea) {
if (!wasTextarea) {
Expand All @@ -151,11 +176,11 @@ - (void)show:(CDVInvokedUrlCommand*)command {
if (![field isDescendantOfView:self.viewController.view]) {
[self.viewController.view addSubview:field];
}

allowClose = NO;

CGRect screenBounds = [[UIScreen mainScreen] bounds];

if (options[@"type"] != nil) {
if ([NativeKeyboardHelper allowFeature:NKFeatureKeyboardType]) {
UIKeyboardType keyBoardType = [NativeKeyboardHelper getUIKeyboardType:options[@"type"]];
Expand All @@ -179,20 +204,20 @@ - (void)show:(CDVInvokedUrlCommand*)command {
}
[field setReturnKeyType:[NativeKeyboardHelper getUIReturnKeyType:returnKeyType]];
[field setKeyboardAppearance:[NativeKeyboardHelper getUIKeyboardAppearance:options[@"appearance"]]];

double phoneHeight = screenBounds.size.height;
// prolly better to grab it like this: https://github.com/driftyco/ionic-plugin-keyboard/blob/master/src/ios/IonicKeyboard.m#L27
double keyboardHeight = 240;

NSDictionary *accessorybar = options[@"accessorybar"];
if (accessorybar == nil) {
[field setInputAccessoryView:nil];
} else {
int toolbarHeight = 44;
keyboardHeight += toolbarHeight;

toolBar.frame = CGRectMake(0, 0, screenBounds.size.width, toolbarHeight);

NSArray *btns = accessorybar[@"buttons"];
NSMutableArray<UIBarButtonItem*> *buttons = [[NSMutableArray alloc] initWithCapacity:btns.count];
for (int i = 0; i < (int)btns.count; i++) {
Expand Down Expand Up @@ -243,7 +268,7 @@ - (void)show:(CDVInvokedUrlCommand*)command {
[buttons addObject:button];
}
}

if (buttons.count > 0) {
[NativeKeyboardHelper setUIBarStyle:accessorybar[@"style"] forToolbar:toolBar];
[toolBar setItems:buttons];
Expand All @@ -253,15 +278,15 @@ - (void)show:(CDVInvokedUrlCommand*)command {
[field setInputAccessoryView:nil];
}
}

// used elsewhere
maxlength = [options[@"maxlength"] intValue];
offsetTop = [options[@"offsetTop"] doubleValue];

double yCorrection = [field updatePostion:options
forPhoneHeight:phoneHeight
andKeyboardHeight:keyboardHeight];

// adjust the scrollposition if needed
if (yCorrection > 0) {
// set this to 0 to hide the caret initially
Expand All @@ -275,13 +300,13 @@ - (void)show:(CDVInvokedUrlCommand*)command {
}

[self.webView.scrollView setContentOffset: CGPointMake(0, yCorrection + offsetTop) animated:YES];

// do this to early and things will crash
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 500 * NSEC_PER_MSEC), dispatch_get_main_queue(), ^{
[self.webView.scrollView setScrollEnabled:NO];
self.webView.scrollView.delegate = self;
});

// now show the caret
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 300 * NSEC_PER_MSEC), dispatch_get_main_queue(), ^{
field.alpha = 1;
Expand Down Expand Up @@ -355,7 +380,7 @@ - (void) close:(id)type {
[field hide];
[self.webView.scrollView setScrollEnabled:YES];
self.webView.scrollView.delegate = nil;

[self dismissKeyboard:YES];

// restore the scroll position
Expand Down Expand Up @@ -395,7 +420,7 @@ - (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRang
} else if ([text isEqualToString:@"\t"]) {
return NO;
}

if (maxlength > 0 && textField.text.length >= maxlength && text.length > 0) {
return NO;
}
Expand Down
Loading

0 comments on commit 9bf8688

Please sign in to comment.