Editor refactoring #9242

Merged
root merged 1 commit from editor_refactoring into master 2025-01-31 20:46:04 +00:00
Contributor

fixes #9129, fixes #8102, fixes #2298, fixes #6260, fixes #6292, fixes #9126, fixes #6939, fixes #9508, fixes #9311

This PR supersedes #9138 and adds a Journal to explicitly store which changes were submitted by the user. See #9129 for why his information is needed when uploading to OSM.

Approach

Edits are logged in the Journal. A log contains info like e.g. Tag "website" changed from "www.organicmaps.app" to "organicmaps.app" or ObjectCreated, Type amenity-bench, Location .... When uploading, only the Journal entries are used do update the OSM object. After a successful upload, the Journal is cleared.

Saving and restoring the Journal after an app restart is implemented now.

For the transition phase to the new editing logic the old uploading code is still functional. The old code is used when the object was modified in a previous OM version.

Todo

  • Logging
    • Add logging for all Tags
    • Add logging for FeatureType
    • Safe and Restore Data after App restart
  • New uploading logic
  • Transition from old OM versions

Bugs fixed

Testing

Tested with the OSM dev API, but only on Android.

Transition

The PR only affects new edits. Old edits from previous OM versions that were not uploaded yet use the old uploading code.

New features I keep in mind to not block anything

  • Adding "komplex" Category types (#4523)
  • Mark POI as disused
  • POI category change (#3491)
  • Add address POIs (#9199)
  • Support editing POIs mapped as areas (#6727)

Follow up issues (Issues not addressed in this PR)

  • #9043
  • #9503
  • Remove code of the old editor after some time (e.g. three months)
fixes #9129, fixes #8102, fixes #2298, fixes #6260, fixes #6292, fixes #9126, fixes #6939, fixes #9508, fixes #9311 This PR supersedes #9138 and adds a Journal to explicitly store which changes were submitted by the user. See #9129 for why his information is needed when uploading to OSM. #### Approach Edits are logged in the Journal. A log contains info like e.g. `Tag "website" changed from "www.organicmaps.app" to "organicmaps.app"` or `ObjectCreated, Type amenity-bench, Location ...`. When uploading, only the Journal entries are used do update the OSM object. After a successful upload, the Journal is cleared. Saving and restoring the Journal after an app restart is implemented now. For the transition phase to the new editing logic the old uploading code is still functional. The old code is used when the object was modified in a previous OM version. #### Todo - [x] Logging - [x] Add logging for all Tags - [x] Add logging for FeatureType - [x] Safe and Restore Data after App restart - [x] New uploading logic - [x] Transition from old OM versions #### Bugs fixed - #8102 - #2298 - #6260 - #6292 - #9126 #### Testing Tested with the OSM dev API, but only on Android. #### Transition The PR only affects new edits. Old edits from previous OM versions that were not uploaded yet use the old uploading code. #### New features I keep in mind to not block anything - Adding "komplex" Category types (#4523) - Mark POI as disused - POI category change (#3491) - Add address POIs (#9199) - Support editing POIs mapped as areas (#6727) #### Follow up issues (Issues not addressed in this PR) - #9043 - #9503 - Remove code of the old editor after some time (e.g. three months)
RedAuburn reviewed 2024-09-07 19:23:02 +00:00
biodranik (Migrated from github.com) reviewed 2024-09-07 19:23:02 +00:00
vng (Migrated from github.com) reviewed 2024-12-01 19:34:31 +00:00
vng (Migrated from github.com) left a comment

Will finish review later.

Please:

  • setup your editor to use open { braces from the new line (not KR-style)
  • don't use braces for one-line expressions
Will finish review later. Please: - setup your editor to use open { braces from the new line (not KR-style) - don't use braces for one-line expressions
@ -151,2 +151,3 @@
{
g_editableMapObject.SetInternet(hasWifi ? feature::Internet::Wlan : feature::Internet::Unknown);
if (hasWifi != (g_editableMapObject.GetInternet() == feature::Internet::Wlan))
g_editableMapObject.SetInternet(hasWifi ? feature::Internet::Wlan : feature::Internet::Unknown);
vng (Migrated from github.com) commented 2024-12-01 18:35:19 +00:00

Incapsulate this logic in EditableMapObject::SetInternet ?

Incapsulate this logic in EditableMapObject::SetInternet ?
vng (Migrated from github.com) commented 2024-12-01 18:36:38 +00:00

name.starts_with("name:")

name.starts_with("name:")
vng (Migrated from github.com) commented 2024-12-01 18:37:55 +00:00

Put the ASSERT here? Is it a possible case?

Put the ASSERT here? Is it a _possible_ case?
vng (Migrated from github.com) commented 2024-12-01 18:48:23 +00:00

Is this block the same as some lines above? ("Add tags to XMLFeature"). Take out a function?

Is this block the same as some lines above? ("Add tags to XMLFeature"). Take out a function?
@ -717,0 +808,4 @@
XMLFeature const osmFeatureCopy = osmFeature;
osmFeature.ApplyPatch(feature);
// Check to avoid uploading duplicates into OSM.
if (osmFeature == osmFeatureCopy)
vng (Migrated from github.com) commented 2024-12-01 18:51:38 +00:00

Should support this legacy in case when we have the old edits.xml after updating the app?

Should support this legacy in case when we have the old edits.xml after updating the app?
@ -813,3 +944,3 @@
if (status == FeatureStatus::Created)
{
editor::FromXML(xml, fti.m_object);
if (loadFromJournal)
vng (Migrated from github.com) commented 2024-12-01 18:56:55 +00:00

No need braces here.

No need braces here.
vng (Migrated from github.com) commented 2024-12-01 19:00:18 +00:00

std::move(journal)

std::move(journal)
vng (Migrated from github.com) commented 2024-12-01 19:08:52 +00:00

Call time(nullptr) once here?

Call time(nullptr) once here?
@ -412,0 +495,4 @@
entry.data = legacyObjData;
break;
}
}
vng (Migrated from github.com) commented 2024-12-01 19:08:14 +00:00

What will happen if xml file is broken, say any XXX.value() does not exist? Should we have any generic error processing here? Like catch an exception and continue/skip the whole entry?

What will happen if xml file is broken, say any XXX.value() does not exist? Should we have any generic error processing here? Like catch an exception and continue/skip the whole entry?
@ -412,0 +574,4 @@
auto xmlJournalHistory = GetRootNode().append_child("journalHistory");
insertEditJournalList(xmlJournalHistory, journal.GetJournalHistory());
vng (Migrated from github.com) commented 2024-12-01 19:11:22 +00:00

value.empty()

value.empty()
vng (Migrated from github.com) commented 2024-12-01 19:14:27 +00:00

GetReadableObjectName(type)

```GetReadableObjectName(type)```
vng (Migrated from github.com) commented 2024-12-01 19:16:32 +00:00

I suspect that we have more 3-arity types besides amenity-recycling-xxx
Add ASSERT/CHECK(!(++iter), ("Add an exception:", strType))

I suspect that we have more 3-arity types besides amenity-recycling-xxx Add ASSERT/CHECK(!(++iter), ("Add an exception:", strType))
vng (Migrated from github.com) commented 2024-12-01 19:20:12 +00:00

Braces are not needed here

Braces are not needed here
vng (Migrated from github.com) commented 2024-12-01 19:24:11 +00:00

Here is how I'd prefer to see this code:

LOG(LDEBUG, ("Key ", key, "changed from \"", old_value, "\" to \"", new_value, "\""));
AddJournalEntry({JournalEntryType::TagModification, time(nullptr), {key, std::move(old_value), std::move(new_value)}});
Here is how I'd prefer to see this code: ``` LOG(LDEBUG, ("Key ", key, "changed from \"", old_value, "\" to \"", new_value, "\"")); AddJournalEntry({JournalEntryType::TagModification, time(nullptr), {key, std::move(old_value), std::move(new_value)}}); ```
vng (Migrated from github.com) commented 2024-12-01 19:24:46 +00:00

JournalEntry entry

JournalEntry entry
vng (Migrated from github.com) commented 2024-12-01 19:25:00 +00:00

std::move(entry)

std::move(entry)
vng (Migrated from github.com) commented 2024-12-01 19:25:35 +00:00
for (JournalEntry & entry : journal)
  journalHistory.push_back(std::move(entry));
``` for (JournalEntry & entry : journal) journalHistory.push_back(std::move(entry)); ```
vng (Migrated from github.com) commented 2024-12-01 19:25:58 +00:00

JournalEntry entry

JournalEntry entry
vng (Migrated from github.com) commented 2024-12-01 19:26:07 +00:00

std::move(entry)

std::move(entry)
@ -0,0 +35,4 @@
void EditJournal::MarkAsCreated(uint32_t type, feature::GeomType geomType, m2::PointD mercator)
{
ASSERT(m_journal.empty(), ("Only empty journals can be marked as created"));
LOG(LDEBUG, ("Object of type ", classif().GetReadableObjectName(type), " created"));
vng (Migrated from github.com) commented 2024-12-01 19:28:54 +00:00
ASSERT(journal.empty(), ("Only empty journals can be marked as created"));
LOG(LDEBUG, ("Object of type ", classif().GetReadableObjectName(type), " created"));
AddJournalEntry({JournalEntryType::ObjectCreated, time(nullptr), {type, geomType, mercator}});
``` ASSERT(journal.empty(), ("Only empty journals can be marked as created")); LOG(LDEBUG, ("Object of type ", classif().GetReadableObjectName(type), " created")); AddJournalEntry({JournalEntryType::ObjectCreated, time(nullptr), {type, geomType, mercator}}); ```
@ -0,0 +109,4 @@
return "ObjectCreated";
case osm::JournalEntryType::LegacyObject:
return "LegacyObject";
}
vng (Migrated from github.com) commented 2024-12-01 19:27:16 +00:00

UNREACHABLE();

UNREACHABLE();
vng (Migrated from github.com) commented 2024-12-01 19:18:47 +00:00

Please, use "m_" notation at least here.

Please, use "m_" notation at least here.
vng (Migrated from github.com) commented 2024-12-01 19:01:01 +00:00

EditJournal && editJournal

EditJournal && editJournal
vng (Migrated from github.com) commented 2024-12-01 19:01:12 +00:00

std::move(editJournal)

std::move(editJournal)
vng (Migrated from github.com) commented 2024-12-01 19:29:55 +00:00

No need braces here

No need braces here
vng (Migrated from github.com) commented 2024-12-01 19:32:28 +00:00

Ok, so check langCode != StringUtf8Multilang:: UnsupportedLanguageCode

Ok, so check ```langCode != StringUtf8Multilang:: UnsupportedLanguageCode```
map-per reviewed 2024-12-04 09:34:43 +00:00
@ -0,0 +109,4 @@
return "ObjectCreated";
case osm::JournalEntryType::LegacyObject:
return "LegacyObject";
}
Author
Contributor

Is UNREACHABLE() necessary? All three JournalEntryType enum values are handled here, so the compiler can figure out by itself that the end is unreachable.

Is UNREACHABLE() necessary? All three JournalEntryType enum values are handled here, so the compiler can figure out by itself that the end is unreachable.
map-per reviewed 2024-12-04 09:49:07 +00:00
@ -717,0 +808,4 @@
XMLFeature const osmFeatureCopy = osmFeature;
osmFeature.ApplyPatch(feature);
// Check to avoid uploading duplicates into OSM.
if (osmFeature == osmFeatureCopy)
Author
Contributor

Yes, the old editor upload code is used for all POIs that were edited before the EditJournal was introduced because these POIs don't have a full journal history of the changes.

My plan is to remove the old editor code about three months after this PR is merged.

Yes, the old editor upload code is used for all POIs that were edited before the EditJournal was introduced because these POIs don't have a full journal history of the changes. My plan is to remove the old editor code about three months after this PR is merged.
map-per reviewed 2024-12-04 11:54:19 +00:00
@ -151,2 +151,3 @@
{
g_editableMapObject.SetInternet(hasWifi ? feature::Internet::Wlan : feature::Internet::Unknown);
if (hasWifi != (g_editableMapObject.GetInternet() == feature::Internet::Wlan))
g_editableMapObject.SetInternet(hasWifi ? feature::Internet::Wlan : feature::Internet::Unknown);
Author
Contributor

That's not a good idea, because iOS uses all Internet values and not just Wifi true/false.
(This is a fix for the Android only bug #9508)

That's not a good idea, because iOS uses all `Internet` values and not just Wifi `true`/`false`. (This is a fix for the Android only bug #9508)
map-per reviewed 2024-12-04 12:46:53 +00:00
@ -412,0 +495,4 @@
entry.data = legacyObjData;
break;
}
}
Author
Contributor

pugixml shouldn't throw exceptions. It's very fault tolerant, so e.g. calling .attribute("key").value() on an empty xml node doesn't crash, but just returns "".

The current GetEditJournal() assumes that the xml is correct. Should I add checks and use MYTHROW in case read in values are invalid like it is done in other parts of the xml_feature class?

pugixml shouldn't throw exceptions. It's very fault tolerant, so e.g. calling `.attribute("key").value()` on an empty xml node doesn't crash, but just returns "". The current `GetEditJournal()` assumes that the xml is correct. Should I add checks and use MYTHROW in case read in values are invalid like it is done in other parts of the `xml_feature` class?
map-per reviewed 2024-12-04 12:54:16 +00:00
Author
Contributor

Added ASSERT_FAIL for that case

Added ASSERT_FAIL for that case
map-per reviewed 2024-12-04 12:54:53 +00:00
Author
Contributor

Moved it to a new function

Moved it to a new function
map-per reviewed 2024-12-04 12:57:16 +00:00
Author
Contributor

👍 Added an assertion

:+1: Added an assertion
map-per reviewed 2024-12-04 16:17:33 +00:00
@ -412,0 +495,4 @@
entry.data = legacyObjData;
break;
}
}
Author
Contributor

I added checks to make sure only correct values are read from the xml file. (exceptions are thrown when the xml contains an invalid value)

I added checks to make sure only correct values are read from the xml file. (exceptions are thrown when the xml contains an invalid value)
vng (Migrated from github.com) reviewed 2024-12-05 03:39:14 +00:00
@ -151,2 +151,3 @@
{
g_editableMapObject.SetInternet(hasWifi ? feature::Internet::Wlan : feature::Internet::Unknown);
if (hasWifi != (g_editableMapObject.GetInternet() == feature::Internet::Wlan))
g_editableMapObject.SetInternet(hasWifi ? feature::Internet::Wlan : feature::Internet::Unknown);
vng (Migrated from github.com) commented 2024-12-05 03:12:21 +00:00

ok

ok
vng (Migrated from github.com) commented 2024-12-05 03:14:09 +00:00

Please, all braces { here and below from the new line.

Please, all braces { here and below from the new line.
vng (Migrated from github.com) commented 2024-12-05 03:23:31 +00:00

std::move(key)

std::move(key)
vng (Migrated from github.com) commented 2024-12-05 03:24:44 +00:00

std::move(osmLangName)

std::move(osmLangName)
vng (Migrated from github.com) commented 2024-12-05 03:26:33 +00:00

std::string_view value = ...
std::string_view old_value = ...

std::string_view value = ... std::string_view old_value = ...
vng (Migrated from github.com) commented 2024-12-05 03:26:57 +00:00

m_journal.AddTagChange(ToString(type), std::string(old_value), std::string(value));

m_journal.AddTagChange(ToString(type), std::string(old_value), std::string(value));
vng (Migrated from github.com) commented 2024-12-05 03:30:31 +00:00

(std::vector<std::string> & cuisinesPtr, std::string_view s)

```(std::vector<std::string> & cuisinesPtr, std::string_view s)```
vng (Migrated from github.com) commented 2024-12-05 03:33:37 +00:00
if (!base::IsExist(old_cuisines, new_cuisine))
{
  cuisinesModified = true;
  break;
}
``` if (!base::IsExist(old_cuisines, new_cuisine)) { cuisinesModified = true; break; } ```
map-per reviewed 2024-12-05 20:46:26 +00:00
Author
Contributor

Thanks! That makes the code way cleaner than with the goto

Thanks! That makes the code way cleaner than with the `goto`
vng (Migrated from github.com) reviewed 2024-12-22 22:02:56 +00:00
vng (Migrated from github.com) commented 2024-12-22 22:02:52 +00:00

Take out into a separate function to avoid copy-paste-check ?

Take out into a separate function to avoid copy-paste-check ?
map-per reviewed 2024-12-22 22:12:55 +00:00
Author
Contributor

It's not really worth it because I want to remove the decision logic for old/new editor in a few months anyway. This code is only needed for the transition period.

It's not really worth it because I want to remove the decision logic for old/new editor in a few months anyway. This code is only needed for the transition period.
vng (Migrated from github.com) approved these changes 2025-01-31 20:44:42 +00:00
vng (Migrated from github.com) left a comment

I did permanent testing of this PR for 2 months. Merge, and everyone interested can check it in Beta.

I did permanent testing of this PR for 2 months. Merge, and everyone interested can check it in Beta.
This repo is archived. You cannot comment on pull requests.
No labels
Accessibility
Accessibility
Address
Address
Android
Android
Android Auto
Android Auto
Android Automotive (AAOS)
Android Automotive (AAOS)
API
API
AppGallery
AppGallery
AppStore
AppStore
Battery and Performance
Battery and Performance
Blocker
Blocker
Bookmarks and Tracks
Bookmarks and Tracks
Borders
Borders
Bug
Bug
Build
Build
CarPlay
CarPlay
Classificator
Classificator
Community
Community
Core
Core
CrashReports
CrashReports
Cycling
Cycling
Desktop
Desktop
DevEx
DevEx
DevOps
DevOps
dev_sandbox
dev_sandbox
Directions
Directions
Documentation
Documentation
Downloader
Downloader
Drape
Drape
Driving
Driving
Duplicate
Duplicate
Editor
Editor
Elevation
Elevation
Enhancement
Enhancement
Epic
Epic
External Map Datasets
External Map Datasets
F-Droid
F-Droid
Fonts
Fonts
Frequently User Reported
Frequently User Reported
Fund
Fund
Generator
Generator
Good first issue
Good first issue
Google Play
Google Play
GPS
GPS
GSoC
GSoC
iCloud
iCloud
Icons
Icons
iOS
iOS
Legal
Legal
Linux Desktop
Linux Desktop
Linux packaging
Linux packaging
Linux Phone
Linux Phone
Mac OS
Mac OS
Map Data
Map Data
Metro
Metro
Navigation
Navigation
Need Feedback
Need Feedback
Night Mode
Night Mode
NLnet 2024-06-281
NLnet 2024-06-281
No Feature Parity
No Feature Parity
Opening Hours
Opening Hours
Outdoors
Outdoors
POI Info
POI Info
Privacy
Privacy
Public Transport
Public Transport
Raw Idea
Raw Idea
Refactoring
Refactoring
Regional
Regional
Regression
Regression
Releases
Releases
RoboTest
RoboTest
Route Planning
Route Planning
Routing
Routing
Ruler
Ruler
Search
Search
Security
Security
Styles
Styles
Tests
Tests
Track Recording
Track Recording
Translations
Translations
TTS
TTS
UI
UI
UX
UX
Walk Navigation
Walk Navigation
Watches
Watches
Web
Web
Wikipedia
Wikipedia
Windows
Windows
Won't fix
Won't fix
World Map
World Map
No project
No assignees
3 participants
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: organicmaps/organicmaps-tmp#9242
No description provided.