Giter Site home page Giter Site logo

emadalam / atvjs Goto Github PK

View Code? Open in Web Editor NEW
311.0 23.0 48.0 1.28 MB

Blazing fast Apple TV application development using pure JavaScript

Home Page: https://emadalam.github.io/atvjs

License: MIT License

JavaScript 100.00%
apple-tv tvml apple-tv-application apple-tv-development tvjs apple-tv-framework atvjs tvos tvmlkit tvmlkitjs

atvjs's People

Contributors

emadalam avatar erveon avatar gitter-badger avatar hhumphrey-dazn avatar hhumphrey84 avatar marhycz avatar spunkedy avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

atvjs's Issues

Implement testing strategy

  • evaluate and implement a core test strategy
  • stubs and mocks for the Apple's tvmljs library
  • core setup and integration to facilitate writing tests

How to handle Deep Linking from TopShelf when using MenuPages

When using Menu Pages like the boilerplate, how can I handle deeplinking from the app Top Shelf?
I'd like to check if the "options" parameter of onLaunch has the "DEEPLINK" property and load the movies page directly without loading the Home page.

Navigation.showError() modals are unable to be dismissed

Modal dialogs created with navigationDocument.presentModal() are able to be dismissed but using Navigation.showError() results in a dialog where the button does not work, escape or home must be used to dismiss.

Consider the following code if added to the Movie Catalog example app in the ready method of the HomePage object:

const showError = () => {
  // const alert = `<?xml version="1.0" encoding="UTF-8" ?>
  //     <document>
  //       <alertTemplate>
  //         <title>Error</title>
  //         <description>This modal cannot be dismissed.</description>
  //         <button data-alert-dissmiss="close">
  //           <text>OK</text>
  //         </button>
  //       </alertTemplate>
  //     </document>`;
  // const error = ATV.Navigation.showError({ template: alert, style: '' });

  const alert = `<?xml version="1.0" encoding="UTF-8" ?>
    <document>
      <alertTemplate>
        <title>Error</title>
        <description>This modal can be dismissed.</description>
        <button>
          <text>OK</text>
        </button>
      </alertTemplate>
    </document>`;
  const parser = new DOMParser();
  const error = parser.parseFromString(alert, 'application/xml');
  navigationDocument.presentModal(error);

  error.addEventListener('select', () => {
    ATV.Navigation.dismissModal();
  })
};

The uncommented version works as expected. Inverting the commented code results in the modal not being dismissed but with the data-alert-dissmiss [sic] attribute the navigationDocument.dismissModal() method is called, as indicated by the log:
close button clicked within the modal, dismissing modal...

Cannot hide the loading indicator

I'm trying to build this app that uses a third party library to access an API and thus does not use the Ajax component of atvjs.

When I use ATV.start() and pass to it the loadingTpl, it will show the loading indicator when I change page from the menubar, however even though by ready() method does call resolve(), the loading indicator is still being displayed.

How can I hide it?

Pages not regenerating

Came across this comment on SO indicating that pages would regenerate when you navigate to them.

This doesn't seem to be the case for me at the moment, are changes to the template supposed to be available without rebooting the application?

Multiple page event-handlers causes app to crash

If you define more than one event listener in the events object, the application will crash when it displays that page. I've confirmed this by adding two events to various pages in the example app, for example:

import ATV from 'atvjs';

import template from './template.hbs';

let Page = ATV.Page.create({
  name: 'list-with-banner',
  template: template,
  events: {
    highlight: 'onHighlight',
    select: 'onSelect'
  },
  onSelect(e) {
    console.log(e);
  },
  onHighlight(e) {
    console.log(e);
  }
});

export default Page;

This is the error in Safari's console: There was an error in the page code. TypeError: self type check failed for Objective-C instance method

I've tried various ways of declaring the event config/handlers but the result is always the same (sometimes a different error message, however).

DOMParser is not defined

Hey.
First, thanks for your work. I think, that this project can be very useful, but I got the following problem.

I've created an index.js file with the following content, based on your example code.

var ATV = require('atvjs');

