Skip to content

Commit

Permalink
Add eslint and lint everything
Browse files Browse the repository at this point in the history
  • Loading branch information
TranquilMarmot committed Jul 6, 2018
1 parent 93c25ef commit 846becd
Show file tree
Hide file tree
Showing 22 changed files with 2,006 additions and 124 deletions.
19 changes: 19 additions & 0 deletions .eslintrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"env": {
"node": true
},
"extends": "airbnb",
"rules": {
"import/no-unresolved": "off",
"import/prefer-default-export": "off",
"no-console": "off",
"comma-dangle": "off",
"react/react-in-jsx-scope": "off",
"react/jsx-no-undef": "off",
"jsx-a11y/anchor-is-valid": "off"
},
"globals": {
"fetch": true,
"registerSettingsPage": true
}
}
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
# since there's no REAL way to do environment variables or anything with the Fitbit SDK
# we have to export them from a JS file and ignore it
common/secrets.js
common/secrets.js

node_modules
21 changes: 17 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,26 @@ The sidebar will display the date, weather, and steps. When the watch is tapped,
![](readme-images/screenshot-1.png)
![](readme-images/screenshot-2.png)
![](readme-images/screenshot-3.png)
![](readme-images/screenshot-3.png)
![](readme-images/screenshot-4.png)

## Developing

