Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Respect time format system-wide #370

Closed
wants to merge 1 commit into from

Conversation

Raupinger
Copy link
Contributor

@Raupinger Raupinger commented May 19, 2021

added a function in DateTime to give a correctly formatted time. It is used by tiles and quick settings. fixes #368

@JF002
Copy link
Collaborator

JF002 commented Jul 24, 2021

Thanks for this PR! We indeed need to make the time formatting more consistent across the application and to remove code duplication across multiple Screens and Watchfaces.

However, in previous PR, we tried to remove most of the call the sprintf and to replace them by lv_label_set_text(). This allows more readable code, and less intermediate variables.

While your code probably works fine, I would like to see if we can find a better way to do it. With these changes, every time we want to generate the time string, we need to instantiate a char array of 9 chars. If a developer instantiates a smaller array, memory will be corrupted. If they create a bigger array, memory will be wasted. Can we try to find a way to encapsulate the string formatting a bit more?

@jonvmey
Copy link
Contributor

jonvmey commented Jul 24, 2021

Maybe just return a std::string? The returned string might even be small enough to fit within small string optimization limits (not sure what they are on 32-bit ARM).

Comment on lines +123 to +145
sprintf(minutesChar, "%02d", static_cast<int>(minute));
char hoursChar[3];
char ampmChar[3] = " ";
if (is24h) {
sprintf(hoursChar, "%02d", hour);
} else {
if (hour == 0) {
hour = 12;
sprintf(ampmChar, "AM");
} else if (hour < 12) {
sprintf(ampmChar, "AM");
} else if (hour >= 12) {
hour = hour - 12;
sprintf(ampmChar, "PM");
}
sprintf(hoursChar, "%02d", hour);
if (hoursChar[0] == '0') {
hoursChar[0] = ' ';
}
}

sprintf(string, "%c%c:%c%c %c%c", hoursChar[0], hoursChar[1], minutesChar[0], minutesChar[1], ampmChar[0], ampmChar[1]);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can be reduced down to:

if (is24h) {
  sprintf(string, "%02u:%02u   ", hour, minute);
} else {
  char const* const ampmStr = hour < 12 ? "AM" : "PM;
  
  auto tempHour = hour;
  if (tempHour == 0) {
    tempHour = 12;
  } else if (tempHour > 12) {
    tempHour -= 12;
  }

  sprintf(string, "%2u:%02u %s", tempHour, minute, ampmStr);
}

} else {
if (hour == 0) {
hour = 12;
Copy link
Contributor

@jonvmey jonvmey Jul 24, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a bug. This code was moved from elsewhere in the code where hour was a local variable. Here it's a member of DateTime so modifying it here actually changes the time other parts of the code see.

"--", "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"};

void DateTime::GetTimeStr(char* string, bool is24h) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a personal preference but I dislike using a bool as a stand-in for a two state enum. Making the second argument a ClockType instead would be better IMO. This would actually make the calling code simpler too since they all end up doing a comparison like someClockTypeVariable == ClockType::H24 now anyways.

@Raupinger
Copy link
Contributor Author

Thanks for this PR! We indeed need to make the time formatting more consistent across the application and to remove code duplication across multiple Screens and Watchfaces.

I thought about this recently and would also like to have the Bluetooth/charging icon display consistently between all screens. Plus I would like a little preview of the timer and stopwatch when active.

The idea I had come up with is to create a component to manage this "top bar". The component holds a 12 char cstring. Any screen who wants to use that gets that pointer and calls lv_label_set_text_static() with it. Then it has to call an update method on the component every refresh. (or not, currently the time isn't getting refreshed either)

This has the benefit of further unifying things and being able to statically allocate that memory. Its not very flexible though. I imagine there would have to be a method to toggle the time display so its not included in a watch face, but there wouldn't be super fine grain control.

I suggest we close this and I make a new PR for that bar controller.

@Riksu9000
Copy link
Contributor

Having a top bar component is a good idea, and having more icons, but the top bar could just use this function for time, so this PR doesn't need to be closed.

The component holds a 12 char cstring. Any screen who wants to use that gets that pointer and calls lv_label_set_text_static() with it.

If we did this, we wouldn't be able to have the time on the left and icons on the right right?

currently the time isn't getting refreshed either

It is getting refreshed by an LVGL task every 5s currently, which we could just keep using.

I imagine there would have to be a method to toggle the time display so its not included in a watch face

I don't think the watch faces shouldn't use the bar anyway. Only the digital watch face might slightly benefit from this, but I don't think it's worth the extra complication.

Also about this implementation. Maybe in the DateTime class there should be a char array, and when we run GetTimeStr(), it checks if the array needs to be updated, updates it if necessary, and finally returns a pointer to it.

@JF002
Copy link
Collaborator

JF002 commented Jul 25, 2021

The top bar is a good idea! Maybe you can have a look at the top layer provided by LVGL, it might be useful to implement it.

Also about this implementation. Maybe in the DateTime class there should be a char array, and when we run GetTimeStr(), it checks if the array needs to be updated, updates it if necessary, and finally returns a pointer to it.

Maybe we can split the DateTime class in 2 parts : the one that knows what time it is (based on a timepoint) and another one, closer to the UI, that converts the timepoint into a human readable string (and caches the last string to ensure it's refreshed only when needed). This way, we keep a clear separation between the DateTime component and the UI.

I suggest we close this and I make a new PR for that bar controller.

It's up to you! Right now, this PR makes sense, and you can finish it so that your work is not lost and you can still implement the top bar in a new PR.

@JF002 JF002 added this to the Version 1.4 milestone Jul 28, 2021
@JF002
Copy link
Collaborator

JF002 commented Jul 28, 2021

I've just added this PR to the next milestone so that I know I'm reviewing it. Tell me if you want to close it to open a new one ;)

@Raupinger
Copy link
Contributor Author

I think ill finish this one up. Should also get to work on it now since my exams are over.

@geekbozu
Copy link
Member

geekbozu commented Sep 1, 2021

Where did this leave off? I know @JF002 is wanting to finish up 1.4....

@JF002 JF002 removed this from the Version 1.4 milestone Sep 2, 2021
@JF002
Copy link
Collaborator

JF002 commented Sep 3, 2021

Where did this leave off? I know @JF002 is wanting to finish up 1.4....

I released without this feature, but I'll gladly review and merge it once it's finished :)

@Avamander
Copy link
Collaborator

Can you please rebase/fix conflicts with this and address jonvmey's comments?

@trman
Copy link

trman commented Feb 21, 2022

this one should be closed since it have been resolved, unless i'm wrong @Avamander or @JF002 @Riksu9000 ?
resolved by #907 and #927 pr , maybe?

@Riksu9000
Copy link
Contributor

This has been implemented in #821

@Riksu9000 Riksu9000 closed this Feb 21, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Time format on Quick Actions screen does not honor Time Format setting
7 participants