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

Default settings on initial load

ANSWERED

Is there a way to set default values for various components in settings/index.jsx? In other words, instead of the user starting with a settings page that looks like this:

 

defBlank.PNG

 

I'd like to start the user with a page that looks something like this:

defSet.PNG

 

 

It seems to me that this should be easy to do, and it probably is. But I'll be danged if I can find a way to do it.

 

Here is the code in the index.jsx file:

function mySettings(props) {
  return (
    <Page>
      <Section
        title={<Text bold align="center">Functionally Fuzzy Settings</Text>}>
        <Toggle
          settingsKey="bSteps"
          label="Steps"
        />
        
        <Toggle
          settingsKey="bHRM"
          label="Heart Rate"
        />
        <Toggle
          settingsKey="bDigiTime"
          label="Digital Time"
        />
        <Toggle
          settingsKey="bAMPM"
          label="Use AM/PM?"
        />
        <Toggle
          settingsKey="bBattery"
          label="Battery"
        />
        <Toggle
          settingsKey="bDate"
          label="Date"
        />
      </Section>
      <Section
        title={<Text bold align="center">Weather Settings</Text>}>
        <Select
          settingsKey="selWeather"
          label="Weather?"
          selectViewTitle="None"
          options={[
            {name:"Yahoo Weather"},
            {name:"OpenWeather"},
            {name:"None"}
          ]}
          
        />
        <Toggle
          settingsKey="bTemp"
          label="Temperature"
        />
        <TextInput
          settingsKey="strKey"
          label="OpenWeather Key"
          placeholder="Enter OpenWeather Key Here"
          action="Add/Update Key"
          //disabled={!(this.props.settings.bTemp === "true")}// && this.props.settings.selWeather.name === "OpenWeather"}
        />
        <Toggle
          settingsKey="bImperial"
          label="Temperature Unit On=F / Off=C"
          />
      </Section>
    </Page>
  );
}

