Cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Saving Color Select Settings

ANSWERED

I have been receiving feedback that my watch face color picker settings only stay applied for a short period of time until they open up an app or when they swipe to look at the menu. Then the colors revert back to the original colors.

 

How would I go about fixing this?

 

app/index.js

 

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 dividerTop = document.getElementById ("divider-top");
let dividerBtm = document.getElementById ("divider-btm");

messaging.peerSocket.onmessage = (evt) => {
  let newColor;
  
  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;   
    
    case 'colorDivider':
      dividerTop.style.fill = evt.data.value;
      dividerBtm.style.fill = evt.data.value;
      break;    
  }
}

 

settingsStorage.onchange = 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);
  }
}

companion/index.js

settingsStorage.onchange = 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);
  }
}

 

 

Best Answer
0 Votes
1 BEST ANSWER

Accepted Solutions

There's a couple of issues:

 

1. You have a typo in app/index.js. settingCallback / settingsCallback

2. It looks like there is somehow an invalid settings file persisted, maybe it's just empty. Anyway, change loadSettings() in app/simple/device-settings.js

 

// Load settings from filesystem
function loadSettings() {
  try {
    let savedSettings = fs.readFileSync(SETTINGS_FILE, SETTINGS_TYPE);
    if (typeof savedSettings === "undefined") {
      return {};
    } else {
      return savedSettings;
    }
  } catch (ex) {
    return {};
  }
}

View best answer in original post

Best Answer
12 REPLIES 12

On the device, you need to save and load your settings to a file.

 

You can see an example in the SDK Moment example https://github.com/Fitbit/sdk-moment/blob/master/app/simple/device-settings.js

Best Answer
0 Votes

Thank you for this. I have edited my code to replicate the one in the SDK Moment example. 

 

But I am now having the problem that the colors of each of my elements will not change.

I can't seem to see what would be causing the problem.

 

app/index

import * as simpleSettings from "./simple/device-settings.js";

let stepsLabel = document.getElementById("stepsLabel");
let timeLabel = document.getElementById("timeLabel");
let dayLabel = document.getElementById("dayLabel");
let monthLabel = document.getElementById("monthLabel");
let dividerTop = document.getElementById ("divider-top");
let dividerBtm = document.getElementById ("divider-btm");
  
  function settingCallback(data){
    if (!evt.data.value){
    return;
  } 
    if (data.colorSteps) {
      stepsLabel.style.fill = evt.data.value;
    }
    if (data.colorTime) {
      timeLabel.style.fill = evt.data.value;
    }
    if (data.colorDay) {
      dayLabel.style.fill = evt.data.value;
    }
    if (data.colorMonth) {
      monthLabel.style.fill = evt.data.value;   
     }
    if (data.colorDivider) {
      dividerTop.style.fill = evt.data.value;
      dividerBtm.style.fill = evt.data.value;   
    }
  }

simpleSettings.initialize(settingsCallback);

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);
}

companion/index

import * as simpleSettings from "./simple/companion-settings";

simpleSettings.initialize();

companion/simple/companion-settings.js

import * as messaging from "messaging";
import { settingsStorage } from "settings";

export function initialize() {
  settingsStorage.addEventListener("change", evt => {
    if (evt.oldValue !== evt.newValue) {
      sendValue(evt.key, evt.newValue);
    }
  });
}

  function sendValue(key, val) {
    if (val) {
    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");
  }
}  

settings/index

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 Answer
0 Votes

Your settingsCallback() isn't right. You're not receiving evt.data, you actually receive each setting in the data object.

 

Take a look at this function again. https://github.com/Fitbit/sdk-moment/blob/master/app/index.js#L52

Best Answer
0 Votes

 

I have amended the code.

 

I received this error when selecting a color for the time element.Capture 7.PNG

 

 

It references this line of code

Capture 8.PNG

 

 

 

 

 

This same error happens for each of my watch face elements.

 

It also states that settingsCallback is not defined.

Best Answer
0 Votes

It's saying the `settings` object isn't defined. Can you put your project on Github?

Best Answer
0 Votes

I have created an account but I have not used Github before.

How do I upload my project?

Best Answer
0 Votes

@SunsetRunner wrote:

I have created an account but I have not used Github before.

How do I upload my project?


I'd probably start with a tutorial like this https://product.hubspot.com/blog/git-and-github-tutorial-for-beginners

Best Answer
0 Votes

Thank you for the link to the tutorial.

 

I've now got the project up onto GitHub 

 

https://github.com/CESAOCRA/Large_Print_Watchface

 

Best Answer
0 Votes

There's a couple of issues:

 

1. You have a typo in app/index.js. settingCallback / settingsCallback

2. It looks like there is somehow an invalid settings file persisted, maybe it's just empty. Anyway, change loadSettings() in app/simple/device-settings.js

 

// Load settings from filesystem
function loadSettings() {
  try {
    let savedSettings = fs.readFileSync(SETTINGS_FILE, SETTINGS_TYPE);
    if (typeof savedSettings === "undefined") {
      return {};
    } else {
      return savedSettings;
    }
  } catch (ex) {
    return {};
  }
}
Best Answer

Thank you. It is all working correctly now.

Best Answer
0 Votes

I've downloaded your project and applied TypeScript over it, raising the typos mentioned in this thread:

TypeScript check detect typoTypeScript check detect typo

Adding TypeScript to your project will prevent you from that kind of mistakes.

Best Answer
0 Votes

Hi I'm trying to reference your issue with saving the settings to my Toggle switch.  I keep getting an error for "Cannot read property 'value' of undefined onsettingschange at app/simple/device-settings.js:14,1" .  What did you do to fix yours?

 

app/index.js

  function settingCallback(data){
    if (!evt.data.value){
    // 24h format
    hours12.style.display = "none";
    hour24.style.display = "inline";  
    console.log("24 hour format");
    }
    else {
      // 12h format
    hours12.style.display = "inline";
    hour24.style.display = "none";
    console.log("12 hour format");
    }
  }
  simpleSettings.initialize(settingCallback);

 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 {
    let savedSettings = fs.readFileSync(SETTINGS_FILE, SETTINGS_TYPE);
    if (typeof savedSettings === "undefined") {
      return {};
    } else {
      return savedSettings;
    }
  } catch (ex) {
    return {};
  }
}
// Save settings to the filesystem
function saveSettings() {
  fs.writeFileSync(SETTINGS_FILE, settings, SETTINGS_TYPE);
}
Best Answer
0 Votes