ATV.Page.create({
    name: 'home',
    // use a template function from your favourite templating engine
    // or pass a raw template function
    template(data) {
        return `<document>
                    <alertTemplate>
                        <title>${data.title}</title>
                        <description>${data.description}</description>
                    </alertTemplate>
                </document>`;
    },
    // pass some raw data to be applied
    // or a data function that returns the data
    data: {
        title: 'Homepage',
        description: 'This is my super awesome homepage created using atvjs.'
    }
});

// later in your application you can do something like below to navigate to the page
ATV.Navigation.navigate('home');

I'm using Node.js 4.4.0. And the following error ist the result of that.

/srv/www/SUB.DOMAIN.TLD/www/node_modules/atvjs/dist/atv.js:18710
    var parser = new DOMParser(); // native DOM parser
                     ^

ReferenceError: DOMParser is not defined
    at Object._typeof (/srv/www/SUB.DOMAIN.TLD/www/node_modules/atvjs/dist/atv.js:18710:19)
    at __webpack_require__ (/srv/www/SUB.DOMAIN.TLD/www/node_modules/atvjs/dist/atv.js:34:30)
    at Object.<anonymous> (/srv/www/SUB.DOMAIN.TLD/www/node_modules/atvjs/dist/atv.js:77:16)
    at __webpack_require__ (/srv/www/SUB.DOMAIN.TLD/www/node_modules/atvjs/dist/atv.js:34:30)
    at /srv/www/SUB.DOMAIN.TLD/www/node_modules/atvjs/dist/atv.js:54:18
    at /srv/www/SUB.DOMAIN.TLD/www/node_modules/atvjs/dist/atv.js:57:10
    at webpackUniversalModuleDefinition (/srv/www/SUB.DOMAIN.TLD/www/node_modules/atvjs/dist/atv.js:7:20)
    at Object.<anonymous> (/srv/www/SUB.DOMAIN.TLD/www/node_modules/atvjs/dist/atv.js:14:3)
    at Module._compile (module.js:435:26)
    at Object.Module._extensions..js (module.js:442:10)

Do you have any idea how this can be fixed?

Thanks.

Ajax should utilize more complete promise

I find it confusing and limiting when the Ajax call returns a promise but doesn't utilize the reject capability.

So instead of handling success/failure in the resolved promise (the then()):

ATV
			.Ajax
			.post('someURL', {data: data})
			.then((xhr) => {
				// xhr succeeded
			}, (xhr) => {
				// xhr failed
			});

You would have more true promise-based logic using then() and/or catch() and/or finally():

ATV
			.Ajax
			.post('someURL', {data: data})
			.then((xhr) => {
				// xhr succeeded
			})
			.catch((xhr) => {
				// xhr failed
			})
			.finally(() => {
				// regardless of success/failure, also do this
			});

For developers who understand promises, the current implementation seems halfway done. It also prevents normal promise chaining, which flattens out the old "callback hell" problem.

Support menu item reload configuration

Currently

Selecting the menu item loads the previously loaded cached page and there is no way to force reload it based on configuration.

Wanted

Support attribute configuration reloadOnSelect to load a non-cached version of the page on every selection.

...
menu: {
    items: [{
        ...
        attributes: {
            reloadOnSelect: true
        }
    }]
}
...

Sample code for player

Hello. Could you please provide a sample code for initializing the player and playing the actual movie.

Thank you.

presentModal closes itself on first use

When ATV.Navigation.presentModal(descriptiveAlertTemplateString) is called the modal opens, but on the first time it closes itself right away. It seems fine on the calls after that. Might this be a bug?

Need help, newbie here

I am trying to develop an application using atvjs; installed node and npm; installed packages and so on. If in my app.js I do "import atvjs" is not working; also if I do "var atvjs = require('atvjs') is not working and I get "ReferenceError: Can't find variable: require"

Where am I wrong?

Debugging?

Is there any way of debugging the JS? Even console.log doesn't seem to do anything.

Secure image fetch

Would it possible to add a header when fetching images?
My app requires authorisation for downloading user images, this can be done by adding a Authorization header with the bearer token to the request.

Replacing error pages

Hi – great library, helped us a lot in setting up our tvOS app. But I believe I've come across a bug with the handling of error pages. The logic to detect whether to replace or push a document to the navigation stack is this, within the cleanNavigate method:

