├── .gitignore ├── LICENSE ├── README.md ├── apps ├── news-headlines │ ├── app │ │ └── index.js │ ├── companion │ │ ├── headlines.js │ │ └── index.js │ ├── convert-sdk.sh │ ├── package-lock.json │ ├── package-sdk4.json │ ├── package-sdk5.json │ ├── package.json │ ├── resources │ │ ├── arrow-left.png │ │ ├── arrow-right.png │ │ ├── icon.png │ │ ├── index.view │ │ ├── index~336x336.view │ │ ├── styles.css │ │ ├── styles~300x300.css │ │ ├── styles~336x336.css │ │ ├── widget.defs │ │ └── widget~336x336.defs │ ├── screenshots │ │ ├── ionic-desc.png │ │ ├── ionic-title.png │ │ ├── versa2-desc.png │ │ ├── versa2-title.png │ │ ├── versa3-desc.png │ │ └── versa3-title.png │ └── settings │ │ └── index.jsx ├── tube-status │ ├── app │ │ ├── constants.js │ │ └── index.js │ ├── companion │ │ ├── index.js │ │ └── status.js │ ├── convert-sdk.sh │ ├── package-lock.json │ ├── package-sdk4.json │ ├── package-sdk5.json │ ├── package.json │ ├── resources │ │ ├── images │ │ │ ├── alert-red.png │ │ │ ├── alert-yellow.png │ │ │ └── icon.png │ │ ├── index.view │ │ ├── index~300x300.view │ │ ├── index~336x336.view │ │ ├── styles.css │ │ ├── styles~300x300.css │ │ ├── styles~336x336.css │ │ └── widget.defs │ └── screenshots │ │ ├── Screenshot 2020-08-31 at 17.58.56.png │ │ ├── Screenshot 2020-08-31 at 17.59.03.png │ │ ├── Screenshot 2020-08-31 at 17.59.11.png │ │ └── Screenshot 2020-08-31 at 17.59.19.png └── upcoming │ ├── app │ ├── dateTimeUtils.js │ └── index.js │ ├── common │ └── constants.js │ ├── companion │ └── index.js │ ├── convert-sdk.sh │ ├── package-lock.json │ ├── package-sdk4.json │ ├── package-sdk5.json │ ├── package.json │ ├── resources │ ├── bg-rounded.png │ ├── bg-rounded~300x300.png │ ├── bg-rounded~336x336.png │ ├── date.png │ ├── gesture-tap.png │ ├── icon.png │ ├── index.view │ ├── index~336x336.view │ ├── styles.css │ ├── styles~300x300.css │ ├── styles~336x336.css │ ├── time.png │ ├── widget.defs │ └── widget~336x336.defs │ ├── screenshots │ ├── Screenshot 2019-07-28 at 15.37.40.png │ ├── Screenshot 2019-07-28 at 15.37.51.png │ ├── Screenshot 2020-09-03 at 11.32.24.png │ ├── Screenshot 2020-09-03 at 11.33.28.png │ └── Screenshot 2020-09-03 at 11.35.27.png │ └── settings │ └── index.jsx ├── faces ├── beam-up │ ├── app │ │ ├── SecondsBar.js │ │ ├── data.js │ │ └── index.js │ ├── companion │ │ └── index.js │ ├── convert-sdk.sh │ ├── package-lock.json │ ├── package-sdk4.json │ ├── package-sdk5.json │ ├── package.json │ ├── resources │ │ ├── date │ │ │ ├── 0_s.png │ │ │ ├── 1_s.png │ │ │ ├── 2_s.png │ │ │ ├── 3_s.png │ │ │ ├── 4_s.png │ │ │ ├── 5_s.png │ │ │ ├── 6_s.png │ │ │ ├── 7_s.png │ │ │ ├── 8_s.png │ │ │ └── 9_s.png │ │ ├── day │ │ │ ├── fri.png │ │ │ ├── mon.png │ │ │ ├── sat.png │ │ │ ├── sun.png │ │ │ ├── thu.png │ │ │ ├── tue.png │ │ │ └── wed.png │ │ ├── index.view │ │ ├── index~300x300.view │ │ ├── index~336x336.view │ │ ├── styles.css │ │ ├── styles~300x300.css │ │ ├── styles~336x336.css │ │ ├── time │ │ │ ├── 0.png │ │ │ ├── 1.png │ │ │ ├── 2.png │ │ │ ├── 3.png │ │ │ ├── 4.png │ │ │ ├── 5.png │ │ │ ├── 6.png │ │ │ ├── 7.png │ │ │ ├── 8.png │ │ │ ├── 9.png │ │ │ └── colon.png │ │ └── widget.defs │ ├── screenshots │ │ ├── Screenshot 2019-07-28 at 15.32.30.png │ │ ├── Screenshot 2020-09-03 at 11.13.50.png │ │ ├── Screenshot 2020-09-03 at 11.14.22.png │ │ ├── Screenshot 2020-09-03 at 11.14.35.png │ │ └── Screenshot 2020-09-03 at 11.14.48.png │ └── settings │ │ └── index.jsx ├── cosmic-rays │ ├── app │ │ ├── Ray.js │ │ ├── constants.js │ │ └── index.js │ ├── companion │ │ └── index.js │ ├── convert-sdk.sh │ ├── package-lock.json │ ├── package-sdk4.json │ ├── package-sdk5.json │ ├── package.json │ ├── render-char.py │ ├── resources │ │ ├── font │ │ │ ├── 0.png │ │ │ ├── 1.png │ │ │ ├── 2.png │ │ │ ├── 3.png │ │ │ ├── 4.png │ │ │ ├── 5.png │ │ │ ├── 6.png │ │ │ ├── 7.png │ │ │ ├── 8.png │ │ │ ├── 9.png │ │ │ └── originals │ │ │ │ ├── 0.png │ │ │ │ ├── 1.png │ │ │ │ ├── 2.png │ │ │ │ ├── 3.png │ │ │ │ ├── 4.png │ │ │ │ ├── 5.png │ │ │ │ ├── 6.png │ │ │ │ ├── 7.png │ │ │ │ ├── 8.png │ │ │ │ └── 9.png │ │ ├── index.view │ │ ├── styles.css │ │ └── widget.defs │ ├── screenshots │ │ ├── 336-classic.png │ │ ├── 336-electric.png │ │ ├── 336-orange.png │ │ └── 336-rainbow.png │ └── settings │ │ └── index.jsx ├── dayring │ ├── app │ │ └── index.js │ ├── convert-sdk.sh │ ├── package-lock.json │ ├── package-sdk4.json │ ├── package-sdk5.json │ ├── package.json │ ├── resources │ │ ├── index.view │ │ ├── index~336x336.view │ │ ├── index~348x250.view │ │ ├── styles.css │ │ └── widget.defs │ └── screenshots │ │ ├── Screenshot 2019-07-28 at 17.07.42.png │ │ ├── Screenshot 2019-07-28 at 17.08.21.png │ │ ├── Screenshot 2019-07-28 at 17.08.42.png │ │ └── Screenshot 2020-08-31 at 11.59.22.png ├── deeprock │ ├── .gitignore │ ├── app │ │ ├── constants.js │ │ ├── index.js │ │ └── util.js │ ├── assets │ │ ├── OstrichSans-Heavy.otf │ │ ├── circuit.xcf │ │ └── text-pools.txt │ ├── convert-sdk.sh │ ├── package-lock.json │ ├── package-sdk4.json │ ├── package-sdk5.json │ ├── package.json │ ├── resources │ │ ├── fitfont.defs │ │ ├── fonts │ │ │ ├── Ostrich_Sans_21 │ │ │ │ ├── 65.png │ │ │ │ ├── 67.png │ │ │ │ ├── 68.png │ │ │ │ ├── 69.png │ │ │ │ ├── 71.png │ │ │ │ ├── 73.png │ │ │ │ ├── 76.png │ │ │ │ ├── 77.png │ │ │ │ ├── 78.png │ │ │ │ ├── 79.png │ │ │ │ ├── 82.png │ │ │ │ ├── 83.png │ │ │ │ ├── 84.png │ │ │ │ ├── 85.png │ │ │ │ └── ff │ │ │ ├── Ostrich_Sans_36 │ │ │ │ ├── 48.png │ │ │ │ ├── 49.png │ │ │ │ ├── 50.png │ │ │ │ ├── 51.png │ │ │ │ ├── 52.png │ │ │ │ ├── 53.png │ │ │ │ ├── 54.png │ │ │ │ ├── 55.png │ │ │ │ ├── 56.png │ │ │ │ ├── 57.png │ │ │ │ ├── 63.png │ │ │ │ └── ff │ │ │ ├── Ostrich_Sans_42 │ │ │ │ ├── 115.png │ │ │ │ ├── 33.png │ │ │ │ ├── 39.png │ │ │ │ ├── 46.png │ │ │ │ ├── 48.png │ │ │ │ ├── 49.png │ │ │ │ ├── 50.png │ │ │ │ ├── 51.png │ │ │ │ ├── 52.png │ │ │ │ ├── 53.png │ │ │ │ ├── 54.png │ │ │ │ ├── 55.png │ │ │ │ ├── 56.png │ │ │ │ ├── 57.png │ │ │ │ ├── 63.png │ │ │ │ ├── 65.png │ │ │ │ ├── 66.png │ │ │ │ ├── 67.png │ │ │ │ ├── 68.png │ │ │ │ ├── 69.png │ │ │ │ ├── 70.png │ │ │ │ ├── 71.png │ │ │ │ ├── 72.png │ │ │ │ ├── 73.png │ │ │ │ ├── 74.png │ │ │ │ ├── 75.png │ │ │ │ ├── 76.png │ │ │ │ ├── 77.png │ │ │ │ ├── 78.png │ │ │ │ ├── 79.png │ │ │ │ ├── 80.png │ │ │ │ ├── 82.png │ │ │ │ ├── 83.png │ │ │ │ ├── 84.png │ │ │ │ ├── 85.png │ │ │ │ ├── 86.png │ │ │ │ ├── 87.png │ │ │ │ ├── 89.png │ │ │ │ └── ff │ │ │ └── Ostrich_Sans_64 │ │ │ │ ├── 48.png │ │ │ │ ├── 49.png │ │ │ │ ├── 50.png │ │ │ │ ├── 51.png │ │ │ │ ├── 52.png │ │ │ │ ├── 53.png │ │ │ │ ├── 54.png │ │ │ │ ├── 55.png │ │ │ │ ├── 56.png │ │ │ │ ├── 57.png │ │ │ │ ├── 58.png │ │ │ │ ├── 72.png │ │ │ │ ├── 84.png │ │ │ │ ├── 88.png │ │ │ │ └── ff │ │ ├── images │ │ │ ├── Driller_icon.png │ │ │ ├── Driller_portrait.png │ │ │ ├── Engineer_icon.png │ │ │ ├── Engineer_portrait.png │ │ │ ├── Gunner_icon.png │ │ │ ├── Gunner_portrait.png │ │ │ ├── Scout_icon.png │ │ │ ├── Scout_portrait.png │ │ │ ├── bg.png │ │ │ ├── calories.png │ │ │ ├── drg_logo.png │ │ │ ├── health.png │ │ │ ├── label_end.png │ │ │ ├── pickaxe.png │ │ │ ├── shield.png │ │ │ └── steps.png │ │ ├── index~300x300.view │ │ ├── index~336x336.view │ │ ├── styles.css │ │ └── widget.defs │ └── screenshots │ │ ├── 300x300 │ │ ├── Screenshot 2022-06-02 at 15.44.47.png │ │ ├── Screenshot 2022-06-02 at 15.44.53.png │ │ ├── Screenshot 2022-06-02 at 15.44.58.png │ │ ├── Screenshot 2022-06-02 at 15.46.09.png │ │ └── Screenshot 2022-06-02 at 15.46.17.png │ │ └── 336x336 │ │ ├── Screenshot 2022-05-29 at 11.13.40.png │ │ ├── Screenshot 2022-05-29 at 11.13.50.png │ │ ├── Screenshot 2022-05-29 at 11.13.59.png │ │ ├── Screenshot 2022-05-29 at 11.14.09.png │ │ └── Screenshot 2022-05-29 at 11.14.38.png ├── elemental │ ├── app │ │ └── index.js │ ├── convert-sdk.sh │ ├── package-lock.json │ ├── package-sdk4.json │ ├── package-sdk5.json │ ├── package.json │ ├── resources │ │ ├── index.view │ │ ├── styles.css │ │ └── widget.defs │ └── screenshots │ │ └── Screenshot 2019-07-28 at 15.30.17.png ├── hollywatch │ ├── app │ │ └── index.js │ ├── convert-sdk.sh │ ├── package-lock.json │ ├── package-sdk4.json │ ├── package-sdk5.json │ ├── package.json │ ├── resources │ │ ├── holly.jpg │ │ ├── index.view │ │ ├── index~336x336.view │ │ ├── index~348x250.view │ │ ├── styles.css │ │ └── widget.defs │ └── screenshots │ │ ├── Screenshot 2019-03-17 at 17.06.42.png │ │ ├── Screenshot 2019-03-17 at 17.24.15.png │ │ ├── Screenshot 2019-03-17 at 17.24.29.png │ │ ├── Screenshot 2019-03-17 at 17.24.48.png │ │ ├── Screenshot 2019-03-17 at 17.25.06.png │ │ ├── Screenshot 2019-03-17 at 17.25.15.png │ │ ├── Screenshot 2019-03-17 at 17.25.38.png │ │ ├── Screenshot 2020-08-31 at 12.45.08.png │ │ └── Screenshot 2020-08-31 at 12.45.21.png ├── isotime │ ├── app │ │ └── index.js │ ├── companion │ │ └── index.js │ ├── convert-sdk.sh │ ├── package-lock.json │ ├── package-sdk4.json │ ├── package-sdk5.json │ ├── package.json │ ├── resources │ │ ├── 0.png │ │ ├── 1.png │ │ ├── 2.png │ │ ├── 3.png │ │ ├── 4.png │ │ ├── 5.png │ │ ├── 6.png │ │ ├── 7.png │ │ ├── 8.png │ │ ├── 9.png │ │ ├── index.view │ │ ├── index~300x300.view │ │ ├── index~336x336.view │ │ ├── styles.css │ │ └── widget.defs │ ├── screenshots │ │ ├── Screenshot 2019-07-28 at 15.34.15.png │ │ ├── Screenshot 2019-07-28 at 15.34.27.png │ │ ├── Screenshot 2020-08-31 at 14.08.11.png │ │ ├── Screenshot 2020-08-31 at 14.08.26.png │ │ ├── Screenshot 2020-08-31 at 14.08.34.png │ │ └── Screenshot 2020-08-31 at 14.08.49.png │ └── settings │ │ └── index.jsx └── pseudotime │ ├── app │ └── index.js │ ├── convert-sdk.sh │ ├── package-lock.json │ ├── package-sdk4.json │ ├── package-sdk5.json │ ├── package.json │ ├── resources │ ├── index.view │ ├── index~336x336.view │ ├── index~348x250.view │ ├── styles.css │ └── widget.defs │ └── screenshots │ ├── Screenshot 2020-08-31 at 12.37.29.png │ ├── Screenshot 2020-08-31 at 14.11.26.png │ ├── ionic.png │ └── versa.png ├── misc ├── aod-test │ ├── app │ │ └── index.js │ ├── common │ │ └── aod.js │ ├── package-lock.json │ ├── package.json │ └── resources │ │ ├── index.gui │ │ ├── styles.css │ │ └── widgets.gui └── calendar-test │ ├── app │ └── index.js │ ├── companion │ └── index.js │ ├── package.json │ └── resources │ ├── index.gui │ ├── styles.css │ └── widgets.gui └── utils ├── LICENSE ├── README.md ├── package-lock.json ├── package.json └── src ├── app ├── aod.js ├── comm.js ├── db.js ├── format.js ├── index.js ├── maths.js └── ui.js └── companion ├── comm.js ├── index.js └── web.js /.gitignore: -------------------------------------------------------------------------------- 1 | *.DS_Store 2 | build 3 | node_modules 4 | secrets.js 5 | utils/app 6 | utils/companion 7 | *.fba -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # fitbit-dev 2 | 3 | My FitBit app and watchface source code. 4 | -------------------------------------------------------------------------------- /apps/news-headlines/companion/headlines.js: -------------------------------------------------------------------------------- 1 | /** Max stories */ 2 | const MAX_STORIES = 10; 3 | 4 | /** 5 | * Decode some XML encodings. 6 | * 7 | * @param {string} str - String to decode. 8 | * @returns {string} str with encodings removed. 9 | */ 10 | const decode = str => str.split(/&/g).join('&') 11 | .split('').join(''); 13 | 14 | /** 15 | * Extract some string from a larger string. 16 | * 17 | * @param {string} text - Text to extract from. 18 | * @param {Array} beforeArr - Array of strings that lead to the chunk to extract. 19 | * @param {string} after - Marker of the end of the string to extract. 20 | * @returns {string} Extracted string. 21 | */ 22 | const extract = (text, beforeArr, after) => { 23 | let index = 0; 24 | 25 | for (let i = 0; i < beforeArr.length; i++) { 26 | index = text.indexOf(beforeArr[i]); 27 | if(index === -1) return; 28 | 29 | text = text.substring(index); 30 | } 31 | 32 | text = text.substring(beforeArr[beforeArr.length - 1].length); 33 | return text.substring(0, text.indexOf(after)); 34 | }; 35 | 36 | /** 37 | * Get JSON of stories from the XML string. 38 | * 39 | * @param {string} xml - XML downloaded. 40 | * @returns {Array} Array of stories with { title, description, dateTime }. 41 | */ 42 | const buildStories = (xml) => { 43 | const items = []; 44 | xml = xml.split(''); 45 | xml.shift(); 46 | xml.map((xmlChunk) => { 47 | items.push({ 48 | title: decode(extract(xmlChunk, [''], '')), 49 | description: decode(extract(xmlChunk, [''], '')), 50 | dateTime: decode(extract(xmlChunk, [''], '')) 51 | }); 52 | }); 53 | 54 | console.log(`Extracted ${items.length} items.`); 55 | return items; 56 | }; 57 | 58 | /** 59 | * Download and extract news stories. 60 | * 61 | * @param {string} category - News category. 62 | * @returns {Promise>} List of stories. 63 | */ 64 | export const downloadNews = (category) => { 65 | const url = category === 'headlines' 66 | ? 'https://feeds.bbci.co.uk/news/rss.xml' 67 | : `https://feeds.bbci.co.uk/news/${category}/rss.xml`; 68 | console.log(url); 69 | 70 | return fetch(url) 71 | .then(res => res.text()) 72 | .then(text => buildStories(text).slice(0, MAX_STORIES)); 73 | }; 74 | -------------------------------------------------------------------------------- /apps/news-headlines/companion/index.js: -------------------------------------------------------------------------------- 1 | import { settingsStorage } from 'settings'; 2 | import { me } from 'companion'; 3 | import { Comm } from '@chris-lewis/fitbit-utils/companion' 4 | import { downloadNews } from './headlines'; 5 | 6 | const STORAGE_KEY_CATEGORY = 'category'; 7 | 8 | /** 9 | * Download the news headlines, then send them 10 | */ 11 | const download = () => { 12 | console.log('Downloading...'); 13 | 14 | const value = settingsStorage.getItem(STORAGE_KEY_CATEGORY); 15 | const category = value ? JSON.parse(value).values[0].value : 'headlines'; 16 | downloadNews(category) 17 | .then((stories) => { 18 | console.log(`Total size: ${JSON.stringify(stories).length} B`); 19 | Comm.sendFile({ stories }); 20 | }); 21 | }; 22 | 23 | 24 | /** 25 | * The main function. 26 | */ 27 | const main = () => { 28 | console.log('News Headlines companion start'); 29 | 30 | Comm.setup({ open: download }); 31 | 32 | // Settings were changed while the companion was not running 33 | if (me.launchReasons.settingChanged) { 34 | console.log('settingChanged'); 35 | } 36 | 37 | // Settings changed while companion is running 38 | settingsStorage.onchange = (event) => { 39 | console.log(`onchange:\n${JSON.stringify(event)}`); 40 | 41 | download(); 42 | }; 43 | }; 44 | 45 | main(); 46 | -------------------------------------------------------------------------------- /apps/news-headlines/convert-sdk.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Script to convert a FitBit project between SDK 4 and SDK 5. 4 | # Usage: ./convert-sdk.sh 5 5 | 6 | function convert_sdk_5 { 7 | # Rename resources/widgets.gui >> resources/widget.defs 8 | mv resources/widgets.gui resources/widget.defs 9 | # Substitute in resources/widget.defs 'widgets_common.gui' for 'system_widget.defs' 10 | sed -i '' 's/widgets_common\.gui/system_widget\.defs/g' resources/widget.defs 11 | # Substitute other gui for defs 12 | sed -i '' 's/\.gui/\.defs/g' resources/widget.defs 13 | # Rename resources/*.gui >> resources/*.view 14 | cd resources 15 | for f in *.gui; do mv -- "$f" "${f%.gui}.view"; done 16 | cd - 17 | # Copy package-sdk5.json to package.json 18 | cp package-sdk5.json package.json 19 | # Install dependencies 20 | npm i 21 | } 22 | 23 | function convert_sdk_4 { 24 | # Rename resources/widget.defs >> resources/widgets.gui 25 | mv resources/widget.defs resources/widgets.gui 26 | # Substitute in resources/widgets.gui 'system_widget.defs' for 'widgets_common.gui' 27 | sed -i '' 's/system_widget\.defs/widgets_common\.gui/g' resources/widgets.gui 28 | # Substitute other gui for defs 29 | sed -i '' 's/\.defs/\.gui/g' resources/widgets.gui 30 | # Rename resources/*.view >> resources/*.gui 31 | cd resources 32 | for f in *.view; do mv -- "$f" "${f%.view}.gui"; done 33 | cd - 34 | # Copy package-sdk4.json to package.json 35 | cp package-sdk4.json package.json 36 | # Install dependencies 37 | npm i 38 | } 39 | 40 | VERSION=$1 41 | if [[ "$VERSION" == "4" ]]; then 42 | convert_sdk_4 43 | elif [[ "$VERSION" == "5" ]]; then 44 | convert_sdk_5 45 | else 46 | echo "Invalid version parameter" 47 | fi 48 | -------------------------------------------------------------------------------- /apps/news-headlines/package-sdk4.json: -------------------------------------------------------------------------------- 1 | { 2 | "fitbit": { 3 | "appUUID": "51b7a243-61de-4b5b-8b35-09c5f3f30ad4", 4 | "appType": "app", 5 | "appDisplayName": "Headlines", 6 | "iconFile": "resources/icon.png", 7 | "wipeColor": "#f44336", 8 | "requestedPermissions": [ 9 | "access_internet" 10 | ], 11 | "buildTargets": [ 12 | "higgs", 13 | "meson", 14 | "gemini", 15 | "mira" 16 | ], 17 | "i18n": { 18 | "en": { 19 | "name": "Headlines" 20 | } 21 | } 22 | }, 23 | "devDependencies": { 24 | "@chris-lewis/fitbit-utils": "^1.1.4", 25 | "@fitbit/sdk": "^4.3.2", 26 | "@fitbit/sdk-cli": "^1.7.1" 27 | }, 28 | "scripts": { 29 | "build": "fitbit-build" 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /apps/news-headlines/package-sdk5.json: -------------------------------------------------------------------------------- 1 | { 2 | "fitbit": { 3 | "appUUID": "51b7a243-61de-4b5b-8b35-09c5f3f30ad4", 4 | "appType": "app", 5 | "appDisplayName": "Headlines", 6 | "iconFile": "resources/icon.png", 7 | "wipeColor": "#f44336", 8 | "requestedPermissions": [ 9 | "access_internet" 10 | ], 11 | "buildTargets": [ 12 | "atlas", 13 | "vulcan" 14 | ], 15 | "i18n": { 16 | "en": { 17 | "name": "Headlines" 18 | } 19 | } 20 | }, 21 | "devDependencies": { 22 | "@chris-lewis/fitbit-utils": "^1.1.4", 23 | "@fitbit/sdk": "^6.0.2", 24 | "@fitbit/sdk-cli": "^1.7.3" 25 | }, 26 | "scripts": { 27 | "build": "fitbit-build" 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /apps/news-headlines/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "fitbit": { 3 | "appUUID": "51b7a243-61de-4b5b-8b35-09c5f3f30ad4", 4 | "appType": "app", 5 | "appDisplayName": "Headlines", 6 | "iconFile": "resources/icon.png", 7 | "wipeColor": "#f44336", 8 | "requestedPermissions": [ 9 | "access_internet" 10 | ], 11 | "buildTargets": [ 12 | "atlas", 13 | "vulcan" 14 | ], 15 | "i18n": { 16 | "en": { 17 | "name": "Headlines" 18 | } 19 | } 20 | }, 21 | "devDependencies": { 22 | "@chris-lewis/fitbit-utils": "^1.1.4", 23 | "@fitbit/sdk": "^6.0.2", 24 | "@fitbit/sdk-cli": "^1.7.3" 25 | }, 26 | "scripts": { 27 | "build": "fitbit-build" 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /apps/news-headlines/resources/arrow-left.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/C-D-Lewis/fitbit-dev/dabba32806ffab5f34b76095e4156468d598c383/apps/news-headlines/resources/arrow-left.png -------------------------------------------------------------------------------- /apps/news-headlines/resources/arrow-right.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/C-D-Lewis/fitbit-dev/dabba32806ffab5f34b76095e4156468d598c383/apps/news-headlines/resources/arrow-right.png -------------------------------------------------------------------------------- /apps/news-headlines/resources/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/C-D-Lewis/fitbit-dev/dabba32806ffab5f34b76095e4156468d598c383/apps/news-headlines/resources/icon.png -------------------------------------------------------------------------------- /apps/news-headlines/resources/index.view: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 9 | 10 | 11 | 12 | 13 | 14 | date 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | Loading 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /apps/news-headlines/resources/index~336x336.view: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 9 | 10 | 11 | 12 | 13 | 14 | date 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | Loading 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /apps/news-headlines/resources/styles.css: -------------------------------------------------------------------------------- 1 | .app-background { 2 | x: 0; 3 | y: 0; 4 | width: 100%; 5 | height: 100%; 6 | fill: #000000; 7 | } 8 | 9 | .loading-icon { 10 | x: 135; 11 | y: 50; 12 | width: 80; 13 | height: 80; 14 | } 15 | 16 | .loading-text { 17 | x: 50%; 18 | y: 65%; 19 | width: 100%; 20 | height: 30%; 21 | fill: #999999; 22 | text-anchor: middle; 23 | text-length: 64; 24 | font-family: Colfax-Medium; 25 | font-size: 24; 26 | font-weight: bold; 27 | } 28 | 29 | .card-banner { 30 | y: 10; 31 | height: 35; 32 | width: 100%; 33 | } 34 | 35 | .card-title { 36 | x: 20; 37 | y: 50; 38 | width: 88%; 39 | height: 90%; 40 | fill: #FFFFFF; 41 | text-anchor: start; 42 | text-length: 256; 43 | font-family: Colfax-Medium; 44 | font-size: 26; 45 | rows: 5; 46 | text-overflow: ellipsis; 47 | } 48 | 49 | .card-description { 50 | x: 25; 51 | y: 50; 52 | width: 85%; 53 | height: 75%; 54 | fill: #FFFFFF; 55 | text-anchor: start; 56 | text-length: 256; 57 | font-family: Colfax-Medium; 58 | font-size: 24; 59 | rows: 5; 60 | text-overflow: ellipsis; 61 | } 62 | 63 | .card-index { 64 | x: 50%; 65 | y: 35; 66 | width: 100%; 67 | height: 20%; 68 | fill: #FFFFFF; 69 | text-anchor: middle; 70 | text-length: 8; 71 | font-family: Colfax-Medium; 72 | font-size: 20; 73 | } 74 | 75 | .card-date { 76 | x: 50%; 77 | y: 240; 78 | width: 100%; 79 | height: 20%; 80 | fill: #BBBBBB; 81 | text-anchor: start; 82 | text-length: 32; 83 | font-family: Colfax-Medium; 84 | font-size: 22; 85 | text-overflow: ellipsis; 86 | text-anchor: middle; 87 | } 88 | 89 | .card-div-line { 90 | x: 10%; 91 | y: 215; 92 | width: 80%; 93 | height: 3; 94 | fill: #444444; 95 | } 96 | 97 | .card-arrow-right { 98 | x: 85%; 99 | y: 4%; 100 | width: 36; 101 | height: 36; 102 | } 103 | 104 | .card-arrow-left { 105 | x: 5%; 106 | y: 4%; 107 | width: 36; 108 | height: 36; 109 | } 110 | -------------------------------------------------------------------------------- /apps/news-headlines/resources/styles~300x300.css: -------------------------------------------------------------------------------- 1 | .app-background { 2 | x: 0; 3 | y: 0; 4 | width: 100%; 5 | height: 100%; 6 | fill: #000000; 7 | } 8 | 9 | .loading-icon { 10 | x: 110; 11 | y: 90; 12 | width: 80; 13 | height: 80; 14 | } 15 | 16 | .loading-text { 17 | x: 50%; 18 | y: 67%; 19 | width: 100%; 20 | height: 30%; 21 | fill: #999999; 22 | text-anchor: middle; 23 | text-length: 64; 24 | font-family: Colfax-Medium; 25 | font-size: 24; 26 | font-weight: bold; 27 | } 28 | 29 | .card-banner { 30 | y: 10; 31 | height: 35; 32 | width: 100%; 33 | } 34 | 35 | .card-title { 36 | x: 20; 37 | y: 50; 38 | width: 88%; 39 | height: 90%; 40 | fill: #FFFFFF; 41 | text-anchor: start; 42 | text-length: 256; 43 | font-family: Colfax-Medium; 44 | font-size: 28; 45 | rows: 6; 46 | text-overflow: ellipsis; 47 | } 48 | 49 | .card-description { 50 | x: 25; 51 | y: 50; 52 | width: 85%; 53 | height: 75%; 54 | fill: #FFFFFF; 55 | text-anchor: start; 56 | text-length: 256; 57 | font-family: Colfax-Medium; 58 | font-size: 24; 59 | rows: 7; 60 | text-overflow: ellipsis; 61 | } 62 | 63 | .card-index { 64 | x: 50%; 65 | y: 35; 66 | width: 100%; 67 | height: 20%; 68 | fill: #FFFFFF; 69 | text-anchor: middle; 70 | text-length: 8; 71 | font-family: Colfax-Medium; 72 | font-size: 20; 73 | } 74 | 75 | .card-date { 76 | x: 50%; 77 | y: 290; 78 | width: 100%; 79 | height: 20%; 80 | fill: #BBBBBB; 81 | text-anchor: start; 82 | text-length: 32; 83 | font-family: Colfax-Medium; 84 | font-size: 22; 85 | text-overflow: ellipsis; 86 | text-anchor: middle; 87 | } 88 | 89 | .card-div-line { 90 | x: 5%; 91 | y: 265; 92 | width: 90%; 93 | height: 3; 94 | fill: #444444; 95 | } 96 | 97 | .card-arrow-right { 98 | x: 85%; 99 | y: 9; 100 | width: 36; 101 | height: 36; 102 | } 103 | 104 | .card-arrow-left { 105 | x: 5%; 106 | y: 9; 107 | width: 36; 108 | height: 36; 109 | } 110 | -------------------------------------------------------------------------------- /apps/news-headlines/resources/styles~336x336.css: -------------------------------------------------------------------------------- 1 | .app-background { 2 | x: 0; 3 | y: 0; 4 | width: 100%; 5 | height: 100%; 6 | fill: #000000; 7 | } 8 | 9 | .loading-icon { 10 | x: 128; 11 | y: 112; 12 | width: 80; 13 | height: 80; 14 | } 15 | 16 | .loading-text { 17 | x: 50%; 18 | y: 65%; 19 | width: 100%; 20 | height: 30%; 21 | fill: #999999; 22 | text-anchor: middle; 23 | text-length: 64; 24 | font-family: Colfax-Medium; 25 | font-size: 24; 26 | font-weight: bold; 27 | } 28 | 29 | .card-banner { 30 | y: 10; 31 | height: 35; 32 | width: 100%; 33 | } 34 | 35 | .card-title { 36 | x: 20; 37 | y: 50; 38 | width: 88%; 39 | height: 90%; 40 | fill: #FFFFFF; 41 | text-anchor: start; 42 | text-length: 256; 43 | font-family: Colfax-Medium; 44 | font-size: 32; 45 | rows: 6; 46 | text-overflow: ellipsis; 47 | } 48 | 49 | .card-description { 50 | x: 25; 51 | y: 50; 52 | width: 85%; 53 | height: 80%; 54 | fill: #FFFFFF; 55 | text-anchor: start; 56 | text-length: 256; 57 | font-family: Colfax-Medium; 58 | font-size: 26; 59 | rows: 7; 60 | text-overflow: ellipsis; 61 | } 62 | 63 | .card-index { 64 | x: 50%; 65 | y: 35; 66 | width: 100%; 67 | height: 20%; 68 | fill: #FFFFFF; 69 | text-anchor: middle; 70 | text-length: 8; 71 | font-family: Colfax-Medium; 72 | font-size: 20; 73 | } 74 | 75 | .card-date { 76 | x: 50%; 77 | y: 313; 78 | width: 100%; 79 | height: 20%; 80 | fill: #BBBBBB; 81 | text-anchor: start; 82 | text-length: 32; 83 | font-family: Colfax-Medium; 84 | font-size: 22; 85 | text-overflow: ellipsis; 86 | text-anchor: middle; 87 | } 88 | 89 | .card-div-line { 90 | x: 10%; 91 | y: 285; 92 | width: 80%; 93 | height: 3; 94 | fill: #444444; 95 | } 96 | 97 | .card-arrow-right { 98 | x: 75%; 99 | y: 10; 100 | width: 36; 101 | height: 36; 102 | } 103 | 104 | .card-arrow-left { 105 | x: 15%; 106 | y: 10; 107 | width: 36; 108 | height: 36; 109 | } 110 | -------------------------------------------------------------------------------- /apps/news-headlines/resources/widget.defs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /apps/news-headlines/resources/widget~336x336.defs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /apps/news-headlines/screenshots/ionic-desc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/C-D-Lewis/fitbit-dev/dabba32806ffab5f34b76095e4156468d598c383/apps/news-headlines/screenshots/ionic-desc.png -------------------------------------------------------------------------------- /apps/news-headlines/screenshots/ionic-title.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/C-D-Lewis/fitbit-dev/dabba32806ffab5f34b76095e4156468d598c383/apps/news-headlines/screenshots/ionic-title.png -------------------------------------------------------------------------------- /apps/news-headlines/screenshots/versa2-desc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/C-D-Lewis/fitbit-dev/dabba32806ffab5f34b76095e4156468d598c383/apps/news-headlines/screenshots/versa2-desc.png -------------------------------------------------------------------------------- /apps/news-headlines/screenshots/versa2-title.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/C-D-Lewis/fitbit-dev/dabba32806ffab5f34b76095e4156468d598c383/apps/news-headlines/screenshots/versa2-title.png -------------------------------------------------------------------------------- /apps/news-headlines/screenshots/versa3-desc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/C-D-Lewis/fitbit-dev/dabba32806ffab5f34b76095e4156468d598c383/apps/news-headlines/screenshots/versa3-desc.png -------------------------------------------------------------------------------- /apps/news-headlines/screenshots/versa3-title.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/C-D-Lewis/fitbit-dev/dabba32806ffab5f34b76095e4156468d598c383/apps/news-headlines/screenshots/versa3-title.png -------------------------------------------------------------------------------- /apps/news-headlines/settings/index.jsx: -------------------------------------------------------------------------------- 1 | const categories = [ 2 | { name: 'Headlines', value: 'headlines' }, 3 | { name: 'World', value: 'world' }, 4 | { name: 'UK', value: 'uk' }, 5 | { name: 'Politics', value: 'politics' }, 6 | { name: 'Health', value: 'health' }, 7 | { name: 'Education', value: 'education' }, 8 | { name: 'Science and Environment', value: 'science_and_environment' }, 9 | { name: 'Technology', value: 'technology' }, 10 | { name: 'Entertainment and Arts', value: 'entertainment_and_arts' }, 11 | ]; 12 | 13 | const SettingsPage = () => ( 14 | 15 |
17 | 0 ? sourceOptions : NOT_FOUND_OPTIONS} 25 | onChange={value => settingsStorage.setItem('sourceSelection', value)} 26 | onSelection={(selected, values) => { 27 | sourceSelection = selected; 28 | }} 29 | /> 30 |
31 | {sourceSelection && ( 32 |
33 | Note: Calendars you do not own may not return any events. 34 | 24 |
25 |
26 | ); 27 | 28 | registerSettingsPage(SettingsPage); 29 | -------------------------------------------------------------------------------- /faces/cosmic-rays/app/Ray.js: -------------------------------------------------------------------------------- 1 | import { me as device } from 'device'; 2 | import { UI } from '@chris-lewis/fitbit-utils/app'; 3 | import { deviceWidths } from './constants'; 4 | 5 | /** Movement step size */ 6 | const MOVE_DELTA = 15; 7 | /** Length of a ray */ 8 | const RAY_LENGTH = 100; 9 | /** Range of spawn delays in milliseconds */ 10 | const DELAY_RANGE_MS = [300, 2000]; 11 | /** Min x1 value */ 12 | const X_MIN = 50; 13 | /** Minimum ray spacing */ 14 | const X_MOD = 30; 15 | 16 | /** 17 | * Ray class 18 | */ 19 | export default class Ray { 20 | /** 21 | * Ray constructor. 22 | * 23 | * @param {number} index - Ray index. 24 | */ 25 | constructor (index) { 26 | this.index = index; 27 | this.isResetting = false; 28 | this.displaySize = deviceWidths[device.modelName]; 29 | 30 | this.line = UI.get(`ray[${index}]`); 31 | 32 | // Handed in index.resume 33 | // this.reset(); 34 | } 35 | 36 | /** 37 | * Begin the Ray's movement again. 38 | */ 39 | reset () { 40 | this.hide(); 41 | this.isResetting = true; 42 | 43 | const delay = Math.round(Math.random() * DELAY_RANGE_MS[1]) + DELAY_RANGE_MS[0]; 44 | setTimeout(() => { 45 | // Even ray spacing 46 | let nextX1 = X_MOD + 1; 47 | while (nextX1 % X_MOD !== 0) { 48 | nextX1 = Math.round(Math.random() * 1.5 * this.displaySize) + X_MIN; 49 | } 50 | 51 | // Set the new start position 52 | this.line.x1 = nextX1; 53 | this.line.y1 = 0; 54 | this.line.x2 = this.line.x1 + RAY_LENGTH; 55 | this.line.y2 = this.line.y1 - RAY_LENGTH; 56 | 57 | this.isResetting = false; 58 | this.show(); 59 | }, delay); 60 | } 61 | 62 | /** 63 | * Step the Ray's movement. 64 | */ 65 | update () { 66 | this.line.x1 -= MOVE_DELTA; 67 | this.line.y1 += MOVE_DELTA; 68 | this.line.x2 -= MOVE_DELTA; 69 | this.line.y2 += MOVE_DELTA; 70 | 71 | if (this.line.x2 < 0 && !this.isResetting) this.reset(); 72 | } 73 | 74 | /** 75 | * Set the new ray color. 76 | * 77 | * @param {string} color - CSS color. 78 | */ 79 | setColor (color) { 80 | this.line.style.fill = color; 81 | } 82 | 83 | /** 84 | * Hide the ray. 85 | */ 86 | hide () { 87 | UI.setVisible(this.line, false); 88 | } 89 | 90 | /** 91 | * Show the ray. 92 | */ 93 | show () { 94 | UI.setVisible(this.line, true); 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /faces/cosmic-rays/app/constants.js: -------------------------------------------------------------------------------- 1 | export const DB_KEY_THEME = 'theme'; 2 | 3 | export const deviceWidths = { 4 | Ionic: 348, 5 | Versa: 300, 6 | 'Versa 2': 300, 7 | 'Versa 3': 336, 8 | 'Sense': 336, 9 | }; 10 | 11 | const pastelRainbowColors = [ 12 | '#fea3aa', 13 | '#f8b88b', 14 | '#faf884', 15 | '#baed91', 16 | '#b2cefe', 17 | '#f2a2e8', 18 | ]; 19 | 20 | export const Themes = { 21 | classic: { 22 | foreground: () => '#ffffff', 23 | }, 24 | electricblue: { 25 | foreground: () => '#0096FF', 26 | }, 27 | steelgrey: { 28 | foreground: () => '#999999', 29 | }, 30 | jazzberryjam: { 31 | foreground: () => '#aa0055', 32 | }, 33 | bloodred: { 34 | foreground: () => '#8e0000', 35 | }, 36 | cyan: { 37 | foreground: () => '#5b979a', 38 | }, 39 | orange: { 40 | foreground: () => '#ff8c00', 41 | }, 42 | royalblue: { 43 | foreground: () => '#1d00c4', 44 | }, 45 | pastelrainbow: { 46 | foreground: () => { 47 | const index = Math.round(Math.random() * (pastelRainbowColors.length - 1)); 48 | return pastelRainbowColors[index]; 49 | }, 50 | }, 51 | }; 52 | -------------------------------------------------------------------------------- /faces/cosmic-rays/companion/index.js: -------------------------------------------------------------------------------- 1 | import { settingsStorage } from 'settings'; 2 | import { me } from 'companion'; 3 | import { Comm } from '@chris-lewis/fitbit-utils/companion'; 4 | 5 | const DB_KEY_THEME = 'theme'; 6 | 7 | /** 8 | * Send a value to the watch. 9 | * 10 | * @param {string} key - Key to send. 11 | * @param {string} value - Value to send. 12 | */ 13 | const sendValue = (key, value) => { 14 | if (!value) throw new Error('No value to send'); 15 | 16 | const data = { [key]: value }; 17 | Comm.sendMessage(data); 18 | console.log(`Send:\n${JSON.stringify(data)}`); 19 | }; 20 | 21 | // Settings changed while companion is running 22 | settingsStorage.onchange = (event) => { 23 | console.log(`settingsStorage.onchange:\n${JSON.stringify(event)}`); 24 | 25 | sendValue(event.key, JSON.parse(event.newValue).values[0].name); 26 | }; 27 | 28 | /** 29 | * The main function. 30 | */ 31 | const main = () => { 32 | // Settings were changed while the companion was not running 33 | if (me.launchReasons.settingChanged) { 34 | console.log('me.launchReasons.settingChanged'); 35 | 36 | sendValue(DB_KEY_THEME, settingsStorage.getItem(DB_KEY_THEME)); 37 | } 38 | }; 39 | 40 | main(); 41 | -------------------------------------------------------------------------------- /faces/cosmic-rays/convert-sdk.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Script to convert a FitBit project between SDK 4 and SDK 5. 4 | # Usage: ./convert-sdk.sh 5 5 | 6 | function convert_sdk_5 { 7 | # Rename resources/widgets.gui >> resources/widget.defs 8 | mv resources/widgets.gui resources/widget.defs 9 | # Substitute in resources/widget.defs 'widgets_common.gui' for 'system_widget.defs' 10 | sed -i '' 's/widgets_common\.gui/system_widget\.defs/g' resources/widget.defs 11 | # Substitute other gui for defs 12 | sed -i '' 's/\.gui/\.defs/g' resources/widget.defs 13 | # Rename resources/*.gui >> resources/*.view 14 | cd resources 15 | for f in *.gui; do mv -- "$f" "${f%.gui}.view"; done 16 | cd - 17 | # Copy package-sdk5.json to package.json 18 | cp package-sdk5.json package.json 19 | # Install dependencies 20 | npm i 21 | } 22 | 23 | function convert_sdk_4 { 24 | # Rename resources/widget.defs >> resources/widgets.gui 25 | mv resources/widget.defs resources/widgets.gui 26 | # Substitute in resources/widgets.gui 'system_widget.defs' for 'widgets_common.gui' 27 | sed -i '' 's/system_widget\.defs/widgets_common\.gui/g' resources/widgets.gui 28 | # Substitute other gui for defs 29 | sed -i '' 's/\.defs/\.gui/g' resources/widgets.gui 30 | # Rename resources/*.view >> resources/*.gui 31 | cd resources 32 | for f in *.view; do mv -- "$f" "${f%.view}.gui"; done 33 | cd - 34 | # Copy package-sdk4.json to package.json 35 | cp package-sdk4.json package.json 36 | # Install dependencies 37 | npm i 38 | } 39 | 40 | VERSION=$1 41 | if [[ "$VERSION" == "4" ]]; then 42 | convert_sdk_4 43 | elif [[ "$VERSION" == "5" ]]; then 44 | convert_sdk_5 45 | else 46 | echo "Invalid version parameter" 47 | fi 48 | -------------------------------------------------------------------------------- /faces/cosmic-rays/package-sdk4.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cosmic-rays", 3 | "version": "1.0.0", 4 | "devDependencies": { 5 | "@chris-lewis/fitbit-utils": "^1.1.4", 6 | "@fitbit/sdk": "^4.3.2", 7 | "@fitbit/sdk-cli": "^1.7.1" 8 | }, 9 | "fitbit": { 10 | "appUUID": "d1013bcf-b95b-4a73-95dc-cc9ae6dd47a6", 11 | "appType": "clockface", 12 | "appDisplayName": "Cosmic Rays", 13 | "iconFile": "resources/icon.png", 14 | "wipeColor": "", 15 | "requestedPermissions": [ 16 | ], 17 | "buildTargets": [ 18 | "higgs", 19 | "meson", 20 | "gemini", 21 | "mira" 22 | ], 23 | "i18n": { 24 | "en-US": { 25 | "name": "Cosmic Rays" 26 | } 27 | }, 28 | "defaultLanguage": "en-US" 29 | }, 30 | "scripts": { 31 | "build": "fitbit-build", 32 | "debug": "fitbit", 33 | "clearCredentials": "node -e \"require('keytar').deletePassword('fitbit-sdk','production');console.log('done')\"" 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /faces/cosmic-rays/package-sdk5.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cosmic-rays", 3 | "version": "1.0.0", 4 | "devDependencies": { 5 | "@chris-lewis/fitbit-utils": "^1.1.4", 6 | "@fitbit/sdk": "^6.0.2", 7 | "@fitbit/sdk-cli": "^1.7.3", 8 | "keytar": "^7.7.0" 9 | }, 10 | "fitbit": { 11 | "appUUID": "d1013bcf-b95b-4a73-95dc-cc9ae6dd47a6", 12 | "appType": "clockface", 13 | "appDisplayName": "Cosmic Rays", 14 | "iconFile": "resources/icon.png", 15 | "wipeColor": "", 16 | "requestedPermissions": [ 17 | "access_aod" 18 | ], 19 | "buildTargets": [ 20 | "atlas", 21 | "vulcan" 22 | ], 23 | "i18n": { 24 | "en-US": { 25 | "name": "Cosmic Rays" 26 | } 27 | }, 28 | "defaultLanguage": "en-US" 29 | }, 30 | "scripts": { 31 | "build": "fitbit-build", 32 | "debug": "fitbit", 33 | "clearCredentials": "node -e \"require('keytar').deletePassword('fitbit-sdk','production');console.log('done')\"" 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /faces/cosmic-rays/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cosmic-rays", 3 | "version": "1.0.0", 4 | "devDependencies": { 5 | "@chris-lewis/fitbit-utils": "^1.1.5", 6 | "@fitbit/sdk": "^6.0.2", 7 | "@fitbit/sdk-cli": "^1.7.3", 8 | "keytar": "^7.7.0" 9 | }, 10 | "fitbit": { 11 | "appUUID": "d1013bcf-b95b-4a73-95dc-cc9ae6dd47a6", 12 | "appType": "clockface", 13 | "appDisplayName": "Cosmic Rays", 14 | "iconFile": "resources/icon.png", 15 | "wipeColor": "", 16 | "requestedPermissions": [ 17 | "access_aod" 18 | ], 19 | "buildTargets": [ 20 | "atlas", 21 | "vulcan" 22 | ], 23 | "i18n": { 24 | "en-US": { 25 | "name": "Cosmic Rays" 26 | } 27 | }, 28 | "defaultLanguage": "en-US" 29 | }, 30 | "scripts": { 31 | "build": "fitbit-build", 32 | "debug": "fitbit", 33 | "clearCredentials": "node -e \"require('keytar').deletePassword('fitbit-sdk','production');console.log('done')\"" 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /faces/cosmic-rays/render-char.py: -------------------------------------------------------------------------------- 1 | from PIL import Image, ImageFont, ImageDraw 2 | import sys 3 | 4 | CHAR = sys.argv[1] 5 | GLYPH_SIZE = 100 6 | FONT_COLOR = (255, 255, 255) 7 | OFFSET = (10, -12) 8 | 9 | out = Image.new('RGBA', (GLYPH_SIZE, GLYPH_SIZE), (0, 0, 0, 0)) 10 | draw = ImageDraw.Draw(out) 11 | 12 | ttf = ImageFont.truetype('hemi head bd it.ttf', GLYPH_SIZE) 13 | draw.text(OFFSET, CHAR, font=ttf, fill=FONT_COLOR) 14 | 15 | out.save(f"resources/font/{CHAR}.png") 16 | -------------------------------------------------------------------------------- /faces/cosmic-rays/resources/font/0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/C-D-Lewis/fitbit-dev/dabba32806ffab5f34b76095e4156468d598c383/faces/cosmic-rays/resources/font/0.png -------------------------------------------------------------------------------- /faces/cosmic-rays/resources/font/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/C-D-Lewis/fitbit-dev/dabba32806ffab5f34b76095e4156468d598c383/faces/cosmic-rays/resources/font/1.png -------------------------------------------------------------------------------- /faces/cosmic-rays/resources/font/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/C-D-Lewis/fitbit-dev/dabba32806ffab5f34b76095e4156468d598c383/faces/cosmic-rays/resources/font/2.png -------------------------------------------------------------------------------- /faces/cosmic-rays/resources/font/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/C-D-Lewis/fitbit-dev/dabba32806ffab5f34b76095e4156468d598c383/faces/cosmic-rays/resources/font/3.png -------------------------------------------------------------------------------- /faces/cosmic-rays/resources/font/4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/C-D-Lewis/fitbit-dev/dabba32806ffab5f34b76095e4156468d598c383/faces/cosmic-rays/resources/font/4.png -------------------------------------------------------------------------------- /faces/cosmic-rays/resources/font/5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/C-D-Lewis/fitbit-dev/dabba32806ffab5f34b76095e4156468d598c383/faces/cosmic-rays/resources/font/5.png -------------------------------------------------------------------------------- /faces/cosmic-rays/resources/font/6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/C-D-Lewis/fitbit-dev/dabba32806ffab5f34b76095e4156468d598c383/faces/cosmic-rays/resources/font/6.png -------------------------------------------------------------------------------- /faces/cosmic-rays/resources/font/7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/C-D-Lewis/fitbit-dev/dabba32806ffab5f34b76095e4156468d598c383/faces/cosmic-rays/resources/font/7.png -------------------------------------------------------------------------------- /faces/cosmic-rays/resources/font/8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/C-D-Lewis/fitbit-dev/dabba32806ffab5f34b76095e4156468d598c383/faces/cosmic-rays/resources/font/8.png -------------------------------------------------------------------------------- /faces/cosmic-rays/resources/font/9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/C-D-Lewis/fitbit-dev/dabba32806ffab5f34b76095e4156468d598c383/faces/cosmic-rays/resources/font/9.png -------------------------------------------------------------------------------- /faces/cosmic-rays/resources/font/originals/0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/C-D-Lewis/fitbit-dev/dabba32806ffab5f34b76095e4156468d598c383/faces/cosmic-rays/resources/font/originals/0.png -------------------------------------------------------------------------------- /faces/cosmic-rays/resources/font/originals/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/C-D-Lewis/fitbit-dev/dabba32806ffab5f34b76095e4156468d598c383/faces/cosmic-rays/resources/font/originals/1.png -------------------------------------------------------------------------------- /faces/cosmic-rays/resources/font/originals/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/C-D-Lewis/fitbit-dev/dabba32806ffab5f34b76095e4156468d598c383/faces/cosmic-rays/resources/font/originals/2.png -------------------------------------------------------------------------------- /faces/cosmic-rays/resources/font/originals/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/C-D-Lewis/fitbit-dev/dabba32806ffab5f34b76095e4156468d598c383/faces/cosmic-rays/resources/font/originals/3.png -------------------------------------------------------------------------------- /faces/cosmic-rays/resources/font/originals/4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/C-D-Lewis/fitbit-dev/dabba32806ffab5f34b76095e4156468d598c383/faces/cosmic-rays/resources/font/originals/4.png -------------------------------------------------------------------------------- /faces/cosmic-rays/resources/font/originals/5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/C-D-Lewis/fitbit-dev/dabba32806ffab5f34b76095e4156468d598c383/faces/cosmic-rays/resources/font/originals/5.png -------------------------------------------------------------------------------- /faces/cosmic-rays/resources/font/originals/6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/C-D-Lewis/fitbit-dev/dabba32806ffab5f34b76095e4156468d598c383/faces/cosmic-rays/resources/font/originals/6.png -------------------------------------------------------------------------------- /faces/cosmic-rays/resources/font/originals/7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/C-D-Lewis/fitbit-dev/dabba32806ffab5f34b76095e4156468d598c383/faces/cosmic-rays/resources/font/originals/7.png -------------------------------------------------------------------------------- /faces/cosmic-rays/resources/font/originals/8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/C-D-Lewis/fitbit-dev/dabba32806ffab5f34b76095e4156468d598c383/faces/cosmic-rays/resources/font/originals/8.png -------------------------------------------------------------------------------- /faces/cosmic-rays/resources/font/originals/9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/C-D-Lewis/fitbit-dev/dabba32806ffab5f34b76095e4156468d598c383/faces/cosmic-rays/resources/font/originals/9.png -------------------------------------------------------------------------------- /faces/cosmic-rays/resources/index.view: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /faces/cosmic-rays/resources/styles.css: -------------------------------------------------------------------------------- 1 | #app-background { 2 | width: 100%; 3 | height: 100%; 4 | fill: black; 5 | } 6 | 7 | .ray { 8 | fill: white; 9 | stroke-width: 4; 10 | } 11 | 12 | .digit { 13 | width: 100; 14 | height: 100; 15 | } 16 | 17 | .h0 { 18 | x: 60; 19 | y: 80; 20 | } 21 | 22 | .h1 { 23 | x: 130; 24 | y: 80; 25 | } 26 | 27 | .m0 { 28 | x: 110; 29 | y: 170; 30 | } 31 | 32 | .m1 { 33 | x: 180; 34 | y: 170; 35 | } 36 | -------------------------------------------------------------------------------- /faces/cosmic-rays/resources/widget.defs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /faces/cosmic-rays/screenshots/336-classic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/C-D-Lewis/fitbit-dev/dabba32806ffab5f34b76095e4156468d598c383/faces/cosmic-rays/screenshots/336-classic.png -------------------------------------------------------------------------------- /faces/cosmic-rays/screenshots/336-electric.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/C-D-Lewis/fitbit-dev/dabba32806ffab5f34b76095e4156468d598c383/faces/cosmic-rays/screenshots/336-electric.png -------------------------------------------------------------------------------- /faces/cosmic-rays/screenshots/336-orange.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/C-D-Lewis/fitbit-dev/dabba32806ffab5f34b76095e4156468d598c383/faces/cosmic-rays/screenshots/336-orange.png -------------------------------------------------------------------------------- /faces/cosmic-rays/screenshots/336-rainbow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/C-D-Lewis/fitbit-dev/dabba32806ffab5f34b76095e4156468d598c383/faces/cosmic-rays/screenshots/336-rainbow.png -------------------------------------------------------------------------------- /faces/cosmic-rays/settings/index.jsx: -------------------------------------------------------------------------------- 1 | const themeOptions = [ 2 | { name: 'classic' }, 3 | { name: 'electricblue' }, 4 | { name: 'steelgrey' }, 5 | { name: 'pastelrainbow' }, 6 | { name: 'jazzberryjam' }, 7 | { name: 'bloodred' }, 8 | { name: 'cyan' }, 9 | { name: 'orange' }, 10 | { name: 'royalblue' }, 11 | ]; 12 | 13 | /** 14 | * SettingsPage component. 15 | * 16 | * @param {object} props - Component props. 17 | * @returns {HTMLElement} 18 | */ 19 | const SettingsPage = props => ( 20 | 21 |
23 |