Import of the watch repository from Pebble

This commit is contained in:
Matthieu Jeanson 2024-12-12 16:43:03 -08:00 committed by Katharine Berry
commit 3b92768480
10334 changed files with 2564465 additions and 0 deletions

View file

@ -0,0 +1,116 @@
/**
* Copyright 2024 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
@import url(https://fonts.googleapis.com/css?family=Bowlby+One+SC|Roboto:400,700,400italic);
body {
font: 16px/1.5 'Roboto', sans-serif;
}
body {
padding-bottom: 2em;
}
body > .container:first-child > .row:first-child > div > p:first-child {
display: none;
}
h1 {
font-size: 3em;
}
h1 + blockquote {
border: 0 none;
max-width: 600px;
text-align: center;
margin: 0 auto 3em;
padding: 0;
}
h1, h2 {
font-family: "Bowlby One SC";
overflow: hidden;
text-align: center;
margin: 2em 0 1em;
text-transform: uppercase;
}
h1:before, h1:after, h2:before, h2:after {
background-color: #ddd;
content: "";
display: inline-block;
height: 1px;
position: relative;
vertical-align: middle;
width: 50%;
}
h1:before, h2:before {
right: 0.5em;
margin-left: -50%;
}
h1:after, h2:after {
left: 0.5em;
margin-right: -50%;
}
h3 {
margin: 1em 0 0.5em;
}
form {
width: 100%;
}
label {
width: 100%;
}
#githubForkLink {
background: url(../img/forkBanner.png) no-repeat top right;
position: absolute;
display: block;
width: 149px;
height: 149px;
top: 0;
right: 0;
/* Hide the text. */
text-indent: 100%;
white-space: nowrap;
overflow: hidden;
}
table.table-compatibility>tbody>tr.standard {
background-color: #d9edf7;
}
table.table-compatibility>tbody>tr.implemented {
background-color: #dff0db;
}
table.table-compatibility>tbody>tr.partial {
background-color: #ffffff;
}
table.table-compatibility>tbody>tr.planned {
background-color: #fcf8e3;
}
table.table-compatibility>tbody>tr.not-planned {
background-color: #f2dede
}

View file

@ -0,0 +1,94 @@
<!DOCTYPE html>
<!--
Copyright 2024 Google LLC
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- The above 3 meta tags *must* come first in the head; any other head content must come *after* these tags -->
<title>Simple Rocky Simulator</title>
<link rel="stylesheet" href="css/bootstrap.css"/>
<link rel="stylesheet" href="css/style.css"/>
<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
<!--[if lt IE 9]>
<script type="text/javascript" src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
<script type="text/javascript" src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
<![endif]-->
<script type="text/javascript" src="rocky.js"></script>
</head>
<body>
<div class="container">
<div class="page-header">
<h1>[Simple Rocky Simulator]</h1>
</div>
<div class="col-md-6">
<canvas id="pebble" class="rocky" width="432" height="504"></canvas>
</div>
<div class="col-md-6">
<h3>Controls</h3>
<p><form id="controls-form">
<label for="timestamp-input">Set Time (Epoch timestamp)</label>
<input id="timestamp-input" type="text" />
<label for="timezone-offset-input">Timezone Offset (<span id="timezone-offset-span"></span>)</label>
<input id="timezone-offset-input" type="range" min="-720" max="840" step="15" value="0" />
<label>24h Style</label>
<input id="24h-style-input" type="checkbox" />
</form></p>
</div>
</div>
<script type="text/javascript">
// Create a new simulator and bind it to the canvas:
var rockySimulator = new RockySimulator({
canvas: document.getElementById("pebble")
});
// in the future, we will replace the singleton
// `rocky` as well as the namespace `Rocky`, e.g.
// `Rocky.tween` and `Rocky.WatchfaceHelper` with modules
var rocky = _rocky;
function getQueryVariable(variable) {
var query = window.location.search.substring(1);
var vars = query.split('&');
for (var i = 0; i < vars.length; i++) {
var pair = vars[i].split('=');
if (decodeURIComponent(pair[0]) == variable) {
return decodeURIComponent(pair[1]);
}
}
}
// Load app source from 'src' query param (URL / data URI):
var src = getQueryVariable('src');
// If 'src' is set to empty string, don't load anything (for testing):
if (src !== '') {
src = src || 'js/tictoc.js';
var script = document.createElement('script');
script.src = src;
document.getElementsByTagName('html')[0].appendChild(script);
}
</script>
<script type="text/javascript" src="js/controls.js"></script>
</body>
</html>

View file

