Skip to content
This repository has been archived by the owner on Nov 3, 2021. It is now read-only.

Commit

Permalink
Merge pull request #31621 from justindarc/bug1196425-v2
Browse files Browse the repository at this point in the history
Bug 1196425 - [Music][NGA] Implement 'open' and 'pick' activity handlers
  • Loading branch information
justindarc committed Aug 31, 2015
2 parents f81ba41 + 09101b0 commit 4a9a954
Show file tree
Hide file tree
Showing 22 changed files with 363 additions and 79 deletions.
2 changes: 2 additions & 0 deletions apps/music/test/marionette/fakeactivitycaller/index.html
Expand Up @@ -9,6 +9,8 @@

<body>
<span>I am fake activity caller</span>
<button id="open">Open</button>
<button id="pick">Pick</button>
</body>

</html>
Expand Up @@ -3,10 +3,18 @@

var FakeActivityCaller = {
init: function() {
this.callActicity();
this.openButton = document.getElementById('open');
this.pickButton = document.getElementById('pick');

this.openButton.addEventListener('click', this.openActivity);
this.pickButton.addEventListener('click', this.pickActivity);
},

openActivity: function() {
// NOOP
},

callActicity: function() {
pickActivity: function() {
var activity = new MozActivity({
name: 'pick',
data: {
Expand All @@ -20,4 +28,6 @@ var FakeActivityCaller = {
}
};

FakeActivityCaller.init();
window.addEventListener('DOMContentLoaded', function() {
FakeActivityCaller.init();
});
43 changes: 43 additions & 0 deletions apps/music/test/marionette/lib/fakeactivitycaller.js
Expand Up @@ -10,9 +10,31 @@ module.exports = FakeActivityCaller;

FakeActivityCaller.DEFAULT_ORIGIN = 'fakeactivity.gaiamobile.org';

FakeActivityCaller.Selector = Object.freeze({
openButton: '#open',
pickButton: '#pick',

actionMenu: 'form[data-z-index-level="action-menu"]'
});

FakeActivityCaller.prototype = {
client: null,

get openButton() {
return this.client.helper.waitForElement(
FakeActivityCaller.Selector.openButton);
},

get pickButton() {
return this.client.helper.waitForElement(
FakeActivityCaller.Selector.pickButton);
},

get actionMenu() {
return this.client.helper.waitForElement(
FakeActivityCaller.Selector.actionMenu);
},

launch: function() {
this.client.switchToFrame();
this.client.apps.launch(this.origin);
Expand All @@ -21,5 +43,26 @@ FakeActivityCaller.prototype = {

close: function() {
this.client.apps.close(this.origin);
},

tapOpenButton: function() {
this.openButton.tap();
},

tapPickButton: function() {
this.pickButton.tap();
},

selectMusicApp: function() {
this.client.switchToFrame();

var list = this.actionMenu.findElements('button');
for (var i = 0; i < list.length; i++) {
if (list[i].text() === 'Music') {
this.client.helper.waitForElement(list[i]);
list[i].tap();
return;
}
}
}
};
33 changes: 21 additions & 12 deletions apps/music/test/marionette/music_test.js
@@ -1,6 +1,8 @@
/* global require, marionette, setup, suite, test, __dirname */
'use strict';

var assert = require('assert');

var Music = require('./lib/music.js');
var FakeActivityCaller = require('./lib/fakeactivitycaller.js');

Expand All @@ -17,8 +19,7 @@ marionette('Music ui tests', function() {
},

apps: apps
},
desiredCapabilities: { raisesAccessibilityExceptions: true }
}
});

var music, system;
Expand Down Expand Up @@ -65,11 +66,15 @@ marionette('Music ui tests', function() {
});

test('Overlay should be shown when storage has no songs', function() {
activitycaller.launch();

music.switchToMe();
music.waitFinishedScanning();
music.waitForMessageOverlayShown(true);
try {
activitycaller.launch();
activitycaller.tapPickButton();
activitycaller.selectMusicApp();

music.switchToMe();
music.waitFinishedScanning();
music.waitForMessageOverlayShown(true);
} catch (e) { assert.ok(false, e.stack); }
});
});

Expand All @@ -85,11 +90,15 @@ marionette('Music ui tests', function() {
});

test('Overlay should be hidden when storage has some songs', function() {
activitycaller.launch();

music.switchToMe();
music.waitFinishedScanning();
music.waitForMessageOverlayShown(false);
try {
activitycaller.launch();
activitycaller.tapPickButton();
activitycaller.selectMusicApp();

music.switchToMe();
music.waitFinishedScanning();
music.waitForMessageOverlayShown(false);
} catch (e) { assert.ok(false, e.stack); }
});
});
});
6 changes: 6 additions & 0 deletions dev_apps/music-nga/css/activity.css
@@ -0,0 +1,6 @@
#view-stack {
bottom: 0;
}
#tab-bar {
display: none;
}
2 changes: 1 addition & 1 deletion dev_apps/music-nga/index.html
Expand Up @@ -18,7 +18,7 @@
<gaia-header id="header" no-font-fit>
<h1 id="header-title"></h1>
<button id="player-button" data-icon="play-circle" hidden></button>
<button id="done-button" hidden>Done</button>
<button id="activity-done-button" hidden></button>
</gaia-header>

