-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1 from Fitbit/separate-view-logic-to-multiple-files
Split JS code into per-scenario files
- Loading branch information
Showing
11 changed files
with
262 additions
and
247 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,207 +1,30 @@ | ||
import clock from "clock"; | ||
import document from "document"; | ||
|
||
////////////////////////////////// | ||
// { Single view menu entry | ||
|
||
function singleViewStart() { | ||
console.log("single-view clicked"); | ||
document.location.assign('single.view'); | ||
} | ||
|
||
// } | ||
////////////////////////////////// | ||
|
||
|
||
////////////////////////////////// | ||
// { Backswipe override menu entry | ||
|
||
// Delta between the toggle click event is sent out, and the toggle value actually updates. | ||
const TOGGLE_VALUE_DELAY_MS = 300; | ||
// Leave some room to observe the view coming back when backswipe is canceled. Not mandatory. | ||
const VIEW_RESET_DELAY_MS = 200; | ||
|
||
var sessionBackswipeCallback = undefined; | ||
var sessionStart = undefined; | ||
var sessionResult = "00:00:000" | ||
var durationText = undefined; | ||
|
||
function resetSession() { | ||
// Reset internal session variables | ||
sessionStart = undefined; | ||
clock.ontick = undefined; | ||
} | ||
|
||
function sessionDurationUpdate() { | ||
if (durationText === undefined) { | ||
return; | ||
} | ||
|
||
const now = new Date(); | ||
const millis = now - sessionStart; | ||
const secs = Math.floor(millis / 1000); | ||
const mins = Math.floor(secs / 60); | ||
durationText.text = (mins < 10 ? "0" + mins : mins) + ":" + (secs < 10 ? "0" + secs : secs) + ":" + (millis % 1000); | ||
} | ||
|
||
function updateFinishView() { | ||
// When this view exits, we want to restore the document.onbeforeunload handler | ||
document.onunload = () => { | ||
document.onbeforeunload = sessionBackswipeCallback; | ||
} | ||
|
||
// Finishing the session will reload the view. Update just the last session duration. | ||
document.getElementById("btn-finish").addEventListener("click", () => { | ||
console.log("Finishing session"); | ||
|
||
// Final updates | ||
sessionDurationUpdate(); | ||
sessionResult = durationText.text; | ||
|
||
resetSession(); | ||
document.history.back(); // we know that this is the topmost view | ||
|
||
// NOTE: The side-effect is that the forward view stack history is cleared and the views | ||
// are unloaded. | ||
document.location.replace("session.view").then(updateSessionView); | ||
}); | ||
|
||
// Hitting cancel will go back to the previous view, which doesn't unload the current one. We also | ||
// don't want to replace the previous view (session), but we need to re-set the document backswipe | ||
// handler, since it's been cleared when loading this view. | ||
document.getElementById("btn-cancel").addEventListener("click", () => { | ||
document.history.back(); // we know that this is the topmost view | ||
document.onbeforeunload = sessionBackswipeCallback; | ||
}); | ||
} | ||
|
||
function updateSessionView() { | ||
const sessionToggle = document.getElementById("session-toggle"); | ||
// Display of the current session time. | ||
durationText = document.getElementById("duration"); | ||
durationText.text = sessionResult; | ||
|
||
// Session start / stop logic | ||
sessionToggle.addEventListener("click", () => { | ||
setTimeout(() => { | ||
if (sessionToggle.value == false) { | ||
resetSession(); | ||
document.onbeforeunload = undefined; | ||
return; | ||
} | ||
|
||
sessionStart = new Date(); | ||
durationText.text = "00:00:000"; | ||
|
||
clock.granularity = "seconds"; | ||
clock.ontick = sessionDurationUpdate; | ||
|
||
document.onbeforeunload = (evt) => { | ||
console.log("onbeforeunload called"); | ||
evt.preventDefault(); | ||
|
||
const background = document.getElementById("background"); | ||
const animateToggle = document.getElementById("animate-toggle"); | ||
|
||
if (animateToggle.value == true) { | ||
console.log("resetting view with animation"); | ||
background.animate("enable"); | ||
} else { | ||
console.log("resetting view directly"); | ||
background.x = 0; | ||
} | ||
|
||
// save the old session handling, we'll need it in case session is not finished | ||
sessionBackswipeCallback = document.onbeforeunload; | ||
|
||
// leave some time for the animation to happen, then load the new view | ||
setTimeout(() => { | ||
document.location.assign('session-finish.view').then(updateFinishView); | ||
}, VIEW_RESET_DELAY_MS); | ||
} | ||
}, TOGGLE_VALUE_DELAY_MS); | ||
}); | ||
}; | ||
|
||
function sessionViewStart() { | ||
console.log("backswipe-override start"); | ||
document.location.assign('session.view').then(updateSessionView); | ||
} | ||
|
||
// } | ||
////////////////////////////////// | ||
|
||
|
||
////////////////////////////////// | ||
// { Cycle view menu entry | ||
|
||
const NUM_CYCLE_VIEWS = 3; | ||
|
||
var cycleCurrent; | ||
var cycleViewsLoaded; | ||
|
||
function cyclePrev() { | ||
if (cycleCurrent === 0) { | ||
return; | ||
} | ||
|
||
cycleCurrent--; | ||
|
||
document.history.back(); | ||
} | ||
|
||
function cycleNext() { | ||
if (cycleCurrent === NUM_CYCLE_VIEWS - 1) { | ||
return; | ||
} | ||
|
||
cycleCurrent++; | ||
|
||
// Lazy initialze the view. Note that event handlers are invalidated after when calling | ||
// `document.location.assign()`, but will be set back in `updateCycleViews()` | ||
if (cycleViewsLoaded[cycleCurrent] === false) { | ||
document.location.assign(`cycle${cycleCurrent}.view`).then(updateCycleViews); | ||
cycleViewsLoaded[cycleCurrent] = true; | ||
} else { | ||
document.history.forward(); | ||
} | ||
} | ||
|
||
function updateCycleViews() { | ||
document.getElementById("btn-prev").addEventListener("click", () => { | ||
console.log("btn-prev clicked"); | ||
cyclePrev(); | ||
}); | ||
|
||
document.getElementById("btn-next").addEventListener("click", () => { | ||
console.log("btn-next clicked"); | ||
cycleNext(); | ||
/** | ||
* Handlers for the tile list buttons. Each button navigates to a different scenario | ||
* involving multiple views. | ||
*/ | ||
const buttonCallbacks = [ | ||
["single-view/start", () => import("./views/single")], | ||
["session-view/start", () => import("./views/session")], | ||
["cycle-views/start", () => import("./views/cycle")], | ||
]; | ||
|
||
/** | ||
* Assign button click handlers for all items in the menu. The view's | ||
* associated JavaScript is loaded and executed, and the new view is loaded on | ||
* top of the current one. | ||
*/ | ||
buttonCallbacks.forEach((view) => { | ||
const [buttonID, viewJSLoader] = view; | ||
|
||
document.getElementById(buttonID).addEventListener("click", () => { | ||
viewJSLoader().then(({ init, update }) => { | ||
init().then(update).catch((err) => { | ||
console.error(`Error loading view: ${err.message}`); | ||
}); | ||
}).catch((err) => { | ||
console.error(`Failed to load view JS: ${buttonID} - ${err.message}`); | ||
}); | ||
}); | ||
|
||
document.onbeforeunload = (evt) => { | ||
console.log("onbeforeunload called"); | ||
evt.preventDefault(); | ||
document.history.go(-cycleCurrent - 1); | ||
// Here is the alternative mentioned in `updateBackswipeOverridePrompt()` | ||
document.onbeforeunload = undefined; | ||
} | ||
} | ||
|
||
function cycleStart() { | ||
console.log("cycle-views start"); | ||
cycleCurrent = 0; | ||
cycleViewsLoaded = [true, false, false]; | ||
document.location.assign(`cycle${cycleCurrent}.view`).then(updateCycleViews); | ||
} | ||
|
||
// } | ||
////////////////////////////////// | ||
|
||
|
||
function updateMainMenu() { | ||
document.getElementById("single-view/start").addEventListener("click", singleViewStart); | ||
document.getElementById("backswipe-override/start").addEventListener("click", sessionViewStart); | ||
document.getElementById("cycle-views/start").addEventListener("click", cycleStart); | ||
} | ||
|
||
updateMainMenu(); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
import document from "document"; | ||
|
||
/** | ||
* Cycle views menu entry | ||
*/ | ||
|
||
const NUM_CYCLE_VIEWS = 3; | ||
|
||
let cycleCurrent; | ||
let cycleViewsLoaded; | ||
|
||
function cycleToView(pos) { | ||
/* Validate input */ | ||
if (pos != -1 && pos != 1) { | ||
return; | ||
} | ||
|
||
/* When at either edge of the cycle array, return immediately. */ | ||
if ((pos > 0 && cycleCurrent == NUM_CYCLE_VIEWS - 1) || | ||
(pos < 0 && cycleCurrent == 0)) { | ||
return; | ||
} | ||
|
||
cycleCurrent += pos; | ||
|
||
/* Go to previous view */ | ||
if (pos < 0) { | ||
document.history.back(); | ||
return; | ||
} | ||
|
||
/** | ||
* Lazy initialize the view. Note that event handlers are invalidated after when calling | ||
* `document.location.assign()`, but will be set back in `update()` | ||
*/ | ||
if (cycleViewsLoaded[cycleCurrent] == false) { | ||
document.location.assign(`cycle${cycleCurrent}.view`).then(update); | ||
cycleViewsLoaded[cycleCurrent] = true; | ||
} else { | ||
document.history.forward(); | ||
} | ||
|
||
} | ||
|
||
export function update() { | ||
document.getElementById("btn-prev").addEventListener("click", () => { | ||
console.log("btn-prev clicked"); | ||
cycleToView(-1); | ||
}); | ||
|
||
document.getElementById("btn-next").addEventListener("click", () => { | ||
console.log("btn-next clicked"); | ||
cycleToView(1); | ||
}); | ||
|
||
document.onbeforeunload = (evt) => { | ||
console.log("onbeforeunload called"); | ||
evt.preventDefault(); | ||
document.history.go(-cycleCurrent - 1); | ||
document.onbeforeunload = undefined; | ||
} | ||
} | ||
|
||
export function init() { | ||
console.log("cycle-views start"); | ||
cycleCurrent = 0; | ||
cycleViewsLoaded = [true, false, false]; | ||
return document.location.assign(`cycle${cycleCurrent}.view`); | ||
} |
Oops, something went wrong.