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

Add an option to invalidate the quest cache #706

Merged
merged 8 commits into from
Jan 7, 2018

Conversation

ENT8R
Copy link
Contributor

@ENT8R ENT8R commented Nov 23, 2017

This PR adds an option in the settings to easily delete all saved quests without needing to wipe the whole data of the app. This PR fixes #300

@ENT8R
Copy link
Contributor Author

ENT8R commented Nov 23, 2017

Currently there is no confirmation dialog if the user clicks on the button (maybe even accidentally). Do you think that this should be added?

@ghost
Copy link

ghost commented Nov 23, 2017

It can be bothersome to reload all of it if you have a slow or no connection at the moment. If it's not too much work it may be a good idea :)

@westnordost
Copy link
Member

Oh no, I think there has been a misunderstanding. The user should never have the option to delete all quests. Just the cache should be invalidated. More information in the comments below.

@ENT8R
Copy link
Contributor Author

ENT8R commented Nov 23, 2017

Oops...

{
SQLiteDatabase db = dbHelper.getReadableDatabase();
db.execSQL("DELETE FROM " + getTableName());
}
Copy link
Member

Choose a reason for hiding this comment

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

So this, by the way, also deletes to-be-uploaded quests, reverted quests, ... everything.

android:key="quests.deletion"
android:title="@string/pref_title_quests_deletion"
android:summary="@string/pref_title_quests_deletion_summary"
android:widgetLayout="@layout/widget_image_delete"
Copy link
Member

Choose a reason for hiding this comment

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

I misuse the widget layout in some cases only to signal that something is a subpage or that something leads out of this app (into a browser). It should not be used to generally display an icon.

@ENT8R
Copy link
Contributor Author

ENT8R commented Nov 23, 2017

So I will close this for the first time

@ENT8R ENT8R closed this Nov 23, 2017
@westnordost
Copy link
Member

westnordost commented Nov 23, 2017

So the option in the settings should be called "Invalidate Quest Cache" and what it should do is to clear the downloaded tiles table only.

To clarify for the user, a message like the following should be shown:
"Invalidating the cache causes the quests to be updated next time they are downloaded each.

The quest cache is invalidated automatically after one week and immediately when a quest you solved turns out to be already answered by someone else."

Optionally, the dialog could also ask whether to clear the cache just here (in the tile the user is looking at) or everywhere because I think for most users, the former is what they actually want to do.

@ENT8R
Copy link
Contributor Author

ENT8R commented Nov 23, 2017

I'm sorry, this is maybe a dumb question, but how do I get the current shown tile (to be more precise: the Point I have to pass as an argument to remove(Point tile) in DownloadedTilesDao.java)

@westnordost
Copy link
Member

It needs to be calculated from a LatLon:

SlippyMapMath.enclosingTile(current position as lat lon, ApplicationConstants.QUEST_TILE_ZOOM)

Now, getting that LatLon is the hard(er) part. Hint: MapFragment saves the current LatLon into SharedPreferences on onPause().

But this is all optional, you don't need to do it.

@ENT8R
Copy link
Contributor Author

ENT8R commented Nov 23, 2017

Oh great thank you! I think this will help me a lot!

@ENT8R
Copy link
Contributor Author

ENT8R commented Nov 24, 2017

Now I updated the code to fit your proposals. There is now the option in the settings to either invalidate all quests in the currently shown tile or just invalidate all known tiles.
It looks like this:

@ENT8R ENT8R reopened this Nov 24, 2017
@rugk
Copy link
Contributor

rugk commented Nov 24, 2017

"Shown tile" the "shown" is unnecessary IMHO.
And "cancel" should be at the bottom, that is just what I as a user would expect.

@westnordost
Copy link
Member

westnordost commented Nov 24, 2017

Not sure if the subtitle of the Invalidate Quest Cache is necessary. I do not want to put more text than necessary there. Opinions?

Also, could you split the text into paragraphs, like I did in my comment?

