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

Update timezone to update if user has it set to automatic #2318

Merged
merged 6 commits into from
Apr 12, 2021

Conversation

NikkiWines
Copy link
Contributor

@NikkiWines NikkiWines commented Apr 8, 2021

cc: @iwiznia

Details

Fixed Issues

Fixes https://expensify.slack.com/archives/C01GTK53T8Q/p1617920244466600?thread_ts=1617784393.408700&cid=C01GTK53T8Q

Tests

  1. Open your developer console (opt + cmd + j for chrome) and go to the Sources tab
  2. Set a breakpoint at if (_.isObject(timezone) && timezone.automatic && timezone.selected !== currentTimezone) { in AuthScreens.js
Video to set breakpoint
Untitled.mov
  1. Reload the page
  2. When the point stops at the debugger, manually update your timezone by running the following in the console
timezone = {automatic: true, selected: "Africa/Tripoli"};
  1. Continue execution
  2. Navigate to the Application tab the developer console, click on the value under Local Storage on the left hand side.
Video to find personalDetails
navToPersonalDetails.mov
  1. Search for myPersonalDetails, and click on the value.
  2. Confirm it's update to your current timezone.

QA Steps

Repeat test steps (Web only QA)

Tested On

  • Web
  • Mobile Web
  • Desktop
  • iOS
  • Android

Screenshots

N/A no UI changes.

@NikkiWines NikkiWines self-assigned this Apr 8, 2021
@NikkiWines NikkiWines requested a review from a team as a code owner April 8, 2021 23:35
@MelvinBot MelvinBot requested review from thienlnam and removed request for a team April 8, 2021 23:35
src/libs/Navigation/AppNavigator/AuthScreens.js Outdated Show resolved Hide resolved
@@ -56,11 +60,13 @@ const modalScreenListeners = {

const propTypes = {
network: PropTypes.shape({isOffline: PropTypes.bool}),
myPersonalDetails: PropTypes.objectOf(personalDetailsPropType),
Copy link
Contributor

Choose a reason for hiding this comment

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

this prop is never passed in and will always be a default prop right? In that case, should we just modify it in componentDidMount?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ahh this is a good point, I think maybe this logic is better suited to personalDetails.js

@@ -87,6 +88,11 @@ function formatPersonalDetails(personalDetailsList) {
const pronouns = lodashGet(personalDetailsResponse, 'pronouns', '');
const timezone = lodashGet(personalDetailsResponse, 'timeZone', CONST.DEFAULT_TIME_ZONE);

// Update the users timezone if they have it set to automatic
if (login === currentUserEmail && _.isObject(timezone) && timezone.automatic) {
Copy link
Contributor

Choose a reason for hiding this comment

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

This is not really updating the NVP, IMO it should update the NVP. Also, it feels a bit weird that we are doing this logic here... we will be guessing the timezone all the time we format your details? Doesn't it make more sense to do this once on app init?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Oh, yeah good point, I should make sure I sent the NVP as well.

Copy link
Contributor Author

@NikkiWines NikkiWines Apr 9, 2021

Choose a reason for hiding this comment

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

As for doing it all the time, we only call personalDetails.fetch() in Authscreens.js in two places. Once on init, and then every 30 min to update the details as necessary. Since we want this to be automatic, I don't see an issue with it running every 30 min, but maybe I am too lenient.

Copy link
Contributor

Choose a reason for hiding this comment

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

I don't know, feels weird to me that we do this here... you call formatPersonalDetails and all of a sudden an NVP is set... it's weird.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah, I can understand that - you wouldn't expect a function called formatXYZ to set any values. I could move this logic into it's own function and call it in fetch() which isn't much better, but makes a little more sense since the value from the DB might be outdated if the user has moved to a new timezone.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That's where I had it before, but there were issues because we don't necessarily have the personalDetails at that point. I suppose we could make PersonalDetails.fetch() return a promise and when that resolves run the logic for updating the timezone if it's set to automatic.

Copy link
Contributor

Choose a reason for hiding this comment

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

I think we should not use the personal details at all there, just get the NVP from your own account.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Hmm, I think that'll potentially cause some issues since we are already fetching personalDetails (which contains the timezone) here. We'd need to be sure that the myPersonalDetails and personalDetails onyx keys are updated correctly after we modify the timezone.

Based on your suggestion, I think we'd end up doing something like this in AuthScreens.js (adding some small modifications to NameValuePairs.get as well).

NameValuePair.get(CONST.NVP.TIMEZONE, CONST.DEFAULT_TIMEZONE)
    .then((value) => {
        const timezone = value;
        if (timezone.automatic) {
            timezone.selected = moment.tz.guess(true);
            NameValuePair.set(CONST.NVP.TIMEZONE, timezone);
            PersonalDetails.fetch();
        }
    });

Is that along the lines of what you were thinking?

Copy link
Contributor

Choose a reason for hiding this comment

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

No, not really since actions should not return a promise, you need to subscribe to the onyx key, no?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ok, chatted 1:1 and I messed around with this a bit. Works now!

iwiznia
iwiznia previously approved these changes Apr 9, 2021
Copy link
Contributor

@thienlnam thienlnam left a comment

Choose a reason for hiding this comment

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

Looks good! I like that now it only updates if it doesn't match the current timezone. I just had a small comment

src/libs/Navigation/AppNavigator/AuthScreens.js Outdated Show resolved Hide resolved
@NikkiWines
Copy link
Contributor Author

updated!

Copy link
Contributor

@thienlnam thienlnam left a comment

Choose a reason for hiding this comment

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

Thanks! LGTM

@thienlnam thienlnam merged commit 0874880 into master Apr 12, 2021
@thienlnam thienlnam deleted the nikki-automatic-timezone branch April 12, 2021 16:39
Comment on lines +47 to +61
Onyx.connect({
key: ONYXKEYS.MY_PERSONAL_DETAILS,
callback: (val) => {
const timezone = lodashGet(val, 'timezone', {});
const currentTimezone = moment.tz.guess(true);

// If the current timezone is different than the user's timezone, and their timezone is set to automatic
// then update their timezone.
if (_.isObject(timezone) && timezone.automatic && timezone.selected !== currentTimezone) {
timezone.selected = currentTimezone;
PersonalDetails.setPersonalDetails({timezone});
}
},
});

Copy link
Contributor

@kidroca kidroca Apr 13, 2021

Choose a reason for hiding this comment

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

Why is this block defined here?

The code here would run as soon as this file is imported and it's not related to the actual AtuhScreens component lifecycle (E.g. the subscription would happen even before you login and AtuhScreens are rendered)

It could have been added to PersonalDetails along with the existing static Onix.connect calls there?

https://github.com/Expensify/Expensify.cash/blob/9b0938441611f90ed8611513954258227dabbd35/src/libs/actions/PersonalDetails.js#L13-L23

I noticed this while resolving a merge conflict in AtuhScreens in #2346

Copy link
Contributor Author

@NikkiWines NikkiWines Apr 13, 2021

Choose a reason for hiding this comment

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

There is a larger conversation here about the reasoning for moving this logic to AuthScreens.js.

Copy link
Contributor

Choose a reason for hiding this comment

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

The linked conversations is about setting the timezone should not be a side effect of the format function and should be moved out of it.

Ok it was moved out but you can literally copy this whole block, put it anywhere and it will still work

https://github.com/Expensify/Expensify.cash/blob/87c3b3dbf5045b196eacf2d89554a3cd2d74586f/src/libs/Navigation/AppNavigator/AuthScreens.js#L47-L60

I just don't get why it's in AuthScreens it's not related to anything in this file.

That's why I suggested that it can be housed in PersonalDetails below the other Onyx.connect calls there

Copy link
Contributor

Choose a reason for hiding this comment

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

Oh, that's a good point. It indeed can be anywhere. I am fine with putting it in the PersonalDetails file

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ah, I see. Yeah, it could be in PersonalDetails.js. @kidroca if you feel strongly about it you can modify it in your PR (or a future PR), or I will modify it in my next E.cash change.

Copy link
Contributor

Choose a reason for hiding this comment

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

I could, but then git would annotate me as the author of the code, while I don't know how it actually works. It would be best if the author (or at least someone involved in this) moves it

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.

4 participants