Different interfaces based on devices?

What about implementing something similar to Meteoric?

You could implement something similar to what Meteoric has done using navigator.userAgent along with Meteor.isClient and Meteor.isCordova. Their solution allows you to use {{#if isAndroid}}{{/if}} or {{#if isIOS}}{{/if}}. It’s implied that if isAndroid and isIOS are both false, the user is using a web browser - although that’s not 100% true, it is mostly true and can be used that way.

Here is a link to Meteoric’s solution: https://github.com/meteoric/meteor-ionic/tree/ab050a67c55d5507bd0878635c7d90ae48bf4dce/components/ionBody. And listed below is the exact code I am talking about:

Platform = {
  isIOS: function () {
    return (!!navigator.userAgent.match(/iPad/i) || !!navigator.userAgent.match(/iPhone/i) || !!navigator.userAgent.match(/iPod/i))
           || Session.get('platformOverride') === 'iOS';
  },

  isAndroid: function () {
    return navigator.userAgent.indexOf('Android') > 0
           || Session.get('platformOverride') === 'Android';
  }
};

Template.registerHelper('isIOS', function () {
  return Platform.isIOS();
});

Template.registerHelper('isAndroid', function () {
  return Platform.isAndroid();
});

Template.ionBody.helpers({
  platformClasses: function () {
    var classes = ['grade-a'];

    if (Meteor.isCordova) {
      classes.push('platform-cordova');
    }
    if (Meteor.isClient) {
      classes.push('platform-web');
    }
    if ((Meteor.isCordova && Platform.isIOS()) || Session.get('platformOverride') === 'iOS') {
      classes.push('platform-ios');
    }
    if ((Meteor.isCordova && Platform.isAndroid()) || Session.get('platformOverride') === 'Android') {
      classes.push('platform-android');
    }

    return classes.join(' ');
  }
});

You can see how the platformClasses template helper is used to apply CSS styles based on the current user’s device/platform here:

<template name="ionBody">
  <div class="ionic-body {{platformClasses}}">
    {{> UI.contentBlock}}
  </div>
</template>

You can also see Meteoric uses Session.get('platformOverride') as the default if the userAgent match returns false. However, they do not actually set that session variable anywhere in their code (You can check by searching for Session.set('platformOverride' in their github repo), so their full implementation of platform-specific code is included in the two snippets you see above.

Finally, you could use this in your templates like so:

<template name="navbar">
   {{#if isIOS}}
       <h1>This is my iOS navbar!</h1> 
   {{else}}
       {{#if isAndroid}}
           <h1>This is my Android navbar!</h1> 
       {{else}}
           <h1>This is my web navbar!</h1> 
       {{/if}}
   {{/if}}
</template>
3 Likes

hi, where can I read more about DDP connection between meteor and meteor app?

@danielfbm looks like a cleaner approach for building and maintaining larger applications. But i am trying to find out how these packages renders based on the platform, I could see the code being segregated as different packages but how the rendering happens in runtime? I couldn’t find the code for that in the example.

Thanks for sharing.

I can only add two links to this reply, so I will make references only to this repo
Let me try to break things up here so that it might make it easier to understand.

  • The mobile and web interfaces could be created inside the same package. In this case it is important to segregate the target while adding the files and dependent packages like this:

    //Cordova dependencies
    api.use([
    ‘meteoric:ionic’,
    ‘meteoric:ionic-sass’,
    ‘meteoric:ionicons-sass’
    ],‘web.cordova’);

    //Web dependencies
    api.use([
    ‘materialize:materialize’,
    ],‘web.browser’);

extracted from the package.js in the home package
Basically this would use different CSS files/libraries for each client type, instead of just trying to mix everything up and fix whatever comes out of it. Use case: “I want to use Ionic css files for my Cordova app, but bootstrap for my web app.”

  1. Rendering: in the Github repo I shared I am using iron:router to create the routes and help with rendering. It will still use Blaze to render, but I have full control of which routes should be created in each type of client. For the Cordova app in that repo I am using Meteoric so, you might see some more specific Meteoric helpers like @jdrorrer commented above

For the cordova app rendering happens like this:

  1. Iron:router finds the route ( in packages/home/cordova/routes/home.js)
  2. As the template name is not defined, Iron:router will render the template (in packages/home/cordova/home.html) with the same name as the route

And that’s basically what happens in the web as well, but because the files the web client receive are different, it will work only with the set of files it has at the moment:
route in packages/home/web/routes/home.js
template packages/home/web/home.html

If you don’t want to use this approach, you can still use the attribute Meteor.isCordova and using different routes, layouts and templates for your different clients, but that will not separate the CSS files/libraries you are sending to each client type. Also, remember that in the Cordova app all the assets will be downloaded for every hot code push, if I am not mistaken.

It will all come to the choices you make and how you will be able to maintain it. In my case, I suffered enough with puzzling my head around CSS tricks and hacks to make one and only CSS file, but it is not really worth the headache. In the end you might decide to go full native in the mobile part, and throw away all the cordova parts of your app in meteor. In that case, it is better to have it all separated from the beginning, just one of the benefits to illustrate.

I am not sure if I explained what you were asking, I am sorry . Let me know if it is not clear.

9 Likes

@danielfbm There cant be a better explanation than this. You nailed it. Thanks a lot for spending time to write this explanation. Makes sense to me now. I was thinking package.js just has the dependencies never expected that it will load based on platform. Now I understand how this whole thing work. Definitely a better approach than using isCordova.

Thanks

Thanks for sharing this awesome pattern.

Hi @jamgold ,have you ever tried the meteor-client-side package which mentioned in this github issue (which you attended to). If yes, does the result look promising ?

No, I didn’t try it.

Just if you want to know. I give it a try with my mobile app (Angular + Ionic) and very happy with the result :smiley:

1 Like