Finally, I wouldn't introduce the term "tile" to the user here, is is not introduced to the user anywhere and basically is just a technical detail.
An idea: Add a title - "Where to invalidate the cache?", the answer options are then "Here", "Everywhere" (and "Cancel")

@ENT8R
Copy link
Contributor Author

ENT8R commented Nov 24, 2017

And "cancel" should be at the bottom

I have no idea how to change the order of the buttons...

@@ -70,6 +70,12 @@ public int remove(Point tile)
DownloadedTilesTable.Columns.Y + " = ?", whereArgs);
}

public void removeAll()
{
SQLiteDatabase db = dbHelper.getReadableDatabase();
Copy link
Member

Choose a reason for hiding this comment

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

getWritableDatabase

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@@ -559,7 +560,7 @@ private void saveMapState()
{
if(controller == null) return;

SharedPreferences.Editor editor = getActivity().getPreferences(Activity.MODE_PRIVATE).edit();
SharedPreferences.Editor editor = getActivity().getSharedPreferences(PREF_NAME, Activity.MODE_PRIVATE).edit();
Copy link
Member

Choose a reason for hiding this comment

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

Ah ok,... that's the caveat. Hmm, it's a but ugly that other activities access the preferences of the map this way. But I don't have an idea right now to have a cleaner interface there.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Mmh... me too...

@@ -57,6 +96,21 @@ public void onStart()
getActivity().setTitle(R.string.action_settings);
}

private Point getShownTile()
{
SharedPreferences preferences = getActivity().getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE);
Copy link
Member

@westnordost westnordost Nov 24, 2017

Choose a reason for hiding this comment

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

I'd prefer to have the static const here fully qualified, i.e. MapFragment.PREF_NAME etc. because this is the SettingsFragment, everything is settings and prefernces here. It is necessary to know the context of any such preference/settings.

LngLat pos = new LngLat(
Double.longBitsToDouble(preferences.getLong(PREF_LON,0)),
Double.longBitsToDouble(preferences.getLong(PREF_LAT,0))
);
Copy link
Member

Choose a reason for hiding this comment

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

You create a LngLat here, and then convert the LngLat to a LatLon. Why not simply create a LatLon in the first place? (The default implementation of that interface is OsmLatLon)

} else
{
Toast.makeText(getContext(), R.string.invalidation_error, Toast.LENGTH_SHORT).show();
}
Copy link
Member

@westnordost westnordost Nov 24, 2017

Choose a reason for hiding this comment

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

Please leave out the success and error messages. This will only confuse the users. Instead, just check if getShownTile() is null before building the dialog and only add that answer option ("Only this tile") if the current shown tile can be determined.

Or, optionally, if possible, show that option but disable it.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

But if the invalidation succeeded, there should really be no success message?

@westnordost
Copy link
Member

An idea: Add a title - "Where to invalidate the cache?", the answer options are then "Here", "Everywhere" (and "Cancel")

Or, "Invalidate the cache?" - "Only here" - "Everywhere"

@westnordost
Copy link
Member

The location of the positive - negative - cancel buttons is predefined by the Android system. Do not attempt to change it.

@ENT8R
Copy link
Contributor Author

ENT8R commented Nov 24, 2017

This is how it looks now:

@westnordost
Copy link
Member

westnordost commented Nov 24, 2017 via email

@westnordost
Copy link
Member

westnordost commented Nov 24, 2017 via email

@ENT8R
Copy link
Contributor Author

ENT8R commented Nov 24, 2017

Oh, that's a bug then!

Should I fix it too?

@westnordost
Copy link
Member

westnordost commented Nov 24, 2017 via email

@rugk
Copy link
Contributor

rugk commented Nov 24, 2017

Okay, but what does "Here" mean? I thought one selection clears the "map/tile cache" (maybe call it "map cache" to avoid the term "tile") and when choosing "everywhere" it invalidates the quest cache and the map cache.