registerSettingsPage(mySettings

 

 

Best Answer
0 Votes
1 BEST ANSWER

Accepted Solutions

Unfortunately, I'm between computers ATM, and it seems I've never had to do this with toggles. However, I think you may need to call setItem() passing the setting value as a JSON string. Here's something I cooked earlier that works with lists; you'll have to adapt it to work with toggles, of course...

// Initialise settings to default values:
if (locale.language === "en-US")
  setDefaultSetting("dateFormat", {"selected":[1],"values":[{"name":"Dec 25","value":1}]});
else
  setDefaultSetting("dateFormat", {"selected":[0],"values":[{"name":"25 Dec","value":0}]});
setDefaultSetting("distMeasure", {"selected":[0],"values":[{"name":"Steps","value":0}]});
setDefaultSetting("activeFrom", {"selected":[6],"values":[{"name":"6 AM","value":6}]});
setDefaultSetting("activeTo", {"selected":[6],"values":[{"name":"6 PM","value":18}]});
  
function setDefaultSetting(key, value) {
  let extantValue = settingsStorage.getItem(key);
  if (extantValue === null) settingsStorage.setItem(key, JSON.stringify(value));
}

 

Peter McLennan
Gondwana Software

View best answer in original post

Best Answer
0 Votes
19 REPLIES 19

A way to do it is to initialise the settings in companion/index.js.

 

You can find out what values work by inspecting the values that get stored by the system when the settings UI is used to specify a value.

Peter McLennan
Gondwana Software
Best Answer
0 Votes

@Gondwana

Yes. And that is exactly what I'm trying to do. What I don't know, however, is the code I need to use to make it happen.

 

I thought maybe something like settingsStorage.setItem("bSteps") = true; might work, but it gives me a scary error message on build and I think that setItem doesn't even exist. I don't believesettingsStorage.initialize exists either.

 

I know what values I want to set and I know what I want to set them to. I just need the code to do it.

 

My code in companion/index.js looks something like this:

 

import { settingsStorage } from "settings";
let defaultSettings = { bSteps: true, bHRM: false, bDigiTime: false, bAMPM: false, bBattery: true, bDate: false, bTemp: false, bImperial: true, selWeather: 0 }

function sendSettingData(data) {
if (messaging.peerSocket.readyState === messaging.peerSocket.OPEN) {
messaging.peerSocket.send(data);
}
}

// Message socket opens
messaging.peerSocket.onopen = () => {
console.log("Companion Socket Open");
};

// Message socket closes
messaging.peerSocket.onclose = () => {
console.log("Companion Socket Closed");
};

//A user changes settings
settingsStorage.onchange = evt => {
if (evt.oldValue !== evt.newValue) {
let data = {
key: evt.key,
newValue: JSON.parse(evt.newValue)
};
sendVal(data);
}
};

// Listen for the onerror event
messaging.peerSocket.onerror = function(err) {
console.log("Connection error: " + err.code + " - " + err.message);
}

 

Best Answer
0 Votes

Unfortunately, I'm between computers ATM, and it seems I've never had to do this with toggles. However, I think you may need to call setItem() passing the setting value as a JSON string. Here's something I cooked earlier that works with lists; you'll have to adapt it to work with toggles, of course...

// Initialise settings to default values:
if (locale.language === "en-US")
  setDefaultSetting("dateFormat", {"selected":[1],"values":[{"name":"Dec 25","value":1}]});
else
  setDefaultSetting("dateFormat", {"selected":[0],"values":[{"name":"25 Dec","value":0}]});
setDefaultSetting("distMeasure", {"selected":[0],"values":[{"name":"Steps","value":0}]});
setDefaultSetting("activeFrom", {"selected":[6],"values":[{"name":"6 AM","value":6}]});
setDefaultSetting("activeTo", {"selected":[6],"values":[{"name":"6 PM","value":18}]});
  
function setDefaultSetting(key, value) {
  let extantValue = settingsStorage.getItem(key);
  if (extantValue === null) settingsStorage.setItem(key, JSON.stringify(value));
}

 

Peter McLennan
Gondwana Software
Best Answer
0 Votes

Hi,

 

Did you ever use setItem to set a colour value?

 

I want to be able to select one of the colours in the list when the companion app starts.

I am using the code below to try and find what works when, as far as setting values in the settings UI at run-time goes.

 

// These 2 work
// toggle
settingsStorage.setItem('tglPaintHourNumbers', 'true'); // selectbox
settingsStorage.setItem('selShowAt0', JSON.stringify({ selected: [4] })); // These don't. All the 'clr*' properties are colour-selectors
// I want to select the 3rd option in the selectbox (or colour #FFFFFF) settingsStorage.setItem('clrHourNumbersColour', JSON.stringify({ selected: [3] })); settingsStorage.setItem('clrHourColour', JSON.stringify({ selected: ['#FFFFFF"'] })); settingsStorage.setItem('clrMinColour', JSON.stringify({ color: 3 })); settingsStorage.setItem('clrSecColour', JSON.stringify({ color: '#FFFFFF"' }));

 

Cheers,

Nick

Best Answer

I think the best general approach is to do a getItem() and inspect what comes back when the user selects what you want as a default. Pass that same data to setItem() to initialise a default. (It seems that you can leave out some attributes, but I never bothered exploring this.)

Peter McLennan
Gondwana Software
Best Answer
0 Votes

Thanks for the quick reply!

 

I tried the following

let cc = settingsStorage.getItem('clrHourNumbersColour');
console.log(cc) ;  // the result was '#FFCCCC'
// so I then did
settingsStorage.setItem('clrHourNumbersColour', '#FFCCCC');

 

Alas, it caused the following error

[12:38:59]SyntaxError: Unexpected token # in JSON at position 0
[12:38:59]Uncaught SyntaxError: Unexpected token # in JSON at position 0
 
It does not like receiving a string as a colour value.
It looks like it wants an object but I can't figure out the structure.
Best Answer
0 Votes

What type of component are you using in your .jsx? ColorSelect?

Peter McLennan
Gondwana Software
Best Answer
0 Votes

 

 

 

let handColours = [
{color: "#FFCCCC"},
{color: "#FF7F7F"},
{color: "#FF0000"},
{color: "#CC0000"},
{color: "#990000"},
{color: "#00A629"},

-snip-

{color: "#FF009E"},
{color: "#FFF8DC"},
{color: "#A9A9A9"},
{color: "#696969"},
{color: "#DCDCDC"},
{color: "#000000"}
];
...
...
...
<Section title={<Text bold align="center">Hour numbers colour</Text>}> <ColorSelect settingsKey="clrHourNumbersColour" colors={handColours} /> </Section>

 

Best Answer
0 Votes

Found it!

settingsStorage.setItem('clrSecColour',         JSON.stringify(   '#FFCCCC'  ));

instead of 

settingsStorage.setItem('clrSecColour',       '#FFCCCC' );

 

So the total info I now have on this is

// toggle
settingsStorage.setItem('tglPaintHourNumbers', 'true');
// selectbox (select 5th entry) settingsStorage.setItem('selShowAt0', JSON.stringify({ selected: [4] })); // colour selector settingsStorage.setItem('clrSecColour', JSON.stringify( '#FFCCCC' ));

 

 

Best Answer

Well done! I was going to guess that, but thought I should test it first. 🙂

Peter McLennan
Gondwana Software
Best Answer
0 Votes

Thanks for helping out!

I hope this will save someone else the trouble of banging his head against the wall.

Best Answer
0 Votes

Sorry to revive a very old thread, but I'm trying to do something similar and I am having issues.

 

I tried to use settingsStorage.getItem() and .setItem() inside my companion class, in order to check if a value is set and if it isn't set, set a default. But I keep getting exceptions when I try to access settingsStorage object methods.

 

Error: ENOENT: no such file or directory, open '/Users/f92a4nu/Library/Application Support/Fitbit OS Simulator/mira/companion/app_dec65d47-e3a2-4e98-8610-7cef3e65bd78/settingsstorage/kanjiColourGradient

 

When I just try to set the item, this happens when I first install the app, though the default value does seem to be set, and if I run the app again I won't get the same exception for that config. When I try this with multiple configs, it seems I have to run it again for each config to clear them one by one.

If I try to get the item first to check before setting, then the exception prevents the item from being set, so the default settings never work.

 

I have also tried to write a config file with default settings but that doesn't seem to work when my app loads its settings. 

 

I'm curious where the settingsStorage.setItem() should be called from, since it gives an exception when called from the companion/index.js file.

Best Answer
0 Votes

settingsStorage.setItem() etc definitely works in companion/index.js, assuming you've imported settingsStorage.

In some cases, I've found it necessary to set defaults in settings/index.jsx, because sometimes the jsx starts before companion/index.js. It's accessible via the argument passed to settingsComponent().

I note that your error message has incorrect capitalisation of settingsStorage; that may be significant (or not).

Peter McLennan
Gondwana Software
Best Answer
0 Votes

If I uninstall the app from the simulator and then run it again, it gives exceptions initially when I use settingsStorage.setItem() or getItem(). This was on a Mac. I just tried it again on my PC and while I did see the same error yesterday, now it seems to be working. No idea why, won't be surprised if it stops working again later.

 

For reference, here is my companion/index.js

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

if (settingsStorage.getItem('kanjiColourGradient') == null) {
  settingsStorage.setItem('kanjiColourGradient', 'true');
}
if (settingsStorage.getItem('clockColor') == null) {
  settingsStorage.setItem('clockColor', JSON.stringify('#68FC68'));
}
if (settingsStorage.getItem('stepsColor') == null) {
  settingsStorage.setItem('stepsColor', JSON.stringify('#FFFF00'));
}

// 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) {
  console.log("send value")
  if (!key || !val) {
    return;
  };
  
  sendSettingData({
    key: key,
    value: JSON.parse(val)
  });
}

