• Hi all,

    Safe to say I've got the bug for writing apps for the Bangle2! But I'm not very experienced with javascript, and confused how to turn what I've written into a keyboard.

    See here for an example of my multitap/T9 keyboard, using the layout library and the logic from here:
    Try it out by loading it onto your watch as filename textinput, then use the Noteify app to try and write something.

    It can write text quite happily, but I'm stuck returning it to the app. Something to do with resolve(text), but not sure what a resolve is, or how to get it to work. Can anyone offer any suggestions?

  • Nevermind, got it. A keyboard needs to look something like this:

    exports.input = function(options) {
      options = options||{};
      var text = options.text;
      if ("string"!=typeof text) text="";
      return new Promise((resolve,reject) => {
        layout = new Layout( { LAYOUT }
          ,{back: ()=>{

    I'll wrap it up into an app next.

  • Great! I look forward to seeing it in action ;)

  • It's ready, if anyone wants to try it out: https://sir-indy.github.io/BangleApps/?i­d=kbmulti
    You'll also need to install Noteify to be able to use it.

    I'm probably going to tweak it some more, try a few different fonts on the buttons to see what looks clearest.

    Any feedback please let me know, I've found that with just a little practice I'm now quite accurate and quick with it.

  • Nice one, I like this!

    Feature suggestions:

    • User defined duration for charTimout via settings.
    • Swipe left-to-right: 1) cut charTimeout short if active. 2) else input space.
    • Swipe right-to-left: Backspace.
    • Swipe bottom-to-top: switch caps lock.
    • Swipe top-to-bottom: Hide/show bottom row and increase/decrease the height of the rows
      • (Possibly also/instead hide widget field to gain more vertical pixels per button?)
    • Auto switching letter casing maybe?

    What do you think?

    I might try and add some of these suggestions :)

    Here it's updated as per my suggestions on my app loader: Multitap keyboard v0.05. I'd be happy to do a pull request once you've submitted the keyboard to the main repo! (I don't think I can do one into your fork?) I added a setting for disabling swiping as well.

    EDIT2: I've messed something up, it doesn't exit correctly. I don't really grasp how promises work, and how to make Bangle.on('swipe' ....) stop, after the promise has resolved the text. Here's the code.

  • Hi @Ganblejs, thanks for your feedback and suggestions! It's great to have someone excited by something you've made!

    Going point-by-point:

    • User defined duration - we can make it configurable, just wondering why you'd want to change it? Was it too fast, too slow? Is there a better default we should use?
    • Swipe - really like this idea, I've been giving it some thought and will fold your code into mine to use left for space, right for backspace, up/down for caps lock. Hiding the bottom row is a good idea, and with most of the bottom row functions replaced by swipes we can permanently remove it and have bigger buttons, which will help a lot!
      It's come up in these forums before that swipes without an indicator that you can swipe could mean people don't know the option is there, but we can list it in the description, and maybe put a help message up when the text is tapped?
    • Auto switching letter case - this could make it hard to type in all caps, so I'll leave this as it is for now.
    • promises - I can't help there, I don't know either! It was basically trial and (lots of) error getting this far. As far as I know though, when we call the back function which includes Bangle.setUI();, that should clear any custom interface code. I'll have a look though and see what I can find out.
  • Just regarding user defined duration, I wanted a shorter duration, around 225-300 ms works good for me. I felt 750 ms was a little long - that I had to wait too long to make for example two A's.

  • @Ganblejs, I've made some progress with the swipe issues, turns out you need to Bangle.removeListener("swipe", onSwipe); on exit, then it works fine.

    I'm having the opposite problem with the help screen though, tap the text to open the help screen, press ok to go back, and all the buttons in the layout stop responding. I'll look into this as I've had the problem before in my timer app, and fudged it with a custom onTouch, but it looks like we need a proper solution.

    I'll add your setting for duration in later, for now shortened to 500ms, any less for me and I can't press the buttons quickly (and accurately) enough. Shows why a setting is a good idea!

    (EDIT: tried to download a screenshot, came as a .dib format, attached to the message fine, but no preview image. Tried to remove and replace with a converted PNG version, error)

  • Ah, great about Bangle.removeListener()!

    Generating the layout anew when exiting onHelp() makes the buttons pressable. I suspect there's a better way to do it though.
    Test here.
    Code here .

    What I changed (line 1, 7, 12 and 41 below):

    function onHelp(resolve,reject) {
      Bangle.removeListener("swipe", onSwipe);
        helpMessage, {title: "Help", buttons : {"Ok":true}}
      ).then(function(v) {
        Bangle.on('swipe', onSwipe);
    function generateLayout(resolve,reject) {
      layout = new Layout( {
      type:"v", c: [
        {type:"txt", font:"10%", label:text, id:"text", cb: l=>onHelp(resolve,reject), fillx:1},
        {type:"h", c: [
          {type:"btn", font:fontSize, label:letters[1], cb: l=>onKeyPad(1), id:'1', fillx:1, filly:1 },
          {type:"btn", font:fontSize, label:letters[2], cb: l=>onKeyPad(2), id:'2', fillx:1, filly:1 },
          {type:"btn", font:fontSize, label:letters[3], cb: l=>onKeyPad(3), id:'3', fillx:1, filly:1 },
        {type:"h", filly:1, c: [
          {type:"btn", font:fontSize, label:letters[4], cb: l=>onKeyPad(4), id:'4', fillx:1, filly:1 },
          {type:"btn", font:fontSize, label:letters[5], cb: l=>onKeyPad(5), id:'5', fillx:1, filly:1 },
          {type:"btn", font:fontSize, label:letters[6], cb: l=>onKeyPad(6), id:'6', fillx:1, filly:1 },
        {type:"h", filly:1, c: [
          {type:"btn", font:fontSize, label:letters[7], cb: l=>onKeyPad(7), id:'7', fillx:1, filly:1 },
          {type:"btn", font:fontSize, label:letters[8], cb: l=>onKeyPad(8), id:'8', fillx:1, filly:1 },
          {type:"btn", font:fontSize, label:letters[9], cb: l=>onKeyPad(9), id:'9', fillx:1, filly:1 },
      },{back: ()=>{
      Bangle.removeListener("swipe", onSwipe);
      return new Promise((resolve,reject) => {
        Bangle.on('swipe', onSwipe);

    The help message is a good idea! Maybe it can be displayed directly on first launch as well?
    Something like this at the beginning of the promise:

    var settings = require('Storage').readJSON("kbmulti.set­tings.json", true) || {};
    if (!settings.firstLaunch) { onHelp(resolve,reject); 
      settings.firstLaunch = false;
      require('Storage').writeJSON("kbmulti.se­ttings.json", settings);
  • Thank you, you're right generating the layout again seems to be the only way to do it at the moment. It feels like there should be a better way, but it works.

    Great idea to pop up the help message on first launch! Very nice way to make it clear to the user how to use the app. I think I'll use that in future apps too, so thank you for that.

    I'll make these changes and submit a pull request. How do you want to be credited? It seems most apps have a link to the original author Github Page, do you want your name on it as @Ganblejs or thyttan?

  • Ok, nice!

    I'd be happy to be credited as my github alias 🙂

  • And done! Thank you @Gordon for accepting the pull request, I really am having fun with this project!
    And thank you @Ganblejs for your help, this has been a great experience collaboratively writing an app with you!

  • Thank you for the keyboard, collaboration and being generous with the crediting :)

    I've done some more tweaks that can be tested here. Code here.

    0.02: Introduce setting "Show help button?". Make setting firstLaunch invisible by removing corresponding code from settings.js. Add marker that shows when character selection timeout has run out. Display opened text on launch when editing existing text string.

    I have noticed a problem with how I implement the marker. If I exit the keyboard before characterTimeout has run out the displayText()-function displays over the noteify-screen.

    Thoughts? :)

  • Hi, they sound like good changes, good idea.
    I did have the text displayed correctly on launch, but accidentally overwrote my code with an old version, oops! Didn't notice that I'd missed that. Can you do me a favour and make another change? Capitalise the first word 'Swipe' in the help text, that's been bugging me.

    I suspect you can fix the exit problem by clearing the charTimeout in the 'back' function of the layout. Use the same code as in the backspace and onKeypad function. Now that chunk will be used in 3 places you could wrap it up as it's own clearTimeout function if you want.

    Hope that helps!

  • Thanks for the tip! Just opened a pull request.

    Can be tested here. Code here.

    Small bug:

    • The font on the ok-button in help message changes to be smaller when pressing it - I think it's to do with loading the layout which has a smaller font on buttons. Maybe.

    Suggested future improvements:

    • wrap the text field in another way so that all available space is always used independent of character widths. Now the displayed string is fixed to a specified number of characters.
    • maybe align buttons perfectly in the button layout. (this is nitpicking)
    • maybe make the marker blink.
  • Hi @Ganblejs,
    I'm trying to test out your new changes, but I can only see V0.01 at the link you posted? Am I looking in the wrong place?

    I've seen the bug with the ok-button shrinking the text, but in the alarm message, so it's not something we've changed here. It may be something that I've broken when I tweaked the layout library, I'll look into it.

    Align buttons: Annoyingly, that is something else I changed then accidentally overwrote my code and missed it! Easy to fix though, at the start of the code put var btnWidth = g.getWidth()/3;, then in each button in the layout add width:btnWidth. This will fix them all at exactly the same size.

  • My mistake, I tested some changes I did to Desktop Launcher and left that branch on my github pages/app loader. I've changed back to my kbmulti branch now.

    Ok, I'll try and add the button alignment before the pr gets merged!

  • Yep, that works! All looks good to me. I particularly like the marker, having a visual indication for when the letter is locked in really helps.

    Do you mind sharing how you change branch in GitHub? I've been working on one thing at a time because the checking script and pages only work on the main branch. Switching between branches would be very helpful!

  • First, I presume you already went through this guide.

    On your fork start page, click the branch-button that says 'master' -> then enter a new branch name in the text input box -> then click 'Create branch: ....'

    See if the screenshots below help you.

    After that you can choose which branch should be published on your github-pages, by on your fork start page going 'settings' -> 'Pages' -> 'Source' -> select branch in drop-down list.

    2 Attachments

    • Screenshot from 2022-05-16 12-00-14.png
    • Screenshot from 2022-05-16 12-00-59.png
  • Also, maybe you find my answer here regarding resetting a branch relevant at some point.

  • on your fork start page going 'settings' -> 'Pages' -> 'Source' -> select branch in drop-down list.

    Thank you! That looks like what I was missing, that'll be very helpful! GitHub/Git in general is still new to me, but I'm learning a lot here.

  • No problem! The same goes for me! :)

  • Post a reply
    • Bold
    • Italics
    • Link
    • Image
    • List
    • Quote
    • code
    • Preview

Help with keyboard for BangleJS2 - Multitap/T9 layout

Posted by Avatar for Sir_Indy @Sir_Indy