Unfortunately, Fitbit does not offer any sort of CLI for building watchfaces or application (although is is listed on their [Fitbit OS Roadmap](https://dev.fitbit.com/build/roadmap/)). As such, if you want to develop this you have to open up [Fitbit Studio](https://studio.fitbit.com/) and recreate the project. To import it, open the project folder in your OS file browser, select all the files, and then drag them into Fitbit Studio in your browser.
Unfortunately, Fitbit does not offer any sort of CLI for building watchfaces or application (although is is listed on their [Fitbit OS Roadmap](https://dev.fitbit.com/build/roadmap/)). As such, if you want to develop this you have to open up [Fitbit Studio](https://studio.fitbit.com/) and re-create the project.

To import the project into Fitbit Studio, open the project folder in your OS file browser, select all the files (EXCEPT `node_modules` and `.git`), and then drag them into Fitbit Studio in your browser. To keep things in sync with git, drag all the files in again and overwrite the old ones.

For more info on Fitbit's libraries, check out https://dev.fitbit.com/

### Lint

To lint the entire project, run `npm install` followed by:
```sh
npm run lint
```

If there are no lint errors, nothing will be printed out.

For more info on how Fitbit's libraries work, check out https://dev.fitbit.com/
Lint rules are based off of [Airbnb's eslint rules](https://github.com/airbnb/javascript) with some modifications to meet the project's requirements.

### Project layout

Expand Down Expand Up @@ -42,7 +55,7 @@ In `resources/gui` there is a folder for each "widget" on the watchface; there i
### Secrets
There is also no support or best practices for secrets since there aren't any environment variables or anything. As such, there is a file `common/secrets.js` that has all the secrets needed by the application. This file is not checked into source control.

At the minimum, this file should contain:
At a minimum, this file should contain:

```js
export const getOpenWeatherMapApiKey = () => 'YOUR_OPENWEATHERMAP_KEY';
Expand Down
81 changes: 54 additions & 27 deletions app/battery.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,28 +6,11 @@ const batteryFill = document.getElementById('batteryFill');

const maxBatteryFillWidth = 40;

export const updateBattery = () => {
const chargeLevel = battery.chargeLevel;
batteryLabel.text = `${chargeLevel}%`;

const fixedPercent = chargeLevel / (100 / maxBatteryFillWidth)

batteryFill.width = fixedPercent;
batteryFill.style.fill = getHexFillColor(chargeLevel);
}

const getHexFillColor = (percent) => {
// in hsv, hue of 0 is red and 120 is green
// hue is out of 360, though, so we need to multiply by 360
// percent / 100 because it needs to be between 0 and 1
const hue = (percent / 100) * (120 / 360);
return rgbToHex(hsvToRgb(hue, 1, 1));
}


// Thanks Michael Jackson! https://gist.github.com/mjackson/5311256
function hsvToRgb(h, s, v) {
let r, g, b;
let r;
let g;
let b;

const i = Math.floor(h * 6);
const f = h * 6 - i;
Expand All @@ -36,19 +19,63 @@ function hsvToRgb(h, s, v) {
const t = v * (1 - (1 - f) * s);

switch (i % 6) {
case 0: r = v, g = t, b = p; break;
case 1: r = q, g = v, b = p; break;
case 2: r = p, g = v, b = t; break;
case 3: r = p, g = q, b = v; break;
case 4: r = t, g = p, b = v; break;
case 5: r = v, g = p, b = q; break;
case 0:
r = v;
g = t;
b = p;
break;
case 1:
r = q;
g = v;
b = p;
break;
case 2:
r = p;
g = v;
b = t;
break;
case 3:
r = p;
g = q;
b = v;
break;
case 4:
r = t;
g = p;
b = v;
break;
case 5:
r = v;
g = p;
b = q;
break;
default:
break;
}

return { r: r * 255, g: g * 255, b: b * 255 };
}

// fuckin' magic https://stackoverflow.com/a/19765382
function rgbToHex(color) {
var rgb = color.b | (color.g << 8) | (color.r << 16);
const rgb = color.b | (color.g << 8) | (color.r << 16); // eslint-disable-line no-bitwise
return `#${(0x1000000 + rgb).toString(16).slice(1)}`;
}

const getHexFillColor = (percent) => {
// in hsv, hue of 0 is red and 120 is green
// hue is out of 360, though, so we need to multiply by 360
// percent / 100 because it needs to be between 0 and 1
const hue = (percent / 100) * (120 / 360);
return rgbToHex(hsvToRgb(hue, 1, 1));
};

export const updateBattery = () => {
const { chargeLevel } = battery;
batteryLabel.text = `${chargeLevel}%`;

const fixedPercent = chargeLevel / (100 / maxBatteryFillWidth);

batteryFill.width = fixedPercent;
batteryFill.style.fill = getHexFillColor(chargeLevel);
};
8 changes: 4 additions & 4 deletions app/calendar.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,10 @@ const getDayOfWeekString = (date) => {
default:
return '???';
}
}
};

const getMonthString = (date) => {
switch(date.getMonth()) {
switch (date.getMonth()) {
case 0:
return 'Jan';
case 1:
Expand Down Expand Up @@ -56,10 +56,10 @@ const getMonthString = (date) => {
default:
return '???';
}
}
};

export const updateCalendar = (currentDate) => {
calendarDayOfWeekLabel.text = getDayOfWeekString(currentDate);
calendarMonthLabel.text = getMonthString(currentDate);
calendarDayOfMonthLabel.text = currentDate.getDate();
}
};
2 changes: 1 addition & 1 deletion app/floors.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@ const floorsLabel = document.getElementById('floorsLabel');

export const updateFloors = () => {
floorsLabel.text = today.local.elevationGain || 0;
}
};
6 changes: 3 additions & 3 deletions app/heartRate.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@ const heartRateSensor = new HeartRateSensor();

heartRateSensor.onreading = () => {
heartRateLabel.text = heartRateSensor.heartRate;

// stop the sensor until the next reading
heartRateSensor.stop();
}
};

export const readHeartRate = () => {
heartRateSensor.start();
}
};
8 changes: 4 additions & 4 deletions app/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,14 @@ clock.ontick = (evt) => {
updateFloors();
updateBattery();
readHeartRate();
}
};

main.onclick = () => {
// on "click" swap the sidebar display
vibration.start('bump');
currentSidebar.style.display = 'none';
currentSidebar = currentSidebar === sidebar1 ? sidebar2 : sidebar1;
currentSidebar = currentSidebar === sidebar1 ? sidebar2 : sidebar1;
currentSidebar.style.display = 'inline';
}
};