// Send JSON object
function sendSettingData(data) {
  console.log("send settings data")
  if (messaging.peerSocket.readyState === messaging.peerSocket.OPEN) {
    messaging.peerSocket.send(data);
  } else {
    console.log("No peerSocket connection");
  }
}

 

I'm curious how you set default values in the settings/index.jsx. Would "props" in the code below be the argument you are referring to? Could you give an example of how you use it?

function SettingsPage(props) {
  return (
    <Page>
      ...
    </Page>
  );
}
registerSettingsPage(SettingsPage);

 

Best Answer

I should clarify what I mean when I say it's working. The companion app seems to show the expected default settings, but the clockface doesn't show the expected colour, it seems setting the default values doesn't make those values get written to a config file. I still have to manually change a setting for it to be rendered in the clock face.

Best Answer
0 Votes

props.settingsStorage.getItem(...), etc (of the top of my head).

 

It's up to you to send settings from companion to watch. It doesn't happen automatically. To avoid latency, I ensure that the watch's initial state (colours, etc) matches the default settings. Duplication. 😞

Peter McLennan
Gondwana Software
Best Answer

Thanks, I'll have a look at the settings/index.jsx and see if I can make something work there.

 

To clarify, when I change a setting manually in the companion settings app, it does get sent to the watch and the UI is updated and config is saved to file and reused later.

But in the companion app when I set a default value, this is reflected in the companion app but not the clockface. I have tried saving config to a file but had problems with imports. Not sure I can write a config file directly in the companion app, and I also thought about manually triggering an onchange event but haven't been able to do that yet either.

Best Answer
0 Votes

I think the onchange event only occurs when something changes in the .jsx. If you're changing values in .js code, you'll probably have to explicitly call the send-to-watch code you've written.

 

Even then, there will be a small delay before the watch receives those initial settings. That's why I'd get the watch to default to those of its own accord. It also spares you from having to do that initial transfer.

Peter McLennan
Gondwana Software
Best Answer
0 Votes

Yeah, I tried calling the sendValue() method after setItem() in the companion app, but never saw any change to the UI, it always just stayed with the default colour, which I had already set manually in the clock face before even trying to set default config values.

 

My main issue is just getting default values to be shown as selected in the companion app. Especially for toggles, I don't want features that are enabled by default to appear as toggled off in the settings.

 

Anyway, setting the value in the settings/index.jsx seems to be working well now!

function SettingsPage(props) {
  if(props.settingsStorage.getItem("clockColor") == null) {
    props.settingsStorage.setItem('clockColor', JSON.stringify('#68FC68'));
  }
  return (
    <Page>
      <Section
        title={<Text bold align="center">CHANGE CLOCK COLOR</Text>}>
        <ColorSelect
          settingsKey="clockColor"
          colors={colorSet}
        />
      </Section>
      ...
    </Page>
  );
}

 As I was already setting default colour in the clock, this works perfectly, but when testing I did see the delayed update you mentioned, so yeah, worth noting for anyone not already setting a default value in the clock code.

 

Thanks for helping with this! Much appreciated!

Best Answer