08-27-2018 09:11
08-27-2018 09:11
I have been looking into adding customizable settings to my watch face. (I am really new to creating watch faces and coding)
I have been struggling to get the specific element of the watch face to be customizable.
My watch face has labels in styles.css for the time, steps, day and month which I would like to make the color customizable. Also within my index.gui I have two lines which I would also like to make customizable to the user.
I would really appreciate any help that can be given.
Thanks
Answered! Go to the Best Answer.
09-16-2018 02:24 - edited 09-16-2018 02:26
09-16-2018 02:24 - edited 09-16-2018 02:26
give each divider a unique ID, so you can access them directly
(classes also work but I am trying to keep this simple)
index.gui
<rect id="top-divider" class="divider divider-top" /> <rect id="btm-divider" class="divider divider-btm" />
app\index.js
let dividerTop = document.getElementById ("top-divider");
let dividerBtm = document.getElementById ("btm-divider");
// then further down
case 'colorDivider':
dividerTop.style.fill = evt.data.value;
dividerBtm.style.fill = evt.data.value;[UPDATE]: changed ID names to avoid confusion.
Best Answer09-01-2018 10:07
Fitbit Developers oversee the SDK and API forums. We're here to answer questions about Fitbit developer tools, assist with projects, and make sure your voice is heard by the development team.
09-01-2018 10:07
Take a look at the Moment example.
It has some colors in the settings page, a generic approach to sending those settings via the companion, and also demostrates how to use them on the device, as well as persisting them on the device too.
Best Answer09-07-2018 04:43
09-07-2018 04:43
Thanks this has been really helpful.
I have run into a small issue that when I run a simulation of the watch face the settings display blank.
It might be that I have missed out something really obvious which is causing the problem.
Best Answer09-07-2018 08:09
09-07-2018 08:09
This is what displays when a run my watch face. The settings are blank even though I have code in place that should generate and display settings.
I would really appreciate any help with this problem as I am unsure where I have gone wrong.
Thanks
Best Answer09-07-2018 08:12
Fitbit Developers oversee the SDK and API forums. We're here to answer questions about Fitbit developer tools, assist with projects, and make sure your voice is heard by the development team.
09-07-2018 08:12
Can you paste the contents of your settings/index.jsx file?
Best Answer09-07-2018 08:14
09-07-2018 08:14
const colorSet = [
{color: "white"},
{color: "black"},
{color: "grey"},
{color: "navy"},
{color: "blue"},
{color: "cyan"},
{color: "olive"},
{color: "darkgreen"},
{color: "springgreen"},
{color: "slate blue"},
{color: "khaki"},
{color: "yellow"},
{color: "lemonchiffon"},
{color: "coral"},
{color: "lightpink"},
{color: "red"},
{color: "crimson"}
];
const options = [
['Time Color', 'colorTime'],
['Dividers Color', 'colorDividers'],
['Steps Color', 'colorSteps'],
['Day Color', 'colorDay'],
['Month Color', 'colorMonth']
];
function mySettings(props) {
return (
<Page>
<Section
title={<Text bold align="center">Time Colour</Text>}>
<ColorSelect
settingsKey={colorTime}
colors={colorSet} />
</Section>
<Section
title={<Text bold align="center">Divider Colour</Text>}>
<ColorSelect
settingsKey={colorDividers}
colors={colorSet} />
</Section>
<Section
title={<Text bold align="centre">Steps Colour</Text>}>
<ColorSelect
settingsKey={colorSteps}
colors={colorSet} />
</Section>
<Section
title={<Text bold align="centre">Day Colour</Text>}>
<ColorSelect
settingsKey={colorDay}
colors={colorSet} />
</Section>
<Section
title={<Text bold align= "center">Month Colour</Text>}>
<ColorSelect
settingsKey={colorMonth}
colors={colorSet} />
</Section>
</Page>
);
}
registerSettingsPage(mySettings);
Best Answer09-07-2018 08:55
Fitbit Developers oversee the SDK and API forums. We're here to answer questions about Fitbit developer tools, assist with projects, and make sure your voice is heard by the development team.
09-07-2018 08:55
That's not quite right.
colorTime and colorSet aren't variables.
<ColorSelect
settingsKey={colorTime}
colors={colorSet} />
</Section>
You should just be able to do this to build color options for each of the items in the options array:
const colorSet = [
{color: "white"},
{color: "black"},
{color: "grey"},
{color: "navy"},
{color: "blue"},
{color: "cyan"},
{color: "olive"},
{color: "darkgreen"},
{color: "springgreen"},
{color: "slate blue"},
{color: "khaki"},
{color: "yellow"},
{color: "lemonchiffon"},
{color: "coral"},
{color: "lightpink"},
{color: "red"},
{color: "crimson"}
];
const options = [
['Time Color', 'colorTime'],
['Dividers Color', 'colorDividers'],
['Steps Color', 'colorSteps'],
['Day Color', 'colorDay'],
['Month Color', 'colorMonth']
];
function mySettings(props) {
return (
<Page>
{options.map(([title, settingsKey]) =>
<Section
title={title}>
<ColorSelect
settingsKey={settingsKey}
colors={colorSet} />
</Section>
)}
</Page>
);
}
registerSettingsPage(mySettings);
Best Answer09-07-2018 11:44
09-07-2018 11:44
Thank you. I have now edited my code. It displayed the color selection settings for a short time but after I started to change the colors in the color set it then displayed blank again.
Sorry about this. I haven't got a great understanding of coding. This is the first watch face that I have created.
Best Answer09-08-2018 08:51
09-08-2018 08:51
I have now sorted out so the color selection now displays. But I am getting an error when I try to change the color.
Thanks for all of your help.
Best Answer09-08-2018 10:20
09-08-2018 10:20
I think you will have to post the code for anyone to comment on this.
John
Best Answer09-09-2018 03:21 - edited 09-09-2018 03:24
09-09-2018 03:21 - edited 09-09-2018 03:24
app/index.js
import * as simpleSettings from "./simple/device-settings.js";
function settingsCallback(data) {
if (!data) {
return;
}
if (data.colorDividers) {
dividers.forEach(item => {
item.style.fill = data.colorDividers;
});
}
if (data.colorTime) {
timeLabel.style.fill = data.colorTime;
}
if (data.colorSteps) {
stepsLabel.style.fill = data.colorSteps;
}
if (data.colorDay) {
DayLabel.style.fill = data.colorDay;
}
if (data.colorMonth) {
MonthLabel.style.fill = data.colorMonth;
}
}
simpleSettings.initialize(settingsCallback);
app/simple/device-settings.js
import { me as device } from "device";
import * as fs from "fs";
import * as messaging from "messaging";
const SETTINGS_TYPE = "cbor";
const SETTINGS_FILE = "settings.cbor";
let settings, onsettingschange;
export function initialize(callback) {
settings = loadSettings();
onsettingschange = callback;
onsettingschange(settings);
}
// Received message containing settings data
messaging.peerSocket.addEventListener("message", function(evt) {
settings[evt.data.key] = evt.data.value;
onsettingschange(settings);
})
// Register for the unload event
me.addEventListener("unload", saveSettings);
// Load settings from filesystem
function loadSettings() {
try {
return fs.readFileSync(SETTINGS_FILE, SETTINGS_TYPE);
} catch (ex) {
return {};
}
}
// Save settings to the filesystem
function saveSettings() {
fs.writeFileSync(SETTINGS_FILE, settings, SETTINGS_TYPE);
}
settings/index.jsx
const colorSet = [
{color: "white"},
{color: "grey"},
{color: "silver"},
{color: "lightgrey"},
{color: "navy"},
{color: "dodgerblue"},
{color: "deepskyblue"},
{color: "lightskyblue"},
{color: "teal"},
{color: "lightgreen"},
{color: "olivedrab"},
{color: "seagreen"},
{color: "darkgreen"},
{color: "#B8FC68"},
{color: "yellow"},
{color: "#FFCC33"},
{color: "orange"},
{color: "orangered"},
{color: "pink"},
{color: "lightpink"},
{color: "crimson"},
{color: "#F83C40"},
{color: "red"},
];
const options = [
['Time Color', 'colorTime'],
['Dividers Color', 'colorDividers'],
['Steps Color', 'colorSteps'],
['Day Color', 'colorDay'],
['Month Color', 'colorMonth']
];
function mySettings(props) {
return (
<Page>
{options.map(([title, settingsKey]) =>
<Section
title={title}>
<ColorSelect
settingsKey={settingsKey}
colors={colorSet} />
</Section>
)}
</Page>
);
}
registerSettingsPage(mySettings);
Best Answer09-09-2018 03:25
09-09-2018 03:25
app/simple/device-settings.js
import { me } from "appbit";
import { me as device } from "device";
import * as fs from "fs";
import * as messaging from "messaging";
const SETTINGS_TYPE = "cbor";
const SETTINGS_FILE = "settings.cbor";
let settings, onsettingschange;
export function initialize(callback) {
settings = loadSettings();
onsettingschange = callback;
onsettingschange(settings);
}
// Received message containing settings data
messaging.peerSocket.addEventListener("message", function(evt) {
settings[evt.data.key] = evt.data.value;
onsettingschange(settings);
})
// Register for the unload event
me.addEventListener("unload", saveSettings);
// Load settings from filesystem
function loadSettings() {
try {
return fs.readFileSync(SETTINGS_FILE, SETTINGS_TYPE);
} catch (ex) {
return {};
}
}
// Save settings to the filesystem
function saveSettings() {
fs.writeFileSync(SETTINGS_FILE, settings, SETTINGS_TYPE);
}
Best Answer09-09-2018 10:30
09-09-2018 10:30
I do not see any reference in your code to colorTime variable that is giving the error. Also, if you copy your code, then select the </> symbol in the formatting section, you can paste your code in there and it will show in an easier to read format.
Best Answer09-10-2018 02:45 - edited 09-10-2018 02:59
09-10-2018 02:45 - edited 09-10-2018 02:59
I can't see how you use the value that comes in from the companion app but here is what I do with colours
peerSocket.onmessage = evt => {
newColour = JSON.parse(evt.data.newValue);
...
...
}
// extract from my code, for your info ...
/*
The user changed a setting in the companion UI
The format of the received data is:
------------------------------------
Toggle
{"isTrusted":false,"key":"tglKeyName","newValue":"false","oldValue":"true"}
Slide
{"isTrusted":false,"key":"sldKeyName","newValue":"2","oldValue":"1"}
ColorSelect
{"isTrusted":false,"key":"clrKeyName","newValue":"\"#FF0000\"","oldValue":"\"#33FF33\""}
Select
{"isTrusted":false,"key":"selKeyName","newValue":"{\"selected\":[2],\"values\":[{\"name\":\"Calories\"}]}","oldValue":"{\"selected\":[0],\"values\":[{}]}"}
Image picker
{"isTrusted":false,"key":"imgBackground","newValue":"{\"imageUri\":\"data:image/png;base64, <base-64 image data goes here>",\"imageSize\":{\"width\":\"300\",\"height\":\"300\"}}","oldValue":null}
*/
Best Answer09-10-2018 08:12
09-10-2018 08:12
import * as simpleSettings from "./simple/device-settings.js";
function settingsCallback(data) {
if (!data) {
return;
}
if (data.colorDividers) {
dividers.forEach(item => {
item.style.fill = data.colorDividers;
});
}
if (data.colorTime) {
timeLabel.style.fill = data.colorTime;
}
if (data.colorSteps) {
stepsLabel.style.fill = data.colorSteps;
}
if (data.colorDay) {
DayLabel.style.fill = data.colorDay;
}
if (data.colorMonth) {
MonthLabel.style.fill = data.colorMonth;
}
}
simpleSettings.initialize(settingsCallback);
This is the code within my app/index.js
Best Answer09-10-2018 08:16 - edited 09-10-2018 08:46
09-10-2018 08:16 - edited 09-10-2018 08:46
const options = [
['Time Color', 'colorTime'],
['Dividers Color', 'colorDividers'],
['Steps Color', 'colorSteps'],
['Day Color', 'colorDay'],
['Month Color', 'colorMonth']
];
function mySettings(props) {
return (
<Page>
{options.map(([title, settingsKey]) =>
<Section
title={title}>
<ColorSelect
settingsKey={settingsKey}
colors={colorSet} />
</Section>
)}
</Page>
);
}
registerSettingsPage(mySettings);This is the code in my settings/index.jsx
It currently will not change the color of any of the elements that I have set. It just comes up with the error. The error that appears always links back to this line of code (app/simpe/device-settings.js:24,3):
// Received message containing settings data
messaging.peerSocket.addEventListener("message", function(evt) {
settings[evt.data.key] = evt.data.value;
onsettingschange(settings);
})
Best Answer09-10-2018 08:29
09-10-2018 08:29
As a novice programmer myself, I came across a similar problem. Check the value you are trying to assign as a color, it may not be properly formatted. On mine, I was having problems on the first pass and had to strip off the quotes for it to work. I just did an error catch and removed them.
In my app/index.js
} catch (error) {
if (loadColor !== undefined) {
//on first run-through there are still quotes on the color
loadColor = util.myColor(loadColor);
console.log("Refine loadColor <" + loadColor + ">");then in common/util.js
//get the color without quotes
export function myColor(str) {
return str.substring(1,str.length - 1);
}I hope this helps.
Best Answer09-10-2018 09:19
09-10-2018 09:19
I have just run the simulator and it no longer displays the error when I click on the color options. But it is still not changing the color of the selected area.
These are the id for the elements that I want to change color.
index.gui
<text id="timeLabel" />
<text id="stepsLabel" />
<text id= "dayLabel" />
<text id= "monthLabel"/>
<rect class="divider divider-top" />
<rect class="divider divider-btm" />
settings/index.jsx
const colorSet = [
{color: "white"},
{color: "grey"},
{color: "silver"},
{color: "lightgrey"},
{color: "navy"},
{color: "dodgerblue"},
{color: "deepskyblue"},
{color: "lightskyblue"},
{color: "teal"},
{color: "lightgreen"},
{color: "olivedrab"},
{color: "seagreen"},
{color: "darkgreen"},
{color: "#B8FC68"},
{color: "yellow"},
{color: "#FFCC33"},
{color: "orange"},
{color: "orangered"},
{color: "pink"},
{color: "lightpink"},
{color: "crimson"},
{color: "#F83C40"},
{color: "red"},
];
const options = [
['Time Color', 'colorTime'],
['Dividers Color', 'colorDividers'],
['Steps Color', 'colorSteps'],
['Day Color', 'colorDay'],
['Month Color', 'colorMonth']
];
function mySettings(props) {
return (
<Page>
{options.map(([title, settingsKey]) =>
<Section
title={title}>
<ColorSelect
settingsKey={settingsKey}
colors={colorSet} />
</Section>
)}
</Page>
);
}
registerSettingsPage(mySettings);app/index.js
unction settingsCallback(data) {
if (!data) {
return;
}
if (data.colorDividers) {
dividers.forEach(item => {
item.style.fill = data.colorDividers;
});
}
if (data.colorTime) {
timeLabel.style.fill = data.colorTime;
}
if (data.colorSteps) {
stepsLabel.style.fill = data.colorSteps;
}
if (data.colorDay) {
dayLabel.style.fill = data.colorDay;
}
if (data.colorMonth) {
monthLabel.style.fill = data.colorMonth;
}
}
simpleSettings.initialize(settingsCallback);Is this because I am not referencing the elements using the correct terms?
Sorry if this is a really silly question. I haven't got a great understanding of coding. I have been using the guides and this forum to find out how to create the code for the elements that I want to have within my watch face.
Best Answer09-10-2018 20:21 - edited 09-10-2018 20:25
09-10-2018 20:21 - edited 09-10-2018 20:25
Can you please try using this code (changes are in bold)
messaging.peerSocket.onmessage = (evt) => {
let newColour = JSON.parse(evt.data.newValue);
console.log(`new colour: ${newColour}`);
setting[evt.data.key] = newColour;
onsettingsChange(settings);
}instead of
// Received message containing settings data
messaging.peerSocket.addEventListener("message", function(evt) {
settings[evt.data.key] = evt.data.value;
onsettingschange(settings);
})
Best Answer09-14-2018 04:20
09-14-2018 04:20
I have just replaced the code and I am still having the same problem. The color I select in the settings is still not applying to the specified area.
As you can see here I have selected the color of the time to be grey and there has been no change.
I have on idea where I am going wrong.
Best Answer