<music-view-stack id="view-stack"></music-view-stack>
Expand Down
87 changes: 76 additions & 11 deletions dev_apps/music-nga/js/app.js
Expand Up @@ -26,6 +26,11 @@ var $id = document.getElementById.bind(document);

var views = {};
var isPlaying = false;
var activity = null;

if (navigator.mozSetMessageHandler) {
navigator.mozSetMessageHandler('activity', activity => onActivity(activity));
}

var service = bridge.service('*')
.on('message', message => message.forward($id('endpoint')))
Expand All @@ -36,37 +41,83 @@ var client = bridge.client({
endpoint: $id('endpoint'),
timeout: false
});

client.connect();

client.connected.then(() => {
client.on('play', () => isPlaying = true);
});

var header = $id('header');
var headerTitle = $id('header-title');
var playerButton = $id('player-button');
var doneButton = $id('done-button');
var viewStack = $id('view-stack');
var tabBar = $id('tab-bar');
var header = $id('header');
var headerTitle = $id('header-title');
var playerButton = $id('player-button');
var activityDoneButton = $id('activity-done-button');
var viewStack = $id('view-stack');
var tabBar = $id('tab-bar');

header.addEventListener('action', (evt) => {
if (evt.detail.type === 'back' && viewStack.states.length > 1) {
viewStack.popView();
window.history.back();
if (evt.detail.type === 'back') {
if (viewStack.states.length > 1) {
viewStack.popView();
window.history.back();
return;
}

switch (activity && activity.source.name) {
case 'open':
activity.postResult({ saved: false });
break;
case 'pick':
activity.postError('pick cancelled');
break;
}
}
});

playerButton.addEventListener('click', () => navigateToURL('/player'));

activityDoneButton.addEventListener('click', () => {
switch (activity && activity.source.name) {
case 'open':
// TODO: Implement 'Save' functionality
activity.postResult({ saved: false });
break;
case 'pick':
client.method('getPlaybackStatus').then((status) => {
var getSong = client.method('getSong', status.filePath);
var getSongFile = client.method('getSongFile', status.filePath);
var getSongThumbnail = client.method('getSongThumbnail', status.filePath);

Promise.all([getSong, getSongFile, getSongThumbnail])
.then(([song, file, thumbnail]) => {
activity.postResult({
type: file.type,
blob: file,
name: song.metadata.title || '',
// We only pass some metadata attributes so we don't share
// personal details like # of times played and ratings.
metadata: {
title: song.metadata.title,
artist: song.metadata.artist,
album: song.metadata.album,
picture: thumbnail
}
});
});
});
break;
}
});

viewStack.addEventListener('change', (evt) => {
var view = evt.detail.view;
var viewId = view && view.dataset.viewId;
var backButton = header.els.actionButton;

document.body.dataset.activeViewId = viewId;

backButton.style.visibility = viewStack.states.length < 2 ? 'hidden' : 'visible';
playerButton.hidden = viewId === 'player' || !isPlaying;
activityDoneButton.hidden = viewId !== 'player' || !activity;
setBackButtonHidden(!activity && viewStack.states.length < 2);
});

viewStack.addEventListener('pop', (evt) => {
Expand Down Expand Up @@ -112,6 +163,10 @@ function setHeaderTitle(title) {
window.requestAnimationFrame(() => headerTitle.textContent = title);
}

function setBackButtonHidden(hidden) {
header.els.actionButton.style.visibility = hidden ? 'hidden' : 'visible';
}

function getViewById(viewId) {
var view = views[viewId];
if (view) {
Expand Down Expand Up @@ -172,6 +227,16 @@ function parseQueryString(queryString) {
return query;
}

function onActivity(activity) {
window.activity = activity;

if (activity.source.name === 'open') {
client.method('open', activity.source.data.blob);
}

setBackButtonHidden(false);
}

function onSearchOpen() {
document.body.dataset.search = true;
}
Expand Down
14 changes: 14 additions & 0 deletions dev_apps/music-nga/js/db.js
Expand Up @@ -25,6 +25,16 @@ var Database = (function() {
// See init()
// var musicdb; // XXX

var resolveEnumerable;
var enumerable = new Promise((resolve) => {
resolveEnumerable = resolve;
});

var resolveReady;
var ready = new Promise((resolve) => {
resolveReady = resolve;
});

function init() {
// We want to exclude some folders that store ringtones so they don't show
// up in the music app. The regex matches absolute paths starting with a
Expand Down Expand Up @@ -128,6 +138,7 @@ var Database = (function() {
musicdb.onready = onReady;
}
// });
resolveEnumerable(); // XXX
console.log('XXX: App.dbEnumerable(...)');
}

Expand All @@ -137,6 +148,7 @@ var Database = (function() {
// musicdb.scan();
// });
musicdb.scan(); // XXX
resolveReady(); // XXX
console.log('XXX: App.dbReady(...)');

// Subsequent onready events need to refresh the UI.
Expand Down Expand Up @@ -306,6 +318,8 @@ var Database = (function() {
advancedEnumerate: advancedEnumerate,
count: count,
cancelEnumeration: cancelEnumeration,
enumerable, // XXX: ADDED
ready, // XXX: ADDED

// This is just here for testing.
get initialScanComplete() {
Expand Down

0 comments on commit 4a9a954

Please sign in to comment.