if (!replace && (!last || last !== loaderDoc || last !== errorDoc)) {

If the last doc was an errorDoc this returns true...as the last doc wasn't a loader doc. Therefore I believe it should be this:

if (!replace && (!last || ( last !== loaderDoc && last !== errorDoc ))) {

This will correctly fathom if the last doc was either an error or a loader, return false and proceed to replace the doc and not push.

If you are happy with this change I'll create a PR

Dark loading indicator page

I have an app that uses a MenuBar template with items set with reloadOnSelect.
Every time I change view it reloads the content from an API and the loading indicator shows up. Each view has a dark theme but when the loading indicator shows, the background is bright.

Is it possible to set a dark background when the loader shows?

I thought of setting a class to the element and use CSS but it does not work either.

Re-render a template?

Use-case

Using a listTemplate, I would like to make the relatedContent area dynamic, populating it with content when a listItemLockup is highlighted by the user.

Consider the following (simplified) page:

import ATV from 'atvjs';
import template from './template.hbs';

const APIURL = 'http://myapi/shows';

let Page = ATV.Page.create({
  name: 'shows',
  template: template,
  events: {
    select(e) {
      console.log(e);
    },
    highlight(e) {
      // RE-RENDER
    }
  },
  ready(options, resolve, reject) {
    ATV.Ajax
      .get(APIURL)
      .then((xhr) => {
        let response = xhr.response;
        resolve(response);
      }, (xhr) => {
        let response = xhr.response;
        reject({
          status: xhr.status,
          message: response.message
        });
      });
  }
});

export default Page;

Using the ReactJS model as an analogy, I would like to be able to do something like:

  • on select event, derive data from event object to create "related content".
  • manipulate the 'state' (data) of that page that gets passed to the template.
  • re-render the template with new data.

I tried to do this by storing a reference to the resolve method passed into ready and giving that fresh data but, although I can see output in the console that this has done something with the data, the page doesn't re-render.

I'm assuming this is possible somehow, I'm probably missing something really obvious...

EDIT:

Having played around, it seems you can do some old-fashioned DOM traversal/manipulation using the reference to doc that the afterReady method receives. Although this is a passable way of doing things, I would be interested to know if there scope for something more aligned with the way modern SPA's are built, rather than hunting down nodes and injecting content in to them.

Create common aliases

Currently

The commonly used methods are under a second level object.

Wanted

Create aliases

  • ATV.Page.create --> ATV.createPage
  • ATV.Menu.create --> ATV.createMenu
  • ATV.Navigation.navigate --> ATV.navigateTo
  • ATV.Navigation.navigateToMenuPage --> ATV.navigateToMenuPage
  • ATV.Navigation.presentModal --> ATV.presentModal
  • ATV.Navigation.dismissModal --> ATV.dismissModal

Pass options to page and display it

Hello,

I would like to pass options to a page with data-href-page-options.
<button data-href-page="details-page" data-href-page-options='{"title": "Hello World"}'>

/details-page/index.js :

ATV.Page.create({
    name: 'DetailsPage',
    template: template,
    WHAT CODE TO RETRIEVE OPTIONS ?
});

/details-page/template.hbs :

<document>
  <productTemplate>
    <banner>
      <stack>
        <title>WHAT CODE TO DISPLAY OPTIONS</title>
      </stack>
    </banner>
  </productTemplate>
</document>

Thanks.

resolve parameters in Page.url

From one of the PRs #12

This allows to build URLs for pages dynamically based on the options.urlParams that are handed over to the page.
Uses the same node-module that express uses, so the very same syntax applies. For example use “http://httpbin.org/get?test=:test” with options = {urlParams: {test: true}} to get “http://httpbin.org/get?test=true”.

  • evaluate configuration format
  • implement a stripped down version without using path-to-regexp

Handy code snippet

function toQueryString(obj) {
    return (
        _.map(obj, (v, k) => {
            if (_.isArray(v)) {
                return (_.map(v, (av) => `${k}[]=${av}`)).join('&');
            } else {
                return `${encodeURIComponent(k)}=${encodeURIComponent(v)}`;
            }
        })
    ).join('&');
}

function toUrl(url = '', params = {}) {
    let q = toQueryString(params);
    let urlBuffer = [url];
    if (q) {
        urlBuffer.push(/\?.+$/.test(url) ? `&${q}` : `?${q}`);
    }
    return urlBuffer.join('');
}

how can I get from catalog view to product view

I want when I click on a thumbnail in the catalogue view to the product view to play the video of the thumbnail.

I get thumbnail and video from a json file.
and this is my catalog index.js file:

let Page = ATV.Page.create({
	name: 'catalog',
	url: 'http://localhost:9001/assets/data/video.json',
	template: template,
    events: {
        select: 'onSelect'
    },

	onSelect(e) {
		ATV.Navigation.navigate('product');
	}
});

And I don't know how I can play the video when I get to the product(video) view.

Menu doesnt work when created outside ATV.start

var amc = ATV.Page.create({name: 'amc', ...... });
var allVideos = ATV.Page.create({name: 'allVideos', ...... });
var menu = ATV.Menu.create({
    // any attributes that you want to set on the root level menuBar element of TVML
    attributes: {},
    // array of menu item configurations
    items: [{
        id: 'amc',
        name: 'AMC',
        page: amc
        }, {
        id: 'allVideos',
        name: 'All Videos',
        page: allVideos,
        attributes: {
            autoHighlight: true // auto highlight on navigate
        }
    }]
});

When I run ATV.Navigation.navigateToMenuPage();
I get [Warning] No menu configuration exists, cannot navigate to the menu page.

This seems to work when its inside ATV.start

reloadOnSelect not working

I have a page which generated depend on the storage via page ready method:
ready(options, resolve, reject) {
var history = ATV.Settings.get('history');
...
}

and I set the option reloadOnSelect for this page in menu:

menu: {
items: [{
id: 'home',
name: 'My TV',
page: HomePage,
attributes: { autoHighlight: true,
reloadOnSelect: true
}
},
}

While I update storage in other page and navigate back the home page, the page can not be updated. Looking to the debug console, the ready is not been called. So will reloadOnSelect invoke ready() to be called every time even the page already in the stack ? Anyway to update the content in the stack ? I have read you suggestion to use pubsub-js, any sample code for that ?

Thanks for help.
hong

Remove unwanted dependencies

Now that the AppleTV platform is stable enough, it would make sense to get rid of the redundant dependencies and rely on ES6 or related resolutions. Read #15 (comment) and #15 (comment).

  • remove babel-polyfill
  • evaluate and replace Promise alternatives
  • evaluate and remove lodash (use custom stripped down build if required)
  • evaluate and remove pubsub-js

Reload a Page with AJAX Content

I'm actually writing a private TVML/TVJS-App with atvjs.
First thanks for your brilliant framework-work!

I've got one problem:
I've got an interactive HomePage and also interactive subpages.
So at the start of the app the app gets the JSON from the server and render it to the template.
This page is cached then and can not be re-rendered; or?

For example:
I've got a page with a list of TV-Show episodes, on these episodes I've got a marker for the "Last seen"-episode. When I watch an episode the JS-File of the player then tells the server that the episode is watched. After exiting the player, the list should be dynamically re-rendered to display the newest server-information.

Is there a way to make boundings between ajax/template to re-render pages dynamically?

Thanks a lot!

Fetching data and display it

Hello,

I would like to fetch json and display it on template.

I use :

ATV.Page.create({
    name: 'home',
    url: 'http://www.example.com/data.json',
    template: template
});

data.json :

{
    "CATALOG": {
        "ITEM": [{
            "TITLE": "Title 1"
        }, {
            "TITLE": "Title 2"
        }, {
            "TITLE": "Title 3"
        }]
    }
}

in template.hbs, I use :

... <title>{{ CATALOG.ITEM[0].TITLE }}</title> ...

But I have error launching application.
How do I do to get the first title ?

Refreshing app

@emadalam this isn't an issue so much as a question - How would you go about refreshing the UI when you need new data to populate? For example, if you have a movie listing page, periodically the list of movies changes. I'd like to cause the UI to refresh periodically. Thanks in advance 😄

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.