@ -0,0 +1,62 @@
/**
* Copyright 2024 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
window.addEventListener('load', function() {
var form = document.getElementById("controls-form");
form.addEventListener('submit', function(e) {
e.preventDefault();
});
var timestampInput = document.getElementById("timestamp-input");
timestampInput.addEventListener('change', function(e) {
rockySimulator.setTime(Number(e.target.value) * 1000);
});
var timezoneSlider = document.getElementById("timezone-offset-input");
var timezoneSpan = document.getElementById("timezone-offset-span");
var timezoneSliderOnChange = function() {
var offset = timezoneSlider.value;
rockySimulator.setTimezoneOffset(offset);
var sign;
if (offset > 0) {
sign = '+';
} else if (offset < 0) {
sign = '-';
} else {
sign = '';
}
var offsetMinutes = (offset % 60);
var absOffsetHours = Math.abs((offset - offsetMinutes) / 60);
var gmtText = 'GMT ' + sign + absOffsetHours;
if (offsetMinutes) {
var absOffsetMinutes = Math.abs(offsetMinutes);
gmtText += ':' + (absOffsetMinutes < 10 ? '0' : '') + absOffsetMinutes;
}
timezoneSpan.innerText = gmtText;
};
timezoneSlider.addEventListener('change', timezoneSliderOnChange);
timezoneSlider.addEventListener('input', timezoneSliderOnChange);
// After loading the page, set the slider to the local TZ:
var localTimezoneOffset = new Date().getTimezoneOffset();
timezoneSlider.value = localTimezoneOffset;
timezoneSliderOnChange();
var time24hStyle = document.getElementById("24h-style-input");
time24hStyle.addEventListener('change', function(e) {
rockySimulator.set24hStyle(e.target.checked);
});
});

View file

@ -0,0 +1,91 @@
/**
* Copyright 2024 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
var WatchfaceHelper = function(date) {
function clockwiseRad(fraction) {
// TODO: figure out if this is actually correct orientation for Canvas APIs
return (1.5 - fraction) * 2 * Math.PI;
}
date = date || new Date();
var secondFraction = date.getSeconds() / 60;
var minuteFraction = (date.getMinutes()) / 60;
var hourFraction = (date.getHours() % 12 + minuteFraction) / 12;
this.secondAngle = clockwiseRad(secondFraction);
this.minuteAngle = clockwiseRad(minuteFraction);
this.hourAngle = clockwiseRad(hourFraction);
};
// book keeping so that we can easily animate the two hands for the watchface
// .scale/.angle are updated by tween/event handler (see below)
var renderState = {
minute: {style: 'white', scale: 0.80, angle: 0},
hour: {style: 'red', scale: 0.51, angle: 0}
};
// helper function for the draw function (see below)
// extracted as a standalone function to satisfy common believe in efficient JS code
// TODO: verify that this has actually any effect on byte code level
var drawHand = function(handState, ctx, cx, cy, maxRadius) {
ctx.lineWidth = 8;
ctx.strokeStyle = handState.style;
ctx.beginPath();
ctx.moveTo(cx, cy);
ctx.lineTo(cx + Math.sin(handState.angle) * handState.scale * maxRadius,
cy + Math.cos(handState.angle) * handState.scale * maxRadius);
ctx.stroke();
};
// the 'draw' event is being emitted after each call to rocky.requestDraw() but
// at most once for each screen update, even if .requestDraw() is called frequently
// the 'draw' event might also fire at other meaningful times (e.g. upon launch)
rocky.on('draw', function(drawEvent) {
var ctx = drawEvent.context;
var w = ctx.canvas.unobstructedWidth;
var h = ctx.canvas.unobstructedHeight;
// clear canvas on each render
ctx.fillStyle = 'black';
ctx.fillRect(0, 0, ctx.canvas.clientWidth, ctx.canvas.clientHeight);
// center point
var cx = w / 2;
var cy = h / 2;
var maxRadius = Math.min(w, h - 2 * 10) / 2;
drawHand(renderState.minute, ctx, cx, cy, maxRadius);
drawHand(renderState.hour, ctx, cx, cy, maxRadius);
// Draw a 12 o clock indicator
drawHand({style: 'white', scale: 0, angle: 0}, ctx, cx, 8, 0);
// overdraw center so that no white part of the minute hand is visible
drawHand({style: 'red', scale: 0, angle: 0}, ctx, cx, cy, 0);
});
// listener is called on each full minute and once immediately after registration
rocky.on('minutechange', function(e) {
// WatchfaceHelper will later be extracted as npm module
var wfh = new WatchfaceHelper(e.date);
renderState.minute.angle = wfh.minuteAngle;
renderState.hour.angle = wfh.hourAngle;
rocky.requestDraw();
});
rocky.on('secondchange', function(e) {
console.log(e.date.toLocaleTimeString() + ' ' + e.date.toLocaleDateString() +
' ' + e.date.toLocaleString());
});
console.log('TicToc launched');