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-14-2018 04:41 - edited 09-14-2018 07:25
09-14-2018 04:41 - edited 09-14-2018 07:25
I added your colour selectors and colour array into my settings\index.js.
I then added the following code to catch the event and change the colour of a textbox ("test-text1") in my index.gui.
The code below works and changes the colour whenever the user picks a new one in the Settings UI
// no need to have this inside the event handler
let tt = document.getElementById("test-text1");
peerSocket.onmessage = (evt) => {
console.log(`handleMessages(): ${JSON.stringify(evt)}`);
if (evt.data.key == 'colorTime') {
// for debugging only
let s = JSON.parse(evt.data.newValue);
console.log(`colour is ${s}`);
tt.style.fill = JSON.parse(evt.data.newValue);
}
}
[Updated to correct typing error!]
Best Answer09-14-2018 07:18 - edited 09-14-2018 07:37
09-14-2018 07:18 - edited 09-14-2018 07:37
I have placed the code into my index.gui and it hasn't worked.
It displays in all white text which doesn't seem right.
Thanks for the suggestion.
Best Answer09-14-2018 07:39 - edited 09-14-2018 07:44
09-14-2018 07:39 - edited 09-14-2018 07:44
did you mean app\index.js?
Also, the line
let tt = document.getElementById("test-text1");
needs to be changed to reference your component ID, for example "dayLabel"
Best Answer09-14-2018 07:48 - edited 09-14-2018 07:54
09-14-2018 07:48 - edited 09-14-2018 07:54
I have changed the "test-text1" to "timeLabel" and there is no change it still will not change the color of the time element.
Best Answer09-15-2018 03:32
09-15-2018 03:32
I have created a small project that works.
All of the source is included below.
Please let me know if this solves the problem.
app\index.js
import document from "document"; import * as messaging from "messaging";
let stepsLabel = document.getElementById("stepsLabel"); let timeLabel = document.getElementById("timeLabel"); let dayLabel = document.getElementById("dayLabel"); let monthLabel = document.getElementById("monthLabel"); messaging.peerSocket.onmessage = (evt) => { let newColour; console.log(`handleMessages(): ${JSON.stringify(evt)}`); switch(evt.data.key) { case 'colorSteps': stepsLabel.style.fill = evt.data.value; break; case 'colorTime': timeLabel.style.fill = evt.data.value; break; case 'colorDay': dayLabel.style.fill = evt.data.value; break; case 'colorMonth': monthLabel.style.fill = evt.data.value; break; } }
companion\index.js (extracted from a Fitbit sample project)
import { settingsStorage } from "settings";
import * as messaging from "messaging";
// Settings have been changed
settingsStorage.onchange = function(evt) {
if (evt.newValue !== evt.oldValue) {
sendValue(evt.key, evt.newValue);
}
}
// Send key/value pair
function sendValue(key, val) {
if (!key || !val) {
return;
};
sendSettingData({
key: key,
value: JSON.parse(val)
});
}
// Send JSON object
function sendSettingData(data) {
if (messaging.peerSocket.readyState === messaging.peerSocket.OPEN) {
messaging.peerSocket.send(data);
} else {
console.log("No peerSocket connection");
}
}resources\index.gui (based on your UI)
<svg class="background">
<svg >
<text id="timeLabel" class="my-text">Time</text>
<text id="stepsLabel" class="my-text">Steps</text>
<text id="dayLabel" class="my-text">Day</text>
<text id="monthLabel" class="my-text">Month</text>
</svg>
</svg>styles.css
.background {
viewport-fill: black;
}
.my-text {
font-size: 24;
fill: white;
}
#timeLabel {
x: 10;
y: 30;
}
#stepsLabel {
x: 10;
y: 70;
}
#dayLabel {
x: 10;
y: 110;
}
#monthLabel {
x: 10;
y: 150;
}widgets.gui
<svg>
<defs>
<link rel="stylesheet" href="styles.css" />
<link rel="import" href="/mnt/sysassets/widgets_common.gui" />
<link rel="import" href="/mnt/sysassets/widgets/square_button_widget.gui" />
</defs>
</svg>settings\index.jsx (partial. based on your UI)
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'],
['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-15-2018 08:32 - edited 09-15-2018 08:34
09-15-2018 08:32 - edited 09-15-2018 08:34
I am still having no luck.
This is what I have within my app/index.js, companion/index.js, resources/index.gui, resources/styles.css and settings/index.jsx.
app/index.js
import clock from "clock";
import document from "document";
import { preferences } from "user-settings";
import { zeroPad, } from "../common/utils";
import userActivity from "user-activity";
import { me } from "appbit";
import { me as device } from "device";
import * as fs from "fs";
import * as messaging from "messaging";
// Update the clock every minute
clock.granularity = "minutes";
// Get a handle on the <text> elements specified in the index.gui file
const timeHandle = document.getElementById("timeLabel");
const stepsHandle = document.getElementById("stepsLabel");
const dayHandle = document.getElementById ("dayLabel");
const monthHandle = document.getElementById ("monthLabel");
const divider = document.getElementsByClassName("divider");
// Update the <text> element every tick with the current time
clock.ontick = (evt) => {
let today = new Date();
let monthnum = today.getMonth();
let day = today.getDate();
var month = new Array();
month[0] = "Jan";
month[1] = "Feb";
month[2] = "Mar";
month[3] = "Apr";
month[4] = "May";
month[5] = "Jun";
month[6] = "Jul";
month[7] = "Aug";
month[8] = "Sep";
month[9] = "Oct";
month[10] = "Nov";
month[11] = "Dec";
let monthname = month[monthnum];
const now = evt.date;
let hours = now.getHours();
let mins = now.getMinutes();
if (preferences.clockDisplay === "12h") {
hours = hours % 12 || 12;
} else {
hours = zeroPad(hours);
}
let minsZeroed = zeroPad(mins);
timeHandle.text = `${hours}:${minsZeroed}`;
monthHandle.text = `${monthname}`;
dayHandle.text = `${day}`;
// Activity Values: adjusted type
let stepsValue = (userActivity.today.adjusted["steps"] || 0);
let stepsString = stepsValue + ' steps';
stepsHandle.text = stepsString;
}
/* -------- SETTINGS -------- */
const SETTINGS_TYPE = "cbor";
const SETTINGS_FILE = "settings.cbor";
let settings, onsettingschange;
let stepsLabel = document.getElementById("stepsLabel");
let timeLabel = document.getElementById("timeLabel");
let dayLabel = document.getElementById("dayLabel");
let monthLabel = documnet.getElementById("monthLabel");
let dividers = document.getElementById ("divider");
messaging.peerSocket.onmessage = (evt) => {
let newColor;
consol.log('handleMessages(): $JSON.stringify(evt)}');
switch(evt.data.key) {
case 'colorSteps':
stepsLabel.style.fill = evt.data.value;
break;
case 'colorTime':
timelabel.style.fill = evt.data.value;
break;
case 'colorDay':
dayLabel.style.fill = evt.data.value;
break;
case 'colorMonth':
monthLabel.style.fill = evt.data.value;
break;
case 'colorDivider':
divider.style.fill = evt.data.value;
break;
}
}
companion/index.js
import * as messaging from "messaging";
import { settingsStorage } from "settings";
settingStorage.onchnage = function(evt) {
if (evt.newValue !== Evt.oldValue) {
sendValue(evt.key, evt.newValue);
}
}
function sendValue(key, val) {
if (!key || !val) {
return;
};
sendSettingData({
key: key,
value: JSON.parse(val)
});
}
function sendSettingData(data) {
if (messaging.peerSocket.readyState === messaging.peerSocket.OPEN) {
messaging.peerSocket.send(data);
} else {
console.log("No peerSocket connection");
}
}resources/index.gui
<svg class="background"> <text id="timeLabel" /> <text id="stepsLabel" /> <text id= "dayLabel" /> <text id= "monthLabel"/> <rect class="divider divider-top" /> <rect class="divider divider-btm" />
resources/styles.css
.background {
viewport-fill: black;
}
#timeLabel {
font-size: 170;
font-family: Tungsten-Medium;
text-length: 5;
text-anchor: middle;
letter-spacing: 15;
x: 50%;
y: 70%;
fill: white;
}
#stepsLabel {
font-size: 45;
font-family: Fabrikat-Black;
text-length: 10;
text-anchor: middle;
letter-spacing: 3;
x: 50%;
y: 93%;
fill: white;
}
#monthLabel {
font-size: 50;
font-family: Fabrikat-Black;
text-length: 10;
text-anchor: middle;
letter-spacing: 4;
x: 63%;
y: 17%;
fill: white;
}
#dayLabel {
font-size: 50;
font-family: Fabrikat-Black;
text-length: 2;
text-anchor: start;
letter-spacing: 5;
x: 21%;
y: 17%;
fill: white;
}
.divider {
x: 2%;
width: 286;
height: 5;
fill: teal;
}
.divider-top {
y: 24%;
}
.divider-btm {
y: 75%;
}setting/index.jsx
const colorSet = [
{color: "white"},
{color: "grey"},
{color: "silver"},
{color: "lightgrey"},
{color: "dodgerblue"},
{color: "deepskyblue"},
{color: "lightskyblue"},
{color: "teal"},
{color: "seagreen"},
{color: "olivedrab"},
{color: "yellowgreen"},
{color: "lightgreen"},
{color: "#B8FC68"},
{color: "#E4FA3C"},
{color: "yellow"},
{color: "#FFCC33"},
{color: "orange"},
{color: "orangered"},
{color: "red"},
{color: "#F83C40"},
{color: "crimson"},
{color: "lightpink"},
{color: "mistyrose"},
];
const options = [
['Time Color', 'colorTime'],
['Divider Color', 'colorDivider'],
['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-15-2018 10:19
09-15-2018 10:19
I'm still having no luck.
Thank you for all your help.
Best Answer09-15-2018 10:36
09-15-2018 10:36
This is what I have in my app/index.js
import clock from "clock";
import document from "document";
import { preferences } from "user-settings";
import { zeroPad, } from "../common/utils";
import userActivity from "user-activity";
import { me } from "appbit";
import { me as device } from "device";
import * as fs from "fs";
import * as messaging from "messaging";
// required imports
import * as kpay from './kpay/release/kpay.js';
import * as kpay_common from '../common/kpay/kpay_common.js';
import './kpay/release/kpay_filetransfer.js';
import './kpay/release/kpay_dialogs.js'; // remove if you handle KPay dialogs yourself
import './kpay/release/kpay_time_trial.js'; // remove if you do not want a time based trial
import './kpay/release/kpay_msg_validation.js';
/**** KPAY INIT - REQUIRED ***/
kpay.initialize();
// Update the clock every minute
clock.granularity = "minutes";
// Get a handle on the <text> elements specified in the index.gui file
const timeHandle = document.getElementById("timeLabel");
const stepsHandle = document.getElementById("stepsLabel");
const dayHandle = document.getElementById ("dayLabel");
const monthHandle = document.getElementById ("monthLabel");
const divider = document.getElementsByClassName("divider");
// Update the <text> element every tick with the current time
clock.ontick = (evt) => {
let today = new Date();
let monthnum = today.getMonth();
let day = today.getDate();
var month = new Array();
month[0] = "Jan";
month[1] = "Feb";
month[2] = "Mar";
month[3] = "Apr";
month[4] = "May";
month[5] = "Jun";
month[6] = "Jul";
month[7] = "Aug";
month[8] = "Sep";
month[9] = "Oct";
month[10] = "Nov";
month[11] = "Dec";
let monthname = month[monthnum];
const now = evt.date;
let hours = now.getHours();
let mins = now.getMinutes();
if (preferences.clockDisplay === "12h") {
hours = hours % 12 || 12;
} else {
hours = zeroPad(hours);
}
let minsZeroed = zeroPad(mins);
timeHandle.text = `${hours}:${minsZeroed}`;
monthHandle.text = `${monthname}`;
dayHandle.text = `${day}`;
// Activity Values: adjusted type
let stepsValue = (userActivity.today.adjusted["steps"] || 0);
let stepsString = stepsValue + ' steps';
stepsHandle.text = stepsString;
}
/* -------- SETTINGS -------- */
const SETTINGS_TYPE = "cbor";
const SETTINGS_FILE = "settings.cbor";
let settings, onsettingschange;
let stepsLabel = document.getElementById("stepsLabel");
let timeLabel = document.getElementById("timeLabel");
let dayLabel = document.getElementById("dayLabel");
let monthLabel = document.getElementById("monthLabel");
let dividers = document.getElementById ("divider");
messaging.peerSocket.onmessage = (evt) => {
let newColor;
consol.log('handleMessages(): $JSON.stringify(evt)}');
switch(evt.data.key) {
case 'colorSteps':
stepsLabel.style.fill = evt.data.value;
break;
case 'colorTime':
timelabel.style.fill = evt.data.value;
break;
case 'colorDay':
dayLabel.style.fill = evt.data.value;
break;
case 'colorMonth':
monthLabel.style.fill = evt.data.value;
break;
case 'colorDivider':
divider.style.fill = evt.data.value;
break;
}
}This is what I have in my companion/index.js
import * as kpay from './kpay/release/kpay_companion.js';
import * as kpay_common from '../common/kpay/kpay_common.js';
import { settingsStorage } from "settings";
import * as messaging from "messaging";
// Settings have been changed
settingsStorage.onchnage = function(evt) {
if (evt.newValue !== Evt.oldValue) {
sendValue(evt.key, evt.newValue);
}
}
function sendValue(key, val) {
if (!key || !val) {
return;
};
sendSettingData({
key: key,
value: JSON.parse(val)
});
}
function sendSettingData(data) {
if (messaging.peerSocket.readyState === messaging.peerSocket.OPEN) {
messaging.peerSocket.send(data);
} else {
console.log("No peerSocket connection");
}
}
/**** KPAY INIT - REQUIRED ***/
kpay.initialize();
Best Answer09-15-2018 18:22 - edited 09-15-2018 23:31
09-15-2018 18:22 - edited 09-15-2018 23:31
// typo in event name. It should be onchange
settingsStorage.onchnage = function(evt) {
// js is case-sensitive, so you need to use 'evt' instead of 'Evt' if (evt.newValue !== Evt.oldValue) {
Best Answer09-16-2018 02:07 - edited 09-16-2018 02:18
09-16-2018 02:07 - edited 09-16-2018 02:18
The time, steps, day and month label will now all change color thank you so much.
The dividers will not change color and returns this error.
unhandled TypeError: Cannot set property 'fill' of undefined
index.gui
<rect class="divider divider-top" /> <rect class="divider divider-btm" />
index.js
let divider = document.getElementsByClassName ("divider");styles.css
.divider {
x: 2%;
width: 286;
height: 5;
fill: teal;
}
.divider-top {
y: 24%;
}
.divider-btm {
y: 75%;
}
Best Answer09-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-16-2018 02:38
09-16-2018 02:38
Thank you so much for all your help.
All of the color select functions are working correctly.
Best Answer09-16-2018 02:57
09-16-2018 02:57
No problem at all.
Looking back at some of my posts, I realised that I'd made some mistakes, so I just had to make sure it works in the end! 🙂