@ENT8R
Copy link
Contributor Author

ENT8R commented Nov 24, 2017

Mmhh... The intention behind this is that the user can redownload the quests in a specific tile (or even on the whole map), if he thinks that some of the quests are outdated, after clicking on one of the two buttons.

The app knows where it downloaded quests already and where not. This information is stored in a database (downloaded_tiles). If the user wants to invalidate the quests through the settings, this database is either completely cleared or only a specific area (tile) gets deleted. If the user now scans again for quests in this specific area, all quests in this area are redownloaded, because StreetComplete thinks that it has not scanned yet there for new quests.

It's not intented for clearing the map cache...

@rugk
Copy link
Contributor

rugk commented Nov 24, 2017

Ah so "here" makes sense.
It could only be a bit confusing as the last screen the user sees is the settings screen, so one does not immediately associate "here" with the current map position. If you see what I mean…

"In this area" would maybe be a bit more explicit/specific, but I admit that it may be too long.

@westnordost
Copy link
Member

westnordost commented Nov 24, 2017

Hmm, yeah, actually...

I think, @rugk ist right.

You know, I have had to explain the mechanism with quest cache invalidation to various people what seemed to me a dozen times already. I had hoped that the implementation of such a "flush cache" button would bring this thing to a close (also using the confirmation message box to shortly explain the mechanism) but it seems the separation of "clear cache here" and "clear cache everywhere" is overengineered, in, that it actually adds to the confusion:
Not only the thing about "what is here?". Additionally, I came to remember that the user does not know how big the "here" is. The enclosing tile of any position might be something like 1km² (I think), but the position itself might be on the edge of that tile. Meaning, that he might be very close to an area where the cache has not been cleared. And that will confuse the user because he thinks, "well, didn't I just clear the cache here? Why isn't this working?!"

Finally, I think it is not too necessary to have the user have such a finegrained control over where to clear the cache because after one week only, all his freshly downloaded quests will be invalidated anyway. Not deleted, just invalidated.
So, if he pre-downloaded some area where he plans to go on vacation in the next few weeks, even though the quests are by then already invalidated, he can still solve them as normal.

All in all, my conclusion is to remove that "clear cache only here" option again. There is too little gain for the added complexity and confusion.

Sorry about my idée fixe, first letting you implement this and then deciding otherwise. To accommodate, I can offer to remove these parts myself so you do not have to do that.

@ENT8R
Copy link
Contributor Author

ENT8R commented Nov 24, 2017

No problem! I will do this tomorrow 😀

@ENT8R ENT8R changed the title Add an option to delete the quest cache Add an option to invalidate the quest cache Nov 25, 2017
@ENT8R
Copy link
Contributor Author

ENT8R commented Nov 25, 2017

All in all, my conclusion is to remove that "clear cache only here" option again

This is removed now

.setPositiveButton(R.string.invalidate_confirmation, (dialog, which) -> {
downloadedTilesDao.removeAll();
})
.setNegativeButton(android.R.string.cancel, (dialog, which) -> {})
Copy link
Member

Choose a reason for hiding this comment

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

(dialog, which) -> {} can be null, by the way.

@westnordost
Copy link
Member

Looks good!

Note that I will merge this into v4, as it contains both new strings and, well, is a new feature. (I will be not available the whole December to fix possible bugs, so I am very cautious right now).

@ENT8R
Copy link
Contributor Author

ENT8R commented Nov 25, 2017

That's fine!

@westnordost
Copy link
Member

This github resolve conflict editor does not seem to work.

@westnordost westnordost merged commit e58b5ec into streetcomplete:master Jan 7, 2018
@ENT8R ENT8R deleted the flush-quest-cache branch January 14, 2018 14:53
@pietervdvn
Copy link

Awesome! You guys rock a lot!

I really appreciate the app and all the effort you are putting into it!

@westnordost
Copy link
Member

westnordost commented Feb 8, 2018 via email

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.

Flush quest cache button
4 participants