initMessaging();
initMessaging();
8 changes: 4 additions & 4 deletions app/messaging.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@ export const initMessaging = () => {
break;
}
}
}
};

messaging.peerSocket.onerror = (err) => {
console.error(`Peer Socket Connection error: ${err.code} - ${err.message}`);
}
}
};
};
17 changes: 10 additions & 7 deletions app/settings.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,17 @@ const onWeatherZipCodeSettingChanged = (newValue) => {
requestWeatherFromCompanion(weatherZipCode);

// fetch weather every hour
weatherIntervalId = setInterval(() => { requestWeatherFromCompanion(weatherZipCode) }, 30 * 1000 * 60);
weatherIntervalId = setInterval(
() => { requestWeatherFromCompanion(weatherZipCode); },
30 * 1000 * 60
);
}
}
};

// Called whenever a SETTING_CHANGED event gets sent
// Note that on watchface init, every setting that has a value will go through here which will set all the colors etc.
export const onSettingChanged = ({ key, newValue}) => {
// Note that on watchface init, every setting that has a value
// will go through here which will set all the colors etc.
export const onSettingChanged = ({ key, newValue }) => {
switch (key) {
case 'backgroundColor':
document.getElementById('mainBackground').style.fill = newValue.replace(/"/g, '');
Expand All @@ -40,8 +44,7 @@ export const onSettingChanged = ({ key, newValue}) => {
document.getElementById('sidebarBackground').style.fill = newValue.replace(/"/g, '');
break;
case 'sidebarWidgetColor':
const newSidebarWidgetColor = newValue.replace(/"/g, '');
document.getElementsByClassName('sidebar-widget-element').forEach(element => element.style.fill = newSidebarWidgetColor);
document.getElementsByClassName('sidebar-widget-element').forEach((element) => { element.style.fill = newValue.replace(/"/g, ''); }); // eslint-disable-line no-param-reassign
break;
case 'weatherZipCode':
onWeatherZipCodeSettingChanged(newValue);
Expand All @@ -50,4 +53,4 @@ export const onSettingChanged = ({ key, newValue}) => {
console.warn(`Unknown setting for ${key} with value ${newValue}`);
break;
}
}
};
21 changes: 11 additions & 10 deletions app/steps.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,18 @@ const stepsLabel = document.getElementById('stepsLabel');

const stepsToString = (steps) => {
if (steps < 1000) {
return `${steps}`;
} else {
// pad with 0s and add a K to signify thousands of steps
let thousandsOfSteps = `${steps / 1000}`.substring(0, 4);
while (thousandsOfSteps.length < 4) {
thousandsOfSteps += '0';
}
return `${thousandsOfSteps}K`;
return `${steps}`;
}
}

// pad with 0s and add a K to signify thousands of steps
let thousandsOfSteps = `${steps / 1000}`.substring(0, 4);
while (thousandsOfSteps.length < 4) {
thousandsOfSteps += '0';
}

return `${thousandsOfSteps}K`;
};

export const updateSteps = () => {
stepsLabel.text = stepsToString(today.local.steps || 0);
}
};
17 changes: 10 additions & 7 deletions app/time.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,25 @@ const hoursLabel = document.getElementById('hoursLabel');
const minutesLabel = document.getElementById('minutesLabel');

// Add a zero in front of a number if it's less than 10
const zeroPad = (i) => {
if (i < 10) {
i = '0' + i;
const zeroPad = (number) => {
let padded = number;

if (padded < 10) {
padded = `0${padded}`;
}
return i;
}

return padded;
};

export const updateTime = (currentDate) => {
const hours = currentDate.getHours();
if (preferences.clockDisplay === '12h') {
// 12h format
hoursLabel.text = zeroPad(hours % 12 || 12);
hoursLabel.text = zeroPad(hours % 12 || 12);
} else {
// 24h format
hoursLabel.text = zeroPad(hours);
}

minutesLabel.text = zeroPad(currentDate.getMinutes());
}
};
Loading

0 comments on commit 846becd

Please sign in to comment.