08-27-2018 09:11
- Mark as New
- Bookmark
- Subscribe
- Permalink
- Report this post

SunsetRunner
08-27-2018 09:11
- Mark as New
- Bookmark
- Subscribe
- Permalink
- Report this post
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.
Accepted Solutions
09-16-2018 02:24 - edited 09-16-2018 02:26
- Mark as New
- Bookmark
- Subscribe
- Permalink
- Report this post

09-16-2018 02:24 - edited 09-16-2018 02:26
- Mark as New
- Bookmark
- Subscribe
- Permalink
- Report this post
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.

09-01-2018 10:07
- Mark as New
- Bookmark
- Subscribe
- Permalink
- Report this post


09-01-2018 10:07
- Mark as New
- Bookmark
- Subscribe
- Permalink
- Report this post
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.

09-07-2018 04:43
- Mark as New
- Bookmark
- Subscribe
- Permalink
- Report this post

SunsetRunner
09-07-2018 04:43
- Mark as New
- Bookmark
- Subscribe
- Permalink
- Report this post
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.

09-07-2018 08:09
- Mark as New
- Bookmark
- Subscribe
- Permalink
- Report this post

SunsetRunner
09-07-2018 08:09
- Mark as New
- Bookmark
- Subscribe
- Permalink
- Report this post
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

09-07-2018 08:12
- Mark as New
- Bookmark
- Subscribe
- Permalink
- Report this post


09-07-2018 08:12
- Mark as New
- Bookmark
- Subscribe
- Permalink
- Report this post
Can you paste the contents of your settings/index.jsx file?

09-07-2018 08:14
- Mark as New
- Bookmark
- Subscribe
- Permalink
- Report this post

SunsetRunner
09-07-2018 08:14
- Mark as New
- Bookmark
- Subscribe
- Permalink
- Report this post
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);

09-07-2018 08:55
- Mark as New
- Bookmark
- Subscribe
- Permalink
- Report this post


09-07-2018 08:55
- Mark as New
- Bookmark
- Subscribe
- Permalink
- Report this post
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);

09-07-2018 11:44
- Mark as New
- Bookmark
- Subscribe
- Permalink
- Report this post

SunsetRunner
09-07-2018 11:44
- Mark as New
- Bookmark
- Subscribe
- Permalink
- Report this post
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.

09-08-2018 08:51
- Mark as New
- Bookmark
- Subscribe
- Permalink
- Report this post

SunsetRunner
09-08-2018 08:51
- Mark as New
- Bookmark
- Subscribe
- Permalink
- Report this post
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.

09-08-2018 10:20
- Mark as New
- Bookmark
- Subscribe
- Permalink
- Report this post

09-08-2018 10:20
- Mark as New
- Bookmark
- Subscribe
- Permalink
- Report this post
I think you will have to post the code for anyone to comment on this.
John

09-09-2018 03:21 - edited 09-09-2018 03:24
- Mark as New
- Bookmark
- Subscribe
- Permalink
- Report this post

SunsetRunner
09-09-2018 03:21 - edited 09-09-2018 03:24
- Mark as New
- Bookmark
- Subscribe
- Permalink
- Report this post
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);

09-09-2018 03:25
- Mark as New
- Bookmark
- Subscribe
- Permalink
- Report this post

SunsetRunner
09-09-2018 03:25
- Mark as New
- Bookmark
- Subscribe
- Permalink
- Report this post
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);
}

09-09-2018 10:30
- Mark as New
- Bookmark
- Subscribe
- Permalink
- Report this post

09-09-2018 10:30
- Mark as New
- Bookmark
- Subscribe
- Permalink
- Report this post
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.

09-10-2018 02:45 - edited 09-10-2018 02:59
- Mark as New
- Bookmark
- Subscribe
- Permalink
- Report this post

09-10-2018 02:45 - edited 09-10-2018 02:59
- Mark as New
- Bookmark
- Subscribe
- Permalink
- Report this post
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}
*/

09-10-2018 08:12
- Mark as New
- Bookmark
- Subscribe
- Permalink
- Report this post

SunsetRunner
09-10-2018 08:12
- Mark as New
- Bookmark
- Subscribe
- Permalink
- Report this post
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

09-10-2018 08:16 - edited 09-10-2018 08:46
- Mark as New
- Bookmark
- Subscribe
- Permalink
- Report this post

SunsetRunner
09-10-2018 08:16 - edited 09-10-2018 08:46
- Mark as New
- Bookmark
- Subscribe
- Permalink
- Report this post
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);
})

09-10-2018 08:29
- Mark as New
- Bookmark
- Subscribe
- Permalink
- Report this post

09-10-2018 08:29
- Mark as New
- Bookmark
- Subscribe
- Permalink
- Report this post
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.

09-10-2018 09:19
- Mark as New
- Bookmark
- Subscribe
- Permalink
- Report this post

SunsetRunner
09-10-2018 09:19
- Mark as New
- Bookmark
- Subscribe
- Permalink
- Report this post
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.

09-10-2018 20:21 - edited 09-10-2018 20:25
- Mark as New
- Bookmark
- Subscribe
- Permalink
- Report this post

09-10-2018 20:21 - edited 09-10-2018 20:25
- Mark as New
- Bookmark
- Subscribe
- Permalink
- Report this post
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);
})

09-14-2018 04:20
- Mark as New
- Bookmark
- Subscribe
- Permalink
- Report this post

SunsetRunner
09-14-2018 04:20
- Mark as New
- Bookmark
- Subscribe
- Permalink
- Report this post
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.

